Title: [192111] trunk/Source/WebKit2
Revision
192111
Author
[email protected]
Date
2015-11-06 11:29:24 -0800 (Fri, 06 Nov 2015)

Log Message

[WK2][SpeculativeRevalidation] Save to disk cache relationship between resources
https://bugs.webkit.org/show_bug.cgi?id=150951
<rdar://problem/23092196>

Reviewed by Darin Adler.

This patch is a first step towards speculative revalidation support in
the WebKit network cache. It maps sub-resources to the main resource
that caused them to be requested. We then write this information to the
network cache, as a list of subresource keys for each main resource,
even if the main resource is not cacheable.

To map sub-resources to main resources, we track the loads happening
in each frame and store the key of the main resource for the frame,
as well as the key of each sub-resource later loaded in the frame. We
use a HysteresisActivity to detect when loads settle down in each frame
(no loads happen for a while) and we then write the information to the
disk. If a new main resource is loaded in a frame where we were already
tracking a load, we save the data to disk before tracking the new load,
instead of waiting for the HysteresisActivity to detect the end of the
load.

The feature is currently behind a compile-time flag that is enabled on
Mac and iOS only. It is also behind a runtime flag (NSUserDefaults)
that is disabled by default.

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::start):
Pass frameID in addition to the pageID. We need to globally identify
frames (using <pageID, frameID> pair) to be able to track loads in
each frame.

* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::Cache::initialize):
Only initialize the SpeculativeLoader if the
enableNetworkCacheSpeculativeRevalidation run-time flag is set.

(WebKit::NetworkCache::Cache::retrieve):
Register the load with the SpeculativeLoader.

* NetworkProcess/cache/NetworkCacheKey.h:
(WebKit::NetworkCache::Key::Key):
(WebKit::NetworkCache::Key::isHashTableDeletedValue):
(WebKit::NetworkCache::Key::range):
(WTF::NetworkCacheKeyHash::hash):
(WTF::NetworkCacheKeyHash::equal):
(WTF::HashTraits<WebKit::NetworkCache::Key>::isEmptyValue):
Add needed HashTraits for NetworkCache::Key so it can be used as key in
HashMap / HashSet.

* NetworkProcess/cache/NetworkCacheSpeculativeLoader.cpp: Added.
* NetworkProcess/cache/NetworkCacheSpeculativeLoader.h: Added.
Add new NetworkCacheSpeculativeLoader class that takes care of tracking
loads in each frame to map subresources to main resources and then write
this information to the network disk cache. In the future, this class we
also take care of triggering speculative revalidations, thus the naming.

* NetworkProcess/cocoa/NetworkProcessCocoa.mm:
(WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
* NetworkProcess/soup/NetworkProcessSoup.cpp:
(WebKit::NetworkProcess::platformInitializeNetworkProcess):
* Shared/Network/NetworkProcessCreationParameters.cpp:
(WebKit::NetworkProcessCreationParameters::encode):
(WebKit::NetworkProcessCreationParameters::decode):
* Shared/Network/NetworkProcessCreationParameters.h:
* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::registerUserDefaultsIfNeeded):
(WebKit::WebProcessPool::platformInitializeNetworkProcess):
Add new NetworkProcess parameter to control at runtime if speculative loading
should be enabled or not. It is disabled by default.

* WebKit2.xcodeproj/project.pbxproj:
Add new files to XCode project.

* config.h:
Add ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION build flag for the new
feature that is enable by default on COCOA.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (192110 => 192111)


--- trunk/Source/WebKit2/ChangeLog	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/ChangeLog	2015-11-06 19:29:24 UTC (rev 192111)
@@ -1,5 +1,85 @@
 2015-11-06  Chris Dumez  <[email protected]>
 
