Speculative disk cache resource revalidations are sometimes wasted
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cache / NetworkCacheEntry.cpp
index 3aefce7..f74cecf 100644 (file)
@@ -30,7 +30,6 @@
 #include "NetworkCacheCoders.h"
 #include "NetworkCacheDecoder.h"
 #include "NetworkCacheEncoder.h"
-#include <JavaScriptCore/JSONObject.h>
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/SharedBuffer.h>
 #include <wtf/text/StringBuilder.h>
@@ -45,7 +44,30 @@ Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, RefPtr<W
     , m_timeStamp(std::chrono::system_clock::now())
     , m_response(response)
     , m_varyingRequestHeaders(varyingRequestHeaders)
-    , m_buffer(WTF::move(buffer))
+    , m_buffer(WTFMove(buffer))
+{
+    ASSERT(m_key.type() == "resource");
+}
+
+Entry::Entry(const Key& key, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& redirectRequest, const Vector<std::pair<String, String>>& varyingRequestHeaders)
+    : m_key(key)
+    , m_timeStamp(std::chrono::system_clock::now())
+    , m_response(response)
+    , m_varyingRequestHeaders(varyingRequestHeaders)
+    , m_redirectRequest(WebCore::ResourceRequest::adopt(redirectRequest.copyData())) // Don't include the underlying platform request object.
+{
+    ASSERT(m_key.type() == "resource");
+    // Redirect body is not needed even if exists.
+    m_redirectRequest->setHTTPBody(nullptr);
+}
+
+Entry::Entry(const Entry& other)
+    : m_key(other.m_key)
+    , m_timeStamp(other.m_timeStamp)
+    , m_response(other.m_response)
+    , m_varyingRequestHeaders(other.m_varyingRequestHeaders)
+    , m_buffer(other.m_buffer)
+    , m_sourceStorageRecord(other.m_sourceStorageRecord)
 {
 }
 
@@ -54,6 +76,7 @@ Entry::Entry(const Storage::Record& storageEntry)
     , m_timeStamp(storageEntry.timeStamp)
     , m_sourceStorageRecord(storageEntry)
 {
+    ASSERT(m_key.type() == "resource");
 }
 
 Storage::Record Entry::encodeAsStorageRecord() const
@@ -66,6 +89,11 @@ Storage::Record Entry::encodeAsStorageRecord() const
     if (hasVaryingRequestHeaders)
         encoder << m_varyingRequestHeaders;
 
+    bool isRedirect = !!m_redirectRequest;
+    encoder << isRedirect;
+    if (isRedirect)
+        m_redirectRequest->encodeWithoutPlatformData(encoder);
+
     encoder.encodeChecksum();
 
     Data header(encoder.buffer(), encoder.bufferSize());
@@ -78,7 +106,7 @@ Storage::Record Entry::encodeAsStorageRecord() const
 
 std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storageEntry)
 {
-    std::unique_ptr<Entry> entry(new Entry(storageEntry));
+    auto entry = std::make_unique<Entry>(storageEntry);
 
     Decoder decoder(storageEntry.header.data(), storageEntry.header.size());
     if (!decoder.decode(entry->m_response))
@@ -94,6 +122,16 @@ std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storage
             return nullptr;
     }
 
+    bool isRedirect;
+    if (!decoder.decode(isRedirect))
+        return nullptr;
+
+    if (isRedirect) {
+        entry->m_redirectRequest = std::make_unique<WebCore::ResourceRequest>();
+        if (!entry->m_redirectRequest->decodeWithoutPlatformData(decoder))
+            return nullptr;
+    }
+
     if (!decoder.verifyChecksum()) {
         LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n");
         return nullptr;
@@ -102,19 +140,29 @@ std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storage
     return entry;
 }
 
