Title: [210374] trunk/Source
Revision
210374
Author
[email protected]
Date
2017-01-05 13:27:50 -0800 (Thu, 05 Jan 2017)

Log Message

[SOUP] Network process crash in WebKit::CustomProtocolManagerImpl::didFailWithError
https://bugs.webkit.org/show_bug.cgi?id=165082

Patch by Carlos Garcia Campos <[email protected]> on 2017-01-05
Reviewed by Alex Christensen.

Source/WebCore:

Simplified WebKitSoupRequestGenericClient.

* platform/network/soup/WebKitSoupRequestGeneric.cpp:
(webkitSoupRequestGenericSendAsync):
(webkitSoupRequestGenericSendFinish):
(webkitSoupRequestGenericGetRequest):
* platform/network/soup/WebKitSoupRequestGeneric.h:
* platform/network/soup/WebKitSoupRequestGenericClient.h:

Source/WebKit2:

CustomProtocolManager uses a Workqueue to receive the IPC messages since r149194. Then we added the Soup
implementation adopting that approach, but without making our implementation thread safe. The crash happens
because the CustomProtocolManager implementation is used by two threads at the same time, the main thread
because of a ping load (probably caused by an image load in the unload handler, I haven't been able to
reproduce the crash) and the work queue thread. The reasons to make CustomProtocolManager use a WorkQueue
are no longer valid because CustomProtocolManager is now only used in the network process and sync loads don't
use any nested run loop, they are just an IPC sync message. So this patch makes CustomProtocolManager a normal
message receiver again to ensure messages are handled in the main thread. It also adds the common implementation
to a new CustomProtocolManager.cpp file shared by Cocoa and Soup based ports.

* CMakeLists.txt: Add CustomProtocolManager.cpp.
* NetworkProcess/CustomProtocols/Cocoa/CustomProtocolManagerCocoa.mm:
(-[WKCustomProtocol initWithRequest:cachedResponse:client:]): Use new CustomProtocolManager API.
(-[WKCustomProtocol startLoading]): Ditto.
(-[WKCustomProtocol stopLoading]): Ditto.
(WebKit::CustomProtocolManager::registerProtocolClass): Register the NSURLProtocol class when not using the
network session.
(WebKit::CustomProtocolManager::didFailWithError): removeCustomProtocol now receives an ID.
(WebKit::CustomProtocolManager::didFinishLoading): Ditto.
* NetworkProcess/CustomProtocols/CustomProtocolManager.cpp: Added.
(WebKit::generateCustomProtocolID): Moved from CustomProtocolManagerCocoa.mm and CustomProtocolManagerSoup.cpp.
(WebKit::CustomProtocolManager::supplementName): Ditto.
(WebKit::CustomProtocolManager::CustomProtocolManager): Also removes the work queue initialization.
(WebKit::CustomProtocolManager::initialize): Copied and modernized the loop.
(WebKit::CustomProtocolManager::addCustomProtocol): Copied from CustomProtocolManagerCocoa.mm.
(WebKit::CustomProtocolManager::removeCustomProtocol): Ditto.
(WebKit::CustomProtocolManager::startLoading): Send the StartLoading message to the proxy.
(WebKit::CustomProtocolManager::stopLoading): Send the StopLoading message to the proxy.
* NetworkProcess/CustomProtocols/CustomProtocolManager.h:
* NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp: Removed.
* NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h: Removed.
* NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp: Moved the implementation from
CustomProtocolManagerImpl and updated to the new CustomProtocolManager API.
(WebKit::CustomProtocolManager::WebSoupRequestAsyncData::WebSoupRequestAsyncData):
(WebKit::CustomProtocolManager::WebSoupRequestAsyncData::~WebSoupRequestAsyncData):
(WebKit::CustomProtocolManager::registerProtocolClass):
(WebKit::CustomProtocolManager::registerScheme):
(WebKit::CustomProtocolManager::supportsScheme):
(WebKit::CustomProtocolManager::didFailWithError):
(WebKit::CustomProtocolManager::didLoadData):
(WebKit::CustomProtocolManager::didReceiveResponse):
(WebKit::CustomProtocolManager::didFinishLoading):
(WebKit::CustomProtocolManager::wasRedirectedToRequest):
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(WebKit::globalCustomProtocolManager):
(WebKit::NetworkSessionCocoa::defaultSession):
CustomProtocolManager is no longer refcounted, so just pass a pointer.
A static pointer has the same lifetime as the NetworkProcess object in the NetworkProcess,
and in the WebProcess it will remain nullptr, just like it used to.
* PlatformEfl.cmake:
* PlatformGTK.cmake:
* WebKit2.xcodeproj/project.pbxproj:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (210373 => 210374)


--- trunk/Source/WebCore/ChangeLog	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebCore/ChangeLog	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1,3 +1,19 @@
+2017-01-05  Carlos Garcia Campos  <[email protected]>
+
+        [SOUP] Network process crash in WebKit::CustomProtocolManagerImpl::didFailWithError
+        https://bugs.webkit.org/show_bug.cgi?id=165082
+
+        Reviewed by Alex Christensen.
+
+        Simplified WebKitSoupRequestGenericClient.
+
+        * platform/network/soup/WebKitSoupRequestGeneric.cpp:
+        (webkitSoupRequestGenericSendAsync):
+        (webkitSoupRequestGenericSendFinish):
+        (webkitSoupRequestGenericGetRequest):
+        * platform/network/soup/WebKitSoupRequestGeneric.h:
+        * platform/network/soup/WebKitSoupRequestGenericClient.h:
+
 2017-01-05  Chris Dumez  <[email protected]>
 
         Turn preferLowPowerWebGLRendering setting on by default

Modified: trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.cpp (210373 => 210374)


--- trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.cpp	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.cpp	2017-01-05 21:27:50 UTC (rev 210374)
@@ -50,15 +50,14 @@
 {
     WebKitSoupRequestGenericClient* client = WEBKIT_SOUP_REQUEST_GENERIC_GET_CLASS(request)->client;
     ASSERT(client);
-    client->start(g_task_new(request, cancellable, callback, userData));
+    client->startRequest(adoptGRef(g_task_new(request, cancellable, callback, userData)));
 }
 
 static GInputStream* webkitSoupRequestGenericSendFinish(SoupRequest* request, GAsyncResult* result, GError** error)
 {
     g_return_val_if_fail(g_task_is_valid(result, request), nullptr);
-    WebKitSoupRequestGenericClient* client = WEBKIT_SOUP_REQUEST_GENERIC_GET_CLASS(request)->client;
-    ASSERT(client);
-    return client->finish(G_TASK(result), error);
+    auto* inputStream = g_task_propagate_pointer(G_TASK(result), error);
+    return inputStream ? G_INPUT_STREAM(inputStream) : nullptr;
 }
 
 static goffset webkitSoupRequestGenericGetContentLength(SoupRequest* request)
