0

WebLayer: Add integration tests of external intent launching

This CL adds initial integration tests of external intent launching,
covering the following cases:
- That an intent is not launched for a vanilla browsing URL.
- That an intent is blocked if navigated to directly.
- That an intent is launched if navigated to via a redirect.

Future CLs will add tests of more cases.

Change-Id: I6141a6aff81acef40155dfaf74d4a11bc10c7a40
Bug: 1029710, 1031465
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2119535
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753558}
This commit is contained in:
Colin Blundell
2020-03-26 09:31:56 +00:00
committed by Commit Bot
parent 5514307793
commit 83a33e5db4
4 changed files with 141 additions and 6 deletions
weblayer
browser
shell
android
shell_apk
src
org
chromium

@ -18,6 +18,7 @@ android_library("weblayer_java_tests") {
"src/org/chromium/weblayer/test/ErrorPageCallbackTest.java",
"src/org/chromium/weblayer/test/EventUtils.java",
"src/org/chromium/weblayer/test/ExecuteScriptTest.java",
"src/org/chromium/weblayer/test/ExternalNavigationTest.java",
"src/org/chromium/weblayer/test/FindInPageTest.java",
"src/org/chromium/weblayer/test/FullscreenCallbackTest.java",
"src/org/chromium/weblayer/test/InputTypesTest.java",

@ -0,0 +1,115 @@
// Copyright 2020 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.weblayer.test;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.test.filters.SmallTest;
import android.support.v4.app.Fragment;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Tab;
import org.chromium.weblayer.shell.InstrumentationActivity;
/**
* Tests handling of external intents.
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class ExternalNavigationTest {
@Rule
public InstrumentationActivityTestRule mActivityTestRule =
new InstrumentationActivityTestRule();
private static final String INTENT_TO_CHROME_URL =
"intent://play.google.com/store/apps/details?id=com.facebook.katana/#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.chrome;end";
private class IntentInterceptor implements InstrumentationActivity.IntentInterceptor {
public Intent mLastIntent;
private CallbackHelper mCallbackHelper = new CallbackHelper();
@Override
public void interceptIntent(
Fragment fragment, Intent intent, int requestCode, Bundle options) {
mLastIntent = intent;
mCallbackHelper.notifyCalled();
}
public void waitForIntent() {
try {
mCallbackHelper.waitForFirst();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private IntentInterceptor mIntentInterceptor = new IntentInterceptor();
@Before
public void setUp() throws Exception {
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null);
activity.setIntentInterceptor(mIntentInterceptor);
}
/**
* Verifies that for a navigation to a URI that WebLayer can handle internally, there
* is no external intent triggered.
*/
@Test
@SmallTest
public void testBrowserNavigation() throws Throwable {
mActivityTestRule.navigateAndWait("about:blank");
Assert.assertNull(mIntentInterceptor.mLastIntent);
}
/**
* Tests that a direct navigation to an external intent is blocked, resulting in a failed
* browser navigation.
*/
@Test
@SmallTest
public void testExternalIntentWithNoRedirectBlocked() throws Throwable {
Tab tab = mActivityTestRule.getActivity().getTab();
// Note that this navigation will not result in a paint.
mActivityTestRule.navigateAndWaitForFailure(
tab, INTENT_TO_CHROME_URL, /*waitForPaint=*/false);
Assert.assertNull(mIntentInterceptor.mLastIntent);
}
/**
* Tests that a navigation that redirects to an external intent results in the external intent
* being launched.
*/
@Test
@SmallTest
public void testExternalIntentAfterRedirectLaunched() throws Throwable {
String url = mActivityTestRule.getTestServer().getURL(
"/server-redirect?" + INTENT_TO_CHROME_URL);
Tab tab = mActivityTestRule.getActivity().getTab();
TestThreadUtils.runOnUiThreadBlocking(
() -> { tab.getNavigationController().navigate(Uri.parse(url)); });
mIntentInterceptor.waitForIntent();
Intent intent = mIntentInterceptor.mLastIntent;
Assert.assertNotNull(intent);
Assert.assertEquals("com.android.chrome", intent.getPackage());
Assert.assertEquals("android.intent.action.VIEW", intent.getAction());
Assert.assertEquals("https://play.google.com/store/apps/details?id=com.facebook.katana/",
intent.getDataString());
}
}

@ -151,18 +151,19 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument
navigateAndWait(getActivity().getTab(), url, true /* waitForPaint */);
}
public void navigateAndWait(Tab controller, String url, boolean waitForPaint) {
(new NavigationWaiter(url, controller, false /* expectFailure */, waitForPaint))
.navigateAndWait();
public void navigateAndWait(Tab tab, String url, boolean waitForPaint) {
(new NavigationWaiter(url, tab, false /* expectFailure */, waitForPaint)).navigateAndWait();
}
/**
* Loads the given URL in the shell, expecting failure.
*/
public void navigateAndWaitForFailure(String url) {
(new NavigationWaiter(
url, getActivity().getTab(), true /* expectFailure */, true /* waitForPaint */))
.navigateAndWait();
navigateAndWaitForFailure(getActivity().getTab(), url, true /* waitForPaint */);
}
public void navigateAndWaitForFailure(Tab tab, String url, boolean waitForPaint) {
(new NavigationWaiter(url, tab, true /* expectFailure */, waitForPaint)).navigateAndWait();
}
/**

@ -103,6 +103,24 @@ public class InstrumentationActivity extends FragmentActivity {
super.startActivityFromFragment(fragment, intent, requestCode, options);
}
@Override
public void startActivity(Intent intent) {
if (mIntentInterceptor != null) {
mIntentInterceptor.interceptIntent(null, intent, 0, null);
return;
}
super.startActivity(intent);
}
@Override
public boolean startActivityIfNeeded(Intent intent, int requestCode) {
if (mIntentInterceptor != null) {
mIntentInterceptor.interceptIntent(null, intent, requestCode, null);
return true;
}
return super.startActivityIfNeeded(intent, requestCode);
}
public View getTopContentsContainer() {
return mTopContentsContainer;
}