Persist derived data
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Jan 2017 01:14:33 +0000 (01:14 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Jan 2017 01:14:33 +0000 (01:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=167136

Reviewed by Andreas Kling.

Source/WebCore:

* loader/LoaderStrategy.h:
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::didRetrieveDerivedDataFromCache):
* loader/ResourceLoader.h:
(WebCore::ResourceLoader::options):
* loader/ResourceLoaderOptions.h:
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::didRetrieveDerivedDataFromCache):
* loader/SubresourceLoader.h:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::didRetrieveDerivedDataFromCache):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::defaultCachedResourceOptions):
* platform/network/ResourceResponseBase.h:
(WebCore::ResourceResponseBase::cacheBodyKey):
(WebCore::ResourceResponseBase::setCacheBodyKey):
(WebCore::ResourceResponseBase::encode):
(WebCore::ResourceResponseBase::decode):

Source/WebKit:

* WebCoreSupport/WebResourceLoadScheduler.h:

Source/WebKit2:

Add a mechanism for storing arbitrary data into disk cache.

From WebCore level data can be stored using

    loaderStrategy()->storeDerivedDataToCache(key, partition, type, data);

The data is keyed with the body hash of a network resource. It can be retrieved along
with the resource by specifying the type in ResourceLoaderOptions. If a related data
blob is found it will be deliver via CachedResource::didRetrieveDerivedDataFromCache()
callback.

This patch adds the mechanism but doesn't yet use it for anything.

* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::storeDerivedDataToCache):
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/NetworkConnectionToWebProcess.messages.in:
* NetworkProcess/NetworkResourceLoadParameters.cpp:
(WebKit::NetworkResourceLoadParameters::encode):
(WebKit::NetworkResourceLoadParameters::decode):
* NetworkProcess/NetworkResourceLoadParameters.h:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::didRetrieveCacheEntry):

    Look for related resources to return if needed.

(WebKit::NetworkResourceLoader::sendResultForCacheEntry):
* NetworkProcess/NetworkResourceLoader.h:
* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::resourceType):
 (WebKit::NetworkCache::Cache::retrieveData):
(WebKit::NetworkCache::Cache::storeData):
(WebKit::NetworkCache::Cache::makeCacheKey): Deleted.
* NetworkProcess/cache/NetworkCache.h:
* NetworkProcess/cache/NetworkCacheEntry.cpp:
(WebKit::NetworkCache::Entry::encodeAsStorageRecord):
(WebKit::NetworkCache::Entry::decodeStorageRecord):
* NetworkProcess/cache/NetworkCacheKey.cpp:
(WebKit::NetworkCache::Key::Key):
* NetworkProcess/cache/NetworkCacheKey.h:
(WebKit::NetworkCache::DataKey::encode):
(WebKit::NetworkCache::DataKey::decode):
* NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::readRecord):
(WebKit::NetworkCache::Storage::traverse):
* NetworkProcess/cache/NetworkCacheStorage.h:

    Return body hash with the Record.

* NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp:
(WebKit::NetworkCache::SubresourcesEntry::encodeAsStorageRecord):
* Platform/IPC/ArgumentCoders.cpp:
(IPC::ArgumentCoder<SHA1::Digest>::encode):
(IPC::ArgumentCoder<SHA1::Digest>::decode):
* Platform/IPC/ArgumentCoders.h:
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::scheduleLoad):
(WebKit::WebLoaderStrategy::storeDerivedDataToCache):
* WebProcess/Network/WebLoaderStrategy.h:
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didRetrieveDerivedData):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Network/WebResourceLoader.messages.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210835 268f45cc-cd09-0410-ab3c-d52691b4dbfc

35 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/LoaderStrategy.h
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/ResourceLoader.h
Source/WebCore/loader/ResourceLoaderOptions.h
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/SubresourceLoader.h
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/platform/network/ResourceResponseBase.h
Source/WebKit/ChangeLog
Source/WebKit/WebCoreSupport/WebResourceLoadScheduler.h
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in
Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.cpp
Source/WebKit2/NetworkProcess/NetworkResourceLoadParameters.h
Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp
Source/WebKit2/NetworkProcess/NetworkResourceLoader.h
Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCache.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp
Source/WebKit2/Platform/IPC/ArgumentCoders.cpp
Source/WebKit2/Platform/IPC/ArgumentCoders.h
Source/WebKit2/WebProcess/Network/WebLoaderStrategy.cpp
Source/WebKit2/WebProcess/Network/WebLoaderStrategy.h
Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp
Source/WebKit2/WebProcess/Network/WebResourceLoader.h
Source/WebKit2/WebProcess/Network/WebResourceLoader.messages.in