@@ -100,7 +99,7 @@
     request->priv->resourceRequest = resourceRequest;
 }
 
-const ResourceRequest* webkitSoupRequestGenericGetRequest(WebKitSoupRequestGeneric* request)
+const ResourceRequest& webkitSoupRequestGenericGetRequest(WebKitSoupRequestGeneric* request)
 {
-    return &request->priv->resourceRequest;
+    return request->priv->resourceRequest;
 }

Modified: trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.h (210373 => 210374)


--- trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.h	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGeneric.h	2017-01-05 21:27:50 UTC (rev 210374)
@@ -58,7 +58,7 @@
 void webkitSoupRequestGenericSetContentLength(WebKitSoupRequestGeneric*, goffset contentLength);
 void webkitSoupRequestGenericSetContentType(WebKitSoupRequestGeneric*, const char* mimeType);
 void webkitSoupRequestGenericSetRequest(WebKitSoupRequestGeneric*, const WebCore::ResourceRequest&);
-const WebCore::ResourceRequest* webkitSoupRequestGenericGetRequest(WebKitSoupRequestGeneric*);
+const WebCore::ResourceRequest& webkitSoupRequestGenericGetRequest(WebKitSoupRequestGeneric*);
 
 G_END_DECLS
 

Modified: trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGenericClient.h (210373 => 210374)


--- trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGenericClient.h	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebCore/platform/network/soup/WebKitSoupRequestGenericClient.h	2017-01-05 21:27:50 UTC (rev 210374)
@@ -17,11 +17,10 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef WebKitSoupRequestGenericClient_h
-#define WebKitSoupRequestGenericClient_h
+#pragma once
 
-typedef struct _GError GError;
-typedef struct _GInputStream GInputStream;
+#include <wtf/glib/GRefPtr.h>
+
 typedef struct _GTask GTask;
 
 namespace WebCore {
@@ -28,10 +27,8 @@
 
 class WebKitSoupRequestGenericClient {
 public:
-    virtual void start(GTask*) = 0;
-    virtual GInputStream* finish(GTask*, GError**) = 0;
+    virtual void startRequest(GRefPtr<GTask>&&) = 0;
 };
 
 } // namespace WebCore
 
-#endif // WebKitSoupRequestGenericClient_h

Modified: trunk/Source/WebKit2/CMakeLists.txt (210373 => 210374)