+        [WK2][SpeculativeRevalidation] Save to disk cache relationship between resources
+        https://bugs.webkit.org/show_bug.cgi?id=150951
+        <rdar://problem/23092196>
+
+        Reviewed by Darin Adler.
+
+        This patch is a first step towards speculative revalidation support in
+        the WebKit network cache. It maps sub-resources to the main resource
+        that caused them to be requested. We then write this information to the
+        network cache, as a list of subresource keys for each main resource,
+        even if the main resource is not cacheable.
+
+        To map sub-resources to main resources, we track the loads happening
+        in each frame and store the key of the main resource for the frame,
+        as well as the key of each sub-resource later loaded in the frame. We
+        use a HysteresisActivity to detect when loads settle down in each frame
+        (no loads happen for a while) and we then write the information to the
+        disk. If a new main resource is loaded in a frame where we were already
+        tracking a load, we save the data to disk before tracking the new load,
+        instead of waiting for the HysteresisActivity to detect the end of the
+        load.
+
+        The feature is currently behind a compile-time flag that is enabled on
+        Mac and iOS only. It is also behind a runtime flag (NSUserDefaults)
+        that is disabled by default.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::start):
+        Pass frameID in addition to the pageID. We need to globally identify
+        frames (using <pageID, frameID> pair) to be able to track loads in
+        each frame.
+
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::Cache::initialize):
+        Only initialize the SpeculativeLoader if the
+        enableNetworkCacheSpeculativeRevalidation run-time flag is set.
+
+        (WebKit::NetworkCache::Cache::retrieve):
+        Register the load with the SpeculativeLoader.
+
+        * NetworkProcess/cache/NetworkCacheKey.h:
+        (WebKit::NetworkCache::Key::Key):
+        (WebKit::NetworkCache::Key::isHashTableDeletedValue):
+        (WebKit::NetworkCache::Key::range):
+        (WTF::NetworkCacheKeyHash::hash):
+        (WTF::NetworkCacheKeyHash::equal):
+        (WTF::HashTraits<WebKit::NetworkCache::Key>::isEmptyValue):
+        Add needed HashTraits for NetworkCache::Key so it can be used as key in
+        HashMap / HashSet.
+
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoader.cpp: Added.
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoader.h: Added.
+        Add new NetworkCacheSpeculativeLoader class that takes care of tracking
+        loads in each frame to map subresources to main resources and then write
+        this information to the network disk cache. In the future, this class we
+        also take care of triggering speculative revalidations, thus the naming.
+
+        * NetworkProcess/cocoa/NetworkProcessCocoa.mm:
+        (WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
+        * NetworkProcess/soup/NetworkProcessSoup.cpp:
+        (WebKit::NetworkProcess::platformInitializeNetworkProcess):
+        * Shared/Network/NetworkProcessCreationParameters.cpp:
+        (WebKit::NetworkProcessCreationParameters::encode):
+        (WebKit::NetworkProcessCreationParameters::decode):
+        * Shared/Network/NetworkProcessCreationParameters.h:
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::registerUserDefaultsIfNeeded):
+        (WebKit::WebProcessPool::platformInitializeNetworkProcess):
+        Add new NetworkProcess parameter to control at runtime if speculative loading
+        should be enabled or not. It is disabled by default.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        Add new files to XCode project.
+
+        * config.h:
+        Add ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION build flag for the new
+        feature that is enable by default on COCOA.
+
+2015-11-06  Chris Dumez  <[email protected]>
+
         Unreviewed, remove empty #if block landed by mistake in r192038.
 
         * NetworkProcess/NetworkLoad.cpp:

Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -128,7 +128,7 @@
     }
 
     RefPtr<NetworkResourceLoader> loader(this);
