chromium/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIncognitoManager.java

// Copyright 2019 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.customtabs;

import static org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CustomTabProfileType.INCOGNITO;

import android.app.Activity;

import androidx.annotation.Nullable;

import org.chromium.base.CommandLine;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.DestroyObserver;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.profiles.ProfileProvider;
import org.chromium.chrome.browser.tabmodel.IncognitoTabHost;
import org.chromium.chrome.browser.tabmodel.IncognitoTabHostRegistry;

import javax.inject.Inject;

/**
 * Implements incognito tab host for the given instance of Custom Tab activity.
 * This class exists for every custom tab, but its only active if
 * |isEnabledIncognitoCCT| returns true.
 */
@ActivityScope
public class CustomTabIncognitoManager implements NativeInitObserver, DestroyObserver {
    private final Activity mActivity;
    private final CustomTabActivityNavigationController mNavigationController;
    private final BrowserServicesIntentDataProvider mIntentDataProvider;

    @Nullable private IncognitoCustomTabHost mIncognitoTabHost;

    private final IncognitoTabHostRegistry mIncognitoTabHostRegistry;
    private final OneshotSupplier<ProfileProvider> mProfileProviderSupplier;

    @Inject
    public CustomTabIncognitoManager(
            Activity activity,
            BrowserServicesIntentDataProvider intentDataProvider,
            CustomTabActivityNavigationController navigationController,
            ActivityLifecycleDispatcher lifecycleDispatcher,
            IncognitoTabHostRegistry incognitoTabHostRegistry,
            OneshotSupplier<ProfileProvider> profileProviderSupplier) {
        mActivity = activity;
        mIntentDataProvider = intentDataProvider;
        mNavigationController = navigationController;
        mIncognitoTabHostRegistry = incognitoTabHostRegistry;
        mProfileProviderSupplier = profileProviderSupplier;

        lifecycleDispatcher.register(this);
    }

    @Override
    public void onFinishNativeInitialization() {
        if (mIntentDataProvider.getCustomTabMode() == INCOGNITO) {
            initializeIncognito();
        }
    }

    @Override
    public void onDestroy() {
        if (mIncognitoTabHost != null) {
            mIncognitoTabHostRegistry.unregister(mIncognitoTabHost);
        }

        if (mProfileProviderSupplier.get().hasOffTheRecordProfile()) {
            ProfileManager.destroyWhenAppropriate(
                    mProfileProviderSupplier
                            .get()
                            .getOffTheRecordProfile(/* createIfNeeded= */ false));
        }
    }

    public Profile getProfile() {
        return mProfileProviderSupplier.get().getOffTheRecordProfile(/* createIfNeeded= */ true);
    }

    private void initializeIncognito() {
        if (mIntentDataProvider.isOpenedByChrome()) {
            mIncognitoTabHost = new IncognitoCustomTabHost();
            mIncognitoTabHostRegistry.register(mIncognitoTabHost);
        }

        maybeCreateIncognitoTabSnapshotController();
    }

    private void maybeCreateIncognitoTabSnapshotController() {
        if (!CommandLine.getInstance()
                .hasSwitch(ChromeSwitches.ENABLE_INCOGNITO_SNAPSHOTS_IN_ANDROID_RECENTS)) {
            new IncognitoCustomTabSnapshotController(
                    mActivity, () -> mIntentDataProvider.getCustomTabMode() == INCOGNITO);
        }
    }

    /**
     * This class registers itself with {@link IncognitoTabHostRegistry} only if the Incognito
     * custom tab was opened by Chrome.
     */
    private class IncognitoCustomTabHost implements IncognitoTabHost {
        @Override
        public boolean isActiveModel() {
            return true;
        }

        @Override
        public boolean hasIncognitoTabs() {
            return !mActivity.isFinishing();
        }

        @Override
        public void closeAllIncognitoTabs() {
            mNavigationController.finish(CustomTabActivityNavigationController.FinishReason.OTHER);
        }
    }
}