diff options
author | mnaganov <mnaganov@chromium.org> | 2015-03-23 14:28:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-23 21:30:06 +0000 |
commit | 7a3234c9a19a38726a4a984ff12e2b406423c1d3 (patch) | |
tree | 565d43f11238ce6e2c79c7ce56957d36c784796b /android_webview | |
parent | 03b770885dbf8d873c38f72b98fd4faddf80633e (diff) | |
download | chromium_src-7a3234c9a19a38726a4a984ff12e2b406423c1d3.zip chromium_src-7a3234c9a19a38726a4a984ff12e2b406423c1d3.tar.gz chromium_src-7a3234c9a19a38726a4a984ff12e2b406423c1d3.tar.bz2 |
[Android WebView] Provide user-initiated provisional load detection
Do not synthesize page loading events on DOM modification, if the provisional
load has been started from the API side.
It appears that a lot of apps tend to use the following scenario:
webView.loadUrl(...);
webView.loadUrl('javascript:...');
Which was triggering page loading events to be emitted. This scenario is
dubious, as no one guarantees that loading will actually finish prior to
executing javascript. But for compatibility reasons we must take it into
account and not emit page loading events for "about:blank", as it seems
that some apps do unexpected things when they receive it.
BUG=458569,469099
Review URL: https://codereview.chromium.org/1024103002
Cr-Commit-Position: refs/heads/master@{#321857}
Diffstat (limited to 'android_webview')
3 files changed, 26 insertions, 20 deletions
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 a61311c..8df209d 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -2294,7 +2294,7 @@ public class AwContents implements SmartClipProvider, public boolean getDidAttemptLoad() { if (mDidAttemptLoad) return mDidAttemptLoad; - mDidAttemptLoad = mWebContentsObserver.hasStartedAnyProvisionalLoad(); + mDidAttemptLoad = mWebContentsObserver.hasStartedNonApiProvisionalLoadInMainFrame(); return mDidAttemptLoad; } diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java index f985369..f600470 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java @@ -6,9 +6,11 @@ package org.chromium.android_webview; import org.chromium.android_webview.AwContents.VisualStateCallback; import org.chromium.base.ThreadUtils; +import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.net.NetError; +import org.chromium.ui.base.PageTransition; import java.lang.ref.WeakReference; @@ -22,7 +24,7 @@ public class AwWebContentsObserver extends WebContentsObserver { // and should be found and cleaned up. private final WeakReference<AwContents> mAwContents; private final AwContentsClient mAwContentsClient; - private boolean mHasStartedAnyProvisionalLoad = false; + private boolean mStartedNonApiProvisionalLoadInMainFrame = false; public AwWebContentsObserver( WebContents webContents, AwContents awContents, AwContentsClient awContentsClient) { @@ -31,8 +33,8 @@ public class AwWebContentsObserver extends WebContentsObserver { mAwContentsClient = awContentsClient; } - boolean hasStartedAnyProvisionalLoad() { - return mHasStartedAnyProvisionalLoad; + boolean hasStartedNonApiProvisionalLoadInMainFrame() { + return mStartedNonApiProvisionalLoadInMainFrame; } @Override @@ -99,6 +101,14 @@ public class AwWebContentsObserver extends WebContentsObserver { String validatedUrl, boolean isErrorPage, boolean isIframeSrcdoc) { - mHasStartedAnyProvisionalLoad = true; + if (!isMainFrame) return; + AwContents awContents = mAwContents.get(); + if (awContents != null) { + NavigationEntry pendingEntry = awContents.getNavigationController().getPendingEntry(); + if (pendingEntry != null + && (pendingEntry.getTransition() & PageTransition.FROM_API) == 0) { + mStartedNonApiProvisionalLoadInMainFrame = true; + } + } } } diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java index 1084c0f..a574fc0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java @@ -285,7 +285,7 @@ public class ClientOnPageFinishedTest extends AwTestBase { public void testOnPageFinishedNotCalledOnDomModificationForBlankWebView() throws Throwable { TestWebServer webServer = TestWebServer.start(); try { - doTestOnPageFinishedNotCalledOnDomMutation(webServer); + doTestOnPageFinishedNotCalledOnDomMutation(webServer, null); } finally { webServer.shutdown(); } @@ -293,20 +293,14 @@ public class ClientOnPageFinishedTest extends AwTestBase { @MediumTest @Feature({"AndroidWebView"}) - public void testOnPageFinishedCalledOnDomModificationAfterNonCommittedLoad() throws Throwable { + public void testOnPageFinishedNotCalledOnDomModificationAfterNonCommittedLoadFromApi() + throws Throwable { enableJavaScriptOnUiThread(mAwContents); TestWebServer webServer = TestWebServer.start(); try { final String noContentUrl = webServer.setResponseWithNoContentStatus("/nocontent.html"); - TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = - mContentsClient.getOnPageFinishedHelper(); - final int onPageFinishedCallCount = onPageFinishedHelper.getCallCount(); loadUrlAsync(mAwContents, noContentUrl); - // Mutate DOM. - executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, - "document.body.innerHTML='Hello, World!'"); - onPageFinishedHelper.waitForCallback(onPageFinishedCallCount); - assertEquals("about:blank", onPageFinishedHelper.getUrl()); + doTestOnPageFinishedNotCalledOnDomMutation(webServer, noContentUrl); } finally { webServer.shutdown(); } @@ -320,7 +314,7 @@ public class ClientOnPageFinishedTest extends AwTestBase { final String testUrl = webServer.setResponse("/test.html", CommonResources.ABOUT_HTML, null); loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), testUrl); - doTestOnPageFinishedNotCalledOnDomMutation(webServer); + doTestOnPageFinishedNotCalledOnDomMutation(webServer, null); } finally { webServer.shutdown(); } @@ -334,13 +328,13 @@ public class ClientOnPageFinishedTest extends AwTestBase { try { loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML, "text/html", false); - doTestOnPageFinishedNotCalledOnDomMutation(webServer); + doTestOnPageFinishedNotCalledOnDomMutation(webServer, null); } finally { webServer.shutdown(); } } - private void doTestOnPageFinishedNotCalledOnDomMutation(TestWebServer webServer) + private void doTestOnPageFinishedNotCalledOnDomMutation(TestWebServer webServer, String syncUrl) throws Throwable { enableJavaScriptOnUiThread(mAwContents); TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = @@ -353,8 +347,10 @@ public class ClientOnPageFinishedTest extends AwTestBase { // we load another valid page. Since callbacks arrive sequentially if the next callback // we get is for the synchronizationUrl we know that DOM mutation did not schedule // a callback for the iframe. - final String syncUrl = webServer.setResponse("/sync.html", "", null); - loadUrlAsync(mAwContents, syncUrl); + if (syncUrl == null) { + syncUrl = webServer.setResponse("/sync.html", "", null); + loadUrlAsync(mAwContents, syncUrl); + } onPageFinishedHelper.waitForCallback(onPageFinishedCallCount); assertEquals(syncUrl, onPageFinishedHelper.getUrl()); assertEquals(onPageFinishedCallCount + 1, onPageFinishedHelper.getCallCount()); |