void SVGUseElement::updateExternalDocument() { URL externalDocumentURL; if (inDocument() && isExternalURIReference(href(), document())) { externalDocumentURL = document().completeURL(href()); if (!externalDocumentURL.hasFragmentIdentifier()) externalDocumentURL = URL(); } if (externalDocumentURL == (m_externalDocument ? m_externalDocument->url() : URL())) return; if (m_externalDocument) m_externalDocument->removeClient(this); if (externalDocumentURL.isNull()) m_externalDocument = nullptr; else { ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions(); options.setContentSecurityPolicyImposition(isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck); CachedResourceRequest request { ResourceRequest { externalDocumentURL }, options }; request.setInitiator(this); m_externalDocument = document().cachedResourceLoader().requestSVGDocument(request); if (m_externalDocument) m_externalDocument->addClient(this); } invalidateShadowTree(); }
void SVGUseElement::updateExternalDocument() { URL externalDocumentURL; if (inDocument() && isExternalURIReference(href(), document())) { externalDocumentURL = document().completeURL(href()); if (!externalDocumentURL.hasFragmentIdentifier()) externalDocumentURL = URL(); } if (externalDocumentURL == (m_externalDocument ? m_externalDocument->url() : URL())) return; if (m_externalDocument) m_externalDocument->removeClient(this); if (externalDocumentURL.isNull()) m_externalDocument = nullptr; else { CachedResourceRequest request { ResourceRequest { externalDocumentURL } }; request.setInitiator(this); m_externalDocument = document().cachedResourceLoader().requestSVGDocument(request); if (m_externalDocument) { // FIXME: Is it really OK for us to set this to false for a document that might be shared by another client? m_externalDocument->setShouldCreateFrameForDocument(false); // No frame needed, we just want the elements. m_externalDocument->addClient(this); } } invalidateShadowTree(); }
CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(CachedResourceRequest& request) { if (Frame* f = frame()) { if (f->loader()->pageDismissalEventBeingDispatched() != FrameLoader::NoDismissal) { KURL requestURL = request.resourceRequest().url(); if (requestURL.isValid() && canRequest(CachedResource::ImageResource, requestURL)) PingLoader::loadImage(f, requestURL); return 0; } } request.setDefer(clientDefersImage(request.resourceRequest().url()) ? CachedResourceRequest::DeferredByClient : CachedResourceRequest::NoDefer); return static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request).get()); }
CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, CachedResourceRequest& request, const String& charset) { ASSERT(!memoryCache()->resourceForRequest(request.resourceRequest())); LOG(ResourceLoading, "Loading CachedResource for '%s'.", request.resourceRequest().url().elidedString().latin1().data()); CachedResourceHandle<CachedResource> resource = createResource(type, request.mutableResourceRequest(), charset); if (!memoryCache()->add(resource.get())) resource->setOwningCachedResourceLoader(this); #if ENABLE(RESOURCE_TIMING) storeResourceTimingInitiatorInformation(resource, request); #endif return resource; }
CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestUserCSSStyleSheet(CachedResourceRequest& request) { KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(request.resourceRequest().url()); #if ENABLE(CACHE_PARTITIONING) request.mutableResourceRequest().setCachePartition(document()->topOrigin()->cachePartition()); #endif if (CachedResource* existing = memoryCache()->resourceForRequest(request.resourceRequest())) { if (existing->type() == CachedResource::CSSStyleSheet) return static_cast<CachedCSSStyleSheet*>(existing); memoryCache()->remove(existing); } if (url.string() != request.resourceRequest().url()) request.mutableResourceRequest().setURL(url); CachedResourceHandle<CachedCSSStyleSheet> userSheet = new CachedCSSStyleSheet(request.resourceRequest(), request.charset()); memoryCache()->add(userSheet.get()); // FIXME: loadResource calls setOwningCachedResourceLoader() if the resource couldn't be added to cache. Does this function need to call it, too? userSheet->load(this, ResourceLoaderOptions(DoNotSendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForCrossOriginCredentials, SkipSecurityCheck)); return userSheet; }
void CachedResourceLoader::requestPreload(CachedResource::Type type, CachedResourceRequest& request, const String& charset) { String encoding; if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) encoding = charset.isEmpty() ? m_document->charset() : charset; request.setCharset(encoding); request.setForPreload(true); CachedResourceHandle<CachedResource> resource = requestResource(type, request); if (!resource || (m_preloads && m_preloads->contains(resource.get()))) return; resource->increasePreloadCount(); if (!m_preloads) m_preloads = adoptPtr(new ListHashSet<CachedResource*>); m_preloads->add(resource.get()); #if PRELOAD_DEBUG printf("PRELOADING %s\n", resource->url().latin1().data()); #endif }
void CachedResourceLoader::storeResourceTimingInitiatorInformation(const CachedResourceHandle<CachedResource>& resource, const CachedResourceRequest& request) { if (resource->type() == CachedResource::MainResource) { // <iframe>s should report the initial navigation requested by the parent document, but not subsequent navigations. if (frame()->ownerElement() && m_documentLoader->frameLoader()->stateMachine()->committingFirstRealLoad()) { InitiatorInfo info = { frame()->ownerElement()->localName(), monotonicallyIncreasingTime() }; m_initiatorMap.add(resource.get(), info); } } else { InitiatorInfo info = { request.initiatorName(), monotonicallyIncreasingTime() }; m_initiatorMap.add(resource.get(), info); } }
void ResourceTimingInformation::storeResourceTimingInitiatorInformation(const CachedResourceHandle<CachedResource>& resource, const CachedResourceRequest& request, Frame* frame) { ASSERT(RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled()); ASSERT(resource.get()); if (resource->type() == CachedResource::MainResource) { // <iframe>s should report the initial navigation requested by the parent document, but not subsequent navigations. ASSERT(frame); if (frame->ownerElement()) { InitiatorInfo info = { frame->ownerElement()->localName(), monotonicallyIncreasingTime(), NotYetAdded }; m_initiatorMap.add(resource.get(), info); } } else { InitiatorInfo info = { request.initiatorName(), monotonicallyIncreasingTime(), NotYetAdded }; m_initiatorMap.add(resource.get(), info); } }
void CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest& request, const String& charset) { bool delaySubresourceLoad = true; #if PLATFORM(IOS) || PLATFORM(CHROMIUM) delaySubresourceLoad = false; #endif #if PLATFORM(CHROMIUM) // FIXME: All ports should take advantage of this, but first must support ResourceHandle::didChangePriority(). if (type == CachedResource::ImageResource) request.setPriority(ResourceLoadPriorityVeryLow); #endif if (delaySubresourceLoad) { bool hasRendering = m_document->body() && m_document->body()->renderer(); bool canBlockParser = type == CachedResource::Script || type == CachedResource::CSSStyleSheet; if (!hasRendering && !canBlockParser) { // Don't preload subresources that can't block the parser before we have something to draw. // This helps prevent preloads from delaying first display when bandwidth is limited. PendingPreload pendingPreload = { type, request, charset }; m_pendingPreloads.append(pendingPreload); return; } } requestPreload(type, request, charset); }
CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, CachedResourceRequest& request) { KURL url = request.resourceRequest().url(); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.elidedString().latin1().data(), request.charset().latin1().data(), request.priority(), request.forPreload()); // If only the fragment identifiers differ, it is the same resource. url = MemoryCache::removeFragmentIdentifierIfNeeded(url); if (!url.isValid()) return 0; if (!canRequest(type, url, request.forPreload())) return 0; if (Frame* f = frame()) f->loader()->client()->dispatchWillRequestResource(&request); if (memoryCache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(url.string()); if (it != m_documentResources.end()) { it->value->setOwningCachedResourceLoader(0); m_documentResources.remove(it); } } // See if we can use an existing resource from the cache. CachedResourceHandle<CachedResource> resource; #if ENABLE(CACHE_PARTITIONING) if (document()) request.mutableResourceRequest().setCachePartition(document()->topOrigin()->cachePartition()); #endif resource = memoryCache()->resourceForRequest(request.resourceRequest()); const RevalidationPolicy policy = determineRevalidationPolicy(type, request.mutableResourceRequest(), request.forPreload(), resource.get(), request.defer()); switch (policy) { case Reload: memoryCache()->remove(resource.get()); // Fall through case Load: resource = loadResource(type, request, request.charset()); break; case Revalidate: resource = revalidateResource(request, resource.get()); break; case Use: memoryCache()->resourceAccessed(resource.get()); notifyLoadedFromMemoryCache(resource.get()); break; } if (!resource) return 0; if (!request.forPreload() || policy != Use) resource->setLoadPriority(request.priority()); if ((policy != Use || resource->stillNeedsLoad()) && CachedResourceRequest::NoDefer == request.defer()) { resource->load(this, request.options()); // We don't support immediate loads, but we do support immediate failure. if (resource->errorOccurred()) { if (resource->inCache()) memoryCache()->remove(resource.get()); return 0; } } #if PLATFORM(CHROMIUM) // FIXME: Temporarily leave main resource caching disabled for chromium, see https://bugs.webkit.org/show_bug.cgi?id=107962 // Ensure main resources aren't preloaded, and other main resource loads are removed from cache to prevent reuse. if (type == CachedResource::MainResource) { ASSERT(policy != Use); ASSERT(policy != Revalidate); memoryCache()->remove(resource.get()); if (request.forPreload()) return 0; } #endif if (!request.resourceRequest().url().protocolIsData()) m_validatedURLs.add(request.resourceRequest().url()); ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }