Commit 17b517f8 authored by Colin Blundell's avatar Colin Blundell Committed by Commit Bot

[WebLayer] Set type of navigations from embedder appropriately

In WebLayer, navigations coming from the embedder currently get the
type TYPED | FROM_ADDRESS_BAR. This type has implications on how intent
launching is handled for these navigations: for user-typed navigations,

(1) Intents are blocked from launching without a redirect
(2) Intents to URLs that the app can handle stay within the app even
    if (a) there was a redirect and (b) an external app has registered
    as a default handler for such URLs

Fact 2 in particular is problematic for intended production use cases
of WebLayer. This CL changes the navigation type for navigations coming
from the embedder to be reflective of these use cases: LINK with a user
gesture. Setting the navigation params this way ensures that intents
will be launched in the cases (1) and (2) described above.

Bug: 1087434
Change-Id: Ib43d2ea2cbbfd0352dcde3f5895ac82292b3415f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2219892
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773161}
parent aaa2b01c
......@@ -143,26 +143,29 @@ public class ExternalNavigationTest {
}
/**
* Tests that a direct navigation to an external intent is blocked, resulting in a failed
* browser navigation.
* Tests that a direct navigation to an external intent is launched due to the navigation type
* being set as from a link with a user gesture.
*/
@Test
@SmallTest
public void testExternalIntentWithNoRedirectBlocked() throws Throwable {
public void testExternalIntentWithNoRedirectLaunched() throws Throwable {
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL);
IntentInterceptor intentInterceptor = new IntentInterceptor();
activity.setIntentInterceptor(intentInterceptor);
Tab tab = mActivityTestRule.getActivity().getTab();
TestThreadUtils.runOnUiThreadBlocking(
() -> { tab.getNavigationController().navigate(Uri.parse(INTENT_TO_CHROME_URL)); });
// Note that this navigation will not result in a paint.
mActivityTestRule.navigateAndWaitForFailure(
tab, INTENT_TO_CHROME_URL, /*waitForPaint=*/false);
Assert.assertNull(intentInterceptor.mLastIntent);
intentInterceptor.waitForIntent();
// The current URL should not have changed.
// The current URL should not have changed, and the intent should have been launched.
Assert.assertEquals(ABOUT_BLANK_URL, mActivityTestRule.getCurrentDisplayUrl());
Intent intent = intentInterceptor.mLastIntent;
Assert.assertNotNull(intent);
Assert.assertEquals(INTENT_TO_CHROME_PACKAGE, intent.getPackage());
Assert.assertEquals(INTENT_TO_CHROME_ACTION, intent.getAction());
Assert.assertEquals(INTENT_TO_CHROME_DATA_STRING, intent.getDataString());
}
/**
......@@ -448,12 +451,14 @@ public class ExternalNavigationTest {
/**
* Tests that going to a page that loads an intent that can be handled in onload() results in
* the external intent being blocked by policy on intents without user gestures loading in the
* midst of a user-typed navigation.
* the external intent being launched due to the navigation being specified as being from a link
* with a user gesture (if the navigation were specified as being from user typing the intent
* would be blocked due to Chrome's policy on not launching intents from user-typed navigations
* without a redirect).
*/
@Test
@SmallTest
public void testExternalIntentViaOnLoadBlocked() throws Throwable {
public void testExternalIntentViaOnLoadLaunched() throws Throwable {
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL);
IntentInterceptor intentInterceptor = new IntentInterceptor();
activity.setIntentInterceptor(intentInterceptor);
......@@ -465,14 +470,15 @@ public class ExternalNavigationTest {
TestThreadUtils.runOnUiThreadBlocking(
() -> { tab.getNavigationController().navigate(Uri.parse(url)); });
NavigationWaiter waiter = new NavigationWaiter(
INTENT_TO_CHROME_URL, tab, /*expectFailure=*/true, /*waitForPaint=*/false);
waiter.waitForNavigation();
Assert.assertNull(intentInterceptor.mLastIntent);
intentInterceptor.waitForIntent();
// The current URL should not have changed.
// The current URL should not have changed, and the intent should have been launched.
Assert.assertEquals(url, mActivityTestRule.getCurrentDisplayUrl());
Intent intent = intentInterceptor.mLastIntent;
Assert.assertNotNull(intent);
Assert.assertEquals(INTENT_TO_CHROME_PACKAGE, intent.getPackage());
Assert.assertEquals(INTENT_TO_CHROME_ACTION, intent.getAction());
Assert.assertEquals(INTENT_TO_CHROME_DATA_STRING, intent.getDataString());
}
/**
......
......@@ -435,8 +435,12 @@ void NavigationControllerImpl::DoNavigate(
return;
}
params->transition_type = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
// For WebLayer's production use cases, navigations from the embedder are most
// appropriately viewed as being from links with user gestures. In particular,
// this ensures that intents resulting from these navigations get launched as
// the embedder expects.
params->transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK);
params->has_user_gesture = true;
web_contents()->GetController().LoadURLWithParams(*params);
// So that if the user had entered the UI in a bar it stops flashing the
// caret.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment