Source/WebCore:
[WebKit-https.git] / Source / WebKit / WebProcess / Network / WebLoaderStrategy.cpp
1 /*
2  * Copyright (C) 2012, 2015, 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 "WebLoaderStrategy.h"
28
29 #include "DataReference.h"
30 #include "HangDetectionDisabler.h"
31 #include "Logging.h"
32 #include "NetworkConnectionToWebProcessMessages.h"
33 #include "NetworkProcessConnection.h"
34 #include "NetworkResourceLoadParameters.h"
35 #include "SharedBufferDataReference.h"
36 #include "WebCompiledContentRuleList.h"
37 #include "WebCoreArgumentCoders.h"
38 #include "WebErrors.h"
39 #include "WebFrame.h"
40 #include "WebFrameLoaderClient.h"
41 #include "WebPage.h"
42 #include "WebPageProxyMessages.h"
43 #include "WebProcess.h"
44 #include "WebProcessPoolMessages.h"
45 #include "WebResourceLoader.h"
46 #include "WebSWContextManagerConnection.h"
47 #include "WebServiceWorkerProvider.h"
48 #include "WebURLSchemeHandlerProxy.h"
49 #include "WebURLSchemeTaskProxy.h"
50 #include <WebCore/ApplicationCacheHost.h>
51 #include <WebCore/CachedResource.h>
52 #include <WebCore/ContentSecurityPolicy.h>
53 #include <WebCore/DiagnosticLoggingClient.h>
54 #include <WebCore/DiagnosticLoggingKeys.h>
55 #include <WebCore/Document.h>
56 #include <WebCore/DocumentLoader.h>
57 #include <WebCore/FetchOptions.h>
58 #include <WebCore/Frame.h>
59 #include <WebCore/FrameLoader.h>
60 #include <WebCore/HTMLFrameOwnerElement.h>
61 #include <WebCore/NetscapePlugInStreamLoader.h>
62 #include <WebCore/NetworkLoadInformation.h>
63 #include <WebCore/PlatformStrategies.h>
64 #include <WebCore/ReferrerPolicy.h>
65 #include <WebCore/ResourceLoader.h>
66 #include <WebCore/RuntimeApplicationChecks.h>
67 #include <WebCore/RuntimeEnabledFeatures.h>
68 #include <WebCore/SecurityOrigin.h>
69 #include <WebCore/Settings.h>
70 #include <WebCore/SubresourceLoader.h>
71 #include <WebCore/UserContentProvider.h>
72 #include <pal/SessionID.h>
73 #include <wtf/CompletionHandler.h>
74 #include <wtf/text/CString.h>
75
76 #if USE(QUICK_LOOK)
77 #include <WebCore/QuickLook.h>
78 #endif
79
80
81 #define RELEASE_LOG_IS_ALLOWED (WebProcess::singleton().sessionID().isAlwaysOnLoggingAllowed())
82
83 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(RELEASE_LOG_IS_ALLOWED, Network, "%p - WebLoaderStrategy::" fmt, this, ##__VA_ARGS__)
84 #define RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(RELEASE_LOG_IS_ALLOWED, Network, "%p - WebLoaderStrategy::" fmt, this, ##__VA_ARGS__)
85
86 #define WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_TEMPLATE "%p - [resourceLoader=%p, frameLoader=%p, frame=%p, webPageID=%" PRIu64 ", frameID=%" PRIu64 ", resourceID=%" PRIu64 "] WebLoaderStrategy::"
87 #define WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_PARAMETERS this, &resourceLoader, resourceLoader.frameLoader(), resourceLoader.frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), trackingParameters.resourceID
88 #define WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_STANDARD_PARAMETERS this, nullptr, &frameLoader, &frameLoader.frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), trackingParameters.resourceID
89
90 #define WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(RELEASE_LOG_IS_ALLOWED, Network, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_TEMPLATE fmt, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_PARAMETERS, ##__VA_ARGS__)
91 #define WEBLOADERSTRATEGY_RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(RELEASE_LOG_IS_ALLOWED, Network, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_TEMPLATE fmt, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_PARAMETERS, ##__VA_ARGS__)
92
93 #define WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(RELEASE_LOG_IS_ALLOWED, Network, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_TEMPLATE fmt, WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_STANDARD_PARAMETERS, ##__VA_ARGS__)
94 #define WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(RELEASE_LOG_IS_ALLOWED, Network, WEBLOADERSTRATEGY_RELEASE_LOG_STANDARD_TEMPLATE fmt, WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_STANDARD_PARAMETERS, ##__VA_ARGS__)
95
96 namespace WebKit {
97 using namespace WebCore;
98
99 WebLoaderStrategy::WebLoaderStrategy()
100     : m_internallyFailedLoadTimer(RunLoop::main(), this, &WebLoaderStrategy::internallyFailedLoadTimerFired)
101 {
102 }
103
104 WebLoaderStrategy::~WebLoaderStrategy()
105 {
106 }
107
108 void WebLoaderStrategy::loadResource(Frame& frame, CachedResource& resource, ResourceRequest&& request, const ResourceLoaderOptions& options, CompletionHandler<void(RefPtr<SubresourceLoader>&&)>&& completionHandler)
109 {
110     SubresourceLoader::create(frame, resource, WTFMove(request), options, [this, referrerPolicy = options.referrerPolicy, completionHandler = WTFMove(completionHandler), resource = CachedResourceHandle<CachedResource>(&resource), frame = makeRef(frame)] (RefPtr<SubresourceLoader>&& loader) mutable {
111         if (loader)
112             scheduleLoad(*loader, resource.get(), referrerPolicy == ReferrerPolicy::NoReferrerWhenDowngrade);
113         else
114             RELEASE_LOG_IF(RELEASE_LOG_IS_ALLOWED, Network, "%p - [webPageID=%" PRIu64 ", frameID=%" PRIu64 "] WebLoaderStrategy::loadResource: Unable to create SubresourceLoader", this, frame->pageID().valueOr(PageIdentifier()).toUInt64(), frame->frameID().valueOr(FrameIdentifier()).toUInt64());
115         completionHandler(WTFMove(loader));
116     });
117 }
118
119 void WebLoaderStrategy::schedulePluginStreamLoad(Frame& frame, NetscapePlugInStreamLoaderClient& client, ResourceRequest&& request, CompletionHandler<void(RefPtr<NetscapePlugInStreamLoader>&&)>&& completionHandler)
120 {
121     NetscapePlugInStreamLoader::create(frame, client, WTFMove(request), [this, completionHandler = WTFMove(completionHandler), frame = makeRef(frame)] (RefPtr<NetscapePlugInStreamLoader>&& loader) mutable {
122         if (loader)
123             scheduleLoad(*loader, 0, frame->document()->referrerPolicy() == ReferrerPolicy::NoReferrerWhenDowngrade);
124         completionHandler(WTFMove(loader));
125     });
126 }
127
128 static Seconds maximumBufferingTime(CachedResource* resource)
129 {
130     if (!resource)
131         return 0_s;
132
133     switch (resource->type()) {
134     case CachedResource::Type::Beacon:
135     case CachedResource::Type::Ping:
136     case CachedResource::Type::CSSStyleSheet:
137     case CachedResource::Type::Script:
138 #if ENABLE(SVG_FONTS)
139     case CachedResource::Type::SVGFontResource:
140 #endif
141     case CachedResource::Type::FontResource:
142 #if ENABLE(APPLICATION_MANIFEST)
143     case CachedResource::Type::ApplicationManifest:
144 #endif
145         return Seconds::infinity();
146     case CachedResource::Type::ImageResource:
147         return 500_ms;
148     case CachedResource::Type::MediaResource:
149         return 50_ms;
150     case CachedResource::Type::MainResource:
151     case CachedResource::Type::Icon:
152     case CachedResource::Type::RawResource:
153     case CachedResource::Type::SVGDocumentResource:
154     case CachedResource::Type::LinkPrefetch:
155 #if ENABLE(VIDEO_TRACK)
156     case CachedResource::Type::TextTrackResource:
157 #endif
158 #if ENABLE(XSLT)
159     case CachedResource::Type::XSLStyleSheet:
160 #endif
161         return 0_s;
162     }
163
164     ASSERT_NOT_REACHED();
165     return 0_s;
166 }
167
168 void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResource* resource, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
169 {
170     ResourceLoadIdentifier identifier = resourceLoader.identifier();
171     ASSERT(identifier);
172
173     auto& frameLoaderClient = resourceLoader.frameLoader()->client();
174
175     WebResourceLoader::TrackingParameters trackingParameters;
176     if (auto* webFrameLoaderClient = toWebFrameLoaderClient(frameLoaderClient))
177         trackingParameters.webPageProxyID = webFrameLoaderClient->webPageProxyID().valueOr(WebPageProxyIdentifier { });
178 #if ENABLE(SERVICE_WORKER)
179     else if (is<ServiceWorkerFrameLoaderClient>(frameLoaderClient))
180         trackingParameters.webPageProxyID = downcast<ServiceWorkerFrameLoaderClient>(frameLoaderClient).webPageProxyID();
181 #endif
182     trackingParameters.pageID = frameLoaderClient.pageID().valueOr(PageIdentifier { });
183     trackingParameters.frameID = frameLoaderClient.frameID().valueOr(FrameIdentifier { });
184     trackingParameters.resourceID = identifier;
185
186 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
187     // If the DocumentLoader schedules this as an archive resource load,
188     // then we should remember the ResourceLoader in our records but not schedule it in the NetworkProcess.
189     if (resourceLoader.documentLoader()->scheduleArchiveLoad(resourceLoader, resourceLoader.request())) {
190         LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be handled as an archive resource.", resourceLoader.url().string().utf8().data());
191         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be handled as an archive resource");
192         m_webResourceLoaders.set(identifier, WebResourceLoader::create(resourceLoader, trackingParameters));
193         return;
194     }
195 #endif
196
197     if (resourceLoader.documentLoader()->applicationCacheHost().maybeLoadResource(resourceLoader, resourceLoader.request(), resourceLoader.request().url())) {
198         LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be loaded from application cache.", resourceLoader.url().string().utf8().data());
199         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be loaded from application cache");
200         m_webResourceLoaders.set(identifier, WebResourceLoader::create(resourceLoader, trackingParameters));
201         return;
202     }
203
204     if (resourceLoader.request().url().protocolIsData()) {
205         LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be loaded as data.", resourceLoader.url().string().utf8().data());
206         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be loaded as data");
207         startLocalLoad(resourceLoader);
208         return;
209     }
210
211 #if USE(QUICK_LOOK)
212     if (isQuickLookPreviewURL(resourceLoader.request().url())) {
213         LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be handled as a QuickLook resource.", resourceLoader.url().string().utf8().data());
214         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be handled as a QuickLook resource");
215         startLocalLoad(resourceLoader);
216         return;
217     }
218 #endif
219
220 #if USE(SOUP)
221     // For apps that call g_resource_load in a web extension.
222     // https://blogs.gnome.org/alexl/2012/01/26/resources-in-glib/
223     if (resourceLoader.request().url().protocolIs("resource")) {
224         LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be handled as a GResource.", resourceLoader.url().string().utf8().data());
225         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be handled as a GResource");
226         startLocalLoad(resourceLoader);
227         return;
228     }
229 #endif
230
231     if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) {
232         WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess");
233         scheduleLoadFromNetworkProcess(resourceLoader, resourceLoader.request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource));
234         return;
235     }
236
237     WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL not handled by any handlers");
238 }
239
240 bool WebLoaderStrategy::tryLoadingUsingURLSchemeHandler(ResourceLoader& resourceLoader, const WebResourceLoader::TrackingParameters& trackingParameters)
241 {
242     auto* webFrameLoaderClient = toWebFrameLoaderClient(resourceLoader.frameLoader()->client());
243     if (!webFrameLoaderClient)
244         return false;
245
246     auto& webFrame = webFrameLoaderClient->webFrame();
247     auto* webPage = webFrame.page();
248     if (!webPage)
249         return false;
250
251     auto* handler = webPage->urlSchemeHandlerForScheme(resourceLoader.request().url().protocol().toStringWithoutCopying());
252     if (!handler)
253         return false;
254
255     LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, URL '%s' will be handled by a UIProcess URL scheme handler.", resourceLoader.url().string().utf8().data());
256     WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("tryLoadingUsingURLSchemeHandler: URL will be handled by a UIProcess URL scheme handler");
257
258     handler->startNewTask(resourceLoader, webFrame);
259     return true;
260 }
261
262 static void addParametersShared(const Frame* frame, NetworkResourceLoadParameters& parameters)
263 {
264     parameters.crossOriginAccessControlCheckEnabled = CrossOriginAccessControlCheckDisabler::singleton().crossOriginAccessControlCheckEnabled();
265
266     if (!frame)
267         return;
268
269     parameters.isHTTPSUpgradeEnabled = frame->settings().HTTPSUpgradeEnabled();
270
271     if (auto* page = frame->page())
272         parameters.pageHasResourceLoadClient = page->hasResourceLoadClient();
273
274     if (auto* ownerElement = frame->ownerElement()) {
275         if (auto* parentFrame = ownerElement->document().frame())
276             parameters.parentFrameID = parentFrame->loader().client().frameID();
277     }
278 }
279
280 void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime)
281 {
282     ResourceLoadIdentifier identifier = resourceLoader.identifier();
283     ASSERT(identifier);
284
285     LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be scheduled with the NetworkProcess with priority %d", resourceLoader.url().string().latin1().data(), static_cast<int>(resourceLoader.request().priority()));
286
287     ContentSniffingPolicy contentSniffingPolicy = resourceLoader.shouldSniffContent() ? ContentSniffingPolicy::SniffContent : ContentSniffingPolicy::DoNotSniffContent;
288     ContentEncodingSniffingPolicy contentEncodingSniffingPolicy = resourceLoader.shouldSniffContentEncoding() ? ContentEncodingSniffingPolicy::Sniff : ContentEncodingSniffingPolicy::DoNotSniff;
289     StoredCredentialsPolicy storedCredentialsPolicy = resourceLoader.shouldUseCredentialStorage() ? StoredCredentialsPolicy::Use : StoredCredentialsPolicy::DoNotUse;
290
291     auto* frame = resourceLoader.frame();
292
293     NetworkResourceLoadParameters loadParameters;
294     loadParameters.identifier = identifier;
295     loadParameters.webPageProxyID = trackingParameters.webPageProxyID;
296     loadParameters.webPageID = trackingParameters.pageID;
297     loadParameters.webFrameID = trackingParameters.frameID;
298     loadParameters.parentPID = presentingApplicationPID();
299 #if HAVE(AUDIT_TOKEN)
300     loadParameters.networkProcessAuditToken = WebProcess::singleton().ensureNetworkProcessConnection().networkProcessAuditToken();
301 #endif
302     loadParameters.request = request;
303     loadParameters.contentSniffingPolicy = contentSniffingPolicy;
304     loadParameters.contentEncodingSniffingPolicy = contentEncodingSniffingPolicy;
305     loadParameters.storedCredentialsPolicy = storedCredentialsPolicy;
306     // If there is no WebFrame then this resource cannot be authenticated with the client.
307     loadParameters.clientCredentialPolicy = (loadParameters.webFrameID && loadParameters.webPageID && resourceLoader.isAllowedToAskUserForCredentials()) ? ClientCredentialPolicy::MayAskClientForCredentials : ClientCredentialPolicy::CannotAskClientForCredentials;
308     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = shouldClearReferrerOnHTTPSToHTTPRedirect;
309     loadParameters.needsCertificateInfo = resourceLoader.shouldIncludeCertificateInfo();
310     loadParameters.maximumBufferingTime = maximumBufferingTime;
311     loadParameters.options = resourceLoader.options();
312     loadParameters.preflightPolicy = resourceLoader.options().preflightPolicy;
313     addParametersShared(frame, loadParameters);
314
315 #if ENABLE(SERVICE_WORKER)
316     loadParameters.serviceWorkersMode = resourceLoader.options().serviceWorkersMode;
317     loadParameters.serviceWorkerRegistrationIdentifier = resourceLoader.options().serviceWorkerRegistrationIdentifier;
318     loadParameters.httpHeadersToKeep = resourceLoader.options().httpHeadersToKeep;
319 #endif
320
321     auto* document = frame ? frame->document() : nullptr;
322     if (resourceLoader.options().cspResponseHeaders)
323         loadParameters.cspResponseHeaders = resourceLoader.options().cspResponseHeaders;
324     else if (document && !document->shouldBypassMainWorldContentSecurityPolicy() && resourceLoader.options().contentSecurityPolicyImposition == ContentSecurityPolicyImposition::DoPolicyCheck) {
325         if (auto* contentSecurityPolicy = document->contentSecurityPolicy())
326             loadParameters.cspResponseHeaders = contentSecurityPolicy->responseHeaders();
327     }
328     
329     auto* webFrameLoaderClient = frame ? toWebFrameLoaderClient(frame->loader().client()) : nullptr;
330     auto* webFrame = webFrameLoaderClient ? &webFrameLoaderClient->webFrame() : nullptr;
331     auto* webPage = webFrame ? webFrame->page() : nullptr;
332     if (webPage)
333         loadParameters.isNavigatingToAppBoundDomain = webPage->isNavigatingToAppBoundDomain();
334
335 #if ENABLE(CONTENT_EXTENSIONS)
336     if (document) {
337         loadParameters.mainDocumentURL = document->topDocument().url();
338         // FIXME: Instead of passing userContentControllerIdentifier, the NetworkProcess should be able to get it using webPageId.
339         if (webPage)
340             loadParameters.userContentControllerIdentifier = webPage->userContentControllerIdentifier();
341     }
342 #endif
343
344     // FIXME: All loaders should provide their origin if navigation mode is cors/no-cors/same-origin.
345     // As a temporary approach, we use the document origin if available or the HTTP Origin header otherwise.
346     if (is<SubresourceLoader>(resourceLoader)) {
347         auto& loader = downcast<SubresourceLoader>(resourceLoader);
348         loadParameters.sourceOrigin = loader.origin();
349
350         if (auto* headers = loader.originalHeaders())
351             loadParameters.originalRequestHeaders = *headers;
352     }
353
354     if (!loadParameters.sourceOrigin && document)
355         loadParameters.sourceOrigin = &document->securityOrigin();
356     if (!loadParameters.sourceOrigin) {
357         auto origin = request.httpOrigin();
358         if (!origin.isNull())
359             loadParameters.sourceOrigin = SecurityOrigin::createFromString(origin);
360     }
361     if (document)
362         loadParameters.topOrigin = &document->topOrigin();
363
364     if (loadParameters.options.mode != FetchOptions::Mode::Navigate) {
365         ASSERT(loadParameters.sourceOrigin);
366         if (!loadParameters.sourceOrigin) {
367             WEBLOADERSTRATEGY_RELEASE_LOG_ERROR_IF_ALLOWED("scheduleLoad: no sourceOrigin (priority=%d)", static_cast<int>(resourceLoader.request().priority()));
368             scheduleInternallyFailedLoad(resourceLoader);
369             return;
370         }
371     }
372
373     loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks();
374
375     loadParameters.isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate;
376
377     loadParameters.isMainResourceNavigationForAnyFrame = resourceLoader.frame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate;
378
379     loadParameters.shouldEnableCrossOriginResourcePolicy = RuntimeEnabledFeatures::sharedFeatures().crossOriginResourcePolicyEnabled() && !loadParameters.isMainFrameNavigation;
380
381     if (resourceLoader.options().mode == FetchOptions::Mode::Navigate) {
382         Vector<RefPtr<SecurityOrigin>> frameAncestorOrigins;
383         for (auto* frame = resourceLoader.frame()->tree().parent(); frame; frame = frame->tree().parent())
384             frameAncestorOrigins.append(makeRefPtr(frame->document()->securityOrigin()));
385         loadParameters.frameAncestorOrigins = WTFMove(frameAncestorOrigins);
386     }
387
388     ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials);
389
390     WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: Resource is being scheduled with the NetworkProcess (priority=%d)", static_cast<int>(resourceLoader.request().priority()));
391     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ScheduleResourceLoad(loadParameters), 0)) {
392         WEBLOADERSTRATEGY_RELEASE_LOG_ERROR_IF_ALLOWED("scheduleLoad: Unable to schedule resource with the NetworkProcess (priority=%d)", static_cast<int>(resourceLoader.request().priority()));
393         // We probably failed to schedule this load with the NetworkProcess because it had crashed.
394         // This load will never succeed so we will schedule it to fail asynchronously.
395         scheduleInternallyFailedLoad(resourceLoader);
396         return;
397     }
398
399     auto loader = WebResourceLoader::create(resourceLoader, trackingParameters);
400     if (resourceLoader.originalRequest().hasUpload()) {
401         if (m_loadersWithUploads.isEmpty())
402             WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessPool::SetWebProcessHasUploads(Process::identifier()), 0);
403         m_loadersWithUploads.add(loader.ptr());
404     }
405
406     m_webResourceLoaders.set(identifier, WTFMove(loader));
407 }
408
409 void WebLoaderStrategy::scheduleInternallyFailedLoad(WebCore::ResourceLoader& resourceLoader)
410 {
411     m_internallyFailedResourceLoaders.add(&resourceLoader);
412     m_internallyFailedLoadTimer.startOneShot(0_s);
413 }
414
415 void WebLoaderStrategy::internallyFailedLoadTimerFired()
416 {
417     for (auto& resourceLoader : copyToVector(m_internallyFailedResourceLoaders))
418         resourceLoader->didFail(internalError(resourceLoader->url()));
419 }
420
421 void WebLoaderStrategy::startLocalLoad(WebCore::ResourceLoader& resourceLoader)
422 {
423     resourceLoader.start();
424     m_webResourceLoaders.set(resourceLoader.identifier(), WebResourceLoader::create(resourceLoader, { }));
425 }
426
427 void WebLoaderStrategy::addURLSchemeTaskProxy(WebURLSchemeTaskProxy& task)
428 {
429     auto result = m_urlSchemeTasks.add(task.identifier(), &task);
430     ASSERT_UNUSED(result, result.isNewEntry);
431 }
432
433 void WebLoaderStrategy::removeURLSchemeTaskProxy(WebURLSchemeTaskProxy& task)
434 {
435     m_urlSchemeTasks.remove(task.identifier());
436 }
437
438 void WebLoaderStrategy::remove(ResourceLoader* resourceLoader)
439 {
440     ASSERT(resourceLoader);
441     LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::remove, url '%s'", resourceLoader->url().string().utf8().data());
442
443     if (auto task = m_urlSchemeTasks.take(resourceLoader->identifier())) {
444         ASSERT(!m_internallyFailedResourceLoaders.contains(resourceLoader));
445         task->stopLoading();
446         return;
447     }
448
449     if (m_internallyFailedResourceLoaders.contains(resourceLoader)) {
450         m_internallyFailedResourceLoaders.remove(resourceLoader);
451         return;
452     }
453     
454     ResourceLoadIdentifier identifier = resourceLoader->identifier();
455     if (!identifier) {
456         LOG_ERROR("WebLoaderStrategy removing a ResourceLoader that has no identifier.");
457         return;
458     }
459
460     RefPtr<WebResourceLoader> loader = m_webResourceLoaders.take(identifier);
461     // Loader may not be registered if we created it, but haven't scheduled yet (a bundle client can decide to cancel such request via willSendRequest).
462     if (!loader)
463         return;
464
465     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveLoadIdentifier(identifier), 0);
466
467     if (m_loadersWithUploads.remove(loader.get()) && m_loadersWithUploads.isEmpty())
468         WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessPool::ClearWebProcessHasUploads { Process::identifier() }, 0);
469
470     // It's possible that this WebResourceLoader might be just about to message back to the NetworkProcess (e.g. ContinueWillSendRequest)
471     // but there's no point in doing so anymore.
472     loader->detachFromCoreLoader();
473 }
474
475 void WebLoaderStrategy::setDefersLoading(ResourceLoader&, bool)
476 {
477 }
478
479 void WebLoaderStrategy::crossOriginRedirectReceived(ResourceLoader*, const URL&)
480 {
481     // We handle cross origin redirects entirely within the NetworkProcess.
482     // We override this call in the WebProcess to make it a no-op.
483 }
484
485 void WebLoaderStrategy::servePendingRequests(ResourceLoadPriority)
486 {
487     // This overrides the base class version.
488     // We don't need to do anything as this is handled by the network process.
489 }
490
491 void WebLoaderStrategy::suspendPendingRequests()
492 {
493     // Network process does keep requests in pending state.
494 }
495
496 void WebLoaderStrategy::resumePendingRequests()
497 {
498     // Network process does keep requests in pending state.
499 }
500
501 void WebLoaderStrategy::networkProcessCrashed()
502 {
503     RELEASE_LOG_ERROR_IF_ALLOWED("networkProcessCrashed: failing all pending resource loaders");
504
505     for (auto& loader : m_webResourceLoaders.values()) {
506         scheduleInternallyFailedLoad(*loader->resourceLoader());
507         loader->detachFromCoreLoader();
508     }
509
510     m_webResourceLoaders.clear();
511
512     auto pingLoadCompletionHandlers = WTFMove(m_pingLoadCompletionHandlers);
513     for (auto& pingLoadCompletionHandler : pingLoadCompletionHandlers.values())
514         pingLoadCompletionHandler(internalError(URL()), { });
515
516     auto preconnectCompletionHandlers = WTFMove(m_preconnectCompletionHandlers);
517     for (auto& preconnectCompletionHandler : preconnectCompletionHandlers.values())
518         preconnectCompletionHandler(internalError(URL()));
519 }
520
521 static bool shouldClearReferrerOnHTTPSToHTTPRedirect(Frame* frame)
522 {
523     if (frame) {
524         if (auto* document = frame->document())
525             return document->referrerPolicy() == ReferrerPolicy::NoReferrerWhenDowngrade;
526     }
527     return true;
528 }
529
530 Optional<WebLoaderStrategy::SyncLoadResult> WebLoaderStrategy::tryLoadingSynchronouslyUsingURLSchemeHandler(FrameLoader& frameLoader, ResourceLoadIdentifier identifier, const ResourceRequest& request)
531 {
532     auto* webFrameLoaderClient = toWebFrameLoaderClient(frameLoader.client());
533     auto* webFrame = webFrameLoaderClient ? &webFrameLoaderClient->webFrame() : nullptr;
534     auto* webPage = webFrame ? webFrame->page() : nullptr;
535     if (!webPage)
536         return WTF::nullopt;
537
538     auto* handler = webPage->urlSchemeHandlerForScheme(request.url().protocol().toStringWithoutCopying());
539     if (!handler)
540         return WTF::nullopt;
541
542     LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, sync load to URL '%s' will be handled by a UIProcess URL scheme handler.", request.url().string().utf8().data());
543
544     SyncLoadResult result;
545     handler->loadSynchronously(identifier, *webFrame, request, result.response, result.error, result.data);
546
547     return result;
548 }
549
550 void WebLoaderStrategy::loadResourceSynchronously(FrameLoader& frameLoader, unsigned long resourceLoadIdentifier, const ResourceRequest& request, ClientCredentialPolicy clientCredentialPolicy,  const FetchOptions& options, const HTTPHeaderMap& originalRequestHeaders, ResourceError& error, ResourceResponse& response, Vector<char>& data)
551 {
552     auto* webFrameLoaderClient = toWebFrameLoaderClient(frameLoader.client());
553     auto* webFrame = webFrameLoaderClient ? &webFrameLoaderClient->webFrame() : nullptr;
554     auto* webPage = webFrame ? webFrame->page() : nullptr;
555     auto* page = webPage ? webPage->corePage() : nullptr;
556
557     auto webPageProxyID = webPage ? webPage->webPageProxyIdentifier() : WebPageProxyIdentifier { };
558     auto pageID = webPage ? webPage->identifier() : PageIdentifier { };
559     auto frameID = webFrame ? webFrame->frameID() : FrameIdentifier { };
560
561     WebResourceLoader::TrackingParameters trackingParameters;
562     trackingParameters.pageID = pageID;
563     trackingParameters.frameID = frameID;
564     trackingParameters.resourceID = resourceLoadIdentifier;
565
566     auto* document = frameLoader.frame().document();
567     if (!document) {
568         WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED("loadResourceSynchronously: no document");
569         error = internalError(request.url());
570         return;
571     }
572
573     if (auto syncLoadResult = tryLoadingSynchronouslyUsingURLSchemeHandler(frameLoader, resourceLoadIdentifier, request)) {
574         WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED("loadResourceSynchronously: failed calling tryLoadingSynchronouslyUsingURLSchemeHandler (error=%d)", syncLoadResult->error.errorCode());
575         error = WTFMove(syncLoadResult->error);
576         response = WTFMove(syncLoadResult->response);
577         data = WTFMove(syncLoadResult->data);
578         return;
579     }
580
581     NetworkResourceLoadParameters loadParameters;
582     loadParameters.identifier = resourceLoadIdentifier;
583     loadParameters.webPageProxyID = webPageProxyID;
584     loadParameters.webPageID = pageID;
585     loadParameters.webFrameID = frameID;
586     loadParameters.parentPID = presentingApplicationPID();
587 #if HAVE(AUDIT_TOKEN)
588     loadParameters.networkProcessAuditToken = WebProcess::singleton().ensureNetworkProcessConnection().networkProcessAuditToken();
589 #endif
590     loadParameters.request = request;
591     loadParameters.contentSniffingPolicy = ContentSniffingPolicy::SniffContent;
592     loadParameters.contentEncodingSniffingPolicy = ContentEncodingSniffingPolicy::Sniff;
593     loadParameters.storedCredentialsPolicy = options.credentials == FetchOptions::Credentials::Omit ? StoredCredentialsPolicy::DoNotUse : StoredCredentialsPolicy::Use;
594     loadParameters.clientCredentialPolicy = clientCredentialPolicy;
595     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = shouldClearReferrerOnHTTPSToHTTPRedirect(webFrame ? webFrame->coreFrame() : nullptr);
596     loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks();
597
598     loadParameters.options = options;
599     loadParameters.sourceOrigin = &document->securityOrigin();
600     loadParameters.topOrigin = &document->topOrigin();
601     if (!document->shouldBypassMainWorldContentSecurityPolicy()) {
602         if (auto* contentSecurityPolicy = document->contentSecurityPolicy())
603             loadParameters.cspResponseHeaders = contentSecurityPolicy->responseHeaders();
604     }
605     loadParameters.originalRequestHeaders = originalRequestHeaders;
606     
607     if (webPage)
608         loadParameters.isNavigatingToAppBoundDomain = webPage->isNavigatingToAppBoundDomain();
609
610     addParametersShared(webFrame->coreFrame(), loadParameters);
611
612     data.shrink(0);
613
614     HangDetectionDisabler hangDetectionDisabler;
615     IPC::UnboundedSynchronousIPCScope unboundedSynchronousIPCScope;
616
617     bool shouldNotifyOfUpload = request.hasUpload() && m_loadersWithUploads.isEmpty();
618     if (shouldNotifyOfUpload)
619         WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessPool::SetWebProcessHasUploads { Process::identifier() }, 0);
620
621     if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad(loadParameters), Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::Reply(error, response, data), 0)) {
622         WEBLOADERSTRATEGY_WITH_FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED("loadResourceSynchronously: failed sending synchronous network process message");
623         if (page)
624             page->diagnosticLoggingClient().logDiagnosticMessage(WebCore::DiagnosticLoggingKeys::internalErrorKey(), WebCore::DiagnosticLoggingKeys::synchronousMessageFailedKey(), WebCore::ShouldSample::No);
625         response = ResourceResponse();
626         error = internalError(request.url());
627     }
628
629     if (shouldNotifyOfUpload)
630         WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessPool::ClearWebProcessHasUploads { Process::identifier() }, 0);
631 }
632
633 void WebLoaderStrategy::pageLoadCompleted(Page& page)
634 {
635     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::PageLoadCompleted(WebPage::fromCorePage(page).identifier()), 0);
636 }
637
638 void WebLoaderStrategy::browsingContextRemoved(Frame& frame)
639 {
640     ASSERT(frame.page());
641     auto& page = WebPage::fromCorePage(*frame.page());
642     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::BrowsingContextRemoved(page.webPageProxyIdentifier(), page.identifier(), WebFrame::fromCoreFrame(frame)->frameID()), 0);
643 }
644
645 static uint64_t generateLoadIdentifier()
646 {
647     static uint64_t identifier = 0;
648     return ++identifier;
649 }
650
651 bool WebLoaderStrategy::usePingLoad() const
652 {
653     return !RuntimeEnabledFeatures::sharedFeatures().fetchAPIKeepAliveEnabled();
654 }
655
656 void WebLoaderStrategy::startPingLoad(Frame& frame, ResourceRequest& request, const HTTPHeaderMap& originalRequestHeaders, const FetchOptions& options, ContentSecurityPolicyImposition policyCheck, PingLoadCompletionHandler&& completionHandler)
657 {
658     auto* document = frame.document();
659     if (!document) {
660         if (completionHandler)
661             completionHandler(internalError(request.url()), { });
662         return;
663     }
664
665     NetworkResourceLoadParameters loadParameters;
666     loadParameters.identifier = generateLoadIdentifier();
667     loadParameters.request = request;
668     loadParameters.sourceOrigin = &document->securityOrigin();
669     loadParameters.topOrigin = &document->topOrigin();
670     loadParameters.parentPID = presentingApplicationPID();
671 #if HAVE(AUDIT_TOKEN)
672     loadParameters.networkProcessAuditToken = WebProcess::singleton().ensureNetworkProcessConnection().networkProcessAuditToken();
673 #endif
674     loadParameters.storedCredentialsPolicy = options.credentials == FetchOptions::Credentials::Omit ? StoredCredentialsPolicy::DoNotUse : StoredCredentialsPolicy::Use;
675     loadParameters.options = options;
676     loadParameters.originalRequestHeaders = originalRequestHeaders;
677     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = shouldClearReferrerOnHTTPSToHTTPRedirect(&frame);
678     loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks();
679     if (policyCheck == ContentSecurityPolicyImposition::DoPolicyCheck && !document->shouldBypassMainWorldContentSecurityPolicy()) {
680         if (auto* contentSecurityPolicy = document->contentSecurityPolicy())
681             loadParameters.cspResponseHeaders = contentSecurityPolicy->responseHeaders();
682     }
683     addParametersShared(&frame, loadParameters);
684     
685     auto* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client());
686     auto* webFrame = webFrameLoaderClient ? &webFrameLoaderClient->webFrame() : nullptr;
687     auto* webPage = webFrame ? webFrame->page() : nullptr;
688     if (webPage)
689         loadParameters.isNavigatingToAppBoundDomain = webPage->isNavigatingToAppBoundDomain();
690     
691 #if ENABLE(CONTENT_EXTENSIONS)
692     loadParameters.mainDocumentURL = document->topDocument().url();
693     // FIXME: Instead of passing userContentControllerIdentifier, we should just pass webPageId to NetworkProcess.
694     if (webPage)
695         loadParameters.userContentControllerIdentifier = webPage->userContentControllerIdentifier();
696 #endif
697
698     if (completionHandler)
699         m_pingLoadCompletionHandlers.add(loadParameters.identifier, WTFMove(completionHandler));
700
701     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::LoadPing { loadParameters }, 0);
702 }
703
704 void WebLoaderStrategy::didFinishPingLoad(uint64_t pingLoadIdentifier, ResourceError&& error, ResourceResponse&& response)
705 {
706     if (auto completionHandler = m_pingLoadCompletionHandlers.take(pingLoadIdentifier))
707         completionHandler(WTFMove(error), WTFMove(response));
708 }
709
710 void WebLoaderStrategy::preconnectTo(FrameLoader& frameLoader, const URL& url, StoredCredentialsPolicy storedCredentialsPolicy, PreconnectCompletionHandler&& completionHandler)
711 {
712     ASSERT(completionHandler);
713     auto* webFrameLoaderClient = toWebFrameLoaderClient(frameLoader.client());
714     if (!webFrameLoaderClient) {
715         completionHandler(internalError(url));
716         return;
717     }
718     auto& webFrame = webFrameLoaderClient->webFrame();
719     auto* webPage = webFrame.page();
720     if (!webPage) {
721         completionHandler(internalError(url));
722         return;
723     }
724
725     preconnectTo(ResourceRequest { url }, *webPage, webFrame, storedCredentialsPolicy, WTFMove(completionHandler));
726 }
727
728 void WebLoaderStrategy::preconnectTo(WebCore::ResourceRequest&& request, WebPage& webPage, WebFrame& webFrame, WebCore::StoredCredentialsPolicy storedCredentialsPolicy, PreconnectCompletionHandler&& completionHandler)
729 {
730     Optional<uint64_t> preconnectionIdentifier;
731     if (completionHandler) {
732         preconnectionIdentifier = generateLoadIdentifier();
733         auto addResult = m_preconnectCompletionHandlers.add(*preconnectionIdentifier, WTFMove(completionHandler));
734         ASSERT_UNUSED(addResult, addResult.isNewEntry);
735     }
736
737     NetworkResourceLoadParameters parameters;
738     parameters.request = WTFMove(request);
739     if (parameters.request.httpUserAgent().isEmpty()) {
740         // FIXME: we add user-agent to the preconnect request because otherwise the preconnect
741         // gets thrown away by CFNetwork when using an HTTPS proxy (<rdar://problem/59434166>).
742         String webPageUserAgent = webPage.userAgent(parameters.request.url());
743         if (!webPageUserAgent.isEmpty())
744             parameters.request.setHTTPUserAgent(webPageUserAgent);
745     }
746     parameters.webPageProxyID = webPage.webPageProxyIdentifier();
747     parameters.webPageID = webPage.identifier();
748     parameters.webFrameID = webFrame.frameID();
749     parameters.parentPID = presentingApplicationPID();
750 #if HAVE(AUDIT_TOKEN)
751     parameters.networkProcessAuditToken = WebProcess::singleton().ensureNetworkProcessConnection().networkProcessAuditToken();
752 #endif
753     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
754     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
755     parameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks();
756     // FIXME: Use the proper destination once all fetch options are passed.
757     parameters.options.destination = FetchOptions::Destination::EmptyString;
758
759     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::PreconnectTo(preconnectionIdentifier, WTFMove(parameters)), 0);
760 }
761
762 void WebLoaderStrategy::didFinishPreconnection(uint64_t preconnectionIdentifier, ResourceError&& error)
763 {
764     if (auto completionHandler = m_preconnectCompletionHandlers.take(preconnectionIdentifier))
765         completionHandler(WTFMove(error));
766 }
767
768 bool WebLoaderStrategy::isOnLine() const
769 {
770     return m_isOnLine;
771 }
772
773 void WebLoaderStrategy::addOnlineStateChangeListener(Function<void(bool)>&& listener)
774 {
775     WebProcess::singleton().ensureNetworkProcessConnection();
776     m_onlineStateChangeListeners.append(WTFMove(listener));
777 }
778
779 void WebLoaderStrategy::setOnLineState(bool isOnLine)
780 {
781     if (m_isOnLine == isOnLine)
782         return;
783
784     m_isOnLine = isOnLine;
785     for (auto& listener : m_onlineStateChangeListeners)
786         listener(isOnLine);
787 }
788
789 void WebLoaderStrategy::setCaptureExtraNetworkLoadMetricsEnabled(bool enabled)
790 {
791     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCaptureExtraNetworkLoadMetricsEnabled(enabled), 0);
792 }
793
794 ResourceResponse WebLoaderStrategy::responseFromResourceLoadIdentifier(uint64_t resourceLoadIdentifier)
795 {
796     ResourceResponse response;
797     WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::GetNetworkLoadInformationResponse { resourceLoadIdentifier }, Messages::NetworkConnectionToWebProcess::GetNetworkLoadInformationResponse::Reply { response }, 0);
798     return response;
799 }
800
801 Vector<NetworkTransactionInformation> WebLoaderStrategy::intermediateLoadInformationFromResourceLoadIdentifier(uint64_t resourceLoadIdentifier)
802 {
803     Vector<NetworkTransactionInformation> information;
804     WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::GetNetworkLoadIntermediateInformation { resourceLoadIdentifier }, Messages::NetworkConnectionToWebProcess::GetNetworkLoadIntermediateInformation::Reply { information }, 0);
805     return information;
806 }
807
808 NetworkLoadMetrics WebLoaderStrategy::networkMetricsFromResourceLoadIdentifier(uint64_t resourceLoadIdentifier)
809 {
810     NetworkLoadMetrics networkMetrics;
811     WebProcess::singleton().ensureNetworkProcessConnection().connection().sendSync(Messages::NetworkConnectionToWebProcess::TakeNetworkLoadInformationMetrics { resourceLoadIdentifier }, Messages::NetworkConnectionToWebProcess::TakeNetworkLoadInformationMetrics::Reply { networkMetrics }, 0);
812     return networkMetrics;
813 }
814
815 bool WebLoaderStrategy::shouldPerformSecurityChecks() const
816 {
817     return RuntimeEnabledFeatures::sharedFeatures().restrictedHTTPResponseAccess();
818 }
819
820 bool WebLoaderStrategy::havePerformedSecurityChecks(const ResourceResponse& response) const
821 {
822     if (!shouldPerformSecurityChecks())
823         return false;
824     switch (response.source()) {
825     case ResourceResponse::Source::DOMCache:
826     case ResourceResponse::Source::ApplicationCache:
827     case ResourceResponse::Source::MemoryCache:
828     case ResourceResponse::Source::MemoryCacheAfterValidation:
829     case ResourceResponse::Source::ServiceWorker:
830     case ResourceResponse::Source::InspectorOverride:
831         return false;
832     case ResourceResponse::Source::DiskCache:
833     case ResourceResponse::Source::DiskCacheAfterValidation:
834     case ResourceResponse::Source::Network:
835     case ResourceResponse::Source::Unknown:
836         return true;
837     }
838     ASSERT_NOT_REACHED();
839     return false;
840 }
841
842 } // namespace WebKit
843
844 #undef RELEASE_LOG_IF_ALLOWED
845 #undef RELEASE_LOG_ERROR_IF_ALLOWED