OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.webapps; | 5 package org.chromium.chrome.browser.webapps; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.SharedPreferences; | 10 import android.content.SharedPreferences; |
11 import android.support.test.InstrumentationRegistry; | 11 import android.support.test.InstrumentationRegistry; |
12 import android.support.test.filters.MediumTest; | 12 import android.support.test.filters.MediumTest; |
13 import android.view.View; | 13 import android.view.View; |
14 | 14 |
15 import org.junit.After; | 15 import org.junit.After; |
16 import org.junit.Assert; | 16 import org.junit.Assert; |
17 import org.junit.Before; | 17 import org.junit.Before; |
18 import org.junit.Rule; | 18 import org.junit.Rule; |
19 import org.junit.Test; | 19 import org.junit.Test; |
20 import org.junit.runner.RunWith; | 20 import org.junit.runner.RunWith; |
21 | 21 |
22 import org.chromium.base.ApplicationStatus; | 22 import org.chromium.base.ApplicationStatus; |
23 import org.chromium.base.ContextUtils; | 23 import org.chromium.base.ContextUtils; |
24 import org.chromium.base.ThreadUtils; | |
25 import org.chromium.base.test.util.CommandLineFlags; | 24 import org.chromium.base.test.util.CommandLineFlags; |
26 import org.chromium.base.test.util.Feature; | 25 import org.chromium.base.test.util.Feature; |
27 import org.chromium.base.test.util.RetryOnFailure; | 26 import org.chromium.base.test.util.RetryOnFailure; |
28 import org.chromium.base.test.util.UrlUtils; | 27 import org.chromium.base.test.util.UrlUtils; |
29 import org.chromium.blink_public.platform.WebDisplayMode; | 28 import org.chromium.blink_public.platform.WebDisplayMode; |
30 import org.chromium.chrome.browser.ChromeActivity; | 29 import org.chromium.chrome.browser.ChromeActivity; |
31 import org.chromium.chrome.browser.ChromeSwitches; | 30 import org.chromium.chrome.browser.ChromeSwitches; |
32 import org.chromium.chrome.browser.ChromeTabbedActivity; | 31 import org.chromium.chrome.browser.ChromeTabbedActivity; |
33 import org.chromium.chrome.browser.ShortcutHelper; | 32 import org.chromium.chrome.browser.ShortcutHelper; |
34 import org.chromium.chrome.browser.ShortcutSource; | 33 import org.chromium.chrome.browser.ShortcutSource; |
35 import org.chromium.chrome.browser.tab.Tab; | 34 import org.chromium.chrome.browser.tab.Tab; |
36 import org.chromium.chrome.browser.tab.TabIdManager; | 35 import org.chromium.chrome.browser.tab.TabIdManager; |
37 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; | 36 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
38 import org.chromium.chrome.test.MultiActivityTestRule; | 37 import org.chromium.chrome.test.MultiActivityTestRule; |
39 import org.chromium.chrome.test.util.ActivityUtils; | |
40 import org.chromium.chrome.test.util.ApplicationTestUtils; | 38 import org.chromium.chrome.test.util.ApplicationTestUtils; |
41 import org.chromium.chrome.test.util.browser.TabLoadObserver; | |
42 import org.chromium.content.browser.test.util.Criteria; | 39 import org.chromium.content.browser.test.util.Criteria; |
43 import org.chromium.content.browser.test.util.CriteriaHelper; | 40 import org.chromium.content.browser.test.util.CriteriaHelper; |
44 import org.chromium.content.browser.test.util.JavaScriptUtils; | |
45 import org.chromium.content.browser.test.util.TouchCommon; | |
46 import org.chromium.content_public.common.ScreenOrientationValues; | 41 import org.chromium.content_public.common.ScreenOrientationValues; |
47 import org.chromium.net.test.EmbeddedTestServer; | 42 import org.chromium.net.test.EmbeddedTestServer; |
48 | 43 |
49 /** | 44 /** |
50 * Tests that WebappActivities are launched correctly. | 45 * Tests that WebappActivities are launched correctly. |
51 * | 46 * |
52 * This test seems a little wonky because WebappActivities launched differently,
depending on what | 47 * This test seems a little wonky because WebappActivities launched differently,
depending on what |
53 * OS the user is on. Pre-L, WebappActivities were manually instanced and assig
ned by the | 48 * OS the user is on. Pre-L, WebappActivities were manually instanced and assig
ned by the |
54 * WebappManager. On L and above, WebappActivities are automatically instanced
by Android and the | 49 * WebappManager. On L and above, WebappActivities are automatically instanced
by Android and the |
55 * FLAG_ACTIVITY_NEW_DOCUMENT mechanism. Moreover, we don't have access to the
task list pre-L so | 50 * FLAG_ACTIVITY_NEW_DOCUMENT mechanism. Moreover, we don't have access to the
task list pre-L so |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON,
true); | 261 fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON,
true); |
267 CriteriaHelper.pollUiThread(new Criteria() { | 262 CriteriaHelper.pollUiThread(new Criteria() { |
268 @Override | 263 @Override |
269 public boolean isSatisfied() { | 264 public boolean isSatisfied() { |
270 return isWebappActivityReady(ApplicationStatus.getLastTrackedFoc
usedActivity()); | 265 return isWebappActivityReady(ApplicationStatus.getLastTrackedFoc
usedActivity()); |
271 } | 266 } |
272 }); | 267 }); |
273 } | 268 } |
274 | 269 |
275 /** | 270 /** |
276 * Tests that WebappActivities handle window.open() properly in tabbed mode. | |
277 */ | |
278 @Test | |
279 @MediumTest | |
280 @Feature({"Webapps"}) | |
281 public void testWebappHandlesWindowOpenInTabbedMode() throws Exception { | |
282 triggerWindowOpenAndWaitForLoad(ChromeTabbedActivity.class, getOnClickLi
nkUrl(), true); | |
283 } | |
284 | |
285 /** | |
286 * Tests that WebappActivities handle suppressed window.open() properly in t
abbed mode. | |
287 */ | |
288 @Test | |
289 @MediumTest | |
290 @Feature({"Webapps"}) | |
291 public void testWebappHandlesSuppressedWindowOpenInTabbedMode() throws Excep
tion { | |
292 triggerWindowOpenAndWaitForLoad( | |
293 ChromeTabbedActivity.class, getHrefNoReferrerLinkUrl(), false); | |
294 } | |
295 | |
296 private <T extends ChromeActivity> void triggerWindowOpenAndWaitForLoad( | |
297 Class<T> classToWaitFor, String linkHtml, boolean checkContents) thr
ows Exception { | |
298 final WebappActivity firstActivity = | |
299 startWebappActivity(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, W
EBAPP_ICON); | |
300 final int firstWebappId = firstActivity.getActivityTab().getId(); | |
301 | |
302 // Load up the test page. | |
303 new TabLoadObserver(firstActivity.getActivityTab()).fullyLoadUrl(linkHtm
l); | |
304 | |
305 // Do a plain click to make the link open in the main browser via a wind
ow.open(). | |
306 // If the window is opened successfully, javascript on the first page tr
iggers and changes | |
307 // its URL as a signal for this test. | |
308 Runnable fgTrigger = new Runnable() { | |
309 @Override | |
310 public void run() { | |
311 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
312 @Override | |
313 public void run() { | |
314 View view = firstActivity.findViewById(android.R.id.cont
ent).getRootView(); | |
315 TouchCommon.singleClickView(view); | |
316 } | |
317 }); | |
318 } | |
319 }; | |
320 ChromeActivity secondActivity = ActivityUtils.waitForActivity( | |
321 InstrumentationRegistry.getInstrumentation(), classToWaitFor, fg
Trigger); | |
322 mTestRule.waitForFullLoad(secondActivity, "The Google"); | |
323 if (checkContents) { | |
324 Assert.assertEquals("New WebContents was not created", "SUCCESS", | |
325 firstActivity.getActivityTab().getTitle()); | |
326 } | |
327 Assert.assertNotSame("Wrong Activity in foreground", firstActivity, | |
328 ApplicationStatus.getLastTrackedFocusedActivity()); | |
329 | |
330 // Close the child window to kick the user back to the WebappActivity. | |
331 JavaScriptUtils.executeJavaScript( | |
332 secondActivity.getActivityTab().getWebContents(), "window.close(
)"); | |
333 CriteriaHelper.pollUiThread(new Criteria() { | |
334 @Override | |
335 public boolean isSatisfied() { | |
336 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); | |
337 if (!isWebappActivityReady(lastActivity)) return false; | |
338 | |
339 WebappActivity webappActivity = (WebappActivity) lastActivity; | |
340 return webappActivity.getActivityTab().getId() == firstWebappId; | |
341 } | |
342 }); | |
343 ApplicationTestUtils.waitUntilChromeInForeground(); | |
344 } | |
345 | |
346 /** | |
347 * Starts a WebappActivity for the given data and waits for it to be initial
ized. We can't use | 271 * Starts a WebappActivity for the given data and waits for it to be initial
ized. We can't use |
348 * ActivityUtils.waitForActivity() because of the way WebappActivity is inst
anced on pre-L | 272 * ActivityUtils.waitForActivity() because of the way WebappActivity is inst
anced on pre-L |
349 * devices. | 273 * devices. |
350 */ | 274 */ |
351 private WebappActivity startWebappActivity(String id, String url, String tit
le, String icon) { | 275 private WebappActivity startWebappActivity(String id, String url, String tit
le, String icon) { |
352 fireWebappIntent(id, url, title, icon, true); | 276 fireWebappIntent(id, url, title, icon, true); |
353 CriteriaHelper.pollUiThread(new Criteria() { | 277 CriteriaHelper.pollUiThread(new Criteria() { |
354 @Override | 278 @Override |
355 public boolean isSatisfied() { | 279 public boolean isSatisfied() { |
356 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); | 280 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
357 return isWebappActivityReady(lastActivity); | 281 return isWebappActivityReady(lastActivity); |
358 } | 282 } |
359 }); | 283 }); |
360 return (WebappActivity) ApplicationStatus.getLastTrackedFocusedActivity(
); | 284 return (WebappActivity) ApplicationStatus.getLastTrackedFocusedActivity(
); |
361 } | 285 } |
362 | 286 |
363 /** Returns true when the last Activity is a WebappActivity and is ready for
testing .*/ | 287 /** Returns true when the last Activity is a WebappActivity and is ready for
testing .*/ |
364 private boolean isWebappActivityReady(Activity lastActivity) { | 288 private boolean isWebappActivityReady(Activity lastActivity) { |
365 if (!(lastActivity instanceof WebappActivity)) return false; | 289 if (!(lastActivity instanceof WebappActivity)) return false; |
366 | 290 |
367 WebappActivity webappActivity = (WebappActivity) lastActivity; | 291 WebappActivity webappActivity = (WebappActivity) lastActivity; |
368 if (webappActivity.getActivityTab() == null) return false; | 292 if (webappActivity.getActivityTab() == null) return false; |
369 | 293 |
370 View rootView = webappActivity.findViewById(android.R.id.content); | 294 View rootView = webappActivity.findViewById(android.R.id.content); |
371 if (!rootView.hasWindowFocus()) return false; | 295 if (!rootView.hasWindowFocus()) return false; |
372 | 296 |
373 return true; | 297 return true; |
374 } | 298 } |
375 | |
376 /** Defines one gigantic link spanning the whole page that creates a new | |
377 * window with chrome/test/data/android/google.html. Disallowing a referrer
from being | |
378 * sent triggers another codepath. | |
379 */ | |
380 private String getHrefNoReferrerLinkUrl() { | |
381 return UrlUtils.encodeHtmlDataUri("<html>" | |
382 + " <head>" | |
383 + " <title>href no referrer link page</title>" | |
384 + " <meta name='viewport'" | |
385 + " content='width=device-width initial-scale=0.5, maximu
m-scale=0.5'>" | |
386 + " <style>" | |
387 + " body {margin: 0em;} div {width: 100%; height: 100%; bac
kground: #011684;}" | |
388 + " </style>" | |
389 + " </head>" | |
390 + " <body>" | |
391 + " <a href='" + mTestServer.getURL("/chrome/test/data/androi
d/google.html") | |
392 + "' target='_blank' rel='noreferrer'><div></div></a>" | |
393 + " </body>"); | |
394 } | |
395 | |
396 /** Returns a URL where clicking the body triggers a window.open() call to o
pen | |
397 * chrome/test/data/android/google.html. */ | |
398 private String getOnClickLinkUrl() { | |
399 return UrlUtils.encodeHtmlDataUri("<html>" | |
400 + " <head>" | |
401 + " <title>window.open page</title>" | |
402 + " <meta name='viewport'" | |
403 + " content='width=device-width initial-scale=0.5, maximu
m-scale=0.5'>" | |
404 + " <style>" | |
405 + " body {margin: 0em;} div {width: 100%; height: 100%; bac
kground: #011684;}" | |
406 + " </style>" | |
407 + " <script>" | |
408 + " function openNewWindow() {" | |
409 + " var site = window.open('" | |
410 + mTestServer.getURL("/chrome/test/data/android/google.html") +
"');" | |
411 + " document.title = site ? 'SUCCESS' : 'FAILURE';" | |
412 + " }" | |
413 + " </script>" | |
414 + " </head>" | |
415 + " <body id='body'>" | |
416 + " <div onclick='openNewWindow()'></div>" | |
417 + " </body>" | |
418 + "</html>"); | |
419 } | |
420 } | 299 } |
OLD | NEW |