<rdar://problem/13194263> Crashes in NetworkProcess due to threading issues
authorap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Mar 2013 21:27:45 +0000 (21:27 +0000)
committerap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Mar 2013 21:27:45 +0000 (21:27 +0000)
        https://bugs.webkit.org/show_bug.cgi?id=113256

        Reviewed by Brady Eidson.

        Added a new code path in ResourceHandle/ResourceHandleClient that doesn't need
        blocking calls. Implemented it for NSURLConnection by changing NSOperationQueue
        version to forward calls to main thread.

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

27 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/network/CredentialStorage.cpp
Source/WebCore/platform/network/ResourceHandle.cpp
Source/WebCore/platform/network/ResourceHandle.h
Source/WebCore/platform/network/ResourceHandleClient.cpp
Source/WebCore/platform/network/ResourceHandleClient.h
Source/WebCore/platform/network/ResourceHandleInternal.h
Source/WebCore/platform/network/chromium/ResourceHandle.cpp
Source/WebCore/platform/network/mac/ResourceHandleMac.mm
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.h
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.h [new file with mode: 0644]
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm [new file with mode: 0644]
Source/WebKit2/ChangeLog
Source/WebKit2/DerivedSources.make
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit2/NetworkProcess/NetworkResourceLoader.h
Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in [new file with mode: 0644]
Source/WebKit2/Shared/Authentication/AuthenticationManager.cpp
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/Network/NetworkProcessConnection.cpp
Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp
Source/WebKit2/WebProcess/Network/WebResourceLoader.h
Source/WebKit2/WebProcess/Network/WebResourceLoader.messages.in

index 260f9c0..731104c 100644 (file)
@@ -1,3 +1,91 @@
+2013-03-26  Alexey Proskuryakov  <ap@apple.com>
+
+        <rdar://problem/13194263> Crashes in NetworkProcess due to threading issues
+        https://bugs.webkit.org/show_bug.cgi?id=113256
+
+        Reviewed by Brady Eidson.
+
+        Added a new code path in ResourceHandle/ResourceHandleClient that doesn't need
+        blocking calls. Implemented it for NSURLConnection by changing NSOperationQueue
+        version to forward calls to main thread.
+
+        * WebCore.exp.in: Export new methods.
+        * WebCore.xcodeproj/project.pbxproj: Added WebCoreResourceHandleAsOperationQueueDelegate.
+
+        * platform/network/CredentialStorage.cpp: Assert that unprotected global map operations
+        happen on main thread.
+
+        * platform/network/ResourceHandle.cpp: Added default implementations of functions
+        that handle async responses.
+
+        * platform/network/chromium/ResourceHandle.cpp: Ditto.
+
+        * platform/network/ResourceHandle.h: Added functions that are called in response
+        to new async functions in ResourceHandleClient. Changed Mac delegate type to id,
+        ast can now be either WebCoreResourceHandleAsDelegate or WebCoreResourceHandleAsOperationQueueDelegate.
+
+        * platform/network/ResourceHandleClient.cpp:
+        (WebCore::ResourceHandleClient::willSendRequestAsync):
+        (WebCore::ResourceHandleClient::shouldUseCredentialStorageAsync):
+        (WebCore::ResourceHandleClient::canAuthenticateAgainstProtectionSpaceAsync):
+        (WebCore::ResourceHandleClient::willCacheResponseAsync):
+        Default implementations of async client functions. These match default behavior of
+        sync versions.
+
+        * platform/network/ResourceHandleClient.h: Added async functions. A ResourceHandle
+        should use these when the client returns true from usesAsyncCallbacks().
+
+        * platform/network/ResourceHandleInternal.h: Changed to use id for delegate type
+        here, too.
+
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::delegate): Create an appropriate delegate for the client.
+        (WebCore::ResourceHandle::willSendRequest): Since this function has a lot of common
+        behavior in sync and async cases, implement the new code path as a branch inside
+        it, not as a new function.
+        (WebCore::ResourceHandle::continueWillSendRequest): Unblock the connection when
+        response is known.
+        (WebCore::ResourceHandle::shouldUseCredentialStorage): Branched here too, for consistency.
+        Perhaps we'll want to break this into separate functions though.
+        (WebCore::ResourceHandle::continueShouldUseCredentialStorage): Unblock the connection.
+        (WebCore::ResourceHandle::canAuthenticateAgainstProtectionSpace): Same change as above.
+        (WebCore::ResourceHandle::continueCanAuthenticateAgainstProtectionSpace): Ditto.
+        (WebCore::ResourceHandle::continueWillCacheResponse): Ditto. Currently, delegate
+        calls the client directly, so we only have a "continue" function, and no "willCacheResponse".
+
+        * platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
+        (-[WebCoreResourceHandleAsDelegate connection:willCacheResponse:]): Removed some
+        nonsense code.
+
+        * platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.h: Copied from Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.h.
+        This delegate is responsible for forwarding calls to main thread. Unfortunately,
+        this adds some code duplication, which I tried to rectify somewhat in previous patches
+        by moving more logic to ResourceHandle.
+
+        * platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm: Copied from Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate detachHandle]): Unblock waiting
+        threads if we don't expect a response any more.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate dealloc]): Release the semaphore.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate continueWillSendRequest:]): Unblock
+        a waiting thread with a response.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate continueShouldUseCredentialStorage:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate continueCanAuthenticateAgainstProtectionSpace:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate continueWillCacheResponse:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:willSendRequest:redirectResponse:]):
+        Run code that uses WebCore objects on main thread.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connectionShouldUseCredentialStorage:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveAuthenticationChallenge:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didCancelAuthenticationChallenge:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:canAuthenticateAgainstProtectionSpace:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveResponse:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveDataArray:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveData:lengthReceived:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:willStopBufferingData:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connectionDidFinishLoading:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didFailWithError:]): Ditto.
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:willCacheResponse:]): Ditto.
+
 2013-03-26  Tony Chang  <tony@chromium.org>
 
         Autogenerate the scrollAnimatorEnabled setting in Settings.in
index a72ca7a..516a226 100644 (file)
@@ -340,8 +340,12 @@ __ZN7WebCore14ResourceBufferC2Ev
 __ZN7WebCore14ResourceBufferD1Ev
 __ZN7WebCore14ResourceBufferD2Ev
 __ZN7WebCore14ResourceHandle20forceContentSniffingEv
+__ZN7WebCore14ResourceHandle23continueWillSendRequestERKNS_15ResourceRequestE
+__ZN7WebCore14ResourceHandle25continueWillCacheResponseEP19NSCachedURLResponse
 __ZN7WebCore14ResourceHandle25loadResourceSynchronouslyEPNS_17NetworkingContextERKNS_15ResourceRequestENS_17StoredCredentialsERNS_13ResourceErrorERNS_16ResourceResponseERN3WTF6VectorIcLm0EEE
 __ZN7WebCore14ResourceHandle26synchronousLoadRunLoopModeEv
+__ZN7WebCore14ResourceHandle34continueShouldUseCredentialStorageEb
+__ZN7WebCore14ResourceHandle45continueCanAuthenticateAgainstProtectionSpaceEb
 __ZN7WebCore14ResourceHandle6createEPNS_17NetworkingContextERKNS_15ResourceRequestEPNS_20ResourceHandleClientEbb
 __ZN7WebCore14ResourceLoader14cancelledErrorEv
 __ZN7WebCore14ResourceLoader6cancelEv
@@ -632,6 +636,10 @@ __ZN7WebCore20NodeRenderingContextC1EPNS_4NodeE
 __ZN7WebCore20NodeRenderingContextD1Ev
 __ZN7WebCore20RenderEmbeddedObject29setPluginUnavailabilityReasonENS0_26PluginUnavailabilityReasonE
 __ZN7WebCore20ResourceHandleClient16didReceiveBufferEPNS_14ResourceHandleEN3WTF10PassRefPtrINS_12SharedBufferEEEi