-    NetworkCache::singleton().retrieve(originalRequest(), m_parameters.webPageID, [loader](std::unique_ptr<NetworkCache::Entry> entry) {
+    NetworkCache::singleton().retrieve(originalRequest(), m_parameters.webPageID, m_parameters.webFrameID, [loader](std::unique_ptr<NetworkCache::Entry> entry) {
         if (loader->hasOneRef()) {
             // The loader has been aborted and is only held alive by this lambda.
             return;

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -29,6 +29,7 @@
 #if ENABLE(NETWORK_CACHE)
 
 #include "Logging.h"
+#include "NetworkCacheSpeculativeLoader.h"
 #include "NetworkCacheStatistics.h"
 #include "NetworkCacheStorage.h"
 #include <WebCore/CacheValidation.h>
@@ -71,11 +72,16 @@
 }
 #endif
 
-bool Cache::initialize(const String& cachePath, bool enableEfficacyLogging)
+bool Cache::initialize(const String& cachePath, const Parameters& parameters)
 {
     m_storage = Storage::open(cachePath);
 
-    if (enableEfficacyLogging)
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    if (parameters.enableNetworkCacheSpeculativeRevalidation)
+        m_speculativeLoader = std::make_unique<SpeculativeLoader>(*m_storage);
+#endif
+
+    if (parameters.enableEfficacyLogging)
         m_statistics = Statistics::open(cachePath);
 
 #if PLATFORM(COCOA)
@@ -337,7 +343,7 @@
     return StoreDecision::Yes;
 }
 
-void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t webPageID, std::function<void (std::unique_ptr<Entry>)> completionHandler)
+void Cache::retrieve(const WebCore::ResourceRequest& originalRequest, uint64_t webPageID, uint64_t webFrameID, std::function<void (std::unique_ptr<Entry>)> completionHandler)
 {
     ASSERT(isEnabled());
     ASSERT(originalRequest.url().protocolIsInHTTPFamily());
@@ -348,6 +354,14 @@
         m_statistics->recordRetrievalRequest(webPageID);
 
     Key storageKey = makeCacheKey(originalRequest);
+
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    if (m_speculativeLoader)
+        m_speculativeLoader->registerLoad(webPageID, webFrameID, originalRequest, storageKey);
+#else
+    UNUSED_PARAM(webFrameID);
+#endif
+
     auto retrieveDecision = makeRetrieveDecision(originalRequest);
     if (retrieveDecision != RetrieveDecision::Yes) {
         if (m_statistics)

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -44,6 +44,7 @@
 namespace NetworkCache {
 
 class Cache;
+class SpeculativeLoader;
 class Statistics;
 
 Cache& singleton();
@@ -87,13 +88,19 @@
     WTF_MAKE_NONCOPYABLE(Cache);
     friend class WTF::NeverDestroyed<Cache>;
 public:
-    bool initialize(const String& cachePath, bool enableEfficacyLogging);
+    struct Parameters {
+        bool enableEfficacyLogging;
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+        bool enableNetworkCacheSpeculativeRevalidation;
+#endif
+    };
+    bool initialize(const String& cachePath, const Parameters&);
     void setCapacity(size_t);
 
     bool isEnabled() const { return !!m_storage; }
 
     // Completion handler may get called back synchronously on failure.
-    void retrieve(const WebCore::ResourceRequest&, uint64_t webPageID, std::function<void (std::unique_ptr<Entry>)>);
+    void retrieve(const WebCore::ResourceRequest&, uint64_t webPageID, uint64_t webFrameID, std::function<void (std::unique_ptr<Entry>)>);
     void store(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, std::function<void (MappedBody&)>);
     void update(const WebCore::ResourceRequest&, uint64_t webPageID, const Entry&, const WebCore::ResourceResponse& validatingResponse);
 
@@ -116,6 +123,9 @@
     void deleteDumpFile();
 
     std::unique_ptr<Storage> m_storage;
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    std::unique_ptr<SpeculativeLoader> m_speculativeLoader;
+#endif
     std::unique_ptr<Statistics> m_statistics;
 };
 

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -79,7 +79,7 @@
 
 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))

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -46,6 +46,7 @@
     WTF_MAKE_NONCOPYABLE(Entry); WTF_MAKE_FAST_ALLOCATED;
 public:
     Entry(const Key&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, const Vector<std::pair<String, String>>& varyingRequestHeaders);
+    explicit Entry(const Storage::Record&);
 
     Storage::Record encodeAsStorageRecord() const;
     static std::unique_ptr<Entry> decodeStorageRecord(const Storage::Record&);
@@ -68,7 +69,6 @@
     void asJSON(StringBuilder&, const Storage::RecordInfo&) const;
 
 private:
-    Entry(const Storage::Record&);
     void initializeBufferFromStorageRecord() const;
 #if ENABLE(SHAREABLE_RESOURCE)
     void initializeShareableResourceHandleFromStorageRecord() const;

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -54,6 +54,11 @@
 {
 }
 
+Key::Key(WTF::HashTableDeletedValueType)
+    : m_identifier(WTF::HashTableDeletedValue)
+{
+}
+
 Key& Key::operator=(const Key& other)
 {
     m_partition = other.m_partition.isolatedCopy();

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -49,11 +49,15 @@
     Key& operator=(const Key&);
     Key& operator=(Key&&) = default;
 
+    Key(WTF::HashTableDeletedValueType);
+    bool isHashTableDeletedValue() const { return m_identifier.isHashTableDeletedValue(); }
+
     bool isNull() const { return m_identifier.isNull(); }
 
     const String& partition() const { return m_partition; }
     const String& identifier() const { return m_identifier; }
     const String& type() const { return m_type; }
+    const String& range() const { return m_range; }
 
     HashType hash() const { return m_hash; }
 
@@ -81,5 +85,36 @@
 }
 }
 
+namespace WTF {
+
+struct NetworkCacheKeyHash {
+    static unsigned hash(const WebKit::NetworkCache::Key& key)
+    {
+        static_assert(SHA1::hashSize >= sizeof(unsigned), "Hash size must be greater than sizeof(unsigned)");
+        return *reinterpret_cast<const unsigned*>(key.hash().data());
+    }
+
+    static bool equal(const WebKit::NetworkCache::Key& a, const WebKit::NetworkCache::Key& b)
+    {
+        return a == b;
+    }
+
+    static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<WebKit::NetworkCache::Key> {
+    typedef NetworkCacheKeyHash Hash;
+};
+
+template<> struct HashTraits<WebKit::NetworkCache::Key> : SimpleClassHashTraits<WebKit::NetworkCache::Key> {
+    static const bool emptyValueIsZero = false;
+
+    static const bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const WebKit::NetworkCache::Key& key) { return key.isNull(); }
+};
+
+} // namespace WTF
+
 #endif
 #endif

Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.cpp (0 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.cpp	                        (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+#include "NetworkCacheSpeculativeLoader.h"
+
+#include "Logging.h"
+#include "NetworkCacheSubresourcesEntry.h"
+#include <WebCore/HysteresisActivity.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RunLoop.h>
+
+namespace WebKit {
+
+namespace NetworkCache {
+
+using namespace WebCore;
+
+static const AtomicString& subresourcesType()
+{
+    ASSERT(RunLoop::isMain());
+    static NeverDestroyed<const AtomicString> resource("subresources", AtomicString::ConstructFromLiteral);
+    return resource;
+}
+
+static inline Key makeSubresourcesKey(const Key& resourceKey)
+{
+    return Key(resourceKey.partition(), subresourcesType(), resourceKey.range(), resourceKey.identifier());
+}
+
+class SpeculativeLoader::PendingFrameLoad {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    PendingFrameLoad(const Key& mainResourceKey, std::function<void()> completionHandler)
+        : m_mainResourceKey(mainResourceKey)
+        , m_completionHandler(completionHandler)
+        , m_loadHysteresisActivity([this](HysteresisState state) { if (state == HysteresisState::Stopped) m_completionHandler(); })
+    { }
+
+    void registerSubresource(const Key& subresourceKey)
+    {
+        ASSERT(RunLoop::isMain());
+        m_subresourceKeys.add(subresourceKey);
+        m_loadHysteresisActivity.impulse();
+    }
+
+    Optional<Storage::Record> encodeAsSubresourcesRecord()
+    {
+        ASSERT(RunLoop::isMain());
+        if (m_subresourceKeys.isEmpty())
+            return { };
+
+        auto subresourcesStorageKey = makeSubresourcesKey(m_mainResourceKey);
+        Vector<Key> subresourceKeys;
+        copyToVector(m_subresourceKeys, subresourceKeys);
+
+#if !LOG_DISABLED
+        LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) Saving to disk list of subresources for '%s':", m_mainResourceKey.identifier().utf8().data());
+        for (auto& subresourceKey : subresourceKeys)
+            LOG(NetworkCacheSpeculativePreloading, "(NetworkProcess) * Subresource: '%s'.", subresourceKey.identifier().utf8().data());
+#endif
+
+        return SubresourcesEntry(subresourcesStorageKey, WTF::move(subresourceKeys)).encodeAsStorageRecord();
+    }
+
+    void markAsCompleted()
+    {
+        ASSERT(RunLoop::isMain());
+        m_completionHandler();
+    }
+
+private:
+    Key m_mainResourceKey;
+    HashSet<Key> m_subresourceKeys;
+    std::function<void()> m_completionHandler;
+    HysteresisActivity m_loadHysteresisActivity;
+};
+
+SpeculativeLoader::SpeculativeLoader(Storage& storage)
+    : m_storage(storage)
+{
+}
+
+SpeculativeLoader::~SpeculativeLoader()
+{
+}
+
+void SpeculativeLoader::registerLoad(uint64_t webPageID, uint64_t webFrameID, const ResourceRequest& request, const Key& resourceKey)
+{
+    ASSERT(RunLoop::isMain());
+
+    if (!request.url().protocolIsInHTTPFamily() || request.httpMethod() != "GET")
+        return;
+
+    auto frameKey = std::make_pair(webPageID, webFrameID);
+    auto isMainResource = request.requester() == ResourceRequest::Requester::Main;
+    if (isMainResource) {
+        // Mark previous load in this frame as completed if necessary.
+        if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameKey))
+            pendingFrameLoad->markAsCompleted();
+
+        // Start tracking loads in this frame.
+        m_pendingFrameLoads.add(frameKey, std::make_unique<PendingFrameLoad>(resourceKey, [this, frameKey]() {
+            auto frameLoad = m_pendingFrameLoads.take(frameKey);
+            auto optionalRecord = frameLoad->encodeAsSubresourcesRecord();
+            if (!optionalRecord)
+                return;
+            m_storage.store(optionalRecord.value(), [](const Data&) { });
+        }));
+        return;
+    }
+
+    if (auto* pendingFrameLoad = m_pendingFrameLoads.get(frameKey))
+        pendingFrameLoad->registerSubresource(resourceKey);
+}
+
+} // namespace NetworkCache
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)

Copied: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.h (from rev 192110, trunk/Source/WebKit2/Platform/Logging.h) (0 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.h	                        (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoader.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheSpeculativeLoader_h
+#define NetworkCacheSpeculativeLoader_h
+
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+
+#include "NetworkCacheStorage.h"
+#include <WebCore/ResourceRequest.h>
+#include <wtf/HashMap.h>
+
+namespace WebKit {
+
+namespace NetworkCache {
+
+class SpeculativeLoader {
+public:
+    explicit SpeculativeLoader(Storage&);
+    ~SpeculativeLoader();
+
+    void registerLoad(uint64_t webPageID, uint64_t webFrameID, const WebCore::ResourceRequest&, const Key& resourceKey);
+
+private:
+    Storage& m_storage;
+
+    class PendingFrameLoad;
+    using GlobalFrameID = std::pair<uint64_t /*webPageID*/, uint64_t /*webFrameID*/>;
+    HashMap<GlobalFrameID, std::unique_ptr<PendingFrameLoad>> m_pendingFrameLoads;
+};
+
+} // namespace NetworkCache
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+
+#endif // NetworkCacheSpeculativeLoader_h

Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp (0 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp	                        (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+#include "NetworkCacheSubresourcesEntry.h"
+
+#include "Logging.h"
+#include "NetworkCacheCoders.h"
+#include "NetworkCacheDecoder.h"
+#include "NetworkCacheEncoder.h"
+
+namespace WebKit {
+namespace NetworkCache {
+
+Storage::Record SubresourcesEntry::encodeAsStorageRecord() const
+{
+    Encoder encoder;
+    encoder << m_subresourceKeys;
+
+    encoder.encodeChecksum();
+
+    return { m_key, m_timeStamp, { encoder.buffer(), encoder.bufferSize() } , { } };
+}
+
+std::unique_ptr<SubresourcesEntry> SubresourcesEntry::decodeStorageRecord(const Storage::Record& storageEntry)
+{
+    auto entry = std::make_unique<SubresourcesEntry>(storageEntry);
+
+    Decoder decoder(storageEntry.header.data(), storageEntry.header.size());
+    if (!decoder.decode(entry->m_subresourceKeys))
+        return nullptr;
+
+    if (!decoder.verifyChecksum()) {
+        LOG(NetworkCache, "(NetworkProcess) checksum verification failure\n");
+        return nullptr;
+    }
+
+    return entry;
+}
+
+SubresourcesEntry::SubresourcesEntry(const Storage::Record& storageEntry)
+    : m_key(storageEntry.key)
+    , m_timeStamp(storageEntry.timeStamp)
+{
+    ASSERT(m_key.type() == "subresources");
+}
+
+SubresourcesEntry::SubresourcesEntry(const Key& key, Vector<Key>&& subresourceKeys)
+    : m_key(key)
+    , m_timeStamp(std::chrono::system_clock::now())
+    , m_subresourceKeys(WTF::move(subresourceKeys))
+{
+    ASSERT(m_key.type() == "subresources");
+}
+
+} // namespace WebKit
+} // namespace NetworkCache
+
+#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)

Copied: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h (from rev 192110, trunk/Source/WebKit2/Platform/Logging.h) (0 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h	                        (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSubresourcesEntry.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheSubresourcesEntry_h
+#define NetworkCacheSubresourcesEntry_h
+
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+
+#include "NetworkCacheStorage.h"
+
+namespace WebKit {
+namespace NetworkCache {
+
+class SubresourcesEntry {
+    WTF_MAKE_NONCOPYABLE(SubresourcesEntry); WTF_MAKE_FAST_ALLOCATED;
+public:
+    SubresourcesEntry(const Key&, Vector<Key>&& subresourceKeys);
+    explicit SubresourcesEntry(const Storage::Record&);
+
+    Storage::Record encodeAsStorageRecord() const;
+    static std::unique_ptr<SubresourcesEntry> decodeStorageRecord(const Storage::Record&);
+
+    const Key& key() const { return m_key; }
+    std::chrono::system_clock::time_point timeStamp() const { return m_timeStamp; }
+    const Vector<Key>& subresourceKeys() const { return m_subresourceKeys; }
+
+private:
+    Key m_key;
+    std::chrono::system_clock::time_point m_timeStamp;
+    Storage::Record m_sourceStorageRecord;
+    Vector<Key> m_subresourceKeys;
+};
+
+} // namespace WebKit
+} // namespace NetworkCache
+
+#endif // ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+#endif // NetworkCacheSubresourcesEntry_h

Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm	2015-11-06 19:29:24 UTC (rev 192111)
@@ -95,10 +95,18 @@
     if (!m_diskCacheDirectory.isNull()) {
         SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
 #if ENABLE(NETWORK_CACHE)
-        if (parameters.shouldEnableNetworkCache && NetworkCache::singleton().initialize(m_diskCacheDirectory, parameters.shouldEnableNetworkCacheEfficacyLogging)) {
-            RetainPtr<NSURLCache> urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
-            [NSURLCache setSharedURLCache:urlCache.get()];
-            return;
+        if (parameters.shouldEnableNetworkCache) {
+            NetworkCache::Cache::Parameters cacheParameters = {
+                parameters.shouldEnableNetworkCacheEfficacyLogging
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+                , parameters.shouldEnableNetworkCacheSpeculativeRevalidation
+#endif
+            };
+            if (NetworkCache::singleton().initialize(m_diskCacheDirectory, cacheParameters)) {
+                auto urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
+                [NSURLCache setSharedURLCache:urlCache.get()];
+                return;
+            }
         }
 #endif
         String nsURLCacheDirectory = m_diskCacheDirectory;

Modified: trunk/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp (192110 => 192111)


--- trunk/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/NetworkProcess/soup/NetworkProcessSoup.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -74,7 +74,7 @@
     // Clear the old soup cache if it exists.
     SoupNetworkSession::defaultSession().clearCache(WebCore::directoryName(m_diskCacheDirectory));
 
-    NetworkCache::singleton().initialize(m_diskCacheDirectory, parameters.shouldEnableNetworkCacheEfficacyLogging);
+    NetworkCache::singleton().initialize(m_diskCacheDirectory, { parameters.shouldEnableNetworkCacheEfficacyLogging });
 #else
     // We used to use the given cache directory for the soup cache, but now we use a subdirectory to avoid
     // conflicts with other cache files in the same directory. Remove the old cache files if they still exist.

Modified: trunk/Source/WebKit2/Platform/Logging.h (192110 => 192111)


--- trunk/Source/WebKit2/Platform/Logging.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/Platform/Logging.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -46,6 +46,7 @@
     M(Network) \
     M(NetworkCache) \
     M(NetworkCacheStorage) \
+    M(NetworkCacheSpeculativePreloading) \
     M(NetworkScheduling) \
     M(Plugins) \
     M(Printing) \

Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp (192110 => 192111)


--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp	2015-11-06 19:29:24 UTC (rev 192111)
@@ -51,7 +51,10 @@
 #if ENABLE(NETWORK_CACHE)
     encoder << shouldEnableNetworkCache;
     encoder << shouldEnableNetworkCacheEfficacyLogging;
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    encoder << shouldEnableNetworkCacheSpeculativeRevalidation;
 #endif
+#endif
 #if ENABLE(SECCOMP_FILTERS)
     encoder << cookieStorageDirectory;
 #endif
@@ -104,7 +107,11 @@
         return false;
     if (!decoder.decode(result.shouldEnableNetworkCacheEfficacyLogging))
         return false;
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    if (!decoder.decode(result.shouldEnableNetworkCacheSpeculativeRevalidation))
+        return false;
 #endif
+#endif
 #if ENABLE(SECCOMP_FILTERS)
     if (!decoder.decode(result.cookieStorageDirectory))
         return false;

Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h (192110 => 192111)


--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -60,7 +60,10 @@
 #if ENABLE(NETWORK_CACHE)
     bool shouldEnableNetworkCache;
     bool shouldEnableNetworkCacheEfficacyLogging;
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    bool shouldEnableNetworkCacheSpeculativeRevalidation;
 #endif
+#endif
 #if ENABLE(SECCOMP_FILTERS)
     String cookieStorageDirectory;
 #endif

Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm (192110 => 192111)


--- trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2015-11-06 19:29:24 UTC (rev 192111)
@@ -84,7 +84,10 @@
 #if ENABLE(NETWORK_CACHE)
 static NSString * const WebKitNetworkCacheEnabledDefaultsKey = @"WebKitNetworkCacheEnabled";
 static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @"WebKitNetworkCacheEfficacyLoggingEnabled";
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+static NSString * const WebKitNetworkCacheSpeculativeRevalidationEnabledDefaultsKey = @"WebKitNetworkCacheResourceRevalidationEnabled";
 #endif
+#endif
 
 namespace WebKit {
 
@@ -106,7 +109,10 @@
 #if ENABLE(NETWORK_CACHE)
     [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEnabledDefaultsKey];
     [registrationDictionary setObject:[NSNumber numberWithBool:NO] forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    [registrationDictionary setObject:[NSNumber numberWithBool:NO] forKey:WebKitNetworkCacheSpeculativeRevalidationEnabledDefaultsKey];
 #endif
+#endif
 
     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
 }
@@ -254,7 +260,10 @@
 #if ENABLE(NETWORK_CACHE)
     parameters.shouldEnableNetworkCache = isNetworkCacheEnabled();
     parameters.shouldEnableNetworkCacheEfficacyLogging = [defaults boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
+#if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
+    parameters.shouldEnableNetworkCacheSpeculativeRevalidation = [defaults boolForKey:WebKitNetworkCacheSpeculativeRevalidationEnabledDefaultsKey];
 #endif
+#endif
 
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
     RetainPtr<CFDataRef> cookieStorageData = adoptCF(CFHTTPCookieStorageCreateIdentifyingData(kCFAllocatorDefault, [[NSHTTPCookieStorage sharedHTTPCookieStorage] _cookieStorage]));

Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (192110 => 192111)


--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2015-11-06 19:29:24 UTC (rev 192111)
@@ -1176,6 +1176,10 @@
 		7CF47FFF17276AE3008ACB91 /* WKBundlePageBannerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7EC4F0FB18E4ACBB008056AF /* NetworkProcessCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */; };
 		83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 83048AE51ACA45DC0082C832 /* ProcessThrottlerClient.h */; };
+		8310428B1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 831042891BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h */; };
+		8310428C1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8310428A1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp */; };
+		832AE2521BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 832AE2501BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.h */; };
+		832AE2531BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 832AE2511BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.cpp */; };
 		834B250F1A831A8D00CFB150 /* NetworkCacheFileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystem.h */; };
 		834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */; };
 		8360349F1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8360349D1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp */; };
@@ -3410,6 +3414,10 @@
 		7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundlePageBannerMac.h; sourceTree = "<group>"; };
 		7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkProcessCocoa.mm; path = NetworkProcess/cocoa/NetworkProcessCocoa.mm; sourceTree = "<group>"; };
 		83048AE51ACA45DC0082C832 /* ProcessThrottlerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessThrottlerClient.h; sourceTree = "<group>"; };
+		831042891BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheSubresourcesEntry.h; sourceTree = "<group>"; };
+		8310428A1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheSubresourcesEntry.cpp; sourceTree = "<group>"; };
+		832AE2501BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheSpeculativeLoader.h; sourceTree = "<group>"; };
+		832AE2511BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheSpeculativeLoader.cpp; sourceTree = "<group>"; };
 		834B250E1A831A8D00CFB150 /* NetworkCacheFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheFileSystem.h; sourceTree = "<group>"; };
 		834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheStatistics.h; sourceTree = "<group>"; };
 		8360349D1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSQLiteDatabaseTracker.cpp; sourceTree = "<group>"; };
@@ -7573,10 +7581,14 @@
 				E42E060D1AA750E500B11699 /* NetworkCacheIOChannelCocoa.mm */,
 				E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */,
 				E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */,
+				832AE2511BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.cpp */,
+				832AE2501BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.h */,
 				83BDCCB81AC5FDB6003F6441 /* NetworkCacheStatistics.cpp */,
 				834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */,
 				E4436EC31A0CFDB200EAD204 /* NetworkCacheStorage.cpp */,
 				E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */,
+				8310428A1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp */,
+				831042891BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h */,
 			);
 			name = cache;
 			path = NetworkProcess/cache;
