REGRESSION(r150867): FrameView auto-sizing + delegate denied image load may cause...
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jul 2013 00:53:57 +0000 (00:53 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jul 2013 00:53:57 +0000 (00:53 +0000)
<rdar://problem/14324895>
<http://webkit.org/b/119023>

Reviewed by Simon Fraser.

Source/WebCore:

The bug happened when FrameView::autoSizeIfEnabled() was getting called below FrameLoader::checkCompleted()
triggered by an incorrect loadDone() callback originating in SubresourceLoader::didCancel().

* css/StyleResolver.cpp:
(WebCore::StyleResolver::loadPendingResources):

    Add an assertion that this function is not getting re-entered. If a similar bug occurs
    in the future, this will help the lucky person debugging.

* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::didCancel):

    Don't notifyDone() if the SubresourceLoader is in Uninitialized state.

Tools:

Add a test for this rather specific problem.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm: Added.
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp: Added.
(TestWebKitAPI::DenyWillSendRequestTest::DenyWillSendRequestTest):
(TestWebKitAPI::DenyWillSendRequestTest::willSendRequestForFrame):
(TestWebKitAPI::DenyWillSendRequestTest::didCreatePage):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@153072 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/loader/SubresourceLoader.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp [new file with mode: 0644]

index f996441..0241865 100644 (file)
@@ -1,3 +1,25 @@
+2013-07-23  Andreas Kling  <akling@apple.com>
+
+        REGRESSION(r150867): FrameView auto-sizing + delegate denied image load may cause StyleResolver to re-enter itself.
+        <rdar://problem/14324895>
+        <http://webkit.org/b/119023>
+
+        Reviewed by Simon Fraser.
+
+        The bug happened when FrameView::autoSizeIfEnabled() was getting called below FrameLoader::checkCompleted()
+        triggered by an incorrect loadDone() callback originating in SubresourceLoader::didCancel().
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::loadPendingResources):
+
+            Add an assertion that this function is not getting re-entered. If a similar bug occurs
+            in the future, this will help the lucky person debugging.
+
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::didCancel):
+
+            Don't notifyDone() if the SubresourceLoader is in Uninitialized state.
+
 2013-07-23  Tim Horton  <timothy_horton@apple.com>
 
         Pixel-snap the unavailable plugin indicator arrow for maximum sharpness
index a100ae4..26352e6 100644 (file)
@@ -4198,6 +4198,10 @@ void StyleResolver::loadPendingImages()
     m_state.pendingImageProperties().clear();
 }
 
+#ifndef NDEBUG
+static bool inLoadPendingResources = false;
+#endif
+
 void StyleResolver::loadPendingResources()
 {
     // We've seen crashes in all three of the functions below. Some of them
@@ -4207,6 +4211,12 @@ void StyleResolver::loadPendingResources()
     if (!style())
         return;
 
+#ifndef NDEBUG
+    // Re-entering this function will probably mean trouble. Catch it in debug builds.
+    ASSERT(!inLoadPendingResources);
+    inLoadPendingResources = true;
+#endif
+
     // Start loading images referenced by this style.
     loadPendingImages();
 
@@ -4219,6 +4229,10 @@ void StyleResolver::loadPendingResources()
     // Start loading the SVG Documents referenced by this style.
     loadPendingSVGDocuments();
 #endif
+
+#ifndef NDEBUG
+    inLoadPendingResources = false;
+#endif
 }
 
 inline StyleResolver::MatchedProperties::MatchedProperties()
index cf619e4..fafd6e3 100644 (file)
@@ -334,6 +334,9 @@ void SubresourceLoader::willCancel(const ResourceError& error)
 
 void SubresourceLoader::didCancel(const ResourceError&)
 {
+    if (m_state == Uninitialized)
+        return;
+
     m_resource->cancelLoad();
     notifyDone();
 }
