CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, bool isPreload) { KURL fullURL = m_doc->completeURL(url); if (!fullURL.isValid() || !canRequest(type, fullURL)) return 0; if (cache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(fullURL.string()); if (it != m_documentResources.end()) { it->second->setDocLoader(0); m_documentResources.remove(it); } } checkForReload(fullURL); CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, isPreload); if (resource) { // Check final URL of resource to catch redirects. // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. if (!canRequest(type, KURL(resource->url()))) return 0; m_documentResources.set(resource->url(), resource); checkCacheObjectStatus(resource); } return resource; }
CachedImage* CachedResourceLoader::requestImage(ResourceRequest& request) { if (Frame* f = frame()) { Settings* settings = f->settings(); if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) return 0; if (f->loader()->pageDismissalEventBeingDispatched()) { KURL requestURL = request.url(); if (requestURL.isValid() && canRequest(CachedResource::ImageResource, requestURL)) PingLoader::loadImage(f, requestURL); return 0; } } CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String())); if (resource) { #ifdef ANDROID_BLOCK_NETWORK_IMAGE resource->setAutoLoadWasPreventedBySettings(!autoLoadImages() || shouldBlockNetworkImage(request.url())); #else resource->setAutoLoadWasPreventedBySettings(!autoLoadImages()); #endif if (autoLoadImages() && resource->stillNeedsLoad()) { #ifdef ANDROID_BLOCK_NETWORK_IMAGE if (shouldBlockNetworkImage(request.url())) { return resource; } #endif resource->setLoading(true); load(resource, true); } } return resource; }
CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& resourceURL, const String& charset, ResourceLoadPriority priority, bool forPreload) { KURL url = m_document->completeURL(resourceURL); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.string().latin1().data(), charset.latin1().data(), priority, 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)) return 0; // FIXME: Figure out what is the correct way to merge this security check with the one above. if (!document()->securityOrigin()->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(document()->frame(), url.string()); LOG(ResourceLoading, "CachedResourceLoader::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return 0; } if (memoryCache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(url.string()); if (it != m_documentResources.end()) { it->second->setOwningCachedResourceLoader(0); m_documentResources.remove(it); } } // See if we can use an existing resource from the cache. CachedResource* resource = memoryCache()->resourceForURL(url); switch (determineRevalidationPolicy(type, forPreload, resource)) { case Load: resource = loadResource(type, url, charset, priority); break; case Reload: memoryCache()->remove(resource); resource = loadResource(type, url, charset, priority); break; case Revalidate: resource = revalidateResource(resource, priority); break; case Use: memoryCache()->resourceAccessed(resource); notifyLoadedFromMemoryCache(resource); break; } if (!resource) return 0; ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, ResourceLoadPriority priority, bool forPreload) { KURL url = request.url(); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.string().latin1().data(), charset.latin1().data(), priority, 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, forPreload)) return 0; if (memoryCache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(url.string()); if (it != m_documentResources.end()) { it->second->setOwningCachedResourceLoader(0); m_documentResources.remove(it); } } // See if we can use an existing resource from the cache. CachedResource* resource = memoryCache()->resourceForURL(url); if (request.url() != url) request.setURL(url); switch (determineRevalidationPolicy(type, forPreload, resource)) { case Load: resource = loadResource(type, request, charset, priority); break; case Reload: memoryCache()->remove(resource); resource = loadResource(type, request, charset, priority); break; case Revalidate: resource = revalidateResource(resource, priority); break; case Use: memoryCache()->resourceAccessed(resource); notifyLoadedFromMemoryCache(resource); break; } if (!resource) return 0; ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
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()); }
CachedImage* CachedResourceLoader::requestImage(ResourceRequest& request) { if (Frame* f = frame()) { if (f->loader()->pageDismissalEventBeingDispatched() != FrameLoader::NoDismissal) { KURL requestURL = request.url(); if (requestURL.isValid() && canRequest(CachedResource::ImageResource, requestURL)) PingLoader::loadImage(f, requestURL); return 0; } } CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String(), defaultCachedResourceOptions())); if (autoLoadImages() && resource && resource->stillNeedsLoad()) resource->load(this, defaultCachedResourceOptions()); return resource; }
bool SecurityOrigin::taintsCanvas(const KURL& url) const { if (canRequest(url)) return false; // This function exists because we treat data URLs as having a unique origin, // contrary to the current (9/19/2009) draft of the HTML5 specification. // We still want to let folks paint data URLs onto untainted canvases, so // we special case data URLs below. If we change to match HTML5 w.r.t. // data URL security, then we can remove this function in favor of // !canRequest. if (url.protocolIsData()) return false; return true; }
bool SecurityOrigin::canDisplay(const KURL& url) const { String protocol = url.protocol().lower(); if (isFeedWithNestedProtocolInHTTPFamily(url)) return true; if (SchemeRegistry::canDisplayOnlyIfCanRequest(protocol)) return canRequest(url); if (SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(protocol)) return m_protocol == protocol || SecurityPolicy::isAccessToURLWhiteListed(this, url); if (SecurityPolicy::restrictAccessToLocal() && SchemeRegistry::shouldTreatURLSchemeAsLocal(protocol)) return canLoadLocalResources() || SecurityPolicy::isAccessToURLWhiteListed(this, url); return true; }
bool SecurityOrigin::canDisplay(const KURL& url) const { if (m_universalAccess) return true; String protocol = url.protocol().lower(); if (SchemeRegistry::canDisplayOnlyIfCanRequest(protocol)) return canRequest(url); if (SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(protocol)) return m_protocol == protocol || SecurityPolicy::isAccessToURLWhiteListed(this, url); if (SchemeRegistry::shouldTreatURLSchemeAsLocal(protocol)) return canLoadLocalResources() || SecurityPolicy::isAccessToURLWhiteListed(this, url); return true; }
CachedImage* CachedResourceLoader::requestImage(ResourceRequest& request) { if (Frame* f = frame()) { Settings* settings = f->settings(); if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) return 0; if (f->loader()->pageDismissalEventBeingDispatched() != FrameLoader::NoDismissal) { KURL requestURL = request.url(); if (requestURL.isValid() && canRequest(CachedResource::ImageResource, requestURL)) PingLoader::loadImage(f, requestURL); return 0; } } CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String())); if (autoLoadImages() && resource && resource->stillNeedsLoad()) resource->load(this); return resource; }
bool SecurityOrigin::canDisplay(const URL& url) const { if (m_universalAccess) return true; if (isFeedWithNestedProtocolInHTTPFamily(url)) return true; String protocol = url.protocol().toString(); if (SchemeRegistry::canDisplayOnlyIfCanRequest(protocol)) return canRequest(url); if (SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(protocol)) return equalIgnoringASCIICase(m_protocol, protocol) || SecurityPolicy::isAccessToURLWhiteListed(this, url); if (SecurityPolicy::restrictAccessToLocal() && SchemeRegistry::shouldTreatURLSchemeAsLocal(protocol)) return canLoadLocalResources() || SecurityPolicy::isAccessToURLWhiteListed(this, url); return true; }
CachedImage* CachedResourceLoader::requestImage(const String& url) { if (Frame* f = frame()) { Settings* settings = f->settings(); if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) return 0; if (f->loader()->pageDismissalEventBeingDispatched()) { KURL completeURL = m_document->completeURL(url); if (completeURL.isValid() && canRequest(CachedResource::ImageResource, completeURL)) PingLoader::loadImage(f, completeURL); return 0; } } CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url, String())); if (autoLoadImages() && resource && resource->stillNeedsLoad()) { resource->setLoading(true); load(resource, true); } return resource; }
ResourcePtr<Resource> ResourceFetcher::requestResource(Resource::Type type, FetchRequest& request) { ASSERT(request.options().synchronousPolicy == RequestAsynchronously || type == Resource::Raw); TRACE_EVENT0("blink", "ResourceFetcher::requestResource"); KURL url = request.resourceRequest().url(); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource '%s', charset '%s', priority=%d, type=%s", url.elidedString().latin1().data(), request.charset().latin1().data(), request.priority(), ResourceTypeName(type)); // 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.options(), request.originRestriction())) return 0; if (LocalFrame* f = frame()) f->loaderClient()->dispatchWillRequestResource(&request); // See if we can use an existing resource from the cache. ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url); const RevalidationPolicy policy = determineRevalidationPolicy(type, request, resource.get()); switch (policy) { case Reload: memoryCache()->remove(resource.get()); // Fall through case Load: resource = createResourceForLoading(type, request, request.charset()); break; case Revalidate: resource = createResourceForRevalidation(request, resource.get()); break; case Use: memoryCache()->updateForAccess(resource.get()); break; } if (!resource) return 0; if (!resource->hasClients()) m_deadStatsRecorder.update(policy); if (policy != Use) resource->setIdentifier(createUniqueIdentifier()); ResourceLoadPriority priority = loadPriority(type, request); if (priority != resource->resourceRequest().priority()) { resource->mutableResourceRequest().setPriority(priority); resource->didChangePriority(priority, 0); } if (resourceNeedsLoad(resource.get(), request, policy)) { if (!shouldLoadNewResource(type)) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } resource->load(this, request.options()); // For asynchronous loads that immediately fail, it's sufficient to return a // null Resource, as it indicates that something prevented the load from starting. // If there's a network error, that failure will happen asynchronously. However, if // a sync load receives a network error, it will have already happened by this point. // In that case, the requester should have access to the relevant ResourceError, so // we need to return a non-null Resource. if (resource->errorOccurred()) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } } requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork); ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
bool SecurityOrigin::canRequestNoSuborigin(const KURL& url) const { return !hasSuborigin() && canRequest(url); }
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; }