--- trunk/Source/WebKit2/CMakeLists.txt	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/CMakeLists.txt	2017-01-05 21:27:50 UTC (rev 210374)
@@ -93,6 +93,8 @@
 endif ()
 
 set(NetworkProcess_COMMON_SOURCES
+    NetworkProcess/CustomProtocols/CustomProtocolManager.cpp
+
     NetworkProcess/NetworkConnectionToWebProcess.cpp
     NetworkProcess/NetworkDataTask.cpp
     NetworkProcess/NetworkDataTaskBlob.cpp

Modified: trunk/Source/WebKit2/ChangeLog (210373 => 210374)


--- trunk/Source/WebKit2/ChangeLog	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/ChangeLog	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1,3 +1,63 @@
+2017-01-05  Carlos Garcia Campos  <[email protected]>
+
+        [SOUP] Network process crash in WebKit::CustomProtocolManagerImpl::didFailWithError
+        https://bugs.webkit.org/show_bug.cgi?id=165082
+
+        Reviewed by Alex Christensen.
+
+        CustomProtocolManager uses a Workqueue to receive the IPC messages since r149194. Then we added the Soup
+        implementation adopting that approach, but without making our implementation thread safe. The crash happens
+        because the CustomProtocolManager implementation is used by two threads at the same time, the main thread
+        because of a ping load (probably caused by an image load in the unload handler, I haven't been able to
+        reproduce the crash) and the work queue thread. The reasons to make CustomProtocolManager use a WorkQueue
+        are no longer valid because CustomProtocolManager is now only used in the network process and sync loads don't
+        use any nested run loop, they are just an IPC sync message. So this patch makes CustomProtocolManager a normal
+        message receiver again to ensure messages are handled in the main thread. It also adds the common implementation
+        to a new CustomProtocolManager.cpp file shared by Cocoa and Soup based ports.
+
+        * CMakeLists.txt: Add CustomProtocolManager.cpp.
+        * NetworkProcess/CustomProtocols/Cocoa/CustomProtocolManagerCocoa.mm:
+        (-[WKCustomProtocol initWithRequest:cachedResponse:client:]): Use new CustomProtocolManager API.
+        (-[WKCustomProtocol startLoading]): Ditto.
+        (-[WKCustomProtocol stopLoading]): Ditto.
+        (WebKit::CustomProtocolManager::registerProtocolClass): Register the NSURLProtocol class when not using the
+        network session.
+        (WebKit::CustomProtocolManager::didFailWithError): removeCustomProtocol now receives an ID.
+        (WebKit::CustomProtocolManager::didFinishLoading): Ditto.
+        * NetworkProcess/CustomProtocols/CustomProtocolManager.cpp: Added.
+        (WebKit::generateCustomProtocolID): Moved from CustomProtocolManagerCocoa.mm and CustomProtocolManagerSoup.cpp.
+        (WebKit::CustomProtocolManager::supplementName): Ditto.
+        (WebKit::CustomProtocolManager::CustomProtocolManager): Also removes the work queue initialization.
+        (WebKit::CustomProtocolManager::initialize): Copied and modernized the loop.
+        (WebKit::CustomProtocolManager::addCustomProtocol): Copied from CustomProtocolManagerCocoa.mm.
+        (WebKit::CustomProtocolManager::removeCustomProtocol): Ditto.
+        (WebKit::CustomProtocolManager::startLoading): Send the StartLoading message to the proxy.
+        (WebKit::CustomProtocolManager::stopLoading): Send the StopLoading message to the proxy.
+        * NetworkProcess/CustomProtocols/CustomProtocolManager.h:
+        * NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp: Removed.
+        * NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h: Removed.
+        * NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp: Moved the implementation from
+        CustomProtocolManagerImpl and updated to the new CustomProtocolManager API.
+        (WebKit::CustomProtocolManager::WebSoupRequestAsyncData::WebSoupRequestAsyncData):
+        (WebKit::CustomProtocolManager::WebSoupRequestAsyncData::~WebSoupRequestAsyncData):
+        (WebKit::CustomProtocolManager::registerProtocolClass):
+        (WebKit::CustomProtocolManager::registerScheme):
+        (WebKit::CustomProtocolManager::supportsScheme):
+        (WebKit::CustomProtocolManager::didFailWithError):
+        (WebKit::CustomProtocolManager::didLoadData):
+        (WebKit::CustomProtocolManager::didReceiveResponse):
+        (WebKit::CustomProtocolManager::didFinishLoading):
+        (WebKit::CustomProtocolManager::wasRedirectedToRequest):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (WebKit::globalCustomProtocolManager):
+        (WebKit::NetworkSessionCocoa::defaultSession):
+        CustomProtocolManager is no longer refcounted, so just pass a pointer.
+        A static pointer has the same lifetime as the NetworkProcess object in the NetworkProcess,
+        and in the WebProcess it will remain nullptr, just like it used to.
+        * PlatformEfl.cmake:
+        * PlatformGTK.cmake:
+        * WebKit2.xcodeproj/project.pbxproj:
+
 2017-01-05  Antti Koivisto  <[email protected]>
 
         Use WTF::Function instead of std::function in network cache code

Modified: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/Cocoa/CustomProtocolManagerCocoa.mm (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/Cocoa/CustomProtocolManagerCocoa.mm	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/Cocoa/CustomProtocolManagerCocoa.mm	2017-01-05 21:27:50 UTC (rev 210374)
@@ -26,14 +26,9 @@
 #import "config.h"
 #import "CustomProtocolManager.h"
 
-#import "ChildProcess.h"
 #import "CustomProtocolManagerMessages.h"
-#import "CustomProtocolManagerProxyMessages.h"
 #import "DataReference.h"
 #import "NetworkProcess.h"
-#import "NetworkProcessCreationParameters.h"
-#import "WebCoreArgumentCoders.h"
-#import "WebProcessCreationParameters.h"
 #import <Foundation/NSURLSession.h>
 #import <WebCore/NSURLConnectionSPI.h>
 #import <WebCore/URL.h>
@@ -44,16 +39,6 @@
 
 using namespace WebKit;
 
-namespace WebKit {
-
-static uint64_t generateCustomProtocolID()
-{
-    static uint64_t uniqueCustomProtocolID = 0;
-    return ++uniqueCustomProtocolID;
-}
-
-} // namespace WebKit
-
 @interface WKCustomProtocol : NSURLProtocol {
 @private
     uint64_t _customProtocolID;
@@ -89,11 +74,11 @@
     self = [super initWithRequest:request cachedResponse:cachedResponse client:client];
     if (!self)
         return nil;
-    
-    _customProtocolID = generateCustomProtocolID();
+
+    if (auto* customProtocolManager = NetworkProcess::singleton().supplement<CustomProtocolManager>())
+        _customProtocolID = customProtocolManager->addCustomProtocol(self);
     _initializationRunLoop = CFRunLoopGetCurrent();
-    if (auto* customProtocolManager = NetworkProcess::singleton().supplement<CustomProtocolManager>())
-        customProtocolManager->addCustomProtocol(self);
+
     return self;
 }
 
@@ -105,14 +90,14 @@
 - (void)startLoading
 {
     if (auto* customProtocolManager = NetworkProcess::singleton().supplement<CustomProtocolManager>())
-        customProtocolManager->childProcess()->send(Messages::CustomProtocolManagerProxy::StartLoading(self.customProtocolID, [self request]), 0);
+        customProtocolManager->startLoading(self.customProtocolID, [self request]);
 }
 
 - (void)stopLoading
 {
     if (auto* customProtocolManager = NetworkProcess::singleton().supplement<CustomProtocolManager>()) {
-        customProtocolManager->childProcess()->send(Messages::CustomProtocolManagerProxy::StopLoading(self.customProtocolID), 0);
-        customProtocolManager->removeCustomProtocol(self);
+        customProtocolManager->stopLoading(self.customProtocolID);
+        customProtocolManager->removeCustomProtocol(self.customProtocolID);
     }
 }
 
@@ -120,47 +105,13 @@
 
 namespace WebKit {
 
-const char* CustomProtocolManager::supplementName()
+void CustomProtocolManager::registerProtocolClass()
 {
-    return "CustomProtocolManager";
-}
-
-CustomProtocolManager::CustomProtocolManager(ChildProcess* childProcess)
-    : m_childProcess(childProcess)
-    , m_messageQueue(WorkQueue::create("com.apple.WebKit.CustomProtocolManager"))
-{
-    WebCore::UTF8Encoding();
-}
-
-void CustomProtocolManager::initializeConnection(IPC::Connection* connection)
-{
-    connection->addWorkQueueMessageReceiver(Messages::CustomProtocolManager::messageReceiverName(), m_messageQueue.get(), this);
-}
-
-void CustomProtocolManager::initialize(const NetworkProcessCreationParameters& parameters)
-{
 #if !USE(NETWORK_SESSION)
     [NSURLProtocol registerClass:[WKCustomProtocol class]];
 #endif
-
-    for (size_t i = 0; i < parameters.urlSchemesRegisteredForCustomProtocols.size(); ++i)
-        registerScheme(parameters.urlSchemesRegisteredForCustomProtocols[i]);
 }
 
-void CustomProtocolManager::addCustomProtocol(WKCustomProtocol *customProtocol)
-{
-    ASSERT(customProtocol);
-    LockHolder locker(m_customProtocolMapMutex);
-    m_customProtocolMap.add(customProtocol.customProtocolID, customProtocol);
-}
-
-void CustomProtocolManager::removeCustomProtocol(WKCustomProtocol *customProtocol)
-{
-    ASSERT(customProtocol);
-    LockHolder locker(m_customProtocolMapMutex);
-    m_customProtocolMap.remove(customProtocol.customProtocolID);
-}
-
 #if USE(NETWORK_SESSION)
 void CustomProtocolManager::registerProtocolClass(NSURLSessionConfiguration *configuration)
 {
@@ -174,7 +125,7 @@
     LockHolder locker(m_registeredSchemesMutex);
     m_registeredSchemes.add(scheme);
 }
-    
+
 void CustomProtocolManager::unregisterScheme(const String& scheme)
 {
     ASSERT(!scheme.isNull());
@@ -210,7 +161,7 @@
         [[protocol client] URLProtocol:protocol.get() didFailWithError:nsError.get()];
     });
 
-    removeCustomProtocol(protocol.get());
+    removeCustomProtocol(customProtocolID);
 }
 
 void CustomProtocolManager::didLoadData(uint64_t customProtocolID, const IPC::DataReference& data)
@@ -249,7 +200,7 @@
         [[protocol client] URLProtocolDidFinishLoading:protocol.get()];
     });
 
-    removeCustomProtocol(protocol.get());
+    removeCustomProtocol(customProtocolID);
 }
 
 void CustomProtocolManager::wasRedirectedToRequest(uint64_t customProtocolID, const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& redirectResponse)

