| 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 | |