blob: 244a688d41404054a0c090e38e7862b4b2eafcb4 [file] [view]
# Android Web App Architectures (WebAPK and TWA)
This document describes the architecture of Webapp, WebAPK, and Trusted Web
Activity (TWA) related classes, focusing on their interactions and call
patterns.
## Code Locations
The code is distributed across several key directories:
- [`chrome/android/java/src/org/chromium/chrome/browser/webapps/`](../../../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/`](../../../chrome/android/java/src/org/chromium/chrome/browser/browserservices/):
Java logic for Custom Tabs and Trusted Web Activities (TWA).
- [`chrome/android/webapk/`](../../../chrome/android/webapk/): Code for the
WebAPK shell (the installed APK wrapper) and client libraries.
- [`components/webapps/browser/android/`](../browser/android/): C++ shared
component code specific to Android.
- [`components/webapps/browser/`](../browser/): Cross-platform C++ shared
component code (installability, banners).
## Installation Systems
Chromium on Android supports three distinct systems for "installing" web
applications, each with different characteristics and use cases.
### 1. WebAPK
WebAPK is the standard and most integrated way to install Progressive Web Apps
(PWAs) on Android.
- **Mechanism**: Chrome requests a specialized server (WebAPK minting server) to
generate a real Android APK for the web app. This APK is then installed on the
device.
- **Integration**: WebAPKs appear in the Android app drawer, settings, and can
handle intents for their registered scope.
- **Runtime**: They are thin shells that load Chrome to render the content. They
share logic with Chrome via a runtime library extracted from Chrome.
- **Updates**: Handled by `WebApkUpdateManager` and `WebApkUpdateTask`.
### 2. Standard Trusted Web Activity (TWA)
Standard TWAs are used by 3rd party Android apps to display web content in a
customized Custom Tab without browser UI.
- **Mechanism**: A 3rd party app launches an intent to Chrome specifying a URL
and a session.
- **Verification**: Chrome verifies that the app is authorized to open the URL
in TWA mode (via Digital Asset Links).
- **Characteristics**: Shares cookies and storage with the user's main Chrome
profile. It does not create a new APK; it uses the existing Custom Tabs
infrastructure.
- **Updates**: The Android app shell must be updated externally by the developer
via the app store. The web content updates automatically like a normal
website.
### 3. Auto-minted TWA (TWA Installer)
This system allows Chrome to install a TWA-like experience directly, used in
specific projects like Desktop Android.
- **Mechanism**: Uses `TwaInstaller` in components/webapps, which calls
`WebAppManager` via `AconfigFlaggedApiDelegate`.
- **API**: Relies on Android's `WebAppManager` / `IWebAppService` (Mainline
module) for the actual installation on the OS side.
- **Runtime**: Once running in Chrome, it follows the same path as a standard
TWA, calling `InstalledWebappRegistrar.registerClient` to establish the link.
- **Updates**: Handled by the Android system's `WebAppManager` or follows the
TWA model.
## General Webapp Architecture
`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.
## Differences from Normal Browser Usage
Installed web apps (WebAPKs and TWAs) differ from normal browser usage in
several key ways to provide an app-like experience:
- **UI**: They run in a nearly UI-less mode (`WebappActivity`), hiding the URL
bar, tab switcher, and other browser controls.
- **Task Management**: WebAPKs and TWAs can run in their own Android tasks,
separate from the main Chrome task, making them appear as separate apps in the
Android recents screen.
- **Storage and Cookies**: Standard TWAs share cookies and storage with the
user's main Chrome profile, ensuring a seamless transition from the browser.
- **Permission Delegation**: Permissions granted to the Android app shell (e.g.,
notification permission) can be delegated to the web origin inside Chrome, so
the user doesn't have to grant permissions twice.
- **Lifespan**: Webapps can have specific lifecycles managed by
`WebappActivityCoordinator` and deferred startup tasks.
______________________________________________________________________
## WebAPK Architecture
This section covers details specific to WebAPKs.
### Component Overview (WebAPK)
- **`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.
### Interactions Graph
This graph illustrates the interactions between the core Webapp and WebAPK
components, showing how they fit into the Custom Tabs base class.
```mermaid
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
```
### Call Flows
#### 1. Launch Flow (Deferred Startup)
When a WebAPK is launched, `WebApkActivityCoordinator` executes the following
steps during deferred startup:
1. **Update Usage in Storage**: Increments launch count in `WebappDataStorage`.
2. **Sync Usage**: Calls `WebApkSyncService.onWebApkUsed` to notify sync that
the app was used.
3. **Check for Updates**: Calls `WebApkUpdateManager.updateIfNeeded` to check if
the manifest has changed.
4. **Register Permissions (Android T+)**: Calls
`InstalledWebappRegistrar.registerClient` and
`PermissionUpdater.onWebApkLaunch` to ensure permissions are delegated
correctly.
#### 2. Update Flow
1. **Check for Updates**: `WebApkUpdateManager` fetches the current Web Manifest
and compares it with the data stored in `WebappInfo` (extracted from the
installed WebAPK's Android Manifest).
2. **Generate Update Reasons**: It compares fields like name, short name, icons,
colors, orientation, display mode, share target, and shortcuts.
3. **Persist Request via JNI**: If an update is needed, it encodes icons in the
background and calls native code via JNI
(`WebApkUpdateManagerJni.get().storeWebApkUpdateRequestToFile`) to serialize
the update request data to a file.
4. **Schedule Background Task**: After the file is successfully saved, it
schedules a `WebApkUpdateTask` via `BackgroundTaskScheduler`.
5. **Perform Update**: When the task triggers (typically when the app is closed
and on an unmetered network), `WebApkUpdateTask` calls
`WebApkUpdateManager.updateWhileNotRunning`.
6. **Request New APK**: `WebApkUpdateManager` calls native code
(`WebApkUpdateManagerJni.get().updateWebApkFromFile`) which reads the file
and sends the update request to the WebAPK server.
#### 3. Installation Flow (C++ to Java)
This sequence diagram shows the flow when a WebAPK installation is triggered,
crossing the JNI boundary between C++ and Java.
```mermaid
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]
```
#### 4. Uninstall Flow
1. **Detection**: A broadcast receiver detects that a WebAPK has been
uninstalled.
2. **Deferral**: `WebApkUninstallTracker.deferRecordWebApkUninstalled` is called
to save the package name and timestamp in `SharedPreferences`, avoiding
loading native libraries.
3. **Processing**: When Chrome is next launched and native libraries are loaded,
`WebApkUninstallTracker.runDeferredTasks` is called.
4. **Metrics and Sync**: It records histograms and UKM metrics, and calls
`WebApkSyncService.onWebApkUninstalled` to notify sync.
### Interface Points between WebAPK and Clank
WebAPKs are thin shells that rely heavily on Chrome (Clank) for their logic and
rendering. They interface with Clank in several key ways:
#### 1. Launch Intent
When a user launches a WebAPK, it sends an intent to Chrome to start the web
application.
- **Action**: If the WebAPK is bound to Chrome, it uses
`com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_WEBAPP`. If
unbound, it uses `android.intent.action.VIEW`.
- **Routing**: Chrome's `WebappLauncherActivity` receives this intent and routes
it to `SameTaskWebApkActivity` or `WebappActivity`.
#### 2. Runtime Library Extraction
To keep the WebAPK small and up-to-date, it does not contain most of the web app
logic. Instead:
- The WebAPK extracts a runtime library from Chrome's assets at runtime.
- This allows the WebAPK to share logic with Chrome and be updated whenever
Chrome updates, without reinstalling the WebAPK.
#### 3. AIDL Bound Service (`IWebApkApi`)
Chrome communicates with the WebAPK via a bound service using the `IWebApkApi`
AIDL interface.
- **Class**: `WebApkServiceClient` in Chrome manages this connection.
- **Uses**:
- **Notifications**: Chrome hands over notifications to the WebAPK to display,
so they look like they come from the WebAPK.
- **Permissions**: Chrome can query and request notification permissions from
the WebAPK (especially on Android T+).
#### 4. JNI Bridges (Java \<-> C++)
WebAPK features in Java often rely on C++ components via JNI:
- **Sync**: `WebApkSyncService` calls native code to sync usage and
uninstallation.
- **Update**: `WebApkUpdateManager` calls native code to serialize update
requests to a file, and to perform the update from that file.
- **Permissions**: `InstalledWebappBridge` facilitates permission decisions
between C++ permission system and Java updaters.
______________________________________________________________________
## Trusted Web Activity (TWA) Architecture
This section covers details specific to TWAs.
### Component Overview (TWA)
- **`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.
### Interactions Graph
This graph illustrates the ownership and management structure of the key
components in the TWA area.
```mermaid
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
```
### Call Flows
#### 1. Auto-minted TWA Installation Flow
This sequence diagram shows the flow when an Auto-minted TWA installation is
triggered on platforms like Desktop Android.
```mermaid
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]
```
#### 2. Standard TWA Launch and Verification Flow
This sequence diagram shows the flow when a standard TWA is launched by a 3rd
party app.
```mermaid
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
```
### TWA Disclosure (Running in Chrome)
To ensure users know their data is shared with Chrome, a disclosure is shown
when a TWA is launched.
1. **Logic**: `TrustedWebActivityDisclosureController` checks
`BrowserServicesStore` to see if the user has already accepted or seen the
disclosure.
2. **UI Selection**: `DisclosureUiPicker` decides which UI to show:
- **Notification**: High or low priority silent notification, used if
notifications are enabled.
- **Snackbar**: Auto-dismissing snackbar, used if notifications are disabled.
- **Infobar**: The old persistent infobar, used as a fallback or if
explicitly requested by intent.
3. **State**: The choice and state are maintained in `TrustedWebActivityModel`.
### UI Mode Switching
`SharedActivityCoordinator` optimistically applies "app mode" UI (no browser
controls, Twa theme colors) before layout inflation.
- If site verification **succeeds**, it maintains app mode.
- If site verification **fails**, it switches to "tab mode" UI, showing browser
controls and standard Chrome theming to indicate the site is not trusted by
the TWA app.
- **`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.
### Display Modes and Immersive Mode
`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`**:
- Used when a TWA explicitly requests immersive mode via intent, or
synthesized for installed webapps/WebAPKs when the manifest declares
`display: fullscreen`.
- This triggers full immersive mode, honoring client-supplied cutout mode and
sticky flags. It hides system bars.
______________________________________________________________________
## Common Systems
### Site Settings and Permission Delegation
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](android_registration_and_permissions.md).
## Testing
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](android_testing_guide.md).
## TODO / Next Steps
- [ ] Add more details on TWA installer and interaction with Play Store.
- [ ] Document the interaction with Android's `WebAppManager` in more detail.
- [ ] Research WebAPK update server communication details.
## Resources
- go/webapps-android-docs