Commit 6d967f87 authored by Bo Liu's avatar Bo Liu Committed by Commit Bot

aw: Delay onPageStarted until navigation commit part 2

This CL moves onPageStarted to page commit for browser navigations.
However the old code path is not removed since we still do not want to
enable this for old versions of GMSCore. Add a kill switch feature
that's disabled by default and a test finch config to enable it for
testing.

Bug: 896022
Change-Id: I7cd0777687ca4be096209a3a0cfed8dba4e5bd13
Reviewed-on: https://chromium-review.googlesource.com/c/1327170Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607466}
parent 1f1be08c
...@@ -24,6 +24,7 @@ namespace { ...@@ -24,6 +24,7 @@ namespace {
// in other locations in the code base (e.g. content/, components/, etc). // in other locations in the code base (e.g. content/, components/, etc).
const base::Feature* kFeaturesExposedToJava[] = { const base::Feature* kFeaturesExposedToJava[] = {
&features::kWebViewConnectionlessSafeBrowsing, &features::kWebViewConnectionlessSafeBrowsing,
&features::kWebViewPageStartedOnCommit,
}; };
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) { const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
...@@ -47,6 +48,11 @@ namespace features { ...@@ -47,6 +48,11 @@ namespace features {
const base::Feature kWebViewConnectionlessSafeBrowsing{ const base::Feature kWebViewConnectionlessSafeBrowsing{
"WebViewConnectionlessSafeBrowsing", base::FEATURE_DISABLED_BY_DEFAULT}; "WebViewConnectionlessSafeBrowsing", base::FEATURE_DISABLED_BY_DEFAULT};
// Kill switch for feature to call onPageFinished for browser-initiated
// navigations when the navigation commits.
const base::Feature kWebViewPageStartedOnCommit{
"WebViewPageStartedOnCommit", base::FEATURE_DISABLED_BY_DEFAULT};
// Whether the application package name is logged in UMA. // Whether the application package name is logged in UMA.
const base::Feature kWebViewUmaLogAppPackageName{ const base::Feature kWebViewUmaLogAppPackageName{
"WebViewUmaLogAppPackageName", base::FEATURE_DISABLED_BY_DEFAULT}; "WebViewUmaLogAppPackageName", base::FEATURE_DISABLED_BY_DEFAULT};
......
...@@ -15,6 +15,7 @@ namespace features { ...@@ -15,6 +15,7 @@ namespace features {
// Alphabetical: // Alphabetical:
extern const base::Feature kWebViewConnectionlessSafeBrowsing; extern const base::Feature kWebViewConnectionlessSafeBrowsing;
extern const base::Feature kWebViewPageStartedOnCommit;
extern const base::Feature kWebViewUmaLogAppPackageName; extern const base::Feature kWebViewUmaLogAppPackageName;
} // namespace features } // namespace features
......
...@@ -640,7 +640,7 @@ public class AwContents implements SmartClipProvider { ...@@ -640,7 +640,7 @@ public class AwContents implements SmartClipProvider {
// The shouldOverrideUrlLoading call might have resulted in posting messages to the // The shouldOverrideUrlLoading call might have resulted in posting messages to the
// UI thread. Using sendMessage here (instead of calling onPageStarted directly) // UI thread. Using sendMessage here (instead of calling onPageStarted directly)
// will allow those to run in order. // will allow those to run in order.
if (!navigationParams.isRendererInitiated) { if (!AwFeatureList.pageStartedOnCommitEnabled(navigationParams.isRendererInitiated)) {
mContentsClient.getCallbackHelper().postOnPageStarted(navigationParams.url); mContentsClient.getCallbackHelper().postOnPageStarted(navigationParams.url);
} }
return false; return false;
......
...@@ -301,7 +301,8 @@ public class AwContentsClientBridge { ...@@ -301,7 +301,8 @@ public class AwContentsClientBridge {
} else { } else {
error.errorCode = ErrorCodeConversionHelper.convertErrorCode(error.errorCode); error.errorCode = ErrorCodeConversionHelper.convertErrorCode(error.errorCode);
} }
if (request.isMainFrame && isRendererInitiated) { if (request.isMainFrame
&& AwFeatureList.pageStartedOnCommitEnabled(isRendererInitiated)) {
mClient.getCallbackHelper().postOnPageStarted(request.url); mClient.getCallbackHelper().postOnPageStarted(request.url);
} }
mClient.getCallbackHelper().postOnReceivedError(request, error); mClient.getCallbackHelper().postOnReceivedError(request, error);
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
package org.chromium.android_webview; package org.chromium.android_webview;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.MainDex; import org.chromium.base.annotations.MainDex;
...@@ -16,6 +20,36 @@ final public class AwFeatureList { ...@@ -16,6 +20,36 @@ final public class AwFeatureList {
// Do not instantiate this class. // Do not instantiate this class.
private AwFeatureList() {} private AwFeatureList() {}
private static final String GMS_PACKAGE = "com.google.android.gms";
private static Boolean sPageStartedOnCommitForBrowserNavigations;
private static boolean computePageStartedOnCommitForBrowserNavigations() {
if (!nativeIsEnabled(WEBVIEW_PAGE_STARTED_ON_COMMIT)) return false;
if (GMS_PACKAGE.equals(ContextUtils.getApplicationContext().getPackageName())) {
try {
PackageInfo gmsPackage =
ContextUtils.getApplicationContext().getPackageManager().getPackageInfo(
GMS_PACKAGE, 0);
return gmsPackage.versionCode >= 15000000;
} catch (PackageManager.NameNotFoundException e) {
}
return false;
}
return true;
}
public static boolean pageStartedOnCommitEnabled(boolean isRendererInitiated) {
// Always enable for renderer-initiated navigations.
if (isRendererInitiated) return true;
if (sPageStartedOnCommitForBrowserNavigations != null) {
return sPageStartedOnCommitForBrowserNavigations;
}
sPageStartedOnCommitForBrowserNavigations =
computePageStartedOnCommitForBrowserNavigations();
return sPageStartedOnCommitForBrowserNavigations;
}
/** /**
* Returns whether the specified feature is enabled or not. * Returns whether the specified feature is enabled or not.
* *
...@@ -32,6 +66,7 @@ final public class AwFeatureList { ...@@ -32,6 +66,7 @@ final public class AwFeatureList {
// Alphabetical: // Alphabetical:
public static final String WEBVIEW_CONNECTIONLESS_SAFE_BROWSING = public static final String WEBVIEW_CONNECTIONLESS_SAFE_BROWSING =
"WebViewConnectionlessSafeBrowsing"; "WebViewConnectionlessSafeBrowsing";
public static final String WEBVIEW_PAGE_STARTED_ON_COMMIT = "WebViewPageStartedOnCommit";
private static native boolean nativeIsEnabled(String featureName); private static native boolean nativeIsEnabled(String featureName);
} }
...@@ -107,7 +107,8 @@ public class AwWebContentsObserver extends WebContentsObserver { ...@@ -107,7 +107,8 @@ public class AwWebContentsObserver extends WebContentsObserver {
if (client != null) { if (client != null) {
// OnPageStarted is not called for fragment navigations. // OnPageStarted is not called for fragment navigations.
// Error page is handled by AwContentsClientBridge.onReceivedError. // Error page is handled by AwContentsClientBridge.onReceivedError.
if (!isFragmentNavigation && !isErrorPage && isRendererInitiated) { if (!isFragmentNavigation && !isErrorPage
&& AwFeatureList.pageStartedOnCommitEnabled(isRendererInitiated)) {
client.getCallbackHelper().postOnPageStarted(url); client.getCallbackHelper().postOnPageStarted(url);
} }
......
...@@ -285,19 +285,21 @@ public class ClientOnPageStartedTest { ...@@ -285,19 +285,21 @@ public class ClientOnPageStartedTest {
int hangingRequestCount = mHangingRequestCallbackHelper.getCallCount(); int hangingRequestCount = mHangingRequestCallbackHelper.getCallCount();
mActivityTestRule.loadUrlAsync(mAwContents, mHangingUrl); mActivityTestRule.loadUrlAsync(mAwContents, mHangingUrl);
// onPageStarted should be called, but not onPageFinished. // onPageStarted and onPageFinished should not be called yet.
mContentsClient.getOnLoadResourceHelper().waitForCallback(onLoadResourceCount); mContentsClient.getOnLoadResourceHelper().waitForCallback(onLoadResourceCount);
mHangingRequestCallbackHelper.waitForCallback(hangingRequestCount); mHangingRequestCallbackHelper.waitForCallback(hangingRequestCount);
mContentsClient.getOnPageStartedHelper().waitForCallback(pageStartedCount);
Assert.assertEquals( Assert.assertEquals(
mHangingUrl, mContentsClient.getOnLoadResourceHelper().getLastLoadedResource()); mHangingUrl, mContentsClient.getOnLoadResourceHelper().getLastLoadedResource());
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageStartedHelper().getUrl()); Assert.assertEquals(
pageStartedCount, mContentsClient.getOnPageStartedHelper().getCallCount());
Assert.assertEquals( Assert.assertEquals(
pageFinishedCount, mContentsClient.getOnPageFinishedHelper().getCallCount()); pageFinishedCount, mContentsClient.getOnPageFinishedHelper().getCallCount());
// Release request on server. Should get onPageStarted/Finished after. // Release request on server. Should get onPageStarted/Finished after.
mHangingRequestSemaphore.release(); mHangingRequestSemaphore.release();
mContentsClient.getOnPageStartedHelper().waitForCallback(pageStartedCount);
mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount); mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount);
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageStartedHelper().getUrl());
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageFinishedHelper().getUrl()); Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageFinishedHelper().getUrl());
} }
...@@ -356,24 +358,26 @@ public class ClientOnPageStartedTest { ...@@ -356,24 +358,26 @@ public class ClientOnPageStartedTest {
int hangingRequestCount = mHangingRequestCallbackHelper.getCallCount(); int hangingRequestCount = mHangingRequestCallbackHelper.getCallCount();
mActivityTestRule.loadUrlAsync(mAwContents, mRedirectToHangingUrl); mActivityTestRule.loadUrlAsync(mAwContents, mRedirectToHangingUrl);
// onPageStarted should be called, but not onPageFinished. // onPageStarted and onPageFinished should not be called yet.
mContentsClient.getShouldOverrideUrlLoadingHelper().waitForCallback( mContentsClient.getShouldOverrideUrlLoadingHelper().waitForCallback(
shouldOverrideUrlLoadingCount); shouldOverrideUrlLoadingCount);
mContentsClient.getOnLoadResourceHelper().waitForCallback(onLoadResourceCount); mContentsClient.getOnLoadResourceHelper().waitForCallback(onLoadResourceCount);
mHangingRequestCallbackHelper.waitForCallback(hangingRequestCount); mHangingRequestCallbackHelper.waitForCallback(hangingRequestCount);
mContentsClient.getOnPageStartedHelper().waitForCallback(pageStartedCount);
Assert.assertEquals(mHangingUrl, Assert.assertEquals(mHangingUrl,
mContentsClient.getShouldOverrideUrlLoadingHelper() mContentsClient.getShouldOverrideUrlLoadingHelper()
.getShouldOverrideUrlLoadingUrl()); .getShouldOverrideUrlLoadingUrl());
Assert.assertEquals(mRedirectToHangingUrl, Assert.assertEquals(mRedirectToHangingUrl,
mContentsClient.getOnLoadResourceHelper().getLastLoadedResource()); mContentsClient.getOnLoadResourceHelper().getLastLoadedResource());
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageStartedHelper().getUrl()); Assert.assertEquals(
pageStartedCount, mContentsClient.getOnPageStartedHelper().getCallCount());
Assert.assertEquals( Assert.assertEquals(
pageFinishedCount, mContentsClient.getOnPageFinishedHelper().getCallCount()); pageFinishedCount, mContentsClient.getOnPageFinishedHelper().getCallCount());
// Release request on server. Should get onPageStarted/Finished after. // Release request on server. Should get onPageStarted/Finished after.
mHangingRequestSemaphore.release(); mHangingRequestSemaphore.release();
mContentsClient.getOnPageStartedHelper().waitForCallback(pageStartedCount);
mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount); mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount);
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageStartedHelper().getUrl());
Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageFinishedHelper().getUrl()); Assert.assertEquals(mHangingUrl, mContentsClient.getOnPageFinishedHelper().getUrl());
} }
} }
...@@ -37,10 +37,51 @@ ...@@ -37,10 +37,51 @@
{ {
"apk": "android-cts/repository/testcases/CtsWebkitTestCases.apk", "apk": "android-cts/repository/testcases/CtsWebkitTestCases.apk",
"excludes": [ "excludes": [
{ {
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoadingOnCreateWindow", "match": "android.webkit.cts.WebViewClientTest#testDoUpdateVisitedHistory",
"_bug_id": "crbug.com/896857" "_bug_id": "crbug.com/896022"
}] },
{
"match": "android.webkit.cts.WebViewClientTest#testLoadPage",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnFormResubmission",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedError",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedErrorForSubresource",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedHttpAuthRequest",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedHttpError",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedLoginRequest",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnScaleChanged",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoading",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoadingOnCreateWindow",
"_bug_id": "crbug.com/896022"
}
]
}, },
{ {
"apk": "android-cts/repository/testcases/CtsWidgetTestCases.apk", "apk": "android-cts/repository/testcases/CtsWidgetTestCases.apk",
...@@ -58,10 +99,51 @@ ...@@ -58,10 +99,51 @@
{ {
"apk": "android-cts/repository/testcases/CtsWebkitTestCases.apk", "apk": "android-cts/repository/testcases/CtsWebkitTestCases.apk",
"excludes": [ "excludes": [
{ {
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoadingOnCreateWindow", "match": "android.webkit.cts.WebViewClientTest#testDoUpdateVisitedHistory",
"_bug_id": "crbug.com/896857" "_bug_id": "crbug.com/896022"
}] },
{
"match": "android.webkit.cts.WebViewClientTest#testLoadPage",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnFormResubmission",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedError",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedErrorForSubresource",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedHttpAuthRequest",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedHttpError",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnReceivedLoginRequest",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testOnScaleChanged",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoading",
"_bug_id": "crbug.com/896022"
},
{
"match": "android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoadingOnCreateWindow",
"_bug_id": "crbug.com/896022"
}
]
}, },
{ {
"apk": "android-cts/repository/testcases/CtsWidgetTestCases.apk", "apk": "android-cts/repository/testcases/CtsWidgetTestCases.apk",
......
...@@ -477,6 +477,21 @@ ...@@ -477,6 +477,21 @@
] ]
} }
], ],
"AndroidWebViewPageStartedOnCommit": [
{
"platforms": [
"android_webview"
],
"experiments": [
{
"name": "Enabled",
"enable_features": [
"WebViewPageStartedOnCommit"
]
}
]
}
],
"AppLauncherRefresh": [ "AppLauncherRefresh": [
{ {
"platforms": [ "platforms": [
......
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