Title: [186434] releases/WebKitGTK/webkit-2.8
Revision
186434
Author
[email protected]
Date
2015-07-07 03:33:34 -0700 (Tue, 07 Jul 2015)

Log Message

Merge r186049 - Crash: com.apple.WebKit.WebContent at com.apple.WebCore: WebCore::CachedFrameBase::restore + 333
https://bugs.webkit.org/show_bug.cgi?id=146388
<rdar://problem/21567343>

Reviewed by Darin Adler.

Source/WebCore:

Pages that are currently loading are not supposed to go into the
PageCache. However, PageCache::canCache() only checks if the
FrameLoader's documentLoader is loading. If the subframe is in
provisional load stage, we would fail to detect that the frame is
actually loading because the FrameLoader active documentLoader would
be the provisional documentLoader, not the regular documentLoader.
Therefore, the page would get added to the PageCache and the frame
would keep loading while in the PageCache.

On http://www.audiusa.com/models, this is what was happening. It was
crashing because the subframe would finish loading while in the
PageCache, in which case we would fire the 'load' event and the
content 'load' event handler would then proceed to remove the iframe.
Upon restoring the PageCache entry, we would run into trouble as we
would have a CachedFrame whose Frame has been removed.

The solution proposed is to prevent page-caching if a subframe is in
provisional load stage.

Test: http/tests/navigation/page-cache-iframe-provisional-load.html

* history/PageCache.cpp:
(WebCore::logCanCacheFrameDecision):
(WebCore::PageCache::canCachePageContainingThisFrame):
* page/DiagnosticLoggingKeys.cpp:
(WebCore::DiagnosticLoggingKeys::provisionalLoadKey):
* page/DiagnosticLoggingKeys.h:

LayoutTests:

Add layout test to cover the case where a subframe is currently in
provisional load stage when checking if the page if page-cacheable.

The test also removes the iframe once loaded in order to cause a crash
if the frame were to finish loading while in the page cache.

* http/tests/navigation/page-cache-iframe-provisional-load-expected.txt: Added.
* http/tests/navigation/page-cache-iframe-provisional-load.html: Added.
* http/tests/navigation/resources/page-cache-helper-slow.html: Added.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog (186433 => 186434)


--- releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog	2015-07-07 10:22:13 UTC (rev 186433)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog	2015-07-07 10:33:34 UTC (rev 186434)
@@ -1,3 +1,21 @@
+2015-06-28  Chris Dumez  <[email protected]>
+
+        Crash: com.apple.WebKit.WebContent at com.apple.WebCore: WebCore::CachedFrameBase::restore + 333
+        https://bugs.webkit.org/show_bug.cgi?id=146388
+        <rdar://problem/21567343>
+
+        Reviewed by Darin Adler.
+
+        Add layout test to cover the case where a subframe is currently in
+        provisional load stage when checking if the page if page-cacheable.
+
+        The test also removes the iframe once loaded in order to cause a crash
+        if the frame were to finish loading while in the page cache.
+
+        * http/tests/navigation/page-cache-iframe-provisional-load-expected.txt: Added.
+        * http/tests/navigation/page-cache-iframe-provisional-load.html: Added.
+        * http/tests/navigation/resources/page-cache-helper-slow.html: Added.
+
 2015-06-25  Zalan Bujtas  <[email protected]>
 
         Do not send touch events to the slider's thumb when it does not have a renderer.

Added: releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load-expected.txt (0 => 186434)


--- releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load-expected.txt	2015-07-07 10:33:34 UTC (rev 186434)
@@ -0,0 +1,11 @@
+A frame in provisional load stage should prevent page caching.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+pageshow - not from cache
+PASS Page was not restored from PageCache
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load.html (0 => 186434)


--- releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/page-cache-iframe-provisional-load.html	2015-07-07 10:33:34 UTC (rev 186434)
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("A frame in provisional load stage should prevent page caching.");
+window.jsTestIsAsync = true;
+
+if (window.testRunner)
+    testRunner.overridePreference("WebKitUsesPageCachePreferenceKey", 1);
+
+window.addEventListener("pageshow", function(event) {
+    debug("pageshow - " + (event.persisted ? "" : "not ") + "from cache");
+
+    if (!window.sessionStorage.page_cache_provisional_load_test_started)
+        return;
+
+    delete window.sessionStorage.page_cache_provisional_load_test_started;
+
+    if (event.persisted)
+        testFailed("Page was restored from PageCache");
+    else
+        testPassed("Page was not restored from PageCache");
+
+    finishJSTest();
+}, false);
+
+window.addEventListener("pagehide", function(event) {
+    debug("pagehide");
+}, false);
+
+function loadSubframeAndNavigateAway()
+{
+    // Force a back navigation back to this page.
+    window.sessionStorage.page_cache_provisional_load_test_started = true;
+    window.location.href = ""
+
+    var testFrame = document.getElementById("testFrame");
+    testFrame.src = ""
+
+    // If the page goes into the page cache and the frame keeps loading while in the cache,
+    // the following will cause crashes.
+    testFrame._onload_ = function() { document.getElementById("testFrame").remove(); };
+}
+
+window.addEventListener('load', function() {
+    setTimeout(function() {
+        loadSubframeAndNavigateAway();
+    }, 0);
+}, false);
+
+</script>
+<iframe id="testFrame" src=""
+<script src=""
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/resources/page-cache-helper-slow.html (0 => 186434)


--- releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/resources/page-cache-helper-slow.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/http/tests/navigation/resources/page-cache-helper-slow.html	2015-07-07 10:33:34 UTC (rev 186434)
@@ -0,0 +1,9 @@
+This page should go back. If a test outputs the contents of this
+page, then the test page failed to enter the page cache.
+<script>
+  window.addEventListener("load", function() {
+    setTimeout(function() {
+      history.back();
+    }, 500);
+  }, false);
+</script>

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog (186433 => 186434)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog	2015-07-07 10:22:13 UTC (rev 186433)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog	2015-07-07 10:33:34 UTC (rev 186434)
@@ -1,3 +1,39 @@
+2015-06-28  Chris Dumez  <[email protected]>
+
+        Crash: com.apple.WebKit.WebContent at com.apple.WebCore: WebCore::CachedFrameBase::restore + 333
+        https://bugs.webkit.org/show_bug.cgi?id=146388
+        <rdar://problem/21567343>
+
+        Reviewed by Darin Adler.
+
+        Pages that are currently loading are not supposed to go into the
+        PageCache. However, PageCache::canCache() only checks if the
+        FrameLoader's documentLoader is loading. If the subframe is in
+        provisional load stage, we would fail to detect that the frame is
+        actually loading because the FrameLoader active documentLoader would
+        be the provisional documentLoader, not the regular documentLoader.
+        Therefore, the page would get added to the PageCache and the frame
+        would keep loading while in the PageCache.
+
+        On http://www.audiusa.com/models, this is what was happening. It was
+        crashing because the subframe would finish loading while in the
+        PageCache, in which case we would fire the 'load' event and the
+        content 'load' event handler would then proceed to remove the iframe.
+        Upon restoring the PageCache entry, we would run into trouble as we
+        would have a CachedFrame whose Frame has been removed.
+
+        The solution proposed is to prevent page-caching if a subframe is in
+        provisional load stage.
+
+        Test: http/tests/navigation/page-cache-iframe-provisional-load.html
+
+        * history/PageCache.cpp:
+        (WebCore::logCanCacheFrameDecision):
+        (WebCore::PageCache::canCachePageContainingThisFrame):
+        * page/DiagnosticLoggingKeys.cpp:
+        (WebCore::DiagnosticLoggingKeys::provisionalLoadKey):
+        * page/DiagnosticLoggingKeys.h:
+
 2015-06-25  Zalan Bujtas  <[email protected]>
 
         Do not send touch events to the slider's thumb when it does not have a renderer.

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/history/PageCache.cpp (186433 => 186434)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/history/PageCache.cpp	2015-07-07 10:22:13 UTC (rev 186433)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/history/PageCache.cpp	2015-07-07 10:33:34 UTC (rev 186434)
@@ -93,6 +93,7 @@
     DocumentLoaderUsesApplicationCache,
     ClientDeniesCaching,
     NumberOfReasonsFramesCannotBeInPageCache,
+    IsInProvisionalLoadStage,
 };
 COMPILE_ASSERT(NumberOfReasonsFramesCannotBeInPageCache <= sizeof(unsigned)*8, ReasonFrameCannotBeInPageCacheDoesNotFitInBitmap);
 
@@ -112,6 +113,11 @@
 static unsigned logCanCacheFrameDecision(Frame& frame, DiagnosticLoggingClient& diagnosticLoggingClient, unsigned indentLevel)
 {
     PCLOG("+---");
+    if (!frame.isMainFrame() && frame.loader().state() == FrameStateProvisional) {
+        PCLOG("   -Frame is in provisional load stage");
+        logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::provisionalLoadKey());
+        return 1 << IsInProvisionalLoadStage;
+    }
     if (!frame.loader().documentLoader()) {
         PCLOG("   -There is no DocumentLoader object");
         logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::noDocumentLoaderKey());
@@ -305,6 +311,12 @@
     }
     
     FrameLoader& frameLoader = frame.loader();
+
+    // Prevent page caching if a subframe is still in provisional load stage.
+    // We only do this check for subframes because the main frame is reused when navigating to a new page.
+    if (!frame.isMainFrame() && frameLoader.state() == FrameStateProvisional)
+        return false;
+
     DocumentLoader* documentLoader = frameLoader.documentLoader();
     Document* document = frame.document();
     

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.cpp (186433 => 186434)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.cpp	2015-07-07 10:22:13 UTC (rev 186433)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.cpp	2015-07-07 10:33:34 UTC (rev 186434)
@@ -53,6 +53,11 @@
     return ASCIILiteral("pluginFailedLoading");
 }
 
+String DiagnosticLoggingKeys::provisionalLoadKey()
+{
+    return ASCIILiteral("provisionalLoad");
+}
+
 String DiagnosticLoggingKeys::pageContainsPluginKey()
 {
     return ASCIILiteral("pageContainsPlugin");

Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.h (186433 => 186434)


--- releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.h	2015-07-07 10:22:13 UTC (rev 186433)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/page/DiagnosticLoggingKeys.h	2015-07-07 10:33:34 UTC (rev 186434)
@@ -81,6 +81,7 @@
     static String playedKey();
     static String pluginLoadedKey();
     static String pluginLoadingFailedKey();
+    static String provisionalLoadKey();
     static String prunedDueToMaxSizeReached();
     static String prunedDueToMemoryPressureKey();
     static String prunedDueToProcessSuspended();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to