# 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.

There are two paths that enable drawing into the cutout area:

- **`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.
  - When the `WebAppShortEdgesCutoutMode` feature is enabled, the immersive mode
    synthesized for `display: fullscreen` webapps uses sticky immersive and
    `LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES`, so fullscreen webapps draw into
    the cutout immediately at activity creation, without waiting for the page's
    `viewport-fit` value.

- **Non-immersive edge-to-edge, deferred to `DisplayCutoutController`** (behind
  the `WebAppShortEdgesCutoutMode` feature):

  - With the feature enabled, `display: standalone` webapps no longer draw
    edge-to-edge unconditionally at activity creation:
    `WebappActivity#shouldDrawEdgeToEdgeOnCreate` returns false, so the activity
    starts with the default (non-edge-to-edge) window layout.
  - Instead, `DisplayCutoutController` takes over once the page's `viewport-fit`
    value is known. Only pages declaring `viewport-fit=cover` get
    `LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES` together with the matching
    edge-to-edge window state; all other pages keep the default layout, and web
    content stays below the status bar.
  - The controller also reacts to dynamic changes: if a page updates its
    `viewport-fit` meta tag via JavaScript after load, the window layout is
    updated accordingly.
  - With the feature disabled, standalone webapps keep the legacy behavior of
    drawing edge-to-edge on creation regardless of `viewport-fit`.

### TWA Launch Parameters

For file intents (sharing files with a TWA), the launch parameters must be
securely matched and delivered to the web page. This involves a complex C++
state machine triggered from Java. For a deep dive into this mechanism and the
security protections against cross-origin leaks, see
[TWA Launch Parameters Handling](android_twa_launch_params.md).

______________________________________________________________________

## 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
