<!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>[190320] trunk</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/190320">190320</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-09-29 12:04:18 -0700 (Tue, 29 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Memory cache revalidations should refresh the network disk cache
https://bugs.webkit.org/show_bug.cgi?id=149606

Reviewed by Darin Adler.

Source/WebKit2:

Previously, resource revalidations triggered by the memory cache would
bypass the disk cache entirely because the requests are conditional. As
a result, when the server responds with a 304, we were unable to update
the headers (e.g. new expiration date) of the corresponding entry in
the disk cache.

This patch updates our disk cache implementation to not bypass the disk
cache when the request is conditional. Instead, we look up the cached
entry and force its revalidation from the network. If the server then
returns a 304, we are now able to update the headers of this cached
entry. In such case though, we let the 304 response through to WebCore
unlike revalidations triggered by the disk cache.

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::didReceiveResponseAsync):
* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::makeUseDecision):
(WebKit::NetworkCache::makeRetrieveDecision):

LayoutTests:

Add layout test to check that revalidations requested by the memory cache
update the corresponding disk cache entry when the server responds with a
304 status code.

* http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt: Added.
* http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformmacTestExpectations">trunk/LayoutTests/platform/mac/TestExpectations</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp">trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestscachediskcachememorycacherevalidationupdatesdiskcacheexpectedtxt">trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcachememorycacherevalidationupdatesdiskcachehtml">trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (190319 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-09-29 18:35:38 UTC (rev 190319)
+++ trunk/LayoutTests/ChangeLog        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2015-09-29  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Memory cache revalidations should refresh the network disk cache
+        https://bugs.webkit.org/show_bug.cgi?id=149606
+
+        Reviewed by Darin Adler.
+
+        Add layout test to check that revalidations requested by the memory cache
+        update the corresponding disk cache entry when the server responds with a
+        304 status code.
+
+        * http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt: Added.
+        * http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html: Added.
+
+2015-09-29  Chris Dumez  &lt;cdumez@apple.com&gt;
+
</ins><span class="cx">         Unreviewed, mark several newly imported W3C media tests as flaky on Mavericks.
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=149636
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachememorycacherevalidationupdatesdiskcacheexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt (0 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache-expected.txt        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+Tests that revalidations from the memory cache update the disk cache.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+running 1 tests
+
+Warming up cache...
+Load trough the Memory Cache...
+Clear the memory cache and load again, it should load from the disk cache *without* revalidation.
+response headers: {&quot;Expires&quot;:&quot;now(0)&quot;,&quot;ETag&quot;:&quot;match&quot;}
+response's 'Expires' header is overriden by future date in 304 response
+response source: Disk cache
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachememorycacherevalidationupdatesdiskcachehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html (0 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/memory-cache-revalidation-updates-disk-cache.html        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+&lt;script src=&quot;/js-test-resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/cache-test.js&quot;&gt;&lt;/script&gt;
+&lt;body&gt;
+&lt;script&gt;
+
+var tests =
+[
+ { responseHeaders: {'Expires': 'now(0)', 'ETag': 'match' }, expiresInFutureIn304: true },
+];
+
+description(&quot;Tests that revalidations from the memory cache update the disk cache.&quot;);
+
+debug(&quot;running &quot; + tests.length + &quot; tests&quot;);
+debug(&quot;&quot;);
+
+function runTests(tests)
+{
+    debug(&quot;Warming up cache...&quot;);
+    loadResources(tests, function () {
+        debug(&quot;Load trough the Memory Cache...&quot;);
+        loadResourcesWithOptions(tests, { &quot;SubresourceValidationPolicy&quot;: true }, function () {
+            debug(&quot;Clear the memory cache and load again, it should load from the disk cache *without* revalidation.&quot;);
+            loadResourcesWithOptions(tests, { &quot;ClearMemoryCache&quot; : true }, function () {
+                printResults(tests);
+                finishJSTest();
+            });
+        });
+    });
+}
+
+runTests(tests);
+
+&lt;/script&gt;
+&lt;script src=&quot;/js-test-resources/js-test-post.js&quot;&gt;&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/TestExpectations (190319 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2015-09-29 18:35:38 UTC (rev 190319)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -1080,10 +1080,6 @@
</span><span class="cx"> # Seems like this should happen everywhere, but it only does on Yosemite.
</span><span class="cx"> [ Yosemite+ ] http/tests/navigation/post-frames-goback1.html [ Pass Failure ]
</span><span class="cx"> 
</span><del>-# FIXME: Needs bugzilla (&lt;rdar://problem/16664245&gt;)
-# We should land updated results if we can't get this bug fixed in time.
-[ Yosemite+ ] http/tests/xmlhttprequest/cache-override.html [ Failure ]
-
</del><span class="cx"> # FIXME: Needs bugzilla (&lt;rdar://problem/16802068&gt;)
</span><span class="cx"> [ Yosemite+ ] fast/css/input-search-padding.html [ Failure ]
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (190319 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-09-29 18:35:38 UTC (rev 190319)
+++ trunk/Source/WebKit2/ChangeLog        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2015-09-29  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Memory cache revalidations should refresh the network disk cache
+        https://bugs.webkit.org/show_bug.cgi?id=149606
+
+        Reviewed by Darin Adler.
+
+        Previously, resource revalidations triggered by the memory cache would
+        bypass the disk cache entirely because the requests are conditional. As
+        a result, when the server responds with a 304, we were unable to update
+        the headers (e.g. new expiration date) of the corresponding entry in
+        the disk cache.
+
+        This patch updates our disk cache implementation to not bypass the disk
+        cache when the request is conditional. Instead, we look up the cached
+        entry and force its revalidation from the network. If the server then
+        returns a 304, we are now able to update the headers of this cached
+        entry. In such case though, we let the 304 response through to WebCore
+        unlike revalidations triggered by the disk cache.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::didReceiveResponseAsync):
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::makeUseDecision):
+        (WebKit::NetworkCache::makeRetrieveDecision):
+
</ins><span class="cx"> 2015-09-16  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         printing does not use minimum page zoom factor
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp (190319 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2015-09-29 18:35:38 UTC (rev 190319)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -258,9 +258,13 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_cacheEntryForValidation) {
</span><span class="cx">         bool validationSucceeded = m_response.httpStatusCode() == 304; // 304 Not Modified
</span><del>-        if (validationSucceeded)
</del><ins>+        if (validationSucceeded) {
</ins><span class="cx">             NetworkCache::singleton().update(originalRequest(), m_parameters.webPageID, *m_cacheEntryForValidation, m_response);
</span><del>-        else
</del><ins>+            // If the request was conditional then this revalidation was not triggered by the network cache and we pass the
+            // 304 response to WebCore.
+            if (originalRequest().isConditional())
+                m_cacheEntryForValidation = nullptr;
+        } else
</ins><span class="cx">             m_cacheEntryForValidation = nullptr;
</span><span class="cx">     }
</span><span class="cx">     shouldSendDidReceiveResponse = !m_cacheEntryForValidation;
</span><span class="lines">@@ -590,12 +594,16 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_handle);
</span><span class="cx"> 
</span><del>-    String eTag = entry-&gt;response().httpHeaderField(WebCore::HTTPHeaderName::ETag);
-    String lastModified = entry-&gt;response().httpHeaderField(WebCore::HTTPHeaderName::LastModified);
-    if (!eTag.isEmpty())
-        m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfNoneMatch, eTag);
-    if (!lastModified.isEmpty())
-        m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfModifiedSince, lastModified);
</del><ins>+    // If the request is already conditional then the revalidation was not triggered by the disk cache
+    // and we should not overwrite the existing conditional headers.
+    if (!m_currentRequest.isConditional()) {
+        String eTag = entry-&gt;response().httpHeaderField(WebCore::HTTPHeaderName::ETag);
+        String lastModified = entry-&gt;response().httpHeaderField(WebCore::HTTPHeaderName::LastModified);
+        if (!eTag.isEmpty())
+            m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfNoneMatch, eTag);
+        if (!lastModified.isEmpty())
+            m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfModifiedSince, lastModified);
+    }
</ins><span class="cx"> 
</span><span class="cx">     m_cacheEntryForValidation = WTF::move(entry);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (190319 => 190320)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-09-29 18:35:38 UTC (rev 190319)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-09-29 19:04:18 UTC (rev 190320)
</span><span class="lines">@@ -204,6 +204,11 @@
</span><span class="cx"> 
</span><span class="cx"> static UseDecision makeUseDecision(const Entry&amp; entry, const WebCore::ResourceRequest&amp; request)
</span><span class="cx"> {
</span><ins>+    // The request is conditional so we force revalidation from the network. We merely check the disk cache
+    // so we can update the cache entry.
+    if (request.isConditional())
+        return UseDecision::Validate;
+
</ins><span class="cx">     if (!verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request))
</span><span class="cx">         return UseDecision::NoDueToVaryingHeaderMismatch;
</span><span class="cx"> 
</span><span class="lines">@@ -225,10 +230,7 @@
</span><span class="cx">     // FIXME: Support HEAD requests.
</span><span class="cx">     if (request.httpMethod() != &quot;GET&quot;)
</span><span class="cx">         return RetrieveDecision::NoDueToHTTPMethod;
</span><del>-    // FIXME: We should be able to validate conditional requests using cache.
-    if (request.isConditional())
-        return RetrieveDecision::NoDueToConditionalRequest;
-    if (request.cachePolicy() == WebCore::ReloadIgnoringCacheData)
</del><ins>+    if (request.cachePolicy() == WebCore::ReloadIgnoringCacheData &amp;&amp; !request.isConditional())
</ins><span class="cx">         return RetrieveDecision::NoDueToReloadIgnoringCache;
</span><span class="cx"> 
</span><span class="cx">     return RetrieveDecision::Yes;
</span></span></pre>
</div>
</div>

</body>
</html>