chromium/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorObserverTestRule.java

// Copyright 2016 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.tabmodel;

import androidx.test.core.app.ApplicationProvider;

import org.junit.runner.Description;
import org.junit.runners.model.Statement;

import org.chromium.base.CommandLine;
import org.chromium.base.ThreadUtils;
import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton;
import org.chromium.chrome.browser.flags.ActivityType;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tab.TabSelectionType;
import org.chromium.chrome.browser.tab_ui.TabContentManager;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
import org.chromium.chrome.test.ChromeBrowserTestRule;
import org.chromium.content_public.browser.LoadUrlParams;

import java.util.HashSet;
import java.util.Set;

/** Basis for testing tab model selector observers. */
public class TabModelSelectorObserverTestRule extends ChromeBrowserTestRule {
    // Test activity type that does not restore tab on cold restart.
    // Any type other than ActivityType.TABBED works.
    private static final @ActivityType int NO_RESTORE_TYPE = ActivityType.CUSTOM_TAB;
    private TabModelSelectorBase mSelector;
    private TabModelSelectorTestTabModel mNormalTabModel;
    private TabModelSelectorTestIncognitoTabModel mIncognitoTabModel;

    public TabModelSelectorBase getSelector() {
        return mSelector;
    }

    public TabModelSelectorTestTabModel getNormalTabModel() {
        return mNormalTabModel;
    }

    public TabModelSelectorTestIncognitoTabModel getIncognitoTabModel() {
        return mIncognitoTabModel;
    }

    @Override
    public Statement apply(final Statement base, Description description) {
        CommandLine.init(null);
        return super.apply(
                new Statement() {
                    @Override
                    public void evaluate() throws Throwable {
                        setUp();
                        base.evaluate();
                    }
                },
                description);
    }

    private void setUp() {
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    initialize();
                });
    }

    private void initialize() {
        mSelector =
                new TabModelSelectorBase(null, TabGroupModelFilter::new, false) {
                    @Override
                    public void requestToShowTab(Tab tab, int type) {}

                    @Override
                    public boolean isSessionRestoreInProgress() {
                        return false;
                    }

                    @Override
                    public Tab openNewTab(
                            LoadUrlParams loadUrlParams,
                            @TabLaunchType int type,
                            Tab parent,
                            boolean incognito) {
                        return null;
                    }
                };

        TabModelOrderController orderController = new TabModelOrderControllerImpl(mSelector);
        TabContentManager tabContentManager =
                new TabContentManager(
                        ApplicationProvider.getApplicationContext(),
                        null,
                        false,
                        mSelector::getTabById,
                        TabWindowManagerSingleton.getInstance());
        tabContentManager.initWithNative();
        NextTabPolicySupplier nextTabPolicySupplier = () -> NextTabPolicy.HIERARCHICAL;
        AsyncTabParamsManager asyncTabParamsManager = AsyncTabParamsManagerSingleton.getInstance();

        TabModelDelegate delegate =
                new TabModelDelegate() {
                    @Override
                    public void selectModel(boolean incognito) {
                        mSelector.selectModel(incognito);
                    }

                    @Override
                    public void requestToShowTab(Tab tab, @TabSelectionType int type) {}

                    @Override
                    public boolean isSessionRestoreInProgress() {
                        return false;
                    }

                    @Override
                    public TabModel getModel(boolean incognito) {
                        return mSelector.getModel(incognito);
                    }

                    @Override
                    public TabModel getCurrentModel() {
                        return mSelector.getCurrentModel();
                    }

                    @Override
                    public boolean isReparentingInProgress() {
                        return false;
                    }
                };

        mNormalTabModel =
                new TabModelSelectorTestTabModel(
                        ProfileManager.getLastUsedRegularProfile(),
                        orderController,
                        tabContentManager,
                        nextTabPolicySupplier,
                        asyncTabParamsManager,
                        NO_RESTORE_TYPE,
                        delegate);

        mIncognitoTabModel =
                new TabModelSelectorTestIncognitoTabModel(
                        ProfileManager.getLastUsedRegularProfile()
                                .getPrimaryOTRProfile(/* createIfNeeded= */ true),
                        orderController,
                        tabContentManager,
                        nextTabPolicySupplier,
                        asyncTabParamsManager,
                        delegate);

        mSelector.initialize(mNormalTabModel, mIncognitoTabModel);
    }

    /** Test TabModel that exposes the needed capabilities for testing. */
    public static class TabModelSelectorTestTabModel extends TabModelImpl {
        private Set<TabModelObserver> mObserverSet = new HashSet<>();

        public TabModelSelectorTestTabModel(
                Profile profile,
                TabModelOrderController orderController,
                TabContentManager tabContentManager,
                NextTabPolicySupplier nextTabPolicySupplier,
                AsyncTabParamsManager asyncTabParamsManager,
                @ActivityType int activityType,
                TabModelDelegate modelDelegate) {
            super(
                    profile,
                    activityType,
                    null,
                    null,
                    orderController,
                    tabContentManager,
                    nextTabPolicySupplier,
                    asyncTabParamsManager,
                    modelDelegate,
                    /* supportUndo= */ false,
                    /* trackInNativeModelList= */ true);
        }

        @Override
        public void addObserver(TabModelObserver observer) {
            super.addObserver(observer);
            mObserverSet.add(observer);
        }

        @Override
        public void removeObserver(TabModelObserver observer) {
            super.removeObserver(observer);
            mObserverSet.remove(observer);
        }

        public Set<TabModelObserver> getObservers() {
            return mObserverSet;
        }
    }

    /** Test IncognitoTabModel that exposes the needed capabilities for testing. */
    private static class TabModelSelectorTestIncognitoTabModel extends TabModelSelectorTestTabModel
            implements IncognitoTabModel {
        public TabModelSelectorTestIncognitoTabModel(
                Profile profile,
                TabModelOrderController orderController,
                TabContentManager tabContentManager,
                NextTabPolicySupplier nextTabPolicySupplier,
                AsyncTabParamsManager asyncTabParamsManager,
                TabModelDelegate modelDelegate) {
            super(
                    ProfileManager.getLastUsedRegularProfile()
                            .getPrimaryOTRProfile(/* createIfNeeded= */ true),
                    orderController,
                    tabContentManager,
                    nextTabPolicySupplier,
                    asyncTabParamsManager,
                    NO_RESTORE_TYPE,
                    modelDelegate);
        }

        @Override
        public void addIncognitoObserver(IncognitoTabModelObserver observer) {}

        @Override
        public void removeIncognitoObserver(IncognitoTabModelObserver observer) {}
    }
}