summaryrefslogtreecommitdiff
path: root/Source/WebKit2/NetworkProcess/CustomProtocols
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/NetworkProcess/CustomProtocols
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebKit2/NetworkProcess/CustomProtocols')
-rw-r--r--Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp88
-rw-r--r--Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h137
-rw-r--r--Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in32
-rw-r--r--Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp209
4 files changed, 466 insertions, 0 deletions
diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp
new file mode 100644
index 000000000..df33db9fb
--- /dev/null
+++ b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.cpp
@@ -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
diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h
new file mode 100644
index 000000000..95937ba10
--- /dev/null
+++ b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h
@@ -0,0 +1,137 @@
+/*
+ * 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
+ * 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.
+ */
+
+#pragma once
+
+#include "MessageReceiver.h"
+#include "NetworkProcessSupplement.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(COCOA)
+#include <wtf/RetainPtr.h>
+OBJC_CLASS NSURLSessionConfiguration;
+OBJC_CLASS WKCustomProtocol;
+#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
+
+namespace WebCore {
+class ResourceError;
+class ResourceRequest;
+class ResourceResponse;
+} // namespace WebCore
+
+namespace WebKit {
+
+class ChildProcess;
+struct NetworkProcessCreationParameters;
+
+class CustomProtocolManager : public NetworkProcessSupplement, public IPC::MessageReceiver {
+ WTF_MAKE_NONCOPYABLE(CustomProtocolManager);
+public:
+ explicit CustomProtocolManager(ChildProcess*);
+
+ static const char* supplementName();
+
+ void registerScheme(const String&);
+ void unregisterScheme(const String&);
+ bool supportsScheme(const String&);
+
+#if PLATFORM(COCOA)
+ 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:
+ // NetworkProcessSupplement
+ void initialize(const NetworkProcessCreationParameters&) override;
+
+ // IPC::MessageReceiver
+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
+
+ void didFailWithError(uint64_t customProtocolID, const WebCore::ResourceError&);
+ void didLoadData(uint64_t customProtocolID, const IPC::DataReference&);
+ void didReceiveResponse(uint64_t customProtocolID, const WebCore::ResourceResponse&, uint32_t cacheStoragePolicy);
+ void didFinishLoading(uint64_t customProtocolID);
+ void wasRedirectedToRequest(uint64_t customProtocolID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse);
+
+ void registerProtocolClass();
+
+ ChildProcess* m_childProcess;
+
+ typedef HashMap<uint64_t, CustomProtocol> CustomProtocolMap;
+ CustomProtocolMap m_customProtocolMap;
+ Lock m_customProtocolMapMutex;
+
+#if PLATFORM(COCOA)
+ HashSet<String, ASCIICaseInsensitiveHash> m_registeredSchemes;
+ Lock m_registeredSchemesMutex;
+
+ // 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);
+#endif
+
+#if USE(SOUP)
+ GRefPtr<GPtrArray> m_registeredSchemes;
+#endif
+};
+
+} // namespace WebKit
+
diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in
new file mode 100644
index 000000000..0f55eceb1
--- /dev/null
+++ b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 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 -> CustomProtocolManager {
+ DidFailWithError(uint64_t customProtocolID, WebCore::ResourceError error)
+ DidLoadData(uint64_t customProtocolID, IPC::DataReference data)
+ DidReceiveResponse(uint64_t customProtocolID, WebCore::ResourceResponse response, uint32_t cacheStoragePolicy)
+ DidFinishLoading(uint64_t customProtocolID)
+ WasRedirectedToRequest(uint64_t customProtocolID, WebCore::ResourceRequest request, WebCore::ResourceResponse redirectResponse);
+
+ RegisterScheme(String name)
+ UnregisterScheme(String name)
+}
diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp b/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp
new file mode 100644
index 000000000..43a03b8cb
--- /dev/null
+++ b/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2013 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 "CustomProtocolManager.h"
+
+#include "CustomProtocolManagerMessages.h"
+#include "DataReference.h"
+#include "NetworkProcess.h"
+#include "WebKitSoupRequestInputStream.h"
+#include <WebCore/NetworkStorageSession.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 {
+
+
+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));
+}
+
+CustomProtocolManager::WebSoupRequestAsyncData::~WebSoupRequestAsyncData()
+{
+ if (request)
+ g_object_remove_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
+}
+
+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()
+{
+ static_cast<WebKitSoupRequestGenericClass*>(g_type_class_ref(WEBKIT_TYPE_SOUP_REQUEST_GENERIC))->client = &CustomProtocolRequestClient::singleton();
+ SoupNetworkSession::setCustomProtocolRequestType(WEBKIT_TYPE_SOUP_REQUEST_GENERIC);
+}
+
+void CustomProtocolManager::registerScheme(const String& 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_peek(WEBKIT_TYPE_SOUP_REQUEST_GENERIC));
+ ASSERT(genericRequestClass);
+ genericRequestClass->schemes = const_cast<const char**>(reinterpret_cast<char**>(m_registeredSchemes->pdata));
+ NetworkStorageSession::forEach([](const WebCore::NetworkStorageSession& session) {
+ if (auto* soupSession = session.soupNetworkSession())
+ soupSession->setupCustomProtocols();
+ });
+}
+
+void CustomProtocolManager::unregisterScheme(const String&)
+{
+ notImplemented();
+}
+
+bool CustomProtocolManager::supportsScheme(const String& 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 ResourceError& error)
+{
+ auto* data = m_customProtocolMap.get(customProtocolID);
+ 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)
+{
+ auto* data = m_customProtocolMap.get(customProtocolID);
+ // 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 ResourceResponse& response, uint32_t)
+{
+ auto* data = m_customProtocolMap.get(customProtocolID);
+ // 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)
+{
+ ASSERT(m_customProtocolMap.contains(customProtocolID));
+ removeCustomProtocol(customProtocolID);
+}
+
+void CustomProtocolManager::wasRedirectedToRequest(uint64_t, const ResourceRequest&, const ResourceResponse&)
+{
+ notImplemented();
+}
+
+} // namespace WebKit