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