+__ZN7WebCore20ResourceHandleClient20willSendRequestAsyncEPNS_14ResourceHandleERKNS_15ResourceRequestERKNS_16ResourceResponseE
+__ZN7WebCore20ResourceHandleClient22willCacheResponseAsyncEPNS_14ResourceHandleEP19NSCachedURLResponse
+__ZN7WebCore20ResourceHandleClient31shouldUseCredentialStorageAsyncEPNS_14ResourceHandleE
+__ZN7WebCore20ResourceHandleClient42canAuthenticateAgainstProtectionSpaceAsyncEPNS_14ResourceHandleERKNS_15ProtectionSpaceE
 __ZN7WebCore20ResourceHandleClientC2Ev
 __ZN7WebCore20ResourceHandleClientD2Ev
 __ZN7WebCore20ResourceResponseBase11setMimeTypeERKN3WTF6StringE
index a9ea374..784318d 100644 (file)
                973F418B169B96030006BF60 /* HTMLParserOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 973F4187169B95EF0006BF60 /* HTMLParserOptions.cpp */; };
                974187D316A7932700FA77A7 /* HTMLParserThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 974187D016A7932200FA77A7 /* HTMLParserThread.cpp */; };
                974187D416A7932900FA77A7 /* HTMLParserThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 974187D116A7932200FA77A7 /* HTMLParserThread.h */; };
-               9746AF2114F4DDE6003E7A72 /* Coordinates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9746AF1114F4DDE6003E7A72 /* Coordinates.cpp */; };
                9746AF2114F4DDE6003E7A71 /* Coordinates.h in Headers */ = {isa = PBXBuildFile; fileRef = 9746AF1114F4DDE6003E7A70 /* Coordinates.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               9746AF2114F4DDE6003E7A72 /* Coordinates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9746AF1114F4DDE6003E7A72 /* Coordinates.cpp */; };
                9746AF2314F4DDE6003E7A70 /* Geolocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9746AF1314F4DDE6003E7A70 /* Geolocation.cpp */; };
                9746AF2414F4DDE6003E7A70 /* Geolocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9746AF1414F4DDE6003E7A70 /* Geolocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9746AF2514F4DDE6003E7A71 /* GeolocationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 9746AF1514F4DDE6003E7A71 /* GeolocationClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E14F1C4514B5DAC600EA9009 /* HTMLFormControlElementWithState.h in Headers */ = {isa = PBXBuildFile; fileRef = E14F1C4314B5DAC600EA9009 /* HTMLFormControlElementWithState.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E1513D4F1677EA8300149FCB /* InitializeLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = E1513D4E1677EA8300149FCB /* InitializeLogging.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E1513D511677F08800149FCB /* NotImplemented.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1513D501677F08800149FCB /* NotImplemented.cpp */; };
+               E152551516FD2350003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E152551316FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h */; };
+               E152551616FD2350003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E152551416FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm */; };
                E15A36D71104572000B7B639 /* XMLNSNames.h in Headers */ = {isa = PBXBuildFile; fileRef = E15A36D61104572000B7B639 /* XMLNSNames.h */; };
                E15A36D91104572700B7B639 /* XMLNSNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E15A36D81104572700B7B639 /* XMLNSNames.cpp */; };
                E169803D1133542D00894115 /* CRuntimeObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E169803C1133542D00894115 /* CRuntimeObject.h */; };
                973F4188169B95EF0006BF60 /* HTMLParserOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLParserOptions.h; path = parser/HTMLParserOptions.h; sourceTree = "<group>"; };
                974187D016A7932200FA77A7 /* HTMLParserThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLParserThread.cpp; path = parser/HTMLParserThread.cpp; sourceTree = "<group>"; };
                974187D116A7932200FA77A7 /* HTMLParserThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLParserThread.h; path = parser/HTMLParserThread.h; sourceTree = "<group>"; };
-               9746AF1114F4DDE6003E7A72 /* Coordinates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Coordinates.cpp; path = Modules/geolocation/Coordinates.cpp; sourceTree = "<group>"; };
                9746AF1114F4DDE6003E7A70 /* Coordinates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Coordinates.h; path = Modules/geolocation/Coordinates.h; sourceTree = "<group>"; };
+               9746AF1114F4DDE6003E7A72 /* Coordinates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Coordinates.cpp; path = Modules/geolocation/Coordinates.cpp; sourceTree = "<group>"; };
                9746AF1214F4DDE6003E7A70 /* Coordinates.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Coordinates.idl; path = Modules/geolocation/Coordinates.idl; sourceTree = "<group>"; };
                9746AF1314F4DDE6003E7A70 /* Geolocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Geolocation.cpp; path = Modules/geolocation/Geolocation.cpp; sourceTree = "<group>"; };
                9746AF1414F4DDE6003E7A70 /* Geolocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Geolocation.h; path = Modules/geolocation/Geolocation.h; sourceTree = "<group>"; };
                E14F1C4314B5DAC600EA9009 /* HTMLFormControlElementWithState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLFormControlElementWithState.h; sourceTree = "<group>"; };
                E1513D4E1677EA8300149FCB /* InitializeLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeLogging.h; sourceTree = "<group>"; };
                E1513D501677F08800149FCB /* NotImplemented.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotImplemented.cpp; sourceTree = "<group>"; };
+               E152551316FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreResourceHandleAsOperationQueueDelegate.h; sourceTree = "<group>"; };
+               E152551416FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreResourceHandleAsOperationQueueDelegate.mm; sourceTree = "<group>"; };
                E15A36D61104572000B7B639 /* XMLNSNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLNSNames.h; sourceTree = "<group>"; };
                E15A36D81104572700B7B639 /* XMLNSNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLNSNames.cpp; sourceTree = "<group>"; };
                E169803C1133542D00894115 /* CRuntimeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CRuntimeObject.h; sourceTree = "<group>"; };
                                514C764B0CE9234E007EF3CD /* ResourceResponseMac.mm */,
                                1FAFBF1615A5FA5200083A20 /* UTIUtilities.h */,
                                1FAFBF1715A5FA5200083A20 /* UTIUtilities.mm */,
-                               E180810C16FCECDF00B80D07 /* WebCoreResourceHandleAsDelegate.mm */,
                                E180810D16FCECDF00B80D07 /* WebCoreResourceHandleAsDelegate.h */,
+                               E180810C16FCECDF00B80D07 /* WebCoreResourceHandleAsDelegate.mm */,
+                               E152551316FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h */,
+                               E152551416FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm */,
                                E180811416FCF9CB00B80D07 /* SynchronousLoaderClient.mm */,
                                37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */,
                                37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */,
                                50E18CDA16F9285800C65486 /* StyleCustomFilterProgramCache.h in Headers */,
                                E180810F16FCECDF00B80D07 /* WebCoreResourceHandleAsDelegate.h in Headers */,
                                E180811716FCF9CB00B80D07 /* SynchronousLoaderClient.h in Headers */,
+                               E152551516FD2350003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E180810E16FCECDF00B80D07 /* WebCoreResourceHandleAsDelegate.mm in Sources */,
                                E180811216FCF42F00B80D07 /* SynchronousLoaderClient.cpp in Sources */,
                                E180811616FCF9CB00B80D07 /* SynchronousLoaderClient.mm in Sources */,
+                               E152551616FD2350003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 8b5ac47..588ff5b 100644 (file)
@@ -33,6 +33,7 @@
 #include <wtf/text/StringHash.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