index 4d1d181..7c0d6b0 100644 (file)
@@ -1,3 +1,29 @@
+2017-01-17  Antti Koivisto  <antti@apple.com>
+
+        Persist derived data
+        https://bugs.webkit.org/show_bug.cgi?id=167136
+
+        Reviewed by Andreas Kling.
+
+        * loader/LoaderStrategy.h:
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::didRetrieveDerivedDataFromCache):
+        * loader/ResourceLoader.h:
+        (WebCore::ResourceLoader::options):
+        * loader/ResourceLoaderOptions.h:
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::didRetrieveDerivedDataFromCache):
+        * loader/SubresourceLoader.h:
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::didRetrieveDerivedDataFromCache):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::defaultCachedResourceOptions):
+        * platform/network/ResourceResponseBase.h:
+        (WebCore::ResourceResponseBase::cacheBodyKey):
+        (WebCore::ResourceResponseBase::setCacheBodyKey):
+        (WebCore::ResourceResponseBase::encode):
+        (WebCore::ResourceResponseBase::decode):
+
 2017-01-17  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Turn modern media controls on by default
index 4c33810..8121f0e 100644 (file)
@@ -28,6 +28,7 @@
 #include "ResourceHandleTypes.h"
 #include "ResourceLoadPriority.h"
 #include "ResourceLoaderOptions.h"
+#include <wtf/SHA1.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
@@ -41,6 +42,7 @@ class ResourceError;
 class ResourceLoader;
 class ResourceRequest;
 class ResourceResponse;
+class SharedBuffer;
 class SubresourceLoader;
 class URL;
 
@@ -59,6 +61,8 @@ public:
 
     virtual void createPingHandle(NetworkingContext*, ResourceRequest&, bool shouldUseCredentialStorage, bool shouldFollowRedirects) = 0;
 
+    virtual void storeDerivedDataToCache(const SHA1::Digest& bodyKey, const String& type, const String& partition, WebCore::SharedBuffer&) = 0;
+
 protected:
     virtual ~LoaderStrategy();
 };
index 9e2abda..bb6f9cc 100644 (file)
@@ -744,4 +744,8 @@ bool ResourceLoader::isAlwaysOnLoggingAllowed() const
     return frameLoader() && frameLoader()->isAlwaysOnLoggingAllowed();
 }
 
+void ResourceLoader::didRetrieveDerivedDataFromCache(const String&, SharedBuffer&)
+{
+}
+
 }
index 45d6e24..dd8ac62 100644 (file)
@@ -107,6 +107,7 @@ public:
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
     virtual void didReceiveDataArray(CFArrayRef dataArray);
 #endif
+    virtual void didRetrieveDerivedDataFromCache(const String& type, SharedBuffer&);
 
     virtual bool shouldUseCredentialStorage();
     virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
@@ -147,6 +148,8 @@ public:
     const Frame* frame() const { return m_frame.get(); }
     WEBCORE_EXPORT bool isAlwaysOnLoggingAllowed() const;
 
+    const ResourceLoaderOptions& options() const { return m_options; }
+
 protected:
     ResourceLoader(Frame&, ResourceLoaderOptions);
 
@@ -157,8 +160,6 @@ protected:
 
     void didReceiveDataOrBuffer(const char*, unsigned, RefPtr<SharedBuffer>&&, long long encodedDataLength, DataPayloadType);
 
-    const ResourceLoaderOptions& options() { return m_options; }
-
 #if PLATFORM(COCOA) && !USE(CFURLCONNECTION)
     NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse*) override;
 #endif
index 0b9208c..190ccaa 100644 (file)
@@ -32,6 +32,8 @@
 
 #include "FetchOptions.h"
 #include "ResourceHandleTypes.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -119,6 +121,8 @@ struct ResourceLoaderOptions : public FetchOptions {
 
     ClientCredentialPolicy clientCredentialPolicy { ClientCredentialPolicy::CannotAskClientForCredentials };
     unsigned maxRedirectCount { 20 };
+
+    Vector<String> derivedCachedDataTypesToRetrieve;
 };
 
 } // namespace WebCore
index b6a6341..642940a 100644 (file)
@@ -621,6 +621,13 @@ void SubresourceLoader::didCancel(const ResourceError&)
     notifyDone();
 }
 
