Commit 90f36b6d authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

🤝 Finish Custom Tabs early when last tab is closed.

Bug: 1087108
Change-Id: Ibf1775d96ea5600a1c2d73ee31ef4db8fbe307e8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2228617Reviewed-by: default avatarPeter Kotwicz <pkotwicz@chromium.org>
Commit-Queue: Peter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#776873}
parent bb867b46
...@@ -94,9 +94,6 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ ...@@ -94,9 +94,6 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ
@Nullable @Nullable
private ToolbarManager mToolbarManager; private ToolbarManager mToolbarManager;
@Nullable
private BackHandler mBackHandler;
@Nullable @Nullable
private FinishHandler mFinishHandler; private FinishHandler mFinishHandler;
...@@ -204,26 +201,19 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ ...@@ -204,26 +201,19 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ
return true; return true;
} }
if (mBackHandler != null if (mToolbarManager != null && mToolbarManager.back()) return true;
&& mBackHandler.handleBackPressed(this::executeDefaultBackHandling)) {
return true;
}
executeDefaultBackHandling(); if (mTabController.onlyOneTabRemaining()) {
return true; // If we're closing the last tab, just finish the Activity manually. If we had called
} // mTabController.closeTab() and waited for the Activity to close as a result we would
// have a visual glitch: https://crbug.com/1087108.
private void executeDefaultBackHandling() { finish(USER_NAVIGATION);
if (mToolbarManager != null && mToolbarManager.back()) return; } else {
// mTabController.closeTab may result in either closing the only tab (through the back
// button or the close button), or swapping to the previous tab. In the first case we need
// finish to be called with USER_NAVIGATION reason.
mIsHandlingUserNavigation = true;
mTabController.closeTab(); mTabController.closeTab();
mIsHandlingUserNavigation = false;
} }
return true;
}
/** /**
* Handles close button navigation. * Handles close button navigation.
*/ */
...@@ -310,14 +300,6 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ ...@@ -310,14 +300,6 @@ public class CustomTabActivityNavigationController implements StartStopWithNativ
} }
} }
/**
* See {@link BackHandler}. Only one BackHandler at a time should be set.
*/
public void setBackHandler(BackHandler handler) {
assert mBackHandler == null : "Multiple BackHandlers not supported";
mBackHandler = handler;
}
/** /**
* Sets a {@link FinishHandler} to be notified when the custom tab is being closed. * Sets a {@link FinishHandler} to be notified when the custom tab is being closed.
*/ */
......
...@@ -181,8 +181,13 @@ public class CustomTabActivityTabController implements InflationObserver { ...@@ -181,8 +181,13 @@ public class CustomTabActivityTabController implements InflationObserver {
* {@link CustomTabActivityTabProvider.Observer#onAllTabsClosed}. * {@link CustomTabActivityTabProvider.Observer#onAllTabsClosed}.
*/ */
public void closeTab() { public void closeTab() {
mTabFactory.getTabModelSelector().getCurrentModel().closeTab(mTabProvider.getTab(), TabModel model = mTabFactory.getTabModelSelector().getCurrentModel();
false, false, false); model.closeTab(mTabProvider.getTab(), false, false, false);
}
public boolean onlyOneTabRemaining() {
TabModel model = mTabFactory.getTabModelSelector().getCurrentModel();
return model.getCount() == 1;
} }
public void closeAndForgetTab() { public void closeAndForgetTab() {
......
...@@ -9,8 +9,6 @@ import static org.mockito.ArgumentMatchers.anyInt; ...@@ -9,8 +9,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
...@@ -28,7 +26,6 @@ import org.robolectric.annotation.Config; ...@@ -28,7 +26,6 @@ import org.robolectric.annotation.Config;
import org.chromium.base.task.TaskTraits; import org.chromium.base.task.TaskTraits;
import org.chromium.base.task.test.ShadowPostTask; import org.chromium.base.task.test.ShadowPostTask;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.BackHandler;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishHandler; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishHandler;
import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason;
import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl; import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl;
...@@ -69,37 +66,9 @@ public class CustomTabActivityNavigationControllerTest { ...@@ -69,37 +66,9 @@ public class CustomTabActivityNavigationControllerTest {
env.tabProvider.setInitialTab(tab, TabCreationMode.DEFAULT); env.tabProvider.setInitialTab(tab, TabCreationMode.DEFAULT);
} }
@Test
public void handlesBackNavigation_IfExternalBackHandlerRejectsSynchronously() {
mNavigationController.setBackHandler(notHandledRunnable -> false);
mNavigationController.navigateOnBack();
verify(mTabController).closeTab();
}
@Test
public void handlesBackNavigation_IfExternalBackHandlerRejectsAsynchronously() {
ArgumentCaptor<Runnable> notHandledRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
BackHandler backHandler = mock(BackHandler.class);
doReturn(true).when(backHandler).handleBackPressed(notHandledRunnableCaptor.capture());
mNavigationController.setBackHandler(backHandler);
mNavigationController.navigateOnBack();
notHandledRunnableCaptor.getValue().run();
verify(mTabController).closeTab();
}
@Test
public void doesntHandlesBackNavigation_IfExternalBackHandlerAccepts() {
mNavigationController.setBackHandler(notHandledRunnable -> true);
mNavigationController.navigateOnBack();
verify(mTabController, never()).closeTab();
}
@Test @Test
public void finishes_IfBackNavigationClosesTheOnlyTab() { public void finishes_IfBackNavigationClosesTheOnlyTab() {
doAnswer((Answer<Void>) invocation -> { when(mTabController.onlyOneTabRemaining()).thenReturn(true);
env.tabProvider.swapTab(null);
return null;
}).when(mTabController).closeTab();
mNavigationController.navigateOnBack(); mNavigationController.navigateOnBack();
verify(mFinishHandler).onFinish(eq(FinishReason.USER_NAVIGATION)); verify(mFinishHandler).onFinish(eq(FinishReason.USER_NAVIGATION));
......
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