+#include <wtf/MainThread.h>
 #include <wtf/StdLibExtras.h>
 
 namespace WebCore {
@@ -40,12 +41,14 @@ namespace WebCore {
 typedef HashMap<ProtectionSpace, Credential> ProtectionSpaceToCredentialMap;
 static ProtectionSpaceToCredentialMap& protectionSpaceToCredentialMap()
 {
+    ASSERT(isMainThread());
     DEFINE_STATIC_LOCAL(ProtectionSpaceToCredentialMap, map, ());
     return map;
 }
 
 static HashSet<String>& originsWithCredentials()
 {
+    ASSERT(isMainThread());
     DEFINE_STATIC_LOCAL(HashSet<String>, set, ());
     return set;
 }
@@ -53,6 +56,7 @@ static HashSet<String>& originsWithCredentials()
 typedef HashMap<String, ProtectionSpace> PathToDefaultProtectionSpaceMap;
 static PathToDefaultProtectionSpaceMap& pathToDefaultProtectionSpaceMap()
 {
+    ASSERT(isMainThread());
     DEFINE_STATIC_LOCAL(PathToDefaultProtectionSpaceMap, map, ());
     return map;
 }
index d610f7d..a3a88fb 100644 (file)
@@ -147,6 +147,26 @@ void ResourceHandle::setClient(ResourceHandleClient* client)
     d->m_client = client;
 }
 
+#if !PLATFORM(MAC)
+// ResourceHandle never uses async client calls on these platforms yet.
+void ResourceHandle::continueWillSendRequest(const ResourceRequest&)
+{
+    ASSERT_NOT_REACHED();
+}
+
+void ResourceHandle::continueShouldUseCredentialStorage(bool)
+{
+    ASSERT_NOT_REACHED();
+}
+
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+void ResourceHandle::continueCanAuthenticateAgainstProtectionSpace(bool)
+{
+    ASSERT_NOT_REACHED();
+}
+#endif
+#endif
+
 ResourceRequest& ResourceHandle::firstRequest()
 {
     return d->m_firstRequest;
index d918546..65708f1 100644 (file)
@@ -55,10 +55,10 @@ typedef LPVOID HINTERNET;
 #endif
 
 #if PLATFORM(MAC)
+OBJC_CLASS NSCachedURLResponse;
 OBJC_CLASS NSData;
 OBJC_CLASS NSError;
 OBJC_CLASS NSURLConnection;
-OBJC_CLASS WebCoreResourceHandleAsDelegate;
 #ifndef __OBJC__
 typedef struct objc_object *id;
 #endif
@@ -125,7 +125,7 @@ public:
 #if !USE(CFNETWORK)
     void didCancelAuthenticationChallenge(const AuthenticationChallenge&);
     NSURLConnection *connection() const;
-    WebCoreResourceHandleAsDelegate *delegate();
+    id delegate();
     void releaseDelegate();
     id releaseProxy();
 #endif
@@ -188,10 +188,23 @@ public:
     ResourceHandleClient* client() const;
     void setClient(ResourceHandleClient*);
 
+    // Called in response to ResourceHandleClient::willSendRequestAsync().
+    void continueWillSendRequest(const ResourceRequest&);
+    // Called in response to ResourceHandleClient::shouldUseCredentialStorageAsync().
+    void continueShouldUseCredentialStorage(bool);
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+    // Called in response to ResourceHandleClient::canAuthenticateAgainstProtectionSpaceAsync().
+    void continueCanAuthenticateAgainstProtectionSpace(bool);
+#endif
+#if PLATFORM(MAC)
+    // Called in response to ResourceHandleClient::willCacheResponseAsync().
+    void continueWillCacheResponse(NSCachedURLResponse *);
+#endif
+
     void setDefersLoading(bool);
 
 #if PLATFORM(BLACKBERRY)
-    void pauseLoad(bool);
+    void pauseLoad(bool); // FIXME: How is this different from setDefersLoading()?
 #endif
 
     void didChangePriority(ResourceLoadPriority);
index f5dd88e..e8d3bc6 100644 (file)
@@ -52,6 +52,30 @@ ResourceHandleClient::~ResourceHandleClient()
 #endif
 }
 
+void ResourceHandleClient::willSendRequestAsync(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& /*redirectResponse*/)
+{
+    handle->continueWillSendRequest(request);
+}
+
+void ResourceHandleClient::shouldUseCredentialStorageAsync(ResourceHandle* handle)
+{
+    handle->continueShouldUseCredentialStorage(false);
+}
+
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+void ResourceHandleClient::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle* handle, const ProtectionSpace&)
+{
+    handle->continueCanAuthenticateAgainstProtectionSpace(false);
+}
+#endif
+
+#if PLATFORM(MAC)
+void ResourceHandleClient::willCacheResponseAsync(ResourceHandle* handle, NSCachedURLResponse *response)
+{
+    handle->continueWillCacheResponse(response);
+}
+#endif
+
 void ResourceHandleClient::didReceiveBuffer(ResourceHandle* handle, PassRefPtr<SharedBuffer> buffer, int encodedDataLength)
 {
     didReceiveData(handle, buffer->data(), buffer->size(), encodedDataLength);
index c44ccfe..df3a29d 100644 (file)
@@ -76,6 +76,18 @@ namespace WebCore {
         virtual void cannotShowURL(ResourceHandle*) { }
 
         virtual bool usesAsyncCallbacks() { return false; }
+        // Client will pass an updated request using ResourceHandle::continueWillSendRequest() when ready.
+        virtual void willSendRequestAsync(ResourceHandle*, const ResourceRequest&, const ResourceResponse& redirectResponse);
+        // Client will pass an updated request using ResourceHandle::continueShouldUseCredentialStorage() when ready.
+        virtual void shouldUseCredentialStorageAsync(ResourceHandle*);
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+        // Client will pass an updated request using ResourceHandle::continueCanAuthenticateAgainstProtectionSpace() when ready.
+        virtual void canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle*, const ProtectionSpace&);
+#endif
+#if PLATFORM(MAC)
+        // Client will pass an updated request using ResourceHandle::continueWillCacheResponse() when ready.
+        virtual void willCacheResponseAsync(ResourceHandle*, NSCachedURLResponse *);
+#endif
 
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
         virtual bool supportsDataArray() { return false; }
@@ -98,7 +110,7 @@ namespace WebCore {
 #if USE(CFNETWORK)
         virtual CFCachedURLResponseRef willCacheResponse(ResourceHandle*, CFCachedURLResponseRef response) { return response; }
 #else
-        virtual NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse* response) { return response; }
+        virtual NSCachedURLResponse *willCacheResponse(ResourceHandle*, NSCachedURLResponse *response) { return response; }
 #endif
         virtual void willStopBufferingData(ResourceHandle*, const char*, int) { }
 #endif // PLATFORM(MAC)
index 112ecb1..e4c970b 100644 (file)
@@ -160,7 +160,7 @@ namespace WebCore {
 #endif
 #if PLATFORM(MAC) && !USE(CFNETWORK)
         RetainPtr<NSURLConnection> m_connection;
-        RetainPtr<WebCoreResourceHandleAsDelegate> m_delegate;
+        RetainPtr<id> m_delegate;
         RetainPtr<id> m_proxy;
 #endif
 #if PLATFORM(MAC)
index b56dc63..2eb478c 100644 (file)
@@ -222,6 +222,18 @@ void ResourceHandle::setClient(ResourceHandleClient* client)
     d->setClient(client);
 }
 
+void ResourceHandle::continueWillSendRequest(const ResourceRequest&)
+{
+    // ResourceHandle never uses async client calls on Chromium yet.
+    ASSERT_NOT_REACHED();
+}
+
+void ResourceHandle::continueShouldUseCredentialStorage(bool)
+{
+    // ResourceHandle never uses async client calls on Chromium yet.
+    ASSERT_NOT_REACHED();
+}
+
 void ResourceHandle::setDefersLoading(bool value)
 {
     d->setDefersLoading(value);
index e2f3a56..5d2904c 100644 (file)
@@ -48,6 +48,7 @@
 #import "SharedBuffer.h"
 #import "SubresourceLoader.h"
 #import "WebCoreResourceHandleAsDelegate.h"
+#import "WebCoreResourceHandleAsOperationQueueDelegate.h"
 #import "SynchronousLoaderClient.h"
 #import "WebCoreSystemInterface.h"
 #import "WebCoreURLResponse.h"
@@ -256,10 +257,12 @@ void ResourceHandle::unschedule(SchedulePair* pair)
         [d->m_connection.get() unscheduleFromRunLoop:runLoop forMode:(NSString *)pair->mode()];
 }
 
-WebCoreResourceHandleAsDelegate *ResourceHandle::delegate()
+id ResourceHandle::delegate()
 {
     if (!d->m_delegate) {
-        WebCoreResourceHandleAsDelegate *delegate = [[WebCoreResourceHandleAsDelegate alloc] initWithHandle:this];
+        id <NSURLConnectionDelegate> delegate = (client() && client()->usesAsyncCallbacks()) ?
+            [[WebCoreResourceHandleAsOperationQueueDelegate alloc] initWithHandle:this]
+          : [[WebCoreResourceHandleAsDelegate alloc] initWithHandle:this];
         d->m_delegate = delegate;
         [delegate release];
     }
@@ -400,20 +403,46 @@ void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceRes
         }
     }
 
