OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.externalnav; |
| 6 |
| 7 import android.app.Activity; |
| 8 import android.app.Instrumentation; |
| 9 import android.content.Intent; |
| 10 import android.content.IntentFilter; |
| 11 import android.os.SystemClock; |
| 12 import android.test.FlakyTest; |
| 13 import android.test.suitebuilder.annotation.SmallTest; |
| 14 import android.text.TextUtils; |
| 15 |
| 16 import org.chromium.base.test.util.DisabledTest; |
| 17 import org.chromium.chrome.browser.ChromeActivity; |
| 18 import org.chromium.chrome.browser.EmptyTabObserver; |
| 19 import org.chromium.chrome.browser.Tab; |
| 20 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.Overrid
eUrlLoadingResult; |
| 21 import org.chromium.chrome.browser.tab.ChromeTab; |
| 22 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; |
| 23 import org.chromium.chrome.test.ChromeActivityTestCaseBase; |
| 24 import org.chromium.chrome.test.util.TestHttpServerClient; |
| 25 import org.chromium.content.browser.test.util.CallbackHelper; |
| 26 import org.chromium.content.browser.test.util.Criteria; |
| 27 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 28 import org.chromium.content_public.browser.LoadUrlParams; |
| 29 import org.chromium.ui.base.PageTransition; |
| 30 |
| 31 import java.util.concurrent.TimeUnit; |
| 32 import java.util.concurrent.TimeoutException; |
| 33 |
| 34 /** |
| 35 * Test suite for verifying the behavior of various URL overriding actions. |
| 36 */ |
| 37 public class UrlOverridingTest extends ChromeActivityTestCaseBase<ChromeActivity
> { |
| 38 private static final String BASE_URL = "chrome/test/data/android/url_overrid
ing/"; |
| 39 private static final String NAVIGATION_FROM_TIMEOUT_PAGE = |
| 40 BASE_URL + "navigation_from_timer.html"; |
| 41 private static final String NAVIGATION_FROM_TIMEOUT_PARENT_FRAME_PAGE = |
| 42 BASE_URL + "navigation_from_timer_parent_frame.html"; |
| 43 private static final String NAVIGATION_FROM_USER_GESTURE_PAGE = |
| 44 BASE_URL + "navigation_from_user_gesture.html"; |
| 45 private static final String NAVIGATION_FROM_USER_GESTURE_PARENT_FRAME_PAGE = |
| 46 BASE_URL + "navigation_from_user_gesture_parent_frame.html"; |
| 47 private static final String NAVIGATION_FROM_XHR_CALLBACK_PAGE = |
| 48 BASE_URL + "navigation_from_xhr_callback.html"; |
| 49 private static final String NAVIGATION_FROM_XHR_CALLBACK_PARENT_FRAME_PAGE = |
| 50 BASE_URL + "navigation_from_xhr_callback_parent_frame.html"; |
| 51 private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_P
AGE = |
| 52 BASE_URL + "navigation_from_xhr_callback_and_short_timeout.html"; |
| 53 private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_LONG_TIMEOUT_PA
GE = |
| 54 BASE_URL + "navigation_from_xhr_callback_and_long_timeout.html"; |
| 55 private static final String NAVIGATION_WITH_FALLBACK_URL_PAGE = |
| 56 BASE_URL + "navigation_with_fallback_url.html"; |
| 57 private static final String NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE = |
| 58 BASE_URL + "navigation_with_fallback_url_parent_frame.html"; |
| 59 private static final String FALLBACK_LANDING_URL = BASE_URL + "hello.html"; |
| 60 private static final String OPEN_WINDOW_FROM_USER_GESTURE_PAGE = |
| 61 BASE_URL + "open_window_from_user_gesture.html"; |
| 62 |
| 63 private static class TestTabObserver extends EmptyTabObserver { |
| 64 private final CallbackHelper mFinishCallback; |
| 65 private final CallbackHelper mPageFailCallback; |
| 66 private final CallbackHelper mLoadFailCallback; |
| 67 |
| 68 TestTabObserver(final CallbackHelper finishCallback, final CallbackHelpe
r pageFailCallback, |
| 69 final CallbackHelper loadFailCallback) { |
| 70 mFinishCallback = finishCallback; |
| 71 mPageFailCallback = pageFailCallback; |
| 72 mLoadFailCallback = loadFailCallback; |
| 73 } |
| 74 |
| 75 @Override |
| 76 public void onPageLoadFinished(Tab tab) { |
| 77 mFinishCallback.notifyCalled(); |
| 78 } |
| 79 |
| 80 @Override |
| 81 public void onPageLoadFailed(Tab tab, int errorCode) { |
| 82 mPageFailCallback.notifyCalled(); |
| 83 } |
| 84 |
| 85 @Override |
| 86 public void onDidFailLoad(Tab tab, boolean isProvisionalLoad, boolean is
MainFrame, |
| 87 int errorCode, String description, String failingUrl) { |
| 88 mLoadFailCallback.notifyCalled(); |
| 89 } |
| 90 |
| 91 @Override |
| 92 public void onDestroyed(Tab tab) { |
| 93 // A new tab is destroyed when loading is overridden while opening i
t. |
| 94 mPageFailCallback.notifyCalled(); |
| 95 } |
| 96 } |
| 97 |
| 98 public UrlOverridingTest() { |
| 99 super(ChromeActivity.class); |
| 100 } |
| 101 |
| 102 @Override |
| 103 protected void setUp() throws Exception { |
| 104 super.setUp(); |
| 105 IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW); |
| 106 filter.addCategory(Intent.CATEGORY_BROWSABLE); |
| 107 filter.addDataScheme("market"); |
| 108 getInstrumentation().addMonitor( |
| 109 filter, new Instrumentation.ActivityResult(Activity.RESULT_OK, n
ull), true); |
| 110 } |
| 111 |
| 112 private void loadUrlAndWaitForIntentUrl(final String url, boolean needClick, |
| 113 boolean shouldLaunchExternalIntent, final String expectedFinalUrl, b
oolean isMainFrame) |
| 114 throws InterruptedException { |
| 115 loadUrlAndWaitForIntentUrl( |
| 116 url, needClick, 0, shouldLaunchExternalIntent, expectedFinalUrl,
isMainFrame); |
| 117 } |
| 118 |
| 119 private void loadUrlAndWaitForIntentUrl(final String url, boolean needClick, |
| 120 int expectedNewTabCount, final boolean shouldLaunchExternalIntent, |
| 121 final String expectedFinalUrl, boolean isMainFrame) throws Interrupt
edException { |
| 122 final CallbackHelper finishCallback = new CallbackHelper(); |
| 123 final CallbackHelper pageFailCallback = new CallbackHelper(); |
| 124 final CallbackHelper loadFailCallback = new CallbackHelper(); |
| 125 final CallbackHelper newTabCallback = new CallbackHelper(); |
| 126 |
| 127 final Tab tab = getActivity().getActivityTab(); |
| 128 final Tab[] latestTabHolder = new Tab[1]; |
| 129 latestTabHolder[0] = tab; |
| 130 tab.addObserver(new TestTabObserver(finishCallback, pageFailCallback, lo
adFailCallback)); |
| 131 if (expectedNewTabCount > 0) { |
| 132 getActivity().getTabModelSelector().addObserver(new EmptyTabModelSel
ectorObserver() { |
| 133 @Override |
| 134 public void onNewTabCreated(Tab newTab) { |
| 135 newTabCallback.notifyCalled(); |
| 136 newTab.addObserver(new TestTabObserver( |
| 137 finishCallback, pageFailCallback, loadFailCallback))
; |
| 138 latestTabHolder[0] = newTab; |
| 139 } |
| 140 }); |
| 141 } |
| 142 |
| 143 getActivity().onUserInteraction(); |
| 144 getInstrumentation().runOnMainSync(new Runnable() { |
| 145 @Override |
| 146 public void run() { |
| 147 tab.loadUrl(new LoadUrlParams(url, PageTransition.LINK)); |
| 148 } |
| 149 }); |
| 150 |
| 151 if (finishCallback.getCallCount() == 0) { |
| 152 try { |
| 153 finishCallback.waitForCallback(0, 1, 20, TimeUnit.SECONDS); |
| 154 } catch (TimeoutException ex) { |
| 155 fail(); |
| 156 return; |
| 157 } |
| 158 } |
| 159 |
| 160 SystemClock.sleep(1); |
| 161 getActivity().onUserInteraction(); |
| 162 if (needClick) { |
| 163 singleClickView(tab.getView()); |
| 164 } |
| 165 |
| 166 CallbackHelper helper = isMainFrame ? pageFailCallback : loadFailCallbac
k; |
| 167 if (helper.getCallCount() == 0) { |
| 168 try { |
| 169 helper.waitForCallback(0, 1, 20, TimeUnit.SECONDS); |
| 170 } catch (TimeoutException ex) { |
| 171 fail(); |
| 172 return; |
| 173 } |
| 174 } |
| 175 |
| 176 assertEquals(expectedNewTabCount, newTabCallback.getCallCount()); |
| 177 // For sub frames, the |loadFailCallback| run through different threads |
| 178 // from the ExternalNavigationHandler. As a result, there is no guarante
e |
| 179 // when url override result would come. |
| 180 assertTrue(CriteriaHelper.pollForUIThreadCriteria( |
| 181 new Criteria() { |
| 182 @Override |
| 183 public boolean isSatisfied() { |
| 184 // Note that we do not distinguish between OVERRIDE_WITH
_CLOBBERING_TAB |
| 185 // and NO_OVERRIDE since tab clobbering will eventually
lead to NO_OVERRIDE. |
| 186 // in the tab. Rather, we check the final URL to disting
uish between |
| 187 // fallback and normal navigation. See crbug.com/487364
for more. |
| 188 ChromeTab tab = (ChromeTab) latestTabHolder[0]; |
| 189 if (shouldLaunchExternalIntent |
| 190 != (OverrideUrlLoadingResult.OVERRIDE_WITH_EXTER
NAL_INTENT |
| 191 == tab.getLastOverrideUrlLoadingResultFo
rTests())) { |
| 192 return false; |
| 193 } |
| 194 if (expectedFinalUrl == null) { |
| 195 return TextUtils.equals(url, tab.getUrl()); |
| 196 } else { |
| 197 return TextUtils.equals(expectedFinalUrl, tab.getUrl
()); |
| 198 } |
| 199 } |
| 200 })); |
| 201 } |
| 202 |
| 203 @SmallTest |
| 204 public void testNavigationFromTimer() throws InterruptedException { |
| 205 loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_T
IMEOUT_PAGE), false, |
| 206 false, null, true); |
| 207 } |
| 208 |
| 209 @SmallTest |
| 210 public void testNavigationFromTimerInSubFrame() throws InterruptedException
{ |
| 211 loadUrlAndWaitForIntentUrl( |
| 212 TestHttpServerClient.getUrl(NAVIGATION_FROM_TIMEOUT_PARENT_FRAME
_PAGE), false, |
| 213 false, null, false); |
| 214 } |
| 215 |
| 216 @SmallTest |
| 217 public void testNavigationFromUserGesture() throws InterruptedException { |
| 218 loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_U
SER_GESTURE_PAGE), |
| 219 true, true, null, true); |
| 220 } |
| 221 |
| 222 /* |
| 223 * crbug.com/485665. |
| 224 * @SmallTest |
| 225 */ |
| 226 @FlakyTest |
| 227 public void testNavigationFromUserGestureInSubFrame() throws InterruptedExce
ption { |
| 228 loadUrlAndWaitForIntentUrl( |
| 229 TestHttpServerClient.getUrl(NAVIGATION_FROM_USER_GESTURE_PARENT_
FRAME_PAGE), true, |
| 230 true, null, false); |
| 231 } |
| 232 |
| 233 @SmallTest |
| 234 public void testNavigationFromXHRCallback() throws InterruptedException { |
| 235 loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_FROM_X
HR_CALLBACK_PAGE), |
| 236 true, true, null, true); |
| 237 } |
| 238 |
| 239 /* |
| 240 * crbug.com/485665. |
| 241 * @SmallTest |
| 242 */ |
| 243 @FlakyTest |
| 244 public void testNavigationFromXHRCallbackInSubFrame() throws InterruptedExce
ption { |
| 245 loadUrlAndWaitForIntentUrl( |
| 246 TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_PARENT_
FRAME_PAGE), true, |
| 247 true, null, false); |
| 248 } |
| 249 |
| 250 @SmallTest |
| 251 public void testNavigationFromXHRCallbackAndShortTimeout() throws Interrupte
dException { |
| 252 loadUrlAndWaitForIntentUrl( |
| 253 TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_AND_SHO
RT_TIMEOUT_PAGE), |
| 254 true, true, null, true); |
| 255 } |
| 256 |
| 257 @SmallTest |
| 258 public void testNavigationFromXHRCallbackAndLongTimeout() throws Interrupted
Exception { |
| 259 loadUrlAndWaitForIntentUrl( |
| 260 TestHttpServerClient.getUrl(NAVIGATION_FROM_XHR_CALLBACK_AND_LON
G_TIMEOUT_PAGE), |
| 261 true, false, null, true); |
| 262 } |
| 263 |
| 264 @SmallTest |
| 265 public void testNavigationWithFallbackURL() throws InterruptedException { |
| 266 loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(NAVIGATION_WITH_F
ALLBACK_URL_PAGE), |
| 267 true, false, TestHttpServerClient.getUrl(FALLBACK_LANDING_URL),
true); |
| 268 } |
| 269 |
| 270 @SmallTest |
| 271 public void testNavigationWithFallbackURLInSubFrame() throws InterruptedExce
ption { |
| 272 // Fallback URL from a subframe will not trigger main or sub frame navig
ation. |
| 273 loadUrlAndWaitForIntentUrl( |
| 274 TestHttpServerClient.getUrl(NAVIGATION_WITH_FALLBACK_URL_PARENT_
FRAME_PAGE), true, |
| 275 false, null, false); |
| 276 } |
| 277 |
| 278 /** |
| 279 * crbug.com/477260. |
| 280 * @SmallTest |
| 281 * @Restriction(RESTRICTION_TYPE_TABLET) |
| 282 */ |
| 283 @DisabledTest |
| 284 public void testOpenWindowFromUserGesture() throws InterruptedException { |
| 285 loadUrlAndWaitForIntentUrl(TestHttpServerClient.getUrl(OPEN_WINDOW_FROM_
USER_GESTURE_PAGE), |
| 286 true, 1, true, null, true); |
| 287 } |
| 288 |
| 289 @Override |
| 290 public void startMainActivity() throws InterruptedException { |
| 291 startMainActivityOnBlankPage(); |
| 292 } |
| 293 } |
OLD | NEW |