Commit 314cbf4c authored by Henrique Nakashima's avatar Henrique Nakashima Committed by Chromium LUCI CQ

Create glue-layer TabModelOrchestrators

TabModelSelectorImpl does not create or destroy TabPersistentStore
anymore. Instead, TabModelOrchestrators manage the lifetime of TabModelSelectorImpl and
TabPersistentStore.

Give TabModelSelectorImpl a Supplier<TabPersistentStore> instead of
passing TabPersistentStore directly.

This is a step to break the two-way dependency between
TabModelSelectorImpl and TabPersistentStore.

Bug: 1138561
Change-Id: Ie2fa4a2735e509ff816b3e2cf5f8f6fffda7999c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2572639
Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarElla Ge <eirage@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835819}
parent 9ecc67d3
......@@ -86,8 +86,11 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/app/tabmodel/AsyncTabParamsManagerSingleton.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/ChromeNextTabPolicySupplier.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/ChromeTabModelFilterFactory.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/CustomTabsTabModelOrchestrator.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/DefaultTabModelSelectorFactory.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/TabModelOrchestrator.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/TabWindowManagerSingleton.java",
"java/src/org/chromium/chrome/browser/app/tabmodel/TabbedModeTabModelOrchestrator.java",
"java/src/org/chromium/chrome/browser/app/video_tutorials/ChromeLanguageInfoProvider.java",
"java/src/org/chromium/chrome/browser/app/video_tutorials/NewTabPageVideoIPHManager.java",
"java/src/org/chromium/chrome/browser/app/video_tutorials/VideoPlayerActivity.java",
......
......@@ -56,7 +56,9 @@ import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.ChromeNextTabPolicySupplier;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.TabbedModeTabModelOrchestrator;
import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator;
......@@ -242,6 +244,7 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
private ToolbarControlContainer mControlContainer;
private TabbedModeTabModelOrchestrator mTabModelOrchestrator;
private TabModelSelectorImpl mTabModelSelectorImpl;
private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
private TabModelSelectorTabModelObserver mTabModelObserver;
......@@ -1601,7 +1604,13 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
}
@Override
protected TabModelSelector createTabModelSelector() {
protected TabModelOrchestrator createTabModelOrchestrator() {
mTabModelOrchestrator = new TabbedModeTabModelOrchestrator();
return mTabModelOrchestrator;
}
@Override
protected void createTabModels() {
assert mTabModelSelectorImpl == null;
Bundle savedInstanceState = getSavedInstanceState();
......@@ -1612,17 +1621,15 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
int index = savedInstanceState != null ? savedInstanceState.getInt(WINDOW_INDEX, 0) : 0;
mNextTabPolicySupplier = new ChromeNextTabPolicySupplier(mOverviewModeBehaviorSupplier);
mTabModelSelectorImpl =
(TabModelSelectorImpl) TabWindowManagerSingleton.getInstance().requestSelector(
this, this, mNextTabPolicySupplier, index);
if (mTabModelSelectorImpl == null) {
Toast.makeText(
this, getString(R.string.unsupported_number_of_windows), Toast.LENGTH_LONG)
.show();
boolean tabModelWasCreated =
mTabModelOrchestrator.createTabModels(this, this, mNextTabPolicySupplier, index);
if (!tabModelWasCreated) {
finish();
return null;
return;
}
mTabModelSelectorImpl = mTabModelOrchestrator.getTabModelSelector();
mTabModelSelectorImpl.addObserver(new EmptyTabModelSelectorObserver() {
@Override
public void onTabStateInitialized() {
......@@ -1646,8 +1653,6 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
mAppIndexingUtil = new AppIndexingUtil(mTabModelSelectorImpl);
if (startIncognito) mTabModelSelectorImpl.selectModel(true);
return mTabModelSelectorImpl;
}
@Override
......@@ -2180,6 +2185,13 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
super.onDestroyInternal();
}
@Override
protected void destroyTabModels() {
if (mTabModelOrchestrator != null) {
mTabModelOrchestrator.destroy();
}
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
......
......@@ -69,6 +69,7 @@ import org.chromium.chrome.browser.app.flags.ChromeCachedFlags;
import org.chromium.chrome.browser.app.tab_activity_glue.ReparentingDelegateFactory;
import org.chromium.chrome.browser.app.tab_activity_glue.TabReparentingController;
import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
......@@ -239,7 +240,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
new TabModelSelectorProfileSupplier(mTabModelSelectorSupplier);
protected ObservableSupplierImpl<BookmarkBridge> mBookmarkBridgeSupplier =
new ObservableSupplierImpl<>();
private TabModelSelector mTabModelSelector;
private TabModelOrchestrator mTabModelOrchestrator;
private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
private TabCreator mRegularTabCreator;
private TabCreator mIncognitoTabCreator;
......@@ -261,7 +262,6 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
/** Whether or not {@link #postDeferredStartupIfNeeded()} has already successfully run. */
private boolean mDeferredStartupPosted;
private boolean mTabModelsInitialized;
private boolean mNativeInitialized;
private boolean mRemoveWindowBackgroundDone;
protected AccessibilityVisibilityHandler mAccessibilityVisibilityHandler;
......@@ -353,6 +353,9 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
// onPreInflationStartup event.
mComponent = createComponent();
// Create the orchestrator that manages Tab models and persistence
mTabModelOrchestrator = createTabModelOrchestrator();
// There's no corresponding call to removeObserver() for this addObserver() because
// mTabModelProfileSupplier has the same lifecycle as this activity.
mTabModelProfileSupplier.addObserver((profile) -> {
......@@ -478,9 +481,10 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
mCompositorViewHolder.getCompositorView());
initializeTabModels();
TabModelSelector tabModelSelector = mTabModelOrchestrator.getTabModelSelector();
setTabContentManager(new TabContentManager(this, getContentOffsetProvider(),
!SysUtils.isLowEndDevice(),
mTabModelSelector != null ? mTabModelSelector::getTabById : null));
tabModelSelector != null ? tabModelSelector::getTabById : null));
if (!isFinishing()) {
getBrowserControlsManager().initialize(
......@@ -642,28 +646,28 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
* this activity.
*/
public final void initializeTabModels() {
if (mTabModelsInitialized) return;
if (mTabModelOrchestrator.areTabModelsInitialized()) return;
mTabModelSelector = createTabModelSelector();
createTabModels();
TabModelSelector tabModelSelector = mTabModelOrchestrator.getTabModelSelector();
if (mTabModelSelector == null) {
if (tabModelSelector == null) {
assert isFinishing();
mTabModelsInitialized = true;
return;
}
mTabModelSelectorSupplier.set(mTabModelSelector);
mActivityTabProvider.setTabModelSelector(mTabModelSelector);
getStatusBarColorController().setTabModelSelector(mTabModelSelector);
mTabModelSelectorSupplier.set(tabModelSelector);
mActivityTabProvider.setTabModelSelector(tabModelSelector);
getStatusBarColorController().setTabModelSelector(tabModelSelector);
Pair<? extends TabCreator, ? extends TabCreator> tabCreators = createTabCreators();
mRegularTabCreator = tabCreators.first;
mIncognitoTabCreator = tabCreators.second;
OfflinePageUtils.observeTabModelSelector(this, mTabModelSelector);
OfflinePageUtils.observeTabModelSelector(this, tabModelSelector);
if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) {
mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(tabModelSelector) {
@Override
public void onLoadStopped(Tab tab, boolean toDifferentDocument) {
postDeferredStartupIfNeeded();
......@@ -680,8 +684,6 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
postDeferredStartupIfNeeded();
}
};
mTabModelsInitialized = true;
}
/**
......@@ -697,9 +699,19 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
}
/**
* @return The {@link TabModelSelector} owned by this {@link ChromeActivity}.
* @return The {@link TabModelOrchestrator} owned by this {@link ChromeActivity}.
*/
protected abstract TabModelOrchestrator createTabModelOrchestrator();
/**
* Call the {@link TabModelOrchestrator} to initialize its members.
*/
protected abstract TabModelSelector createTabModelSelector();
protected abstract void createTabModels();
/**
* Call the {@link TabModelOrchestrator} to destroy its members.
*/
protected abstract void destroyTabModels();
/**
* @return The {@link TabCreator}s owned
......@@ -826,7 +838,8 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
VrModuleProvider.getDelegate().onActivityHidden(this);
Tab tab = getActivityTab();
if (mTabModelSelector != null && !mTabModelSelector.isReparentingInProgress()
TabModelSelector tabModelSelector = mTabModelOrchestrator.getTabModelSelector();
if (tabModelSelector != null && !tabModelSelector.isReparentingInProgress()
&& tab != null) {
tab.hide(TabHidingType.ACTIVITY_HIDDEN);
}
......@@ -1288,10 +1301,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
mActivityTabStartupMetricsTracker = null;
}
if (mTabModelsInitialized) {
TabModelSelector selector = getTabModelSelector();
if (selector != null) selector.destroy();
}
destroyTabModels();
if (mBookmarkBridgeSupplier != null) {
BookmarkBridge bookmarkBridge = mBookmarkBridgeSupplier.get();
......@@ -1562,7 +1572,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
* @return Whether the tab models have been fully initialized.
*/
public boolean areTabModelsInitialized() {
return mTabModelsInitialized;
return mTabModelOrchestrator.areTabModelsInitialized();
}
/**
......@@ -1571,11 +1581,11 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
* @return The {@link TabModelSelector}, possibly null.
*/
public TabModelSelector getTabModelSelector() {
if (!mTabModelsInitialized) {
if (!mTabModelOrchestrator.areTabModelsInitialized()) {
throw new IllegalStateException(
"Attempting to access TabModelSelector before initialization");
}
return mTabModelSelector;
return mTabModelOrchestrator.getTabModelSelector();
}
/**
......@@ -1596,7 +1606,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
@Override
public TabCreator getTabCreator(boolean incognito) {
if (!mTabModelsInitialized) {
if (!mTabModelOrchestrator.areTabModelsInitialized()) {
throw new IllegalStateException(
"Attempting to access TabCreator before initialization");
}
......@@ -1663,7 +1673,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
* null if the Tab does not exist or the system is not initialized.
*/
public Tab getActivityTab() {
if (!mTabModelsInitialized) {
if (!mTabModelOrchestrator.areTabModelsInitialized()) {
return null;
}
return TabModelUtils.getCurrentTab(getCurrentTabModel());
......@@ -1674,7 +1684,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
* WebContents.
*/
public WebContents getCurrentWebContents() {
if (!mTabModelsInitialized) {
if (!mTabModelOrchestrator.areTabModelsInitialized()) {
return null;
}
return TabModelUtils.getCurrentWebContents(getCurrentTabModel());
......@@ -1997,7 +2007,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
if (id == R.id.help_id) {
String url = currentTab != null ? currentTab.getUrlString() : "";
Profile profile = mTabModelSelector.isIncognitoSelected()
Profile profile = getTabModelSelector().isIncognitoSelected()
? Profile.getLastUsedRegularProfile().getPrimaryOTRProfile()
: Profile.getLastUsedRegularProfile();
startHelpAndFeedback(url, "MobileMenuFeedback", profile);
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// 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.app.tabmodel;
import androidx.annotation.Nullable;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
import org.chromium.chrome.browser.tabmodel.TabModelFilterFactory;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
import org.chromium.ui.base.WindowAndroid;
import javax.inject.Inject;
/**
* Glue-level class that manages lifetime of root .tabmodel objects: {@link TabPersistentStore} and
* {@link TabModelSelectorImpl} for custom tabs.
*/
@ActivityScope
public class CustomTabsTabModelOrchestrator extends TabModelOrchestrator {
@Inject
public CustomTabsTabModelOrchestrator() {}
/**
* Creates the TabModelSelector and the TabPersistentStore.
*/
public void createTabModels(@Nullable Supplier<WindowAndroid> windowAndroidSupplier,
TabCreatorManager tabCreatorManager, TabModelFilterFactory tabModelFilterFactory,
TabPersistencePolicy persistencePolicy, AsyncTabParamsManager asyncTabParamsManager) {
// Instantiate TabModelSelectorImpl
NextTabPolicySupplier nextTabPolicySupplier = () -> NextTabPolicy.LOCATIONAL;
mTabModelSelector = new TabModelSelectorImpl(windowAndroidSupplier, tabCreatorManager,
tabModelFilterFactory, nextTabPolicySupplier, asyncTabParamsManager, false, false,
false);
// Instantiate TabPersistentStore
mTabPersistentStore =
new TabPersistentStore(persistencePolicy, mTabModelSelector, tabCreatorManager);
wireSelectorAndStore();
markTabModelsInitialized();
}
}
......@@ -5,19 +5,15 @@
package org.chromium.chrome.browser.app.tabmodel;
import android.app.Activity;
import android.os.Build;
import org.chromium.base.annotations.VerifiesOnN;
import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
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.TabModelSelectorFactory;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
/**
* Default {@link TabModelSelectorFactory} for Chrome.
......@@ -29,32 +25,11 @@ public class DefaultTabModelSelectorFactory implements TabModelSelectorFactory {
@Override
public TabModelSelector buildSelector(Activity activity, TabCreatorManager tabCreatorManager,
NextTabPolicySupplier nextTabPolicySupplier, int selectorIndex) {
// Merge tabs if this TabModelSelector is for a ChromeTabbedActivity created in
// fullscreen mode and there are no TabModelSelector's currently alive. This indicates
// that it is a cold start or process restart in fullscreen mode.
boolean mergeTabs = Build.VERSION.SDK_INT > Build.VERSION_CODES.M
&& MultiInstanceManager.isTabModelMergingEnabled()
&& !activity.isInMultiWindowMode();
if (MultiInstanceManager.shouldMergeOnStartup(activity)) {
mergeTabs = mergeTabs
&& (!MultiWindowUtils.getInstance().isInMultiDisplayMode(activity)
|| TabWindowManagerSingleton.getInstance()
.getNumberOfAssignedTabModelSelectors()
== 0);
} else {
mergeTabs = mergeTabs
&& TabWindowManagerSingleton.getInstance()
.getNumberOfAssignedTabModelSelectors()
== 0;
}
if (mergeTabs) {
MultiInstanceManager.mergedOnStartup();
}
TabPersistencePolicy persistencePolicy =
new TabbedModeTabPersistencePolicy(selectorIndex, mergeTabs);
TabModelFilterFactory tabModelFilterFactory = new ChromeTabModelFilterFactory();
return new TabModelSelectorImpl(activity, /*windowAndroidSupplier=*/null, tabCreatorManager,
persistencePolicy, tabModelFilterFactory, nextTabPolicySupplier,
AsyncTabParamsManagerSingleton.getInstance(), true, true, false);
AsyncTabParamsManager asyncTabParamsManager = AsyncTabParamsManagerSingleton.getInstance();
return new TabModelSelectorImpl(/*windowAndroidSupplier=*/null, tabCreatorManager,
tabModelFilterFactory, nextTabPolicySupplier, asyncTabParamsManager, true, true,
false);
}
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// 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.app.tabmodel;
import org.chromium.base.supplier.ObservableSupplierImpl;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
/**
* Implementers are glue-level objects that manage lifetime of root .tabmodel objects: {@link
* TabPersistentStore} and {@link TabModelSelectorImpl}.
*/
public abstract class TabModelOrchestrator {
protected TabPersistentStore mTabPersistentStore;
protected TabModelSelectorImpl mTabModelSelector;
private boolean mTabModelsInitialized;
/**
* @return Whether the tab models have been fully initialized.
*/
public boolean areTabModelsInitialized() {
return mTabModelsInitialized;
}
/**
* @return The {@link TabModelSelectorImpl} managed by this orchestrator.
*/
public TabModelSelectorImpl getTabModelSelector() {
return mTabModelSelector;
}
/**
* Destroy the {@link TabPersistentStore} and {@link TabModelSelectorImpl} members.
*/
public void destroy() {
if (!mTabModelsInitialized) {
return;
}
if (mTabPersistentStore != null) {
mTabPersistentStore.destroy();
mTabPersistentStore = null;
}
if (mTabModelSelector != null) {
mTabModelSelector.destroy();
mTabModelSelector = null;
}
mTabModelsInitialized = false;
}
protected void wireSelectorAndStore() {
// Supply TabModelSelectorImpl with TabPersistentStore.
//
// TODO(crbug.com/1138561): Remove this dependency by making TabModelSelectorImpl emit
// events and TabPersistentStore react to them as an observer.
ObservableSupplierImpl<TabPersistentStore> tabPersistentStoreSupplier =
new ObservableSupplierImpl<>();
tabPersistentStoreSupplier.set(mTabPersistentStore);
mTabModelSelector.setTabPersistentStoreSupplier(tabPersistentStoreSupplier);
// Notify TabModelSelectorImpl when TabPersistentStore initializes tab state
final TabPersistentStoreObserver persistentStoreObserver =
new TabPersistentStoreObserver() {
@Override
public void onStateLoaded() {
mTabModelSelector.markTabStateInitialized();
}
};
mTabPersistentStore.addObserver(persistentStoreObserver);
}
protected void markTabModelsInitialized() {
mTabModelsInitialized = true;
}
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// 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.app.tabmodel;
import android.app.Activity;
import android.os.Build;
import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
import org.chromium.ui.widget.Toast;
/**
* Glue-level class that manages lifetime of root .tabmodel objects: {@link TabPersistentStore} and
* {@link TabModelSelectorImpl} for tabbed mode.
*/
public class TabbedModeTabModelOrchestrator extends TabModelOrchestrator {
public TabbedModeTabModelOrchestrator() {}
/**
* Creates the TabModelSelector and the TabPersistentStore.
*
* @return Whether the creation was successful. It may fail is we reached the limit of number of
* windows.
*/
public boolean createTabModels(Activity activity, TabCreatorManager tabCreatorManager,
NextTabPolicySupplier nextTabPolicySupplier, int selectorIndex) {
boolean mergeTabs = shouldMergeTabs(activity);
if (mergeTabs) {
MultiInstanceManager.mergedOnStartup();
}
// Instantiate TabModelSelectorImpl
mTabModelSelector =
(TabModelSelectorImpl) TabWindowManagerSingleton.getInstance().requestSelector(
activity, tabCreatorManager, nextTabPolicySupplier, selectorIndex);
if (mTabModelSelector == null) {
markTabModelsInitialized();
Toast.makeText(activity,
activity.getString(
org.chromium.chrome.R.string.unsupported_number_of_windows),
Toast.LENGTH_LONG)
.show();
return false;
}
// Instantiate TabPersistentStore
TabPersistencePolicy tabPersistencePolicy =
new TabbedModeTabPersistencePolicy(selectorIndex, mergeTabs);
mTabPersistentStore =
new TabPersistentStore(tabPersistencePolicy, mTabModelSelector, tabCreatorManager);
wireSelectorAndStore();
markTabModelsInitialized();
return true;
}
private boolean shouldMergeTabs(Activity activity) {
// Merge tabs if this TabModelSelector is for a ChromeTabbedActivity created in
// fullscreen mode and there are no TabModelSelector's currently alive. This indicates
// that it is a cold start or process restart in fullscreen mode.
boolean mergeTabs = Build.VERSION.SDK_INT > Build.VERSION_CODES.M
&& MultiInstanceManager.isTabModelMergingEnabled()
&& !activity.isInMultiWindowMode();
if (MultiInstanceManager.shouldMergeOnStartup(activity)) {
mergeTabs = mergeTabs
&& (!MultiWindowUtils.getInstance().isInMultiDisplayMode(activity)
|| TabWindowManagerSingleton.getInstance()
.getNumberOfAssignedTabModelSelectors()
== 0);
} else {
mergeTabs = mergeTabs
&& TabWindowManagerSingleton.getInstance()
.getNumberOfAssignedTabModelSelectors()
== 0;
}
return mergeTabs;
}
}
......@@ -24,6 +24,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.KeyboardShortcuts;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.browserservices.ui.controller.Verifier;
import org.chromium.chrome.browser.browserservices.ui.trustedwebactivity.TrustedWebActivityCoordinator;
......@@ -45,7 +46,6 @@ import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabState;
import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
import org.chromium.chrome.browser.ui.RootUiCoordinator;
......@@ -293,8 +293,20 @@ public abstract class BaseCustomTabActivity extends ChromeActivity<BaseCustomTab
}
@Override
protected TabModelSelector createTabModelSelector() {
return mTabFactory.createTabModelSelector();
protected TabModelOrchestrator createTabModelOrchestrator() {
return mTabFactory.createTabModelOrchestrator();
}
@Override
protected void destroyTabModels() {
if (mTabFactory != null) {
mTabFactory.destroyTabModelOrchestrator();
}
}
@Override
protected void createTabModels() {
mTabFactory.createTabModels();
}
@Override
......
......@@ -15,6 +15,8 @@ import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.app.ChromeActivity;
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.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory;
import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
......@@ -26,7 +28,6 @@ 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.NextTabPolicy;
import org.chromium.chrome.browser.tabmodel.TabModelFilterFactory;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
......@@ -56,7 +57,7 @@ public class CustomTabActivityTabFactory {
private final Lazy<AsyncTabParamsManager> mAsyncTabParamsManager;
@Nullable
private TabModelSelectorImpl mTabModelSelector;
private CustomTabsTabModelOrchestrator mTabModelOrchestrator;
@Inject
public CustomTabActivityTabFactory(ChromeActivity<?> activity,
......@@ -77,21 +78,35 @@ public class CustomTabActivityTabFactory {
mAsyncTabParamsManager = asyncTabParamsManager;
}
/** Creates a {@link TabModelSelector} for the custom tab. */
public TabModelSelectorImpl createTabModelSelector() {
mTabModelSelector = new TabModelSelectorImpl(mActivity, mActivityWindowAndroid::get,
mActivity, mPersistencePolicy, mTabModelFilterFactory,
() -> NextTabPolicy.LOCATIONAL, mAsyncTabParamsManager.get(), false, false, false);
return mTabModelSelector;
/** 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(mActivityWindowAndroid::get, mActivity,
mTabModelFilterFactory, mPersistencePolicy, mAsyncTabParamsManager.get());
}
/** Returns the previously created {@link TabModelSelector}. */
public TabModelSelectorImpl getTabModelSelector() {
if (mTabModelSelector == null) {
if (mTabModelOrchestrator == null) {
assert false;
createTabModelOrchestrator();
}
if (mTabModelOrchestrator.getTabModelSelector() == null) {
assert false;
return createTabModelSelector();
createTabModels();
}
return mTabModelSelector;
return mTabModelOrchestrator.getTabModelSelector();
}
/** Creates a {@link ChromeTabCreator}s for the custom tab. */
......
......@@ -34,12 +34,11 @@ import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.ChromeTabbedActivity;
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.compositor.layouts.content.TabContentManager;
import org.chromium.chrome.browser.tab.MockTab;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabStateFileManager;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy;
import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
......@@ -456,12 +455,11 @@ public class CustomTabTabPersistencePolicyTest {
CustomTabActivity activity = new CustomTabActivity();
ApplicationStatus.onStateChangeForTesting(activity, ActivityState.CREATED);
NextTabPolicySupplier nextTabPolicySupplier = () -> NextTabPolicy.LOCATIONAL;
TabModelSelectorImpl selector = new TabModelSelectorImpl(activity,
activity::getWindowAndroid, activity, buildTestPersistencePolicy(),
new ChromeTabModelFilterFactory(), nextTabPolicySupplier,
AsyncTabParamsManagerSingleton.getInstance(), false, false, false);
CustomTabsTabModelOrchestrator orchestrator = new CustomTabsTabModelOrchestrator();
orchestrator.createTabModels(activity::getWindowAndroid, activity,
new ChromeTabModelFilterFactory(), buildTestPersistencePolicy(),
AsyncTabParamsManagerSingleton.getInstance());
TabModelSelectorImpl selector = orchestrator.getTabModelSelector();
selector.initializeForTesting(normalTabModel, incognitoTabModel);
ApplicationStatus.onStateChangeForTesting(activity, ActivityState.DESTROYED);
return selector;
......
......@@ -67,8 +67,7 @@ public class ContextMenuLoadUrlParamsTest {
public RecordingTabModelSelector(Activity activity, TabCreatorManager tabCreatorManager,
TabModelFilterFactory tabModelFilterFactory, int selectorIndex) {
super(activity, null, tabCreatorManager,
new TabbedModeTabPersistencePolicy(selectorIndex, false), tabModelFilterFactory,
super(null, tabCreatorManager, tabModelFilterFactory,
()
-> NextTabPolicy.HIERARCHICAL,
AsyncTabParamsManagerSingleton.getInstance(), false, false, false);
......
......@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton;
import org.chromium.chrome.browser.app.tabmodel.ChromeTabModelFilterFactory;
import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton;
import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelper;
import org.chromium.chrome.browser.flags.ActivityType;
......@@ -237,10 +238,16 @@ public class TabPersistentStoreTest {
}
@Override
protected TabModelSelector createTabModelSelector() {
protected TabModelOrchestrator createTabModelOrchestrator() {
return null;
}
@Override
protected void createTabModels() {}
@Override
protected void destroyTabModels() {}
@Override
protected BrowserControlsManager createBrowserControlsManager() {
return null;
......
......@@ -8,8 +8,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import android.app.Activity;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
......@@ -17,7 +15,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
......@@ -37,8 +34,6 @@ import org.chromium.ui.base.WindowAndroid;
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class TabModelSelectorImplTest {
@Mock
TabPersistencePolicy mMockTabPersistencePolicy;
@Mock
TabModelFilterFactory mMockTabModelFilterFactory;
@Mock
......@@ -50,27 +45,22 @@ public class TabModelSelectorImplTest {
private TabModelSelectorImpl mTabModelSelector;
private MockTabCreatorManager mTabCreatorManager;
private Activity mActivity;
@Before
public void setUp() {
mActivity = Robolectric.buildActivity(Activity.class).setup().get();
MockitoAnnotations.initMocks(this);
doReturn(TabPersistentStore.SAVED_STATE_FILE_PREFIX)
.when(mMockTabPersistencePolicy)
.getStateFileName();
doReturn(mock(TabModelFilter.class))
.when(mMockTabModelFilterFactory)
.createTabModelFilter(any());
mTabCreatorManager = new MockTabCreatorManager();
AsyncTabParamsManager realAsyncTabParamsManager =
AsyncTabParamsManagerFactory.createAsyncTabParamsManager();
mTabModelSelector = new TabModelSelectorImpl(mActivity, null, mTabCreatorManager,
mMockTabPersistencePolicy, mMockTabModelFilterFactory, mNextTabPolicySupplier,
realAsyncTabParamsManager, /*supportUndo=*/false,
mTabModelSelector = new TabModelSelectorImpl(null, mTabCreatorManager,
mMockTabModelFilterFactory, mNextTabPolicySupplier, realAsyncTabParamsManager,
/*supportUndo=*/false,
/*isTabbedActivity=*/false, /*startIncognito=*/false);
mTabModelSelector.setTabPersistentStoreSupplier(() -> null);
mTabCreatorManager.initialize(mTabModelSelector);
mTabModelSelector.onNativeLibraryReadyInternal(mMockTabContentManager,
new MockTabModel(false, null), new MockTabModel(true, null));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment