StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* loader, const ResourceLoaderOptions& options) { ASSERT(loader); Document* document = loader->document(); if (Page* page = document->page()) m_scaleFactor = page->deviceScaleFactor(); else m_scaleFactor = 1; if (!m_imagesInSet.size()) fillImageSet(); if (!m_accessedBestFitImage) { // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698 ImageWithScale image = bestImageForScaleFactor(); CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options); request.setInitiator(cachedResourceRequestInitiators().css); if (options.requestOriginPolicy() == PotentiallyCrossOriginEnabled) updateRequestForAccessControl(request.mutableResourceRequest(), document->securityOrigin(), options.allowCredentials()); if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) { detachPendingImage(); m_imageSet = StyleCachedImageSet::create(cachedImage.get(), image.scaleFactor, this); m_accessedBestFitImage = true; } } return (m_imageSet && m_imageSet->isCachedImageSet()) ? toStyleCachedImageSet(m_imageSet.get()) : nullptr; }
StyleCachedImage* CSSImageSetValue::bestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options) { Document* document = loader.document(); if (Page* page = document->page()) m_scaleFactor = page->deviceScaleFactor(); else m_scaleFactor = 1; if (!m_imagesInSet.size()) fillImageSet(); if (!m_accessedBestFitImage) { // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698 ImageWithScale image = bestImageForScaleFactor(); CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options); request.setInitiator(cachedResourceRequestInitiators().css); if (options.mode == FetchOptions::Mode::Cors) { ASSERT(document->securityOrigin()); updateRequestForAccessControl(request.mutableResourceRequest(), *document->securityOrigin(), options.allowCredentials); } if (CachedResourceHandle<CachedImage> cachedImage = loader.requestImage(request)) { detachPendingImage(); m_image = StyleCachedImage::createForImageSet(cachedImage.get(), image.scaleFactor, *this); m_accessedBestFitImage = true; } } return is<StyleCachedImage>(m_image.get()) ? downcast<StyleCachedImage>(m_image.get()) : nullptr; }
StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* loader) { ASSERT(loader); Document* document = loader->document(); if (Page* page = document->page()) m_scaleFactor = page->deviceScaleFactor(); else m_scaleFactor = 1; if (!m_imagesInSet.size()) fillImageSet(); if (!m_accessedBestFitImage) { // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698 ImageWithScale image = bestImageForScaleFactor(); CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL))); request.setInitiator(cachedResourceRequestInitiators().css); if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) { m_imageSet = StyleCachedImageSet::create(cachedImage.get(), image.scaleFactor, this); m_accessedBestFitImage = true; } } return (m_imageSet && m_imageSet->isCachedImageSet()) ? static_cast<StyleCachedImageSet*>(m_imageSet.get()) : 0; }
void IconLoader::startLoading() { ASSERT(m_frame || m_documentLoader); if (m_resource) return; if (m_frame && !m_frame->document()) return; if (m_documentLoader && !m_documentLoader->frame()) return; ResourceRequest resourceRequest(m_url); resourceRequest.setPriority(ResourceLoadPriority::Low); // ContentSecurityPolicyImposition::DoPolicyCheck is a placeholder value. It does not affect the request since Content Security Policy does not apply to raw resources. CachedResourceRequest request(WTFMove(resourceRequest), ResourceLoaderOptions(SendCallbacks, SniffContent, BufferData, DoNotAllowStoredCredentials, ClientCredentialPolicy::CannotAskClientForCredentials, FetchOptions::Credentials::Omit, DoSecurityCheck, FetchOptions::Mode::NoCors, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching)); request.setInitiator(cachedResourceRequestInitiators().icon); auto* frame = m_frame ? m_frame : m_documentLoader->frame(); m_resource = frame->document()->cachedResourceLoader().requestRawResource(WTFMove(request)); if (m_resource) m_resource->addClient(*this); else LOG_ERROR("Failed to start load for icon at url %s", frame->loader().icon().url().string().ascii().data()); }
void FetchLoader::start(ScriptExecutionContext& context, const FetchRequest& request) { ThreadableLoaderOptions options(request.fetchOptions(), ConsiderPreflight, context.shouldBypassMainWorldContentSecurityPolicy() ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceConnectSrcDirective, String(cachedResourceRequestInitiators().fetch), OpaqueResponseBodyPolicy::DoNotReceive); options.sendLoadCallbacks = SendCallbacks; options.dataBufferingPolicy = DoNotBufferData; options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set; ResourceRequest fetchRequest = request.internalRequest(); ASSERT(context.contentSecurityPolicy()); auto& contentSecurityPolicy = *context.contentSecurityPolicy(); contentSecurityPolicy.upgradeInsecureRequestIfNeeded(fetchRequest, ContentSecurityPolicy::InsecureRequestType::Load); if (!context.shouldBypassMainWorldContentSecurityPolicy() && !contentSecurityPolicy.allowConnectToSource(fetchRequest.url())) { m_client.didFail(); return; } String referrer = request.internalRequestReferrer(); if (referrer == "no-referrer") { options.referrerPolicy = FetchOptions::ReferrerPolicy::NoReferrer; referrer = String(); } else referrer = (referrer == "client") ? context.url().strippedForUseAsReferrer() : URL(context.url(), referrer).strippedForUseAsReferrer(); m_loader = ThreadableLoader::create(context, *this, WTFMove(fetchRequest), options, WTFMove(referrer)); m_isStarted = m_loader; }
CachedFont* CSSFontFaceSrcValue::cachedFont(Document* document) { if (!m_cachedFont) { CachedResourceRequest request(ResourceRequest(document->completeURL(m_resource))); request.setInitiator(cachedResourceRequestInitiators().css); m_cachedFont = document->cachedResourceLoader()->requestFont(request); } return m_cachedFont.get(); }
void DocumentLoader::startLoadingMainResource() { m_mainDocumentError = ResourceError(); timing()->markNavigationStart(); ASSERT(!m_mainResource); ASSERT(!m_loadingMainResource); m_loadingMainResource = true; if (maybeLoadEmpty()) return; ASSERT(timing()->navigationStart()); ASSERT(!timing()->fetchStart()); timing()->markFetchStart(); willSendRequest(m_request, ResourceResponse()); // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest. if (!m_frame || m_request.isNull()) return; m_applicationCacheHost->willStartLoadingMainResource(m_request); prepareSubframeArchiveLoadIfNeeded(); if (m_substituteData.isValid()) { m_identifierForLoadWithoutResourceLoader = createUniqueIdentifier(); frameLoader()->notifier()->dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, m_request, ResourceResponse()); handleSubstituteDataLoadSoon(); return; } ResourceRequest request(m_request); DEFINE_STATIC_LOCAL(ResourceLoaderOptions, mainResourceLoadOptions, (SendCallbacks, SniffContent, DoNotBufferData, AllowStoredCredentials, ClientRequestedCredentials, AskClientForCrossOriginCredentials, SkipSecurityCheck, CheckContentSecurityPolicy, UseDefaultOriginRestrictionsForType)); CachedResourceRequest cachedResourceRequest(request, cachedResourceRequestInitiators().document, mainResourceLoadOptions); m_mainResource = m_cachedResourceLoader->requestMainResource(cachedResourceRequest); if (!m_mainResource) { setRequest(ResourceRequest()); // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost // is now in a state where starting an empty load will be inconsistent. Replace it with // a new ApplicationCacheHost. m_applicationCacheHost = adoptPtr(new ApplicationCacheHost(this)); maybeLoadEmpty(); return; } m_mainResource->addClient(this); // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those. if (mainResourceLoader()) request = mainResourceLoader()->originalRequest(); // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include // the fragment identifier, so add that back in. if (equalIgnoringFragmentIdentifier(m_request.url(), request.url())) request.setURL(m_request.url()); setRequest(request); }
StyleCachedShader* WebKitCSSShaderValue::cachedShader(CachedResourceLoader* loader) { ASSERT(loader); if (!m_accessedShader) { m_accessedShader = true; CachedResourceRequest request(ResourceRequest(completeURL(loader))); request.setInitiator(cachedResourceRequestInitiators().css); if (CachedResourceHandle<CachedShader> cachedShader = loader->requestShader(request)) m_shader = StyleCachedShader::create(cachedShader.get()); } return (m_shader && m_shader->isCachedShader()) ? static_cast<StyleCachedShader*>(m_shader.get()) : 0; }
void IconLoader::startLoading() { if (m_resource || !m_frame.document()) return; CachedResourceRequest request(ResourceRequest(m_frame.loader().icon().url()), ResourceLoaderOptions(SendCallbacks, SniffContent, BufferData, DoNotAllowStoredCredentials, DoNotAskClientForAnyCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType, DoNotIncludeCertificateInfo)); request.mutableResourceRequest().setPriority(ResourceLoadPriorityLow); request.setInitiator(cachedResourceRequestInitiators().icon); m_resource = m_frame.document()->cachedResourceLoader().requestRawResource(request); if (m_resource) m_resource->addClient(this); else LOG_ERROR("Failed to start load for icon at url %s", m_frame.loader().icon().url().string().ascii().data()); }
void StyleRuleImport::requestStyleSheet() { if (!m_parentStyleSheet) return; Document* document = m_parentStyleSheet->singleOwnerDocument(); if (!document) return; CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); if (!cachedResourceLoader) return; URL absURL; if (!m_parentStyleSheet->baseURL().isNull()) // use parent styleheet's URL as the base URL absURL = URL(m_parentStyleSheet->baseURL(), m_strHref); else absURL = document->completeURL(m_strHref); // Check for a cycle in our import chain. If we encounter a stylesheet // in our parent chain with the same URL, then just bail. StyleSheetContents* rootSheet = m_parentStyleSheet; for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) { if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL()) || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL()))) return; rootSheet = sheet; } CachedResourceRequest request(ResourceRequest(absURL), m_parentStyleSheet->charset()); request.setInitiator(cachedResourceRequestInitiators().css); if (m_cachedSheet) m_cachedSheet->removeClient(&m_styleSheetClient); if (m_parentStyleSheet->isUserStyleSheet()) m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request); else m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request); if (m_cachedSheet) { // if the import rule is issued dynamically, the sheet may be // removed from the pending sheet count, so let the doc know // the sheet being imported is pending. if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet) m_parentStyleSheet->startLoadingDynamicSheet(); m_loading = true; m_cachedSheet->addClient(&m_styleSheetClient); } }
StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader) { ASSERT(loader); if (!m_accessedImage) { m_accessedImage = true; CachedResourceRequest request(ResourceRequest(loader->document()->completeURL(m_url))); if (m_initiatorName.isEmpty()) request.setInitiator(cachedResourceRequestInitiators().css); else request.setInitiator(m_initiatorName); if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) m_image = StyleCachedImage::create(cachedImage.get()); } return (m_image && m_image->isCachedImage()) ? static_cast<StyleCachedImage*>(m_image.get()) : 0; }
void CachedSVGDocumentReference::load(CachedResourceLoader& loader) { if (m_loadRequested) return; CachedResourceRequest request(ResourceRequest(loader.document()->completeURL(m_url))); request.setInitiator(cachedResourceRequestInitiators().css); m_document = loader.requestSVGDocument(request); if (m_document) { m_document->setCanReuse(m_canReuseResource); m_document->addClient(this); if (m_additionalDocumentClient) m_document->addClient(m_additionalDocumentClient); } m_loadRequested = true; }
std::pair<CachedImage*, float> CSSImageSetValue::loadBestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options) { Document* document = loader.document(); updateDeviceScaleFactor(*document); if (!m_accessedBestFitImage) { m_accessedBestFitImage = true; // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698 ImageWithScale image = bestImageForScaleFactor(); CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options); request.setInitiator(cachedResourceRequestInitiators().css); if (options.mode == FetchOptions::Mode::Cors) { ASSERT(document->securityOrigin()); updateRequestForAccessControl(request.mutableResourceRequest(), *document->securityOrigin(), options.allowCredentials); } m_cachedImage = loader.requestImage(request); m_bestFitImageScaleFactor = image.scaleFactor; } return { m_cachedImage.get(), m_bestFitImageScaleFactor }; }
StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const ResourceLoaderOptions& options) { ASSERT(loader); if (!m_accessedImage) { m_accessedImage = true; CachedResourceRequest request(ResourceRequest(loader->document()->completeURL(m_url)), options); if (m_initiatorName.isEmpty()) request.setInitiator(cachedResourceRequestInitiators().css); else request.setInitiator(m_initiatorName); if (options.requestOriginPolicy() == PotentiallyCrossOriginEnabled) updateRequestForAccessControl(request.mutableResourceRequest(), loader->document()->securityOrigin(), options.allowCredentials()); if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) { detachPendingImage(); m_image = StyleCachedImage::create(cachedImage.get()); } } return (m_image && m_image->isCachedImage()) ? toStyleCachedImage(m_image.get()) : nullptr; }
CachedDocument* CSSSVGDocumentValue::load(CachedResourceLoader* loader) { ASSERT(loader); if (!m_loadRequested) { m_loadRequested = true; CachedResourceRequest request(ResourceRequest(loader->document()->completeURL(m_url)), cachedResourceRequestInitiators().css); m_document = loader->requestSVGDocument(request); } return m_document.get(); }
bool DocumentThreadableLoader::isXMLHttpRequest() const { return m_options.initiator == cachedResourceRequestInitiators().xmlhttprequest; }
void XMLHttpRequest::createRequest(ExceptionCode& ec) { #if ENABLE(BLOB) // Only GET request is supported for blob URL. if (m_url.protocolIs("blob") && m_method != "GET") { ec = XMLHttpRequestException::NETWORK_ERR; return; } #endif // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all. // Also, only async requests support upload progress events. bool uploadEvents = false; if (m_async) { m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent)); if (m_requestEntityBody && m_upload) { uploadEvents = m_upload->hasEventListeners(); m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent)); } } m_sameOriginRequest = securityOrigin()->canRequest(m_url); // We also remember whether upload events should be allowed for this request in case the upload listeners are // added after the request is started. m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders); ResourceRequest request(m_url); request.setHTTPMethod(m_method); #if PLATFORM(CHROMIUM) || PLATFORM(BLACKBERRY) request.setTargetType(ResourceRequest::TargetIsXHR); #endif InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_method, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m_requestHeaders, m_includeCredentials); if (m_requestEntityBody) { ASSERT(m_method != "GET"); ASSERT(m_method != "HEAD"); request.setHTTPBody(m_requestEntityBody.release()); } if (m_requestHeaders.size() > 0) request.addHTTPHeaderFields(m_requestHeaders); ThreadableLoaderOptions options; options.sendLoadCallbacks = SendCallbacks; options.sniffContent = DoNotSniffContent; options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; options.crossOriginRequestPolicy = UseAccessControl; options.securityOrigin = securityOrigin(); #if ENABLE(RESOURCE_TIMING) options.initiator = cachedResourceRequestInitiators().xmlhttprequest; #endif #if ENABLE(XHR_TIMEOUT) if (m_timeoutMilliseconds) request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0); #endif m_exceptionCode = 0; m_error = false; if (m_async) { if (m_upload) request.setReportUploadProgress(true); // ThreadableLoader::create can return null here, for example if we're no longer attached to a page. // This is true while running onunload handlers. // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>. // FIXME: Maybe create() can return null for other reasons too? m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options); if (m_loader) { // Neither this object nor the JavaScript wrapper should be deleted while // a request is in progress because we need to keep the listeners alive, // and they are referenced by the JavaScript wrapper. setPendingActivity(this); } } else { InspectorInstrumentation::willLoadXHRSynchronously(scriptExecutionContext()); ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options); InspectorInstrumentation::didLoadXHRSynchronously(scriptExecutionContext()); } if (!m_exceptionCode && m_error) m_exceptionCode = XMLHttpRequestException::NETWORK_ERR; ec = m_exceptionCode; }
void XMLHttpRequest::createRequest(ExceptionCode& ec) { // Only GET request is supported for blob URL. if (!m_async && m_url.protocolIsBlob() && m_method != "GET") { ec = NETWORK_ERR; return; } m_sendFlag = true; // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all. // Also, only async requests support upload progress events. bool uploadEvents = false; if (m_async) { m_progressEventThrottle.dispatchProgressEvent(eventNames().loadstartEvent); if (m_requestEntityBody && m_upload) { uploadEvents = m_upload->hasEventListeners(); m_upload->dispatchProgressEvent(eventNames().loadstartEvent); } } m_sameOriginRequest = securityOrigin()->canRequest(m_url); // We also remember whether upload events should be allowed for this request in case the upload listeners are // added after the request is started. m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders); ResourceRequest request(m_url); request.setRequester(ResourceRequest::Requester::XHR); request.setHTTPMethod(m_method); if (m_requestEntityBody) { ASSERT(m_method != "GET"); ASSERT(m_method != "HEAD"); request.setHTTPBody(WTFMove(m_requestEntityBody)); } if (!m_requestHeaders.isEmpty()) request.setHTTPHeaderFields(m_requestHeaders); ThreadableLoaderOptions options; options.setSendLoadCallbacks(SendCallbacks); options.setSniffContent(DoNotSniffContent); options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; options.setAllowCredentials((m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials); options.setCredentialRequest(m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials); options.crossOriginRequestPolicy = UseAccessControl; options.securityOrigin = securityOrigin(); options.contentSecurityPolicyEnforcement = scriptExecutionContext()->shouldBypassMainWorldContentSecurityPolicy() ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceConnectSrcDirective; options.initiator = cachedResourceRequestInitiators().xmlhttprequest; if (m_timeoutMilliseconds) { if (!m_async) request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0); else { m_sendingTime = std::chrono::steady_clock::now(); m_timeoutTimer.startOneShot(std::chrono::milliseconds { m_timeoutMilliseconds }); } } m_exceptionCode = 0; m_error = false; if (m_async) { if (m_upload) request.setReportUploadProgress(true); // ThreadableLoader::create can return null here, for example if we're no longer attached to a page or if a content blocker blocks the load. // This is true while running onunload handlers. // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>. m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options); // Neither this object nor the JavaScript wrapper should be deleted while // a request is in progress because we need to keep the listeners alive, // and they are referenced by the JavaScript wrapper. setPendingActivity(this); if (!m_loader) { m_sendFlag = false; m_timeoutTimer.stop(); m_networkErrorTimer.startOneShot(0); } } else { InspectorInstrumentation::willLoadXHRSynchronously(scriptExecutionContext()); ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options); InspectorInstrumentation::didLoadXHRSynchronously(scriptExecutionContext()); } if (!m_exceptionCode && m_error) m_exceptionCode = NETWORK_ERR; ec = m_exceptionCode; }