Title: [188486] trunk
Revision
188486
Author
[email protected]
Date
2015-08-14 14:08:13 -0700 (Fri, 14 Aug 2015)

Log Message

[Cocoa] Downloads do not start if policy decision is made asynchronously
https://bugs.webkit.org/show_bug.cgi?id=147985

Reviewed by Brady Eidson.

Source/WebCore:

It's only possible to convert a NSURLConnection to a download while the connection delegate's
-connection:didReceiveResponse: is being called. However, WebKit clients can decide content policy
asynchronously. If a client chooses to download a response asynchronously, we can no longer convert the
connection to a download, so we should start a new download instead.

New API test: _WKDownload.AsynchronousDownloadPolicy

* dom/Document.cpp: Updated to include SubresourceLoader.h.
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::mainResourceLoader): Updated to return a SubresourceLoader.
(WebCore::DocumentLoader::continueAfterContentPolicy): Cast mainResourceLoader() to a ResourceLoader since
didFail() is private in SubresourceLoader.
* loader/DocumentLoader.h:
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::SubresourceLoader): Initialized m_callingDidReceiveResponse to false.
(WebCore::SubresourceLoader::didReceiveResponse): Used TemporaryChange<> to set m_callingDidReceiveResponse to true.
* loader/SubresourceLoader.h:
* loader/appcache/ApplicationCacheHost.cpp: Updated to include SubresourceLoader.h.
* loader/mac/DocumentLoaderMac.cpp: Ditto.

Source/WebKit/mac:

* WebCoreSupport/WebFrameLoaderClient.mm:
(WebFrameLoaderClient::convertMainResourceLoadToDownload): Started a new download if the main resource loader is not calling didReceiveResponse.

Source/WebKit/win:

* WebCoreSupport/WebFrameLoaderClient.cpp: Updated to include SubresourceLoader.h.

Source/WebKit2:

* WebProcess/Network/WebResourceLoader.cpp: Updated to include SubresourceLoader.h.
* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::convertMainResourceLoadToDownload): Started a new download if the main resource loader is not calling didReceiveResponse.

Tools:

Added a new API test.

* TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm:
(-[AsynchronousDownloadNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
(-[AsynchronousDownloadDelegate _downloadDidStart:]):
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (188485 => 188486)


--- trunk/Source/WebCore/ChangeLog	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/ChangeLog	2015-08-14 21:08:13 UTC (rev 188486)
@@ -1,3 +1,30 @@
+2015-08-13  Andy Estes  <[email protected]>
+
+        [Cocoa] Downloads do not start if policy decision is made asynchronously
+        https://bugs.webkit.org/show_bug.cgi?id=147985
+
+        Reviewed by Brady Eidson.
+
+        It's only possible to convert a NSURLConnection to a download while the connection delegate's
+        -connection:didReceiveResponse: is being called. However, WebKit clients can decide content policy
+        asynchronously. If a client chooses to download a response asynchronously, we can no longer convert the
+        connection to a download, so we should start a new download instead.
+
+        New API test: _WKDownload.AsynchronousDownloadPolicy
+
+        * dom/Document.cpp: Updated to include SubresourceLoader.h.
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::mainResourceLoader): Updated to return a SubresourceLoader.
+        (WebCore::DocumentLoader::continueAfterContentPolicy): Cast mainResourceLoader() to a ResourceLoader since
+        didFail() is private in SubresourceLoader.
+        * loader/DocumentLoader.h:
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::SubresourceLoader): Initialized m_callingDidReceiveResponse to false.
+        (WebCore::SubresourceLoader::didReceiveResponse): Used TemporaryChange<> to set m_callingDidReceiveResponse to true.
+        * loader/SubresourceLoader.h:
+        * loader/appcache/ApplicationCacheHost.cpp: Updated to include SubresourceLoader.h.
+        * loader/mac/DocumentLoaderMac.cpp: Ditto.
+
 2015-08-14  Zalan Bujtas  <[email protected]>
 
         RenderBlock::simplifiedLayout should pop LayoutStateMaintainer when early returns.

Modified: trunk/Source/WebCore/dom/Document.cpp (188485 => 188486)


--- trunk/Source/WebCore/dom/Document.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/dom/Document.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -124,7 +124,6 @@
 #include "RenderView.h"
 #include "RenderWidget.h"
 #include "ResourceLoadScheduler.h"
