components/webapps/docs/projects/al-site-settings/webapp_android_architecture.md
This document describes the architecture of Webapp, WebAPK, and Trusted Web
Activity (TWA) related classes in chrome/android/java/src, focusing on their
interactions and call patterns.
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
(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
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_permissions.md.
WebAppManager in more detail.