How Chromium Manages System Tray Icons and Background Apps

This article explores the internal mechanisms the Chromium web browser uses to remain active in the background after all visible browser windows are closed. It covers the core architectural components responsible for process persistence, including the KeepAlive registry and the BackgroundModeManager. Additionally, it explains how web extensions trigger this background state and how Chromium interfaces with different operating systems to display and manage the system tray icon.

The KeepAlive Architecture

By default, Chromium is designed to terminate its main browser process when the user closes the last open browser window. To override this behavior, Chromium relies on an internal system called the KeepAliveRegistry.

The KeepAliveRegistry acts as a reference counter for the browser's lifecycle. Various browser subsystems can instantiate a ScopedKeepAlive object, which increments this counter. When the last browser window is closed, Chromium checks the KeepAliveRegistry. If the count is greater than zero, the browser halts its shutdown sequence and continues running silently in the background.

The BackgroundModeManager

The specific component responsible for keeping the browser alive for web apps and extensions is the BackgroundModeManager. This manager monitors the lifecycle of all installed extensions and web applications across user profiles.

Background persistence is triggered through the following steps:

  1. A user installs a Chromium extension or Progressive Web App (PWA) that explicitly requests the "background" permission in its manifest.json file.
  2. The BackgroundModeManager detects this permission during extension loading or browser startup.
  3. The manager requests a ScopedKeepAlive from the KeepAliveRegistry using the KeepAliveOrigin::BACKGROUND_MODE_MANAGER flag.
  4. Chromium launches a hidden background renderer process for the extension, allowing it to listen for events, fetch data, and trigger notifications without a visible UI.

Rendering the System Tray Icon

To ensure the user is aware that Chromium is still consuming system resources in the background, the BackgroundModeManager creates a system tray icon as soon as background mode is activated.

Because operating systems handle system tray icons differently, Chromium uses an abstraction layer defined by the StatusTray and StatusIcon C++ classes. The browser translates these generic classes into native OS calls:

  • Windows: Chromium uses StatusIconWin, which interacts directly with the Win32 Shell_NotifyIcon API to place the Chromium logo in the Windows Notification Area.
  • Linux: Chromium utilizes StatusIconLinuxWrapper, which communicates via D-Bus using the StatusNotifierItem protocol (and formerly libappindicator) to display the icon in desktop environments like KDE and GNOME.
  • macOS: Chromium generally bypasses the BackgroundModeManager tray icon on macOS. Because macOS natively keeps applications running in the Dock after their last window is closed, a separate system tray mechanism is redundant.

Context Menus and Process Termination

When the system tray icon is initialized, Chromium attaches a StatusIconMenuModel to it. When a user clicks or right-clicks the tray icon, this model dynamically generates a native OS context menu. This menu displays a list of the specific extensions currently holding the browser open, a shortcut to the browser's internal Task Manager, and an option to toggle background mode off.

The background process will persist until one of three events occurs:

  • User Termination: The user clicks "Exit" from the system tray icon's context menu. This forces the BackgroundModeManager to release its ScopedKeepAlive immediately, triggering a full browser shutdown.
  • Permission Revocation: The user uninstalls or disables all extensions that use the "background" permission. Once the last background extension is removed, the BackgroundModeManager removes the system tray icon and releases its ScopedKeepAlive.
  • Settings Override: The user navigates to chrome://settings/system and disables the "Continue running background apps when Chromium is closed" toggle. This writes a boolean flag (kBackgroundModeEnabled) to the local state preferences file, instructing the BackgroundModeManager to ignore "background" permissions entirely and release its hold on the browser process.