Added: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp (0 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp	                        (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp	2017-01-05 21:27:50 UTC (rev 210374)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CustomProtocolManager.h"
+
+#include "ChildProcess.h"
+#include "CustomProtocolManagerMessages.h"
+#include "CustomProtocolManagerProxyMessages.h"
+#include "NetworkProcessCreationParameters.h"
+#include "WebCoreArgumentCoders.h"
+#include <WebCore/ResourceRequest.h>
+
+namespace WebKit {
+
+static uint64_t generateCustomProtocolID()
+{
+    static uint64_t uniqueCustomProtocolID = 0;
+    return ++uniqueCustomProtocolID;
+}
+
+const char* CustomProtocolManager::supplementName()
+{
+    return "CustomProtocolManager";
+}
+
+CustomProtocolManager::CustomProtocolManager(ChildProcess* childProcess)
+    : m_childProcess(childProcess)
+{
+    m_childProcess->addMessageReceiver(Messages::CustomProtocolManager::messageReceiverName(), *this);
+}
+
+void CustomProtocolManager::initialize(const NetworkProcessCreationParameters& parameters)
+{
+    registerProtocolClass();
+
+    for (const auto& scheme : parameters.urlSchemesRegisteredForCustomProtocols)
+        registerScheme(scheme);
+}
+
+uint64_t CustomProtocolManager::addCustomProtocol(CustomProtocol&& customProtocol)
+{
+    LockHolder locker(m_customProtocolMapMutex);
+    auto customProtocolID = generateCustomProtocolID();
+    m_customProtocolMap.add(customProtocolID, WTFMove(customProtocol));
+    return customProtocolID;
+}
+
+void CustomProtocolManager::removeCustomProtocol(uint64_t customProtocolID)
+{
+    LockHolder locker(m_customProtocolMapMutex);
+    m_customProtocolMap.remove(customProtocolID);
+}
+
+void CustomProtocolManager::startLoading(uint64_t customProtocolID, const WebCore::ResourceRequest& request)
+{
+    m_childProcess->send(Messages::CustomProtocolManagerProxy::StartLoading(customProtocolID, request));
+}
+
+void CustomProtocolManager::stopLoading(uint64_t customProtocolID)
+{
+    m_childProcess->send(Messages::CustomProtocolManagerProxy::StopLoading(customProtocolID), 0);
+}
+
+} // namespace WebKit

Modified: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h	2017-01-05 21:27:50 UTC (rev 210374)
@@ -23,27 +23,30 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef CustomProtocolManager_h
-#define CustomProtocolManager_h
+#pragma once
 
-#include "Connection.h"
+#include "MessageReceiver.h"
 #include "NetworkProcessSupplement.h"
-#include <wtf/WorkQueue.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
 
 #if PLATFORM(COCOA)
-#include <wtf/HashMap.h>
-#include <wtf/HashSet.h>
 #include <wtf/RetainPtr.h>
-#include <wtf/Threading.h>
-#include <wtf/text/StringHash.h>
 OBJC_CLASS NSURLSessionConfiguration;
 OBJC_CLASS WKCustomProtocol;
-#else
-#include "CustomProtocolManagerImpl.h"
 #endif
 
+#if USE(SOUP)
+#include <wtf/glib/GRefPtr.h>
 
+typedef struct _GCancellable GCancellable;
+typedef struct _GInputStream GInputStream;
+typedef struct _GTask GTask;
+typedef struct _WebKitSoupRequestGeneric WebKitSoupRequestGeneric;
+#endif
+
 namespace IPC {
 class DataReference;
 } // namespace IPC
@@ -59,7 +62,7 @@
 class ChildProcess;
 struct NetworkProcessCreationParameters;
 
-class CustomProtocolManager : public NetworkProcessSupplement, public IPC::Connection::WorkQueueMessageReceiver {
+class CustomProtocolManager : public NetworkProcessSupplement, public IPC::MessageReceiver {
     WTF_MAKE_NONCOPYABLE(CustomProtocolManager);
 public:
     explicit CustomProtocolManager(ChildProcess*);
@@ -66,24 +69,36 @@
 
     static const char* supplementName();
 
-    ChildProcess* childProcess() const { return m_childProcess; }
-
     void registerScheme(const String&);
     void unregisterScheme(const String&);
     bool supportsScheme(const String&);
-    
+
 #if PLATFORM(COCOA)
-    void addCustomProtocol(WKCustomProtocol *);
-    void removeCustomProtocol(WKCustomProtocol *);
-#if USE(NETWORK_SESSION)
-    void registerProtocolClass(NSURLSessionConfiguration *);
+    typedef RetainPtr<WKCustomProtocol> CustomProtocol;
 #endif
+#if USE(SOUP)
+    struct WebSoupRequestAsyncData {
+        WebSoupRequestAsyncData(GRefPtr<GTask>&&, WebKitSoupRequestGeneric*);
+        ~WebSoupRequestAsyncData();
+
+        GRefPtr<GTask> task;
+        WebKitSoupRequestGeneric* request;
+        GRefPtr<GCancellable> cancellable;
+        GRefPtr<GInputStream> stream;
+    };
+    typedef std::unique_ptr<WebSoupRequestAsyncData> CustomProtocol;
 #endif
 
+    uint64_t addCustomProtocol(CustomProtocol&&);
+    void removeCustomProtocol(uint64_t customProtocolID);
+    void startLoading(uint64_t customProtocolID, const WebCore::ResourceRequest&);
+    void stopLoading(uint64_t customProtocolID);
+
+#if PLATFORM(COCOA) && USE(NETWORK_SESSION)
+    void registerProtocolClass(NSURLSessionConfiguration*);
+#endif
+
 private:
-    // ChildProcessSupplement
-    void initializeConnection(IPC::Connection*) override;
-
     // NetworkProcessSupplement
     void initialize(const NetworkProcessCreationParameters&) override;
 
@@ -96,26 +111,27 @@
     void didFinishLoading(uint64_t customProtocolID);
     void wasRedirectedToRequest(uint64_t customProtocolID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse);
 
+    void registerProtocolClass();
+
     ChildProcess* m_childProcess;
-    Ref<WorkQueue> m_messageQueue;
 
+    typedef HashMap<uint64_t, CustomProtocol> CustomProtocolMap;
+    CustomProtocolMap m_customProtocolMap;
+    Lock m_customProtocolMapMutex;
+
 #if PLATFORM(COCOA)
     HashSet<String, ASCIICaseInsensitiveHash> m_registeredSchemes;
     Lock m_registeredSchemesMutex;
 
-    typedef HashMap<uint64_t, RetainPtr<WKCustomProtocol>> CustomProtocolMap;
-    CustomProtocolMap m_customProtocolMap;
-    Lock m_customProtocolMapMutex;
-    
     // WKCustomProtocol objects can be removed from the m_customProtocolMap from multiple threads.
     // We return a RetainPtr here because it is unsafe to return a raw pointer since the object might immediately be destroyed from a different thread.
     RetainPtr<WKCustomProtocol> protocolForID(uint64_t customProtocolID);
-#else
-    // FIXME: Move mac specific code to CustomProtocolManagerImpl.
-    std::unique_ptr<CustomProtocolManagerImpl> m_impl;
 #endif
+
+#if USE(SOUP)
+    GRefPtr<GPtrArray> m_registeredSchemes;
+#endif
 };
 
 } // namespace WebKit
 
-#endif // CustomProtocolManager_h

Deleted: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "CustomProtocolManagerImpl.h"
-
-#include "ChildProcess.h"
-#include "CustomProtocolManagerProxyMessages.h"
-#include "DataReference.h"
-#include "WebCoreArgumentCoders.h"
-#include "WebKitSoupRequestInputStream.h"
-#include <WebCore/ResourceError.h>
-#include <WebCore/ResourceRequest.h>
-#include <WebCore/ResourceResponse.h>
-#include <WebCore/SoupNetworkSession.h>
-#include <WebCore/WebKitSoupRequestGeneric.h>
-
-namespace WebKit {
-
-static uint64_t generateCustomProtocolID()
-{
-    static uint64_t uniqueCustomProtocolID = 0;
-    return ++uniqueCustomProtocolID;
-}
-
-struct WebSoupRequestAsyncData {
-    WebSoupRequestAsyncData(GTask* task, WebKitSoupRequestGeneric* requestGeneric)
-        : task(task)
-        , request(requestGeneric)
-        , cancellable(g_task_get_cancellable(task))
-    {
-        // If the struct contains a null request, it is because the request failed.
-        g_object_add_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
-    }
-
-    ~WebSoupRequestAsyncData()
-    {
-        if (request)
-            g_object_remove_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
-    }
-
-    bool requestFailed()
-    {
-        return g_cancellable_is_cancelled(cancellable.get()) || !request;
-    }
-
-    GRefPtr<GTask> releaseTask()
-    {
-        GTask* returnValue = task;
-        task = nullptr;
-        return adoptGRef(returnValue);
-    }
-
-    GTask* task;
-    WebKitSoupRequestGeneric* request;
-    GRefPtr<GCancellable> cancellable;
-    GRefPtr<GInputStream> stream;
-};
-
-CustomProtocolManagerImpl::CustomProtocolManagerImpl(ChildProcess* childProcess)
-    : m_childProcess(childProcess)
-    , m_schemes(adoptGRef(g_ptr_array_new_with_free_func(g_free)))
-{
-}
-
-CustomProtocolManagerImpl::~CustomProtocolManagerImpl()
-{
-}
-
-void CustomProtocolManagerImpl::registerScheme(const String& scheme)
-{
-    if (m_schemes->len)
-        g_ptr_array_remove_index_fast(m_schemes.get(), m_schemes->len - 1);
-    g_ptr_array_add(m_schemes.get(), g_strdup(scheme.utf8().data()));
-    g_ptr_array_add(m_schemes.get(), nullptr);
-
-    SoupSession* session = WebCore::SoupNetworkSession::defaultSession().soupSession();
-    SoupRequestClass* genericRequestClass = static_cast<SoupRequestClass*>(g_type_class_ref(WEBKIT_TYPE_SOUP_REQUEST_GENERIC));
-    genericRequestClass->schemes = const_cast<const char**>(reinterpret_cast<char**>(m_schemes->pdata));
-    static_cast<WebKitSoupRequestGenericClass*>(g_type_class_ref(WEBKIT_TYPE_SOUP_REQUEST_GENERIC))->client = this;
-    soup_session_add_feature_by_type(session, WEBKIT_TYPE_SOUP_REQUEST_GENERIC);
-}
-
-bool CustomProtocolManagerImpl::supportsScheme(const String& scheme)
-{
-    if (scheme.isNull())
-        return false;
-
-    CString cScheme = scheme.utf8();
-    for (unsigned i = 0; i < m_schemes->len; ++i) {
-        if (cScheme == static_cast<char*>(g_ptr_array_index(m_schemes.get(), i)))
-            return true;
-    }
-
-    return false;
-}
-
-void CustomProtocolManagerImpl::didFailWithError(uint64_t customProtocolID, const WebCore::ResourceError& error)
-{
-    WebSoupRequestAsyncData* data = ""
-    ASSERT(data);
-
-    // Either we haven't started reading the stream yet, in which case we need to complete the
-    // task first, or we failed reading it and the task was already completed by didLoadData().
-    ASSERT(!data->stream || !data->task);
-
-    if (!data->stream) {
-        GRefPtr<GTask> task = data->releaseTask();
-        ASSERT(task.get());
-        g_task_return_new_error(task.get(), g_quark_from_string(error.domain().utf8().data()),
-            error.errorCode(), "%s", error.localizedDescription().utf8().data());
-    } else
-        webkitSoupRequestInputStreamDidFailWithError(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), error);
-
-    m_customProtocolMap.remove(customProtocolID);
-}
-
-void CustomProtocolManagerImpl::didLoadData(uint64_t customProtocolID, const IPC::DataReference& dataReference)
-{
-    WebSoupRequestAsyncData* data = ""
-    // The data might have been removed from the request map if a previous chunk failed
-    // and a new message was sent by the UI process before being notified about the failure.
-    if (!data)
-        return;
-
-    if (!data->stream) {
-        GRefPtr<GTask> task = data->releaseTask();
-        ASSERT(task.get());
-
-        goffset soupContentLength = soup_request_get_content_length(SOUP_REQUEST(g_task_get_source_object(task.get())));
-        uint64_t contentLength = soupContentLength == -1 ? 0 : static_cast<uint64_t>(soupContentLength);
-        if (!dataReference.size()) {
-            // Empty reply, just create and empty GMemoryInputStream.
-            data->stream = g_memory_input_stream_new();
-        } else if (dataReference.size() == contentLength) {
-            // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
-            data->stream = g_memory_input_stream_new_from_data(g_memdup(dataReference.data(), dataReference.size()), contentLength, g_free);
-        } else {
-            // We expect more data chunks from the UI process.
-            data->stream = webkitSoupRequestInputStreamNew(contentLength);
-            webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), dataReference.data(), dataReference.size());
-        }
-        g_task_return_pointer(task.get(), data->stream.get(), g_object_unref);
-        return;
-    }
-
-    if (data->requestFailed()) {
-        // ResourceRequest failed or it was cancelled. It doesn't matter here the error or if it was cancelled,
-        // because that's already handled by the resource handle client, we just want to notify the UI process
-        // to stop reading data from the user input stream. If UI process already sent all the data we simply
-        // finish silently.
-        if (!webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
-            m_childProcess->send(Messages::CustomProtocolManagerProxy::StopLoading(customProtocolID), 0);
-
-        return;
-    }
-
-    webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), dataReference.data(), dataReference.size());
-}
-
-void CustomProtocolManagerImpl::didReceiveResponse(uint64_t customProtocolID, const WebCore::ResourceResponse& response)
-{
-    WebSoupRequestAsyncData* data = ""
-    // The data might have been removed from the request map if an error happened even before this point.
-    if (!data)
-        return;
-
-    ASSERT(data->task);
-
-    WebKitSoupRequestGeneric* request = WEBKIT_SOUP_REQUEST_GENERIC(g_task_get_source_object(data->task));
-    webkitSoupRequestGenericSetContentLength(request, response.expectedContentLength() ? response.expectedContentLength() : -1);
-    webkitSoupRequestGenericSetContentType(request, !response.mimeType().isEmpty() ? response.mimeType().utf8().data() : 0);
-}
-
-void CustomProtocolManagerImpl::didFinishLoading(uint64_t customProtocolID)
-{
-    ASSERT(m_customProtocolMap.contains(customProtocolID));
-    m_customProtocolMap.remove(customProtocolID);
-}
-
-void CustomProtocolManagerImpl::start(GTask* task)
-{
-    uint64_t customProtocolID = generateCustomProtocolID();
-    WebKitSoupRequestGeneric* request = WEBKIT_SOUP_REQUEST_GENERIC(g_task_get_source_object(task));
-    m_customProtocolMap.set(customProtocolID, std::make_unique<WebSoupRequestAsyncData>(task, request));
-
-    m_childProcess->send(Messages::CustomProtocolManagerProxy::StartLoading(customProtocolID, *webkitSoupRequestGenericGetRequest(request)), 0);
-}
-
-GInputStream* CustomProtocolManagerImpl::finish(GTask* task, GError** error)
-{
-    gpointer inputStream = g_task_propagate_pointer(task, error);
-    return inputStream ? G_INPUT_STREAM(inputStream) : 0;
-}
-
-} // namespace WebKit