-    RefPtr<ResourceHandle> protect(this);
-    client()->willSendRequest(this, request, redirectResponse);
+    if (client()->usesAsyncCallbacks()) {
+        client()->willSendRequestAsync(this, request, redirectResponse);
+    } else {
+        RefPtr<ResourceHandle> protect(this);
+        client()->willSendRequest(this, request, redirectResponse);
+
+        // Client call may not preserve the session, especially if the request is sent over IPC.
+        if (!request.isNull())
+            request.setStorageSession(d->m_storageSession.get());
+    }
+}
+
+void ResourceHandle::continueWillSendRequest(const ResourceRequest& request)
+{
+    ASSERT(client() && client()->usesAsyncCallbacks());
 
     // Client call may not preserve the session, especially if the request is sent over IPC.
-    if (!request.isNull())
-        request.setStorageSession(d->m_storageSession.get());
+    ResourceRequest newRequest = request;
+    if (!newRequest.isNull())
+        newRequest.setStorageSession(d->m_storageSession.get());
+    [(id)delegate() continueWillSendRequest:newRequest.nsURLRequest(UpdateHTTPBody)];
 }
 
 bool ResourceHandle::shouldUseCredentialStorage()
 {
-    if (client())
-        return client()->shouldUseCredentialStorage(this);
+    if (client()->usesAsyncCallbacks()) {
+        if (client())
+            client()->shouldUseCredentialStorageAsync(this);
+        else
+            continueShouldUseCredentialStorage(false);
+        return false; // Ignored by caller.
+    } else
+        return client() && client()->shouldUseCredentialStorage(this);
+}
 
-    return false;
+void ResourceHandle::continueShouldUseCredentialStorage(bool useCredentialStorage)
+{
+    ASSERT(client() && client()->usesAsyncCallbacks());
+
+    [(id)delegate() continueShouldUseCredentialStorage:useCredentialStorage];
 }
 
 void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
@@ -492,10 +521,21 @@ void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChalle
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
 bool ResourceHandle::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
 {
-    if (client())
-        return client()->canAuthenticateAgainstProtectionSpace(this, protectionSpace);
-        
-    return false;
+    if (client()->usesAsyncCallbacks()) {
+        if (client())
+            client()->canAuthenticateAgainstProtectionSpaceAsync(this, protectionSpace);
+        else
+            continueCanAuthenticateAgainstProtectionSpace(false);
+        return false; // Ignored by caller.
+    } else
+        return client() && client()->canAuthenticateAgainstProtectionSpace(this, protectionSpace);
+}
+
+void ResourceHandle::continueCanAuthenticateAgainstProtectionSpace(bool result)
+{
+    ASSERT(client() && client()->usesAsyncCallbacks());
+
+    [(id)delegate() continueCanAuthenticateAgainstProtectionSpace:result];
 }
 #endif
 
@@ -553,6 +593,14 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
         client()->receivedCancellation(this, challenge);
 }
 
+void ResourceHandle::continueWillCacheResponse(NSCachedURLResponse *response)
+{
+    ASSERT(client() && client()->usesAsyncCallbacks());
+
+    [(id)delegate() continueWillCacheResponse:response];
+}
+
+
 } // namespace WebCore
 
 #endif // !USE(CFNETWORK)
index 2dc7fc4..4f4155e 100644 (file)
@@ -29,7 +29,7 @@
 #if !USE(CFNETWORK)
 
 namespace WebCore {
-    class ResourceHandle;
+class ResourceHandle;
 }
 
 @interface WebCoreResourceHandleAsDelegate : NSObject <NSURLConnectionDelegate> {
index 3d39ec0..0b1e0af 100644 (file)
@@ -259,11 +259,7 @@ using namespace WebCore;
         && [[(NSHTTPURLResponse *)[cachedResponse response] allHeaderFields] objectForKey:@"Vary"])
         return nil;
 
-    NSCachedURLResponse *newResponse = m_handle->client()->willCacheResponse(m_handle, cachedResponse);
-    if (newResponse != cachedResponse)
-        return newResponse;
-    
-    return newResponse;
+    return m_handle->client()->willCacheResponse(m_handle, cachedResponse);
 }
 
 @end
diff --git a/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.h b/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.h
new file mode 100644 (file)
index 0000000..0be6675
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef WebCoreResourceHandleAsOperationQueueDelegate_h
+#define WebCoreResourceHandleAsOperationQueueDelegate_h
+
+#if !USE(CFNETWORK)
+
+#include <dispatch/dispatch.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+class ResourceHandle;
+}
+
+@interface WebCoreResourceHandleAsOperationQueueDelegate : NSObject <NSURLConnectionDelegate> {
+    WebCore::ResourceHandle* m_handle;
+
+    // Synchronous delegates on operation queue wait until main thread sends an asynchronous response.
+    dispatch_semaphore_t m_semaphore;
+    RetainPtr<NSURLRequest> m_requestResult;
+    RetainPtr<NSCachedURLResponse> m_cachedResponseResult;
+    BOOL m_boolResult;
+}
+- (id)initWithHandle:(WebCore::ResourceHandle*)handle;
+- (void)detachHandle;
+- (void)continueWillSendRequest:(NSURLRequest *)newRequest;
+- (void)continueShouldUseCredentialStorage:(BOOL)useCredentialStorage;
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+- (void)continueCanAuthenticateAgainstProtectionSpace:(BOOL)canAuthenticate;
+#endif
+- (void)continueWillCacheResponse:(NSCachedURLResponse *)response;
+@end
+
+#endif // !USE(CFNETWORK)
+#endif // WebCoreResourceHandleAsOperationQueueDelegate_h
diff --git a/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm b/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm
new file mode 100644 (file)
index 0000000..8510543
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 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 "WebCoreResourceHandleAsOperationQueueDelegate.h"
+
+#if !USE(CFNETWORK)
+
+#import "AuthenticationChallenge.h"
+#import "AuthenticationMac.h"
+#import "Logging.h"
+#import "ResourceHandle.h"
+#import "ResourceHandleClient.h"
+#import "ResourceRequest.h"
+#import "ResourceResponse.h"
+#import "SharedBuffer.h"
+#import "WebCoreURLResponse.h"
+#import <wtf/MainThread.h>
+
+@interface NSURLRequest (Details)
+- (id)_propertyForKey:(NSString *)key;
+@end
+
+using namespace WebCore;
+
+@implementation WebCoreResourceHandleAsOperationQueueDelegate
+
+- (id)initWithHandle:(ResourceHandle*)handle
+{
+    self = [self init];
+    if (!self)
+        return nil;
+
+    m_handle = handle;
+    m_semaphore = dispatch_semaphore_create(0);
+
+    return self;
+}
+
+- (void)detachHandle
+{
+    m_handle = 0;
+
+    m_requestResult = nullptr;
+    m_cachedResponseResult = nullptr;
+    m_boolResult = NO;
+    dispatch_semaphore_signal(m_semaphore); // OK to signal even if we are not waiting.
+}
+
+- (void)dealloc
+{
+    dispatch_release(m_semaphore);
+    [super dealloc];
+}
+
+- (void)continueWillSendRequest:(NSURLRequest *)newRequest
+{
+    m_requestResult = [newRequest retain];
+    dispatch_semaphore_signal(m_semaphore);
+}
+
+- (void)continueShouldUseCredentialStorage:(BOOL)useCredentialStorage
+{
+    m_boolResult = useCredentialStorage;
+    dispatch_semaphore_signal(m_semaphore);
+}
+
+- (void)continueCanAuthenticateAgainstProtectionSpace:(BOOL)canAuthenticate
+{
+    m_boolResult = canAuthenticate;
+    dispatch_semaphore_signal(m_semaphore);
+}
+
+- (void)continueWillCacheResponse:(NSCachedURLResponse *)response
+{
+    m_cachedResponseResult = response;
+    dispatch_semaphore_signal(m_semaphore);
+}
+
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    // See <rdar://problem/5380697>. This is a workaround for a behavior change in CFNetwork where willSendRequest gets called more often.
+    if (!redirectResponse)
+        return newRequest;
+
+#if !LOG_DISABLED
+    if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]])
+        LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%d, Location:<%@>", m_handle, connection, [newRequest description], static_cast<int>([(id)redirectResponse statusCode]), [[(id)redirectResponse allHeaderFields] objectForKey:@"Location"]);
+    else
+        LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:non-HTTP", m_handle, connection, [newRequest description]); 
+#endif
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle) {
+            m_requestResult = nullptr;
+            dispatch_semaphore_signal(m_semaphore);
+            return;
+        }
+
+        ResourceRequest request = newRequest;
+
+        m_handle->willSendRequest(request, redirectResponse);
+    });
+
+    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+    return [m_requestResult.leakRef() autorelease];
+}
+
+- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connectionShouldUseCredentialStorage:%p", m_handle, connection);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle) {
+            m_boolResult = NO;
+            dispatch_semaphore_signal(m_semaphore);
+            return;
+        }
+        m_handle->shouldUseCredentialStorage();
+    });
+
+    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+    return m_boolResult;
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p didReceiveAuthenticationChallenge:%p", m_handle, connection, challenge);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle) {
+            [[challenge sender] cancelAuthenticationChallenge:challenge];
+            return;
+        }
+        m_handle->didReceiveAuthenticationChallenge(core(challenge));
+    });
+}
+
+- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+    // FIXME: We probably don't need to implement this (see <rdar://problem/8960124>).
+
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p didCancelAuthenticationChallenge:%p", m_handle, connection, challenge);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle)
+            return;
+        m_handle->didCancelAuthenticationChallenge(core(challenge));
+    });
+}
+
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p canAuthenticateAgainstProtectionSpace:%@://%@:%u realm:%@ method:%@ %@%@", m_handle, connection, [protectionSpace protocol], [protectionSpace host], [protectionSpace port], [protectionSpace realm], [protectionSpace authenticationMethod], [protectionSpace isProxy] ? @"proxy:" : @"", [protectionSpace isProxy] ? [protectionSpace proxyType] : @"");
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle) {
+            m_boolResult = NO;
+            dispatch_semaphore_signal(m_semaphore);
+            return;
+        }
+        m_handle->canAuthenticateAgainstProtectionSpace(core(protectionSpace));
+    });
+
+    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+    return m_boolResult;
+}
+#endif
+
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d, reported MIMEType '%s')", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0, [[r MIMEType] UTF8String]);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+
+        // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
+        int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0;
+        if (statusCode != 304)
+            adjustMIMETypeIfNecessary([r _CFURLResponse]);
+
+        if ([m_handle->firstRequest().nsURLRequest(DoNotUpdateHTTPBody) _propertyForKey:@"ForceHTMLMIMEType"])
+            [r _setMIMEType:@"text/html"];
+
+        m_handle->client()->didReceiveResponse(m_handle, r);
+    });
+}
+
+#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
+- (void)connection:(NSURLConnection *)connection didReceiveDataArray:(NSArray *)dataArray
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p didReceiveDataArray:%p arraySize:%d", m_handle, connection, dataArray, [dataArray count]);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!dataArray)
+            return;
+
+        if (!m_handle || !m_handle->client())
+            return;
+
+        m_handle->handleDataArray(reinterpret_cast<CFArrayRef>(dataArray));
+        // The call to didReceiveData above can cancel a load, and if so, the delegate (self) could have been deallocated by this point.
+    });
+}
+#endif
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+    UNUSED_PARAM(lengthReceived);
+
+    LOG(Network, "Handle %p delegate connection:%p didReceiveData:%p lengthReceived:%lld", m_handle, connection, data, lengthReceived);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+        // FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing.
+        // However, with today's computers and networking speeds, this won't happen in practice.
+        // Could be an issue with a giant local file.
+
+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
+        // -1 means we do not provide any data about transfer size to inspector so it would use
+        // Content-Length headers or content size to show transfer size.
+        m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
+    });
+}
+
+- (void)connection:(NSURLConnection *)connection willStopBufferingData:(NSData *)data
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p willStopBufferingData:%p", m_handle, connection, data);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+        // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
+        // However, with today's computers and networking speeds, this won't happen in practice.
+        // Could be an issue with a giant local file.
+        m_handle->client()->willStopBufferingData(m_handle, (const char*)[data bytes], static_cast<int>([data length]));
+    });
+}
+
+- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+    UNUSED_PARAM(bytesWritten);
+
+    LOG(Network, "Handle %p delegate connection:%p didSendBodyData:%d totalBytesWritten:%d totalBytesExpectedToWrite:%d", m_handle, connection, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+        m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite);
+    });
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connectionDidFinishLoading:%p", m_handle, connection);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+
+        m_handle->client()->didFinishLoading(m_handle, 0);
+    });
+}
+
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p didFailWithError:%@", m_handle, connection, error);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client())
+            return;
+
+        m_handle->client()->didFail(m_handle, error);
+    });
+}
+
+
+- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
+{
+    ASSERT(!isMainThread());
+    UNUSED_PARAM(connection);
+
+    LOG(Network, "Handle %p delegate connection:%p willCacheResponse:%p", m_handle, connection, cachedResponse);
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_handle || !m_handle->client()) {
+            m_cachedResponseResult = nullptr;
+            dispatch_semaphore_signal(m_semaphore);
+            return;
+        }
+
+        // Workaround for <rdar://problem/6300990> Caching does not respect Vary HTTP header.
+        // FIXME: WebCore cache has issues with Vary, too (bug 58797, bug 71509).
+        if ([[cachedResponse response] isKindOfClass:[NSHTTPURLResponse class]]
+            && [[(NSHTTPURLResponse *)[cachedResponse response] allHeaderFields] objectForKey:@"Vary"]) {
+            m_cachedResponseResult = nullptr;
+            dispatch_semaphore_signal(m_semaphore);
+            return;
+        }
+
+        m_handle->client()->willCacheResponseAsync(m_handle, cachedResponse);
+    });
+
+    dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
+    return [m_cachedResponseResult.leakRef() autorelease];
+}
+
+@end
+
+#endif // !USE(CFNETWORK)
+
index d5ae780..cae95a6 100644 (file)
@@ -1,3 +1,62 @@
+2013-03-26  Alexey Proskuryakov  <ap@apple.com>
+
+        <rdar://problem/13194263> Crashes in NetworkProcess due to threading issues
+        https://bugs.webkit.org/show_bug.cgi?id=113256
+
+        Reviewed by Brady Eidson.
+
+        Use asynchronous version of ResourceHandle/ResourceHandleClient in NetworkProcess.
+        We now run WebCore code on main thread, so we can't block it.
+
+        * DerivedSources.make:
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::didReceiveMessage):
+        * NetworkProcess/NetworkResourceLoader.messages.in: Added.
+        * WebKit2.xcodeproj/project.pbxproj:
+        Made NetworkResourceLoader a message receiver. Messages that used to be sync are
+        now async, and responses need to be sent to the loader.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::willSendRequestAsync): This now happens on main
+        thread, and thus cannot be sync.
+        (WebKit::NetworkResourceLoader::continueWillSendRequest): Notify the resource
+        handle once a response is ready.
+        (WebKit::NetworkResourceLoader::didSendData): Removed unnecessary WebCore prefixes.
+        (WebKit::NetworkResourceLoader::didReceiveCachedMetadata): Ditto.
+        (WebKit::NetworkResourceLoader::wasBlocked):  Ditto.
+        (WebKit::NetworkResourceLoader::cannotShowURL): Ditto.
+        (WebKit::NetworkResourceLoader::shouldUseCredentialStorageAsync): This function
+        doesn't call through to WebProcess, so we can keep it synchronous. But we still
+        need to implement the async version, since that's what ResourceHandle calls.
+        (WebKit::NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync):
+        Made async.
+        (WebKit::NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace):
+        Notify ResourceHandle when response is ready.
+        (WebKit::NetworkResourceLoader::didReceiveDataArray): Removed unnecessary WebCore prefixes.
+        (WebKit::NetworkResourceLoader::willCacheResponseAsync): This matches default
+        implementation, but we are overriding everything to make it clearer what's missing.
+        (WebKit::NetworkResourceLoader::willStopBufferingData): Removed unnecessary WebCore prefixes.
+
+        * NetworkProcess/NetworkResourceLoader.h: Updated to use async client methods.
+        Keep ResourceRequest around while handling willSendRequest, as we need the original
+        to recombine the request. Removed CFNet version of willCacheResponse for now,
+        as we are not using it yet.
+
+        * Shared/Authentication/AuthenticationManager.cpp: Assert that methods touching
+        a global HashMap all run on main thread. Changed generateAuthenticationChallengeID()
+        to use regular increment, as there is no need to run it from a secondary thread.
+
+        * WebProcess/Network/NetworkProcessConnection.cpp:
+        (WebKit::NetworkProcessConnection::didReceiveSyncMessage): We no longer have any
+        sync messages.
+
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::willSendRequest):
+        (WebKit::WebResourceLoader::canAuthenticateAgainstProtectionSpace):
+        * WebProcess/Network/WebResourceLoader.messages.in:
+        Changed to use async messages.
+
 2013-03-26  Tim Horton  <timothy_horton@apple.com>
 
         [wk2] Don't send intrinsic content size updates more than once per runloop