+void SubresourceLoader::didRetrieveDerivedDataFromCache(const String& type, SharedBuffer& buffer)
+{
+    if (m_state != Initialized)
+        return;
+    m_resource->didRetrieveDerivedDataFromCache(type, buffer);
+}
+
 void SubresourceLoader::notifyDone()
 {
     if (reachedTerminalState())
index f6ea66e..e6284ce 100644 (file)
@@ -75,6 +75,7 @@ private:
     void didFail(const ResourceError&) override;
     void willCancel(const ResourceError&) override;
     void didCancel(const ResourceError&) override;
+    void didRetrieveDerivedDataFromCache(const String& type, SharedBuffer&) override;
 
 #if PLATFORM(COCOA) && !USE(CFURLCONNECTION)
     NSCachedURLResponse *willCacheResponse(ResourceHandle*, NSCachedURLResponse*) override;
index c8bc0df..e29ea94 100644 (file)
@@ -258,6 +258,8 @@ public:
 
     virtual void didSendData(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { }
 
+    virtual void didRetrieveDerivedDataFromCache(const String& /* type */, SharedBuffer&) { }
+
     void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; }
     double loadFinishTime() const { return m_loadFinishTime; }
 
index 940d311..beb7da0 100644 (file)
@@ -1313,7 +1313,7 @@ void CachedResourceLoader::printPreloadStats()
 
 const ResourceLoaderOptions& CachedResourceLoader::defaultCachedResourceOptions()
 {
-    static ResourceLoaderOptions options(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, DoSecurityCheck, FetchOptions::Mode::NoCors, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching);
+    static NeverDestroyed<ResourceLoaderOptions> options(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, DoSecurityCheck, FetchOptions::Mode::NoCors, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching);
     return options;
 }
 
index f35edc6..e1fc466 100644 (file)
@@ -32,6 +32,7 @@
 #include "NetworkLoadTiming.h"
 #include "ParsedContentRange.h"
 #include "URL.h"
+#include <wtf/SHA1.h>
 
 namespace WebCore {
 
@@ -135,6 +136,9 @@ public:
     WEBCORE_EXPORT Source source() const;
     WEBCORE_EXPORT void setSource(Source);
 
+    const std::optional<SHA1::Digest>& cacheBodyKey() const { return m_cacheBodyKey; }
+    void setCacheBodyKey(const SHA1::Digest& key) { m_cacheBodyKey = key; }
+
     NetworkLoadTiming& networkLoadTiming() const { return m_networkLoadTiming; }
 
     // The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
@@ -210,6 +214,8 @@ private:
 
     Source m_source { Source::Unknown };
 
+    std::optional<SHA1::Digest> m_cacheBodyKey;
+
     Type m_type { Type::Default };
     bool m_isRedirected { false };
 };
@@ -241,6 +247,7 @@ void ResourceResponseBase::encode(Encoder& encoder) const
     encoder << m_httpStatusCode;
     encoder << m_certificateInfo;
     encoder.encodeEnum(m_source);
+    encoder << m_cacheBodyKey;
     encoder.encodeEnum(m_type);
     encoder << m_isRedirected;
 }
@@ -280,6 +287,8 @@ bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& respon
         return false;
     if (!decoder.decodeEnum(response.m_source))
         return false;
+    if (!decoder.decode(response.m_cacheBodyKey))
+        return false;
     if (!decoder.decodeEnum(response.m_type))
         return false;
     if (!decoder.decode(response.m_isRedirected))
index b5fd85c..f7ae456 100644 (file)
@@ -1,3 +1,12 @@
+2017-01-17  Antti Koivisto  <antti@apple.com>
+
+        Persist derived data
+        https://bugs.webkit.org/show_bug.cgi?id=167136
+
+        Reviewed by Andreas Kling.
+
+        * WebCoreSupport/WebResourceLoadScheduler.h:
+
 2017-01-05  Per Arne Vollan  <pvollan@apple.com>
 
         [Win] Compile error.
index 12ecb1a..e80933a 100644 (file)
@@ -56,6 +56,8 @@ public:
 
     void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, bool shouldUseCredentialStorage, bool shouldFollowRedirects) override;
 
+    void storeDerivedDataToCache(const SHA1::Digest&, const String&, const String&, WebCore::SharedBuffer&) override { }
+
     bool isSerialLoadingEnabled() const { return m_isSerialLoadingEnabled; }
     void setSerialLoadingEnabled(bool b) { m_isSerialLoadingEnabled = b; }
 
