This document describes the architecture of Webapp, WebAPK, and Trusted Web Activity (TWA) related classes, focusing on their interactions and call patterns.
The code is distributed across several key directories:
chrome/android/java/src/org/chromium/chrome/browser/webapps/: Core Java logic for Webapps and WebAPKs in Chrome.chrome/android/java/src/org/chromium/chrome/browser/browserservices/: Java logic for Custom Tabs and Trusted Web Activities (TWA).chrome/android/webapk/: Code for the WebAPK shell (the installed APK wrapper) and client libraries.components/webapps/browser/android/: C++ shared component code specific to Android.components/webapps/browser/: Cross-platform C++ shared component code (installability, banners).Chromium on Android supports three distinct systems for “installing” web applications, each with different characteristics and use cases.
WebAPK is the standard and most integrated way to install Progressive Web Apps (PWAs) on Android.
WebApkUpdateManager and WebApkUpdateTask.Standard TWAs are used by 3rd party Android apps to display web content in a customized Custom Tab without browser UI.
This system allows Chrome to install a TWA-like experience directly, used in specific projects like Desktop Android.
TwaInstaller in components/webapps, which calls WebAppManager via AconfigFlaggedApiDelegate.WebAppManager / IWebAppService (Mainline module) for the actual installation on the OS side.InstalledWebappRegistrar.registerClient to establish the link.WebAppManager or follows the TWA model.WebappActivity is the base class for displaying a web app in a nearly UI-less Chrome. It extends BaseCustomTabActivity, leveraging the Custom Tabs infrastructure but hiding most of the browser UI.
WebappActivity: Thin shell that overrides some methods to customize behavior (e.g., disabling bookmarking, handling “open in browser”). It determines whether to use a standard Webapp or WebAPK intent data provider.WebappActivityCoordinator: Handles lifecycle events and storage updates. It uses WebappDeferredStartupWithStorageHandler to manage tasks that need storage access. It also warms up shared preferences for the web app.Installed web apps (WebAPKs and TWAs) differ from normal browser usage in several key ways to provide an app-like experience:
WebappActivity), hiding the URL bar, tab switcher, and other browser controls.WebappActivityCoordinator and deferred startup tasks.This section covers details specific to WebAPKs.
WebApkActivityCoordinator: Orchestrates the startup and deferred startup tasks for a WebAPK activity. It triggers sync, update checks, and permission registration.WebApkUpdateManager: Manages checking for updates to the Web Manifest and scheduling background update tasks.WebApkUpdateTask: A background task executed by the BackgroundTaskScheduler to perform updates when the WebAPK is not running.WebApkSyncService: A utility class that communicates with native code via JNI to sync WebAPK data (like usage and uninstallation) with the user's account.WebApkUninstallTracker: Tracks uninstalls of WebAPKs and defers reporting metrics until native is loaded.This graph illustrates the interactions between the core Webapp and WebAPK components, showing how they fit into the Custom Tabs base class.
classDiagram class BaseCustomTabActivity { -mWebappActivityCoordinator: WebappActivityCoordinator } class WebappActivity { %% Extends BaseCustomTabActivity } class SameTaskWebApkActivity { %% Extends WebappActivity } class WebappActivityCoordinator { -mWebappInfo: WebappInfo } class WebApkActivityCoordinator { +onDeferredStartupWithStorage(...) +onDestroy() } class WebApkUpdateManager { +updateIfNeeded(...) +updateWhileNotRunning(...) } class WebApkUpdateTask { #onStartTaskWithNative(...) } class WebApkSyncService { <<static>> +onWebApkUsed(...) +onWebApkUninstalled(...) } class WebappDataStorage { +incrementLaunchCount() +getLastUsedTimeMs() } class InstalledWebappRegistrar { <<Singleton>> +registerClient(...) } class PermissionUpdater { <<Utility>> +onWebApkLaunch(...) } BaseCustomTabActivity <|-- WebappActivity WebappActivity <|-- SameTaskWebApkActivity BaseCustomTabActivity *-- WebappActivityCoordinator BaseCustomTabActivity *-- WebApkActivityCoordinator : created if WebAPK WebApkActivityCoordinator --> WebappDataStorage : reads/writes WebApkActivityCoordinator --> WebApkSyncService : calls WebApkActivityCoordinator --> WebApkUpdateManager : calls WebApkActivityCoordinator --> InstalledWebappRegistrar : calls WebApkActivityCoordinator --> PermissionUpdater : calls WebApkUpdateManager --> WebappDataStorage : reads/writes WebApkUpdateManager ..> WebApkUpdateTask : schedules via BackgroundTaskScheduler WebApkUpdateTask --> WebApkUpdateManager : calls (updateWhileNotRunning) WebApkSyncService --> WebappDataStorage : reads
When a WebAPK is launched, WebApkActivityCoordinator executes the following steps during deferred startup:
WebappDataStorage.WebApkSyncService.onWebApkUsed to notify sync that the app was used.WebApkUpdateManager.updateIfNeeded to check if the manifest has changed.InstalledWebappRegistrar.registerClient and PermissionUpdater.onWebApkLaunch to ensure permissions are delegated correctly.WebApkUpdateManager fetches the current Web Manifest and compares it with the data stored in WebappInfo (extracted from the installed WebAPK's Android Manifest).WebApkUpdateManagerJni.get().storeWebApkUpdateRequestToFile) to serialize the update request data to a file.WebApkUpdateTask via BackgroundTaskScheduler.WebApkUpdateTask calls WebApkUpdateManager.updateWhileNotRunning.WebApkUpdateManager calls native code (WebApkUpdateManagerJni.get().updateWebApkFromFile) which reads the file and sends the update request to the WebAPK server.This sequence diagram shows the flow when a WebAPK installation is triggered, crossing the JNI boundary between C++ and Java.
sequenceDiagram autonumber participant CPP_ABM as C++ AppBannerManagerAndroid participant CPP_WIS as C++ WebApkInstallService participant CPP_WI as C++ WebApkInstaller participant J_WI as Java WebApkInstaller participant J_WIS as Java WebApkInstallService Note over CPP_ABM, J_WIS: WebAPK Installation Flow CPP_ABM->>CPP_WIS: InstallAsync(...) CPP_WIS->>CPP_WI: InstallAsync(...) CPP_WIS->>J_WIS: showInstallInProgressNotification(...) [JNI] CPP_WI->>J_WI: create(...) [JNI] Note over J_WI: Java side performs the actual install<br/>(via Play Store or download) J_WI-->>CPP_WI: onInstallFinished(...) [JNI] CPP_WI-->>CPP_WIS: Callback CPP_WIS->>J_WIS: showInstalledNotification(...) [JNI]
WebApkUninstallTracker.deferRecordWebApkUninstalled is called to save the package name and timestamp in SharedPreferences, avoiding loading native libraries.WebApkUninstallTracker.runDeferredTasks is called.WebApkSyncService.onWebApkUninstalled to notify sync.WebAPKs are thin shells that rely heavily on Chrome (Clank) for their logic and rendering. They interface with Clank in several key ways:
When a user launches a WebAPK, it sends an intent to Chrome to start the web application.
com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_WEBAPP. If unbound, it uses android.intent.action.VIEW.WebappLauncherActivity receives this intent and routes it to SameTaskWebApkActivity or WebappActivity.To keep the WebAPK small and up-to-date, it does not contain most of the web app logic. Instead:
IWebApkApi)Chrome communicates with the WebAPK via a bound service using the IWebApkApi AIDL interface.
WebApkServiceClient in Chrome manages this connection.WebAPK features in Java often rely on C++ components via JNI:
WebApkSyncService calls native code to sync usage and uninstallation.WebApkUpdateManager calls native code to serialize update requests to a file, and to perform the update from that file.InstalledWebappBridge facilitates permission decisions between C++ permission system and Java updaters.This section covers details specific to TWAs.
TrustedWebActivityCoordinator: The main entry point for TWA-specific logic in a Custom Tab activity. It handles splash screens and registers the client with InstalledWebappRegistrar upon successful verification.SharedActivityCoordinator: Manages UI state (immersive mode, theme color, status bar color) that is shared between TWAs and general Webapps. It switches between “app mode” and “tab mode” based on site verification results.TrustedWebActivityDisclosureController: Controls when to show the “Running in Chrome” disclosure to the user.TrustedWebActivityModel: Holds the state for the TWA, particularly regarding the disclosure UI.DisclosureUiPicker: Chooses the appropriate disclosure UI (Notification, Snackbar, or Infobar) based on user settings and intent parameters.This graph illustrates the ownership and management structure of the key components in the TWA area.
classDiagram class BaseCustomTabActivity { -mWebappActivityCoordinator: WebappActivityCoordinator -mTwaCoordinator: TrustedWebActivityCoordinator } class WebappActivityCoordinator { -mWebappInfo: WebappInfo } class TrustedWebActivityCoordinator { -mTwaDisclosureController: TrustedWebActivityDisclosureController -mSharedActivityCoordinator: SharedActivityCoordinator } class TrustedWebActivityDisclosureController { -mModel: TrustedWebActivityModel -mUiPicker: DisclosureUiPicker } class TrustedWebActivityModel { +state } class DisclosureUiPicker { +pickUi() } class SharedActivityCoordinator { +applyAppMode() +applyTabMode() } BaseCustomTabActivity *-- TrustedWebActivityCoordinator BaseCustomTabActivity *-- WebappActivityCoordinator TrustedWebActivityCoordinator *-- TrustedWebActivityDisclosureController TrustedWebActivityCoordinator *-- SharedActivityCoordinator TrustedWebActivityDisclosureController *-- TrustedWebActivityModel TrustedWebActivityDisclosureController *-- DisclosureUiPicker
This sequence diagram shows the flow when an Auto-minted TWA installation is triggered on platforms like Desktop Android.
sequenceDiagram autonumber participant User participant C_ABM as C++ AppBannerManager participant C_TI as C++ TwaInstaller participant J_TI as Java TwaInstaller participant AFAD as AconfigFlaggedApiDelegate participant WAM as Android WebAppManager User->>C_ABM: Triggers Install C_ABM->>C_TI: Install(...) C_TI->>J_TI: start(...) [JNI] J_TI->>AFAD: installTwa(...) AFAD->>WAM: install(...) Note over WAM: Android system handles<br/>installation in background WAM-->>AFAD: Callback (Success/Fail) AFAD-->>J_TI: Callback J_TI->>C_TI: onInstallEvent(...) [JNI]
This sequence diagram shows the flow when a standard TWA is launched by a 3rd party app.
sequenceDiagram autonumber participant App as 3rd Party TWA App participant LA as WebappLauncherActivity participant WA as WebappActivity / CustomTabActivity participant TV as TwaVerifier participant IWR as InstalledWebappRegistrar App->>LA: Sends Intent LA->>WA: Routes to Activity WA->>TV: Verify Origin Note over TV: Checks Digital Asset Links TV-->>WA: Verification Result alt Success WA->>WA: Maintain App Mode UI WA->>IWR: registerClient(...) else Failure WA->>WA: Switch to Tab Mode UI (Browser Controls) end
To ensure users know their data is shared with Chrome, a disclosure is shown when a TWA is launched.
TrustedWebActivityDisclosureController checks BrowserServicesStore to see if the user has already accepted or seen the disclosure.DisclosureUiPicker decides which UI to show:TrustedWebActivityModel.SharedActivityCoordinator optimistically applies “app mode” UI (no browser controls, Twa theme colors) before layout inflation.
WebAppHeaderLayoutCoordinator: This class is responsible for drawing the web app header UI (e.g., custom action bar, window-controls-overlay, minimal-ui) depending on the display mode requested by the PWA manifest and browser settings.SharedActivityCoordinator also manages how the app draws relative to system bars (status bar and navigation bar) and display cutouts.
Currently, the main path to enable drawing into the cutout area is:
TrustedWebActivityDisplayMode.ImmersiveMode:display: fullscreen.A key difference between webapps and normal browser usage is how site settings and permissions are managed.
InstalledWebappRegistrar: A singleton that handles registration requests when a TWA/WebAPK is verified or navigated.InstalledWebappDataRegister: Manages the storage of registered web apps in SharedPreferences.PermissionUpdater: Coordinates updating permissions (notifications, location) in Chrome when apps are verified or uninstalled.For more details on Registration and Permission Delegation, see Registration and Permission Delegation.
For details on how to test Web Apps on Android, including manual testing instructions and a list of automated test suites, see the Android Testing Guide.
WebAppManager in more detail.