| Index: chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
|
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..026974f8147d556a20760f949af29cb13724441d
|
| --- /dev/null
|
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
|
| @@ -0,0 +1,213 @@
|
| +// 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.webapps;
|
| +
|
| +import android.R;
|
| +import android.app.Activity;
|
| +import android.content.Context;
|
| +import android.content.Intent;
|
| +import android.os.Build;
|
| +import android.test.suitebuilder.annotation.MediumTest;
|
| +import android.view.View;
|
| +
|
| +import org.chromium.base.ApplicationStatus;
|
| +import org.chromium.base.test.util.DisabledTest;
|
| +import org.chromium.base.test.util.UrlUtils;
|
| +import org.chromium.chrome.browser.ChromeTabbedActivity;
|
| +import org.chromium.chrome.browser.ShortcutHelper;
|
| +import org.chromium.chrome.browser.document.ChromeLauncherActivity;
|
| +import org.chromium.chrome.browser.document.DocumentActivity;
|
| +import org.chromium.chrome.test.MultiActivityTestBase;
|
| +import org.chromium.content.browser.test.util.Criteria;
|
| +import org.chromium.content.browser.test.util.CriteriaHelper;
|
| +import org.chromium.content_public.common.ScreenOrientationValues;
|
| +
|
| +import java.lang.ref.WeakReference;
|
| +import java.util.List;
|
| +
|
| +/**
|
| + * Tests that WebappActivities are launched correctly.
|
| + *
|
| + * This test seems a little wonky because WebappActivities launched differently, depending on what
|
| + * OS the user is on. Pre-L, WebappActivities were manually instanced and assigned by the
|
| + * WebappManager. On L and above, WebappActivities are automatically instanced by Android and the
|
| + * FLAG_ACTIVITY_NEW_DOCUMENT mechanism. Moreover, we don't have access to the task list pre-L so
|
| + * we have to assume that any non-running WebappActivities are not listed in Android's Overview.
|
| + */
|
| +public class WebappModeTest extends MultiActivityTestBase {
|
| + private static final String WEBAPP_1_ID = "webapp_id_1";
|
| + private static final String WEBAPP_1_URL =
|
| + UrlUtils.encodeHtmlDataUri("<html><body bgcolor='#011684'>Webapp 1</body></html>");
|
| + private static final String WEBAPP_1_TITLE = "Web app #1";
|
| +
|
| + private static final String WEBAPP_2_ID = "webapp_id_2";
|
| + private static final String WEBAPP_2_URL =
|
| + UrlUtils.encodeHtmlDataUri("<html><body bgcolor='#840116'>Webapp 2</body></html>");
|
| + private static final String WEBAPP_2_TITLE = "Web app #2";
|
| +
|
| + private static final String WEBAPP_ICON = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXB"
|
| + + "IWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wQIFB4cxOfiSQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdG"
|
| + + "ggR0lNUFeBDhcAAAAMSURBVAjXY2AUawEAALcAnI/TkI8AAAAASUVORK5CYII=";
|
| +
|
| + private boolean isNumberOfRunningActivitiesCorrect(final int numActivities) throws Exception {
|
| + return CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Context context = getInstrumentation().getTargetContext();
|
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
| + && MultiActivityTestBase.getNumChromeTasks(context) != numActivities) {
|
| + return false;
|
| + }
|
| +
|
| + int count = 0;
|
| + List<WeakReference<Activity>> activities = ApplicationStatus.getRunningActivities();
|
| + for (WeakReference<Activity> activity : activities) {
|
| + if (activity.get() instanceof WebappActivity) count++;
|
| + }
|
| + return count == numActivities;
|
| + }
|
| + });
|
| + }
|
| +
|
| + private void fireWebappIntent(String id, String url, String title, String icon,
|
| + boolean addMac) throws Exception {
|
| + Intent intent = new Intent();
|
| + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| + intent.setPackage(getInstrumentation().getTargetContext().getPackageName());
|
| + intent.setAction(ChromeLauncherActivity.ACTION_START_WEBAPP);
|
| + intent.putExtra(ShortcutHelper.EXTRA_ID, id);
|
| + intent.putExtra(ShortcutHelper.EXTRA_URL, url);
|
| + intent.putExtra(ShortcutHelper.EXTRA_TITLE, title);
|
| + intent.putExtra(ShortcutHelper.EXTRA_ICON, icon);
|
| + intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.PORTRAIT);
|
| + if (addMac) {
|
| + // Needed for security reasons. If the MAC is excluded, the URL of the webapp is opened
|
| + // in a browser window, instead.
|
| + String mac = ShortcutHelper.getEncodedMac(getInstrumentation().getTargetContext(), url);
|
| + intent.putExtra(ShortcutHelper.EXTRA_MAC, mac);
|
| + }
|
| +
|
| + getInstrumentation().getTargetContext().startActivity(intent);
|
| + getInstrumentation().waitForIdleSync();
|
| + MultiActivityTestBase.waitUntilChromeInForeground();
|
| + }
|
| +
|
| + /**
|
| + * Tests that WebappActivities are started properly.
|
| + */
|
| + @MediumTest
|
| + public void testWebappLaunches() throws Exception {
|
| + // Start the WebappActivity. We can't use ActivityUtils.waitForActivity() because
|
| + // of the way WebappActivity is instanced on pre-L devices.
|
| + fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + return lastActivity instanceof WebappActivity
|
| + && lastActivity.findViewById(R.id.content).hasWindowFocus();
|
| + }
|
| + }));
|
| + assertTrue(isNumberOfRunningActivitiesCorrect(1));
|
| + final Activity firstActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| +
|
| + // Firing a different Intent should start a new WebappActivity instance.
|
| + fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON, true);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + return lastActivity instanceof WebappActivity && lastActivity != firstActivity
|
| + && lastActivity.findViewById(R.id.content).hasWindowFocus();
|
| + }
|
| + }));
|
| + assertTrue(isNumberOfRunningActivitiesCorrect(2));
|
| +
|
| + // Firing the first Intent should bring back the first WebappActivity instance.
|
| + fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + return lastActivity instanceof WebappActivity && lastActivity == firstActivity
|
| + && lastActivity.findViewById(R.id.content).hasWindowFocus();
|
| + }
|
| + }));
|
| + assertTrue(isNumberOfRunningActivitiesCorrect(2));
|
| + }
|
| +
|
| + /**
|
| + * Tests that a WebappActivity can be brought forward by calling
|
| + * WebContentsDelegateAndroid.activateContents().
|
| + */
|
| + @MediumTest
|
| + public void testActivateContents() throws Exception {
|
| + final Context context = getInstrumentation().getTargetContext();
|
| +
|
| + // Start the WebappActivity.
|
| + fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + View rootView = lastActivity.findViewById(R.id.content);
|
| + return lastActivity instanceof WebappActivity && rootView.hasWindowFocus();
|
| + }
|
| + }));
|
| + assertTrue(isNumberOfRunningActivitiesCorrect(1));
|
| +
|
| + // Return home.
|
| + final WebappActivity activity =
|
| + (WebappActivity) ApplicationStatus.getLastTrackedFocusedActivity();
|
| + MultiActivityTestBase.launchHomescreenIntent(context);
|
| + getInstrumentation().waitForIdleSync();
|
| +
|
| + // Bring it back via the Tab.
|
| + activity.getActivityTab().getChromeWebContentsDelegateAndroid().activateContents();
|
| + getInstrumentation().waitForIdleSync();
|
| + MultiActivityTestBase.waitUntilChromeInForeground();
|
| + assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return activity == ApplicationStatus.getLastTrackedFocusedActivity()
|
| + && activity.hasWindowFocus();
|
| + }
|
| + }));
|
| + assertTrue(isNumberOfRunningActivitiesCorrect(1));
|
| + }
|
| +
|
| + /**
|
| + * Ensure WebappActivities can't be launched without proper security checks.
|
| + *
|
| + * https://crbug.com/490473
|
| + * @MediumTest
|
| + */
|
| + @DisabledTest
|
| + public void testWebappRequiresValidMac() throws Exception {
|
| + // Try to start a WebappActivity. Fail because the Intent is insecure.
|
| + fireWebappIntent(WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, false);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + if (!lastActivity.findViewById(R.id.content).hasWindowFocus()) return false;
|
| + return lastActivity instanceof ChromeTabbedActivity
|
| + || lastActivity instanceof DocumentActivity;
|
| + }
|
| + }));
|
| + final Activity firstActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| +
|
| + // Firing a correct Intent should start a new WebappActivity instance.
|
| + fireWebappIntent(WEBAPP_2_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON, true);
|
| + assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
|
| + return lastActivity instanceof WebappActivity && lastActivity != firstActivity
|
| + && lastActivity.findViewById(R.id.content).hasWindowFocus();
|
| + }
|
| + }));
|
| + }
|
| +}
|
|
|