index e38a21e..5db0575 100644 (file)
@@ -1,3 +1,74 @@
+2017-01-17  Antti Koivisto  <antti@apple.com>
+
+        Persist derived data
+        https://bugs.webkit.org/show_bug.cgi?id=167136
+
+        Reviewed by Andreas Kling.
+
+        Add a mechanism for storing arbitrary data into disk cache.
+
+        From WebCore level data can be stored using
+
+            loaderStrategy()->storeDerivedDataToCache(key, partition, type, data);
+
+        The data is keyed with the body hash of a network resource. It can be retrieved along
+        with the resource by specifying the type in ResourceLoaderOptions. If a related data
+        blob is found it will be deliver via CachedResource::didRetrieveDerivedDataFromCache()
+        callback.
+
+        This patch adds the mechanism but doesn't yet use it for anything.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::storeDerivedDataToCache):
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+        * NetworkProcess/NetworkResourceLoadParameters.cpp:
+        (WebKit::NetworkResourceLoadParameters::encode):
+        (WebKit::NetworkResourceLoadParameters::decode):
+        * NetworkProcess/NetworkResourceLoadParameters.h:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
+
+            Look for related resources to return if needed.
+
+        (WebKit::NetworkResourceLoader::sendResultForCacheEntry):
+        * NetworkProcess/NetworkResourceLoader.h:
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::resourceType):
+         (WebKit::NetworkCache::Cache::retrieveData):
+        (WebKit::NetworkCache::Cache::storeData):
+        (WebKit::NetworkCache::Cache::makeCacheKey): Deleted.
+        * NetworkProcess/cache/NetworkCache.h:
+        * NetworkProcess/cache/NetworkCacheEntry.cpp:
+        (WebKit::NetworkCache::Entry::encodeAsStorageRecord):
+        (WebKit::NetworkCache::Entry::decodeStorageRecord):
+        * NetworkProcess/cache/NetworkCacheKey.cpp:
+        (WebKit::NetworkCache::Key::Key):
+        * NetworkProcess/cache/NetworkCacheKey.h:
+        (WebKit::NetworkCache::DataKey::encode):
+        (WebKit::NetworkCache::DataKey::decode):
+        * NetworkProcess/cache/NetworkCacheStorage.cpp:
+        (WebKit::NetworkCache::Storage::readRecord):
+        (WebKit::NetworkCache::Storage::traverse):
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+
+            Return body hash with the Record.
+
+        * NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp:
+        (WebKit::NetworkCache::SubresourcesEntry::encodeAsStorageRecord):
+        * Platform/IPC/ArgumentCoders.cpp:
+        (IPC::ArgumentCoder<SHA1::Digest>::encode):
+        (IPC::ArgumentCoder<SHA1::Digest>::decode):
+        * Platform/IPC/ArgumentCoders.h:
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::scheduleLoad):
+        (WebKit::WebLoaderStrategy::storeDerivedDataToCache):
+        * WebProcess/Network/WebLoaderStrategy.h:
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::didRetrieveDerivedData):
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.messages.in:
+
 2017-01-17  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] Turn modern media controls on by default
index 0794823..29085e6 100644 (file)
@@ -27,7 +27,9 @@
 #include "NetworkConnectionToWebProcess.h"
 
 #include "BlobDataFileReferenceWithSandboxExtension.h"
+#include "DataReference.h"
 #include "NetworkBlobRegistry.h"
+#include "NetworkCache.h"
 #include "NetworkConnectionToWebProcessMessages.h"
 #include "NetworkLoad.h"
 #include "NetworkProcess.h"
@@ -322,6 +324,11 @@ void NetworkConnectionToWebProcess::writeBlobsToTemporaryFiles(const Vector<Stri
     });
 }
 
