diff options
Diffstat (limited to 'Source/WebCore/loader/cache/CachedRawResource.cpp')
-rw-r--r-- | Source/WebCore/loader/cache/CachedRawResource.cpp | 164 |
1 files changed, 102 insertions, 62 deletions
diff --git a/Source/WebCore/loader/cache/CachedRawResource.cpp b/Source/WebCore/loader/cache/CachedRawResource.cpp index a6eff5efb..05b9de128 100644 --- a/Source/WebCore/loader/cache/CachedRawResource.cpp +++ b/Source/WebCore/loader/cache/CachedRawResource.cpp @@ -29,23 +29,26 @@ #include "CachedRawResourceClient.h" #include "CachedResourceClientWalker.h" #include "CachedResourceLoader.h" -#include "ResourceBuffer.h" +#include "HTTPHeaderNames.h" +#include "SharedBuffer.h" #include "SubresourceLoader.h" -#include <wtf/PassRefPtr.h> +#include <wtf/text/StringView.h> namespace WebCore { -CachedRawResource::CachedRawResource(ResourceRequest& resourceRequest, Type type) - : CachedResource(resourceRequest, type) +CachedRawResource::CachedRawResource(CachedResourceRequest&& request, Type type, SessionID sessionID) + : CachedResource(WTFMove(request), type, sessionID) , m_identifier(0) + , m_allowEncodedDataReplacement(true) { + ASSERT(isMainOrMediaOrRawResource()); } -const char* CachedRawResource::calculateIncrementalDataChunk(ResourceBuffer* data, unsigned& incrementalDataLength) +const char* CachedRawResource::calculateIncrementalDataChunk(SharedBuffer* data, unsigned& incrementalDataLength) { incrementalDataLength = 0; if (!data) - return 0; + return nullptr; unsigned previousDataLength = encodedSize(); ASSERT(data->size() >= previousDataLength); @@ -53,34 +56,37 @@ const char* CachedRawResource::calculateIncrementalDataChunk(ResourceBuffer* dat return data->data() + previousDataLength; } -void CachedRawResource::addDataBuffer(ResourceBuffer* data) +void CachedRawResource::addDataBuffer(SharedBuffer& data) { - CachedResourceHandle<CachedRawResource> protect(this); - ASSERT(m_options.dataBufferingPolicy == BufferData); - m_data = data; + CachedResourceHandle<CachedRawResource> protectedThis(this); + ASSERT(dataBufferingPolicy() == BufferData); + m_data = &data; unsigned incrementalDataLength; - const char* incrementalData = calculateIncrementalDataChunk(data, incrementalDataLength); - if (data) - setEncodedSize(data->size()); + const char* incrementalData = calculateIncrementalDataChunk(&data, incrementalDataLength); + setEncodedSize(data.size()); notifyClientsDataWasReceived(incrementalData, incrementalDataLength); - if (m_options.dataBufferingPolicy == DoNotBufferData) { + if (dataBufferingPolicy() == DoNotBufferData) { if (m_loader) m_loader->setDataBufferingPolicy(DoNotBufferData); clear(); + return; } + + CachedResource::addDataBuffer(data); } void CachedRawResource::addData(const char* data, unsigned length) { - ASSERT(m_options.dataBufferingPolicy == DoNotBufferData); + ASSERT(dataBufferingPolicy() == DoNotBufferData); notifyClientsDataWasReceived(data, length); + CachedResource::addData(data, length); } -void CachedRawResource::finishLoading(ResourceBuffer* data) +void CachedRawResource::finishLoading(SharedBuffer* data) { - CachedResourceHandle<CachedRawResource> protect(this); - DataBufferingPolicy dataBufferingPolicy = m_options.dataBufferingPolicy; + CachedResourceHandle<CachedRawResource> protectedThis(this); + DataBufferingPolicy dataBufferingPolicy = this->dataBufferingPolicy(); if (dataBufferingPolicy == BufferData) { m_data = data; @@ -91,8 +97,12 @@ void CachedRawResource::finishLoading(ResourceBuffer* data) notifyClientsDataWasReceived(incrementalData, incrementalDataLength); } +#if USE(QUICK_LOOK) + m_allowEncodedDataReplacement = !m_loader->isQuickLookResource(); +#endif + CachedResource::finishLoading(data); - if (dataBufferingPolicy == BufferData && m_options.dataBufferingPolicy == DoNotBufferData) { + if (dataBufferingPolicy == BufferData && this->dataBufferingPolicy() == DoNotBufferData) { if (m_loader) m_loader->setDataBufferingPolicy(DoNotBufferData); clear(); @@ -104,37 +114,45 @@ void CachedRawResource::notifyClientsDataWasReceived(const char* data, unsigned if (!length) return; - CachedResourceHandle<CachedRawResource> protect(this); + CachedResourceHandle<CachedRawResource> protectedThis(this); CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); while (CachedRawResourceClient* c = w.next()) - c->dataReceived(this, data, length); + c->dataReceived(*this, data, length); } -void CachedRawResource::didAddClient(CachedResourceClient* c) +void CachedRawResource::didAddClient(CachedResourceClient& c) { if (!hasClient(c)) return; // The calls to the client can result in events running, potentially causing // this resource to be evicted from the cache and all clients to be removed, // so a protector is necessary. - CachedResourceHandle<CachedRawResource> protect(this); - CachedRawResourceClient* client = static_cast<CachedRawResourceClient*>(c); + CachedResourceHandle<CachedRawResource> protectedThis(this); + CachedRawResourceClient& client = static_cast<CachedRawResourceClient&>(c); size_t redirectCount = m_redirectChain.size(); for (size_t i = 0; i < redirectCount; i++) { RedirectPair redirect = m_redirectChain[i]; ResourceRequest request(redirect.m_request); - client->redirectReceived(this, request, redirect.m_redirectResponse); + client.redirectReceived(*this, request, redirect.m_redirectResponse); if (!hasClient(c)) return; } ASSERT(redirectCount == m_redirectChain.size()); - if (!m_response.isNull()) - client->responseReceived(this, m_response); + if (!m_response.isNull()) { + ResourceResponse response(m_response); + if (validationCompleting()) + response.setSource(ResourceResponse::Source::MemoryCacheAfterValidation); + else { + ASSERT(!validationInProgress()); + response.setSource(ResourceResponse::Source::MemoryCache); + } + client.responseReceived(*this, response); + } if (!hasClient(c)) return; if (m_data) - client->dataReceived(this, m_data->data(), m_data->size()); + client.dataReceived(*this, m_data->data(), m_data->size()); if (!hasClient(c)) return; CachedResource::didAddClient(client); @@ -146,34 +164,51 @@ void CachedRawResource::allClientsRemoved() m_loader->cancelIfNotFinishing(); } -void CachedRawResource::willSendRequest(ResourceRequest& request, const ResourceResponse& response) +void CachedRawResource::redirectReceived(ResourceRequest& request, const ResourceResponse& response) { - CachedResourceHandle<CachedRawResource> protect(this); + CachedResourceHandle<CachedRawResource> protectedThis(this); if (!response.isNull()) { CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); while (CachedRawResourceClient* c = w.next()) - c->redirectReceived(this, request, response); + c->redirectReceived(*this, request, response); m_redirectChain.append(RedirectPair(request, response)); } - CachedResource::willSendRequest(request, response); + CachedResource::redirectReceived(request, response); } void CachedRawResource::responseReceived(const ResourceResponse& response) { - CachedResourceHandle<CachedRawResource> protect(this); + CachedResourceHandle<CachedRawResource> protectedThis(this); if (!m_identifier) m_identifier = m_loader->identifier(); CachedResource::responseReceived(response); CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); while (CachedRawResourceClient* c = w.next()) - c->responseReceived(this, m_response); + c->responseReceived(*this, m_response); +} + +bool CachedRawResource::shouldCacheResponse(const ResourceResponse& response) +{ + CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); + while (CachedRawResourceClient* c = w.next()) { + if (!c->shouldCacheResponse(*this, response)) + return false; + } + return true; } void CachedRawResource::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); while (CachedRawResourceClient* c = w.next()) - c->dataSent(this, bytesSent, totalBytesToBeSent); + c->dataSent(*this, bytesSent, totalBytesToBeSent); +} + +void CachedRawResource::finishedTimingForWorkerLoad(ResourceTiming&& resourceTiming) +{ + CachedResourceClientWalker<CachedRawResourceClient> w(m_clients); + while (CachedRawResourceClient* c = w.next()) + c->finishedTimingForWorkerLoad(*this, resourceTiming); } void CachedRawResource::switchClientsToRevalidatedResource() @@ -181,7 +216,7 @@ void CachedRawResource::switchClientsToRevalidatedResource() ASSERT(m_loader); // If we're in the middle of a successful revalidation, responseReceived() hasn't been called, so we haven't set m_identifier. ASSERT(!m_identifier); - static_cast<CachedRawResource*>(resourceToRevalidate())->m_identifier = m_loader->identifier(); + downcast<CachedRawResource>(*resourceToRevalidate()).m_identifier = m_loader->identifier(); CachedResource::switchClientsToRevalidatedResource(); } @@ -196,25 +231,26 @@ void CachedRawResource::setDataBufferingPolicy(DataBufferingPolicy dataBuffering m_options.dataBufferingPolicy = dataBufferingPolicy; } -static bool shouldIgnoreHeaderForCacheReuse(AtomicString headerName) +static bool shouldIgnoreHeaderForCacheReuse(HTTPHeaderName name) { + switch (name) { // FIXME: This list of headers that don't affect cache policy almost certainly isn't complete. - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, m_headers, ()); - if (m_headers.isEmpty()) { - m_headers.add("Accept"); - m_headers.add("Cache-Control"); - m_headers.add("Origin"); - m_headers.add("Pragma"); - m_headers.add("Purpose"); - m_headers.add("Referer"); - m_headers.add("User-Agent"); + case HTTPHeaderName::Accept: + case HTTPHeaderName::CacheControl: + case HTTPHeaderName::Pragma: + case HTTPHeaderName::Purpose: + case HTTPHeaderName::Referer: + case HTTPHeaderName::UserAgent: + return true; + + default: + return false; } - return m_headers.contains(headerName); } bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const { - if (m_options.dataBufferingPolicy == DoNotBufferData) + if (dataBufferingPolicy() == DoNotBufferData) return false; if (m_resourceRequest.httpMethod() != newRequest.httpMethod()) @@ -226,6 +262,9 @@ bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const 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 @@ -233,22 +272,23 @@ bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const const HTTPHeaderMap& newHeaders = newRequest.httpHeaderFields(); const HTTPHeaderMap& oldHeaders = m_resourceRequest.httpHeaderFields(); - HTTPHeaderMap::const_iterator end = newHeaders.end(); - for (HTTPHeaderMap::const_iterator i = newHeaders.begin(); i != end; ++i) { - AtomicString headerName = i->key; - if (!shouldIgnoreHeaderForCacheReuse(headerName) && i->value != oldHeaders.get(headerName)) - return false; - } - - end = oldHeaders.end(); - for (HTTPHeaderMap::const_iterator i = oldHeaders.begin(); i != end; ++i) { - AtomicString headerName = i->key; - if (!shouldIgnoreHeaderForCacheReuse(headerName) && i->value != newHeaders.get(headerName)) + 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 (size_t i = 0; i < m_redirectChain.size(); i++) { - if (m_redirectChain[i].m_redirectResponse.cacheControlContainsNoStore()) + // 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; } @@ -257,7 +297,7 @@ bool CachedRawResource::canReuse(const ResourceRequest& newRequest) const void CachedRawResource::clear() { - m_data.clear(); + m_data = nullptr; setEncodedSize(0); if (m_loader) m_loader->clearResourceData(); |