Deleted: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef CustomProtocolManagerImpl_h
-#define CustomProtocolManagerImpl_h
-
-#include <WebCore/WebKitSoupRequestGenericClient.h>
-#include <wtf/HashMap.h>
-#include <wtf/glib/GRefPtr.h>
-#include <wtf/text/WTFString.h>
-
-namespace IPC {
-class DataReference;
-} // namespace IPC
-
-namespace WebCore {
-class ResourceError;
-class ResourceResponse;
-} // namespace WebCore
-
-namespace WebKit {
-
-class ChildProcess;
-struct WebSoupRequestAsyncData;
-
-class CustomProtocolManagerImpl : public WebCore::WebKitSoupRequestGenericClient {
-    WTF_MAKE_NONCOPYABLE(CustomProtocolManagerImpl);
-public:
-    explicit CustomProtocolManagerImpl(ChildProcess*);
-    ~CustomProtocolManagerImpl();
-
-    void registerScheme(const String&);
-    bool supportsScheme(const String&);
-
-    void didFailWithError(uint64_t customProtocolID, const WebCore::ResourceError&);
-    void didLoadData(uint64_t customProtocolID, const IPC::DataReference&);
-    void didReceiveResponse(uint64_t customProtocolID, const WebCore::ResourceResponse&);
-    void didFinishLoading(uint64_t customProtocolID);
-
-private:
-    void start(GTask*) final;
-    GInputStream* finish(GTask*, GError**) final;
-
-    ChildProcess* m_childProcess;
-    GRefPtr<GPtrArray> m_schemes;
-    HashMap<uint64_t, std::unique_ptr<WebSoupRequestAsyncData>> m_customProtocolMap;
-};
-
-} // namespace WebKit
-
-#endif // CustomProtocolManagerImpl_h

