| Index: chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
|
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ef5551e36b2d4d85ef350a3b0f4a26d2ccc1042e
|
| --- /dev/null
|
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
|
| @@ -0,0 +1,293 @@
|
| +// Copyright 2015 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.externalnav;
|
| +
|
| +import android.app.Activity;
|
| +import android.app.Instrumentation;
|
| +import android.content.Intent;
|
| +import android.content.IntentFilter;
|
| +import android.os.SystemClock;
|
| +import android.test.FlakyTest;
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +import android.text.TextUtils;
|
| +
|
| +import org.chromium.base.test.util.DisabledTest;
|
| +import org.chromium.chrome.browser.ChromeActivity;
|
| +import org.chromium.chrome.browser.EmptyTabObserver;
|
| +import org.chromium.chrome.browser.Tab;
|
| +import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
|
| +import org.chromium.chrome.browser.tab.ChromeTab;
|
| +import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
|
| +import org.chromium.chrome.test.ChromeActivityTestCaseBase;
|
| +import org.chromium.chrome.test.util.TestHttpServerClient;
|
| +import org.chromium.content.browser.test.util.CallbackHelper;
|
| +import org.chromium.content.browser.test.util.Criteria;
|
| +import org.chromium.content.browser.test.util.CriteriaHelper;
|
| +import org.chromium.content_public.browser.LoadUrlParams;
|
| +import org.chromium.ui.base.PageTransition;
|
| +
|
| +import java.util.concurrent.TimeUnit;
|
| +import java.util.concurrent.TimeoutException;
|
| +
|
| +/**
|
| + * Test suite for verifying the behavior of various URL overriding actions.
|
| + */
|
| +public class UrlOverridingTest extends ChromeActivityTestCaseBase<ChromeActivity> {
|
| + private static final String BASE_URL = "chrome/test/data/android/url_overriding/";
|
| + private static final String NAVIGATION_FROM_TIMEOUT_PAGE =
|
| + BASE_URL + "navigation_from_timer.html";
|
| + private static final String NAVIGATION_FROM_TIMEOUT_PARENT_FRAME_PAGE =
|
| + BASE_URL + "navigation_from_timer_parent_frame.html";
|
| + private static final String NAVIGATION_FROM_USER_GESTURE_PAGE =
|
| + BASE_URL + "navigation_from_user_gesture.html";
|
| + private static final String NAVIGATION_FROM_USER_GESTURE_PARENT_FRAME_PAGE =
|
| + BASE_URL + "navigation_from_user_gesture_parent_frame.html";
|
| + private static final String NAVIGATION_FROM_XHR_CALLBACK_PAGE =
|
| + BASE_URL + "navigation_from_xhr_callback.html";
|
| + private static final String NAVIGATION_FROM_XHR_CALLBACK_PARENT_FRAME_PAGE =
|
| + BASE_URL + "navigation_from_xhr_callback_parent_frame.html";
|
| + private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_PAGE =
|
| + BASE_URL + "navigation_from_xhr_callback_and_short_timeout.html";
|
| + private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_LONG_TIMEOUT_PAGE =
|
| + BASE_URL + "navigation_from_xhr_callback_and_long_timeout.html";
|
| + private static final String NAVIGATION_WITH_FALLBACK_URL_PAGE =
|
| + BASE_URL + "navigation_with_fallback_url.html";
|
| + private static final String NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE =
|
| + BASE_URL + "navigation_with_fallback_url_parent_frame.html";
|
| + private static final String FALLBACK_LANDING_URL = BASE_URL + "hello.html";
|
| + private static final String OPEN_WINDOW_FROM_USER_GESTURE_PAGE =
|
| + BASE_URL + "open_window_from_user_gesture.html";
|
| +
|
| + private static class TestTabObserver extends EmptyTabObserver {
|
| + private final CallbackHelper mFinishCallback;
|
| + private final CallbackHelper mPageFailCallback;
|
| + private final CallbackHelper mLoadFailCallback;
|
| +
|
| + TestTabObserver(final CallbackHelper finishCallback, final CallbackHelper pageFailCallback,
|
| + final CallbackHelper loadFailCallback) {
|
| + mFinishCallback = finishCallback;
|
| + mPageFailCallback = pageFailCallback;
|
| + mLoadFailCallback = loadFailCallback;
|
| + }
|
| +
|
| + @Override
|
| + public void onPageLoadFinished(Tab tab) {
|
| + mFinishCallback.notifyCalled();
|
| + }
|
| +
|
| + @Override
|
| + public void onPageLoadFailed(Tab tab, int errorCode) {
|
| + mPageFailCallback.notifyCalled();
|
| + }
|
| +
|
| + @Override
|
| + public void onDidFailLoad(Tab tab, boolean isProvisionalLoad, boolean isMainFrame,
|
| + int errorCode, String description, String failingUrl) {
|
| + mLoadFailCallback.notifyCalled();
|
| + }
|
| +
|
| + @Override
|
| + public void onDestroyed(Tab tab) {
|
| + // A new tab is destroyed when loading is overridden while opening it.
|
| + mPageFailCallback.notifyCalled();
|
| + }
|
| + }
|
| +
|
| + public UrlOverridingTest() {
|
| + super(ChromeActivity.class);
|
| + }
|
| +
|
| + @Override
|
| + protected void setUp() throws Exception {
|
| + super.setUp();
|
| + IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW);
|
| + filter.addCategory(Intent.CATEGORY_BROWSABLE);
|
| + filter.addDataScheme("market");
|
| + getInstrumentation().addMonitor(
|
| + filter, new Instrumentation.ActivityResult(Activity.RESULT_OK, null), true);
|
| + }
|
| +
|
| + private void loadUrlAndWaitForIntentUrl(final String url, boolean needClick,
|
| + boolean shouldLaunchExternalIntent, final String expectedFinalUrl, boolean isMainFrame)
|
| + throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + url, needClick, 0, shouldLaunchExternalIntent, expectedFinalUrl, isMainFrame);
|
| + }
|
| +
|
| + private void loadUrlAndWaitForIntentUrl(final String url, boolean needClick,
|
| + int expectedNewTabCount, final boolean shouldLaunchExternalIntent,
|
| + final String expectedFinalUrl, boolean isMainFrame) throws InterruptedException {
|
| + final CallbackHelper finishCallback = new CallbackHelper();
|
| + final CallbackHelper pageFailCallback = new CallbackHelper();
|
| + final CallbackHelper loadFailCallback = new CallbackHelper();
|
| + final CallbackHelper newTabCallback = new CallbackHelper();
|
| +
|
| + final Tab tab = getActivity().getActivityTab();
|
| + final Tab[] latestTabHolder = new Tab[1];
|
| + latestTabHolder[0] = tab;
|
| + tab.addObserver(new TestTabObserver(finishCallback, pageFailCallback, loadFailCallback));
|
| + if (expectedNewTabCount > 0) {
|
| + getActivity().getTabModelSelector().addObserver(new EmptyTabModelSelectorObserver() {
|
| + @Override
|
| + public void onNewTabCreated(Tab newTab) {
|
| + newTabCallback.notifyCalled();
|
| + newTab.addObserver(new TestTabObserver(
|
| + finishCallback, pageFailCallback, loadFailCallback));
|
| + latestTabHolder[0] = newTab;
|
| + }
|
| + });
|
| + }
|
| +
|
| + getActivity().onUserInteraction();
|
| + getInstrumentation().runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + tab.loadUrl(new LoadUrlParams(url, PageTransition.LINK));
|
| + }
|
| + });
|
| +
|
| + if (finishCallback.getCallCount() == 0) {
|
| + try {
|
| + finishCallback.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
|
| + } catch (TimeoutException ex) {
|
| + fail();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + SystemClock.sleep(1);
|
| + getActivity().onUserInteraction();
|
| + if (needClick) {
|
| + singleClickView(tab.getView());
|
| + }
|
| +
|
| + CallbackHelper helper = isMainFrame ? pageFailCallback : loadFailCallback;
|
| + if (helper.getCallCount() == 0) {
|
| + try {
|
| + helper.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
|
| + } catch (TimeoutException ex) {
|
| + fail();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + assertEquals(expectedNewTabCount, newTabCallback.getCallCount());
|
| + // For sub frames, the |loadFailCallback| run through different threads
|
| + // from the ExternalNavigationHandler. As a result, there is no guarantee
|
| + // when url override result would come.
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(
|
| + new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + // Note that we do not distinguish between OVERRIDE_WITH_CLOBBERING_TAB
|
| + // and NO_OVERRIDE since tab clobbering will eventually lead to NO_OVERRIDE.
|
| + // in the tab. Rather, we check the final URL to distinguish between
|
| + // fallback and normal navigation. See crbug.com/487364 for more.
|
| + ChromeTab tab = (ChromeTab) latestTabHolder[0];
|
| + if (shouldLaunchExternalIntent
|
| + != (OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT
|
| + == tab.getLastOverrideUrlLoadingResultForTests())) {
|
| + return false;
|
| + }
|
| + if (expectedFinalUrl == null) {
|
| + return TextUtils.equals(url, tab.getUrl());
|
| + } else {
|
| + return TextUtils.equals(expectedFinalUrl, tab.getUrl());
|
| + }
|
| + }
|
| + }));
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromTimer() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_TIMEOUT_PAGE), false,
|
| + false, null, true);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromTimerInSubFrame() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_FROM_TIMEOUT_PARENT_FRAME_PAGE), false,
|
| + false, null, false);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromUserGesture() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_USER_GESTURE_PAGE),
|
| + true, true, null, true);
|
| + }
|
| +
|
| + /*
|
| + * crbug.com/485665.
|
| + * @SmallTest
|
| + */
|
| + @FlakyTest
|
| + public void testNavigationFromUserGestureInSubFrame() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_FROM_USER_GESTURE_PARENT_FRAME_PAGE), true,
|
| + true, null, false);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromXHRCallback() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_PAGE),
|
| + true, true, null, true);
|
| + }
|
| +
|
| + /*
|
| + * crbug.com/485665.
|
| + * @SmallTest
|
| + */
|
| + @FlakyTest
|
| + public void testNavigationFromXHRCallbackInSubFrame() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_PARENT_FRAME_PAGE), true,
|
| + true, null, false);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromXHRCallbackAndShortTimeout() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_PAGE),
|
| + true, true, null, true);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationFromXHRCallbackAndLongTimeout() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_AND_LONG_TIMEOUT_PAGE),
|
| + true, false, null, true);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationWithFallbackURL() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_WITH_FALLBACK_URL_PAGE),
|
| + true, false, TestHttpServerClient.getUrl(FALLBACK_LANDING_URL), true);
|
| + }
|
| +
|
| + @SmallTest
|
| + public void testNavigationWithFallbackURLInSubFrame() throws InterruptedException {
|
| + // Fallback URL from a subframe will not trigger main or sub frame navigation.
|
| + loadUrlAndWaitForIntentUrl(
|
| + TestHttpServerClient.getUrl(NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE), true,
|
| + false, null, false);
|
| + }
|
| +
|
| + /**
|
| + * crbug.com/477260.
|
| + * @SmallTest
|
| + * @Restriction(RESTRICTION_TYPE_TABLET)
|
| + */
|
| + @DisabledTest
|
| + public void testOpenWindowFromUserGesture() throws InterruptedException {
|
| + loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(OPEN_WINDOW_FROM_USER_GESTURE_PAGE),
|
| + true, 1, true, null, true);
|
| + }
|
| +
|
| + @Override
|
| + public void startMainActivity() throws InterruptedException {
|
| + startMainActivityOnBlankPage();
|
| + }
|
| +}
|
|
|