-#include "ResourceLoader.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGDocumentExtensions.h"
 #include "SVGElement.h"
@@ -147,6 +146,7 @@
 #include "StyleResolver.h"
 #include "StyleSheetContents.h"
 #include "StyleSheetList.h"
+#include "SubresourceLoader.h"
 #include "TextNodeTraversal.h"
 #include "TextResourceDecoder.h"
 #include "TransformSource.h"

Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (188485 => 188486)


--- trunk/Source/WebCore/loader/DocumentLoader.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -154,7 +154,7 @@
     return &m_frame->loader();
 }
 
-ResourceLoader* DocumentLoader::mainResourceLoader() const
+SubresourceLoader* DocumentLoader::mainResourceLoader() const
 {
     return m_mainResource ? m_mainResource->loader() : 0;
 }
@@ -729,7 +729,7 @@
 
         // It might have gone missing
         if (mainResourceLoader())
-            mainResourceLoader()->didFail(interruptedForPolicyChangeError());
+            static_cast<ResourceLoader*>(mainResourceLoader())->didFail(interruptedForPolicyChangeError());
         return;
     }
     case PolicyIgnore:

Modified: trunk/Source/WebCore/loader/DocumentLoader.h (188485 => 188486)


--- trunk/Source/WebCore/loader/DocumentLoader.h	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/DocumentLoader.h	2015-08-14 21:08:13 UTC (rev 188486)
@@ -70,6 +70,7 @@
     class Page;
     class ResourceLoader;
     class SharedBuffer;
+    class SubresourceLoader;
     class SubstituteResource;
 
 #if ENABLE(CONTENT_FILTERING)
@@ -94,7 +95,7 @@
         WEBCORE_EXPORT virtual void detachFromFrame();
 
         WEBCORE_EXPORT FrameLoader* frameLoader() const;
-        WEBCORE_EXPORT ResourceLoader* mainResourceLoader() const;
+        WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const;
         WEBCORE_EXPORT PassRefPtr<SharedBuffer> mainResourceData() const;
         
         DocumentWriter& writer() const { return m_writer; }

Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (188485 => 188486)


--- trunk/Source/WebCore/loader/SubresourceLoader.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/SubresourceLoader.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -44,6 +44,7 @@
 #include <wtf/Ref.h>
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/StdLibExtras.h>
+#include <wtf/TemporaryChange.h>
 #include <wtf/text/CString.h>
 
 #if PLATFORM(IOS)
@@ -202,6 +203,8 @@
     ASSERT(!response.isNull());
     ASSERT(m_state == Initialized);
 
+    TemporaryChange<bool> callingDidReceiveResponse(m_callingDidReceiveResponse, true);
+
     // Reference the object in this method since the additional processing can do
     // anything including removing the last reference to this object; one example of this is 3266216.
     Ref<SubresourceLoader> protect(*this);

Modified: trunk/Source/WebCore/loader/SubresourceLoader.h (188485 => 188486)


--- trunk/Source/WebCore/loader/SubresourceLoader.h	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/SubresourceLoader.h	2015-08-14 21:08:13 UTC (rev 188486)
@@ -58,6 +58,8 @@
     virtual const ResourceRequest& iOSOriginalRequest() const override { return m_iOSOriginalRequest; }
 #endif
 
+    bool callingDidReceiveResponse() const { return m_callingDidReceiveResponse; }
+
 private:
     SubresourceLoader(Frame*, CachedResource*, const ResourceLoaderOptions&);
 
@@ -124,6 +126,7 @@
     bool m_loadingMultipartContent;
     SubresourceLoaderState m_state;
     std::unique_ptr<RequestCountTracker> m_requestCountTracker;
+    bool m_callingDidReceiveResponse { false };
 };
 
 }

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp (188485 => 188486)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -39,9 +39,9 @@
 #include "MainFrame.h"
 #include "ProgressEvent.h"
 #include "ResourceHandle.h"
-#include "ResourceLoader.h"
 #include "ResourceRequest.h"
 #include "Settings.h"