Modified: trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp	2017-01-05 21:27:50 UTC (rev 210374)
@@ -20,41 +20,77 @@
 #include "config.h"
 #include "CustomProtocolManager.h"
 
-#include "ChildProcess.h"
-#include "CustomProtocolManagerImpl.h"
 #include "CustomProtocolManagerMessages.h"
-#include "NetworkProcessCreationParameters.h"
-#include "WebProcessCreationParameters.h"
+#include "DataReference.h"
+#include "NetworkProcess.h"
+#include "WebKitSoupRequestInputStream.h"
 #include <WebCore/NotImplemented.h>
+#include <WebCore/ResourceError.h>
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/ResourceResponse.h>
+#include <WebCore/SoupNetworkSession.h>
+#include <WebCore/WebKitSoupRequestGeneric.h>
+#include <wtf/NeverDestroyed.h>
 
+using namespace WebCore;
+
 namespace WebKit {
 
-const char* CustomProtocolManager::supplementName()
-{
-    return "CustomProtocolManager";
-}
 
-CustomProtocolManager::CustomProtocolManager(ChildProcess* childProcess)
-    : m_childProcess(childProcess)
-    , m_messageQueue(WorkQueue::create("com.apple.WebKit.CustomProtocolManager"))
-    , m_impl(std::make_unique<CustomProtocolManagerImpl>(childProcess))
+CustomProtocolManager::WebSoupRequestAsyncData::WebSoupRequestAsyncData(GRefPtr<GTask>&& requestTask, WebKitSoupRequestGeneric* requestGeneric)
+    : task(WTFMove(requestTask))
+    , request(requestGeneric)
+    , cancellable(g_task_get_cancellable(task.get()))
 {
+    // If the struct contains a null request, it is because the request failed.
+    g_object_add_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
 }
 
-void CustomProtocolManager::initializeConnection(IPC::Connection* connection)
+CustomProtocolManager::WebSoupRequestAsyncData::~WebSoupRequestAsyncData()
 {
-    connection->addWorkQueueMessageReceiver(Messages::CustomProtocolManager::messageReceiverName(), m_messageQueue.get(), this);
+    if (request)
+        g_object_remove_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
 }
 
-void CustomProtocolManager::initialize(const NetworkProcessCreationParameters& parameters)
+class CustomProtocolRequestClient final : public WebKitSoupRequestGenericClient {
+public:
+    static CustomProtocolRequestClient& singleton()
+    {
+        static NeverDestroyed<CustomProtocolRequestClient> client;
+        return client;
+    }
+
+private:
+    void startRequest(GRefPtr<GTask>&& task) override
+    {
+        WebKitSoupRequestGeneric* request = WEBKIT_SOUP_REQUEST_GENERIC(g_task_get_source_object(task.get()));
+        auto* customProtocolManager = NetworkProcess::singleton().supplement<CustomProtocolManager>();
+        if (!customProtocolManager)
+            return;
+
+        auto customProtocolID = customProtocolManager->addCustomProtocol(std::make_unique<CustomProtocolManager::WebSoupRequestAsyncData>(WTFMove(task), request));
+        customProtocolManager->startLoading(customProtocolID, webkitSoupRequestGenericGetRequest(request));
+    }
+};
+
+void CustomProtocolManager::registerProtocolClass()
 {
-    for (size_t i = 0; i < parameters.urlSchemesRegisteredForCustomProtocols.size(); ++i)
-        registerScheme(parameters.urlSchemesRegisteredForCustomProtocols[i]);
+    static_cast<WebKitSoupRequestGenericClass*>(g_type_class_ref(WEBKIT_TYPE_SOUP_REQUEST_GENERIC))->client = &CustomProtocolRequestClient::singleton();
 }
 
 void CustomProtocolManager::registerScheme(const String& scheme)
 {
-    m_impl->registerScheme(scheme);
+    if (!m_registeredSchemes)
+        m_registeredSchemes = adoptGRef(g_ptr_array_new_with_free_func(g_free));
+
+    if (m_registeredSchemes->len)
+        g_ptr_array_remove_index_fast(m_registeredSchemes.get(), m_registeredSchemes->len - 1);
+    g_ptr_array_add(m_registeredSchemes.get(), g_strdup(scheme.utf8().data()));
+    g_ptr_array_add(m_registeredSchemes.get(), nullptr);
+
+    auto* genericRequestClass = static_cast<SoupRequestClass*>(g_type_class_ref(WEBKIT_TYPE_SOUP_REQUEST_GENERIC));
+    genericRequestClass->schemes = const_cast<const char**>(reinterpret_cast<char**>(m_registeredSchemes->pdata));
+    soup_session_add_feature_by_type(SoupNetworkSession::defaultSession().soupSession(), WEBKIT_TYPE_SOUP_REQUEST_GENERIC);
 }
 
 void CustomProtocolManager::unregisterScheme(const String&)
@@ -64,30 +100,102 @@
 
 bool CustomProtocolManager::supportsScheme(const String& scheme)
 {
-    return m_impl->supportsScheme(scheme);
+    if (scheme.isNull())
+        return false;
+
+    CString cScheme = scheme.utf8();
+    for (unsigned i = 0; i < m_registeredSchemes->len; ++i) {
+        if (cScheme == static_cast<char*>(g_ptr_array_index(m_registeredSchemes.get(), i)))
+            return true;
+    }
+
+    return false;
 }
 
-void CustomProtocolManager::didFailWithError(uint64_t customProtocolID, const WebCore::ResourceError& error)
+void CustomProtocolManager::didFailWithError(uint64_t customProtocolID, const ResourceError& error)
 {
-    m_impl->didFailWithError(customProtocolID, error);
+    auto* data = ""
+    ASSERT(data);
+
+    // Either we haven't started reading the stream yet, in which case we need to complete the
+    // task first, or we failed reading it and the task was already completed by didLoadData().
+    ASSERT(!data->stream || !data->task);
+
+    if (!data->stream) {
+        GRefPtr<GTask> task = std::exchange(data->task, nullptr);
+        ASSERT(task.get());
+        g_task_return_new_error(task.get(), g_quark_from_string(error.domain().utf8().data()),
+            error.errorCode(), "%s", error.localizedDescription().utf8().data());
+    } else
+        webkitSoupRequestInputStreamDidFailWithError(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), error);
+
+    removeCustomProtocol(customProtocolID);
 }
 
 void CustomProtocolManager::didLoadData(uint64_t customProtocolID, const IPC::DataReference& dataReference)
 {
-    m_impl->didLoadData(customProtocolID, dataReference);
+    auto* data = ""
+    // The data might have been removed from the request map if a previous chunk failed
+    // and a new message was sent by the UI process before being notified about the failure.
+    if (!data)
+        return;
+
+    if (!data->stream) {
+        GRefPtr<GTask> task = std::exchange(data->task, nullptr);
+        ASSERT(task.get());
+
+        goffset soupContentLength = soup_request_get_content_length(SOUP_REQUEST(g_task_get_source_object(task.get())));
+        uint64_t contentLength = soupContentLength == -1 ? 0 : static_cast<uint64_t>(soupContentLength);
+        if (!dataReference.size()) {
+            // Empty reply, just create and empty GMemoryInputStream.
+            data->stream = g_memory_input_stream_new();
+        } else if (dataReference.size() == contentLength) {
+            // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
+            data->stream = g_memory_input_stream_new_from_data(g_memdup(dataReference.data(), dataReference.size()), contentLength, g_free);
+        } else {
+            // We expect more data chunks from the UI process.
+            data->stream = webkitSoupRequestInputStreamNew(contentLength);
+            webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), dataReference.data(), dataReference.size());
+        }
+        g_task_return_pointer(task.get(), data->stream.get(), g_object_unref);
+        return;
+    }
+
+    if (g_cancellable_is_cancelled(data->cancellable.get()) || !data->request) {
+        // ResourceRequest failed or it was cancelled. It doesn't matter here the error or if it was cancelled,
+        // because that's already handled by the resource handle client, we just want to notify the UI process
+        // to stop reading data from the user input stream. If UI process already sent all the data we simply
+        // finish silently.
+        if (!webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
+            stopLoading(customProtocolID);
+
+        return;
+    }
+
+    webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), dataReference.data(), dataReference.size());
 }
 
