bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const { if (m_options.shouldBufferData == DoNotBufferData) return false; if (m_resourceRequest.httpMethod() != newRequest.httpMethod()) return false; if (m_resourceRequest.httpBody() != newRequest.httpBody()) return false; if (m_resourceRequest.allowCookies() != newRequest.allowCookies()) return false; // Ensure all headers match the existing headers before continuing. // Note that only headers set by our client will be present in either // ResourceRequest, since SubresourceLoader creates a separate copy // for its purposes. // FIXME: There might be some headers that shouldn't block reuse. const HTTPHeaderMap& newHeaders = newRequest.httpHeaderFields(); const HTTPHeaderMap& oldHeaders = m_resourceRequest.httpHeaderFields(); if (newHeaders.size() != oldHeaders.size()) return false; HTTPHeaderMap::const_iterator end = newHeaders.end(); for (HTTPHeaderMap::const_iterator i = newHeaders.begin(); i != end; ++i) { AtomicString headerName = i->first; if (i->second != oldHeaders.get(headerName)) return false; } return true; }
bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const { if (dataBufferingPolicy() == DoNotBufferData) return false; if (m_resourceRequest.httpMethod() != newRequest.httpMethod()) return false; if (m_resourceRequest.httpBody() != newRequest.httpBody()) return false; if (m_resourceRequest.allowCookies() != newRequest.allowCookies()) return false; if (newRequest.isConditional()) return false; // Ensure most headers match the existing headers before continuing. // Note that the list of ignored headers includes some headers explicitly related to caching. // A more detailed check of caching policy will be performed later, this is simply a list of // headers that we might permit to be different and still reuse the existing CachedResource. const HTTPHeaderMap& newHeaders = newRequest.httpHeaderFields(); const HTTPHeaderMap& oldHeaders = m_resourceRequest.httpHeaderFields(); for (const auto& header : newHeaders) { if (header.keyAsHTTPHeaderName) { if (!shouldIgnoreHeaderForCacheReuse(header.keyAsHTTPHeaderName.value()) && header.value != oldHeaders.commonHeaders().get(header.keyAsHTTPHeaderName.value())) return false; } else if (header.value != oldHeaders.uncommonHeaders().get(header.key)) return false; } // For this second loop, we don't actually need to compare values, checking that the // key is contained in newHeaders is sufficient due to the previous loop. for (const auto& header : oldHeaders) { if (header.keyAsHTTPHeaderName) { if (!shouldIgnoreHeaderForCacheReuse(header.keyAsHTTPHeaderName.value()) && !newHeaders.commonHeaders().contains(header.keyAsHTTPHeaderName.value())) return false; } else if (!newHeaders.uncommonHeaders().contains(header.key)) return false; } return true; }
bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const { if (m_options.dataBufferingPolicy() == DoNotBufferData) return false; if (m_resourceRequest.httpMethod() != newRequest.httpMethod()) return false; if (m_resourceRequest.httpBody() != newRequest.httpBody()) return false; if (m_resourceRequest.allowCookies() != newRequest.allowCookies()) return false; // Ensure most headers match the existing headers before continuing. // Note that the list of ignored headers includes some headers explicitly related to caching. // A more detailed check of caching policy will be performed later, this is simply a list of // headers that we might permit to be different and still reuse the existing CachedResource. const HTTPHeaderMap& newHeaders = newRequest.httpHeaderFields(); const HTTPHeaderMap& oldHeaders = m_resourceRequest.httpHeaderFields(); for (const auto& header : newHeaders) { if (!shouldIgnoreHeaderForCacheReuse(header.key) && header.value != oldHeaders.get(header.key)) return false; } for (const auto& header : oldHeaders) { if (!shouldIgnoreHeaderForCacheReuse(header.key) && header.value != newHeaders.get(header.key)) return false; } for (size_t i = 0; i < m_redirectChain.size(); i++) { if (m_redirectChain[i].m_redirectResponse.cacheControlContainsNoStore()) return false; } return true; }
void ArgumentCoder<ResourceRequest>::encodePlatformData(ArgumentEncoder& encoder, const ResourceRequest& resourceRequest) { encoder << resourceRequest.url().string(); encoder << resourceRequest.httpMethod(); encoder << resourceRequest.httpHeaderFields(); encoder << resourceRequest.timeoutInterval(); // FIXME: Do not encode HTTP message body. // 1. It can be large and thus costly to send across. // 2. It is misleading to provide a body with some requests, while others use body streams, which cannot be serialized at all. FormData* httpBody = resourceRequest.httpBody(); encoder << static_cast<bool>(httpBody); if (httpBody) encoder << httpBody->flattenToString(); encoder << resourceRequest.firstPartyForCookies().string(); encoder << resourceRequest.allowCookies(); encoder.encodeEnum(resourceRequest.priority()); encoder.encodeEnum(resourceRequest.cachePolicy()); encoder.encodeEnum(resourceRequest.requester()); encoder << static_cast<uint32_t>(resourceRequest.soupMessageFlags()); encoder << resourceRequest.initiatingPageID(); }
CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalidationPolicy(CachedResource::Type type, ResourceRequest& request, bool forPreload, CachedResource* existingResource) const { if (!existingResource) return Load; // We already have a preload going for this URL. if (forPreload && existingResource->isPreloaded()) return Use; // If the same URL has been loaded as a different type, we need to reload. if (existingResource->type() != type) { LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to type mismatch."); return Reload; } if (existingResource->type() == CachedResource::RawResource && !static_cast<CachedRawResource*>(existingResource)->canReuse()) 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. if (request.isConditional()) return Reload; // Don't reload resources while pasting. if (m_allowStaleResources) return Use; // Alwaus use preloads. if (existingResource->isPreloaded()) return Use; // CachePolicyHistoryBuffer uses the cache no matter what. if (cachePolicy() == CachePolicyHistoryBuffer) return Use; // Don't reuse resources with Cache-control: no-store. if (existingResource->response().cacheControlContainsNoStore()) { LOG(ResourceLoading, "CachedResourceLoader::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().allowCookies() != request.allowCookies()) { LOG(ResourceLoading, "CachedResourceLoader::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. if (!document()->loadEventFinished() && m_validatedURLs.contains(existingResource->url())) return Use; // CachePolicyReload always reloads if (cachePolicy() == CachePolicyReload) { LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to CachePolicyReload."); return Reload; } // We'll try to reload the resource if it failed last time. if (existingResource->errorOccurred()) { LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicye reloading due to resource being in the error state"); return Reload; } // For resources that are not yet loaded we ignore the cache policy. if (existingResource->isLoading()) return Use; // Check if the cache headers requires us to revalidate (cache expiration for example). if (existingResource->mustRevalidateDueToCacheHeaders(cachePolicy())) { // See if the resource has usable ETag or Last-modified headers. if (existingResource->canUseCacheValidator()) return Revalidate; // No, must reload. LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to missing cache validators."); return Reload; } return Use; }