diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebKit2/NetworkProcess | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebKit2/NetworkProcess')
37 files changed, 2625 insertions, 751 deletions
diff --git a/Source/WebKit2/NetworkProcess/Info.plist b/Source/WebKit2/NetworkProcess/EntryPoint/mac/LegacyProcess/Info.plist index ca50b3cab..45905e5a6 100644 --- a/Source/WebKit2/NetworkProcess/Info.plist +++ b/Source/WebKit2/NetworkProcess/EntryPoint/mac/LegacyProcess/Info.plist @@ -5,7 +5,7 @@ <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleGetInfoString</key> - <string>${BUNDLE_VERSION}, Copyright 2003-2012 Apple Inc.</string> + <string>${BUNDLE_VERSION}, Copyright 2003-2013 Apple Inc.</string> <key>CFBundleIdentifier</key> <string>com.apple.WebKit.${PRODUCT_NAME}</string> <key>CFBundleInfoDictionaryVersion</key> @@ -26,5 +26,9 @@ <true/> <key>NSPrincipalClass</key> <string>NSApplication</string> + <key>CFBundleIconFile</key> + <string>${APP_ICON}</string> + <key>WebKitEntryPoint</key> + <string>NetworkProcessMain</string> </dict> </plist> diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessMain.h b/Source/WebKit2/NetworkProcess/EntryPoint/mac/LegacyProcess/NetworkProcessMain.mm index ee55a37d6..87b9e4000 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcessMain.h +++ b/Source/WebKit2/NetworkProcess/EntryPoint/mac/LegacyProcess/NetworkProcessMain.mm @@ -23,19 +23,21 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NetworkProcessMain_h -#define NetworkProcessMain_h +#import "config.h" #if ENABLE(NETWORK_PROCESS) -namespace WebKit { - -class CommandLine; +#import "ChildProcessEntryPoint.h" +#import "NetworkProcess.h" +#import "WKBase.h" -int NetworkProcessMain(const CommandLine&); - -} // namespace WebKit +using namespace WebKit; -#endif // ENABLE(NETWORK_PROCESS) +extern "C" WK_EXPORT int NetworkProcessMain(int argc, char** argv); + +int NetworkProcessMain(int argc, char** argv) +{ + return ChildProcessMain<NetworkProcess, ChildProcessMainDelegate>(argc, argv); +} -#endif // NetworkProcessMain_h +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService.Development/Info.plist b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService.Development/Info.plist new file mode 100644 index 000000000..c73c3d3bb --- /dev/null +++ b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService.Development/Info.plist @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleGetInfoString</key> + <string>${BUNDLE_VERSION}, Copyright 2003-2013 Apple Inc.</string> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>com.apple.WebKit.Networking.Development</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>XPC!</string> + <key>CFBundleShortVersionString</key> + <string>${SHORT_VERSION_STRING}</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${BUNDLE_VERSION}</string> + <key>LSFileQuarantineEnabled</key> + <true/> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>WebKitEntryPoint</key> + <string>NetworkServiceInitializer</string> + <key>LSUIElement</key> + <true/> + <key>XPCService</key> + <dict> + <key>ServiceType</key> + <string>Application</string> + <key>JoinExistingSession</key> + <true/> + <key>RunLoopType</key> + <string>NSRunLoop</string> + <key>_MultipleInstances</key> + <true/> + </dict> +</dict> +</plist> diff --git a/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService/Info.plist b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService/Info.plist new file mode 100644 index 000000000..ac5e4e522 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkService/Info.plist @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleGetInfoString</key> + <string>${BUNDLE_VERSION}, Copyright 2003-2013 Apple Inc.</string> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>com.apple.WebKit.Networking</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>XPC!</string> + <key>CFBundleShortVersionString</key> + <string>${SHORT_VERSION_STRING}</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>${BUNDLE_VERSION}</string> + <key>LSFileQuarantineEnabled</key> + <true/> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>WebKitEntryPoint</key> + <string>NetworkServiceInitializer</string> + <key>LSUIElement</key> + <true/> + <key>XPCService</key> + <dict> + <key>ServiceType</key> + <string>Application</string> + <key>JoinExistingSession</key> + <true/> + <key>RunLoopType</key> + <string>NSRunLoop</string> + <key>_MultipleInstances</key> + <true/> + <key>EnvironmentVariables</key> + <dict> + <key>DYLD_INSERT_LIBRARIES</key> + <string>$(WEBKIT2_FRAMEWORKS_DIR)/WebKit2.framework/NetworkProcess.app/Contents/MacOS/SecItemShim.dylib</string> + </dict> + </dict> +</dict> +</plist> diff --git a/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm new file mode 100644 index 000000000..1c6ab641a --- /dev/null +++ b/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#import "config.h" + +#if HAVE(XPC) + +#import "EnvironmentUtilities.h" +#import "NetworkProcess.h" +#import "WKBase.h" +#import "XPCServiceEntryPoint.h" + +using namespace WebKit; + +extern "C" WK_EXPORT void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage); + +void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage) +{ + // Remove the SecItemShim from the DYLD_INSERT_LIBRARIES environment variable so any processes spawned by + // the this process don't try to insert the shim and crash. + EnvironmentUtilities::stripValuesEndingWithString("DYLD_INSERT_LIBRARIES", "/SecItemShim.dylib"); + + XPCServiceInitializer<NetworkProcess, XPCServiceInitializerDelegate>(connection, initializerMessage); +} + +#endif // HAVE(XPC) diff --git a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp new file mode 100644 index 000000000..1e60d401b --- /dev/null +++ b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.cpp @@ -0,0 +1,117 @@ +/* + * 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 "NetworkBlobRegistry.h" + +#if ENABLE(BLOB) && ENABLE(NETWORK_PROCESS) + +#include "SandboxExtension.h" +#include <WebCore/BlobRegistryImpl.h> +#include <wtf/MainThread.h> + +using namespace WebCore; + +namespace WebKit { + +NetworkBlobRegistry& NetworkBlobRegistry::shared() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(NetworkBlobRegistry, registry, ()); + return registry; +} + +NetworkBlobRegistry::NetworkBlobRegistry() +{ +} + +void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const KURL& url, PassOwnPtr<BlobData> data, const Vector<RefPtr<SandboxExtension>>& newSandboxExtensions) +{ + 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())); + } + + blobRegistry().registerBlobURL(url, data); + + if (!sandboxExtensions.isEmpty()) + m_sandboxExtensions.add(url.string(), sandboxExtensions); + + 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<KURL>()).iterator; + mapIterator->value.add(url); +} + +void NetworkBlobRegistry::registerBlobURL(NetworkConnectionToWebProcess* connection, const WebCore::KURL& url, const WebCore::KURL& srcURL) +{ + 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(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::KURL& url) +{ + blobRegistry().unregisterBlobURL(url); + m_sandboxExtensions.remove(url.string()); + + 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) +{ + if (!m_blobsForConnection.contains(connection)) + return; + + HashSet<KURL>& blobsForConnection = m_blobsForConnection.find(connection)->value; + for (HashSet<KURL>::iterator iter = blobsForConnection.begin(), end = blobsForConnection.end(); iter != end; ++iter) { + blobRegistry().unregisterBlobURL(*iter); + m_sandboxExtensions.remove(*iter); + } + + m_blobsForConnection.remove(connection); +} + +const Vector<RefPtr<SandboxExtension>> NetworkBlobRegistry::sandboxExtensions(const WebCore::KURL& url) +{ + return m_sandboxExtensions.get(url.string()); +} + +} + +#endif diff --git a/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h new file mode 100644 index 000000000..6d71bbfc9 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/FileAPI/NetworkBlobRegistry.h @@ -0,0 +1,72 @@ +/* + * 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 NetworkBlobRegistry_h +#define NetworkBlobRegistry_h + +#if ENABLE(BLOB) && ENABLE(NETWORK_PROCESS) + +#include <WebCore/KURLHash.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> + +namespace WebCore { +class BlobData; +} + +namespace WebKit { + +class NetworkConnectionToWebProcess; +class SandboxExtension; + +class NetworkBlobRegistry { +WTF_MAKE_NONCOPYABLE(NetworkBlobRegistry); +public: + NetworkBlobRegistry(); + static NetworkBlobRegistry& shared(); + + void registerBlobURL(NetworkConnectionToWebProcess*, const WebCore::KURL&, PassOwnPtr<WebCore::BlobData>, const Vector<RefPtr<SandboxExtension>>&); + void registerBlobURL(NetworkConnectionToWebProcess*, const WebCore::KURL&, const WebCore::KURL& srcURL); + void unregisterBlobURL(NetworkConnectionToWebProcess*, const WebCore::KURL&); + + void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*); + + const Vector<RefPtr<SandboxExtension>> sandboxExtensions(const WebCore::KURL&); + +private: + ~NetworkBlobRegistry(); + + typedef HashMap<String, Vector<RefPtr<SandboxExtension>>> SandboxExtensionMap; + SandboxExtensionMap m_sandboxExtensions; + + typedef HashMap<NetworkConnectionToWebProcess*, HashSet<WebCore::KURL>> 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 index 7bc96175f..e7ce34b0b 100644 --- a/Source/WebKit2/NetworkProcess/HostRecord.cpp +++ b/Source/WebKit2/NetworkProcess/HostRecord.cpp @@ -32,6 +32,8 @@ #include "NetworkResourceLoadParameters.h" #include "NetworkResourceLoadScheduler.h" #include "NetworkResourceLoader.h" +#include "SyncNetworkResourceLoader.h" +#include <wtf/MainThread.h> #if ENABLE(NETWORK_PROCESS) @@ -48,46 +50,71 @@ HostRecord::HostRecord(const String& name, int maxRequestsInFlight) HostRecord::~HostRecord() { #ifndef NDEBUG - ASSERT(m_resourceIdentifiersLoading.isEmpty()); + ASSERT(m_loadersInProgress.isEmpty()); for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) ASSERT(m_loadersPending[p].isEmpty()); #endif } -void HostRecord::schedule(PassRefPtr<NetworkResourceLoader> loader) +void HostRecord::scheduleResourceLoader(PassRefPtr<SchedulableLoader> loader) { - m_loadersPending[loader->priority()].append(loader); + ASSERT(isMainThread()); + + loader->setHostRecord(this); + + if (loader->isSynchronous()) + m_syncLoadersPending.append(loader); + else + m_loadersPending[loader->priority()].append(loader); } -void HostRecord::addLoadInProgress(ResourceLoadIdentifier identifier) +void HostRecord::addLoaderInProgress(SchedulableLoader* loader) { - m_resourceIdentifiersLoading.add(identifier); + ASSERT(isMainThread()); + + m_loadersInProgress.add(loader); + loader->setHostRecord(this); } -void HostRecord::remove(ResourceLoadIdentifier identifier) +inline bool removeLoaderFromQueue(SchedulableLoader* loader, LoaderQueue& queue) { - // FIXME (NetworkProcess): Due to IPC race conditions, it's possible this HostRecord will be asked to remove the same identifer twice. - // It would be nice to know the identifier has already been removed and treat it as a no-op. + 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(SchedulableLoader* loader) +{ + ASSERT(isMainThread()); - if (m_resourceIdentifiersLoading.contains(identifier)) { - m_resourceIdentifiersLoading.remove(identifier); + // 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. + + SchedulableLoaderSet::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) { - LoaderQueue::iterator end = m_loadersPending[priority].end(); - for (LoaderQueue::iterator it = m_loadersPending[priority].begin(); it != end; ++it) { - if (it->get()->identifier() == identifier) { - m_loadersPending[priority].remove(it); - return; - } - } + for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) { + if (removeLoaderFromQueue(loader, m_loadersPending[priority])) + return; } } bool HostRecord::hasRequests() const { - if (!m_resourceIdentifiersLoading.isEmpty()) + if (!m_loadersInProgress.isEmpty()) return true; for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) { @@ -98,12 +125,105 @@ bool HostRecord::hasRequests() const return false; } -bool HostRecord::limitRequests(ResourceLoadPriority priority, bool serialLoadingEnabled) const +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<SchedulableLoader> 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) { - if (priority == ResourceLoadPriorityVeryLow && !m_resourceIdentifiersLoading.isEmpty()) + 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, SchedulableLoader* 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; - return m_resourceIdentifiersLoading.size() >= (serialLoadingEnabled ? 1 : m_maxRequestsInFlight); + // 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. + SchedulableLoaderSet::iterator i = m_loadersInProgress.begin(); + SchedulableLoaderSet::iterator end = m_loadersInProgress.end(); + for (; i != end; ++i) { + if (i->get()->isSynchronous()) + break; + } + ASSERT(i != end); +#endif + return true; + } + return false; } } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/HostRecord.h b/Source/WebKit2/NetworkProcess/HostRecord.h index 1b21376de..058208975 100644 --- a/Source/WebKit2/NetworkProcess/HostRecord.h +++ b/Source/WebKit2/NetworkProcess/HostRecord.h @@ -28,36 +28,52 @@ #if ENABLE(NETWORK_PROCESS) -#include <WebCore/ResourceRequest.h> +#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; +class SchedulableLoader; +class SyncNetworkResourceLoader; + +typedef Deque<RefPtr<SchedulableLoader>> LoaderQueue; typedef uint64_t ResourceLoadIdentifier; -class HostRecord { - WTF_MAKE_NONCOPYABLE(HostRecord); WTF_MAKE_FAST_ALLOCATED; +class HostRecord : public RefCounted<HostRecord> { public: - HostRecord(const String& name, int maxRequestsInFlight); + static PassRefPtr<HostRecord> create(const String& name, int maxRequestsInFlight) + { + return adoptRef(new HostRecord(name, maxRequestsInFlight)); + } + ~HostRecord(); const String& name() const { return m_name; } - void schedule(PassRefPtr<NetworkResourceLoader>); - void addLoadInProgress(ResourceLoadIdentifier); - void remove(ResourceLoadIdentifier); + + void scheduleResourceLoader(PassRefPtr<SchedulableLoader>); + void addLoaderInProgress(SchedulableLoader*); + void removeLoader(SchedulableLoader*); bool hasRequests() const; - bool limitRequests(WebCore::ResourceLoadPriority, bool serialLoadingEnabled) const; + void servePendingRequests(WebCore::ResourceLoadPriority); - typedef Deque<RefPtr<NetworkResourceLoader> > LoaderQueue; - LoaderQueue& loadersPending(WebCore::ResourceLoadPriority priority) { return m_loadersPending[priority]; } + uint64_t pendingRequestCount() const; + uint64_t activeLoadCount() const; + +private: + HostRecord(const String& name, int maxRequestsInFlight); + + void servePendingRequestsForQueue(LoaderQueue&, WebCore::ResourceLoadPriority); + bool limitsRequests(WebCore::ResourceLoadPriority, SchedulableLoader*) const; -private: LoaderQueue m_loadersPending[WebCore::ResourceLoadPriorityHighest + 1]; - typedef HashSet<ResourceLoadIdentifier> ResourceLoadIdentifierSet; - ResourceLoadIdentifierSet m_resourceIdentifiersLoading; + LoaderQueue m_syncLoadersPending; + + typedef HashSet<RefPtr<SchedulableLoader>> SchedulableLoaderSet; + SchedulableLoaderSet m_loadersInProgress; const String m_name; int m_maxRequestsInFlight; diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp index f07165107..b21815418 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp @@ -26,10 +26,17 @@ #include "config.h" #include "NetworkConnectionToWebProcess.h" +#include "BlobRegistrationData.h" #include "ConnectionStack.h" +#include "NetworkBlobRegistry.h" +#include "NetworkConnectionToWebProcessMessages.h" #include "NetworkProcess.h" +#include "NetworkResourceLoadParameters.h" #include "NetworkResourceLoader.h" +#include "NetworkResourceLoaderMessages.h" #include "RemoteNetworkingContext.h" +#include "SyncNetworkResourceLoader.h" +#include <WebCore/BlobData.h> #include <WebCore/PlatformCookieJar.h> #include <WebCore/ResourceLoaderOptions.h> #include <WebCore/ResourceRequest.h> @@ -56,42 +63,29 @@ NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(CoreIPC::Connection NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess() { - ASSERT(!m_connection); - ASSERT(m_observers.isEmpty()); -} - -void NetworkConnectionToWebProcess::registerObserver(NetworkConnectionToWebProcessObserver* observer) -{ - ASSERT(!m_observers.contains(observer)); - m_observers.add(observer); -} - -void NetworkConnectionToWebProcess::unregisterObserver(NetworkConnectionToWebProcessObserver* observer) -{ - ASSERT(m_observers.contains(observer)); - m_observers.remove(observer); } -void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder) +void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder) { - if (messageID.is<CoreIPC::MessageClassNetworkConnectionToWebProcess>()) { - didReceiveNetworkConnectionToWebProcessMessage(connection, messageID, decoder); + if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) { + didReceiveNetworkConnectionToWebProcessMessage(connection, decoder); return; } - - if (messageID.is<CoreIPC::MessageClassNetworkResourceLoader>()) { - NetworkResourceLoader* loader = NetworkProcess::shared().networkResourceLoadScheduler().networkResourceLoaderForIdentifier(decoder.destinationID()); - if (loader) - loader->didReceiveNetworkResourceLoaderMessage(connection, messageID, decoder); + + if (decoder.messageReceiverName() == Messages::NetworkResourceLoader::messageReceiverName()) { + HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator loaderIterator = m_networkResourceLoaders.find(decoder.destinationID()); + if (loaderIterator != m_networkResourceLoaders.end()) + loaderIterator->value->didReceiveNetworkResourceLoaderMessage(connection, decoder); return; } + ASSERT_NOT_REACHED(); } -void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& reply) +void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& reply) { - if (messageID.is<CoreIPC::MessageClassNetworkConnectionToWebProcess>()) { - didReceiveSyncNetworkConnectionToWebProcessMessage(connection, messageID, decoder, reply); + if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) { + didReceiveSyncNetworkConnectionToWebProcessMessage(connection, decoder, reply); return; } ASSERT_NOT_REACHED(); @@ -99,39 +93,55 @@ void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* c void NetworkConnectionToWebProcess::didClose(CoreIPC::Connection*) { - // Protect ourself as we might be otherwise be deleted during this function + // Protect ourself as we might be otherwise be deleted during this function. RefPtr<NetworkConnectionToWebProcess> protector(this); + + 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(); + + HashMap<ResourceLoadIdentifier, RefPtr<SyncNetworkResourceLoader>>::iterator syncEnd = m_syncNetworkResourceLoaders.end(); + for (HashMap<ResourceLoadIdentifier, RefPtr<SyncNetworkResourceLoader>>::iterator i = m_syncNetworkResourceLoaders.begin(); i != syncEnd; ++i) + i->value->abort(); + + NetworkBlobRegistry::shared().connectionToWebProcessDidClose(this); + + m_networkResourceLoaders.clear(); NetworkProcess::shared().removeNetworkConnectionToWebProcess(this); - - Vector<NetworkConnectionToWebProcessObserver*> observers; - copyToVector(m_observers, observers); - for (size_t i = 0; i < observers.size(); ++i) - observers[i]->connectionToWebProcessDidClose(this); - - // FIXME (NetworkProcess): We might consider actively clearing out all requests for this connection. - // But that might not be necessary as the observer mechanism used above is much more direct. - - m_connection = 0; } void NetworkConnectionToWebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference, CoreIPC::StringReference) { } -void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters, ResourceLoadIdentifier& resourceLoadIdentifier) +void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters) { - resourceLoadIdentifier = NetworkProcess::shared().networkResourceLoadScheduler().scheduleResourceLoad(loadParameters, this); + RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, this); + m_networkResourceLoaders.add(loadParameters.identifier, loader); + NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get()); } -void NetworkConnectionToWebProcess::addLoadInProgress(const KURL& url, ResourceLoadIdentifier& identifier) +void NetworkConnectionToWebProcess::performSynchronousLoad(const NetworkResourceLoadParameters& loadParameters, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) { - identifier = NetworkProcess::shared().networkResourceLoadScheduler().addLoadInProgress(url); + RefPtr<SyncNetworkResourceLoader> loader = SyncNetworkResourceLoader::create(loadParameters, this, reply); + m_syncNetworkResourceLoaders.add(loadParameters.identifier, loader); + NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get()); } void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier) { - NetworkProcess::shared().networkResourceLoadScheduler().removeLoadIdentifier(identifier); + RefPtr<SchedulableLoader> loader = m_networkResourceLoaders.take(identifier); + if (!loader) + loader = m_syncNetworkResourceLoaders.take(identifier); + + // It's possible we have no loader for this identifier if the NetworkProcess crashed and this was a respawned NetworkProcess. + if (!loader) + return; + + // 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(); } void NetworkConnectionToWebProcess::servePendingRequests(uint32_t resourceLoadPriority) @@ -139,75 +149,95 @@ void NetworkConnectionToWebProcess::servePendingRequests(uint32_t resourceLoadPr NetworkProcess::shared().networkResourceLoadScheduler().servePendingRequests(static_cast<ResourceLoadPriority>(resourceLoadPriority)); } -void NetworkConnectionToWebProcess::suspendPendingRequests() +void NetworkConnectionToWebProcess::setSerialLoadingEnabled(bool enabled) { - NetworkProcess::shared().networkResourceLoadScheduler().suspendPendingRequests(); + m_serialLoadingEnabled = enabled; } -void NetworkConnectionToWebProcess::resumePendingRequests() +static NetworkStorageSession& storageSession(bool privateBrowsingEnabled) { - NetworkProcess::shared().networkResourceLoadScheduler().resumePendingRequests(); + if (privateBrowsingEnabled) { + NetworkStorageSession* privateSession = RemoteNetworkingContext::privateBrowsingSession(); + 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."); + } + return NetworkStorageSession::defaultStorageSession(); } -void NetworkConnectionToWebProcess::setSerialLoadingEnabled(bool enabled) +void NetworkConnectionToWebProcess::startDownload(bool privateBrowsingEnabled, uint64_t downloadID, const ResourceRequest& request) { - m_serialLoadingEnabled = enabled; + // FIXME: Do something with the private browsing flag. + NetworkProcess::shared().downloadManager().startDownload(downloadID, request); } -void NetworkConnectionToWebProcess::cookiesForDOM(const KURL& firstParty, const KURL& url, String& result) +void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, const ResourceRequest& request, const ResourceResponse& response) { - // FIXME (NetworkProcess): Use a correct storage session. - result = WebCore::cookiesForDOM(RemoteNetworkingContext::create(false, false).get(), firstParty, url); + if (!mainResourceLoadIdentifier) { + NetworkProcess::shared().downloadManager().startDownload(downloadID, request); + return; + } + + NetworkResourceLoader* loader = m_networkResourceLoaders.get(mainResourceLoadIdentifier); + NetworkProcess::shared().downloadManager().convertHandleToDownload(downloadID, loader->handle(), request, response); + + // Unblock the URL connection operation queue. + loader->handle()->continueDidReceiveResponse(); + + loader->didConvertHandleToDownload(); +} + +void NetworkConnectionToWebProcess::cookiesForDOM(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, String& result) +{ + result = WebCore::cookiesForDOM(storageSession(privateBrowsingEnabled), firstParty, url); } -void NetworkConnectionToWebProcess::setCookiesFromDOM(const KURL& firstParty, const KURL& url, const String& cookieString) +void NetworkConnectionToWebProcess::setCookiesFromDOM(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, const String& cookieString) { - // FIXME (NetworkProcess): Use a correct storage session. - WebCore::setCookiesFromDOM(RemoteNetworkingContext::create(false, false).get(), firstParty, url, cookieString); + WebCore::setCookiesFromDOM(storageSession(privateBrowsingEnabled), firstParty, url, cookieString); } -void NetworkConnectionToWebProcess::cookiesEnabled(const KURL& firstParty, const KURL& url, bool& result) +void NetworkConnectionToWebProcess::cookiesEnabled(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, bool& result) { - // FIXME (NetworkProcess): Use a correct storage session. - result = WebCore::cookiesEnabled(RemoteNetworkingContext::create(false, false).get(), firstParty, url); + result = WebCore::cookiesEnabled(storageSession(privateBrowsingEnabled), firstParty, url); } -void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(const KURL& firstParty, const KURL& url, String& result) +void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, String& result) { - // FIXME (NetworkProcess): Use a correct storage session. - result = WebCore::cookieRequestHeaderFieldValue(0, firstParty, url); + result = WebCore::cookieRequestHeaderFieldValue(storageSession(privateBrowsingEnabled), firstParty, url); } -void NetworkConnectionToWebProcess::getRawCookies(const KURL& firstParty, const KURL& url, Vector<Cookie>& result) +void NetworkConnectionToWebProcess::getRawCookies(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, Vector<Cookie>& result) { - // FIXME (NetworkProcess): Use a correct storage session. - WebCore::getRawCookies(RemoteNetworkingContext::create(false, false).get(), firstParty, url, result); + WebCore::getRawCookies(storageSession(privateBrowsingEnabled), firstParty, url, result); } -void NetworkConnectionToWebProcess::deleteCookie(const KURL& url, const String& cookieName) +void NetworkConnectionToWebProcess::deleteCookie(bool privateBrowsingEnabled, const KURL& url, const String& cookieName) { - // FIXME (NetworkProcess): Use a correct storage session. - WebCore::deleteCookie(RemoteNetworkingContext::create(false, false).get(), url, cookieName); + WebCore::deleteCookie(storageSession(privateBrowsingEnabled), url, cookieName); } -void NetworkConnectionToWebProcess::getHostnamesWithCookies(Vector<String>& hostnames) +void NetworkConnectionToWebProcess::registerBlobURL(const KURL& url, const BlobRegistrationData& data) { - // FIXME (NetworkProcess): Use a correct storage session. - HashSet<String> hostnamesSet; - WebCore::getHostnamesWithCookies(RemoteNetworkingContext::create(false, false).get(), hostnamesSet); - WTF::copyToVector(hostnamesSet, hostnames); + 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); + } + + NetworkBlobRegistry::shared().registerBlobURL(this, url, data.releaseData(), extensions); } -void NetworkConnectionToWebProcess::deleteCookiesForHostname(const String& hostname) +void NetworkConnectionToWebProcess::registerBlobURLFromURL(const KURL& url, const KURL& srcURL) { - // FIXME (NetworkProcess): Use a correct storage session. - WebCore::deleteCookiesForHostname(RemoteNetworkingContext::create(false, false).get(), hostname); + NetworkBlobRegistry::shared().registerBlobURL(this, url, srcURL); } -void NetworkConnectionToWebProcess::deleteAllCookies() +void NetworkConnectionToWebProcess::unregisterBlobURL(const KURL& url) { - // FIXME (NetworkProcess): Use a correct storage session. - WebCore::deleteAllCookies(RemoteNetworkingContext::create(false, false).get()); + NetworkBlobRegistry::shared().unregisterBlobURL(this, url); } } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h index 042a7dd00..e63215812 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h @@ -28,6 +28,7 @@ #if ENABLE(NETWORK_PROCESS) +#include "BlockingResponseMap.h" #include "Connection.h" #include "NetworkConnectionToWebProcessMessages.h" #include <WebCore/ResourceLoadPriority.h> @@ -40,24 +41,18 @@ class ResourceRequest; namespace WebKit { +class BlobRegistrationData; class NetworkConnectionToWebProcess; +class NetworkResourceLoader; +class SyncNetworkResourceLoader; typedef uint64_t ResourceLoadIdentifier; -class NetworkConnectionToWebProcessObserver { -public: - virtual ~NetworkConnectionToWebProcessObserver() { } - virtual void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*) = 0; -}; - class NetworkConnectionToWebProcess : public RefCounted<NetworkConnectionToWebProcess>, CoreIPC::Connection::Client { public: static PassRefPtr<NetworkConnectionToWebProcess> create(CoreIPC::Connection::Identifier); virtual ~NetworkConnectionToWebProcess(); CoreIPC::Connection* connection() const { return m_connection.get(); } - - void registerObserver(NetworkConnectionToWebProcessObserver*); - void unregisterObserver(NetworkConnectionToWebProcessObserver*); bool isSerialLoadingEnabled() const { return m_serialLoadingEnabled; } @@ -65,37 +60,41 @@ private: NetworkConnectionToWebProcess(CoreIPC::Connection::Identifier); // CoreIPC::Connection::Client - virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); - virtual void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); + virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); + virtual void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); virtual void didClose(CoreIPC::Connection*); virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference messageReceiverName, CoreIPC::StringReference messageName); // Message handlers. - void didReceiveNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); - void didReceiveSyncNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); + void didReceiveNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); + void didReceiveSyncNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); - void scheduleResourceLoad(const NetworkResourceLoadParameters&, ResourceLoadIdentifier&); - void addLoadInProgress(const WebCore::KURL&, ResourceLoadIdentifier&); + void scheduleResourceLoad(const NetworkResourceLoadParameters&); + void performSynchronousLoad(const NetworkResourceLoadParameters&, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>); + void removeLoadIdentifier(ResourceLoadIdentifier); void crossOriginRedirectReceived(ResourceLoadIdentifier, const WebCore::KURL& redirectURL); void servePendingRequests(uint32_t resourceLoadPriority); - void suspendPendingRequests(); - void resumePendingRequests(); void setSerialLoadingEnabled(bool); - void cookiesForDOM(const WebCore::KURL& firstParty, const WebCore::KURL&, String& result); - void setCookiesFromDOM(const WebCore::KURL& firstParty, const WebCore::KURL&, const String&); - void cookiesEnabled(const WebCore::KURL& firstParty, const WebCore::KURL&, bool& result); - void cookieRequestHeaderFieldValue(const WebCore::KURL& firstParty, const WebCore::KURL&, String& result); - void getRawCookies(const WebCore::KURL& firstParty, const WebCore::KURL&, Vector<WebCore::Cookie>&); - void deleteCookie(const WebCore::KURL&, const String& cookieName); - void getHostnamesWithCookies(Vector<String>& hostnames); - void deleteCookiesForHostname(const String& hostname); - void deleteAllCookies(); + void startDownload(bool privateBrowsingEnabled, uint64_t downloadID, const WebCore::ResourceRequest&); + void convertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + + void cookiesForDOM(bool privateBrowsingEnabled, const WebCore::KURL& firstParty, const WebCore::KURL&, String& result); + void setCookiesFromDOM(bool privateBrowsingEnabled, const WebCore::KURL& firstParty, const WebCore::KURL&, const String&); + void cookiesEnabled(bool privateBrowsingEnabled, const WebCore::KURL& firstParty, const WebCore::KURL&, bool& result); + void cookieRequestHeaderFieldValue(bool privateBrowsingEnabled, const WebCore::KURL& firstParty, const WebCore::KURL&, String& result); + void getRawCookies(bool privateBrowsingEnabled, const WebCore::KURL& firstParty, const WebCore::KURL&, Vector<WebCore::Cookie>&); + void deleteCookie(bool privateBrowsingEnabled, const WebCore::KURL&, const String& cookieName); + + void registerBlobURL(const WebCore::KURL&, const BlobRegistrationData&); + void registerBlobURLFromURL(const WebCore::KURL&, const WebCore::KURL& srcURL); + void unregisterBlobURL(const WebCore::KURL&); RefPtr<CoreIPC::Connection> m_connection; - - HashSet<NetworkConnectionToWebProcessObserver*> m_observers; - + + HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>> m_networkResourceLoaders; + HashMap<ResourceLoadIdentifier, RefPtr<SyncNetworkResourceLoader>> m_syncNetworkResourceLoaders; + bool m_serialLoadingEnabled; }; diff --git a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in index d6c5f65b8..afae1a230 100644 --- a/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in @@ -22,32 +22,29 @@ #if ENABLE(NETWORK_PROCESS) -messages -> NetworkConnectionToWebProcess { +messages -> NetworkConnectionToWebProcess LegacyReceiver { - // FIXME (NetworkProcess): At least some of these synchronous messages are synchronous due to the requirement - // that we synchronously get an identifier for new ResourceLoaders as they are created. - // There's possible ResourceLoader identifier refactoring that can remove that requirement. - // We might also have the NetworkProcess divvy up identifiers in blocks to each WebProcess beforehand. - ScheduleResourceLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) -> (uint64_t resourceLoadIdentifier) - AddLoadInProgress(WebCore::KURL url) -> (uint64_t resourceLoadIdentifier) + ScheduleResourceLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) + PerformSynchronousLoad(WebKit::NetworkResourceLoadParameters resourceLoadParameters) -> (WebCore::ResourceError error, WebCore::ResourceResponse response, CoreIPC::DataReference data) Delayed RemoveLoadIdentifier(uint64_t resourceLoadIdentifier) ServePendingRequests(uint32_t resourceLoadPriority) - - SuspendPendingRequests() -> () - ResumePendingRequests() -> () SetSerialLoadingEnabled(bool enabled) -> () - CookiesForDOM(WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::String result) - SetCookiesFromDOM(WebCore::KURL firstParty, WebCore::KURL url, WTF::String cookieString) - CookiesEnabled(WebCore::KURL firstParty, WebCore::KURL url) -> (bool enabled) - CookieRequestHeaderFieldValue(WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::String result) - GetRawCookies(WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::Vector<WebCore::Cookie> cookies) - DeleteCookie(WebCore::KURL url, WTF::String cookieName) - GetHostnamesWithCookies() -> (WTF::Vector<WTF::String> hostnames) - DeleteCookiesForHostname(WTF::String hostname) - DeleteAllCookies() + StartDownload(bool privateBrowsingEnabled, uint64_t downloadID, WebCore::ResourceRequest request) + ConvertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, WebCore::ResourceRequest request, WebCore::ResourceResponse response) + + CookiesForDOM(bool privateBrowsingEnabled, WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::String result) + SetCookiesFromDOM(bool privateBrowsingEnabled, WebCore::KURL firstParty, WebCore::KURL url, WTF::String cookieString) + CookiesEnabled(bool privateBrowsingEnabled, WebCore::KURL firstParty, WebCore::KURL url) -> (bool enabled) + CookieRequestHeaderFieldValue(bool privateBrowsingEnabled, WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::String result) + GetRawCookies(bool privateBrowsingEnabled, WebCore::KURL firstParty, WebCore::KURL url) -> (WTF::Vector<WebCore::Cookie> cookies) + DeleteCookie(bool privateBrowsingEnabled, WebCore::KURL url, WTF::String cookieName) + + RegisterBlobURL(WebCore::KURL url, WebKit::BlobRegistrationData data) + RegisterBlobURLFromURL(WebCore::KURL url, WebCore::KURL srcURL) + UnregisterBlobURL(WebCore::KURL url) } #endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.cpp b/Source/WebKit2/NetworkProcess/NetworkProcess.cpp index 634333559..917ddc5c1 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.cpp @@ -30,12 +30,27 @@ #include "ArgumentCoders.h" #include "Attachment.h" +#include "AuthenticationManager.h" +#include "CustomProtocolManager.h" +#include "Logging.h" #include "NetworkConnectionToWebProcess.h" +#include "NetworkProcessCreationParameters.h" +#include "NetworkProcessPlatformStrategies.h" #include "NetworkProcessProxyMessages.h" +#include "RemoteNetworkingContext.h" +#include "SchedulableLoader.h" +#include "StatisticsData.h" +#include "WebContextMessages.h" +#include "WebCookieManager.h" +#include <WebCore/InitializeLogging.h> #include <WebCore/ResourceRequest.h> #include <WebCore/RunLoop.h> #include <wtf/text/CString.h> +#if USE(SECURITY_FRAMEWORK) +#include "SecItemShim.h" +#endif + using namespace WebCore; namespace WebKit { @@ -47,20 +62,32 @@ NetworkProcess& NetworkProcess::shared() } NetworkProcess::NetworkProcess() + : m_hasSetCacheModel(false) + , m_cacheModel(CacheModelDocumentViewer) +#if PLATFORM(MAC) + , m_clearCacheDispatchGroup(0) +#endif { + NetworkProcessPlatformStrategies::initialize(); + + addSupplement<AuthenticationManager>(); + addSupplement<WebCookieManager>(); + addSupplement<CustomProtocolManager>(); } NetworkProcess::~NetworkProcess() { } -void NetworkProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, WebCore::RunLoop* runLoop) +AuthenticationManager& NetworkProcess::authenticationManager() { - ASSERT(!m_uiConnection); + return *supplement<AuthenticationManager>(); +} - m_uiConnection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop); - m_uiConnection->setDidCloseOnConnectionWorkQueueCallback(didCloseOnConnectionWorkQueue); - m_uiConnection->open(); +DownloadManager& NetworkProcess::downloadManager() +{ + DEFINE_STATIC_LOCAL(DownloadManager, downloadManager, (this)); + return downloadManager; } void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection) @@ -73,17 +100,26 @@ void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebP bool NetworkProcess::shouldTerminate() { - return true; + // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive). + return false; } -void NetworkProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder) +void NetworkProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder) { - didReceiveNetworkProcessMessage(connection, messageID, decoder); + if (messageReceiverMap().dispatchMessage(connection, decoder)) + return; + + didReceiveNetworkProcessMessage(connection, decoder); +} + +void NetworkProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder) +{ + messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder); } void NetworkProcess::didClose(CoreIPC::Connection*) { - // The UIProcess just crashed. + // The UIProcess just exited. RunLoop::current()->stop(); } @@ -92,13 +128,57 @@ void NetworkProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::Str RunLoop::current()->stop(); } -void NetworkProcess::syncMessageSendTimedOut(CoreIPC::Connection*) +void NetworkProcess::didCreateDownload() +{ + disableTermination(); +} + +void NetworkProcess::didDestroyDownload() +{ + enableTermination(); +} + +CoreIPC::Connection* NetworkProcess::downloadProxyConnection() { + return parentProcessConnection(); +} + +AuthenticationManager& NetworkProcess::downloadsAuthenticationManager() +{ + return authenticationManager(); } void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters) { - platformInitialize(parameters); + platformInitializeNetworkProcess(parameters); + + setCacheModel(static_cast<uint32_t>(parameters.cacheModel)); + +#if PLATFORM(MAC) || USE(CFNETWORK) + RemoteNetworkingContext::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier); +#endif + + if (parameters.privateBrowsingEnabled) + RemoteNetworkingContext::ensurePrivateBrowsingSession(); + + NetworkProcessSupplementMap::const_iterator it = m_supplements.begin(); + NetworkProcessSupplementMap::const_iterator end = m_supplements.end(); + for (; it != end; ++it) + it->value->initialize(parameters); +} + +void NetworkProcess::initializeConnection(CoreIPC::Connection* connection) +{ + ChildProcess::initializeConnection(connection); + +#if USE(SECURITY_FRAMEWORK) + SecItemShim::shared().initializeConnection(connection); +#endif + + NetworkProcessSupplementMap::const_iterator it = m_supplements.begin(); + NetworkProcessSupplementMap::const_iterator end = m_supplements.end(); + for (; it != end; ++it) + it->value->initializeConnection(connection); } void NetworkProcess::createNetworkConnectionToWebProcess() @@ -113,12 +193,79 @@ void NetworkProcess::createNetworkConnectionToWebProcess() m_webProcessConnections.append(connection.release()); CoreIPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND); - m_uiConnection->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0); + parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0); #else notImplemented(); #endif } +void NetworkProcess::ensurePrivateBrowsingSession() +{ + RemoteNetworkingContext::ensurePrivateBrowsingSession(); +} + +void NetworkProcess::destroyPrivateBrowsingSession() +{ + RemoteNetworkingContext::destroyPrivateBrowsingSession(); +} + +void NetworkProcess::downloadRequest(uint64_t downloadID, const ResourceRequest& request) +{ + downloadManager().startDownload(downloadID, request); +} + +void NetworkProcess::cancelDownload(uint64_t downloadID) +{ + downloadManager().cancelDownload(downloadID); +} + +void NetworkProcess::setCacheModel(uint32_t cm) +{ + CacheModel cacheModel = static_cast<CacheModel>(cm); + + if (!m_hasSetCacheModel || cacheModel != m_cacheModel) { + m_hasSetCacheModel = true; + m_cacheModel = cacheModel; + platformSetCacheModel(cacheModel); + } +} + +void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID) +{ + NetworkResourceLoadScheduler& scheduler = NetworkProcess::shared().networkResourceLoadScheduler(); + + StatisticsData data; + + 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()); + + parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0); +} + +void NetworkProcess::terminate() +{ + platformTerminate(); + ChildProcess::terminate(); +} + +#if !PLATFORM(MAC) +void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&) +{ +} + +void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&) +{ +} + +void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&) +{ +} +#endif + } // namespace WebKit #endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.h b/Source/WebKit2/NetworkProcess/NetworkProcess.h index 66a1185e9..00f4068cf 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.h +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,7 +28,10 @@ #if ENABLE(NETWORK_PROCESS) +#include "CacheModel.h" #include "ChildProcess.h" +#include "DownloadManager.h" +#include "MessageReceiverMap.h" #include "NetworkResourceLoadScheduler.h" #include <wtf/Forward.h> @@ -38,47 +41,98 @@ namespace WebCore { namespace WebKit { +class AuthenticationManager; class NetworkConnectionToWebProcess; +class NetworkProcessSupplement; +class PlatformCertificateInfo; struct NetworkProcessCreationParameters; -class NetworkProcess : ChildProcess { +class NetworkProcess : public ChildProcess, private DownloadManager::Client { WTF_MAKE_NONCOPYABLE(NetworkProcess); public: static NetworkProcess& shared(); - void initialize(CoreIPC::Connection::Identifier, WebCore::RunLoop*); + template <typename T> + T* supplement() + { + return static_cast<T*>(m_supplements.get(T::supplementName())); + } + + template <typename T> + void addSupplement() + { + m_supplements.add(T::supplementName(), adoptPtr<NetworkProcessSupplement>(new T(this))); + } void removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess*); NetworkResourceLoadScheduler& networkResourceLoadScheduler() { return m_networkResourceLoadScheduler; } + AuthenticationManager& authenticationManager(); + DownloadManager& downloadManager(); + private: NetworkProcess(); ~NetworkProcess(); - void platformInitialize(const NetworkProcessCreationParameters&); + void platformInitializeNetworkProcess(const NetworkProcessCreationParameters&); + + virtual void terminate() OVERRIDE; + void platformTerminate(); // ChildProcess - virtual bool shouldTerminate(); + virtual void initializeProcess(const ChildProcessInitializationParameters&) OVERRIDE; + virtual void initializeProcessName(const ChildProcessInitializationParameters&) OVERRIDE; + virtual void initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&) OVERRIDE; + virtual void initializeConnection(CoreIPC::Connection*) OVERRIDE; + virtual bool shouldTerminate() OVERRIDE; // CoreIPC::Connection::Client - virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); - virtual void didClose(CoreIPC::Connection*); - virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference messageReceiverName, CoreIPC::StringReference messageName); - virtual void syncMessageSendTimedOut(CoreIPC::Connection*); + virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&) OVERRIDE; + virtual void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); + virtual void didClose(CoreIPC::Connection*) OVERRIDE; + virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference messageReceiverName, CoreIPC::StringReference messageName) OVERRIDE; + + // DownloadManager::Client + virtual void didCreateDownload() OVERRIDE; + virtual void didDestroyDownload() OVERRIDE; + virtual CoreIPC::Connection* downloadProxyConnection() OVERRIDE; + virtual AuthenticationManager& downloadsAuthenticationManager() OVERRIDE; // Message Handlers - void didReceiveNetworkProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); + void didReceiveNetworkProcessMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); void initializeNetworkProcess(const NetworkProcessCreationParameters&); void createNetworkConnectionToWebProcess(); - - // The connection to the UI process. - RefPtr<CoreIPC::Connection> m_uiConnection; + void ensurePrivateBrowsingSession(); + void destroyPrivateBrowsingSession(); + void downloadRequest(uint64_t downloadID, const WebCore::ResourceRequest&); + void cancelDownload(uint64_t downloadID); + void setCacheModel(uint32_t); + void allowSpecificHTTPSCertificateForHost(const PlatformCertificateInfo&, const String& host); + void getNetworkProcessStatistics(uint64_t callbackID); + void clearCacheForAllOrigins(uint32_t cachesToClear); + + // Platform Helpers + void platformSetCacheModel(CacheModel); // Connections to WebProcesses. - Vector<RefPtr<NetworkConnectionToWebProcess> > m_webProcessConnections; + Vector<RefPtr<NetworkConnectionToWebProcess>> m_webProcessConnections; NetworkResourceLoadScheduler m_networkResourceLoadScheduler; + + String m_diskCacheDirectory; + bool m_hasSetCacheModel; + CacheModel m_cacheModel; + + typedef HashMap<const char*, OwnPtr<NetworkProcessSupplement>, PtrHash<const char*>> NetworkProcessSupplementMap; + NetworkProcessSupplementMap m_supplements; + +#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 }; } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in index d243bd44f..a5fcbc7be 100644 --- a/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in @@ -22,16 +22,28 @@ #if ENABLE(NETWORK_PROCESS) -messages -> NetworkProcess { +messages -> NetworkProcess LegacyReceiver { # Initializes the network process. InitializeNetworkProcess(WebKit::NetworkProcessCreationParameters processCreationParameters) # Creates a connection for communication with a WebProcess CreateNetworkConnectionToWebProcess() + EnsurePrivateBrowsingSession() + DestroyPrivateBrowsingSession() + + DownloadRequest(uint64_t downloadID, WebCore::ResourceRequest request) + CancelDownload(uint64_t downloadID) + #if PLATFORM(MAC) - SetApplicationIsOccluded(bool flag) + SetProcessSuppressionEnabled(bool flag) #endif + + AllowSpecificHTTPSCertificateForHost(WebKit::PlatformCertificateInfo certificate, WTF::String host) + + GetNetworkProcessStatistics(uint64_t callbackID) + + ClearCacheForAllOrigins(uint32_t cachesToClear) } #endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp new file mode 100644 index 000000000..dcf758877 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.cpp @@ -0,0 +1,101 @@ +/* + * 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 "NetworkProcessPlatformStrategies.h" + +#include <WebCore/BlobRegistryImpl.h> + +using namespace WebCore; + +namespace WebKit { + +void NetworkProcessPlatformStrategies::initialize() +{ + DEFINE_STATIC_LOCAL(NetworkProcessPlatformStrategies, platformStrategies, ()); + setPlatformStrategies(&platformStrategies); +} + +CookiesStrategy* NetworkProcessPlatformStrategies::createCookiesStrategy() +{ + return 0; +} + +DatabaseStrategy* NetworkProcessPlatformStrategies::createDatabaseStrategy() +{ + return 0; +} + +LoaderStrategy* NetworkProcessPlatformStrategies::createLoaderStrategy() +{ + return this; +} + +PasteboardStrategy* NetworkProcessPlatformStrategies::createPasteboardStrategy() +{ + return 0; +} + +PluginStrategy* NetworkProcessPlatformStrategies::createPluginStrategy() +{ + 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 resourceLoadIdentifier, const ResourceRequest&, StoredCredentials, ClientCredentialPolicy, ResourceError&, ResourceResponse&, Vector<char>& data) +{ + 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 new file mode 100644 index 000000000..818ccebb1 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/NetworkProcessPlatformStrategies.h @@ -0,0 +1,60 @@ +/* + * 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 NetworkProcessPlatformStrategies_h +#define NetworkProcessPlatformStrategies_h + +#include <WebCore/LoaderStrategy.h> +#include <WebCore/PlatformStrategies.h> + +namespace WebKit { + +class NetworkProcessPlatformStrategies : public WebCore::PlatformStrategies, private WebCore::LoaderStrategy { +public: + static void initialize(); + +private: + // WebCore::PlatformStrategies + 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 + + +#endif // NetworkProcessPlatformStrategies_h diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp index 8a5d7a139..9aebcc699 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp @@ -3,10 +3,10 @@ #include "HostRecord.h" #include "Logging.h" -#include "NetworkConnectionToWebProcess.h" -#include "NetworkProcessconnectionMessages.h" +#include "NetworkProcess.h" #include "NetworkResourceLoadParameters.h" #include "NetworkResourceLoader.h" +#include "SyncNetworkResourceLoader.h" #include <wtf/MainThread.h> #include <wtf/text/CString.h> @@ -17,15 +17,13 @@ using namespace WebCore; namespace WebKit { static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20; -static unsigned maxRequestsInFlightPerHost; -static ResourceLoadIdentifier s_currentResourceLoadIdentifier; NetworkResourceLoadScheduler::NetworkResourceLoadScheduler() - : m_nonHTTPProtocolHost(new HostRecord(String(), maxRequestsInFlightForNonHTTPProtocols)) + : m_nonHTTPProtocolHost(HostRecord::create(String(), maxRequestsInFlightForNonHTTPProtocols)) , m_requestTimer(this, &NetworkResourceLoadScheduler::requestTimerFired) { - maxRequestsInFlightPerHost = platformInitializeMaximumHTTPConnectionCountPerHost(); + platformInitializeMaximumHTTPConnectionCountPerHost(); } void NetworkResourceLoadScheduler::scheduleServePendingRequests() @@ -39,223 +37,190 @@ void NetworkResourceLoadScheduler::requestTimerFired(WebCore::Timer<NetworkResou servePendingRequests(); } -ResourceLoadIdentifier NetworkResourceLoadScheduler::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters, NetworkConnectionToWebProcess* connection) +void NetworkResourceLoadScheduler::scheduleLoader(PassRefPtr<SchedulableLoader> loader) { - ResourceLoadPriority priority = loadParameters.priority(); - const ResourceRequest& resourceRequest = loadParameters.request(); - - ResourceLoadIdentifier identifier = ++s_currentResourceLoadIdentifier; - RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, identifier, connection); - - m_resourceLoaders.add(identifier, loader); - - LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::scheduleNetworkResourceRequest resource %llu '%s'", identifier, resourceRequest.url().string().utf8().data()); + 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->schedule(loader); - m_identifiers.add(identifier, host); + host->scheduleResourceLoader(loader); if (priority > ResourceLoadPriorityLow || !resourceRequest.url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) { // Try to request important resources immediately. - servePendingRequestsForHost(host, priority); - return identifier; + host->servePendingRequests(priority); + return; } // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones. scheduleServePendingRequests(); - return identifier; -} - -ResourceLoadIdentifier NetworkResourceLoadScheduler::addLoadInProgress(const WebCore::KURL& url) -{ - ResourceLoadIdentifier identifier = ++s_currentResourceLoadIdentifier; - - LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::addLoadInProgress resource %llu with url '%s'", identifier, url.string().utf8().data()); - - HostRecord* host = hostForURL(url, CreateIfNotFound); - host->addLoadInProgress(identifier); - m_identifiers.add(identifier, host); - - return identifier; } HostRecord* NetworkResourceLoadScheduler::hostForURL(const WebCore::KURL& url, CreateHostPolicy createHostPolicy) { if (!url.protocolIsInHTTPFamily()) - return m_nonHTTPProtocolHost; + return m_nonHTTPProtocolHost.get(); m_hosts.checkConsistency(); String hostName = url.host(); HostRecord* host = m_hosts.get(hostName); if (!host && createHostPolicy == CreateIfNotFound) { - host = new HostRecord(hostName, maxRequestsInFlightPerHost); - m_hosts.add(hostName, host); + RefPtr<HostRecord> newHost = HostRecord::create(hostName, m_maxRequestsInFlightPerHost); + host = newHost.get(); + m_hosts.add(hostName, newHost.release()); } return host; } -void NetworkResourceLoadScheduler::removeLoadIdentifier(ResourceLoadIdentifier identifier) +void NetworkResourceLoadScheduler::removeLoader(SchedulableLoader* loader) { ASSERT(isMainThread()); - ASSERT(identifier); + ASSERT(loader); - LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing load identifier %llu", identifier); + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing loader %s", loader->request().url().string().utf8().data()); - HostRecord* host = m_identifiers.take(identifier); + 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->remove(identifier); - - m_resourceLoaders.remove(identifier); + host->removeLoader(loader); scheduleServePendingRequests(); } -NetworkResourceLoader* NetworkResourceLoadScheduler::networkResourceLoaderForIdentifier(ResourceLoadIdentifier identifier) -{ - ASSERT(m_resourceLoaders.get(identifier)); - return m_resourceLoaders.get(identifier).get(); -} - -void NetworkResourceLoadScheduler::receivedRedirect(ResourceLoadIdentifier identifier, const WebCore::KURL& redirectURL) +void NetworkResourceLoadScheduler::receivedRedirect(SchedulableLoader* loader, const WebCore::KURL& redirectURL) { ASSERT(isMainThread()); - LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::receivedRedirect resource %llu redirected to '%s'", identifier, redirectURL.string().utf8().data()); + 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* oldHost = m_identifiers.get(identifier); HostRecord* newHost = hostForURL(redirectURL, CreateIfNotFound); - ASSERT(oldHost); if (oldHost->name() == newHost->name()) return; - - newHost->addLoadInProgress(identifier); - m_identifiers.set(identifier, newHost); - oldHost->remove(identifier); + oldHost->removeLoader(loader); + newHost->addLoaderInProgress(loader); } void NetworkResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority) { - if (m_suspendPendingRequestsCount) - return; - - LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts", m_hosts.size()); + LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts with minimum priority %i", m_hosts.size(), minimumPriority); m_requestTimer.stop(); - servePendingRequestsForHost(m_nonHTTPProtocolHost, minimumPriority); + m_nonHTTPProtocolHost->servePendingRequests(minimumPriority); m_hosts.checkConsistency(); - Vector<HostRecord*> hostsToServe; + 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]; + HostRecord* host = hostsToServe[i].get(); if (host->hasRequests()) - servePendingRequestsForHost(host, minimumPriority); + host->servePendingRequests(minimumPriority); else - delete m_hosts.take(host->name()); + m_hosts.remove(host->name()); } } -void NetworkResourceLoadScheduler::servePendingRequestsForHost(HostRecord* host, ResourceLoadPriority minimumPriority) +static bool removeScheduledLoadersCalled = false; + +void NetworkResourceLoadScheduler::removeScheduledLoaders(void* context) { - LOG(NetworkScheduling, "NetworkResourceLoadScheduler::servePendingRequests Host name='%s'", host->name().utf8().data()); - - for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) { - HostRecord::LoaderQueue& loadersPending = host->loadersPending(ResourceLoadPriority(priority)); - - while (!loadersPending.isEmpty()) { - RefPtr<NetworkResourceLoader> loader = loadersPending.first(); - - // This request might be from WebProcess we've lost our connection to. - // If so we should just skip it. - if (!loader->connectionToWebProcess()) { - loadersPending.removeFirst(); - continue; - } - - // For named hosts - which are only http(s) hosts - we should always enforce the connection limit. - // 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. - - bool shouldLimitRequests = !host->name().isNull(); - if (shouldLimitRequests && host->limitRequests(ResourceLoadPriority(priority), loader->connectionToWebProcess()->isSerialLoadingEnabled())) - return; - - loadersPending.removeFirst(); - host->addLoadInProgress(loader->identifier()); - - loader->start(); - } + ASSERT(isMainThread()); + ASSERT(removeScheduledLoadersCalled); + + NetworkResourceLoadScheduler* scheduler = static_cast<NetworkResourceLoadScheduler*>(context); + scheduler->removeScheduledLoaders(); +} + +void NetworkResourceLoadScheduler::removeScheduledLoaders() +{ + Vector<RefPtr<SchedulableLoader>> 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::suspendPendingRequests() +void NetworkResourceLoadScheduler::scheduleRemoveLoader(SchedulableLoader* loader) { - ++m_suspendPendingRequestsCount; + MutexLocker locker(m_loadersToRemoveMutex); + + m_loadersToRemove.append(loader); + + if (!removeScheduledLoadersCalled) { + removeScheduledLoadersCalled = true; + callOnMainThread(NetworkResourceLoadScheduler::removeScheduledLoaders, this); + } } -void NetworkResourceLoadScheduler::resumePendingRequests() +uint64_t NetworkResourceLoadScheduler::hostsPendingCount() const { - ASSERT(m_suspendPendingRequestsCount); - --m_suspendPendingRequestsCount; - if (m_suspendPendingRequestsCount) - return; + uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount() ? 1 : 0; - if (!m_hosts.isEmpty() || m_nonHTTPProtocolHost->hasRequests()) - scheduleServePendingRequests(); -} + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) { + if (i->value->pendingRequestCount()) + ++count; + } -static bool removeScheduledLoadIdentifiersCalled = false; + return count; +} -void NetworkResourceLoadScheduler::removeScheduledLoadIdentifiers(void* context) +uint64_t NetworkResourceLoadScheduler::loadsPendingCount() const { - ASSERT(isMainThread()); - ASSERT(removeScheduledLoadIdentifiersCalled); + uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount(); - NetworkResourceLoadScheduler* scheduler = static_cast<NetworkResourceLoadScheduler*>(context); - scheduler->removeScheduledLoadIdentifiers(); + HostMap::const_iterator end = m_hosts.end(); + for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) + count += i->value->pendingRequestCount(); + + return count; } -void NetworkResourceLoadScheduler::removeScheduledLoadIdentifiers() +uint64_t NetworkResourceLoadScheduler::hostsActiveCount() const { - Vector<ResourceLoadIdentifier> identifiers; - { - MutexLocker locker(m_identifiersToRemoveMutex); - copyToVector(m_identifiersToRemove, identifiers); - m_identifiersToRemove.clear(); - removeScheduledLoadIdentifiersCalled = false; + 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; } - - for (size_t i = 0; i < identifiers.size(); ++i) - removeLoadIdentifier(identifiers[i]); + + return count; } -void NetworkResourceLoadScheduler::scheduleRemoveLoadIdentifier(ResourceLoadIdentifier identifier) +uint64_t NetworkResourceLoadScheduler::loadsActiveCount() const { - MutexLocker locker(m_identifiersToRemoveMutex); - - m_identifiersToRemove.add(identifier); - - if (!removeScheduledLoadIdentifiersCalled) { - removeScheduledLoadIdentifiersCalled = true; - callOnMainThread(NetworkResourceLoadScheduler::removeScheduledLoadIdentifiers, this); - } + 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 diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h index 85a19cd24..dfe710268 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h @@ -26,20 +26,22 @@ #ifndef NetworkResourceLoadScheduler_h #define NetworkResourceLoadScheduler_h -#include "NetworkResourceLoader.h" -#include <WebCore/ResourceLoaderOptions.h> -#include <WebCore/ResourceRequest.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 KURL; +} + namespace WebKit { class HostRecord; -class NetworkResourceLoadParameters; -class NetworkConnectionToWebProcess; -typedef uint64_t ResourceLoadIdentifier; +class SchedulableLoader; class NetworkResourceLoadScheduler { WTF_MAKE_NONCOPYABLE(NetworkResourceLoadScheduler); WTF_MAKE_FAST_ALLOCATED; @@ -47,24 +49,23 @@ class NetworkResourceLoadScheduler { public: NetworkResourceLoadScheduler(); - // Adds the request to the queue for its host and create a unique identifier for it. - ResourceLoadIdentifier scheduleResourceLoad(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*); - - // Creates a unique identifier for an already-in-progress load. - ResourceLoadIdentifier addLoadInProgress(const WebCore::KURL&); + // Adds the request to the queue for its host. + void scheduleLoader(PassRefPtr<SchedulableLoader>); // Called by the WebProcess when a ResourceLoader is being cleaned up. - void removeLoadIdentifier(ResourceLoadIdentifier); + void removeLoader(SchedulableLoader*); // Called within the NetworkProcess on a background thread when a resource load has finished. - void scheduleRemoveLoadIdentifier(ResourceLoadIdentifier); + void scheduleRemoveLoader(SchedulableLoader*); - void receivedRedirect(ResourceLoadIdentifier, const WebCore::KURL& redirectURL); + void receivedRedirect(SchedulableLoader*, const WebCore::KURL& redirectURL); void servePendingRequests(WebCore::ResourceLoadPriority = WebCore::ResourceLoadPriorityVeryLow); - void suspendPendingRequests(); - void resumePendingRequests(); - - NetworkResourceLoader* networkResourceLoaderForIdentifier(ResourceLoadIdentifier); + + // For NetworkProcess statistics reporting. + uint64_t hostsPendingCount() const; + uint64_t loadsPendingCount() const; + uint64_t hostsActiveCount() const; + uint64_t loadsActiveCount() const; private: enum CreateHostPolicy { @@ -77,30 +78,27 @@ private: void scheduleServePendingRequests(); void requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*); - void servePendingRequestsForHost(HostRecord*, WebCore::ResourceLoadPriority); + void platformInitializeMaximumHTTPConnectionCountPerHost(); - unsigned platformInitializeMaximumHTTPConnectionCountPerHost(); + static void removeScheduledLoaders(void* context); + void removeScheduledLoaders(); - static void removeScheduledLoadIdentifiers(void* context); - void removeScheduledLoadIdentifiers(); - - HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader> > m_resourceLoaders; - - typedef HashMap<String, HostRecord*, StringHash> HostMap; + typedef HashMap<String, RefPtr<HostRecord>, StringHash> HostMap; HostMap m_hosts; - typedef HashMap<ResourceLoadIdentifier, HostRecord*> IdentifierHostMap; - IdentifierHostMap m_identifiers; + typedef HashSet<RefPtr<SchedulableLoader>> SchedulableLoaderSet; + SchedulableLoaderSet m_loaders; - HostRecord* m_nonHTTPProtocolHost; + RefPtr<HostRecord> m_nonHTTPProtocolHost; - unsigned m_suspendPendingRequestsCount; bool m_isSerialLoadingEnabled; WebCore::Timer<NetworkResourceLoadScheduler> m_requestTimer; - Mutex m_identifiersToRemoveMutex; - HashSet<ResourceLoadIdentifier> m_identifiersToRemove; + Mutex m_loadersToRemoveMutex; + Vector<RefPtr<SchedulableLoader>> m_loadersToRemove; + + unsigned m_maxRequestsInFlightPerHost; }; } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp index 80aa813ac..5ad12d324 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp @@ -28,354 +28,323 @@ #if ENABLE(NETWORK_PROCESS) -#include "BlockingResponseMap.h" +#include "AuthenticationManager.h" #include "DataReference.h" #include "Logging.h" #include "NetworkConnectionToWebProcess.h" #include "NetworkProcess.h" +#include "NetworkProcessConnectionMessages.h" #include "NetworkResourceLoadParameters.h" +#include "PlatformCertificateInfo.h" #include "RemoteNetworkingContext.h" +#include "ShareableResource.h" #include "SharedMemory.h" #include "WebCoreArgumentCoders.h" +#include "WebErrors.h" #include "WebResourceLoaderMessages.h" #include <WebCore/NotImplemented.h> #include <WebCore/ResourceBuffer.h> #include <WebCore/ResourceHandle.h> +#include <wtf/CurrentTime.h> #include <wtf/MainThread.h> using namespace WebCore; namespace WebKit { -NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& requestParameters, ResourceLoadIdentifier identifier, NetworkConnectionToWebProcess* connection) - : m_requestParameters(requestParameters) - , m_identifier(identifier) - , m_connection(connection) +NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& loadParameters, NetworkConnectionToWebProcess* connection) + : SchedulableLoader(loadParameters, connection) + , m_bytesReceived(0) + , m_handleConvertedToDownload(false) { ASSERT(isMainThread()); - connection->registerObserver(this); } NetworkResourceLoader::~NetworkResourceLoader() { ASSERT(isMainThread()); - - if (m_connection) - m_connection->unregisterObserver(this); -} - -CoreIPC::Connection* NetworkResourceLoader::connection() const -{ - return m_connection->connection(); -} - -ResourceLoadPriority NetworkResourceLoader::priority() const -{ - return m_requestParameters.priority(); + ASSERT(!m_handle); } void NetworkResourceLoader::start() { ASSERT(isMainThread()); - // Explicit ref() balanced by a deref() in NetworkResourceLoader::stop() + // Explicit ref() balanced by a deref() in NetworkResourceLoader::resourceHandleStopped() ref(); // FIXME (NetworkProcess): Create RemoteNetworkingContext with actual settings. - m_networkingContext = RemoteNetworkingContext::create(false, false); + m_networkingContext = RemoteNetworkingContext::create(false, false, inPrivateBrowsingMode(), shouldClearReferrerOnHTTPSToHTTPRedirect()); + + consumeSandboxExtensions(); // FIXME (NetworkProcess): Pass an actual value for defersLoading - m_handle = ResourceHandle::create(m_networkingContext.get(), m_requestParameters.request(), this, false /* defersLoading */, m_requestParameters.contentSniffingPolicy() == SniffContent); + m_handle = ResourceHandle::create(m_networkingContext.get(), request(), this, false /* defersLoading */, contentSniffingPolicy() == SniffContent); } -static bool stopRequestsCalled = false; - -static Mutex& requestsToStopMutex() +void NetworkResourceLoader::cleanup() { - DEFINE_STATIC_LOCAL(Mutex, mutex, ()); - return mutex; -} + ASSERT(isMainThread()); -static HashSet<NetworkResourceLoader*>& requestsToStop() -{ - DEFINE_STATIC_LOCAL(HashSet<NetworkResourceLoader*>, requests, ()); - return requests; -} + invalidateSandboxExtensions(); -void NetworkResourceLoader::scheduleStopOnMainThread() -{ - MutexLocker locker(requestsToStopMutex()); + if (FormData* formData = request().httpBody()) + formData->removeGeneratedFilesIfNeeded(); + + // Tell the scheduler about this finished loader soon so it can start more network requests. + NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoader(this); - requestsToStop().add(this); - if (!stopRequestsCalled) { - stopRequestsCalled = true; - callOnMainThread(NetworkResourceLoader::performStops, 0); + 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::performStops(void*) +template<typename U> bool NetworkResourceLoader::sendAbortingOnFailure(const U& message, unsigned messageSendFlags) { - ASSERT(stopRequestsCalled); - - Vector<NetworkResourceLoader*> requests; - { - MutexLocker locker(requestsToStopMutex()); - copyToVector(requestsToStop(), requests); - requestsToStop().clear(); - stopRequestsCalled = false; - } - - for (size_t i = 0; i < requests.size(); ++i) - requests[i]->stop(); + bool result = messageSenderConnection()->send(message, messageSenderDestinationID(), messageSendFlags); + if (!result) + abort(); + return result; } -void NetworkResourceLoader::stop() +void NetworkResourceLoader::didConvertHandleToDownload() { - ASSERT(isMainThread()); - - // Remove this load identifier soon so we can start more network requests. - NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoadIdentifier(m_identifier); - - // Explicit deref() balanced by a ref() in NetworkResourceLoader::stop() - // This might cause the NetworkResourceLoader to be destroyed and therefore we do it last. - deref(); + ASSERT(m_handle); + m_handleConvertedToDownload = true; } -void NetworkResourceLoader::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection) +void NetworkResourceLoader::abort() { - ASSERT_ARG(connection, connection == m_connection.get()); - m_connection->unregisterObserver(this); - m_connection = 0; + ASSERT(isMainThread()); + + if (m_handle && !m_handleConvertedToDownload) + m_handle->cancel(); + + cleanup(); } -void NetworkResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) +void NetworkResourceLoader::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& response) { + ASSERT_UNUSED(handle, handle == m_handle); + // FIXME (NetworkProcess): Cache the response. - send(Messages::WebResourceLoader::DidReceiveResponse(response)); + if (FormData* formData = request().httpBody()) + formData->removeGeneratedFilesIfNeeded(); + + sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponseWithCertificateInfo(response, PlatformCertificateInfo(response), isLoadingMainResource())); + + // m_handle will be 0 if the request got aborted above. + if (!m_handle) + return; + + if (!isLoadingMainResource()) { + // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message. + m_handle->continueDidReceiveResponse(); + } } void NetworkResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength) { + // 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. - CoreIPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(data), length); - send(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedDataLength, false)); + m_bytesReceived += buffer->size(); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + ShareableResource::Handle shareableResourceHandle; + tryGetShareableHandleFromSharedBuffer(shareableResourceHandle, buffer.get()); + if (!shareableResourceHandle.isNull()) { + // Since we're delivering this resource by ourselves all at once, we'll abort the resource handle since we don't need anymore callbacks from ResourceHandle. + abort(); + send(Messages::WebResourceLoader::DidReceiveResource(shareableResourceHandle, currentTime())); + return; + } +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + + CoreIPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); + sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveData(dataReference, encodedDataLength)); } -void NetworkResourceLoader::didFinishLoading(ResourceHandle*, double finishTime) +void NetworkResourceLoader::didFinishLoading(ResourceHandle* handle, double finishTime) { + ASSERT_UNUSED(handle, handle == m_handle); + // FIXME (NetworkProcess): For the memory cache we'll need to update the finished status of the cached resource here. // Such bookkeeping will need to be thread safe, as this callback is happening on a background thread. send(Messages::WebResourceLoader::DidFinishResourceLoad(finishTime)); - scheduleStopOnMainThread(); + + cleanup(); } -void NetworkResourceLoader::didFail(ResourceHandle*, const ResourceError& error) +void NetworkResourceLoader::didFail(ResourceHandle* handle, const ResourceError& error) { + ASSERT_UNUSED(handle, handle == m_handle); + // FIXME (NetworkProcess): For the memory cache we'll need to update the finished status of the cached resource here. // Such bookkeeping will need to be thread safe, as this callback is happening on a background thread. send(Messages::WebResourceLoader::DidFailResourceLoad(error)); - scheduleStopOnMainThread(); + cleanup(); } -static BlockingResponseMap<ResourceRequest*>& willSendRequestResponseMap() +void NetworkResourceLoader::willSendRequestAsync(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& redirectResponse) { - AtomicallyInitializedStatic(BlockingResponseMap<ResourceRequest*>&, responseMap = *new BlockingResponseMap<ResourceRequest*>); - return responseMap; -} + ASSERT_UNUSED(handle, handle == m_handle); -static uint64_t generateWillSendRequestID() -{ - static int64_t uniqueWillSendRequestID; - return atomicIncrement(&uniqueWillSendRequestID); -} - -void NetworkResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect + // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect. ASSERT(!redirectResponse.isNull()); + ASSERT(isMainThread()); - uint64_t requestID = generateWillSendRequestID(); - - send(Messages::WebResourceLoader::WillSendRequest(requestID, request, redirectResponse)); - - OwnPtr<ResourceRequest> newRequest = willSendRequestResponseMap().waitForResponse(requestID); - request = *newRequest; + m_suggestedRequestForWillSendRequest = request; - RunLoop::main()->dispatch(WTF::bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), m_identifier, request.url())); + // This message is DispatchMessageEvenWhenWaitingForSyncReply to avoid a situation where the NetworkProcess is deadlocked waiting for 6 connections + // to complete while the WebProcess is waiting for a 7th to complete. + sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(request, redirectResponse), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply); } -void NetworkResourceLoader::willSendRequestHandled(uint64_t requestID, const WebCore::ResourceRequest& newRequest) +void NetworkResourceLoader::continueWillSendRequest(const ResourceRequest& newRequest) { - willSendRequestResponseMap().didReceiveResponse(requestID, adoptPtr(new ResourceRequest(newRequest))); -} + m_suggestedRequestForWillSendRequest.updateFromDelegatePreservingOldHTTPBody(newRequest.nsURLRequest(DoNotUpdateHTTPBody)); -// FIXME (NetworkProcess): Many of the following ResourceHandleClient methods definitely need implementations. A few will not. -// Once we know what they are they can be removed. + RunLoop::main()->dispatch(bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), this, m_suggestedRequestForWillSendRequest.url())); + m_handle->continueWillSendRequest(m_suggestedRequestForWillSendRequest); -void NetworkResourceLoader::didSendData(WebCore::ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/) -{ - notImplemented(); + m_suggestedRequestForWillSendRequest = ResourceRequest(); } -void NetworkResourceLoader::didReceiveCachedMetadata(WebCore::ResourceHandle*, const char*, int) +void NetworkResourceLoader::continueDidReceiveResponse() { - notImplemented(); -} + // 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_handle) + return; -void NetworkResourceLoader::wasBlocked(WebCore::ResourceHandle*) -{ - notImplemented(); + m_handle->continueDidReceiveResponse(); } -void NetworkResourceLoader::cannotShowURL(WebCore::ResourceHandle*) +void NetworkResourceLoader::didSendData(ResourceHandle* handle, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { - notImplemented(); -} + ASSERT_UNUSED(handle, handle == m_handle); -void NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, WebCore::CacheStoragePolicy&) -{ - notImplemented(); + send(Messages::WebResourceLoader::DidSendData(bytesSent, totalBytesToBeSent)); } -bool NetworkResourceLoader::shouldUseCredentialStorage(ResourceHandle*) +void NetworkResourceLoader::wasBlocked(ResourceHandle* handle) { - // When the WebProcess is handling loading a client is consulted each time this shouldUseCredentialStorage question is asked. - // In NetworkProcess mode we ask the WebProcess client up front once and then reuse the cached answer. + ASSERT_UNUSED(handle, handle == m_handle); - return m_requestParameters.allowStoredCredentials() == AllowStoredCredentials; + didFail(handle, WebKit::blockedError(request())); } -void NetworkResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) +void NetworkResourceLoader::cannotShowURL(ResourceHandle* handle) { - ASSERT(!m_currentAuthenticationChallenge); - m_currentAuthenticationChallenge = adoptPtr(new AuthenticationChallenge(challenge)); + ASSERT_UNUSED(handle, handle == m_handle); - send(Messages::WebResourceLoader::DidReceiveAuthenticationChallenge(*m_currentAuthenticationChallenge)); + didFail(handle, WebKit::cannotShowURLError(request())); } -void NetworkResourceLoader::didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) +bool NetworkResourceLoader::shouldUseCredentialStorage(ResourceHandle* handle) { - ASSERT(m_currentAuthenticationChallenge); - ASSERT(m_currentAuthenticationChallenge->identifier() == challenge.identifier()); + ASSERT_UNUSED(handle, handle == m_handle || !m_handle); // m_handle will be 0 if called from ResourceHandle::start(). - send(Messages::WebResourceLoader::DidCancelAuthenticationChallenge(*m_currentAuthenticationChallenge)); + // 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. - m_currentAuthenticationChallenge.clear(); -} + // We still need this sync version, because ResourceHandle itself uses it internally, even when the delegate uses an async one. -void NetworkResourceLoader::receivedCancellation(ResourceHandle*, const AuthenticationChallenge& challenge) -{ - receivedAuthenticationCancellation(challenge); + return allowStoredCredentials() == AllowStoredCredentials; } -void NetworkResourceLoader::receivedAuthenticationCredential(const AuthenticationChallenge& challenge, const Credential& credential) +void NetworkResourceLoader::shouldUseCredentialStorageAsync(ResourceHandle* handle) { - ASSERT(m_currentAuthenticationChallenge); - ASSERT(m_currentAuthenticationChallenge->authenticationClient()); + ASSERT_UNUSED(handle, handle == m_handle); - if (m_currentAuthenticationChallenge->identifier() != challenge.identifier()) - return; - - m_currentAuthenticationChallenge->authenticationClient()->receivedCredential(*m_currentAuthenticationChallenge, credential); - m_currentAuthenticationChallenge.clear(); + handle->continueShouldUseCredentialStorage(shouldUseCredentialStorage(handle)); } -void NetworkResourceLoader::receivedRequestToContinueWithoutAuthenticationCredential(const AuthenticationChallenge& challenge) +void NetworkResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - ASSERT(m_currentAuthenticationChallenge); - ASSERT(m_currentAuthenticationChallenge->authenticationClient()); + ASSERT_UNUSED(handle, handle == m_handle); - if (m_currentAuthenticationChallenge->identifier() != challenge.identifier()) + // 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 (clientCredentialPolicy() == DoNotAskClientForAnyCredentials) { + challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge); return; + } - m_currentAuthenticationChallenge->authenticationClient()->receivedRequestToContinueWithoutCredential(*m_currentAuthenticationChallenge); - m_currentAuthenticationChallenge.clear(); + NetworkProcess::shared().authenticationManager().didReceiveAuthenticationChallenge(webPageID(), webFrameID(), challenge); } -void NetworkResourceLoader::receivedAuthenticationCancellation(const AuthenticationChallenge& challenge) +void NetworkResourceLoader::didCancelAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - ASSERT(m_currentAuthenticationChallenge); - ASSERT(m_currentAuthenticationChallenge->authenticationClient()); - - if (m_currentAuthenticationChallenge->identifier() != challenge.identifier()) - return; + ASSERT_UNUSED(handle, handle == m_handle); - m_currentAuthenticationChallenge->authenticationClient()->receivedCancellation(*m_currentAuthenticationChallenge); - m_currentAuthenticationChallenge.clear(); + // This function is probably not needed (see <rdar://problem/8960124>). + notImplemented(); } -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -static BlockingBoolResponseMap& canAuthenticateAgainstProtectionSpaceResponseMap() +CoreIPC::Connection* NetworkResourceLoader::messageSenderConnection() { - AtomicallyInitializedStatic(BlockingBoolResponseMap&, responseMap = *new BlockingBoolResponseMap); - return responseMap; + return connectionToWebProcess()->connection(); } -static uint64_t generateCanAuthenticateAgainstProtectionSpaceID() +uint64_t NetworkResourceLoader::messageSenderDestinationID() { - static int64_t uniqueCanAuthenticateAgainstProtectionSpaceID; - return atomicIncrement(&uniqueCanAuthenticateAgainstProtectionSpaceID); + return identifier(); } -bool NetworkResourceLoader::canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace& protectionSpace) +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle* handle, const ProtectionSpace& protectionSpace) { - uint64_t requestID = generateCanAuthenticateAgainstProtectionSpaceID(); - - send(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(requestID, protectionSpace)); + ASSERT(isMainThread()); + ASSERT_UNUSED(handle, handle == m_handle); - return canAuthenticateAgainstProtectionSpaceResponseMap().waitForResponse(requestID); + // This message is DispatchMessageEvenWhenWaitingForSyncReply to avoid a situation where the NetworkProcess is deadlocked + // waiting for 6 connections to complete while the WebProcess is waiting for a 7th to complete. + sendAbortingOnFailure(Messages::WebResourceLoader::CanAuthenticateAgainstProtectionSpace(protectionSpace), CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply); } -void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceHandled(uint64_t requestID, bool canAuthenticate) +void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result) { - canAuthenticateAgainstProtectionSpaceResponseMap().didReceiveResponse(requestID, canAuthenticate); + m_handle->continueCanAuthenticateAgainstProtectionSpace(result); } + #endif -#if HAVE(NETWORK_CFDATA_ARRAY_CALLBACK) +#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) bool NetworkResourceLoader::supportsDataArray() { notImplemented(); return false; } -void NetworkResourceLoader::didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef) +void NetworkResourceLoader::didReceiveDataArray(ResourceHandle*, CFArrayRef) { + ASSERT_NOT_REACHED(); notImplemented(); } #endif #if PLATFORM(MAC) -#if USE(CFNETWORK) -CFCachedURLResponseRef NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, CFCachedURLResponseRef response) -{ - notImplemented(); - return response; -} -#else -NSCachedURLResponse* NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, NSCachedURLResponse* response) -{ - notImplemented(); - return response; -} -#endif - -void NetworkResourceLoader::willStopBufferingData(WebCore::ResourceHandle*, const char*, int) +void NetworkResourceLoader::willStopBufferingData(ResourceHandle*, const char*, int) { notImplemented(); } #endif // PLATFORM(MAC) -#if ENABLE(BLOB) -WebCore::AsyncFileStream* NetworkResourceLoader::createAsyncFileStream(WebCore::FileStreamClient*) -{ - notImplemented(); - return 0; -} -#endif - } // namespace WebKit #endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h index bbfbc5dfe..798cccf20 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h @@ -29,107 +29,109 @@ #if ENABLE(NETWORK_PROCESS) #include "MessageSender.h" -#include "NetworkConnectionToWebProcess.h" -#include "NetworkResourceLoadParameters.h" -#include <WebCore/AuthenticationChallenge.h> +#include "SchedulableLoader.h" +#include "ShareableResource.h" #include <WebCore/ResourceHandleClient.h> -#include <WebCore/ResourceLoaderOptions.h> -#include <WebCore/ResourceRequest.h> +#include <WebCore/RunLoop.h> + +typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef; namespace WebCore { class ResourceBuffer; class ResourceHandle; +class ResourceRequest; } namespace WebKit { +class NetworkConnectionToWebProcess; class RemoteNetworkingContext; -typedef uint64_t ResourceLoadIdentifier; -class NetworkResourceLoader : public RefCounted<NetworkResourceLoader>, public NetworkConnectionToWebProcessObserver, public WebCore::ResourceHandleClient, public CoreIPC::MessageSender<NetworkResourceLoader> { +class NetworkResourceLoader : public SchedulableLoader, public WebCore::ResourceHandleClient, public CoreIPC::MessageSender { public: - static RefPtr<NetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, ResourceLoadIdentifier identifier, NetworkConnectionToWebProcess* connection) + static RefPtr<NetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection) { - return adoptRef(new NetworkResourceLoader(parameters, identifier, connection)); + return adoptRef(new NetworkResourceLoader(parameters, connection)); } ~NetworkResourceLoader(); - // Used by MessageSender. - CoreIPC::Connection* connection() const; - uint64_t destinationID() const { return identifier(); } - - void didReceiveNetworkResourceLoaderMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); - - void start(); + WebCore::ResourceHandle* handle() const { return m_handle.get(); } + void didConvertHandleToDownload(); - virtual void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*) OVERRIDE; - - ResourceLoadIdentifier identifier() const { return m_identifier; } - WebCore::ResourceLoadPriority priority() const; - - NetworkConnectionToWebProcess* connectionToWebProcess() { return m_connection.get(); } + virtual void start() OVERRIDE; + virtual void abort() OVERRIDE; // ResourceHandleClient methods - virtual void willSendRequest(WebCore::ResourceHandle*, WebCore::ResourceRequest&, const WebCore::ResourceResponse& /*redirectResponse*/) OVERRIDE; - virtual void didSendData(WebCore::ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/) OVERRIDE; - virtual void didReceiveResponse(WebCore::ResourceHandle*, const WebCore::ResourceResponse&) OVERRIDE; - virtual void didReceiveData(WebCore::ResourceHandle*, const char*, int, int /*encodedDataLength*/) OVERRIDE; - virtual void didReceiveCachedMetadata(WebCore::ResourceHandle*, const char*, int) OVERRIDE; - virtual void didFinishLoading(WebCore::ResourceHandle*, double /*finishTime*/) OVERRIDE; + virtual void 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*, int, 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 void willCacheResponse(WebCore::ResourceHandle*, WebCore::CacheStoragePolicy&) 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 bool canAuthenticateAgainstProtectionSpace(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&) OVERRIDE; + virtual void canAuthenticateAgainstProtectionSpaceAsync(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&) OVERRIDE; #endif -#if HAVE(NETWORK_CFDATA_ARRAY_CALLBACK) +#if USE(NETWORK_CFDATA_ARRAY_CALLBACK) virtual bool supportsDataArray() OVERRIDE; virtual void didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef) OVERRIDE; #endif #if PLATFORM(MAC) -#if USE(CFNETWORK) - virtual CFCachedURLResponseRef willCacheResponse(WebCore::ResourceHandle*, CFCachedURLResponseRef) OVERRIDE; -#else - virtual NSCachedURLResponse* willCacheResponse(WebCore::ResourceHandle*, NSCachedURLResponse*) OVERRIDE; -#endif + static size_t fileBackedResourceMinimumSize(); + virtual void willCacheResponseAsync(WebCore::ResourceHandle*, NSCachedURLResponse *) OVERRIDE; virtual void willStopBufferingData(WebCore::ResourceHandle*, const char*, int) OVERRIDE; #endif // PLATFORM(MAC) -#if ENABLE(BLOB) - virtual WebCore::AsyncFileStream* createAsyncFileStream(WebCore::FileStreamClient*) OVERRIDE; + // Message handlers. + void didReceiveNetworkResourceLoaderMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + static void tryGetShareableHandleFromCFURLCachedResponse(ShareableResource::Handle&, CFCachedURLResponseRef); #endif private: - NetworkResourceLoader(const NetworkResourceLoadParameters&, ResourceLoadIdentifier, NetworkConnectionToWebProcess*); + NetworkResourceLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*); - void willSendRequestHandled(uint64_t requestID, const WebCore::ResourceRequest&); - void canAuthenticateAgainstProtectionSpaceHandled(uint64_t requestID, bool canAuthenticate); - void receivedAuthenticationCredential(const WebCore::AuthenticationChallenge&, const WebCore::Credential&); - void receivedRequestToContinueWithoutAuthenticationCredential(const WebCore::AuthenticationChallenge&); - void receivedAuthenticationCancellation(const WebCore::AuthenticationChallenge&); - - void scheduleStopOnMainThread(); - static void performStops(void*); + // CoreIPC::MessageSender + virtual CoreIPC::Connection* messageSenderConnection() OVERRIDE; + virtual uint64_t messageSenderDestinationID() OVERRIDE; + + void continueWillSendRequest(const WebCore::ResourceRequest& newRequest); + void continueDidReceiveResponse(); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + void continueCanAuthenticateAgainstProtectionSpace(bool); +#endif - void stop(); + void cleanup(); + + void platformDidReceiveResponse(const WebCore::ResourceResponse&); - NetworkResourceLoadParameters m_requestParameters; - ResourceLoadIdentifier m_identifier; + template<typename U> bool sendAbortingOnFailure(const U& message, unsigned messageSendFlags = 0); RefPtr<RemoteNetworkingContext> m_networkingContext; - RefPtr<WebCore::ResourceHandle> m_handle; - RefPtr<NetworkConnectionToWebProcess> m_connection; - - OwnPtr<WebCore::AuthenticationChallenge> m_currentAuthenticationChallenge; + RefPtr<WebCore::ResourceHandle> m_handle; + + // Keep the suggested request around while asynchronously asking to update it, because some parts of the request don't survive IPC. + WebCore::ResourceRequest m_suggestedRequestForWillSendRequest; + + uint64_t m_bytesReceived; + + bool m_handleConvertedToDownload; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + static void tryGetShareableHandleFromSharedBuffer(ShareableResource::Handle&, WebCore::SharedBuffer*); +#endif }; } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in index c6c0f0bbe..00706af43 100644 --- a/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in +++ b/Source/WebKit2/NetworkProcess/NetworkResourceLoader.messages.in @@ -1,4 +1,4 @@ -# Copyright (C) 2012 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 @@ -20,15 +20,9 @@ # 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 { -messages -> NetworkResourceLoader { - WillSendRequestHandled(uint64_t requestID, WebCore::ResourceRequest newRequest) - CanAuthenticateAgainstProtectionSpaceHandled(uint64_t requestID, bool canAuthenticate) - - ReceivedAuthenticationCredential(WebCore::AuthenticationChallenge challenge, WebCore::Credential credential) - ReceivedRequestToContinueWithoutAuthenticationCredential(WebCore::AuthenticationChallenge challenge) - ReceivedAuthenticationCancellation(WebCore::AuthenticationChallenge challenge) + ContinueWillSendRequest(WebCore::ResourceRequest request) + ContinueDidReceiveResponse() + ContinueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate) } - -#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/SchedulableLoader.cpp b/Source/WebKit2/NetworkProcess/SchedulableLoader.cpp new file mode 100644 index 000000000..ae7b20397 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SchedulableLoader.cpp @@ -0,0 +1,118 @@ +/* + * 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 "SchedulableLoader.h" + +#if ENABLE(NETWORK_PROCESS) + +#include "NetworkBlobRegistry.h" +#include "NetworkConnectionToWebProcess.h" +#include "NetworkResourceLoadParameters.h" +#include <WebCore/FormData.h> + +using namespace WebCore; + +namespace WebKit { + +SchedulableLoader::SchedulableLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection) + : m_identifier(parameters.identifier) + , m_webPageID(parameters.webPageID) + , m_webFrameID(parameters.webFrameID) + , m_request(parameters.request) + , m_priority(parameters.priority) + , m_contentSniffingPolicy(parameters.contentSniffingPolicy) + , m_allowStoredCredentials(parameters.allowStoredCredentials) + , m_clientCredentialPolicy(parameters.clientCredentialPolicy) + , m_inPrivateBrowsingMode(parameters.inPrivateBrowsingMode) + , m_shouldClearReferrerOnHTTPSToHTTPRedirect(parameters.shouldClearReferrerOnHTTPSToHTTPRedirect) + , m_isLoadingMainResource(parameters.isMainResource) + , m_sandboxExtensionsAreConsumed(false) + , m_connection(connection) +{ + // 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_webPageID && m_webFrameID) || m_clientCredentialPolicy == DoNotAskClientForAnyCredentials); + + 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 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 (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); +} + +SchedulableLoader::~SchedulableLoader() +{ + ASSERT(!m_hostRecord); +} + +void SchedulableLoader::consumeSandboxExtensions() +{ + for (size_t i = 0, count = m_requestBodySandboxExtensions.size(); i < count; ++i) + m_requestBodySandboxExtensions[i]->consume(); + + for (size_t i = 0, count = m_resourceSandboxExtensions.size(); i < count; ++i) + m_resourceSandboxExtensions[i]->consume(); + + m_sandboxExtensionsAreConsumed = true; +} + +void SchedulableLoader::invalidateSandboxExtensions() +{ + 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_requestBodySandboxExtensions.clear(); + m_resourceSandboxExtensions.clear(); + + m_sandboxExtensionsAreConsumed = false; +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/SchedulableLoader.h b/Source/WebKit2/NetworkProcess/SchedulableLoader.h new file mode 100644 index 000000000..81ff5e5ce --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SchedulableLoader.h @@ -0,0 +1,102 @@ +/* + * 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 SchedulableLoader_h +#define SchedulableLoader_h + +#include "HostRecord.h" +#include <WebCore/ResourceLoaderOptions.h> +#include <WebCore/ResourceRequest.h> +#include <wtf/MainThread.h> +#include <wtf/RefCounted.h> + +#if ENABLE(NETWORK_PROCESS) + +namespace WebKit { + +class NetworkConnectionToWebProcess; +class NetworkResourceLoadParameters; +class SandboxExtension; + +class SchedulableLoader : public RefCounted<SchedulableLoader> { +public: + virtual ~SchedulableLoader(); + + ResourceLoadIdentifier identifier() const { return m_identifier; } + uint64_t webPageID() const { return m_webPageID; } + uint64_t webFrameID() const { return m_webFrameID; } + const WebCore::ResourceRequest& request() const { return m_request; } + WebCore::ResourceLoadPriority priority() const { return m_priority; } + WebCore::ContentSniffingPolicy contentSniffingPolicy() const { return m_contentSniffingPolicy; } + WebCore::StoredCredentials allowStoredCredentials() const { return m_allowStoredCredentials; } + WebCore::ClientCredentialPolicy clientCredentialPolicy() const { return m_clientCredentialPolicy; } + bool inPrivateBrowsingMode() const { return m_inPrivateBrowsingMode; } + bool isLoadingMainResource() const { return m_isLoadingMainResource; } + + NetworkConnectionToWebProcess* connectionToWebProcess() const { return m_connection.get(); } + + virtual void start() = 0; + virtual void abort() = 0; + + virtual bool isSynchronous() { return false; } + + void setHostRecord(HostRecord* hostRecord) { ASSERT(isMainThread()); m_hostRecord = hostRecord; } + HostRecord* hostRecord() const { ASSERT(isMainThread()); return m_hostRecord.get(); } + +protected: + SchedulableLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*); + + void consumeSandboxExtensions(); + void invalidateSandboxExtensions(); + + bool shouldClearReferrerOnHTTPSToHTTPRedirect() const { return m_shouldClearReferrerOnHTTPSToHTTPRedirect; } + +private: + ResourceLoadIdentifier m_identifier; + uint64_t m_webPageID; + uint64_t m_webFrameID; + WebCore::ResourceRequest m_request; + WebCore::ResourceLoadPriority m_priority; + WebCore::ContentSniffingPolicy m_contentSniffingPolicy; + WebCore::StoredCredentials m_allowStoredCredentials; + WebCore::ClientCredentialPolicy m_clientCredentialPolicy; + bool m_inPrivateBrowsingMode; + bool m_shouldClearReferrerOnHTTPSToHTTPRedirect; + bool m_isLoadingMainResource; + + Vector<RefPtr<SandboxExtension>> m_requestBodySandboxExtensions; + Vector<RefPtr<SandboxExtension>> m_resourceSandboxExtensions; + bool m_sandboxExtensionsAreConsumed; + + RefPtr<NetworkConnectionToWebProcess> m_connection; + + RefPtr<HostRecord> m_hostRecord; +}; + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) + +#endif // SchedulableLoader_h diff --git a/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.cpp b/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.cpp new file mode 100644 index 000000000..02b05ed7d --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.cpp @@ -0,0 +1,87 @@ +/* + * 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 "SyncNetworkResourceLoader.h" + +#if ENABLE(NETWORK_PROCESS) + +#include "DataReference.h" +#include "NetworkProcess.h" +#include "RemoteNetworkingContext.h" +#include <WebCore/ResourceError.h> +#include <WebCore/ResourceHandle.h> +#include <WebCore/ResourceResponse.h> +#include <wtf/MainThread.h> + +using namespace WebCore; + +namespace WebKit { + +SyncNetworkResourceLoader::SyncNetworkResourceLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) + : SchedulableLoader(parameters, connection) + , m_delayedReply(reply) +{ +} + +void SyncNetworkResourceLoader::start() +{ + // FIXME (NetworkProcess): This is called on the NetworkProcess main thread, blocking any other requests from being scheduled. + // This should move to a background thread, but we'd either need to be sure that: + // A - ResourceHandle::loadResourceSynchronously is safe to run on a background thread. + // B - Write custom loading logic that is known to be safe on a background thread. + + ASSERT(isMainThread()); + + ResourceError error; + ResourceResponse response; + Vector<char> data; + + // FIXME (NetworkProcess): Create RemoteNetworkingContext with actual settings. + RefPtr<RemoteNetworkingContext> networkingContext = RemoteNetworkingContext::create(false, false, inPrivateBrowsingMode(), shouldClearReferrerOnHTTPSToHTTPRedirect()); + + consumeSandboxExtensions(); + + ResourceHandle::loadResourceSynchronously(networkingContext.get(), request(), allowStoredCredentials(), error, response, data); + + cleanup(); + + m_delayedReply->send(error, response, CoreIPC::DataReference((uint8_t*)data.data(), data.size())); +} + +void SyncNetworkResourceLoader::abort() +{ + cleanup(); +} + +void SyncNetworkResourceLoader::cleanup() +{ + invalidateSandboxExtensions(); + NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoader(this); +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.h b/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.h new file mode 100644 index 000000000..a60929b76 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/SyncNetworkResourceLoader.h @@ -0,0 +1,61 @@ +/* + * 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 SyncNetworkResourceLoader_h +#define SyncNetworkResourceLoader_h + +#include "NetworkConnectionToWebProcessMessages.h" +#include "SchedulableLoader.h" +#include <wtf/RefCounted.h> + +#if ENABLE(NETWORK_PROCESS) + +namespace WebKit { + +class SyncNetworkResourceLoader : public SchedulableLoader { +public: + static PassRefPtr<SyncNetworkResourceLoader> create(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply) + { + return adoptRef(new SyncNetworkResourceLoader(parameters, connection, reply)); + } + + virtual void start() OVERRIDE; + virtual void abort() OVERRIDE; + + virtual bool isSynchronous() OVERRIDE { return true; } + +private: + SyncNetworkResourceLoader(const NetworkResourceLoadParameters&, NetworkConnectionToWebProcess*, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>); + + void cleanup(); + + RefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> m_delayedReply; +}; + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) + +#endif // SyncNetworkResourceLoader_h diff --git a/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.h b/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.h new file mode 100644 index 000000000..c137995e5 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.h @@ -0,0 +1,60 @@ +/* + * 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 DiskCacheMonitor_h +#define DiskCacheMonitor_h + +#include "MessageSender.h" +#include <WebCore/ResourceRequest.h> +#include <WebCore/RunLoop.h> + +typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef; + +namespace WebKit { + +class NetworkConnectionToWebProcess; +class NetworkResourceLoader; + +class DiskCacheMonitor : public CoreIPC::MessageSender { +public: + static void monitorFileBackingStoreCreation(CFCachedURLResponseRef, NetworkResourceLoader*); + + const WebCore::ResourceRequest& resourceRequest() const { return m_resourceRequest; } + +private: + DiskCacheMonitor(CFCachedURLResponseRef, NetworkResourceLoader*); + + // CoreIPC::MessageSender + virtual CoreIPC::Connection* messageSenderConnection() OVERRIDE; + virtual uint64_t messageSenderDestinationID() OVERRIDE; + + RefPtr<NetworkConnectionToWebProcess> m_connectionToWebProcess; + WebCore::ResourceRequest m_resourceRequest; +}; + + +} // namespace WebKit + +#endif // DiskCacheMonitor_h diff --git a/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.mm b/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.mm new file mode 100644 index 000000000..34c81e61d --- /dev/null +++ b/Source/WebKit2/NetworkProcess/mac/DiskCacheMonitor.mm @@ -0,0 +1,109 @@ +/* + * 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. + */ + +#import "config.h" +#import "DiskCacheMonitor.h" + +#import "NetworkConnectionToWebProcess.h" +#import "NetworkProcessConnectionMessages.h" +#import "NetworkResourceLoader.h" +#import "WebCoreArgumentCoders.h" + +#ifdef __has_include +#if __has_include(<CFNetwork/CFURLCachePriv.h>) +#include <CFNetwork/CFURLCachePriv.h> +#endif +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + +typedef void (^CFCachedURLResponseCallBackBlock)(CFCachedURLResponseRef); +extern "C" void _CFCachedURLResponseSetBecameFileBackedCallBackBlock(CFCachedURLResponseRef, CFCachedURLResponseCallBackBlock, dispatch_queue_t); + +using namespace WebCore; + +namespace WebKit { + +// The maximum number of seconds we'll try to wait for a resource to be disk cached before we forget the request. +static const double diskCacheMonitorTimeout = 20; + +void DiskCacheMonitor::monitorFileBackingStoreCreation(CFCachedURLResponseRef cachedResponse, NetworkResourceLoader* loader) +{ + if (!cachedResponse) + return; + + ASSERT(loader); + + new DiskCacheMonitor(cachedResponse, loader); // Balanced by adoptPtr in the blocks setup in the constructor, one of which is guaranteed to run. +} + +DiskCacheMonitor::DiskCacheMonitor(CFCachedURLResponseRef cachedResponse, NetworkResourceLoader* loader) + : m_connectionToWebProcess(loader->connectionToWebProcess()) + , m_resourceRequest(loader->request()) +{ + ASSERT(isMainThread()); + + // Set up a delayed callback to cancel this monitor if the resource hasn't been cached yet. + __block DiskCacheMonitor* rawMonitor = this; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * diskCacheMonitorTimeout), dispatch_get_main_queue(), ^{ + adoptPtr(rawMonitor); // Balanced by `new DiskCacheMonitor` in monitorFileBackingStoreCreation. + rawMonitor = 0; + }); + + // Set up the disk caching callback to create the ShareableResource and send it to the WebProcess. + CFCachedURLResponseCallBackBlock block = ^(CFCachedURLResponseRef cachedResponse) + { + // If the monitor isn't there then it timed out before this resource was cached to disk. + if (!rawMonitor) + return; + + OwnPtr<DiskCacheMonitor> monitor = adoptPtr(rawMonitor); // Balanced by `new DiskCacheMonitor` in monitorFileBackingStoreCreation. + rawMonitor = 0; + + ShareableResource::Handle handle; + NetworkResourceLoader::tryGetShareableHandleFromCFURLCachedResponse(handle, cachedResponse); + if (handle.isNull()) + return; + + monitor->send(Messages::NetworkProcessConnection::DidCacheResource(monitor->resourceRequest(), handle)); + }; + + _CFCachedURLResponseSetBecameFileBackedCallBackBlock(cachedResponse, block, dispatch_get_main_queue()); +} + +CoreIPC::Connection* DiskCacheMonitor::messageSenderConnection() +{ + return m_connectionToWebProcess->connection(); +} + +uint64_t DiskCacheMonitor::messageSenderDestinationID() +{ + return 0; +} + +} // namespace WebKit + +#endif // #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 diff --git a/Source/WebKit2/NetworkProcess/mac/NetworkProcessMac.mm b/Source/WebKit2/NetworkProcess/mac/NetworkProcessMac.mm index e635acb19..3e96fa4dc 100644 --- a/Source/WebKit2/NetworkProcess/mac/NetworkProcessMac.mm +++ b/Source/WebKit2/NetworkProcess/mac/NetworkProcessMac.mm @@ -29,22 +29,203 @@ #if ENABLE(NETWORK_PROCESS) #import "NetworkProcessCreationParameters.h" +#import "NetworkResourceLoader.h" +#import "PlatformCertificateInfo.h" +#import "ResourceCachesToClear.h" +#import "SandboxExtension.h" +#import "SandboxInitializationParameters.h" +#import "StringUtilities.h" +#import <WebCore/FileSystem.h> #import <WebCore/LocalizedStrings.h> #import <WebKitSystemInterface.h> +#import <mach/host_info.h> +#import <mach/mach.h> +#import <mach/mach_error.h> +#import <sysexits.h> #import <wtf/text/WTFString.h> +#if USE(SECURITY_FRAMEWORK) +#import "SecItemShim.h" +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +typedef struct _CFURLCache* CFURLCacheRef; +extern "C" CFURLCacheRef CFURLCacheCopySharedURLCache(); +extern "C" void _CFURLCacheSetMinSizeForVMCachedResource(CFURLCacheRef, CFIndex); +#endif + using namespace WebCore; +@interface NSURLRequest (Details) ++ (void)setAllowsSpecificHTTPSCertificate:(NSArray *)allow forHost:(NSString *)host; +@end + namespace WebKit { -void NetworkProcess::platformInitialize(const NetworkProcessCreationParameters& parameters) +void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&) { - NSString *applicationName = [NSString stringWithFormat:WEB_UI_STRING("%@ Networking", "visible name of the network process. The argument is the application name."), - (NSString *)parameters.parentProcessName]; - + // Having a window server connection in this process would result in spin logs (<rdar://problem/13239119>). + setApplicationIsDaemon(); +} + +void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters& parameters) +{ + NSString *applicationName = [NSString stringWithFormat:WEB_UI_STRING("%@ Networking", "visible name of the network process. The argument is the application name."), (NSString *)parameters.uiProcessName]; WKSetVisibleApplicationName((CFStringRef)applicationName); } +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +static void overrideSystemProxies(const String& httpProxy, const String& httpsProxy) +{ + NSMutableDictionary *proxySettings = [NSMutableDictionary dictionary]; + + if (!httpProxy.isNull()) { + KURL httpProxyURL(KURL(), httpProxy); + if (httpProxyURL.isValid()) { + [proxySettings setObject:nsStringFromWebCoreString(httpProxyURL.host()) forKey:(NSString *)kCFNetworkProxiesHTTPProxy]; + if (httpProxyURL.hasPort()) { + NSNumber *port = [NSNumber numberWithInt:httpProxyURL.port()]; + [proxySettings setObject:port forKey:(NSString *)kCFNetworkProxiesHTTPPort]; + } + } + else + NSLog(@"Malformed HTTP Proxy URL '%s'. Expected 'http://<hostname>[:<port>]'\n", httpProxy.utf8().data()); + } + + if (!httpsProxy.isNull()) { + KURL httpsProxyURL(KURL(), httpsProxy); + if (httpsProxyURL.isValid()) { + [proxySettings setObject:nsStringFromWebCoreString(httpsProxyURL.host()) forKey:(NSString *)kCFNetworkProxiesHTTPSProxy]; + if (httpsProxyURL.hasPort()) { + NSNumber *port = [NSNumber numberWithInt:httpsProxyURL.port()]; + [proxySettings setObject:port forKey:(NSString *)kCFNetworkProxiesHTTPSPort]; + } + } else + NSLog(@"Malformed HTTPS Proxy URL '%s'. Expected 'https://<hostname>[:<port>]'\n", httpsProxy.utf8().data()); + } + + if ([proxySettings count] > 0) + WKCFNetworkSetOverrideSystemProxySettings((CFDictionaryRef)proxySettings); +} +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + +void NetworkProcess::platformInitializeNetworkProcess(const NetworkProcessCreationParameters& parameters) +{ + m_diskCacheDirectory = parameters.diskCacheDirectory; + + if (!m_diskCacheDirectory.isNull()) { + SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle); + [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc] + initWithMemoryCapacity:parameters.nsURLCacheMemoryCapacity + diskCapacity:parameters.nsURLCacheDiskCapacity + diskPath:parameters.diskCacheDirectory]).get()]; + } + +#if USE(SECURITY_FRAMEWORK) + SecItemShim::shared().initialize(this); +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + if (!parameters.httpProxy.isNull() || !parameters.httpsProxy.isNull()) + overrideSystemProxies(parameters.httpProxy, parameters.httpsProxy); +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + RetainPtr<CFURLCacheRef> cache = adoptCF(CFURLCacheCopySharedURLCache()); + if (!cache) + return; + + _CFURLCacheSetMinSizeForVMCachedResource(cache.get(), NetworkResourceLoader::fileBackedResourceMinimumSize()); +#endif +} + +static uint64_t memorySize() +{ + static host_basic_info_data_t hostInfo; + + static dispatch_once_t once; + dispatch_once(&once, ^() { + mach_port_t host = mach_host_self(); + mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; + kern_return_t r = host_info(host, HOST_BASIC_INFO, (host_info_t)&hostInfo, &count); + mach_port_deallocate(mach_task_self(), host); + + if (r != KERN_SUCCESS) + LOG_ERROR("%s : host_info(%d) : %s.\n", __FUNCTION__, r, mach_error_string(r)); + }); + + return hostInfo.max_mem; +} + +static uint64_t volumeFreeSize(const String& path) +{ + NSDictionary *fileSystemAttributesDictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:(NSString *)path error:NULL]; + return [[fileSystemAttributesDictionary objectForKey:NSFileSystemFreeSize] unsignedLongLongValue]; +} + +void NetworkProcess::platformSetCacheModel(CacheModel cacheModel) +{ + + // As a fudge factor, use 1000 instead of 1024, in case the reported byte + // count doesn't align exactly to a megabyte boundary. + uint64_t memSize = memorySize() / 1024 / 1000; + uint64_t diskFreeSize = volumeFreeSize(m_diskCacheDirectory) / 1024 / 1000; + + unsigned cacheTotalCapacity = 0; + unsigned cacheMinDeadCapacity = 0; + unsigned cacheMaxDeadCapacity = 0; + double deadDecodedDataDeletionInterval = 0; + unsigned pageCacheCapacity = 0; + unsigned long urlCacheMemoryCapacity = 0; + unsigned long urlCacheDiskCapacity = 0; + + calculateCacheSizes(cacheModel, memSize, diskFreeSize, + cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval, + pageCacheCapacity, urlCacheMemoryCapacity, urlCacheDiskCapacity); + + + NSURLCache *nsurlCache = [NSURLCache sharedURLCache]; + [nsurlCache setMemoryCapacity:urlCacheMemoryCapacity]; + [nsurlCache setDiskCapacity:std::max<unsigned long>(urlCacheDiskCapacity, [nsurlCache diskCapacity])]; // Don't shrink a big disk cache, since that would cause churn. +} + +void NetworkProcess::allowSpecificHTTPSCertificateForHost(const PlatformCertificateInfo& certificateInfo, const String& host) +{ + [NSURLRequest setAllowsSpecificHTTPSCertificate:(NSArray *)certificateInfo.certificateChain() forHost:(NSString *)host]; +} + +void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters& parameters, SandboxInitializationParameters& sandboxParameters) +{ + // Need to overide the default, because service has a different bundle ID. + NSBundle *webkit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKView")]; + sandboxParameters.setOverrideSandboxProfilePath([webkit2Bundle pathForResource:@"com.apple.WebKit.NetworkProcess" ofType:@"sb"]); + + ChildProcess::initializeSandbox(parameters, sandboxParameters); +} + +void NetworkProcess::clearCacheForAllOrigins(uint32_t cachesToClear) +{ + ResourceCachesToClear resourceCachesToClear = static_cast<ResourceCachesToClear>(cachesToClear); + if (resourceCachesToClear == InMemoryResourceCachesOnly) + return; + + if (!m_clearCacheDispatchGroup) + m_clearCacheDispatchGroup = dispatch_group_create(); + + dispatch_group_async(m_clearCacheDispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [[NSURLCache sharedURLCache] removeAllCachedResponses]; + }); +} + +void NetworkProcess::platformTerminate() +{ + if (m_clearCacheDispatchGroup) { + dispatch_group_wait(m_clearCacheDispatchGroup, DISPATCH_TIME_FOREVER); + dispatch_release(m_clearCacheDispatchGroup); + m_clearCacheDispatchGroup = 0; + } +} + } // namespace WebKit #endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/mac/NetworkProcessMainMac.mm b/Source/WebKit2/NetworkProcess/mac/NetworkProcessMainMac.mm deleted file mode 100644 index c56f80a2a..000000000 --- a/Source/WebKit2/NetworkProcess/mac/NetworkProcessMainMac.mm +++ /dev/null @@ -1,99 +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. - */ - -#import "config.h" -#import "NetworkProcessMain.h" - -#if ENABLE(NETWORK_PROCESS) - -#import "CommandLine.h" -#import "EnvironmentUtilities.h" -#import "NetworkProcess.h" -#import <WebCore/RunLoop.h> -#import <WebKitSystemInterface.h> -#import <WebSystemInterface.h> -#import <mach/mach_error.h> -#import <runtime/InitializeThreading.h> -#import <servers/bootstrap.h> -#import <stdio.h> -#import <wtf/MainThread.h> -#import <wtf/RetainPtr.h> -#import <wtf/text/CString.h> -#import <wtf/text/WTFString.h> - -#define SHOW_CRASH_REPORTER 1 - -using namespace WebCore; - -namespace WebKit { - -// FIXME: There is much code here that is duplicated in WebProcessMainMac.mm, we should add a shared base class where -// we can put everything. - -int NetworkProcessMain(const CommandLine& commandLine) -{ - String serviceName = commandLine["servicename"]; - if (serviceName.isEmpty()) - return EXIT_FAILURE; - - // Get the server port. - mach_port_t serverPort; - kern_return_t kr = bootstrap_look_up(bootstrap_port, serviceName.utf8().data(), &serverPort); - if (kr) { - WTFLogAlways("bootstrap_look_up result: %s (%x)\n", mach_error_string(kr), kr); - return EXIT_FAILURE; - } - - String localization = commandLine["localization"]; - RetainPtr<CFStringRef> cfLocalization(AdoptCF, CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(localization.characters()), localization.length())); - if (cfLocalization) - WKSetDefaultLocalization(cfLocalization.get()); - -#if !SHOW_CRASH_REPORTER - // Installs signal handlers that exit on a crash so that CrashReporter does not show up. - signal(SIGILL, _exit); - signal(SIGFPE, _exit); - signal(SIGBUS, _exit); - signal(SIGSEGV, _exit); -#endif - - InitWebCoreSystemInterface(); - JSC::initializeThreading(); - WTF::initializeMainThread(); - RunLoop::initializeMainRunLoop(); - - // Initialize the network process connection. - NetworkProcess::shared().initialize(CoreIPC::Connection::Identifier(serverPort), RunLoop::main()); - - [NSApplication sharedApplication]; - - RunLoop::run(); - - return 0; -} - -} // namespace WebKit - -#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm b/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm index 14b3657b9..15f21c47b 100644 --- a/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm +++ b/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm @@ -37,13 +37,15 @@ using namespace WebCore; namespace WebKit { -unsigned NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost() +void NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost() { wkInitializeMaximumHTTPConnectionCountPerHost = WKInitializeMaximumHTTPConnectionCountPerHost; wkSetHTTPPipeliningMaximumPriority = WKSetHTTPPipeliningMaximumPriority; wkSetHTTPPipeliningMinimumFastLanePriority = WKSetHTTPPipeliningMinimumFastLanePriority; - static const unsigned preferredConnectionCount = 6; + // Our preferred connection-per-host limit is the standard 6, but we need to let CFNetwork handle a 7th + // in case a synchronous XHRs is made while 6 loads are already outstanding. + static const unsigned preferredConnectionCount = 7; static const unsigned unlimitedConnectionCount = 10000; // Always set the connection count per host, even when pipelining. @@ -60,10 +62,13 @@ unsigned NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCo wkSetHTTPPipeliningMinimumFastLanePriority(toHTTPPipeliningPriority(ResourceLoadPriorityMedium)); // When pipelining do not rate-limit requests sent from WebCore since CFNetwork handles that. - return unlimitedConnectionCount; + m_maxRequestsInFlightPerHost = unlimitedConnectionCount; + + return; } - return maximumHTTPConnectionCountPerHost; + // We've asked for one more connection per host than we intend to use in most cases so synch XHRs can bypass that limit. + m_maxRequestsInFlightPerHost = maximumHTTPConnectionCountPerHost - 1; } } // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoaderMac.mm b/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoaderMac.mm new file mode 100644 index 000000000..84ea149c7 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoaderMac.mm @@ -0,0 +1,116 @@ +/* + * 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. + */ + +#import "config.h" +#import "NetworkResourceLoader.h" + +#import "DiskCacheMonitor.h" +#import "ShareableResource.h" +#import <WebCore/ResourceHandle.h> +#import <WebCore/SharedBuffer.h> + +using namespace WebCore; + +#ifdef __has_include +#if __has_include(<CFNetwork/CFURLCache.h>) +#include <CFNetwork/CFURLCache.h> +#endif +#if __has_include(<CFNetwork/CFURLCachePriv.h>) +#include <CFNetwork/CFURLCachePriv.h> +#endif +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +typedef const struct _CFURLCache* CFURLCacheRef; +typedef const struct _CFCachedURLResponse* CFCachedURLResponseRef; +extern "C" CFURLCacheRef CFURLCacheCopySharedURLCache(); +extern "C" CFCachedURLResponseRef CFURLCacheCopyResponseForRequest(CFURLCacheRef, CFURLRequestRef); +extern "C" CFDataRef _CFCachedURLResponseGetMemMappedData(CFCachedURLResponseRef); +extern "C" CFBooleanRef _CFURLCacheIsResponseDataMemMapped(CFURLCacheRef, CFDataRef); +#endif + +@interface NSCachedURLResponse (NSCachedURLResponseDetails) +-(CFCachedURLResponseRef)_CFCachedURLResponse; +@end + +namespace WebKit { + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + +static void tryGetShareableHandleFromCFData(ShareableResource::Handle& handle, CFDataRef data) +{ + if (!data || CFDataGetLength(data) < (CFIndex)NetworkResourceLoader::fileBackedResourceMinimumSize()) + return; + + RefPtr<SharedMemory> sharedMemory = SharedMemory::createFromVMBuffer((void*)CFDataGetBytePtr(data), CFDataGetLength(data)); + if (!sharedMemory) { + LOG_ERROR("Failed to create VM shared memory for cached resource."); + return; + } + + size_t size = sharedMemory->size(); + RefPtr<ShareableResource> resource = ShareableResource::create(sharedMemory.release(), 0, size); + resource->createHandle(handle); +} + +void NetworkResourceLoader::tryGetShareableHandleFromCFURLCachedResponse(ShareableResource::Handle& handle, CFCachedURLResponseRef cachedResponse) +{ + CFDataRef data = _CFCachedURLResponseGetMemMappedData(cachedResponse); + + tryGetShareableHandleFromCFData(handle, data); +} + +void NetworkResourceLoader::tryGetShareableHandleFromSharedBuffer(ShareableResource::Handle& handle, SharedBuffer* buffer) +{ + RetainPtr<CFURLCacheRef> cache = adoptCF(CFURLCacheCopySharedURLCache()); + if (!cache) + return; + + RetainPtr<CFDataRef> data = adoptCF(buffer->createCFData()); + if (_CFURLCacheIsResponseDataMemMapped(cache.get(), data.get()) == kCFBooleanFalse) + return; + + tryGetShareableHandleFromCFData(handle, data.get()); +} +#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + +size_t NetworkResourceLoader::fileBackedResourceMinimumSize() +{ + return SharedMemory::systemPageSize(); +} + +void NetworkResourceLoader::willCacheResponseAsync(ResourceHandle* handle, NSCachedURLResponse *nsResponse) +{ + ASSERT_UNUSED(handle, handle == m_handle); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + if (m_bytesReceived >= fileBackedResourceMinimumSize()) + DiskCacheMonitor::monitorFileBackingStoreCreation([nsResponse _CFCachedURLResponse], this); +#endif + + m_handle->continueWillCacheResponse(nsResponse); +} + +} // namespace WebKit diff --git a/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.h b/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.h index 8f51186b4..d0402246b 100644 --- a/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.h +++ b/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.h @@ -32,25 +32,35 @@ namespace WebKit { class RemoteNetworkingContext : public WebCore::NetworkingContext { public: - static PassRefPtr<RemoteNetworkingContext> create(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled) + static PassRefPtr<RemoteNetworkingContext> create(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled, bool privateBrowsingEnabled, bool shouldClearReferrerOnHTTPSToHTTPRedirect) { - return adoptRef(new RemoteNetworkingContext(needsSiteSpecificQuirks, localFileContentSniffingEnabled)); + return adoptRef(new RemoteNetworkingContext(needsSiteSpecificQuirks, localFileContentSniffingEnabled, privateBrowsingEnabled, shouldClearReferrerOnHTTPSToHTTPRedirect)); } virtual ~RemoteNetworkingContext(); + static void setPrivateBrowsingStorageSessionIdentifierBase(const String&); + static void ensurePrivateBrowsingSession(); + static void destroyPrivateBrowsingSession(); + + static WebCore::NetworkStorageSession* privateBrowsingSession(); + + virtual bool shouldClearReferrerOnHTTPSToHTTPRedirect() const OVERRIDE; + private: - RemoteNetworkingContext(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled); + RemoteNetworkingContext(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled, bool privateBrowsingEnabled, bool m_shouldClearReferrerOnHTTPSToHTTPRedirect); virtual bool isValid() const OVERRIDE; virtual bool needsSiteSpecificQuirks() const OVERRIDE; virtual bool localFileContentSniffingEnabled() const OVERRIDE; - virtual CFURLStorageSessionRef storageSession() const OVERRIDE; - virtual NSOperationQueue *scheduledOperationQueue() const OVERRIDE; + virtual WebCore::NetworkStorageSession& storageSession() const OVERRIDE; + virtual RetainPtr<CFDataRef> sourceApplicationAuditData() const OVERRIDE; virtual WebCore::ResourceError blockedError(const WebCore::ResourceRequest&) const OVERRIDE; bool m_needsSiteSpecificQuirks; bool m_localFileContentSniffingEnabled; + bool m_privateBrowsingEnabled; + bool m_shouldClearReferrerOnHTTPSToHTTPRedirect; }; } diff --git a/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.mm b/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.mm index 0eb7024f6..53ec91c5d 100644 --- a/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.mm +++ b/Source/WebKit2/NetworkProcess/mac/RemoteNetworkingContext.mm @@ -26,16 +26,33 @@ #import "config.h" #import "RemoteNetworkingContext.h" -#import "WebCore/ResourceError.h" #import "WebErrors.h" +#import <WebCore/ResourceError.h> +#import <WebKitSystemInterface.h> +#import <wtf/MainThread.h> +#import <wtf/PassOwnPtr.h> using namespace WebCore; namespace WebKit { -RemoteNetworkingContext::RemoteNetworkingContext(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled) +static OwnPtr<NetworkStorageSession>& privateBrowsingStorageSession() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(OwnPtr<NetworkStorageSession>, session, ()); + return session; +} + +bool RemoteNetworkingContext::shouldClearReferrerOnHTTPSToHTTPRedirect() const +{ + return m_shouldClearReferrerOnHTTPSToHTTPRedirect; +} + +RemoteNetworkingContext::RemoteNetworkingContext(bool needsSiteSpecificQuirks, bool localFileContentSniffingEnabled, bool privateBrowsingEnabled, bool shouldClearReferrerOnHTTPSToHTTPRedirect) : m_needsSiteSpecificQuirks(needsSiteSpecificQuirks) , m_localFileContentSniffingEnabled(localFileContentSniffingEnabled) + , m_privateBrowsingEnabled(privateBrowsingEnabled) + , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect) { } @@ -58,21 +75,28 @@ bool RemoteNetworkingContext::localFileContentSniffingEnabled() const return m_localFileContentSniffingEnabled; } -CFURLStorageSessionRef RemoteNetworkingContext::storageSession() const +NetworkStorageSession& RemoteNetworkingContext::storageSession() const { - // FIXME (NetworkProcess): Implement. - return 0; + if (m_privateBrowsingEnabled) { + NetworkStorageSession* privateSession = privateBrowsingStorageSession().get(); + 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."); + } + + return NetworkStorageSession::defaultStorageSession(); } -NSOperationQueue *RemoteNetworkingContext::scheduledOperationQueue() const +NetworkStorageSession* RemoteNetworkingContext::privateBrowsingSession() { - static NSOperationQueue *queue; - if (!queue) { - queue = [[NSOperationQueue alloc] init]; - // Default concurrent operation count depends on current system workload, but delegate methods are mostly idling in IPC, so we can run as many as needed. - [queue setMaxConcurrentOperationCount:NSIntegerMax]; - } - return queue; + return privateBrowsingStorageSession().get(); +} + +RetainPtr<CFDataRef> RemoteNetworkingContext::sourceApplicationAuditData() const +{ + return nil; } ResourceError RemoteNetworkingContext::blockedError(const ResourceRequest& request) const @@ -80,4 +104,32 @@ ResourceError RemoteNetworkingContext::blockedError(const ResourceRequest& reque return WebKit::blockedError(request); } +static String& privateBrowsingStorageSessionIdentifierBase() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(String, base, ()); + return base; +} + +void RemoteNetworkingContext::setPrivateBrowsingStorageSessionIdentifierBase(const String& identifier) +{ + privateBrowsingStorageSessionIdentifierBase() = identifier; +} + +void RemoteNetworkingContext::ensurePrivateBrowsingSession() +{ + if (privateBrowsingStorageSession()) + return; + + ASSERT(!privateBrowsingStorageSessionIdentifierBase().isNull()); + RetainPtr<CFStringRef> cfIdentifier = String(privateBrowsingStorageSessionIdentifierBase() + ".PrivateBrowsing").createCFString(); + + privateBrowsingStorageSession() = NetworkStorageSession::createPrivateBrowsingSession(privateBrowsingStorageSessionIdentifierBase()); +} + +void RemoteNetworkingContext::destroyPrivateBrowsingSession() +{ + privateBrowsingStorageSession() = nullptr; +} + } diff --git a/Source/WebKit2/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in b/Source/WebKit2/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in new file mode 100644 index 000000000..7ba86c038 --- /dev/null +++ b/Source/WebKit2/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in @@ -0,0 +1,148 @@ +(version 1) +(deny default (with partial-symbolication)) +(allow system-audit file-read-metadata) + +(import "system.sb") + +;; Utility functions for home directory relative path filters +(define (home-regex home-relative-regex) + (regex (string-append "^" (regex-quote (param "HOME_DIR")) home-relative-regex))) + +(define (home-subpath home-relative-subpath) + (subpath (string-append (param "HOME_DIR") home-relative-subpath))) + +(define (home-literal home-relative-literal) + (literal (string-append (param "HOME_DIR") home-relative-literal))) + +#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1070 +;; Low level networking. Defined in system.sb on newer OS versions. +(define (system-network) + (allow file-read* + (literal "/Library/Preferences/com.apple.networkd.plist")) + (allow mach-lookup + (global-name "com.apple.SystemConfiguration.PPPController") + (global-name "com.apple.SystemConfiguration.SCNetworkReachability") + (global-name "com.apple.networkd")) + (allow network-outbound + (control-name "com.apple.netsrc") + (control-name "com.apple.network.statistics")) + (allow system-socket + (require-all (socket-domain AF_SYSTEM) + (socket-protocol 2)) ; SYSPROTO_CONTROL + (socket-domain AF_ROUTE))) +#endif + +;; Read-only preferences and data +(allow file-read* + ;; Basic system paths + (subpath "/Library/Frameworks") + (subpath "/Library/Managed Preferences") + + ;; System and user preferences + (literal "/Library/Preferences/.GlobalPreferences.plist") + (regex #"^/Library/Managed Preferences/[^/]+/com\.apple\.networkConnect\.plist$") + (home-literal "/Library/Preferences/.GlobalPreferences.plist") + (home-regex #"/Library/Preferences/ByHost/\.GlobalPreferences\.") + (home-regex #"/Library/Preferences/ByHost/com\.apple\.networkConnect\.") + (home-literal "/Library/Preferences/com.apple.DownloadAssessment.plist") + (home-literal "/Library/Preferences/com.apple.WebFoundation.plist") + + ;; On-disk WebKit2 framework location, to account for debug installations + ;; outside of /System/Library/Frameworks + (subpath (param "WEBKIT2_FRAMEWORK_DIR"))) + +;; Sandbox extensions +(define (apply-read-and-issue-extension op path-filter) + (op file-read* path-filter) + (op file-issue-extension (require-all (extension-class "com.apple.app-sandbox.read") path-filter))) +(define (apply-write-and-issue-extension op path-filter) + (op file-write* path-filter) + (op file-issue-extension (require-all (extension-class "com.apple.app-sandbox.read-write") path-filter))) +(define (read-only-and-issue-extensions path-filter) + (apply-read-and-issue-extension allow path-filter)) +(define (read-write-and-issue-extensions path-filter) + (apply-read-and-issue-extension allow path-filter) + (apply-write-and-issue-extension allow path-filter)) +(read-only-and-issue-extensions (extension "com.apple.app-sandbox.read")) +(read-write-and-issue-extensions (extension "com.apple.app-sandbox.read-write")) + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +(allow file-read* file-write* (subpath (param "DARWIN_USER_CACHE_DIR"))) +#else +(allow file-read* file-write* (subpath (string-append (param "DARWIN_USER_CACHE_DIR") "/mds"))) +#endif + +(allow file-read* file-write* (subpath (param "DARWIN_USER_TEMP_DIR"))) + +;; IOKit user clients +(allow iokit-open + (iokit-user-client-class "RootDomainUserClient")) + +;; cookied. +;; FIXME: Update for <rdar://problem/13642852>. +(allow ipc-posix-shm-read-data + (ipc-posix-name "FNetwork.defaultStorageSession") + (ipc-posix-name-regex #"\.PrivateBrowsing-") + (ipc-posix-name-regex #"^Private WebKit Session-")) + +;; Various services required by CFNetwork and other frameworks +(allow mach-lookup + (global-name "com.apple.PowerManagement.control") + (global-name "com.apple.SystemConfiguration.configd") + (global-name "com.apple.cookied") + (global-name "com.apple.cfnetwork.AuthBrokerAgent")) + +;; Security framework +(allow mach-lookup + (global-name "com.apple.ocspd") + (global-name "com.apple.SecurityServer")) +(allow file-read* file-write* (home-subpath "/Library/Keychains")) ;; FIXME: This should be removed when <rdar://problem/10479685> is fixed. +(allow file-read* file-write* (subpath "/private/var/db/mds/system")) ;; FIXME: This should be removed when <rdar://problem/9538414> is fixed. +(allow file-read* + (subpath "/Library/Keychains") + (subpath "/private/var/db/mds") + (literal "/private/var/db/DetachedSignatures") + (literal "/Library/Preferences/com.apple.crypto.plist") + (literal "/Library/Preferences/com.apple.security.plist") + (literal "/Library/Preferences/com.apple.security.common.plist") + (literal "/Library/Preferences/com.apple.security.revocation.plist") + (home-literal "/Library/Application Support/SyncServices/Local/ClientsWithChanges/com.apple.Keychain") + (home-literal "/Library/Preferences/com.apple.security.plist") + (home-literal "/Library/Preferences/com.apple.security.revocation.plist")) +(allow ipc-posix-shm-read* ipc-posix-shm-write-data + (ipc-posix-name "com.apple.AppleDatabaseChanged")) + +(system-network) +(allow network-outbound + ;; Local mDNSResponder for DNS, arbitrary outbound TCP + (literal "/private/var/run/mDNSResponder") + (remote tcp)) + +;; FIXME should be removed when <rdar://problem/9347205> + related radar in Safari is fixed +(allow mach-lookup + (global-name "org.h5l.kcm") + (global-name "com.apple.system.logger") + (global-name "com.apple.system.notification_center")) +(allow network-outbound + (remote udp)) +(allow file-read* + (home-subpath "/Library/Preferences/com.apple.Kerberos.plist") + (home-subpath "/Library/Preferences/com.apple.GSS.plist") + (home-subpath "/Library/Preferences/edu.mit.Kerberos") + (literal "/Library/Preferences/com.apple.Kerberos.plist") + (literal "/Library/Preferences/com.apple.GSS.plist") + (literal "/Library/Preferences/edu.mit.Kerberos") + (literal "/private/etc/krb5.conf") + (literal "/private/etc/services") + (literal "/private/etc/host")) + +(if (defined? 'vnode-type) + (deny file-write-create (vnode-type SYMLINK))) + +(deny file-read* file-write* (with no-log) +#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 + (home-literal "/Library/Caches/Cache.db") ;; <rdar://problem/9422957> +#endif + ;; FIXME: Should be removed after <rdar://problem/10463881> is fixed. + (home-literal "/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2") + (home-literal "/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2-journal")) diff --git a/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.cpp b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.cpp new file mode 100644 index 000000000..c82af840e --- /dev/null +++ b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.cpp @@ -0,0 +1,80 @@ +/* + * 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 + * 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 THE COPYRIGHT HOLDERS ``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 "NetworkProcessMainUnix.h" + +#if ENABLE(NETWORK_PROCESS) + +#include "WKBase.h" +#include "WebKit2Initialize.h" +#include <WebCore/RunLoop.h> +#include <WebKit2/NetworkProcess.h> +#include <error.h> +#include <runtime/InitializeThreading.h> +#include <stdlib.h> +#include <wtf/MainThread.h> + +#if PLATFORM(EFL) +#include <Ecore.h> +#endif + +using namespace WebCore; + +namespace WebKit { + +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(); + + // FIXME: handle proxy settings. + + int socket = atoi(argv[1]); + + WebKit::ChildProcessInitializationParameters parameters; + parameters.connectionIdentifier = int(socket); + + NetworkProcess::shared().initialize(parameters); + + RunLoop::run(); + + return 0; +} + +} // namespace WebKit + +#endif // ENABLE(NETWORK_PROCESS) diff --git a/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h new file mode 100644 index 000000000..cb62eda2d --- /dev/null +++ b/Source/WebKit2/NetworkProcess/unix/NetworkProcessMainUnix.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 University of Szeged. 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 + * 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 NetworkProcessMainUnix_h +#define NetworkProcessMainUnix_h + +#include <WebKit2/WKBase.h> + +namespace WebKit { + +#ifdef __cplusplus +extern "C" { +WK_EXPORT int NetworkProcessMain(int argc, char* argv[]); +} // extern "C" +#endif // __cplusplus + +} // namespace WebKit + +#endif // NetworkProcessMainUnix_h |