index 6547042..df2dbcb 100644 (file)
@@ -69,6 +69,7 @@ MESSAGE_RECEIVERS = \
     NetworkProcess \
     NetworkProcessConnection \
     NetworkProcessProxy \
+    NetworkResourceLoader \
     NPObjectMessageReceiver \
     OfflineStorageProcess \
     PluginControllerProxy \
index b249e82..54d5ac9 100644 (file)
@@ -33,6 +33,7 @@
 #include "NetworkProcess.h"
 #include "NetworkResourceLoadParameters.h"
 #include "NetworkResourceLoader.h"
+#include "NetworkResourceLoaderMessages.h"
 #include "RemoteNetworkingContext.h"
 #include "SyncNetworkResourceLoader.h"
 #include <WebCore/BlobData.h>
@@ -70,6 +71,13 @@ void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* conne
         didReceiveNetworkConnectionToWebProcessMessage(connection, decoder);
         return;
     }
+
+    if (decoder.messageReceiverName() == Messages::NetworkResourceLoader::messageReceiverName()) {
+        HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader> >::iterator loaderIterator = m_networkResourceLoaders.find(decoder.destinationID());
+        if (loaderIterator != m_networkResourceLoaders.end())
+            loaderIterator->value->didReceiveNetworkResourceLoaderMessage(connection, decoder);
+        return;
+    }
     
     ASSERT_NOT_REACHED();
 }
index 96c2c70..ca8cac3 100644 (file)
@@ -277,54 +277,58 @@ void NetworkResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
     scheduleCleanupOnMainThread();
 }
 
-void NetworkResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
+void NetworkResourceLoader::willSendRequestAsync(ResourceHandle*, const ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
     // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect.
     ASSERT(!redirectResponse.isNull());
-    ASSERT(!isMainThread());
+    ASSERT(isMainThread());
+
+    m_suggestedRequestForWillSendRequest = request;
 
-    // IMPORTANT: The fact that this message to the WebProcess is sync is what makes our current approach to synchronous XMLHttpRequests safe.
-    // If this message changes to be asynchronous we might introduce a situation where the NetworkProcess is deadlocked waiting for 6 connections
+    // This message is DispatchMessageEvenWhenWaitingForSyncReply to avoid a situation where the NetworkProcess is deadlocked waiting for 6 connections
     // to complete while the WebProcess is waiting for a 7th to complete.
-    // If we ever change this message to be asynchronous we have to include safeguards to make sure the new design interacts well with sync XHR.
-    ResourceRequest returnedRequest;
-    if (!sendSyncAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(request, redirectResponse), Messages::WebResourceLoader::WillSendRequest::Reply(returnedRequest)))
-        return;
-    
-    request.updateFromDelegatePreservingOldHTTPBody(returnedRequest.nsURLRequest(DoNotUpdateHTTPBody));
+    connection()->send(Messages::WebResourceLoader::WillSendRequest(request, redirectResponse), destinationID(), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
+}
+
+void NetworkResourceLoader::continueWillSendRequest(const ResourceRequest& newRequest)
+{
+    m_suggestedRequestForWillSendRequest.updateFromDelegatePreservingOldHTTPBody(newRequest.nsURLRequest(DoNotUpdateHTTPBody));
 
-    RunLoop::main()->dispatch(bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), this, request.url()));
+    RunLoop::main()->dispatch(bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), this, m_suggestedRequestForWillSendRequest.url()));
+    m_handle->continueWillSendRequest(m_suggestedRequestForWillSendRequest);
+
+    m_suggestedRequestForWillSendRequest = ResourceRequest();
 }
 
 // FIXME (NetworkProcess): Many of the following ResourceHandleClient methods definitely need implementations. A few will not.
 // Once we know what they are they can be removed.
 
-void NetworkResourceLoader::didSendData(WebCore::ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/)
+void NetworkResourceLoader::didSendData(ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/)
 {
     notImplemented();
 }
 
-void NetworkResourceLoader::didReceiveCachedMetadata(WebCore::ResourceHandle*, const char*, int)
+void NetworkResourceLoader::didReceiveCachedMetadata(ResourceHandle*, const char*, int)
 {
     notImplemented();
 }
 
-void NetworkResourceLoader::wasBlocked(WebCore::ResourceHandle*)
+void NetworkResourceLoader::wasBlocked(ResourceHandle*)
 {
     notImplemented();
 }
 
-void NetworkResourceLoader::cannotShowURL(WebCore::ResourceHandle*)
+void NetworkResourceLoader::cannotShowURL(ResourceHandle*)
 {
     notImplemented();
 }
 
-bool NetworkResourceLoader::shouldUseCredentialStorage(ResourceHandle*)
+void NetworkResourceLoader::shouldUseCredentialStorageAsync(ResourceHandle* handle)
 {
     // When the WebProcess is handling loading a client is consulted each time this shouldUseCredentialStorage question is asked.
     // In NetworkProcess mode we ask the WebProcess client up front once and then reuse the cached answer.
 
-    return allowStoredCredentials() == AllowStoredCredentials;
+    handle->continueShouldUseCredentialStorage(allowStoredCredentials() == AllowStoredCredentials);
 }
 
 void NetworkResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge)
@@ -338,20 +342,20 @@ void NetworkResourceLoader::didCancelAuthenticationChallenge(ResourceHandle*, co
 }
 
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
-bool NetworkResourceLoader::canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace& protectionSpace)
+void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle*, const ProtectionSpace& protectionSpace)
 {
-    ASSERT(!isMainThread());
+    ASSERT(isMainThread());
 
-    // IMPORTANT: The fact that this message to the WebProcess is sync is what makes our current approach to synchronous XMLHttpRequests safe.
-    // If this message changes to be asynchronous we might introduce a situation where the NetworkProcess is deadlocked waiting for 6 connections
-    // to complete while the WebProcess is waiting for a 7th to complete.
-    // If we ever change this message to be asynchronous we have to include safeguards to make sure the new design interacts well with sync XHR.
-    bool result;
-    if (!sendSyncAbortingOnFailure(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(protectionSpace), Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace::Reply(result)))
-        return false;
+    // This message is DispatchMessageEvenWhenWaitingForSyncReply to avoid a situation where the NetworkProcess is deadlocked
+    // waiting for 6 connections to complete while the WebProcess is waiting for a 7th to complete.
+    connection()->send(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(protectionSpace), destinationID(), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
+}
 
-    return result;
+void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result)
+{
+    m_handle->continueCanAuthenticateAgainstProtectionSpace(result);
 }
+
 #endif
 
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
@@ -361,7 +365,7 @@ bool NetworkResourceLoader::supportsDataArray()
     return false;
 }
 
-void NetworkResourceLoader::didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef)
+void NetworkResourceLoader::didReceiveDataArray(ResourceHandle*, CFArrayRef)
 {
     ASSERT_NOT_REACHED();
     notImplemented();
@@ -369,21 +373,13 @@ void NetworkResourceLoader::didReceiveDataArray(WebCore::ResourceHandle*, CFArra
 #endif
 
 #if PLATFORM(MAC)
-#if USE(CFNETWORK)
-CFCachedURLResponseRef NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, CFCachedURLResponseRef response)
+void NetworkResourceLoader::willCacheResponseAsync(ResourceHandle* handle, NSCachedURLResponse* response)
 {
     notImplemented();
-    return response;
+    handle->continueWillCacheResponse(response);
 }
-#else
-NSCachedURLResponse* NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, NSCachedURLResponse* response)
-{
-    notImplemented();
-    return response;
-}
-#endif
 
-void NetworkResourceLoader::willStopBufferingData(WebCore::ResourceHandle*, const char*, int)
+void NetworkResourceLoader::willStopBufferingData(ResourceHandle*, const char*, int)
 {
     notImplemented();
 }
