diff --git a/android_webview/browser/aw_web_contents_delegate.cc b/android_webview/browser/aw_web_contents_delegate.cc index 28a4c1049d86c..23d2d07a8f1f2 100644 --- a/android_webview/browser/aw_web_contents_delegate.cc +++ b/android_webview/browser/aw_web_contents_delegate.cc @@ -296,7 +296,7 @@ void AwWebContentsDelegate::UpdateUserGestureCarryoverInfo( auto* intercept_navigation_delegate = navigation_interception::InterceptNavigationDelegate::Get(web_contents); if (intercept_navigation_delegate) - intercept_navigation_delegate->UpdateLastUserGestureCarryoverTimestamp(); + intercept_navigation_delegate->OnResourceRequestWithGesture(); } scoped_refptr<content::FileSelectListener> diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 20f70e752432a..72263bf55d089 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -689,8 +689,7 @@ public class AwContents implements SmartClipProvider { // private class InterceptNavigationDelegateImpl extends InterceptNavigationDelegate { @Override - public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, GURL escapedUrl, - boolean applyUserGestureCarryover) { + public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, GURL escapedUrl) { // The shouldOverrideUrlLoading call might have resulted in posting messages to the // UI thread. Using sendMessage here (instead of calling onPageStarted directly) // will allow those to run in order. diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java index 60a39f0c54149..733861a1d2b54 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java @@ -161,8 +161,7 @@ public class OverlayPanelContent { } @Override - public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, GURL escapedUrl, - boolean applyUserGestureCarryover) { + public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, GURL escapedUrl) { // If either of the required params for the delegate are null, do not call the // delegate and ignore the navigation. if (mExternalNavHandler == null || navigationHandle == null) return true; diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index c1e66af00bc8c..9c45de9ba397f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java @@ -228,8 +228,8 @@ public class ReaderModeManager extends EmptyTabObserver implements UserData { mCustomTabNavigationDelegate = new InterceptNavigationDelegate() { @Override - public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, - GURL escapedUrl, boolean applyUserGestureCarryover) { + public boolean shouldIgnoreNavigation( + NavigationHandle navigationHandle, GURL escapedUrl) { if (DomDistillerUrlUtils.isDistilledPage(navigationHandle.getUrl()) || navigationHandle.isExternalProtocol()) { return false; diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java index ee8996d9a3500..dcc3b5ef1260a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java @@ -17,6 +17,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.SystemClock; import android.support.test.InstrumentationRegistry; import android.support.test.runner.lifecycle.Stage; import android.text.TextUtils; @@ -35,6 +36,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; @@ -133,8 +135,6 @@ public class UrlOverridingTest { BASE_PATH + "navigation_from_xhr_callback_parent_frame.html"; private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_PAGE = BASE_PATH + "navigation_from_xhr_callback_and_short_timeout.html"; - private static final String NAVIGATION_FROM_XHR_CALLBACK_AND_LONG_TIMEOUT_PAGE = - BASE_PATH + "navigation_from_xhr_callback_and_long_timeout.html"; private static final String NAVIGATION_WITH_FALLBACK_URL_PAGE = BASE_PATH + "navigation_with_fallback_url.html"; private static final String NAVIGATION_WITH_FALLBACK_URL_PARENT_FRAME_PAGE = @@ -171,6 +171,9 @@ public class UrlOverridingTest { @Mock private RedirectHandler mRedirectHandler; + @Spy + private RedirectHandler mSpyRedirectHandler; + private static class TestTabObserver extends EmptyTabObserver { private final CallbackHelper mFinishCallback; private final CallbackHelper mFailCallback; @@ -579,11 +582,30 @@ public class UrlOverridingTest { @Test @SmallTest - public void testNavigationFromXHRCallbackAndLongTimeout() { + public void testNavigationFromXHRCallbackAndLongTimeout() throws Exception { mActivityTestRule.startMainActivityOnBlankPage(); - loadUrlAndWaitForIntentUrl( - mTestServer.getURL(NAVIGATION_FROM_XHR_CALLBACK_AND_LONG_TIMEOUT_PAGE), true, + + final Tab tab = mActivityTestRule.getActivity().getActivityTab(); + TestThreadUtils.runOnUiThreadBlocking( + () -> RedirectHandlerTabHelper.swapHandlerFor(tab, mSpyRedirectHandler)); + + // This is a little fragile to code changes, but better than waiting 15 real seconds. + Mockito.doReturn(SystemClock.elapsedRealtime()) // Initial Navigation create + .doReturn(SystemClock.elapsedRealtime()) // Initial Navigation shouldOverride + .doReturn(SystemClock.elapsedRealtime()) // XHR Navigation create + .doReturn(SystemClock.elapsedRealtime() + + RedirectHandler.NAVIGATION_CHAIN_TIMEOUT_MILLIS + 1) // xhr callback + .when(mSpyRedirectHandler) + .currentRealtime(); + + @OverrideUrlLoadingResultType + int result = loadUrlAndWaitForIntentUrl( + mTestServer.getURL(NAVIGATION_FROM_XHR_CALLBACK_AND_SHORT_TIMEOUT_PAGE), true, false); + + Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, result); + + assertMessagePresent(); } @Test diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java index 06ce74522a2dd..77cee839b2b6f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java @@ -111,11 +111,10 @@ public class InterceptNavigationDelegateTest { new InterceptNavigationDelegateClientImpl(tab); InterceptNavigationDelegateImpl delegate = new InterceptNavigationDelegateImpl(client) { @Override - public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, - GURL escapedUrl, boolean applyUserGestureCarryover) { + public boolean shouldIgnoreNavigation( + NavigationHandle navigationHandle, GURL escapedUrl) { mNavParamHistory.add(navigationHandle); - return super.shouldIgnoreNavigation( - navigationHandle, escapedUrl, applyUserGestureCarryover); + return super.shouldIgnoreNavigation(navigationHandle, escapedUrl); } }; client.initializeWithDelegate(delegate); diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index e95c473ee3d16..5ff2d9942fc86 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc @@ -439,7 +439,7 @@ void TabWebContentsDelegateAndroid::UpdateUserGestureCarryoverInfo( auto* intercept_navigation_delegate = navigation_interception::InterceptNavigationDelegate::Get(web_contents); if (intercept_navigation_delegate) - intercept_navigation_delegate->UpdateLastUserGestureCarryoverTimestamp(); + intercept_navigation_delegate->OnResourceRequestWithGesture(); } content::PictureInPictureResult diff --git a/chrome/test/data/android/url_overriding/navigation_from_xhr_callback_and_long_timeout.html b/chrome/test/data/android/url_overriding/navigation_from_xhr_callback_and_long_timeout.html deleted file mode 100644 index d566c7c05d50c..0000000000000 --- a/chrome/test/data/android/url_overriding/navigation_from_xhr_callback_and_long_timeout.html +++ /dev/null @@ -1,29 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta name="viewport" - content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> - <script> - var xmlhttp = new XMLHttpRequest(); - - function openApp() { - window.location = 'intent://test/#Intent;scheme=externalappscheme;end'; - }; - - function xhrOnReadyStateChange() { - if (xmlhttp.readyState==4 && xmlhttp.status==200) { - setTimeout(openApp, 11000); - } - }; - - function xhrAndOpenApp() { - xmlhttp.onreadystatechange = xhrOnReadyStateChange; - xmlhttp.open("GET", 'hello.html' , true); - xmlhttp.send(); - }; - </script> -</head> -<body style='height:10000px;' onclick='xhrAndOpenApp();'> - Click page to open App!! -</body> -</html> diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index 72d7fd3f1de9e..33ef01b0f5d1f 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java @@ -930,6 +930,24 @@ public class ExternalNavigationHandler { return false; } + /** + * See RedirectHandler#NAVIGATION_CHAIN_TIMEOUT_MILLIS for details. We don't want an unattended + * page to redirect to an app. + */ + private boolean isNavigationChainExpired(ExternalNavigationParams params) { + if (params.getRedirectHandler() != null + && params.getRedirectHandler().isNavigationChainExpired()) { + if (DEBUG) { + Log.i(TAG, + "Navigation chain expired " + + "(a page waited more than %d seconds to redirect).", + RedirectHandler.NAVIGATION_CHAIN_TIMEOUT_MILLIS); + } + return true; + } + return false; + } + /** * If the intent can't be resolved, we should fall back to the browserFallbackUrl, or try to * find the app on the market if no fallback is provided. @@ -1471,18 +1489,13 @@ public class ExternalNavigationHandler { QueryIntentActivitiesSupplier resolvingInfos = new QueryIntentActivitiesSupplier(targetIntent); - boolean requiresPromptForExternalIntent = false; - - if (redirectShouldStayInApp(params, isExternalProtocol, targetIntent, resolvingInfos)) { - requiresPromptForExternalIntent = true; - } - boolean intentMatchesNonDefaultWebApk = intentMatchesNonDefaultWebApk(params, resolvingInfos); - if (!preferToShowIntentPicker(params, isExternalProtocol, incomingIntentRedirect, - intentMatchesNonDefaultWebApk)) { - requiresPromptForExternalIntent = true; - } + + boolean requiresPromptForExternalIntent = isNavigationChainExpired(params) + || redirectShouldStayInApp(params, isExternalProtocol, targetIntent, resolvingInfos) + || !preferToShowIntentPicker(params, isExternalProtocol, incomingIntentRedirect, + intentMatchesNonDefaultWebApk); // Short-circuit expensive quertyIntentActivities calls below since we won't prompt anyways // for protocols the browser can handle. diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java index bd5a8b7e1955c..536d0a0025c17 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java @@ -24,6 +24,7 @@ import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.ConsoleMessageLevel; +import org.chromium.ui.base.PageTransition; import org.chromium.url.GURL; import org.chromium.url.Origin; @@ -103,8 +104,7 @@ public class InterceptNavigationDelegateImpl extends InterceptNavigationDelegate } @Override - public boolean shouldIgnoreNavigation( - NavigationHandle navigationHandle, GURL escapedUrl, boolean applyUserGestureCarryover) { + public boolean shouldIgnoreNavigation(NavigationHandle navigationHandle, GURL escapedUrl) { mClient.onNavigationStarted(navigationHandle); GURL url = escapedUrl; @@ -135,12 +135,6 @@ public class InterceptNavigationDelegateImpl extends InterceptNavigationDelegate return false; } - // Temporarily apply User Gesture Carryover exception for resource requests to the - // NavigationHandle. - if (applyUserGestureCarryover) { - assert !navigationHandle.hasUserGesture(); - navigationHandle.setUserGestureForCarryover(true); - } redirectHandler.updateNewUrlLoading(navigationHandle.pageTransition(), navigationHandle.isRedirect(), navigationHandle.hasUserGesture(), lastUserInteractionTime, getLastCommittedEntryIndex(), isInitialNavigation()); @@ -155,10 +149,6 @@ public class InterceptNavigationDelegateImpl extends InterceptNavigationDelegate mClient.onDecisionReachedForNavigation(navigationHandle, result); - if (applyUserGestureCarryover) { - navigationHandle.setUserGestureForCarryover(false); - } - boolean isExternalProtocol = !UrlUtilities.isAcceptedScheme(params.getUrl()); String protocolType = isExternalProtocol ? "ExternalProtocol" : "InternalProtocol"; RecordHistogram.recordEnumeratedHistogram( @@ -186,6 +176,16 @@ public class InterceptNavigationDelegateImpl extends InterceptNavigationDelegate } } + @Override + public void onResourceRequestWithGesture() { + // LINK is the default transition type, and is generally used for everything coming from a + // renderer that isn't a form submission (or subframe). + @PageTransition + int transition = PageTransition.LINK; + mClient.getOrCreateRedirectHandler().updateNewUrlLoading(transition, false, true, + mClient.getLastUserInteractionTime(), getLastCommittedEntryIndex(), false); + } + /** * Returns ExternalNavigationParams.Builder to generate ExternalNavigationParams for * ExternalNavigationHandler#shouldOverrideUrlLoading(). diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java index 5dfcd23c11a39..80b526af75f74 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java @@ -11,6 +11,8 @@ import android.os.SystemClock; import android.provider.Browser; import android.text.TextUtils; +import androidx.annotation.VisibleForTesting; + import org.chromium.base.ContextUtils; import org.chromium.base.Function; import org.chromium.base.IntentUtils; @@ -39,6 +41,14 @@ public class RedirectHandler { private static final int NAVIGATION_TYPE_FROM_RELOAD = 4; private static final int NAVIGATION_TYPE_OTHER = 5; + // Analogous to Transient User Activation in blink (See + // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation). We don't + // want an "unattended" page to redirect to an app as the user is likely not expecting that. + // However, historically there was no timeout like this for external navigation (and instead + // touching the screen reset the navigation chain), so this timeout is very generous and should + // allow for redirect chains. + public static final long NAVIGATION_CHAIN_TIMEOUT_MILLIS = 15000; + private static class IntentState { final Intent mInitialIntent; final boolean mIsCustomTabIntent; @@ -57,12 +67,14 @@ public class RedirectHandler { } } - private static class NavigationState { + private class NavigationState { final int mInitialNavigationType; final boolean mHasUserStartedNonInitialNavigation; boolean mIsOnEffectiveRedirectChain; boolean mShouldNotOverrideUrlLoadingOnCurrentRedirectChain; boolean mShouldNotBlockOverrideUrlLoadingOnCurrentRedirectionChain; + // TODO(https://crbug.com/1286053): Plumb through the user activation time from blink. + final long mNavigationChainStartTime = currentRealtime(); NavigationState(int initialNavigationType, boolean hasUserStartedNonInitialNavigation) { mInitialNavigationType = initialNavigationType; @@ -350,6 +362,16 @@ public class RedirectHandler { return mIntentState != null ? mIntentState.mInitialIntent : null; } + /** + * @return whether the navigation chain has expired, meaning + * {@link #NAVIGATION_CHAIN_TIMEOUT_MILLIS} milliseconds passed since a navigation initiated by + * the user was started. + */ + public boolean isNavigationChainExpired() { + return currentRealtime() - mNavigationState.mNavigationChainStartTime + > NAVIGATION_CHAIN_TIMEOUT_MILLIS; + } + public void maybeLogExternalRedirectBlockedWithMissingGesture() { if (mNavigationState.mInitialNavigationType == NAVIGATION_TYPE_FROM_LINK_WITHOUT_USER_GESTURE) { @@ -362,4 +384,10 @@ public class RedirectHandler { "Android.Intent.BlockedExternalNavLastGestureTime", millisSinceLastGesture); } } + + // Facilitates simulated waiting in tests. + @VisibleForTesting + public long currentRealtime() { + return SystemClock.elapsedRealtime(); + } } diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java index 327332ca30301..cafdf33ba4c43 100644 --- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java +++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java @@ -67,6 +67,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; /** @@ -2543,6 +2544,36 @@ public class ExternalNavigationHandlerTest { START_OTHER_ACTIVITY); } + @Test + @SmallTest + public void testExpiredNavigationChain() { + mDelegate.add(new IntentActivity(YOUTUBE_MOBILE_URL, YOUTUBE_PACKAGE_NAME)); + + AtomicBoolean isExpired = new AtomicBoolean(false); + RedirectHandler redirectHandler = new RedirectHandler() { + @Override + public boolean isNavigationChainExpired() { + return isExpired.get(); + } + }; + + // User clicks a link. + redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false); + + // Redirects to youtube with javascript simulated link click. + redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 1, false); + checkUrl(YOUTUBE_MOBILE_URL) + .withRedirectHandler(redirectHandler) + .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, + START_OTHER_ACTIVITY); + + // Page takes > 15 seconds to redirect. + isExpired.set(true); + checkUrl(YOUTUBE_MOBILE_URL) + .withRedirectHandler(redirectHandler) + .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE); + } + private static List<ResolveInfo> makeResolveInfos(ResolveInfo... infos) { return Arrays.asList(infos); } diff --git a/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java b/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java index 682095a6b3600..5e24c4c1f06e6 100644 --- a/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java +++ b/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java @@ -23,7 +23,7 @@ public abstract class InterceptNavigationDelegate { */ @CalledByNative public abstract boolean shouldIgnoreNavigation( - NavigationHandle navigationHandle, GURL escapedUrl, boolean applyUserGestureCarryover); + NavigationHandle navigationHandle, GURL escapedUrl); /** * This method is called for navigations to external protocols, which on Android are handled in @@ -50,6 +50,14 @@ public abstract class InterceptNavigationDelegate { true /* isExternalProtocol */, 0 /* navigationId - doesn't correspond to a native NavigationHandle*/, false /* isPageActivation */, false /* isReload */); - shouldIgnoreNavigation(navigationHandle, escapedUrl, false); + shouldIgnoreNavigation(navigationHandle, escapedUrl); } + + /** + * This method is called when a main frame requests a resource with a user gesture (eg. xhr, + * fetch, etc.). The page may wish to redirect to an app after the resource requests completes, + * which may be after blink user activation has expired. + */ + @CalledByNative + protected void onResourceRequestWithGesture() {} } diff --git a/components/navigation_interception/intercept_navigation_delegate.cc b/components/navigation_interception/intercept_navigation_delegate.cc index 15c4b5166bc6f..a155dc22dd687 100644 --- a/components/navigation_interception/intercept_navigation_delegate.cc +++ b/components/navigation_interception/intercept_navigation_delegate.cc @@ -32,8 +32,6 @@ namespace navigation_interception { namespace { -const int kMaxValidityOfUserGestureCarryoverInSeconds = 10; - const void* const kInterceptNavigationDelegateUserDataKey = &kInterceptNavigationDelegateUserDataKey; @@ -119,16 +117,9 @@ bool InterceptNavigationDelegate::ShouldIgnoreNavigation( if (jdelegate.is_null()) return false; - bool has_user_gesture = navigation_handle->HasUserGesture(); - bool apply_user_gesture_carryover = - !has_user_gesture && - base::TimeTicks::Now() - last_user_gesture_carryover_timestamp_ <= - base::Seconds(kMaxValidityOfUserGestureCarryoverInSeconds); - return Java_InterceptNavigationDelegate_shouldIgnoreNavigation( env, jdelegate, navigation_handle->GetJavaNavigationHandle(), - url::GURLAndroid::FromNativeGURL(env, escaped_url), - apply_user_gesture_carryover); + url::GURLAndroid::FromNativeGURL(env, escaped_url)); } void InterceptNavigationDelegate::HandleExternalProtocolDialog( @@ -153,8 +144,12 @@ void InterceptNavigationDelegate::HandleExternalProtocolDialog( initiating_origin ? initiating_origin->CreateJavaObject() : nullptr); } -void InterceptNavigationDelegate::UpdateLastUserGestureCarryoverTimestamp() { - last_user_gesture_carryover_timestamp_ = base::TimeTicks::Now(); +void InterceptNavigationDelegate::OnResourceRequestWithGesture() { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jobject> jdelegate = weak_jdelegate_.get(env); + if (jdelegate.is_null()) + return; + Java_InterceptNavigationDelegate_onResourceRequestWithGesture(env, jdelegate); } } // namespace navigation_interception diff --git a/components/navigation_interception/intercept_navigation_delegate.h b/components/navigation_interception/intercept_navigation_delegate.h index 6ae9ab57a01d2..b773898f90ee5 100644 --- a/components/navigation_interception/intercept_navigation_delegate.h +++ b/components/navigation_interception/intercept_navigation_delegate.h @@ -76,13 +76,12 @@ class InterceptNavigationDelegate : public base::SupportsUserData::Data { bool has_user_gesture, const absl::optional<url::Origin>& initiating_origin); - // Updates |last_user_gesture_carryover_timestamp_| when user gesture is - // carried over. - void UpdateLastUserGestureCarryoverTimestamp(); + // To be called when a main frame requests a resource with a user gesture (eg. + // xrh, fetch, etc.) + void OnResourceRequestWithGesture(); private: JavaObjectWeakGlobalRef weak_jdelegate_; - base::TimeTicks last_user_gesture_carryover_timestamp_; bool escape_external_handler_value_ = false; }; diff --git a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java index b961b68f8069c..fd38b623e145c 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java @@ -303,14 +303,6 @@ public class NavigationHandle { return mIsPageActivation; } - /** - * TODO(https://crbug.com/1310013): This is a hack, restoring M99 Chrome behavior for gesture - * carryover on resource requests. To be deleted as soon as a better alternative is agreed upon. - */ - public void setUserGestureForCarryover(boolean hasUserGesture) { - mHasUserGesture = hasUserGesture; - } - /** * Whether this navigation was initiated by a page reload. */