<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197879] trunk/Source/WebKit2</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197879">197879</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2016-03-09 13:22:36 -0800 (Wed, 09 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Speculative disk cache resource revalidations are sometimes wasted
https://bugs.webkit.org/show_bug.cgi?id=155187
&lt;rdar://problem/25032905&gt;

Reviewed by Antti Koivisto.

Speculative disk cache resource revalidations were sometimes wasted.

We would sometimes correctly revalidate a resource but the
NetworkResourceLoader then either:
1. Fail to reuse the speculatively validated entry
2. Reuse the speculatively validated entry but then validate it again

Bug 1 was caused by the revalidated entry key sometimes being
different from the cached entry key. This could happen when
revalidation fails (the server did not send back a 304) in
which case we call NetworkCache::store() which creates a new
cache Entry, generating a cache key from our revalidation
request. If the original request has a cache partition or a
range, then the keys would not match because we did not set
the cache partition or the range on the revalidation request.
This has been addressed by setting the cache partition on the
revalidation request in constructRevalidationRequest() and by
not doing revalidation if the original request had a 'range'
header.

Bug 2 was caused by us marking a speculatively revalidated entry
as &quot;not needing revalidating&quot; only in Cache::update(). Cache::update()
is only called in the case the revalidation was successful (server
returned a 304). If revalidation was not successful, Cache::store()
would be called instead was we would fail to update the
needsRevalidation flag. NetworkResourceLoader would then validate
again the resource that was already speculatively revalidated.
To address the problem, we now update the 'needsRevalidation' flag
as soon as the speculative revalidation completes, in
SpeculativeLoad::didComplete().

* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::Cache::retrieve):
(WebKit::NetworkCache::makeCacheKey):
(WebKit::NetworkCache::Cache::update):
* NetworkProcess/cache/NetworkCacheEntry.cpp:
(WebKit::NetworkCache::Entry::setNeedsValidation):
* NetworkProcess/cache/NetworkCacheEntry.h:
* NetworkProcess/cache/NetworkCacheKey.cpp:
(WebKit::NetworkCache::noPartitionString):
(WebKit::NetworkCache::Key::Key):
(WebKit::NetworkCache::Key::hasPartition):
* NetworkProcess/cache/NetworkCacheKey.h:
* NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp:
(WebKit::NetworkCache::SpeculativeLoad::didComplete):
* NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp:
(WebKit::NetworkCache::constructRevalidationRequest):
(WebKit::NetworkCache::SpeculativeLoadManager::retrieveEntryFromStorage):
(WebKit::NetworkCache::SpeculativeLoadManager::revalidateEntry):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheEntrycpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheEntryh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeycpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeyh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadcpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadManagercpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/ChangeLog        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2016-03-09  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Speculative disk cache resource revalidations are sometimes wasted
+        https://bugs.webkit.org/show_bug.cgi?id=155187
+        &lt;rdar://problem/25032905&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Speculative disk cache resource revalidations were sometimes wasted.
+
+        We would sometimes correctly revalidate a resource but the
+        NetworkResourceLoader then either:
+        1. Fail to reuse the speculatively validated entry
+        2. Reuse the speculatively validated entry but then validate it again
+
+        Bug 1 was caused by the revalidated entry key sometimes being
+        different from the cached entry key. This could happen when
+        revalidation fails (the server did not send back a 304) in
+        which case we call NetworkCache::store() which creates a new
+        cache Entry, generating a cache key from our revalidation
+        request. If the original request has a cache partition or a
+        range, then the keys would not match because we did not set
+        the cache partition or the range on the revalidation request.
+        This has been addressed by setting the cache partition on the
+        revalidation request in constructRevalidationRequest() and by
+        not doing revalidation if the original request had a 'range'
+        header.
+
+        Bug 2 was caused by us marking a speculatively revalidated entry
+        as &quot;not needing revalidating&quot; only in Cache::update(). Cache::update()
+        is only called in the case the revalidation was successful (server
+        returned a 304). If revalidation was not successful, Cache::store()
+        would be called instead was we would fail to update the
+        needsRevalidation flag. NetworkResourceLoader would then validate
+        again the resource that was already speculatively revalidated.
+        To address the problem, we now update the 'needsRevalidation' flag
+        as soon as the speculative revalidation completes, in
+        SpeculativeLoad::didComplete().
+
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::Cache::retrieve):
+        (WebKit::NetworkCache::makeCacheKey):
+        (WebKit::NetworkCache::Cache::update):
+        * NetworkProcess/cache/NetworkCacheEntry.cpp:
+        (WebKit::NetworkCache::Entry::setNeedsValidation):
+        * NetworkProcess/cache/NetworkCacheEntry.h:
+        * NetworkProcess/cache/NetworkCacheKey.cpp:
+        (WebKit::NetworkCache::noPartitionString):
+        (WebKit::NetworkCache::Key::Key):
+        (WebKit::NetworkCache::Key::hasPartition):
+        * NetworkProcess/cache/NetworkCacheKey.h:
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp:
+        (WebKit::NetworkCache::SpeculativeLoad::didComplete):
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp:
+        (WebKit::NetworkCache::constructRevalidationRequest):
+        (WebKit::NetworkCache::SpeculativeLoadManager::retrieveEntryFromStorage):
+        (WebKit::NetworkCache::SpeculativeLoadManager::revalidateEntry):
+
</ins><span class="cx"> 2016-03-09  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Local HTML should be blocked from localStorage access unless &quot;Disable Local File Restrictions&quot; is checked
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -121,8 +121,6 @@
</span><span class="cx"> #else
</span><span class="cx">     String partition;
</span><span class="cx"> #endif
</span><del>-    if (partition.isEmpty())
-        partition = ASCIILiteral(&quot;No partition&quot;);
</del><span class="cx"> 
</span><span class="cx">     // FIXME: This implements minimal Range header disk cache support. We don't parse
</span><span class="cx">     // ranges so only the same exact range request will be served from the cache.
</span><span class="lines">@@ -402,7 +400,7 @@
</span><span class="cx">         case UseDecision::Use:
</span><span class="cx">             break;
</span><span class="cx">         case UseDecision::Validate:
</span><del>-            entry-&gt;setNeedsValidation();
</del><ins>+            entry-&gt;setNeedsValidation(true);
</ins><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="cx">             entry = nullptr;
</span><span class="lines">@@ -495,7 +493,6 @@
</span><span class="cx"> 
</span><span class="cx">     WebCore::ResourceResponse response = existingEntry.response();
</span><span class="cx">     WebCore::updateResponseHeadersAfterRevalidation(response, validatingResponse);
</span><del>-    response.setSource(WebCore::ResourceResponse::Source::DiskCache);
</del><span class="cx"> 
</span><span class="cx">     auto updateEntry = std::make_unique&lt;Entry&gt;(existingEntry.key(), response, existingEntry.buffer(), collectVaryingRequestHeaders(originalRequest, response));
</span><span class="cx">     auto updateRecord = updateEntry-&gt;encodeAsStorageRecord();
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheEntrycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -188,10 +188,9 @@
</span><span class="cx">     return m_response.source() == WebCore::ResourceResponse::Source::DiskCacheAfterValidation;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Entry::setNeedsValidation()
</del><ins>+void Entry::setNeedsValidation(bool value)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_response.source() == WebCore::ResourceResponse::Source::DiskCache);
-    m_response.setSource(WebCore::ResourceResponse::Source::DiskCacheAfterValidation);
</del><ins>+    m_response.setSource(value ? WebCore::ResourceResponse::Source::DiskCacheAfterValidation : WebCore::ResourceResponse::Source::DiskCache);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Entry::asJSON(StringBuilder&amp; json, const Storage::RecordInfo&amp; info) const
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheEntryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.h        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool needsValidation() const;
</span><del>-    void setNeedsValidation();
</del><ins>+    void setNeedsValidation(bool);
</ins><span class="cx"> 
</span><span class="cx">     const Storage::Record&amp; sourceStorageRecord() const { return m_sourceStorageRecord; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -30,12 +30,19 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;NetworkCacheCoders.h&quot;
</span><span class="cx"> #include &lt;wtf/ASCIICType.h&gt;
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> namespace NetworkCache {
</span><span class="cx"> 
</span><ins>+static const String&amp; noPartitionString()
+{
+    static NeverDestroyed&lt;String&gt; noPartition(ASCIILiteral(&quot;No partition&quot;));
+    return noPartition;
+}
+
</ins><span class="cx"> Key::Key(const Key&amp; o)
</span><span class="cx">     : m_partition(o.m_partition.isolatedCopy())
</span><span class="cx">     , m_type(o.m_type.isolatedCopy())
</span><span class="lines">@@ -46,7 +53,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Key::Key(const String&amp; partition, const String&amp; type, const String&amp; range, const String&amp; identifier)
</span><del>-    : m_partition(partition.isolatedCopy())
</del><ins>+    : m_partition(partition.isEmpty() ? noPartitionString().isolatedCopy() : partition.isolatedCopy())
</ins><span class="cx">     , m_type(type.isolatedCopy())
</span><span class="cx">     , m_identifier(identifier.isolatedCopy())
</span><span class="cx">     , m_range(range.isolatedCopy())
</span><span class="lines">@@ -59,6 +66,11 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Key::hasPartition() const
+{
+    return m_partition != noPartitionString();
+}
+
</ins><span class="cx"> Key&amp; Key::operator=(const Key&amp; other)
</span><span class="cx"> {
</span><span class="cx">     m_partition = other.m_partition.isolatedCopy();
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool isNull() const { return m_identifier.isNull(); }
</span><span class="cx"> 
</span><ins>+    bool hasPartition() const;
</ins><span class="cx">     const String&amp; partition() const { return m_partition; }
</span><span class="cx">     const String&amp; identifier() const { return m_identifier; }
</span><span class="cx">     const String&amp; type() const { return m_type; }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.cpp        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -139,6 +139,10 @@
</span><span class="cx"> 
</span><span class="cx">     m_networkLoad = nullptr;
</span><span class="cx"> 
</span><ins>+    // Make sure speculatively revalidated resources do not get validated by the NetworkResourceLoader again.
+    if (m_cacheEntryForValidation)
+        m_cacheEntryForValidation-&gt;setNeedsValidation(false);
+
</ins><span class="cx">     m_completionHandler(WTFMove(m_cacheEntryForValidation));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp (197878 => 197879)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp        2016-03-09 21:15:00 UTC (rev 197878)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoadManager.cpp        2016-03-09 21:22:36 UTC (rev 197879)
</span><span class="lines">@@ -87,6 +87,11 @@
</span><span class="cx"> static inline ResourceRequest constructRevalidationRequest(const Entry&amp; entry)
</span><span class="cx"> {
</span><span class="cx">     ResourceRequest revalidationRequest(entry.key().identifier());
</span><ins>+#if ENABLE(CACHE_PARTITIONING)
+    if (entry.key().hasPartition())
+        revalidationRequest.setCachePartition(entry.key().partition());
+#endif
+    ASSERT_WITH_MESSAGE(entry.key().range().isEmpty(), &quot;range is not supported&quot;);
</ins><span class="cx"> 
</span><span class="cx">     String eTag = entry.response().httpHeaderField(HTTPHeaderName::ETag);
</span><span class="cx">     if (!eTag.isEmpty())
</span><span class="lines">@@ -344,7 +349,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (responseNeedsRevalidation(response, entry-&gt;timeStamp()))
</span><del>-            entry-&gt;setNeedsValidation();
</del><ins>+            entry-&gt;setNeedsValidation(true);
</ins><span class="cx"> 
</span><span class="cx">         completionHandler(WTFMove(entry));
</span><span class="cx">         return true;
</span><span class="lines">@@ -369,9 +374,16 @@
</span><span class="cx">     ASSERT(entry-&gt;needsValidation());
</span><span class="cx"> 
</span><span class="cx">     auto key = entry-&gt;key();
</span><ins>+
+    // Range is not supported.
+    if (!key.range().isEmpty())
+        return;
+
</ins><span class="cx">     LOG(NetworkCacheSpeculativePreloading, &quot;(NetworkProcess) Speculatively revalidating '%s':&quot;, key.identifier().utf8().data());
</span><span class="cx">     auto revalidator = std::make_unique&lt;SpeculativeLoad&gt;(frameID, constructRevalidationRequest(*entry), WTFMove(entry), [this, key, frameID](std::unique_ptr&lt;Entry&gt; revalidatedEntry) {
</span><span class="cx">         ASSERT(!revalidatedEntry || !revalidatedEntry-&gt;needsValidation());
</span><ins>+        ASSERT(!revalidatedEntry || revalidatedEntry-&gt;key() == key);
+
</ins><span class="cx">         auto protectRevalidator = m_pendingPreloads.take(key);
</span><span class="cx">         LOG(NetworkCacheSpeculativePreloading, &quot;(NetworkProcess) Speculative revalidation completed for '%s':&quot;, key.identifier().utf8().data());
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>