index 5145861..a4f3fdb 100644 (file)
@@ -63,22 +63,22 @@ public:
     virtual void connectionToWebProcessDidClose() OVERRIDE;
         
     // ResourceHandleClient methods
-    virtual void willSendRequest(WebCore::ResourceHandle*, WebCore::ResourceRequest&, const WebCore::ResourceResponse& /*redirectResponse*/) OVERRIDE;
-    virtual void didSendData(WebCore::ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/) OVERRIDE;
+    virtual void willSendRequestAsync(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse) OVERRIDE;
+    virtual void didSendData(WebCore::ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) OVERRIDE;
     virtual void didReceiveResponse(WebCore::ResourceHandle*, const WebCore::ResourceResponse&) OVERRIDE;
-    virtual void didReceiveData(WebCore::ResourceHandle*, const char*, int, int /*encodedDataLength*/) OVERRIDE;
+    virtual void didReceiveData(WebCore::ResourceHandle*, const char*, int, int encodedDataLength) OVERRIDE;
     virtual void didReceiveCachedMetadata(WebCore::ResourceHandle*, const char*, int) OVERRIDE;
-    virtual void didFinishLoading(WebCore::ResourceHandle*, double /*finishTime*/) OVERRIDE;
+    virtual void didFinishLoading(WebCore::ResourceHandle*, double finishTime) OVERRIDE;
     virtual void didFail(WebCore::ResourceHandle*, const WebCore::ResourceError&) OVERRIDE;
     virtual void wasBlocked(WebCore::ResourceHandle*) OVERRIDE;
     virtual void cannotShowURL(WebCore::ResourceHandle*) OVERRIDE;
-    virtual bool shouldUseCredentialStorage(WebCore::ResourceHandle*) OVERRIDE;
+    virtual void shouldUseCredentialStorageAsync(WebCore::ResourceHandle*) OVERRIDE;
     virtual void didReceiveAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) OVERRIDE;
     virtual void didCancelAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) OVERRIDE;
     virtual bool usesAsyncCallbacks() OVERRIDE { return true; }
 
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
-    virtual bool canAuthenticateAgainstProtectionSpace(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&) OVERRIDE;
+    virtual void canAuthenticateAgainstProtectionSpaceAsync(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&);
 #endif
 
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
@@ -88,17 +88,21 @@ public:
 
 #if PLATFORM(MAC)
     static size_t fileBackedResourceMinimumSize();
-#if USE(CFNETWORK)
-    virtual CFCachedURLResponseRef willCacheResponse(WebCore::ResourceHandle*, CFCachedURLResponseRef) OVERRIDE;
-#else
-    virtual NSCachedURLResponse* willCacheResponse(WebCore::ResourceHandle*, NSCachedURLResponse*) OVERRIDE;
-#endif
+    virtual void willCacheResponseAsync(WebCore::ResourceHandle*, NSCachedURLResponse *);
     virtual void willStopBufferingData(WebCore::ResourceHandle*, const char*, int) OVERRIDE;
 #endif // PLATFORM(MAC)
 
+    // Message handlers.
+    void didReceiveNetworkResourceLoaderMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&);
+
 private:
     NetworkResourceLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*);
 
+    void continueWillSendRequest(const WebCore::ResourceRequest& newRequest);
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+    void continueCanAuthenticateAgainstProtectionSpace(bool);
+#endif
+
     void scheduleCleanupOnMainThread();
     static void performCleanups(void*);
     void cleanup();
@@ -114,6 +118,9 @@ private:
     RefPtr<RemoteNetworkingContext> m_networkingContext;
     RefPtr<WebCore::ResourceHandle> m_handle;
 
+    // Keep the suggested request around while asynchronously asking to update it, because some parts of the request don't survive IPC.
+    WebCore::ResourceRequest m_suggestedRequestForWillSendRequest;
+
     uint64_t m_bytesReceived;
 
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in
new file mode 100644 (file)
index 0000000..47f8ba3
--- /dev/null
@@ -0,0 +1,27 @@
+# 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.
+
+messages -> NetworkResourceLoader LegacyReceiver {
+
+    ContinueWillSendRequest(WebCore::ResourceRequest request)
+    ContinueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate)
+}
index 07e8633..7f7dca2 100644 (file)
@@ -36,7 +36,6 @@
 #include "WebPageProxyMessages.h"
 #include <WebCore/AuthenticationChallenge.h>
 #include <WebCore/AuthenticationClient.h>
-#include <wtf/Atomics.h>
 
 #if ENABLE(NETWORK_PROCESS)
 #include "NetworkProcessProxyMessages.h"
