chromium/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabFactory.java

// Copyright 2018 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.content;

import android.app.Activity;
import android.content.Intent;
import android.util.Pair;

import androidx.annotation.Nullable;

import dagger.Lazy;

import org.chromium.base.Callback;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.ChromeTabModelFilterFactory;
import org.chromium.chrome.browser.app.tabmodel.CustomTabsTabModelOrchestrator;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory;
import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.flags.ActivityType;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileProvider;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabBuilder;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
import org.chromium.chrome.browser.tabmodel.TabModelFilterFactory;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorBase;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ActivityWindowAndroid;

import javax.inject.Inject;

/**
 * Creates {@link Tab}, {@link TabModelSelector}, and {@link ChromeTabCreator}s in the context of a
 * Custom Tab activity.
 */
@ActivityScope
public class CustomTabActivityTabFactory {
    private final Activity mActivity;
    private final CustomTabTabPersistencePolicy mPersistencePolicy;
    private final TabModelFilterFactory mTabModelFilterFactory;
    private final Lazy<ActivityWindowAndroid> mActivityWindowAndroid;
    private final OneshotSupplier<ProfileProvider> mProfileProviderSupplier;
    private final Lazy<CustomTabDelegateFactory> mCustomTabDelegateFactory;
    private final BrowserServicesIntentDataProvider mIntentDataProvider;
    private final TabCreatorManager mTabCreatorManager;
    private final Supplier<TabModelSelector> mTabModelSelectorSupplier;
    private final Supplier<CompositorViewHolder> mCompositorViewHolderSupplier;

    private final Lazy<AsyncTabParamsManager> mAsyncTabParamsManager;

    @Nullable private CustomTabsTabModelOrchestrator mTabModelOrchestrator;
    @ActivityType int mActivityType;

    @Inject
    public CustomTabActivityTabFactory(
            Activity activity,
            CustomTabTabPersistencePolicy persistencePolicy,
            ChromeTabModelFilterFactory tabModelFilterFactory,
            Lazy<ActivityWindowAndroid> activityWindowAndroid,
            OneshotSupplier<ProfileProvider> profileProviderSupplier,
            Lazy<CustomTabDelegateFactory> customTabDelegateFactory,
            BrowserServicesIntentDataProvider intentDataProvider,
            Lazy<AsyncTabParamsManager> asyncTabParamsManager,
            TabCreatorManager tabCreatorManager,
            Supplier<TabModelSelector> tabModelSelectorSupplier,
            Supplier<CompositorViewHolder> compositorViewHolderSupplier) {
        mActivity = activity;
        mPersistencePolicy = persistencePolicy;
        mTabModelFilterFactory = tabModelFilterFactory;
        mActivityWindowAndroid = activityWindowAndroid;
        mProfileProviderSupplier = profileProviderSupplier;
        mCustomTabDelegateFactory = customTabDelegateFactory;
        mIntentDataProvider = intentDataProvider;
        mAsyncTabParamsManager = asyncTabParamsManager;
        mTabCreatorManager = tabCreatorManager;
        mTabModelSelectorSupplier = tabModelSelectorSupplier;
        mCompositorViewHolderSupplier = compositorViewHolderSupplier;
    }

    public void setActivityType(int activityType) {
        mActivityType = activityType;
    }

    /** Creates a {@link TabModelOrchestrator} for the custom tab. */
    public TabModelOrchestrator createTabModelOrchestrator() {
        mTabModelOrchestrator = new CustomTabsTabModelOrchestrator();
        return mTabModelOrchestrator;
    }

    public void destroyTabModelOrchestrator() {
        if (mTabModelOrchestrator != null) {
            mTabModelOrchestrator.destroy();
        }
    }

    /** Calls the {@link TabModelOrchestrator} to create TabModels and TabPersistentStore. */
    public void createTabModels() {
        mTabModelOrchestrator.createTabModels(
                mProfileProviderSupplier,
                mTabCreatorManager,
                mTabModelFilterFactory,
                mPersistencePolicy,
                mActivityType,
                mAsyncTabParamsManager.get());
    }

    /** Returns the previously created {@link TabModelSelector}. */
    public TabModelSelectorBase getTabModelSelector() {
        getTabModelOrchestrator();
        if (mTabModelOrchestrator.getTabModelSelector() == null) {
            assert false;
            createTabModels();
        }
        return mTabModelOrchestrator.getTabModelSelector();
    }

    /** Returns the previously created {@link CustomTabsTabModelOrchestrator}. */
    public CustomTabsTabModelOrchestrator getTabModelOrchestrator() {
        if (mTabModelOrchestrator == null) {
            assert false;
            createTabModelOrchestrator();
        }
        return mTabModelOrchestrator;
    }

    /** Creates a {@link ChromeTabCreator}s for the custom tab. */
    public Pair<ChromeTabCreator, ChromeTabCreator> createTabCreators() {
        return Pair.create(createTabCreator(false), createTabCreator(true));
    }

    private ChromeTabCreator createTabCreator(boolean incognito) {
        return new ChromeTabCreator(
                mActivity,
                mActivityWindowAndroid.get(),
                mCustomTabDelegateFactory::get,
                mProfileProviderSupplier,
                incognito,
                AsyncTabParamsManagerSingleton.getInstance(),
                mTabModelSelectorSupplier,
                mCompositorViewHolderSupplier,
                null);
    }

    /** Creates a new tab for a Custom Tab activity */
    public Tab createTab(
            WebContents webContents, TabDelegateFactory delegateFactory, Callback<Tab> action) {
        Intent intent = mIntentDataProvider.getIntent();
        Profile profile =
                ProfileProvider.getOrCreateProfile(
                        mProfileProviderSupplier.get(), mIntentDataProvider.isOffTheRecord());
        return TabBuilder.createLiveTab(profile, /* initiallyHidden= */ false)
                .setId(IntentHandler.getTabId(intent))
                .setWindow(mActivityWindowAndroid.get())
                .setLaunchType(TabLaunchType.FROM_EXTERNAL_APP)
                .setWebContents(webContents)
                .setDelegateFactory(delegateFactory)
                .setPreInitializeAction(action)
                .build();
    }
}