blob: 6fb583bb660dd73d45591c9e8afee0ddaed5a127 [file] [log] [blame]
// Copyright 2018 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.customtabs.dynamicmodule;
import android.content.Intent;
import android.support.customtabs.CustomTabsCallback;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.AppHooksModule;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest;
import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate;
import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.IntentBuilder;
import org.chromium.chrome.browser.dependency_injection.ModuleOverridesRule;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.content_public.browser.test.util.JavaScriptUtils;
import org.chromium.content_public.common.ContentSwitches;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.net.test.ServerCertificate;
import org.chromium.ui.base.PageTransition;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeoutException;
/**
* Instrumentation tests for the CustomTabsDynamicModuleNavigationObserver.
*/
@RunWith(ParameterizedRunner.class)
@UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1", "ignore-certificate-errors"})
public class CustomTabsDynamicModuleNavigationTest {
private final TestRule mModuleOverridesRule = new ModuleOverridesRule()
.setOverride(AppHooksModule.Factory.class, AppHooksModuleForTest::new);
private final CustomTabActivityTestRule mActivityRule = new CustomTabActivityTestRule();
@Rule
public final TestRule mOverrideModulesThenLaunchRule =
RuleChain.outerRule(mModuleOverridesRule).around(mActivityRule);
private String mTestPage;
private String mTestPage2;
private String mTestPage3;
private EmbeddedTestServer mTestServer;
/**
* Test against different module versions i.e. before and after API was introduced.
*/
@ClassParameter
private static List<ParameterSet> sModuleVersionsList = Arrays.asList(
new ParameterSet().value(1).name("API_1"), new ParameterSet().value(4).name("API_4"));
public CustomTabsDynamicModuleNavigationTest(int moduleVersion) {
CustomTabsDynamicModuleTestUtils.setModuleVersion(moduleVersion);
}
@Before
public void setUp() throws Exception {
LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
// Module managed hosts only work with HTTPS.
mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
InstrumentationRegistry.getInstrumentation().getContext(),
ServerCertificate.CERT_OK);
mTestPage = mTestServer.getURLWithHostName(
"google.com", "/chrome/test/data/android/google.html");
mTestPage2 = mTestServer.getURLWithHostName(
"google.com", "/chrome/test/data/android/simple.html");
mTestPage3 = mTestServer.getURLWithHostName(
"google.com", "/chrome/test/data/android/about.html");
// The EmbeddedTestServer uses a non standard port.
DynamicModuleCoordinator.setAllowNonStandardPortNumber(true);
}
@After
public void tearDown() {
mTestServer.stopAndDestroyServer();
DynamicModuleCoordinator.setAllowNonStandardPortNumber(false);
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.CCT_MODULE)
public void testModuleNavigationNotification() throws TimeoutException, InterruptedException {
Intent intent = new IntentBuilder(mTestPage).build();
mActivityRule.startCustomTabActivityWithIntent(intent);
mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
getActivity().getActivityTab());
mActivityRule.loadUrlInTab(mTestPage3, PageTransition.LINK,
getActivity().getActivityTab());
FakeCCTActivityDelegate activityDelegate =
(FakeCCTActivityDelegate) getModuleCoordinator().getActivityDelegateForTesting();
activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_STARTED,
0, 3);
activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_FINISHED,
0, 3);
activityDelegate.waitForFirstContentfulPaint(0, 3);
}
private CustomTabActivity getActivity() {
return mActivityRule.getActivity();
}
private DynamicModuleCoordinator getModuleCoordinator() {
return getActivity().getComponent().resolveDynamicModuleCoordinator();
}
/**
* Returns the text content of the document body.
*/
private String getDocumentContent() throws Exception {
Tab tab = getActivity().getActivityTab();
return JavaScriptUtils.executeJavaScriptAndWaitForResult(
tab.getWebContents(), "document.body.textContent");
}
private static final String HEADER_VALUE = "HEADER_VALUE";
private static final String HEADER_VALUE_QUOTED = "\"" + HEADER_VALUE + "\"";
private static final String NONE_QUOTED = "\"None\"";
// The managed url regex matches the URL. The custom header is added.
@Test
@SmallTest
@EnableFeatures(
{ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER})
public void
testHeaderShown() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
Intent intent = new IntentBuilder(finalURL)
.setModuleManagedUrlRegex(".*")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(HEADER_VALUE_QUOTED, getDocumentContent());
}
// The managed url regex matches the URL, but CCT_MODULE_CUSTOM_REQUEST_HEADER is disabled. The
// custom header is not added.
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.CCT_MODULE)
@DisableFeatures(ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER)
public void testHeaderFeatureDisabled() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
Intent intent = new IntentBuilder(finalURL)
.setModuleManagedUrlRegex(".*")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(NONE_QUOTED, getDocumentContent());
}
// The managed url regex doesn't match the URL. No custom header is added.
@Test
@SmallTest
@EnableFeatures(
{ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER})
public void
testHeaderNotShown() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
Intent intent = new IntentBuilder(finalURL)
.setModuleManagedUrlRegex("no-match")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(NONE_QUOTED, getDocumentContent());
}
// The managed url regex doesn't match the initial URL, but match the final
// URL after a redirect. A custom header is added.
@Test
@SmallTest
@EnableFeatures(
{ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER})
public void
testHeaderMatchFinalURLOnly() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
String redirectURL = mTestServer.getURL("/server-redirect?" + finalURL);
Intent intent = new IntentBuilder(redirectURL)
.setModuleManagedUrlRegex("^((?!redirect).)*$")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(HEADER_VALUE_QUOTED, getDocumentContent());
}
// The managed url regex matches the initial URL, but doesn't match the
// final URL after a redirect. The custom header must have been removed from
// the second request.
@Test
@SmallTest
@EnableFeatures(
{ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER})
public void
testHeaderMatchRedirectURLOnly() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
String redirectURL = mTestServer.getURL("/server-redirect?" + finalURL);
Intent intent = new IntentBuilder(redirectURL)
.setModuleManagedUrlRegex(".*redirect.*")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(NONE_QUOTED, getDocumentContent());
}
// The managed url regex matches the initial URL and the final URL after a
// redirect. The custom header is added to both requests.
@Test
@SmallTest
@EnableFeatures(
{ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER})
public void
testHeaderMatchBoth() throws Exception {
String finalURL = mTestServer.getURLWithHostName(
"google.com", "/echoheader?" + DynamicModuleConstants.MANAGED_URL_HEADER);
String redirectURL = mTestServer.getURL("/server-redirect?" + finalURL);
Intent intent = new IntentBuilder(redirectURL)
.setModuleManagedUrlRegex(".*")
.setModuleManagedUrlHeaderValue(HEADER_VALUE)
.build();
mActivityRule.startCustomTabActivityWithIntent(intent);
Assert.assertEquals(HEADER_VALUE_QUOTED, getDocumentContent());
}
}