@@ -48,8 +47,10 @@ namespace WebKit {
 
 static uint64_t generateAuthenticationChallengeID()
 {
+    ASSERT(isMainThread());
+
     static int64_t uniqueAuthenticationChallengeID;
-    return atomicIncrement(&uniqueAuthenticationChallengeID);
+    return ++uniqueAuthenticationChallengeID;
 }
 
 const char* AuthenticationManager::supplementName()
@@ -65,6 +66,8 @@ AuthenticationManager::AuthenticationManager(ChildProcess* process)
 
 uint64_t AuthenticationManager::establishIdentifierForChallenge(const WebCore::AuthenticationChallenge& authenticationChallenge)
 {
+    ASSERT(isMainThread());
+
     uint64_t challengeID = generateAuthenticationChallengeID();
     m_challenges.set(challengeID, authenticationChallenge);
     return challengeID;
@@ -103,6 +106,8 @@ bool AuthenticationManager::tryUsePlatformCertificateInfoForChallenge(const WebC
 
 void AuthenticationManager::useCredentialForChallenge(uint64_t challengeID, const Credential& credential, const PlatformCertificateInfo& certificateInfo)
 {
+    ASSERT(isMainThread());
+
     AuthenticationChallenge challenge = m_challenges.take(challengeID);
     ASSERT(!challenge.isNull());
     
@@ -121,6 +126,8 @@ void AuthenticationManager::useCredentialForChallenge(uint64_t challengeID, cons
 
 void AuthenticationManager::continueWithoutCredentialForChallenge(uint64_t challengeID)
 {
+    ASSERT(isMainThread());
+
     AuthenticationChallenge challenge = m_challenges.take(challengeID);
     ASSERT(!challenge.isNull());
     AuthenticationClient* coreClient = challenge.authenticationClient();
@@ -135,6 +142,8 @@ void AuthenticationManager::continueWithoutCredentialForChallenge(uint64_t chall
 
 void AuthenticationManager::cancelChallenge(uint64_t challengeID)
 {
+    ASSERT(isMainThread());
+
     AuthenticationChallenge challenge = m_challenges.take(challengeID);
     ASSERT(!challenge.isNull());
     AuthenticationClient* coreClient = challenge.authenticationClient();
index ef33b67..56f61a1 100644 (file)
                E14A954A16E016A40068DE82 /* NetworkProcessPlatformStrategies.h in Headers */ = {isa = PBXBuildFile; fileRef = E14A954816E016A40068DE82 /* NetworkProcessPlatformStrategies.h */; };
                E1513C66166EABB200149FCB /* ChildProcessProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1513C64166EABB200149FCB /* ChildProcessProxy.cpp */; };
                E1513C67166EABB200149FCB /* ChildProcessProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = E1513C65166EABB200149FCB /* ChildProcessProxy.h */; };
+               E152551A17011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E152551817011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp */; };
+               E152551B17011819003D7ADB /* NetworkResourceLoaderMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = E152551917011819003D7ADB /* NetworkResourceLoaderMessages.h */; };
                E170876B16D6CA6900F99226 /* BlobRegistryProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E170876916D6CA6900F99226 /* BlobRegistryProxy.cpp */; };
                E170876C16D6CA6900F99226 /* BlobRegistryProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = E170876A16D6CA6900F99226 /* BlobRegistryProxy.h */; };
                E170877016D6CFE500F99226 /* BlobRegistrationData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E170876E16D6CFE400F99226 /* BlobRegistrationData.cpp */; };
                E14A954816E016A40068DE82 /* NetworkProcessPlatformStrategies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkProcessPlatformStrategies.h; path = NetworkProcess/NetworkProcessPlatformStrategies.h; sourceTree = "<group>"; };
                E1513C64166EABB200149FCB /* ChildProcessProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChildProcessProxy.cpp; sourceTree = "<group>"; };
                E1513C65166EABB200149FCB /* ChildProcessProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildProcessProxy.h; sourceTree = "<group>"; };
+               E1525517170109FB003D7ADB /* NetworkResourceLoader.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = NetworkResourceLoader.messages.in; path = NetworkProcess/NetworkResourceLoader.messages.in; sourceTree = "<group>"; };
+               E152551817011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkResourceLoaderMessageReceiver.cpp; sourceTree = "<group>"; };
+               E152551917011819003D7ADB /* NetworkResourceLoaderMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkResourceLoaderMessages.h; sourceTree = "<group>"; };
                E170876916D6CA6900F99226 /* BlobRegistryProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlobRegistryProxy.cpp; path = WebProcess/FileAPI/BlobRegistryProxy.cpp; sourceTree = "<group>"; };
                E170876A16D6CA6900F99226 /* BlobRegistryProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlobRegistryProxy.h; path = WebProcess/FileAPI/BlobRegistryProxy.h; sourceTree = "<group>"; };
                E170876E16D6CFE400F99226 /* BlobRegistrationData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlobRegistrationData.cpp; path = FileAPI/BlobRegistrationData.cpp; sourceTree = "<group>"; };
                                51A8A6171627F5BB000D90E9 /* NetworkProcess.messages.in */,
                                51FD18B31651FBAD00DBE1CE /* NetworkResourceLoader.cpp */,
                                51FD18B41651FBAD00DBE1CE /* NetworkResourceLoader.h */,
+                               E1525517170109FB003D7ADB /* NetworkResourceLoader.messages.in */,
                                51829DA31637C70C000953D6 /* NetworkResourceLoadScheduler.cpp */,
                                51829DA41637C70C000953D6 /* NetworkResourceLoadScheduler.h */,
                                519B4FF216A9EA970066874D /* SchedulableLoader.cpp */,
                                51ACC9351628064800342550 /* NetworkProcessMessages.h */,
                                513A163A163088F6005D7D22 /* NetworkProcessProxyMessageReceiver.cpp */,
                                513A163B163088F6005D7D22 /* NetworkProcessProxyMessages.h */,
+                               E152551817011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp */,
+                               E152551917011819003D7ADB /* NetworkResourceLoaderMessages.h */,
                                1A2D8437127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp */,
                                1A2D8438127F65D5001EB962 /* NPObjectMessageReceiverMessages.h */,
                                BCAF35E016CA249300D4E9FC /* OfflineStorageProcessMessageReceiver.cpp */,
                                E170877116D6CFE500F99226 /* BlobRegistrationData.h in Headers */,
                                E14A954A16E016A40068DE82 /* NetworkProcessPlatformStrategies.h in Headers */,
                                E1798C7A16E6818800240139 /* NetworkBlobRegistry.h in Headers */,
+                               E152551B17011819003D7ADB /* NetworkResourceLoaderMessages.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                E170877016D6CFE500F99226 /* BlobRegistrationData.cpp in Sources */,
                                E14A954916E016A40068DE82 /* NetworkProcessPlatformStrategies.cpp in Sources */,
                                E1798C7916E6818800240139 /* NetworkBlobRegistry.cpp in Sources */,
+                               E152551A17011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 10b91a1..c243fad 100644 (file)
@@ -66,13 +66,6 @@ void NetworkProcessConnection::didReceiveMessage(CoreIPC::Connection* connection
 
 void NetworkProcessConnection::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
 {
-    if (decoder.messageReceiverName() == Messages::WebResourceLoader::messageReceiverName()) {
-        if (WebResourceLoader* webResourceLoader = WebProcess::shared().webResourceLoadScheduler().webResourceLoaderForIdentifier(decoder.destinationID()))
-            webResourceLoader->didReceiveSyncWebResourceLoaderMessage(connection, decoder, replyEncoder);
-        
-        return;
-    }
-
     ASSERT_NOT_REACHED();
 }
 
index 94e6e95..6e19c18 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 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
@@ -31,6 +31,7 @@
 #include "DataReference.h"
 #include "Logging.h"
 #include "NetworkProcessConnection.h"
+#include "NetworkResourceLoaderMessages.h"
 #include "PlatformCertificateInfo.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebErrors.h"
@@ -72,12 +73,13 @@ void WebResourceLoader::cancelResourceLoader()
     m_coreLoader->cancel();
 }
 
-void WebResourceLoader::willSendRequest(const ResourceRequest& proposedRequest, const ResourceResponse& redirectResponse, ResourceRequest& newRequest)
+void WebResourceLoader::willSendRequest(const ResourceRequest& proposedRequest, const ResourceResponse& redirectResponse)
 {
     LOG(Network, "(WebProcess) WebResourceLoader::willSendRequest to '%s'", proposedRequest.url().string().utf8().data());
     
-    newRequest = proposedRequest;
+    ResourceRequest newRequest = proposedRequest;
     m_coreLoader->willSendRequest(newRequest, redirectResponse);
+    send(Messages::NetworkResourceLoader::ContinueWillSendRequest(newRequest));
 }
 
 void WebResourceLoader::didReceiveResponseWithCertificateInfo(const ResourceResponse& response, const PlatformCertificateInfo& certificateInfo)
@@ -125,9 +127,10 @@ void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& hand
     m_coreLoader->didFinishLoading(finishTime);
 }
 
-void WebResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace, bool& result)
+void WebResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
 {
-    result = m_coreLoader->canAuthenticateAgainstProtectionSpace(protectionSpace);
+    bool result = m_coreLoader->canAuthenticateAgainstProtectionSpace(protectionSpace);
+    send(Messages::NetworkResourceLoader::ContinueCanAuthenticateAgainstProtectionSpace(result));
 }
 
 } // namespace WebKit
index ecb03fd..3cf7b47 100644 (file)
@@ -64,7 +64,6 @@ public:
     uint64_t destinationID() const;
 
     void didReceiveWebResourceLoaderMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&);
-    void didReceiveSyncWebResourceLoaderMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&);
 
     WebCore::ResourceLoader* resourceLoader() const { return m_coreLoader.get(); }
 
@@ -73,14 +72,14 @@ private:
 
     void cancelResourceLoader();
 
-    void willSendRequest(const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse, WebCore::ResourceRequest& newRequest);
+    void willSendRequest(const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse);
     void didReceiveResponseWithCertificateInfo(const WebCore::ResourceResponse&, const PlatformCertificateInfo&);
     void didReceiveData(const CoreIPC::DataReference&, int64_t encodedDataLength);
     void didFinishResourceLoad(double finishTime);
     void didFailResourceLoad(const WebCore::ResourceError&);
     void didReceiveResource(const ShareableResource::Handle&, double finishTime);
 
-    void canAuthenticateAgainstProtectionSpace(const WebCore::ProtectionSpace&, bool& result);
+    void canAuthenticateAgainstProtectionSpace(const WebCore::ProtectionSpace&);
 
     RefPtr<WebCore::ResourceLoader> m_coreLoader;
 };
index 45c4fc7..4835d4d 100644 (file)
@@ -25,13 +25,13 @@ messages -> WebResourceLoader LegacyReceiver {
     CancelResourceLoader()
 
     // FIXME (NetworkProcess): We'll need much more granularity for response messages.
-    WillSendRequest(WebCore::ResourceRequest request, WebCore::ResourceResponse redirectResponse) -> (WebCore::ResourceRequest newRequest)
+    WillSendRequest(WebCore::ResourceRequest request, WebCore::ResourceResponse redirectResponse)
     DidReceiveResponseWithCertificateInfo(WebCore::ResourceResponse response, WebKit::PlatformCertificateInfo certificateInfo)
     DidReceiveData(CoreIPC::DataReference data, int64_t encodedDataLength)
     DidFinishResourceLoad(double finishTime)
     DidFailResourceLoad(WebCore::ResourceError error)
     
-    CanAuthenticateAgainstProtectionSpace(WebCore::ProtectionSpace protectionSpace) -> (bool response)
+    CanAuthenticateAgainstProtectionSpace(WebCore::ProtectionSpace protectionSpace)
 
     // DidReceiveResource is for when we have the entire resource data available at once, such as when the resource is cached in memory
     DidReceiveResource(WebKit::ShareableResource::Handle resource, double finishTime)