19abc9abff057bf03f52a897ba546a8e9eebc1ae
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "NetworkProcess.h"
28
29 #include "ArgumentCoders.h"
30 #include "Attachment.h"
31 #include "AuthenticationManager.h"
32 #include "ChildProcessMessages.h"
33 #include "CustomProtocolManager.h"
34 #include "Logging.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>
56
57 #if ENABLE(SEC_ITEM_SHIM)
58 #include "SecItemShim.h"
59 #endif
60
61 #if ENABLE(NETWORK_CACHE)
62 #include "NetworkCache.h"
63 #include "NetworkCacheCoders.h"
64 #endif
65
66 using namespace WebCore;
67
68 namespace WebKit {
69
70 NetworkProcess& NetworkProcess::singleton()
71 {
72     static NeverDestroyed<NetworkProcess> networkProcess;
73     return networkProcess;
74 }
75
76 NetworkProcess::NetworkProcess()
77     : m_hasSetCacheModel(false)
78     , m_cacheModel(CacheModelDocumentViewer)
79     , m_diskCacheIsDisabledForTesting(false)
80     , m_canHandleHTTPSServerTrustEvaluation(true)
81 #if PLATFORM(COCOA)
82     , m_clearCacheDispatchGroup(0)
83 #endif
84 #if PLATFORM(IOS)
85     , m_webSQLiteDatabaseTracker(*this)
86 #endif
87 {
88     NetworkProcessPlatformStrategies::initialize();
89
90     addSupplement<AuthenticationManager>();
91     addSupplement<WebCookieManager>();
92     addSupplement<CustomProtocolManager>();
93 }
94
95 NetworkProcess::~NetworkProcess()
96 {
97 }
98
99 AuthenticationManager& NetworkProcess::authenticationManager()
100 {
101     return *supplement<AuthenticationManager>();
102 }
103
104 DownloadManager& NetworkProcess::downloadManager()
105 {
106     static NeverDestroyed<DownloadManager> downloadManager(this);
107     return downloadManager;
108 }
109
110 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
111 {
112     size_t vectorIndex = m_webProcessConnections.find(connection);
113     ASSERT(vectorIndex != notFound);
114
115     m_webProcessConnections.remove(vectorIndex);
116 }
117
118 bool NetworkProcess::shouldTerminate()
119 {
120     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
121     return false;
122 }
123
124 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
125 {
126     if (messageReceiverMap().dispatchMessage(connection, decoder))
127         return;
128
129     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
130         ChildProcess::didReceiveMessage(connection, decoder);
131         return;
132     }
133
134     didReceiveNetworkProcessMessage(connection, decoder);
135 }
136
137 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
138 {
139     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
140         return;
141
142     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
143 }
144
145 void NetworkProcess::didClose(IPC::Connection&)
146 {
147     // The UIProcess just exited.
148     RunLoop::current().stop();
149 }
150
151 void NetworkProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
152 {
153     RunLoop::current().stop();
154 }
155
156 void NetworkProcess::didCreateDownload()
157 {
158     disableTermination();
159 }
160
161 void NetworkProcess::didDestroyDownload()
162 {
163     enableTermination();
164 }
165
166 IPC::Connection* NetworkProcess::downloadProxyConnection()
167 {
168     return parentProcessConnection();
169 }
170
171 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
172 {
173     return authenticationManager();
174 }
175
176 void NetworkProcess::lowMemoryHandler(Critical critical)
177 {
178     platformLowMemoryHandler(critical);
179     WTF::releaseFastMallocFreeMemory();
180 }
181
182 void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters)
183 {
184     platformInitializeNetworkProcess(parameters);
185
186     WTF::setCurrentThreadIsUserInitiated();
187
188     auto& memoryPressureHandler = MemoryPressureHandler::singleton();
189     memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
190         lowMemoryHandler(critical);
191     });
192     memoryPressureHandler.install();
193
194     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
195
196     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
197     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
198
199     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
200
201 #if PLATFORM(MAC) || USE(CFNETWORK)
202     SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
203 #endif
204
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());
208
209     if (parameters.shouldUseTestingNetworkSession)
210         NetworkStorageSession::switchToNewTestingSession();
211
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);
216 }
217
218 void NetworkProcess::initializeConnection(IPC::Connection* connection)
219 {
220     ChildProcess::initializeConnection(connection);
221
222 #if ENABLE(SEC_ITEM_SHIM)
223     SecItemShim::singleton().initializeConnection(connection);
224 #endif
225
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);
230 }
231
232 void NetworkProcess::createNetworkConnectionToWebProcess()
233 {
234 #if USE(UNIX_DOMAIN_SOCKETS)
235     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
236
237     RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(socketPair.server);
238     m_webProcessConnections.append(connection.release());
239
240     IPC::Attachment clientSocket(socketPair.client);
241     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
242 #elif OS(DARWIN)
243     // Create the listening port.
244     mach_port_t listeningPort;
245     mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
246
247     // Create a listening connection.
248     RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
249     m_webProcessConnections.append(connection.release());
250
251     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
252     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
253 #else
254     notImplemented();
255 #endif
256 }
257
258 void NetworkProcess::ensurePrivateBrowsingSession(SessionID sessionID)
259 {
260     RemoteNetworkingContext::ensurePrivateBrowsingSession(sessionID);
261 }
262
263 void NetworkProcess::destroyPrivateBrowsingSession(SessionID sessionID)
264 {
265     SessionTracker::destroySession(sessionID);
266 }
267
268 static void fetchDiskCacheEntries(SessionID sessionID, std::function<void (Vector<WebsiteData::Entry>)> completionHandler)
269 {
270 #if ENABLE(NETWORK_CACHE)
271     if (NetworkCache::singleton().isEnabled()) {
272         auto* origins = new HashSet<RefPtr<SecurityOrigin>>();
273
274         NetworkCache::singleton().traverse([completionHandler, origins](const NetworkCache::Entry *entry) {
275             if (!entry) {
276                 Vector<WebsiteData::Entry> entries;
277
278                 for (auto& origin : *origins)
279                     entries.append(WebsiteData::Entry { origin, WebsiteDataTypeDiskCache });
280
281                 delete origins;
282
283                 RunLoop::main().dispatch([completionHandler, entries] {
284                     completionHandler(entries);
285                 });
286
287                 return;
288             }
289
290             origins->add(SecurityOrigin::create(entry->response().url()));
291         });
292
293         return;
294     }
295 #endif
296
297     Vector<WebsiteData::Entry> entries;
298
299 #if USE(CFURLCACHE)
300     for (auto& origin : NetworkProcess::cfURLCacheOrigins())
301         entries.append(WebsiteData::Entry { WTF::move(origin), WebsiteDataTypeDiskCache });
302 #endif
303
304     RunLoop::main().dispatch([completionHandler, entries] {
305         completionHandler(entries);
306     });
307 }
308
309 void NetworkProcess::fetchWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, uint64_t callbackID)
310 {
311     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
312         explicit CallbackAggregator(std::function<void (WebsiteData)> completionHandler)
313             : m_completionHandler(WTF::move(completionHandler))
314         {
315         }
316
317         ~CallbackAggregator()
318         {
319             ASSERT(RunLoop::isMain());
320
321             auto completionHandler = WTF::move(m_completionHandler);
322             auto websiteData = WTF::move(m_websiteData);
323
324             RunLoop::main().dispatch([completionHandler, websiteData] {
325                 completionHandler(websiteData);
326             });
327         }
328
329         std::function<void (WebsiteData)> m_completionHandler;
330         WebsiteData m_websiteData;
331     };
332
333     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator([this, callbackID](WebsiteData websiteData) {
334         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
335     }));
336
337     if (websiteDataTypes & WebsiteDataTypeCookies) {
338         if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
339             getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies);
340     }
341
342     if (websiteDataTypes & WebsiteDataTypeDiskCache) {
343         fetchDiskCacheEntries(sessionID, [callbackAggregator](Vector<WebsiteData::Entry> entries) {
344             callbackAggregator->m_websiteData.entries.appendVector(entries);
345         });
346     }
347 }
348
349 void NetworkProcess::deleteWebsiteData(SessionID sessionID, uint64_t websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
350 {
351 #if PLATFORM(COCOA)
352     if (websiteDataTypes & WebsiteDataTypeHSTSCache) {
353         if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
354             clearHSTSCache(*networkStorageSession, modifiedSince);
355     }
356 #endif
357
358     if (websiteDataTypes & WebsiteDataTypeCookies) {
359         if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
360             deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince);
361     }
362
363     auto completionHandler = [this, callbackID] {
364         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
365     };
366
367     if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) {
368         clearDiskCache(modifiedSince, WTF::move(completionHandler));
369         return;
370     }
371
372     completionHandler();
373 }
374
375 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, std::function<void ()> completionHandler)
376 {
377 #if ENABLE(NETWORK_CACHE)
378     if (NetworkCache::singleton().isEnabled()) {
379         auto* originsToDelete = new HashSet<RefPtr<SecurityOrigin>>();
380
381         for (auto& origin : origins)
382             originsToDelete->add(origin.securityOrigin());
383
384         auto* cacheKeysToDelete = new Vector<NetworkCache::Key>;
385
386         NetworkCache::singleton().traverse([completionHandler, originsToDelete, cacheKeysToDelete](const NetworkCache::Entry *entry) {
387
388             if (entry) {
389                 if (originsToDelete->contains(SecurityOrigin::create(entry->response().url())))
390                     cacheKeysToDelete->append(entry->key());
391                 return;
392             }
393
394             delete originsToDelete;
395
396             for (auto& key : *cacheKeysToDelete)
397                 NetworkCache::singleton().remove(key);
398
399             delete cacheKeysToDelete;
400
401             RunLoop::main().dispatch(completionHandler);
402             return;
403         });
404
405         return;
406     }
407 #endif
408
409 #if USE(CFURLCACHE)
410     NetworkProcess::clearCFURLCacheForOrigins(origins);
411 #endif
412
413     RunLoop::main().dispatch(WTF::move(completionHandler));
414 }
415
416 void NetworkProcess::deleteWebsiteDataForOrigins(SessionID sessionID, uint64_t websiteDataTypes, const Vector<SecurityOriginData>& origins, const Vector<String>& cookieHostNames, uint64_t callbackID)
417 {
418     if (websiteDataTypes & WebsiteDataTypeCookies) {
419         if (auto* networkStorageSession = SessionTracker::storageSession(sessionID))
420             deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
421     }
422
423     auto completionHandler = [this, callbackID] {
424         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
425     };
426
427     if ((websiteDataTypes & WebsiteDataTypeDiskCache) && !sessionID.isEphemeral()) {
428         clearDiskCacheEntries(origins, WTF::move(completionHandler));
429         return;
430     }
431
432     completionHandler();
433 }
434
435 void NetworkProcess::downloadRequest(SessionID sessionID, uint64_t downloadID, const ResourceRequest& request)
436 {
437     downloadManager().startDownload(sessionID, downloadID, request);
438 }
439
440 void NetworkProcess::resumeDownload(SessionID sessionID, uint64_t downloadID, const IPC::DataReference& resumeData, const String& path, const WebKit::SandboxExtension::Handle& sandboxExtensionHandle)
441 {
442     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, sandboxExtensionHandle);
443 }
444
445 void NetworkProcess::cancelDownload(uint64_t downloadID)
446 {
447     downloadManager().cancelDownload(downloadID);
448 }
449
450 void NetworkProcess::setCacheModel(uint32_t cm)
451 {
452     CacheModel cacheModel = static_cast<CacheModel>(cm);
453
454     if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
455         m_hasSetCacheModel = true;
456         m_cacheModel = cacheModel;
457         platformSetCacheModel(cacheModel);
458     }
459 }
460
461 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
462 {
463     m_canHandleHTTPSServerTrustEvaluation = value;
464 }
465
466 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
467 {
468     StatisticsData data;
469
470     auto& networkProcess = NetworkProcess::singleton();
471     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
472     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
473
474     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
475 }
476
477 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, WebCore::ShouldSample shouldSample)
478 {
479     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
480         return;
481
482     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessage(webPageID, message, description), 0);
483 }
484
485 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, WebCore::DiagnosticLoggingResultType result, WebCore::ShouldSample shouldSample)
486 {
487     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
488         return;
489
490     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithResult(webPageID, message, description, result), 0);
491 }
492
493 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, const String& value, WebCore::ShouldSample shouldSample)
494 {
495     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
496         return;
497
498     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogSampledDiagnosticMessageWithValue(webPageID, message, description, value), 0);
499 }
500
501 void NetworkProcess::terminate()
502 {
503     platformTerminate();
504     ChildProcess::terminate();
505 }
506
507 void NetworkProcess::processWillSuspendImminently(bool& handled)
508 {
509     lowMemoryHandler(Critical::Yes);
510     handled = true;
511 }
512
513 void NetworkProcess::prepareToSuspend()
514 {
515     lowMemoryHandler(Critical::Yes);
516     parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
517 }
518
519 void NetworkProcess::cancelPrepareToSuspend()
520 {
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.
525 }
526
527 void NetworkProcess::processDidResume()
528 {
529 }
530
531 void NetworkProcess::prefetchDNS(const String& hostname)
532 {
533     WebCore::prefetchDNS(hostname);
534 }
535
536 #if !PLATFORM(COCOA)
537 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
538 {
539 }
540
541 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
542 {
543 }
544
545 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
546 {
547 }
548
549 void NetworkProcess::platformLowMemoryHandler(Critical)
550 {
551 }
552 #endif
553
554 } // namespace WebKit