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.content.ComponentName; | |
8 import android.content.Context; | |
9 import android.content.Intent; | |
10 import android.content.pm.ActivityInfo; | |
11 import android.content.pm.PackageManager; | |
12 import android.content.pm.ResolveInfo; | |
13 import android.net.Uri; | |
14 import android.os.SystemClock; | |
15 import android.provider.Browser; | |
16 import android.test.InstrumentationTestCase; | |
17 import android.test.mock.MockContext; | |
18 import android.test.mock.MockPackageManager; | |
19 import android.test.suitebuilder.annotation.SmallTest; | |
20 | |
21 import org.chromium.base.CommandLine; | |
22 import org.chromium.chrome.browser.Tab; | |
23 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.Overrid
eUrlLoadingResult; | |
24 import org.chromium.chrome.browser.tab.TabRedirectHandler; | |
25 import org.chromium.chrome.browser.util.FeatureUtilities; | |
26 import org.chromium.ui.base.PageTransition; | |
27 | |
28 import java.net.URISyntaxException; | |
29 import java.util.ArrayList; | |
30 import java.util.List; | |
31 | |
32 /** | |
33 * Instrumentation tests for {@link ExternalNavigationHandler}. | |
34 */ | |
35 public class ExternalNavigationHandlerTest extends InstrumentationTestCase { | |
36 | |
37 // Expectations | |
38 private static final int IGNORE = 0x0; | |
39 private static final int START_INCOGNITO = 0x1; | |
40 private static final int START_ACTIVITY = 0x2; | |
41 private static final int INTENT_SANITIZATION_EXCEPTION = 0x4; | |
42 | |
43 private static final int NO_REDIRECT = 0x0; | |
44 private static final int REDIRECT = 0x1; | |
45 | |
46 private static final String SEARCH_RESULT_URL_FOR_TOM_HANKS = | |
47 "https://www.google.com/search?q=tom+hanks"; | |
48 private static final String IMDB_WEBPAGE_FOR_TOM_HANKS = "http://m.imdb.com/
name/nm0000158"; | |
49 private static final String INTENT_URL_WITH_FALLBACK_URL = | |
50 "intent:///name/nm0000158#Intent;scheme=imdb;package=com.imdb.mobile
;" | |
51 + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" | |
52 + Uri.encode(IMDB_WEBPAGE_FOR_TOM_HANKS) + ";end"; | |
53 private static final String INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAM
E = | |
54 "intent:///name/nm0000158#Intent;scheme=imdb;" | |
55 + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" | |
56 + Uri.encode(IMDB_WEBPAGE_FOR_TOM_HANKS) + ";end"; | |
57 private static final String SOME_JAVASCRIPT_PAGE = "javascript:window.open(0
);"; | |
58 private static final String INTENT_URL_WITH_JAVASCRIPT_FALLBACK_URL = | |
59 "intent:///name/nm0000158#Intent;scheme=imdb;package=com.imdb.mobile
;" | |
60 + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" | |
61 + Uri.encode(SOME_JAVASCRIPT_PAGE) + ";end"; | |
62 private static final String IMDB_APP_INTENT_FOR_TOM_HANKS = "imdb:///name/nm
0000158"; | |
63 private static final String INTENT_URL_WITH_CHAIN_FALLBACK_URL = | |
64 "intent://scan/#Intent;scheme=zxing;" | |
65 + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" | |
66 + Uri.encode("http://url.myredirector.com/aaa") + ";end"; | |
67 | |
68 private static final String PLUS_STREAM_URL = "https://plus.google.com/strea
m"; | |
69 private static final String CALENDAR_URL = "http://www.google.com/calendar"; | |
70 private static final String KEEP_URL = "http://www.google.com/keep"; | |
71 | |
72 private final TestExternalNavigationDelegate mDelegate; | |
73 private ExternalNavigationHandler mUrlHandler; | |
74 | |
75 public ExternalNavigationHandlerTest() { | |
76 mDelegate = new TestExternalNavigationDelegate(); | |
77 mUrlHandler = new ExternalNavigationHandler(mDelegate); | |
78 } | |
79 | |
80 @Override | |
81 protected void setUp() throws Exception { | |
82 super.setUp(); | |
83 mDelegate.setContext(getInstrumentation().getContext()); | |
84 CommandLine.init(new String[0]); | |
85 } | |
86 | |
87 @SmallTest | |
88 public void testOrdinaryIncognitoUri() { | |
89 check("http://youtube.com/", | |
90 null, /* referrer */ | |
91 true, /* incognito */ | |
92 PageTransition.LINK, | |
93 NO_REDIRECT, | |
94 true, | |
95 false, | |
96 null, | |
97 OverrideUrlLoadingResult.OVERRIDE_WITH_INCOGNITO_MODE, | |
98 START_INCOGNITO); | |
99 } | |
100 | |
101 @SmallTest | |
102 public void testChromeReferrer() { | |
103 // http://crbug.com/159153: Don't override http or https URLs from the N
TP or bookmarks. | |
104 check("http://youtube.com/", | |
105 "chrome://about", /* referrer */ | |
106 false, /* incognito */ | |
107 PageTransition.LINK, | |
108 NO_REDIRECT, | |
109 true, | |
110 false, | |
111 null, | |
112 OverrideUrlLoadingResult.NO_OVERRIDE, | |
113 IGNORE); | |
114 check("tel:012345678", | |
115 "chrome://about", /* referrer */ | |
116 false, /* incognito */ | |
117 PageTransition.LINK, | |
118 NO_REDIRECT, | |
119 true, | |
120 false, | |
121 null, | |
122 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
123 START_ACTIVITY); | |
124 } | |
125 | |
126 @SmallTest | |
127 public void testForwardBackNavigation() { | |
128 // http://crbug.com/164194. We shouldn't show the intent picker on | |
129 // forwards or backwards navigations. | |
130 check("http://youtube.com/", | |
131 null, /* referrer */ | |
132 false, /* incognito */ | |
133 PageTransition.LINK | |
134 | PageTransition.FORWARD_BACK, | |
135 NO_REDIRECT, | |
136 true, | |
137 false, | |
138 null, | |
139 OverrideUrlLoadingResult.NO_OVERRIDE, | |
140 IGNORE); | |
141 } | |
142 | |
143 @SmallTest | |
144 public void testRedirectFromFormSubmit() { | |
145 // http://crbug.com/181186: We need to show the intent picker when we re
ceive a redirect | |
146 // following a form submit. OAuth of native applications rely on this. | |
147 check("market://1234", | |
148 null, /* referrer */ | |
149 false, /* incognito */ | |
150 PageTransition.FORM_SUBMIT, | |
151 REDIRECT, | |
152 true, | |
153 false, | |
154 null, | |
155 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
156 START_ACTIVITY); | |
157 check("http://youtube.com://", | |
158 null, /* referrer */ | |
159 false, /* incognito */ | |
160 PageTransition.FORM_SUBMIT, | |
161 REDIRECT, | |
162 true, | |
163 false, | |
164 null, | |
165 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
166 START_ACTIVITY); | |
167 // It doesn't make sense to allow intent picker without redirect, since
form data | |
168 // is not encoded in the intent (although, in theory, it could be passed
in as | |
169 // an extra data in the intent). | |
170 check("http://youtube.com://", | |
171 null, /* referrer */ | |
172 false, /* incognito */ | |
173 PageTransition.FORM_SUBMIT, | |
174 NO_REDIRECT, | |
175 true, | |
176 false, | |
177 null, | |
178 OverrideUrlLoadingResult.NO_OVERRIDE, | |
179 IGNORE); | |
180 } | |
181 | |
182 @SmallTest | |
183 public void testIgnore() { | |
184 // Ensure about: URLs are not broadcast for external navigation. | |
185 check("about:test", | |
186 null, /* referrer */ | |
187 false, /* incognito */ | |
188 PageTransition.LINK, | |
189 NO_REDIRECT, | |
190 true, | |
191 false, | |
192 null, | |
193 OverrideUrlLoadingResult.NO_OVERRIDE, | |
194 IGNORE); | |
195 check("about:test", | |
196 null, /* referrer */ | |
197 true, /* incognito */ | |
198 PageTransition.LINK, | |
199 NO_REDIRECT, | |
200 true, | |
201 false, | |
202 null, | |
203 OverrideUrlLoadingResult.NO_OVERRIDE, | |
204 IGNORE); | |
205 | |
206 // Ensure content: URLs are not broadcast for external navigation. | |
207 check("content:test", | |
208 null, /* referrer */ | |
209 true, /* incognito */ | |
210 PageTransition.LINK, | |
211 NO_REDIRECT, | |
212 true, | |
213 false, | |
214 null, | |
215 OverrideUrlLoadingResult.NO_OVERRIDE, | |
216 IGNORE); | |
217 check("content:test", | |
218 null, /* referrer */ | |
219 false, /* incognito */ | |
220 PageTransition.LINK, | |
221 NO_REDIRECT, | |
222 true, | |
223 false, | |
224 null, | |
225 OverrideUrlLoadingResult.NO_OVERRIDE, | |
226 IGNORE); | |
227 | |
228 // Ensure chrome: URLs are not broadcast for external navigation. | |
229 check("chrome://history", | |
230 null, /* referrer */ | |
231 true, /* incognito */ | |
232 PageTransition.LINK, | |
233 NO_REDIRECT, | |
234 true, | |
235 false, | |
236 null, | |
237 OverrideUrlLoadingResult.NO_OVERRIDE, | |
238 IGNORE); | |
239 check("chrome://history", | |
240 null, /* referrer */ | |
241 false, /* incognito */ | |
242 PageTransition.LINK, | |
243 NO_REDIRECT, | |
244 true, | |
245 false, | |
246 null, | |
247 OverrideUrlLoadingResult.NO_OVERRIDE, | |
248 IGNORE); | |
249 | |
250 // Ensure chrome-native: URLs are not broadcast for external navigation. | |
251 check("chrome-native://newtab", | |
252 null, /* referrer */ | |
253 true, /* incognito */ | |
254 PageTransition.LINK, | |
255 NO_REDIRECT, | |
256 true, | |
257 false, | |
258 null, | |
259 OverrideUrlLoadingResult.NO_OVERRIDE, | |
260 IGNORE); | |
261 check("chrome-native://newtab", | |
262 null, /* referrer */ | |
263 false, /* incognito */ | |
264 PageTransition.LINK, | |
265 NO_REDIRECT, | |
266 true, | |
267 false, | |
268 null, | |
269 OverrideUrlLoadingResult.NO_OVERRIDE, | |
270 IGNORE); | |
271 } | |
272 | |
273 @SmallTest | |
274 public void testPageTransitionType() { | |
275 // Non-link page transition type are ignored. | |
276 check("http://youtube.com/", | |
277 null, /* referrer */ | |
278 false, /* incognito */ | |
279 PageTransition.LINK, | |
280 NO_REDIRECT, | |
281 true, | |
282 false, | |
283 null, | |
284 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
285 START_ACTIVITY); | |
286 check("http://youtube.com/", | |
287 null, /* referrer */ | |
288 false, /* incognito */ | |
289 PageTransition.LINK, | |
290 REDIRECT, | |
291 true, | |
292 false, | |
293 null, | |
294 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
295 START_ACTIVITY); | |
296 // http://crbug.com/143118 - Don't show the picker for directly typed UR
Ls, unless | |
297 // the URL results in a redirect. | |
298 check("http://youtube.com/", | |
299 null, /* referrer */ | |
300 false, /* incognito */ | |
301 PageTransition.TYPED, | |
302 NO_REDIRECT, | |
303 true, | |
304 false, | |
305 null, | |
306 OverrideUrlLoadingResult.NO_OVERRIDE, | |
307 IGNORE); | |
308 // http://crbug.com/162106 - Don't show the picker on reload. | |
309 check("http://youtube.com/", | |
310 null, /* referrer */ | |
311 false, /* incognito */ | |
312 PageTransition.RELOAD, | |
313 NO_REDIRECT, | |
314 true, | |
315 false, | |
316 null, | |
317 OverrideUrlLoadingResult.NO_OVERRIDE, | |
318 IGNORE); | |
319 } | |
320 | |
321 @SmallTest | |
322 public void testWtai() { | |
323 // Start the telephone application with the given number. | |
324 check("wtai://wp/mc;0123456789", | |
325 null, /* referrer */ | |
326 true, /* incognito */ | |
327 PageTransition.LINK, | |
328 NO_REDIRECT, | |
329 true, | |
330 false, | |
331 null, | |
332 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
333 START_ACTIVITY | INTENT_SANITIZATION_EXCEPTION); | |
334 // These two cases are currently unimplemented. | |
335 check("wtai://wp/sd;0123456789", | |
336 null, /* referrer */ | |
337 false, /* incognito */ | |
338 PageTransition.LINK, | |
339 NO_REDIRECT, | |
340 true, | |
341 false, | |
342 null, | |
343 OverrideUrlLoadingResult.NO_OVERRIDE, | |
344 IGNORE | INTENT_SANITIZATION_EXCEPTION); | |
345 check("wtai://wp/ap;0123456789", | |
346 null, /* referrer */ | |
347 false, /* incognito */ | |
348 PageTransition.LINK, | |
349 NO_REDIRECT, | |
350 true, | |
351 false, | |
352 null, | |
353 OverrideUrlLoadingResult.NO_OVERRIDE, | |
354 IGNORE | INTENT_SANITIZATION_EXCEPTION); | |
355 // Ignore other WTAI urls. | |
356 check("wtai://wp/invalid", | |
357 null, /* referrer */ | |
358 false, /* incognito */ | |
359 PageTransition.LINK, | |
360 NO_REDIRECT, | |
361 true, | |
362 false, | |
363 null, | |
364 OverrideUrlLoadingResult.NO_OVERRIDE, | |
365 IGNORE | INTENT_SANITIZATION_EXCEPTION); | |
366 } | |
367 | |
368 @SmallTest | |
369 public void testExternalUri() { | |
370 check("tel:012345678", | |
371 null, /* referrer */ | |
372 false, /* incognito */ | |
373 PageTransition.LINK, | |
374 NO_REDIRECT, | |
375 true, | |
376 false, | |
377 null, | |
378 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
379 START_ACTIVITY); | |
380 } | |
381 | |
382 @SmallTest | |
383 public void testTypedRedirectToExternalProtocol() { | |
384 // http://crbug.com/331571 reverted http://crbug.com/169549 | |
385 check("market://1234", | |
386 null, /* referrer */ | |
387 false, /* incognito */ | |
388 PageTransition.TYPED, | |
389 REDIRECT, | |
390 true, | |
391 false, | |
392 null, | |
393 OverrideUrlLoadingResult.NO_OVERRIDE, | |
394 IGNORE); | |
395 // http://crbug.com/143118 | |
396 check("market://1234", | |
397 null, /* referrer */ | |
398 false, /* incognito */ | |
399 PageTransition.TYPED, | |
400 NO_REDIRECT, | |
401 true, | |
402 false, | |
403 null, | |
404 OverrideUrlLoadingResult.NO_OVERRIDE, | |
405 IGNORE); | |
406 } | |
407 | |
408 @SmallTest | |
409 public void testIncomingIntentRedirect() { | |
410 int transitionTypeIncomingIntent = PageTransition.LINK | |
411 | PageTransition.FROM_API; | |
412 // http://crbug.com/149218 | |
413 check("http://youtube.com/", | |
414 null, /* referrer */ | |
415 false, /* incognito */ | |
416 transitionTypeIncomingIntent, | |
417 NO_REDIRECT, | |
418 true, | |
419 false, | |
420 null, | |
421 OverrideUrlLoadingResult.NO_OVERRIDE, | |
422 IGNORE); | |
423 // http://crbug.com/170925 | |
424 check("http://youtube.com/", | |
425 null, /* referrer */ | |
426 false, /* incognito */ | |
427 transitionTypeIncomingIntent, | |
428 REDIRECT, | |
429 true, | |
430 false, | |
431 null, | |
432 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
433 START_ACTIVITY); | |
434 } | |
435 | |
436 @SmallTest | |
437 public void testIntentScheme() { | |
438 String url = "intent:wtai://wp/#Intent;action=android.settings.SETTINGS;
" | |
439 + "component=package/class;end"; | |
440 String urlWithSel = "intent:wtai://wp/#Intent;SEL;action=android.setting
s.SETTINGS;" | |
441 + "component=package/class;end"; | |
442 | |
443 check(url, | |
444 null, /* referrer */ | |
445 false, /* incognito */ | |
446 PageTransition.LINK, | |
447 NO_REDIRECT, | |
448 true, | |
449 false, | |
450 null, | |
451 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
452 START_ACTIVITY); | |
453 | |
454 // http://crbug.com/370399 | |
455 check(urlWithSel, | |
456 null, /* referrer */ | |
457 false, /* incognito */ | |
458 PageTransition.LINK, | |
459 NO_REDIRECT, | |
460 true, | |
461 false, | |
462 null, | |
463 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
464 START_ACTIVITY); | |
465 } | |
466 | |
467 @SmallTest | |
468 public void testYouTubePairingCode() { | |
469 int transitionTypeIncomingIntent = PageTransition.LINK | |
470 | PageTransition.FROM_API; | |
471 String url = "http://m.youtube.com/watch?v=1234&pairingCode=5678"; | |
472 | |
473 // http://crbug/386600 - it makes no sense to switch activities for pair
ing code URLs. | |
474 check(url, | |
475 null, /* referrer */ | |
476 false, /* incognito */ | |
477 PageTransition.LINK, | |
478 REDIRECT, | |
479 true, | |
480 false, | |
481 null, | |
482 OverrideUrlLoadingResult.NO_OVERRIDE, | |
483 IGNORE); | |
484 | |
485 check(url, | |
486 null, /* referrer */ | |
487 false, /* incognito */ | |
488 transitionTypeIncomingIntent, | |
489 REDIRECT, | |
490 true, | |
491 false, | |
492 null, | |
493 OverrideUrlLoadingResult.NO_OVERRIDE, | |
494 IGNORE); | |
495 } | |
496 | |
497 @SmallTest | |
498 public void testInitialIntent() throws URISyntaxException { | |
499 TabRedirectHandler redirectHandler = new TabRedirectHandler(new TestCont
ext()); | |
500 Intent ytIntent = Intent.parseUri("http://youtube.com/", Intent.URI_INTE
NT_SCHEME); | |
501 Intent fooIntent = Intent.parseUri("http://foo.com/", Intent.URI_INTENT_
SCHEME); | |
502 int transTypeLinkFromIntent = PageTransition.LINK | |
503 | PageTransition.FROM_API; | |
504 | |
505 // Ignore if url is redirected, transition type is IncomingIntent and a
new intent doesn't | |
506 // have any new resolver. | |
507 redirectHandler.updateIntent(ytIntent); | |
508 redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, fals
e, 0, 0); | |
509 redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false
, 0, 0); | |
510 check("http://m.youtube.com/", | |
511 null, /* referrer */ | |
512 false, /* incognito */ | |
513 transTypeLinkFromIntent, | |
514 REDIRECT, | |
515 true, | |
516 false, | |
517 redirectHandler, | |
518 OverrideUrlLoadingResult.NO_OVERRIDE, | |
519 IGNORE); | |
520 // Do not ignore if a new intent has any new resolver. | |
521 redirectHandler.updateIntent(fooIntent); | |
522 redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, fals
e, 0, 0); | |
523 redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false
, 0, 0); | |
524 check("http://m.youtube.com/", | |
525 null, /* referrer */ | |
526 false, /* incognito */ | |
527 transTypeLinkFromIntent, | |
528 REDIRECT, | |
529 true, | |
530 false, | |
531 redirectHandler, | |
532 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
533 START_ACTIVITY); | |
534 } | |
535 | |
536 @SmallTest | |
537 public void testFallbackUrl_IntentResolutionSucceeds() { | |
538 // IMDB app is installed. | |
539 mDelegate.setCanResolveActivity(true); | |
540 | |
541 check(INTENT_URL_WITH_FALLBACK_URL, | |
542 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */ | |
543 false, /* incognito */ | |
544 PageTransition.LINK, | |
545 NO_REDIRECT, | |
546 true, | |
547 false, | |
548 null, | |
549 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
550 START_ACTIVITY); | |
551 | |
552 Intent invokedIntent = mDelegate.startActivityIntent; | |
553 assertEquals(IMDB_APP_INTENT_FOR_TOM_HANKS, invokedIntent.getData().toSt
ring()); | |
554 assertNull("The invoked intent should not have browser_fallback_url\n", | |
555 invokedIntent.getStringExtra(ExternalNavigationHandler.EXTRA_BRO
WSER_FALLBACK_URL)); | |
556 assertNull(mDelegate.getNewUrlAfterClobbering()); | |
557 assertNull(mDelegate.getReferrerUrlForClobbering()); | |
558 } | |
559 | |
560 @SmallTest | |
561 public void testFallbackUrl_IntentResolutionFails() { | |
562 // IMDB app isn't installed. | |
563 mDelegate.setCanResolveActivity(false); | |
564 | |
565 // When intent resolution fails, we should not start an activity, but in
stead clobber | |
566 // the current tab. | |
567 check(INTENT_URL_WITH_FALLBACK_URL, | |
568 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */ | |
569 false, /* incognito */ | |
570 PageTransition.LINK, | |
571 NO_REDIRECT, | |
572 true, | |
573 false, | |
574 null, | |
575 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, | |
576 IGNORE); | |
577 | |
578 assertNull(mDelegate.startActivityIntent); | |
579 assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mDelegate.getNewUrlAfterClobber
ing()); | |
580 assertEquals(SEARCH_RESULT_URL_FOR_TOM_HANKS, mDelegate.getReferrerUrlFo
rClobbering()); | |
581 } | |
582 | |
583 @SmallTest | |
584 public void testFallbackUrl_IntentResolutionFailsWithoutPackageName() { | |
585 // IMDB app isn't installed. | |
586 mDelegate.setCanResolveActivity(false); | |
587 | |
588 // Fallback URL should work even when package name isn't given. | |
589 check(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME, | |
590 SEARCH_RESULT_URL_FOR_TOM_HANKS, /* referrer */ | |
591 false, /* incognito */ | |
592 PageTransition.LINK, | |
593 NO_REDIRECT, | |
594 true, | |
595 false, | |
596 null, | |
597 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, | |
598 IGNORE); | |
599 | |
600 assertNull(mDelegate.startActivityIntent); | |
601 assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mDelegate.getNewUrlAfterClobber
ing()); | |
602 assertEquals(SEARCH_RESULT_URL_FOR_TOM_HANKS, mDelegate.getReferrerUrlFo
rClobbering()); | |
603 } | |
604 | |
605 @SmallTest | |
606 public void testFallbackUrl_FallbackShouldNotWarnOnIncognito() { | |
607 // IMDB app isn't installed. | |
608 mDelegate.setCanResolveActivity(false); | |
609 | |
610 check(INTENT_URL_WITH_FALLBACK_URL, | |
611 SEARCH_RESULT_URL_FOR_TOM_HANKS, | |
612 true, /* incognito */ | |
613 PageTransition.LINK, | |
614 NO_REDIRECT, | |
615 true, | |
616 false, | |
617 null, | |
618 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, | |
619 IGNORE); | |
620 | |
621 assertNull(mDelegate.startActivityIntent); | |
622 assertEquals(IMDB_WEBPAGE_FOR_TOM_HANKS, mDelegate.getNewUrlAfterClobber
ing()); | |
623 assertEquals(SEARCH_RESULT_URL_FOR_TOM_HANKS, mDelegate.getReferrerUrlFo
rClobbering()); | |
624 } | |
625 | |
626 @SmallTest | |
627 public void testFallbackUrl_IgnoreJavascriptFallbackUrl() { | |
628 // IMDB app isn't installed. | |
629 mDelegate.setCanResolveActivity(false); | |
630 | |
631 // Will be redirected market since package is given. | |
632 check(INTENT_URL_WITH_JAVASCRIPT_FALLBACK_URL, | |
633 SEARCH_RESULT_URL_FOR_TOM_HANKS, | |
634 true, /* incognito */ | |
635 PageTransition.LINK, | |
636 NO_REDIRECT, | |
637 true, | |
638 false, | |
639 null, | |
640 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
641 START_ACTIVITY); | |
642 | |
643 Intent invokedIntent = mDelegate.startActivityIntent; | |
644 assertTrue(invokedIntent.getData().toString().startsWith("market://")); | |
645 assertEquals(null, mDelegate.getNewUrlAfterClobbering()); | |
646 assertEquals(null, mDelegate.getReferrerUrlForClobbering()); | |
647 } | |
648 | |
649 @SmallTest | |
650 public void testFallback_UseFallbackUrlForRedirectionFromTypedInUrl() { | |
651 TabRedirectHandler redirectHandler = new TabRedirectHandler(null); | |
652 | |
653 redirectHandler.updateNewUrlLoading(PageTransition.TYPED, false, false,
0, 0); | |
654 check("http://goo.gl/abcdefg", null, /* referrer */ | |
655 false, /* incognito */ | |
656 PageTransition.TYPED, NO_REDIRECT, true, false, redirectHandler, | |
657 OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); | |
658 | |
659 redirectHandler.updateNewUrlLoading(PageTransition.TYPED, true, false, 0
, 0); | |
660 check(INTENT_URL_WITH_FALLBACK_URL_WITHOUT_PACKAGE_NAME, null, /* referr
er */ | |
661 false, /* incognito */ | |
662 PageTransition.TYPED, REDIRECT, true, false, redirectHandler, | |
663 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE); | |
664 | |
665 // Now the user opens a link. | |
666 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0,
1); | |
667 check("http://m.youtube.com/", null, /* referrer */ | |
668 false, /* incognito */ | |
669 PageTransition.LINK, NO_REDIRECT, true, false, redirectHandler, | |
670 OverrideUrlLoadingResult.NO_OVERRIDE, IGNORE); | |
671 } | |
672 | |
673 @SmallTest | |
674 public void testIgnoreEffectiveRedirectFromIntentFallbackUrl() { | |
675 // We cannot resolve any intent, so fall-back URL will be used. | |
676 mDelegate.setCanResolveActivity(false); | |
677 | |
678 TabRedirectHandler redirectHandler = new TabRedirectHandler(null); | |
679 | |
680 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0,
0); | |
681 check(INTENT_URL_WITH_CHAIN_FALLBACK_URL, | |
682 null, /* referrer */ | |
683 false, /* incognito */ | |
684 PageTransition.LINK, | |
685 NO_REDIRECT, | |
686 true, | |
687 false, | |
688 redirectHandler, | |
689 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, | |
690 IGNORE); | |
691 | |
692 // As a result of intent resolution fallback, we have clobberred the cur
rent tab. | |
693 // The fall-back URL was HTTP-schemed, but it was effectively redirected
to a new intent | |
694 // URL using javascript. However, we do not allow chained fallback inten
t, so we do NOT | |
695 // override URL loading here. | |
696 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0
, 0); | |
697 check(INTENT_URL_WITH_FALLBACK_URL, | |
698 null, /* referrer */ | |
699 false, /* incognito */ | |
700 PageTransition.LINK, | |
701 NO_REDIRECT, | |
702 true, | |
703 false, | |
704 redirectHandler, | |
705 OverrideUrlLoadingResult.NO_OVERRIDE, | |
706 IGNORE); | |
707 | |
708 // Now enough time (2 seconds) have passed. | |
709 // New URL loading should not be affected. | |
710 // (The URL happened to be the same as previous one.) | |
711 // TODO(changwan): this is not likely cause flakiness, but it may be bet
ter to refactor | |
712 // systemclock or pass the new time as parameter. | |
713 long lastUserInteractionTimeInMillis = SystemClock.elapsedRealtime() + 2
* 1000L; | |
714 redirectHandler.updateNewUrlLoading( | |
715 PageTransition.LINK, false, true, lastUserInteractionTimeInMilli
s, 1); | |
716 check(INTENT_URL_WITH_FALLBACK_URL, | |
717 null, /* referrer */ | |
718 false, /* incognito */ | |
719 PageTransition.LINK, | |
720 NO_REDIRECT, | |
721 true, | |
722 false, | |
723 redirectHandler, | |
724 OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, | |
725 IGNORE); | |
726 } | |
727 | |
728 @SmallTest | |
729 public void testIgnoreEffectiveRedirectFromUserTyping() { | |
730 TabRedirectHandler redirectHandler = new TabRedirectHandler(null); | |
731 | |
732 redirectHandler.updateNewUrlLoading(PageTransition.TYPED, false, false,
0, 0); | |
733 check("http://m.youtube.com/", | |
734 null, /* referrer */ | |
735 false, /* incognito */ | |
736 PageTransition.TYPED, | |
737 NO_REDIRECT, | |
738 true, | |
739 false, | |
740 redirectHandler, | |
741 OverrideUrlLoadingResult.NO_OVERRIDE, | |
742 IGNORE); | |
743 | |
744 redirectHandler.updateNewUrlLoading(PageTransition.TYPED, true, false, 0
, 0); | |
745 check("http://m.youtube.com/", | |
746 null, /* referrer */ | |
747 false, /* incognito */ | |
748 PageTransition.TYPED, | |
749 REDIRECT, | |
750 true, | |
751 false, | |
752 redirectHandler, | |
753 OverrideUrlLoadingResult.NO_OVERRIDE, | |
754 IGNORE); | |
755 | |
756 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0
, 1); | |
757 check("http://m.youtube.com/", | |
758 null, /* referrer */ | |
759 false, /* incognito */ | |
760 PageTransition.LINK, | |
761 NO_REDIRECT, | |
762 true, | |
763 false, | |
764 redirectHandler, | |
765 OverrideUrlLoadingResult.NO_OVERRIDE, | |
766 IGNORE); | |
767 } | |
768 | |
769 @SmallTest | |
770 public void testNavigationFromLinkWithoutUserGesture() { | |
771 TabRedirectHandler redirectHandler = new TabRedirectHandler(null); | |
772 | |
773 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1
, 0); | |
774 check("http://m.youtube.com/", | |
775 null, /* referrer */ | |
776 false, /* incognito */ | |
777 PageTransition.LINK, | |
778 NO_REDIRECT, | |
779 true, | |
780 false, | |
781 redirectHandler, | |
782 OverrideUrlLoadingResult.NO_OVERRIDE, | |
783 IGNORE); | |
784 | |
785 redirectHandler.updateNewUrlLoading(PageTransition.LINK, true, false, 1,
0); | |
786 check("http://m.youtube.com/", | |
787 null, /* referrer */ | |
788 false, /* incognito */ | |
789 PageTransition.LINK, | |
790 REDIRECT, | |
791 true, | |
792 false, | |
793 redirectHandler, | |
794 OverrideUrlLoadingResult.NO_OVERRIDE, | |
795 IGNORE); | |
796 | |
797 redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 1
, 1); | |
798 check("http://m.youtube.com/", | |
799 null, /* referrer */ | |
800 false, /* incognito */ | |
801 PageTransition.LINK, | |
802 NO_REDIRECT, | |
803 true, | |
804 false, | |
805 redirectHandler, | |
806 OverrideUrlLoadingResult.NO_OVERRIDE, | |
807 IGNORE); | |
808 } | |
809 | |
810 @SmallTest | |
811 public void testChromeAppInBackground() { | |
812 mDelegate.setIsChromeAppInForeground(false); | |
813 check("http://youtube.com/", | |
814 null, /* referrer */ | |
815 false, /* incognito */ | |
816 PageTransition.LINK, | |
817 NO_REDIRECT, | |
818 true, | |
819 false, | |
820 null, | |
821 OverrideUrlLoadingResult.NO_OVERRIDE, | |
822 IGNORE); | |
823 } | |
824 | |
825 @SmallTest | |
826 public void testNotChromeAppInForegroundRequired() { | |
827 mDelegate.setIsChromeAppInForeground(false); | |
828 check("http://youtube.com/", | |
829 null, /* referrer */ | |
830 false, /* incognito */ | |
831 PageTransition.LINK, | |
832 NO_REDIRECT, | |
833 false, | |
834 false, | |
835 null, | |
836 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
837 START_ACTIVITY); | |
838 } | |
839 | |
840 @SmallTest | |
841 public void testCreatesIntentsToOpenInNewTab() { | |
842 mUrlHandler = new ExternalNavigationHandler(mDelegate); | |
843 ExternalNavigationParams params = new ExternalNavigationParams.Builder( | |
844 "http://m.youtube.com", false) | |
845 .setOpenInNewTab(true) | |
846 .build(); | |
847 OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(p
arams); | |
848 assertEquals(OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, res
ult); | |
849 assertTrue(mDelegate.startActivityIntent != null); | |
850 assertTrue(mDelegate.startActivityIntent.getBooleanExtra( | |
851 Browser.EXTRA_CREATE_NEW_TAB, false)); | |
852 } | |
853 | |
854 @SmallTest | |
855 public void testCanExternalAppHandleUrl() { | |
856 mDelegate.setCanResolveActivity(true); | |
857 assertTrue(mUrlHandler.canExternalAppHandleUrl("some_app://some_app.com/
")); | |
858 | |
859 mDelegate.setCanResolveActivity(false); | |
860 assertTrue(mUrlHandler.canExternalAppHandleUrl("wtai://wp/mc;0123456789"
)); | |
861 assertTrue(mUrlHandler.canExternalAppHandleUrl( | |
862 "intent:/#Intent;scheme=no_app;package=com.no_app;end")); | |
863 assertFalse(mUrlHandler.canExternalAppHandleUrl("no_app://no_app.com/"))
; | |
864 } | |
865 | |
866 @SmallTest | |
867 public void testPlusAppRefresh() { | |
868 check(PLUS_STREAM_URL, | |
869 PLUS_STREAM_URL, | |
870 false, /* incognito */ | |
871 PageTransition.LINK, | |
872 NO_REDIRECT, | |
873 true, | |
874 false, | |
875 null, | |
876 OverrideUrlLoadingResult.NO_OVERRIDE, | |
877 IGNORE); | |
878 } | |
879 | |
880 @SmallTest | |
881 public void testSameDomainDifferentApps() { | |
882 check(CALENDAR_URL, | |
883 KEEP_URL, | |
884 false, /* incognito */ | |
885 PageTransition.LINK, | |
886 NO_REDIRECT, | |
887 true, | |
888 false, | |
889 null, | |
890 OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, | |
891 START_ACTIVITY); | |
892 } | |
893 | |
894 @SmallTest | |
895 public void testBackgroundTabNavigation() { | |
896 check("http://youtube.com/", | |
897 null, /* referrer */ | |
898 false, /* incognito */ | |
899 PageTransition.LINK, | |
900 NO_REDIRECT, | |
901 true, | |
902 true, | |
903 null, | |
904 OverrideUrlLoadingResult.NO_OVERRIDE, | |
905 IGNORE); | |
906 } | |
907 | |
908 private static class TestExternalNavigationDelegate implements ExternalNavig
ationDelegate { | |
909 private Context mContext; | |
910 | |
911 public void setContext(Context context) { | |
912 mContext = context; | |
913 } | |
914 | |
915 @Override | |
916 public List<ComponentName> queryIntentActivities(Intent intent) { | |
917 List<ComponentName> list = new ArrayList<ComponentName>(); | |
918 if (intent.getDataString().startsWith("http://m.youtube.com") | |
919 || intent.getDataString().startsWith("http://youtube.com"))
{ | |
920 list.add(new ComponentName("youtube", "youtube")); | |
921 } else if (intent.getDataString().startsWith(PLUS_STREAM_URL)) { | |
922 list.add(new ComponentName("plus", "plus")); | |
923 } else if (intent.getDataString().startsWith(CALENDAR_URL)) { | |
924 list.add(new ComponentName("calendar", "calendar")); | |
925 } else { | |
926 list.add(new ComponentName("foo", "foo")); | |
927 } | |
928 | |
929 return list; | |
930 } | |
931 | |
932 @Override | |
933 public boolean canResolveActivity(Intent intent) { | |
934 return mCanResolveActivity; | |
935 } | |
936 | |
937 @Override | |
938 public boolean willChromeHandleIntent(Intent intent) { | |
939 return !isSpecializedHandlerAvailable(intent); | |
940 } | |
941 | |
942 @Override | |
943 public boolean isSpecializedHandlerAvailable(Intent intent) { | |
944 String data = intent.getDataString(); | |
945 return (data.startsWith("http://youtube.com") | |
946 || data.startsWith("http://m.youtube.com") | |
947 || data.startsWith(CALENDAR_URL) | |
948 || data.startsWith("wtai://wp/")); | |
949 } | |
950 | |
951 @Override | |
952 public String getPackageName() { | |
953 return "test"; | |
954 } | |
955 | |
956 @Override | |
957 public void startActivity(Intent intent) { | |
958 startActivityIntent = intent; | |
959 } | |
960 | |
961 @Override | |
962 public boolean startActivityIfNeeded(Intent intent) { | |
963 // For simplicity, don't distinguish between startActivityIfNeeded a
nd startActivity | |
964 // until a test requires this distinction. | |
965 startActivityIntent = intent; | |
966 return true; | |
967 } | |
968 | |
969 @Override | |
970 public void startIncognitoIntent(Intent intent, String referrerUrl, Stri
ng fallbackUrl, | |
971 Tab tab, boolean needsToCloseTab) { | |
972 startIncognitoIntentCalled = true; | |
973 } | |
974 | |
975 @Override | |
976 public OverrideUrlLoadingResult clobberCurrentTab( | |
977 String url, String referrerUrl, Tab tab) { | |
978 mNewUrlAfterClobbering = url; | |
979 mReferrerUrlForClobbering = referrerUrl; | |
980 return OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB; | |
981 } | |
982 | |
983 @Override | |
984 public boolean isChromeAppInForeground() { | |
985 return mIsChromeAppInForeground; | |
986 } | |
987 | |
988 @Override | |
989 public boolean isDocumentMode() { | |
990 return FeatureUtilities.isDocumentMode(mContext); | |
991 } | |
992 | |
993 public void reset() { | |
994 startActivityIntent = null; | |
995 startIncognitoIntentCalled = false; | |
996 } | |
997 | |
998 public void setCanResolveActivity(boolean value) { | |
999 mCanResolveActivity = value; | |
1000 } | |
1001 | |
1002 public String getNewUrlAfterClobbering() { | |
1003 return mNewUrlAfterClobbering; | |
1004 } | |
1005 | |
1006 public String getReferrerUrlForClobbering() { | |
1007 return mReferrerUrlForClobbering; | |
1008 } | |
1009 | |
1010 public void setIsChromeAppInForeground(boolean value) { | |
1011 mIsChromeAppInForeground = value; | |
1012 } | |
1013 | |
1014 public Intent startActivityIntent = null; | |
1015 public boolean startIncognitoIntentCalled = false; | |
1016 | |
1017 // This should not be reset for every run of check(). | |
1018 private boolean mCanResolveActivity = true; | |
1019 private String mNewUrlAfterClobbering; | |
1020 private String mReferrerUrlForClobbering; | |
1021 public boolean mIsChromeAppInForeground = true; | |
1022 } | |
1023 | |
1024 private void checkIntentSanity(Intent intent, String name) { | |
1025 assertTrue("The invoked " + name + " doesn't have the BROWSABLE category
set\n", | |
1026 intent.hasCategory(Intent.CATEGORY_BROWSABLE)); | |
1027 assertNull("The invoked " + name + " should not have a Component set\n", | |
1028 intent.getComponent()); | |
1029 } | |
1030 | |
1031 public void check(String url, | |
1032 String referrerUrl, | |
1033 boolean isIncognito, | |
1034 int pageTransition, | |
1035 int isRedirect, | |
1036 boolean chromeAppInForegroundRequired, | |
1037 boolean isBackgroundTabNavigation, | |
1038 TabRedirectHandler redirectHandler, | |
1039 OverrideUrlLoadingResult expectedOverrideResult, | |
1040 int otherExpectation) { | |
1041 boolean expectStartIncognito = (otherExpectation & START_INCOGNITO) != 0
; | |
1042 boolean expectStartActivity = (otherExpectation & START_ACTIVITY) != 0; | |
1043 boolean expectSaneIntent = (otherExpectation & INTENT_SANITIZATION_EXCEP
TION) == 0; | |
1044 | |
1045 mDelegate.reset(); | |
1046 | |
1047 ExternalNavigationParams params = new ExternalNavigationParams.Builder(u
rl, isIncognito, | |
1048 referrerUrl, pageTransition, isRedirect == REDIRECT) | |
1049 .setApplicationMustBeInForeground(chromeAppInForegroundRequired) | |
1050 .setRedirectHandler(redirectHandler) | |
1051 .setIsBackgroundTabNavigation(isBackgroundTabNavigation) | |
1052 .setIsMainFrame(true) | |
1053 .build(); | |
1054 OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(p
arams); | |
1055 boolean startActivityCalled = mDelegate.startActivityIntent != null; | |
1056 | |
1057 assertEquals(expectedOverrideResult, result); | |
1058 assertEquals(expectStartIncognito, mDelegate.startIncognitoIntentCalled)
; | |
1059 assertEquals(expectStartActivity, startActivityCalled); | |
1060 | |
1061 if (startActivityCalled && expectSaneIntent) { | |
1062 checkIntentSanity(mDelegate.startActivityIntent, "Intent"); | |
1063 if (mDelegate.startActivityIntent.getSelector() != null) { | |
1064 checkIntentSanity(mDelegate.startActivityIntent.getSelector(), | |
1065 "Intent's selector"); | |
1066 } | |
1067 } | |
1068 } | |
1069 | |
1070 private static class TestPackageManager extends MockPackageManager { | |
1071 @Override | |
1072 public List<ResolveInfo> queryIntentActivities(Intent intent, int flags)
{ | |
1073 List<ResolveInfo> resolves = new ArrayList<ResolveInfo>(); | |
1074 if (intent.getDataString().startsWith("http://m.youtube.com") | |
1075 || intent.getDataString().startsWith("http://youtube.com"))
{ | |
1076 ResolveInfo youTubeApp = new ResolveInfo(); | |
1077 youTubeApp.activityInfo = new ActivityInfo(); | |
1078 youTubeApp.activityInfo.packageName = "youtube"; | |
1079 youTubeApp.activityInfo.name = "youtube"; | |
1080 resolves.add(youTubeApp); | |
1081 } else { | |
1082 ResolveInfo fooApp = new ResolveInfo(); | |
1083 fooApp.activityInfo = new ActivityInfo(); | |
1084 fooApp.activityInfo.packageName = "foo"; | |
1085 fooApp.activityInfo.name = "foo"; | |
1086 resolves.add(fooApp); | |
1087 } | |
1088 return resolves; | |
1089 } | |
1090 } | |
1091 | |
1092 private static class TestContext extends MockContext { | |
1093 @Override | |
1094 public PackageManager getPackageManager() { | |
1095 return new TestPackageManager(); | |
1096 } | |
1097 | |
1098 @Override | |
1099 public String getPackageName() { | |
1100 return "test.app.name"; | |
1101 } | |
1102 | |
1103 } | |
1104 } | |
OLD | NEW |