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