chromium/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.webapps;

import android.os.Build;

import androidx.annotation.NonNull;

import dagger.Lazy;

import org.chromium.chrome.browser.browserservices.InstalledWebappRegistrar;
import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.browserservices.permissiondelegation.PermissionUpdater;
import org.chromium.chrome.browser.browserservices.ui.controller.webapps.WebappDisclosureController;
import org.chromium.chrome.browser.browserservices.ui.view.DisclosureInfobar;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.DestroyObserver;
import org.chromium.components.embedder_support.util.Origin;

import javax.inject.Inject;

/**
 * Coordinator for the WebAPK activity component. Add methods here if other components need to
 * communicate with the WebAPK activity component.
 */
@ActivityScope
public class WebApkActivityCoordinator implements DestroyObserver {
    private final BrowserServicesIntentDataProvider mIntentDataProvider;
    private final Lazy<WebApkUpdateManager> mWebApkUpdateManager;
    private final InstalledWebappRegistrar mInstalledWebappRegistrar;

    @Inject
    public WebApkActivityCoordinator(
            WebappDeferredStartupWithStorageHandler deferredStartupWithStorageHandler,
            WebappDisclosureController disclosureController,
            DisclosureInfobar disclosureInfobar,
            WebApkActivityLifecycleUmaTracker webApkActivityLifecycleUmaTracker,
            ActivityLifecycleDispatcher lifecycleDispatcher,
            BrowserServicesIntentDataProvider intendDataProvider,
            Lazy<WebApkUpdateManager> webApkUpdateManager,
            InstalledWebappRegistrar installedWebappRegistrar) {
        // We don't need to do anything with |disclosureController|, |disclosureInfobar| and
        // |webApkActivityLifecycleUmaTracker|. We just need to resolve
        // them so that they start working.

        mIntentDataProvider = intendDataProvider;
        mWebApkUpdateManager = webApkUpdateManager;
        mInstalledWebappRegistrar = installedWebappRegistrar;

        deferredStartupWithStorageHandler.addTask(
                (storage, didCreateStorage) -> {
                    if (lifecycleDispatcher.isActivityFinishingOrDestroyed()) return;

                    onDeferredStartupWithStorage(storage, didCreateStorage);
                });
        lifecycleDispatcher.register(this);
    }

    public void onDeferredStartupWithStorage(
            @NonNull WebappDataStorage storage, boolean didCreateStorage) {
        assert storage != null;
        storage.incrementLaunchCount();

        WebApkSyncService.onWebApkUsed(mIntentDataProvider, storage, false /* isInstall */);
        mWebApkUpdateManager.get().updateIfNeeded(storage, mIntentDataProvider);

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            return;
        }

        // The scope should not be empty here, this is for a WebAPK that just launched.
        String scope = storage.getScope();
        assert !scope.isEmpty();

        Origin origin = Origin.create(scope);
        String packageName = storage.getWebApkPackageName();

        mInstalledWebappRegistrar.registerClient(packageName, origin, storage.getUrl());
        PermissionUpdater.get().onWebApkLaunch(origin, packageName);
    }

    @Override
    public void onDestroy() {
        // The common case is to be connected to just one WebAPK's services. For the sake of
        // simplicity disconnect from the services of all WebAPKs.
        ChromeWebApkHost.disconnectFromAllServices(/* waitForPendingWork= */ true);
    }
}