Commit 04942507 authored by Anna Malova's avatar Anna Malova Committed by Commit Bot

Update X button behaviour if dynamic module exists.

Bug: 889916
Change-Id: I552a8c4e7da4e3916a0e8bb5378d4f60252c4cd6
Reviewed-on: https://chromium-review.googlesource.com/c/1329797
Commit-Queue: Anna Malova <amalova@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: default avatarMichael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609318}
parent 01577738
......@@ -110,7 +110,9 @@ import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.chrome.browser.webapps.WebappCustomTabTimeSpentLogger;
import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.NavigationEntry;
import org.chromium.content_public.browser.NavigationHistory;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.PageTransition;
......@@ -370,6 +372,32 @@ public class CustomTabActivity extends ChromeActivity<CustomTabActivityComponent
}
}
/**
* @return The index of the previous navigation history entry managed by a dynamic module
* or -1 if there is no such entry.
*/
private boolean goToModuleManagedNavigationIndex() {
if (mModuleActivityDelegate == null && mModuleCallback == null) return false;
NavigationController navigationController = getNavigationController();
if (navigationController == null) return false;
NavigationHistory history = navigationController.getNavigationHistory();
for (int i = history.getCurrentEntryIndex() - 1; i >= 0; i--) {
if (isModuleManagedUrl(history.getEntryAtIndex(i).getUrl())) {
navigationController.goToNavigationIndex(i);
return true;
}
}
return false;
}
@Nullable
private NavigationController getNavigationController() {
WebContents webContents = getActivityTab().getWebContents();
return webContents == null ? null : webContents.getNavigationController();
}
@VisibleForTesting
void maybeInitialiseDynamicModulePostMessageHandler(PostMessageBackend backend) {
// Only initialise the handler if the feature is enabled.
......@@ -592,6 +620,11 @@ public class CustomTabActivity extends ChromeActivity<CustomTabActivityComponent
if (mIntentDataProvider.shouldEnableEmbeddedMediaExperience()) {
RecordUserAction.record("CustomTabs.CloseButtonClicked.DownloadsUI");
}
if (goToModuleManagedNavigationIndex()) {
RecordUserAction.record(
"CustomTabs.CloseButtonClicked.GoToModuleManagedUrl");
return;
}
recordClientConnectionStatus();
finishAndClose(false);
}
......
......@@ -134,10 +134,12 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
"org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_URLS_REGEX";
/** The APK package to load the module from. */
@VisibleForTesting
/* package */ static final String EXTRA_MODULE_PACKAGE_NAME =
"org.chromium.chrome.browser.customtabs.EXTRA_MODULE_PACKAGE_NAME";
/** The class name of the module entry point. */
@VisibleForTesting
/* package */ static final String EXTRA_MODULE_CLASS_NAME =
"org.chromium.chrome.browser.customtabs.EXTRA_MODULE_CLASS_NAME";
......
......@@ -42,6 +42,7 @@ import android.support.customtabs.PostMessageBackend;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.support.test.uiautomator.UiDevice;
import android.support.v7.content.res.AppCompatResources;
import android.text.TextUtils;
import android.view.Menu;
......@@ -77,6 +78,7 @@ import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.AppHooksModule;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches;
......@@ -88,6 +90,7 @@ import org.chromium.chrome.browser.appmenu.AppMenuHandler;
import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
import org.chromium.chrome.browser.browserservices.Origin;
import org.chromium.chrome.browser.browserservices.OriginVerifier;
import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.firstrun.FirstRunStatus;
import org.chromium.chrome.browser.history.BrowsingHistoryBridge;
......@@ -117,6 +120,7 @@ import org.chromium.chrome.test.util.browser.TabTitleObserver;
import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.content_public.browser.test.util.ClickUtils;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.DOMUtils;
......@@ -124,12 +128,14 @@ import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.net.test.util.TestWebServer;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.mojom.WindowOpenDisposition;
import org.chromium.ui.test.util.UiRestriction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
......@@ -220,6 +226,9 @@ public class CustomTabActivityTest {
PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
mWebServer = TestWebServer.start();
ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class,
CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new);
}
@After
......@@ -236,6 +245,8 @@ public class CustomTabActivityTest {
if (handler != null) handler.hideAppMenu();
});
mWebServer.shutdown();
ModuleFactoryOverrides.clearOverrides();
}
private CustomTabActivity getActivity() {
......@@ -1110,6 +1121,119 @@ public class CustomTabActivityTest {
}
}
private void runAndWaitForActivityStopped(Runnable runnable)
throws TimeoutException, InterruptedException {
CallbackHelper cctHiddenCallback = new CallbackHelper();
ActivityStateListener listener = (activity, newState) -> {
if (activity == mCustomTabActivityTestRule.getActivity()
&& (newState == ActivityState.STOPPED || newState == ActivityState.DESTROYED)) {
cctHiddenCallback.notifyCalled();
}
};
ApplicationStatus.registerStateListenerForAllActivities(listener);
runnable.run();
cctHiddenCallback.waitForCallback("Hide cct", 0);
ApplicationStatus.unregisterActivityStateListener(listener);
}
/**
This test executes the following workflow assuming dynamic module has been loaded succesfully:
- moduleManagedUrl1 -> nav1.1 -> nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
- User hits the "close button", therefore goes back to modulemanagedUrl2
- User hits the Android back button, going returning to nav1.2
- User hits the "close button" again, going return to moduleManagedUrl1
- User hits the Android back button thereby closes CCT.
*/
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.CCT_MODULE)
public void testCloseButtonBehaviourWithDynamicModule()
throws InterruptedException, ExecutionException, TimeoutException {
String moduleManagedUrl1 = "https://www.google.com/search?q=cat";
String moduleManagedUrl2 = "https://www.google.com/search?q=dog";
Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
moduleManagedUrl1, "^https://www.google.com/search.*");
// Open CCT with moduleManagedUrl1 and navigate
// moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.TYPED,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
cctActivity.getActivityTab());
// click the close button and wait while tab page loaded
ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
// close button returns back to moduleManagedUrl2
Assert.assertEquals(moduleManagedUrl2, cctActivity.getActivityTab().getUrl());
// press the back button and wait while tab page loaded
UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mDevice.pressBack();
ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
// the back button returns to nav1.2
Assert.assertEquals(mTestPage2, cctActivity.getActivityTab().getUrl());
// click the close button and wait while tab page loaded
ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
// close button returns back to moduleManagedUrl1
Assert.assertEquals(moduleManagedUrl1, cctActivity.getActivityTab().getUrl());
// press back button and while cct is hidden
runAndWaitForActivityStopped(mDevice::pressBack);
}
/**
This test executes the following workflow assuming dynamic module has not been loaded:
- moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
- User hits the close button, thereby closes CCT
*/
@Test
@SmallTest
public void testCloseButtonBehaviourWithoutDynamicModule()
throws InterruptedException, ExecutionException, TimeoutException {
String moduleManagedUrl1 = "https://www.google.com/search?q=cat";
String moduleManagedUrl2 = "https://www.google.com/search?q=dog";
// Open CCT with moduleManagedUrl1 and navigate
// moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
InstrumentationRegistry.getTargetContext(), moduleManagedUrl1);
mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
cctActivity.getActivityTab());
mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
cctActivity.getActivityTab());
// click close button and wait while cct is hidden
runAndWaitForActivityStopped(() ->
ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)));
}
@Test
@SmallTest
@RetryOnFailure
......
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