@@ -7714,6 +7726,7 @@
 				75A8D2E1187DEC1A00C39C9E /* APISession.h in Headers */,
 				1AFDE6621954E9B100C48FFA /* APISessionState.h in Headers */,
 				1A4D664818A2D91A00D82E21 /* APIUIClient.h in Headers */,
+				832AE2521BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.h in Headers */,
 				BCDB86C11200FB97007254BE /* APIURL.h in Headers */,
 				BCE2315D122C30CA00D5C35A /* APIURLRequest.h in Headers */,
 				BC90A1D2122DD55E00CC8C50 /* APIURLResponse.h in Headers */,
@@ -8315,6 +8328,7 @@
 				293EBEAB1627D9C9005F89F1 /* WKDOMText.h in Headers */,
 				BC017D2116263308007054F5 /* WKDOMTextIterator.h in Headers */,
 				1AB7D78D1288CD9A00CFD08C /* WKDownload.h in Headers */,
+				8310428B1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.h in Headers */,
 				1AF4592F19464B2000F9D4A2 /* WKError.h in Headers */,
 				BCFD548C132D82680055D816 /* WKErrorCF.h in Headers */,
 				37B5045219EEF31300CE2CF8 /* WKErrorPrivate.h in Headers */,
@@ -9525,6 +9539,7 @@
 				7C89D2971A6753B2003A5FDE /* APIPageConfiguration.cpp in Sources */,
 				1A3A73CF1A48C7F1007231B3 /* APIPageGroupHandle.cpp in Sources */,
 				1AC1336E18565D2B00F3EC05 /* APIPageHandle.cpp in Sources */,
