static void* openFunc(const char* uri) { ASSERT(XMLDocumentParserScope::currentCachedResourceLoader); ASSERT(currentThread() == libxmlLoaderThread); KURL url(KURL(), uri); if (!shouldAllowExternalLoad(url)) return &globalDescriptor; ResourceError error; ResourceResponse response; Vector<char> data; { CachedResourceLoader* cachedResourceLoader = XMLDocumentParserScope::currentCachedResourceLoader; XMLDocumentParserScope scope(0); // FIXME: We should restore the original global error handler as well. if (cachedResourceLoader->frame()) cachedResourceLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data); } // We have to check the URL again after the load to catch redirects. // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. if (!shouldAllowExternalLoad(response.url())) return &globalDescriptor; return new OffsetBuffer(data); }
bool TextTrackLoader::load(const KURL& url, const String& crossOriginMode) { cancelLoad(); if (!m_client->shouldLoadCues(this)) return false; ASSERT(m_scriptExecutionContext->isDocument()); Document* document = static_cast<Document*>(m_scriptExecutionContext); ResourceRequest cueRequest(document->completeURL(url)); if (!crossOriginMode.isNull()) { m_crossOriginMode = crossOriginMode; StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; updateRequestForAccessControl(cueRequest, document->securityOrigin(), allowCredentials); } else { // Cross-origin resources that are not suitably CORS-enabled may not load. if (!document->securityOrigin()->canRequest(url)) { corsPolicyPreventedLoad(); return false; } } CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); m_cachedCueData = cachedResourceLoader->requestTextTrack(cueRequest); if (m_cachedCueData) m_cachedCueData->addClient(this); m_client->cueLoadingStarted(this); return true; }
void Internals::garbageCollectDocumentResources(Document* document, ExceptionCode& ec) const { if (!document) { ec = INVALID_ACCESS_ERR; return; } CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); if (!cachedResourceLoader) return; cachedResourceLoader->garbageCollectDocumentResources(); }
std::pair<CachedImage*, float> CSSCursorImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options) { if (is<CSSImageSetValue>(m_imageValue.get())) return downcast<CSSImageSetValue>(m_imageValue.get()).loadBestFitImage(loader, options); if (auto* cursorElement = updateCursorElement(*loader.document())) { if (cursorElement->href() != downcast<CSSImageValue>(m_imageValue.get()).url()) m_imageValue = CSSImageValue::create(loader.document()->completeURL(cursorElement->href())); } return { downcast<CSSImageValue>(m_imageValue.get()).loadImage(loader, options), 1 }; }
void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*) { Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading; fontsToBeginLoading.swap(m_fontsToBeginLoading); CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader(); for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) { fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader); // Balances incrementRequestCount() in beginLoadingFontSoon(). cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get()); } // Ensure that if the request count reaches zero, the frame loader will know about it. cachedResourceLoader->loadDone(); }
void CachedImage::load(CachedResourceLoader& cachedResourceLoader, const ResourceLoaderOptions& options) { if (cachedResourceLoader.shouldPerformImageLoad(url())) CachedResource::load(cachedResourceLoader, options); else setLoading(false); }
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); } }
void SVGFontFaceUriElement::loadFont() { if (m_cachedFont) m_cachedFont->removeClient(this); const AtomicString& href = getAttribute(XLinkNames::hrefAttr); if (!href.isNull()) { CachedResourceLoader* cachedResourceLoader = document()->cachedResourceLoader(); ResourceRequest request(document()->completeURL(href)); m_cachedFont = cachedResourceLoader->requestFont(request); if (m_cachedFont) { m_cachedFont->addClient(this); m_cachedFont->beginLoadIfNeeded(cachedResourceLoader); } } else m_cachedFont = 0; }
void SVGFontFaceUriElement::loadFont() { if (m_cachedFont) m_cachedFont->removeClient(this); String href = getAttribute(XLinkNames::hrefAttr); if (!href.isNull()) { CachedResourceLoader* cachedResourceLoader = document()->cachedResourceLoader(); m_cachedFont = cachedResourceLoader->requestFont(href); if (m_cachedFont) { m_cachedFont->setSVGFont(true); m_cachedFont->addClient(this); m_cachedFont->beginLoadIfNeeded(cachedResourceLoader); } } else m_cachedFont = 0; }
void preload(Document* document, const KURL& baseURL) { if (m_urlToLoad.isEmpty()) return; CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); CachedResourceRequest request(ResourceRequest(document->completeURL(m_urlToLoad, baseURL))); request.setInitiator(tagName()); if (m_tagName == scriptTag) { request.mutableResourceRequest().setAllowCookies(crossOriginModeAllowsCookies()); cachedResourceLoader->preload(CachedResource::Script, request, m_charset); } else if (m_tagName == imgTag || (m_tagName == inputTag && m_inputIsImage)) cachedResourceLoader->preload(CachedResource::ImageResource, request, String()); else if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen) cachedResourceLoader->preload(CachedResource::CSSStyleSheet, request, m_charset); }
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; }
void XSLImportRule::loadSheet() { CachedResourceLoader* cachedResourceLoader = 0; XSLStyleSheet* rootSheet = parentStyleSheet(); if (rootSheet) { while (XSLStyleSheet* parentSheet = rootSheet->parentStyleSheet()) rootSheet = parentSheet; } if (rootSheet) cachedResourceLoader = rootSheet->cachedResourceLoader(); String absHref = m_strHref; XSLStyleSheet* parentSheet = parentStyleSheet(); if (!parentSheet->baseURL().isNull()) // use parent styleheet's URL as the base URL absHref = KURL(parentSheet->baseURL(), m_strHref).string(); // Check for a cycle in our import chain. If we encounter a stylesheet // in our parent chain with the same URL, then just bail. for (XSLStyleSheet* parentSheet = parentStyleSheet(); parentSheet; parentSheet = parentSheet->parentStyleSheet()) { if (absHref == parentSheet->baseURL().string()) return; } CachedResourceRequest request(ResourceRequest(cachedResourceLoader->document()->completeURL(absHref))); if (m_cachedSheet) m_cachedSheet->removeClient(this); m_cachedSheet = cachedResourceLoader->requestXSLStyleSheet(request); if (m_cachedSheet) { m_cachedSheet->addClient(this); // If the imported sheet is in the cache, then setXSLStyleSheet gets called, // and the sheet even gets parsed (via parseString). In this case we have // loaded (even if our subresources haven't), so if we have a stylesheet after // checking the cache, then we've clearly loaded. if (!m_styleSheet) m_loading = true; } }
void CSSImportRule::requestStyleSheet() { CSSStyleSheet* parentSheet = parentStyleSheet(); if (!parentSheet) return; Document* document = parentSheet->findDocument(); if (!document) return; CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); if (!cachedResourceLoader) return; String absHref = m_strHref; if (!parentSheet->finalURL().isNull()) // use parent styleheet's URL as the base URL absHref = KURL(parentSheet->finalURL(), m_strHref).string(); // Check for a cycle in our import chain. If we encounter a stylesheet // in our parent chain with the same URL, then just bail. CSSStyleSheet* rootSheet = parentSheet; for (CSSStyleSheet* sheet = parentSheet; sheet; sheet = sheet->parentStyleSheet()) { // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL. if (absHref == sheet->finalURL().string()) return; rootSheet = sheet; } ResourceRequest request(document->completeURL(absHref)); if (parentSheet->isUserStyleSheet()) m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parentSheet->charset()); else m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parentSheet->charset()); 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 (parentSheet && parentSheet->loadCompleted() && rootSheet == parentSheet) parentSheet->startLoadingDynamicSheet(); m_loading = true; m_cachedSheet->addClient(&m_styleSheetClient); } }
void CSSFontSelector::clearDocument() { if (!m_document) { ASSERT(!m_beginLoadingTimer.isActive()); ASSERT(m_fontsToBeginLoading.isEmpty()); return; } m_beginLoadingTimer.stop(); CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader(); for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) { // Balances incrementRequestCount() in beginLoadingFontSoon(). cachedResourceLoader->decrementRequestCount(m_fontsToBeginLoading[i].get()); } m_fontsToBeginLoading.clear(); m_document = 0; }
bool TextTrackLoader::load(const KURL& url) { if (!m_client->shouldLoadCues(this)) return false; cancelLoad(); ASSERT(m_scriptExecutionContext->isDocument()); Document* document = static_cast<Document*>(m_scriptExecutionContext); ResourceRequest cueRequest(document->completeURL(url)); CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); m_cachedCueData = static_cast<CachedTextTrack*>(cachedResourceLoader->requestTextTrack(cueRequest)); if (m_cachedCueData) m_cachedCueData->addClient(this); m_client->cueLoadingStarted(this); return true; }
void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*) { Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading; fontsToBeginLoading.swap(m_fontsToBeginLoading); // CSSFontSelector could get deleted via beginLoadIfNeeded() or loadDone() unless protected. RefPtr<CSSFontSelector> protect(this); CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader(); for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) { fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader); // Balances incrementRequestCount() in beginLoadingFontSoon(). cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get()); } // Ensure that if the request count reaches zero, the frame loader will know about it. cachedResourceLoader->loadDone(); // New font loads may be triggered by layout after the document load is complete but before we have dispatched // didFinishLoading for the frame. Make sure the delegate is always dispatched by checking explicitly. if (m_document && m_document->frame()) m_document->frame()->loader()->checkLoadComplete(); }
void CSSImportRule::insertedIntoParent() { CSSStyleSheet* parentSheet = parentStyleSheet(); if (!parentSheet || !parentSheet->document()) return; CachedResourceLoader* cachedResourceLoader = parentSheet->document()->cachedResourceLoader(); if (!cachedResourceLoader) return; String absHref = m_strHref; if (!parentSheet->finalURL().isNull()) // use parent styleheet's URL as the base URL absHref = KURL(parentSheet->finalURL(), m_strHref).string(); // Check for a cycle in our import chain. If we encounter a stylesheet // in our parent chain with the same URL, then just bail. StyleBase* root = this; for (StyleBase* curr = parent(); curr; curr = curr->parent()) { // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL. if (curr->isCSSStyleSheet() && absHref == static_cast<CSSStyleSheet*>(curr)->finalURL().string()) return; root = curr; } if (parentSheet->isUserStyleSheet()) m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(absHref, parentSheet->charset()); else m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(absHref, parentSheet->charset()); 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 (parentSheet && parentSheet->loadCompleted() && root == parentSheet) parentSheet->document()->addPendingSheet(); m_loading = true; m_cachedSheet->addClient(this); } }
void CachedImage::load(CachedResourceLoader& loader) { if (loader.shouldPerformImageLoad(url())) CachedResource::load(loader); else setLoading(false); if (m_loader) { m_allowSubsampling = m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled(); m_allowAsyncImageDecoding = m_loader->frameLoader()->frame().settings().asyncImageDecodingEnabled(); m_showDebugBackground = m_loader->frameLoader()->frame().settings().showDebugBorders(); } }
void StyleRuleImport::requestStyleSheet(CSSStyleSheet* rootSheet, const CSSParserContext& parserContext) { ASSERT(!rootSheet->parentStyleSheet()); ASSERT(!m_cachedSheet); Node* ownerNode = rootSheet->ownerNode(); if (!ownerNode) return; Document* document = ownerNode->document(); KURL resolvedURL; if (!parserContext.baseURL.isNull()) resolvedURL = KURL(parserContext.baseURL, m_strHref); else resolvedURL = document->completeURL(m_strHref); StyleSheetContents* rootSheetContents = rootSheet->contents(); if (rootSheetContents->hasImportCycle(this, resolvedURL, document->baseURL())) return; ResourceRequest request(resolvedURL); CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); if (rootSheetContents->isUserStyleSheet()) m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parserContext.charset); else m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parserContext.charset); if (!m_cachedSheet) return; // 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 (rootSheetContents->loadCompleted()) ownerNode->startLoadingDynamicSheet(); m_loadContext = adoptPtr(new LoadContext(rootSheet, parserContext)); m_cachedSheet->addClient(this); }
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 }; }
void CachedResource::load(CachedResourceLoader& cachedResourceLoader) { if (!cachedResourceLoader.frame()) { RELEASE_LOG_IF_ALLOWED("load: No associated frame"); failBeforeStarting(); return; } Frame& frame = *cachedResourceLoader.frame(); // Prevent new loads if we are in the PageCache or being added to the PageCache. // We query the top document because new frames may be created in pagehide event handlers // and their pageCacheState will not reflect the fact that they are about to enter page // cache. if (auto* topDocument = frame.mainFrame().document()) { if (topDocument->pageCacheState() != Document::NotInPageCache) { RELEASE_LOG_IF_ALLOWED("load: Already in page cache or being added to it (frame = %p)", &frame); failBeforeStarting(); return; } } FrameLoader& frameLoader = frame.loader(); if (m_options.securityCheck == DoSecurityCheck && (frameLoader.state() == FrameStateProvisional || !frameLoader.activeDocumentLoader() || frameLoader.activeDocumentLoader()->isStopping())) { if (frameLoader.state() == FrameStateProvisional) RELEASE_LOG_IF_ALLOWED("load: Failed security check -- state is provisional (frame = %p)", &frame); else if (!frameLoader.activeDocumentLoader()) RELEASE_LOG_IF_ALLOWED("load: Failed security check -- not active document (frame = %p)", &frame); else if (frameLoader.activeDocumentLoader()->isStopping()) RELEASE_LOG_IF_ALLOWED("load: Failed security check -- active loader is stopping (frame = %p)", &frame); failBeforeStarting(); return; } m_loading = true; #if USE(QUICK_LOOK) if (!m_resourceRequest.isNull() && m_resourceRequest.url().protocolIs(QLPreviewProtocol())) { // When QuickLook is invoked to convert a document, it returns a unique URL in the // NSURLReponse for the main document. To make safeQLURLForDocumentURLAndResourceURL() // work, we need to use the QL URL not the original URL. const URL& documentURL = frameLoader.documentLoader()->response().url(); m_resourceRequest.setURL(safeQLURLForDocumentURLAndResourceURL(documentURL, url())); } #endif if (isCacheValidator()) { CachedResource* resourceToRevalidate = m_resourceToRevalidate; ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::LastModified); const String& eTag = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::ETag); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(cachedResourceLoader.cachePolicy(type()) != CachePolicyReload); if (cachedResourceLoader.cachePolicy(type()) == CachePolicyRevalidate) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0"); if (!lastModified.isEmpty()) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified); if (!eTag.isEmpty()) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag); } } #if ENABLE(LINK_PREFETCH) if (type() == CachedResource::LinkPrefetch || type() == CachedResource::LinkSubresource) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::Purpose, "prefetch"); #endif m_resourceRequest.setPriority(loadPriority()); // Navigation algorithm is setting up the request before sending it to CachedResourceLoader?CachedResource. // So no need for extra fields for MainResource. if (type() != CachedResource::MainResource) frameLoader.addExtraFieldsToSubresourceRequest(m_resourceRequest); // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers. // We should look into removing the expectation of that knowledge from the platform network stacks. ResourceRequest request(m_resourceRequest); if (!m_fragmentIdentifierForRequest.isNull()) { URL url = request.url(); url.setFragmentIdentifier(m_fragmentIdentifierForRequest); request.setURL(url); m_fragmentIdentifierForRequest = String(); } m_loader = platformStrategies()->loaderStrategy()->loadResource(frame, *this, request, m_options); if (!m_loader) { RELEASE_LOG_IF_ALLOWED("load: Unable to create SubresourceLoader (frame = %p)", &frame); failBeforeStarting(); return; } m_status = Pending; }