+void NetworkConnectionToWebProcess::storeDerivedDataToCache(const WebKit::NetworkCache::DataKey& dataKey, const IPC::DataReference& data)
+{
+    NetworkCache::singleton().storeData(dataKey, data.data(), data.size());
+}
+
 void NetworkConnectionToWebProcess::ensureLegacyPrivateBrowsingSession()
 {
     NetworkProcess::singleton().ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
index cb0e503..fae305a 100644 (file)
@@ -44,6 +44,10 @@ class NetworkResourceLoader;
 class SyncNetworkResourceLoader;
 typedef uint64_t ResourceLoadIdentifier;
 
+namespace NetworkCache {
+struct DataKey;
+}
+
 class NetworkConnectionToWebProcess : public RefCounted<NetworkConnectionToWebProcess>, IPC::Connection::Client {
 public:
     static Ref<NetworkConnectionToWebProcess> create(IPC::Connection::Identifier);
@@ -97,6 +101,8 @@ private:
     void unregisterBlobURL(const WebCore::URL&);
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, uint64_t requestIdentifier);
 
+    void storeDerivedDataToCache(const WebKit::NetworkCache::DataKey&, const IPC::DataReference&);
+
     void ensureLegacyPrivateBrowsingSession();
 
     Ref<IPC::Connection> m_connection;
index c2f78e8..a263a4e 100644 (file)
@@ -50,5 +50,7 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver {
     BlobSize(WebCore::URL url) -> (uint64_t resultSize)
     WriteBlobsToTemporaryFiles(Vector<String> blobURLs, uint64_t requestIdentifier)
 
+    StoreDerivedDataToCache(WebKit::NetworkCache::DataKey key, IPC::DataReference data)
+
     EnsureLegacyPrivateBrowsingSession()
 }
index 49ec4a0..4e197c8 100644 (file)
@@ -80,6 +80,7 @@ void NetworkResourceLoadParameters::encode(IPC::Encoder& encoder) const
     encoder << defersLoading;
     encoder << needsCertificateInfo;
     encoder << maximumBufferingTime;
+    encoder << derivedCachedDataTypesToRetrieve;
 }
 
 bool NetworkResourceLoadParameters::decode(IPC::Decoder& decoder, NetworkResourceLoadParameters& result)
@@ -141,6 +142,8 @@ bool NetworkResourceLoadParameters::decode(IPC::Decoder& decoder, NetworkResourc
         return false;
     if (!decoder.decode(result.maximumBufferingTime))
         return false;
+    if (!decoder.decode(result.derivedCachedDataTypesToRetrieve))
+        return false;
 
     return true;
 }
index 4255ade..ee6f9cb 100644 (file)
@@ -51,6 +51,7 @@ public:
     Vector<RefPtr<SandboxExtension>> requestBodySandboxExtensions; // Created automatically for the sender.
     RefPtr<SandboxExtension> resourceSandboxExtension; // Created automatically for the sender.
     std::chrono::milliseconds maximumBufferingTime { 0ms };
+    Vector<String> derivedCachedDataTypesToRetrieve;
 };
 
 } // namespace WebKit
index 2ffe202..48b904c 100644 (file)
@@ -563,25 +563,62 @@ void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::
     if (isSynchronous()) {
         m_synchronousLoadData->response = entry->response();
         sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer());
-    } else {
-        bool needsContinueDidReceiveResponseMessage = isMainResource();
-        send(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage));
+        cleanup();
+        return;
+    }
 
-#if ENABLE(SHAREABLE_RESOURCE)
-        if (!entry->shareableResourceHandle().isNull())
-            send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime()));
-        else {
+    bool needsContinueDidReceiveResponseMessage = isMainResource();
+    send(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage));
+
+    if (entry->sourceStorageRecord().bodyHash && !m_parameters.derivedCachedDataTypesToRetrieve.isEmpty()) {
+#if ENABLE(CACHE_PARTITIONING)
+        String partition = originalRequest().cachePartition();
+#else
+        String partition;
 #endif
-            sendBuffer(*entry->buffer(), entry->buffer()->size());
-            send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime()));
-#if ENABLE(SHAREABLE_RESOURCE)
+        auto bodyHash = *entry->sourceStorageRecord().bodyHash;
+        auto* entryPtr = entry.release();
+        auto retrieveCount = m_parameters.derivedCachedDataTypesToRetrieve.size();
+
+        for (auto& type : m_parameters.derivedCachedDataTypesToRetrieve) {
+            NetworkCache::DataKey key { partition, type, bodyHash };
+            NetworkCache::singleton().retrieveData(key, [loader = makeRef(*this), entryPtr, type, retrieveCount] (const uint8_t* data, size_t size) mutable {
+                loader->m_retrievedDerivedDataCount++;
+                bool retrievedAll = loader->m_retrievedDerivedDataCount == retrieveCount;
+                std::unique_ptr<NetworkCache::Entry> entry(retrievedAll ? entryPtr : nullptr);
+                if (loader->hasOneRef())
+                    return;
+                if (data) {
+                    IPC::DataReference dataReference(data, size);
+                    loader->send(Messages::WebResourceLoader::DidRetrieveDerivedData(type, dataReference));
+                }
+                if (retrievedAll) {
+                    loader->sendResultForCacheEntry(WTFMove(entry));
+                    loader->cleanup();
+                }
+            });
         }
