diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
| commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
| tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebKit2/NetworkProcess | |
| parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
| download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz | |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebKit2/NetworkProcess')
87 files changed, 1766 insertions, 10943 deletions
diff --git a/Source/WebKit2/NetworkProcess/AsynchronousNetworkLoaderClient.cpp b/Source/WebKit2/NetworkProcess/AsynchronousNetworkLoaderClient.cpp new file mode 100644 index 000000000..3cb5cb435 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/AsynchronousNetworkLoaderClient.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AsynchronousNetworkLoaderClient.h" + +#include "DataReference.h" +#include "NetworkResourceLoader.h" +#include "WebCoreArgumentCoders.h" +#include "WebResourceLoaderMessages.h" +#include <WebCore/CertificateInfo.h> +#include <WebCore/ResourceError.h> +#include <WebCore/SharedBuffer.h> +#include <wtf/CurrentTime.h> + +#if ENABLE(NETWORK_PROCESS) + +using namespace WebCore; + +namespace WebKit { + +AsynchronousNetworkLoaderClient::AsynchronousNetworkLoaderClient() +{ +} + +void AsynchronousNetworkLoaderClient::willSendRequest(NetworkResourceLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse) +{ + // 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 (Synchronous XHR) to complete. + loader->sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(request, redirectResponse), IPC::DispatchMessageEvenWhenWaitingForSyncReply); +} + +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +void AsynchronousNetworkLoaderClient::canAuthenticateAgainstProtectionSpace(NetworkResourceLoader* loader, const ProtectionSpace& protectionSpace) +{ + // 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 (Synchronous XHR) to complete. + loader->sendAbortingOnFailure(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(protectionSpace), IPC::DispatchMessageEvenWhenWaitingForSyncReply); +} +#endif + +void AsynchronousNetworkLoaderClient::didReceiveResponse(NetworkResourceLoader* loader, const ResourceResponse& response) +{ + loader->sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponseWithCertificateInfo(response, CertificateInfo(response), loader->isLoadingMainResource())); +} + +void AsynchronousNetworkLoaderClient::didReceiveBuffer(NetworkResourceLoader* loader, SharedBuffer* buffer, int encodedDataLength) +{ +#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + ShareableResource::Handle shareableResourceHandle; + NetworkResourceLoader::tryGetShareableHandleFromSharedBuffer(shareableResourceHandle, buffer); + if (!shareableResourceHandle.isNull()) { + // Since we're delivering this resource by ourselves all at once and don't need anymore data or callbacks from the network layer, abort the loader. + loader->abort(); + loader->send(Messages::WebResourceLoader::DidReceiveResource(shareableResourceHandle, currentTime())); + return; + } +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + + IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); + loader->sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedDataLength)); +} + +void AsynchronousNetworkLoaderClient::didSendData(NetworkResourceLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) +{ + loader->send(Messages::WebResourceLoader::DidSendData(bytesSent, totalBytesToBeSent)); +} + +void AsynchronousNetworkLoaderClient::didFinishLoading(NetworkResourceLoader* loader, double finishTime) +{ + loader->send(Messages::WebResourceLoader::DidFinishResourceLoad(finishTime)); +} + +void AsynchronousNetworkLoaderClient::didFail(NetworkResourceLoader* loader, const ResourceError& error) +{ + loader->send(Messages::WebResourceLoader::DidFailResourceLoad(error)); +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkLoadParameters.h b/Source/WebKit2/NetworkProcess/AsynchronousNetworkLoaderClient.h index 130aaa348..ab8aacf2a 100644 --- a/Source/WebKit2/NetworkProcess/NetworkLoadParameters.h +++ b/Source/WebKit2/NetworkProcess/AsynchronousNetworkLoaderClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * 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 @@ -23,34 +23,34 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NetworkLoadParameters_h -#define NetworkLoadParameters_h +#ifndef AsynchronousNetworkLoaderClient_h +#define AsynchronousNetworkLoaderClient_h -#include <WebCore/ResourceLoaderOptions.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/SessionID.h> +#include "NetworkLoaderClient.h" +#include "ShareableResource.h" -namespace WebKit { +#if ENABLE(NETWORK_PROCESS) -class NetworkResourceLoadParameters; +namespace WebKit { -class NetworkLoadParameters { +class AsynchronousNetworkLoaderClient : public NetworkLoaderClient { public: - NetworkLoadParameters() = default; - NetworkLoadParameters(const NetworkResourceLoadParameters&); - - uint64_t webPageID { 0 }; - uint64_t webFrameID { 0 }; - WebCore::SessionID sessionID { WebCore::SessionID::emptySessionID() }; - WebCore::ResourceRequest request; - WebCore::ContentSniffingPolicy contentSniffingPolicy { WebCore::SniffContent }; - WebCore::StoredCredentials allowStoredCredentials { WebCore::DoNotAllowStoredCredentials }; - WebCore::ClientCredentialPolicy clientCredentialPolicy { WebCore::DoNotAskClientForAnyCredentials }; - bool shouldClearReferrerOnHTTPSToHTTPRedirect { true }; - bool defersLoading { false }; - bool needsCertificateInfo { false }; + AsynchronousNetworkLoaderClient(); + +private: + virtual void willSendRequest(NetworkResourceLoader*, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse) override; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual void canAuthenticateAgainstProtectionSpace(NetworkResourceLoader*, const WebCore::ProtectionSpace&) override; +#endif + virtual void didReceiveResponse(NetworkResourceLoader*, const WebCore::ResourceResponse&) override; + virtual void didReceiveBuffer(NetworkResourceLoader*, WebCore::SharedBuffer*, int encodedDataLength) override; + virtual void didSendData(NetworkResourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override; + virtual void didFinishLoading(NetworkResourceLoader*, double finishTime) override; + virtual void didFail(NetworkResourceLoader*, const WebCore::ResourceError&) override; }; } // namespace WebKit -#endif // NetworkLoadParameters_h +#endif // ENABLE(NETWORK_PROCESS) + +#endif // AsynchronousNetworkLoaderClient_h diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h deleted file mode 100644 index bf2bd4720..000000000 --- a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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. - */ - -#ifndef CustomProtocolManager_h -#define CustomProtocolManager_h - -#include "Connection.h" -#include "NetworkProcessSupplement.h" -#include <wtf/WorkQueue.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 - - -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::Connection::WorkQueueMessageReceiver { - WTF_MAKE_NONCOPYABLE(CustomProtocolManager); -public: - explicit CustomProtocolManager(ChildProcess*); - - 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 *); -#endif -#endif - -private: - // ChildProcessSupplement - void initializeConnection(IPC::Connection*) override; - - // NetworkProcessSupplement - void initialize(const NetworkProcessCreationParameters&) override; - - // IPC::MessageReceiver - virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) 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); - - ChildProcess* m_childProcess; - RefPtr<WorkQueue> m_messageQueue; - -#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 -}; - -} // namespace WebKit - -#endif // CustomProtocolManager_h diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in b/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in deleted file mode 100644 index 0f55eceb1..000000000 --- a/Source/WebKit2/NetworkProcess/CustomProtocols/CustomProtocolManager.messages.in +++ /dev/null @@ -1,32 +0,0 @@ -# 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/CustomProtocolManagerImpl.cpp b/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp deleted file mode 100644 index dd8ec8bc9..000000000 --- a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.cpp +++ /dev/null @@ -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 = 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 = 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 = 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 = 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 = 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)); - 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 diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h b/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h deleted file mode 100644 index eda3dbef9..000000000 --- a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerImpl.h +++ /dev/null @@ -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 override; - GInputStream* finish(GTask*, GError**) final override; - - ChildProcess* m_childProcess; - GRefPtr<GPtrArray> m_schemes; - HashMap<uint64_t, std::unique_ptr<WebSoupRequestAsyncData>> m_customProtocolMap; -}; - -} // namespace WebKit - -#endif // CustomProtocolManagerImpl_h diff --git a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp b/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp deleted file mode 100644 index 72f7f708b..000000000 --- a/Source/WebKit2/NetworkProcess/CustomProtocols/soup/CustomProtocolManagerSoup.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 "ChildProcess.h" -#include "CustomProtocolManagerImpl.h" -#include "CustomProtocolManagerMessages.h" -#include "NetworkProcessCreationParameters.h" -#include "WebProcessCreationParameters.h" -#include <WebCore/NotImplemented.h> - -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)) -{ -} - -void CustomProtocolManager::initializeConnection(IPC::Connection* connection) -{ - connection->addWorkQueueMessageReceiver(Messages::CustomProtocolManager::messageReceiverName(), m_messageQueue.get(), this); -} - -void CustomProtocolManager::initialize(const NetworkProcessCreationParameters& parameters) -{ - for (size_t i = 0; i < parameters.urlSchemesRegisteredForCustomProtocols.size(); ++i) - registerScheme(parameters.urlSchemesRegisteredForCustomProtocols[i]); -} - -void CustomProtocolManager::registerScheme(const String& scheme) -{ - m_impl->registerScheme(scheme); -} - -void CustomProtocolManager::unregisterScheme(const String&) -{ - notImplemented(); -} - -bool CustomProtocolManager::supportsScheme(const String& scheme) -{ - return m_impl->supportsScheme(scheme); -} - -void CustomProtocolManager::didFailWithError(uint64_t customProtocolID, const WebCore::ResourceError& error) -{ - m_impl->didFailWithError(customProtocolID, error); -} - -void CustomProtocolManager::didLoadData(uint64_t customProtocolID, const IPC::DataReference& dataReference) -{ - m_impl->didLoadData(customProtocolID, dataReference); -} - -void CustomProtocolManager::didReceiveResponse(uint64_t customProtocolID, const WebCore::ResourceResponse& response, uint32_t) -{ - m_impl->didReceiveResponse(customProtocolID, response); -} - -void CustomProtocolManager::didFinishLoading(uint64_t customProtocolID) -{ - m_impl->didFinishLoading(customProtocolID); -} - -void CustomProtocolManager::wasRedirectedToRequest(uint64_t, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&) -{ - notImplemented(); -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/Downloads/Download.cpp b/Source/WebKit2/NetworkProcess/Downloads/Download.cpp deleted file mode 100644 index 4d2398a54..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/Download.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Download.h" - -#include "AuthenticationManager.h" -#include "Connection.h" -#include "DataReference.h" -#include "DownloadManager.h" -#include "DownloadProxyMessages.h" -#include "SandboxExtension.h" -#include "WebCoreArgumentCoders.h" -#include <WebCore/NotImplemented.h> - -#if !USE(NETWORK_SESSION) -#include "DownloadAuthenticationClient.h" -#endif - -using namespace WebCore; - -namespace WebKit { - -#if USE(NETWORK_SESSION) -Download::Download(DownloadManager& downloadManager, DownloadID downloadID) -#else -Download::Download(DownloadManager& downloadManager, DownloadID downloadID, const ResourceRequest& request) -#endif - : m_downloadManager(downloadManager) - , m_downloadID(downloadID) -#if !USE(NETWORK_SESSION) - , m_request(request) -#endif -{ - ASSERT(m_downloadID.downloadID()); - - m_downloadManager.didCreateDownload(); -} - -Download::~Download() -{ - platformInvalidate(); - - m_downloadManager.didDestroyDownload(); -} - -#if USE(NETWORK_SESSION) -void Download::didStart(const ResourceRequest& request) -{ - send(Messages::DownloadProxy::DidStart(request)); -} -#else -void Download::didStart() -{ - send(Messages::DownloadProxy::DidStart(m_request)); -} -#endif - -#if !USE(NETWORK_SESSION) -void Download::didReceiveAuthenticationChallenge(const AuthenticationChallenge& authenticationChallenge) -{ - m_downloadManager.downloadsAuthenticationManager().didReceiveAuthenticationChallenge(*this, authenticationChallenge); -} -#endif - -void Download::didReceiveResponse(const ResourceResponse& response) -{ - send(Messages::DownloadProxy::DidReceiveResponse(response)); -} - -void Download::didReceiveData(uint64_t length) -{ - send(Messages::DownloadProxy::DidReceiveData(length)); -} - -bool Download::shouldDecodeSourceDataOfMIMEType(const String& mimeType) -{ - bool result; - if (!sendSync(Messages::DownloadProxy::ShouldDecodeSourceDataOfMIMEType(mimeType), Messages::DownloadProxy::ShouldDecodeSourceDataOfMIMEType::Reply(result))) - return true; - - return result; -} - -String Download::decideDestinationWithSuggestedFilename(const String& filename, bool& allowOverwrite) -{ - String destination; - SandboxExtension::Handle sandboxExtensionHandle; - if (!sendSync(Messages::DownloadProxy::DecideDestinationWithSuggestedFilename(filename), Messages::DownloadProxy::DecideDestinationWithSuggestedFilename::Reply(destination, allowOverwrite, sandboxExtensionHandle))) - return String(); - - m_sandboxExtension = SandboxExtension::create(sandboxExtensionHandle); - if (m_sandboxExtension) - m_sandboxExtension->consume(); - - return destination; -} - -void Download::didCreateDestination(const String& path) -{ - send(Messages::DownloadProxy::DidCreateDestination(path)); -} - -void Download::didFinish() -{ - platformDidFinish(); - - send(Messages::DownloadProxy::DidFinish()); - - if (m_sandboxExtension) { - m_sandboxExtension->revoke(); - m_sandboxExtension = nullptr; - } - - m_downloadManager.downloadFinished(this); -} - -void Download::didFail(const ResourceError& error, const IPC::DataReference& resumeData) -{ - send(Messages::DownloadProxy::DidFail(error, resumeData)); - - if (m_sandboxExtension) { - m_sandboxExtension->revoke(); - m_sandboxExtension = nullptr; - } - m_downloadManager.downloadFinished(this); -} - -void Download::didCancel(const IPC::DataReference& resumeData) -{ - send(Messages::DownloadProxy::DidCancel(resumeData)); - - if (m_sandboxExtension) { - m_sandboxExtension->revoke(); - m_sandboxExtension = nullptr; - } - m_downloadManager.downloadFinished(this); -} - -IPC::Connection* Download::messageSenderConnection() -{ - return m_downloadManager.downloadProxyConnection(); -} - -uint64_t Download::messageSenderDestinationID() -{ - return m_downloadID.downloadID(); -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/Downloads/Download.h b/Source/WebKit2/NetworkProcess/Downloads/Download.h deleted file mode 100644 index 6fcb4e779..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/Download.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2010, 2011 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 Download_h -#define Download_h - -#include "DownloadID.h" -#include "MessageSender.h" -#include "SandboxExtension.h" -#include <WebCore/ResourceRequest.h> -#include <wtf/Noncopyable.h> - -#if PLATFORM(COCOA) -#include <wtf/RetainPtr.h> - -#if USE(NETWORK_SESSION) -OBJC_CLASS NSURLSessionDownloadTask; -#else -OBJC_CLASS NSURLDownload; -OBJC_CLASS WKDownloadAsDelegate; -#endif -#endif - -#if PLATFORM(GTK) || PLATFORM(EFL) -#include <WebCore/ResourceHandle.h> -#include <WebCore/ResourceHandleClient.h> -#include <memory> -#endif - -#if USE(CFNETWORK) -#include <CFNetwork/CFURLDownloadPriv.h> -#endif - -namespace IPC { -class DataReference; -} - -namespace WebCore { -class AuthenticationChallenge; -class Credential; -class ResourceError; -class ResourceHandle; -class ResourceResponse; -} - -namespace WebKit { - -class DownloadAuthenticationClient; -class DownloadManager; -class NetworkSession; -class WebPage; - -class Download : public IPC::MessageSender { - WTF_MAKE_NONCOPYABLE(Download); -public: -#if USE(NETWORK_SESSION) - Download(DownloadManager&, DownloadID); -#else - Download(DownloadManager&, DownloadID, const WebCore::ResourceRequest&); -#endif - ~Download(); - -#if USE(NETWORK_SESSION) && PLATFORM(COCOA) - void dataTaskDidBecomeDownloadTask(const NetworkSession&, RetainPtr<NSURLSessionDownloadTask>&&); -#else - void start(); - void startWithHandle(WebCore::ResourceHandle*, const WebCore::ResourceResponse&); -#endif - void resume(const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle&); - void cancel(); - - DownloadID downloadID() const { return m_downloadID; } - -#if USE(NETWORK_SESSION) - void didStart(const WebCore::ResourceRequest&); -#else - void didStart(); - void didReceiveAuthenticationChallenge(const WebCore::AuthenticationChallenge&); -#endif - void didReceiveResponse(const WebCore::ResourceResponse&); - void didReceiveData(uint64_t length); - bool shouldDecodeSourceDataOfMIMEType(const String& mimeType); - String decideDestinationWithSuggestedFilename(const String& filename, bool& allowOverwrite); - void didCreateDestination(const String& path); - void didFinish(); - void platformDidFinish(); - void didFail(const WebCore::ResourceError&, const IPC::DataReference& resumeData); - void didCancel(const IPC::DataReference& resumeData); - -#if USE(CFNETWORK) - DownloadAuthenticationClient* authenticationClient(); -#endif - -private: - // IPC::MessageSender - virtual IPC::Connection* messageSenderConnection() override; - virtual uint64_t messageSenderDestinationID() override; - - void platformInvalidate(); - - DownloadManager& m_downloadManager; - DownloadID m_downloadID; -#if !USE(NETWORK_SESSION) - WebCore::ResourceRequest m_request; -#endif - - RefPtr<SandboxExtension> m_sandboxExtension; - -#if PLATFORM(COCOA) -#if USE(NETWORK_SESSION) - RetainPtr<NSURLSessionDownloadTask> m_download; -#else - RetainPtr<NSURLDownload> m_nsURLDownload; - RetainPtr<WKDownloadAsDelegate> m_delegate; -#endif -#endif -#if USE(CFNETWORK) - RetainPtr<CFURLDownloadRef> m_download; - RefPtr<DownloadAuthenticationClient> m_authenticationClient; -#endif -#if PLATFORM(GTK) || PLATFORM(EFL) - std::unique_ptr<WebCore::ResourceHandleClient> m_downloadClient; - RefPtr<WebCore::ResourceHandle> m_resourceHandle; -#endif -}; - -} // namespace WebKit - -#endif // Download_h diff --git a/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.cpp b/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.cpp deleted file mode 100644 index ba122642c..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DownloadAuthenticationClient.h" - -#if !USE(NETWORK_SESSION) - -#include "Download.h" - -using namespace WebCore; - -namespace WebKit { - -DownloadAuthenticationClient::DownloadAuthenticationClient(Download* download) - : m_download(download) -{ - ASSERT_ARG(download, download); -} - -void DownloadAuthenticationClient::receivedCredential(const AuthenticationChallenge&, const Credential&) -{ - // FIXME (119667): This can probably be just removed. -} - -void DownloadAuthenticationClient::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) -{ - // FIXME (119667): This can probably be just removed. -} - -void DownloadAuthenticationClient::receivedCancellation(const AuthenticationChallenge&) -{ - // FIXME (119667): This can probably be just removed. -} - -void DownloadAuthenticationClient::receivedRequestToPerformDefaultHandling(const AuthenticationChallenge&) -{ - // FIXME (119667): This can probably be just removed. -} - -void DownloadAuthenticationClient::receivedChallengeRejection(const AuthenticationChallenge&) -{ - // FIXME (119667): This can probably be just removed. -} - -} // namespace WebKit - -#endif diff --git a/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.h b/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.h deleted file mode 100644 index 9cfc7c693..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/DownloadAuthenticationClient.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 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 DownloadAuthenticationClient_h -#define DownloadAuthenticationClient_h - -#if !USE(NETWORK_SESSION) - -#include <WebCore/AuthenticationClient.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - -namespace WebCore { - class AuthenticationChallenge; - class Credential; -} - -namespace WebKit { - -class Download; - -class DownloadAuthenticationClient : public RefCounted<DownloadAuthenticationClient>, public WebCore::AuthenticationClient { -public: - static Ref<DownloadAuthenticationClient> create(Download* download) { return adoptRef(*new DownloadAuthenticationClient(download)); } - - void detach() { m_download = 0; } - - using RefCounted<DownloadAuthenticationClient>::ref; - using RefCounted<DownloadAuthenticationClient>::deref; - -private: - DownloadAuthenticationClient(Download*); - - virtual void receivedCredential(const WebCore::AuthenticationChallenge&, const WebCore::Credential&) override; - virtual void receivedRequestToContinueWithoutCredential(const WebCore::AuthenticationChallenge&) override; - virtual void receivedCancellation(const WebCore::AuthenticationChallenge&) override; - virtual void receivedRequestToPerformDefaultHandling(const WebCore::AuthenticationChallenge&) override; - virtual void receivedChallengeRejection(const WebCore::AuthenticationChallenge&) override; - - virtual void refAuthenticationClient() override { ref(); } - virtual void derefAuthenticationClient() override { deref(); } - - Download* m_download; -}; - -} // namespace WebKit - -#endif // !USE(NETWORK_SESSION) - -#endif // DownloadAuthenticationClient_h diff --git a/Source/WebKit2/NetworkProcess/Downloads/DownloadID.h b/Source/WebKit2/NetworkProcess/Downloads/DownloadID.h deleted file mode 100644 index 37e68c3e9..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/DownloadID.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2015 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 DownloadID_h -#define DownloadID_h - -#include "ArgumentCoder.h" -#include "ArgumentDecoder.h" -#include "ArgumentEncoder.h" -#include <wtf/HashTraits.h> - -namespace WebKit { - -class DownloadID { -public: - DownloadID() - { - } - - explicit DownloadID(uint64_t downloadID) - : m_downloadID(downloadID) - { - } - - bool operator==(DownloadID other) const { return m_downloadID == other.m_downloadID; } - bool operator!=(DownloadID other) const { return m_downloadID != other.m_downloadID; } - - uint64_t downloadID() const { return m_downloadID; } -private: - uint64_t m_downloadID { 0 }; -}; - -} - -namespace IPC { - -template<> struct ArgumentCoder<WebKit::DownloadID> { - static void encode(ArgumentEncoder& encoder, const WebKit::DownloadID& downloadID) - { - encoder << downloadID.downloadID(); - } - static bool decode(ArgumentDecoder& decoder, WebKit::DownloadID& downloadID) - { - uint64_t id; - if (!decoder.decode(id)) - return false; - - downloadID = WebKit::DownloadID(id); - - return true; - } -}; - -} - -namespace WTF { - -struct DownloadIDHash { - static unsigned hash(const WebKit::DownloadID& d) { return intHash(d.downloadID()); } - static bool equal(const WebKit::DownloadID& a, const WebKit::DownloadID& b) { return a.downloadID() == b.downloadID(); } - static const bool safeToCompareToEmptyOrDeleted = true; -}; -template<> struct HashTraits<WebKit::DownloadID> : GenericHashTraits<WebKit::DownloadID> { - static WebKit::DownloadID emptyValue() { return { }; } - - static void constructDeletedValue(WebKit::DownloadID& slot) { slot = WebKit::DownloadID(std::numeric_limits<uint64_t>::max()); } - static bool isDeletedValue(const WebKit::DownloadID& slot) { return slot.downloadID() == std::numeric_limits<uint64_t>::max(); } -}; -template<> struct DefaultHash<WebKit::DownloadID> { - typedef DownloadIDHash Hash; -}; - -} -#endif /* DownloadID_h */ diff --git a/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp b/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp deleted file mode 100644 index fe46a7fc0..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DownloadManager.h" - -#include "Download.h" -#include "NetworkLoad.h" -#include "NetworkSession.h" -#include "PendingDownload.h" -#include "SessionTracker.h" -#include <WebCore/NotImplemented.h> -#include <WebCore/SessionID.h> -#include <wtf/StdLibExtras.h> - -using namespace WebCore; - -namespace WebKit { - -DownloadManager::DownloadManager(Client& client) - : m_client(client) -{ -} - -void DownloadManager::startDownload(SessionID sessionID, DownloadID downloadID, const ResourceRequest& request) -{ -#if USE(NETWORK_SESSION) - auto* networkSession = SessionTracker::networkSession(sessionID); - if (!networkSession) - return; - NetworkLoadParameters parameters; - parameters.sessionID = sessionID; - parameters.request = request; - parameters.clientCredentialPolicy = AskClientForAllCredentials; - m_pendingDownloads.add(downloadID, std::make_unique<PendingDownload>(parameters, downloadID)); -#else - auto download = std::make_unique<Download>(*this, downloadID, request); - download->start(); - - ASSERT(!m_downloads.contains(downloadID)); - m_downloads.add(downloadID, WTFMove(download)); -#endif -} - -#if USE(NETWORK_SESSION) -std::unique_ptr<PendingDownload> DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr<Download>&& download) -{ - // This is needed for downloads started with startDownload, otherwise it will return nullptr. - auto pendingDownload = m_pendingDownloads.take(downloadID); - - m_downloads.add(downloadID, WTFMove(download)); - return pendingDownload; -} - -void DownloadManager::continueCanAuthenticateAgainstProtectionSpace(DownloadID downloadID, bool canAuthenticate) -{ - auto* pendingDownload = m_pendingDownloads.get(downloadID); - ASSERT(pendingDownload); - if (pendingDownload) - pendingDownload->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate); -} - -void DownloadManager::continueWillSendRequest(DownloadID downloadID, const WebCore::ResourceRequest& request) -{ - auto* pendingDownload = m_pendingDownloads.get(downloadID); - ASSERT(pendingDownload); - if (pendingDownload) - pendingDownload->continueWillSendRequest(request); -} -#else -void DownloadManager::convertHandleToDownload(DownloadID downloadID, ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& response) -{ - auto download = std::make_unique<Download>(*this, downloadID, request); - - download->startWithHandle(handle, response); - ASSERT(!m_downloads.contains(downloadID)); - m_downloads.add(downloadID, WTFMove(download)); -} -#endif - -void DownloadManager::resumeDownload(SessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle& sandboxExtensionHandle) -{ -#if USE(NETWORK_SESSION) - notImplemented(); -#else - // Download::resume() is responsible for setting the Download's resource request. - auto download = std::make_unique<Download>(*this, downloadID, ResourceRequest()); - - download->resume(resumeData, path, sandboxExtensionHandle); - ASSERT(!m_downloads.contains(downloadID)); - m_downloads.add(downloadID, WTFMove(download)); -#endif -} - -void DownloadManager::cancelDownload(DownloadID downloadID) -{ - Download* download = m_downloads.get(downloadID); - if (!download) - return; - - download->cancel(); -} - -void DownloadManager::downloadFinished(Download* download) -{ - ASSERT(m_downloads.contains(download->downloadID())); - m_downloads.remove(download->downloadID()); -} - -void DownloadManager::didCreateDownload() -{ - m_client.didCreateDownload(); -} - -void DownloadManager::didDestroyDownload() -{ - m_client.didDestroyDownload(); -} - -IPC::Connection* DownloadManager::downloadProxyConnection() -{ - return m_client.downloadProxyConnection(); -} - -AuthenticationManager& DownloadManager::downloadsAuthenticationManager() -{ - return m_client.downloadsAuthenticationManager(); -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h b/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h deleted file mode 100644 index 9a52b5198..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010 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 DownloadManager_h -#define DownloadManager_h - -#include "DownloadID.h" -#include "PendingDownload.h" -#include "SandboxExtension.h" -#include <WebCore/NotImplemented.h> -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> - -namespace WebCore { -#if !USE(NETWORK_SESSION) -class ResourceHandle; -#endif -class ResourceRequest; -class ResourceResponse; -class SessionID; -} - -namespace IPC { -class Connection; -class DataReference; -} - -namespace WebKit { - -class AuthenticationManager; -class Download; -class PendingDownload; - -class DownloadManager { - WTF_MAKE_NONCOPYABLE(DownloadManager); - -public: - class Client { - public: - virtual ~Client() { } - - virtual void didCreateDownload() = 0; - virtual void didDestroyDownload() = 0; - virtual IPC::Connection* downloadProxyConnection() = 0; - virtual AuthenticationManager& downloadsAuthenticationManager() = 0; - }; - - explicit DownloadManager(Client&); - - void startDownload(WebCore::SessionID, DownloadID, const WebCore::ResourceRequest&); -#if USE(NETWORK_SESSION) - std::unique_ptr<PendingDownload> dataTaskBecameDownloadTask(DownloadID, std::unique_ptr<Download>&&); - void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate); - void continueWillSendRequest(DownloadID, const WebCore::ResourceRequest&); -#else - void convertHandleToDownload(DownloadID, WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); -#endif - - void resumeDownload(WebCore::SessionID, DownloadID, const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle&); - - void cancelDownload(DownloadID); - - Download* download(DownloadID downloadID) { return m_downloads.get(downloadID); } - - void downloadFinished(Download*); - bool isDownloading() const { return !m_downloads.isEmpty(); } - uint64_t activeDownloadCount() const { return m_downloads.size(); } - - void didCreateDownload(); - void didDestroyDownload(); - - IPC::Connection* downloadProxyConnection(); - AuthenticationManager& downloadsAuthenticationManager(); - -private: - Client& m_client; -#if USE(NETWORK_SESSION) - HashMap<DownloadID, std::unique_ptr<PendingDownload>> m_pendingDownloads; -#endif - HashMap<DownloadID, std::unique_ptr<Download>> m_downloads; -}; - -} // namespace WebKit - -#endif // DownloadManager_h diff --git a/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp b/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp deleted file mode 100644 index 62e3799d2..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "PendingDownload.h" - -#if USE(NETWORK_SESSION) - -#include "DownloadProxyMessages.h" -#include "NetworkLoad.h" -#include "NetworkProcess.h" -#include "WebCoreArgumentCoders.h" - -using namespace WebCore; - -namespace WebKit { - -PendingDownload::PendingDownload(const NetworkLoadParameters& parameters, DownloadID downloadID) - : m_networkLoad(std::make_unique<NetworkLoad>(*this, parameters)) -{ - m_networkLoad->setPendingDownloadID(downloadID); - m_networkLoad->setPendingDownload(*this); -} - -void PendingDownload::willSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse& redirectResponse) -{ - send(Messages::DownloadProxy::WillSendRequest(redirectRequest, redirectResponse)); -}; - -void PendingDownload::continueWillSendRequest(const WebCore::ResourceRequest& newRequest) -{ - m_networkLoad->continueWillSendRequest(newRequest); -} - -void PendingDownload::canAuthenticateAgainstProtectionSpaceAsync(const WebCore::ProtectionSpace& protectionSpace) -{ - send(Messages::DownloadProxy::CanAuthenticateAgainstProtectionSpace(protectionSpace)); -} - -void PendingDownload::continueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate) -{ - m_networkLoad->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate); -} - -void PendingDownload::didConvertToDownload() -{ - m_networkLoad = nullptr; -} - -IPC::Connection* PendingDownload::messageSenderConnection() -{ - return NetworkProcess::singleton().parentProcessConnection(); -} - -uint64_t PendingDownload::messageSenderDestinationID() -{ - return m_networkLoad->pendingDownloadID().downloadID(); -} - -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h b/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h deleted file mode 100644 index 72a744cb2..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2016 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 PendingDownload_h -#define PendingDownload_h - -#if USE(NETWORK_SESSION) - -#include "MessageSender.h" -#include "NetworkLoadClient.h" - -namespace WebCore { -class ResourceResponse; -} - -namespace WebKit { - -class DownloadID; -class NetworkLoad; -class NetworkLoadParameters; - -class PendingDownload : public NetworkLoadClient, public IPC::MessageSender { -public: - PendingDownload(const NetworkLoadParameters&, DownloadID); - - void continueWillSendRequest(const WebCore::ResourceRequest&); - void continueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate); - -private: - // NetworkLoadClient. - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override { } - virtual void canAuthenticateAgainstProtectionSpaceAsync(const WebCore::ProtectionSpace&) override; - virtual bool isSynchronous() const override { return false; } - virtual void willSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse& redirectResponse) override; - virtual ShouldContinueDidReceiveResponse didReceiveResponse(const WebCore::ResourceResponse&) override { return ShouldContinueDidReceiveResponse::No; }; - virtual void didReceiveBuffer(RefPtr<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override { }; - virtual void didFinishLoading(double finishTime) override { }; - virtual void didFailLoading(const WebCore::ResourceError&) override { }; - virtual void didConvertToDownload() override; -#if PLATFORM(COCOA) - virtual void willCacheResponseAsync(CFCachedURLResponseRef) override { } -#endif - - // MessageSender. - virtual IPC::Connection* messageSenderConnection() override; - virtual uint64_t messageSenderDestinationID() override; - -private: - std::unique_ptr<NetworkLoad> m_networkLoad; -}; - -} - -#endif - -#endif diff --git a/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoup.cpp b/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoup.cpp deleted file mode 100644 index b4198b131..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoup.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org> - * - * 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 "Download.h" - -#include "DataReference.h" -#include "DownloadSoupErrors.h" -#include <WebCore/NotImplemented.h> -#include <WebCore/ResourceHandleInternal.h> -#include <gio/gio.h> -#include <wtf/RunLoop.h> -#include <wtf/glib/GRefPtr.h> -#include <wtf/glib/GUniquePtr.h> -#include <wtf/text/CString.h> - -#if PLATFORM(GTK) -#include <glib/gi18n-lib.h> -#endif - -using namespace WebCore; - -namespace WebKit { - -class DownloadClient : public ResourceHandleClient { - WTF_MAKE_NONCOPYABLE(DownloadClient); -public: - DownloadClient(Download* download) - : m_download(download) - , m_handleResponseLater(RunLoop::main(), this, &DownloadClient::handleResponse) - , m_allowOverwrite(false) - { - } - - ~DownloadClient() - { - } - - void deleteFilesIfNeeded() - { - if (m_destinationFile) - g_file_delete(m_destinationFile.get(), nullptr, nullptr); - - if (m_intermediateFile) { - ASSERT(m_destinationFile); - g_file_delete(m_intermediateFile.get(), nullptr, nullptr); - } - } - - void downloadFailed(const ResourceError& error) - { - deleteFilesIfNeeded(); - m_download->didFail(error, IPC::DataReference()); - } - - void didReceiveResponse(ResourceHandle*, const ResourceResponse& response) - { - m_response = response; - m_download->didReceiveResponse(response); - - if (response.httpStatusCode() >= 400) { - downloadFailed(platformDownloadNetworkError(response.httpStatusCode(), response.url(), response.httpStatusText())); - return; - } - - String suggestedFilename = response.suggestedFilename(); - if (suggestedFilename.isEmpty()) { - URL url = response.url(); - url.setQuery(String()); - url.removeFragmentIdentifier(); - suggestedFilename = decodeURLEscapeSequences(url.lastPathComponent()); - } - - String destinationURI = m_download->decideDestinationWithSuggestedFilename(suggestedFilename, m_allowOverwrite); - if (destinationURI.isEmpty()) { -#if PLATFORM(GTK) - GUniquePtr<char> buffer(g_strdup_printf(_("Cannot determine destination URI for download with suggested filename %s"), suggestedFilename.utf8().data())); - String errorMessage = String::fromUTF8(buffer.get()); -#else - String errorMessage = makeString("Cannot determine destination URI for download with suggested filename ", suggestedFilename); -#endif - downloadFailed(platformDownloadDestinationError(response, errorMessage)); - return; - } - - m_destinationFile = adoptGRef(g_file_new_for_uri(destinationURI.utf8().data())); - GRefPtr<GFileOutputStream> outputStream; - GUniqueOutPtr<GError> error; - if (m_allowOverwrite) - outputStream = adoptGRef(g_file_replace(m_destinationFile.get(), nullptr, FALSE, G_FILE_CREATE_NONE, nullptr, &error.outPtr())); - else - outputStream = adoptGRef(g_file_create(m_destinationFile.get(), G_FILE_CREATE_NONE, nullptr, &error.outPtr())); - if (!outputStream) { - m_destinationFile.clear(); - downloadFailed(platformDownloadDestinationError(response, error->message)); - return; - } - - String intermediateURI = destinationURI + ".wkdownload"; - m_intermediateFile = adoptGRef(g_file_new_for_uri(intermediateURI.utf8().data())); - m_outputStream = adoptGRef(g_file_replace(m_intermediateFile.get(), 0, TRUE, G_FILE_CREATE_NONE, 0, &error.outPtr())); - if (!m_outputStream) { - downloadFailed(platformDownloadDestinationError(response, error->message)); - return; - } - - m_download->didCreateDestination(destinationURI); - } - - void didReceiveData(ResourceHandle*, const char* data, unsigned length, int /*encodedDataLength*/) - { - if (m_handleResponseLater.isActive()) { - m_handleResponseLater.stop(); - handleResponse(); - } - - gsize bytesWritten; - GUniqueOutPtr<GError> error; - g_output_stream_write_all(G_OUTPUT_STREAM(m_outputStream.get()), data, length, &bytesWritten, 0, &error.outPtr()); - if (error) { - downloadFailed(platformDownloadDestinationError(m_response, error->message)); - return; - } - m_download->didReceiveData(bytesWritten); - } - - void didFinishLoading(ResourceHandle*, double) - { - m_outputStream = 0; - - ASSERT(m_destinationFile); - ASSERT(m_intermediateFile); - GUniqueOutPtr<GError> error; - if (!g_file_move(m_intermediateFile.get(), m_destinationFile.get(), G_FILE_COPY_OVERWRITE, nullptr, nullptr, nullptr, &error.outPtr())) { - downloadFailed(platformDownloadDestinationError(m_response, error->message)); - return; - } - - GRefPtr<GFileInfo> info = adoptGRef(g_file_info_new()); - CString uri = m_response.url().string().utf8(); - g_file_info_set_attribute_string(info.get(), "metadata::download-uri", uri.data()); - g_file_info_set_attribute_string(info.get(), "xattr::xdg.origin.url", uri.data()); - g_file_set_attributes_async(m_destinationFile.get(), info.get(), G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, nullptr, nullptr, nullptr); - - m_download->didFinish(); - } - - void didFail(ResourceHandle*, const ResourceError& error) - { - downloadFailed(platformDownloadNetworkError(error.errorCode(), error.failingURL(), error.localizedDescription())); - } - - void wasBlocked(ResourceHandle*) - { - notImplemented(); - } - - void cannotShowURL(ResourceHandle*) - { - notImplemented(); - } - - void cancel(ResourceHandle* handle) - { - handle->cancel(); - deleteFilesIfNeeded(); - m_download->didCancel(IPC::DataReference()); - } - - void handleResponse() - { - didReceiveResponse(nullptr, m_delayedResponse); - } - - void handleResponseLater(const ResourceResponse& response) - { - ASSERT(m_response.isNull()); - ASSERT(!m_handleResponseLater.isActive()); - - m_delayedResponse = response; - - // Call didReceiveResponse in an idle to make sure the download is added - // to the DownloadManager downloads map. - m_handleResponseLater.startOneShot(0); - } - - Download* m_download; - GRefPtr<GFileOutputStream> m_outputStream; - ResourceResponse m_response; - GRefPtr<GFile> m_destinationFile; - GRefPtr<GFile> m_intermediateFile; - ResourceResponse m_delayedResponse; - RunLoop::Timer<DownloadClient> m_handleResponseLater; - bool m_allowOverwrite; -}; - -void Download::start() -{ - ASSERT(!m_downloadClient); - ASSERT(!m_resourceHandle); - m_downloadClient = std::make_unique<DownloadClient>(this); - m_resourceHandle = ResourceHandle::create(0, m_request, m_downloadClient.get(), false, false); - didStart(); -} - -void Download::startWithHandle(ResourceHandle* resourceHandle, const ResourceResponse& response) -{ - ASSERT(!m_downloadClient); - ASSERT(!m_resourceHandle); - m_downloadClient = std::make_unique<DownloadClient>(this); - m_resourceHandle = resourceHandle->releaseForDownload(m_downloadClient.get()); - didStart(); - static_cast<DownloadClient*>(m_downloadClient.get())->handleResponseLater(response); -} - -void Download::resume(const IPC::DataReference&, const String&, const SandboxExtension::Handle&) -{ - notImplemented(); -} - -void Download::cancel() -{ - if (!m_resourceHandle) - return; - - // Cancelling the download will delete it and platformInvalidate() will be called by the destructor. - // So, we need to set m_resourceHandle to nullptr before actually cancelling the download to make sure - // it won't be cancelled again by platformInvalidate. See https://bugs.webkit.org/show_bug.cgi?id=127650. - RefPtr<ResourceHandle> resourceHandle = m_resourceHandle.release(); - static_cast<DownloadClient*>(m_downloadClient.get())->cancel(resourceHandle.get()); -} - -void Download::platformInvalidate() -{ - if (m_resourceHandle) { - m_resourceHandle->clearClient(); - m_resourceHandle->cancel(); - m_resourceHandle = nullptr; - } - - m_downloadClient = nullptr; -} - -void Download::platformDidFinish() -{ - m_resourceHandle = nullptr; -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoupErrors.h b/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoupErrors.h deleted file mode 100644 index ff397ec22..000000000 --- a/Source/WebKit2/NetworkProcess/Downloads/soup/DownloadSoupErrors.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 Intel Corporation. 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 DownloadSoupErrors_h -#define DownloadSoupErrors_h - -#include <WebCore/ResourceHandle.h> -#include <WebCore/URL.h> -#include <wtf/text/WTFString.h> - -namespace WebKit { - -WebCore::ResourceError platformDownloadNetworkError(int errorCode, const WebCore::URL& failingURL, const String& localizedDescription); -WebCore::ResourceError platformDownloadDestinationError(const WebCore::ResourceResponse&, const String& message); - -} // namespace WebKit - -#endif // DownloadSoupErrors_h diff --git a/Source/WebKit2/NetworkProcess/EntryPoint/unix/NetworkProcessMain.cpp b/Source/WebKit2/NetworkProcess/EntryPoint/unix/NetworkProcessMain.cpp deleted file mode 100644 index b282e16a3..000000000 --- a/Source/WebKit2/NetworkProcess/EntryPoint/unix/NetworkProcessMain.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2014 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 "NetworkProcessMainUnix.h" - -#include <cstdlib> - -using namespace WebKit; - -int main(int argc, char** argv) -{ - // Disable SSLv3 very early because it is practically impossible to safely - // use setenv() when multiple threads are running, as another thread calling - // getenv() could cause a crash, and many functions use getenv() internally. - // This workaround will stop working if glib-networking switches away from - // GnuTLS or simply stops parsing this variable. We intentionally do not - // overwrite this priority string if it's already set by the user. - // https://bugzilla.gnome.org/show_bug.cgi?id=738633 - // WARNING: This needs to be KEPT IN SYNC with WebProcessMain.cpp. - setenv("G_TLS_GNUTLS_PRIORITY", "NORMAL:%COMPAT:%LATEST_RECORD_VERSION:!VERS-SSL3.0:!ARCFOUR-128", 0); - - return NetworkProcessMainUnix(argc, argv); -} diff --git a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp index 025e2fc65..a2ac7d124 100644 --- a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp +++ b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp @@ -26,20 +26,20 @@ #include "config.h" #include "NetworkBlobRegistry.h" -#include "BlobDataFileReferenceWithSandboxExtension.h" +#if ENABLE(BLOB) && ENABLE(NETWORK_PROCESS) + #include "SandboxExtension.h" -#include <WebCore/BlobPart.h> #include <WebCore/BlobRegistryImpl.h> +#include <wtf/MainThread.h> #include <wtf/NeverDestroyed.h> -#include <wtf/RunLoop.h> using namespace WebCore; namespace WebKit { -NetworkBlobRegistry& NetworkBlobRegistry::singleton() +NetworkBlobRegistry& NetworkBlobRegistry::shared() { - ASSERT(RunLoop::isMain()); + ASSERT(isMainThread()); static NeverDestroyed<NetworkBlobRegistry> registry; return registry; } @@ -48,20 +48,22 @@ NetworkBlobRegistry::NetworkBlobRegistry() { } -void NetworkBlobRegistry::registerFileBlobURL(NetworkConnectionToWebProcess* connection, const URL& url, const String& path, RefPtr<SandboxExtension>&& sandboxExtension, const String& contentType) +void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const URL& url, std::unique_ptr<BlobData> data, const Vector<RefPtr<SandboxExtension>>& newSandboxExtensions) { - blobRegistry().registerFileBlobURL(url, BlobDataFileReferenceWithSandboxExtension::create(path, sandboxExtension), contentType); + ASSERT(!m_sandboxExtensions.contains(url.string())); + + // Combine new extensions for File items and existing extensions for inner Blob items. + Vector<RefPtr<SandboxExtension>> sandboxExtensions = newSandboxExtensions; + const BlobDataItemList& items = data->items(); + for (size_t i = 0, count = items.size(); i < count; ++i) { + if (items[i].type == BlobDataItem::Blob) + sandboxExtensions.appendVector(m_sandboxExtensions.get(items[i].url.string())); + } - ASSERT(!m_blobsForConnection.get(connection).contains(url)); - BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection); - if (mapIterator == m_blobsForConnection.end()) - mapIterator = m_blobsForConnection.add(connection, HashSet<URL>()).iterator; - mapIterator->value.add(url); -} + blobRegistry().registerBlobURL(url, std::move(data)); -void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const URL& url, Vector<WebCore::BlobPart> blobParts, const String& contentType) -{ - blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType); + if (!sandboxExtensions.isEmpty()) + m_sandboxExtensions.add(url.string(), sandboxExtensions); ASSERT(!m_blobsForConnection.get(connection).contains(url)); BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection); @@ -72,49 +74,24 @@ void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connect void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::URL& url, const WebCore::URL& srcURL) { - // The connection may not be registered if NetworkProcess prevously crashed for any reason. - BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection); - if (mapIterator == m_blobsForConnection.end()) - return; - blobRegistry().registerBlobURL(url, srcURL); + SandboxExtensionMap::iterator iter = m_sandboxExtensions.find(srcURL.string()); + if (iter != m_sandboxExtensions.end()) + m_sandboxExtensions.add(url.string(), iter->value); - ASSERT(mapIterator->value.contains(srcURL)); - mapIterator->value.add(url); -} - -void NetworkBlobRegistry::registerBlobURLForSlice(NetworkConnectionToWebProcess* connection, const WebCore::URL& url, const WebCore::URL& srcURL, int64_t start, int64_t end) -{ - // The connection may not be registered if NetworkProcess prevously crashed for any reason. - BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection); - if (mapIterator == m_blobsForConnection.end()) - return; - - blobRegistry().registerBlobURLForSlice(url, srcURL, start, end); - - ASSERT(mapIterator->value.contains(srcURL)); - mapIterator->value.add(url); + ASSERT(m_blobsForConnection.contains(connection)); + ASSERT(m_blobsForConnection.find(connection)->value.contains(srcURL)); + m_blobsForConnection.find(connection)->value.add(url); } void NetworkBlobRegistry::unregisterBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::URL& url) { - // The connection may not be registered if NetworkProcess prevously crashed for any reason. - BlobForConnectionMap::iterator mapIterator = m_blobsForConnection.find(connection); - if (mapIterator == m_blobsForConnection.end()) - return; - blobRegistry().unregisterBlobURL(url); + m_sandboxExtensions.remove(url.string()); - ASSERT(mapIterator->value.contains(url)); - mapIterator->value.remove(url); -} - -uint64_t NetworkBlobRegistry::blobSize(NetworkConnectionToWebProcess* connection, const WebCore::URL& url) -{ - if (!m_blobsForConnection.contains(connection) || !m_blobsForConnection.find(connection)->value.contains(url)) - return 0; - - return blobRegistry().blobSize(url); + ASSERT(m_blobsForConnection.contains(connection)); + ASSERT(m_blobsForConnection.find(connection)->value.contains(url)); + m_blobsForConnection.find(connection)->value.remove(url); } void NetworkBlobRegistry::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection) @@ -123,29 +100,19 @@ void NetworkBlobRegistry::connectionToWebProcessDidClose(NetworkConnectionToWebP return; HashSet<URL>& blobsForConnection = m_blobsForConnection.find(connection)->value; - for (HashSet<URL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter) + for (HashSet<URL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter) { blobRegistry().unregisterBlobURL(*iter); + m_sandboxExtensions.remove(*iter); + } m_blobsForConnection.remove(connection); } -Vector<RefPtr<BlobDataFileReference>> NetworkBlobRegistry::filesInBlob(NetworkConnectionToWebProcess& connection, const WebCore::URL& url) +const Vector<RefPtr<SandboxExtension>> NetworkBlobRegistry::sandboxExtensions(const WebCore::URL& url) { - if (!m_blobsForConnection.contains(&connection) || !m_blobsForConnection.find(&connection)->value.contains(url)) - return Vector<RefPtr<BlobDataFileReference>>(); - - ASSERT(blobRegistry().isBlobRegistryImpl()); - BlobData* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(url); - if (!blobData) - return Vector<RefPtr<BlobDataFileReference>>(); - - Vector<RefPtr<BlobDataFileReference>> result; - for (const BlobDataItem& item : blobData->items()) { - if (item.type() == BlobDataItem::Type::File) - result.append(item.file()); - } - - return result; + return m_sandboxExtensions.get(url.string()); } } + +#endif diff --git a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h index 4adde415d..16c6adb09 100644 --- a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h +++ b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h @@ -26,13 +26,14 @@ #ifndef NetworkBlobRegistry_h #define NetworkBlobRegistry_h +#if ENABLE(BLOB) && ENABLE(NETWORK_PROCESS) + #include <WebCore/URLHash.h> #include <wtf/HashMap.h> #include <wtf/HashSet.h> namespace WebCore { -class BlobDataFileReference; -class BlobPart; +class BlobData; } namespace WebKit { @@ -44,26 +45,28 @@ class NetworkBlobRegistry { WTF_MAKE_NONCOPYABLE(NetworkBlobRegistry); public: NetworkBlobRegistry(); - static NetworkBlobRegistry& singleton(); + static NetworkBlobRegistry& shared(); - void registerFileBlobURL(NetworkConnectionToWebProcess*, const WebCore::URL&, const String& path, RefPtr<SandboxExtension>&&, const String& contentType); - void registerBlobURL(NetworkConnectionToWebProcess*, const WebCore::URL&, Vector<WebCore::BlobPart>, const String& contentType); + void registerBlobURL(NetworkConnectionToWebProcess*, const WebCore::URL&, std::unique_ptr<WebCore::BlobData>, const Vector<RefPtr<SandboxExtension>>&); void registerBlobURL(NetworkConnectionToWebProcess*, const WebCore::URL&, const WebCore::URL& srcURL); - void registerBlobURLForSlice(NetworkConnectionToWebProcess*, const WebCore::URL&, const WebCore::URL& srcURL, int64_t start, int64_t end); void unregisterBlobURL(NetworkConnectionToWebProcess*, const WebCore::URL&); - uint64_t blobSize(NetworkConnectionToWebProcess*, const WebCore::URL&); void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*); - Vector<RefPtr<WebCore::BlobDataFileReference>> filesInBlob(NetworkConnectionToWebProcess&, const WebCore::URL&); + const Vector<RefPtr<SandboxExtension>> sandboxExtensions(const WebCore::URL&); private: ~NetworkBlobRegistry(); + typedef HashMap<String, Vector<RefPtr<SandboxExtension>>> SandboxExtensionMap; + SandboxExtensionMap m_sandboxExtensions; + typedef HashMap<NetworkConnectionToWebProcess*, HashSet<WebCore::URL>> BlobForConnectionMap; BlobForConnectionMap m_blobsForConnection; }; } +#endif // ENABLE(BLOB) && ENABLE(NETWORK_PROCESS) + #endif // NetworkBlobRegistry_h diff --git a/Source/WebKit2/NetworkProcess/HostRecord.cpp b/Source/WebKit2/NetworkProcess/HostRecord.cpp new file mode 100644 index 000000000..35248f296 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/HostRecord.cpp @@ -0,0 +1,230 @@ +/* + * 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. + */ + +#include "config.h" +#include "HostRecord.h" + +#include "Logging.h" +#include "NetworkConnectionToWebProcess.h" +#include "NetworkProcess.h" +#include "NetworkResourceLoadParameters.h" +#include "NetworkResourceLoadScheduler.h" +#include "NetworkResourceLoader.h" +#include <wtf/MainThread.h> + +#if ENABLE(NETWORK_PROCESS) + +using namespace WebCore; + +namespace WebKit { + +HostRecord::HostRecord(const String& name, int maxRequestsInFlight) + : m_name(name) + , m_maxRequestsInFlight(maxRequestsInFlight) +{ +} + +HostRecord::~HostRecord() +{ +#ifndef NDEBUG + ASSERT(m_loadersInProgress.isEmpty()); + for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) + ASSERT(m_loadersPending[p].isEmpty()); +#endif +} + +void HostRecord::scheduleResourceLoader(PassRefPtr<NetworkResourceLoader> loader) +{ + ASSERT(isMainThread()); + + loader->setHostRecord(this); + + if (loader->isSynchronous()) + m_syncLoadersPending.append(loader); + else + m_loadersPending[loader->priority()].append(loader); +} + +void HostRecord::addLoaderInProgress(NetworkResourceLoader* loader) +{ + ASSERT(isMainThread()); + + m_loadersInProgress.add(loader); + loader->setHostRecord(this); +} + +inline bool removeLoaderFromQueue(NetworkResourceLoader* loader, LoaderQueue& queue) +{ + LoaderQueue::iterator end = queue.end(); + for (LoaderQueue::iterator it = queue.begin(); it != end; ++it) { + if (it->get() == loader) { + loader->setHostRecord(0); + queue.remove(it); + return true; + } + } + return false; +} + +void HostRecord::removeLoader(NetworkResourceLoader* loader) +{ + ASSERT(isMainThread()); + + // FIXME (NetworkProcess): Due to IPC race conditions, it's possible this HostRecord will be asked to remove the same loader twice. + // It would be nice to know the loader has already been removed and treat it as a no-op. + + NetworkResourceLoaderSet::iterator i = m_loadersInProgress.find(loader); + if (i != m_loadersInProgress.end()) { + i->get()->setHostRecord(0); + m_loadersInProgress.remove(i); + return; + } + + if (removeLoaderFromQueue(loader, m_syncLoadersPending)) + return; + + for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) { + if (removeLoaderFromQueue(loader, m_loadersPending[priority])) + return; + } +} + +bool HostRecord::hasRequests() const +{ + if (!m_loadersInProgress.isEmpty()) + return true; + + for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) { + if (!m_loadersPending[p].isEmpty()) + return true; + } + + return false; +} + +uint64_t HostRecord::pendingRequestCount() const +{ + uint64_t count = 0; + + for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) + count += m_loadersPending[p].size(); + + return count; +} + +uint64_t HostRecord::activeLoadCount() const +{ + return m_loadersInProgress.size(); +} + +void HostRecord::servePendingRequestsForQueue(LoaderQueue& queue, ResourceLoadPriority priority) +{ + // We only enforce the connection limit for http(s) hosts, which are the only ones with names. + bool shouldLimitRequests = !name().isNull(); + + // For non-named hosts - everything but http(s) - we should only enforce the limit if the document + // isn't done parsing and we don't know all stylesheets yet. + + // FIXME (NetworkProcess): The above comment about document parsing and stylesheets is a holdover + // from the WebCore::ResourceLoadScheduler. + // The behavior described was at one time important for WebCore's single threadedness. + // It's possible that we don't care about it with the NetworkProcess. + // We should either decide it's not important and change the above comment, or decide it is + // still important and somehow account for it. + + // Very low priority loaders are only handled when no other loaders are in progress. + if (shouldLimitRequests && priority == ResourceLoadPriorityVeryLow && !m_loadersInProgress.isEmpty()) + return; + + while (!queue.isEmpty()) { + RefPtr<NetworkResourceLoader> loader = queue.first(); + ASSERT(loader->hostRecord() == this); + + // This request might be from WebProcess we've lost our connection to. + // If so we should just skip it. + if (!loader->connectionToWebProcess()) { + removeLoader(loader.get()); + continue; + } + + if (shouldLimitRequests && limitsRequests(priority, loader.get())) + return; + + m_loadersInProgress.add(loader); + queue.removeFirst(); + + LOG(NetworkScheduling, "(NetworkProcess) HostRecord::servePendingRequestsForQueue - Starting load of %s\n", loader->request().url().string().utf8().data()); + loader->start(); + } +} + +void HostRecord::servePendingRequests(ResourceLoadPriority minimumPriority) +{ + LOG(NetworkScheduling, "(NetworkProcess) HostRecord::servePendingRequests Host name='%s'", name().utf8().data()); + + // We serve synchronous requests before any other requests to improve responsiveness in any + // WebProcess that is waiting on a synchronous load. + servePendingRequestsForQueue(m_syncLoadersPending, ResourceLoadPriorityHighest); + + for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) + servePendingRequestsForQueue(m_loadersPending[priority], (ResourceLoadPriority)priority); +} + +bool HostRecord::limitsRequests(ResourceLoadPriority priority, NetworkResourceLoader* loader) const +{ + ASSERT(loader); + ASSERT(loader->connectionToWebProcess()); + + if (priority == ResourceLoadPriorityVeryLow && !m_loadersInProgress.isEmpty()) + return true; + + if (loader->connectionToWebProcess()->isSerialLoadingEnabled() && m_loadersInProgress.size() >= 1) + return true; + + // If we're exactly at the limit for requests in flight, and this loader is asynchronous, then we're done serving new requests. + // The synchronous loader exception handles the case where a sync XHR is made while 6 other requests are already in flight. + if (m_loadersInProgress.size() == m_maxRequestsInFlight && !loader->isSynchronous()) + return true; + + // If we're already past the limit of the number of loaders in flight, we won't even serve new synchronous requests right now. + if (m_loadersInProgress.size() > m_maxRequestsInFlight) { +#ifndef NDEBUG + // If we have more loaders in progress than we should, at least one of them had better be synchronous. + NetworkResourceLoaderSet::iterator i = m_loadersInProgress.begin(); + NetworkResourceLoaderSet::iterator end = m_loadersInProgress.end(); + for (; i != end; ++i) { + if (i->get()->isSynchronous()) + break; + } + ASSERT(i != end); +#endif + return true; + } + return false; +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/HostRecord.h b/Source/WebKit2/NetworkProcess/HostRecord.h new file mode 100644 index 000000000..7e18c3a7e --- /dev/null +++ b/Source/WebKit2/NetworkProcess/HostRecord.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifndef HostRecord_h +#define HostRecord_h + +#if ENABLE(NETWORK_PROCESS) + +#include <WebCore/ResourceLoadPriority.h> +#include <wtf/Deque.h> +#include <wtf/HashSet.h> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +class NetworkResourceLoader; + +typedef Deque<RefPtr<NetworkResourceLoader>> LoaderQueue; +typedef uint64_t ResourceLoadIdentifier; + +class HostRecord : public RefCounted<HostRecord> { +public: + static PassRefPtr<HostRecord> create(const String& name, int maxRequestsInFlight) + { + return adoptRef(new HostRecord(name, maxRequestsInFlight)); + } + + ~HostRecord(); + + const String& name() const { return m_name; } + + void scheduleResourceLoader(PassRefPtr<NetworkResourceLoader>); + void addLoaderInProgress(NetworkResourceLoader*); + void removeLoader(NetworkResourceLoader*); + bool hasRequests() const; + void servePendingRequests(WebCore::ResourceLoadPriority); + + uint64_t pendingRequestCount() const; + uint64_t activeLoadCount() const; + +private: + HostRecord(const String& name, int maxRequestsInFlight); + + void servePendingRequestsForQueue(LoaderQueue&, WebCore::ResourceLoadPriority); + bool limitsRequests(WebCore::ResourceLoadPriority, NetworkResourceLoader*) const; + + LoaderQueue m_loadersPending[WebCore::ResourceLoadPriorityHighest + 1]; + LoaderQueue m_syncLoadersPending; + + typedef HashSet<RefPtr<NetworkResourceLoader>> NetworkResourceLoaderSet; + NetworkResourceLoaderSet m_loadersInProgress; + + const String m_name; + int m_maxRequestsInFlight; +}; + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) + +#endif // #ifndef HostRecord_h diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp index 812919890..1fee498a9 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp @@ -26,50 +26,46 @@ #include "config.h" #include "NetworkConnectionToWebProcess.h" +#if ENABLE(NETWORK_PROCESS) + +#include "BlobRegistrationData.h" +#include "ConnectionStack.h" #include "NetworkBlobRegistry.h" #include "NetworkConnectionToWebProcessMessages.h" -#include "NetworkLoad.h" #include "NetworkProcess.h" #include "NetworkResourceLoadParameters.h" #include "NetworkResourceLoader.h" #include "NetworkResourceLoaderMessages.h" #include "RemoteNetworkingContext.h" #include "SessionTracker.h" -#include <WebCore/NotImplemented.h> -#include <WebCore/PingHandle.h> +#include <WebCore/BlobData.h> #include <WebCore/PlatformCookieJar.h> #include <WebCore/ResourceLoaderOptions.h> #include <WebCore/ResourceRequest.h> -#include <WebCore/SessionID.h> #include <wtf/RunLoop.h> using namespace WebCore; namespace WebKit { -Ref<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(IPC::Connection::Identifier connectionIdentifier) +PassRefPtr<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(IPC::Connection::Identifier connectionIdentifier) { - return adoptRef(*new NetworkConnectionToWebProcess(connectionIdentifier)); + return adoptRef(new NetworkConnectionToWebProcess(connectionIdentifier)); } NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(IPC::Connection::Identifier connectionIdentifier) + : m_serialLoadingEnabled(false) { - m_connection = IPC::Connection::createServerConnection(connectionIdentifier, *this); + m_connection = IPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main()); + m_connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true); m_connection->open(); } NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess() { } - -void NetworkConnectionToWebProcess::didCleanupResourceLoader(NetworkResourceLoader& loader) -{ - ASSERT(m_networkResourceLoaders.get(loader.identifier()) == &loader); - - m_networkResourceLoaders.remove(loader.identifier()); -} -void NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder) +void NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder) { if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) { didReceiveNetworkConnectionToWebProcessMessage(connection, decoder); @@ -86,7 +82,7 @@ void NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection& connectio ASSERT_NOT_REACHED(); } -void NetworkConnectionToWebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& reply) +void NetworkConnectionToWebProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& reply) { if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) { didReceiveSyncNetworkConnectionToWebProcessMessage(connection, decoder, reply); @@ -95,50 +91,43 @@ void NetworkConnectionToWebProcess::didReceiveSyncMessage(IPC::Connection& conne ASSERT_NOT_REACHED(); } -void NetworkConnectionToWebProcess::didClose(IPC::Connection&) +void NetworkConnectionToWebProcess::didClose(IPC::Connection*) { // Protect ourself as we might be otherwise be deleted during this function. Ref<NetworkConnectionToWebProcess> protector(*this); - Vector<RefPtr<NetworkResourceLoader>> loaders; - copyValuesToVector(m_networkResourceLoaders, loaders); - for (auto& loader : loaders) - loader->abort(); - ASSERT(m_networkResourceLoaders.isEmpty()); + HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator end = m_networkResourceLoaders.end(); + for (HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator i = m_networkResourceLoaders.begin(); i != end; ++i) + i->value->abort(); - NetworkBlobRegistry::singleton().connectionToWebProcessDidClose(this); - NetworkProcess::singleton().removeNetworkConnectionToWebProcess(this); -} + NetworkBlobRegistry::shared().connectionToWebProcessDidClose(this); -void NetworkConnectionToWebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference) -{ + m_networkResourceLoaders.clear(); + + NetworkProcess::shared().removeNetworkConnectionToWebProcess(this); } -void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters) +void NetworkConnectionToWebProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference) { - auto loader = NetworkResourceLoader::create(loadParameters, *this); - m_networkResourceLoaders.add(loadParameters.identifier, loader.ptr()); - loader->start(); } -void NetworkConnectionToWebProcess::performSynchronousLoad(const NetworkResourceLoadParameters& loadParameters, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply) +void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters) { - auto loader = NetworkResourceLoader::create(loadParameters, *this, WTFMove(reply)); - m_networkResourceLoaders.add(loadParameters.identifier, loader.ptr()); - loader->start(); + RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, this); + m_networkResourceLoaders.add(loadParameters.identifier, loader); + NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get()); } -void NetworkConnectionToWebProcess::loadPing(const NetworkResourceLoadParameters& loadParameters) +void NetworkConnectionToWebProcess::performSynchronousLoad(const NetworkResourceLoadParameters& loadParameters, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) { - RefPtr<NetworkingContext> context = RemoteNetworkingContext::create(loadParameters.sessionID, loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect); - - // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled. - new PingHandle(context.get(), loadParameters.request, loadParameters.allowStoredCredentials == AllowStoredCredentials, PingHandle::UsesAsyncCallbacks::Yes); + RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, this, reply); + m_networkResourceLoaders.add(loadParameters.identifier, loader); + NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get()); } void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier) { - RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier); + RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.take(identifier); // It's possible we have no loader for this identifier if the NetworkProcess crashed and this was a respawned NetworkProcess. if (!loader) @@ -147,29 +136,24 @@ void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier // Abort the load now, as the WebProcess won't be able to respond to messages any more which might lead // to leaked loader resources (connections, threads, etc). loader->abort(); - ASSERT(!m_networkResourceLoaders.contains(identifier)); } -void NetworkConnectionToWebProcess::setDefersLoading(ResourceLoadIdentifier identifier, bool defers) +void NetworkConnectionToWebProcess::servePendingRequests(uint32_t resourceLoadPriority) { - RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier); - if (!loader) - return; - - loader->setDefersLoading(defers); + NetworkProcess::shared().networkResourceLoadScheduler().servePendingRequests(static_cast<ResourceLoadPriority>(resourceLoadPriority)); } -void NetworkConnectionToWebProcess::prefetchDNS(const String& hostname) +void NetworkConnectionToWebProcess::setSerialLoadingEnabled(bool enabled) { - NetworkProcess::singleton().prefetchDNS(hostname); + m_serialLoadingEnabled = enabled; } -static NetworkStorageSession& storageSession(SessionID sessionID) +static NetworkStorageSession& storageSession(uint64_t sessionID) { - if (sessionID.isEphemeral()) { - NetworkStorageSession* privateStorageSession = SessionTracker::storageSession(sessionID); - if (privateStorageSession) - return *privateStorageSession; + if (SessionTracker::isEphemeralID(sessionID)) { + NetworkStorageSession* privateSession = SessionTracker::session(sessionID); + if (privateSession) + return *privateSession; // Some requests with private browsing mode requested may still be coming shortly after NetworkProcess was told to destroy its session. // FIXME: Find a way to track private browsing sessions more rigorously. LOG_ERROR("Private browsing was requested, but there was no session for it. Please file a bug unless you just disabled private browsing, in which case it's an expected race."); @@ -177,97 +161,79 @@ static NetworkStorageSession& storageSession(SessionID sessionID) return NetworkStorageSession::defaultStorageSession(); } -void NetworkConnectionToWebProcess::startDownload(SessionID sessionID, DownloadID downloadID, const ResourceRequest& request) +void NetworkConnectionToWebProcess::startDownload(uint64_t sessionID, uint64_t downloadID, const ResourceRequest& request) { - NetworkProcess::singleton().downloadManager().startDownload(sessionID, downloadID, request); + // FIXME: Do something with the session ID. + NetworkProcess::shared().downloadManager().startDownload(downloadID, request); } -void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(SessionID sessionID, uint64_t mainResourceLoadIdentifier, DownloadID downloadID, const ResourceRequest& request, const ResourceResponse& response) +void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, const ResourceRequest& request, const ResourceResponse& response) { - auto& networkProcess = NetworkProcess::singleton(); if (!mainResourceLoadIdentifier) { - networkProcess.downloadManager().startDownload(sessionID, downloadID, request); + NetworkProcess::shared().downloadManager().startDownload(downloadID, request); return; } NetworkResourceLoader* loader = m_networkResourceLoaders.get(mainResourceLoadIdentifier); - if (!loader) { - // If we're trying to download a blob here loader can be null. - return; - } - -#if USE(NETWORK_SESSION) - loader->networkLoad()->convertTaskToDownload(downloadID); -#else - networkProcess.downloadManager().convertHandleToDownload(downloadID, loader->networkLoad()->handle(), request, response); + NetworkProcess::shared().downloadManager().convertHandleToDownload(downloadID, loader->handle(), request, response); // Unblock the URL connection operation queue. - loader->networkLoad()->handle()->continueDidReceiveResponse(); + loader->handle()->continueDidReceiveResponse(); - loader->didConvertToDownload(); -#endif + loader->didConvertHandleToDownload(); } -void NetworkConnectionToWebProcess::cookiesForDOM(SessionID sessionID, const URL& firstParty, const URL& url, String& result) +void NetworkConnectionToWebProcess::cookiesForDOM(uint64_t sessionID, const URL& firstParty, const URL& url, String& result) { result = WebCore::cookiesForDOM(storageSession(sessionID), firstParty, url); } -void NetworkConnectionToWebProcess::setCookiesFromDOM(SessionID sessionID, const URL& firstParty, const URL& url, const String& cookieString) +void NetworkConnectionToWebProcess::setCookiesFromDOM(uint64_t sessionID, const URL& firstParty, const URL& url, const String& cookieString) { WebCore::setCookiesFromDOM(storageSession(sessionID), firstParty, url, cookieString); } -void NetworkConnectionToWebProcess::cookiesEnabled(SessionID sessionID, const URL& firstParty, const URL& url, bool& result) +void NetworkConnectionToWebProcess::cookiesEnabled(uint64_t sessionID, const URL& firstParty, const URL& url, bool& result) { result = WebCore::cookiesEnabled(storageSession(sessionID), firstParty, url); } -void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(SessionID sessionID, const URL& firstParty, const URL& url, String& result) +void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(uint64_t sessionID, const URL& firstParty, const URL& url, String& result) { result = WebCore::cookieRequestHeaderFieldValue(storageSession(sessionID), firstParty, url); } -void NetworkConnectionToWebProcess::getRawCookies(SessionID sessionID, const URL& firstParty, const URL& url, Vector<Cookie>& result) +void NetworkConnectionToWebProcess::getRawCookies(uint64_t sessionID, const URL& firstParty, const URL& url, Vector<Cookie>& result) { WebCore::getRawCookies(storageSession(sessionID), firstParty, url, result); } -void NetworkConnectionToWebProcess::deleteCookie(SessionID sessionID, const URL& url, const String& cookieName) +void NetworkConnectionToWebProcess::deleteCookie(uint64_t sessionID, const URL& url, const String& cookieName) { WebCore::deleteCookie(storageSession(sessionID), url, cookieName); } -void NetworkConnectionToWebProcess::registerFileBlobURL(const URL& url, const String& path, const SandboxExtension::Handle& extensionHandle, const String& contentType) +void NetworkConnectionToWebProcess::registerBlobURL(const URL& url, const BlobRegistrationData& data) { - RefPtr<SandboxExtension> extension = SandboxExtension::create(extensionHandle); - - NetworkBlobRegistry::singleton().registerFileBlobURL(this, url, path, WTFMove(extension), contentType); -} + Vector<RefPtr<SandboxExtension>> extensions; + for (size_t i = 0, count = data.sandboxExtensions().size(); i < count; ++i) { + if (RefPtr<SandboxExtension> extension = SandboxExtension::create(data.sandboxExtensions()[i])) + extensions.append(extension); + } -void NetworkConnectionToWebProcess::registerBlobURL(const URL& url, Vector<BlobPart> blobParts, const String& contentType) -{ - NetworkBlobRegistry::singleton().registerBlobURL(this, url, WTFMove(blobParts), contentType); + NetworkBlobRegistry::shared().registerBlobURL(this, url, data.releaseData(), extensions); } void NetworkConnectionToWebProcess::registerBlobURLFromURL(const URL& url, const URL& srcURL) { - NetworkBlobRegistry::singleton().registerBlobURL(this, url, srcURL); -} - -void NetworkConnectionToWebProcess::registerBlobURLForSlice(const URL& url, const URL& srcURL, int64_t start, int64_t end) -{ - NetworkBlobRegistry::singleton().registerBlobURLForSlice(this, url, srcURL, start, end); + NetworkBlobRegistry::shared().registerBlobURL(this, url, srcURL); } void NetworkConnectionToWebProcess::unregisterBlobURL(const URL& url) { - NetworkBlobRegistry::singleton().unregisterBlobURL(this, url); -} - -void NetworkConnectionToWebProcess::blobSize(const URL& url, uint64_t& resultSize) -{ - resultSize = NetworkBlobRegistry::singleton().blobSize(this, url); + NetworkBlobRegistry::shared().unregisterBlobURL(this, url); } } // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h index c80f08a58..3981fa5eb 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h @@ -26,9 +26,10 @@ #ifndef NetworkConnectionToWebProcess_h #define NetworkConnectionToWebProcess_h +#if ENABLE(NETWORK_PROCESS) + #include "BlockingResponseMap.h" #include "Connection.h" -#include "DownloadID.h" #include "NetworkConnectionToWebProcessMessages.h" #include <WebCore/ResourceLoadPriority.h> #include <wtf/HashSet.h> @@ -40,6 +41,7 @@ class ResourceRequest; namespace WebKit { +class BlobRegistrationData; class NetworkConnectionToWebProcess; class NetworkResourceLoader; class SyncNetworkResourceLoader; @@ -47,58 +49,56 @@ typedef uint64_t ResourceLoadIdentifier; class NetworkConnectionToWebProcess : public RefCounted<NetworkConnectionToWebProcess>, IPC::Connection::Client { public: - static Ref<NetworkConnectionToWebProcess> create(IPC::Connection::Identifier); + static PassRefPtr<NetworkConnectionToWebProcess> create(IPC::Connection::Identifier); virtual ~NetworkConnectionToWebProcess(); IPC::Connection* connection() const { return m_connection.get(); } - void didCleanupResourceLoader(NetworkResourceLoader&); + bool isSerialLoadingEnabled() const { return m_serialLoadingEnabled; } private: NetworkConnectionToWebProcess(IPC::Connection::Identifier); // IPC::Connection::Client - virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override; - virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override; - virtual void didClose(IPC::Connection&) override; - virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override; - virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Network; } - virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::Web; } + virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&); + virtual void didReceiveSyncMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&); + virtual void didClose(IPC::Connection*); + virtual void didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference messageReceiverName, IPC::StringReference messageName); // Message handlers. - void didReceiveNetworkConnectionToWebProcessMessage(IPC::Connection&, IPC::MessageDecoder&); - void didReceiveSyncNetworkConnectionToWebProcessMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&); + void didReceiveNetworkConnectionToWebProcessMessage(IPC::Connection*, IPC::MessageDecoder&); + void didReceiveSyncNetworkConnectionToWebProcessMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&); void scheduleResourceLoad(const NetworkResourceLoadParameters&); - void performSynchronousLoad(const NetworkResourceLoadParameters&, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&&); - void loadPing(const NetworkResourceLoadParameters&); - void prefetchDNS(const String&); + void performSynchronousLoad(const NetworkResourceLoadParameters&, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>); void removeLoadIdentifier(ResourceLoadIdentifier); - void setDefersLoading(ResourceLoadIdentifier, bool); void crossOriginRedirectReceived(ResourceLoadIdentifier, const WebCore::URL& redirectURL); - void startDownload(WebCore::SessionID, DownloadID, const WebCore::ResourceRequest&); - void convertMainResourceLoadToDownload(WebCore::SessionID, uint64_t mainResourceLoadIdentifier, DownloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); - - void cookiesForDOM(WebCore::SessionID, const WebCore::URL& firstParty, const WebCore::URL&, String& result); - void setCookiesFromDOM(WebCore::SessionID, const WebCore::URL& firstParty, const WebCore::URL&, const String&); - void cookiesEnabled(WebCore::SessionID, const WebCore::URL& firstParty, const WebCore::URL&, bool& result); - void cookieRequestHeaderFieldValue(WebCore::SessionID, const WebCore::URL& firstParty, const WebCore::URL&, String& result); - void getRawCookies(WebCore::SessionID, const WebCore::URL& firstParty, const WebCore::URL&, Vector<WebCore::Cookie>&); - void deleteCookie(WebCore::SessionID, const WebCore::URL&, const String& cookieName); - - void registerFileBlobURL(const WebCore::URL&, const String& path, const SandboxExtension::Handle&, const String& contentType); - void registerBlobURL(const WebCore::URL&, Vector<WebCore::BlobPart>, const String& contentType); + void servePendingRequests(uint32_t resourceLoadPriority); + void setSerialLoadingEnabled(bool); + void startDownload(uint64_t sessionID, uint64_t downloadID, const WebCore::ResourceRequest&); + void convertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + + void cookiesForDOM(uint64_t sessionID, const WebCore::URL& firstParty, const WebCore::URL&, String& result); + void setCookiesFromDOM(uint64_t sessionID, const WebCore::URL& firstParty, const WebCore::URL&, const String&); + void cookiesEnabled(uint64_t sessionID, const WebCore::URL& firstParty, const WebCore::URL&, bool& result); + void cookieRequestHeaderFieldValue(uint64_t sessionID, const WebCore::URL& firstParty, const WebCore::URL&, String& result); + void getRawCookies(uint64_t sessionID, const WebCore::URL& firstParty, const WebCore::URL&, Vector<WebCore::Cookie>&); + void deleteCookie(uint64_t sessionID, const WebCore::URL&, const String& cookieName); + + void registerBlobURL(const WebCore::URL&, const BlobRegistrationData&); void registerBlobURLFromURL(const WebCore::URL&, const WebCore::URL& srcURL); - void registerBlobURLForSlice(const WebCore::URL&, const WebCore::URL& srcURL, int64_t start, int64_t end); - void blobSize(const WebCore::URL&, uint64_t& resultSize); void unregisterBlobURL(const WebCore::URL&); RefPtr<IPC::Connection> m_connection; HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>> m_networkResourceLoaders; + + bool m_serialLoadingEnabled; }; } // namespace WebKit +#endif // ENABLE(NETWORK_PROCESS) + #endif // NetworkConnectionToWebProcess_h diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in index 03fdd92fd..a4597fcd2 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in @@ -20,29 +20,31 @@ # 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. +#if ENABLE(NETWORK_PROCESS) + messages -> NetworkConnectionToWebProcess LegacyReceiver { ScheduleResourceLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) PerformSynchronousLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) -> (WebCore::ResourceError error, WebCore::ResourceResponse response, Vector<char> data) Delayed - LoadPing(WebKit::NetworkResourceLoadParameters resourceLoadParameters) RemoveLoadIdentifier(uint64_t resourceLoadIdentifier) - SetDefersLoading(uint64_t resourceLoadIdentifier, bool defers) - PrefetchDNS(String hostname) + + ServePendingRequests(uint32_t resourceLoadPriority) + + SetSerialLoadingEnabled(bool enabled) -> () - StartDownload(WebCore::SessionID sessionID, WebKit::DownloadID downloadID, WebCore::ResourceRequest request) - ConvertMainResourceLoadToDownload(WebCore::SessionID sessionID, uint64_t mainResourceLoadIdentifier, WebKit::DownloadID downloadID, WebCore::ResourceRequest request, WebCore::ResourceResponse response) + StartDownload(uint64_t sessionID, uint64_t downloadID, WebCore::ResourceRequest request) + ConvertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, WebCore::ResourceRequest request, WebCore::ResourceResponse response) - CookiesForDOM(WebCore::SessionID sessionID, WebCore::URL firstParty, WebCore::URL url) -> (String result) - SetCookiesFromDOM(WebCore::SessionID sessionID, WebCore::URL firstParty, WebCore::URL url, String cookieString) - CookiesEnabled(WebCore::SessionID sessionID, WebCore::URL firstParty, WebCore::URL url) -> (bool enabled) - CookieRequestHeaderFieldValue(WebCore::SessionID sessionID, WebCore::URL firstParty, WebCore::URL url) -> (String result) - GetRawCookies(WebCore::SessionID sessionID, WebCore::URL firstParty, WebCore::URL url) -> (Vector<WebCore::Cookie> cookies) - DeleteCookie(WebCore::SessionID sessionID, WebCore::URL url, String cookieName) + CookiesForDOM(uint64_t sessionID, WebCore::URL firstParty, WebCore::URL url) -> (String result) + SetCookiesFromDOM(uint64_t sessionID, WebCore::URL firstParty, WebCore::URL url, String cookieString) + CookiesEnabled(uint64_t sessionID, WebCore::URL firstParty, WebCore::URL url) -> (bool enabled) + CookieRequestHeaderFieldValue(uint64_t sessionID, WebCore::URL firstParty, WebCore::URL url) -> (String result) + GetRawCookies(uint64_t sessionID, WebCore::URL firstParty, WebCore::URL url) -> (Vector<WebCore::Cookie> cookies) + DeleteCookie(uint64_t sessionID, WebCore::URL url, String cookieName) - RegisterFileBlobURL(WebCore::URL url, String path, WebKit::SandboxExtension::Handle extensionHandle, String contentType) - RegisterBlobURL(WebCore::URL url, Vector<WebCore::BlobPart> blobParts, String contentType) + RegisterBlobURL(WebCore::URL url, WebKit::BlobRegistrationData data) RegisterBlobURLFromURL(WebCore::URL url, WebCore::URL srcURL) - RegisterBlobURLForSlice(WebCore::URL url, WebCore::URL srcURL, int64_t start, int64_t end) UnregisterBlobURL(WebCore::URL url) - BlobSize(WebCore::URL url) -> (uint64_t resultSize) } + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkDataTask.h b/Source/WebKit2/NetworkProcess/NetworkDataTask.h deleted file mode 100644 index 86482cb7a..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkDataTask.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2016 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 NetworkDataTask_h -#define NetworkDataTask_h - -#include <WebCore/FrameLoaderTypes.h> -#include <WebCore/ResourceHandleTypes.h> -#include <WebCore/ResourceLoaderOptions.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/Timer.h> -#include <wtf/RetainPtr.h> -#include <wtf/text/WTFString.h> - -#if PLATFORM(COCOA) -OBJC_CLASS NSURLSessionDataTask; -#endif - -namespace WebCore { -class AuthenticationChallenge; -class Credential; -class ResourceError; -class ResourceRequest; -class ResourceResponse; -class SharedBuffer; -} - -namespace WebKit { - -class NetworkSession; -class PendingDownload; - -enum class AuthenticationChallengeDisposition { - UseCredential, - PerformDefaultHandling, - Cancel, - RejectProtectionSpace -}; - -typedef std::function<void(const WebCore::ResourceRequest&)> RedirectCompletionHandler; -typedef std::function<void(AuthenticationChallengeDisposition, const WebCore::Credential&)> ChallengeCompletionHandler; -typedef std::function<void(WebCore::PolicyAction)> ResponseCompletionHandler; - -class NetworkDataTaskClient { -public: - virtual void willPerformHTTPRedirection(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, RedirectCompletionHandler) = 0; - virtual void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler) = 0; - virtual void didReceiveResponseNetworkSession(const WebCore::ResourceResponse&, ResponseCompletionHandler) = 0; - virtual void didReceiveData(RefPtr<WebCore::SharedBuffer>&&) = 0; - virtual void didCompleteWithError(const WebCore::ResourceError&) = 0; - virtual void didBecomeDownload() = 0; - virtual void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) = 0; - virtual void wasBlocked() = 0; - virtual void cannotShowURL() = 0; - - virtual ~NetworkDataTaskClient() { } -}; - -class NetworkDataTask : public RefCounted<NetworkDataTask> { - friend class NetworkSession; -public: - static Ref<NetworkDataTask> create(NetworkSession& session, NetworkDataTaskClient& client, const WebCore::ResourceRequest& request, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect) - { - return adoptRef(*new NetworkDataTask(session, client, request, storedCredentials, shouldContentSniff, shouldClearReferrerOnHTTPSToHTTPRedirect)); - } - - void suspend(); - void cancel(); - void resume(); - - typedef uint64_t TaskIdentifier; - TaskIdentifier taskIdentifier(); - - ~NetworkDataTask(); - - NetworkDataTaskClient& client() { return m_client; } - - DownloadID pendingDownloadID() { return m_pendingDownloadID; } - PendingDownload* pendingDownload() { return m_pendingDownload; } - void setPendingDownloadID(DownloadID downloadID) - { - ASSERT(!m_pendingDownloadID.downloadID()); - ASSERT(downloadID.downloadID()); - m_pendingDownloadID = downloadID; - } - void setPendingDownload(PendingDownload& pendingDownload) - { - ASSERT(!m_pendingDownload); - m_pendingDownload = &pendingDownload; - } - bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler); - void willPerformHTTPRedirection(const WebCore::ResourceResponse&, WebCore::ResourceRequest&&, RedirectCompletionHandler); - -private: - NetworkDataTask(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect); - - enum FailureType { - NoFailure, - BlockedFailure, - InvalidURLFailure - }; - FailureType m_scheduledFailureType { NoFailure }; - WebCore::Timer m_failureTimer; - void failureTimerFired(); - void scheduleFailure(FailureType); - - NetworkSession& m_session; - NetworkDataTaskClient& m_client; - PendingDownload* m_pendingDownload { nullptr }; - DownloadID m_pendingDownloadID; - String m_user; - String m_password; - String m_lastHTTPMethod; - WebCore::ResourceRequest m_firstRequest; - bool m_shouldClearReferrerOnHTTPSToHTTPRedirect; -#if PLATFORM(COCOA) - RetainPtr<NSURLSessionDataTask> m_task; -#endif -}; - -#if PLATFORM(COCOA) -WebCore::Credential serverTrustCredential(const WebCore::AuthenticationChallenge&); -#endif - -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/NetworkLoad.cpp b/Source/WebKit2/NetworkProcess/NetworkLoad.cpp deleted file mode 100644 index bf27fd306..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkLoad.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "NetworkLoad.h" - -#include "AuthenticationManager.h" -#include "NetworkProcess.h" -#include "SessionTracker.h" -#include "WebErrors.h" -#include <WebCore/NotImplemented.h> -#include <WebCore/ResourceHandle.h> -#include <WebCore/SessionID.h> -#include <wtf/MainThread.h> - -namespace WebKit { - -using namespace WebCore; - -NetworkLoad::NetworkLoad(NetworkLoadClient& client, const NetworkLoadParameters& parameters) - : m_client(client) - , m_parameters(parameters) -#if !USE(NETWORK_SESSION) - , m_networkingContext(RemoteNetworkingContext::create(parameters.sessionID, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect)) -#endif - , m_currentRequest(parameters.request) -{ -#if USE(NETWORK_SESSION) - if (parameters.request.url().protocolIsBlob()) { - m_handle = ResourceHandle::create(nullptr, parameters.request, this, parameters.defersLoading, parameters.contentSniffingPolicy == SniffContent); - return; - } - if (auto* networkSession = SessionTracker::networkSession(parameters.sessionID)) { - m_task = NetworkDataTask::create(*networkSession, *this, parameters.request, parameters.allowStoredCredentials, parameters.contentSniffingPolicy, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect); - if (!parameters.defersLoading) - m_task->resume(); - } else - ASSERT_NOT_REACHED(); -#else - m_handle = ResourceHandle::create(m_networkingContext.get(), parameters.request, this, parameters.defersLoading, parameters.contentSniffingPolicy == SniffContent); -#endif -} - -NetworkLoad::~NetworkLoad() -{ - ASSERT(RunLoop::isMain()); -#if USE(NETWORK_SESSION) - if (m_responseCompletionHandler) - m_responseCompletionHandler(PolicyIgnore); -#endif - if (m_handle) - m_handle->clearClient(); -} - -void NetworkLoad::setDefersLoading(bool defers) -{ -#if USE(NETWORK_SESSION) - if (m_task) { - if (defers) - m_task->suspend(); - else - m_task->resume(); - } -#endif - if (m_handle) - m_handle->setDefersLoading(defers); -} - -void NetworkLoad::cancel() -{ -#if USE(NETWORK_SESSION) - if (m_task) - m_task->cancel(); -#endif - if (m_handle) - m_handle->cancel(); -} - -void NetworkLoad::continueWillSendRequest(const WebCore::ResourceRequest& newRequest) -{ -#if PLATFORM(COCOA) - m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest.nsURLRequest(DoNotUpdateHTTPBody)); -#elif USE(SOUP) - // FIXME: Implement ResourceRequest::updateFromDelegatePreservingOldProperties. See https://bugs.webkit.org/show_bug.cgi?id=126127. - m_currentRequest.updateFromDelegatePreservingOldProperties(newRequest); -#endif - - if (m_currentRequest.isNull()) { - if (m_handle) - m_handle->cancel(); - didFail(m_handle.get(), cancelledError(m_currentRequest)); - } else if (m_handle) - m_handle->continueWillSendRequest(m_currentRequest); - -#if USE(NETWORK_SESSION) - ASSERT(m_redirectCompletionHandler); - if (m_redirectCompletionHandler) { - m_redirectCompletionHandler(m_currentRequest); - m_redirectCompletionHandler = nullptr; - } -#endif -} - -void NetworkLoad::continueDidReceiveResponse() -{ -#if USE(NETWORK_SESSION) - ASSERT(m_responseCompletionHandler); - if (m_responseCompletionHandler) { - m_responseCompletionHandler(PolicyUse); - m_responseCompletionHandler = nullptr; - } -#endif - if (m_handle) - m_handle->continueDidReceiveResponse(); -} - -NetworkLoadClient::ShouldContinueDidReceiveResponse NetworkLoad::sharedDidReceiveResponse(const ResourceResponse& receivedResponse) -{ - ResourceResponse response = receivedResponse; - response.setSource(ResourceResponse::Source::Network); - if (m_parameters.needsCertificateInfo) - response.includeCertificateInfo(); - - return m_client.didReceiveResponse(response); -} - -void NetworkLoad::sharedWillSendRedirectedRequest(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(RunLoop::isMain()); - - auto oldRequest = m_currentRequest; - m_currentRequest = request; - m_client.willSendRedirectedRequest(oldRequest, request, redirectResponse); -} - -#if USE(NETWORK_SESSION) - -void NetworkLoad::convertTaskToDownload(DownloadID downloadID) -{ - m_task->setPendingDownloadID(downloadID); - - ASSERT(m_responseCompletionHandler); - if (m_responseCompletionHandler) { - m_responseCompletionHandler(PolicyDownload); - m_responseCompletionHandler = nullptr; - } -} - -void NetworkLoad::setPendingDownloadID(DownloadID downloadID) -{ - m_task->setPendingDownloadID(downloadID); -} - -void NetworkLoad::setPendingDownload(PendingDownload& pendingDownload) -{ - m_task->setPendingDownload(pendingDownload); -} - -void NetworkLoad::willPerformHTTPRedirection(const ResourceResponse& response, const ResourceRequest& request, RedirectCompletionHandler completionHandler) -{ - ASSERT(!m_redirectCompletionHandler); - m_redirectCompletionHandler = completionHandler; - sharedWillSendRedirectedRequest(request, response); -} - -void NetworkLoad::didReceiveChallenge(const AuthenticationChallenge& challenge, std::function<void(AuthenticationChallengeDisposition, const Credential&)> completionHandler) -{ - // NetworkResourceLoader does not know whether the request is cross origin, so Web process computes an applicable credential policy for it. - ASSERT(m_parameters.clientCredentialPolicy != DoNotAskClientForCrossOriginCredentials); - - // Handle server trust evaluation at platform-level if requested, for performance reasons. - if (challenge.protectionSpace().authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested - && !NetworkProcess::singleton().canHandleHTTPSServerTrustEvaluation()) { - completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, Credential()); - return; - } - - m_challengeCompletionHandler = completionHandler; - m_challenge = challenge; - - if (m_client.isSynchronous()) { - // FIXME: We should ask the WebProcess like the asynchronous case below does. - // This is currently impossible as the WebProcess is blocked waiting on this synchronous load. - // It's possible that we can jump straight to the UI process to resolve this. - continueCanAuthenticateAgainstProtectionSpace(true); - return; - } else - m_client.canAuthenticateAgainstProtectionSpaceAsync(challenge.protectionSpace()); -} - -void NetworkLoad::didReceiveResponseNetworkSession(const ResourceResponse& response, ResponseCompletionHandler completionHandler) -{ - ASSERT(isMainThread()); - if (m_task && m_task->pendingDownloadID().downloadID()) - completionHandler(PolicyDownload); - else if (sharedDidReceiveResponse(response) == NetworkLoadClient::ShouldContinueDidReceiveResponse::Yes) - completionHandler(PolicyUse); - else - m_responseCompletionHandler = completionHandler; -} - -void NetworkLoad::didReceiveData(RefPtr<SharedBuffer>&& buffer) -{ - ASSERT(buffer); - auto size = buffer->size(); - m_client.didReceiveBuffer(WTFMove(buffer), size); -} - -void NetworkLoad::didCompleteWithError(const ResourceError& error) -{ - if (error.isNull()) - m_client.didFinishLoading(WTF::monotonicallyIncreasingTime()); - else - m_client.didFailLoading(error); -} - -void NetworkLoad::didBecomeDownload() -{ - m_client.didConvertToDownload(); -} - -void NetworkLoad::didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) -{ - m_client.didSendData(totalBytesSent, totalBytesExpectedToSend); -} - -void NetworkLoad::wasBlocked() -{ - m_client.didFailLoading(blockedError(m_currentRequest)); -} - -void NetworkLoad::cannotShowURL() -{ - m_client.didFailLoading(cannotShowURLError(m_currentRequest)); -} - -#endif - -void NetworkLoad::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& receivedResponse) -{ - ASSERT_UNUSED(handle, handle == m_handle); - if (sharedDidReceiveResponse(receivedResponse) == NetworkLoadClient::ShouldContinueDidReceiveResponse::Yes) - m_handle->continueDidReceiveResponse(); -} - -void NetworkLoad::didReceiveData(ResourceHandle*, const char* /* data */, unsigned /* length */, int /* encodedDataLength */) -{ - // The NetworkProcess should never get a didReceiveData callback. - // We should always be using didReceiveBuffer. - ASSERT_NOT_REACHED(); -} - -void NetworkLoad::didReceiveBuffer(ResourceHandle* handle, PassRefPtr<SharedBuffer> buffer, int reportedEncodedDataLength) -{ - ASSERT_UNUSED(handle, handle == m_handle); - m_client.didReceiveBuffer(WTFMove(buffer), reportedEncodedDataLength); -} - -void NetworkLoad::didFinishLoading(ResourceHandle* handle, double finishTime) -{ - ASSERT_UNUSED(handle, handle == m_handle); - m_client.didFinishLoading(finishTime); -} - -void NetworkLoad::didFail(ResourceHandle* handle, const ResourceError& error) -{ - ASSERT_UNUSED(handle, !handle || handle == m_handle); - ASSERT(!error.isNull()); - - m_client.didFailLoading(error); -} - -void NetworkLoad::willSendRequestAsync(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - ASSERT_UNUSED(handle, handle == m_handle); - sharedWillSendRedirectedRequest(request, redirectResponse); -} - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -void NetworkLoad::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle* handle, const ProtectionSpace& protectionSpace) -{ - ASSERT(RunLoop::isMain()); - ASSERT_UNUSED(handle, handle == m_handle); - - // Handle server trust evaluation at platform-level if requested, for performance reasons. - if (protectionSpace.authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested - && !NetworkProcess::singleton().canHandleHTTPSServerTrustEvaluation()) { - continueCanAuthenticateAgainstProtectionSpace(false); - return; - } - - if (m_client.isSynchronous()) { - // FIXME: We should ask the WebProcess like the asynchronous case below does. - // This is currently impossible as the WebProcess is blocked waiting on this synchronous load. - // It's possible that we can jump straight to the UI process to resolve this. - continueCanAuthenticateAgainstProtectionSpace(true); - return; - } - - m_client.canAuthenticateAgainstProtectionSpaceAsync(protectionSpace); -} -#endif - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -void NetworkLoad::continueCanAuthenticateAgainstProtectionSpace(bool result) -{ -#if USE(NETWORK_SESSION) - ASSERT_WITH_MESSAGE(!m_handle, "Blobs should never give authentication challenges"); - ASSERT(m_challengeCompletionHandler); - auto completionHandler = WTFMove(m_challengeCompletionHandler); - if (!result) { - completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, Credential()); - return; - } - - if (!m_challenge.protectionSpace().isPasswordBased()) { - completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(m_challenge)); - return; - } - - if (m_parameters.clientCredentialPolicy == DoNotAskClientForAnyCredentials) { - completionHandler(AuthenticationChallengeDisposition::UseCredential, Credential()); - return; - } - - if (m_task) { - if (auto* pendingDownload = m_task->pendingDownload()) - NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(*pendingDownload, m_challenge, completionHandler); - else - NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(m_parameters.webPageID, m_parameters.webFrameID, m_challenge, completionHandler); - } -#endif - if (m_handle) - m_handle->continueCanAuthenticateAgainstProtectionSpace(result); -} -#endif - -#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) -bool NetworkLoad::supportsDataArray() -{ - notImplemented(); - return false; -} - -void NetworkLoad::didReceiveDataArray(ResourceHandle*, CFArrayRef) -{ - ASSERT_NOT_REACHED(); - notImplemented(); -} -#endif - -void NetworkLoad::didSendData(ResourceHandle* handle, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - ASSERT_UNUSED(handle, handle == m_handle); - - m_client.didSendData(bytesSent, totalBytesToBeSent); -} - -void NetworkLoad::wasBlocked(ResourceHandle* handle) -{ - ASSERT_UNUSED(handle, handle == m_handle); - - didFail(handle, WebKit::blockedError(m_currentRequest)); -} - -void NetworkLoad::cannotShowURL(ResourceHandle* handle) -{ - ASSERT_UNUSED(handle, handle == m_handle); - - didFail(handle, WebKit::cannotShowURLError(m_currentRequest)); -} - -bool NetworkLoad::shouldUseCredentialStorage(ResourceHandle* handle) -{ - ASSERT_UNUSED(handle, handle == m_handle || !m_handle); // m_handle will be 0 if called from ResourceHandle::start(). - - // 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. - - // We still need this sync version, because ResourceHandle itself uses it internally, even when the delegate uses an async one. - - return m_parameters.allowStoredCredentials == AllowStoredCredentials; -} - -void NetworkLoad::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) -{ - ASSERT_UNUSED(handle, handle == m_handle); - // NetworkResourceLoader does not know whether the request is cross origin, so Web process computes an applicable credential policy for it. - ASSERT(m_parameters.clientCredentialPolicy != DoNotAskClientForCrossOriginCredentials); - - if (m_parameters.clientCredentialPolicy == DoNotAskClientForAnyCredentials) { - challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge); - return; - } - - NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(m_parameters.webPageID, m_parameters.webFrameID, challenge); -} - -void NetworkLoad::didCancelAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge&) -{ - ASSERT_UNUSED(handle, handle == m_handle); - - // This function is probably not needed (see <rdar://problem/8960124>). - notImplemented(); -} - -void NetworkLoad::receivedCancellation(ResourceHandle* handle, const AuthenticationChallenge&) -{ - ASSERT_UNUSED(handle, handle == m_handle); - - m_handle->cancel(); - didFail(m_handle.get(), cancelledError(m_currentRequest)); -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkLoad.h b/Source/WebKit2/NetworkProcess/NetworkLoad.h deleted file mode 100644 index 77164c2f2..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkLoad.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkLoad_h -#define NetworkLoad_h - -#include "NetworkLoadClient.h" -#include "NetworkLoadParameters.h" -#include "RemoteNetworkingContext.h" -#include <WebCore/ResourceHandleClient.h> - -#if USE(NETWORK_SESSION) -#include "DownloadID.h" -#include "NetworkSession.h" -#include <WebCore/AuthenticationChallenge.h> -#endif - -namespace WebKit { - -class NetworkLoad : public WebCore::ResourceHandleClient -#if USE(NETWORK_SESSION) - , public NetworkDataTaskClient -#endif -{ - WTF_MAKE_FAST_ALLOCATED; -public: - NetworkLoad(NetworkLoadClient&, const NetworkLoadParameters&); - ~NetworkLoad(); - - void setDefersLoading(bool); - void cancel(); - - const WebCore::ResourceRequest& currentRequest() const { return m_currentRequest; } - void clearCurrentRequest() { m_currentRequest = WebCore::ResourceRequest(); } - - void continueWillSendRequest(const WebCore::ResourceRequest&); - void continueDidReceiveResponse(); - -#if USE(NETWORK_SESSION) - void convertTaskToDownload(DownloadID); - void setPendingDownloadID(DownloadID); - void setPendingDownload(PendingDownload&); - DownloadID pendingDownloadID() { return m_task->pendingDownloadID(); } - - // NetworkDataTaskClient - virtual void willPerformHTTPRedirection(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, RedirectCompletionHandler) final override; - virtual void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler) final override; - virtual void didReceiveResponseNetworkSession(const WebCore::ResourceResponse&, ResponseCompletionHandler) final override; - virtual void didReceiveData(RefPtr<WebCore::SharedBuffer>&&) final override; - virtual void didCompleteWithError(const WebCore::ResourceError&) final override; - virtual void didBecomeDownload() final override; - virtual void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) override; - virtual void wasBlocked() override; - virtual void cannotShowURL() override; -#endif - // ResourceHandleClient - 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 didReceiveResponseAsync(WebCore::ResourceHandle*, const WebCore::ResourceResponse&) override; - virtual void didReceiveData(WebCore::ResourceHandle*, const char*, unsigned, int encodedDataLength) override; - virtual void didReceiveBuffer(WebCore::ResourceHandle*, PassRefPtr<WebCore::SharedBuffer>, int encodedDataLength) 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 didReceiveAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) override; - virtual void didCancelAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) override; - virtual void receivedCancellation(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) override; - virtual bool usesAsyncCallbacks() override { return true; } - virtual bool loadingSynchronousXHR() override { return m_client.isSynchronous(); } - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - virtual void canAuthenticateAgainstProtectionSpaceAsync(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&) override; -#endif -#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) - virtual bool supportsDataArray() override; - virtual void didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef) override; -#endif -#if PLATFORM(COCOA) -#if USE(CFNETWORK) - virtual void willCacheResponseAsync(WebCore::ResourceHandle*, CFCachedURLResponseRef) override; -#else - virtual void willCacheResponseAsync(WebCore::ResourceHandle*, NSCachedURLResponse *) override; -#endif -#endif - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - void continueCanAuthenticateAgainstProtectionSpace(bool); -#endif - -#if !USE(NETWORK_SESSION) - WebCore::ResourceHandle* handle() const { return m_handle.get(); } -#endif - -private: - NetworkLoadClient::ShouldContinueDidReceiveResponse sharedDidReceiveResponse(const WebCore::ResourceResponse&); - void sharedWillSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); - - NetworkLoadClient& m_client; - const NetworkLoadParameters m_parameters; -#if USE(NETWORK_SESSION) - RefPtr<NetworkDataTask> m_task; - WebCore::AuthenticationChallenge m_challenge; - ChallengeCompletionHandler m_challengeCompletionHandler; - ResponseCompletionHandler m_responseCompletionHandler; - RedirectCompletionHandler m_redirectCompletionHandler; -#else - RefPtr<RemoteNetworkingContext> m_networkingContext; -#endif - RefPtr<WebCore::ResourceHandle> m_handle; - - WebCore::ResourceRequest m_currentRequest; // Updated on redirects. -}; - -} // namespace WebKit - -#endif // NetworkLoad_h diff --git a/Source/WebKit2/NetworkProcess/NetworkLoadClient.h b/Source/WebKit2/NetworkProcess/NetworkLoadClient.h deleted file mode 100644 index e454738a8..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkLoadClient.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkLoadClient_h -#define NetworkLoadClient_h - -#include <WebCore/ResourceError.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/ResourceResponse.h> -#include <WebCore/SharedBuffer.h> -#include <wtf/Forward.h> - -#if PLATFORM(COCOA) -typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef; -#endif - -namespace WebCore { -class ProtectionSpace; -} - -namespace WebKit { - -class NetworkLoadClient { -public: - virtual ~NetworkLoadClient() { } - - virtual bool isSynchronous() const = 0; - - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0; - virtual void canAuthenticateAgainstProtectionSpaceAsync(const WebCore::ProtectionSpace&) = 0; - virtual void willSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse& redirectResponse) = 0; - enum class ShouldContinueDidReceiveResponse { No, Yes }; - virtual ShouldContinueDidReceiveResponse didReceiveResponse(const WebCore::ResourceResponse&) = 0; - virtual void didReceiveBuffer(RefPtr<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) = 0; - virtual void didFinishLoading(double finishTime) = 0; - virtual void didFailLoading(const WebCore::ResourceError&) = 0; - virtual void didConvertToDownload() = 0; - -#if PLATFORM(COCOA) - virtual void willCacheResponseAsync(CFCachedURLResponseRef) = 0; -#endif -}; - -} // namespace WebKit - -#endif // NetworkLoadClient_h - diff --git a/Source/WebKit2/NetworkProcess/NetworkLoadParameters.cpp b/Source/WebKit2/NetworkProcess/NetworkLoadParameters.cpp deleted file mode 100644 index cc8487555..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkLoadParameters.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkLoadParameters.h" - -#include "NetworkResourceLoadParameters.h" - -namespace WebKit { - -NetworkLoadParameters::NetworkLoadParameters(const NetworkResourceLoadParameters& parameters) - : webPageID(parameters.webPageID) - , webFrameID(parameters.webFrameID) - , sessionID(parameters.sessionID) - , request(parameters.request) - , contentSniffingPolicy(parameters.contentSniffingPolicy) - , allowStoredCredentials(parameters.allowStoredCredentials) - , clientCredentialPolicy(parameters.clientCredentialPolicy) - , shouldClearReferrerOnHTTPSToHTTPRedirect(parameters.shouldClearReferrerOnHTTPSToHTTPRedirect) - , defersLoading(parameters.defersLoading) - , needsCertificateInfo(parameters.needsCertificateInfo) -{ -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkSession.h b/Source/WebKit2/NetworkProcess/NetworkLoaderClient.h index 083ed96fe..e6d6b889c 100644 --- a/Source/WebKit2/NetworkProcess/NetworkSession.h +++ b/Source/WebKit2/NetworkProcess/NetworkLoaderClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * 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 @@ -23,54 +23,47 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NetworkSession_h -#define NetworkSession_h +#ifndef NetworkLoaderClient_h +#define NetworkLoaderClient_h -#if PLATFORM(COCOA) -OBJC_CLASS NSURLSession; -OBJC_CLASS NSOperationQueue; -OBJC_CLASS WKNetworkSessionDelegate; -#endif - -#include "DownloadID.h" -#include "NetworkDataTask.h" -#include <WebCore/SessionID.h> -#include <wtf/HashMap.h> -#include <wtf/Ref.h> #include <wtf/RefCounted.h> +#if ENABLE(NETWORK_PROCESS) + +namespace WebCore { +class ProtectionSpace; +class ResourceError; +class ResourceRequest; +class ResourceResponse; +class SharedBuffer; +} + namespace WebKit { -class CustomProtocolManager; +class NetworkResourceLoader; -class NetworkSession { - friend class NetworkDataTask; +class NetworkLoaderClient { public: - enum class Type { - Normal, - Ephemeral - }; - NetworkSession(Type, WebCore::SessionID, CustomProtocolManager*); - ~NetworkSession(); + virtual ~NetworkLoaderClient() { } - static NetworkSession& defaultSession(); + virtual void willSendRequest(NetworkResourceLoader*, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse) = 0; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual void canAuthenticateAgainstProtectionSpace(NetworkResourceLoader*, const WebCore::ProtectionSpace&) = 0; +#endif + virtual void didReceiveResponse(NetworkResourceLoader*, const WebCore::ResourceResponse&) = 0; + virtual void didReceiveBuffer(NetworkResourceLoader*, WebCore::SharedBuffer*, int encodedDataLength) = 0; + virtual void didSendData(NetworkResourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0; + virtual void didFinishLoading(NetworkResourceLoader*, double finishTime) = 0; + virtual void didFail(NetworkResourceLoader*, const WebCore::ResourceError&) = 0; - NetworkDataTask* dataTaskForIdentifier(NetworkDataTask::TaskIdentifier); + virtual bool isSynchronous() { return false; } - void addDownloadID(NetworkDataTask::TaskIdentifier, DownloadID); - DownloadID downloadID(NetworkDataTask::TaskIdentifier); - DownloadID takeDownloadID(NetworkDataTask::TaskIdentifier); - -private: - HashMap<NetworkDataTask::TaskIdentifier, NetworkDataTask*> m_dataTaskMap; - HashMap<NetworkDataTask::TaskIdentifier, DownloadID> m_downloadMap; -#if PLATFORM(COCOA) - RetainPtr<NSURLSession> m_sessionWithCredentialStorage; - RetainPtr<NSURLSession> m_sessionWithoutCredentialStorage; - RetainPtr<WKNetworkSessionDelegate> m_sessionDelegate; -#endif +protected: + NetworkLoaderClient() { } }; } // namespace WebKit -#endif // NetworkSession_h +#endif // ENABLE(NETWORK_PROCESS) + +#endif // NetworkLoaderClient_h diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.cpp b/Source/WebKit2/NetworkProcess/NetworkProcess.cpp index 15ee4a8f5..9c1c1cc1e 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * 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 @@ -26,10 +26,11 @@ #include "config.h" #include "NetworkProcess.h" +#if ENABLE(NETWORK_PROCESS) + #include "ArgumentCoders.h" #include "Attachment.h" #include "AuthenticationManager.h" -#include "ChildProcessMessages.h" #include "CustomProtocolManager.h" #include "Logging.h" #include "NetworkConnectionToWebProcess.h" @@ -40,17 +41,10 @@ #include "RemoteNetworkingContext.h" #include "SessionTracker.h" #include "StatisticsData.h" +#include "WebContextMessages.h" #include "WebCookieManager.h" -#include "WebProcessPoolMessages.h" -#include "WebsiteData.h" -#include <WebCore/DNS.h> -#include <WebCore/DiagnosticLoggingClient.h> #include <WebCore/Logging.h> -#include <WebCore/PlatformCookieJar.h> #include <WebCore/ResourceRequest.h> -#include <WebCore/SecurityOriginData.h> -#include <WebCore/SecurityOriginHash.h> -#include <WebCore/SessionID.h> #include <wtf/RunLoop.h> #include <wtf/text/CString.h> @@ -58,16 +52,11 @@ #include "SecItemShim.h" #endif -#if ENABLE(NETWORK_CACHE) -#include "NetworkCache.h" -#include "NetworkCacheCoders.h" -#endif - using namespace WebCore; namespace WebKit { -NetworkProcess& NetworkProcess::singleton() +NetworkProcess& NetworkProcess::shared() { static NeverDestroyed<NetworkProcess> networkProcess; return networkProcess; @@ -76,20 +65,17 @@ NetworkProcess& NetworkProcess::singleton() NetworkProcess::NetworkProcess() : m_hasSetCacheModel(false) , m_cacheModel(CacheModelDocumentViewer) - , m_diskCacheIsDisabledForTesting(false) - , m_canHandleHTTPSServerTrustEvaluation(true) -#if PLATFORM(COCOA) +#if PLATFORM(MAC) , m_clearCacheDispatchGroup(0) #endif -#if PLATFORM(IOS) - , m_webSQLiteDatabaseTracker(*this) -#endif { NetworkProcessPlatformStrategies::initialize(); addSupplement<AuthenticationManager>(); addSupplement<WebCookieManager>(); +#if ENABLE(CUSTOM_PROTOCOLS) addSupplement<CustomProtocolManager>(); +#endif } NetworkProcess::~NetworkProcess() @@ -103,7 +89,7 @@ AuthenticationManager& NetworkProcess::authenticationManager() DownloadManager& NetworkProcess::downloadManager() { - static NeverDestroyed<DownloadManager> downloadManager(*this); + static NeverDestroyed<DownloadManager> downloadManager(this); return downloadManager; } @@ -121,36 +107,28 @@ bool NetworkProcess::shouldTerminate() return false; } -void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder) +void NetworkProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder) { if (messageReceiverMap().dispatchMessage(connection, decoder)) return; - if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) { - ChildProcess::didReceiveMessage(connection, decoder); - return; - } - didReceiveNetworkProcessMessage(connection, decoder); } -void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) +void NetworkProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder) { - if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder)) - return; - - didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder); + messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder); } -void NetworkProcess::didClose(IPC::Connection&) +void NetworkProcess::didClose(IPC::Connection*) { // The UIProcess just exited. - RunLoop::current().stop(); + RunLoop::current()->stop(); } -void NetworkProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference) +void NetworkProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference) { - RunLoop::current().stop(); + RunLoop::current()->stop(); } void NetworkProcess::didCreateDownload() @@ -173,38 +151,19 @@ AuthenticationManager& NetworkProcess::downloadsAuthenticationManager() return authenticationManager(); } -void NetworkProcess::lowMemoryHandler(Critical critical) -{ - platformLowMemoryHandler(critical); - WTF::releaseFastMallocFreeMemory(); -} - void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters) { platformInitializeNetworkProcess(parameters); - WTF::setCurrentThreadIsUserInitiated(); - - auto& memoryPressureHandler = MemoryPressureHandler::singleton(); - memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) { - lowMemoryHandler(critical); - }); - memoryPressureHandler.install(); - - m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession; - - m_diskCacheSizeOverride = parameters.diskCacheSizeOverride; setCacheModel(static_cast<uint32_t>(parameters.cacheModel)); - setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation); - -#if PLATFORM(COCOA) || USE(CFNETWORK) +#if PLATFORM(MAC) || USE(CFNETWORK) SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier); #endif // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions) if (parameters.privateBrowsingEnabled) - RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()); + RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionTracker::legacyPrivateSessionID); if (parameters.shouldUseTestingNetworkSession) NetworkStorageSession::switchToNewTestingSession(); @@ -220,7 +179,7 @@ void NetworkProcess::initializeConnection(IPC::Connection* connection) ChildProcess::initializeConnection(connection); #if ENABLE(SEC_ITEM_SHIM) - SecItemShim::singleton().initializeConnection(connection); + SecItemShim::shared().initializeConnection(connection); #endif NetworkProcessSupplementMap::const_iterator it = m_supplements.begin(); @@ -231,15 +190,7 @@ void NetworkProcess::initializeConnection(IPC::Connection* connection) void NetworkProcess::createNetworkConnectionToWebProcess() { -#if USE(UNIX_DOMAIN_SOCKETS) - IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection(); - - RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(socketPair.server); - m_webProcessConnections.append(connection.release()); - - IPC::Attachment clientSocket(socketPair.client); - parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0); -#elif OS(DARWIN) +#if PLATFORM(MAC) // Create the listening port. mach_port_t listeningPort; mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort); @@ -250,219 +201,38 @@ void NetworkProcess::createNetworkConnectionToWebProcess() IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND); parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0); +#elif USE(UNIX_DOMAIN_SOCKETS) + IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection(); + + RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(socketPair.server); + m_webProcessConnections.append(connection.release()); + + IPC::Attachment clientSocket(socketPair.client); + parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0); #else notImplemented(); #endif } -void NetworkProcess::clearCachedCredentials() -{ - NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials(); -} - -void NetworkProcess::ensurePrivateBrowsingSession(SessionID sessionID) +void NetworkProcess::ensurePrivateBrowsingSession(uint64_t sessionID) { RemoteNetworkingContext::ensurePrivateBrowsingSession(sessionID); } -void NetworkProcess::destroyPrivateBrowsingSession(SessionID sessionID) +void NetworkProcess::destroyPrivateBrowsingSession(uint64_t sessionID) { SessionTracker::destroySession(sessionID); } -static void fetchDiskCacheEntries(SessionID sessionID, std::function<void (Vector<WebsiteData::Entry>)> completionHandler) -{ -#if ENABLE(NETWORK_CACHE) - if (NetworkCache::singleton().isEnabled()) { - auto* origins = new HashSet<RefPtr<SecurityOrigin>>(); - - NetworkCache::singleton().traverse([completionHandler, origins](const NetworkCache::Cache::TraversalEntry *traversalEntry) { - if (!traversalEntry) { - Vector<WebsiteData::Entry> entries; - - for (auto& origin : *origins) - entries.append(WebsiteData::Entry { origin, WebsiteDataTypeDiskCache }); - - delete origins; - - RunLoop::main().dispatch([completionHandler, entries] { - completionHandler(entries); - }); - - return; - } - - origins->add(SecurityOrigin::create(traversalEntry->entry.response().url())); - }); - - return; - } -#endif - - Vector<WebsiteData::Entry> entries; - -#if USE(CFURLCACHE) - for (auto& origin : NetworkProcess::cfURLCacheOrigins()) - entries.append(WebsiteData::Entry { WTFMove(origin), WebsiteDataTypeDiskCache }); -#endif - - RunLoop::main().dispatch([completionHandler, entries] { - completionHandler(entries); - }); -} - -void NetworkProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID) -{ - struct CallbackAggregator final : public RefCounted<CallbackAggregator> { - explicit CallbackAggregator(std::function<void (WebsiteData)> completionHandler) - : m_completionHandler(WTFMove(completionHandler)) - { - } - - ~CallbackAggregator() - { - ASSERT(RunLoop::isMain()); - - auto completionHandler = WTFMove(m_completionHandler); - auto websiteData = WTFMove(m_websiteData); - - RunLoop::main().dispatch([completionHandler, websiteData] { - completionHandler(websiteData); - }); - } - - std::function<void (WebsiteData)> m_completionHandler; - WebsiteData m_websiteData; - }; - - RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID](WebsiteData websiteData) { - parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0); - })); - - if (websiteDataTypes & WebsiteDataTypeCookies) { - if (auto* networkStorageSession = SessionTracker::storageSession(sessionID)) - getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies); - } - - if (websiteDataTypes & WebsiteDataTypeDiskCache) { - fetchDiskCacheEntries(sessionID, [callbackAggregator](Vector<WebsiteData::Entry> entries) { - callbackAggregator->m_websiteData.entries.appendVector(entries); - }); - } -} - -void NetworkProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID) +void NetworkProcess::downloadRequest(uint64_t downloadID, const ResourceRequest& request) { -#if PLATFORM(COCOA) - if (websiteDataTypes & WebsiteDataTypeHSTSCache) { - if (auto* networkStorageSession = SessionTracker::storageSession(sessionID)) - clearHSTSCache(*networkStorageSession, modifiedSince); - } -#endif - - if (websiteDataTypes & WebsiteDataTypeCookies) { - if (auto* networkStorageSession = SessionTracker::storageSession(sessionID)) - deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince); - } - - auto completionHandler = [this, callbackID] { - parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0); - }; - - if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) { - clearDiskCache(modifiedSince, WTFMove(completionHandler)); - return; - } - - completionHandler(); + downloadManager().startDownload(downloadID, request); } -static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, std::function<void ()> completionHandler) -{ -#if ENABLE(NETWORK_CACHE) - if (NetworkCache::singleton().isEnabled()) { - auto* originsToDelete = new HashSet<RefPtr<SecurityOrigin>>(); - - for (auto& origin : origins) - originsToDelete->add(origin.securityOrigin()); - - auto* cacheKeysToDelete = new Vector<NetworkCache::Key>; - - NetworkCache::singleton().traverse([completionHandler, originsToDelete, cacheKeysToDelete](const NetworkCache::Cache::TraversalEntry *traversalEntry) { - - if (traversalEntry) { - if (originsToDelete->contains(SecurityOrigin::create(traversalEntry->entry.response().url()))) - cacheKeysToDelete->append(traversalEntry->entry.key()); - return; - } - - delete originsToDelete; - - for (auto& key : *cacheKeysToDelete) - NetworkCache::singleton().remove(key); - - delete cacheKeysToDelete; - - RunLoop::main().dispatch(completionHandler); - return; - }); - - return; - } -#endif - -#if USE(CFURLCACHE) - NetworkProcess::clearCFURLCacheForOrigins(origins); -#endif - - RunLoop::main().dispatch(WTFMove(completionHandler)); -} - -void NetworkProcess::deleteWebsiteDataForOrigins(SessionID sessionID, uint64_t websiteDataTypes, const Vector<SecurityOriginData>& origins, const Vector<String>& cookieHostNames, uint64_t callbackID) -{ - if (websiteDataTypes & WebsiteDataTypeCookies) { - if (auto* networkStorageSession = SessionTracker::storageSession(sessionID)) - deleteCookiesForHostnames(*networkStorageSession, cookieHostNames); - } - - auto completionHandler = [this, callbackID] { - parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0); - }; - - if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) { - clearDiskCacheEntries(origins, WTFMove(completionHandler)); - return; - } - - completionHandler(); -} - -void NetworkProcess::downloadRequest(SessionID sessionID, DownloadID downloadID, const ResourceRequest& request) -{ - downloadManager().startDownload(sessionID, downloadID, request); -} - -void NetworkProcess::resumeDownload(SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle) -{ - downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, sandboxExtensionHandle); -} - -void NetworkProcess::cancelDownload(DownloadID downloadID) +void NetworkProcess::cancelDownload(uint64_t downloadID) { downloadManager().cancelDownload(downloadID); } - -#if USE(NETWORK_SESSION) -void NetworkProcess::continueCanAuthenticateAgainstProtectionSpace(DownloadID downloadID, bool canAuthenticate) -{ - downloadManager().continueCanAuthenticateAgainstProtectionSpace(downloadID, canAuthenticate); -} - -void NetworkProcess::continueWillSendRequest(DownloadID downloadID, const WebCore::ResourceRequest& request) -{ - downloadManager().continueWillSendRequest(downloadID, request); -} -#endif void NetworkProcess::setCacheModel(uint32_t cm) { @@ -475,44 +245,20 @@ void NetworkProcess::setCacheModel(uint32_t cm) } } -void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value) -{ - m_canHandleHTTPSServerTrustEvaluation = value; -} - void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID) { - StatisticsData data; - - auto& networkProcess = NetworkProcess::singleton(); - data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount()); - data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount()); - - parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0); -} - -void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample) -{ - if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample)) - return; - - parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessage(webPageID, message, description), 0); -} + NetworkResourceLoadScheduler& scheduler = NetworkProcess::shared().networkResourceLoadScheduler(); -void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample) -{ - if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample)) - return; + StatisticsData data; - parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithResult(webPageID, message, description, result), 0); -} + data.statisticsNumbers.set("HostsPendingCount", scheduler.hostsPendingCount()); + data.statisticsNumbers.set("HostsActiveCount", scheduler.hostsActiveCount()); + data.statisticsNumbers.set("LoadsPendingCount", scheduler.loadsPendingCount()); + data.statisticsNumbers.set("LoadsActiveCount", scheduler.loadsActiveCount()); + data.statisticsNumbers.set("DownloadsActiveCount", shared().downloadManager().activeDownloadCount()); + data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", shared().authenticationManager().outstandingAuthenticationChallengeCount()); -void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, const String& value, ShouldSample shouldSample) -{ - if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample)) - return; - - parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithValue(webPageID, message, description, value), 0); + parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0); } void NetworkProcess::terminate() @@ -521,36 +267,7 @@ void NetworkProcess::terminate() ChildProcess::terminate(); } -void NetworkProcess::processWillSuspendImminently(bool& handled) -{ - lowMemoryHandler(Critical::Yes); - handled = true; -} - -void NetworkProcess::prepareToSuspend() -{ - lowMemoryHandler(Critical::Yes); - parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0); -} - -void NetworkProcess::cancelPrepareToSuspend() -{ - // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here - // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend - // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend- - // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both. -} - -void NetworkProcess::processDidResume() -{ -} - -void NetworkProcess::prefetchDNS(const String& hostname) -{ - WebCore::prefetchDNS(hostname); -} - -#if !PLATFORM(COCOA) +#if !PLATFORM(MAC) void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&) { } @@ -562,10 +279,8 @@ void NetworkProcess::initializeProcessName(const ChildProcessInitializationParam void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&) { } - -void NetworkProcess::platformLowMemoryHandler(Critical) -{ -} #endif } // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.h b/Source/WebKit2/NetworkProcess/NetworkProcess.h index e43a91fe9..ad5a8c11b 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.h +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.h @@ -26,27 +26,18 @@ #ifndef NetworkProcess_h #define NetworkProcess_h +#if ENABLE(NETWORK_PROCESS) + #include "CacheModel.h" #include "ChildProcess.h" #include "DownloadManager.h" #include "MessageReceiverMap.h" -#include <WebCore/DiagnosticLoggingClient.h> -#include <WebCore/MemoryPressureHandler.h> -#include <WebCore/SessionID.h> -#include <memory> +#include "NetworkResourceLoadScheduler.h" #include <wtf/Forward.h> #include <wtf/NeverDestroyed.h> -#if PLATFORM(IOS) -#include "WebSQLiteDatabaseTracker.h" -#endif - namespace WebCore { class CertificateInfo; -class NetworkStorageSession; -class SecurityOrigin; -class SessionID; -struct SecurityOriginData; } namespace WebKit { @@ -60,7 +51,7 @@ class NetworkProcess : public ChildProcess, private DownloadManager::Client { friend class NeverDestroyed<NetworkProcess>; friend class NeverDestroyed<DownloadManager>; public: - static NetworkProcess& singleton(); + static NetworkProcess& shared(); template <typename T> T* supplement() @@ -71,35 +62,15 @@ public: template <typename T> void addSupplement() { - m_supplements.add(T::supplementName(), std::make_unique<T>(this)); + m_supplements.add(T::supplementName(), adoptPtr<NetworkProcessSupplement>(new T(this))); } void removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess*); + NetworkResourceLoadScheduler& networkResourceLoadScheduler() { return m_networkResourceLoadScheduler; } + AuthenticationManager& authenticationManager(); DownloadManager& downloadManager(); - bool canHandleHTTPSServerTrustEvaluation() const { return m_canHandleHTTPSServerTrustEvaluation; } - - void processWillSuspendImminently(bool& handled); - void prepareToSuspend(); - void cancelPrepareToSuspend(); - void processDidResume(); - - // Diagnostic messages logging. - void logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, WebCore::ShouldSample); - void logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, WebCore::DiagnosticLoggingResultType, WebCore::ShouldSample); - void logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, const String& value, WebCore::ShouldSample); - -#if USE(CFURLCACHE) - static Vector<Ref<WebCore::SecurityOrigin>> cfURLCacheOrigins(); - static void clearCFURLCacheForOrigins(const Vector<WebCore::SecurityOriginData>&); -#endif - -#if PLATFORM(COCOA) - void clearHSTSCache(WebCore::NetworkStorageSession&, std::chrono::system_clock::time_point modifiedSince); -#endif - - void prefetchDNS(const String&); private: NetworkProcess(); @@ -110,9 +81,6 @@ private: virtual void terminate() override; void platformTerminate(); - void lowMemoryHandler(WebCore::Critical); - void platformLowMemoryHandler(WebCore::Critical); - // ChildProcess virtual void initializeProcess(const ChildProcessInitializationParameters&) override; virtual void initializeProcessName(const ChildProcessInitializationParameters&) override; @@ -121,12 +89,10 @@ private: virtual bool shouldTerminate() override; // IPC::Connection::Client - virtual void didReceiveMessage(IPC::Connection&, IPC::MessageDecoder&) override; - virtual void didReceiveSyncMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override; - virtual void didClose(IPC::Connection&) override; - virtual void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override; - virtual IPC::ProcessType localProcessType() override { return IPC::ProcessType::Network; } - virtual IPC::ProcessType remoteProcessType() override { return IPC::ProcessType::UI; } + virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override; + virtual void didReceiveSyncMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&); + virtual void didClose(IPC::Connection*) override; + virtual void didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override; // DownloadManager::Client virtual void didCreateDownload() override; @@ -135,32 +101,15 @@ private: virtual AuthenticationManager& downloadsAuthenticationManager() override; // Message Handlers - void didReceiveNetworkProcessMessage(IPC::Connection&, IPC::MessageDecoder&); - void didReceiveSyncNetworkProcessMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&); + void didReceiveNetworkProcessMessage(IPC::Connection*, IPC::MessageDecoder&); void initializeNetworkProcess(const NetworkProcessCreationParameters&); void createNetworkConnectionToWebProcess(); - void ensurePrivateBrowsingSession(WebCore::SessionID); - void destroyPrivateBrowsingSession(WebCore::SessionID); - - void fetchWebsiteData(WebCore::SessionID, uint64_t websiteDataTypes, uint64_t callbackID); - void deleteWebsiteData(WebCore::SessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID); - void deleteWebsiteDataForOrigins(WebCore::SessionID, uint64_t websiteDataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, uint64_t callbackID); - - void clearCachedCredentials(); - - // FIXME: This should take a session ID so we can identify which disk cache to delete. - void clearDiskCache(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler); - - void downloadRequest(WebCore::SessionID, DownloadID, const WebCore::ResourceRequest&); - void resumeDownload(WebCore::SessionID, DownloadID, const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle&); - void cancelDownload(DownloadID); -#if USE(NETWORK_SESSION) - void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate); - void continueWillSendRequest(DownloadID, const WebCore::ResourceRequest&); -#endif + void ensurePrivateBrowsingSession(uint64_t sessionID); + void destroyPrivateBrowsingSession(uint64_t sessionID); + void downloadRequest(uint64_t downloadID, const WebCore::ResourceRequest&); + void cancelDownload(uint64_t downloadID); void setCacheModel(uint32_t); void allowSpecificHTTPSCertificateForHost(const WebCore::CertificateInfo&, const String& host); - void setCanHandleHTTPSServerTrustEvaluation(bool); void getNetworkProcessStatistics(uint64_t callbackID); void clearCacheForAllOrigins(uint32_t cachesToClear); @@ -175,30 +124,25 @@ private: // Connections to WebProcesses. Vector<RefPtr<NetworkConnectionToWebProcess>> m_webProcessConnections; + NetworkResourceLoadScheduler m_networkResourceLoadScheduler; + String m_diskCacheDirectory; bool m_hasSetCacheModel; CacheModel m_cacheModel; - int64_t m_diskCacheSizeOverride { -1 }; - bool m_diskCacheIsDisabledForTesting; - bool m_canHandleHTTPSServerTrustEvaluation; - typedef HashMap<const char*, std::unique_ptr<NetworkProcessSupplement>, PtrHash<const char*>> NetworkProcessSupplementMap; + typedef HashMap<const char*, OwnPtr<NetworkProcessSupplement>, PtrHash<const char*>> NetworkProcessSupplementMap; NetworkProcessSupplementMap m_supplements; -#if PLATFORM(COCOA) - void platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters&); - +#if PLATFORM(MAC) // FIXME: We'd like to be able to do this without the #ifdef, but WorkQueue + BinarySemaphore isn't good enough since // multiple requests to clear the cache can come in before previous requests complete, and we need to wait for all of them. // In the future using WorkQueue and a counting semaphore would work, as would WorkQueue supporting the libdispatch concept of "work groups". dispatch_group_t m_clearCacheDispatchGroup; #endif - -#if PLATFORM(IOS) - WebSQLiteDatabaseTracker m_webSQLiteDatabaseTracker; -#endif }; } // namespace WebKit +#endif // ENABLE(NETWORK_PROCESS) + #endif // NetworkProcess_h diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in index 315a54721..566deb401 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in @@ -20,9 +20,11 @@ # 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. +#if ENABLE(NETWORK_PROCESS) + messages -> NetworkProcess LegacyReceiver { # Initializes the network process. - InitializeNetworkProcess(struct WebKit::NetworkProcessCreationParameters processCreationParameters) + InitializeNetworkProcess(WebKit::NetworkProcessCreationParameters processCreationParameters) # Creates a connection for communication with a WebProcess CreateNetworkConnectionToWebProcess() @@ -32,38 +34,22 @@ messages -> NetworkProcess LegacyReceiver { UserPreferredLanguagesChanged(Vector<String> languages) #endif - ClearCachedCredentials() - - EnsurePrivateBrowsingSession(WebCore::SessionID sessionID) - DestroyPrivateBrowsingSession(WebCore::SessionID sessionID) - - FetchWebsiteData(WebCore::SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID) - DeleteWebsiteData(WebCore::SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID) - DeleteWebsiteDataForOrigins(WebCore::SessionID sessionID, uint64_t websiteDataTypes, Vector<WebCore::SecurityOriginData> origins, Vector<String> cookieHostNames, uint64_t callbackID) + EnsurePrivateBrowsingSession(uint64_t sessionID) + DestroyPrivateBrowsingSession(uint64_t sessionID) - DownloadRequest(WebCore::SessionID sessionID, WebKit::DownloadID downloadID, WebCore::ResourceRequest request) - ResumeDownload(WebCore::SessionID sessionID, WebKit::DownloadID downloadID, IPC::DataReference resumeData, String path, WebKit::SandboxExtension::Handle sandboxExtensionHandle) - CancelDownload(WebKit::DownloadID downloadID) -#if USE(NETWORK_SESSION) - ContinueCanAuthenticateAgainstProtectionSpace(WebKit::DownloadID downloadID, bool canAuthenticate) - ContinueWillSendRequest(WebKit::DownloadID downloadID, WebCore::ResourceRequest request) -#endif + DownloadRequest(uint64_t downloadID, WebCore::ResourceRequest request) + CancelDownload(uint64_t downloadID) +#if PLATFORM(MAC) SetProcessSuppressionEnabled(bool flag) -#if PLATFORM(COCOA) SetQOS(int latencyQOS, int throughputQOS) #endif AllowSpecificHTTPSCertificateForHost(WebCore::CertificateInfo certificate, String host) - SetCanHandleHTTPSServerTrustEvaluation(bool value) GetNetworkProcessStatistics(uint64_t callbackID) ClearCacheForAllOrigins(uint32_t cachesToClear) - SetCacheModel(uint32_t cacheModel); - - ProcessWillSuspendImminently() -> (bool handled) - PrepareToSuspend() - CancelPrepareToSuspend() - ProcessDidResume() } + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp b/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp deleted file mode 100644 index 751fbb11c..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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. - */ - -#include "config.h" -#include "NetworkProcessCreationParameters.h" - -#include "ArgumentCoders.h" - -#if PLATFORM(COCOA) -#include "ArgumentCodersCF.h" -#endif - -namespace WebKit { - -NetworkProcessCreationParameters::NetworkProcessCreationParameters() -{ -} - -void NetworkProcessCreationParameters::encode(IPC::ArgumentEncoder& encoder) const -{ - encoder << privateBrowsingEnabled; - encoder.encodeEnum(cacheModel); - encoder << diskCacheSizeOverride; - encoder << canHandleHTTPSServerTrustEvaluation; - encoder << diskCacheDirectory; - encoder << diskCacheDirectoryExtensionHandle; -#if ENABLE(NETWORK_CACHE) - encoder << shouldEnableNetworkCache; - encoder << shouldEnableNetworkCacheEfficacyLogging; -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - encoder << shouldEnableNetworkCacheSpeculativeRevalidation; -#endif -#endif -#if ENABLE(SECCOMP_FILTERS) - encoder << cookieStorageDirectory; -#endif -#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 - encoder << uiProcessCookieStorageIdentifier; -#endif -#if PLATFORM(IOS) - encoder << cookieStorageDirectoryExtensionHandle; - encoder << containerCachesDirectoryExtensionHandle; - encoder << parentBundleDirectoryExtensionHandle; -#endif - encoder << shouldUseTestingNetworkSession; - encoder << urlSchemesRegisteredForCustomProtocols; -#if PLATFORM(COCOA) - encoder << parentProcessName; - encoder << uiProcessBundleIdentifier; - encoder << nsURLCacheMemoryCapacity; - encoder << nsURLCacheDiskCapacity; - encoder << httpProxy; - encoder << httpsProxy; -#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - IPC::encode(encoder, networkATSContext.get()); -#endif -#endif -#if USE(SOUP) - encoder << cookiePersistentStoragePath; - encoder << cookiePersistentStorageType; - encoder.encodeEnum(cookieAcceptPolicy); - encoder << ignoreTLSErrors; - encoder << languages; -#endif -} - -bool NetworkProcessCreationParameters::decode(IPC::ArgumentDecoder& decoder, NetworkProcessCreationParameters& result) -{ - if (!decoder.decode(result.privateBrowsingEnabled)) - return false; - if (!decoder.decodeEnum(result.cacheModel)) - return false; - if (!decoder.decode(result.diskCacheSizeOverride)) - return false; - if (!decoder.decode(result.canHandleHTTPSServerTrustEvaluation)) - return false; - if (!decoder.decode(result.diskCacheDirectory)) - return false; - if (!decoder.decode(result.diskCacheDirectoryExtensionHandle)) - return false; -#if ENABLE(NETWORK_CACHE) - if (!decoder.decode(result.shouldEnableNetworkCache)) - return false; - if (!decoder.decode(result.shouldEnableNetworkCacheEfficacyLogging)) - return false; -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - if (!decoder.decode(result.shouldEnableNetworkCacheSpeculativeRevalidation)) - return false; -#endif -#endif -#if ENABLE(SECCOMP_FILTERS) - if (!decoder.decode(result.cookieStorageDirectory)) - return false; -#endif -#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 - if (!decoder.decode(result.uiProcessCookieStorageIdentifier)) - return false; -#endif -#if PLATFORM(IOS) - if (!decoder.decode(result.cookieStorageDirectoryExtensionHandle)) - return false; - if (!decoder.decode(result.containerCachesDirectoryExtensionHandle)) - return false; - if (!decoder.decode(result.parentBundleDirectoryExtensionHandle)) - return false; -#endif - if (!decoder.decode(result.shouldUseTestingNetworkSession)) - return false; - if (!decoder.decode(result.urlSchemesRegisteredForCustomProtocols)) - return false; -#if PLATFORM(COCOA) - if (!decoder.decode(result.parentProcessName)) - return false; - if (!decoder.decode(result.uiProcessBundleIdentifier)) - return false; - if (!decoder.decode(result.nsURLCacheMemoryCapacity)) - return false; - if (!decoder.decode(result.nsURLCacheDiskCapacity)) - return false; - if (!decoder.decode(result.httpProxy)) - return false; - if (!decoder.decode(result.httpsProxy)) - return false; -#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - if (!IPC::decode(decoder, result.networkATSContext)) - return false; -#endif -#endif - -#if USE(SOUP) - if (!decoder.decode(result.cookiePersistentStoragePath)) - return false; - if (!decoder.decode(result.cookiePersistentStorageType)) - return false; - if (!decoder.decodeEnum(result.cookieAcceptPolicy)) - return false; - if (!decoder.decode(result.ignoreTLSErrors)) - return false; - if (!decoder.decode(result.languages)) - return false; -#endif - - return true; -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h b/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h deleted file mode 100644 index a605d0ed3..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - -#ifndef NetworkProcessCreationParameters_h -#define NetworkProcessCreationParameters_h - -#include "CacheModel.h" -#include "SandboxExtension.h" -#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> - -#if USE(SOUP) -#include "HTTPCookieAcceptPolicy.h" -#endif - -namespace IPC { -class ArgumentDecoder; -class ArgumentEncoder; -} - -namespace WebKit { - -struct NetworkProcessCreationParameters { - NetworkProcessCreationParameters(); - - void encode(IPC::ArgumentEncoder&) const; - static bool decode(IPC::ArgumentDecoder&, NetworkProcessCreationParameters&); - - bool privateBrowsingEnabled; - CacheModel cacheModel; - int64_t diskCacheSizeOverride { -1 }; - bool canHandleHTTPSServerTrustEvaluation; - - String diskCacheDirectory; - SandboxExtension::Handle diskCacheDirectoryExtensionHandle; -#if ENABLE(NETWORK_CACHE) - bool shouldEnableNetworkCache; - bool shouldEnableNetworkCacheEfficacyLogging; -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - bool shouldEnableNetworkCacheSpeculativeRevalidation; -#endif -#endif -#if ENABLE(SECCOMP_FILTERS) - String cookieStorageDirectory; -#endif -#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 - Vector<uint8_t> uiProcessCookieStorageIdentifier; -#endif -#if PLATFORM(IOS) - SandboxExtension::Handle cookieStorageDirectoryExtensionHandle; - SandboxExtension::Handle containerCachesDirectoryExtensionHandle; - SandboxExtension::Handle parentBundleDirectoryExtensionHandle; -#endif - bool shouldUseTestingNetworkSession; - - Vector<String> urlSchemesRegisteredForCustomProtocols; - -#if PLATFORM(COCOA) - String parentProcessName; - String uiProcessBundleIdentifier; - uint64_t nsURLCacheMemoryCapacity; - uint64_t nsURLCacheDiskCapacity; - - String httpProxy; - String httpsProxy; -#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - RetainPtr<CFDataRef> networkATSContext; -#endif -#endif - -#if USE(SOUP) - String cookiePersistentStoragePath; - uint32_t cookiePersistentStorageType; - HTTPCookieAcceptPolicy cookieAcceptPolicy; - bool ignoreTLSErrors; - Vector<String> languages; -#endif -}; - -} // namespace WebKit - -#endif // NetworkProcessCreationParameters_h diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp index 2f038ebc7..5ca2a227a 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp @@ -41,27 +41,62 @@ void NetworkProcessPlatformStrategies::initialize() CookiesStrategy* NetworkProcessPlatformStrategies::createCookiesStrategy() { - return nullptr; + return 0; +} + +DatabaseStrategy* NetworkProcessPlatformStrategies::createDatabaseStrategy() +{ + return 0; } LoaderStrategy* NetworkProcessPlatformStrategies::createLoaderStrategy() { - return nullptr; + return this; } PasteboardStrategy* NetworkProcessPlatformStrategies::createPasteboardStrategy() { - return nullptr; + return 0; } PluginStrategy* NetworkProcessPlatformStrategies::createPluginStrategy() { - return nullptr; + return 0; +} + +SharedWorkerStrategy* NetworkProcessPlatformStrategies::createSharedWorkerStrategy() +{ + return 0; +} + +StorageStrategy* NetworkProcessPlatformStrategies::createStorageStrategy() +{ + return 0; +} + +VisitedLinkStrategy* NetworkProcessPlatformStrategies::createVisitedLinkStrategy() +{ + return 0; +} + +ResourceLoadScheduler* NetworkProcessPlatformStrategies::resourceLoadScheduler() +{ + ASSERT_NOT_REACHED(); + return 0; } +void NetworkProcessPlatformStrategies::loadResourceSynchronously(NetworkingContext*, unsigned long, const ResourceRequest&, StoredCredentials, ClientCredentialPolicy, ResourceError&, ResourceResponse&, Vector<char>&) +{ + ASSERT_NOT_REACHED(); +} + +#if ENABLE(BLOB) BlobRegistry* NetworkProcessPlatformStrategies::createBlobRegistry() { return new BlobRegistryImpl; } +#endif + + } diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.h b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.h index b6c0b6102..9dfc8f3af 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.h +++ b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.h @@ -31,17 +31,27 @@ namespace WebKit { -class NetworkProcessPlatformStrategies : public WebCore::PlatformStrategies { +class NetworkProcessPlatformStrategies : public WebCore::PlatformStrategies, private WebCore::LoaderStrategy { public: static void initialize(); private: // WebCore::PlatformStrategies - WebCore::CookiesStrategy* createCookiesStrategy() override; - WebCore::LoaderStrategy* createLoaderStrategy() override; - WebCore::PasteboardStrategy* createPasteboardStrategy() override; - WebCore::PluginStrategy* createPluginStrategy() override; - WebCore::BlobRegistry* createBlobRegistry() override; + virtual WebCore::CookiesStrategy* createCookiesStrategy() override; + virtual WebCore::DatabaseStrategy* createDatabaseStrategy() override; + virtual WebCore::LoaderStrategy* createLoaderStrategy() override; + virtual WebCore::PasteboardStrategy* createPasteboardStrategy() override; + virtual WebCore::PluginStrategy* createPluginStrategy() override; + virtual WebCore::SharedWorkerStrategy* createSharedWorkerStrategy() override; + virtual WebCore::StorageStrategy* createStorageStrategy() override; + virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy() override; + + // WebCore::LoaderStrategy + virtual WebCore::ResourceLoadScheduler* resourceLoadScheduler() override; + virtual void loadResourceSynchronously(WebCore::NetworkingContext*, unsigned long resourceLoadIdentifier, const WebCore::ResourceRequest&, WebCore::StoredCredentials, WebCore::ClientCredentialPolicy, WebCore::ResourceError&, WebCore::ResourceResponse&, Vector<char>& data) override; +#if ENABLE(BLOB) + virtual WebCore::BlobRegistry* createBlobRegistry() override; +#endif }; } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessSupplement.h b/Source/WebKit2/NetworkProcess/NetworkProcessSupplement.h deleted file mode 100644 index e2b46b391..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkProcessSupplement.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -#ifndef NetworkProcessSupplement_h -#define NetworkProcessSupplement_h - -#include "ChildProcessSupplement.h" - -namespace WebKit { - -struct NetworkProcessCreationParameters; - -class NetworkProcessSupplement : public ChildProcessSupplement { -public: - virtual void initialize(const NetworkProcessCreationParameters&) - { - } -}; - -} // namespace WebKit - -#endif // NetworkProcessSupplement_h diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.cpp deleted file mode 100644 index b56b2f7d8..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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. - */ - -#include "config.h" -#include "NetworkResourceLoadParameters.h" - -#include "ArgumentCoders.h" -#include "DataReference.h" -#include "WebCoreArgumentCoders.h" - -using namespace WebCore; - -namespace WebKit { - -NetworkResourceLoadParameters::NetworkResourceLoadParameters() - : identifier(0) - , webPageID(0) - , webFrameID(0) - , sessionID(SessionID::emptySessionID()) - , contentSniffingPolicy(SniffContent) - , allowStoredCredentials(DoNotAllowStoredCredentials) - , clientCredentialPolicy(DoNotAskClientForAnyCredentials) - , shouldClearReferrerOnHTTPSToHTTPRedirect(true) - , defersLoading(false) - , needsCertificateInfo(false) - , maximumBufferingTime(0_ms) -{ -} - -void NetworkResourceLoadParameters::encode(IPC::ArgumentEncoder& encoder) const -{ - encoder << identifier; - encoder << webPageID; - encoder << webFrameID; - encoder << sessionID; - encoder << request; - - encoder << static_cast<bool>(request.httpBody()); - if (request.httpBody()) { - request.httpBody()->encode(encoder); - - const Vector<FormDataElement>& elements = request.httpBody()->elements(); - size_t fileCount = 0; - for (size_t i = 0, count = elements.size(); i < count; ++i) { - if (elements[i].m_type == FormDataElement::Type::EncodedFile) - ++fileCount; - } - - SandboxExtension::HandleArray requestBodySandboxExtensions; - requestBodySandboxExtensions.allocate(fileCount); - size_t extensionIndex = 0; - for (size_t i = 0, count = elements.size(); i < count; ++i) { - const FormDataElement& element = elements[i]; - if (element.m_type == FormDataElement::Type::EncodedFile) { - const String& path = element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename; - SandboxExtension::createHandle(path, SandboxExtension::ReadOnly, requestBodySandboxExtensions[extensionIndex++]); - } - } - encoder << requestBodySandboxExtensions; - } - - if (request.url().isLocalFile()) { - SandboxExtension::Handle requestSandboxExtension; - SandboxExtension::createHandle(request.url().fileSystemPath(), SandboxExtension::ReadOnly, requestSandboxExtension); - encoder << requestSandboxExtension; - } - - encoder.encodeEnum(contentSniffingPolicy); - encoder.encodeEnum(allowStoredCredentials); - encoder.encodeEnum(clientCredentialPolicy); - encoder << shouldClearReferrerOnHTTPSToHTTPRedirect; - encoder << defersLoading; - encoder << needsCertificateInfo; - encoder << maximumBufferingTime; -} - -bool NetworkResourceLoadParameters::decode(IPC::ArgumentDecoder& decoder, NetworkResourceLoadParameters& result) -{ - if (!decoder.decode(result.identifier)) - return false; - - if (!decoder.decode(result.webPageID)) - return false; - - if (!decoder.decode(result.webFrameID)) - return false; - - if (!decoder.decode(result.sessionID)) - return false; - - if (!decoder.decode(result.request)) - return false; - - bool hasHTTPBody; - if (!decoder.decode(hasHTTPBody)) - return false; - - if (hasHTTPBody) { - RefPtr<FormData> formData = FormData::decode(decoder); - if (!formData) - return false; - result.request.setHTTPBody(WTFMove(formData)); - - SandboxExtension::HandleArray requestBodySandboxExtensionHandles; - if (!decoder.decode(requestBodySandboxExtensionHandles)) - return false; - for (size_t i = 0; i < requestBodySandboxExtensionHandles.size(); ++i) { - if (RefPtr<SandboxExtension> extension = SandboxExtension::create(requestBodySandboxExtensionHandles[i])) - result.requestBodySandboxExtensions.append(extension.release()); - } - } - - if (result.request.url().isLocalFile()) { - SandboxExtension::Handle resourceSandboxExtensionHandle; - if (!decoder.decode(resourceSandboxExtensionHandle)) - return false; - result.resourceSandboxExtension = SandboxExtension::create(resourceSandboxExtensionHandle); - } - - if (!decoder.decodeEnum(result.contentSniffingPolicy)) - return false; - if (!decoder.decodeEnum(result.allowStoredCredentials)) - return false; - if (!decoder.decodeEnum(result.clientCredentialPolicy)) - return false; - if (!decoder.decode(result.shouldClearReferrerOnHTTPSToHTTPRedirect)) - return false; - if (!decoder.decode(result.defersLoading)) - return false; - if (!decoder.decode(result.needsCertificateInfo)) - return false; - if (!decoder.decode(result.maximumBufferingTime)) - return false; - - return true; -} - -} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.h deleted file mode 100644 index 22e10c6af..000000000 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -#ifndef NetworkResourceLoadParameters_h -#define NetworkResourceLoadParameters_h - -#include "SandboxExtension.h" -#include <WebCore/ResourceHandle.h> -#include <WebCore/ResourceLoaderOptions.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/SessionID.h> - -namespace IPC { -class ArgumentDecoder; -class ArgumentEncoder; -} - -namespace WebKit { - -typedef uint64_t ResourceLoadIdentifier; - -class NetworkResourceLoadParameters { -public: - NetworkResourceLoadParameters(); - - void encode(IPC::ArgumentEncoder&) const; - static bool decode(IPC::ArgumentDecoder&, NetworkResourceLoadParameters&); - - ResourceLoadIdentifier identifier; - uint64_t webPageID; - uint64_t webFrameID; - WebCore::SessionID sessionID; - WebCore::ResourceRequest request; - Vector<RefPtr<SandboxExtension>> requestBodySandboxExtensions; // Created automatically for the sender. - RefPtr<SandboxExtension> resourceSandboxExtension; // Created automatically for the sender. - WebCore::ContentSniffingPolicy contentSniffingPolicy; - WebCore::StoredCredentials allowStoredCredentials; - WebCore::ClientCredentialPolicy clientCredentialPolicy; - bool shouldClearReferrerOnHTTPSToHTTPRedirect; - bool defersLoading; - bool needsCertificateInfo; - std::chrono::milliseconds maximumBufferingTime; -}; - -} // namespace WebKit - -#endif // NetworkResourceLoadParameters_h diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp new file mode 100644 index 000000000..ff42743ed --- /dev/null +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp @@ -0,0 +1,227 @@ +#include "config.h" +#include "NetworkResourceLoadScheduler.h" + +#include "HostRecord.h" +#include "Logging.h" +#include "NetworkProcess.h" +#include "NetworkResourceLoadParameters.h" +#include "NetworkResourceLoader.h" +#include <wtf/MainThread.h> +#include <wtf/text/CString.h> + +#if ENABLE(NETWORK_PROCESS) + +using namespace WebCore; + +namespace WebKit { + +static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20; + +NetworkResourceLoadScheduler::NetworkResourceLoadScheduler() + : m_nonHTTPProtocolHost(HostRecord::create(String(), maxRequestsInFlightForNonHTTPProtocols)) + , m_requestTimer(this, &NetworkResourceLoadScheduler::requestTimerFired) + +{ + platformInitializeMaximumHTTPConnectionCountPerHost(); +} + +void NetworkResourceLoadScheduler::scheduleServePendingRequests() +{ + if (!m_requestTimer.isActive()) + m_requestTimer.startOneShot(0); +} + +void NetworkResourceLoadScheduler::requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*) +{ + servePendingRequests(); +} + +void NetworkResourceLoadScheduler::scheduleLoader(PassRefPtr<NetworkResourceLoader> loader) +{ + ResourceLoadPriority priority = loader->priority(); + const ResourceRequest& resourceRequest = loader->request(); + + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::scheduleLoader resource '%s'", resourceRequest.url().string().utf8().data()); + + HostRecord* host = hostForURL(resourceRequest.url(), CreateIfNotFound); + bool hadRequests = host->hasRequests(); + host->scheduleResourceLoader(loader); + + if (priority > ResourceLoadPriorityLow || !resourceRequest.url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) { + // Try to request important resources immediately. + host->servePendingRequests(priority); + return; + } + + // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones. + scheduleServePendingRequests(); +} + +HostRecord* NetworkResourceLoadScheduler::hostForURL(const WebCore::URL& url, CreateHostPolicy createHostPolicy) +{ + if (!url.protocolIsInHTTPFamily()) + return m_nonHTTPProtocolHost.get(); + + m_hosts.checkConsistency(); + String hostName = url.host(); + HostRecord* host = m_hosts.get(hostName); + if (!host && createHostPolicy == CreateIfNotFound) { + RefPtr<HostRecord> newHost = HostRecord::create(hostName, m_maxRequestsInFlightPerHost); + host = newHost.get(); + m_hosts.add(hostName, newHost.release()); + } + + return host; +} + +void NetworkResourceLoadScheduler::removeLoader(NetworkResourceLoader* loader) +{ + ASSERT(isMainThread()); + ASSERT(loader); + + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing loader %s", loader->request().url().string().utf8().data()); + + HostRecord* host = loader->hostRecord(); + + // Due to a race condition the WebProcess might have messaged the NetworkProcess to remove this identifier + // after the NetworkProcess has already removed it internally. + // In this situation we might not have a HostRecord to clean up. + if (host) + host->removeLoader(loader); + + scheduleServePendingRequests(); +} + +void NetworkResourceLoadScheduler::receivedRedirect(NetworkResourceLoader* loader, const WebCore::URL& redirectURL) +{ + ASSERT(isMainThread()); + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::receivedRedirect loader originally for '%s' redirected to '%s'", loader->request().url().string().utf8().data(), redirectURL.string().utf8().data()); + + HostRecord* oldHost = loader->hostRecord(); + + // The load may have been cancelled while the message was in flight from network thread to main thread. + if (!oldHost) + return; + + HostRecord* newHost = hostForURL(redirectURL, CreateIfNotFound); + + if (oldHost->name() == newHost->name()) + return; + + oldHost->removeLoader(loader); + newHost->addLoaderInProgress(loader); +} + +void NetworkResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority) +{ + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts with minimum priority %i", m_hosts.size(), minimumPriority); + + m_requestTimer.stop(); + + m_nonHTTPProtocolHost->servePendingRequests(minimumPriority); + + m_hosts.checkConsistency(); + Vector<RefPtr<HostRecord>> hostsToServe; + copyValuesToVector(m_hosts, hostsToServe); + + size_t size = hostsToServe.size(); + for (size_t i = 0; i < size; ++i) { + HostRecord* host = hostsToServe[i].get(); + if (host->hasRequests()) + host->servePendingRequests(minimumPriority); + else + m_hosts.remove(host->name()); + } +} + +static bool removeScheduledLoadersCalled = false; + +void NetworkResourceLoadScheduler::removeScheduledLoaders(void* context) +{ + ASSERT(isMainThread()); + ASSERT(removeScheduledLoadersCalled); + + NetworkResourceLoadScheduler* scheduler = static_cast<NetworkResourceLoadScheduler*>(context); + scheduler->removeScheduledLoaders(); +} + +void NetworkResourceLoadScheduler::removeScheduledLoaders() +{ + Vector<RefPtr<NetworkResourceLoader>> loadersToRemove; + { + MutexLocker locker(m_loadersToRemoveMutex); + loadersToRemove = m_loadersToRemove; + m_loadersToRemove.clear(); + removeScheduledLoadersCalled = false; + } + + for (size_t i = 0; i < loadersToRemove.size(); ++i) + removeLoader(loadersToRemove[i].get()); +} + +void NetworkResourceLoadScheduler::scheduleRemoveLoader(NetworkResourceLoader* loader) +{ + MutexLocker locker(m_loadersToRemoveMutex); + + m_loadersToRemove.append(loader); + + if (!removeScheduledLoadersCalled) { + removeScheduledLoadersCalled = true; + callOnMainThread(NetworkResourceLoadScheduler::removeScheduledLoaders, this); + } +} + +uint64_t NetworkResourceLoadScheduler::hostsPendingCount() const +{ + uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount() ? 1 : 0; + + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) { + if (i->value->pendingRequestCount()) + ++count; + } + + return count; +} + +uint64_t NetworkResourceLoadScheduler::loadsPendingCount() const +{ + uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount(); + + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) + count += i->value->pendingRequestCount(); + + return count; +} + +uint64_t NetworkResourceLoadScheduler::hostsActiveCount() const +{ + uint64_t count = 0; + + if (m_nonHTTPProtocolHost->activeLoadCount()) + count = 1; + + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) { + if (i->value->activeLoadCount()) + ++count; + } + + return count; +} + +uint64_t NetworkResourceLoadScheduler::loadsActiveCount() const +{ + uint64_t count = m_nonHTTPProtocolHost->activeLoadCount(); + + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) + count += i->value->activeLoadCount(); + + return count; +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h new file mode 100644 index 000000000..840a27829 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#ifndef NetworkResourceLoadScheduler_h +#define NetworkResourceLoadScheduler_h + +#include <WebCore/ResourceLoadPriority.h> +#include <WebCore/Timer.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/text/StringHash.h> + +#if ENABLE(NETWORK_PROCESS) + +namespace WebCore { +class URL; +} + +namespace WebKit { + +class HostRecord; +class NetworkResourceLoader; + +class NetworkResourceLoadScheduler { + WTF_MAKE_NONCOPYABLE(NetworkResourceLoadScheduler); WTF_MAKE_FAST_ALLOCATED; + +public: + NetworkResourceLoadScheduler(); + + // Adds the request to the queue for its host. + void scheduleLoader(PassRefPtr<NetworkResourceLoader>); + + // Called by the WebProcess when a ResourceLoader is being cleaned up. + void removeLoader(NetworkResourceLoader*); + + // Called within the NetworkProcess on a background thread when a resource load has finished. + void scheduleRemoveLoader(NetworkResourceLoader*); + + void receivedRedirect(NetworkResourceLoader*, const WebCore::URL& redirectURL); + void servePendingRequests(WebCore::ResourceLoadPriority = WebCore::ResourceLoadPriorityVeryLow); + + // For NetworkProcess statistics reporting. + uint64_t hostsPendingCount() const; + uint64_t loadsPendingCount() const; + uint64_t hostsActiveCount() const; + uint64_t loadsActiveCount() const; + +private: + enum CreateHostPolicy { + CreateIfNotFound, + FindOnly + }; + + HostRecord* hostForURL(const WebCore::URL&, CreateHostPolicy = FindOnly); + + void scheduleServePendingRequests(); + void requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*); + + void platformInitializeMaximumHTTPConnectionCountPerHost(); + + static void removeScheduledLoaders(void* context); + void removeScheduledLoaders(); + + typedef HashMap<String, RefPtr<HostRecord>, StringHash> HostMap; + HostMap m_hosts; + + typedef HashSet<RefPtr<NetworkResourceLoader>> NetworkResourceLoaderSet; + NetworkResourceLoaderSet m_loaders; + + RefPtr<HostRecord> m_nonHTTPProtocolHost; + + bool m_isSerialLoadingEnabled; + + WebCore::Timer<NetworkResourceLoadScheduler> m_requestTimer; + + Mutex m_loadersToRemoveMutex; + Vector<RefPtr<NetworkResourceLoader>> m_loadersToRemove; + + unsigned m_maxRequestsInFlightPerHost; +}; + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) + +#endif // NetworkResourceLoadScheduler_h diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp index b45e4d2bd..60d13a338 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * 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 @@ -26,605 +26,393 @@ #include "config.h" #include "NetworkResourceLoader.h" +#if ENABLE(NETWORK_PROCESS) + +#include "AsynchronousNetworkLoaderClient.h" +#include "AuthenticationManager.h" #include "DataReference.h" #include "Logging.h" #include "NetworkBlobRegistry.h" -#include "NetworkCache.h" #include "NetworkConnectionToWebProcess.h" -#include "NetworkLoad.h" +#include "NetworkProcess.h" #include "NetworkProcessConnectionMessages.h" +#include "NetworkResourceLoadParameters.h" +#include "RemoteNetworkingContext.h" +#include "ShareableResource.h" +#include "SharedMemory.h" +#include "SynchronousNetworkLoaderClient.h" #include "WebCoreArgumentCoders.h" +#include "WebErrors.h" #include "WebResourceLoaderMessages.h" -#include <WebCore/BlobDataFileReference.h> -#include <WebCore/CertificateInfo.h> -#include <WebCore/HTTPHeaderNames.h> -#include <WebCore/ProtectionSpace.h> -#include <WebCore/SharedBuffer.h> -#include <WebCore/SynchronousLoaderClient.h> -#include <wtf/CurrentTime.h> -#include <wtf/RunLoop.h> +#include <WebCore/NotImplemented.h> +#include <WebCore/ResourceBuffer.h> +#include <WebCore/ResourceHandle.h> +#include <wtf/MainThread.h> using namespace WebCore; namespace WebKit { -struct NetworkResourceLoader::SynchronousLoadData { - SynchronousLoadData(RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply) - : delayedReply(WTFMove(reply)) - { - ASSERT(delayedReply); - } - ResourceRequest currentRequest; - RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> delayedReply; - ResourceResponse response; - ResourceError error; -}; - -static void sendReplyToSynchronousRequest(NetworkResourceLoader::SynchronousLoadData& data, const SharedBuffer* buffer) -{ - ASSERT(data.delayedReply); - ASSERT(!data.response.isNull() || !data.error.isNull()); - - Vector<char> responseBuffer; - if (buffer && buffer->size()) - responseBuffer.append(buffer->data(), buffer->size()); - - data.delayedReply->send(data.error, data.response, responseBuffer); - data.delayedReply = nullptr; -} - -NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess& connection, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& synchronousReply) - : m_parameters(parameters) +NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) + : m_bytesReceived(0) + , m_handleConvertedToDownload(false) + , m_identifier(parameters.identifier) + , m_webPageID(parameters.webPageID) + , m_webFrameID(parameters.webFrameID) + , m_sessionID(parameters.sessionID) + , m_request(parameters.request) + , m_priority(parameters.priority) + , m_contentSniffingPolicy(parameters.contentSniffingPolicy) + , m_allowStoredCredentials(parameters.allowStoredCredentials) + , m_clientCredentialPolicy(parameters.clientCredentialPolicy) + , m_shouldClearReferrerOnHTTPSToHTTPRedirect(parameters.shouldClearReferrerOnHTTPSToHTTPRedirect) + , m_isLoadingMainResource(parameters.isMainResource) + , m_sandboxExtensionsAreConsumed(false) , m_connection(connection) - , m_defersLoading(parameters.defersLoading) - , m_bufferingTimer(*this, &NetworkResourceLoader::bufferingTimerFired) { - ASSERT(RunLoop::isMain()); + // Either this loader has both a webPageID and webFrameID, or it is not allowed to ask the client for authentication credentials. // FIXME: This is necessary because of the existence of EmptyFrameLoaderClient in WebCore. // Once bug 116233 is resolved, this ASSERT can just be "m_webPageID && m_webFrameID" - ASSERT((m_parameters.webPageID && m_parameters.webFrameID) || m_parameters.clientCredentialPolicy == DoNotAskClientForAnyCredentials); + ASSERT((m_webPageID && m_webFrameID) || m_clientCredentialPolicy == DoNotAskClientForAnyCredentials); - if (originalRequest().httpBody()) { - for (const auto& element : originalRequest().httpBody()->elements()) { - if (element.m_type == FormDataElement::Type::EncodedBlob) - m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, element.m_url)); - } + for (size_t i = 0, count = parameters.requestBodySandboxExtensions.size(); i < count; ++i) { + if (RefPtr<SandboxExtension> extension = SandboxExtension::create(parameters.requestBodySandboxExtensions[i])) + m_requestBodySandboxExtensions.append(extension); } - if (originalRequest().url().protocolIsBlob()) { - ASSERT(!m_parameters.resourceSandboxExtension); - m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, originalRequest().url())); +#if ENABLE(BLOB) + if (m_request.httpBody()) { + const Vector<FormDataElement>& elements = m_request.httpBody()->elements(); + for (size_t i = 0, count = elements.size(); i < count; ++i) { + if (elements[i].m_type == FormDataElement::encodedBlob) { + Vector<RefPtr<SandboxExtension>> blobElementExtensions = NetworkBlobRegistry::shared().sandboxExtensions(elements[i].m_url); + m_requestBodySandboxExtensions.appendVector(blobElementExtensions); + } + } } - if (synchronousReply) - m_synchronousLoadData = std::make_unique<SynchronousLoadData>(WTFMove(synchronousReply)); -} - -NetworkResourceLoader::~NetworkResourceLoader() -{ - ASSERT(RunLoop::isMain()); - ASSERT(!m_networkLoad); - ASSERT(!isSynchronous() || !m_synchronousLoadData->delayedReply); -} + if (m_request.url().protocolIs("blob")) { + ASSERT(!SandboxExtension::create(parameters.resourceSandboxExtension)); + m_resourceSandboxExtensions = NetworkBlobRegistry::shared().sandboxExtensions(m_request.url()); + } else +#endif + if (RefPtr<SandboxExtension> resourceSandboxExtension = SandboxExtension::create(parameters.resourceSandboxExtension)) + m_resourceSandboxExtensions.append(resourceSandboxExtension); -#if ENABLE(NETWORK_CACHE) -bool NetworkResourceLoader::canUseCache(const ResourceRequest& request) const -{ - if (!NetworkCache::singleton().isEnabled()) - return false; - if (sessionID().isEphemeral()) - return false; - if (!request.url().protocolIsInHTTPFamily()) - return false; - - return true; + ASSERT(isMainThread()); + + if (reply) + m_networkLoaderClient = std::make_unique<SynchronousNetworkLoaderClient>(m_request, reply); + else + m_networkLoaderClient = std::make_unique<AsynchronousNetworkLoaderClient>(); } -bool NetworkResourceLoader::canUseCachedRedirect(const ResourceRequest& request) const +NetworkResourceLoader::~NetworkResourceLoader() { - if (!canUseCache(request)) - return false; - // Limit cached redirects to avoid cycles and other trouble. - // Networking layer follows over 30 redirects but caching that many seems unnecessary. - static const unsigned maximumCachedRedirectCount { 5 }; - if (m_redirectCount > maximumCachedRedirectCount) - return false; - - return true; + ASSERT(isMainThread()); + ASSERT(!m_handle); + ASSERT(!m_hostRecord); } -#endif bool NetworkResourceLoader::isSynchronous() const { - return !!m_synchronousLoadData; + return m_networkLoaderClient->isSynchronous(); } void NetworkResourceLoader::start() { - ASSERT(RunLoop::isMain()); + ASSERT(isMainThread()); - if (m_defersLoading) - return; + // Explicit ref() balanced by a deref() in NetworkResourceLoader::resourceHandleStopped() + ref(); -#if ENABLE(NETWORK_CACHE) - if (canUseCache(originalRequest())) { - retrieveCacheEntry(originalRequest()); - return; - } -#endif - - startNetworkLoad(originalRequest()); -} + // FIXME (NetworkProcess): Set platform specific settings. + m_networkingContext = RemoteNetworkingContext::create(m_sessionID, m_shouldClearReferrerOnHTTPSToHTTPRedirect); -#if ENABLE(NETWORK_CACHE) -void NetworkResourceLoader::retrieveCacheEntry(const ResourceRequest& request) -{ - ASSERT(canUseCache(request)); - - RefPtr<NetworkResourceLoader> loader(this); - NetworkCache::singleton().retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [loader, request](std::unique_ptr<NetworkCache::Entry> entry) { - if (loader->hasOneRef()) { - // The loader has been aborted and is only held alive by this lambda. - return; - } - if (!entry) { - loader->startNetworkLoad(request); - return; - } - if (entry->redirectRequest()) { - loader->dispatchWillSendRequestForCacheEntry(WTFMove(entry)); - return; - } - if (loader->m_parameters.needsCertificateInfo && !entry->response().containsCertificateInfo()) { - loader->startNetworkLoad(request); - return; - } - if (entry->needsValidation()) { - loader->validateCacheEntry(WTFMove(entry)); - return; - } - loader->didRetrieveCacheEntry(WTFMove(entry)); - }); -} -#endif - -void NetworkResourceLoader::startNetworkLoad(const ResourceRequest& request) -{ consumeSandboxExtensions(); - if (isSynchronous() || m_parameters.maximumBufferingTime > 0_ms) - m_bufferedData = SharedBuffer::create(); - -#if ENABLE(NETWORK_CACHE) - if (canUseCache(request)) - m_bufferedDataForCache = SharedBuffer::create(); -#endif - - NetworkLoadParameters parameters = m_parameters; - parameters.defersLoading = m_defersLoading; - parameters.request = request; - m_networkLoad = std::make_unique<NetworkLoad>(*this, parameters); -} - -void NetworkResourceLoader::setDefersLoading(bool defers) -{ - if (m_defersLoading == defers) - return; - m_defersLoading = defers; - - if (m_networkLoad) { - m_networkLoad->setDefersLoading(defers); - return; - } - - if (!m_defersLoading) - start(); + // FIXME (NetworkProcess): Pass an actual value for defersLoading + m_handle = ResourceHandle::create(m_networkingContext.get(), m_request, this, false /* defersLoading */, m_contentSniffingPolicy == SniffContent); } void NetworkResourceLoader::cleanup() { - ASSERT(RunLoop::isMain()); - - m_bufferingTimer.stop(); + ASSERT(isMainThread()); invalidateSandboxExtensions(); - m_networkLoad = nullptr; + if (FormData* formData = request().httpBody()) + formData->removeGeneratedFilesIfNeeded(); - // This will cause NetworkResourceLoader to be destroyed and therefore we do it last. - m_connection->didCleanupResourceLoader(*this); + // Tell the scheduler about this finished loader soon so it can start more network requests. + NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoader(this); + + if (m_handle) { + // Explicit deref() balanced by a ref() in NetworkResourceLoader::start() + // This might cause the NetworkResourceLoader to be destroyed and therefore we do it last. + m_handle = 0; + deref(); + } } -void NetworkResourceLoader::didConvertToDownload() +void NetworkResourceLoader::didConvertHandleToDownload() { - ASSERT(m_networkLoad); - m_didConvertToDownload = true; -#if USE(NETWORK_SESSION) - m_networkLoad = nullptr; -#endif + ASSERT(m_handle); + m_handleConvertedToDownload = true; } void NetworkResourceLoader::abort() { - ASSERT(RunLoop::isMain()); - - if (m_networkLoad && !m_didConvertToDownload) { -#if ENABLE(NETWORK_CACHE) - if (canUseCache(m_networkLoad->currentRequest())) { - // We might already have used data from this incomplete load. Ensure older versions don't remain in the cache after cancel. - if (!m_response.isNull()) - NetworkCache::singleton().remove(m_networkLoad->currentRequest()); - } -#endif - m_networkLoad->cancel(); - } + ASSERT(isMainThread()); + + if (m_handle && !m_handleConvertedToDownload) + m_handle->cancel(); cleanup(); } -auto NetworkResourceLoader::didReceiveResponse(const ResourceResponse& receivedResponse) -> ShouldContinueDidReceiveResponse +void NetworkResourceLoader::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& response) { - m_response = receivedResponse; - - // For multipart/x-mixed-replace didReceiveResponseAsync gets called multiple times and buffering would require special handling. - if (!isSynchronous() && m_response.isMultipart()) - m_bufferedData = nullptr; - - bool shouldSendDidReceiveResponse = true; -#if ENABLE(NETWORK_CACHE) - if (m_response.isMultipart()) - m_bufferedDataForCache = nullptr; - - if (m_cacheEntryForValidation) { - bool validationSucceeded = m_response.httpStatusCode() == 304; // 304 Not Modified - if (validationSucceeded) { - NetworkCache::singleton().update(originalRequest(), { m_parameters.webPageID, m_parameters.webFrameID }, *m_cacheEntryForValidation, m_response); - // If the request was conditional then this revalidation was not triggered by the network cache and we pass the - // 304 response to WebCore. - if (originalRequest().isConditional()) - m_cacheEntryForValidation = nullptr; - } else - m_cacheEntryForValidation = nullptr; - } - shouldSendDidReceiveResponse = !m_cacheEntryForValidation; -#endif + ASSERT_UNUSED(handle, handle == m_handle); - bool shouldWaitContinueDidReceiveResponse = originalRequest().requester() == ResourceRequest::Requester::Main; - if (shouldSendDidReceiveResponse) { - if (isSynchronous()) - m_synchronousLoadData->response = m_response; - else { - if (!sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(m_response, shouldWaitContinueDidReceiveResponse))) - return ShouldContinueDidReceiveResponse::No; - } - } + // FIXME (NetworkProcess): Cache the response. + if (FormData* formData = request().httpBody()) + formData->removeGeneratedFilesIfNeeded(); - // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message. - bool shouldContinueDidReceiveResponse = !shouldWaitContinueDidReceiveResponse; -#if ENABLE(NETWORK_CACHE) - shouldContinueDidReceiveResponse = shouldContinueDidReceiveResponse || m_cacheEntryForValidation; -#endif + m_networkLoaderClient->didReceiveResponse(this, response); + + // m_handle will be 0 if the request got aborted above. + if (!m_handle) + return; - return shouldContinueDidReceiveResponse ? ShouldContinueDidReceiveResponse::Yes : ShouldContinueDidReceiveResponse::No; + if (!m_isLoadingMainResource) { + // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message. + m_handle->continueDidReceiveResponse(); + } } -void NetworkResourceLoader::didReceiveBuffer(RefPtr<SharedBuffer>&& buffer, int reportedEncodedDataLength) +void NetworkResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength) { -#if ENABLE(NETWORK_CACHE) - ASSERT(!m_cacheEntryForValidation); - - if (m_bufferedDataForCache) { - // Prevent memory growth in case of streaming data. - const size_t maximumCacheBufferSize = 10 * 1024 * 1024; - if (m_bufferedDataForCache->size() + buffer->size() <= maximumCacheBufferSize) - m_bufferedDataForCache->append(buffer.get()); - else - m_bufferedDataForCache = nullptr; - } -#endif - // FIXME: At least on OS X Yosemite we always get -1 from the resource handle. - unsigned encodedDataLength = reportedEncodedDataLength >= 0 ? reportedEncodedDataLength : buffer->size(); + // The NetworkProcess should never get a didReceiveData callback. + // We should always be using didReceiveBuffer. + ASSERT_NOT_REACHED(); +} +void NetworkResourceLoader::didReceiveBuffer(ResourceHandle* handle, PassRefPtr<SharedBuffer> buffer, int encodedDataLength) +{ + ASSERT_UNUSED(handle, handle == m_handle); + + // FIXME (NetworkProcess): For the memory cache we'll also need to cache the response data here. + // Such buffering will need to be thread safe, as this callback is happening on a background thread. + m_bytesReceived += buffer->size(); - if (m_bufferedData) { - m_bufferedData->append(buffer.get()); - m_bufferedDataEncodedDataLength += encodedDataLength; - startBufferingTimerIfNeeded(); - return; - } - sendBufferMaybeAborting(*buffer, encodedDataLength); + m_networkLoaderClient->didReceiveBuffer(this, buffer.get(), encodedDataLength); } -void NetworkResourceLoader::didFinishLoading(double finishTime) +void NetworkResourceLoader::didFinishLoading(ResourceHandle* handle, double finishTime) { -#if ENABLE(NETWORK_CACHE) - if (m_cacheEntryForValidation) { - // 304 Not Modified - ASSERT(m_response.httpStatusCode() == 304); - LOG(NetworkCache, "(NetworkProcess) revalidated"); - didRetrieveCacheEntry(WTFMove(m_cacheEntryForValidation)); - return; - } -#endif + ASSERT_UNUSED(handle, handle == m_handle); - if (isSynchronous()) - sendReplyToSynchronousRequest(*m_synchronousLoadData, m_bufferedData.get()); - else { - if (m_bufferedData && !m_bufferedData->isEmpty()) { - // FIXME: Pass a real value or remove the encoded data size feature. - bool shouldContinue = sendBufferMaybeAborting(*m_bufferedData, -1); - if (!shouldContinue) - return; - } - send(Messages::WebResourceLoader::DidFinishResourceLoad(finishTime)); - } - -#if ENABLE(NETWORK_CACHE) - tryStoreAsCacheEntry(); -#endif + m_networkLoaderClient->didFinishLoading(this, finishTime); cleanup(); } -void NetworkResourceLoader::didFailLoading(const ResourceError& error) +void NetworkResourceLoader::didFail(ResourceHandle* handle, const ResourceError& error) { - ASSERT(!error.isNull()); - -#if ENABLE(NETWORK_CACHE) - m_cacheEntryForValidation = nullptr; -#endif + ASSERT_UNUSED(handle, handle == m_handle); - if (isSynchronous()) { - m_synchronousLoadData->error = error; - sendReplyToSynchronousRequest(*m_synchronousLoadData, nullptr); - } else - send(Messages::WebResourceLoader::DidFailResourceLoad(error)); + m_networkLoaderClient->didFail(this, error); cleanup(); } -void NetworkResourceLoader::willSendRedirectedRequest(const ResourceRequest& request, const WebCore::ResourceRequest& redirectRequest, const ResourceResponse& redirectResponse) +void NetworkResourceLoader::willSendRequestAsync(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& redirectResponse) { - ++m_redirectCount; - - if (isSynchronous()) { - ResourceRequest overridenRequest = redirectRequest; - // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests. - // This includes at least updating host records, and comparing the current request instead of the original request here. - if (!protocolHostAndPortAreEqual(originalRequest().url(), redirectRequest.url())) { - ASSERT(m_synchronousLoadData->error.isNull()); - m_synchronousLoadData->error = SynchronousLoaderClient::platformBadResponseError(); - m_networkLoad->clearCurrentRequest(); - overridenRequest = ResourceRequest(); - } - continueWillSendRequest(overridenRequest); - return; - } - sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(redirectRequest, redirectResponse)); + ASSERT_UNUSED(handle, handle == m_handle); -#if ENABLE(NETWORK_CACHE) - if (canUseCachedRedirect(request)) - NetworkCache::singleton().storeRedirect(request, redirectResponse, redirectRequest); -#else - UNUSED_PARAM(request); -#endif + // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect. + ASSERT(!redirectResponse.isNull()); + ASSERT(isMainThread()); + + ResourceRequest proposedRequest = request; + m_suggestedRequestForWillSendRequest = request; + + m_networkLoaderClient->willSendRequest(this, proposedRequest, redirectResponse); } void NetworkResourceLoader::continueWillSendRequest(const ResourceRequest& newRequest) { -#if ENABLE(NETWORK_CACHE) - if (m_isWaitingContinueWillSendRequestForCachedRedirect) { - LOG(NetworkCache, "(NetworkProcess) Retrieving cached redirect"); +#if PLATFORM(MAC) + m_suggestedRequestForWillSendRequest.updateFromDelegatePreservingOldHTTPBody(newRequest.nsURLRequest(DoNotUpdateHTTPBody)); +#elif USE(SOUP) + // FIXME: Implement ResourceRequest::updateFromDelegatePreservingOldHTTPBody. See https://bugs.webkit.org/show_bug.cgi?id=126127. + m_suggestedRequestForWillSendRequest.updateFromDelegatePreservingOldHTTPBody(newRequest); +#endif + + RunLoop::main()->dispatch(bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), this, m_suggestedRequestForWillSendRequest.url())); - if (canUseCachedRedirect(newRequest)) - retrieveCacheEntry(newRequest); - else - startNetworkLoad(newRequest); + m_request = m_suggestedRequestForWillSendRequest; + m_suggestedRequestForWillSendRequest = ResourceRequest(); - m_isWaitingContinueWillSendRequestForCachedRedirect = false; + if (m_request.isNull()) { + m_handle->cancel(); + didFail(m_handle.get(), cancelledError(m_request)); return; } -#endif - m_networkLoad->continueWillSendRequest(newRequest); + + m_handle->continueWillSendRequest(m_request); } void NetworkResourceLoader::continueDidReceiveResponse() { // FIXME: Remove this check once BlobResourceHandle implements didReceiveResponseAsync correctly. // Currently, it does not wait for response, so the load is likely to finish before continueDidReceiveResponse. - if (m_networkLoad) - m_networkLoad->continueDidReceiveResponse(); -} + if (!m_handle) + return; -void NetworkResourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - if (!isSynchronous()) - send(Messages::WebResourceLoader::DidSendData(bytesSent, totalBytesToBeSent)); + m_handle->continueDidReceiveResponse(); } -void NetworkResourceLoader::startBufferingTimerIfNeeded() +void NetworkResourceLoader::didSendData(ResourceHandle* handle, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { - if (isSynchronous()) - return; - if (m_bufferingTimer.isActive()) - return; - m_bufferingTimer.startOneShot(m_parameters.maximumBufferingTime); + ASSERT_UNUSED(handle, handle == m_handle); + + m_networkLoaderClient->didSendData(this, bytesSent, totalBytesToBeSent); } -void NetworkResourceLoader::bufferingTimerFired() +void NetworkResourceLoader::wasBlocked(ResourceHandle* handle) { - ASSERT(m_bufferedData); - ASSERT(m_networkLoad); + ASSERT_UNUSED(handle, handle == m_handle); - if (m_bufferedData->isEmpty()) - return; - - IPC::SharedBufferDataReference dataReference(m_bufferedData.get()); - size_t encodedLength = m_bufferedDataEncodedDataLength; + didFail(handle, WebKit::blockedError(request())); +} - m_bufferedData = SharedBuffer::create(); - m_bufferedDataEncodedDataLength = 0; +void NetworkResourceLoader::cannotShowURL(ResourceHandle* handle) +{ + ASSERT_UNUSED(handle, handle == m_handle); - sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedLength)); + didFail(handle, WebKit::cannotShowURLError(request())); } -bool NetworkResourceLoader::sendBufferMaybeAborting(SharedBuffer& buffer, size_t encodedDataLength) +bool NetworkResourceLoader::shouldUseCredentialStorage(ResourceHandle* handle) { - ASSERT(!isSynchronous()); - -#if PLATFORM(COCOA) - ShareableResource::Handle shareableResourceHandle; - NetworkResourceLoader::tryGetShareableHandleFromSharedBuffer(shareableResourceHandle, buffer); - if (!shareableResourceHandle.isNull()) { - send(Messages::WebResourceLoader::DidReceiveResource(shareableResourceHandle, currentTime())); - abort(); - return false; - } -#endif + ASSERT_UNUSED(handle, handle == m_handle || !m_handle); // m_handle will be 0 if called from ResourceHandle::start(). + + // 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. - IPC::SharedBufferDataReference dataReference(&buffer); - return sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedDataLength)); + // We still need this sync version, because ResourceHandle itself uses it internally, even when the delegate uses an async one. + + return m_allowStoredCredentials == AllowStoredCredentials; } -#if ENABLE(NETWORK_CACHE) -void NetworkResourceLoader::tryStoreAsCacheEntry() +void NetworkResourceLoader::shouldUseCredentialStorageAsync(ResourceHandle* handle) { - if (!canUseCache(m_networkLoad->currentRequest())) - return; - if (!m_bufferedDataForCache) - return; + ASSERT_UNUSED(handle, handle == m_handle); - // Keep the connection alive. - RefPtr<NetworkConnectionToWebProcess> connection(&connectionToWebProcess()); - RefPtr<NetworkResourceLoader> loader(this); - NetworkCache::singleton().store(m_networkLoad->currentRequest(), m_response, WTFMove(m_bufferedDataForCache), [loader, connection](NetworkCache::MappedBody& mappedBody) { -#if ENABLE(SHAREABLE_RESOURCE) - if (mappedBody.shareableResourceHandle.isNull()) - return; - LOG(NetworkCache, "(NetworkProcess) sending DidCacheResource"); - loader->send(Messages::NetworkProcessConnection::DidCacheResource(loader->originalRequest(), mappedBody.shareableResourceHandle, loader->sessionID())); -#endif - }); + handle->continueShouldUseCredentialStorage(shouldUseCredentialStorage(handle)); } -void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) +void NetworkResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - if (isSynchronous()) { - m_synchronousLoadData->response = entry->response(); - sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer()); - } else { - bool needsContinueDidReceiveResponseMessage = originalRequest().requester() == ResourceRequest::Requester::Main; - sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage)); - -#if ENABLE(SHAREABLE_RESOURCE) - if (!entry->shareableResourceHandle().isNull()) - send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime())); - else { -#endif - bool shouldContinue = sendBufferMaybeAborting(*entry->buffer(), entry->buffer()->size()); - if (!shouldContinue) - return; - send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime())); -#if ENABLE(SHAREABLE_RESOURCE) - } -#endif + ASSERT_UNUSED(handle, handle == m_handle); + + // FIXME (http://webkit.org/b/115291): Since we go straight to the UI process for authentication we don't get WebCore's + // cross-origin check before asking the client for credentials. + // Therefore we are too permissive in the case where the ClientCredentialPolicy is DoNotAskClientForCrossOriginCredentials. + if (m_clientCredentialPolicy == DoNotAskClientForAnyCredentials) { + challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge); + return; } - cleanup(); + NetworkProcess::shared().authenticationManager().didReceiveAuthenticationChallenge(m_webPageID, m_webFrameID, challenge); } -void NetworkResourceLoader::validateCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) +void NetworkResourceLoader::didCancelAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - ASSERT(!m_networkLoad); - - // If the request is already conditional then the revalidation was not triggered by the disk cache - // and we should not overwrite the existing conditional headers. - ResourceRequest revalidationRequest = originalRequest(); - if (!revalidationRequest.isConditional()) { - String eTag = entry->response().httpHeaderField(HTTPHeaderName::ETag); - String lastModified = entry->response().httpHeaderField(HTTPHeaderName::LastModified); - if (!eTag.isEmpty()) - revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag); - if (!lastModified.isEmpty()) - revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified); - } - - m_cacheEntryForValidation = WTFMove(entry); + ASSERT_UNUSED(handle, handle == m_handle); - startNetworkLoad(revalidationRequest); + // This function is probably not needed (see <rdar://problem/8960124>). + notImplemented(); } -void NetworkResourceLoader::dispatchWillSendRequestForCacheEntry(std::unique_ptr<NetworkCache::Entry> entry) +void NetworkResourceLoader::receivedCancellation(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - ASSERT(entry->redirectRequest()); - LOG(NetworkCache, "(NetworkProcess) Executing cached redirect"); + ASSERT_UNUSED(handle, handle == m_handle); - ++m_redirectCount; - sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(*entry->redirectRequest(), entry->response())); - m_isWaitingContinueWillSendRequestForCachedRedirect = true; + m_handle->cancel(); + didFail(m_handle.get(), cancelledError(m_request)); } -#endif IPC::Connection* NetworkResourceLoader::messageSenderConnection() { - return connectionToWebProcess().connection(); + return connectionToWebProcess()->connection(); } void NetworkResourceLoader::consumeSandboxExtensions() { - ASSERT(!m_didConsumeSandboxExtensions); - - for (auto& extension : m_parameters.requestBodySandboxExtensions) - extension->consume(); + for (size_t i = 0, count = m_requestBodySandboxExtensions.size(); i < count; ++i) + m_requestBodySandboxExtensions[i]->consume(); - if (auto& extension = m_parameters.resourceSandboxExtension) - extension->consume(); + for (size_t i = 0, count = m_resourceSandboxExtensions.size(); i < count; ++i) + m_resourceSandboxExtensions[i]->consume(); - for (auto& fileReference : m_fileReferences) - fileReference->prepareForFileAccess(); - - m_didConsumeSandboxExtensions = true; + m_sandboxExtensionsAreConsumed = true; } void NetworkResourceLoader::invalidateSandboxExtensions() { - if (m_didConsumeSandboxExtensions) { - for (auto& extension : m_parameters.requestBodySandboxExtensions) - extension->revoke(); - if (auto& extension = m_parameters.resourceSandboxExtension) - extension->revoke(); - for (auto& fileReference : m_fileReferences) - fileReference->revokeFileAccess(); - - m_didConsumeSandboxExtensions = false; + if (m_sandboxExtensionsAreConsumed) { + for (size_t i = 0, count = m_requestBodySandboxExtensions.size(); i < count; ++i) + m_requestBodySandboxExtensions[i]->revoke(); + for (size_t i = 0, count = m_resourceSandboxExtensions.size(); i < count; ++i) + m_resourceSandboxExtensions[i]->revoke(); } - m_fileReferences.clear(); + m_requestBodySandboxExtensions.clear(); + m_resourceSandboxExtensions.clear(); + + m_sandboxExtensionsAreConsumed = false; } -template<typename T> -bool NetworkResourceLoader::sendAbortingOnFailure(T&& message, unsigned messageSendFlags) +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle* handle, const ProtectionSpace& protectionSpace) { - bool result = messageSenderConnection()->send(std::forward<T>(message), messageSenderDestinationID(), messageSendFlags); - if (!result) - abort(); - return result; + ASSERT(isMainThread()); + ASSERT_UNUSED(handle, handle == m_handle); + + m_networkLoaderClient->canAuthenticateAgainstProtectionSpace(this, protectionSpace); } -void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(const ProtectionSpace& protectionSpace) +void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result) { -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - sendAbortingOnFailure(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(protectionSpace)); -#else - UNUSED_PARAM(protectionSpace); + m_handle->continueCanAuthenticateAgainstProtectionSpace(result); +} + #endif + +#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) +bool NetworkResourceLoader::supportsDataArray() +{ + notImplemented(); + return false; } -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result) +void NetworkResourceLoader::didReceiveDataArray(ResourceHandle*, CFArrayRef) { - m_networkLoad->continueCanAuthenticateAgainstProtectionSpace(result); + ASSERT_NOT_REACHED(); + notImplemented(); } #endif +#if PLATFORM(MAC) && !PLATFORM(IOS) +void NetworkResourceLoader::willStopBufferingData(ResourceHandle*, const char*, unsigned) +{ + notImplemented(); +} +#endif // PLATFORM(MAC) + } // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h index d9810dcb4..7b69a5911 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * 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 @@ -26,146 +26,174 @@ #ifndef NetworkResourceLoader_h #define NetworkResourceLoader_h +#if ENABLE(NETWORK_PROCESS) + +#include "HostRecord.h" #include "MessageSender.h" #include "NetworkConnectionToWebProcessMessages.h" -#include "NetworkLoadClient.h" -#include "NetworkResourceLoadParameters.h" #include "ShareableResource.h" -#include <WebCore/Timer.h> -#include <wtf/Optional.h> +#include <WebCore/ResourceHandleClient.h> +#include <WebCore/ResourceLoaderOptions.h> +#include <WebCore/ResourceRequest.h> +#include <wtf/MainThread.h> +#include <wtf/RunLoop.h> + +typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef; namespace WebCore { -class BlobDataFileReference; +class ResourceBuffer; +class ResourceHandle; class ResourceRequest; } namespace WebKit { class NetworkConnectionToWebProcess; -class NetworkLoad; +class NetworkLoaderClient; +class NetworkResourceLoadParameters; +class RemoteNetworkingContext; class SandboxExtension; -namespace NetworkCache { -class Entry; -} - -class NetworkResourceLoader final : public RefCounted<NetworkResourceLoader>, public NetworkLoadClient, public IPC::MessageSender { +class NetworkResourceLoader : public RefCounted<NetworkResourceLoader>, public WebCore::ResourceHandleClient, public IPC::MessageSender { public: - static Ref<NetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess& connection, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply = nullptr) + static RefPtr<NetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection) { - return adoptRef(*new NetworkResourceLoader(parameters, connection, WTFMove(reply))); + return adoptRef(new NetworkResourceLoader(parameters, connection, nullptr)); } - virtual ~NetworkResourceLoader(); + + static RefPtr<NetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) + { + return adoptRef(new NetworkResourceLoader(parameters, connection, reply)); + } + ~NetworkResourceLoader(); - const WebCore::ResourceRequest& originalRequest() const { return m_parameters.request; } + NetworkConnectionToWebProcess* connectionToWebProcess() const { return m_connection.get(); } - NetworkLoad* networkLoad() const { return m_networkLoad.get(); } + WebCore::ResourceLoadPriority priority() { return m_priority; } + WebCore::ResourceRequest& request() { return m_request; } + + WebCore::ResourceHandle* handle() const { return m_handle.get(); } + void didConvertHandleToDownload(); void start(); void abort(); - void setDefersLoading(bool); + // ResourceHandleClient methods + 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 didReceiveResponseAsync(WebCore::ResourceHandle*, const WebCore::ResourceResponse&) override; + virtual void didReceiveData(WebCore::ResourceHandle*, const char*, unsigned, int encodedDataLength) override; + virtual void didReceiveBuffer(WebCore::ResourceHandle*, PassRefPtr<WebCore::SharedBuffer>, int encodedDataLength) 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 void receivedCancellation(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&) override; + virtual bool usesAsyncCallbacks() override { return true; } + +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual void canAuthenticateAgainstProtectionSpaceAsync(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&) override; +#endif + +#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) + virtual bool supportsDataArray() override; + virtual void didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef) override; +#endif -#if PLATFORM(COCOA) +#if PLATFORM(MAC) static size_t fileBackedResourceMinimumSize(); - virtual void willCacheResponseAsync(CFCachedURLResponseRef) override; +#if !PLATFORM(IOS) + virtual void willCacheResponseAsync(WebCore::ResourceHandle*, NSCachedURLResponse *) override; + virtual void willStopBufferingData(WebCore::ResourceHandle*, const char*, unsigned) override; #endif +#endif // PLATFORM(MAC) // Message handlers. - void didReceiveNetworkResourceLoaderMessage(IPC::Connection&, IPC::MessageDecoder&); + void didReceiveNetworkResourceLoaderMessage(IPC::Connection*, IPC::MessageDecoder&); -#if PLATFORM(COCOA) +#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) static void tryGetShareableHandleFromCFURLCachedResponse(ShareableResource::Handle&, CFCachedURLResponseRef); - static void tryGetShareableHandleFromSharedBuffer(ShareableResource::Handle&, WebCore::SharedBuffer&); #endif + bool isSynchronous() const; + bool isLoadingMainResource() const { return m_isLoadingMainResource; } + + void setHostRecord(HostRecord* hostRecord) { ASSERT(isMainThread()); m_hostRecord = hostRecord; } + HostRecord* hostRecord() const { ASSERT(isMainThread()); return m_hostRecord.get(); } + + template<typename T> + bool sendAbortingOnFailure(T&& message, unsigned messageSendFlags = 0) + { + bool result = messageSenderConnection()->send(std::forward<T>(message), messageSenderDestinationID(), messageSendFlags); + if (!result) + abort(); + return result; + } + + #if USE(PROTECTION_SPACE_AUTH_CALLBACK) void continueCanAuthenticateAgainstProtectionSpace(bool); #endif void continueWillSendRequest(const WebCore::ResourceRequest& newRequest); - WebCore::SharedBuffer* bufferedData() { return m_bufferedData.get(); } - const WebCore::ResourceResponse& response() const { return m_response; } - - NetworkConnectionToWebProcess& connectionToWebProcess() { return m_connection; } - WebCore::SessionID sessionID() const { return m_parameters.sessionID; } - ResourceLoadIdentifier identifier() const { return m_parameters.identifier; } - - struct SynchronousLoadData; - - // NetworkLoadClient. - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override; - virtual void canAuthenticateAgainstProtectionSpaceAsync(const WebCore::ProtectionSpace&) override; - virtual bool isSynchronous() const override; - virtual void willSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse& redirectResponse) override; - virtual ShouldContinueDidReceiveResponse didReceiveResponse(const WebCore::ResourceResponse&) override; - virtual void didReceiveBuffer(RefPtr<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override; - virtual void didFinishLoading(double finishTime) override; - virtual void didFailLoading(const WebCore::ResourceError&) override; - virtual void didConvertToDownload() override; +#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) + static void tryGetShareableHandleFromSharedBuffer(ShareableResource::Handle&, WebCore::SharedBuffer*); +#endif private: - NetworkResourceLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess&, RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&&); + NetworkResourceLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>); // IPC::MessageSender virtual IPC::Connection* messageSenderConnection() override; - virtual uint64_t messageSenderDestinationID() override { return m_parameters.identifier; } + virtual uint64_t messageSenderDestinationID() override { return m_identifier; } -#if ENABLE(NETWORK_CACHE) - bool canUseCache(const WebCore::ResourceRequest&) const; - bool canUseCachedRedirect(const WebCore::ResourceRequest&) const; - - void tryStoreAsCacheEntry(); - void retrieveCacheEntry(const WebCore::ResourceRequest&); - void didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry>); - void validateCacheEntry(std::unique_ptr<NetworkCache::Entry>); - void dispatchWillSendRequestForCacheEntry(std::unique_ptr<NetworkCache::Entry>); -#endif - - void startNetworkLoad(const WebCore::ResourceRequest&); void continueDidReceiveResponse(); void cleanup(); void platformDidReceiveResponse(const WebCore::ResourceResponse&); - void startBufferingTimerIfNeeded(); - void bufferingTimerFired(); - bool sendBufferMaybeAborting(WebCore::SharedBuffer&, size_t encodedDataLength); - void consumeSandboxExtensions(); void invalidateSandboxExtensions(); - template<typename T> bool sendAbortingOnFailure(T&& message, unsigned messageSendFlags = 0); - - const NetworkResourceLoadParameters m_parameters; - - Ref<NetworkConnectionToWebProcess> m_connection; + RefPtr<RemoteNetworkingContext> m_networkingContext; + RefPtr<WebCore::ResourceHandle> m_handle; - std::unique_ptr<NetworkLoad> m_networkLoad; + // 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; - WebCore::ResourceResponse m_response; + uint64_t m_bytesReceived; - size_t m_bytesReceived { 0 }; - size_t m_bufferedDataEncodedDataLength { 0 }; - RefPtr<WebCore::SharedBuffer> m_bufferedData; - unsigned m_redirectCount { 0 }; + bool m_handleConvertedToDownload; + std::unique_ptr<NetworkLoaderClient> m_networkLoaderClient; - std::unique_ptr<SynchronousLoadData> m_synchronousLoadData; - Vector<RefPtr<WebCore::BlobDataFileReference>> m_fileReferences; + ResourceLoadIdentifier m_identifier; + uint64_t m_webPageID; + uint64_t m_webFrameID; + uint64_t m_sessionID; + WebCore::ResourceRequest m_request; + WebCore::ResourceLoadPriority m_priority; + WebCore::ContentSniffingPolicy m_contentSniffingPolicy; + WebCore::StoredCredentials m_allowStoredCredentials; + WebCore::ClientCredentialPolicy m_clientCredentialPolicy; + bool m_shouldClearReferrerOnHTTPSToHTTPRedirect; + bool m_isLoadingMainResource; - bool m_didConvertToDownload { false }; - bool m_didConsumeSandboxExtensions { false }; - bool m_defersLoading { false }; + Vector<RefPtr<SandboxExtension>> m_requestBodySandboxExtensions; + Vector<RefPtr<SandboxExtension>> m_resourceSandboxExtensions; + bool m_sandboxExtensionsAreConsumed; - WebCore::Timer m_bufferingTimer; -#if ENABLE(NETWORK_CACHE) - RefPtr<WebCore::SharedBuffer> m_bufferedDataForCache; - std::unique_ptr<NetworkCache::Entry> m_cacheEntryForValidation; - bool m_isWaitingContinueWillSendRequestForCachedRedirect { false }; -#endif + RefPtr<NetworkConnectionToWebProcess> m_connection; + + RefPtr<HostRecord> m_hostRecord; }; } // namespace WebKit +#endif // ENABLE(NETWORK_PROCESS) + #endif // NetworkResourceLoader_h diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in index ebb8d7cd3..79a35af56 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in @@ -20,6 +20,8 @@ # 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. +#if ENABLE(NETWORK_PROCESS) + messages -> NetworkResourceLoader LegacyReceiver { ContinueWillSendRequest(WebCore::ResourceRequest request) @@ -28,3 +30,5 @@ messages -> NetworkResourceLoader LegacyReceiver { ContinueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate) #endif } + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/RemoteNetworkingContext.h b/Source/WebKit2/NetworkProcess/RemoteNetworkingContext.h index 327f2c308..e3ed12b90 100644 --- a/Source/WebKit2/NetworkProcess/RemoteNetworkingContext.h +++ b/Source/WebKit2/NetworkProcess/RemoteNetworkingContext.h @@ -28,46 +28,50 @@ #define RemoteNetworkingContext_h #include <WebCore/NetworkingContext.h> -#include <WebCore/SessionID.h> namespace WebKit { class RemoteNetworkingContext final : public WebCore::NetworkingContext { public: - static Ref<RemoteNetworkingContext> create(WebCore::SessionID sessionID, bool shouldClearReferrerOnHTTPSToHTTPRedirect) + static PassRefPtr<RemoteNetworkingContext> create(uint64_t sessionID, bool shouldClearReferrerOnHTTPSToHTTPRedirect) { - return adoptRef(*new RemoteNetworkingContext(sessionID, shouldClearReferrerOnHTTPSToHTTPRedirect)); + return adoptRef(new RemoteNetworkingContext(sessionID, shouldClearReferrerOnHTTPSToHTTPRedirect)); } virtual ~RemoteNetworkingContext(); // FIXME: Remove platform-specific code and use SessionTracker. - static void ensurePrivateBrowsingSession(WebCore::SessionID); + static void ensurePrivateBrowsingSession(uint64_t sessionID); virtual bool shouldClearReferrerOnHTTPSToHTTPRedirect() const override { return m_shouldClearReferrerOnHTTPSToHTTPRedirect; } private: - RemoteNetworkingContext(WebCore::SessionID sessionID, bool shouldClearReferrerOnHTTPSToHTTPRedirect) + RemoteNetworkingContext(uint64_t sessionID, bool shouldClearReferrerOnHTTPSToHTTPRedirect) : m_sessionID(sessionID) , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect) - { - } +#if PLATFORM(MAC) + , m_needsSiteSpecificQuirks(false) + , m_localFileContentSniffingEnabled(false) +#endif + { } virtual bool isValid() const override; virtual WebCore::NetworkStorageSession& storageSession() const override; -#if PLATFORM(COCOA) +#if PLATFORM(MAC) + void setNeedsSiteSpecificQuirks(bool value) { m_needsSiteSpecificQuirks = value; } + virtual bool needsSiteSpecificQuirks() const override; void setLocalFileContentSniffingEnabled(bool value) { m_localFileContentSniffingEnabled = value; } virtual bool localFileContentSniffingEnabled() const override; virtual RetainPtr<CFDataRef> sourceApplicationAuditData() const override; - virtual String sourceApplicationIdentifier() const override; virtual WebCore::ResourceError blockedError(const WebCore::ResourceRequest&) const override; #endif - WebCore::SessionID m_sessionID; + uint64_t m_sessionID; bool m_shouldClearReferrerOnHTTPSToHTTPRedirect; -#if PLATFORM(COCOA) - bool m_localFileContentSniffingEnabled = false; +#if PLATFORM(MAC) + bool m_needsSiteSpecificQuirks; + bool m_localFileContentSniffingEnabled; #endif }; diff --git a/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.cpp b/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.cpp new file mode 100644 index 000000000..07b148cfc --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SynchronousNetworkLoaderClient.h" + +#if ENABLE(NETWORK_PROCESS) + +#include "DataReference.h" +#include "NetworkResourceLoader.h" +#include "WebErrors.h" +#include <WebCore/ResourceRequest.h> +#include <WebCore/SharedBuffer.h> +#include <WebCore/SynchronousLoaderClient.h> + +using namespace WebCore; + +namespace WebKit { + +SynchronousNetworkLoaderClient::SynchronousNetworkLoaderClient(const ResourceRequest& request, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) + : m_originalRequest(request) + , m_delayedReply(reply) +{ + ASSERT(m_delayedReply); +} + +SynchronousNetworkLoaderClient::~SynchronousNetworkLoaderClient() +{ + // By the time a SynchronousNetworkLoaderClient is being destroyed, it must always have sent its reply to the WebProcess. + ASSERT(!m_delayedReply); +} + +void SynchronousNetworkLoaderClient::willSendRequest(NetworkResourceLoader* loader, ResourceRequest& proposedRequest, const ResourceResponse& redirectResponse) +{ + // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests. + // This includes at least updating host records, and comparing the current request instead of the original request here. + if (!protocolHostAndPortAreEqual(m_originalRequest.url(), proposedRequest.url())) { + ASSERT(m_error.isNull()); + m_error = SynchronousLoaderClient::platformBadResponseError(); + proposedRequest = ResourceRequest(); + } + + m_currentRequest = proposedRequest; + loader->continueWillSendRequest(m_currentRequest); +} + +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +void SynchronousNetworkLoaderClient::canAuthenticateAgainstProtectionSpace(NetworkResourceLoader* loader, const ProtectionSpace&) +{ + // FIXME: We should ask the WebProcess like the asynchronous case below does. + // This is currently impossible as the WebProcess is blocked waiting on this synchronous load. + // It's possible that we can jump straight to the UI process to resolve this. + loader->continueCanAuthenticateAgainstProtectionSpace(true); +} +#endif + +void SynchronousNetworkLoaderClient::didReceiveResponse(NetworkResourceLoader*, const ResourceResponse& response) +{ + m_response = response; +} + +void SynchronousNetworkLoaderClient::didReceiveBuffer(NetworkResourceLoader*, SharedBuffer* buffer, int encodedDataLength) +{ + // FIXME: There's a potential performance improvement here by preallocating a SharedMemory region + // of the expected content length to avoid a copy when we send it to the WebProcess on completion. + // It's unclear if the potential complexities of that approach are worth it. + + if (!m_responseData) + m_responseData = adoptPtr(new Vector<char>); + + m_responseData->append(buffer->data(), buffer->size()); +} + +void SynchronousNetworkLoaderClient::didFinishLoading(NetworkResourceLoader*, double /* finishTime */) +{ + sendDelayedReply(); +} + +void SynchronousNetworkLoaderClient::didFail(NetworkResourceLoader*, const ResourceError& error) +{ + m_error = error; + sendDelayedReply(); +} + +void SynchronousNetworkLoaderClient::sendDelayedReply() +{ + ASSERT(m_delayedReply); + + if (m_response.isNull()) { + ASSERT(!m_error.isNull()); + //platformSynthesizeErrorResponse(); + } + + m_delayedReply->send(m_error, m_response, m_responseData ? *m_responseData : Vector<char>()); + m_delayedReply = nullptr; +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.h b/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.h new file mode 100644 index 000000000..9470678e9 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SynchronousNetworkLoaderClient.h @@ -0,0 +1,76 @@ +/* + * 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 SynchronousNetworkLoaderClient_h +#define SynchronousNetworkLoaderClient_h + +#include "NetworkConnectionToWebProcessMessages.h" +#include "NetworkLoaderClient.h" +#include <WebCore/ResourceError.h> +#include <WebCore/ResourceRequest.h> +#include <WebCore/ResourceResponse.h> +#include <wtf/RefCounted.h> + +#if ENABLE(NETWORK_PROCESS) + +namespace WebCore { +class SharedBuffer; +} + +namespace WebKit { + +class SynchronousNetworkLoaderClient : public NetworkLoaderClient { +public: + SynchronousNetworkLoaderClient(const WebCore::ResourceRequest& originalRequest, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>); + virtual ~SynchronousNetworkLoaderClient() override; + + virtual bool isSynchronous() override { return true; } + +private: + virtual void willSendRequest(NetworkResourceLoader*, WebCore::ResourceRequest& proposedRequest, const WebCore::ResourceResponse& redirectResponse) override; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual void canAuthenticateAgainstProtectionSpace(NetworkResourceLoader*, const WebCore::ProtectionSpace&) override; +#endif + virtual void didReceiveResponse(NetworkResourceLoader*, const WebCore::ResourceResponse&) override; + virtual void didReceiveBuffer(NetworkResourceLoader*, WebCore::SharedBuffer*, int encodedDataLength) override; + virtual void didSendData(NetworkResourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override { } + virtual void didFinishLoading(NetworkResourceLoader*, double finishTime) override; + virtual void didFail(NetworkResourceLoader*, const WebCore::ResourceError&) override; + + void sendDelayedReply(); + + WebCore::ResourceRequest m_originalRequest; + WebCore::ResourceRequest m_currentRequest; + RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> m_delayedReply; + WebCore::ResourceResponse m_response; + WebCore::ResourceError m_error; + OwnPtr<Vector<char>> m_responseData; +}; + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) + +#endif // SynchronousNetworkLoaderClient_h diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp deleted file mode 100644 index 9ea0d3f41..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2014-2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCache.h" - -#if ENABLE(NETWORK_CACHE) - -#include "Logging.h" -#include "NetworkCacheSpeculativeLoadManager.h" -#include "NetworkCacheStatistics.h" -#include "NetworkCacheStorage.h" -#include <WebCore/CacheValidation.h> -#include <WebCore/FileSystem.h> -#include <WebCore/HTTPHeaderNames.h> -#include <WebCore/NetworkStorageSession.h> -#include <WebCore/PlatformCookieJar.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/ResourceResponse.h> -#include <WebCore/SharedBuffer.h> -#include <wtf/MainThread.h> -#include <wtf/NeverDestroyed.h> -#include <wtf/RunLoop.h> -#include <wtf/text/StringBuilder.h> - -#if PLATFORM(COCOA) -#include <notify.h> -#endif - -namespace WebKit { -namespace NetworkCache { - -static const AtomicString& resourceType() -{ - ASSERT(WTF::isMainThread()); - static NeverDestroyed<const AtomicString> resource("resource", AtomicString::ConstructFromLiteral); - return resource; -} - -Cache& singleton() -{ - static NeverDestroyed<Cache> instance; - return instance; -} - -#if PLATFORM(GTK) -static void dumpFileChanged(Cache* cache) -{ - cache->dumpContentsToFile(); -} -#endif - -bool Cache::initialize(const String& cachePath, const Parameters& parameters) -{ - m_storage = Storage::open(cachePath); - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - if (parameters.enableNetworkCacheSpeculativeRevalidation) - m_speculativeLoadManager = std::make_unique<SpeculativeLoadManager>(*m_storage); -#endif - - if (parameters.enableEfficacyLogging) - m_statistics = Statistics::open(cachePath); - -#if PLATFORM(COCOA) - // Triggers with "notifyutil -p com.apple.WebKit.Cache.dump". - if (m_storage) { - int token; - notify_register_dispatch("com.apple.WebKit.Cache.dump", &token, dispatch_get_main_queue(), ^(int) { - dumpContentsToFile(); - }); - } -#endif -#if PLATFORM(GTK) - // Triggers with "touch $cachePath/dump". - if (m_storage) { - CString dumpFilePath = WebCore::fileSystemRepresentation(WebCore::pathByAppendingComponent(m_storage->basePath(), "dump")); - GRefPtr<GFile> dumpFile = adoptGRef(g_file_new_for_path(dumpFilePath.data())); - GFileMonitor* monitor = g_file_monitor_file(dumpFile.get(), G_FILE_MONITOR_NONE, nullptr, nullptr); - g_signal_connect_swapped(monitor, "changed", G_CALLBACK(dumpFileChanged), this); - } -#endif - - LOG(NetworkCache, "(NetworkProcess) opened cache storage, success %d", !!m_storage); - return !!m_storage; -} - -void Cache::setCapacity(size_t maximumSize) -{ - if (!m_storage) - return; - m_storage->setCapacity(maximumSize); -} - -static Key makeCacheKey(const WebCore::ResourceRequest& request) -{ -#if ENABLE(CACHE_PARTITIONING) - String partition = request.cachePartition(); -#else - String partition; -#endif - if (partition.isEmpty()) - partition = ASCIILiteral("No partition"); - - // FIXME: This implements minimal Range header disk cache support. We don't parse - // ranges so only the same exact range request will be served from the cache. - String range = request.httpHeaderField(WebCore::HTTPHeaderName::Range); - return { partition, resourceType(), range, request.url().string() }; -} - -static String headerValueForVary(const WebCore::ResourceRequest& request, const String& headerName) -{ - // Explicit handling for cookies is needed because they are added magically by the networking layer. - // FIXME: The value might have changed between making the request and retrieving the cookie here. - // We could fetch the cookie when making the request but that seems overkill as the case is very rare and it - // is a blocking operation. This should be sufficient to cover reasonable cases. - if (headerName == httpHeaderNameString(WebCore::HTTPHeaderName::Cookie)) - return WebCore::cookieRequestHeaderFieldValue(WebCore::NetworkStorageSession::defaultStorageSession(), request.firstPartyForCookies(), request.url()); - return request.httpHeaderField(headerName); -} - -static Vector<std::pair<String, String>> collectVaryingRequestHeaders(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response) -{ - String varyValue = response.httpHeaderField(WebCore::HTTPHeaderName::Vary); - if (varyValue.isEmpty()) - return { }; - Vector<String> varyingHeaderNames; - varyValue.split(',', /*allowEmptyEntries*/ false, varyingHeaderNames); - Vector<std::pair<String, String>> varyingRequestHeaders; - varyingRequestHeaders.reserveCapacity(varyingHeaderNames.size()); - for (auto& varyHeaderName : varyingHeaderNames) { - String headerName = varyHeaderName.stripWhiteSpace(); - String headerValue = headerValueForVary(request, headerName); - varyingRequestHeaders.append(std::make_pair(headerName, headerValue)); - } - return varyingRequestHeaders; -} - -static bool verifyVaryingRequestHeaders(const Vector<std::pair<String, String>>& varyingRequestHeaders, const WebCore::ResourceRequest& request) -{ - for (auto& varyingRequestHeader : varyingRequestHeaders) { - // FIXME: Vary: * in response would ideally trigger a cache delete instead of a store. - if (varyingRequestHeader.first == "*") - return false; - String headerValue = headerValueForVary(request, varyingRequestHeader.first); - if (headerValue != varyingRequestHeader.second) - return false; - } - return true; -} - -static bool cachePolicyAllowsExpired(WebCore::ResourceRequestCachePolicy policy) -{ - switch (policy) { - case WebCore::ReturnCacheDataElseLoad: - case WebCore::ReturnCacheDataDontLoad: - return true; - case WebCore::UseProtocolCachePolicy: - case WebCore::ReloadIgnoringCacheData: - return false; - } - ASSERT_NOT_REACHED(); - return false; -} - -static bool responseHasExpired(const WebCore::ResourceResponse& response, std::chrono::system_clock::time_point timestamp, Optional<std::chrono::microseconds> maxStale) -{ - if (response.cacheControlContainsNoCache()) - return true; - - auto age = WebCore::computeCurrentAge(response, timestamp); - auto lifetime = WebCore::computeFreshnessLifetimeForHTTPFamily(response, timestamp); - - auto maximumStaleness = maxStale ? maxStale.value() : 0_ms; - bool hasExpired = age - lifetime > maximumStaleness; - -#ifndef LOG_DISABLED - if (hasExpired) - LOG(NetworkCache, "(NetworkProcess) needsRevalidation hasExpired age=%f lifetime=%f max-stale=%g", age, lifetime, maxStale); -#endif - - return hasExpired; -} - -static bool responseNeedsRevalidation(const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, std::chrono::system_clock::time_point timestamp) -{ - auto requestDirectives = WebCore::parseCacheControlDirectives(request.httpHeaderFields()); - if (requestDirectives.noCache) - return true; - // For requests we ignore max-age values other than zero. - if (requestDirectives.maxAge && requestDirectives.maxAge.value() == 0_ms) - return true; - - return responseHasExpired(response, timestamp, requestDirectives.maxStale); -} - -static UseDecision makeUseDecision(const Entry& entry, const WebCore::ResourceRequest& request) -{ - // The request is conditional so we force revalidation from the network. We merely check the disk cache - // so we can update the cache entry. - if (request.isConditional() && !entry.redirectRequest()) - return UseDecision::Validate; - - if (!verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request)) - return UseDecision::NoDueToVaryingHeaderMismatch; - - // We never revalidate in the case of a history navigation. - if (cachePolicyAllowsExpired(request.cachePolicy())) - return UseDecision::Use; - - if (!responseNeedsRevalidation(entry.response(), request, entry.timeStamp())) - return UseDecision::Use; - - if (!entry.response().hasCacheValidatorFields()) - return UseDecision::NoDueToMissingValidatorFields; - - return entry.redirectRequest() ? UseDecision::NoDueToExpiredRedirect : UseDecision::Validate; -} - -static RetrieveDecision makeRetrieveDecision(const WebCore::ResourceRequest& request) -{ - // FIXME: Support HEAD requests. - if (request.httpMethod() != "GET") - return RetrieveDecision::NoDueToHTTPMethod; - if (request.cachePolicy() == WebCore::ReloadIgnoringCacheData && !request.isConditional()) - return RetrieveDecision::NoDueToReloadIgnoringCache; - - return RetrieveDecision::Yes; -} - -// http://tools.ietf.org/html/rfc7231#page-48 -static bool isStatusCodeCacheableByDefault(int statusCode) -{ - switch (statusCode) { - case 200: // OK - case 203: // Non-Authoritative Information - case 204: // No Content - case 206: // Partial Content - case 300: // Multiple Choices - case 301: // Moved Permanently - case 404: // Not Found - case 405: // Method Not Allowed - case 410: // Gone - case 414: // URI Too Long - case 501: // Not Implemented - return true; - default: - return false; - } -} - -static bool isStatusCodePotentiallyCacheable(int statusCode) -{ - switch (statusCode) { - case 201: // Created - case 202: // Accepted - case 205: // Reset Content - case 302: // Found - case 303: // See Other - case 307: // Temporary redirect - case 403: // Forbidden - case 406: // Not Acceptable - case 415: // Unsupported Media Type - return true; - default: - return false; - } -} - -static bool isMediaMIMEType(const String& mimeType) -{ - if (mimeType.startsWith("video/", /*caseSensitive*/ false)) - return true; - if (mimeType.startsWith("audio/", /*caseSensitive*/ false)) - return true; - return false; -} - -static StoreDecision makeStoreDecision(const WebCore::ResourceRequest& originalRequest, const WebCore::ResourceResponse& response) -{ - if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP()) - return StoreDecision::NoDueToProtocol; - - if (originalRequest.httpMethod() != "GET") - return StoreDecision::NoDueToHTTPMethod; - - auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields()); - if (requestDirectives.noStore) - return StoreDecision::NoDueToNoStoreRequest; - - if (response.cacheControlContainsNoStore()) - return StoreDecision::NoDueToNoStoreResponse; - - if (!isStatusCodeCacheableByDefault(response.httpStatusCode())) { - // http://tools.ietf.org/html/rfc7234#section-4.3.2 - bool hasExpirationHeaders = response.expires() || response.cacheControlMaxAge(); - bool expirationHeadersAllowCaching = isStatusCodePotentiallyCacheable(response.httpStatusCode()) && hasExpirationHeaders; - if (!expirationHeadersAllowCaching) - return StoreDecision::NoDueToHTTPStatusCode; - } - - bool isMainResource = originalRequest.requester() == WebCore::ResourceRequest::Requester::Main; - bool storeUnconditionallyForHistoryNavigation = isMainResource || originalRequest.priority() == WebCore::ResourceLoadPriority::VeryHigh; - if (!storeUnconditionallyForHistoryNavigation) { - auto now = std::chrono::system_clock::now(); - bool hasNonZeroLifetime = !response.cacheControlContainsNoCache() && WebCore::computeFreshnessLifetimeForHTTPFamily(response, now) > 0_ms; - - bool possiblyReusable = response.hasCacheValidatorFields() || hasNonZeroLifetime; - if (!possiblyReusable) - return StoreDecision::NoDueToUnlikelyToReuse; - } - - // Media loaded via XHR is likely being used for MSE streaming (YouTube and Netflix for example). - // Streaming media fills the cache quickly and is unlikely to be reused. - // FIXME: We should introduce a separate media cache partition that doesn't affect other resources. - // FIXME: We should also make sure make the MSE paths are copy-free so we can use mapped buffers from disk effectively. - bool isLikelyStreamingMedia = originalRequest.requester() == WebCore::ResourceRequest::Requester::XHR && isMediaMIMEType(response.mimeType()); - if (isLikelyStreamingMedia) - return StoreDecision::NoDueToStreamingMedia; - - return StoreDecision::Yes; -} - -void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, std::function<void (std::unique_ptr<Entry>)> completionHandler) -{ - ASSERT(isEnabled()); - ASSERT(request.url().protocolIsInHTTPFamily()); - - LOG(NetworkCache, "(NetworkProcess) retrieving %s priority %d", request.url().string().ascii().data(), static_cast<int>(request.priority())); - - if (m_statistics) - m_statistics->recordRetrievalRequest(frameID.first); - - Key storageKey = makeCacheKey(request); - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - if (m_speculativeLoadManager) - m_speculativeLoadManager->registerLoad(frameID, request, storageKey); -#endif - - auto retrieveDecision = makeRetrieveDecision(request); - if (retrieveDecision != RetrieveDecision::Yes) { - if (m_statistics) - m_statistics->recordNotUsingCacheForRequest(frameID.first, storageKey, request, retrieveDecision); - - completionHandler(nullptr); - return; - } - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - if (m_speculativeLoadManager && m_speculativeLoadManager->retrieve(frameID, storageKey, [request, completionHandler](std::unique_ptr<Entry> entry) { - if (entry && verifyVaryingRequestHeaders(entry->varyingRequestHeaders(), request)) - completionHandler(WTFMove(entry)); - else - completionHandler(nullptr); - })) - return; -#endif - - auto startTime = std::chrono::system_clock::now(); - auto priority = static_cast<unsigned>(request.priority()); - - m_storage->retrieve(storageKey, priority, [this, request, completionHandler, startTime, storageKey, frameID](std::unique_ptr<Storage::Record> record) { - if (!record) { - LOG(NetworkCache, "(NetworkProcess) not found in storage"); - - if (m_statistics) - m_statistics->recordRetrievalFailure(frameID.first, storageKey, request); - - completionHandler(nullptr); - return false; - } - - ASSERT(record->key == storageKey); - - auto entry = Entry::decodeStorageRecord(*record); - - auto useDecision = entry ? makeUseDecision(*entry, request) : UseDecision::NoDueToDecodeFailure; - switch (useDecision) { - case UseDecision::Use: - break; - case UseDecision::Validate: - entry->setNeedsValidation(); - break; - default: - entry = nullptr; - }; - -#if !LOG_DISABLED - auto elapsedMS = static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count()); - LOG(NetworkCache, "(NetworkProcess) retrieve complete useDecision=%d priority=%d time=%" PRIi64 "ms", static_cast<int>(useDecision), static_cast<int>(request.priority()), elapsedMS); -#endif - completionHandler(WTFMove(entry)); - - if (m_statistics) - m_statistics->recordRetrievedCachedEntry(frameID.first, storageKey, request, useDecision); - return useDecision != UseDecision::NoDueToDecodeFailure; - }); -} - -std::unique_ptr<Entry> Cache::store(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& responseData, std::function<void (MappedBody&)> completionHandler) -{ - ASSERT(isEnabled()); - ASSERT(responseData); - - LOG(NetworkCache, "(NetworkProcess) storing %s, partition %s", request.url().string().latin1().data(), makeCacheKey(request).partition().latin1().data()); - - StoreDecision storeDecision = makeStoreDecision(request, response); - if (storeDecision != StoreDecision::Yes) { - LOG(NetworkCache, "(NetworkProcess) didn't store, storeDecision=%d", static_cast<int>(storeDecision)); - auto key = makeCacheKey(request); - - auto isSuccessfulRevalidation = response.httpStatusCode() == 304; - if (!isSuccessfulRevalidation) { - // Make sure we don't keep a stale entry in the cache. - remove(key); - } - - if (m_statistics) - m_statistics->recordNotCachingResponse(key, storeDecision); - - return nullptr; - } - - std::unique_ptr<Entry> cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, WTFMove(responseData), collectVaryingRequestHeaders(request, response)); - - auto record = cacheEntry->encodeAsStorageRecord(); - - m_storage->store(record, [completionHandler](const Data& bodyData) { - MappedBody mappedBody; -#if ENABLE(SHAREABLE_RESOURCE) - if (RefPtr<SharedMemory> sharedMemory = bodyData.tryCreateSharedMemory()) { - mappedBody.shareableResource = ShareableResource::create(WTFMove(sharedMemory), 0, bodyData.size()); - ASSERT(mappedBody.shareableResource); - mappedBody.shareableResource->createHandle(mappedBody.shareableResourceHandle); - } -#endif - completionHandler(mappedBody); - LOG(NetworkCache, "(NetworkProcess) stored"); - }); - - return cacheEntry; -} - -std::unique_ptr<Entry> Cache::storeRedirect(const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& redirectRequest) -{ - ASSERT(isEnabled()); - - LOG(NetworkCache, "(NetworkProcess) storing redirect %s -> %s", request.url().string().latin1().data(), redirectRequest.url().string().latin1().data()); - - StoreDecision storeDecision = makeStoreDecision(request, response); - if (storeDecision != StoreDecision::Yes) { - LOG(NetworkCache, "(NetworkProcess) didn't store redirect, storeDecision=%d", static_cast<int>(storeDecision)); - auto key = makeCacheKey(request); - if (m_statistics) - m_statistics->recordNotCachingResponse(key, storeDecision); - - return nullptr; - } - - std::unique_ptr<Entry> cacheEntry = std::make_unique<Entry>(makeCacheKey(request), response, redirectRequest, collectVaryingRequestHeaders(request, response)); - - auto record = cacheEntry->encodeAsStorageRecord(); - - m_storage->store(record, nullptr); - - return cacheEntry; -} - -std::unique_ptr<Entry> Cache::update(const WebCore::ResourceRequest& originalRequest, const GlobalFrameID& frameID, const Entry& existingEntry, const WebCore::ResourceResponse& validatingResponse) -{ - LOG(NetworkCache, "(NetworkProcess) updating %s", originalRequest.url().string().latin1().data()); - - WebCore::ResourceResponse response = existingEntry.response(); - WebCore::updateResponseHeadersAfterRevalidation(response, validatingResponse); - response.setSource(WebCore::ResourceResponse::Source::DiskCache); - - auto updateEntry = std::make_unique<Entry>(existingEntry.key(), response, existingEntry.buffer(), collectVaryingRequestHeaders(originalRequest, response)); - auto updateRecord = updateEntry->encodeAsStorageRecord(); - - m_storage->store(updateRecord, { }); - - if (m_statistics) - m_statistics->recordRevalidationSuccess(frameID.first, existingEntry.key(), originalRequest); - - return updateEntry; -} - -void Cache::remove(const Key& key) -{ - ASSERT(isEnabled()); - - m_storage->remove(key); -} - -void Cache::remove(const WebCore::ResourceRequest& request) -{ - remove(makeCacheKey(request)); -} - -void Cache::traverse(const std::function<void (const TraversalEntry*)>& traverseHandler) -{ - ASSERT(isEnabled()); - - // Protect against clients making excessive traversal requests. - const unsigned maximumTraverseCount = 3; - if (m_traverseCount >= maximumTraverseCount) { - WTFLogAlways("Maximum parallel cache traverse count exceeded. Ignoring traversal request."); - - RunLoop::main().dispatch([traverseHandler] { - traverseHandler(nullptr); - }); - return; - } - - ++m_traverseCount; - - m_storage->traverse(resourceType(), 0, [this, traverseHandler](const Storage::Record* record, const Storage::RecordInfo& recordInfo) { - if (!record) { - --m_traverseCount; - traverseHandler(nullptr); - return; - } - - auto entry = Entry::decodeStorageRecord(*record); - if (!entry) - return; - - TraversalEntry traversalEntry { *entry, recordInfo }; - traverseHandler(&traversalEntry); - }); -} - -String Cache::dumpFilePath() const -{ - return WebCore::pathByAppendingComponent(m_storage->versionPath(), "dump.json"); -} - -void Cache::dumpContentsToFile() -{ - if (!m_storage) - return; - auto fd = WebCore::openFile(dumpFilePath(), WebCore::OpenForWrite); - if (!WebCore::isHandleValid(fd)) - return; - auto prologue = String("{\n\"entries\": [\n").utf8(); - WebCore::writeToFile(fd, prologue.data(), prologue.length()); - - struct Totals { - unsigned count { 0 }; - double worth { 0 }; - size_t bodySize { 0 }; - }; - Totals totals; - auto flags = Storage::TraverseFlag::ComputeWorth | Storage::TraverseFlag::ShareCount; - size_t capacity = m_storage->capacity(); - m_storage->traverse(resourceType(), flags, [fd, totals, capacity](const Storage::Record* record, const Storage::RecordInfo& info) mutable { - if (!record) { - StringBuilder epilogue; - epilogue.appendLiteral("{}\n],\n"); - epilogue.appendLiteral("\"totals\": {\n"); - epilogue.appendLiteral("\"capacity\": "); - epilogue.appendNumber(capacity); - epilogue.appendLiteral(",\n"); - epilogue.appendLiteral("\"count\": "); - epilogue.appendNumber(totals.count); - epilogue.appendLiteral(",\n"); - epilogue.appendLiteral("\"bodySize\": "); - epilogue.appendNumber(totals.bodySize); - epilogue.appendLiteral(",\n"); - epilogue.appendLiteral("\"averageWorth\": "); - epilogue.appendNumber(totals.count ? totals.worth / totals.count : 0); - epilogue.appendLiteral("\n"); - epilogue.appendLiteral("}\n}\n"); - auto writeData = epilogue.toString().utf8(); - WebCore::writeToFile(fd, writeData.data(), writeData.length()); - WebCore::closeFile(fd); - return; - } - auto entry = Entry::decodeStorageRecord(*record); - if (!entry) - return; - ++totals.count; - totals.worth += info.worth; - totals.bodySize += info.bodySize; - - StringBuilder json; - entry->asJSON(json, info); - json.appendLiteral(",\n"); - auto writeData = json.toString().utf8(); - WebCore::writeToFile(fd, writeData.data(), writeData.length()); - }); -} - -void Cache::deleteDumpFile() -{ - auto queue = WorkQueue::create("com.apple.WebKit.Cache.delete"); - StringCapture dumpFilePathCapture(dumpFilePath()); - queue->dispatch([dumpFilePathCapture] { - WebCore::deleteFile(dumpFilePathCapture.string()); - }); -} - -void Cache::clear(std::chrono::system_clock::time_point modifiedSince, std::function<void ()>&& completionHandler) -{ - LOG(NetworkCache, "(NetworkProcess) clearing cache"); - - if (m_statistics) - m_statistics->clear(); - - if (!m_storage) { - RunLoop::main().dispatch(completionHandler); - return; - } - String anyType; - m_storage->clear(anyType, modifiedSince, WTFMove(completionHandler)); - - deleteDumpFile(); -} - -void Cache::clear() -{ - clear(std::chrono::system_clock::time_point::min(), nullptr); -} - -String Cache::recordsPath() const -{ - return m_storage ? m_storage->recordsPath() : String(); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCache.h b/Source/WebKit2/NetworkProcess/cache/NetworkCache.h deleted file mode 100644 index 38db1fab8..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCache.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2014-2015 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 NetworkCache_h -#define NetworkCache_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheEntry.h" -#include "NetworkCacheStorage.h" -#include "ShareableResource.h" -#include <WebCore/ResourceResponse.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { -class ResourceRequest; -class SharedBuffer; -class URL; -} - -namespace WebKit { -namespace NetworkCache { - -class Cache; -class SpeculativeLoadManager; -class Statistics; - -Cache& singleton(); - -struct MappedBody { -#if ENABLE(SHAREABLE_RESOURCE) - RefPtr<ShareableResource> shareableResource; - ShareableResource::Handle shareableResourceHandle; -#endif -}; - -enum class RetrieveDecision { - Yes, - NoDueToHTTPMethod, - NoDueToConditionalRequest, - NoDueToReloadIgnoringCache -}; - -// FIXME: This enum is used in the Statistics code in a way that prevents removing or reordering anything. -enum class StoreDecision { - Yes, - NoDueToProtocol, - NoDueToHTTPMethod, - NoDueToAttachmentResponse, // Unused. - NoDueToNoStoreResponse, - NoDueToHTTPStatusCode, - NoDueToNoStoreRequest, - NoDueToUnlikelyToReuse, - NoDueToStreamingMedia -}; - -enum class UseDecision { - Use, - Validate, - NoDueToVaryingHeaderMismatch, - NoDueToMissingValidatorFields, - NoDueToDecodeFailure, - NoDueToExpiredRedirect, -}; - -using GlobalFrameID = std::pair<uint64_t /*webPageID*/, uint64_t /*webFrameID*/>; - -class Cache { - WTF_MAKE_NONCOPYABLE(Cache); - friend class WTF::NeverDestroyed<Cache>; -public: - struct Parameters { - bool enableEfficacyLogging; -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - bool enableNetworkCacheSpeculativeRevalidation; -#endif - }; - bool initialize(const String& cachePath, const Parameters&); - void setCapacity(size_t); - - bool isEnabled() const { return !!m_storage; } - - // Completion handler may get called back synchronously on failure. - void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, std::function<void (std::unique_ptr<Entry>)>); - std::unique_ptr<Entry> store(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, std::function<void (MappedBody&)>); - std::unique_ptr<Entry> storeRedirect(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, const WebCore::ResourceRequest& redirectRequest); - std::unique_ptr<Entry> update(const WebCore::ResourceRequest&, const GlobalFrameID&, const Entry&, const WebCore::ResourceResponse& validatingResponse); - - struct TraversalEntry { - const Entry& entry; - const Storage::RecordInfo& recordInfo; - }; - void traverse(const std::function<void (const TraversalEntry*)>&); - void remove(const Key&); - void remove(const WebCore::ResourceRequest&); - - void clear(); - void clear(std::chrono::system_clock::time_point modifiedSince, std::function<void ()>&& completionHandler); - - void dumpContentsToFile(); - - String recordsPath() const; - -private: - Cache() = default; - ~Cache() = delete; - - String dumpFilePath() const; - void deleteDumpFile(); - - std::unique_ptr<Storage> m_storage; -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - std::unique_ptr<SpeculativeLoadManager> m_speculativeLoadManager; -#endif - std::unique_ptr<Statistics> m_statistics; - - unsigned m_traverseCount { 0 }; -}; - -} -} -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.cpp deleted file mode 100644 index 32c0a1ec5..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheBlobStorage.h" - -#if ENABLE(NETWORK_CACHE) - -#include "Logging.h" -#include "NetworkCacheFileSystem.h" -#include <WebCore/FileSystem.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <wtf/RunLoop.h> -#include <wtf/SHA1.h> -#include <wtf/text/StringBuilder.h> - -namespace WebKit { -namespace NetworkCache { - -BlobStorage::BlobStorage(const String& blobDirectoryPath) - : m_blobDirectoryPath(blobDirectoryPath) -{ -} - -String BlobStorage::blobDirectoryPath() const -{ - return m_blobDirectoryPath.isolatedCopy(); -} - -void BlobStorage::synchronize() -{ - ASSERT(!RunLoop::isMain()); - - WebCore::makeAllDirectories(blobDirectoryPath()); - - m_approximateSize = 0; - auto blobDirectory = blobDirectoryPath(); - traverseDirectory(blobDirectory, [this, &blobDirectory](const String& name, DirectoryEntryType type) { - if (type != DirectoryEntryType::File) - return; - auto path = WebCore::pathByAppendingComponent(blobDirectory, name); - auto filePath = WebCore::fileSystemRepresentation(path); - struct stat stat; - ::stat(filePath.data(), &stat); - // No clients left for this blob. - if (stat.st_nlink == 1) - unlink(filePath.data()); - else - m_approximateSize += stat.st_size; - }); - - LOG(NetworkCacheStorage, "(NetworkProcess) blob synchronization completed approximateSize=%zu", approximateSize()); -} - -String BlobStorage::blobPathForHash(const SHA1::Digest& hash) const -{ - auto hashAsString = SHA1::hexDigest(hash); - return WebCore::pathByAppendingComponent(blobDirectoryPath(), String::fromUTF8(hashAsString)); -} - -BlobStorage::Blob BlobStorage::add(const String& path, const Data& data) -{ - ASSERT(!RunLoop::isMain()); - - auto hash = computeSHA1(data); - if (data.isEmpty()) - return { data, hash }; - - auto blobPath = WebCore::fileSystemRepresentation(blobPathForHash(hash)); - auto linkPath = WebCore::fileSystemRepresentation(path); - unlink(linkPath.data()); - - bool blobExists = access(blobPath.data(), F_OK) != -1; - if (blobExists) { - auto existingData = mapFile(blobPath.data()); - if (bytesEqual(existingData, data)) { - link(blobPath.data(), linkPath.data()); - return { existingData, hash }; - } - unlink(blobPath.data()); - } - - auto mappedData = data.mapToFile(blobPath.data()); - if (mappedData.isNull()) - return { }; - - link(blobPath.data(), linkPath.data()); - - m_approximateSize += mappedData.size(); - - return { mappedData, hash }; -} - -BlobStorage::Blob BlobStorage::get(const String& path) -{ - ASSERT(!RunLoop::isMain()); - - auto linkPath = WebCore::fileSystemRepresentation(path); - auto data = mapFile(linkPath.data()); - - return { data, computeSHA1(data) }; -} - -void BlobStorage::remove(const String& path) -{ - ASSERT(!RunLoop::isMain()); - - auto linkPath = WebCore::fileSystemRepresentation(path); - unlink(linkPath.data()); -} - -unsigned BlobStorage::shareCount(const String& path) -{ - ASSERT(!RunLoop::isMain()); - - auto linkPath = WebCore::fileSystemRepresentation(path); - struct stat stat; - if (::stat(linkPath.data(), &stat) < 0) - return 0; - // Link count is 2 in the single client case (the blob file and a link). - return stat.st_nlink - 1; -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.h deleted file mode 100644 index e4b494cf9..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheBlobStorage.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheBlobStorage_h -#define NetworkCacheBlobStorage_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheData.h" -#include "NetworkCacheKey.h" -#include <wtf/SHA1.h> - -namespace WebKit { -namespace NetworkCache { - -// BlobStorage deduplicates the data using SHA1 hash computed over the blob bytes. -class BlobStorage { - WTF_MAKE_NONCOPYABLE(BlobStorage); -public: - BlobStorage(const String& blobDirectoryPath); - - struct Blob { - Data data; - SHA1::Digest hash; - }; - // These are all synchronous and should not be used from the main thread. - Blob add(const String& path, const Data&); - Blob get(const String& path); - - // Blob won't be removed until synchronization. - void remove(const String& path); - - unsigned shareCount(const String& path); - - size_t approximateSize() const { return m_approximateSize; } - - void synchronize(); - -private: - String blobDirectoryPath() const; - String blobPathForHash(const SHA1::Digest&) const; - - const String m_blobDirectoryPath; - - std::atomic<size_t> m_approximateSize { 0 }; -}; - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoder.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoder.h deleted file mode 100644 index 4b4be369d..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoder.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010, 2014 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 NetworkCacheCoder_h -#define NetworkCacheCoder_h - -#if ENABLE(NETWORK_CACHE) - -namespace WebKit { -namespace NetworkCache { - -class Decoder; -class Encoder; - -template<typename T> struct Coder { - static void encode(Encoder& encoder, const T& t) - { - t.encode(encoder); - } - - static bool decode(Decoder& decoder, T& t) - { - return T::decode(decoder, t); - } -}; - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.cpp deleted file mode 100644 index 868d7c3ed..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2011, 2014-2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheCoders.h" - -#if ENABLE(NETWORK_CACHE) - -#include "WebCoreArgumentCoders.h" -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -namespace WebKit { -namespace NetworkCache { - -void Coder<AtomicString>::encode(Encoder& encoder, const AtomicString& atomicString) -{ - encoder << atomicString.string(); -} - -bool Coder<AtomicString>::decode(Decoder& decoder, AtomicString& atomicString) -{ - String string; - if (!decoder.decode(string)) - return false; - - atomicString = string; - return true; -} - -void Coder<CString>::encode(Encoder& encoder, const CString& string) -{ - // Special case the null string. - if (string.isNull()) { - encoder << std::numeric_limits<uint32_t>::max(); - return; - } - - uint32_t length = string.length(); - encoder << length; - encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.data()), length); -} - -bool Coder<CString>::decode(Decoder& decoder, CString& result) -{ - uint32_t length; - if (!decoder.decode(length)) - return false; - - if (length == std::numeric_limits<uint32_t>::max()) { - // This is the null string. - result = CString(); - return true; - } - - // Before allocating the string, make sure that the decoder buffer is big enough. - if (!decoder.bufferIsLargeEnoughToContain<char>(length)) - return false; - - char* buffer; - CString string = CString::newUninitialized(length, buffer); - if (!decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(buffer), length)) - return false; - - result = string; - return true; -} - - -void Coder<String>::encode(Encoder& encoder, const String& string) -{ - // Special case the null string. - if (string.isNull()) { - encoder << std::numeric_limits<uint32_t>::max(); - return; - } - - uint32_t length = string.length(); - bool is8Bit = string.is8Bit(); - - encoder << length << is8Bit; - - if (is8Bit) - encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.characters8()), length * sizeof(LChar)); - else - encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(string.characters16()), length * sizeof(UChar)); -} - -template <typename CharacterType> -static inline bool decodeStringText(Decoder& decoder, uint32_t length, String& result) -{ - // Before allocating the string, make sure that the decoder buffer is big enough. - if (!decoder.bufferIsLargeEnoughToContain<CharacterType>(length)) - return false; - - CharacterType* buffer; - String string = String::createUninitialized(length, buffer); - if (!decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(buffer), length * sizeof(CharacterType))) - return false; - - result = string; - return true; -} - -bool Coder<String>::decode(Decoder& decoder, String& result) -{ - uint32_t length; - if (!decoder.decode(length)) - return false; - - if (length == std::numeric_limits<uint32_t>::max()) { - // This is the null string. - result = String(); - return true; - } - - bool is8Bit; - if (!decoder.decode(is8Bit)) - return false; - - if (is8Bit) - return decodeStringText<LChar>(decoder, length, result); - return decodeStringText<UChar>(decoder, length, result); -} - -void Coder<WebCore::CertificateInfo>::encode(Encoder& encoder, const WebCore::CertificateInfo& certificateInfo) -{ - // FIXME: Cocoa CertificateInfo is a CF object tree. Generalize CF type coding so we don't need to use ArgumentCoder here. - IPC::ArgumentEncoder argumentEncoder; - argumentEncoder << certificateInfo; - encoder << static_cast<uint64_t>(argumentEncoder.bufferSize()); - encoder.encodeFixedLengthData(argumentEncoder.buffer(), argumentEncoder.bufferSize()); -} - -bool Coder<WebCore::CertificateInfo>::decode(Decoder& decoder, WebCore::CertificateInfo& certificateInfo) -{ - uint64_t certificateSize; - if (!decoder.decode(certificateSize)) - return false; - Vector<uint8_t> data(certificateSize); - if (!decoder.decodeFixedLengthData(data.data(), data.size())) - return false; - IPC::ArgumentDecoder argumentDecoder(data.data(), data.size()); - return argumentDecoder.decode(certificateInfo); -} - -void Coder<SHA1::Digest>::encode(Encoder& encoder, const SHA1::Digest& digest) -{ - encoder.encodeFixedLengthData(digest.data(), sizeof(digest)); -} - -bool Coder<SHA1::Digest>::decode(Decoder& decoder, SHA1::Digest& digest) -{ - return decoder.decodeFixedLengthData(digest.data(), sizeof(digest)); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.h deleted file mode 100644 index 13aefbf4f..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheCoders.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2010, 2014-2015 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 NetworkCacheCoders_h -#define NetworkCacheCoders_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheDecoder.h" -#include "NetworkCacheEncoder.h" -#include <WebCore/CertificateInfo.h> -#include <utility> -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/SHA1.h> -#include <wtf/Vector.h> - -namespace WebKit { -namespace NetworkCache { - -template<typename T, typename U> struct Coder<std::pair<T, U>> { - static void encode(Encoder& encoder, const std::pair<T, U>& pair) - { - encoder << pair.first << pair.second; - } - - static bool decode(Decoder& decoder, std::pair<T, U>& pair) - { - T first; - if (!decoder.decode(first)) - return false; - - U second; - if (!decoder.decode(second)) - return false; - - pair.first = first; - pair.second = second; - return true; - } -}; - -template<typename Rep, typename Period> struct Coder<std::chrono::duration<Rep, Period>> { - static void encode(Encoder& encoder, const std::chrono::duration<Rep, Period>& duration) - { - static_assert(std::is_integral<Rep>::value && std::is_signed<Rep>::value && sizeof(Rep) <= sizeof(int64_t), "Serialization of this Rep type is not supported yet. Only signed integer type which can be fit in an int64_t is currently supported."); - encoder << static_cast<int64_t>(duration.count()); - } - - static bool decode(Decoder& decoder, std::chrono::duration<Rep, Period>& result) - { - int64_t count; - if (!decoder.decode(count)) - return false; - result = std::chrono::duration<Rep, Period>(static_cast<Rep>(count)); - return true; - } -}; - -template<typename KeyType, typename ValueType> struct Coder<WTF::KeyValuePair<KeyType, ValueType>> { - static void encode(Encoder& encoder, const WTF::KeyValuePair<KeyType, ValueType>& pair) - { - encoder << pair.key << pair.value; - } - - static bool decode(Decoder& decoder, WTF::KeyValuePair<KeyType, ValueType>& pair) - { - KeyType key; - if (!decoder.decode(key)) - return false; - - ValueType value; - if (!decoder.decode(value)) - return false; - - pair.key = key; - pair.value = value; - return true; - } -}; - -template<bool fixedSizeElements, typename T, size_t inlineCapacity> struct VectorCoder; - -template<typename T, size_t inlineCapacity> struct VectorCoder<false, T, inlineCapacity> { - static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector) - { - encoder << static_cast<uint64_t>(vector.size()); - for (size_t i = 0; i < vector.size(); ++i) - encoder << vector[i]; - } - - static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector) - { - uint64_t size; - if (!decoder.decode(size)) - return false; - - Vector<T, inlineCapacity> tmp; - for (size_t i = 0; i < size; ++i) { - T element; - if (!decoder.decode(element)) - return false; - - tmp.append(WTFMove(element)); - } - - tmp.shrinkToFit(); - vector.swap(tmp); - return true; - } -}; - -template<typename T, size_t inlineCapacity> struct VectorCoder<true, T, inlineCapacity> { - static void encode(Encoder& encoder, const Vector<T, inlineCapacity>& vector) - { - encoder << static_cast<uint64_t>(vector.size()); - encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(vector.data()), vector.size() * sizeof(T), alignof(T)); - } - - static bool decode(Decoder& decoder, Vector<T, inlineCapacity>& vector) - { - uint64_t size; - if (!decoder.decode(size)) - return false; - - // Since we know the total size of the elements, we can allocate the vector in - // one fell swoop. Before allocating we must however make sure that the decoder buffer - // is big enough. - if (!decoder.bufferIsLargeEnoughToContain<T>(size)) - return false; - - Vector<T, inlineCapacity> temp; - temp.resize(size); - - decoder.decodeFixedLengthData(reinterpret_cast<uint8_t*>(temp.data()), size * sizeof(T)); - - vector.swap(temp); - return true; - } -}; - -template<typename T, size_t inlineCapacity> struct Coder<Vector<T, inlineCapacity>> : VectorCoder<std::is_arithmetic<T>::value, T, inlineCapacity> { }; - -template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> struct Coder<HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { - typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; - - static void encode(Encoder& encoder, const HashMapType& hashMap) - { - encoder << static_cast<uint64_t>(hashMap.size()); - for (typename HashMapType::const_iterator it = hashMap.begin(), end = hashMap.end(); it != end; ++it) - encoder << *it; - } - - static bool decode(Decoder& decoder, HashMapType& hashMap) - { - uint64_t hashMapSize; - if (!decoder.decode(hashMapSize)) - return false; - - HashMapType tempHashMap; - for (uint64_t i = 0; i < hashMapSize; ++i) { - KeyArg key; - MappedArg value; - if (!decoder.decode(key)) - return false; - if (!decoder.decode(value)) - return false; - - if (!tempHashMap.add(key, value).isNewEntry) { - // The hash map already has the specified key, bail. - return false; - } - } - - hashMap.swap(tempHashMap); - return true; - } -}; - -template<typename KeyArg, typename HashArg, typename KeyTraitsArg> struct Coder<HashSet<KeyArg, HashArg, KeyTraitsArg>> { - typedef HashSet<KeyArg, HashArg, KeyTraitsArg> HashSetType; - - static void encode(Encoder& encoder, const HashSetType& hashSet) - { - encoder << static_cast<uint64_t>(hashSet.size()); - for (typename HashSetType::const_iterator it = hashSet.begin(), end = hashSet.end(); it != end; ++it) - encoder << *it; - } - - static bool decode(Decoder& decoder, HashSetType& hashSet) - { - uint64_t hashSetSize; - if (!decoder.decode(hashSetSize)) - return false; - - HashSetType tempHashSet; - for (uint64_t i = 0; i < hashSetSize; ++i) { - KeyArg key; - if (!decoder.decode(key)) - return false; - - if (!tempHashSet.add(key).isNewEntry) { - // The hash map already has the specified key, bail. - return false; - } - } - - hashSet.swap(tempHashSet); - return true; - } -}; - -template<> struct Coder<AtomicString> { - static void encode(Encoder&, const AtomicString&); - static bool decode(Decoder&, AtomicString&); -}; - -template<> struct Coder<CString> { - static void encode(Encoder&, const CString&); - static bool decode(Decoder&, CString&); -}; - -template<> struct Coder<String> { - static void encode(Encoder&, const String&); - static bool decode(Decoder&, String&); -}; - -template<> struct Coder<WebCore::CertificateInfo> { - static void encode(Encoder&, const WebCore::CertificateInfo&); - static bool decode(Decoder&, WebCore::CertificateInfo&); -}; - -template<> struct Coder<SHA1::Digest> { - static void encode(Encoder&, const SHA1::Digest&); - static bool decode(Decoder&, SHA1::Digest&); -}; - -} -} -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.cpp deleted file mode 100644 index f950d69ed..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheData.h" - -#if ENABLE(NETWORK_CACHE) - -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> - -namespace WebKit { -namespace NetworkCache { - -Data Data::mapToFile(const char* path) const -{ - int fd = open(path, O_CREAT | O_EXCL | O_RDWR , S_IRUSR | S_IWUSR); - if (fd < 0) - return { }; - - if (ftruncate(fd, m_size) < 0) { - close(fd); - return { }; - } - - void* map = mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) { - close(fd); - return { }; - } - - uint8_t* mapData = static_cast<uint8_t*>(map); - apply([&mapData](const uint8_t* bytes, size_t bytesSize) { - memcpy(mapData, bytes, bytesSize); - mapData += bytesSize; - return true; - }); - - // Drop the write permission. - mprotect(map, m_size, PROT_READ); - - // Flush (asynchronously) to file, turning this into clean memory. - msync(map, m_size, MS_ASYNC); - - return Data::adoptMap(map, m_size, fd); -} - -Data mapFile(const char* path) -{ - int fd = open(path, O_RDONLY, 0); - if (fd < 0) - return { }; - struct stat stat; - if (fstat(fd, &stat) < 0) { - close(fd); - return { }; - } - size_t size = stat.st_size; - if (!size) { - close(fd); - return Data::empty(); - } - - return adoptAndMapFile(fd, 0, size); -} - -Data adoptAndMapFile(int fd, size_t offset, size_t size) -{ - if (!size) { - close(fd); - return Data::empty(); - } - - void* map = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, offset); - if (map == MAP_FAILED) { - close(fd); - return { }; - } - - return Data::adoptMap(map, size, fd); -} - -SHA1::Digest computeSHA1(const Data& data) -{ - SHA1 sha1; - data.apply([&sha1](const uint8_t* data, size_t size) { - sha1.addBytes(data, size); - return true; - }); - SHA1::Digest digest; - sha1.computeHash(digest); - return digest; -} - -bool bytesEqual(const Data& a, const Data& b) -{ - if (a.isNull() || b.isNull()) - return false; - if (a.size() != b.size()) - return false; - return !memcmp(a.data(), b.data(), a.size()); -} - -} // namespace NetworkCache -} // namespace WebKit - -#endif // #if ENABLE(NETWORK_CACHE) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h deleted file mode 100644 index 225589854..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheData_h -#define NetworkCacheData_h - -#if ENABLE(NETWORK_CACHE) - -#include <functional> -#include <wtf/FunctionDispatcher.h> -#include <wtf/SHA1.h> -#include <wtf/ThreadSafeRefCounted.h> -#include <wtf/text/WTFString.h> - -#if USE(SOUP) -#include <WebCore/GRefPtrSoup.h> -#endif - -namespace WebKit { - -class SharedMemory; - -namespace NetworkCache { - -#if PLATFORM(COCOA) -template <typename T> class DispatchPtr; -template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject); - -// FIXME: Use OSObjectPtr instead when it works with dispatch_data_t on all platforms. -template<typename T> class DispatchPtr { -public: - DispatchPtr() - : m_ptr(nullptr) - { - } - explicit DispatchPtr(T ptr) - : m_ptr(ptr) - { - if (m_ptr) - dispatch_retain(m_ptr); - } - DispatchPtr(const DispatchPtr& other) - : m_ptr(other.m_ptr) - { - if (m_ptr) - dispatch_retain(m_ptr); - } - ~DispatchPtr() - { - if (m_ptr) - dispatch_release(m_ptr); - } - - DispatchPtr& operator=(const DispatchPtr& other) - { - auto copy = other; - std::swap(m_ptr, copy.m_ptr); - return *this; - } - - T get() const { return m_ptr; } - explicit operator bool() const { return m_ptr; } - - friend DispatchPtr adoptDispatch<T>(T); - -private: - struct Adopt { }; - DispatchPtr(Adopt, T data) - : m_ptr(data) - { - } - - T m_ptr; -}; - -template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject) -{ - return DispatchPtr<T>(typename DispatchPtr<T>::Adopt { }, dispatchObject); -} -#endif - -class Data { -public: - Data() { } - Data(const uint8_t*, size_t); - - static Data empty(); - static Data adoptMap(void* map, size_t, int fd); - -#if PLATFORM(COCOA) - enum class Backing { Buffer, Map }; - Data(DispatchPtr<dispatch_data_t>, Backing = Backing::Buffer); -#endif -#if USE(SOUP) - Data(GRefPtr<SoupBuffer>&&, int fd = -1); -#endif - bool isNull() const; - bool isEmpty() const { return !m_size; } - - const uint8_t* data() const; - size_t size() const { return m_size; } - bool isMap() const { return m_isMap; } - RefPtr<SharedMemory> tryCreateSharedMemory() const; - - Data subrange(size_t offset, size_t) const; - - bool apply(const std::function<bool (const uint8_t*, size_t)>&&) const; - - Data mapToFile(const char* path) const; - -#if PLATFORM(COCOA) - dispatch_data_t dispatchData() const { return m_dispatchData.get(); } -#endif - -#if USE(SOUP) - SoupBuffer* soupBuffer() const { return m_buffer.get(); } -#endif -private: -#if PLATFORM(COCOA) - mutable DispatchPtr<dispatch_data_t> m_dispatchData; -#endif -#if USE(SOUP) - mutable GRefPtr<SoupBuffer> m_buffer; - int m_fileDescriptor { -1 }; -#endif - mutable const uint8_t* m_data { nullptr }; - size_t m_size { 0 }; - bool m_isMap { false }; -}; - -Data concatenate(const Data&, const Data&); -bool bytesEqual(const Data&, const Data&); -Data adoptAndMapFile(int fd, size_t offset, size_t); -Data mapFile(const char* path); -SHA1::Digest computeSHA1(const Data&); - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDataSoup.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheDataSoup.cpp deleted file mode 100644 index 644c38e30..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDataSoup.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2015 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 "NetworkCacheData.h" - -#if ENABLE(NETWORK_CACHE) - -#include "SharedMemory.h" -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace WebKit { -namespace NetworkCache { - -Data::Data(const uint8_t* data, size_t size) - : m_size(size) -{ - uint8_t* copiedData = static_cast<uint8_t*>(fastMalloc(size)); - memcpy(copiedData, data, size); - m_buffer = adoptGRef(soup_buffer_new_with_owner(copiedData, size, copiedData, fastFree)); -} - -Data::Data(GRefPtr<SoupBuffer>&& buffer, int fd) - : m_buffer(buffer) - , m_fileDescriptor(fd) - , m_size(buffer ? buffer->length : 0) - , m_isMap(m_size && fd != -1) -{ -} - -Data Data::empty() -{ - GRefPtr<SoupBuffer> buffer = adoptGRef(soup_buffer_new(SOUP_MEMORY_TAKE, nullptr, 0)); - return { WTFMove(buffer) }; -} - -const uint8_t* Data::data() const -{ - return m_buffer ? reinterpret_cast<const uint8_t*>(m_buffer->data) : nullptr; -} - -bool Data::isNull() const -{ - return !m_buffer; -} - -bool Data::apply(const std::function<bool (const uint8_t*, size_t)>&& applier) const -{ - if (!m_size) - return false; - - return applier(reinterpret_cast<const uint8_t*>(m_buffer->data), m_buffer->length); -} - -Data Data::subrange(size_t offset, size_t size) const -{ - if (!m_buffer) - return { }; - - GRefPtr<SoupBuffer> subBuffer = adoptGRef(soup_buffer_new_subbuffer(m_buffer.get(), offset, size)); - return { WTFMove(subBuffer) }; -} - -Data concatenate(const Data& a, const Data& b) -{ - if (a.isNull()) - return b; - if (b.isNull()) - return a; - - size_t size = a.size() + b.size(); - uint8_t* data = static_cast<uint8_t*>(fastMalloc(size)); - memcpy(data, a.soupBuffer()->data, a.soupBuffer()->length); - memcpy(data + a.soupBuffer()->length, b.soupBuffer()->data, b.soupBuffer()->length); - GRefPtr<SoupBuffer> buffer = adoptGRef(soup_buffer_new_with_owner(data, size, data, fastFree)); - return { WTFMove(buffer) }; -} - -struct MapWrapper { - ~MapWrapper() - { - munmap(map, size); - close(fileDescriptor); - } - - void* map; - size_t size; - int fileDescriptor; -}; - -static void deleteMapWrapper(MapWrapper* wrapper) -{ - delete wrapper; -} - -Data Data::adoptMap(void* map, size_t size, int fd) -{ - ASSERT(map); - ASSERT(map != MAP_FAILED); - MapWrapper* wrapper = new MapWrapper { map, size, fd }; - GRefPtr<SoupBuffer> buffer = adoptGRef(soup_buffer_new_with_owner(map, size, wrapper, reinterpret_cast<GDestroyNotify>(deleteMapWrapper))); - return { WTFMove(buffer), fd }; -} - -RefPtr<SharedMemory> Data::tryCreateSharedMemory() const -{ - if (isNull() || !isMap()) - return nullptr; - - return SharedMemory::wrapMap(const_cast<char*>(m_buffer->data), m_buffer->length, m_fileDescriptor); -} - -} // namespace NetworkCache -} // namespace WebKit - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.cpp deleted file mode 100644 index 80e657578..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2010, 2011, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheDecoder.h" - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheEncoder.h" - -namespace WebKit { -namespace NetworkCache { - -Decoder::Decoder(const uint8_t* buffer, size_t bufferSize) - : m_buffer(buffer) - , m_bufferPosition(buffer) - , m_bufferEnd(buffer + bufferSize) -{ -} - -Decoder::~Decoder() -{ -} - -bool Decoder::bufferIsLargeEnoughToContain(size_t size) const -{ - return size <= static_cast<size_t>(m_bufferEnd - m_bufferPosition); -} - -bool Decoder::decodeFixedLengthData(uint8_t* data, size_t size) -{ - if (!bufferIsLargeEnoughToContain(size)) - return false; - - memcpy(data, m_bufferPosition, size); - m_bufferPosition += size; - - Encoder::updateChecksumForData(m_sha1, data, size); - return true; -} - -template<typename Type> -bool Decoder::decodeNumber(Type& value) -{ - if (!bufferIsLargeEnoughToContain(sizeof(value))) - return false; - - memcpy(&value, m_bufferPosition, sizeof(value)); - m_bufferPosition += sizeof(Type); - - Encoder::updateChecksumForNumber(m_sha1, value); - return true; -} - -bool Decoder::decode(bool& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(uint8_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(uint16_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(uint32_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(uint64_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(int32_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(int64_t& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(float& result) -{ - return decodeNumber(result); -} - -bool Decoder::decode(double& result) -{ - return decodeNumber(result); -} - -bool Decoder::verifyChecksum() -{ - SHA1::Digest computedHash; - m_sha1.computeHash(computedHash); - - SHA1::Digest savedHash; - if (!decodeFixedLengthData(savedHash.data(), sizeof(savedHash))) - return false; - - return computedHash == savedHash; -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.h deleted file mode 100644 index 12e3d03dc..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheDecoder.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2014 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 NetworkCacheDecoder_h -#define NetworkCacheDecoder_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheCoder.h" -#include <wtf/SHA1.h> - -namespace WebKit { -namespace NetworkCache { - -class Decoder { - WTF_MAKE_FAST_ALLOCATED; -public: - Decoder(const uint8_t* buffer, size_t bufferSize); - virtual ~Decoder(); - - size_t length() const { return m_bufferEnd - m_buffer; } - size_t currentOffset() const { return m_bufferPosition - m_buffer; } - - bool verifyChecksum(); - - bool decodeFixedLengthData(uint8_t*, size_t); - - bool decode(bool&); - bool decode(uint8_t&); - bool decode(uint16_t&); - bool decode(uint32_t&); - bool decode(uint64_t&); - bool decode(int32_t&); - bool decode(int64_t&); - bool decode(float&); - bool decode(double&); - - template<typename T> bool decodeEnum(T& result) - { - static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!"); - - uint64_t value; - if (!decode(value)) - return false; - - result = static_cast<T>(value); - return true; - } - - template<typename T> bool decode(T& t) - { - return Coder<T>::decode(*this, t); - } - - template<typename T> - bool bufferIsLargeEnoughToContain(size_t numElements) const - { - static_assert(std::is_arithmetic<T>::value, "Type T must have a fixed, known encoded size!"); - - if (numElements > std::numeric_limits<size_t>::max() / sizeof(T)) - return false; - - return bufferIsLargeEnoughToContain(numElements * sizeof(T)); - } - -private: - bool bufferIsLargeEnoughToContain(size_t) const; - template<typename Type> bool decodeNumber(Type&); - - const uint8_t* m_buffer; - const uint8_t* m_bufferPosition; - const uint8_t* m_bufferEnd; - - SHA1 m_sha1; -}; - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.cpp deleted file mode 100644 index 0c2d7191d..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2010, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheEncoder.h" - -#if ENABLE(NETWORK_CACHE) - -namespace WebKit { -namespace NetworkCache { - -Encoder::Encoder() -{ -} - -Encoder::~Encoder() -{ -} - -uint8_t* Encoder::grow(size_t size) -{ - size_t newPosition = m_buffer.size(); - m_buffer.grow(m_buffer.size() + size); - return m_buffer.data() + newPosition; -} - -void Encoder::updateChecksumForData(SHA1& sha1, const uint8_t* data, size_t size) -{ - auto typeSalt = Salt<uint8_t*>::value; - sha1.addBytes(reinterpret_cast<uint8_t*>(&typeSalt), sizeof(typeSalt)); - sha1.addBytes(data, size); -} - -void Encoder::encodeFixedLengthData(const uint8_t* data, size_t size) -{ - updateChecksumForData(m_sha1, data, size); - - uint8_t* buffer = grow(size); - memcpy(buffer, data, size); -} - -template<typename Type> -void Encoder::encodeNumber(Type value) -{ - Encoder::updateChecksumForNumber(m_sha1, value); - - uint8_t* buffer = grow(sizeof(Type)); - memcpy(buffer, &value, sizeof(Type)); -} - -void Encoder::encode(bool value) -{ - encodeNumber(value); -} - -void Encoder::encode(uint8_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(uint16_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(uint32_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(uint64_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(int32_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(int64_t value) -{ - encodeNumber(value); -} - -void Encoder::encode(float value) -{ - encodeNumber(value); -} - -void Encoder::encode(double value) -{ - encodeNumber(value); -} - -void Encoder::encodeChecksum() -{ - SHA1::Digest hash; - m_sha1.computeHash(hash); - encodeFixedLengthData(hash.data(), hash.size()); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.h deleted file mode 100644 index 469c06c59..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2010 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 NetworkCacheEncoder_h -#define NetworkCacheEncoder_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheCoder.h" -#include <wtf/SHA1.h> -#include <wtf/Vector.h> - -namespace WebKit { -namespace NetworkCache { - -class Encoder; -class DataReference; - -class Encoder { - WTF_MAKE_FAST_ALLOCATED; -public: - Encoder(); - virtual ~Encoder(); - - void encodeChecksum(); - void encodeFixedLengthData(const uint8_t*, size_t); - - template<typename T> void encodeEnum(T t) - { - COMPILE_ASSERT(sizeof(T) <= sizeof(uint64_t), enum_type_must_not_be_larger_than_64_bits); - - encode(static_cast<uint64_t>(t)); - } - - template<typename T> void encode(const T& t) - { - Coder<T>::encode(*this, t); - } - - template<typename T> Encoder& operator<<(const T& t) - { - encode(t); - return *this; - } - - const uint8_t* buffer() const { return m_buffer.data(); } - size_t bufferSize() const { return m_buffer.size(); } - - static void updateChecksumForData(SHA1&, const uint8_t*, size_t); - template <typename Type> static void updateChecksumForNumber(SHA1&, Type); - -private: - void encode(bool); - void encode(uint8_t); - void encode(uint16_t); - void encode(uint32_t); - void encode(uint64_t); - void encode(int32_t); - void encode(int64_t); - void encode(float); - void encode(double); - - template<typename Type> void encodeNumber(Type); - - uint8_t* grow(size_t); - - template <typename Type> struct Salt; - - Vector<uint8_t, 4096> m_buffer; - SHA1 m_sha1; -}; - -template <> struct Encoder::Salt<bool> { static const unsigned value = 3; }; -template <> struct Encoder::Salt<uint8_t> { static const unsigned value = 5; }; -template <> struct Encoder::Salt<uint16_t> { static const unsigned value = 7; }; -template <> struct Encoder::Salt<uint32_t> { static const unsigned value = 11; }; -template <> struct Encoder::Salt<uint64_t> { static const unsigned value = 13; }; -template <> struct Encoder::Salt<int32_t> { static const unsigned value = 17; }; -template <> struct Encoder::Salt<int64_t> { static const unsigned value = 19; }; -template <> struct Encoder::Salt<float> { static const unsigned value = 23; }; -template <> struct Encoder::Salt<double> { static const unsigned value = 29; }; -template <> struct Encoder::Salt<uint8_t*> { static const unsigned value = 101; }; - -template <typename Type> -void Encoder::updateChecksumForNumber(SHA1& sha1, Type value) -{ - auto typeSalt = Salt<Type>::value; - sha1.addBytes(reinterpret_cast<uint8_t*>(&typeSalt), sizeof(typeSalt)); - sha1.addBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); -} - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp deleted file mode 100644 index faa4f04d1..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCache.h" - -#include "Logging.h" -#include "NetworkCacheCoders.h" -#include "NetworkCacheDecoder.h" -#include "NetworkCacheEncoder.h" -#include <WebCore/ResourceRequest.h> -#include <WebCore/SharedBuffer.h> -#include <wtf/text/StringBuilder.h> - -#if ENABLE(NETWORK_CACHE) - -namespace WebKit { -namespace NetworkCache { - -Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, RefPtr<WebCore::SharedBuffer>&& buffer, const Vector<std::pair<String, String>>& varyingRequestHeaders) - : m_key(key) - , m_timeStamp(std::chrono::system_clock::now()) - , m_response(response) - , m_varyingRequestHeaders(varyingRequestHeaders) - , m_buffer(WTFMove(buffer)) -{ - ASSERT(m_key.type() == "resource"); -} - -Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& redirectRequest, const Vector<std::pair<String, String>>& varyingRequestHeaders) - : m_key(key) - , m_timeStamp(std::chrono::system_clock::now()) - , m_response(response) - , m_varyingRequestHeaders(varyingRequestHeaders) - , m_redirectRequest(WebCore::ResourceRequest::adopt(redirectRequest.copyData())) // Don't include the underlying platform request object. -{ - ASSERT(m_key.type() == "resource"); - // Redirect body is not needed even if exists. - m_redirectRequest->setHTTPBody(nullptr); -} - -Entry::Entry(const Entry& other) - : m_key(other.m_key) - , m_timeStamp(other.m_timeStamp) - , m_response(other.m_response) - , m_varyingRequestHeaders(other.m_varyingRequestHeaders) - , m_buffer(other.m_buffer) - , m_sourceStorageRecord(other.m_sourceStorageRecord) -{ -} - -Entry::Entry(const Storage::Record& storageEntry) - : m_key(storageEntry.key) - , m_timeStamp(storageEntry.timeStamp) - , m_sourceStorageRecord(storageEntry) -{ - ASSERT(m_key.type() == "resource"); -} - -Storage::Record Entry::encodeAsStorageRecord() const -{ - Encoder encoder; - encoder << m_response; - - bool hasVaryingRequestHeaders = !m_varyingRequestHeaders.isEmpty(); - encoder << hasVaryingRequestHeaders; - if (hasVaryingRequestHeaders) - encoder << m_varyingRequestHeaders; - - bool isRedirect = !!m_redirectRequest; - encoder << isRedirect; - if (isRedirect) - m_redirectRequest->encodeWithoutPlatformData(encoder); - - encoder.encodeChecksum(); - - Data header(encoder.buffer(), encoder.bufferSize()); - Data body; - if (m_buffer) - body = { reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size() }; - - return { m_key, m_timeStamp, header, body }; -} - -std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storageEntry) -{ - auto entry = std::make_unique<Entry>(storageEntry); - - Decoder decoder(storageEntry.header.data(), storageEntry.header.size()); - if (!decoder.decode(entry->m_response)) - return nullptr; - entry->m_response.setSource(WebCore::ResourceResponse::Source::DiskCache); - - bool hasVaryingRequestHeaders; - if (!decoder.decode(hasVaryingRequestHeaders)) - return nullptr; - - if (hasVaryingRequestHeaders) { - if (!decoder.decode(entry->m_varyingRequestHeaders)) - return nullptr; - } - - bool isRedirect; - if (!decoder.decode(isRedirect)) - return nullptr; - - if (isRedirect) { - entry->m_redirectRequest = std::make_unique<WebCore::ResourceRequest>(); - if (!entry->m_redirectRequest->decodeWithoutPlatformData(decoder)) - return nullptr; - } - - if (!decoder.verifyChecksum()) { - LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n"); - return nullptr; - } - - return entry; -} - -#if ENABLE(SHAREABLE_RESOURCE) -void Entry::initializeShareableResourceHandleFromStorageRecord() const -{ - RefPtr<SharedMemory> sharedMemory = m_sourceStorageRecord.body.tryCreateSharedMemory(); - if (!sharedMemory) - return; - - RefPtr<ShareableResource> shareableResource = ShareableResource::create(sharedMemory.release(), 0, m_sourceStorageRecord.body.size()); - ASSERT(shareableResource); - shareableResource->createHandle(m_shareableResourceHandle); -} -#endif - -void Entry::initializeBufferFromStorageRecord() const -{ -#if ENABLE(SHAREABLE_RESOURCE) - if (!shareableResourceHandle().isNull()) { - m_buffer = m_shareableResourceHandle.tryWrapInSharedBuffer(); - if (m_buffer) - return; - } -#endif - m_buffer = WebCore::SharedBuffer::create(m_sourceStorageRecord.body.data(), m_sourceStorageRecord.body.size()); -} - -WebCore::SharedBuffer* Entry::buffer() const -{ - if (!m_buffer) - initializeBufferFromStorageRecord(); - - return m_buffer.get(); -} - -#if ENABLE(SHAREABLE_RESOURCE) -ShareableResource::Handle& Entry::shareableResourceHandle() const -{ - if (m_shareableResourceHandle.isNull()) - initializeShareableResourceHandleFromStorageRecord(); - - return m_shareableResourceHandle; -} -#endif - -bool Entry::needsValidation() const -{ - return m_response.source() == WebCore::ResourceResponse::Source::DiskCacheAfterValidation; -} - -void Entry::setNeedsValidation() -{ - ASSERT(m_response.source() == WebCore::ResourceResponse::Source::DiskCache); - m_response.setSource(WebCore::ResourceResponse::Source::DiskCacheAfterValidation); -} - -void Entry::asJSON(StringBuilder& json, const Storage::RecordInfo& info) const -{ - json.appendLiteral("{\n"); - json.appendLiteral("\"hash\": "); - json.appendQuotedJSONString(m_key.hashAsString()); - json.appendLiteral(",\n"); - json.appendLiteral("\"bodySize\": "); - json.appendNumber(info.bodySize); - json.appendLiteral(",\n"); - json.appendLiteral("\"worth\": "); - json.appendNumber(info.worth); - json.appendLiteral(",\n"); - json.appendLiteral("\"partition\": "); - json.appendQuotedJSONString(m_key.partition()); - json.appendLiteral(",\n"); - json.appendLiteral("\"timestamp\": "); - json.appendNumber(std::chrono::duration_cast<std::chrono::milliseconds>(m_timeStamp.time_since_epoch()).count()); - json.appendLiteral(",\n"); - json.appendLiteral("\"URL\": "); - json.appendQuotedJSONString(m_response.url().string()); - json.appendLiteral(",\n"); - json.appendLiteral("\"bodyHash\": "); - json.appendQuotedJSONString(info.bodyHash); - json.appendLiteral(",\n"); - json.appendLiteral("\"bodyShareCount\": "); - json.appendNumber(info.bodyShareCount); - json.appendLiteral(",\n"); - json.appendLiteral("\"headers\": {\n"); - bool firstHeader = true; - for (auto& header : m_response.httpHeaderFields()) { - if (!firstHeader) - json.appendLiteral(",\n"); - firstHeader = false; - json.appendLiteral(" "); - json.appendQuotedJSONString(header.key); - json.appendLiteral(": "); - json.appendQuotedJSONString(header.value); - } - json.appendLiteral("\n}\n"); - json.appendLiteral("}"); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h deleted file mode 100644 index 0855a4efe..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheEntry_h -#define NetworkCacheEntry_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheStorage.h" -#include "ShareableResource.h" -#include <WebCore/ResourceRequest.h> -#include <WebCore/ResourceResponse.h> -#include <wtf/Noncopyable.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { -class SharedBuffer; -} - -namespace WebKit { -namespace NetworkCache { - -class Entry { - WTF_MAKE_FAST_ALLOCATED; -public: - Entry(const Key&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, const Vector<std::pair<String, String>>& varyingRequestHeaders); - Entry(const Key&, const WebCore::ResourceResponse&, const WebCore::ResourceRequest& redirectRequest, const Vector<std::pair<String, String>>& varyingRequestHeaders); - explicit Entry(const Storage::Record&); - Entry(const Entry&); - - Storage::Record encodeAsStorageRecord() const; - static std::unique_ptr<Entry> decodeStorageRecord(const Storage::Record&); - - const Key& key() const { return m_key; } - std::chrono::system_clock::time_point timeStamp() const { return m_timeStamp; } - const WebCore::ResourceResponse& response() const { return m_response; } - const Vector<std::pair<String, String>>& varyingRequestHeaders() const { return m_varyingRequestHeaders; } - - WebCore::SharedBuffer* buffer() const; - const WebCore::ResourceRequest* redirectRequest() const { return m_redirectRequest.get(); } - -#if ENABLE(SHAREABLE_RESOURCE) - ShareableResource::Handle& shareableResourceHandle() const; -#endif - - bool needsValidation() const; - void setNeedsValidation(); - - const Storage::Record& sourceStorageRecord() const { return m_sourceStorageRecord; } - - void asJSON(StringBuilder&, const Storage::RecordInfo&) const; - -private: - void initializeBufferFromStorageRecord() const; -#if ENABLE(SHAREABLE_RESOURCE) - void initializeShareableResourceHandleFromStorageRecord() const; -#endif - - Key m_key; - std::chrono::system_clock::time_point m_timeStamp; - WebCore::ResourceResponse m_response; - Vector<std::pair<String, String>> m_varyingRequestHeaders; - - std::unique_ptr<WebCore::ResourceRequest> m_redirectRequest; - mutable RefPtr<WebCore::SharedBuffer> m_buffer; -#if ENABLE(SHAREABLE_RESOURCE) - mutable ShareableResource::Handle m_shareableResourceHandle; -#endif - - Storage::Record m_sourceStorageRecord { }; -}; - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.cpp deleted file mode 100644 index 93d6a58d6..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheFileSystem.h" - -#if ENABLE(NETWORK_CACHE) - -#include <WebCore/FileSystem.h> -#include <dirent.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <wtf/text/CString.h> - -#if USE(SOUP) -#include <gio/gio.h> -#include <wtf/glib/GRefPtr.h> -#endif - -namespace WebKit { -namespace NetworkCache { - -static DirectoryEntryType directoryEntryType(uint8_t dtype) -{ - switch (dtype) { - case DT_DIR: - return DirectoryEntryType::Directory; - case DT_REG: - return DirectoryEntryType::File; - default: - ASSERT_NOT_REACHED(); - return DirectoryEntryType::File; - } -} - -void traverseDirectory(const String& path, const std::function<void (const String&, DirectoryEntryType)>& function) -{ - DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data()); - if (!dir) - return; - dirent* dp; - while ((dp = readdir(dir))) { - if (dp->d_type != DT_DIR && dp->d_type != DT_REG) - continue; - const char* name = dp->d_name; - if (!strcmp(name, ".") || !strcmp(name, "..")) - continue; - auto nameString = String::fromUTF8(name); - if (nameString.isNull()) - continue; - function(nameString, directoryEntryType(dp->d_type)); - } - closedir(dir); -} - -void deleteDirectoryRecursively(const String& path) -{ - traverseDirectory(path, [&path](const String& name, DirectoryEntryType type) { - String entryPath = WebCore::pathByAppendingComponent(path, name); - switch (type) { - case DirectoryEntryType::File: - WebCore::deleteFile(entryPath); - break; - case DirectoryEntryType::Directory: - deleteDirectoryRecursively(entryPath); - break; - // This doesn't follow symlinks. - } - }); - WebCore::deleteEmptyDirectory(path); -} - -FileTimes fileTimes(const String& path) -{ -#if HAVE(STAT_BIRTHTIME) - struct stat fileInfo; - if (stat(WebCore::fileSystemRepresentation(path).data(), &fileInfo)) - return { }; - return { std::chrono::system_clock::from_time_t(fileInfo.st_birthtime), std::chrono::system_clock::from_time_t(fileInfo.st_mtime) }; -#elif USE(SOUP) - // There's no st_birthtime in some operating systems like Linux, so we use xattrs to set/get the creation time. - GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(WebCore::fileSystemRepresentation(path).data())); - GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_info(file.get(), "xattr::birthtime,time::modified", G_FILE_QUERY_INFO_NONE, nullptr, nullptr)); - if (!fileInfo) - return { }; - const char* birthtimeString = g_file_info_get_attribute_string(fileInfo.get(), "xattr::birthtime"); - if (!birthtimeString) - return { }; - return { std::chrono::system_clock::from_time_t(g_ascii_strtoull(birthtimeString, nullptr, 10)), - std::chrono::system_clock::from_time_t(g_file_info_get_attribute_uint64(fileInfo.get(), "time::modified")) }; -#endif -} - -void updateFileModificationTimeIfNeeded(const String& path) -{ - auto times = fileTimes(path); - if (times.creation != times.modification) { - // Don't update more than once per hour. - if (std::chrono::system_clock::now() - times.modification < std::chrono::hours(1)) - return; - } - // This really updates both the access time and the modification time. - utimes(WebCore::fileSystemRepresentation(path).data(), nullptr); -} - -} -} - -#endif // ENABLE(NETWORK_CACHE) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.h deleted file mode 100644 index 17407e8ab..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheFileSystem_h -#define NetworkCacheFileSystem_h - -#if ENABLE(NETWORK_CACHE) - -#include <WebCore/FileSystem.h> -#include <functional> - -namespace WebKit { -namespace NetworkCache { - -enum class DirectoryEntryType { Directory, File }; -void traverseDirectory(const String& path, const std::function<void (const String& fileName, DirectoryEntryType)>&); - -void deleteDirectoryRecursively(const String& path); - -struct FileTimes { - std::chrono::system_clock::time_point creation; - std::chrono::system_clock::time_point modification; -}; -FileTimes fileTimes(const String& path); -void updateFileModificationTimeIfNeeded(const String& path); - -} -} - -#endif - -#endif - diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannel.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannel.h deleted file mode 100644 index c5edaa8f2..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannel.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheIOChannel_h -#define NetworkCacheIOChannel_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheData.h" -#include <functional> -#include <wtf/ThreadSafeRefCounted.h> -#include <wtf/WorkQueue.h> -#include <wtf/text/WTFString.h> - -#if USE(SOUP) -#include <wtf/glib/GRefPtr.h> -#endif - -namespace WebKit { -namespace NetworkCache { - -class IOChannel : public ThreadSafeRefCounted<IOChannel> { -public: - enum class Type { Read, Write, Create }; - static Ref<IOChannel> open(const String& file, Type); - - // Using nullptr as queue submits the result to the main queue. - // FIXME: We should add WorkQueue::main() instead. - void read(size_t offset, size_t, WorkQueue*, std::function<void (Data&, int error)>); - void write(size_t offset, const Data&, WorkQueue*, std::function<void (int error)>); - - const String& path() const { return m_path; } - Type type() const { return m_type; } - - int fileDescriptor() const { return m_fileDescriptor; } - -private: - IOChannel(const String& filePath, IOChannel::Type); - -#if USE(SOUP) - void readSyncInThread(size_t offset, size_t, WorkQueue*, std::function<void (Data&, int error)>); -#endif - - String m_path; - Type m_type; - - int m_fileDescriptor { 0 }; -#if PLATFORM(COCOA) - DispatchPtr<dispatch_io_t> m_dispatchIO; -#endif -#if USE(SOUP) - GRefPtr<GInputStream> m_inputStream; - GRefPtr<GOutputStream> m_outputStream; - GRefPtr<GFileIOStream> m_ioStream; -#endif -}; - -} -} - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp deleted file mode 100644 index 080ce256d..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2015 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 "NetworkCacheIOChannel.h" - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheFileSystem.h" -#include <wtf/MainThread.h> -#include <wtf/RunLoop.h> -#include <wtf/glib/GUniquePtr.h> - -namespace WebKit { -namespace NetworkCache { - -static const size_t gDefaultReadBufferSize = 4096; - -IOChannel::IOChannel(const String& filePath, Type type) - : m_path(filePath) - , m_type(type) -{ - auto path = WebCore::fileSystemRepresentation(filePath); - GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.data())); - switch (m_type) { - case Type::Create: { - g_file_delete(file.get(), nullptr, nullptr); - m_outputStream = adoptGRef(G_OUTPUT_STREAM(g_file_create(file.get(), static_cast<GFileCreateFlags>(G_FILE_CREATE_PRIVATE), nullptr, nullptr))); -#if !HAVE(STAT_BIRTHTIME) - GUniquePtr<char> birthtimeString(g_strdup_printf("%" G_GUINT64_FORMAT, std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))); - g_file_set_attribute_string(file.get(), "xattr::birthtime", birthtimeString.get(), G_FILE_QUERY_INFO_NONE, nullptr, nullptr); -#endif - break; - } - case Type::Write: { - m_ioStream = adoptGRef(g_file_open_readwrite(file.get(), nullptr, nullptr)); - break; - } - case Type::Read: - m_inputStream = adoptGRef(G_INPUT_STREAM(g_file_read(file.get(), nullptr, nullptr))); - break; - } -} - -Ref<IOChannel> IOChannel::open(const String& filePath, IOChannel::Type type) -{ - return adoptRef(*new IOChannel(filePath, type)); -} - -static inline void runTaskInQueue(std::function<void ()> task, WorkQueue* queue) -{ - if (queue) { - queue->dispatch(task); - return; - } - - // Using nullptr as queue submits the result to the main context. - RunLoop::main().dispatch(WTFMove(task)); -} - -static void fillDataFromReadBuffer(SoupBuffer* readBuffer, size_t size, Data& data) -{ - GRefPtr<SoupBuffer> buffer; - if (size != readBuffer->length) { - // The subbuffer does not copy the data. - buffer = adoptGRef(soup_buffer_new_subbuffer(readBuffer, 0, size)); - } else - buffer = readBuffer; - - if (data.isNull()) { - // First chunk, we need to force the data to be copied. - data = { reinterpret_cast<const uint8_t*>(buffer->data), size }; - } else { - Data dataRead(WTFMove(buffer)); - // Concatenate will copy the data. - data = concatenate(data, dataRead); - } -} - -struct ReadAsyncData { - RefPtr<IOChannel> channel; - GRefPtr<SoupBuffer> buffer; - RefPtr<WorkQueue> queue; - size_t bytesToRead; - std::function<void (Data&, int error)> completionHandler; - Data data; -}; - -static void inputStreamReadReadyCallback(GInputStream* stream, GAsyncResult* result, gpointer userData) -{ - std::unique_ptr<ReadAsyncData> asyncData(static_cast<ReadAsyncData*>(userData)); - gssize bytesRead = g_input_stream_read_finish(stream, result, nullptr); - if (bytesRead == -1) { - WorkQueue* queue = asyncData->queue.get(); - auto* asyncDataPtr = asyncData.release(); - runTaskInQueue([asyncDataPtr] { - std::unique_ptr<ReadAsyncData> asyncData(asyncDataPtr); - asyncData->completionHandler(asyncData->data, -1); - }, queue); - return; - } - - if (!bytesRead) { - WorkQueue* queue = asyncData->queue.get(); - auto* asyncDataPtr = asyncData.release(); - runTaskInQueue([asyncDataPtr] { - std::unique_ptr<ReadAsyncData> asyncData(asyncDataPtr); - asyncData->completionHandler(asyncData->data, 0); - }, queue); - return; - } - - ASSERT(bytesRead > 0); - fillDataFromReadBuffer(asyncData->buffer.get(), static_cast<size_t>(bytesRead), asyncData->data); - - size_t pendingBytesToRead = asyncData->bytesToRead - asyncData->data.size(); - if (!pendingBytesToRead) { - WorkQueue* queue = asyncData->queue.get(); - auto* asyncDataPtr = asyncData.release(); - runTaskInQueue([asyncDataPtr] { - std::unique_ptr<ReadAsyncData> asyncData(asyncDataPtr); - asyncData->completionHandler(asyncData->data, 0); - }, queue); - return; - } - - size_t bytesToRead = std::min(pendingBytesToRead, asyncData->buffer->length); - // Use a local variable for the data buffer to pass it to g_input_stream_read_async(), because ReadAsyncData is released. - auto data = const_cast<char*>(asyncData->buffer->data); - g_input_stream_read_async(stream, data, bytesToRead, G_PRIORITY_DEFAULT, nullptr, - reinterpret_cast<GAsyncReadyCallback>(inputStreamReadReadyCallback), asyncData.release()); -} - -void IOChannel::read(size_t offset, size_t size, WorkQueue* queue, std::function<void (Data&, int error)> completionHandler) -{ - RefPtr<IOChannel> channel(this); - if (!m_inputStream) { - runTaskInQueue([channel, completionHandler] { - Data data; - completionHandler(data, -1); - }, queue); - return; - } - - if (!isMainThread()) { - readSyncInThread(offset, size, queue, completionHandler); - return; - } - - size_t bufferSize = std::min(size, gDefaultReadBufferSize); - uint8_t* bufferData = static_cast<uint8_t*>(fastMalloc(bufferSize)); - GRefPtr<SoupBuffer> buffer = adoptGRef(soup_buffer_new_with_owner(bufferData, bufferSize, bufferData, fastFree)); - ReadAsyncData* asyncData = new ReadAsyncData { this, buffer.get(), queue, size, completionHandler, { } }; - - // FIXME: implement offset. - g_input_stream_read_async(m_inputStream.get(), const_cast<char*>(buffer->data), bufferSize, G_PRIORITY_DEFAULT, nullptr, - reinterpret_cast<GAsyncReadyCallback>(inputStreamReadReadyCallback), asyncData); -} - -void IOChannel::readSyncInThread(size_t offset, size_t size, WorkQueue* queue, std::function<void (Data&, int error)> completionHandler) -{ - ASSERT(!isMainThread()); - - RefPtr<IOChannel> channel(this); - detachThread(createThread("IOChannel::readSync", [channel, size, queue, completionHandler] { - size_t bufferSize = std::min(size, gDefaultReadBufferSize); - uint8_t* bufferData = static_cast<uint8_t*>(fastMalloc(bufferSize)); - GRefPtr<SoupBuffer> readBuffer = adoptGRef(soup_buffer_new_with_owner(bufferData, bufferSize, bufferData, fastFree)); - Data data; - size_t pendingBytesToRead = size; - size_t bytesToRead = bufferSize; - do { - // FIXME: implement offset. - gssize bytesRead = g_input_stream_read(channel->m_inputStream.get(), const_cast<char*>(readBuffer->data), bytesToRead, nullptr, nullptr); - if (bytesRead == -1) { - runTaskInQueue([channel, completionHandler] { - Data data; - completionHandler(data, -1); - }, queue); - return; - } - - if (!bytesRead) - break; - - ASSERT(bytesRead > 0); - fillDataFromReadBuffer(readBuffer.get(), static_cast<size_t>(bytesRead), data); - - pendingBytesToRead = size - data.size(); - bytesToRead = std::min(pendingBytesToRead, readBuffer->length); - } while (pendingBytesToRead); - - GRefPtr<SoupBuffer> bufferCapture = data.soupBuffer(); - runTaskInQueue([channel, bufferCapture, completionHandler] { - GRefPtr<SoupBuffer> buffer = bufferCapture; - Data data = { WTFMove(buffer) }; - completionHandler(data, 0); - }, queue); - })); -} - -struct WriteAsyncData { - RefPtr<IOChannel> channel; - GRefPtr<SoupBuffer> buffer; - RefPtr<WorkQueue> queue; - std::function<void (int error)> completionHandler; -}; - -static void outputStreamWriteReadyCallback(GOutputStream* stream, GAsyncResult* result, gpointer userData) -{ - std::unique_ptr<WriteAsyncData> asyncData(static_cast<WriteAsyncData*>(userData)); - gssize bytesWritten = g_output_stream_write_finish(stream, result, nullptr); - if (bytesWritten == -1) { - WorkQueue* queue = asyncData->queue.get(); - auto* asyncDataPtr = asyncData.release(); - runTaskInQueue([asyncDataPtr] { - std::unique_ptr<WriteAsyncData> asyncData(asyncDataPtr); - asyncData->completionHandler(-1); - }, queue); - return; - } - - gssize pendingBytesToWrite = asyncData->buffer->length - bytesWritten; - if (!pendingBytesToWrite) { - WorkQueue* queue = asyncData->queue.get(); - auto* asyncDataPtr = asyncData.release(); - runTaskInQueue([asyncDataPtr] { - std::unique_ptr<WriteAsyncData> asyncData(asyncDataPtr); - asyncData->completionHandler(0); - }, queue); - return; - } - - asyncData->buffer = adoptGRef(soup_buffer_new_subbuffer(asyncData->buffer.get(), bytesWritten, pendingBytesToWrite)); - // Use a local variable for the data buffer to pass it to g_output_stream_write_async(), because WriteAsyncData is released. - auto data = asyncData->buffer->data; - g_output_stream_write_async(stream, data, pendingBytesToWrite, G_PRIORITY_DEFAULT_IDLE, nullptr, - reinterpret_cast<GAsyncReadyCallback>(outputStreamWriteReadyCallback), asyncData.release()); -} - -void IOChannel::write(size_t offset, const Data& data, WorkQueue* queue, std::function<void (int error)> completionHandler) -{ - RefPtr<IOChannel> channel(this); - if (!m_outputStream && !m_ioStream) { - runTaskInQueue([channel, completionHandler] { - completionHandler(-1); - }, queue); - return; - } - - GOutputStream* stream = m_outputStream ? m_outputStream.get() : g_io_stream_get_output_stream(G_IO_STREAM(m_ioStream.get())); - if (!stream) { - runTaskInQueue([channel, completionHandler] { - completionHandler(-1); - }, queue); - return; - } - - WriteAsyncData* asyncData = new WriteAsyncData { this, data.soupBuffer(), queue, completionHandler }; - // FIXME: implement offset. - g_output_stream_write_async(stream, asyncData->buffer->data, data.size(), G_PRIORITY_DEFAULT_IDLE, nullptr, - reinterpret_cast<GAsyncReadyCallback>(outputStreamWriteReadyCallback), asyncData); -} - -} // namespace NetworkCache -} // namespace WebKit - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp deleted file mode 100644 index 1f06a65bb..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2014-2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheKey.h" - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheCoders.h" -#include <wtf/ASCIICType.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuilder.h> - -namespace WebKit { -namespace NetworkCache { - -Key::Key(const Key& o) - : m_partition(o.m_partition.isolatedCopy()) - , m_type(o.m_type.isolatedCopy()) - , m_identifier(o.m_identifier.isolatedCopy()) - , m_range(o.m_range.isolatedCopy()) - , m_hash(o.m_hash) -{ -} - -Key::Key(const String& partition, const String& type, const String& range, const String& identifier) - : m_partition(partition.isolatedCopy()) - , m_type(type.isolatedCopy()) - , m_identifier(identifier.isolatedCopy()) - , m_range(range.isolatedCopy()) - , m_hash(computeHash()) -{ -} - -Key::Key(WTF::HashTableDeletedValueType) - : m_identifier(WTF::HashTableDeletedValue) -{ -} - -Key& Key::operator=(const Key& other) -{ - m_partition = other.m_partition.isolatedCopy(); - m_type = other.m_type.isolatedCopy(); - m_identifier = other.m_identifier.isolatedCopy(); - m_range = other.m_range.isolatedCopy(); - m_hash = other.m_hash; - return *this; -} - -static void hashString(SHA1& sha1, const String& string) -{ - if (string.isNull()) - return; - - if (string.is8Bit() && string.containsOnlyASCII()) { - const uint8_t nullByte = 0; - sha1.addBytes(string.characters8(), string.length()); - sha1.addBytes(&nullByte, 1); - return; - } - auto cString = string.utf8(); - // Include terminating null byte. - sha1.addBytes(reinterpret_cast<const uint8_t*>(cString.data()), cString.length() + 1); -} - -Key::HashType Key::computeHash() const -{ - // We don't really need a cryptographic hash. The key is always verified against the entry header. - // SHA1 just happens to be suitably sized, fast and available. - SHA1 sha1; - hashString(sha1, m_partition); - hashString(sha1, m_type); - hashString(sha1, m_identifier); - hashString(sha1, m_range); - SHA1::Digest hash; - sha1.computeHash(hash); - return hash; -} - -String Key::hashAsString() const -{ - StringBuilder builder; - builder.reserveCapacity(hashStringLength()); - for (auto byte : m_hash) { - builder.append(upperNibbleToASCIIHexDigit(byte)); - builder.append(lowerNibbleToASCIIHexDigit(byte)); - } - return builder.toString(); -} - -template <typename CharType> bool hexDigitsToHash(CharType* characters, Key::HashType& hash) -{ - for (unsigned i = 0; i < sizeof(hash); ++i) { - auto high = characters[2 * i]; - auto low = characters[2 * i + 1]; - if (!isASCIIHexDigit(high) || !isASCIIHexDigit(low)) - return false; - hash[i] = toASCIIHexValue(high, low); - } - return true; -} - -bool Key::stringToHash(const String& string, HashType& hash) -{ - if (string.length() != hashStringLength()) - return false; - if (string.is8Bit()) - return hexDigitsToHash(string.characters8(), hash); - return hexDigitsToHash(string.characters16(), hash); -} - -bool Key::operator==(const Key& other) const -{ - return m_hash == other.m_hash && m_partition == other.m_partition && m_type == other.m_type && m_identifier == other.m_identifier && m_range == other.m_range; -} - -void Key::encode(Encoder& encoder) const -{ - encoder << m_partition; - encoder << m_type; - encoder << m_identifier; - encoder << m_range; - encoder << m_hash; -} - -bool Key::decode(Decoder& decoder, Key& key) -{ - return decoder.decode(key.m_partition) && decoder.decode(key.m_type) && decoder.decode(key.m_identifier) && decoder.decode(key.m_range) && decoder.decode(key.m_hash); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h deleted file mode 100644 index 12a7007fd..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2014-2015 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 NetworkCacheKey_h -#define NetworkCacheKey_h - -#if ENABLE(NETWORK_CACHE) - -#include <wtf/SHA1.h> -#include <wtf/text/WTFString.h> - -namespace WebKit { -namespace NetworkCache { - -class Encoder; -class Decoder; - -class Key { -public: - typedef SHA1::Digest HashType; - - Key() { } - Key(const Key&); - Key(Key&&) = default; - Key(const String& partition, const String& type, const String& range, const String& identifier); - - Key& operator=(const Key&); - Key& operator=(Key&&) = default; - - Key(WTF::HashTableDeletedValueType); - bool isHashTableDeletedValue() const { return m_identifier.isHashTableDeletedValue(); } - - bool isNull() const { return m_identifier.isNull(); } - - const String& partition() const { return m_partition; } - const String& identifier() const { return m_identifier; } - const String& type() const { return m_type; } - const String& range() const { return m_range; } - - HashType hash() const { return m_hash; } - - static bool stringToHash(const String&, HashType&); - - static size_t hashStringLength() { return 2 * sizeof(m_hash); } - String hashAsString() const; - - void encode(Encoder&) const; - static bool decode(Decoder&, Key&); - - bool operator==(const Key&) const; - bool operator!=(const Key& other) const { return !(*this == other); } - -private: - HashType computeHash() const; - - String m_partition; - String m_type; - String m_identifier; - String m_range; - HashType m_hash; -}; - -} -} - -namespace WTF { - -struct NetworkCacheKeyHash { - static unsigned hash(const WebKit::NetworkCache::Key& key) - { - static_assert(SHA1::hashSize >= sizeof(unsigned), "Hash size must be greater than sizeof(unsigned)"); - return *reinterpret_cast<const unsigned*>(key.hash().data()); - } - - static bool equal(const WebKit::NetworkCache::Key& a, const WebKit::NetworkCache::Key& b) - { - return a == b; - } - - static const bool safeToCompareToEmptyOrDeleted = false; -}; - -template<typename T> struct DefaultHash; -template<> struct DefaultHash<WebKit::NetworkCache::Key> { - typedef NetworkCacheKeyHash Hash; -}; - -template<> struct HashTraits<WebKit::NetworkCache::Key> : SimpleClassHashTraits<WebKit::NetworkCache::Key> { - static const bool emptyValueIsZero = false; - - static const bool hasIsEmptyValueFunction = true; - static bool isEmptyValue(const WebKit::NetworkCache::Key& key) { return key.isNull(); } -}; - -} // namespace WTF - -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp deleted file mode 100644 index f6f594030..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) -#include "NetworkCacheSpeculativeLoad.h" - -#include "Logging.h" -#include "NetworkCache.h" -#include "NetworkLoad.h" -#include <WebCore/SessionID.h> -#include <wtf/CurrentTime.h> -#include <wtf/RunLoop.h> - -namespace WebKit { -namespace NetworkCache { - -using namespace WebCore; - -SpeculativeLoad::SpeculativeLoad(const GlobalFrameID& frameID, const ResourceRequest& request, std::unique_ptr<NetworkCache::Entry> cacheEntryForValidation, RevalidationCompletionHandler&& completionHandler) - : m_frameID(frameID) - , m_completionHandler(WTFMove(completionHandler)) - , m_originalRequest(request) - , m_bufferedDataForCache(SharedBuffer::create()) - , m_cacheEntryForValidation(WTFMove(cacheEntryForValidation)) -{ - ASSERT(m_cacheEntryForValidation); - ASSERT(m_cacheEntryForValidation->needsValidation()); - - NetworkLoadParameters parameters; - parameters.sessionID = SessionID::defaultSessionID(); - parameters.allowStoredCredentials = AllowStoredCredentials; - parameters.contentSniffingPolicy = DoNotSniffContent; - parameters.request = m_originalRequest; - m_networkLoad = std::make_unique<NetworkLoad>(*this, parameters); -} - -SpeculativeLoad::~SpeculativeLoad() -{ - ASSERT(!m_networkLoad); -} - -void SpeculativeLoad::willSendRedirectedRequest(const ResourceRequest& request, const ResourceRequest& redirectRequest, const ResourceResponse& redirectResponse) -{ - updateRedirectChainStatus(m_redirectChainCacheStatus, redirectResponse); -} - -auto SpeculativeLoad::didReceiveResponse(const ResourceResponse& receivedResponse) -> ShouldContinueDidReceiveResponse -{ - m_response = receivedResponse; - - if (m_response.isMultipart()) - m_bufferedDataForCache = nullptr; - - ASSERT(m_cacheEntryForValidation); - - bool validationSucceeded = m_response.httpStatusCode() == 304; // 304 Not Modified - if (validationSucceeded) { - m_cacheEntryForValidation = NetworkCache::singleton().update(m_originalRequest, m_frameID, *m_cacheEntryForValidation, m_response); - didComplete(); - return ShouldContinueDidReceiveResponse::No; - } - - m_cacheEntryForValidation = nullptr; - - return ShouldContinueDidReceiveResponse::Yes; -} - -void SpeculativeLoad::didReceiveBuffer(RefPtr<SharedBuffer>&& buffer, int reportedEncodedDataLength) -{ - ASSERT(!m_cacheEntryForValidation); - - if (m_bufferedDataForCache) { - // Prevent memory growth in case of streaming data. - const size_t maximumCacheBufferSize = 10 * 1024 * 1024; - if (m_bufferedDataForCache->size() + buffer->size() <= maximumCacheBufferSize) - m_bufferedDataForCache->append(buffer.get()); - else - m_bufferedDataForCache = nullptr; - } -} - -void SpeculativeLoad::didFinishLoading(double finishTime) -{ - ASSERT(!m_cacheEntryForValidation); - - bool allowStale = m_originalRequest.cachePolicy() >= ReturnCacheDataElseLoad; - bool hasCacheableRedirect = m_response.isHTTP() && redirectChainAllowsReuse(m_redirectChainCacheStatus, allowStale ? ReuseExpiredRedirection : DoNotReuseExpiredRedirection); - if (hasCacheableRedirect && m_redirectChainCacheStatus.status == RedirectChainCacheStatus::CachedRedirection) { - // Maybe we should cache the actual redirects instead of the end result? - auto now = std::chrono::system_clock::now(); - auto responseEndOfValidity = now + computeFreshnessLifetimeForHTTPFamily(m_response, now) - computeCurrentAge(m_response, now); - hasCacheableRedirect = responseEndOfValidity <= m_redirectChainCacheStatus.endOfValidity; - } - - if (m_bufferedDataForCache && hasCacheableRedirect) - m_cacheEntryForValidation = NetworkCache::singleton().store(m_originalRequest, m_response, WTFMove(m_bufferedDataForCache), [](NetworkCache::MappedBody& mappedBody) { }); - else if (!hasCacheableRedirect) { - // Make sure we don't keep a stale entry in the cache. - NetworkCache::singleton().remove(m_originalRequest); - } - - didComplete(); -} - -void SpeculativeLoad::didFailLoading(const ResourceError&) -{ - m_cacheEntryForValidation = nullptr; - - didComplete(); -} - -void SpeculativeLoad::didComplete() -{ - RELEASE_ASSERT(RunLoop::isMain()); - - m_networkLoad = nullptr; - - m_completionHandler(WTFMove(m_cacheEntryForValidation)); -} - -} // namespace NetworkCache -} // namespace WebKit - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h deleted file mode 100644 index 3ce3b63bf..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheSpeculativeLoad_h -#define NetworkCacheSpeculativeLoad_h - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - -#include "NetworkCache.h" -#include "NetworkCacheEntry.h" -#include "NetworkLoadClient.h" -#include <WebCore/ResourceRequest.h> -#include <WebCore/ResourceResponse.h> -#include <WebCore/SharedBuffer.h> - -namespace WebKit { - -class NetworkLoad; - -namespace NetworkCache { - -class SpeculativeLoad final : public NetworkLoadClient { - WTF_MAKE_FAST_ALLOCATED; -public: - typedef std::function<void (std::unique_ptr<NetworkCache::Entry>)> RevalidationCompletionHandler; - SpeculativeLoad(const GlobalFrameID&, const WebCore::ResourceRequest&, std::unique_ptr<NetworkCache::Entry>, RevalidationCompletionHandler&&); - - virtual ~SpeculativeLoad(); - -private: - // NetworkLoadClient. - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override { } - virtual void canAuthenticateAgainstProtectionSpaceAsync(const WebCore::ProtectionSpace&) override { } - virtual bool isSynchronous() const override { return false; } - virtual void willSendRedirectedRequest(const WebCore::ResourceRequest&, const WebCore::ResourceRequest& redirectRequest, const WebCore::ResourceResponse& redirectResponse) override; - virtual ShouldContinueDidReceiveResponse didReceiveResponse(const WebCore::ResourceResponse&) override; - virtual void didReceiveBuffer(RefPtr<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override; - virtual void didFinishLoading(double finishTime) override; - virtual void didFailLoading(const WebCore::ResourceError&) override; - virtual void didConvertToDownload() override { ASSERT_NOT_REACHED(); } -#if PLATFORM(COCOA) - virtual void willCacheResponseAsync(CFCachedURLResponseRef) override { } -#endif - - void didComplete(); - - GlobalFrameID m_frameID; - RevalidationCompletionHandler m_completionHandler; - WebCore::ResourceRequest m_originalRequest; - - std::unique_ptr<NetworkLoad> m_networkLoad; - - WebCore::ResourceResponse m_response; - - RefPtr<WebCore::SharedBuffer> m_bufferedDataForCache; - std::unique_ptr<NetworkCache::Entry> m_cacheEntryForValidation; - - WebCore::RedirectChainCacheStatus m_redirectChainCacheStatus; -}; - -} // namespace NetworkCache -} // namespace WebKit - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - -#endif // NetworkCacheSpeculativeLoad_h diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp deleted file mode 100644 index 027591100..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) -#include "NetworkCacheSpeculativeLoadManager.h" - -#include "Logging.h" -#include "NetworkCacheEntry.h" -#include "NetworkCacheSpeculativeLoad.h" -#include "NetworkCacheSubresourcesEntry.h" -#include "NetworkProcess.h" -#include <WebCore/DiagnosticLoggingKeys.h> -#include <WebCore/HysteresisActivity.h> -#include <wtf/HashCountedSet.h> -#include <wtf/NeverDestroyed.h> -#include <wtf/RefCounted.h> -#include <wtf/RunLoop.h> - -namespace WebKit { - -namespace NetworkCache { - -using namespace WebCore; - -static const auto preloadedEntryLifetime = 10_s; - -#if !LOG_DISABLED -static HashCountedSet<String>& allSpeculativeLoadingDiagnosticMessages() -{ - static NeverDestroyed<HashCountedSet<String>> messages; - return messages; -} - -static void printSpeculativeLoadingDiagnosticMessageCounts() -{ - LOG(NetworkCacheSpeculativePreloading, "-- Speculative loading statistics --"); - for (auto& pair : allSpeculativeLoadingDiagnosticMessages()) - LOG(NetworkCacheSpeculativePreloading, "%s: %u", pair.key.utf8().data(), pair.value); -} -#endif - -static void logSpeculativeLoadingDiagnosticMessage(const GlobalFrameID& frameID, const String& message) -{ -#if !LOG_DISABLED - if (WebKit2LogNetworkCacheSpeculativePreloading.state == WTFLogChannelOn) - allSpeculativeLoadingDiagnosticMessages().add(message); -#endif - NetworkProcess::singleton().logDiagnosticMessage(frameID.first, WebCore::DiagnosticLoggingKeys::networkCacheKey(), message, WebCore::ShouldSample::Yes); -} - -static const AtomicString& subresourcesType() -{ - ASSERT(RunLoop::isMain()); - static NeverDestroyed<const AtomicString> resource("subresources", AtomicString::ConstructFromLiteral); - return resource; -} - -static inline Key makeSubresourcesKey(const Key& resourceKey) -{ - return Key(resourceKey.partition(), subresourcesType(), resourceKey.range(), resourceKey.identifier()); -} - -static inline ResourceRequest constructRevalidationRequest(const Entry& entry) -{ - ResourceRequest revalidationRequest(entry.key().identifier()); - - String eTag = entry.response().httpHeaderField(HTTPHeaderName::ETag); - if (!eTag.isEmpty()) - revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag); - - String lastModified = entry.response().httpHeaderField(HTTPHeaderName::LastModified); - if (!lastModified.isEmpty()) - revalidationRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified); - - return revalidationRequest; -} - -static bool responseNeedsRevalidation(const ResourceResponse& response, std::chrono::system_clock::time_point timestamp) -{ - if (response.cacheControlContainsNoCache()) - return true; - - auto age = computeCurrentAge(response, timestamp); - auto lifetime = computeFreshnessLifetimeForHTTPFamily(response, timestamp); - return age - lifetime > 0_ms; -} - -class SpeculativeLoadManager::ExpiringEntry { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit ExpiringEntry(std::function<void()>&& expirationHandler) - : m_lifetimeTimer(WTFMove(expirationHandler)) - { - m_lifetimeTimer.startOneShot(preloadedEntryLifetime); - } - -private: - Timer m_lifetimeTimer; -}; - -class SpeculativeLoadManager::PreloadedEntry : private ExpiringEntry { - WTF_MAKE_FAST_ALLOCATED; -public: - PreloadedEntry(std::unique_ptr<Entry> entry, WasRevalidated wasRevalidated, std::function<void()>&& lifetimeReachedHandler) - : ExpiringEntry(WTFMove(lifetimeReachedHandler)) - , m_entry(WTFMove(entry)) - , m_wasRevalidated(wasRevalidated == WasRevalidated::Yes) - { } - - std::unique_ptr<Entry> takeCacheEntry() - { - ASSERT(m_entry); - return WTFMove(m_entry); - } - - bool wasRevalidated() const { return m_wasRevalidated; } - -private: - std::unique_ptr<Entry> m_entry; - bool m_wasRevalidated; -}; - -class SpeculativeLoadManager::PendingFrameLoad : public RefCounted<PendingFrameLoad> { -public: - static Ref<PendingFrameLoad> create(Storage& storage, const Key& mainResourceKey, std::function<void()>&& loadCompletionHandler) - { - return adoptRef(*new PendingFrameLoad(storage, mainResourceKey, WTFMove(loadCompletionHandler))); - } - - ~PendingFrameLoad() - { - ASSERT(m_didFinishLoad); - ASSERT(m_didRetrieveExistingEntry); - } - - void registerSubresource(const Key& subresourceKey) - { - ASSERT(RunLoop::isMain()); - m_subresourceKeys.append(subresourceKey); - m_loadHysteresisActivity.impulse(); - } - - void markLoadAsCompleted() - { - ASSERT(RunLoop::isMain()); - if (m_didFinishLoad) - return; - -#if !LOG_DISABLED - printSpeculativeLoadingDiagnosticMessageCounts(); -#endif - - m_didFinishLoad = true; - saveToDiskIfReady(); - m_loadCompletionHandler(); - } - - void setExistingSubresourcesEntry(std::unique_ptr<SubresourcesEntry> entry) - { - ASSERT(!m_existingEntry); - ASSERT(!m_didRetrieveExistingEntry); - - m_existingEntry = WTFMove(entry); - m_didRetrieveExistingEntry = true; - saveToDiskIfReady(); - } - -private: - PendingFrameLoad(Storage& storage, const Key& mainResourceKey, std::function<void()>&& loadCompletionHandler) - : m_storage(storage) - , m_mainResourceKey(mainResourceKey) - , m_loadCompletionHandler(WTFMove(loadCompletionHandler)) - , m_loadHysteresisActivity([this](HysteresisState state) { if (state == HysteresisState::Stopped) markLoadAsCompleted(); }) - { } - - void saveToDiskIfReady() - { - if (!m_didFinishLoad || !m_didRetrieveExistingEntry) - return; - - if (m_subresourceKeys.isEmpty()) - return; - -#if !LOG_DISABLED - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Saving to disk list of subresources for '%s':", m_mainResourceKey.identifier().utf8().data()); - for (auto& subresourceKey : m_subresourceKeys) - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) * Subresource: '%s'.", subresourceKey.identifier().utf8().data()); -#endif - - if (m_existingEntry) { - m_existingEntry->updateSubresourceKeys(m_subresourceKeys); - m_storage.store(m_existingEntry->encodeAsStorageRecord(), [](const Data&) { }); - } else { - SubresourcesEntry entry(makeSubresourcesKey(m_mainResourceKey), m_subresourceKeys); - m_storage.store(entry.encodeAsStorageRecord(), [](const Data&) { }); - } - } - - Storage& m_storage; - Key m_mainResourceKey; - Vector<Key> m_subresourceKeys; - std::function<void()> m_loadCompletionHandler; - HysteresisActivity m_loadHysteresisActivity; - std::unique_ptr<SubresourcesEntry> m_existingEntry; - bool m_didFinishLoad { false }; - bool m_didRetrieveExistingEntry { false }; -}; - -SpeculativeLoadManager::SpeculativeLoadManager(Storage& storage) - : m_storage(storage) -{ -} - -SpeculativeLoadManager::~SpeculativeLoadManager() -{ -} - -bool SpeculativeLoadManager::retrieve(const GlobalFrameID& frameID, const Key& storageKey, const RetrieveCompletionHandler& completionHandler) -{ - // Check already preloaded entries. - if (auto preloadedEntry = m_preloadedEntries.take(storageKey)) { - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Retrieval: Using preloaded entry to satisfy request for '%s':", storageKey.identifier().utf8().data()); - if (preloadedEntry->wasRevalidated()) - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::successfulSpeculativeWarmupWithRevalidationKey()); - else - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::successfulSpeculativeWarmupWithoutRevalidationKey()); - - completionHandler(preloadedEntry->takeCacheEntry()); - return true; - } - - // Check pending speculative revalidations. - if (!m_pendingPreloads.contains(storageKey)) { - if (m_notPreloadedEntries.remove(storageKey)) - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::entryWronglyNotWarmedUpKey()); - else - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::unknownEntryRequestKey()); - - return false; - } - - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Retrieval: revalidation already in progress for '%s':", storageKey.identifier().utf8().data()); - - // FIXME: This breaks incremental loading when the revalidation is not successful. - auto addResult = m_pendingRetrieveRequests.add(storageKey, nullptr); - if (addResult.isNewEntry) - addResult.iterator->value = std::make_unique<Vector<RetrieveCompletionHandler>>(); - addResult.iterator->value->append(completionHandler); - return true; -} - -void SpeculativeLoadManager::registerLoad(const GlobalFrameID& frameID, const ResourceRequest& request, const Key& resourceKey) -{ - ASSERT(RunLoop::isMain()); - - if (!request.url().protocolIsInHTTPFamily() || request.httpMethod() != "GET") - return; - - auto isMainResource = request.requester() == ResourceRequest::Requester::Main; - if (isMainResource) { - // Mark previous load in this frame as completed if necessary. - if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameID)) - pendingFrameLoad->markLoadAsCompleted(); - - ASSERT(!m_pendingFrameLoads.contains(frameID)); - - // Start tracking loads in this frame. - RefPtr<PendingFrameLoad> pendingFrameLoad = PendingFrameLoad::create(m_storage, resourceKey, [this, frameID] { - bool wasRemoved = m_pendingFrameLoads.remove(frameID); - ASSERT_UNUSED(wasRemoved, wasRemoved); - }); - m_pendingFrameLoads.add(frameID, pendingFrameLoad); - - // Retrieve the subresources entry if it exists to start speculative revalidation and to update it. - retrieveSubresourcesEntry(resourceKey, [this, frameID, pendingFrameLoad](std::unique_ptr<SubresourcesEntry> entry) { - if (entry) - startSpeculativeRevalidation(frameID, *entry); - - pendingFrameLoad->setExistingSubresourcesEntry(WTFMove(entry)); - }); - return; - } - - if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameID)) - pendingFrameLoad->registerSubresource(resourceKey); -} - -void SpeculativeLoadManager::addPreloadedEntry(std::unique_ptr<Entry> entry, const GlobalFrameID& frameID, WasRevalidated wasRevalidated) -{ - ASSERT(entry); - ASSERT(!entry->needsValidation()); - auto key = entry->key(); - m_preloadedEntries.add(key, std::make_unique<PreloadedEntry>(WTFMove(entry), wasRevalidated, [this, key, frameID] { - auto preloadedEntry = m_preloadedEntries.take(key); - ASSERT(preloadedEntry); - if (preloadedEntry->wasRevalidated()) - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::wastedSpeculativeWarmupWithRevalidationKey()); - else - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::wastedSpeculativeWarmupWithoutRevalidationKey()); - })); -} - -void SpeculativeLoadManager::retrieveEntryFromStorage(const Key& key, const RetrieveCompletionHandler& completionHandler) -{ - m_storage.retrieve(key, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler](std::unique_ptr<Storage::Record> record) { - if (!record) { - completionHandler(nullptr); - return false; - } - auto entry = Entry::decodeStorageRecord(*record); - if (!entry) { - completionHandler(nullptr); - return false; - } - - auto& response = entry->response(); - if (!response.hasCacheValidatorFields()) { - completionHandler(nullptr); - return true; - } - - if (responseNeedsRevalidation(response, entry->timeStamp())) - entry->setNeedsValidation(); - - completionHandler(WTFMove(entry)); - return true; - }); -} - -bool SpeculativeLoadManager::satisfyPendingRequests(const Key& key, Entry* entry) -{ - auto completionHandlers = m_pendingRetrieveRequests.take(key); - if (!completionHandlers) - return false; - - for (auto& completionHandler : *completionHandlers) - completionHandler(entry ? std::make_unique<Entry>(*entry) : nullptr); - - return true; -} - -void SpeculativeLoadManager::revalidateEntry(std::unique_ptr<Entry> entry, const GlobalFrameID& frameID) -{ - ASSERT(entry); - ASSERT(entry->needsValidation()); - - auto key = entry->key(); - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Speculatively revalidating '%s':", key.identifier().utf8().data()); - auto revalidator = std::make_unique<SpeculativeLoad>(frameID, constructRevalidationRequest(*entry), WTFMove(entry), [this, key, frameID](std::unique_ptr<Entry> revalidatedEntry) { - ASSERT(!revalidatedEntry || !revalidatedEntry->needsValidation()); - auto protectRevalidator = m_pendingPreloads.take(key); - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Speculative revalidation completed for '%s':", key.identifier().utf8().data()); - - if (satisfyPendingRequests(key, revalidatedEntry.get())) { - if (revalidatedEntry) - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::successfulSpeculativeWarmupWithRevalidationKey()); - return; - } - - if (revalidatedEntry) - addPreloadedEntry(WTFMove(revalidatedEntry), frameID, WasRevalidated::Yes); - }); - m_pendingPreloads.add(key, WTFMove(revalidator)); -} - -void SpeculativeLoadManager::preloadEntry(const Key& key, const GlobalFrameID& frameID) -{ - m_pendingPreloads.add(key, nullptr); - retrieveEntryFromStorage(key, [this, key, frameID](std::unique_ptr<Entry> entry) { - m_pendingPreloads.remove(key); - - if (satisfyPendingRequests(key, entry.get())) { - if (entry) - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::successfulSpeculativeWarmupWithoutRevalidationKey()); - return; - } - - if (!entry) - return; - - if (entry->needsValidation()) - revalidateEntry(WTFMove(entry), frameID); - else - addPreloadedEntry(WTFMove(entry), frameID, WasRevalidated::No); - }); -} - -void SpeculativeLoadManager::startSpeculativeRevalidation(const GlobalFrameID& frameID, SubresourcesEntry& entry) -{ - for (auto& subresource : entry.subresources()) { - auto key = subresource.key; - if (!subresource.value.isTransient) - preloadEntry(key, frameID); - else { - LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Not preloading '%s' because it is marked as transient", subresource.key.identifier().utf8().data()); - m_notPreloadedEntries.add(key, std::make_unique<ExpiringEntry>([this, key, frameID] { - logSpeculativeLoadingDiagnosticMessage(frameID, DiagnosticLoggingKeys::entryRightlyNotWarmedUpKey()); - m_notPreloadedEntries.remove(key); - })); - } - } -} - -void SpeculativeLoadManager::retrieveSubresourcesEntry(const Key& storageKey, std::function<void (std::unique_ptr<SubresourcesEntry>)> completionHandler) -{ - ASSERT(storageKey.type() == "resource"); - auto subresourcesStorageKey = makeSubresourcesKey(storageKey); - m_storage.retrieve(subresourcesStorageKey, static_cast<unsigned>(ResourceLoadPriority::Medium), [completionHandler](std::unique_ptr<Storage::Record> record) { - if (!record) { - completionHandler(nullptr); - return false; - } - - auto subresourcesEntry = SubresourcesEntry::decodeStorageRecord(*record); - if (!subresourcesEntry) { - completionHandler(nullptr); - return false; - } - - completionHandler(WTFMove(subresourcesEntry)); - return true; - }); -} - -} // namespace NetworkCache - -} // namespace WebKit - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.h deleted file mode 100644 index 4c1de7200..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheSpeculativeLoadManager_h -#define NetworkCacheSpeculativeLoadManager_h - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - -#include "NetworkCache.h" -#include "NetworkCacheStorage.h" -#include <WebCore/ResourceRequest.h> -#include <wtf/HashMap.h> -#include <wtf/Vector.h> - -namespace WebKit { - -namespace NetworkCache { - -class Entry; -class SpeculativeLoad; -class SubresourcesEntry; - -class SpeculativeLoadManager { -public: - explicit SpeculativeLoadManager(Storage&); - ~SpeculativeLoadManager(); - - void registerLoad(const GlobalFrameID&, const WebCore::ResourceRequest&, const Key& resourceKey); - - typedef std::function<void (std::unique_ptr<Entry>)> RetrieveCompletionHandler; - bool retrieve(const GlobalFrameID&, const Key& storageKey, const RetrieveCompletionHandler&); - -private: - enum class WasRevalidated { No, Yes }; - void addPreloadedEntry(std::unique_ptr<Entry>, const GlobalFrameID&, WasRevalidated); - void preloadEntry(const Key&, const GlobalFrameID&); - void retrieveEntryFromStorage(const Key&, const RetrieveCompletionHandler&); - void revalidateEntry(std::unique_ptr<Entry>, const GlobalFrameID&); - bool satisfyPendingRequests(const Key&, Entry*); - void retrieveSubresourcesEntry(const Key& storageKey, std::function<void (std::unique_ptr<SubresourcesEntry>)>); - void startSpeculativeRevalidation(const GlobalFrameID&, SubresourcesEntry&); - - Storage& m_storage; - - class PendingFrameLoad; - HashMap<GlobalFrameID, RefPtr<PendingFrameLoad>> m_pendingFrameLoads; - - HashMap<Key, std::unique_ptr<SpeculativeLoad>> m_pendingPreloads; - HashMap<Key, std::unique_ptr<Vector<RetrieveCompletionHandler>>> m_pendingRetrieveRequests; - - class PreloadedEntry; - HashMap<Key, std::unique_ptr<PreloadedEntry>> m_preloadedEntries; - - class ExpiringEntry; - HashMap<Key, std::unique_ptr<ExpiringEntry>> m_notPreloadedEntries; // For logging. -}; - -} // namespace NetworkCache - -} // namespace WebKit - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - -#endif // NetworkCacheSpeculativeLoadManager_h diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp deleted file mode 100644 index 263393db7..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(NETWORK_CACHE) -#include "NetworkCacheStatistics.h" - -#include "Logging.h" -#include "NetworkCache.h" -#include "NetworkCacheFileSystem.h" -#include "NetworkProcess.h" -#include <WebCore/DiagnosticLoggingKeys.h> -#include <WebCore/DiagnosticLoggingResultType.h> -#include <WebCore/ResourceRequest.h> -#include <WebCore/SQLiteDatabaseTracker.h> -#include <WebCore/SQLiteStatement.h> -#include <WebCore/SQLiteTransaction.h> -#include <wtf/RunLoop.h> - -namespace WebKit { -namespace NetworkCache { - -static const char* StatisticsDatabaseName = "WebKitCacheStatistics.db"; -static const std::chrono::milliseconds mininumWriteInterval = std::chrono::milliseconds(10000); - -static bool executeSQLCommand(WebCore::SQLiteDatabase& database, const String& sql) -{ - ASSERT(!RunLoop::isMain()); - ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress()); - ASSERT(database.isOpen()); - - bool result = database.executeCommand(sql); - if (!result) - LOG_ERROR("Network cache statistics: failed to execute statement \"%s\" error \"%s\"", sql.utf8().data(), database.lastErrorMsg()); - - return result; -} - -static bool executeSQLStatement(WebCore::SQLiteStatement& statement) -{ - ASSERT(!RunLoop::isMain()); - ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress()); - ASSERT(statement.database().isOpen()); - - if (statement.step() != SQLITE_DONE) { - LOG_ERROR("Network cache statistics: failed to execute statement \"%s\" error \"%s\"", statement.query().utf8().data(), statement.database().lastErrorMsg()); - return false; - } - - return true; -} - -std::unique_ptr<Statistics> Statistics::open(const String& cachePath) -{ - ASSERT(RunLoop::isMain()); - - String databasePath = WebCore::pathByAppendingComponent(cachePath, StatisticsDatabaseName); - return std::unique_ptr<Statistics>(new Statistics(databasePath)); -} - -Statistics::Statistics(const String& databasePath) - : m_serialBackgroundIOQueue(WorkQueue::create("com.apple.WebKit.Cache.Statistics.Background", WorkQueue::Type::Serial, WorkQueue::QOS::Background)) - , m_writeTimer(*this, &Statistics::writeTimerFired) -{ - initialize(databasePath); -} - -void Statistics::initialize(const String& databasePath) -{ - ASSERT(RunLoop::isMain()); - - auto startTime = std::chrono::system_clock::now(); - - StringCapture databasePathCapture(databasePath); - StringCapture networkCachePathCapture(singleton().recordsPath()); - serialBackgroundIOQueue().dispatch([this, databasePathCapture, networkCachePathCapture, startTime] { - WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter; - - String databasePath = databasePathCapture.string(); - if (!WebCore::makeAllDirectories(WebCore::directoryName(databasePath))) - return; - - LOG(NetworkCache, "(NetworkProcess) Opening network cache statistics database at %s...", databasePath.utf8().data()); - m_database.open(databasePath); - m_database.disableThreadingChecks(); - if (!m_database.isOpen()) { - LOG_ERROR("Network cache statistics: Failed to open / create the network cache statistics database"); - return; - } - - executeSQLCommand(m_database, ASCIILiteral("CREATE TABLE IF NOT EXISTS AlreadyRequested (hash TEXT PRIMARY KEY)")); - executeSQLCommand(m_database, ASCIILiteral("CREATE TABLE IF NOT EXISTS UncachedReason (hash TEXT PRIMARY KEY, reason INTEGER)")); - - WebCore::SQLiteStatement statement(m_database, ASCIILiteral("SELECT count(*) FROM AlreadyRequested")); - if (statement.prepareAndStep() != SQLITE_ROW) { - LOG_ERROR("Network cache statistics: Failed to count the number of rows in AlreadyRequested table"); - return; - } - - m_approximateEntryCount = statement.getColumnInt(0); - -#if !LOG_DISABLED - auto elapsedMS = static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count()); -#endif - LOG(NetworkCache, "(NetworkProcess) Network cache statistics database load complete, entries=%lu time=%" PRIi64 "ms", static_cast<size_t>(m_approximateEntryCount), elapsedMS); - - if (!m_approximateEntryCount) { - bootstrapFromNetworkCache(networkCachePathCapture.string()); -#if !LOG_DISABLED - elapsedMS = static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - startTime).count()); -#endif - LOG(NetworkCache, "(NetworkProcess) Network cache statistics database bootstrapping complete, entries=%lu time=%" PRIi64 "ms", static_cast<size_t>(m_approximateEntryCount), elapsedMS); - } - }); -} - -void Statistics::bootstrapFromNetworkCache(const String& networkCachePath) -{ - ASSERT(!RunLoop::isMain()); - - LOG(NetworkCache, "(NetworkProcess) Bootstrapping the network cache statistics database from the network cache..."); - - Vector<StringCapture> hashes; - traverseRecordsFiles(networkCachePath, ASCIILiteral("resource"), [&hashes](const String& fileName, const String& hashString, const String& type, bool isBodyBlob, const String& recordDirectoryPath) { - if (isBodyBlob) - return; - - Key::HashType hash; - if (!Key::stringToHash(hashString, hash)) - return; - - hashes.append(hashString); - }); - - WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter; - WebCore::SQLiteTransaction writeTransaction(m_database); - writeTransaction.begin(); - - addHashesToDatabase(hashes); - - writeTransaction.commit(); -} - -void Statistics::shrinkIfNeeded() -{ - ASSERT(RunLoop::isMain()); - const size_t maxEntries = 100000; - - if (m_approximateEntryCount < maxEntries) - return; - - LOG(NetworkCache, "(NetworkProcess) shrinking statistics cache m_approximateEntryCount=%lu, maxEntries=%lu", static_cast<size_t>(m_approximateEntryCount), maxEntries); - - clear(); - - StringCapture networkCachePathCapture(singleton().recordsPath()); - serialBackgroundIOQueue().dispatch([this, networkCachePathCapture] { - bootstrapFromNetworkCache(networkCachePathCapture.string()); - LOG(NetworkCache, "(NetworkProcess) statistics cache shrink completed m_approximateEntryCount=%lu", static_cast<size_t>(m_approximateEntryCount)); - }); -} - -void Statistics::recordRetrievalRequest(uint64_t webPageID) -{ - NetworkProcess::singleton().logDiagnosticMessage(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::retrievalRequestKey(), WebCore::ShouldSample::Yes); -} - -void Statistics::recordNotCachingResponse(const Key& key, StoreDecision storeDecision) -{ - ASSERT(storeDecision != StoreDecision::Yes); - - m_storeDecisionsToAdd.set(key.hashAsString(), storeDecision); - if (!m_writeTimer.isActive()) - m_writeTimer.startOneShot(mininumWriteInterval); -} - -static String retrieveDecisionToDiagnosticKey(RetrieveDecision retrieveDecision) -{ - switch (retrieveDecision) { - case RetrieveDecision::NoDueToHTTPMethod: - return WebCore::DiagnosticLoggingKeys::unsupportedHTTPMethodKey(); - case RetrieveDecision::NoDueToConditionalRequest: - return WebCore::DiagnosticLoggingKeys::isConditionalRequestKey(); - case RetrieveDecision::NoDueToReloadIgnoringCache: - return WebCore::DiagnosticLoggingKeys::isReloadIgnoringCacheDataKey(); - case RetrieveDecision::Yes: - ASSERT_NOT_REACHED(); - break; - } - return emptyString(); -} - -void Statistics::recordNotUsingCacheForRequest(uint64_t webPageID, const Key& key, const WebCore::ResourceRequest& request, RetrieveDecision retrieveDecision) -{ - ASSERT(retrieveDecision != RetrieveDecision::Yes); - - String hash = key.hashAsString(); - WebCore::URL requestURL = request.url(); - queryWasEverRequested(hash, NeedUncachedReason::No, [this, hash, requestURL, webPageID, retrieveDecision](bool wasEverRequested, const Optional<StoreDecision>&) { - if (wasEverRequested) { - String diagnosticKey = retrieveDecisionToDiagnosticKey(retrieveDecision); - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s was previously requested but we are not using the cache, reason: %s", webPageID, requestURL.string().ascii().data(), diagnosticKey.utf8().data()); - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::unusedKey(), diagnosticKey, WebCore::ShouldSample::Yes); - } else { - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::requestKey(), WebCore::DiagnosticLoggingKeys::neverSeenBeforeKey(), WebCore::ShouldSample::Yes); - markAsRequested(hash); - } - }); -} - -static String storeDecisionToDiagnosticKey(StoreDecision storeDecision) -{ - switch (storeDecision) { - case StoreDecision::NoDueToProtocol: - return WebCore::DiagnosticLoggingKeys::notHTTPFamilyKey(); - case StoreDecision::NoDueToHTTPMethod: - return WebCore::DiagnosticLoggingKeys::unsupportedHTTPMethodKey(); - case StoreDecision::NoDueToAttachmentResponse: - return WebCore::DiagnosticLoggingKeys::isAttachmentKey(); - case StoreDecision::NoDueToNoStoreResponse: - case StoreDecision::NoDueToNoStoreRequest: - return WebCore::DiagnosticLoggingKeys::cacheControlNoStoreKey(); - case StoreDecision::NoDueToHTTPStatusCode: - return WebCore::DiagnosticLoggingKeys::uncacheableStatusCodeKey(); - case StoreDecision::NoDueToUnlikelyToReuse: - return WebCore::DiagnosticLoggingKeys::unlikelyToReuseKey(); - case StoreDecision::NoDueToStreamingMedia: - return WebCore::DiagnosticLoggingKeys::streamingMedia(); - case StoreDecision::Yes: - // It was stored but could not be retrieved so it must have been pruned from the cache. - return WebCore::DiagnosticLoggingKeys::noLongerInCacheKey(); - } - return String(); -} - -void Statistics::recordRetrievalFailure(uint64_t webPageID, const Key& key, const WebCore::ResourceRequest& request) -{ - String hash = key.hashAsString(); - WebCore::URL requestURL = request.url(); - queryWasEverRequested(hash, NeedUncachedReason::Yes, [this, hash, requestURL, webPageID](bool wasPreviouslyRequested, const Optional<StoreDecision>& storeDecision) { - if (wasPreviouslyRequested) { - String diagnosticKey = storeDecisionToDiagnosticKey(storeDecision.value()); - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s was previously request but is not in the cache, reason: %s", webPageID, requestURL.string().ascii().data(), diagnosticKey.utf8().data()); - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::notInCacheKey(), diagnosticKey, WebCore::ShouldSample::Yes); - } else { - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::requestKey(), WebCore::DiagnosticLoggingKeys::neverSeenBeforeKey(), WebCore::ShouldSample::Yes); - markAsRequested(hash); - } - }); -} - -static String cachedEntryReuseFailureToDiagnosticKey(UseDecision decision) -{ - switch (decision) { - case UseDecision::NoDueToVaryingHeaderMismatch: - return WebCore::DiagnosticLoggingKeys::varyingHeaderMismatchKey(); - case UseDecision::NoDueToMissingValidatorFields: - return WebCore::DiagnosticLoggingKeys::missingValidatorFieldsKey(); - case UseDecision::NoDueToDecodeFailure: - case UseDecision::NoDueToExpiredRedirect: - return WebCore::DiagnosticLoggingKeys::otherKey(); - case UseDecision::Use: - case UseDecision::Validate: - ASSERT_NOT_REACHED(); - break; - } - return emptyString(); -} - -void Statistics::recordRetrievedCachedEntry(uint64_t webPageID, const Key& key, const WebCore::ResourceRequest& request, UseDecision decision) -{ - WebCore::URL requestURL = request.url(); - if (decision == UseDecision::Use) { - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s is in the cache and is used", webPageID, requestURL.string().ascii().data()); - NetworkProcess::singleton().logDiagnosticMessageWithResult(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::retrievalKey(), WebCore::DiagnosticLoggingResultPass, WebCore::ShouldSample::Yes); - return; - } - - if (decision == UseDecision::Validate) { - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s is in the cache but needs revalidation", webPageID, requestURL.string().ascii().data()); - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::retrievalKey(), WebCore::DiagnosticLoggingKeys::needsRevalidationKey(), WebCore::ShouldSample::Yes); - return; - } - - String diagnosticKey = cachedEntryReuseFailureToDiagnosticKey(decision); - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s is in the cache but wasn't used, reason: %s", webPageID, requestURL.string().ascii().data(), diagnosticKey.utf8().data()); - NetworkProcess::singleton().logDiagnosticMessageWithValue(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::unusableCachedEntryKey(), diagnosticKey, WebCore::ShouldSample::Yes); -} - -void Statistics::recordRevalidationSuccess(uint64_t webPageID, const Key& key, const WebCore::ResourceRequest& request) -{ - WebCore::URL requestURL = request.url(); - LOG(NetworkCache, "(NetworkProcess) webPageID %" PRIu64 ": %s was successfully revalidated", webPageID, requestURL.string().ascii().data()); - - NetworkProcess::singleton().logDiagnosticMessageWithResult(webPageID, WebCore::DiagnosticLoggingKeys::networkCacheKey(), WebCore::DiagnosticLoggingKeys::revalidatingKey(), WebCore::DiagnosticLoggingResultPass, WebCore::ShouldSample::Yes); -} - -void Statistics::markAsRequested(const String& hash) -{ - ASSERT(RunLoop::isMain()); - - m_hashesToAdd.add(hash); - if (!m_writeTimer.isActive()) - m_writeTimer.startOneShot(mininumWriteInterval); -} - -void Statistics::writeTimerFired() -{ - ASSERT(RunLoop::isMain()); - - Vector<StringCapture> hashesToAdd; - copyToVector(m_hashesToAdd, hashesToAdd); - m_hashesToAdd.clear(); - - Vector<std::pair<StringCapture, StoreDecision>> storeDecisionsToAdd; - copyToVector(m_storeDecisionsToAdd, storeDecisionsToAdd); - m_storeDecisionsToAdd.clear(); - - shrinkIfNeeded(); - - serialBackgroundIOQueue().dispatch([this, hashesToAdd, storeDecisionsToAdd] { - if (!m_database.isOpen()) - return; - - WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter; - WebCore::SQLiteTransaction writeTransaction(m_database); - writeTransaction.begin(); - - addHashesToDatabase(hashesToAdd); - addStoreDecisionsToDatabase(storeDecisionsToAdd); - - writeTransaction.commit(); - }); -} - -void Statistics::queryWasEverRequested(const String& hash, NeedUncachedReason needUncachedReason, const RequestedCompletionHandler& completionHandler) -{ - ASSERT(RunLoop::isMain()); - - // Query pending writes first. - bool wasAlreadyRequested = m_hashesToAdd.contains(hash); - if (wasAlreadyRequested && needUncachedReason == NeedUncachedReason::No) { - completionHandler(true, Nullopt); - return; - } - if (needUncachedReason == NeedUncachedReason::Yes && m_storeDecisionsToAdd.contains(hash)) { - completionHandler(true, m_storeDecisionsToAdd.get(hash)); - return; - } - - // Query the database. - auto everRequestedQuery = std::make_unique<EverRequestedQuery>(EverRequestedQuery { hash, needUncachedReason == NeedUncachedReason::Yes, completionHandler }); - auto& query = *everRequestedQuery; - m_activeQueries.add(WTFMove(everRequestedQuery)); - serialBackgroundIOQueue().dispatch([this, wasAlreadyRequested, &query] () mutable { - WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter; - Optional<StoreDecision> storeDecision; - if (m_database.isOpen()) { - if (!wasAlreadyRequested) { - WebCore::SQLiteStatement statement(m_database, ASCIILiteral("SELECT hash FROM AlreadyRequested WHERE hash=?")); - if (statement.prepare() == SQLITE_OK) { - statement.bindText(1, query.hash); - wasAlreadyRequested = (statement.step() == SQLITE_ROW); - } - } - if (wasAlreadyRequested && query.needUncachedReason) { - WebCore::SQLiteStatement statement(m_database, ASCIILiteral("SELECT reason FROM UncachedReason WHERE hash=?")); - storeDecision = StoreDecision::Yes; - if (statement.prepare() == SQLITE_OK) { - statement.bindText(1, query.hash); - if (statement.step() == SQLITE_ROW) - storeDecision = static_cast<StoreDecision>(statement.getColumnInt(0)); - } - } - } - RunLoop::main().dispatch([this, &query, wasAlreadyRequested, storeDecision] { - query.completionHandler(wasAlreadyRequested, storeDecision); - m_activeQueries.remove(&query); - }); - }); -} - -void Statistics::clear() -{ - ASSERT(RunLoop::isMain()); - - serialBackgroundIOQueue().dispatch([this] { - if (m_database.isOpen()) { - WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter; - WebCore::SQLiteTransaction deleteTransaction(m_database); - deleteTransaction.begin(); - executeSQLCommand(m_database, ASCIILiteral("DELETE FROM AlreadyRequested")); - executeSQLCommand(m_database, ASCIILiteral("DELETE FROM UncachedReason")); - deleteTransaction.commit(); - m_approximateEntryCount = 0; - } - }); -} - -void Statistics::addHashesToDatabase(const Vector<StringCapture>& hashes) -{ - ASSERT(!RunLoop::isMain()); - ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress()); - ASSERT(m_database.isOpen()); - - WebCore::SQLiteStatement statement(m_database, ASCIILiteral("INSERT OR IGNORE INTO AlreadyRequested (hash) VALUES (?)")); - if (statement.prepare() != SQLITE_OK) - return; - - for (auto& hash : hashes) { - statement.bindText(1, hash.string()); - if (executeSQLStatement(statement)) - ++m_approximateEntryCount; - statement.reset(); - } -} - -void Statistics::addStoreDecisionsToDatabase(const Vector<std::pair<StringCapture, StoreDecision>>& storeDecisions) -{ - ASSERT(!RunLoop::isMain()); - ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress()); - ASSERT(m_database.isOpen()); - - WebCore::SQLiteStatement statement(m_database, ASCIILiteral("INSERT OR REPLACE INTO UncachedReason (hash, reason) VALUES (?, ?)")); - if (statement.prepare() != SQLITE_OK) - return; - - for (auto& pair : storeDecisions) { - statement.bindText(1, pair.first.string()); - statement.bindInt(2, static_cast<int>(pair.second)); - executeSQLStatement(statement); - statement.reset(); - } -} - -} -} - -#endif // ENABLE(NETWORK_CACHE) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h deleted file mode 100644 index 9f048e722..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheStatistics_h -#define NetworkCacheStatistics_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCache.h" -#include "NetworkCacheKey.h" -#include <WebCore/SQLiteDatabase.h> -#include <WebCore/Timer.h> -#include <wtf/WorkQueue.h> - -namespace WebCore { -class ResourceRequest; -} - -namespace WebKit { -namespace NetworkCache { - -class Statistics { -public: - static std::unique_ptr<Statistics> open(const String& cachePath); - - void clear(); - - void recordRetrievalRequest(uint64_t webPageID); - void recordNotCachingResponse(const Key&, StoreDecision); - void recordNotUsingCacheForRequest(uint64_t webPageID, const Key&, const WebCore::ResourceRequest&, RetrieveDecision); - void recordRetrievalFailure(uint64_t webPageID, const Key&, const WebCore::ResourceRequest&); - void recordRetrievedCachedEntry(uint64_t webPageID, const Key&, const WebCore::ResourceRequest&, UseDecision); - void recordRevalidationSuccess(uint64_t webPageID, const Key&, const WebCore::ResourceRequest&); - -private: - explicit Statistics(const String& databasePath); - - WorkQueue& serialBackgroundIOQueue() { return m_serialBackgroundIOQueue.get(); } - - void initialize(const String& databasePath); - void bootstrapFromNetworkCache(const String& networkCachePath); - void shrinkIfNeeded(); - - void addHashesToDatabase(const Vector<StringCapture>& hashes); - void addStoreDecisionsToDatabase(const Vector<std::pair<StringCapture, NetworkCache::StoreDecision>>&); - void writeTimerFired(); - - typedef std::function<void (bool wasEverRequested, const Optional<StoreDecision>&)> RequestedCompletionHandler; - enum class NeedUncachedReason { No, Yes }; - void queryWasEverRequested(const String&, NeedUncachedReason, const RequestedCompletionHandler&); - void markAsRequested(const String& hash); - - struct EverRequestedQuery { - String hash; - bool needUncachedReason; - RequestedCompletionHandler completionHandler; - }; - - std::atomic<size_t> m_approximateEntryCount { 0 }; - - mutable Ref<WorkQueue> m_serialBackgroundIOQueue; - mutable HashSet<std::unique_ptr<const EverRequestedQuery>> m_activeQueries; - WebCore::SQLiteDatabase m_database; - HashSet<String> m_hashesToAdd; - HashMap<String, NetworkCache::StoreDecision> m_storeDecisionsToAdd; - WebCore::Timer m_writeTimer; -}; - -} -} - -#endif // ENABLE(NETWORK_CACHE) - -#endif // NetworkCacheStatistics_h diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp deleted file mode 100644 index 1f650bfd1..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * Copyright (C) 2014-2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetworkCacheStorage.h" - -#if ENABLE(NETWORK_CACHE) - -#include "Logging.h" -#include "NetworkCacheCoders.h" -#include "NetworkCacheFileSystem.h" -#include "NetworkCacheIOChannel.h" -#include <mutex> -#include <wtf/Condition.h> -#include <wtf/Lock.h> -#include <wtf/RandomNumber.h> -#include <wtf/RunLoop.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuilder.h> - -namespace WebKit { -namespace NetworkCache { - -static const char versionDirectoryPrefix[] = "Version "; -static const char recordsDirectoryName[] = "Records"; -static const char blobsDirectoryName[] = "Blobs"; -static const char blobSuffix[] = "-blob"; - -static double computeRecordWorth(FileTimes); - -struct Storage::ReadOperation { - WTF_MAKE_FAST_ALLOCATED; -public: - ReadOperation(const Key& key, const RetrieveCompletionHandler& completionHandler) - : key(key) - , completionHandler(completionHandler) - { } - - void cancel(); - bool finish(); - - const Key key; - const RetrieveCompletionHandler completionHandler; - - std::unique_ptr<Record> resultRecord; - SHA1::Digest expectedBodyHash; - BlobStorage::Blob resultBodyBlob; - std::atomic<unsigned> activeCount { 0 }; - bool isCanceled { false }; -}; - -void Storage::ReadOperation::cancel() -{ - ASSERT(RunLoop::isMain()); - - if (isCanceled) - return; - isCanceled = true; - completionHandler(nullptr); -} - -bool Storage::ReadOperation::finish() -{ - ASSERT(RunLoop::isMain()); - - if (isCanceled) - return false; - if (resultRecord && resultRecord->body.isNull()) { - if (resultBodyBlob.hash == expectedBodyHash) - resultRecord->body = resultBodyBlob.data; - else - resultRecord = nullptr; - } - return completionHandler(WTFMove(resultRecord)); -} - -struct Storage::WriteOperation { - WTF_MAKE_FAST_ALLOCATED; -public: - WriteOperation(const Record& record, const MappedBodyHandler& mappedBodyHandler) - : record(record) - , mappedBodyHandler(mappedBodyHandler) - { } - - const Record record; - const MappedBodyHandler mappedBodyHandler; - - std::atomic<unsigned> activeCount { 0 }; -}; - -struct Storage::TraverseOperation { - WTF_MAKE_FAST_ALLOCATED; -public: - TraverseOperation(const String& type, TraverseFlags flags, const TraverseHandler& handler) - : type(type) - , flags(flags) - , handler(handler) - { } - - const String type; - const TraverseFlags flags; - const TraverseHandler handler; - - Lock activeMutex; - Condition activeCondition; - unsigned activeCount { 0 }; -}; - -std::unique_ptr<Storage> Storage::open(const String& cachePath) -{ - ASSERT(RunLoop::isMain()); - - if (!WebCore::makeAllDirectories(cachePath)) - return nullptr; - return std::unique_ptr<Storage>(new Storage(cachePath)); -} - -static String makeVersionedDirectoryPath(const String& baseDirectoryPath) -{ - String versionSubdirectory = versionDirectoryPrefix + String::number(Storage::version); - return WebCore::pathByAppendingComponent(baseDirectoryPath, versionSubdirectory); -} - -static String makeRecordsDirectoryPath(const String& baseDirectoryPath) -{ - return WebCore::pathByAppendingComponent(makeVersionedDirectoryPath(baseDirectoryPath), recordsDirectoryName); -} - -static String makeBlobDirectoryPath(const String& baseDirectoryPath) -{ - return WebCore::pathByAppendingComponent(makeVersionedDirectoryPath(baseDirectoryPath), blobsDirectoryName); -} - -void traverseRecordsFiles(const String& recordsPath, const String& expectedType, const std::function<void (const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath)>& function) -{ - traverseDirectory(recordsPath, [&recordsPath, &function, &expectedType](const String& partitionName, DirectoryEntryType entryType) { - if (entryType != DirectoryEntryType::Directory) - return; - String partitionPath = WebCore::pathByAppendingComponent(recordsPath, partitionName); - traverseDirectory(partitionPath, [&function, &partitionPath, &expectedType](const String& actualType, DirectoryEntryType entryType) { - if (entryType != DirectoryEntryType::Directory) - return; - if (!expectedType.isEmpty() && expectedType != actualType) - return; - String recordDirectoryPath = WebCore::pathByAppendingComponent(partitionPath, actualType); - traverseDirectory(recordDirectoryPath, [&function, &recordDirectoryPath, &actualType](const String& fileName, DirectoryEntryType entryType) { - if (entryType != DirectoryEntryType::File || fileName.length() < Key::hashStringLength()) - return; - - String hashString = fileName.substring(0, Key::hashStringLength()); - auto isBlob = fileName.length() > Key::hashStringLength() && fileName.endsWith(blobSuffix); - function(fileName, hashString, actualType, isBlob, recordDirectoryPath); - }); - }); - }); -} - -static void deleteEmptyRecordsDirectories(const String& recordsPath) -{ - traverseDirectory(recordsPath, [&recordsPath](const String& partitionName, DirectoryEntryType type) { - if (type != DirectoryEntryType::Directory) - return; - - // Delete [type] sub-folders. - String partitionPath = WebCore::pathByAppendingComponent(recordsPath, partitionName); - traverseDirectory(partitionPath, [&partitionPath](const String& subdirName, DirectoryEntryType entryType) { - if (entryType != DirectoryEntryType::Directory) - return; - - // Let system figure out if it is really empty. - WebCore::deleteEmptyDirectory(WebCore::pathByAppendingComponent(partitionPath, subdirName)); - }); - - // Delete [Partition] folders. - // Let system figure out if it is really empty. - WebCore::deleteEmptyDirectory(WebCore::pathByAppendingComponent(recordsPath, partitionName)); - }); -} - -Storage::Storage(const String& baseDirectoryPath) - : m_basePath(baseDirectoryPath) - , m_recordsPath(makeRecordsDirectoryPath(baseDirectoryPath)) - , m_readOperationTimeoutTimer(*this, &Storage::cancelAllReadOperations) - , m_writeOperationDispatchTimer(*this, &Storage::dispatchPendingWriteOperations) - , m_ioQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage", WorkQueue::Type::Concurrent)) - , m_backgroundIOQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage.background", WorkQueue::Type::Concurrent, WorkQueue::QOS::Background)) - , m_serialBackgroundIOQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage.serialBackground", WorkQueue::Type::Serial, WorkQueue::QOS::Background)) - , m_blobStorage(makeBlobDirectoryPath(baseDirectoryPath)) -{ - deleteOldVersions(); - synchronize(); -} - -Storage::~Storage() -{ -} - -String Storage::basePath() const -{ - return m_basePath.isolatedCopy(); -} - -String Storage::versionPath() const -{ - return makeVersionedDirectoryPath(basePath()); -} - -String Storage::recordsPath() const -{ - return m_recordsPath.isolatedCopy(); -} - -size_t Storage::approximateSize() const -{ - return m_approximateRecordsSize + m_blobStorage.approximateSize(); -} - -void Storage::synchronize() -{ - ASSERT(RunLoop::isMain()); - - if (m_synchronizationInProgress || m_shrinkInProgress) - return; - m_synchronizationInProgress = true; - - LOG(NetworkCacheStorage, "(NetworkProcess) synchronizing cache"); - - backgroundIOQueue().dispatch([this] { - auto recordFilter = std::make_unique<ContentsFilter>(); - auto blobFilter = std::make_unique<ContentsFilter>(); - size_t recordsSize = 0; - unsigned count = 0; - String anyType; - traverseRecordsFiles(recordsPath(), anyType, [&recordFilter, &blobFilter, &recordsSize, &count](const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath) { - auto filePath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName); - - Key::HashType hash; - if (!Key::stringToHash(hashString, hash)) { - WebCore::deleteFile(filePath); - return; - } - long long fileSize = 0; - WebCore::getFileSize(filePath, fileSize); - if (!fileSize) { - WebCore::deleteFile(filePath); - return; - } - - if (isBlob) { - blobFilter->add(hash); - return; - } - - recordFilter->add(hash); - recordsSize += fileSize; - ++count; - }); - - auto* recordFilterPtr = recordFilter.release(); - auto* blobFilterPtr = blobFilter.release(); - RunLoop::main().dispatch([this, recordFilterPtr, blobFilterPtr, recordsSize] { - auto recordFilter = std::unique_ptr<ContentsFilter>(recordFilterPtr); - auto blobFilter = std::unique_ptr<ContentsFilter>(blobFilterPtr); - - for (auto& recordFilterKey : m_recordFilterHashesAddedDuringSynchronization) - recordFilter->add(recordFilterKey); - m_recordFilterHashesAddedDuringSynchronization.clear(); - - for (auto& hash : m_blobFilterHashesAddedDuringSynchronization) - blobFilter->add(hash); - m_blobFilterHashesAddedDuringSynchronization.clear(); - - m_recordFilter = WTFMove(recordFilter); - m_blobFilter = WTFMove(blobFilter); - m_approximateRecordsSize = recordsSize; - m_synchronizationInProgress = false; - }); - - m_blobStorage.synchronize(); - - deleteEmptyRecordsDirectories(recordsPath()); - - LOG(NetworkCacheStorage, "(NetworkProcess) cache synchronization completed size=%zu count=%u", recordsSize, count); - }); -} - -void Storage::addToRecordFilter(const Key& key) -{ - ASSERT(RunLoop::isMain()); - - if (m_recordFilter) - m_recordFilter->add(key.hash()); - - // If we get new entries during filter synchronization take care to add them to the new filter as well. - if (m_synchronizationInProgress) - m_recordFilterHashesAddedDuringSynchronization.append(key.hash()); -} - -bool Storage::mayContain(const Key& key) const -{ - ASSERT(RunLoop::isMain()); - return !m_recordFilter || m_recordFilter->mayContain(key.hash()); -} - -bool Storage::mayContainBlob(const Key& key) const -{ - ASSERT(RunLoop::isMain()); - return !m_blobFilter || m_blobFilter->mayContain(key.hash()); -} - -String Storage::recordDirectoryPathForKey(const Key& key) const -{ - ASSERT(!key.partition().isEmpty()); - ASSERT(!key.type().isEmpty()); - return WebCore::pathByAppendingComponent(WebCore::pathByAppendingComponent(recordsPath(), key.partition()), key.type()); -} - -String Storage::recordPathForKey(const Key& key) const -{ - return WebCore::pathByAppendingComponent(recordDirectoryPathForKey(key), key.hashAsString()); -} - -static String blobPathForRecordPath(const String& recordPath) -{ - return recordPath + blobSuffix; -} - -String Storage::blobPathForKey(const Key& key) const -{ - return blobPathForRecordPath(recordPathForKey(key)); -} - -struct RecordMetaData { - RecordMetaData() { } - explicit RecordMetaData(const Key& key) - : cacheStorageVersion(Storage::version) - , key(key) - { } - - unsigned cacheStorageVersion; - Key key; - // FIXME: Add encoder/decoder for time_point. - std::chrono::milliseconds epochRelativeTimeStamp; - SHA1::Digest headerHash; - uint64_t headerSize; - SHA1::Digest bodyHash; - uint64_t bodySize; - bool isBodyInline; - - // Not encoded as a field. Header starts immediately after meta data. - uint64_t headerOffset; -}; - -static bool decodeRecordMetaData(RecordMetaData& metaData, const Data& fileData) -{ - bool success = false; - fileData.apply([&metaData, &success](const uint8_t* data, size_t size) { - Decoder decoder(data, size); - if (!decoder.decode(metaData.cacheStorageVersion)) - return false; - if (!decoder.decode(metaData.key)) - return false; - if (!decoder.decode(metaData.epochRelativeTimeStamp)) - return false; - if (!decoder.decode(metaData.headerHash)) - return false; - if (!decoder.decode(metaData.headerSize)) - return false; - if (!decoder.decode(metaData.bodyHash)) - return false; - if (!decoder.decode(metaData.bodySize)) - return false; - if (!decoder.decode(metaData.isBodyInline)) - return false; - if (!decoder.verifyChecksum()) - return false; - metaData.headerOffset = decoder.currentOffset(); - success = true; - return false; - }); - return success; -} - -static bool decodeRecordHeader(const Data& fileData, RecordMetaData& metaData, Data& headerData) -{ - if (!decodeRecordMetaData(metaData, fileData)) { - LOG(NetworkCacheStorage, "(NetworkProcess) meta data decode failure"); - return false; - } - - if (metaData.cacheStorageVersion != Storage::version) { - LOG(NetworkCacheStorage, "(NetworkProcess) version mismatch"); - return false; - } - - headerData = fileData.subrange(metaData.headerOffset, metaData.headerSize); - if (metaData.headerHash != computeSHA1(headerData)) { - LOG(NetworkCacheStorage, "(NetworkProcess) header checksum mismatch"); - return false; - } - return true; -} - -void Storage::readRecord(ReadOperation& readOperation, const Data& recordData) -{ - ASSERT(!RunLoop::isMain()); - - RecordMetaData metaData; - Data headerData; - if (!decodeRecordHeader(recordData, metaData, headerData)) - return; - - if (metaData.key != readOperation.key) - return; - - // Sanity check against time stamps in future. - auto timeStamp = std::chrono::system_clock::time_point(metaData.epochRelativeTimeStamp); - if (timeStamp > std::chrono::system_clock::now()) - return; - - Data bodyData; - if (metaData.isBodyInline) { - size_t bodyOffset = metaData.headerOffset + headerData.size(); - if (bodyOffset + metaData.bodySize != recordData.size()) - return; - bodyData = recordData.subrange(bodyOffset, metaData.bodySize); - if (metaData.bodyHash != computeSHA1(bodyData)) - return; - } - - readOperation.expectedBodyHash = metaData.bodyHash; - readOperation.resultRecord = std::make_unique<Storage::Record>(Storage::Record { - metaData.key, - timeStamp, - headerData, - bodyData - }); -} - -static Data encodeRecordMetaData(const RecordMetaData& metaData) -{ - Encoder encoder; - - encoder << metaData.cacheStorageVersion; - encoder << metaData.key; - encoder << metaData.epochRelativeTimeStamp; - encoder << metaData.headerHash; - encoder << metaData.headerSize; - encoder << metaData.bodyHash; - encoder << metaData.bodySize; - encoder << metaData.isBodyInline; - - encoder.encodeChecksum(); - - return Data(encoder.buffer(), encoder.bufferSize()); -} - -Optional<BlobStorage::Blob> Storage::storeBodyAsBlob(WriteOperation& writeOperation) -{ - auto blobPath = blobPathForKey(writeOperation.record.key); - - // Store the body. - auto blob = m_blobStorage.add(blobPath, writeOperation.record.body); - if (blob.data.isNull()) - return { }; - - ++writeOperation.activeCount; - - RunLoop::main().dispatch([this, blob, &writeOperation] { - if (m_blobFilter) - m_blobFilter->add(writeOperation.record.key.hash()); - if (m_synchronizationInProgress) - m_blobFilterHashesAddedDuringSynchronization.append(writeOperation.record.key.hash()); - - if (writeOperation.mappedBodyHandler) - writeOperation.mappedBodyHandler(blob.data); - - finishWriteOperation(writeOperation); - }); - return blob; -} - -Data Storage::encodeRecord(const Record& record, Optional<BlobStorage::Blob> blob) -{ - ASSERT(!blob || bytesEqual(blob.value().data, record.body)); - - RecordMetaData metaData(record.key); - metaData.epochRelativeTimeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(record.timeStamp.time_since_epoch()); - metaData.headerHash = computeSHA1(record.header); - metaData.headerSize = record.header.size(); - metaData.bodyHash = blob ? blob.value().hash : computeSHA1(record.body); - metaData.bodySize = record.body.size(); - metaData.isBodyInline = !blob; - - auto encodedMetaData = encodeRecordMetaData(metaData); - auto headerData = concatenate(encodedMetaData, record.header); - - if (metaData.isBodyInline) - return concatenate(headerData, record.body); - - return { headerData }; -} - -void Storage::removeFromPendingWriteOperations(const Key& key) -{ - while (true) { - auto found = m_pendingWriteOperations.findIf([&key](const std::unique_ptr<WriteOperation>& operation) { - return operation->record.key == key; - }); - - if (found == m_pendingWriteOperations.end()) - break; - - m_pendingWriteOperations.remove(found); - } -} - -void Storage::remove(const Key& key) -{ - ASSERT(RunLoop::isMain()); - - if (!mayContain(key)) - return; - - // We can't remove the key from the Bloom filter (but some false positives are expected anyway). - // For simplicity we also don't reduce m_approximateSize on removals. - // The next synchronization will update everything. - - removeFromPendingWriteOperations(key); - - serialBackgroundIOQueue().dispatch([this, key] { - WebCore::deleteFile(recordPathForKey(key)); - m_blobStorage.remove(blobPathForKey(key)); - }); -} - -void Storage::updateFileModificationTime(const String& path) -{ - StringCapture filePathCapture(path); - serialBackgroundIOQueue().dispatch([filePathCapture] { - updateFileModificationTimeIfNeeded(filePathCapture.string()); - }); -} - -void Storage::dispatchReadOperation(std::unique_ptr<ReadOperation> readOperationPtr) -{ - ASSERT(RunLoop::isMain()); - - auto& readOperation = *readOperationPtr; - m_activeReadOperations.add(WTFMove(readOperationPtr)); - - // I/O pressure may make disk operations slow. If they start taking very long time we rather go to network. - const auto readTimeout = 1500_ms; - m_readOperationTimeoutTimer.startOneShot(readTimeout); - - bool shouldGetBodyBlob = mayContainBlob(readOperation.key); - - ioQueue().dispatch([this, &readOperation, shouldGetBodyBlob] { - auto recordPath = recordPathForKey(readOperation.key); - - ++readOperation.activeCount; - if (shouldGetBodyBlob) - ++readOperation.activeCount; - - auto channel = IOChannel::open(recordPath, IOChannel::Type::Read); - channel->read(0, std::numeric_limits<size_t>::max(), &ioQueue(), [this, &readOperation](const Data& fileData, int error) { - if (!error) - readRecord(readOperation, fileData); - finishReadOperation(readOperation); - }); - - if (shouldGetBodyBlob) { - // Read the blob in parallel with the record read. - auto blobPath = blobPathForKey(readOperation.key); - readOperation.resultBodyBlob = m_blobStorage.get(blobPath); - finishReadOperation(readOperation); - } - }); -} - -void Storage::finishReadOperation(ReadOperation& readOperation) -{ - ASSERT(readOperation.activeCount); - // Record and blob reads must finish. - if (--readOperation.activeCount) - return; - - RunLoop::main().dispatch([this, &readOperation] { - bool success = readOperation.finish(); - if (success) - updateFileModificationTime(recordPathForKey(readOperation.key)); - else if (!readOperation.isCanceled) - remove(readOperation.key); - - ASSERT(m_activeReadOperations.contains(&readOperation)); - m_activeReadOperations.remove(&readOperation); - - if (m_activeReadOperations.isEmpty()) - m_readOperationTimeoutTimer.stop(); - - dispatchPendingReadOperations(); - - LOG(NetworkCacheStorage, "(NetworkProcess) read complete success=%d", success); - }); -} - -void Storage::cancelAllReadOperations() -{ - ASSERT(RunLoop::isMain()); - - for (auto& readOperation : m_activeReadOperations) - readOperation->cancel(); - - size_t pendingCount = 0; - for (int priority = maximumRetrievePriority; priority >= 0; --priority) { - auto& pendingRetrieveQueue = m_pendingReadOperationsByPriority[priority]; - pendingCount += pendingRetrieveQueue.size(); - for (auto it = pendingRetrieveQueue.rbegin(), end = pendingRetrieveQueue.rend(); it != end; ++it) - (*it)->cancel(); - pendingRetrieveQueue.clear(); - } - - LOG(NetworkCacheStorage, "(NetworkProcess) retrieve timeout, canceled %u active and %zu pending", m_activeReadOperations.size(), pendingCount); -} - -void Storage::dispatchPendingReadOperations() -{ - ASSERT(RunLoop::isMain()); - - const int maximumActiveReadOperationCount = 5; - - for (int priority = maximumRetrievePriority; priority >= 0; --priority) { - if (m_activeReadOperations.size() > maximumActiveReadOperationCount) { - LOG(NetworkCacheStorage, "(NetworkProcess) limiting parallel retrieves"); - return; - } - auto& pendingRetrieveQueue = m_pendingReadOperationsByPriority[priority]; - if (pendingRetrieveQueue.isEmpty()) - continue; - dispatchReadOperation(pendingRetrieveQueue.takeLast()); - } -} - -template <class T> bool retrieveFromMemory(const T& operations, const Key& key, Storage::RetrieveCompletionHandler& completionHandler) -{ - for (auto& operation : operations) { - if (operation->record.key == key) { - LOG(NetworkCacheStorage, "(NetworkProcess) found write operation in progress"); - auto record = operation->record; - RunLoop::main().dispatch([record, completionHandler] { - completionHandler(std::make_unique<Storage::Record>(record)); - }); - return true; - } - } - return false; -} - -void Storage::dispatchPendingWriteOperations() -{ - ASSERT(RunLoop::isMain()); - - const int maximumActiveWriteOperationCount { 1 }; - - while (!m_pendingWriteOperations.isEmpty()) { - if (m_activeWriteOperations.size() >= maximumActiveWriteOperationCount) { - LOG(NetworkCacheStorage, "(NetworkProcess) limiting parallel writes"); - return; - } - dispatchWriteOperation(m_pendingWriteOperations.takeLast()); - } -} - -static bool shouldStoreBodyAsBlob(const Data& bodyData) -{ - const size_t maximumInlineBodySize { 16 * 1024 }; - return bodyData.size() > maximumInlineBodySize; -} - -void Storage::dispatchWriteOperation(std::unique_ptr<WriteOperation> writeOperationPtr) -{ - ASSERT(RunLoop::isMain()); - - auto& writeOperation = *writeOperationPtr; - m_activeWriteOperations.add(WTFMove(writeOperationPtr)); - - // This was added already when starting the store but filter might have been wiped. - addToRecordFilter(writeOperation.record.key); - - backgroundIOQueue().dispatch([this, &writeOperation] { - auto recordDirectorPath = recordDirectoryPathForKey(writeOperation.record.key); - auto recordPath = recordPathForKey(writeOperation.record.key); - - WebCore::makeAllDirectories(recordDirectorPath); - - ++writeOperation.activeCount; - - bool shouldStoreAsBlob = shouldStoreBodyAsBlob(writeOperation.record.body); - auto blob = shouldStoreAsBlob ? storeBodyAsBlob(writeOperation) : Nullopt; - - auto recordData = encodeRecord(writeOperation.record, blob); - - auto channel = IOChannel::open(recordPath, IOChannel::Type::Create); - size_t recordSize = recordData.size(); - channel->write(0, recordData, nullptr, [this, &writeOperation, recordSize](int error) { - // On error the entry still stays in the contents filter until next synchronization. - m_approximateRecordsSize += recordSize; - finishWriteOperation(writeOperation); - - LOG(NetworkCacheStorage, "(NetworkProcess) write complete error=%d", error); - }); - }); -} - -void Storage::finishWriteOperation(WriteOperation& writeOperation) -{ - ASSERT(RunLoop::isMain()); - ASSERT(writeOperation.activeCount); - ASSERT(m_activeWriteOperations.contains(&writeOperation)); - - if (--writeOperation.activeCount) - return; - - m_activeWriteOperations.remove(&writeOperation); - dispatchPendingWriteOperations(); - - shrinkIfNeeded(); -} - -void Storage::retrieve(const Key& key, unsigned priority, RetrieveCompletionHandler&& completionHandler) -{ - ASSERT(RunLoop::isMain()); - ASSERT(priority <= maximumRetrievePriority); - ASSERT(!key.isNull()); - - if (!m_capacity) { - completionHandler(nullptr); - return; - } - - if (!mayContain(key)) { - completionHandler(nullptr); - return; - } - - if (retrieveFromMemory(m_pendingWriteOperations, key, completionHandler)) - return; - if (retrieveFromMemory(m_activeWriteOperations, key, completionHandler)) - return; - - auto readOperation = std::make_unique<ReadOperation>(key, WTFMove(completionHandler)); - m_pendingReadOperationsByPriority[priority].prepend(WTFMove(readOperation)); - dispatchPendingReadOperations(); -} - -void Storage::store(const Record& record, MappedBodyHandler&& mappedBodyHandler) -{ - ASSERT(RunLoop::isMain()); - ASSERT(!record.key.isNull()); - - if (!m_capacity) - return; - - auto writeOperation = std::make_unique<WriteOperation>(record, WTFMove(mappedBodyHandler)); - m_pendingWriteOperations.prepend(WTFMove(writeOperation)); - - // Add key to the filter already here as we do lookups from the pending operations too. - addToRecordFilter(record.key); - - bool isInitialWrite = m_pendingWriteOperations.size() == 1; - if (!isInitialWrite) - return; - - // Delay the start of writes a bit to avoid affecting early page load. - // Completing writes will dispatch more writes without delay. - static const auto initialWriteDelay = 1_s; - m_writeOperationDispatchTimer.startOneShot(initialWriteDelay); -} - -void Storage::traverse(const String& type, TraverseFlags flags, TraverseHandler&& traverseHandler) -{ - ASSERT(RunLoop::isMain()); - ASSERT(traverseHandler); - // Avoid non-thread safe std::function copies. - - auto traverseOperationPtr = std::make_unique<TraverseOperation>(type, flags, WTFMove(traverseHandler)); - auto& traverseOperation = *traverseOperationPtr; - m_activeTraverseOperations.add(WTFMove(traverseOperationPtr)); - - ioQueue().dispatch([this, &traverseOperation] { - traverseRecordsFiles(recordsPath(), traverseOperation.type, [this, &traverseOperation](const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath) { - ASSERT(type == traverseOperation.type); - if (isBlob) - return; - - auto recordPath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName); - - double worth = -1; - if (traverseOperation.flags & TraverseFlag::ComputeWorth) - worth = computeRecordWorth(fileTimes(recordPath)); - unsigned bodyShareCount = 0; - if (traverseOperation.flags & TraverseFlag::ShareCount) - bodyShareCount = m_blobStorage.shareCount(blobPathForRecordPath(recordPath)); - - std::unique_lock<Lock> lock(traverseOperation.activeMutex); - ++traverseOperation.activeCount; - - auto channel = IOChannel::open(recordPath, IOChannel::Type::Read); - channel->read(0, std::numeric_limits<size_t>::max(), nullptr, [this, &traverseOperation, worth, bodyShareCount](Data& fileData, int) { - RecordMetaData metaData; - Data headerData; - if (decodeRecordHeader(fileData, metaData, headerData)) { - Record record { - metaData.key, - std::chrono::system_clock::time_point(metaData.epochRelativeTimeStamp), - headerData, - { } - }; - RecordInfo info { - static_cast<size_t>(metaData.bodySize), - worth, - bodyShareCount, - String::fromUTF8(SHA1::hexDigest(metaData.bodyHash)) - }; - traverseOperation.handler(&record, info); - } - - std::lock_guard<Lock> lock(traverseOperation.activeMutex); - --traverseOperation.activeCount; - traverseOperation.activeCondition.notifyOne(); - }); - - const unsigned maximumParallelReadCount = 5; - traverseOperation.activeCondition.wait(lock, [&traverseOperation] { - return traverseOperation.activeCount <= maximumParallelReadCount; - }); - }); - // Wait for all reads to finish. - std::unique_lock<Lock> lock(traverseOperation.activeMutex); - traverseOperation.activeCondition.wait(lock, [&traverseOperation] { - return !traverseOperation.activeCount; - }); - RunLoop::main().dispatch([this, &traverseOperation] { - traverseOperation.handler(nullptr, { }); - m_activeTraverseOperations.remove(&traverseOperation); - }); - }); -} - -void Storage::setCapacity(size_t capacity) -{ - ASSERT(RunLoop::isMain()); - -#if !ASSERT_DISABLED - const size_t assumedAverageRecordSize = 50 << 10; - size_t maximumRecordCount = capacity / assumedAverageRecordSize; - // ~10 bits per element are required for <1% false positive rate. - size_t effectiveBloomFilterCapacity = ContentsFilter::tableSize / 10; - // If this gets hit it might be time to increase the filter size. - ASSERT(maximumRecordCount < effectiveBloomFilterCapacity); -#endif - - m_capacity = capacity; - - shrinkIfNeeded(); -} - -void Storage::clear(const String& type, std::chrono::system_clock::time_point modifiedSinceTime, std::function<void ()>&& completionHandler) -{ - ASSERT(RunLoop::isMain()); - LOG(NetworkCacheStorage, "(NetworkProcess) clearing cache"); - - if (m_recordFilter) - m_recordFilter->clear(); - if (m_blobFilter) - m_blobFilter->clear(); - m_approximateRecordsSize = 0; - - // Avoid non-thread safe std::function copies. - auto* completionHandlerPtr = completionHandler ? new std::function<void ()>(WTFMove(completionHandler)) : nullptr; - StringCapture typeCapture(type); - ioQueue().dispatch([this, modifiedSinceTime, completionHandlerPtr, typeCapture] { - auto recordsPath = this->recordsPath(); - traverseRecordsFiles(recordsPath, typeCapture.string(), [modifiedSinceTime](const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath) { - auto filePath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName); - if (modifiedSinceTime > std::chrono::system_clock::time_point::min()) { - auto times = fileTimes(filePath); - if (times.modification < modifiedSinceTime) - return; - } - WebCore::deleteFile(filePath); - }); - - deleteEmptyRecordsDirectories(recordsPath); - - // This cleans unreferenced blobs. - m_blobStorage.synchronize(); - - if (completionHandlerPtr) { - RunLoop::main().dispatch([completionHandlerPtr] { - (*completionHandlerPtr)(); - delete completionHandlerPtr; - }); - } - }); -} - -static double computeRecordWorth(FileTimes times) -{ - using namespace std::chrono; - auto age = system_clock::now() - times.creation; - // File modification time is updated manually on cache read. We don't use access time since OS may update it automatically. - auto accessAge = times.modification - times.creation; - - // For sanity. - if (age <= 0_s || accessAge < 0_s || accessAge > age) - return 0; - - // We like old entries that have been accessed recently. - return duration<double>(accessAge) / age; -} - -static double deletionProbability(FileTimes times, unsigned bodyShareCount) -{ - static const double maximumProbability { 0.33 }; - static const unsigned maximumEffectiveShareCount { 5 }; - - auto worth = computeRecordWorth(times); - - // Adjust a bit so the most valuable entries don't get deleted at all. - auto effectiveWorth = std::min(1.1 * worth, 1.); - - auto probability = (1 - effectiveWorth) * maximumProbability; - - // It is less useful to remove an entry that shares its body data. - if (bodyShareCount) - probability /= std::min(bodyShareCount, maximumEffectiveShareCount); - - return probability; -} - -void Storage::shrinkIfNeeded() -{ - ASSERT(RunLoop::isMain()); - - if (approximateSize() > m_capacity) - shrink(); -} - -void Storage::shrink() -{ - ASSERT(RunLoop::isMain()); - - if (m_shrinkInProgress || m_synchronizationInProgress) - return; - m_shrinkInProgress = true; - - LOG(NetworkCacheStorage, "(NetworkProcess) shrinking cache approximateSize=%zu capacity=%zu", approximateSize(), m_capacity); - - backgroundIOQueue().dispatch([this] { - auto recordsPath = this->recordsPath(); - String anyType; - traverseRecordsFiles(recordsPath, anyType, [this](const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath) { - if (isBlob) - return; - - auto recordPath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName); - auto blobPath = blobPathForRecordPath(recordPath); - - auto times = fileTimes(recordPath); - unsigned bodyShareCount = m_blobStorage.shareCount(blobPath); - auto probability = deletionProbability(times, bodyShareCount); - - bool shouldDelete = randomNumber() < probability; - - LOG(NetworkCacheStorage, "Deletion probability=%f bodyLinkCount=%d shouldDelete=%d", probability, bodyShareCount, shouldDelete); - - if (shouldDelete) { - WebCore::deleteFile(recordPath); - m_blobStorage.remove(blobPath); - } - }); - - RunLoop::main().dispatch([this] { - m_shrinkInProgress = false; - // We could synchronize during the shrink traversal. However this is fast and it is better to have just one code path. - synchronize(); - }); - - LOG(NetworkCacheStorage, "(NetworkProcess) cache shrink completed"); - }); -} - -void Storage::deleteOldVersions() -{ - backgroundIOQueue().dispatch([this] { - auto cachePath = basePath(); - traverseDirectory(cachePath, [&cachePath](const String& subdirName, DirectoryEntryType type) { - if (type != DirectoryEntryType::Directory) - return; - if (!subdirName.startsWith(versionDirectoryPrefix)) - return; - auto versionString = subdirName.substring(strlen(versionDirectoryPrefix)); - bool success; - unsigned directoryVersion = versionString.toUIntStrict(&success); - if (!success) - return; - if (directoryVersion >= version) - return; - -#if PLATFORM(MAC) - // Allow the last stable version of the cache to co-exist with the latest development one on Mac. - const unsigned lastStableVersion = 4; - if (directoryVersion == lastStableVersion) - return; -#endif - - auto oldVersionPath = WebCore::pathByAppendingComponent(cachePath, subdirName); - LOG(NetworkCacheStorage, "(NetworkProcess) deleting old cache version, path %s", oldVersionPath.utf8().data()); - - deleteDirectoryRecursively(oldVersionPath); - }); - }); -} - -} -} - -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h deleted file mode 100644 index 4762a9cbf..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2014-2015 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 NetworkCacheStorage_h -#define NetworkCacheStorage_h - -#if ENABLE(NETWORK_CACHE) - -#include "NetworkCacheBlobStorage.h" -#include "NetworkCacheData.h" -#include "NetworkCacheKey.h" -#include <WebCore/Timer.h> -#include <wtf/BloomFilter.h> -#include <wtf/Deque.h> -#include <wtf/HashSet.h> -#include <wtf/Optional.h> -#include <wtf/WorkQueue.h> -#include <wtf/text/WTFString.h> - -namespace WebKit { -namespace NetworkCache { - -class IOChannel; - -class Storage { - WTF_MAKE_NONCOPYABLE(Storage); -public: - static std::unique_ptr<Storage> open(const String& cachePath); - - struct Record { - WTF_MAKE_FAST_ALLOCATED; - public: - Key key; - std::chrono::system_clock::time_point timeStamp; - Data header; - Data body; - }; - // This may call completion handler synchronously on failure. - typedef std::function<bool (std::unique_ptr<Record>)> RetrieveCompletionHandler; - void retrieve(const Key&, unsigned priority, RetrieveCompletionHandler&&); - - typedef std::function<void (const Data& mappedBody)> MappedBodyHandler; - void store(const Record&, MappedBodyHandler&&); - - void remove(const Key&); - void clear(const String& type, std::chrono::system_clock::time_point modifiedSinceTime, std::function<void ()>&& completionHandler); - - struct RecordInfo { - size_t bodySize; - double worth; // 0-1 where 1 is the most valuable. - unsigned bodyShareCount; - String bodyHash; - }; - enum TraverseFlag { - ComputeWorth = 1 << 0, - ShareCount = 1 << 1, - }; - typedef unsigned TraverseFlags; - typedef std::function<void (const Record*, const RecordInfo&)> TraverseHandler; - // Null record signals end. - void traverse(const String& type, TraverseFlags, TraverseHandler&&); - - void setCapacity(size_t); - size_t capacity() const { return m_capacity; } - size_t approximateSize() const; - - static const unsigned version = 5; - - String basePath() const; - String versionPath() const; - String recordsPath() const; - - ~Storage(); - -private: - Storage(const String& directoryPath); - - String recordDirectoryPathForKey(const Key&) const; - String recordPathForKey(const Key&) const; - String blobPathForKey(const Key&) const; - - void synchronize(); - void deleteOldVersions(); - void shrinkIfNeeded(); - void shrink(); - - struct ReadOperation; - void dispatchReadOperation(std::unique_ptr<ReadOperation>); - void dispatchPendingReadOperations(); - void finishReadOperation(ReadOperation&); - void cancelAllReadOperations(); - - struct WriteOperation; - void dispatchWriteOperation(std::unique_ptr<WriteOperation>); - void dispatchPendingWriteOperations(); - void finishWriteOperation(WriteOperation&); - - Optional<BlobStorage::Blob> storeBodyAsBlob(WriteOperation&); - Data encodeRecord(const Record&, Optional<BlobStorage::Blob>); - void readRecord(ReadOperation&, const Data&); - - void updateFileModificationTime(const String& path); - void removeFromPendingWriteOperations(const Key&); - - WorkQueue& ioQueue() { return m_ioQueue.get(); } - WorkQueue& backgroundIOQueue() { return m_backgroundIOQueue.get(); } - WorkQueue& serialBackgroundIOQueue() { return m_serialBackgroundIOQueue.get(); } - - bool mayContain(const Key&) const; - bool mayContainBlob(const Key&) const; - - void addToRecordFilter(const Key&); - - const String m_basePath; - const String m_recordsPath; - - size_t m_capacity { std::numeric_limits<size_t>::max() }; - size_t m_approximateRecordsSize { 0 }; - - // 2^18 bit filter can support up to 26000 entries with false positive rate < 1%. - using ContentsFilter = BloomFilter<18>; - std::unique_ptr<ContentsFilter> m_recordFilter; - std::unique_ptr<ContentsFilter> m_blobFilter; - - bool m_synchronizationInProgress { false }; - bool m_shrinkInProgress { false }; - - Vector<Key::HashType> m_recordFilterHashesAddedDuringSynchronization; - Vector<Key::HashType> m_blobFilterHashesAddedDuringSynchronization; - - static const int maximumRetrievePriority = 4; - Deque<std::unique_ptr<ReadOperation>> m_pendingReadOperationsByPriority[maximumRetrievePriority + 1]; - HashSet<std::unique_ptr<ReadOperation>> m_activeReadOperations; - WebCore::Timer m_readOperationTimeoutTimer; - - Deque<std::unique_ptr<WriteOperation>> m_pendingWriteOperations; - HashSet<std::unique_ptr<WriteOperation>> m_activeWriteOperations; - WebCore::Timer m_writeOperationDispatchTimer; - - struct TraverseOperation; - HashSet<std::unique_ptr<TraverseOperation>> m_activeTraverseOperations; - - Ref<WorkQueue> m_ioQueue; - Ref<WorkQueue> m_backgroundIOQueue; - Ref<WorkQueue> m_serialBackgroundIOQueue; - - BlobStorage m_blobStorage; -}; - -// FIXME: Remove, used by NetworkCacheStatistics only. -void traverseRecordsFiles(const String& recordsPath, const String& type, const std::function<void (const String& fileName, const String& hashString, const String& type, bool isBodyBlob, const String& recordDirectoryPath)>&); - -} -} -#endif -#endif diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp deleted file mode 100644 index e762c3b33..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) -#include "NetworkCacheSubresourcesEntry.h" - -#include "Logging.h" -#include "NetworkCacheCoders.h" -#include "NetworkCacheDecoder.h" -#include "NetworkCacheEncoder.h" - -namespace WebKit { -namespace NetworkCache { - -Storage::Record SubresourcesEntry::encodeAsStorageRecord() const -{ - Encoder encoder; - encoder << m_subresources; - - encoder.encodeChecksum(); - - return { m_key, m_timeStamp, { encoder.buffer(), encoder.bufferSize() } , { } }; -} - -std::unique_ptr<SubresourcesEntry> SubresourcesEntry::decodeStorageRecord(const Storage::Record& storageEntry) -{ - auto entry = std::make_unique<SubresourcesEntry>(storageEntry); - - Decoder decoder(storageEntry.header.data(), storageEntry.header.size()); - if (!decoder.decode(entry->m_subresources)) - return nullptr; - - if (!decoder.verifyChecksum()) { - LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n"); - return nullptr; - } - - return entry; -} - -SubresourcesEntry::SubresourcesEntry(const Storage::Record& storageEntry) - : m_key(storageEntry.key) - , m_timeStamp(storageEntry.timeStamp) -{ - ASSERT(m_key.type() == "subresources"); -} - -SubresourcesEntry::SubresourcesEntry(Key&& key, const Vector<Key>& subresourceKeys) - : m_key(WTFMove(key)) - , m_timeStamp(std::chrono::system_clock::now()) -{ - ASSERT(m_key.type() == "subresources"); - for (auto& key : subresourceKeys) - m_subresources.add(key, SubresourceInfo()); -} - -void SubresourcesEntry::updateSubresourceKeys(const Vector<Key>& subresourceKeys) -{ - auto oldSubresources = WTFMove(m_subresources); - - // Mark keys that are common with last load as non-Transient. - for (auto& key : subresourceKeys) { - bool isTransient = !oldSubresources.contains(key); - m_subresources.add(key, SubresourceInfo(isTransient)); - } -} - -} // namespace WebKit -} // namespace NetworkCache - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) diff --git a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h b/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h deleted file mode 100644 index d12282ffa..000000000 --- a/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2015 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 NetworkCacheSubresourcesEntry_h -#define NetworkCacheSubresourcesEntry_h - -#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) - -#include "NetworkCacheDecoder.h" -#include "NetworkCacheEncoder.h" -#include "NetworkCacheStorage.h" -#include <wtf/HashMap.h> - -namespace WebKit { -namespace NetworkCache { - -class SubresourcesEntry { - WTF_MAKE_NONCOPYABLE(SubresourcesEntry); WTF_MAKE_FAST_ALLOCATED; -public: - struct SubresourceInfo { - void encode(Encoder& encoder) const { encoder << isTransient; } - static bool decode(Decoder& decoder, SubresourceInfo& info) { return decoder.decode(info.isTransient); } - - SubresourceInfo() = default; - SubresourceInfo(bool isTransient) : isTransient(isTransient) { } - - bool isTransient { false }; - }; - SubresourcesEntry(Key&&, const Vector<Key>& subresourceKeys); - explicit SubresourcesEntry(const Storage::Record&); - - Storage::Record encodeAsStorageRecord() const; - static std::unique_ptr<SubresourcesEntry> decodeStorageRecord(const Storage::Record&); - - const Key& key() const { return m_key; } - std::chrono::system_clock::time_point timeStamp() const { return m_timeStamp; } - const HashMap<Key, SubresourceInfo>& subresources() const { return m_subresources; } - - void updateSubresourceKeys(const Vector<Key>&); - -private: - Key m_key; - std::chrono::system_clock::time_point m_timeStamp; - HashMap<Key, SubresourceInfo> m_subresources; -}; - -} // namespace WebKit -} // namespace NetworkCache - -#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION) -#endif // NetworkCacheSubresourcesEntry_h diff --git a/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp b/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp index c0e70e057..5730ca61c 100644 --- a/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp +++ b/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp @@ -25,9 +25,9 @@ */ #include "config.h" +#if ENABLE(NETWORK_PROCESS) #include "NetworkProcess.h" -#include "NetworkCache.h" #include "NetworkProcessCreationParameters.h" #include "ResourceCachesToClear.h" #include "WebCookieManager.h" @@ -37,15 +37,13 @@ #include <WebCore/ResourceHandle.h> #include <WebCore/SoupNetworkSession.h> #include <libsoup/soup.h> -#include <wtf/RAMSize.h> -#include <wtf/glib/GRefPtr.h> -#include <wtf/glib/GUniquePtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/gobject/GUniquePtr.h> using namespace WebCore; namespace WebKit { -#if !ENABLE(NETWORK_CACHE) static uint64_t getCacheDiskFreeSize(SoupCache* cache) { ASSERT(cache); @@ -57,7 +55,25 @@ static uint64_t getCacheDiskFreeSize(SoupCache* cache) return WebCore::getVolumeFreeSizeForPath(cacheDir.get()); } + +static uint64_t getMemorySize() +{ + static uint64_t kDefaultMemorySize = 512; +#if !OS(WINDOWS) + long pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + return kDefaultMemorySize; + + long physPages = sysconf(_SC_PHYS_PAGES); + if (physPages == -1) + return kDefaultMemorySize; + + return ((pageSize / 1024) * physPages) / 1024; +#else + // Fallback to default for other platforms. + return kDefaultMemorySize; #endif +} void NetworkProcess::userPreferredLanguagesChanged(const Vector<String>& languages) { @@ -67,19 +83,7 @@ void NetworkProcess::userPreferredLanguagesChanged(const Vector<String>& languag void NetworkProcess::platformInitializeNetworkProcess(const NetworkProcessCreationParameters& parameters) { ASSERT(!parameters.diskCacheDirectory.isEmpty()); - m_diskCacheDirectory = parameters.diskCacheDirectory; - -#if ENABLE(NETWORK_CACHE) - // Clear the old soup cache if it exists. - SoupNetworkSession::defaultSession().clearCache(WebCore::directoryName(m_diskCacheDirectory)); - - NetworkCache::singleton().initialize(m_diskCacheDirectory, { parameters.shouldEnableNetworkCacheEfficacyLogging }); -#else - // We used to use the given cache directory for the soup cache, but now we use a subdirectory to avoid - // conflicts with other cache files in the same directory. Remove the old cache files if they still exist. - SoupNetworkSession::defaultSession().clearCache(WebCore::directoryName(m_diskCacheDirectory)); - - GRefPtr<SoupCache> soupCache = adoptGRef(soup_cache_new(m_diskCacheDirectory.utf8().data(), SOUP_CACHE_SINGLE_USER)); + GRefPtr<SoupCache> soupCache = adoptGRef(soup_cache_new(parameters.diskCacheDirectory.utf8().data(), SOUP_CACHE_SINGLE_USER)); SoupNetworkSession::defaultSession().setCache(soupCache.get()); // Set an initial huge max_size for the SoupCache so the call to soup_cache_load() won't evict any cached // resource. The final size of the cache will be set by NetworkProcess::platformSetCacheModel(). @@ -87,7 +91,6 @@ void NetworkProcess::platformInitializeNetworkProcess(const NetworkProcessCreati soup_cache_set_max_size(soupCache.get(), G_MAXUINT); soup_cache_load(soupCache.get()); soup_cache_set_max_size(soupCache.get(), initialMaxSize); -#endif if (!parameters.cookiePersistentStoragePath.isEmpty()) { supplement<WebCookieManager>()->setCookiePersistentStorage(parameters.cookiePersistentStoragePath, @@ -106,32 +109,22 @@ void NetworkProcess::platformSetCacheModel(CacheModel cacheModel) unsigned cacheTotalCapacity = 0; unsigned cacheMinDeadCapacity = 0; unsigned cacheMaxDeadCapacity = 0; - auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 }; + double deadDecodedDataDeletionInterval = 0; unsigned pageCacheCapacity = 0; unsigned long urlCacheMemoryCapacity = 0; unsigned long urlCacheDiskCapacity = 0; -#if ENABLE(NETWORK_CACHE) - uint64_t diskFreeSize = WebCore::getVolumeFreeSizeForPath(m_diskCacheDirectory.utf8().data()) / WTF::MB; -#else SoupCache* cache = SoupNetworkSession::defaultSession().cache(); - uint64_t diskFreeSize = getCacheDiskFreeSize(cache) / WTF::MB; -#endif + uint64_t diskFreeSize = getCacheDiskFreeSize(cache) / 1024 / 1024; - uint64_t memSize = WTF::ramSize() / WTF::MB; + uint64_t memSize = getMemorySize(); calculateCacheSizes(cacheModel, memSize, diskFreeSize, cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, pageCacheCapacity, urlCacheMemoryCapacity, urlCacheDiskCapacity); -#if ENABLE(NETWORK_CACHE) - auto& networkCache = NetworkCache::singleton(); - if (networkCache.isEnabled()) - networkCache.setCapacity(urlCacheDiskCapacity); -#else if (urlCacheDiskCapacity > soup_cache_get_max_size(cache)) soup_cache_set_max_size(cache, urlCacheDiskCapacity); -#endif } void NetworkProcess::setIgnoreTLSErrors(bool ignoreTLSErrors) @@ -149,18 +142,7 @@ void NetworkProcess::clearCacheForAllOrigins(uint32_t cachesToClear) if (cachesToClear == InMemoryResourceCachesOnly) return; - clearDiskCache(std::chrono::system_clock::time_point::min(), [] { }); -} - -void NetworkProcess::clearDiskCache(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler) -{ -#if ENABLE(NETWORK_CACHE) - NetworkCache::singleton().clear(modifiedSince, WTFMove(completionHandler)); -#else - UNUSED_PARAM(modifiedSince); - UNUSED_PARAM(completionHandler); soup_cache_clear(SoupNetworkSession::defaultSession().cache()); -#endif } void NetworkProcess::platformTerminate() @@ -169,3 +151,5 @@ void NetworkProcess::platformTerminate() } } // namespace WebKit + +#endif diff --git a/Source/WebKit2/NetworkProcess/Downloads/gtk/DownloadSoupErrorsGtk.cpp b/Source/WebKit2/NetworkProcess/soup/NetworkResourceLoadSchedulerSoup.cpp index ba2e7b456..9d03979e3 100644 --- a/Source/WebKit2/NetworkProcess/Downloads/gtk/DownloadSoupErrorsGtk.cpp +++ b/Source/WebKit2/NetworkProcess/soup/NetworkResourceLoadSchedulerSoup.cpp @@ -1,5 +1,6 @@ /* - * Copyright (C) 2012 Intel Corporation. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013 Company 100 Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,23 +25,25 @@ */ #include "config.h" -#include "DownloadSoupErrors.h" +#if ENABLE(NETWORK_PROCESS) -#include <WebCore/ErrorsGtk.h> -#include <WebCore/ResourceError.h> - -using namespace WebCore; +#include "NetworkResourceLoadScheduler.h" namespace WebKit { -ResourceError platformDownloadNetworkError(int errorCode, const URL& failingURL, const String& localizedDescription) +void NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost() { - return downloadNetworkError(ResourceError(errorDomainDownload, errorCode, failingURL, localizedDescription)); -} + // Soup has its own queue control; it wants to have all requests given to + // it, so that it is able to look ahead, and schedule them in a good way. + // See the comment in ResourceRequestSoup.cpp + static const unsigned unlimitedConnectionCount = 10000; -ResourceError platformDownloadDestinationError(const ResourceResponse& response, const String& message) -{ - return downloadDestinationError(response, message); + // FIXME: Take advantage of Web-platform specific knowledge that can help + // prioritization better than libsoup alone can do. + // See https://bugs.webkit.org/show_bug.cgi?id=110115#c13 + m_maxRequestsInFlightPerHost = unlimitedConnectionCount; } } // namespace WebKit + +#endif diff --git a/Source/WebKit2/NetworkProcess/soup/RemoteNetworkingContextSoup.cpp b/Source/WebKit2/NetworkProcess/soup/RemoteNetworkingContextSoup.cpp index 6aecb7fbf..d7cf86efb 100644 --- a/Source/WebKit2/NetworkProcess/soup/RemoteNetworkingContextSoup.cpp +++ b/Source/WebKit2/NetworkProcess/soup/RemoteNetworkingContextSoup.cpp @@ -26,6 +26,7 @@ */ #include "config.h" +#if ENABLE(NETWORK_PROCESS) #include "RemoteNetworkingContext.h" #include <WebCore/NetworkStorageSession.h> @@ -45,7 +46,7 @@ bool RemoteNetworkingContext::isValid() const return true; } -void RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID) +void RemoteNetworkingContext::ensurePrivateBrowsingSession(uint64_t sessionID) { notImplemented(); } @@ -56,3 +57,5 @@ NetworkStorageSession& RemoteNetworkingContext::storageSession() const } } + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/gtk/NetworkProcessMainGtk.cpp b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.cpp index 55b9ccf93..84dc636db 100644 --- a/Source/WebKit2/NetworkProcess/gtk/NetworkProcessMainGtk.cpp +++ b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Igalia S.L. + * Copyright (C) 2013 Apple Inc. All rights reserved. * Copyright (C) 2013 Company 100 Inc. * * Redistribution and use in source and binary forms, with or without @@ -27,27 +27,73 @@ #include "config.h" #include "NetworkProcessMainUnix.h" -#include "ChildProcessMain.h" -#include "NetworkProcess.h" +#if ENABLE(NETWORK_PROCESS) + +#include "WKBase.h" +#include "WebKit2Initialize.h" #include <WebCore/SoupNetworkSession.h> +#include <WebKit2/NetworkProcess.h> +#include <runtime/InitializeThreading.h> +#include <stdlib.h> +#include <wtf/MainThread.h> +#include <wtf/RunLoop.h> +#include <wtf/gobject/GRefPtr.h> + +#if PLATFORM(EFL) +#include <Ecore.h> +#endif + +#if USE(SOUP) #include <libsoup/soup.h> +#endif using namespace WebCore; namespace WebKit { -class NetworkProcessMain final: public ChildProcessMainBase { -public: - bool platformInitialize() override - { - SoupNetworkSession::defaultSession().setSSLPolicy(SoupNetworkSession::SSLUseSystemCAFile); - return true; +WK_EXPORT int NetworkProcessMain(int argc, char* argv[]) +{ + if (argc != 2) + return 1; + +#if PLATFORM(EFL) + if (!ecore_init()) + return 1; + + if (!ecore_main_loop_glib_integrate()) + return 1; +#endif + + InitializeWebKit2(); + + SoupNetworkSession::defaultSession().setupHTTPProxyFromEnvironment(); + + int socket = atoi(argv[1]); + + WebKit::ChildProcessInitializationParameters parameters; + parameters.connectionIdentifier = int(socket); + + NetworkProcess::shared().initialize(parameters); + +#if USE(SOUP) + // Despite using system CAs to validate certificates we're + // accepting invalid certificates by default. New API will be + // added later to let client accept/discard invalid certificates. + SoupNetworkSession::defaultSession().setSSLPolicy(SoupNetworkSession::SSLUseSystemCAFile); +#endif + + RunLoop::run(); + +#if USE(SOUP) + if (SoupCache* soupCache = SoupNetworkSession::defaultSession().cache()) { + soup_cache_flush(soupCache); + soup_cache_dump(soupCache); } -}; +#endif -int NetworkProcessMainUnix(int argc, char** argv) -{ - return ChildProcessMain<NetworkProcess, NetworkProcessMain>(argc, argv); + return 0; } } // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h index fa064c358..cb62eda2d 100644 --- a/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h +++ b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h @@ -27,13 +27,15 @@ #ifndef NetworkProcessMainUnix_h #define NetworkProcessMainUnix_h -#include <WebKit/WKBase.h> +#include <WebKit2/WKBase.h> namespace WebKit { +#ifdef __cplusplus extern "C" { -WK_EXPORT int NetworkProcessMainUnix(int argc, char** argv); -} +WK_EXPORT int NetworkProcessMain(int argc, char* argv[]); +} // extern "C" +#endif // __cplusplus } // namespace WebKit |
