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.webapps; |
| 6 |
| 7 import android.R; |
| 8 import android.app.Activity; |
| 9 import android.content.Context; |
| 10 import android.content.Intent; |
| 11 import android.os.Build; |
| 12 import android.test.suitebuilder.annotation.MediumTest; |
| 13 import android.view.View; |
| 14 |
| 15 import org.chromium.base.ApplicationStatus; |
| 16 import org.chromium.base.test.util.DisabledTest; |
| 17 import org.chromium.base.test.util.UrlUtils; |
| 18 import org.chromium.chrome.browser.ChromeTabbedActivity; |
| 19 import org.chromium.chrome.browser.ShortcutHelper; |
| 20 import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
| 21 import org.chromium.chrome.browser.document.DocumentActivity; |
| 22 import org.chromium.chrome.test.MultiActivityTestBase; |
| 23 import org.chromium.content.browser.test.util.Criteria; |
| 24 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 25 import org.chromium.content_public.common.ScreenOrientationValues; |
| 26 |
| 27 import java.lang.ref.WeakReference; |
| 28 import java.util.List; |
| 29 |
| 30 /** |
| 31 * Tests that WebappActivities are launched correctly. |
| 32 * |
| 33 * This test seems a little wonky because WebappActivities launched differently,
depending on what |
| 34 * OS the user is on. Pre-L, WebappActivities were manually instanced and assig
ned by the |
| 35 * WebappManager. On L and above, WebappActivities are automatically instanced
by Android and the |
| 36 * FLAG_ACTIVITY_NEW_DOCUMENT mechanism. Moreover, we don't have access to the
task list pre-L so |
| 37 * we have to assume that any non-running WebappActivities are not listed in And
roid's Overview. |
| 38 */ |
| 39 public class WebappModeTest extends MultiActivityTestBase { |
| 40 private static final String WEBAPP_1_ID = "webapp_id_1"; |
| 41 private static final String WEBAPP_1_URL = |
| 42 UrlUtils.encodeHtmlDataUri("<html><body bgcolor='#011684'>Webapp 1</
body></html>"); |
| 43 private static final String WEBAPP_1_TITLE = "Web app #1"; |
| 44 |
| 45 private static final String WEBAPP_2_ID = "webapp_id_2"; |
| 46 private static final String WEBAPP_2_URL = |
| 47 UrlUtils.encodeHtmlDataUri("<html><body bgcolor='#840116'>Webapp 2</
body></html>"); |
| 48 private static final String WEBAPP_2_TITLE = "Web app #2"; |
| 49 |
| 50 private static final String WEBAPP_ICON = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABC
AIAAACQd1PeAAAACXB" |
| 51 + "IWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wQIFB4cxOfiSQAAABl0RVh0Q29tbWVu
dABDcmVhdGVkIHdpdG" |
| 52 + "ggR0lNUFeBDhcAAAAMSURBVAjXY2AUawEAALcAnI/TkI8AAAAASUVORK5CYII="; |
| 53 |
| 54 private boolean isNumberOfRunningActivitiesCorrect(final int numActivities)
throws Exception { |
| 55 return CriteriaHelper.pollForCriteria(new Criteria() { |
| 56 @Override |
| 57 public boolean isSatisfied() { |
| 58 Context context = getInstrumentation().getTargetContext(); |
| 59 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP |
| 60 && MultiActivityTestBase.getNumChromeTasks(context) != n
umActivities) { |
| 61 return false; |
| 62 } |
| 63 |
| 64 int count = 0; |
| 65 List<WeakReference<Activity>> activities = ApplicationStatus.get
RunningActivities(); |
| 66 for (WeakReference<Activity> activity : activities) { |
| 67 if (activity.get() instanceof WebappActivity) count++; |
| 68 } |
| 69 return count == numActivities; |
| 70 } |
| 71 }); |
| 72 } |
| 73 |
| 74 private void fireWebappIntent(String id, String url, String title, String ic
on, |
| 75 boolean addMac) throws Exception { |
| 76 Intent intent = new Intent(); |
| 77 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| 78 intent.setPackage(getInstrumentation().getTargetContext().getPackageName
()); |
| 79 intent.setAction(ChromeLauncherActivity.ACTION_START_WEBAPP); |
| 80 intent.putExtra(ShortcutHelper.EXTRA_ID, id); |
| 81 intent.putExtra(ShortcutHelper.EXTRA_URL, url); |
| 82 intent.putExtra(ShortcutHelper.EXTRA_TITLE, title); |
| 83 intent.putExtra(ShortcutHelper.EXTRA_ICON, icon); |
| 84 intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValue
s.PORTRAIT); |
| 85 if (addMac) { |
| 86 // Needed for security reasons. If the MAC is excluded, the URL of
the webapp is opened |
| 87 // in a browser window, instead. |
| 88 String mac = ShortcutHelper.getEncodedMac(getInstrumentation().getTa
rgetContext(), url); |
| 89 intent.putExtra(ShortcutHelper.EXTRA_MAC, mac); |
| 90 } |
| 91 |
| 92 getInstrumentation().getTargetContext().startActivity(intent); |
| 93 getInstrumentation().waitForIdleSync(); |
| 94 MultiActivityTestBase.waitUntilChromeInForeground(); |
| 95 } |
| 96 |
| 97 /** |
| 98 * Tests that WebappActivities are started properly. |
| 99 */ |
| 100 @MediumTest |
| 101 public void testWebappLaunches() throws Exception { |
| 102 // Start the WebappActivity. We can't use ActivityUtils.waitForActivity
() because |
| 103 // of the way WebappActivity is instanced on pre-L devices. |
| 104 fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON,
true); |
| 105 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 106 @Override |
| 107 public boolean isSatisfied() { |
| 108 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 109 return lastActivity instanceof WebappActivity |
| 110 && lastActivity.findViewById(R.id.content).hasWindowFocu
s(); |
| 111 } |
| 112 })); |
| 113 assertTrue(isNumberOfRunningActivitiesCorrect(1)); |
| 114 final Activity firstActivity = ApplicationStatus.getLastTrackedFocusedAc
tivity(); |
| 115 |
| 116 // Firing a different Intent should start a new WebappActivity instance. |
| 117 fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON,
true); |
| 118 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 119 @Override |
| 120 public boolean isSatisfied() { |
| 121 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 122 return lastActivity instanceof WebappActivity && lastActivity !=
firstActivity |
| 123 && lastActivity.findViewById(R.id.content).hasWindowFocu
s(); |
| 124 } |
| 125 })); |
| 126 assertTrue(isNumberOfRunningActivitiesCorrect(2)); |
| 127 |
| 128 // Firing the first Intent should bring back the first WebappActivity in
stance. |
| 129 fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON,
true); |
| 130 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 131 @Override |
| 132 public boolean isSatisfied() { |
| 133 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 134 return lastActivity instanceof WebappActivity && lastActivity ==
firstActivity |
| 135 && lastActivity.findViewById(R.id.content).hasWindowFocu
s(); |
| 136 } |
| 137 })); |
| 138 assertTrue(isNumberOfRunningActivitiesCorrect(2)); |
| 139 } |
| 140 |
| 141 /** |
| 142 * Tests that a WebappActivity can be brought forward by calling |
| 143 * WebContentsDelegateAndroid.activateContents(). |
| 144 */ |
| 145 @MediumTest |
| 146 public void testActivateContents() throws Exception { |
| 147 final Context context = getInstrumentation().getTargetContext(); |
| 148 |
| 149 // Start the WebappActivity. |
| 150 fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON,
true); |
| 151 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 152 @Override |
| 153 public boolean isSatisfied() { |
| 154 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 155 View rootView = lastActivity.findViewById(R.id.content); |
| 156 return lastActivity instanceof WebappActivity && rootView.hasWin
dowFocus(); |
| 157 } |
| 158 })); |
| 159 assertTrue(isNumberOfRunningActivitiesCorrect(1)); |
| 160 |
| 161 // Return home. |
| 162 final WebappActivity activity = |
| 163 (WebappActivity) ApplicationStatus.getLastTrackedFocusedActivity
(); |
| 164 MultiActivityTestBase.launchHomescreenIntent(context); |
| 165 getInstrumentation().waitForIdleSync(); |
| 166 |
| 167 // Bring it back via the Tab. |
| 168 activity.getActivityTab().getChromeWebContentsDelegateAndroid().activate
Contents(); |
| 169 getInstrumentation().waitForIdleSync(); |
| 170 MultiActivityTestBase.waitUntilChromeInForeground(); |
| 171 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 172 @Override |
| 173 public boolean isSatisfied() { |
| 174 return activity == ApplicationStatus.getLastTrackedFocusedActivi
ty() |
| 175 && activity.hasWindowFocus(); |
| 176 } |
| 177 })); |
| 178 assertTrue(isNumberOfRunningActivitiesCorrect(1)); |
| 179 } |
| 180 |
| 181 /** |
| 182 * Ensure WebappActivities can't be launched without proper security checks. |
| 183 * |
| 184 * https://crbug.com/490473 |
| 185 * @MediumTest |
| 186 */ |
| 187 @DisabledTest |
| 188 public void testWebappRequiresValidMac() throws Exception { |
| 189 // Try to start a WebappActivity. Fail because the Intent is insecure. |
| 190 fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON,
false); |
| 191 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 192 @Override |
| 193 public boolean isSatisfied() { |
| 194 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 195 if (!lastActivity.findViewById(R.id.content).hasWindowFocus()) r
eturn false; |
| 196 return lastActivity instanceof ChromeTabbedActivity |
| 197 || lastActivity instanceof DocumentActivity; |
| 198 } |
| 199 })); |
| 200 final Activity firstActivity = ApplicationStatus.getLastTrackedFocusedAc
tivity(); |
| 201 |
| 202 // Firing a correct Intent should start a new WebappActivity instance. |
| 203 fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON,
true); |
| 204 assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 205 @Override |
| 206 public boolean isSatisfied() { |
| 207 Activity lastActivity = ApplicationStatus.getLastTrackedFocusedA
ctivity(); |
| 208 return lastActivity instanceof WebappActivity && lastActivity !=
firstActivity |
| 209 && lastActivity.findViewById(R.id.content).hasWindowFocu
s(); |
| 210 } |
| 211 })); |
| 212 } |
| 213 } |
OLD | NEW |