index 63e8407..5ee67ca 100644 (file)
@@ -1,3 +1,21 @@
+2013-07-23  Andreas Kling  <akling@apple.com>
+
+        REGRESSION(r150867): FrameView auto-sizing + delegate denied image load may cause StyleResolver to re-enter itself.
+        <rdar://problem/14324895>
+        <http://webkit.org/b/119023>
+
+        Reviewed by Simon Fraser.
+
+        Add a test for this rather specific problem.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm: Added.
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp: Added.
+        (TestWebKitAPI::DenyWillSendRequestTest::DenyWillSendRequestTest):
+        (TestWebKitAPI::DenyWillSendRequestTest::willSendRequestForFrame):
+        (TestWebKitAPI::DenyWillSendRequestTest::didCreatePage):
+
 2013-07-23  Tim Horton  <timothy_horton@apple.com>
 
         Add a test for plug-in unavailability indicator obscurity detection
index 1bdb2c6..4e2a5d5 100644 (file)
                A5E2027515B21F6E00C13E14 /* WindowlessWebViewWithMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = A5E2027015B2180600C13E14 /* WindowlessWebViewWithMedia.html */; };
                A7A966DB140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */; };
                B4039F9D15E6D8B3007255D6 /* MathExtras.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4039F9C15E6D8B3007255D6 /* MathExtras.cpp */; };