-void CustomProtocolManager::didReceiveResponse(uint64_t customProtocolID, const WebCore::ResourceResponse& response, uint32_t)
+void CustomProtocolManager::didReceiveResponse(uint64_t customProtocolID, const ResourceResponse& response, uint32_t)
 {
-    m_impl->didReceiveResponse(customProtocolID, response);
+    auto* data = ""
+    // The data might have been removed from the request map if an error happened even before this point.
+    if (!data)
+        return;
+
+    ASSERT(data->task);
+
+    WebKitSoupRequestGeneric* request = WEBKIT_SOUP_REQUEST_GENERIC(g_task_get_source_object(data->task.get()));
+    webkitSoupRequestGenericSetContentLength(request, response.expectedContentLength() ? response.expectedContentLength() : -1);
+    webkitSoupRequestGenericSetContentType(request, !response.mimeType().isEmpty() ? response.mimeType().utf8().data() : 0);
 }
 
 void CustomProtocolManager::didFinishLoading(uint64_t customProtocolID)
 {
-    m_impl->didFinishLoading(customProtocolID);
+    ASSERT(m_customProtocolMap.contains(customProtocolID));
+    removeCustomProtocol(customProtocolID);
 }
 
-void CustomProtocolManager::wasRedirectedToRequest(uint64_t, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&)
+void CustomProtocolManager::wasRedirectedToRequest(uint64_t, const ResourceRequest&, const ResourceResponse&)
 {
     notImplemented();
 }

Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (210373 => 210374)


