Index: Source/core/fetch/ResourceFetcher.cpp |
diff --git a/Source/core/fetch/ResourceFetcher.cpp b/Source/core/fetch/ResourceFetcher.cpp |
index 7df5fd157395b48b3b5fe739197e389275547e59..92d504ba6f190e0ec4521ac84ec9e597eaaff92b 100644 |
--- a/Source/core/fetch/ResourceFetcher.cpp |
+++ b/Source/core/fetch/ResourceFetcher.cpp |
@@ -254,12 +254,12 @@ bool ResourceFetcher::resourceNeedsLoad(Resource* resource, const FetchRequest& |
// http://crbug.com/52411 |
static const int kMaxValidatedURLsSize = 10000; |
-void ResourceFetcher::requestLoadStarted(Resource* resource, const FetchRequest& request, ResourceLoadStartType type) |
+void ResourceFetcher::requestLoadStarted(Resource* resource, const FetchRequest& request, ResourceLoadStartType type, bool isStaticData) |
{ |
if (type == ResourceLoadingFromCache) |
notifyLoadedFromMemoryCache(resource); |
- if (request.resourceRequest().url().protocolIsData() || context().hasSubstituteData()) |
+ if (isStaticData) |
return; |
if (type == ResourceLoadingFromCache && !resource->stillNeedsLoad() && !m_validatedURLs.contains(request.resourceRequest().url())) { |
@@ -284,7 +284,52 @@ static PassRefPtr<TraceEvent::ConvertableToTraceFormat> urlForTraceEvent(const K |
return value.release(); |
} |
-ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, const ResourceFactory& factory) |
+void ResourceFetcher::preCacheData(const FetchRequest& request, const ResourceFactory& factory, const SubstituteData& substituteData) |
+{ |
+ const KURL& url = request.resourceRequest().url(); |
+ ASSERT(url.protocolIsData() || substituteData.isValid()); |
+ if ((factory.type() == Resource::MainResource && !substituteData.isValid()) || factory.type() == Resource::Raw || factory.type() == Resource::Media) |
+ return; |
+ |
+ const String cacheIdentifier = getCacheIdentifier(); |
+ if (Resource* oldResource = memoryCache()->resourceForURL(url, cacheIdentifier)) { |
+ if (!substituteData.isValid()) |
+ return; |
+ memoryCache()->remove(oldResource); |
+ } |
+ |
+ WebString mimetype; |
+ WebString charset; |
+ RefPtr<SharedBuffer> data; |
+ if (substituteData.isValid()) { |
+ mimetype = substituteData.mimeType(); |
+ charset = substituteData.textEncoding(); |
+ data = substituteData.content(); |
+ } else { |
+ data = PassRefPtr<SharedBuffer>(Platform::current()->parseDataURL(url, mimetype, charset)); |
+ if (!data) |
+ return; |
+ } |
+ ResourceResponse response(url, mimetype, data->size(), charset, String()); |
+ response.setHTTPStatusCode(200); |
+ response.setHTTPStatusText("OK"); |
+ |
+ ResourcePtr<Resource> resource = factory.create(request.resourceRequest(), request.charset()); |
+ resource->setNeedsSynchronousCacheHit(substituteData.forceSynchronousLoad()); |
+ resource->setOptions(request.options()); |
+ // 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(); |
+ memoryCache()->add(resource.get()); |
+ scheduleDocumentResourcesGC(); |
+} |
+ |
+ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, const ResourceFactory& factory, const SubstituteData& substituteData) |
{ |
ASSERT(request.options().synchronousPolicy == RequestAsynchronously || factory.type() == Resource::Raw); |
@@ -292,6 +337,10 @@ ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, co |
context().addClientHintsIfNecessary(request); |
context().addCSPHeaderIfNecessary(factory.type(), request); |
+ bool isStaticData = request.resourceRequest().url().protocolIsData() || substituteData.isValid(); |
+ if (isStaticData) |
+ preCacheData(request, factory, substituteData); |
+ |
KURL url = request.resourceRequest().url(); |
TRACE_EVENT1("blink", "ResourceFetcher::requestResource", "url", urlForTraceEvent(url)); |
@@ -326,7 +375,7 @@ ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, co |
// See if we can use an existing resource from the cache. |
ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url, getCacheIdentifier()); |
- const RevalidationPolicy policy = determineRevalidationPolicy(factory.type(), request, resource.get()); |
+ const RevalidationPolicy policy = determineRevalidationPolicy(factory.type(), request, resource.get(), isStaticData); |
switch (policy) { |
case Reload: |
memoryCache()->remove(resource.get()); |
@@ -397,12 +446,12 @@ ResourcePtr<Resource> ResourceFetcher::requestResource(FetchRequest& request, co |
// use. |
// Remove main resource from cache to prevent reuse. |
if (factory.type() == Resource::MainResource) { |
- ASSERT(policy != Use || context().hasSubstituteData()); |
+ ASSERT(policy != Use || substituteData.isValid()); |
ASSERT(policy != Revalidate); |
memoryCache()->remove(resource.get()); |
} |
- requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork); |
+ requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork, isStaticData); |
ASSERT(resource->url() == url.string()); |
m_documentResources.set(resource->url(), resource); |
@@ -509,7 +558,7 @@ void ResourceFetcher::storeResourceTimingInitiatorInformation(Resource* resource |
m_resourceTimingInfoMap.add(resource, info.release()); |
} |
-ResourceFetcher::RevalidationPolicy ResourceFetcher::determineRevalidationPolicy(Resource::Type type, const FetchRequest& fetchRequest, Resource* existingResource) const |
+ResourceFetcher::RevalidationPolicy ResourceFetcher::determineRevalidationPolicy(Resource::Type type, const FetchRequest& fetchRequest, Resource* existingResource, bool isStaticData) const |
{ |
const ResourceRequest& request = fetchRequest.resourceRequest(); |
@@ -535,23 +584,18 @@ ResourceFetcher::RevalidationPolicy ResourceFetcher::determineRevalidationPolicy |
if (FetchRequest::DeferredByClient == fetchRequest.defer()) |
return Reload; |
- // Always use data uris. |
- // FIXME: Extend this to non-images. |
- if (type == Resource::Image && request.url().protocolIsData()) |
- return Use; |
+ // Never use cache entries for downloadToFile / useStreamOnResponse |
+ // requests. The data will be delivered through other paths. |
+ if (request.downloadToFile() || request.useStreamOnResponse()) |
+ return Reload; |
- // If a main resource was populated from a SubstituteData load, use it. |
- if (type == Resource::MainResource && context().hasSubstituteData()) |
+ // If resource was populated from a SubstituteData load or data: url, use it. |
+ if (isStaticData) |
return Use; |
if (!existingResource->canReuse(request)) |
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; |
- |
// Certain requests (e.g., XHRs) might have manually set headers that require revalidation. |
// FIXME: 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. |