Move IndexedDB to Network Process
[WebKit-https.git] / Source / WebKit / UIProcess / Network / NetworkProcessProxy.cpp
1 /*
2  * Copyright (C) 2012-2018 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 "NetworkProcessProxy.h"
28
29 #include "APIContentRuleList.h"
30 #include "AuthenticationChallengeProxy.h"
31 #include "DownloadProxyMessages.h"
32 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
33 #include "LegacyCustomProtocolManagerProxyMessages.h"
34 #endif
35 #include "Logging.h"
36 #include "NetworkContentRuleListManagerMessages.h"
37 #include "NetworkProcessCreationParameters.h"
38 #include "NetworkProcessMessages.h"
39 #include "SandboxExtension.h"
40 #include "StorageProcessMessages.h"
41 #include "WebCompiledContentRuleList.h"
42 #include "WebPageProxy.h"
43 #include "WebProcessMessages.h"
44 #include "WebProcessPool.h"
45 #include "WebUserContentControllerProxy.h"
46 #include "WebsiteData.h"
47 #include <wtf/CompletionHandler.h>
48
49 #if ENABLE(SEC_ITEM_SHIM)
50 #include "SecItemShimProxy.h"
51 #endif
52
53 #if PLATFORM(IOS)
54 #include <wtf/spi/darwin/XPCSPI.h>
55 #endif
56
57 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
58
59 namespace WebKit {
60 using namespace WebCore;
61
62 static uint64_t generateCallbackID()
63 {
64     static uint64_t callbackID;
65
66     return ++callbackID;
67 }
68
69 Ref<NetworkProcessProxy> NetworkProcessProxy::create(WebProcessPool& processPool)
70 {
71     return adoptRef(*new NetworkProcessProxy(processPool));
72 }
73
74 NetworkProcessProxy::NetworkProcessProxy(WebProcessPool& processPool)
75     : ChildProcessProxy(processPool.alwaysRunsAtBackgroundPriority())
76     , m_processPool(processPool)
77     , m_numPendingConnectionRequests(0)
78 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
79     , m_customProtocolManagerProxy(*this)
80 #endif
81     , m_throttler(*this, processPool.shouldTakeUIBackgroundAssertion())
82 {
83     connect();
84
85     if (auto* websiteDataStore = m_processPool.websiteDataStore())
86         m_websiteDataStores.set(websiteDataStore->websiteDataStore().sessionID(), makeRef(websiteDataStore->websiteDataStore()));
87 }
88
89 NetworkProcessProxy::~NetworkProcessProxy()
90 {
91     ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
92     ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
93     ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
94 #if ENABLE(CONTENT_EXTENSIONS)
95     for (auto* proxy : m_webUserContentControllerProxies)
96         proxy->removeNetworkProcess(*this);
97 #endif
98 }
99
100 void NetworkProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
101 {
102     launchOptions.processType = ProcessLauncher::ProcessType::Network;
103     ChildProcessProxy::getLaunchOptions(launchOptions);
104
105     if (processPool().shouldMakeNextNetworkProcessLaunchFailForTesting()) {
106         processPool().setShouldMakeNextNetworkProcessLaunchFailForTesting(false);
107         launchOptions.shouldMakeProcessLaunchFailForTesting = true;
108     }
109 }
110
111 void NetworkProcessProxy::connectionWillOpen(IPC::Connection& connection)
112 {
113 #if ENABLE(SEC_ITEM_SHIM)
114     SecItemShimProxy::singleton().initializeConnection(connection);
115 #else
116     UNUSED_PARAM(connection);
117 #endif
118 }
119
120 void NetworkProcessProxy::processWillShutDown(IPC::Connection& connection)
121 {
122     ASSERT_UNUSED(connection, this->connection() == &connection);
123 }
124
125 void NetworkProcessProxy::getNetworkProcessConnection(Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&& reply)
126 {
127     m_pendingConnectionReplies.append(WTFMove(reply));
128
129     if (state() == State::Launching) {
130         m_numPendingConnectionRequests++;
131         return;
132     }
133
134     connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
135 }
136
137 DownloadProxy* NetworkProcessProxy::createDownloadProxy(const ResourceRequest& resourceRequest)
138 {
139     if (!m_downloadProxyMap)
140         m_downloadProxyMap = std::make_unique<DownloadProxyMap>(this);
141
142     return m_downloadProxyMap->createDownloadProxy(m_processPool, resourceRequest);
143 }
144
145 void NetworkProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void (WebsiteData)>&& completionHandler)
146 {
147     ASSERT(canSendMessage());
148
149     uint64_t callbackID = generateCallbackID();
150     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is fetching Website data", this);
151
152     m_pendingFetchWebsiteDataCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] (WebsiteData websiteData) mutable {
153 #if RELEASE_LOG_DISABLED
154         UNUSED_PARAM(this);
155         UNUSED_PARAM(sessionID);
156 #endif
157         completionHandler(WTFMove(websiteData));
158         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done fetching Website data", this);
159     });
160
161     send(Messages::NetworkProcess::FetchWebsiteData(sessionID, dataTypes, fetchOptions, callbackID), 0);
162 }
163
164 void NetworkProcessProxy::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, CompletionHandler<void ()>&& completionHandler)
165 {
166     auto callbackID = generateCallbackID();
167     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is deleting Website data", this);
168
169     m_pendingDeleteWebsiteDataCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] () mutable {
170 #if RELEASE_LOG_DISABLED
171         UNUSED_PARAM(this);
172         UNUSED_PARAM(sessionID);
173 #endif
174         completionHandler();
175         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data", this);
176     });
177     send(Messages::NetworkProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
178 }
179
180 void NetworkProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CompletionHandler<void()>&& completionHandler)
181 {
182     ASSERT(canSendMessage());
183
184     uint64_t callbackID = generateCallbackID();
185     RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is deleting Website data for several origins", this);
186
187     m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] () mutable {
188 #if RELEASE_LOG_DISABLED
189         UNUSED_PARAM(this);
190         UNUSED_PARAM(sessionID);
191 #endif
192         completionHandler();
193         RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data for several origins", this);
194     });
195
196     send(Messages::NetworkProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, callbackID), 0);
197 }
198
199 void NetworkProcessProxy::networkProcessCrashed()
200 {
201     clearCallbackStates();
202
203     Vector<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply> pendingReplies;
204     pendingReplies.reserveInitialCapacity(m_pendingConnectionReplies.size());
205     for (auto& reply : m_pendingConnectionReplies)
206         pendingReplies.append(WTFMove(reply));
207
208     // Tell the network process manager to forget about this network process proxy. This may cause us to be deleted.
209     m_processPool.networkProcessCrashed(*this, WTFMove(pendingReplies));
210 }
211
212 void NetworkProcessProxy::clearCallbackStates()
213 {
214     while (!m_pendingFetchWebsiteDataCallbacks.isEmpty())
215         m_pendingFetchWebsiteDataCallbacks.take(m_pendingFetchWebsiteDataCallbacks.begin()->key)(WebsiteData { });
216
217     while (!m_pendingDeleteWebsiteDataCallbacks.isEmpty())
218         m_pendingDeleteWebsiteDataCallbacks.take(m_pendingDeleteWebsiteDataCallbacks.begin()->key)();
219
220     while (!m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty())
221         m_pendingDeleteWebsiteDataForOriginsCallbacks.take(m_pendingDeleteWebsiteDataForOriginsCallbacks.begin()->key)();
222
223     while (!m_updateBlockCookiesCallbackMap.isEmpty())
224         m_updateBlockCookiesCallbackMap.take(m_updateBlockCookiesCallbackMap.begin()->key)();
225     
226     while (!m_storageAccessResponseCallbackMap.isEmpty())
227         m_storageAccessResponseCallbackMap.take(m_storageAccessResponseCallbackMap.begin()->key)(false);
228 }
229
230 void NetworkProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
231 {
232     if (dispatchMessage(connection, decoder))
233         return;
234
235     if (m_processPool.dispatchMessage(connection, decoder))
236         return;
237
238     didReceiveNetworkProcessProxyMessage(connection, decoder);
239 }
240
241 void NetworkProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
242 {
243     if (dispatchSyncMessage(connection, decoder, replyEncoder))
244         return;
245
246     ASSERT_NOT_REACHED();
247 }
248
249 void NetworkProcessProxy::didClose(IPC::Connection&)
250 {
251     auto protectedProcessPool = makeRef(m_processPool);
252
253     if (m_downloadProxyMap)
254         m_downloadProxyMap->processDidClose();
255 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
256     m_customProtocolManagerProxy.invalidate();
257 #endif
258
259     m_tokenForHoldingLockedFiles = nullptr;
260     
261     m_syncAllCookiesToken = nullptr;
262     m_syncAllCookiesCounter = 0;
263
264     for (auto& callback : m_writeBlobToFilePathCallbackMap.values())
265         callback(false);
266     m_writeBlobToFilePathCallbackMap.clear();
267
268     // This may cause us to be deleted.
269     networkProcessCrashed();
270 }
271
272 void NetworkProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
273 {
274 }
275
276 void NetworkProcessProxy::didCreateNetworkConnectionToWebProcess(const IPC::Attachment& connectionIdentifier)
277 {
278     ASSERT(!m_pendingConnectionReplies.isEmpty());
279
280     // Grab the first pending connection reply.
281     auto reply = m_pendingConnectionReplies.takeFirst();
282
283 #if USE(UNIX_DOMAIN_SOCKETS) || OS(WINDOWS)
284     reply(connectionIdentifier);
285 #elif OS(DARWIN)
286     MESSAGE_CHECK(MACH_PORT_VALID(connectionIdentifier.port()));
287     reply(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
288 #else
289     notImplemented();
290 #endif
291 }
292
293 void NetworkProcessProxy::didReceiveAuthenticationChallenge(uint64_t pageID, uint64_t frameID, WebCore::AuthenticationChallenge&& coreChallenge, uint64_t challengeID)
294 {
295 #if ENABLE(SERVICE_WORKER)
296     if (auto* serviceWorkerProcessProxy = m_processPool.serviceWorkerProcessProxyFromPageID(pageID)) {
297         auto authenticationChallenge = AuthenticationChallengeProxy::create(WTFMove(coreChallenge), challengeID, connection());
298         serviceWorkerProcessProxy->didReceiveAuthenticationChallenge(pageID, frameID, WTFMove(authenticationChallenge));
299         return;
300     }
301 #endif
302
303     WebPageProxy* page = WebProcessProxy::webPage(pageID);
304     MESSAGE_CHECK(page);
305
306     auto authenticationChallenge = AuthenticationChallengeProxy::create(WTFMove(coreChallenge), challengeID, connection());
307     page->didReceiveAuthenticationChallengeProxy(frameID, WTFMove(authenticationChallenge));
308 }
309
310 void NetworkProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
311 {
312     auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
313     callback(websiteData);
314 }
315
316 void NetworkProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
317 {
318     auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
319     callback();
320 }
321
322 void NetworkProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
323 {
324     auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
325     callback();
326 }
327
328 void NetworkProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
329 {
330     ChildProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
331
332     if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
333         networkProcessCrashed();
334         return;
335     }
336
337     for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
338         connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(), 0);
339     
340     m_numPendingConnectionRequests = 0;
341
342 #if PLATFORM(COCOA)
343     if (m_processPool.processSuppressionEnabled())
344         setProcessSuppressionEnabled(true);
345 #endif
346     
347 #if PLATFORM(IOS)
348     if (xpc_connection_t connection = this->connection()->xpcConnection())
349         m_throttler.didConnectToProcess(xpc_connection_get_pid(connection));
350 #endif
351 }
352
353 void NetworkProcessProxy::logDiagnosticMessage(uint64_t pageID, const String& message, const String& description, WebCore::ShouldSample shouldSample)
354 {
355     WebPageProxy* page = WebProcessProxy::webPage(pageID);
356     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
357     // but for now we simply drop the message in the rare case this happens.
358     if (!page)
359         return;
360
361     page->logDiagnosticMessage(message, description, shouldSample);
362 }
363
364 void NetworkProcessProxy::logDiagnosticMessageWithResult(uint64_t pageID, const String& message, const String& description, uint32_t result, WebCore::ShouldSample shouldSample)
365 {
366     WebPageProxy* page = WebProcessProxy::webPage(pageID);
367     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
368     // but for now we simply drop the message in the rare case this happens.
369     if (!page)
370         return;
371
372     page->logDiagnosticMessageWithResult(message, description, result, shouldSample);
373 }
374
375 void NetworkProcessProxy::logDiagnosticMessageWithValue(uint64_t pageID, const String& message, const String& description, double value, unsigned significantFigures, WebCore::ShouldSample shouldSample)
376 {
377     WebPageProxy* page = WebProcessProxy::webPage(pageID);
378     // FIXME: We do this null-check because by the time the decision to log is made, the page may be gone. We should refactor to avoid this,
379     // but for now we simply drop the message in the rare case this happens.
380     if (!page)
381         return;
382
383     page->logDiagnosticMessageWithValue(message, description, value, significantFigures, shouldSample);
384 }
385
386 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
387 void NetworkProcessProxy::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<String>& domainsToBlock, ShouldClearFirst shouldClearFirst, CompletionHandler<void()>&& completionHandler)
388 {
389     if (!canSendMessage()) {
390         completionHandler();
391         return;
392     }
393     
394     auto callbackId = generateCallbackID();
395     auto addResult = m_updateBlockCookiesCallbackMap.add(callbackId, [protectedThis = makeRef(*this), token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler)]() mutable {
396         completionHandler();
397     });
398     ASSERT_UNUSED(addResult, addResult.isNewEntry);
399     send(Messages::NetworkProcess::UpdatePrevalentDomainsToBlockCookiesFor(sessionID, domainsToBlock, shouldClearFirst == ShouldClearFirst::Yes, callbackId), 0);
400 }
401
402 void NetworkProcessProxy::didUpdateBlockCookies(uint64_t callbackId)
403 {
404     m_updateBlockCookiesCallbackMap.take(callbackId)();
405 }
406
407 static uint64_t nextRequestStorageAccessContextId()
408 {
409     static uint64_t nextContextId = 0;
410     return ++nextContextId;
411 }
412
413 void NetworkProcessProxy::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool)>&& callback)
414 {
415     auto contextId = nextRequestStorageAccessContextId();
416     auto addResult = m_storageAccessResponseCallbackMap.add(contextId, WTFMove(callback));
417     ASSERT_UNUSED(addResult, addResult.isNewEntry);
418     send(Messages::NetworkProcess::HasStorageAccessForFrame(sessionID, resourceDomain, firstPartyDomain, frameID, pageID, contextId), 0);
419 }
420
421 void NetworkProcessProxy::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, WTF::CompletionHandler<void(bool)>&& callback)
422 {
423     auto contextId = nextRequestStorageAccessContextId();
424     auto addResult = m_storageAccessResponseCallbackMap.add(contextId, WTFMove(callback));
425     ASSERT_UNUSED(addResult, addResult.isNewEntry);
426     send(Messages::NetworkProcess::GrantStorageAccess(sessionID, resourceDomain, firstPartyDomain, frameID, pageID, contextId), 0);
427 }
428
429 void NetworkProcessProxy::storageAccessRequestResult(bool wasGranted, uint64_t contextId)
430 {
431     auto callback = m_storageAccessResponseCallbackMap.take(contextId);
432     callback(wasGranted);
433 }
434
435 void NetworkProcessProxy::removeAllStorageAccess(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
436 {
437     if (!canSendMessage()) {
438         completionHandler();
439         return;
440     }
441
442     auto contextId = nextRequestStorageAccessContextId();
443     auto addResult = m_removeAllStorageAccessCallbackMap.add(contextId, WTFMove(completionHandler));
444     ASSERT_UNUSED(addResult, addResult.isNewEntry);
445     send(Messages::NetworkProcess::RemoveAllStorageAccess(sessionID, contextId), 0);
446 }
447
448 void NetworkProcessProxy::didRemoveAllStorageAccess(uint64_t contextId)
449 {
450     auto completionHandler = m_removeAllStorageAccessCallbackMap.take(contextId);
451     completionHandler();
452 }
453
454 void NetworkProcessProxy::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String>&& domains)>&& callback)
455 {
456     auto contextId = nextRequestStorageAccessContextId();
457     auto addResult = m_allStorageAccessEntriesCallbackMap.add(contextId, WTFMove(callback));
458     ASSERT_UNUSED(addResult, addResult.isNewEntry);
459     send(Messages::NetworkProcess::GetAllStorageAccessEntries(sessionID, contextId), 0);
460 }
461
462 void NetworkProcessProxy::allStorageAccessEntriesResult(Vector<String>&& domains, uint64_t contextId)
463 {
464     auto callback = m_allStorageAccessEntriesCallbackMap.take(contextId);
465     callback(WTFMove(domains));
466 }
467 #endif
468
469 void NetworkProcessProxy::sendProcessWillSuspendImminently()
470 {
471     if (!canSendMessage())
472         return;
473
474     bool handled = false;
475     sendSync(Messages::NetworkProcess::ProcessWillSuspendImminently(), Messages::NetworkProcess::ProcessWillSuspendImminently::Reply(handled), 0, 1_s);
476 }
477     
478 void NetworkProcessProxy::sendPrepareToSuspend()
479 {
480     if (canSendMessage())
481         send(Messages::NetworkProcess::PrepareToSuspend(), 0);
482 }
483
484 void NetworkProcessProxy::sendCancelPrepareToSuspend()
485 {
486     if (canSendMessage())
487         send(Messages::NetworkProcess::CancelPrepareToSuspend(), 0);
488 }
489
490 void NetworkProcessProxy::sendProcessDidResume()
491 {
492     if (canSendMessage())
493         send(Messages::NetworkProcess::ProcessDidResume(), 0);
494 }
495
496 void NetworkProcessProxy::writeBlobToFilePath(const WebCore::URL& url, const String& path, CompletionHandler<void(bool)>&& callback)
497 {
498     if (!canSendMessage()) {
499         callback(false);
500         return;
501     }
502
503     static uint64_t writeBlobToFilePathCallbackIdentifiers = 0;
504     uint64_t callbackID = ++writeBlobToFilePathCallbackIdentifiers;
505     m_writeBlobToFilePathCallbackMap.add(callbackID, WTFMove(callback));
506
507     SandboxExtension::Handle handleForWriting;
508     SandboxExtension::createHandle(path, SandboxExtension::Type::ReadWrite, handleForWriting);
509     send(Messages::NetworkProcess::WriteBlobToFilePath(url, path, handleForWriting, callbackID), 0);
510 }
511
512 void NetworkProcessProxy::didWriteBlobToFilePath(bool success, uint64_t callbackID)
513 {
514     if (auto handler = m_writeBlobToFilePathCallbackMap.take(callbackID))
515         handler(success);
516     else
517         ASSERT_NOT_REACHED();
518 }
519
520 void NetworkProcessProxy::processReadyToSuspend()
521 {
522     m_throttler.processReadyToSuspend();
523 }
524
525 void NetworkProcessProxy::didSetAssertionState(AssertionState)
526 {
527 }
528     
529 void NetworkProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
530 {
531     if (!isHoldingLockedFiles) {
532         RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the Network process is no longer holding locked files");
533         m_tokenForHoldingLockedFiles = nullptr;
534         return;
535     }
536     if (!m_tokenForHoldingLockedFiles) {
537         RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the Network process is holding locked files");
538         m_tokenForHoldingLockedFiles = m_throttler.backgroundActivityToken();
539     }
540 }
541
542 void NetworkProcessProxy::syncAllCookies()
543 {
544     send(Messages::NetworkProcess::SyncAllCookies(), 0);
545     
546     ++m_syncAllCookiesCounter;
547     if (m_syncAllCookiesToken)
548         return;
549     
550     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is syncing cookies", this);
551     m_syncAllCookiesToken = throttler().backgroundActivityToken();
552 }
553     
554 void NetworkProcessProxy::didSyncAllCookies()
555 {
556     ASSERT(m_syncAllCookiesCounter);
557
558     --m_syncAllCookiesCounter;
559     if (!m_syncAllCookiesCounter) {
560         RELEASE_LOG(ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done syncing cookies", this);
561         m_syncAllCookiesToken = nullptr;
562     }
563 }
564
565 void NetworkProcessProxy::addSession(Ref<WebsiteDataStore>&& store)
566 {
567     if (canSendMessage())
568         send(Messages::NetworkProcess::AddWebsiteDataStore { store->parameters() }, 0);
569     auto sessionID = store->sessionID();
570     if (!sessionID.isEphemeral())
571         m_websiteDataStores.set(sessionID, WTFMove(store));
572 }
573
574 void NetworkProcessProxy::removeSession(PAL::SessionID sessionID)
575 {
576     if (canSendMessage())
577         send(Messages::NetworkProcess::DestroySession { sessionID }, 0);
578     if (!sessionID.isEphemeral())
579         m_websiteDataStores.remove(sessionID);
580 }
581
582 void NetworkProcessProxy::retrieveCacheStorageParameters(PAL::SessionID sessionID)
583 {
584     auto iterator = m_websiteDataStores.find(sessionID);
585     if (iterator == m_websiteDataStores.end()) {
586         auto quota = m_processPool.websiteDataStore() ? m_processPool.websiteDataStore()->websiteDataStore().cacheStoragePerOriginQuota() : WebsiteDataStore::defaultCacheStoragePerOriginQuota;
587         send(Messages::NetworkProcess::SetCacheStorageParameters { sessionID, quota, { }, { } }, 0);
588         return;
589     }
590
591     auto& store = *iterator->value;
592     auto& cacheStorageDirectory = store.cacheStorageDirectory();
593     SandboxExtension::Handle cacheStorageDirectoryExtensionHandle;
594     if (!cacheStorageDirectory.isEmpty())
595         SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, cacheStorageDirectoryExtensionHandle);
596
597     send(Messages::NetworkProcess::SetCacheStorageParameters { sessionID, store.cacheStoragePerOriginQuota(), cacheStorageDirectory, cacheStorageDirectoryExtensionHandle }, 0);
598 }
599
600 #if ENABLE(CONTENT_EXTENSIONS)
601 void NetworkProcessProxy::contentExtensionRules(UserContentControllerIdentifier identifier)
602 {
603     if (auto* webUserContentControllerProxy = WebUserContentControllerProxy::get(identifier)) {
604         m_webUserContentControllerProxies.add(webUserContentControllerProxy);
605         webUserContentControllerProxy->addNetworkProcess(*this);
606
607         auto rules = WTF::map(webUserContentControllerProxy->contentExtensionRules(), [](auto&& keyValue) -> std::pair<String, WebCompiledContentRuleListData> {
608             return std::make_pair(keyValue.value->name(), keyValue.value->compiledRuleList().data());
609         });
610         send(Messages::NetworkContentRuleListManager::AddContentRuleLists { identifier, rules }, 0);
611         return;
612     }
613     send(Messages::NetworkContentRuleListManager::AddContentRuleLists { identifier, { } }, 0);
614 }
615
616 void NetworkProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
617 {
618     send(Messages::NetworkContentRuleListManager::Remove { proxy.identifier() }, 0);
619     m_webUserContentControllerProxies.remove(&proxy);
620 }
621 #endif
622     
623 void NetworkProcessProxy::sendProcessDidTransitionToForeground()
624 {
625     send(Messages::NetworkProcess::ProcessDidTransitionToForeground(), 0);
626 }
627
628 void NetworkProcessProxy::sendProcessDidTransitionToBackground()
629 {
630     send(Messages::NetworkProcess::ProcessDidTransitionToBackground(), 0);
631 }
632
633 #if ENABLE(SANDBOX_EXTENSIONS)
634 void NetworkProcessProxy::getSandboxExtensionsForBlobFiles(uint64_t requestID, const Vector<String>& paths)
635 {
636     SandboxExtension::HandleArray extensions;
637     extensions.allocate(paths.size());
638     for (size_t i = 0; i < paths.size(); ++i) {
639         // ReadWrite is required for creating hard links, which is something that might be done with these extensions.
640         SandboxExtension::createHandle(paths[i], SandboxExtension::Type::ReadWrite, extensions[i]);
641     }
642     
643     send(Messages::NetworkProcess::DidGetSandboxExtensionsForBlobFiles(requestID, extensions), 0);
644 }
645 #endif
646
647 } // namespace WebKit
648
649 #undef MESSAGE_CHECK
650 #undef MESSAGE_CHECK_URL