+#include "SubresourceLoader.h"
 
 namespace WebCore {
 

Modified: trunk/Source/WebCore/loader/mac/DocumentLoaderMac.cpp (188485 => 188486)


--- trunk/Source/WebCore/loader/mac/DocumentLoaderMac.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebCore/loader/mac/DocumentLoaderMac.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -29,7 +29,7 @@
 #include "config.h"
 #include "DocumentLoader.h"
 
-#include "ResourceLoader.h"
+#include "SubresourceLoader.h"
 
 namespace WebCore {
 

Modified: trunk/Source/WebKit/mac/ChangeLog (188485 => 188486)


--- trunk/Source/WebKit/mac/ChangeLog	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit/mac/ChangeLog	2015-08-14 21:08:13 UTC (rev 188486)
@@ -1,3 +1,13 @@
+2015-08-13  Andy Estes  <[email protected]>
+
+        [Cocoa] Downloads do not start if policy decision is made asynchronously
+        https://bugs.webkit.org/show_bug.cgi?id=147985
+
+        Reviewed by Brady Eidson.
+
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        (WebFrameLoaderClient::convertMainResourceLoadToDownload): Started a new download if the main resource loader is not calling didReceiveResponse.
+
 2015-08-13  Tim Horton  <[email protected]>
 
         Performing a Lookup on wrapped text puts the popover arrow in the wrong place (off to the right)

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm (188485 => 188486)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm	2015-08-14 21:08:13 UTC (rev 188486)
@@ -111,10 +111,10 @@
 #import <WebCore/ProtectionSpace.h>
 #import <WebCore/ResourceError.h>
 #import <WebCore/ResourceHandle.h>
-#import <WebCore/ResourceLoader.h>
 #import <WebCore/ResourceRequest.h>
 #import <WebCore/ScriptController.h>
 #import <WebCore/SharedBuffer.h>
+#import <WebCore/SubresourceLoader.h>
 #import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebScriptObjectPrivate.h>
 #import <WebCore/Widget.h>
@@ -286,9 +286,10 @@
 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
 {
     WebView *webView = getWebView(m_webFrame.get());
+    SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
 
-    if (!documentLoader->mainResourceLoader()) {
-        // The resource has already been cached, start a new download.
+    if (!mainResourceLoader || !mainResourceLoader->callingDidReceiveResponse()) {
+        // The resource has already been cached, or the conversion is being attmpted when not calling SubresourceLoader::didReceiveResponse().
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
         WebDownload *webDownload = [[WebDownload alloc] initWithRequest:request.nsURLRequest(UpdateHTTPBody) delegate:[webView downloadDelegate]];
@@ -297,7 +298,7 @@
         return;
     }
 
-    ResourceHandle* handle = documentLoader->mainResourceLoader()->handle();
+    ResourceHandle* handle = mainResourceLoader->handle();
 
 #if USE(CFNETWORK)
     ASSERT([WebDownload respondsToSelector:@selector(_downloadWithLoadingCFURLConnection:request:response:delegate:proxy:)]);

Modified: trunk/Source/WebKit/win/ChangeLog (188485 => 188486)


--- trunk/Source/WebKit/win/ChangeLog	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit/win/ChangeLog	2015-08-14 21:08:13 UTC (rev 188486)
@@ -1,3 +1,12 @@
+2015-08-13  Andy Estes  <[email protected]>
+
+        [Cocoa] Downloads do not start if policy decision is made asynchronously
+        https://bugs.webkit.org/show_bug.cgi?id=147985
+
+        Reviewed by Brady Eidson.
+
+        * WebCoreSupport/WebFrameLoaderClient.cpp: Updated to include SubresourceLoader.h.
+
 2015-08-13  Simon Fraser  <[email protected]>
 
         Windows build fix.

Modified: trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp (188485 => 188486)


--- trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -79,9 +79,9 @@
 #include <WebCore/PolicyChecker.h>
 #include <WebCore/RenderWidget.h>
 #include <WebCore/ResourceHandle.h>
-#include <WebCore/ResourceLoader.h>
 #include <WebCore/ScriptController.h>
 #include <WebCore/Settings.h>
+#include <WebCore/SubresourceLoader.h>
 
 using namespace WebCore;
 using namespace HTMLNames;

Modified: trunk/Source/WebKit2/ChangeLog (188485 => 188486)


--- trunk/Source/WebKit2/ChangeLog	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit2/ChangeLog	2015-08-14 21:08:13 UTC (rev 188486)
@@ -1,3 +1,14 @@
+2015-08-13  Andy Estes  <[email protected]>
+
+        [Cocoa] Downloads do not start if policy decision is made asynchronously
+        https://bugs.webkit.org/show_bug.cgi?id=147985
+
+        Reviewed by Brady Eidson.
+
+        * WebProcess/Network/WebResourceLoader.cpp: Updated to include SubresourceLoader.h.
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::WebFrame::convertMainResourceLoadToDownload): Started a new download if the main resource loader is not calling didReceiveResponse.
+
 2015-08-14  Simon Fraser  <[email protected]>
 
         Speculative fix for iOS build failure.

Modified: trunk/Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp (188485 => 188486)


--- trunk/Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -40,6 +40,7 @@
 #include <WebCore/DocumentLoader.h>
 #include <WebCore/ResourceError.h>
 #include <WebCore/ResourceLoader.h>
+#include <WebCore/SubresourceLoader.h>
 
 using namespace WebCore;
 

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp (188485 => 188486)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp	2015-08-14 21:08:13 UTC (rev 188486)
@@ -70,9 +70,9 @@
 #include <WebCore/Page.h>
 #include <WebCore/PluginDocument.h>
 #include <WebCore/RenderTreeAsText.h>
-#include <WebCore/ResourceLoader.h>
 #include <WebCore/ScriptController.h>
 #include <WebCore/SecurityOrigin.h>
+#include <WebCore/SubresourceLoader.h>
 #include <WebCore/TextIterator.h>
 #include <WebCore/TextResourceDecoder.h>
 #include <wtf/text/StringBuilder.h>
@@ -274,15 +274,16 @@
     uint64_t policyDownloadID = m_policyDownloadID;
     m_policyDownloadID = 0;
 
-    ResourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
+    SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
 
     auto& webProcess = WebProcess::singleton();
 #if ENABLE(NETWORK_PROCESS)
     if (webProcess.usesNetworkProcess()) {
-        // Use 0 to indicate that there is no main resource loader.
-        // This can happen if the main resource is in the WebCore memory cache.
+        // Use 0 to indicate that the resource load can't be converted and a new download must be started.
+        // This can happen if there is no loader because the main resource is in the WebCore memory cache,
+        // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
         uint64_t mainResourceLoadIdentifier;
-        if (mainResourceLoader)
+        if (mainResourceLoader && mainResourceLoader->callingDidReceiveResponse())
             mainResourceLoadIdentifier = mainResourceLoader->identifier();
         else
             mainResourceLoadIdentifier = 0;
@@ -292,7 +293,7 @@
     }
 #endif
 
-    if (!mainResourceLoader) {
+    if (!mainResourceLoader || !mainResourceLoader->callingDidReceiveResponse()) {
         // The main resource has already been loaded. Start a new download instead.
         webProcess.downloadManager().startDownload(policyDownloadID, request);
         return;

Modified: trunk/Tools/ChangeLog (188485 => 188486)


--- trunk/Tools/ChangeLog	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Tools/ChangeLog	2015-08-14 21:08:13 UTC (rev 188486)
@@ -1,3 +1,17 @@
+2015-08-13  Andy Estes  <[email protected]>
+
+        [Cocoa] Downloads do not start if policy decision is made asynchronously
+        https://bugs.webkit.org/show_bug.cgi?id=147985
+
+        Reviewed by Brady Eidson.
+
+        Added a new API test.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm:
+        (-[AsynchronousDownloadNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
+        (-[AsynchronousDownloadDelegate _downloadDidStart:]):
+        (TEST):
+
 2015-08-14  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r187357.

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm (188485 => 188486)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm	2015-08-14 20:27:58 UTC (rev 188485)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/Download.mm	2015-08-14 21:08:13 UTC (rev 188486)
@@ -265,5 +265,34 @@
     TestWebKitAPI::Util::run(&isDone);
 }
 
+@interface AsynchronousDownloadNavigationDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation AsynchronousDownloadNavigationDelegate
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+    dispatch_async(dispatch_get_main_queue(), ^ {
+        decisionHandler(_WKNavigationResponsePolicyBecomeDownload);
+    });
+}
+@end
+
+@interface AsynchronousDownloadDelegate : NSObject <_WKDownloadDelegate>
+@end
+
+@implementation AsynchronousDownloadDelegate
+
+- (void)_downloadDidStart:(_WKDownload *)download
+{
+    isDone = true;
+}
+
+@end
+
+TEST(_WKDownload, AsynchronousDownloadPolicy)
+{
+    runTest(adoptNS([[AsynchronousDownloadNavigationDelegate alloc] init]).get(), adoptNS([[AsynchronousDownloadDelegate alloc] init]).get(), sourceURL);
+}
+
 #endif
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to