Commit 87ef6569 authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

Add tab reparenting support to the TabModel/Selector classes

Bug: 1055228
Change-Id: Icac03f005a378c5b2f15b56641f3c754817fdb47
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2123313
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755145}
parent 71e8ceb9
...@@ -1340,11 +1340,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent> ...@@ -1340,11 +1340,7 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE_TAB_REPARENTING)) { if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE_TAB_REPARENTING)) {
mNightModeReparentingController = new NightModeReparentingController( mNightModeReparentingController = new NightModeReparentingController(
ReparentingDelegateFactory.createNightModeReparentingControllerDelegate( ReparentingDelegateFactory.createNightModeReparentingControllerDelegate(
getActivityTabProvider(), getTabModelSelector()), getActivityTabProvider(), getTabModelSelector()));
ReparentingDelegateFactory.createReparentingTaskDelegate(
getCompositorViewHolder(), getWindowAndroid(),
getTabDelegateFactory()));
mNightModeReparentingController.onNativeInitialized();
} }
} }
......
...@@ -4,16 +4,11 @@ ...@@ -4,16 +4,11 @@
package org.chromium.chrome.browser.night_mode; package org.chromium.chrome.browser.night_mode;
import android.util.SparseArray;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ActivityTabProvider;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabCreationState;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask; import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
import org.chromium.chrome.browser.tabmodel.AsyncTabParams;
import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.TabList; import org.chromium.chrome.browser.tabmodel.TabList;
import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel;
...@@ -21,9 +16,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; ...@@ -21,9 +16,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabReparentingParams; import org.chromium.chrome.browser.tabmodel.TabReparentingParams;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** Controls the reparenting of tabs when the theme is swapped. */ /** Controls the reparenting of tabs when the theme is swapped. */
public class NightModeReparentingController implements NightModeStateProvider.Observer { public class NightModeReparentingController implements NightModeStateProvider.Observer {
...@@ -40,119 +33,45 @@ public class NightModeReparentingController implements NightModeStateProvider.Ob ...@@ -40,119 +33,45 @@ public class NightModeReparentingController implements NightModeStateProvider.Ob
} }
private Delegate mDelegate; private Delegate mDelegate;
private ReparentingTask.Delegate mReparentingDelegate;
/** Constructs a {@link NightModeReparentingController} with the given delegate. */ /** Constructs a {@link NightModeReparentingController} with the given delegate. */
public NightModeReparentingController( public NightModeReparentingController(@NonNull Delegate delegate) {
@NonNull Delegate delegate, @NonNull ReparentingTask.Delegate reparentingDelegate) {
mDelegate = delegate; mDelegate = delegate;
mReparentingDelegate = reparentingDelegate;
}
public void onNativeInitialized() {
// Iterate through the params stored in AsyncTabParams and find the tabs stored by
// #onNightModeStateChanged. Reparent the background tabs and store the foreground tab
// to be reparented last.
TabReparentingParams foregroundTabParams = null;
SparseArray<AsyncTabParams> paramsArray = AsyncTabParamsManager.getAsyncTabParams().clone();
for (int i = 0; i < paramsArray.size(); i++) {
int tabId = paramsArray.keyAt(i);
AsyncTabParams params = paramsArray.get(tabId);
if (!(params instanceof TabReparentingParams)) continue;
final TabReparentingParams reparentingParams = (TabReparentingParams) params;
if (!reparentingParams.isFromNightModeReparenting()) continue;
if (!reparentingParams.hasTabToReparent()) continue;
final ReparentingTask reparentingTask =
ReparentingTask.get(reparentingParams.getTabToReparent());
if (reparentingTask == null) continue;
final TabModel tabModel = mDelegate.getTabModelSelector().getModel(
reparentingParams.getTabToReparent().isIncognito());
if (tabModel == null) {
AsyncTabParamsManager.remove(tabId);
return;
}
if (reparentingParams.isForegroundTab()) {
foregroundTabParams = reparentingParams;
} else {
reattachTab(reparentingTask, reparentingParams, tabModel);
}
}
if (foregroundTabParams == null) return;
final TabModel tabModel = mDelegate.getTabModelSelector().getModel(
foregroundTabParams.getTabToReparent().isIncognito());
if (tabModel == null) return;
ReparentingTask task = ReparentingTask.get(foregroundTabParams.getTabToReparent());
reattachTab(task, foregroundTabParams, tabModel);
}
/** Reattach the given task/pair to the activity/tab-model. */
private void reattachTab(ReparentingTask task, TabReparentingParams params, TabModel tabModel) {
final Tab tab = params.getTabToReparent();
task.finish(mReparentingDelegate, () -> {
int tabIndex = params.getTabIndex() > tabModel.getCount() ? -1 : params.getTabIndex();
tabModel.addTab(tab, tabIndex, TabLaunchType.FROM_REPARENTING,
TabCreationState.LIVE_IN_FOREGROUND);
AsyncTabParamsManager.remove(tab.getId());
});
} }
@Override @Override
public void onNightModeStateChanged() { public void onNightModeStateChanged() {
Tab foregroundTab = mDelegate.getActivityTabProvider().get(); // TODO(crbug.com/1065201): Make tab models detachable.
Map<TabModel, List<Tab>> tabsAndModels = getTabModelAndTabs(); TabModelSelector selector = mDelegate.getTabModelSelector();
for (final TabModel model : tabsAndModels.keySet()) { // Close tabs pending closure before saving params.
List<Tab> tabs = tabsAndModels.get(model); selector.getModel(false).commitAllTabClosures();
for (int i = 0; i < tabs.size(); i++) { selector.getModel(true).commitAllTabClosures();
Tab tab = tabs.get(i);
// Aggregate all the tabs.
// Intentionally skip new tab pages and allow them to reload and restore scroll List<Tab> tabs = new ArrayList<>(selector.getTotalTabCount());
// state themselves. populateComprehensiveTabsFromModel(selector.getModel(false), tabs);
if (mDelegate.isNTPUrl(tab.getUrlString())) continue; populateComprehensiveTabsFromModel(selector.getModel(true), tabs);
TabReparentingParams params = new TabReparentingParams(tab, null, null); // Save all the tabs in memory to be retrieved after restart.
params.setFromNightModeReparenting(true); mDelegate.getTabModelSelector().enterReparentingMode();
params.setIsForegroundTab(tab == foregroundTab); for (int i = 0; i < tabs.size(); i++) {
params.setTabIndex(i); Tab tab = tabs.get(i);
AsyncTabParamsManager.add(tab.getId(), params); // Intentionally skip new tab pages and allow them to reload and restore scroll
ReparentingTask.from(tab).detach(); // state themselves.
} if (mDelegate.isNTPUrl(tab.getUrlString())) continue;
TabReparentingParams params = new TabReparentingParams(tab, null, null);
AsyncTabParamsManager.add(tab.getId(), params);
ReparentingTask.from(tab).detach();
} }
// Save the current state to overwrite tab state that was previously saved to disk. See
// crbug.com/1042565 for more info.
mDelegate.getTabModelSelector().saveState();
} }
/** @return Mapping from TabModel to all the Tabs in that model. */ static void populateComprehensiveTabsFromModel(TabModel model, List<Tab> outputTabs) {
Map<TabModel, List<Tab>> getTabModelAndTabs() {
Map<TabModel, List<Tab>> tabsAndModels = new HashMap<>();
TabModel model = mDelegate.getTabModelSelector().getModel(false);
tabsAndModels.put(model, getTabsForModel(model));
model = mDelegate.getTabModelSelector().getModel(true);
tabsAndModels.put(model, getTabsForModel(model));
return tabsAndModels;
}
/** @return All of a model's Tabs as a List. */
List<Tab> getTabsForModel(TabModel model) {
List<Tab> tabs = new ArrayList<>();
if (model == null) return tabs;
TabList tabList = model.getComprehensiveModel(); TabList tabList = model.getComprehensiveModel();
for (int i = 0; i < tabList.getCount(); i++) { for (int i = 0; i < tabList.getCount(); i++) {
tabs.add(tabList.getTabAt(i)); outputTabs.add(tabList.getTabAt(i));
} }
return tabs;
} }
} }
...@@ -351,7 +351,28 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator { ...@@ -351,7 +351,28 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator {
Tab parent = selector != null ? selector.getTabById(state.parentId) : null; Tab parent = selector != null ? selector.getTabById(state.parentId) : null;
boolean selectTab = mOrderController.willOpenInForeground( boolean selectTab = mOrderController.willOpenInForeground(
TabLaunchType.FROM_RESTORE, state.isIncognito()); TabLaunchType.FROM_RESTORE, state.isIncognito());
Tab tab = TabBuilder.createFromFrozenState() AsyncTabParams asyncParams = AsyncTabParamsManager.remove(id);
Tab tab = null;
@TabLaunchType
int launchType = TabLaunchType.FROM_RESTORE;
@TabCreationState
int creationState = TabCreationState.FROZEN_ON_RESTORE;
if (asyncParams != null && asyncParams.getTabToReparent() != null) {
creationState = TabCreationState.LIVE_IN_BACKGROUND;
TabReparentingParams params = (TabReparentingParams) asyncParams;
tab = params.getTabToReparent();
if (tab.isIncognito() != state.isIncognito()) {
throw new IllegalStateException("Incognito state mismatch");
}
ReparentingTask.from(tab).finish(
ReparentingDelegateFactory.createReparentingTaskDelegate(
mActivity.getCompositorViewHolder(), mActivity.getWindowAndroid(),
createDefaultTabDelegateFactory()),
params.getFinalizeCallback());
}
if (tab == null) {
tab = TabBuilder.createFromFrozenState()
.setId(id) .setId(id)
.setParent(parent) .setParent(parent)
.setIncognito(state.isIncognito()) .setIncognito(state.isIncognito())
...@@ -360,9 +381,9 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator { ...@@ -360,9 +381,9 @@ public class ChromeTabCreator extends TabCreatorManager.TabCreator {
.setInitiallyHidden(!selectTab) .setInitiallyHidden(!selectTab)
.setTabState(state) .setTabState(state)
.build(); .build();
}
assert state.isIncognito() == mIncognito; assert state.isIncognito() == mIncognito;
mTabModel.addTab( mTabModel.addTab(tab, index, launchType, creationState);
tab, index, TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE);
return tab; return tab;
} }
......
...@@ -32,6 +32,11 @@ public interface TabModelDelegate { ...@@ -32,6 +32,11 @@ public interface TabModelDelegate {
*/ */
boolean isCurrentModel(TabModel model); boolean isCurrentModel(TabModel model);
/**
* @return Whether reparenting is currently in progress for this TabModel.
*/
boolean isReparentingInProgress();
// TODO(aurimas): clean these methods up. // TODO(aurimas): clean these methods up.
TabModel getCurrentModel(); TabModel getCurrentModel();
TabModel getModel(boolean incognito); TabModel getModel(boolean incognito);
......
...@@ -106,8 +106,11 @@ public class TabModelImpl extends TabModelJniBridge { ...@@ -106,8 +106,11 @@ public class TabModelImpl extends TabModelJniBridge {
@Override @Override
public void destroy() { public void destroy() {
for (Tab tab : mTabs) { // When reparenting tabs, only commit that tab closures and keep the rest of the tabs alive.
if (tab.isInitialized()) tab.destroy(); if (!mModelDelegate.isReparentingInProgress()) {
for (Tab tab : mTabs) {
if (tab.isInitialized()) tab.destroy();
}
} }
mRewoundList.destroy(); mRewoundList.destroy();
...@@ -752,6 +755,8 @@ public class TabModelImpl extends TabModelJniBridge { ...@@ -752,6 +755,8 @@ public class TabModelImpl extends TabModelJniBridge {
* before destroying it. * before destroying it.
*/ */
public void destroy() { public void destroy() {
// All tabs pending closure are committed in TabModelImpl#destroy.
if (TabModelImpl.this.mModelDelegate.isReparentingInProgress()) return;
for (Tab tab : mRewoundTabs) { for (Tab tab : mRewoundTabs) {
if (tab.isInitialized()) tab.destroy(); if (tab.isInitialized()) tab.destroy();
} }
......
...@@ -163,12 +163,6 @@ public interface TabModelSelector { ...@@ -163,12 +163,6 @@ public interface TabModelSelector {
*/ */
void commitAllTabClosures(); void commitAllTabClosures();
/**
* Save the current state of the tab model. Usage of this method is discouraged due to it
* writing to disk.
**/
void saveState();
/** /**
* Sets the delegate to handle the requests to close tabs in a single model. * Sets the delegate to handle the requests to close tabs in a single model.
* @param delegate The delegate to be used. * @param delegate The delegate to be used.
...@@ -192,6 +186,15 @@ public interface TabModelSelector { ...@@ -192,6 +186,15 @@ public interface TabModelSelector {
*/ */
void mergeState(); void mergeState();
/**
* Prevents the TabModelSelector from destroying its tabs to allow for reparenting.
*
* This is only safe to be called immediately before destruction. After entering reparenting
* mode, all the tabs are removed and stored in memory and on disk. The app is recreated right
* after, so there should never be a need to "exit" reparenting mode.
*/
void enterReparentingMode();
/** /**
* Destroy all owned {@link TabModel}s and {@link Tab}s referenced by this selector. * Destroy all owned {@link TabModel}s and {@link Tab}s referenced by this selector.
*/ */
......
...@@ -36,6 +36,7 @@ public abstract class TabModelSelectorBase implements TabModelSelector { ...@@ -36,6 +36,7 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
private final ObserverList<TabModelSelectorObserver> mObservers = new ObserverList<>(); private final ObserverList<TabModelSelectorObserver> mObservers = new ObserverList<>();
private boolean mTabStateInitialized; private boolean mTabStateInitialized;
private boolean mStartIncognito; private boolean mStartIncognito;
private boolean mReparentingInProgress;
private final TabCreatorManager mTabCreatorManager; private final TabCreatorManager mTabCreatorManager;
...@@ -194,9 +195,6 @@ public abstract class TabModelSelectorBase implements TabModelSelector { ...@@ -194,9 +195,6 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
} }
} }
@Override
public void saveState() {}
@Override @Override
public Tab getTabById(int id) { public Tab getTabById(int id) {
for (int i = 0; i < getModels().size(); i++) { for (int i = 0; i < getModels().size(); i++) {
...@@ -291,4 +289,14 @@ public abstract class TabModelSelectorBase implements TabModelSelector { ...@@ -291,4 +289,14 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
protected TabCreatorManager getTabCreatorManager() { protected TabCreatorManager getTabCreatorManager() {
return mTabCreatorManager; return mTabCreatorManager;
} }
@Override
public void enterReparentingMode() {
mReparentingInProgress = true;
}
/** @see TabModelDelegate#isReparentingInProgress */
protected boolean isReparentingInProgress() {
return mReparentingInProgress;
}
} }
...@@ -193,7 +193,9 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod ...@@ -193,7 +193,9 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
@Override @Override
public void onActivityAttachmentChanged(Tab tab, boolean attached) { public void onActivityAttachmentChanged(Tab tab, boolean attached) {
if (!attached) getModel(tab.isIncognito()).removeTab(tab); if (!attached && !isReparentingInProgress()) {
getModel(tab.isIncognito()).removeTab(tab);
}
} }
@Override @Override
...@@ -263,7 +265,10 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod ...@@ -263,7 +265,10 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
return isIncognitoSelected() == model.isIncognito(); return isIncognitoSelected() == model.isIncognito();
} }
@Override /**
* Save the current state of the tab model. Usage of this method is discouraged due to it
* writing to disk.
*/
public void saveState() { public void saveState() {
commitAllTabClosures(); commitAllTabClosures();
mTabSaver.saveState(); mTabSaver.saveState();
...@@ -393,6 +398,11 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod ...@@ -393,6 +398,11 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
return mSessionRestoreInProgress.get(); return mSessionRestoreInProgress.get();
} }
@Override
public boolean isReparentingInProgress() {
return super.isReparentingInProgress();
}
// TODO(tedchoc): Remove the need for this to be exposed. // TODO(tedchoc): Remove the need for this to be exposed.
@Override @Override
public void notifyChanged() { public void notifyChanged() {
......
...@@ -23,10 +23,6 @@ public class TabReparentingParams implements AsyncTabParams { ...@@ -23,10 +23,6 @@ public class TabReparentingParams implements AsyncTabParams {
private final Intent mOriginalIntent; private final Intent mOriginalIntent;
private final Runnable mFinalizeCallback; private final Runnable mFinalizeCallback;
private int mTabIndex = TAB_INDEX_NOT_SET;
private boolean mIsFromNightModeReparenting;
private boolean mIsForegroundTab;
/** /**
* Basic constructor for {@link TabReparentingParams}. * Basic constructor for {@link TabReparentingParams}.
*/ */
...@@ -82,36 +78,4 @@ public class TabReparentingParams implements AsyncTabParams { ...@@ -82,36 +78,4 @@ public class TabReparentingParams implements AsyncTabParams {
public void destroy() { public void destroy() {
if (mTabToReparent != null) mTabToReparent.destroy(); if (mTabToReparent != null) mTabToReparent.destroy();
} }
// Night mode reparenting implementation.
/** Set the tab index for later retrieval. */
public void setTabIndex(int tabIndex) {
mTabIndex = tabIndex;
}
/** @return Index of the stored tab. */
public int getTabIndex() {
return mTabIndex;
}
/** Set whether these params are from night mode reparenting. */
public void setFromNightModeReparenting(boolean fromNightModeReparenting) {
mIsFromNightModeReparenting = fromNightModeReparenting;
}
/** @return Whether these params are from night mode reparenting. */
public boolean isFromNightModeReparenting() {
return mIsFromNightModeReparenting;
}
/** Set whether this is the foreground tab. */
public void setIsForegroundTab(boolean isForegroundTab) {
mIsForegroundTab = isForegroundTab;
}
/** @return Whether this is a foreground tab. */
public boolean isForegroundTab() {
return mIsForegroundTab;
}
} }
...@@ -123,6 +123,12 @@ public class TabModelSelectorObserverTestRule extends ChromeBrowserTestRule { ...@@ -123,6 +123,12 @@ public class TabModelSelectorObserverTestRule extends ChromeBrowserTestRule {
public boolean closeAllTabsRequest(boolean incognito) { public boolean closeAllTabsRequest(boolean incognito) {
return false; return false;
} }
@Override
public boolean isReparentingInProgress() {
return false;
}
}; };
mNormalTabModel = new TabModelSelectorTestTabModel( mNormalTabModel = new TabModelSelectorTestTabModel(
false, orderController, tabContentManager, tabPersistentStore, delegate); false, orderController, tabContentManager, tabPersistentStore, delegate);
......
...@@ -235,6 +235,11 @@ public class TabPersistentStoreTest { ...@@ -235,6 +235,11 @@ public class TabPersistentStoreTest {
public boolean isCurrentModel(TabModel model) { public boolean isCurrentModel(TabModel model) {
return false; return false;
} }
@Override
public boolean isReparentingInProgress() {
return super.isReparentingInProgress();
}
} }
static class MockTabPersistentStoreObserver extends TabPersistentStoreObserver { static class MockTabPersistentStoreObserver extends TabPersistentStoreObserver {
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
package org.chromium.chrome.browser.night_mode; package org.chromium.chrome.browser.night_mode;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
...@@ -84,8 +82,6 @@ public class NightModeReparentingControllerTest { ...@@ -84,8 +82,6 @@ public class NightModeReparentingControllerTest {
@Mock @Mock
ReparentingTask mTask; ReparentingTask mTask;
@Mock
ReparentingTask.Delegate mReparentingTaskDelegate;
MockTabModel mTabModel; MockTabModel mTabModel;
MockTabModel mIncognitoTabModel; MockTabModel mIncognitoTabModel;
...@@ -104,7 +100,7 @@ public class NightModeReparentingControllerTest { ...@@ -104,7 +100,7 @@ public class NightModeReparentingControllerTest {
mDelegate = new FakeNightModeReparentingDelegate(); mDelegate = new FakeNightModeReparentingDelegate();
mDelegate.setIsNTPUrl(false); mDelegate.setIsNTPUrl(false);
mController = new NightModeReparentingController(mDelegate, mReparentingTaskDelegate); mController = new NightModeReparentingController(mDelegate);
} }
@After @After
...@@ -124,18 +120,9 @@ public class NightModeReparentingControllerTest { ...@@ -124,18 +120,9 @@ public class NightModeReparentingControllerTest {
Assert.assertTrue(params instanceof TabReparentingParams); Assert.assertTrue(params instanceof TabReparentingParams);
TabReparentingParams trp = (TabReparentingParams) params; TabReparentingParams trp = (TabReparentingParams) params;
Assert.assertEquals(
"The index of the first tab stored should match it's index in the tab stack.", 0,
trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Tab tab = trp.getTabToReparent(); Tab tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(1, tab.getId());
verify(mTask, times(1)).detach(); verify(mTask, times(1)).detach();
mController.onNativeInitialized();
verify(mTask, times(1)).finish(anyObject(), anyObject());
} }
@Test @Test
...@@ -147,18 +134,6 @@ public class NightModeReparentingControllerTest { ...@@ -147,18 +134,6 @@ public class NightModeReparentingControllerTest {
Assert.assertFalse(AsyncTabParamsManager.hasParamsWithTabToReparent()); Assert.assertFalse(AsyncTabParamsManager.hasParamsWithTabToReparent());
} }
@Test
public void testReparenting_singleTab_currentModelNullOnStart() {
mForegroundTab = createAndAddMockTab(1, false);
mController.onNightModeStateChanged();
doReturn(null).when(mDelegate.getTabModelSelector()).getModel(anyBoolean());
mController.onNativeInitialized();
AsyncTabParams params = AsyncTabParamsManager.getAsyncTabParams().get(1);
Assert.assertNull(params);
}
@Test @Test
public void testReparenting_multipleTabs() { public void testReparenting_multipleTabs() {
mForegroundTab = createAndAddMockTab(1, false); mForegroundTab = createAndAddMockTab(1, false);
...@@ -167,29 +142,14 @@ public class NightModeReparentingControllerTest { ...@@ -167,29 +142,14 @@ public class NightModeReparentingControllerTest {
TabReparentingParams trp = TabReparentingParams trp =
(TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(1); (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(1);
Assert.assertEquals(
"The index of the first tab stored should match its index in the tab stack.", 0,
trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertTrue(trp.isForegroundTab());
Tab tab = trp.getTabToReparent(); Tab tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(1, tab.getId());
trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(2); trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(2);
Assert.assertEquals(1, trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertFalse(trp.isForegroundTab());
tab = trp.getTabToReparent(); tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(2, tab.getId());
verify(mTask, times(2)).detach(); verify(mTask, times(2)).detach();
mController.onNativeInitialized();
verify(mTask, times(2)).finish(anyObject(), anyObject());
} }
@Test @Test
...@@ -203,18 +163,10 @@ public class NightModeReparentingControllerTest { ...@@ -203,18 +163,10 @@ public class NightModeReparentingControllerTest {
Assert.assertTrue(params instanceof TabReparentingParams); Assert.assertTrue(params instanceof TabReparentingParams);
TabReparentingParams trp = (TabReparentingParams) params; TabReparentingParams trp = (TabReparentingParams) params;
Assert.assertEquals(1, trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertTrue(trp.isForegroundTab());
Tab tab = trp.getTabToReparent(); Tab tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(2, tab.getId());
verify(mTask, times(2)).detach(); verify(mTask, times(2)).detach();
mController.onNativeInitialized();
verify(mTask, times(2)).finish(anyObject(), anyObject());
} }
@Test @Test
...@@ -228,18 +180,11 @@ public class NightModeReparentingControllerTest { ...@@ -228,18 +180,11 @@ public class NightModeReparentingControllerTest {
Assert.assertTrue(params instanceof TabReparentingParams); Assert.assertTrue(params instanceof TabReparentingParams);
TabReparentingParams trp = (TabReparentingParams) params; TabReparentingParams trp = (TabReparentingParams) params;
Assert.assertEquals(0, trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertTrue(trp.isForegroundTab());
Tab tab = trp.getTabToReparent(); Tab tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(2, tab.getId());
verify(mTask, times(2)).detach(); verify(mTask, times(2)).detach();
mController.onNativeInitialized();
verify(mTask, times(2)).finish(anyObject(), anyObject());
} }
@Test @Test
...@@ -252,39 +197,15 @@ public class NightModeReparentingControllerTest { ...@@ -252,39 +197,15 @@ public class NightModeReparentingControllerTest {
// Check the foreground tab. // Check the foreground tab.
TabReparentingParams trp = TabReparentingParams trp =
(TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(2); (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(2);
Assert.assertEquals(1, trp.getTabIndex());
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertTrue(trp.isForegroundTab());
Tab tab = trp.getTabToReparent(); Tab tab = trp.getTabToReparent();
Assert.assertNotNull(tab); Assert.assertNotNull(tab);
Assert.assertEquals(2, tab.getId());
// Check the background tabs. // Check the background tabs.
trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(1); trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(1);
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertFalse(trp.isForegroundTab());
trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(3); trp = (TabReparentingParams) AsyncTabParamsManager.getAsyncTabParams().get(3);
Assert.assertTrue(trp.isFromNightModeReparenting());
Assert.assertFalse(trp.isForegroundTab());
verify(mTask, times(3)).detach(); verify(mTask, times(3)).detach();
mController.onNativeInitialized();
verify(mTask, times(3)).finish(anyObject(), anyObject());
}
@Test
public void testTabGetsStored_noTab() {
try {
mController.onNightModeStateChanged();
mController.onNativeInitialized();
verify(mTask, times(0)).finish(anyObject(), anyObject());
} catch (Exception e) {
Assert.assertTrue(
"NightModeReparentingController shouldn't crash even when there's no tab!",
false);
}
} }
/** /**
......
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