-#endif
+        return;
     }
 
+    sendResultForCacheEntry(WTFMove(entry));
+
     cleanup();
 }
 
+void NetworkResourceLoader::sendResultForCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
+{
+#if ENABLE(SHAREABLE_RESOURCE)
+    if (!entry->shareableResourceHandle().isNull()) {
+        send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle(), currentTime()));
+        return;
+    }
+#endif
+
+    sendBuffer(*entry->buffer(), entry->buffer()->size());
+    send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime()));
+}
+
 void NetworkResourceLoader::validateCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
 {
     ASSERT(!m_networkLoad);
index 972b2d1..fe93ee0 100644 (file)
@@ -116,6 +116,7 @@ private:
     void tryStoreAsCacheEntry();
     void retrieveCacheEntry(const WebCore::ResourceRequest&);
     void didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry>);
+    void sendResultForCacheEntry(std::unique_ptr<NetworkCache::Entry>);
     void validateCacheEntry(std::unique_ptr<NetworkCache::Entry>);
     void dispatchWillSendRequestForCacheEntry(std::unique_ptr<NetworkCache::Entry>);
 #endif
@@ -154,6 +155,8 @@ private:
     bool m_defersLoading { false };
     bool m_hasReceivedData { false };
 
+    unsigned m_retrievedDerivedDataCount { 0 };
+
     WebCore::Timer m_bufferingTimer;
 #if ENABLE(NETWORK_CACHE)
     RefPtr<WebCore::SharedBuffer> m_bufferedDataForCache;
index a80291f..d0fa67d 100644 (file)
@@ -351,7 +351,7 @@ void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameI
     auto startTime = std::chrono::system_clock::now();
     auto priority = static_cast<unsigned>(request.priority());
 
-    m_storage->retrieve(storageKey, priority, [this, request, completionHandler = WTFMove(completionHandler), startTime, storageKey, frameID](std::unique_ptr<Storage::Record> record) {
+    m_storage->retrieve(storageKey, priority, [this, request, completionHandler = WTFMove(completionHandler), startTime, storageKey, frameID](auto record) {
         if (!record) {
             LOG(NetworkCache, "(NetworkProcess) not found in storage");
 
@@ -615,6 +615,30 @@ String Cache::recordsPath() const
     return m_storage ? m_storage->recordsPath() : String();
 }
 
+void Cache::retrieveData(const DataKey& dataKey, Function<void (const uint8_t* data, size_t size)> completionHandler)
+{
+    ASSERT(isEnabled());
+
+    Key key { dataKey, m_storage->salt() };
+    m_storage->retrieve(key, 4, [completionHandler = WTFMove(completionHandler)] (auto record) {
+        if (!record || !record->body.size()) {
+            completionHandler(nullptr, 0);
+            return true;
+        }
+        completionHandler(record->body.data(), record->body.size());
+        return true;
+    });
+}
+
+void Cache::storeData(const DataKey& dataKey, const uint8_t* data, size_t size)
+{
+    if (!m_storage)
+        return;
+    Key key { dataKey, m_storage->salt() };
+    Storage::Record record { key, std::chrono::system_clock::now(), { }, Data { data, size }, { } };
+    m_storage->store(record, { });
+}
+
 }
 }
 
index 4794efa..64a154d 100644 (file)
@@ -121,6 +121,9 @@ public:
     void clear();
     void clear(std::chrono::system_clock::time_point modifiedSince, Function<void ()>&& completionHandler);
 
+    void retrieveData(const DataKey&, Function<void (const uint8_t* data, size_t size)>);
+    void storeData(const DataKey&,  const uint8_t* data, size_t);
+
     void dumpContentsToFile();
 
     String recordsPath() const;
index 312dc87..a94dfef 100644 (file)
@@ -101,7 +101,7 @@ Storage::Record Entry::encodeAsStorageRecord() const
     if (m_buffer)
         body = { reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size() };
 
-    return { m_key, m_timeStamp, header, body };
+    return { m_key, m_timeStamp, header, body, { } };
 }
 
 std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storageEntry)
@@ -112,6 +112,8 @@ std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storage
     if (!decoder.decode(entry->m_response))
         return nullptr;
     entry->m_response.setSource(WebCore::ResourceResponse::Source::DiskCache);