+               B55AD1D2179F336C00AC1494 /* PreventImageLoadWithAutoResizing.mm in Sources */ = {isa = PBXBuildFile; fileRef = B55AD1D1179F336600AC1494 /* PreventImageLoadWithAutoResizing.mm */; };
+               B55AD1D5179F3B3000AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B55AD1D3179F3ABF00AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp */; };
                B55F11A01516834F00915916 /* AttributedString.mm in Sources */ = {isa = PBXBuildFile; fileRef = B55F119F1516834F00915916 /* AttributedString.mm */; };
                B55F11B71517D03300915916 /* attributedStringCustomFont.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = B55F11B01517A2C400915916 /* attributedStringCustomFont.html */; };
                B55F11BE15191A0600915916 /* Ahem.ttf in Copy Resources */ = {isa = PBXBuildFile; fileRef = B55F11B9151916E600915916 /* Ahem.ttf */; };
                A5E2027215B2181900C13E14 /* WindowlessWebViewWithMedia.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowlessWebViewWithMedia.mm; sourceTree = "<group>"; };
                A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckedArithmeticOperations.cpp; path = WTF/CheckedArithmeticOperations.cpp; sourceTree = "<group>"; };
                B4039F9C15E6D8B3007255D6 /* MathExtras.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MathExtras.cpp; path = WTF/MathExtras.cpp; sourceTree = "<group>"; };
+               B55AD1D1179F336600AC1494 /* PreventImageLoadWithAutoResizing.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = PreventImageLoadWithAutoResizing.mm; path = WebKit2ObjC/PreventImageLoadWithAutoResizing.mm; sourceTree = "<group>"; };
+               B55AD1D3179F3ABF00AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PreventImageLoadWithAutoResizing_Bundle.cpp; path = WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp; sourceTree = "<group>"; };
                B55F119F1516834F00915916 /* AttributedString.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AttributedString.mm; sourceTree = "<group>"; };
                B55F11B01517A2C400915916 /* attributedStringCustomFont.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = attributedStringCustomFont.html; sourceTree = "<group>"; };
                B55F11B9151916E600915916 /* Ahem.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ahem.ttf; sourceTree = "<group>"; };
                BC3C4C6F14575B1D0025FB62 /* WebKit2 Objective-C */ = {
                        isa = PBXGroup;
                        children = (
+                               B55AD1D3179F3ABF00AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp */,
+                               B55AD1D1179F336600AC1494 /* PreventImageLoadWithAutoResizing.mm */,
                                297234B2173AD04800983601 /* CustomProtocolsInvalidScheme.mm */,
                                297234B5173AFAC700983601 /* CustomProtocolsInvalidScheme_Bundle.cpp */,
                                29AB8A9F164C735800D49BEC /* CustomProtocolsTest.mm */,
                                BC131885117114B600B69727 /* PlatformUtilitiesMac.mm in Sources */,
                                BC90955D125548AA00083756 /* PlatformWebViewMac.mm in Sources */,
                                333B9CE21277F23100FEFCE3 /* PreventEmptyUserAgent.cpp in Sources */,
+                               B55AD1D2179F336C00AC1494 /* PreventImageLoadWithAutoResizing.mm in Sources */,
                                F6FDDDD314241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */,
                                00BC16871680FE810065F1E5 /* PublicSuffix.mm in Sources */,
                                0FC6C4CC141027E0005B7F0C /* RedBlackTree.cpp in Sources */,
                                51393E221523952D005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp in Sources */,
                                F6F49C6B15545CA70007F39D /* DOMWindowExtensionNoCache_Bundle.cpp in Sources */,
                                C0C5D3C61459912900A802A6 /* GetBackingScaleFactor_Bundle.mm in Sources */,
+                               B55AD1D5179F3B3000AC1494 /* PreventImageLoadWithAutoResizing_Bundle.cpp in Sources */,
                                F660AA1115A5F631003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp in Sources */,
                                4BFDFFA71314776C0061F24B /* HitTestResultNodeHandle_Bundle.cpp in Sources */,
                                BC575AB0126E83C8006F0F12 /* InjectedBundleBasic_Bundle.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing.mm
new file mode 100644 (file)
index 0000000..0e86aaa
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "Test.h"
+
+#import "PlatformUtilities.h"
+#import "PlatformWebView.h"
+#import "TestBrowsingContextLoadDelegate.h"
+#import "TestProtocol.h"
+#import <WebKit2/WebKit2.h>
+#import <WebKit2/WKViewPrivate.h>
+
+static bool testFinished = false;
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, PreventImageLoadWithAutoResizingTest)
+{
+    [NSURLProtocol registerClass:[TestProtocol class]];
+    [WKBrowsingContextController registerSchemeForCustomProtocol:[TestProtocol scheme]];
+
+    WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("DenyWillSendRequestTest"));
+    PlatformWebView webView(context.get());
+
+    webView.platformView().minimumSizeForAutoLayout = NSMakeSize(400, 300);
+    webView.platformView().browsingContextController.loadDelegate = [[TestBrowsingContextLoadDelegate alloc] initWithBlockToRunOnLoad:^(WKBrowsingContextController *sender) {
+        testFinished = true;
+    }];
+    [webView.platformView().browsingContextController loadHTMLString:@"<html><body style='background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFZJREFUeF59z4EJADEIQ1F36k7u5E7ZKXeUQPACJ3wK7UNokVxVk9kHnQH7bY9hbDyDhNXgjpRLqFlo4M2GgfyJHhjq8V4agfrgPQX3JtJQGbofmCHgA/nAKks+JAjFAAAAAElFTkSuQmCC);'></body></html>" baseURL:[NSURL URLWithString:@"about:blank"]];
+
+    Util::run(&testFinished);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp
new file mode 100644 (file)
index 0000000..9f73d75
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+#include <WebKit2/WKBundlePage.h>
+
+#include <wtf/Assertions.h>
+
+namespace TestWebKitAPI {
+    
+class DenyWillSendRequestTest : public InjectedBundleTest {
+public:
+    DenyWillSendRequestTest(const std::string& identifier)
+        : InjectedBundleTest(identifier)
+    {
+    }
+    
+    static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void *clientInfo)
+    {
+        return 0;
+    }
+
+    virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+    {
+        WKBundlePageResourceLoadClient resourceLoadClient;
+        memset(&resourceLoadClient, 0, sizeof(resourceLoadClient));
+        
+        resourceLoadClient.version = 0;
+        resourceLoadClient.willSendRequestForFrame = willSendRequestForFrame;
+
+        WKBundlePageSetResourceLoadClient(page, &resourceLoadClient);
+
+    }
+};
+
+static InjectedBundleTest::Register<DenyWillSendRequestTest> registrar("DenyWillSendRequestTest");
+
+} // namespace TestWebKitAPI