--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2017-01-05 21:27:50 UTC (rev 210374)
@@ -320,10 +320,10 @@
     return [NSURLSessionConfiguration defaultSessionConfiguration];
 }
 
-static RefPtr<CustomProtocolManager>& globalCustomProtocolManager()
+static CustomProtocolManager*& globalCustomProtocolManager()
 {
-    static NeverDestroyed<RefPtr<CustomProtocolManager>> customProtocolManager;
-    return customProtocolManager.get();
+    static CustomProtocolManager* customProtocolManager { nullptr };
+    return customProtocolManager;
 }
 
 static RetainPtr<CFDataRef>& globalSourceApplicationAuditTokenData()
@@ -396,7 +396,7 @@
 NetworkSession& NetworkSessionCocoa::defaultSession()
 {
     ASSERT(isMainThread());
-    static NetworkSession* session = &NetworkSessionCocoa::create(WebCore::SessionID::defaultSessionID(), globalCustomProtocolManager().get()).leakRef();
+    static NetworkSession* session = &NetworkSessionCocoa::create(WebCore::SessionID::defaultSessionID(), globalCustomProtocolManager()).leakRef();
     return *session;
 }
 

Modified: trunk/Source/WebKit2/PlatformEfl.cmake (210373 => 210374)


--- trunk/Source/WebKit2/PlatformEfl.cmake	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/PlatformEfl.cmake	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1,7 +1,6 @@
 list(APPEND WebKit2_SOURCES
     DatabaseProcess/efl/DatabaseProcessMainEfl.cpp
 
-    NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp
     NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp
 
     NetworkProcess/Downloads/efl/DownloadSoupErrorsEfl.cpp

Modified: trunk/Source/WebKit2/PlatformGTK.cmake (210373 => 210374)


--- trunk/Source/WebKit2/PlatformGTK.cmake	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/PlatformGTK.cmake	2017-01-05 21:27:50 UTC (rev 210374)
@@ -28,7 +28,6 @@
 list(APPEND WebKit2_SOURCES
     DatabaseProcess/gtk/DatabaseProcessMainGtk.cpp
 
-    NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp
     NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp
 
     NetworkProcess/Downloads/gtk/DownloadSoupErrorsGtk.cpp

Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (210373 => 210374)


--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-01-05 21:03:12 UTC (rev 210373)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-01-05 21:27:50 UTC (rev 210374)
@@ -1108,6 +1108,7 @@
 		5CBC9B8D1C65279C00A8FDCF /* NetworkDataTaskCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CBC9B8B1C65257300A8FDCF /* NetworkDataTaskCocoa.mm */; };
 		5CBC9B8E1C652CA000A8FDCF /* NetworkDataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CBC9B891C6524A500A8FDCF /* NetworkDataTask.h */; };
 		5CE85B201C88E64B0070BFCE /* PingLoad.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE85B1F1C88E6430070BFCE /* PingLoad.h */; };
+		5CFECB041E1ED1CC00F88504 /* CustomProtocolManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CFECB031E1ED1C800F88504 /* CustomProtocolManager.cpp */; };
 		6501BD1A12F1243400E9F248 /* WKBundleInspector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65B86F1712F11D7B00B7DD8A /* WKBundleInspector.cpp */; };
 		659C551E130006410025C0C2 /* InjectedBundlePageResourceLoadClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6546A82913000164000CEB1C /* InjectedBundlePageResourceLoadClient.cpp */; };
 		65B86F1E12F11DE300B7DD8A /* WKBundleInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B86F1812F11D7B00B7DD8A /* WKBundleInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3245,6 +3246,7 @@
 		5CBC9B891C6524A500A8FDCF /* NetworkDataTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkDataTask.h; path = NetworkProcess/NetworkDataTask.h; sourceTree = "<group>"; };
 		5CBC9B8B1C65257300A8FDCF /* NetworkDataTaskCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkDataTaskCocoa.mm; path = NetworkProcess/cocoa/NetworkDataTaskCocoa.mm; sourceTree = "<group>"; };
 		5CE85B1F1C88E6430070BFCE /* PingLoad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingLoad.h; path = NetworkProcess/PingLoad.h; sourceTree = "<group>"; };
+		5CFECB031E1ED1C800F88504 /* CustomProtocolManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomProtocolManager.cpp; path = NetworkProcess/CustomProtocols/CustomProtocolManager.cpp; sourceTree = "<group>"; };
 		5D442A5516D5856700AC3331 /* PluginService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PluginService.entitlements; sourceTree = "<group>"; };
 		5DAD73F1116FF90C00EE5396 /* BaseTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = BaseTarget.xcconfig; sourceTree = "<group>"; };
 		6546A82913000164000CEB1C /* InjectedBundlePageResourceLoadClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageResourceLoadClient.cpp; sourceTree = "<group>"; };
@@ -5921,6 +5923,7 @@
 		5C1426F21C23F82D00D41183 /* CustomProtocols */ = {
 			isa = PBXGroup;
 			children = (
+				5CFECB031E1ED1C800F88504 /* CustomProtocolManager.cpp */,
 				5C14271A1C23F8BF00D41183 /* Cocoa */,
 				5C1427141C23F8B000D41183 /* CustomProtocolManager.h */,
 				5C1427151C23F8B000D41183 /* CustomProtocolManager.messages.in */,
@@ -9490,6 +9493,7 @@
 				1A043977124D034800FFBFB5 /* PluginProcess.cpp in Sources */,
 				1A0EC907124C0AB8007EF4A5 /* PluginProcessConnection.cpp in Sources */,
 				1A0EC910124C0AF5007EF4A5 /* PluginProcessConnectionManager.cpp in Sources */,
+				5CFECB041E1ED1CC00F88504 /* CustomProtocolManager.cpp in Sources */,
 				1A7865B916CAC71500ACE83A /* PluginProcessConnectionManagerMessageReceiver.cpp in Sources */,
 				1A2BB6D014117B4D000F35D4 /* PluginProcessConnectionMessageReceiver.cpp in Sources */,
 				1A2D90D31281C966001EB962 /* PluginProcessCreationParameters.cpp in Sources */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to