Back to Chromium

Android Web App Architectures (WebAPK and TWA)

components/webapps/docs/projects/al-site-settings/webapp_android_architecture.md

151.0.7873.118.6 KB
Original Source

Android Web App Architectures (WebAPK and TWA)

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.

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
(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
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_permissions.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