2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "NetworkProcess.h"
29 #include "ArgumentCoders.h"
30 #include "Attachment.h"
31 #include "AuthenticationManager.h"
32 #include "ChildProcessMessages.h"
33 #include "CustomProtocolManager.h"
35 #include "NetworkConnectionToWebProcess.h"
36 #include "NetworkProcessCreationParameters.h"
37 #include "NetworkProcessPlatformStrategies.h"
38 #include "NetworkProcessProxyMessages.h"
39 #include "NetworkResourceLoader.h"
40 #include "RemoteNetworkingContext.h"
41 #include "SessionTracker.h"
42 #include "StatisticsData.h"
43 #include "WebCookieManager.h"
44 #include "WebProcessPoolMessages.h"
45 #include "WebsiteData.h"
46 #include <WebCore/DNS.h>
47 #include <WebCore/DiagnosticLoggingClient.h>
48 #include <WebCore/Logging.h>
49 #include <WebCore/PlatformCookieJar.h>
50 #include <WebCore/ResourceRequest.h>
51 #include <WebCore/SecurityOriginData.h>
52 #include <WebCore/SecurityOriginHash.h>
53 #include <WebCore/SessionID.h>
54 #include <wtf/RunLoop.h>
55 #include <wtf/text/CString.h>
57 #if ENABLE(SEC_ITEM_SHIM)
58 #include "SecItemShim.h"
61 #if ENABLE(NETWORK_CACHE)
62 #include "NetworkCache.h"
63 #include "NetworkCacheCoders.h"
66 using namespace WebCore;
70 NetworkProcess& NetworkProcess::singleton()
72 static NeverDestroyed<NetworkProcess> networkProcess;
73 return networkProcess;
76 NetworkProcess::NetworkProcess()
77 : m_hasSetCacheModel(false)
78 , m_cacheModel(CacheModelDocumentViewer)
79 , m_diskCacheIsDisabledForTesting(false)
80 , m_canHandleHTTPSServerTrustEvaluation(true)
82 , m_clearCacheDispatchGroup(0)
85 , m_webSQLiteDatabaseTracker(*this)
88 NetworkProcessPlatformStrategies::initialize();
90 addSupplement<AuthenticationManager>();
91 addSupplement<WebCookieManager>();
92 addSupplement<CustomProtocolManager>();
95 NetworkProcess::~NetworkProcess()
99 AuthenticationManager& NetworkProcess::authenticationManager()
101 return *supplement<AuthenticationManager>();
104 DownloadManager& NetworkProcess::downloadManager()
106 static NeverDestroyed<DownloadManager> downloadManager(this);
107 return downloadManager;
110 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
112 size_t vectorIndex = m_webProcessConnections.find(connection);
113 ASSERT(vectorIndex != notFound);
115 m_webProcessConnections.remove(vectorIndex);
118 bool NetworkProcess::shouldTerminate()
120 // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
124 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
126 if (messageReceiverMap().dispatchMessage(connection, decoder))
129 if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
130 ChildProcess::didReceiveMessage(connection, decoder);
134 didReceiveNetworkProcessMessage(connection, decoder);
137 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
139 if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
142 didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
145 void NetworkProcess::didClose(IPC::Connection&)
147 // The UIProcess just exited.
148 RunLoop::current().stop();
151 void NetworkProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
153 RunLoop::current().stop();
156 void NetworkProcess::didCreateDownload()
158 disableTermination();
161 void NetworkProcess::didDestroyDownload()
166 IPC::Connection* NetworkProcess::downloadProxyConnection()
168 return parentProcessConnection();
171 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
173 return authenticationManager();
176 void NetworkProcess::lowMemoryHandler(Critical critical)
178 platformLowMemoryHandler(critical);
179 WTF::releaseFastMallocFreeMemory();
182 void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters)
184 platformInitializeNetworkProcess(parameters);
186 WTF::setCurrentThreadIsUserInitiated();
188 auto& memoryPressureHandler = MemoryPressureHandler::singleton();
189 memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
190 lowMemoryHandler(critical);
192 memoryPressureHandler.install();
194 m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
196 m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
197 setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
199 setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
201 #if PLATFORM(MAC) || USE(CFNETWORK)
202 SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
205 // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
206 if (parameters.privateBrowsingEnabled)
207 RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
209 if (parameters.shouldUseTestingNetworkSession)
210 NetworkStorageSession::switchToNewTestingSession();
212 NetworkProcessSupplementMap::const_iterator it = m_supplements.begin();
213 NetworkProcessSupplementMap::const_iterator end = m_supplements.end();
214 for (; it != end; ++it)
215 it->value->initialize(parameters);
218 void NetworkProcess::initializeConnection(IPC::Connection* connection)
220 ChildProcess::initializeConnection(connection);
222 #if ENABLE(SEC_ITEM_SHIM)
223 SecItemShim::singleton().initializeConnection(connection);
226 NetworkProcessSupplementMap::const_iterator it = m_supplements.begin();
227 NetworkProcessSupplementMap::const_iterator end = m_supplements.end();
228 for (; it != end; ++it)
229 it->value->initializeConnection(connection);
232 void NetworkProcess::createNetworkConnectionToWebProcess()
234 #if USE(UNIX_DOMAIN_SOCKETS)
235 IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
237 RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(socketPair.server);
238 m_webProcessConnections.append(connection.release());
240 IPC::Attachment clientSocket(socketPair.client);
241 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
243 // Create the listening port.
244 mach_port_t listeningPort;
245 mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
247 // Create a listening connection.
248 RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
249 m_webProcessConnections.append(connection.release());
251 IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
252 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
258 void NetworkProcess::ensurePrivateBrowsingSession(SessionID sessionID)
260 RemoteNetworkingContext::ensurePrivateBrowsingSession(sessionID);
263 void NetworkProcess::destroyPrivateBrowsingSession(SessionID sessionID)
265 SessionTracker::destroySession(sessionID);
268 static void fetchDiskCacheEntries(SessionID sessionID, std::function<void (Vector<WebsiteData::Entry>)> completionHandler)
270 #if ENABLE(NETWORK_CACHE)
271 if (NetworkCache::singleton().isEnabled()) {
272 auto* origins = new HashSet<RefPtr<SecurityOrigin>>();
274 NetworkCache::singleton().traverse([completionHandler, origins](const NetworkCache::Entry *entry) {
276 Vector<WebsiteData::Entry> entries;
278 for (auto& origin : *origins)
279 entries.append(WebsiteData::Entry { origin, WebsiteDataTypeDiskCache });
283 RunLoop::main().dispatch([completionHandler, entries] {
284 completionHandler(entries);
290 origins->add(SecurityOrigin::create(entry->response().url()));
297 Vector<WebsiteData::Entry> entries;
300 for (auto& origin : NetworkProcess::cfURLCacheOrigins())
301 entries.append(WebsiteData::Entry { WTF::move(origin), WebsiteDataTypeDiskCache });
304 RunLoop::main().dispatch([completionHandler, entries] {
305 completionHandler(entries);
309 void NetworkProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID)
311 struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
312 explicit CallbackAggregator(std::function<void (WebsiteData)> completionHandler)
313 : m_completionHandler(WTF::move(completionHandler))
317 ~CallbackAggregator()
319 ASSERT(RunLoop::isMain());
321 auto completionHandler = WTF::move(m_completionHandler);
322 auto websiteData = WTF::move(m_websiteData);
324 RunLoop::main().dispatch([completionHandler, websiteData] {
325 completionHandler(websiteData);
329 std::function<void (WebsiteData)> m_completionHandler;
330 WebsiteData m_websiteData;
333 RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID](WebsiteData websiteData) {
334 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
337 if (websiteDataTypes & WebsiteDataTypeCookies) {
338 if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
339 getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies);
342 if (websiteDataTypes & WebsiteDataTypeDiskCache) {
343 fetchDiskCacheEntries(sessionID, [callbackAggregator](Vector<WebsiteData::Entry> entries) {
344 callbackAggregator->m_websiteData.entries.appendVector(entries);
349 void NetworkProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
352 if (websiteDataTypes & WebsiteDataTypeHSTSCache) {
353 if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
354 clearHSTSCache(*networkStorageSession, modifiedSince);
358 if (websiteDataTypes & WebsiteDataTypeCookies) {
359 if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
360 deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince);
363 auto completionHandler = [this, callbackID] {
364 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
367 if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) {
368 clearDiskCache(modifiedSince, WTF::move(completionHandler));
375 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, std::function<void ()> completionHandler)
377 #if ENABLE(NETWORK_CACHE)
378 if (NetworkCache::singleton().isEnabled()) {
379 auto* originsToDelete = new HashSet<RefPtr<SecurityOrigin>>();
381 for (auto& origin : origins)
382 originsToDelete->add(origin.securityOrigin());
384 auto* cacheKeysToDelete = new Vector<NetworkCache::Key>;
386 NetworkCache::singleton().traverse([completionHandler, originsToDelete, cacheKeysToDelete](const NetworkCache::Entry *entry) {
389 if (originsToDelete->contains(SecurityOrigin::create(entry->response().url())))
390 cacheKeysToDelete->append(entry->key());
394 delete originsToDelete;
396 for (auto& key : *cacheKeysToDelete)
397 NetworkCache::singleton().remove(key);
399 delete cacheKeysToDelete;
401 RunLoop::main().dispatch(completionHandler);
410 NetworkProcess::clearCFURLCacheForOrigins(origins);
413 RunLoop::main().dispatch(WTF::move(completionHandler));
416 void NetworkProcess::deleteWebsiteDataForOrigins(SessionID sessionID, uint64_t websiteDataTypes, const Vector<SecurityOriginData>& origins, const Vector<String>& cookieHostNames, uint64_t callbackID)
418 if (websiteDataTypes & WebsiteDataTypeCookies) {
419 if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
420 deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
423 auto completionHandler = [this, callbackID] {
424 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
427 if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) {
428 clearDiskCacheEntries(origins, WTF::move(completionHandler));
435 void NetworkProcess::downloadRequest(SessionID sessionID, DownloadID downloadID, const ResourceRequest& request)
437 downloadManager().startDownload(sessionID, downloadID, request);
440 void NetworkProcess::resumeDownload(SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle)
442 downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, sandboxExtensionHandle);
445 void NetworkProcess::cancelDownload(DownloadID downloadID)
447 downloadManager().cancelDownload(downloadID);
450 void NetworkProcess::setCacheModel(uint32_t cm)
452 CacheModel cacheModel = static_cast<CacheModel>(cm);
454 if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
455 m_hasSetCacheModel = true;
456 m_cacheModel = cacheModel;
457 platformSetCacheModel(cacheModel);
461 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
463 m_canHandleHTTPSServerTrustEvaluation = value;
466 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
470 auto& networkProcess = NetworkProcess::singleton();
471 data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
472 data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
474 parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
477 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
479 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
482 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessage(webPageID, message, description), 0);
485 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
487 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
490 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithResult(webPageID, message, description, result), 0);
493 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, const String& value, ShouldSample shouldSample)
495 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
498 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithValue(webPageID, message, description, value), 0);
501 void NetworkProcess::terminate()
504 ChildProcess::terminate();
507 void NetworkProcess::processWillSuspendImminently(bool& handled)
509 lowMemoryHandler(Critical::Yes);
513 void NetworkProcess::prepareToSuspend()
515 lowMemoryHandler(Critical::Yes);
516 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
519 void NetworkProcess::cancelPrepareToSuspend()
521 // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
522 // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
523 // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
524 // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
527 void NetworkProcess::processDidResume()
531 void NetworkProcess::prefetchDNS(const String& hostname)
533 WebCore::prefetchDNS(hostname);
537 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
541 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
545 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
549 void NetworkProcess::platformLowMemoryHandler(Critical)
554 } // namespace WebKit