Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Unified Diff: third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp

Issue 2584423002: Loading: move core/fetch to platform/loader/fetch (Closed)
Patch Set: another try Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
deleted file mode 100644
index 5f25871b730cf19284137b85d30a6eb761c716f8..0000000000000000000000000000000000000000
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ /dev/null
@@ -1,1514 +0,0 @@
-/*
- Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
- Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
- Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
- Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
- rights reserved.
- Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
- This class provides all functionality needed for loading images, style
- sheets and html pages from the web. It has a memory cache for these objects.
-*/
-
-#include "core/fetch/ResourceFetcher.h"
-
-#include "core/fetch/FetchContext.h"
-#include "core/fetch/FetchInitiatorTypeNames.h"
-#include "core/fetch/MemoryCache.h"
-#include "core/fetch/ResourceLoader.h"
-#include "core/fetch/ResourceLoadingLog.h"
-#include "core/fetch/UniqueIdentifier.h"
-#include "platform/Histogram.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/instrumentation/tracing/TraceEvent.h"
-#include "platform/instrumentation/tracing/TracedValue.h"
-#include "platform/mhtml/ArchiveResource.h"
-#include "platform/mhtml/MHTMLArchive.h"
-#include "platform/network/NetworkInstrumentation.h"
-#include "platform/network/NetworkUtils.h"
-#include "platform/network/ResourceTimingInfo.h"
-#include "platform/weborigin/KnownPorts.h"
-#include "platform/weborigin/SecurityOrigin.h"
-#include "platform/weborigin/SecurityPolicy.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebCachePolicy.h"
-#include "public/platform/WebURL.h"
-#include "public/platform/WebURLRequest.h"
-#include "wtf/text/CString.h"
-#include "wtf/text/WTFString.h"
-#include <memory>
-
-using blink::WebURLRequest;
-
-namespace blink {
-
-namespace {
-
-// Events for UMA. Do not reorder or delete. Add new events at the end, but
-// before SriResourceIntegrityMismatchEventCount.
-enum SriResourceIntegrityMismatchEvent {
- CheckingForIntegrityMismatch = 0,
- RefetchDueToIntegrityMismatch = 1,
- SriResourceIntegrityMismatchEventCount
-};
-
-#define DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, name) \
- case Resource::name: { \
- DEFINE_THREAD_SAFE_STATIC_LOCAL( \
- EnumerationHistogram, resourceHistogram, \
- new EnumerationHistogram( \
- "Blink.MemoryCache.RevalidationPolicy." prefix #name, Load + 1)); \
- resourceHistogram.count(policy); \
- break; \
- }
-
-#define DEFINE_RESOURCE_HISTOGRAM(prefix) \
- switch (factory.type()) { \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, CSSStyleSheet) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Font) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Image) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, ImportResource) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, LinkPrefetch) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, MainResource) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Manifest) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Media) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Mock) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Raw) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Script) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, SVGDocument) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack) \
- DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet) \
- }
-
-void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) {
- // Store redirect responses that were packed inside the final response.
- const auto& responses = resource->response().redirectResponses();
- for (size_t i = 0; i < responses.size(); ++i) {
- const KURL& newURL = i + 1 < responses.size()
- ? KURL(responses[i + 1].url())
- : resource->resourceRequest().url();
- bool crossOrigin =
- !SecurityOrigin::areSameSchemeHostPort(responses[i].url(), newURL);
- info->addRedirect(responses[i], crossOrigin);
- }
-}
-
-void RecordSriResourceIntegrityMismatchEvent(
- SriResourceIntegrityMismatchEvent event) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- EnumerationHistogram, integrityHistogram,
- new EnumerationHistogram("sri.resource_integrity_mismatch_event",
- SriResourceIntegrityMismatchEventCount));
- integrityHistogram.count(event);
-}
-
-ResourceLoadPriority typeToPriority(Resource::Type type) {
- switch (type) {
- case Resource::MainResource:
- case Resource::CSSStyleSheet:
- case Resource::Font:
- // Also parser-blocking scripts (set explicitly in loadPriority)
- return ResourceLoadPriorityVeryHigh;
- case Resource::XSLStyleSheet:
- DCHECK(RuntimeEnabledFeatures::xsltEnabled());
- case Resource::Raw:
- case Resource::ImportResource:
- case Resource::Script:
- // Also visible resources/images (set explicitly in loadPriority)
- return ResourceLoadPriorityHigh;
- case Resource::Manifest:
- case Resource::Mock:
- // Also late-body scripts discovered by the preload scanner (set
- // explicitly in loadPriority)
- return ResourceLoadPriorityMedium;
- case Resource::Image:
- case Resource::TextTrack:
- case Resource::Media:
- case Resource::SVGDocument:
- // Also async scripts (set explicitly in loadPriority)
- return ResourceLoadPriorityLow;
- case Resource::LinkPrefetch:
- return ResourceLoadPriorityVeryLow;
- }
-
- NOTREACHED();
- return ResourceLoadPriorityUnresolved;
-}
-
-} // namespace
-
-ResourceLoadPriority ResourceFetcher::computeLoadPriority(
- Resource::Type type,
- const FetchRequest& request,
- ResourcePriority::VisibilityStatus visibility) {
- ResourceLoadPriority priority = typeToPriority(type);
-
- // Visible resources (images in practice) get a boost to High priority.
- if (visibility == ResourcePriority::Visible)
- priority = ResourceLoadPriorityHigh;
-
- // Resources before the first image are considered "early" in the document and
- // resources after the first image are "late" in the document. Important to
- // note that this is based on when the preload scanner discovers a resource
- // for the most part so the main parser may not have reached the image element
- // yet.
- if (type == Resource::Image)
- m_imageFetched = true;
-
- if (FetchRequest::IdleLoad == request.defer()) {
- priority = ResourceLoadPriorityVeryLow;
- } else if (type == Resource::Script) {
- // Special handling for scripts.
- // Default/Parser-Blocking/Preload early in document: High (set in
- // typeToPriority)
- // Async/Defer: Low Priority (applies to both preload and parser-inserted)
- // Preload late in document: Medium
- if (FetchRequest::LazyLoad == request.defer())
- priority = ResourceLoadPriorityLow;
- else if (request.forPreload() && m_imageFetched)
- priority = ResourceLoadPriorityMedium;
- } else if (FetchRequest::LazyLoad == request.defer()) {
- priority = ResourceLoadPriorityVeryLow;
- }
-
- // A manually set priority acts as a floor. This is used to ensure that
- // synchronous requests are always given the highest possible priority, as
- // well as to ensure that there isn't priority churn if images move in and out
- // of the viewport, or is displayed more than once, both in and out of the
- // viewport.
- return std::max(context().modifyPriorityForExperiments(priority),
- request.resourceRequest().priority());
-}
-
-static void populateTimingInfo(ResourceTimingInfo* info,
- Resource* resource) {
- KURL initialURL = resource->response().redirectResponses().isEmpty()
- ? resource->resourceRequest().url()
- : resource->response().redirectResponses()[0].url();
- info->setInitialURL(initialURL);
- info->setFinalResponse(resource->response());
-}
-
-static WebURLRequest::RequestContext requestContextFromType(
- bool isMainFrame,
- Resource::Type type) {
- switch (type) {
- case Resource::MainResource:
- if (!isMainFrame)
- return WebURLRequest::RequestContextIframe;
- // FIXME: Change this to a context frame type (once we introduce them):
- // http://fetch.spec.whatwg.org/#concept-request-context-frame-type
- return WebURLRequest::RequestContextHyperlink;
- case Resource::XSLStyleSheet:
- DCHECK(RuntimeEnabledFeatures::xsltEnabled());
- case Resource::CSSStyleSheet:
- return WebURLRequest::RequestContextStyle;
- case Resource::Script:
- return WebURLRequest::RequestContextScript;
- case Resource::Font:
- return WebURLRequest::RequestContextFont;
- case Resource::Image:
- return WebURLRequest::RequestContextImage;
- case Resource::Raw:
- return WebURLRequest::RequestContextSubresource;
- case Resource::ImportResource:
- return WebURLRequest::RequestContextImport;
- case Resource::LinkPrefetch:
- return WebURLRequest::RequestContextPrefetch;
- case Resource::TextTrack:
- return WebURLRequest::RequestContextTrack;
- case Resource::SVGDocument:
- return WebURLRequest::RequestContextImage;
- case Resource::Media: // TODO: Split this.
- return WebURLRequest::RequestContextVideo;
- case Resource::Manifest:
- return WebURLRequest::RequestContextManifest;
- case Resource::Mock:
- return WebURLRequest::RequestContextSubresource;
- }
- NOTREACHED();
- return WebURLRequest::RequestContextSubresource;
-}
-
-ResourceFetcher::ResourceFetcher(FetchContext* newContext)
- : m_context(newContext),
- m_archive(context().isMainFrame() ? nullptr : context().archive()),
- // loadingTaskRunner() is null in tests that use the null fetch context.
- m_resourceTimingReportTimer(
- context().loadingTaskRunner()
- ? context().loadingTaskRunner()
- : Platform::current()->currentThread()->getWebTaskRunner(),
- this,
- &ResourceFetcher::resourceTimingReportTimerFired),
- m_autoLoadImages(true),
- m_imagesEnabled(true),
- m_allowStaleResources(false),
- m_imageFetched(false) {}
-
-ResourceFetcher::~ResourceFetcher() {}
-
-Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const {
- KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL);
- const WeakMember<Resource>& resource = m_documentResources.get(url);
- return resource.get();
-}
-
-bool ResourceFetcher::isControlledByServiceWorker() const {
- return context().isControlledByServiceWorker();
-}
-
-bool ResourceFetcher::resourceNeedsLoad(Resource* resource,
- const FetchRequest& request,
- RevalidationPolicy policy) {
- // Defer a font load until it is actually needed unless this is a preload.
- if (resource->getType() == Resource::Font && !request.forPreload())
- return false;
- if (resource->isImage() && shouldDeferImageLoad(resource->url()))
- return false;
- return policy != Use || resource->stillNeedsLoad();
-}
-
-// Limit the number of URLs in m_validatedURLs to avoid memory bloat.
-// http://crbug.com/52411
-static const int kMaxValidatedURLsSize = 10000;
-
-void ResourceFetcher::requestLoadStarted(unsigned long identifier,
- Resource* resource,
- const FetchRequest& request,
- ResourceLoadStartType type,
- bool isStaticData) {
- if (type == ResourceLoadingFromCache &&
- resource->getStatus() == Resource::Cached &&
- !m_validatedURLs.contains(resource->url())) {
- context().dispatchDidLoadResourceFromMemoryCache(
- identifier, resource, request.resourceRequest().frameType(),
- request.resourceRequest().requestContext());
- }
-
- if (isStaticData)
- return;
-
- if (type == ResourceLoadingFromCache && !resource->stillNeedsLoad() &&
- !m_validatedURLs.contains(request.resourceRequest().url())) {
- // Resources loaded from memory cache should be reported the first time
- // they're used.
- std::unique_ptr<ResourceTimingInfo> info = ResourceTimingInfo::create(
- request.options().initiatorInfo.name, monotonicallyIncreasingTime(),
- resource->getType() == Resource::MainResource);
- populateTimingInfo(info.get(), resource);
- info->clearLoadTimings();
- info->setLoadFinishTime(info->initialTime());
- m_scheduledResourceTimingReports.push_back(std::move(info));
- if (!m_resourceTimingReportTimer.isActive())
- m_resourceTimingReportTimer.startOneShot(0, BLINK_FROM_HERE);
- }
-
- if (m_validatedURLs.size() >= kMaxValidatedURLsSize) {
- m_validatedURLs.clear();
- }
- m_validatedURLs.add(request.resourceRequest().url());
-}
-
-static std::unique_ptr<TracedValue> urlForTraceEvent(const KURL& url) {
- std::unique_ptr<TracedValue> value = TracedValue::create();
- value->setString("url", url.getString());
- return value;
-}
-
-Resource* ResourceFetcher::resourceForStaticData(
- const FetchRequest& request,
- const ResourceFactory& factory,
- const SubstituteData& substituteData) {
- const KURL& url = request.resourceRequest().url();
- DCHECK(url.protocolIsData() || substituteData.isValid() || m_archive);
-
- // TODO(japhet): We only send main resource data: urls through WebURLLoader
- // for the benefit of a service worker test
- // (RenderViewImplTest.ServiceWorkerNetworkProviderSetup), which is at a layer
- // where it isn't easy to mock out a network load. It uses data: urls to
- // emulate the behavior it wants to test, which would otherwise be reserved
- // for network loads.
- if (!m_archive && !substituteData.isValid() &&
- (factory.type() == Resource::MainResource ||
- factory.type() == Resource::Raw))
- return nullptr;
-
- const String cacheIdentifier = getCacheIdentifier();
- if (Resource* oldResource =
- memoryCache()->resourceForURL(url, cacheIdentifier)) {
- // There's no reason to re-parse if we saved the data from the previous
- // parse.
- if (request.options().dataBufferingPolicy != DoNotBufferData)
- return oldResource;
- memoryCache()->remove(oldResource);
- }
-
- AtomicString mimetype;
- AtomicString charset;
- RefPtr<SharedBuffer> data;
- if (substituteData.isValid()) {
- mimetype = substituteData.mimeType();
- charset = substituteData.textEncoding();
- data = substituteData.content();
- } else if (url.protocolIsData()) {
- data = PassRefPtr<SharedBuffer>(
- NetworkUtils::parseDataURL(url, mimetype, charset));
- if (!data)
- return nullptr;
- } else {
- ArchiveResource* archiveResource =
- m_archive->subresourceForURL(request.url());
- // Fall back to the network if the archive doesn't contain the resource.
- if (!archiveResource)
- return nullptr;
- mimetype = archiveResource->mimeType();
- charset = archiveResource->textEncoding();
- data = archiveResource->data();
- }
-
- ResourceResponse response(url, mimetype, data->size(), charset, String());
- response.setHTTPStatusCode(200);
- response.setHTTPStatusText("OK");
-
- Resource* resource = factory.create(request.resourceRequest(),
- request.options(), request.charset());
- resource->setNeedsSynchronousCacheHit(substituteData.forceSynchronousLoad());
- // FIXME: We should provide a body stream here.
- resource->responseReceived(response, nullptr);
- resource->setDataBufferingPolicy(BufferData);
- if (data->size())
- resource->setResourceBuffer(data);
- resource->setIdentifier(createUniqueIdentifier());
- resource->setCacheIdentifier(cacheIdentifier);
- resource->finish();
-
- if (!substituteData.isValid())
- memoryCache()->add(resource);
-
- return resource;
-}
-
-Resource* ResourceFetcher::resourceForBlockedRequest(
- const FetchRequest& request,
- const ResourceFactory& factory,
- ResourceRequestBlockedReason blockedReason) {
- Resource* resource = factory.create(request.resourceRequest(),
- request.options(), request.charset());
- resource->error(ResourceError::cancelledDueToAccessCheckError(request.url(),
- blockedReason));
- return resource;
-}
-
-void ResourceFetcher::moveCachedNonBlockingResourceToBlocking(
- Resource* resource,
- const FetchRequest& request) {
- // TODO(yoav): Test that non-blocking resources (video/audio/track) continue
- // to not-block even after being preloaded and discovered.
- if (resource && resource->loader() &&
- resource->isLoadEventBlockingResourceType() &&
- m_nonBlockingLoaders.contains(resource->loader()) &&
- resource->isLinkPreload() && !request.forPreload()) {
- m_nonBlockingLoaders.remove(resource->loader());
- m_loaders.add(resource->loader());
- }
-}
-
-void ResourceFetcher::updateMemoryCacheStats(Resource* resource,
- RevalidationPolicy policy,
- const FetchRequest& request,
- const ResourceFactory& factory,
- bool isStaticData) const {
- if (isStaticData)
- return;
-
- if (request.forPreload()) {
- DEFINE_RESOURCE_HISTOGRAM("Preload.");
- } else {
- DEFINE_RESOURCE_HISTOGRAM("");
- }
-
- // Aims to count Resource only referenced from MemoryCache (i.e. what would be
- // dead if MemoryCache holds weak references to Resource). Currently we check
- // references to Resource from ResourceClient and |m_preloads| only, because
- // they are major sources of references.
- if (resource && !resource->isAlive() &&
- (!m_preloads || !m_preloads->contains(resource))) {
- DEFINE_RESOURCE_HISTOGRAM("Dead.");
- }
-}
-
-Resource* ResourceFetcher::requestResource(
- FetchRequest& request,
- const ResourceFactory& factory,
- const SubstituteData& substituteData) {
- ResourceRequest& resourceRequest = request.mutableResourceRequest();
-
- unsigned long identifier = createUniqueIdentifier();
- network_instrumentation::ScopedResourceLoadTracker scopedResourceLoadTracker(
- identifier, resourceRequest);
- SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Fetch.RequestResourceTime");
- DCHECK(request.options().synchronousPolicy == RequestAsynchronously ||
- factory.type() == Resource::Raw ||
- factory.type() == Resource::XSLStyleSheet);
-
- context().populateResourceRequest(
- factory.type(), request.clientHintsPreferences(),
- request.getResourceWidth(), resourceRequest);
-
- // TODO(dproy): Remove this. http://crbug.com/659666
- TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url",
- urlForTraceEvent(request.url()));
-
- if (!request.url().isValid())
- return nullptr;
-
- resourceRequest.setPriority(computeLoadPriority(
- factory.type(), request, ResourcePriority::NotVisible));
- initializeResourceRequest(resourceRequest, factory.type(), request.defer());
- network_instrumentation::resourcePrioritySet(identifier,
- resourceRequest.priority());
-
- ResourceRequestBlockedReason blockedReason = context().canRequest(
- factory.type(), resourceRequest,
- MemoryCache::removeFragmentIdentifierIfNeeded(request.url()),
- request.options(), request.forPreload(), request.getOriginRestriction());
- if (blockedReason != ResourceRequestBlockedReason::None) {
- DCHECK(!substituteData.forceSynchronousLoad());
- return resourceForBlockedRequest(request, factory, blockedReason);
- }
-
- context().willStartLoadingResource(
- identifier, resourceRequest, factory.type(),
- request.options().initiatorInfo.name, request.forPreload());
- if (!request.url().isValid())
- return nullptr;
-
- bool isDataUrl = resourceRequest.url().protocolIsData();
- bool isStaticData = isDataUrl || substituteData.isValid() || m_archive;
- Resource* resource(nullptr);
- if (isStaticData) {
- resource = resourceForStaticData(request, factory, substituteData);
- // Abort the request if the archive doesn't contain the resource, except in
- // the case of data URLs which might have resources such as fonts that need
- // to be decoded only on demand. These data URLs are allowed to be
- // processed using the normal ResourceFetcher machinery.
- if (!resource && !isDataUrl && m_archive)
- return nullptr;
- }
- if (!resource) {
- resource =
- memoryCache()->resourceForURL(request.url(), getCacheIdentifier());
- }
-
- // See if we can use an existing resource from the cache. If so, we need to
- // move it to be load blocking.
- moveCachedNonBlockingResourceToBlocking(resource, request);
-
- const RevalidationPolicy policy = determineRevalidationPolicy(
- factory.type(), request, resource, isStaticData);
- TRACE_EVENT_INSTANT1("blink", "ResourceFetcher::determineRevalidationPolicy",
- TRACE_EVENT_SCOPE_THREAD, "revalidationPolicy", policy);
-
- updateMemoryCacheStats(resource, policy, request, factory, isStaticData);
-
- resourceRequest.setAllowStoredCredentials(
- request.options().allowCredentials == AllowStoredCredentials);
-
- switch (policy) {
- case Reload:
- memoryCache()->remove(resource);
- // Fall through
- case Load:
- resource = createResourceForLoading(request, request.charset(), factory);
- break;
- case Revalidate:
- initializeRevalidation(resourceRequest, resource);
- break;
- case Use:
- if (resource->isLinkPreload() && !request.isLinkPreload())
- resource->setLinkPreload(false);
- break;
- }
- if (!resource)
- return nullptr;
- if (resource->getType() != factory.type()) {
- DCHECK(request.forPreload());
- return nullptr;
- }
-
- if (!resource->isAlive())
- m_deadStatsRecorder.update(policy);
-
- if (policy != Use)
- resource->setIdentifier(identifier);
-
- if (!request.forPreload() || policy != Use) {
- // When issuing another request for a resource that is already in-flight
- // make sure to not demote the priority of the in-flight request. If the new
- // request isn't at the same priority as the in-flight request, only allow
- // promotions. This can happen when a visible image's priority is increased
- // and then another reference to the image is parsed (which would be at a
- // lower priority).
- if (resourceRequest.priority() > resource->resourceRequest().priority())
- resource->didChangePriority(resourceRequest.priority(), 0);
- }
-
- // If only the fragment identifiers differ, it is the same resource.
- DCHECK(equalIgnoringFragmentIdentifier(resource->url(), request.url()));
- requestLoadStarted(
- identifier, resource, request,
- policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork,
- isStaticData);
- m_documentResources.set(
- MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), resource);
-
- // Returns with an existing resource if the resource does not need to start
- // loading immediately. If revalidation policy was determined as |Revalidate|,
- // the resource was already initialized for the revalidation here, but won't
- // start loading.
- if (!resourceNeedsLoad(resource, request, policy))
- return resource;
-
- if (!startLoad(resource))
- return nullptr;
- scopedResourceLoadTracker.resourceLoadContinuesBeyondScope();
-
- DCHECK(!resource->errorOccurred() ||
- request.options().synchronousPolicy == RequestSynchronously);
- return resource;
-}
-
-void ResourceFetcher::resourceTimingReportTimerFired(TimerBase* timer) {
- DCHECK_EQ(timer, &m_resourceTimingReportTimer);
- Vector<std::unique_ptr<ResourceTimingInfo>> timingReports;
- timingReports.swap(m_scheduledResourceTimingReports);
- for (const auto& timingInfo : timingReports)
- context().addResourceTiming(*timingInfo);
-}
-
-void ResourceFetcher::determineRequestContext(ResourceRequest& request,
- Resource::Type type,
- bool isMainFrame) {
- WebURLRequest::RequestContext requestContext =
- requestContextFromType(isMainFrame, type);
- request.setRequestContext(requestContext);
-}
-
-void ResourceFetcher::determineRequestContext(ResourceRequest& request,
- Resource::Type type) {
- determineRequestContext(request, type, context().isMainFrame());
-}
-
-void ResourceFetcher::initializeResourceRequest(
- ResourceRequest& request,
- Resource::Type type,
- FetchRequest::DeferOption defer) {
- if (request.getCachePolicy() == WebCachePolicy::UseProtocolCachePolicy) {
- request.setCachePolicy(
- context().resourceRequestCachePolicy(request, type, defer));
- }
- if (request.requestContext() == WebURLRequest::RequestContextUnspecified)
- determineRequestContext(request, type);
- if (type == Resource::LinkPrefetch)
- request.setHTTPHeaderField(HTTPNames::Purpose, "prefetch");
-
- context().addAdditionalRequestHeaders(
- request,
- (type == Resource::MainResource) ? FetchMainResource : FetchSubresource);
-}
-
-void ResourceFetcher::initializeRevalidation(
- ResourceRequest& revalidatingRequest,
- Resource* resource) {
- DCHECK(resource);
- DCHECK(memoryCache()->contains(resource));
- DCHECK(resource->isLoaded());
- DCHECK(resource->canUseCacheValidator());
- DCHECK(!resource->isCacheValidator());
- DCHECK(!context().isControlledByServiceWorker());
-
- const AtomicString& lastModified =
- resource->response().httpHeaderField(HTTPNames::Last_Modified);
- const AtomicString& eTag =
- resource->response().httpHeaderField(HTTPNames::ETag);
- if (!lastModified.isEmpty() || !eTag.isEmpty()) {
- DCHECK_NE(context().getCachePolicy(), CachePolicyReload);
- if (context().getCachePolicy() == CachePolicyRevalidate) {
- revalidatingRequest.setHTTPHeaderField(HTTPNames::Cache_Control,
- "max-age=0");
- }
- }
- if (!lastModified.isEmpty()) {
- revalidatingRequest.setHTTPHeaderField(HTTPNames::If_Modified_Since,
- lastModified);
- }
- if (!eTag.isEmpty())
- revalidatingRequest.setHTTPHeaderField(HTTPNames::If_None_Match, eTag);
-
- double stalenessLifetime = resource->stalenessLifetime();
- if (std::isfinite(stalenessLifetime) && stalenessLifetime > 0) {
- revalidatingRequest.setHTTPHeaderField(
- HTTPNames::Resource_Freshness,
- AtomicString(String::format(
- "max-age=%.0lf,stale-while-revalidate=%.0lf,age=%.0lf",
- resource->freshnessLifetime(), stalenessLifetime,
- resource->currentAge())));
- }
-
- resource->setRevalidatingRequest(revalidatingRequest);
-}
-
-Resource* ResourceFetcher::createResourceForLoading(
- FetchRequest& request,
- const String& charset,
- const ResourceFactory& factory) {
- const String cacheIdentifier = getCacheIdentifier();
- DCHECK(!memoryCache()->resourceForURL(request.resourceRequest().url(),
- cacheIdentifier));
-
- RESOURCE_LOADING_DVLOG(1) << "Loading Resource for "
- << request.resourceRequest().url().elidedString();
-
- Resource* resource =
- factory.create(request.resourceRequest(), request.options(), charset);
- resource->setLinkPreload(request.isLinkPreload());
- if (request.forPreload()) {
- resource->setPreloadDiscoveryTime(request.preloadDiscoveryTime());
- }
- resource->setCacheIdentifier(cacheIdentifier);
-
- // - Don't add main resource to cache to prevent reuse.
- // - Don't add the resource if its body will not be stored.
- if (factory.type() != Resource::MainResource &&
- request.options().dataBufferingPolicy != DoNotBufferData) {
- memoryCache()->add(resource);
- }
- return resource;
-}
-
-void ResourceFetcher::storePerformanceTimingInitiatorInformation(
- Resource* resource) {
- const AtomicString& fetchInitiator = resource->options().initiatorInfo.name;
- if (fetchInitiator == FetchInitiatorTypeNames::internal)
- return;
-
- bool isMainResource = resource->getType() == Resource::MainResource;
-
- // The request can already be fetched in a previous navigation. Thus
- // startTime must be set accordingly.
- double startTime = resource->resourceRequest().navigationStartTime()
- ? resource->resourceRequest().navigationStartTime()
- : monotonicallyIncreasingTime();
-
- // This buffer is created and populated for providing transferSize
- // and redirect timing opt-in information.
- if (isMainResource) {
- DCHECK(!m_navigationTimingInfo);
- m_navigationTimingInfo =
- ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
- }
-
- std::unique_ptr<ResourceTimingInfo> info =
- ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource);
-
- if (resource->isCacheValidator()) {
- const AtomicString& timingAllowOrigin =
- resource->response().httpHeaderField(HTTPNames::Timing_Allow_Origin);
- if (!timingAllowOrigin.isEmpty())
- info->setOriginalTimingAllowOrigin(timingAllowOrigin);
- }
-
- if (!isMainResource ||
- context().updateTimingInfoForIFrameNavigation(info.get())) {
- m_resourceTimingInfoMap.add(resource, std::move(info));
- }
-}
-
-void ResourceFetcher::recordResourceTimingOnRedirect(
- Resource* resource,
- const ResourceResponse& redirectResponse,
- bool crossOrigin) {
- ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
- if (it != m_resourceTimingInfoMap.end()) {
- it->value->addRedirect(redirectResponse, crossOrigin);
- }
-
- if (resource->getType() == Resource::MainResource) {
- DCHECK(m_navigationTimingInfo);
- m_navigationTimingInfo->addRedirect(redirectResponse, crossOrigin);
- }
-}
-
-ResourceFetcher::RevalidationPolicy
-ResourceFetcher::determineRevalidationPolicy(Resource::Type type,
- const FetchRequest& fetchRequest,
- Resource* existingResource,
- bool isStaticData) const {
- const ResourceRequest& request = fetchRequest.resourceRequest();
-
- if (!existingResource)
- return Load;
-
- // Checks if the resource has an explicit policy about integrity metadata.
- //
- // This is necessary because ScriptResource and CSSStyleSheetResource objects
- // do not keep the raw data around after the source is accessed once, so if
- // the resource is accessed from the MemoryCache for a second time, there is
- // no way to redo an integrity check.
- //
- // Thus, Blink implements a scheme where it caches the integrity information
- // for those resources after the first time it is checked, and if there is
- // another request for that resource, with the same integrity metadata, Blink
- // skips the integrity calculation. However, if the integrity metadata is a
- // mismatch, the MemoryCache must be skipped here, and a new request for the
- // resource must be made to get the raw data. This is expected to be an
- // uncommon case, however, as it implies two same-origin requests to the same
- // resource, but with different integrity metadata.
- RecordSriResourceIntegrityMismatchEvent(CheckingForIntegrityMismatch);
- if (existingResource->mustRefetchDueToIntegrityMetadata(fetchRequest)) {
- RecordSriResourceIntegrityMismatchEvent(RefetchDueToIntegrityMismatch);
- return Reload;
- }
-
- // Service Worker's CORS fallback message must not be cached.
- if (existingResource->response().wasFallbackRequiredByServiceWorker())
- return Reload;
-
- // We already have a preload going for this URL.
- if (fetchRequest.forPreload() && existingResource->isPreloaded())
- return Use;
-
- // If the same URL has been loaded as a different type, we need to reload.
- if (existingResource->getType() != type) {
- // FIXME: If existingResource is a Preload and the new type is LinkPrefetch
- // We really should discard the new prefetch since the preload has more
- // specific type information! crbug.com/379893
- // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case.
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to type mismatch.";
- return Reload;
- }
-
- // Do not load from cache if images are not enabled. There are two general
- // cases:
- //
- // 1. Images are disabled. Don't ever load images, even if the image is cached
- // or it is a data: url. In this case, we "Reload" the image, then defer it
- // with resourceNeedsLoad() so that it never actually goes to the network.
- //
- // 2. Images are enabled, but not loaded automatically. In this case, we will
- // Use cached resources or data: urls, but will similarly fall back to a
- // deferred network load if we don't have the data available without a network
- // request. We check allowImage() here, which is affected by m_imagesEnabled
- // but not m_autoLoadImages, in order to allow for this differing behavior.
- //
- // TODO(japhet): Can we get rid of one of these settings?
- if (existingResource->isImage() &&
- !context().allowImage(m_imagesEnabled, existingResource->url()))
- return Reload;
-
- // Never use cache entries for downloadToFile / useStreamOnResponse requests.
- // The data will be delivered through other paths.
- if (request.downloadToFile() || request.useStreamOnResponse())
- return Reload;
-
- // Never reuse opaque responses from a service worker for requests that are
- // not no-cors. https://crbug.com/625575
- if (existingResource->response().wasFetchedViaServiceWorker() &&
- existingResource->response().serviceWorkerResponseType() ==
- WebServiceWorkerResponseTypeOpaque &&
- request.fetchRequestMode() != WebURLRequest::FetchRequestModeNoCORS)
- return Reload;
-
- // If resource was populated from a SubstituteData load or data: url, use it.
- if (isStaticData)
- return Use;
-
- if (!existingResource->canReuse(request))
- return Reload;
-
- // Certain requests (e.g., XHRs) might have manually set headers that require
- // revalidation. In theory, this should be a Revalidate case. In practice, the
- // MemoryCache revalidation path assumes a whole bunch of things about how
- // revalidation works that manual headers violate, so punt to Reload instead.
- //
- // Similarly, a request with manually added revalidation headers can lead to a
- // 304 response for a request that wasn't flagged as a revalidation attempt.
- // Normally, successful revalidation will maintain the original response's
- // status code, but for a manual revalidation the response code remains 304.
- // In this case, the Resource likely has insufficient context to provide a
- // useful cache hit or revalidation. See http://crbug.com/643659
- if (request.isConditional() ||
- existingResource->response().httpStatusCode() == 304)
- return Reload;
-
- // Don't reload resources while pasting.
- if (m_allowStaleResources)
- return Use;
-
- if (!fetchRequest.options().canReuseRequest(existingResource->options()))
- return Reload;
-
- // Always use preloads.
- if (existingResource->isPreloaded())
- return Use;
-
- // CachePolicyHistoryBuffer uses the cache no matter what.
- CachePolicy cachePolicy = context().getCachePolicy();
- if (cachePolicy == CachePolicyHistoryBuffer)
- return Use;
-
- // Don't reuse resources with Cache-control: no-store.
- if (existingResource->hasCacheControlNoStoreHeader()) {
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to Cache-control: no-store.";
- return Reload;
- }
-
- // If credentials were sent with the previous request and won't be with this
- // one, or vice versa, re-fetch the resource.
- //
- // This helps with the case where the server sends back
- // "Access-Control-Allow-Origin: *" all the time, but some of the client's
- // requests are made without CORS and some with.
- if (existingResource->resourceRequest().allowStoredCredentials() !=
- request.allowStoredCredentials()) {
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to difference in credentials "
- "settings.";
- return Reload;
- }
-
- // During the initial load, avoid loading the same resource multiple times for
- // a single document, even if the cache policies would tell us to. We also
- // group loads of the same resource together. Raw resources are exempted, as
- // XHRs fall into this category and may have user-set Cache-Control: headers
- // or other factors that require separate requests.
- if (type != Resource::Raw) {
- if (!context().isLoadComplete() &&
- m_validatedURLs.contains(existingResource->url()))
- return Use;
- if (existingResource->isLoading())
- return Use;
- }
-
- if (request.getCachePolicy() == WebCachePolicy::BypassingCache)
- return Reload;
-
- // CachePolicyReload always reloads
- if (cachePolicy == CachePolicyReload) {
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to CachePolicyReload.";
- return Reload;
- }
-
- // We'll try to reload the resource if it failed last time.
- if (existingResource->errorOccurred()) {
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::"
- "determineRevalidationPolicye reloading due "
- "to resource being in the error state";
- return Reload;
- }
-
- // List of available images logic allows images to be re-used without cache
- // validation. We restrict this only to images from memory cache which are the
- // same as the version in the current document.
- if (type == Resource::Image &&
- existingResource == cachedResource(request.url()))
- return Use;
-
- // Defer to the browser process cache for Vary header handling.
- if (existingResource->hasVaryHeader())
- return Reload;
-
- // If any of the redirects in the chain to loading the resource were not
- // cacheable, we cannot reuse our cached resource.
- if (!existingResource->canReuseRedirectChain()) {
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to an uncacheable redirect";
- return Reload;
- }
-
- // Check if the cache headers requires us to revalidate (cache expiration for
- // example).
- if (cachePolicy == CachePolicyRevalidate ||
- existingResource->mustRevalidateDueToCacheHeaders() ||
- request.cacheControlContainsNoCache()) {
- // See if the resource has usable ETag or Last-modified headers. If the page
- // is controlled by the ServiceWorker, we choose the Reload policy because
- // the revalidation headers should not be exposed to the
- // ServiceWorker.(crbug.com/429570)
- if (existingResource->canUseCacheValidator() &&
- !context().isControlledByServiceWorker()) {
- // If the resource is already a cache validator but not started yet, the
- // |Use| policy should be applied to subsequent requests.
- if (existingResource->isCacheValidator()) {
- DCHECK(existingResource->stillNeedsLoad());
- return Use;
- }
- return Revalidate;
- }
-
- // No, must reload.
- RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
- "reloading due to missing cache validators.";
- return Reload;
- }
-
- return Use;
-}
-
-void ResourceFetcher::setAutoLoadImages(bool enable) {
- if (enable == m_autoLoadImages)
- return;
-
- m_autoLoadImages = enable;
-
- if (!m_autoLoadImages)
- return;
-
- reloadImagesIfNotDeferred();
-}
-
-void ResourceFetcher::setImagesEnabled(bool enable) {
- if (enable == m_imagesEnabled)
- return;
-
- m_imagesEnabled = enable;
-
- if (!m_imagesEnabled)
- return;
-
- reloadImagesIfNotDeferred();
-}
-
-bool ResourceFetcher::shouldDeferImageLoad(const KURL& url) const {
- return !context().allowImage(m_imagesEnabled, url) || !m_autoLoadImages;
-}
-
-void ResourceFetcher::reloadImagesIfNotDeferred() {
- for (Resource* resource : m_documentResources.values()) {
- if (resource->getType() == Resource::Image && resource->stillNeedsLoad() &&
- !shouldDeferImageLoad(resource->url()))
- startLoad(resource);
- }
-}
-
-void ResourceFetcher::clearContext() {
- clearPreloads(ResourceFetcher::ClearAllPreloads);
- m_context.clear();
-}
-
-int ResourceFetcher::requestCount() const {
- return m_loaders.size();
-}
-
-bool ResourceFetcher::hasPendingRequest() const {
- return m_loaders.size() > 0 || m_nonBlockingLoaders.size() > 0;
-}
-
-void ResourceFetcher::preloadStarted(Resource* resource) {
- if (m_preloads && m_preloads->contains(resource))
- return;
- resource->increasePreloadCount();
-
- if (!m_preloads)
- m_preloads = new HeapListHashSet<Member<Resource>>;
- m_preloads->add(resource);
-
- if (m_preloadedURLsForTest)
- m_preloadedURLsForTest->add(resource->url().getString());
-}
-
-void ResourceFetcher::enableIsPreloadedForTest() {
- if (m_preloadedURLsForTest)
- return;
- m_preloadedURLsForTest = WTF::wrapUnique(new HashSet<String>);
-
- if (m_preloads) {
- for (const auto& resource : *m_preloads)
- m_preloadedURLsForTest->add(resource->url().getString());
- }
-}
-
-bool ResourceFetcher::isPreloadedForTest(const KURL& url) const {
- DCHECK(m_preloadedURLsForTest);
- return m_preloadedURLsForTest->contains(url.getString());
-}
-
-void ResourceFetcher::clearPreloads(ClearPreloadsPolicy policy) {
- if (!m_preloads)
- return;
-
- logPreloadStats(policy);
-
- for (const auto& resource : *m_preloads) {
- if (policy == ClearAllPreloads || !resource->isLinkPreload()) {
- resource->decreasePreloadCount();
- if (resource->getPreloadResult() == Resource::PreloadNotReferenced)
- memoryCache()->remove(resource.get());
- m_preloads->remove(resource);
- }
- }
- if (!m_preloads->size())
- m_preloads.clear();
-}
-
-void ResourceFetcher::warnUnusedPreloads() {
- if (!m_preloads)
- return;
- for (const auto& resource : *m_preloads) {
- if (resource && resource->isLinkPreload() &&
- resource->getPreloadResult() == Resource::PreloadNotReferenced) {
- context().addConsoleMessage(
- "The resource " + resource->url().getString() +
- " was preloaded using link preload but not used within a few "
- "seconds from the window's load event. Please make sure it "
- "wasn't preloaded for nothing.",
- FetchContext::LogWarningMessage);
- }
- }
-}
-
-ArchiveResource* ResourceFetcher::createArchive(Resource* resource) {
- // Only the top-frame can load MHTML.
- if (!context().isMainFrame())
- return nullptr;
- m_archive = MHTMLArchive::create(resource->url(), resource->resourceBuffer());
- return m_archive ? m_archive->mainResource() : nullptr;
-}
-
-ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() {
- return m_navigationTimingInfo.get();
-}
-
-void ResourceFetcher::handleLoadCompletion(Resource* resource) {
- context().didLoadResource(resource);
-
- resource->reloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
-}
-
-void ResourceFetcher::handleLoaderFinish(Resource* resource,
- double finishTime,
- LoaderFinishType type) {
- DCHECK(resource);
-
- ResourceLoader* loader = resource->loader();
- if (type == DidFinishFirstPartInMultipart) {
- // When loading a multipart resource, make the loader non-block when
- // finishing loading the first part.
- moveResourceLoaderToNonBlocking(loader);
- } else {
- removeResourceLoader(loader);
- DCHECK(!m_nonBlockingLoaders.contains(loader));
- }
- DCHECK(!m_loaders.contains(loader));
-
- const int64_t encodedDataLength = resource->response().encodedDataLength();
-
- if (resource->getType() == Resource::MainResource) {
- DCHECK(m_navigationTimingInfo);
- // Store redirect responses that were packed inside the final response.
- addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get());
- if (resource->response().isHTTP()) {
- populateTimingInfo(m_navigationTimingInfo.get(), resource);
- m_navigationTimingInfo->addFinalTransferSize(
- encodedDataLength == -1 ? 0 : encodedDataLength);
- }
- }
- if (std::unique_ptr<ResourceTimingInfo> info =
- m_resourceTimingInfoMap.take(resource)) {
- // Store redirect responses that were packed inside the final response.
- addRedirectsToTimingInfo(resource, info.get());
-
- if (resource->response().isHTTP() &&
- resource->response().httpStatusCode() < 400) {
- populateTimingInfo(info.get(), resource);
- info->setLoadFinishTime(finishTime);
- // encodedDataLength == -1 means "not available".
- // TODO(ricea): Find cases where it is not available but the
- // PerformanceResourceTiming spec requires it to be available and fix
- // them.
- info->addFinalTransferSize(encodedDataLength == -1 ? 0
- : encodedDataLength);
-
- if (resource->options().requestInitiatorContext == DocumentContext)
- context().addResourceTiming(*info);
- resource->reportResourceTimingToClients(*info);
- }
- }
-
- context().dispatchDidFinishLoading(resource->identifier(), finishTime,
- encodedDataLength);
-
- if (type == DidFinishLoading)
- resource->finish(finishTime);
-
- handleLoadCompletion(resource);
-}
-
-void ResourceFetcher::handleLoaderError(Resource* resource,
- const ResourceError& error) {
- DCHECK(resource);
-
- removeResourceLoader(resource->loader());
-
- m_resourceTimingInfoMap.take(resource);
-
- bool isInternalRequest = resource->options().initiatorInfo.name ==
- FetchInitiatorTypeNames::internal;
-
- context().dispatchDidFail(resource->identifier(), error,
- resource->response().encodedDataLength(),
- isInternalRequest);
-
- resource->error(error);
-
- handleLoadCompletion(resource);
-}
-
-void ResourceFetcher::moveResourceLoaderToNonBlocking(ResourceLoader* loader) {
- DCHECK(loader);
- // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in.
- CHECK(m_loaders.contains(loader));
- m_nonBlockingLoaders.add(loader);
- m_loaders.remove(loader);
-}
-
-bool ResourceFetcher::startLoad(Resource* resource) {
- DCHECK(resource);
- DCHECK(resource->stillNeedsLoad());
- if (!context().shouldLoadNewResource(resource->getType())) {
- memoryCache()->remove(resource);
- return false;
- }
-
- ResourceRequest request(resource->resourceRequest());
- context().dispatchWillSendRequest(resource->identifier(), request,
- ResourceResponse(),
- resource->options().initiatorInfo);
-
- // TODO(shaochuan): Saving modified ResourceRequest back to |resource|, remove
- // once dispatchWillSendRequest() takes const ResourceRequest.
- // crbug.com/632580
- resource->setResourceRequest(request);
-
- // Resource requests from suborigins should not be intercepted by the service
- // worker of the physical origin. This has the effect that, for now,
- // suborigins do not work with service workers. See
- // https://w3c.github.io/webappsec-suborigins/.
- SecurityOrigin* sourceOrigin = context().getSecurityOrigin();
- if (sourceOrigin && sourceOrigin->hasSuborigin())
- request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All);
-
- ResourceLoader* loader = ResourceLoader::create(this, resource);
- if (resource->shouldBlockLoadEvent())
- m_loaders.add(loader);
- else
- m_nonBlockingLoaders.add(loader);
-
- storePerformanceTimingInitiatorInformation(resource);
- resource->setFetcherSecurityOrigin(sourceOrigin);
-
- loader->activateCacheAwareLoadingIfNeeded(request);
- loader->start(request);
- return true;
-}
-
-void ResourceFetcher::removeResourceLoader(ResourceLoader* loader) {
- DCHECK(loader);
- if (m_loaders.contains(loader))
- m_loaders.remove(loader);
- else if (m_nonBlockingLoaders.contains(loader))
- m_nonBlockingLoaders.remove(loader);
- else
- NOTREACHED();
-}
-
-void ResourceFetcher::stopFetching() {
- HeapVector<Member<ResourceLoader>> loadersToCancel;
- for (const auto& loader : m_nonBlockingLoaders)
- loadersToCancel.push_back(loader);
- for (const auto& loader : m_loaders)
- loadersToCancel.push_back(loader);
-
- for (const auto& loader : loadersToCancel) {
- if (m_loaders.contains(loader) || m_nonBlockingLoaders.contains(loader))
- loader->cancel();
- }
-}
-
-bool ResourceFetcher::isFetching() const {
- return !m_loaders.isEmpty();
-}
-
-void ResourceFetcher::setDefersLoading(bool defers) {
- for (const auto& loader : m_nonBlockingLoaders)
- loader->setDefersLoading(defers);
- for (const auto& loader : m_loaders)
- loader->setDefersLoading(defers);
-}
-
-void ResourceFetcher::updateAllImageResourcePriorities() {
- TRACE_EVENT0(
- "blink",
- "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities");
- for (const auto& documentResource : m_documentResources) {
- Resource* resource = documentResource.value.get();
- if (!resource || !resource->isImage() || !resource->isLoading())
- continue;
-
- ResourcePriority resourcePriority = resource->priorityFromObservers();
- ResourceLoadPriority resourceLoadPriority = computeLoadPriority(
- Resource::Image,
- FetchRequest(resource->resourceRequest(), FetchInitiatorInfo()),
- resourcePriority.visibility);
- if (resourceLoadPriority == resource->resourceRequest().priority())
- continue;
-
- resource->didChangePriority(resourceLoadPriority,
- resourcePriority.intraPriorityValue);
- network_instrumentation::resourcePrioritySet(resource->identifier(),
- resourceLoadPriority);
- context().dispatchDidChangeResourcePriority(
- resource->identifier(), resourceLoadPriority,
- resourcePriority.intraPriorityValue);
- }
-}
-
-void ResourceFetcher::reloadLoFiImages() {
- for (const auto& documentResource : m_documentResources) {
- Resource* resource = documentResource.value.get();
- if (resource)
- resource->reloadIfLoFiOrPlaceholderImage(this, Resource::kReloadAlways);
- }
-}
-
-void ResourceFetcher::logPreloadStats(ClearPreloadsPolicy policy) {
- if (!m_preloads)
- return;
- unsigned scripts = 0;
- unsigned scriptMisses = 0;
- unsigned stylesheets = 0;
- unsigned stylesheetMisses = 0;
- unsigned images = 0;
- unsigned imageMisses = 0;
- unsigned fonts = 0;
- unsigned fontMisses = 0;
- unsigned medias = 0;
- unsigned mediaMisses = 0;
- unsigned textTracks = 0;
- unsigned textTrackMisses = 0;
- unsigned imports = 0;
- unsigned importMisses = 0;
- unsigned raws = 0;
- unsigned rawMisses = 0;
- for (const auto& resource : *m_preloads) {
- // Do not double count link rel preloads. These do not get cleared if the
- // ClearPreloadsPolicy is only clearing speculative markup preloads.
- if (resource->isLinkPreload() && policy == ClearSpeculativeMarkupPreloads) {
- continue;
- }
- int missCount =
- resource->getPreloadResult() == Resource::PreloadNotReferenced ? 1 : 0;
- switch (resource->getType()) {
- case Resource::Image:
- images++;
- imageMisses += missCount;
- break;
- case Resource::Script:
- scripts++;
- scriptMisses += missCount;
- break;
- case Resource::CSSStyleSheet:
- stylesheets++;
- stylesheetMisses += missCount;
- break;
- case Resource::Font:
- fonts++;
- fontMisses += missCount;
- break;
- case Resource::Media:
- medias++;
- mediaMisses += missCount;
- break;
- case Resource::TextTrack:
- textTracks++;
- textTrackMisses += missCount;
- break;
- case Resource::ImportResource:
- imports++;
- importMisses += missCount;
- break;
- case Resource::Raw:
- raws++;
- rawMisses += missCount;
- break;
- case Resource::Mock:
- // Do not count Resource::Mock because this type is only for testing.
- break;
- default:
- NOTREACHED();
- }
- }
- DEFINE_STATIC_LOCAL(CustomCountHistogram, imagePreloads,
- ("PreloadScanner.Counts2.Image", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, imagePreloadMisses,
- ("PreloadScanner.Counts2.Miss.Image", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, scriptPreloads,
- ("PreloadScanner.Counts2.Script", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, scriptPreloadMisses,
- ("PreloadScanner.Counts2.Miss.Script", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, stylesheetPreloads,
- ("PreloadScanner.Counts2.CSSStyleSheet", 0, 100, 25));
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, stylesheetPreloadMisses,
- ("PreloadScanner.Counts2.Miss.CSSStyleSheet", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, fontPreloads,
- ("PreloadScanner.Counts2.Font", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, fontPreloadMisses,
- ("PreloadScanner.Counts2.Miss.Font", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, mediaPreloads,
- ("PreloadScanner.Counts2.Media", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, mediaPreloadMisses,
- ("PreloadScanner.Counts2.Miss.Media", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, textTrackPreloads,
- ("PreloadScanner.Counts2.TextTrack", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, textTrackPreloadMisses,
- ("PreloadScanner.Counts2.Miss.TextTrack", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, importPreloads,
- ("PreloadScanner.Counts2.Import", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, importPreloadMisses,
- ("PreloadScanner.Counts2.Miss.Import", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, rawPreloads,
- ("PreloadScanner.Counts2.Raw", 0, 100, 25));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, rawPreloadMisses,
- ("PreloadScanner.Counts2.Miss.Raw", 0, 100, 25));
- if (images)
- imagePreloads.count(images);
- if (imageMisses)
- imagePreloadMisses.count(imageMisses);
- if (scripts)
- scriptPreloads.count(scripts);
- if (scriptMisses)
- scriptPreloadMisses.count(scriptMisses);
- if (stylesheets)
- stylesheetPreloads.count(stylesheets);
- if (stylesheetMisses)
- stylesheetPreloadMisses.count(stylesheetMisses);
- if (fonts)
- fontPreloads.count(fonts);
- if (fontMisses)
- fontPreloadMisses.count(fontMisses);
- if (medias)
- mediaPreloads.count(medias);
- if (mediaMisses)
- mediaPreloadMisses.count(mediaMisses);
- if (textTracks)
- textTrackPreloads.count(textTracks);
- if (textTrackMisses)
- textTrackPreloadMisses.count(textTrackMisses);
- if (imports)
- importPreloads.count(imports);
- if (importMisses)
- importPreloadMisses.count(importMisses);
- if (raws)
- rawPreloads.count(raws);
- if (rawMisses)
- rawPreloadMisses.count(rawMisses);
-}
-
-const ResourceLoaderOptions& ResourceFetcher::defaultResourceOptions() {
- DEFINE_STATIC_LOCAL(
- ResourceLoaderOptions, options,
- (BufferData, AllowStoredCredentials, ClientRequestedCredentials,
- CheckContentSecurityPolicy, DocumentContext));
- return options;
-}
-
-String ResourceFetcher::getCacheIdentifier() const {
- if (context().isControlledByServiceWorker())
- return String::number(context().serviceWorkerID());
- return MemoryCache::defaultCacheIdentifier();
-}
-
-void ResourceFetcher::emulateLoadStartedForInspector(
- Resource* resource,
- const KURL& url,
- WebURLRequest::RequestContext requestContext,
- const AtomicString& initiatorName) {
- if (cachedResource(url))
- return;
- ResourceRequest resourceRequest(url);
- resourceRequest.setRequestContext(requestContext);
- FetchRequest request(resourceRequest, initiatorName, resource->options());
- context().canRequest(resource->getType(), resource->lastResourceRequest(),
- resource->lastResourceRequest().url(), request.options(),
- false, request.getOriginRestriction());
- requestLoadStarted(resource->identifier(), resource, request,
- ResourceLoadingFromCache);
-}
-
-ResourceFetcher::DeadResourceStatsRecorder::DeadResourceStatsRecorder()
- : m_useCount(0), m_revalidateCount(0), m_loadCount(0) {}
-
-ResourceFetcher::DeadResourceStatsRecorder::~DeadResourceStatsRecorder() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, hitCountHistogram,
- new CustomCountHistogram("WebCore.ResourceFetcher.HitCount", 0, 1000,
- 50));
- hitCountHistogram.count(m_useCount);
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, revalidateCountHistogram,
- new CustomCountHistogram("WebCore.ResourceFetcher.RevalidateCount", 0,
- 1000, 50));
- revalidateCountHistogram.count(m_revalidateCount);
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, loadCountHistogram,
- new CustomCountHistogram("WebCore.ResourceFetcher.LoadCount", 0, 1000,
- 50));
- loadCountHistogram.count(m_loadCount);
-}
-
-void ResourceFetcher::DeadResourceStatsRecorder::update(
- RevalidationPolicy policy) {
- switch (policy) {
- case Reload:
- case Load:
- ++m_loadCount;
- return;
- case Revalidate:
- ++m_revalidateCount;
- return;
- case Use:
- ++m_useCount;
- return;
- }
-}
-
-DEFINE_TRACE(ResourceFetcher) {
- visitor->trace(m_context);
- visitor->trace(m_archive);
- visitor->trace(m_loaders);
- visitor->trace(m_nonBlockingLoaders);
- visitor->trace(m_documentResources);
- visitor->trace(m_preloads);
- visitor->trace(m_resourceTimingInfoMap);
-}
-
-} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/fetch/ResourceFetcher.h ('k') | third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698