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