+    if (storageEntry.bodyHash)
+        entry->m_response.setCacheBodyKey(*storageEntry.bodyHash);
 
     bool hasVaryingRequestHeaders;
     if (!decoder.decode(hasVaryingRequestHeaders))
index faa9f6c..cce50a7 100644 (file)
@@ -64,6 +64,15 @@ Key::Key(WTF::HashTableDeletedValueType)
 {
 }
 
+Key::Key(const DataKey& dataKey, const Salt& salt)
+    : m_partition(dataKey.partition)
+    , m_type(dataKey.type)
+    , m_identifier(hashAsString(dataKey.identifier))
+    , m_hash(computeHash(salt))
+    , m_partitionHash(computePartitionHash(salt))
+{
+}
+
 Key& Key::operator=(const Key& other)
 {
     m_partition = other.m_partition.isolatedCopy();
index a25a83c..439ebf0 100644 (file)
 namespace WebKit {
 namespace NetworkCache {
 
+struct DataKey {
+    String partition;
+    String type;
+    SHA1::Digest identifier;
+
+    template <class Encoder> void encode(Encoder& encoder) const
+    {
+        encoder << partition << type << identifier;
+    }
+
+    template <class Decoder> static bool decode(Decoder& decoder, DataKey& dataKey)
+    {
+        return decoder.decode(dataKey.partition) && decoder.decode(dataKey.type) && decoder.decode(dataKey.identifier);
+    }
+};
+
 class Key {
 public:
     typedef SHA1::Digest HashType;
@@ -44,6 +60,7 @@ public:
     Key(const Key&);
     Key(Key&&) = default;
     Key(const String& partition, const String& type, const String& range, const String& identifier, const Salt&);
+    Key(const DataKey&, const Salt&);
 
     Key& operator=(const Key&);
     Key& operator=(Key&&) = default;
index 8f7b6e3..15cc902 100644 (file)
@@ -458,7 +458,8 @@ void Storage::readRecord(ReadOperation& readOperation, const Data& recordData)
         metaData.key,
         timeStamp,
         headerData,
-        bodyData
+        bodyData,
+        metaData.bodyHash
     });
 }
 
@@ -837,7 +838,8 @@ void Storage::traverse(const String& type, TraverseFlags flags, TraverseHandler&
                         metaData.key,
                         std::chrono::system_clock::time_point(metaData.epochRelativeTimeStamp),
                         headerData,
-                        { }
+                        { },
+                        metaData.bodyHash
                     };
                     RecordInfo info {
                         static_cast<size_t>(metaData.bodySize),
index 023e84a..8994339 100644 (file)
@@ -57,6 +57,7 @@ public:
         std::chrono::system_clock::time_point timeStamp;
         Data header;
         Data body;
+        std::optional<SHA1::Digest> bodyHash;
     };
     // This may call completion handler synchronously on failure.
     typedef Function<bool (std::unique_ptr<Record>)> RetrieveCompletionHandler;
index d47a527..9d7b9b7 100644 (file)
@@ -70,7 +70,7 @@ Storage::Record SubresourcesEntry::encodeAsStorageRecord() const
 
     encoder.encodeChecksum();
 
-    return { m_key, m_timeStamp, { encoder.buffer(), encoder.bufferSize() } , { } };
+    return { m_key, m_timeStamp, { encoder.buffer(), encoder.bufferSize() }, { }, { }};
 }
 
 std::unique_ptr<SubresourcesEntry> SubresourcesEntry::decodeStorageRecord(const Storage::Record& storageEntry)
index 9ac76c6..0c98642 100644 (file)
@@ -162,4 +162,15 @@ bool ArgumentCoder<String>::decode(Decoder& decoder, String& result)
     return decodeStringText<UChar>(decoder, length, result);
 }
 
+
+void ArgumentCoder<SHA1::Digest>::encode(Encoder& encoder, const SHA1::Digest& digest)
+{
+    encoder.encodeFixedLengthData(digest.data(), sizeof(digest), 1);
+}
+
+bool ArgumentCoder<SHA1::Digest>::decode(Decoder& decoder, SHA1::Digest& digest)
+{
+    return decoder.decodeFixedLengthData(digest.data(), sizeof(digest), 1);
+}
+
 } // namespace IPC
index f6d88b7..86166c8 100644 (file)
@@ -34,6 +34,7 @@
 #include <wtf/HashSet.h>
 #include <wtf/OptionSet.h>
 #include <wtf/Optional.h>
+#include <wtf/SHA1.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>
 