+#if ENABLE(SHAREABLE_RESOURCE)
+void Entry::initializeShareableResourceHandleFromStorageRecord() const
+{
+    RefPtr<SharedMemory> sharedMemory = m_sourceStorageRecord.body.tryCreateSharedMemory();
+    if (!sharedMemory)
+        return;
+
+    RefPtr<ShareableResource> shareableResource = ShareableResource::create(sharedMemory.release(), 0, m_sourceStorageRecord.body.size());
+    ASSERT(shareableResource);
+    shareableResource->createHandle(m_shareableResourceHandle);
+}
+#endif
+
 void Entry::initializeBufferFromStorageRecord() const
 {
-    auto* data = m_sourceStorageRecord.body.data();
-    size_t size = m_sourceStorageRecord.body.size();
 #if ENABLE(SHAREABLE_RESOURCE)
-    RefPtr<SharedMemory> sharedMemory = m_sourceStorageRecord.body.isMap() ? SharedMemory::create(const_cast<uint8_t*>(data), size, SharedMemory::Protection::ReadOnly) : nullptr;
-    RefPtr<ShareableResource> shareableResource = sharedMemory ? ShareableResource::create(sharedMemory.release(), 0, m_sourceStorageRecord.body.size()) : nullptr;
-
-    if (shareableResource && shareableResource->createHandle(m_shareableResourceHandle))
+    if (!shareableResourceHandle().isNull()) {
         m_buffer = m_shareableResourceHandle.tryWrapInSharedBuffer();
+        if (m_buffer)
+            return;
+    }
 #endif
-    if (!m_buffer)
-        m_buffer = WebCore::SharedBuffer::create(data, size);
+    m_buffer = WebCore::SharedBuffer::create(m_sourceStorageRecord.body.data(), m_sourceStorageRecord.body.size());
 }
 
 WebCore::SharedBuffer* Entry::buffer() const
@@ -125,30 +173,31 @@ WebCore::SharedBuffer* Entry::buffer() const
     return m_buffer.get();
 }
 
+#if ENABLE(SHAREABLE_RESOURCE)
 ShareableResource::Handle& Entry::shareableResourceHandle() const
 {
-    if (!m_buffer)
-        initializeBufferFromStorageRecord();
+    if (m_shareableResourceHandle.isNull())
+        initializeShareableResourceHandleFromStorageRecord();
 
     return m_shareableResourceHandle;
 }
+#endif
 
 bool Entry::needsValidation() const
 {
     return m_response.source() == WebCore::ResourceResponse::Source::DiskCacheAfterValidation;
 }
 
-void Entry::setNeedsValidation()
+void Entry::setNeedsValidation(bool value)
 {
-    ASSERT(m_response.source() == WebCore::ResourceResponse::Source::DiskCache);
-    m_response.setSource(WebCore::ResourceResponse::Source::DiskCacheAfterValidation);
+    m_response.setSource(value ? WebCore::ResourceResponse::Source::DiskCacheAfterValidation : WebCore::ResourceResponse::Source::DiskCache);
 }
 
 void Entry::asJSON(StringBuilder& json, const Storage::RecordInfo& info) const
 {
     json.appendLiteral("{\n");
     json.appendLiteral("\"hash\": ");
-    JSC::appendQuotedJSONStringToBuilder(json, m_key.hashAsString());
+    json.appendQuotedJSONString(m_key.hashAsString());
     json.appendLiteral(",\n");
     json.appendLiteral("\"bodySize\": ");
     json.appendNumber(info.bodySize);
@@ -157,16 +206,16 @@ void Entry::asJSON(StringBuilder& json, const Storage::RecordInfo& info) const
     json.appendNumber(info.worth);
     json.appendLiteral(",\n");
     json.appendLiteral("\"partition\": ");
-    JSC::appendQuotedJSONStringToBuilder(json, m_key.partition());
+    json.appendQuotedJSONString(m_key.partition());
     json.appendLiteral(",\n");
     json.appendLiteral("\"timestamp\": ");
     json.appendNumber(std::chrono::duration_cast<std::chrono::milliseconds>(m_timeStamp.time_since_epoch()).count());
     json.appendLiteral(",\n");
     json.appendLiteral("\"URL\": ");
-    JSC::appendQuotedJSONStringToBuilder(json, m_response.url().string());
+    json.appendQuotedJSONString(m_response.url().string());
     json.appendLiteral(",\n");
     json.appendLiteral("\"bodyHash\": ");
-    JSC::appendQuotedJSONStringToBuilder(json, info.bodyHash);
+    json.appendQuotedJSONString(info.bodyHash);
     json.appendLiteral(",\n");
     json.appendLiteral("\"bodyShareCount\": ");
     json.appendNumber(info.bodyShareCount);
@@ -178,9 +227,9 @@ void Entry::asJSON(StringBuilder& json, const Storage::RecordInfo& info) const
             json.appendLiteral(",\n");
         firstHeader = false;
         json.appendLiteral("    ");
-        JSC::appendQuotedJSONStringToBuilder(json, header.key);
+        json.appendQuotedJSONString(header.key);
         json.appendLiteral(": ");
-        JSC::appendQuotedJSONStringToBuilder(json, header.value);
+        json.appendQuotedJSONString(header.value);
     }
     json.appendLiteral("\n}\n");
     json.appendLiteral("}");