1/*
2 * Copyright (C) 2012-2019 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 "ShouldGrandfatherStatistics.h"
41#include "StorageAccessStatus.h"
42#include "WebCompiledContentRuleList.h"
43#include "WebPageProxy.h"
44#include "WebProcessMessages.h"
45#include "WebProcessPool.h"
46#include "WebProcessProxy.h"
47#include "WebResourceLoadStatisticsStore.h"
48#include "WebUserContentControllerProxy.h"
49#include "WebsiteData.h"
50#include "WebsiteDataStoreClient.h"
51#include <WebCore/ClientOrigin.h>
52#include <WebCore/RegistrableDomain.h>
53#include <wtf/CompletionHandler.h>
54
55#if ENABLE(SEC_ITEM_SHIM)
56#include "SecItemShimProxy.h"
57#endif
58
59#if PLATFORM(IOS_FAMILY)
60#include <wtf/spi/darwin/XPCSPI.h>
61#endif
62
63#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, connection())
64
65namespace WebKit {
66using namespace WebCore;
67
68static uint64_t generateCallbackID()
69{
70 static uint64_t callbackID;
71
72 return ++callbackID;
73}
74
75NetworkProcessProxy::NetworkProcessProxy(WebProcessPool& processPool)
76 : AuxiliaryProcessProxy(processPool.alwaysRunsAtBackgroundPriority())
77 , m_processPool(processPool)
78 , m_numPendingConnectionRequests(0)
79#if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
80 , m_customProtocolManagerProxy(*this)
81#endif
82 , m_throttler(*this, processPool.shouldTakeUIBackgroundAssertion())
83{
84 connect();
85
86 if (auto* websiteDataStore = m_processPool.websiteDataStore())
87 m_websiteDataStores.set(websiteDataStore->websiteDataStore().sessionID(), makeRef(websiteDataStore->websiteDataStore()));
88}
89
90NetworkProcessProxy::~NetworkProcessProxy()
91{
92 ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty());
93 ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty());
94 ASSERT(m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty());
95#if ENABLE(CONTENT_EXTENSIONS)
96 for (auto* proxy : m_webUserContentControllerProxies)
97 proxy->removeNetworkProcess(*this);
98#endif
99
100 if (m_downloadProxyMap)
101 m_downloadProxyMap->invalidate();
102
103 for (auto& reply : m_pendingConnectionReplies)
104 reply.second({ });
105}
106
107void NetworkProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
108{
109 launchOptions.processType = ProcessLauncher::ProcessType::Network;
110 AuxiliaryProcessProxy::getLaunchOptions(launchOptions);
111
112 if (processPool().shouldMakeNextNetworkProcessLaunchFailForTesting()) {
113 processPool().setShouldMakeNextNetworkProcessLaunchFailForTesting(false);
114 launchOptions.shouldMakeProcessLaunchFailForTesting = true;
115 }
116}
117
118void NetworkProcessProxy::connectionWillOpen(IPC::Connection& connection)
119{
120#if ENABLE(SEC_ITEM_SHIM)
121 SecItemShimProxy::singleton().initializeConnection(connection);
122#else
123 UNUSED_PARAM(connection);
124#endif
125}
126
127void NetworkProcessProxy::processWillShutDown(IPC::Connection& connection)
128{
129 ASSERT_UNUSED(connection, this->connection() == &connection);
130}
131
132void NetworkProcessProxy::getNetworkProcessConnection(WebProcessProxy& webProcessProxy, Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&& reply)
133{
134 m_pendingConnectionReplies.append(std::make_pair(makeWeakPtr(webProcessProxy), WTFMove(reply)));
135
136 if (state() == State::Launching) {
137 m_numPendingConnectionRequests++;
138 return;
139 }
140
141 bool isServiceWorkerProcess = false;
142 RegistrableDomain registrableDomain;
143#if ENABLE(SERVICE_WORKER)
144 if (is<ServiceWorkerProcessProxy>(webProcessProxy)) {
145 isServiceWorkerProcess = true;
146 registrableDomain = downcast<ServiceWorkerProcessProxy>(webProcessProxy).registrableDomain();
147 }
148#endif
149
150 connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(isServiceWorkerProcess, registrableDomain), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
151}
152
153void NetworkProcessProxy::synthesizeAppIsBackground(bool background)
154{
155 if (m_downloadProxyMap) {
156 if (background)
157 m_downloadProxyMap->applicationDidEnterBackground();
158 else
159 m_downloadProxyMap->applicationWillEnterForeground();
160 }
161}
162
163DownloadProxy& NetworkProcessProxy::createDownloadProxy(const ResourceRequest& resourceRequest)
164{
165 if (!m_downloadProxyMap)
166 m_downloadProxyMap = std::make_unique<DownloadProxyMap>(*this);
167
168 return m_downloadProxyMap->createDownloadProxy(m_processPool, resourceRequest);
169}
170
171void NetworkProcessProxy::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void (WebsiteData)>&& completionHandler)
172{
173 ASSERT(canSendMessage());
174
175 uint64_t callbackID = generateCallbackID();
176 RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is fetching Website data", this);
177
178 m_pendingFetchWebsiteDataCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] (WebsiteData websiteData) mutable {
179#if RELEASE_LOG_DISABLED
180 UNUSED_PARAM(this);
181 UNUSED_PARAM(sessionID);
182#endif
183 completionHandler(WTFMove(websiteData));
184 RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done fetching Website data", this);
185 });
186
187 send(Messages::NetworkProcess::FetchWebsiteData(sessionID, dataTypes, fetchOptions, callbackID), 0);
188}
189
190void NetworkProcessProxy::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, CompletionHandler<void ()>&& completionHandler)
191{
192 auto callbackID = generateCallbackID();
193 RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is deleting Website data", this);
194
195 m_pendingDeleteWebsiteDataCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] () mutable {
196#if RELEASE_LOG_DISABLED
197 UNUSED_PARAM(this);
198 UNUSED_PARAM(sessionID);
199#endif
200 completionHandler();
201 RELEASE_LOG_IF(sessionID.isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done deleting Website data", this);
202 });
203 send(Messages::NetworkProcess::DeleteWebsiteData(sessionID, dataTypes, modifiedSince, callbackID), 0);
204}
205
206void NetworkProcessProxy::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, const Vector<WebCore::SecurityOriginData>& origins, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, CompletionHandler<void()>&& completionHandler)
207{
208 ASSERT(canSendMessage());
209
210 uint64_t callbackID = generateCallbackID();
211 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);
212
213 m_pendingDeleteWebsiteDataForOriginsCallbacks.add(callbackID, [this, token = throttler().backgroundActivityToken(), completionHandler = WTFMove(completionHandler), sessionID] () mutable {
214#if RELEASE_LOG_DISABLED
215 UNUSED_PARAM(this);
216 UNUSED_PARAM(sessionID);
217#endif
218 completionHandler();
219 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);
220 });
221
222 send(Messages::NetworkProcess::DeleteWebsiteDataForOrigins(sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, callbackID), 0);
223}
224
225void NetworkProcessProxy::networkProcessCrashed()
226{
227 clearCallbackStates();
228
229 Vector<std::pair<RefPtr<WebProcessProxy>, Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>> pendingReplies;
230 pendingReplies.reserveInitialCapacity(m_pendingConnectionReplies.size());
231 for (auto& reply : m_pendingConnectionReplies) {
232 if (reply.first)
233 pendingReplies.append(std::make_pair(makeRefPtr(reply.first.get()), WTFMove(reply.second)));
234 else
235 reply.second({ });
236 }
237 m_pendingConnectionReplies.clear();
238
239 // Tell the network process manager to forget about this network process proxy. This will cause us to be deleted.
240 m_processPool.networkProcessCrashed(*this, WTFMove(pendingReplies));
241}
242
243void NetworkProcessProxy::clearCallbackStates()
244{
245 while (!m_pendingFetchWebsiteDataCallbacks.isEmpty())
246 m_pendingFetchWebsiteDataCallbacks.take(m_pendingFetchWebsiteDataCallbacks.begin()->key)(WebsiteData { });
247
248 while (!m_pendingDeleteWebsiteDataCallbacks.isEmpty())
249 m_pendingDeleteWebsiteDataCallbacks.take(m_pendingDeleteWebsiteDataCallbacks.begin()->key)();
250
251 while (!m_pendingDeleteWebsiteDataForOriginsCallbacks.isEmpty())
252 m_pendingDeleteWebsiteDataForOriginsCallbacks.take(m_pendingDeleteWebsiteDataForOriginsCallbacks.begin()->key)();
253}
254
255void NetworkProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
256{
257 if (dispatchMessage(connection, decoder))
258 return;
259
260 if (m_processPool.dispatchMessage(connection, decoder))
261 return;
262
263 didReceiveNetworkProcessProxyMessage(connection, decoder);
264}
265
266void NetworkProcessProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
267{
268 if (dispatchSyncMessage(connection, decoder, replyEncoder))
269 return;
270
271 ASSERT_NOT_REACHED();
272}
273
274void NetworkProcessProxy::didClose(IPC::Connection&)
275{
276 auto protectedProcessPool = makeRef(m_processPool);
277
278 if (m_downloadProxyMap)
279 m_downloadProxyMap->invalidate();
280#if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
281 m_customProtocolManagerProxy.invalidate();
282#endif
283
284 m_tokenForHoldingLockedFiles = nullptr;
285
286 m_syncAllCookiesToken = nullptr;
287 m_syncAllCookiesCounter = 0;
288
289 // This will cause us to be deleted.
290 networkProcessCrashed();
291}
292
293void NetworkProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
294{
295}
296
297void NetworkProcessProxy::didCreateNetworkConnectionToWebProcess(const IPC::Attachment& connectionIdentifier)
298{
299 ASSERT(!m_pendingConnectionReplies.isEmpty());
300
301 // Grab the first pending connection reply.
302 auto reply = m_pendingConnectionReplies.takeFirst().second;
303
304#if USE(UNIX_DOMAIN_SOCKETS) || OS(WINDOWS)
305 reply(connectionIdentifier);
306#elif OS(DARWIN)
307 MESSAGE_CHECK(MACH_PORT_VALID(connectionIdentifier.port()));
308 reply(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
309#else
310 notImplemented();
311#endif
312}
313
314void NetworkProcessProxy::didReceiveAuthenticationChallenge(PageIdentifier pageID, uint64_t frameID, WebCore::AuthenticationChallenge&& coreChallenge, uint64_t challengeID)
315{
316#if ENABLE(SERVICE_WORKER)
317 if (auto* serviceWorkerProcessProxy = m_processPool.serviceWorkerProcessProxyFromPageID(pageID)) {
318 auto authenticationChallenge = AuthenticationChallengeProxy::create(WTFMove(coreChallenge), challengeID, makeRef(*connection()), nullptr);
319 serviceWorkerProcessProxy->didReceiveAuthenticationChallenge(pageID, frameID, WTFMove(authenticationChallenge));
320 return;
321 }
322#endif
323
324 WebPageProxy* page = WebProcessProxy::webPage(pageID);
325 MESSAGE_CHECK(page);
326
327 auto authenticationChallenge = AuthenticationChallengeProxy::create(WTFMove(coreChallenge), challengeID, makeRef(*connection()), page->secKeyProxyStore(coreChallenge));
328 page->didReceiveAuthenticationChallengeProxy(frameID, WTFMove(authenticationChallenge));
329}
330
331void NetworkProcessProxy::didFetchWebsiteData(uint64_t callbackID, const WebsiteData& websiteData)
332{
333 auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID);
334 callback(websiteData);
335}
336
337void NetworkProcessProxy::didDeleteWebsiteData(uint64_t callbackID)
338{
339 auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID);
340 callback();
341}
342
343void NetworkProcessProxy::didDeleteWebsiteDataForOrigins(uint64_t callbackID)
344{
345 auto callback = m_pendingDeleteWebsiteDataForOriginsCallbacks.take(callbackID);
346 callback();
347}
348
349void NetworkProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
350{
351 AuxiliaryProcessProxy::didFinishLaunching(launcher, connectionIdentifier);
352
353 if (!IPC::Connection::identifierIsValid(connectionIdentifier)) {
354 networkProcessCrashed();
355 return;
356 }
357
358 for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
359 connection()->send(Messages::NetworkProcess::CreateNetworkConnectionToWebProcess(false, { }), 0);
360
361 m_numPendingConnectionRequests = 0;
362
363#if PLATFORM(COCOA)
364 if (m_processPool.processSuppressionEnabled())
365 setProcessSuppressionEnabled(true);
366#endif
367
368#if PLATFORM(IOS_FAMILY)
369 if (xpc_connection_t connection = this->connection()->xpcConnection())
370 m_throttler.didConnectToProcess(xpc_connection_get_pid(connection));
371#endif
372}
373
374void NetworkProcessProxy::logDiagnosticMessage(PageIdentifier pageID, const String& message, const String& description, WebCore::ShouldSample shouldSample)
375{
376 WebPageProxy* page = WebProcessProxy::webPage(pageID);
377 // 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,
378 // but for now we simply drop the message in the rare case this happens.
379 if (!page)
380 return;
381
382 page->logDiagnosticMessage(message, description, shouldSample);
383}
384
385void NetworkProcessProxy::logDiagnosticMessageWithResult(PageIdentifier pageID, const String& message, const String& description, uint32_t result, WebCore::ShouldSample shouldSample)
386{
387 WebPageProxy* page = WebProcessProxy::webPage(pageID);
388 // 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,
389 // but for now we simply drop the message in the rare case this happens.
390 if (!page)
391 return;
392
393 page->logDiagnosticMessageWithResult(message, description, result, shouldSample);
394}
395
396void NetworkProcessProxy::logDiagnosticMessageWithValue(PageIdentifier pageID, const String& message, const String& description, double value, unsigned significantFigures, WebCore::ShouldSample shouldSample)
397{
398 WebPageProxy* page = WebProcessProxy::webPage(pageID);
399 // 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,
400 // but for now we simply drop the message in the rare case this happens.
401 if (!page)
402 return;
403
404 page->logDiagnosticMessageWithValue(message, description, value, significantFigures, shouldSample);
405}
406
407void NetworkProcessProxy::logGlobalDiagnosticMessageWithValue(const String& message, const String& description, double value, unsigned significantFigures, WebCore::ShouldSample shouldSample)
408{
409 if (auto* page = WebPageProxy::nonEphemeralWebPageProxy())
410 page->logDiagnosticMessageWithValue(message, description, value, significantFigures, shouldSample);
411}
412
413#if ENABLE(RESOURCE_LOAD_STATISTICS)
414void NetworkProcessProxy::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
415{
416 if (!canSendMessage()) {
417 completionHandler({ });
418 return;
419 }
420
421 sendWithAsyncReply(Messages::NetworkProcess::DumpResourceLoadStatistics(sessionID), WTFMove(completionHandler));
422}
423
424void NetworkProcessProxy::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
425{
426 if (!canSendMessage()) {
427 completionHandler();
428 return;
429 }
430
431 Vector<RegistrableDomain> registrableDomainsToBlock;
432 registrableDomainsToBlock.reserveInitialCapacity(domainsToBlock.size());
433 for (auto& domain : domainsToBlock)
434 registrableDomainsToBlock.uncheckedAppend(domain);
435
436 sendWithAsyncReply(Messages::NetworkProcess::UpdatePrevalentDomainsToBlockCookiesFor(sessionID, registrableDomainsToBlock), WTFMove(completionHandler));
437}
438
439void NetworkProcessProxy::isPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler)
440{
441 if (!canSendMessage()) {
442 completionHandler(false);
443 return;
444 }
445
446 sendWithAsyncReply(Messages::NetworkProcess::IsPrevalentResource(sessionID, resourceDomain), WTFMove(completionHandler));
447}
448
449void NetworkProcessProxy::isVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler)
450{
451 if (!canSendMessage()) {
452 completionHandler(false);
453 return;
454 }
455
456 sendWithAsyncReply(Messages::NetworkProcess::IsVeryPrevalentResource(sessionID, resourceDomain), WTFMove(completionHandler));
457}
458
459void NetworkProcessProxy::setPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
460{
461 if (!canSendMessage()) {
462 completionHandler();
463 return;
464 }
465
466 sendWithAsyncReply(Messages::NetworkProcess::SetPrevalentResource(sessionID, resourceDomain), WTFMove(completionHandler));
467}
468
469void NetworkProcessProxy::setPrevalentResourceForDebugMode(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
470{
471 if (!canSendMessage()) {
472 completionHandler();
473 return;
474 }
475
476 sendWithAsyncReply(Messages::NetworkProcess::SetPrevalentResourceForDebugMode(sessionID, resourceDomain), WTFMove(completionHandler));
477}
478
479void NetworkProcessProxy::setVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
480{
481 if (!canSendMessage()) {
482 completionHandler();
483 return;
484 }
485
486 sendWithAsyncReply(Messages::NetworkProcess::SetVeryPrevalentResource(sessionID, resourceDomain), WTFMove(completionHandler));
487}
488
489void NetworkProcessProxy::setLastSeen(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, Seconds lastSeen, CompletionHandler<void()>&& completionHandler)
490{
491 if (!canSendMessage()) {
492 completionHandler();
493 return;
494 }
495
496 sendWithAsyncReply(Messages::NetworkProcess::SetLastSeen(sessionID, resourceDomain, lastSeen), WTFMove(completionHandler));
497}
498
499void NetworkProcessProxy::clearPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
500{
501 if (!canSendMessage()) {
502 completionHandler();
503 return;
504 }
505
506 sendWithAsyncReply(Messages::NetworkProcess::ClearPrevalentResource(sessionID, resourceDomain), WTFMove(completionHandler));
507}
508
509void NetworkProcessProxy::scheduleCookieBlockingUpdate(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
510{
511 if (!canSendMessage()) {
512 completionHandler();
513 return;
514 }
515
516 sendWithAsyncReply(Messages::NetworkProcess::ScheduleCookieBlockingUpdate(sessionID), WTFMove(completionHandler));
517}
518
519void NetworkProcessProxy::scheduleClearInMemoryAndPersistent(PAL::SessionID sessionID, Optional<WallTime> modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
520{
521 if (!canSendMessage()) {
522 completionHandler();
523 return;
524 }
525
526 sendWithAsyncReply(Messages::NetworkProcess::ScheduleClearInMemoryAndPersistent(sessionID, modifiedSince, shouldGrandfather), WTFMove(completionHandler));
527}
528
529void NetworkProcessProxy::scheduleStatisticsAndDataRecordsProcessing(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
530{
531 if (!canSendMessage()) {
532 completionHandler();
533 return;
534 }
535
536 sendWithAsyncReply(Messages::NetworkProcess::ScheduleStatisticsAndDataRecordsProcessing(sessionID), WTFMove(completionHandler));
537}
538
539void NetworkProcessProxy::logUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
540{
541 if (!canSendMessage()) {
542 completionHandler();
543 return;
544 }
545
546 sendWithAsyncReply(Messages::NetworkProcess::LogUserInteraction(sessionID, resourceDomain), WTFMove(completionHandler));
547}
548
549void NetworkProcessProxy::hasHadUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler)
550{
551 if (!canSendMessage()) {
552 completionHandler(false);
553 return;
554 }
555
556 sendWithAsyncReply(Messages::NetworkProcess::HadUserInteraction(sessionID, resourceDomain), WTFMove(completionHandler));
557}
558
559void NetworkProcessProxy::clearUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void()>&& completionHandler)
560{
561 if (!canSendMessage()) {
562 completionHandler();
563 return;
564 }
565
566 sendWithAsyncReply(Messages::NetworkProcess::ClearUserInteraction(sessionID, resourceDomain), WTFMove(completionHandler));
567}
568
569void NetworkProcessProxy::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler)
570{
571 if (!canSendMessage()) {
572 completionHandler(false);
573 return;
574 }
575
576 sendWithAsyncReply(Messages::NetworkProcess::HasLocalStorage(sessionID, resourceDomain), WTFMove(completionHandler));
577}
578
579void NetworkProcessProxy::setAgeCapForClientSideCookies(PAL::SessionID sessionID, Optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
580{
581 if (!canSendMessage()) {
582 completionHandler();
583 return;
584 }
585
586 sendWithAsyncReply(Messages::NetworkProcess::SetAgeCapForClientSideCookies(sessionID, seconds), WTFMove(completionHandler));
587}
588
589void NetworkProcessProxy::setTimeToLiveUserInteraction(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
590{
591 if (!canSendMessage()) {
592 completionHandler();
593 return;
594 }
595
596 sendWithAsyncReply(Messages::NetworkProcess::SetTimeToLiveUserInteraction(sessionID, seconds), WTFMove(completionHandler));
597}
598
599void NetworkProcessProxy::setNotifyPagesWhenTelemetryWasCaptured(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
600{
601 if (!canSendMessage()) {
602 completionHandler();
603 return;
604 }
605
606 sendWithAsyncReply(Messages::NetworkProcess::SetNotifyPagesWhenTelemetryWasCaptured(sessionID, value), WTFMove(completionHandler));
607}
608
609void NetworkProcessProxy::setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
610{
611 if (!canSendMessage()) {
612 completionHandler();
613 return;
614 }
615
616 sendWithAsyncReply(Messages::NetworkProcess::SetNotifyPagesWhenDataRecordsWereScanned(sessionID, value), WTFMove(completionHandler));
617}
618
619void NetworkProcessProxy::setIsRunningResourceLoadStatisticsTest(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
620{
621 if (!canSendMessage()) {
622 completionHandler();
623 return;
624 }
625
626 sendWithAsyncReply(Messages::NetworkProcess::SetIsRunningResourceLoadStatisticsTest(sessionID, value), WTFMove(completionHandler));
627}
628
629void NetworkProcessProxy::setSubframeUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
630{
631 if (!canSendMessage()) {
632 completionHandler();
633 return;
634 }
635
636 sendWithAsyncReply(Messages::NetworkProcess::SetSubframeUnderTopFrameDomain(sessionID, subFrameDomain, topFrameDomain), WTFMove(completionHandler));
637}
638
639void NetworkProcessProxy::isRegisteredAsRedirectingTo(PAL::SessionID sessionID, const RegistrableDomain& domainRedirectedFrom, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
640{
641 if (!canSendMessage()) {
642 completionHandler(false);
643 return;
644 }
645
646 sendWithAsyncReply(Messages::NetworkProcess::IsRegisteredAsRedirectingTo(sessionID, domainRedirectedFrom, domainRedirectedTo), WTFMove(completionHandler));
647}
648
649void NetworkProcessProxy::isRegisteredAsSubFrameUnder(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
650{
651 if (!canSendMessage()) {
652 completionHandler(false);
653 return;
654 }
655
656 sendWithAsyncReply(Messages::NetworkProcess::IsRegisteredAsSubFrameUnder(sessionID, subFrameDomain, topFrameDomain), WTFMove(completionHandler));
657}
658
659void NetworkProcessProxy::setSubresourceUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
660{
661 if (!canSendMessage()) {
662 completionHandler();
663 return;
664 }
665
666 sendWithAsyncReply(Messages::NetworkProcess::SetSubresourceUnderTopFrameDomain(sessionID, subresourceDomain, topFrameDomain), WTFMove(completionHandler));
667}
668
669void NetworkProcessProxy::isRegisteredAsSubresourceUnder(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
670{
671 if (!canSendMessage()) {
672 completionHandler(false);
673 return;
674 }
675
676 sendWithAsyncReply(Messages::NetworkProcess::IsRegisteredAsSubresourceUnder(sessionID, subresourceDomain, topFrameDomain), WTFMove(completionHandler));
677}
678
679void NetworkProcessProxy::setSubresourceUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
680{
681 if (!canSendMessage()) {
682 completionHandler();
683 return;
684 }
685
686 sendWithAsyncReply(Messages::NetworkProcess::SetSubresourceUniqueRedirectTo(sessionID, subresourceDomain, domainRedirectedTo), WTFMove(completionHandler));
687}
688
689void NetworkProcessProxy::setSubresourceUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
690{
691 if (!canSendMessage()) {
692 completionHandler();
693 return;
694 }
695
696 sendWithAsyncReply(Messages::NetworkProcess::SetSubresourceUniqueRedirectFrom(sessionID, subresourceDomain, domainRedirectedFrom), WTFMove(completionHandler));
697}
698
699void NetworkProcessProxy::setTopFrameUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
700{
701 if (!canSendMessage()) {
702 completionHandler();
703 return;
704 }
705
706 sendWithAsyncReply(Messages::NetworkProcess::SetTopFrameUniqueRedirectTo(sessionID, topFrameDomain, domainRedirectedTo), WTFMove(completionHandler));
707}
708
709void NetworkProcessProxy::setTopFrameUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
710{
711 if (!canSendMessage()) {
712 completionHandler();
713 return;
714 }
715
716 sendWithAsyncReply(Messages::NetworkProcess::SetTopFrameUniqueRedirectFrom(sessionID, topFrameDomain, domainRedirectedFrom), WTFMove(completionHandler));
717}
718
719void NetworkProcessProxy::isGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, CompletionHandler<void(bool)>&& completionHandler)
720{
721 if (!canSendMessage()) {
722 completionHandler(false);
723 return;
724 }
725
726 sendWithAsyncReply(Messages::NetworkProcess::IsGrandfathered(sessionID, resourceDomain), WTFMove(completionHandler));
727}
728
729void NetworkProcessProxy::setGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& resourceDomain, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
730{
731 if (!canSendMessage()) {
732 completionHandler();
733 return;
734 }
735
736 sendWithAsyncReply(Messages::NetworkProcess::SetGrandfathered(sessionID, resourceDomain, isGrandfathered), WTFMove(completionHandler));
737}
738
739void NetworkProcessProxy::requestStorageAccessConfirm(PageIdentifier pageID, uint64_t frameID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
740{
741 WebPageProxy* page = WebProcessProxy::webPage(pageID);
742 if (!page) {
743 completionHandler(false);
744 return;
745 }
746
747 page->requestStorageAccessConfirm(subFrameDomain, topFrameDomain, frameID, WTFMove(completionHandler));
748}
749
750void NetworkProcessProxy::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String> domains)>&& completionHandler)
751{
752 if (!canSendMessage()) {
753 completionHandler({ });
754 return;
755 }
756
757 sendWithAsyncReply(Messages::NetworkProcess::GetAllStorageAccessEntries(sessionID), WTFMove(completionHandler));
758}
759
760void NetworkProcessProxy::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
761{
762 if (!canSendMessage()) {
763 completionHandler();
764 return;
765 }
766
767 sendWithAsyncReply(Messages::NetworkProcess::SetCacheMaxAgeCapForPrevalentResources(sessionID, seconds), WTFMove(completionHandler));
768}
769
770void NetworkProcessProxy::setCacheMaxAgeCap(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
771{
772 if (!canSendMessage()) {
773 completionHandler();
774 return;
775 }
776
777 sendWithAsyncReply(Messages::NetworkProcess::SetCacheMaxAgeCapForPrevalentResources(sessionID, seconds), WTFMove(completionHandler));
778}
779
780void NetworkProcessProxy::setGrandfatheringTime(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
781{
782 if (!canSendMessage()) {
783 completionHandler();
784 return;
785 }
786
787 sendWithAsyncReply(Messages::NetworkProcess::SetGrandfatheringTime(sessionID, seconds), WTFMove(completionHandler));
788}
789
790void NetworkProcessProxy::setMaxStatisticsEntries(PAL::SessionID sessionID, size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
791{
792 if (!canSendMessage()) {
793 completionHandler();
794 return;
795 }
796
797 sendWithAsyncReply(Messages::NetworkProcess::SetMaxStatisticsEntries(sessionID, maximumEntryCount), WTFMove(completionHandler));
798}
799
800void NetworkProcessProxy::setMinimumTimeBetweenDataRecordsRemoval(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
801{
802 if (!canSendMessage()) {
803 completionHandler();
804 return;
805 }
806
807 sendWithAsyncReply(Messages::NetworkProcess::SetMinimumTimeBetweenDataRecordsRemoval(sessionID, seconds), WTFMove(completionHandler));
808}
809
810void NetworkProcessProxy::setPruneEntriesDownTo(PAL::SessionID sessionID, size_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
811{
812 if (!canSendMessage()) {
813 completionHandler();
814 return;
815 }
816
817 sendWithAsyncReply(Messages::NetworkProcess::SetPruneEntriesDownTo(sessionID, pruneTargetCount), WTFMove(completionHandler));
818}
819
820void NetworkProcessProxy::setShouldClassifyResourcesBeforeDataRecordsRemoval(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
821{
822 if (!canSendMessage()) {
823 completionHandler();
824 return;
825 }
826
827 sendWithAsyncReply(Messages::NetworkProcess::SetShouldClassifyResourcesBeforeDataRecordsRemoval(sessionID, value), WTFMove(completionHandler));
828}
829
830void NetworkProcessProxy::setResourceLoadStatisticsDebugMode(PAL::SessionID sessionID, bool debugMode, CompletionHandler<void()>&& completionHandler)
831{
832 if (!canSendMessage()) {
833 completionHandler();
834 return;
835 }
836
837 sendWithAsyncReply(Messages::NetworkProcess::SetResourceLoadStatisticsDebugMode(sessionID, debugMode), WTFMove(completionHandler));
838}
839
840void NetworkProcessProxy::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
841{
842 if (!canSendMessage()) {
843 completionHandler();
844 return;
845 }
846
847 sendWithAsyncReply(Messages::NetworkProcess::ResetCacheMaxAgeCapForPrevalentResources(sessionID), WTFMove(completionHandler));
848}
849
850void NetworkProcessProxy::resetParametersToDefaultValues(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
851{
852 if (!canSendMessage()) {
853 completionHandler();
854 return;
855 }
856
857 sendWithAsyncReply(Messages::NetworkProcess::ResetParametersToDefaultValues(sessionID), WTFMove(completionHandler));
858}
859
860void NetworkProcessProxy::submitTelemetry(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
861{
862 if (!canSendMessage()) {
863 completionHandler();
864 return;
865 }
866
867 sendWithAsyncReply(Messages::NetworkProcess::SubmitTelemetry(sessionID), WTFMove(completionHandler));
868}
869
870void NetworkProcessProxy::scheduleClearInMemoryAndPersistent(PAL::SessionID sessionID, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
871{
872 if (!canSendMessage()) {
873 completionHandler();
874 return;
875 }
876
877 sendWithAsyncReply(Messages::NetworkProcess::ScheduleClearInMemoryAndPersistent(sessionID, { }, shouldGrandfather), WTFMove(completionHandler));
878}
879
880void NetworkProcessProxy::logTestingEvent(PAL::SessionID sessionID, const String& event)
881{
882 if (auto* websiteDataStore = websiteDataStoreFromSessionID(sessionID))
883 websiteDataStore->logTestingEvent(event);
884}
885
886void NetworkProcessProxy::notifyResourceLoadStatisticsProcessed()
887{
888 WebProcessProxy::notifyPageStatisticsAndDataRecordsProcessed();
889}
890
891void NetworkProcessProxy::notifyWebsiteDataDeletionForRegistrableDomainsFinished()
892{
893 WebProcessProxy::notifyWebsiteDataDeletionForRegistrableDomainsFinished();
894}
895
896void NetworkProcessProxy::notifyWebsiteDataScanForRegistrableDomainsFinished()
897{
898 WebProcessProxy::notifyWebsiteDataScanForRegistrableDomainsFinished();
899}
900
901void NetworkProcessProxy::notifyResourceLoadStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins)
902{
903 API::Dictionary::MapType messageBody;
904 messageBody.set("TotalPrevalentResources"_s, API::UInt64::create(totalPrevalentResources));
905 messageBody.set("TotalPrevalentResourcesWithUserInteraction"_s, API::UInt64::create(totalPrevalentResourcesWithUserInteraction));
906 messageBody.set("Top3SubframeUnderTopFrameOrigins"_s, API::UInt64::create(top3SubframeUnderTopFrameOrigins));
907
908 WebProcessProxy::notifyPageStatisticsTelemetryFinished(API::Dictionary::create(messageBody).ptr());
909}
910
911void NetworkProcessProxy::didCommitCrossSiteLoadWithDataTransfer(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, OptionSet<WebCore::CrossSiteNavigationDataTransfer::Flag> navigationDataTransfer, PageIdentifier pageID)
912{
913 if (!canSendMessage())
914 return;
915
916 send(Messages::NetworkProcess::DidCommitCrossSiteLoadWithDataTransfer(sessionID, fromDomain, toDomain, navigationDataTransfer, pageID), 0);
917}
918
919void NetworkProcessProxy::didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(PageIdentifier pageID)
920{
921 if (!canSendMessage())
922 return;
923
924 WebPageProxy* page = WebProcessProxy::webPage(pageID);
925 if (!page)
926 return;
927
928 page->didCommitCrossSiteLoadWithDataTransferFromPrevalentResource();
929}
930
931void NetworkProcessProxy::setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
932{
933 if (!canSendMessage()) {
934 completionHandler();
935 return;
936 }
937
938 sendWithAsyncReply(Messages::NetworkProcess::SetCrossSiteLoadWithLinkDecorationForTesting(sessionID, fromDomain, toDomain), WTFMove(completionHandler));
939}
940
941void NetworkProcessProxy::resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
942{
943 if (!canSendMessage()) {
944 completionHandler();
945 return;
946 }
947
948 sendWithAsyncReply(Messages::NetworkProcess::ResetCrossSiteLoadsWithLinkDecorationForTesting(sessionID), WTFMove(completionHandler));
949}
950
951void NetworkProcessProxy::deleteCookiesForTesting(PAL::SessionID sessionID, const RegistrableDomain& domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
952{
953 if (!canSendMessage()) {
954 completionHandler();
955 return;
956 }
957
958 sendWithAsyncReply(Messages::NetworkProcess::DeleteCookiesForTesting(sessionID, domain, includeHttpOnlyCookies), WTFMove(completionHandler));
959}
960
961void NetworkProcessProxy::deleteWebsiteDataInUIProcessForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Vector<RegistrableDomain> domains, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
962{
963 auto* websiteDataStore = websiteDataStoreFromSessionID(sessionID);
964 if (!websiteDataStore || dataTypes.isEmpty() || domains.isEmpty()) {
965 completionHandler({ });
966 return;
967 }
968
969 websiteDataStore->fetchDataForRegistrableDomains(dataTypes, fetchOptions, domains, [dataTypes, websiteDataStore = makeRef(*websiteDataStore), completionHandler = WTFMove(completionHandler)] (Vector<WebsiteDataRecord>&& matchingDataRecords, HashSet<WebCore::RegistrableDomain>&& domainsWithMatchingDataRecords) mutable {
970 websiteDataStore->removeData(dataTypes, WTFMove(matchingDataRecords), [domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords), completionHandler = WTFMove(completionHandler)] () mutable {
971 completionHandler(WTFMove(domainsWithMatchingDataRecords));
972 });
973 });
974}
975
976#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
977
978void NetworkProcessProxy::sendProcessWillSuspendImminently()
979{
980 if (canSendMessage())
981 send(Messages::NetworkProcess::ProcessWillSuspendImminently(), 0);
982}
983
984void NetworkProcessProxy::sendPrepareToSuspend()
985{
986 if (canSendMessage())
987 send(Messages::NetworkProcess::PrepareToSuspend(), 0);
988}
989
990void NetworkProcessProxy::sendCancelPrepareToSuspend()
991{
992 if (canSendMessage())
993 send(Messages::NetworkProcess::CancelPrepareToSuspend(), 0);
994}
995
996void NetworkProcessProxy::sendProcessDidResume()
997{
998 if (canSendMessage())
999 send(Messages::NetworkProcess::ProcessDidResume(), 0);
1000}
1001
1002void NetworkProcessProxy::processReadyToSuspend()
1003{
1004 m_throttler.processReadyToSuspend();
1005}
1006
1007void NetworkProcessProxy::didSetAssertionState(AssertionState)
1008{
1009}
1010
1011void NetworkProcessProxy::setIsHoldingLockedFiles(bool isHoldingLockedFiles)
1012{
1013 if (!isHoldingLockedFiles) {
1014 RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the Network process is no longer holding locked files");
1015 m_tokenForHoldingLockedFiles = nullptr;
1016 return;
1017 }
1018 if (!m_tokenForHoldingLockedFiles) {
1019 RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the Network process is holding locked files");
1020 m_tokenForHoldingLockedFiles = m_throttler.backgroundActivityToken();
1021 }
1022}
1023
1024void NetworkProcessProxy::syncAllCookies()
1025{
1026 send(Messages::NetworkProcess::SyncAllCookies(), 0);
1027
1028 ++m_syncAllCookiesCounter;
1029 if (m_syncAllCookiesToken)
1030 return;
1031
1032 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcessProxy is taking a background assertion because the Network process is syncing cookies", this);
1033 m_syncAllCookiesToken = throttler().backgroundActivityToken();
1034}
1035
1036void NetworkProcessProxy::didSyncAllCookies()
1037{
1038 ASSERT(m_syncAllCookiesCounter);
1039
1040 --m_syncAllCookiesCounter;
1041 if (!m_syncAllCookiesCounter) {
1042 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcessProxy is releasing a background assertion because the Network process is done syncing cookies", this);
1043 m_syncAllCookiesToken = nullptr;
1044 }
1045}
1046
1047void NetworkProcessProxy::addSession(Ref<WebsiteDataStore>&& store)
1048{
1049 if (canSendMessage())
1050 send(Messages::NetworkProcess::AddWebsiteDataStore { store->parameters() }, 0);
1051 auto sessionID = store->sessionID();
1052 if (!sessionID.isEphemeral()) {
1053#if ENABLE(INDEXED_DATABASE)
1054 createSymLinkForFileUpgrade(store->resolvedIndexedDatabaseDirectory());
1055#endif
1056 m_websiteDataStores.set(sessionID, WTFMove(store));
1057 }
1058}
1059
1060void NetworkProcessProxy::removeSession(PAL::SessionID sessionID)
1061{
1062 if (canSendMessage())
1063 send(Messages::NetworkProcess::DestroySession { sessionID }, 0);
1064 if (!sessionID.isEphemeral())
1065 m_websiteDataStores.remove(sessionID);
1066}
1067
1068WebsiteDataStore* NetworkProcessProxy::websiteDataStoreFromSessionID(PAL::SessionID sessionID)
1069{
1070 auto iterator = m_websiteDataStores.find(sessionID);
1071 if (iterator != m_websiteDataStores.end())
1072 return iterator->value.get();
1073
1074 if (auto* websiteDataStore = m_processPool.websiteDataStore()) {
1075 if (sessionID == websiteDataStore->websiteDataStore().sessionID())
1076 return &websiteDataStore->websiteDataStore();
1077 }
1078
1079 if (sessionID != PAL::SessionID::defaultSessionID())
1080 return nullptr;
1081
1082 return &API::WebsiteDataStore::defaultDataStore()->websiteDataStore();
1083}
1084
1085void NetworkProcessProxy::retrieveCacheStorageParameters(PAL::SessionID sessionID)
1086{
1087 auto* store = websiteDataStoreFromSessionID(sessionID);
1088
1089 if (!store) {
1090 RELEASE_LOG_ERROR(CacheStorage, "%p - NetworkProcessProxy is unable to retrieve CacheStorage parameters from the given session ID %" PRIu64, this, sessionID.sessionID());
1091 send(Messages::NetworkProcess::SetCacheStorageParameters { sessionID, { }, { } }, 0);
1092 return;
1093 }
1094
1095 auto& cacheStorageDirectory = store->cacheStorageDirectory();
1096 SandboxExtension::Handle cacheStorageDirectoryExtensionHandle;
1097 if (!cacheStorageDirectory.isEmpty())
1098 SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, cacheStorageDirectoryExtensionHandle);
1099
1100 send(Messages::NetworkProcess::SetCacheStorageParameters { sessionID, cacheStorageDirectory, cacheStorageDirectoryExtensionHandle }, 0);
1101}
1102
1103#if ENABLE(CONTENT_EXTENSIONS)
1104void NetworkProcessProxy::contentExtensionRules(UserContentControllerIdentifier identifier)
1105{
1106 if (auto* webUserContentControllerProxy = WebUserContentControllerProxy::get(identifier)) {
1107 m_webUserContentControllerProxies.add(webUserContentControllerProxy);
1108 webUserContentControllerProxy->addNetworkProcess(*this);
1109
1110 auto rules = WTF::map(webUserContentControllerProxy->contentExtensionRules(), [](auto&& keyValue) -> std::pair<String, WebCompiledContentRuleListData> {
1111 return std::make_pair(keyValue.value->name(), keyValue.value->compiledRuleList().data());
1112 });
1113 send(Messages::NetworkContentRuleListManager::AddContentRuleLists { identifier, rules }, 0);
1114 return;
1115 }
1116 send(Messages::NetworkContentRuleListManager::AddContentRuleLists { identifier, { } }, 0);
1117}
1118
1119void NetworkProcessProxy::didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy& proxy)
1120{
1121 send(Messages::NetworkContentRuleListManager::Remove { proxy.identifier() }, 0);
1122 m_webUserContentControllerProxies.remove(&proxy);
1123}
1124#endif
1125
1126void NetworkProcessProxy::sendProcessDidTransitionToForeground()
1127{
1128 send(Messages::NetworkProcess::ProcessDidTransitionToForeground(), 0);
1129}
1130
1131void NetworkProcessProxy::sendProcessDidTransitionToBackground()
1132{
1133 send(Messages::NetworkProcess::ProcessDidTransitionToBackground(), 0);
1134}
1135
1136#if ENABLE(SANDBOX_EXTENSIONS)
1137void NetworkProcessProxy::getSandboxExtensionsForBlobFiles(const Vector<String>& paths, Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles::AsyncReply&& reply)
1138{
1139 SandboxExtension::HandleArray extensions;
1140 extensions.allocate(paths.size());
1141 for (size_t i = 0; i < paths.size(); ++i) {
1142 // ReadWrite is required for creating hard links, which is something that might be done with these extensions.
1143 SandboxExtension::createHandle(paths[i], SandboxExtension::Type::ReadWrite, extensions[i]);
1144 }
1145 reply(WTFMove(extensions));
1146}
1147#endif
1148
1149#if ENABLE(SERVICE_WORKER)
1150void NetworkProcessProxy::establishWorkerContextConnectionToNetworkProcess(RegistrableDomain&& registrableDomain)
1151{
1152 m_processPool.establishWorkerContextConnectionToNetworkProcess(*this, WTFMove(registrableDomain), WTF::nullopt);
1153}
1154
1155void NetworkProcessProxy::establishWorkerContextConnectionToNetworkProcessForExplicitSession(RegistrableDomain&& registrableDomain, PAL::SessionID sessionID)
1156{
1157 m_processPool.establishWorkerContextConnectionToNetworkProcess(*this, WTFMove(registrableDomain), sessionID);
1158}
1159#endif
1160
1161void NetworkProcessProxy::requestStorageSpace(PAL::SessionID sessionID, const WebCore::ClientOrigin& origin, uint64_t currentQuota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(Optional<uint64_t> quota)>&& completionHandler)
1162{
1163 auto* store = websiteDataStoreFromSessionID(sessionID);
1164
1165 if (!store) {
1166 completionHandler({ });
1167 return;
1168 }
1169
1170 store->client().requestStorageSpace(origin.topOrigin, origin.clientOrigin, currentQuota, currentSize, spaceRequired, [sessionID, origin, currentQuota, currentSize, spaceRequired, completionHandler = WTFMove(completionHandler)](auto quota) mutable {
1171 if (quota) {
1172 completionHandler(quota);
1173 return;
1174 }
1175
1176 if (origin.topOrigin != origin.clientOrigin) {
1177 completionHandler({ });
1178 return;
1179 }
1180
1181 WebPageProxy::forMostVisibleWebPageIfAny(sessionID, origin.topOrigin, [completionHandler = WTFMove(completionHandler), origin, currentQuota, currentSize, spaceRequired](auto* page) mutable {
1182 if (!page) {
1183 completionHandler({ });
1184 return;
1185 }
1186 String name = makeString(FileSystem::encodeForFileName(origin.topOrigin.host), " content");
1187 page->requestStorageSpace(page->mainFrame()->frameID(), origin.topOrigin.databaseIdentifier(), name, name, currentQuota, currentSize, currentSize, spaceRequired, [completionHandler = WTFMove(completionHandler)](auto quota) mutable {
1188 completionHandler(quota);
1189 });
1190 });
1191 });
1192}
1193
1194void NetworkProcessProxy::takeUploadAssertion()
1195{
1196 ASSERT(!m_uploadAssertion);
1197 m_uploadAssertion = std::make_unique<ProcessAssertion>(processIdentifier(), "WebKit uploads"_s, AssertionState::UnboundedNetworking);
1198}
1199
1200void NetworkProcessProxy::clearUploadAssertion()
1201{
1202 ASSERT(m_uploadAssertion);
1203 m_uploadAssertion = nullptr;
1204}
1205
1206#if ENABLE(INDEXED_DATABASE)
1207void NetworkProcessProxy::createSymLinkForFileUpgrade(const String& indexedDatabaseDirectory)
1208{
1209 if (indexedDatabaseDirectory.isEmpty())
1210 return;
1211
1212 String oldVersionDirectory = FileSystem::pathByAppendingComponent(indexedDatabaseDirectory, "v0");
1213 FileSystem::deleteEmptyDirectory(oldVersionDirectory);
1214 if (!FileSystem::fileExists(oldVersionDirectory))
1215 FileSystem::createSymbolicLink(indexedDatabaseDirectory, oldVersionDirectory);
1216}
1217#endif
1218
1219void NetworkProcessProxy::getLocalStorageDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
1220{
1221 if (!canSendMessage()) {
1222 completionHandler({ });
1223 return;
1224 }
1225
1226 sendWithAsyncReply(Messages::NetworkProcess::GetLocalStorageOriginDetails(sessionID), WTFMove(completionHandler));
1227}
1228
1229} // namespace WebKit
1230
1231#undef MESSAGE_CHECK
1232#undef MESSAGE_CHECK_URL
1233