@@ -399,4 +400,9 @@ template<> struct ArgumentCoder<String> {
     static bool decode(Decoder&, String&);
 };
 
+template<> struct ArgumentCoder<SHA1::Digest> {
+    static void encode(Encoder&, const SHA1::Digest&);
+    static bool decode(Decoder&, SHA1::Digest&);
+};
+
 } // namespace IPC
index 1210251..19d42b8 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WebLoaderStrategy.h"
 
+#include "DataReference.h"
 #include "HangDetectionDisabler.h"
 #include "Logging.h"
 #include "NetworkConnectionToWebProcessMessages.h"
@@ -216,6 +217,7 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou
     loadParameters.defersLoading = resourceLoader.defersLoading();
     loadParameters.needsCertificateInfo = resourceLoader.shouldIncludeCertificateInfo();
     loadParameters.maximumBufferingTime = maximumBufferingTime(resource);
+    loadParameters.derivedCachedDataTypesToRetrieve = resourceLoader.options().derivedCachedDataTypesToRetrieve;
 
     ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials);
 
@@ -375,5 +377,11 @@ void WebLoaderStrategy::createPingHandle(NetworkingContext* networkingContext, R
     WebProcess::singleton().networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::LoadPing(loadParameters), 0);
 }
 
+void WebLoaderStrategy::storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer& data)
+{
+    NetworkCache::DataKey key { partition, type, bodyHash };
+    IPC::SharedBufferDataReference dataReference { &data };
+    WebProcess::singleton().networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::StoreDerivedDataToCache(key, dataReference), 0);
+}
 
 } // namespace WebKit
index 72d09eb..b7e1b19 100644 (file)
@@ -57,6 +57,8 @@ public:
 
     void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, bool shouldUseCredentialStorage, bool shouldFollowRedirects) override;
 
+    void storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer&) override;
+
     WebResourceLoader* webResourceLoaderForIdentifier(ResourceLoadIdentifier identifier) const { return m_webResourceLoaders.get(identifier); }
     RefPtr<WebCore::NetscapePlugInStreamLoader> schedulePluginStreamLoad(WebCore::Frame&, WebCore::NetscapePlugInStreamLoaderClient&, const WebCore::ResourceRequest&);
 
index 738b1dc..974df53 100644 (file)
@@ -135,6 +135,14 @@ void WebResourceLoader::didReceiveData(const IPC::DataReference& data, int64_t e
     m_coreLoader->didReceiveData(reinterpret_cast<const char*>(data.data()), data.size(), encodedDataLength, DataPayloadBytes);
 }
 
+void WebResourceLoader::didRetrieveDerivedData(const String& type, const IPC::DataReference& data)
+{
+    LOG(Network, "(WebProcess) WebResourceLoader::didRetrieveDerivedData of size %lu for '%s'", data.size(), m_coreLoader->url().string().latin1().data());
+
+    auto buffer = SharedBuffer::create(data.data(), data.size());
+    m_coreLoader->didRetrieveDerivedDataFromCache(type, buffer.get());
+}
+
 void WebResourceLoader::didFinishResourceLoad(double finishTime)
 {
     LOG(Network, "(WebProcess) WebResourceLoader::didFinishResourceLoad for '%s'", m_coreLoader->url().string().latin1().data());
index 0b8bdf2..9e391b5 100644 (file)
@@ -78,6 +78,7 @@ private:
     void didSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent);
     void didReceiveResponse(const WebCore::ResourceResponse&, bool needsContinueDidReceiveResponseMessage);
     void didReceiveData(const IPC::DataReference&, int64_t encodedDataLength);
+    void didRetrieveDerivedData(const String& type, const IPC::DataReference&);
     void didFinishResourceLoad(double finishTime);
     void didFailResourceLoad(const WebCore::ResourceError&);
 #if ENABLE(SHAREABLE_RESOURCE)
index 2f1908c..842e0a4 100644 (file)
@@ -26,6 +26,7 @@ messages -> WebResourceLoader LegacyReceiver {
     DidReceiveResponse(WebCore::ResourceResponse response, bool needsContinueDidReceiveResponseMessage)
     DidReceiveData(IPC::DataReference data, int64_t encodedDataLength)
     DidFinishResourceLoad(double finishTime)
+    DidRetrieveDerivedData(String type, IPC::DataReference data)
     DidFailResourceLoad(WebCore::ResourceError error)
 
 #if ENABLE(SHAREABLE_RESOURCE)