+				832AE2531BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoader.cpp in Sources */,
 				7CE4D21F1A4914CA00C7F152 /* APIProcessPoolConfiguration.cpp in Sources */,
 				FED3C1DC1B447EAC00E0EB7F /* APISerializedScriptValueCocoa.mm in Sources */,
 				A182D5B41BE6BD250087A7CC /* AccessibilityIOS.mm in Sources */,
@@ -9759,6 +9774,7 @@
 				1A8EF4CC1252403700F7067F /* PluginControllerProxy.cpp in Sources */,
 				1A2D91A61281D739001EB962 /* PluginControllerProxyMac.mm in Sources */,
 				1A8EF96E1252AF6B00F7067F /* PluginControllerProxyMessageReceiver.cpp in Sources */,
+				8310428C1BD6B66F00A715E4 /* NetworkCacheSubresourcesEntry.cpp in Sources */,
 				1A17977F137EE82C00F97D45 /* PluginCreationParameters.cpp in Sources */,
 				7C3F8C90173AF52D007B7F39 /* PluginInformation.cpp in Sources */,
 				7C135AAC173B0CFF00586AE2 /* PluginInformationMac.mm in Sources */,

Modified: trunk/Source/WebKit2/config.h (192110 => 192111)


--- trunk/Source/WebKit2/config.h	2015-11-06 19:18:31 UTC (rev 192110)
+++ trunk/Source/WebKit2/config.h	2015-11-06 19:29:24 UTC (rev 192111)
@@ -98,6 +98,14 @@
 #endif
 #endif
 
+#ifndef ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION
+#if ENABLE(NETWORK_CACHE) && PLATFORM(COCOA)
+#define ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION 1
+#else
+#define ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION 0
+#endif
+#endif
+
 #ifndef HAVE_SAFARI_SERVICES_FRAMEWORK
 #if PLATFORM(IOS) && (!defined TARGET_OS_IOS || TARGET_OS_IOS)
 #define HAVE_SAFARI_SERVICES_FRAMEWORK 1
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to