Add facility for tracking times and results of page and resource loading
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkConnectionToWebProcess.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 "NetworkConnectionToWebProcess.h"
28
29 #include "BlobDataFileReferenceWithSandboxExtension.h"
30 #include "CacheStorageEngineConnectionMessages.h"
31 #include "DataReference.h"
32 #include "Logging.h"
33 #include "NetworkBlobRegistry.h"
34 #include "NetworkCache.h"
35 #include "NetworkConnectionToWebProcessMessages.h"
36 #include "NetworkLoad.h"
37 #include "NetworkMDNSRegisterMessages.h"
38 #include "NetworkProcess.h"
39 #include "NetworkProcessConnectionMessages.h"
40 #include "NetworkRTCMonitorMessages.h"
41 #include "NetworkRTCProviderMessages.h"
42 #include "NetworkRTCSocketMessages.h"
43 #include "NetworkResourceLoadParameters.h"
44 #include "NetworkResourceLoader.h"
45 #include "NetworkResourceLoaderMessages.h"
46 #include "NetworkSocketStream.h"
47 #include "NetworkSocketStreamMessages.h"
48 #include "PingLoad.h"
49 #include "PreconnectTask.h"
50 #include "SessionTracker.h"
51 #include "WebCoreArgumentCoders.h"
52 #include "WebErrors.h"
53 #include "WebsiteDataStore.h"
54 #include "WebsiteDataStoreParameters.h"
55 #include <WebCore/NetworkStorageSession.h>
56 #include <WebCore/PlatformCookieJar.h>
57 #include <WebCore/ResourceLoaderOptions.h>
58 #include <WebCore/ResourceRequest.h>
59 #include <WebCore/SameSiteInfo.h>
60 #include <WebCore/SecurityPolicy.h>
61 #include <pal/SessionID.h>
62
63 using namespace WebCore;
64
65 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(true, Network, "%p - NetworkConnectionToWebProcess::" fmt, this, ##__VA_ARGS__)
66 #define RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(true, Network, "%p - NetworkConnectionToWebProcess::" fmt, this, ##__VA_ARGS__)
67
68 namespace WebKit {
69
70 Ref<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(IPC::Connection::Identifier connectionIdentifier)
71 {
72     return adoptRef(*new NetworkConnectionToWebProcess(connectionIdentifier));
73 }
74
75 NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(IPC::Connection::Identifier connectionIdentifier)
76     : m_connection(IPC::Connection::createServerConnection(connectionIdentifier, *this))
77 #if ENABLE(WEB_RTC)
78     , m_mdnsRegister(*this)
79 #endif
80 {
81     m_connection->open();
82 }
83
84 NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess()
85 {
86     m_connection->invalidate();
87 #if USE(LIBWEBRTC)
88     if (m_rtcProvider)
89         m_rtcProvider->close();
90 #endif
91 }
92
93 void NetworkConnectionToWebProcess::didCleanupResourceLoader(NetworkResourceLoader& loader)
94 {
95     ASSERT(m_networkResourceLoaders.get(loader.identifier()) == &loader);
96
97     m_networkResourceLoaders.remove(loader.identifier());
98 }
99
100 void NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
101 {
102     if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
103         didReceiveNetworkConnectionToWebProcessMessage(connection, decoder);
104         return;
105     }
106
107     if (decoder.messageReceiverName() == Messages::NetworkResourceLoader::messageReceiverName()) {
108         auto loaderIterator = m_networkResourceLoaders.find(decoder.destinationID());
109         if (loaderIterator != m_networkResourceLoaders.end())
110             loaderIterator->value->didReceiveNetworkResourceLoaderMessage(connection, decoder);
111         return;
112     }
113
114     if (decoder.messageReceiverName() == Messages::NetworkSocketStream::messageReceiverName()) {
115         auto socketIterator = m_networkSocketStreams.find(decoder.destinationID());
116         if (socketIterator != m_networkSocketStreams.end()) {
117             socketIterator->value->didReceiveMessage(connection, decoder);
118             if (decoder.messageName() == Messages::NetworkSocketStream::Close::name())
119                 m_networkSocketStreams.remove(socketIterator);
120         }
121         return;
122     }
123
124 #if USE(LIBWEBRTC)
125     if (decoder.messageReceiverName() == Messages::NetworkRTCSocket::messageReceiverName()) {
126         rtcProvider().didReceiveNetworkRTCSocketMessage(connection, decoder);
127         return;
128     }
129     if (decoder.messageReceiverName() == Messages::NetworkRTCMonitor::messageReceiverName()) {
130         rtcProvider().didReceiveNetworkRTCMonitorMessage(connection, decoder);
131         return;
132     }
133     if (decoder.messageReceiverName() == Messages::NetworkRTCProvider::messageReceiverName()) {
134         rtcProvider().didReceiveMessage(connection, decoder);
135         return;
136     }
137 #endif
138 #if ENABLE(WEB_RTC)
139     if (decoder.messageReceiverName() == Messages::NetworkMDNSRegister::messageReceiverName()) {
140         mdnsRegister().didReceiveMessage(connection, decoder);
141         return;
142     }
143 #endif
144
145     if (decoder.messageReceiverName() == Messages::CacheStorageEngineConnection::messageReceiverName()) {
146         cacheStorageConnection().didReceiveMessage(connection, decoder);
147         return;
148     }
149
150     ASSERT_NOT_REACHED();
151 }
152
153 #if USE(LIBWEBRTC)
154 NetworkRTCProvider& NetworkConnectionToWebProcess::rtcProvider()
155 {
156     if (!m_rtcProvider)
157         m_rtcProvider = NetworkRTCProvider::create(*this);
158     return *m_rtcProvider;
159 }
160 #endif
161
162 CacheStorageEngineConnection& NetworkConnectionToWebProcess::cacheStorageConnection()
163 {
164     if (!m_cacheStorageConnection)
165         m_cacheStorageConnection = CacheStorageEngineConnection::create(*this);
166     return *m_cacheStorageConnection;
167 }
168
169 void NetworkConnectionToWebProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& reply)
170 {
171     if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
172         didReceiveSyncNetworkConnectionToWebProcessMessage(connection, decoder, reply);
173         return;
174     }
175     ASSERT_NOT_REACHED();
176 }
177
178 void NetworkConnectionToWebProcess::didClose(IPC::Connection&)
179 {
180     // Protect ourself as we might be otherwise be deleted during this function.
181     Ref<NetworkConnectionToWebProcess> protector(*this);
182
183     for (auto& loader : copyToVector(m_networkResourceLoaders.values()))
184         loader->abort();
185     ASSERT(m_networkResourceLoaders.isEmpty());
186
187     // All trackers of resources that were in the middle of being loaded were
188     // stopped with the abort() calls above, but we still need to sweep up the
189     // root activity trackers.
190     stopAllNetworkActivityTracking();
191
192     NetworkBlobRegistry::singleton().connectionToWebProcessDidClose(this);
193     NetworkProcess::singleton().removeNetworkConnectionToWebProcess(this);
194
195 #if USE(LIBWEBRTC)
196     if (m_rtcProvider) {
197         m_rtcProvider->close();
198         m_rtcProvider = nullptr;
199     }
200 #endif
201 }
202
203 void NetworkConnectionToWebProcess::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference)
204 {
205 }
206
207 void NetworkConnectionToWebProcess::createSocketStream(URL&& url, PAL::SessionID sessionID, String cachePartition, uint64_t identifier)
208 {
209     ASSERT(!m_networkSocketStreams.contains(identifier));
210     WebCore::SourceApplicationAuditToken token = { };
211 #if PLATFORM(COCOA)
212     token = { NetworkProcess::singleton().sourceApplicationAuditData() };
213 #endif
214     m_networkSocketStreams.set(identifier, NetworkSocketStream::create(WTFMove(url), sessionID, cachePartition, identifier, m_connection, WTFMove(token)));
215 }
216
217 void NetworkConnectionToWebProcess::destroySocketStream(uint64_t identifier)
218 {
219     ASSERT(m_networkSocketStreams.get(identifier));
220     m_networkSocketStreams.remove(identifier);
221 }
222
223 void NetworkConnectionToWebProcess::cleanupForSuspension(Function<void()>&& completionHandler)
224 {
225 #if USE(LIBWEBRTC)
226     if (m_rtcProvider) {
227         m_rtcProvider->closeListeningSockets(WTFMove(completionHandler));
228         return;
229     }
230 #endif
231     completionHandler();
232 }
233
234 void NetworkConnectionToWebProcess::endSuspension()
235 {
236 #if USE(LIBWEBRTC)
237     if (m_rtcProvider)
238         m_rtcProvider->authorizeListeningSockets();
239 #endif
240 }
241
242 void NetworkConnectionToWebProcess::scheduleResourceLoad(NetworkResourceLoadParameters&& loadParameters)
243 {
244     auto identifier = loadParameters.identifier;
245     ASSERT(!m_networkResourceLoaders.contains(identifier));
246
247     auto loader = NetworkResourceLoader::create(WTFMove(loadParameters), *this);
248     m_networkResourceLoaders.add(identifier, loader.ptr());
249     loader->start();
250 }
251
252 void NetworkConnectionToWebProcess::performSynchronousLoad(NetworkResourceLoadParameters&& loadParameters, Ref<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply>&& reply)
253 {
254     auto identifier = loadParameters.identifier;
255     ASSERT(!m_networkResourceLoaders.contains(identifier));
256
257     auto loader = NetworkResourceLoader::create(WTFMove(loadParameters), *this, WTFMove(reply));
258     m_networkResourceLoaders.add(identifier, loader.ptr());
259     loader->start();
260 }
261
262 void NetworkConnectionToWebProcess::loadPing(NetworkResourceLoadParameters&& loadParameters)
263 {
264     auto completionHandler = [this, protectedThis = makeRef(*this), identifier = loadParameters.identifier] (const ResourceError& error, const ResourceResponse& response) {
265         didFinishPingLoad(identifier, error, response);
266     };
267
268     // PingLoad manages its own lifetime, deleting itself when its purpose has been fulfilled.
269     new PingLoad(WTFMove(loadParameters), WTFMove(completionHandler));
270 }
271
272 void NetworkConnectionToWebProcess::didFinishPingLoad(uint64_t pingLoadIdentifier, const ResourceError& error, const ResourceResponse& response)
273 {
274     if (!m_connection->isValid())
275         return;
276
277     m_connection->send(Messages::NetworkProcessConnection::DidFinishPingLoad(pingLoadIdentifier, error, response), 0);
278 }
279
280 void NetworkConnectionToWebProcess::setOnLineState(bool isOnLine)
281 {
282     m_connection->send(Messages::NetworkProcessConnection::SetOnLineState(isOnLine), 0);
283 }
284
285 void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier)
286 {
287     RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier);
288
289     // It's possible we have no loader for this identifier if the NetworkProcess crashed and this was a respawned NetworkProcess.
290     if (!loader)
291         return;
292
293     // Abort the load now, as the WebProcess won't be able to respond to messages any more which might lead
294     // to leaked loader resources (connections, threads, etc).
295     loader->abort();
296     ASSERT(!m_networkResourceLoaders.contains(identifier));
297 }
298
299 void NetworkConnectionToWebProcess::pageLoadCompleted(uint64_t webPageID)
300 {
301     stopAllNetworkActivityTrackingForPage(webPageID);
302 }
303
304 void NetworkConnectionToWebProcess::setDefersLoading(ResourceLoadIdentifier identifier, bool defers)
305 {
306     RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.get(identifier);
307     if (!loader)
308         return;
309
310     loader->setDefersLoading(defers);
311 }
312
313 void NetworkConnectionToWebProcess::prefetchDNS(const String& hostname)
314 {
315     NetworkProcess::singleton().prefetchDNS(hostname);
316 }
317
318 void NetworkConnectionToWebProcess::preconnectTo(uint64_t preconnectionIdentifier, NetworkResourceLoadParameters&& parameters)
319 {
320 #if ENABLE(SERVER_PRECONNECT)
321     new PreconnectTask(WTFMove(parameters), [this, protectedThis = makeRef(*this), identifier = preconnectionIdentifier] (const ResourceError& error) {
322         didFinishPreconnection(identifier, error);
323     });
324 #else
325     UNUSED_PARAM(parameters);
326     didFinishPreconnection(preconnectionIdentifier, internalError(parameters.request.url()));
327 #endif
328 }
329
330 void NetworkConnectionToWebProcess::didFinishPreconnection(uint64_t preconnectionIdentifier, const ResourceError& error)
331 {
332     if (!m_connection->isValid())
333         return;
334
335     m_connection->send(Messages::NetworkProcessConnection::DidFinishPreconnection(preconnectionIdentifier, error), 0);
336 }
337
338 static NetworkStorageSession& storageSession(PAL::SessionID sessionID)
339 {
340     ASSERT(sessionID.isValid());
341     if (sessionID != PAL::SessionID::defaultSessionID()) {
342         if (auto* storageSession = NetworkStorageSession::storageSession(sessionID))
343             return *storageSession;
344
345         // Some requests with private browsing mode requested may still be coming shortly after NetworkProcess was told to destroy its session.
346         // FIXME: Find a way to track private browsing sessions more rigorously.
347         LOG_ERROR("Non-default storage session was requested, but there was no session for it. Please file a bug unless you just disabled private browsing, in which case it's an expected race.");
348     }
349     return NetworkStorageSession::defaultStorageSession();
350 }
351
352 void NetworkConnectionToWebProcess::startDownload(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedName)
353 {
354     NetworkProcess::singleton().downloadManager().startDownload(this, sessionID, downloadID, request, suggestedName);
355 }
356
357 void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(PAL::SessionID sessionID, uint64_t mainResourceLoadIdentifier, DownloadID downloadID, const ResourceRequest& request, const ResourceResponse& response)
358 {
359     auto& networkProcess = NetworkProcess::singleton();
360     // In case a response is served from service worker, we do not have yet the ability to convert the load.
361     if (!mainResourceLoadIdentifier || response.source() == ResourceResponse::Source::ServiceWorker) {
362         networkProcess.downloadManager().startDownload(this, sessionID, downloadID, request);
363         return;
364     }
365
366     NetworkResourceLoader* loader = m_networkResourceLoaders.get(mainResourceLoadIdentifier);
367     if (!loader) {
368         // If we're trying to download a blob here loader can be null.
369         return;
370     }
371
372     loader->convertToDownload(downloadID, request, response);
373 }
374
375 void NetworkConnectionToWebProcess::cookiesForDOM(PAL::SessionID sessionID, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies, String& cookieString, bool& secureCookiesAccessed)
376 {
377     auto& networkStorageSession = storageSession(sessionID);
378     std::tie(cookieString, secureCookiesAccessed) = WebCore::cookiesForDOM(networkStorageSession, firstParty, sameSiteInfo, url, frameID, pageID, includeSecureCookies);
379 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
380     if (NetworkProcess::singleton().shouldLogCookieInformation())
381         NetworkResourceLoader::logCookieInformation("NetworkConnectionToWebProcess::cookiesForDOM", reinterpret_cast<const void*>(this), networkStorageSession, firstParty, sameSiteInfo, url, emptyString(), frameID, pageID, std::nullopt);
382 #endif
383 }
384
385 void NetworkConnectionToWebProcess::setCookiesFromDOM(PAL::SessionID sessionID, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, const String& cookieString)
386 {
387     auto& networkStorageSession = storageSession(sessionID);
388     WebCore::setCookiesFromDOM(networkStorageSession, firstParty, sameSiteInfo, url, frameID, pageID, cookieString);
389 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
390     if (NetworkProcess::singleton().shouldLogCookieInformation())
391         NetworkResourceLoader::logCookieInformation("NetworkConnectionToWebProcess::setCookiesFromDOM", reinterpret_cast<const void*>(this), networkStorageSession, firstParty, sameSiteInfo, url, emptyString(), frameID, pageID, std::nullopt);
392 #endif
393 }
394
395 void NetworkConnectionToWebProcess::cookiesEnabled(PAL::SessionID sessionID, bool& result)
396 {
397     result = WebCore::cookiesEnabled(storageSession(sessionID));
398 }
399
400 void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(PAL::SessionID sessionID, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, IncludeSecureCookies includeSecureCookies, String& cookieString, bool& secureCookiesAccessed)
401 {
402     std::tie(cookieString, secureCookiesAccessed) = WebCore::cookieRequestHeaderFieldValue(storageSession(sessionID), firstParty, sameSiteInfo, url, frameID, pageID, includeSecureCookies);
403 }
404
405 void NetworkConnectionToWebProcess::getRawCookies(PAL::SessionID sessionID, const URL& firstParty, const SameSiteInfo& sameSiteInfo, const URL& url, std::optional<uint64_t> frameID, std::optional<uint64_t> pageID, Vector<Cookie>& result)
406 {
407     WebCore::getRawCookies(storageSession(sessionID), firstParty, sameSiteInfo, url, frameID, pageID, result);
408 }
409
410 void NetworkConnectionToWebProcess::deleteCookie(PAL::SessionID sessionID, const URL& url, const String& cookieName)
411 {
412     WebCore::deleteCookie(storageSession(sessionID), url, cookieName);
413 }
414
415 void NetworkConnectionToWebProcess::registerFileBlobURL(const URL& url, const String& path, SandboxExtension::Handle&& extensionHandle, const String& contentType)
416 {
417     RefPtr<SandboxExtension> extension = SandboxExtension::create(WTFMove(extensionHandle));
418
419     NetworkBlobRegistry::singleton().registerFileBlobURL(this, url, path, WTFMove(extension), contentType);
420 }
421
422 void NetworkConnectionToWebProcess::registerBlobURL(const URL& url, Vector<BlobPart>&& blobParts, const String& contentType)
423 {
424     NetworkBlobRegistry::singleton().registerBlobURL(this, url, WTFMove(blobParts), contentType);
425 }
426
427 void NetworkConnectionToWebProcess::registerBlobURLFromURL(const URL& url, const URL& srcURL, bool shouldBypassConnectionCheck)
428 {
429     NetworkBlobRegistry::singleton().registerBlobURL(this, url, srcURL, shouldBypassConnectionCheck);
430 }
431
432 void NetworkConnectionToWebProcess::preregisterSandboxExtensionsForOptionallyFileBackedBlob(const Vector<String>& filePaths, SandboxExtension::HandleArray&& handles)
433 {
434 #if ENABLE(SANDBOX_EXTENSIONS)
435     ASSERT(filePaths.size() == handles.size());
436
437     for (size_t i = 0; i < filePaths.size(); ++i)
438         m_blobDataFileReferences.add(filePaths[i], BlobDataFileReferenceWithSandboxExtension::create(filePaths[i], SandboxExtension::create(WTFMove(handles[i]))));
439 #else
440     for (size_t i = 0; i < filePaths.size(); ++i)
441         m_blobDataFileReferences.add(filePaths[i], BlobDataFileReferenceWithSandboxExtension::create(filePaths[i], nullptr));
442 #endif
443 }
444
445 RefPtr<WebCore::BlobDataFileReference> NetworkConnectionToWebProcess::getBlobDataFileReferenceForPath(const String& path)
446 {
447     ASSERT(m_blobDataFileReferences.contains(path));
448     return m_blobDataFileReferences.get(path);
449 }
450
451 void NetworkConnectionToWebProcess::registerBlobURLOptionallyFileBacked(const URL& url, const URL& srcURL, const String& fileBackedPath, const String& contentType)
452 {
453     NetworkBlobRegistry::singleton().registerBlobURLOptionallyFileBacked(this, url, srcURL, fileBackedPath, contentType);
454 }
455
456 void NetworkConnectionToWebProcess::registerBlobURLForSlice(const URL& url, const URL& srcURL, int64_t start, int64_t end)
457 {
458     NetworkBlobRegistry::singleton().registerBlobURLForSlice(this, url, srcURL, start, end);
459 }
460
461 void NetworkConnectionToWebProcess::unregisterBlobURL(const URL& url)
462 {
463     NetworkBlobRegistry::singleton().unregisterBlobURL(this, url);
464 }
465
466 void NetworkConnectionToWebProcess::blobSize(const URL& url, uint64_t& resultSize)
467 {
468     resultSize = NetworkBlobRegistry::singleton().blobSize(this, url);
469 }
470
471 void NetworkConnectionToWebProcess::writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, uint64_t requestIdentifier)
472 {
473     Vector<RefPtr<BlobDataFileReference>> fileReferences;
474     for (auto& url : blobURLs)
475         fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(*this, { ParsedURLString, url }));
476
477     for (auto& file : fileReferences)
478         file->prepareForFileAccess();
479
480     NetworkBlobRegistry::singleton().writeBlobsToTemporaryFiles(blobURLs, [this, protectedThis = makeRef(*this), requestIdentifier, fileReferences = WTFMove(fileReferences)](auto& fileNames) mutable {
481         for (auto& file : fileReferences)
482             file->revokeFileAccess();
483
484         NetworkProcess::singleton().grantSandboxExtensionsToStorageProcessForBlobs(fileNames, [this, protectedThis = WTFMove(protectedThis), requestIdentifier, fileNames]() {
485             if (!m_connection->isValid())
486                 return;
487
488             m_connection->send(Messages::NetworkProcessConnection::DidWriteBlobsToTemporaryFiles(requestIdentifier, fileNames), 0);
489         });
490     });
491 }
492
493 void NetworkConnectionToWebProcess::storeDerivedDataToCache(const WebKit::NetworkCache::DataKey& dataKey, const IPC::DataReference& data)
494 {
495     if (auto* cache = NetworkProcess::singleton().cache())
496         cache->storeData(dataKey, data.data(), data.size());
497 }
498
499 void NetworkConnectionToWebProcess::setCaptureExtraNetworkLoadMetricsEnabled(bool enabled)
500 {
501     m_captureExtraNetworkLoadMetricsEnabled = enabled;
502     if (!m_captureExtraNetworkLoadMetricsEnabled)
503         m_networkLoadInformationByID.clear();
504 }
505
506 void NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession()
507 {
508     NetworkProcess::singleton().addWebsiteDataStore(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
509 }
510
511 void NetworkConnectionToWebProcess::removeStorageAccessForFrame(PAL::SessionID sessionID, uint64_t frameID, uint64_t pageID)
512 {
513 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
514     if (auto* storageSession = NetworkStorageSession::storageSession(sessionID))
515         storageSession->removeStorageAccessForFrame(frameID, pageID);
516 #else
517     UNUSED_PARAM(sessionID);
518     UNUSED_PARAM(frameID);
519     UNUSED_PARAM(pageID);
520 #endif
521 }
522
523 void NetworkConnectionToWebProcess::removeStorageAccessForAllFramesOnPage(PAL::SessionID sessionID, uint64_t pageID)
524 {
525 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
526     if (auto* storageSession = NetworkStorageSession::storageSession(sessionID))
527         storageSession->removeStorageAccessForAllFramesOnPage(pageID);
528 #else
529     UNUSED_PARAM(sessionID);
530     UNUSED_PARAM(pageID);
531 #endif
532 }
533
534 void NetworkConnectionToWebProcess::addOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains)
535 {
536     SecurityPolicy::addOriginAccessWhitelistEntry(SecurityOrigin::createFromString(sourceOrigin).get(), destinationProtocol, destinationHost, allowDestinationSubdomains);
537 }
538
539 void NetworkConnectionToWebProcess::removeOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains)
540 {
541     SecurityPolicy::removeOriginAccessWhitelistEntry(SecurityOrigin::createFromString(sourceOrigin).get(), destinationProtocol, destinationHost, allowDestinationSubdomains);
542 }
543
544 void NetworkConnectionToWebProcess::resetOriginAccessWhitelists()
545 {
546     SecurityPolicy::resetOriginAccessWhitelists();
547 }
548
549 static bool networkActivityTrackingEnabled()
550 {
551     return NetworkProcess::singleton().trackNetworkActivity();
552 }
553
554 std::optional<NetworkActivityTracker> NetworkConnectionToWebProcess::startTrackingResourceLoad(uint64_t pageID, ResourceLoadIdentifier resourceID, bool isMainResource)
555 {
556     if (!networkActivityTrackingEnabled())
557         return std::nullopt;
558
559     // Either get the existing root activity tracker for this page or create a
560     // new one if this is the main resource.
561
562     size_t rootActivityIndex;
563     if (isMainResource) {
564         // If we're loading a page from the top, make sure any tracking of
565         // previous activity for this page is stopped.
566
567         stopAllNetworkActivityTrackingForPage(pageID);
568
569         rootActivityIndex = m_networkActivityTrackers.size();
570         m_networkActivityTrackers.constructAndAppend(pageID);
571         m_networkActivityTrackers[rootActivityIndex].networkActivity.start();
572
573 #if HAVE(NW_ACTIVITY)
574         ASSERT(m_networkActivityTrackers[rootActivityIndex].networkActivity.getPlatformObject());
575 #endif
576     } else {
577         rootActivityIndex = findRootNetworkActivity(pageID);
578
579         // This could happen if the Networking process crashes, taking its
580         // previous state with it.
581         if (rootActivityIndex == notFound)
582             return std::nullopt;
583
584 #if HAVE(NW_ACTIVITY)
585         ASSERT(m_networkActivityTrackers[rootActivityIndex].networkActivity.getPlatformObject());
586 #endif
587     }
588
589     // Create a tracker for the loading of the new resource, setting the root
590     // activity tracker as its parent.
591
592     size_t newActivityIndex = m_networkActivityTrackers.size();
593     m_networkActivityTrackers.constructAndAppend(pageID, resourceID);
594 #if HAVE(NW_ACTIVITY)
595     ASSERT(m_networkActivityTrackers[newActivityIndex].networkActivity.getPlatformObject());
596 #endif
597
598     auto& newActivityTracker = m_networkActivityTrackers[newActivityIndex];
599     newActivityTracker.networkActivity.setParent(m_networkActivityTrackers[rootActivityIndex].networkActivity);
600     newActivityTracker.networkActivity.start();
601
602     return newActivityTracker.networkActivity;
603 }
604
605 void NetworkConnectionToWebProcess::stopTrackingResourceLoad(ResourceLoadIdentifier resourceID, NetworkActivityTracker::CompletionCode code)
606 {
607     if (!networkActivityTrackingEnabled())
608         return;
609
610     auto itemIndex = findNetworkActivityTracker(resourceID);
611     if (itemIndex == notFound) {
612         RELEASE_LOG_ERROR(Network, "stopTrackingResourceLoad: Unable to find network activity for resource: %d", static_cast<int>(resourceID));
613         return;
614     }
615
616     m_networkActivityTrackers[itemIndex].networkActivity.complete(code);
617     m_networkActivityTrackers.remove(itemIndex);
618 }
619
620 void NetworkConnectionToWebProcess::stopAllNetworkActivityTracking()
621 {
622     if (!networkActivityTrackingEnabled())
623         return;
624
625     for (auto& activityTracker : m_networkActivityTrackers)
626         activityTracker.networkActivity.complete(NetworkActivityTracker::CompletionCode::None);
627
628     m_networkActivityTrackers.clear();
629 }
630
631 void NetworkConnectionToWebProcess::stopAllNetworkActivityTrackingForPage(uint64_t pageID)
632 {
633     if (!networkActivityTrackingEnabled())
634         return;
635
636     for (auto& activityTracker : m_networkActivityTrackers) {
637         if (activityTracker.pageID == pageID)
638             activityTracker.networkActivity.complete(NetworkActivityTracker::CompletionCode::None);
639     }
640
641     m_networkActivityTrackers.removeAllMatching([&](const auto& activityTracker) {
642         return activityTracker.pageID == pageID;
643     });
644 }
645
646 size_t NetworkConnectionToWebProcess::findRootNetworkActivity(uint64_t pageID)
647 {
648     return m_networkActivityTrackers.findMatching([&](const auto& item) {
649         return item.isRootActivity && item.pageID == pageID;
650     });
651 }
652
653 size_t NetworkConnectionToWebProcess::findNetworkActivityTracker(ResourceLoadIdentifier resourceID)
654 {
655     return m_networkActivityTrackers.findMatching([&](const auto& item) {
656         return item.resourceID == resourceID;
657     });
658 }
659
660 } // namespace WebKit