<!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>[189177] 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/189177">189177</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2015-08-31 11:31:04 -0700 (Mon, 31 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Network Cache: Stale content after back navigation
https://bugs.webkit.org/show_bug.cgi?id=148634

Reviewed by Chris Dumez.

Source/WebKit2:

It is possible to get an older version of the previous page when navigating back. This can happen
if the main resource load has not completed before navigating away from the page.

Network cache entry is normally updated when the load completes. In case of cancellation we would leave
any existing entry as-is. However we render incrementally and user might have seen some content from
the partial load already. Navigating back to the cached page could show older version of the content.

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::abort):

    If a network load is canceled by the client after receiving response but before the load has completed
    remove any existing cache entry for it.

LayoutTests:

* http/tests/cache/disk-cache/disk-cache-302-status-code.html:
* http/tests/cache/disk-cache/disk-cache-cancel-expected.txt: Added.
* http/tests/cache/disk-cache/disk-cache-cancel.html: Added.
* http/tests/cache/disk-cache/resources/cache-test.js:

    Support delayed responses so we can test canceling the load.
    Some minor improvements.

(makeHeaderValue):
(generateTestURL):
(loadResource):
(loadResourcesWithOptions):
(generateTests):
* http/tests/cache/disk-cache/resources/generate-response.cgi:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcachediskcache302statuscodehtml">trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-302-status-code.html</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcacheresourcescachetestjs">trunk/LayoutTests/http/tests/cache/disk-cache/resources/cache-test.js</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcacheresourcesgenerateresponsecgi">trunk/LayoutTests/http/tests/cache/disk-cache/resources/generate-response.cgi</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp">trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestscachediskcachediskcachecancelexpectedtxt">trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcachediskcachecancelhtml">trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/LayoutTests/ChangeLog        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2015-08-31  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Network Cache: Stale content after back navigation
+        https://bugs.webkit.org/show_bug.cgi?id=148634
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/cache/disk-cache/disk-cache-302-status-code.html:
+        * http/tests/cache/disk-cache/disk-cache-cancel-expected.txt: Added.
+        * http/tests/cache/disk-cache/disk-cache-cancel.html: Added.
+        * http/tests/cache/disk-cache/resources/cache-test.js:
+
+            Support delayed responses so we can test canceling the load.
+            Some minor improvements.
+
+        (makeHeaderValue):
+        (generateTestURL):
+        (loadResource):
+        (loadResourcesWithOptions):
+        (generateTests):
+        * http/tests/cache/disk-cache/resources/generate-response.cgi:
+
</ins><span class="cx"> 2015-08-31  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Repaint cleanup: 4776765.html. Use repaint rect tracking.
</span></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachediskcache302statuscodehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-302-status-code.html (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-302-status-code.html        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-302-status-code.html        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -5,8 +5,8 @@
</span><span class="cx"> 
</span><span class="cx"> var tests =
</span><span class="cx"> [
</span><del>- { responseHeaders: {'Status': '302', 'Location': '/', 'Cache-control': 'max-age=0' }, includeBody: false },
- { responseHeaders: {'Status': '302', 'Location': '/', 'Cache-control': 'max-age=100' }, includeBody: false },
</del><ins>+ { responseHeaders: {'Status': '302', 'Location': '/', 'Cache-control': 'max-age=0' }, body: &quot;&quot; },
+ { responseHeaders: {'Status': '302', 'Location': '/', 'Cache-control': 'max-age=100' }, body: &quot;&quot; },
</ins><span class="cx"> ];
</span><span class="cx"> 
</span><span class="cx"> description(&quot;Test that responses with HTTP status code 302 are not cached&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachediskcachecancelexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel-expected.txt (0 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel-expected.txt        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+Test that canceled network loads don't leave behind stale cache entries
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+running 3 tests
+
+Warming cache
+Starting loads, then canceling
+Loading again with back navigation cache policy
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;,&quot;ETag&quot;:&quot;match&quot;}
+response source: Network
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachediskcachecancelhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel.html (0 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-cancel.html        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -0,0 +1,45 @@
</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: {'Cache-control': 'max-age=0' }, body: &quot;unique&quot;, delay: 1 },
+ { responseHeaders: {'Cache-control': 'max-age=100' }, body: &quot;unique&quot;, delay: 1 },
+ { responseHeaders: {'Cache-control': 'max-age=0', 'ETag': 'match' }, body: &quot;unique&quot;, delay: 1 },
+];
+
+description(&quot;Test that canceled network loads don't leave behind stale cache entries&quot;);
+
+debug(&quot;running &quot; + tests.length + &quot; tests&quot;);
+debug(&quot;&quot;);
+
+function runTests(tests)
+{
+    debug(&quot;Warming cache&quot;);
+    internals.setOverrideCachePolicy(&quot;ReloadIgnoringCacheData&quot;);
+    loadResources(tests, function () {
+        debug(&quot;Starting loads, then canceling&quot;);
+        loadResources(tests, function (ev) {
+            debug(&quot;Loading again with back navigation cache policy&quot;);
+            internals.setOverrideCachePolicy(&quot;ReturnCacheDataElseLoad&quot;);
+            loadResources(tests, function (ev) {
+                printResults(tests);
+                finishJSTest();
+            });
+        });
+
+        setTimeout(function () {
+            for (var i = 0; i &lt; tests.length; ++i) {
+                var test = tests[i];
+                test.xhr.abort();
+            }
+        }, 200);
+    });
+}
+
+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="trunkLayoutTestshttptestscachediskcacheresourcescachetestjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/cache/disk-cache/resources/cache-test.js (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/resources/cache-test.js        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/resources/cache-test.js        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -40,14 +40,16 @@
</span><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function generateTestURL(test, includeBody, expiresInFutureIn304)
</del><ins>+function generateTestURL(test)
</ins><span class="cx"> {
</span><del>-    includeBody = typeof includeBody !== 'undefined' ? includeBody : true;
-    expiresInFutureIn304 = typeof expiresInFutureIn304 !== 'undefined' ? expiresInFutureIn304 : false;
</del><ins>+    var body = typeof test.body !== 'undefined' ? test.body : &quot;&quot;;
+    var expiresInFutureIn304 = typeof test.expiresInFutureIn304 !== 'undefined' ? test.expiresInFutureIn304 : false;
</ins><span class="cx">     var uniqueTestId = Math.floor((Math.random() * 1000000000000));
</span><del>-    var testURL = &quot;resources/generate-response.cgi?include-body=&quot; + (includeBody ? &quot;1&quot; : &quot;0&quot;);
</del><ins>+    var testURL = &quot;resources/generate-response.cgi?body=&quot; + body;
</ins><span class="cx">     if (expiresInFutureIn304)
</span><span class="cx">         testURL += &quot;&amp;expires-in-future-in-304=1&quot;;
</span><ins>+    if (test.delay)
+        testURL += &quot;&amp;delay=&quot; + test.delay;
</ins><span class="cx">     testURL += &quot;&amp;uniqueId=&quot; + uniqueTestId++;
</span><span class="cx">     if (!test.responseHeaders || !test.responseHeaders[&quot;Content-Type&quot;])
</span><span class="cx">         testURL += &quot;&amp;Content-Type=text/plain&quot;;
</span><span class="lines">@@ -59,10 +61,12 @@
</span><span class="cx"> function loadResource(test, onload)
</span><span class="cx"> {
</span><span class="cx">     if (!test.url)
</span><del>-        test.url = generateTestURL(test, test.includeBody, test.expiresInFutureIn304);
</del><ins>+        test.url = generateTestURL(test);
</ins><span class="cx"> 
</span><span class="cx">     test.xhr = new XMLHttpRequest();
</span><span class="cx">     test.xhr.onload = onload;
</span><ins>+    test.xhr.onerror = onload;
+    test.xhr.onabort = onload;
</ins><span class="cx">     test.xhr.open(&quot;get&quot;, test.url, true);
</span><span class="cx"> 
</span><span class="cx">     for (var header in test.requestHeaders)
</span><span class="lines">@@ -82,7 +86,7 @@
</span><span class="cx">         loadResource(tests[i], function (ev) {
</span><span class="cx">             --pendingCount;
</span><span class="cx">             if (!pendingCount)
</span><del>-                completetion();
</del><ins>+                completetion(ev);
</ins><span class="cx">          });
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -166,7 +170,8 @@
</span><span class="cx">                 mergeFields(test[field], component[field]);
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        test.includeBody = includeBody;
</del><ins>+        if (includeBody &amp;&amp; !test.body)
+            test.body = &quot;test body&quot;;
</ins><span class="cx">         tests.push(test);
</span><span class="cx">     }
</span><span class="cx">     return tests;
</span></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcacheresourcesgenerateresponsecgi"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/cache/disk-cache/resources/generate-response.cgi (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/resources/generate-response.cgi        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/resources/generate-response.cgi        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -5,9 +5,14 @@
</span><span class="cx"> 
</span><span class="cx"> my $query = new CGI;
</span><span class="cx"> @names = $query-&gt;param;
</span><del>-my $includeBody = $query-&gt;param('include-body') || 0;
</del><span class="cx"> my $expiresInFutureIn304 = $query-&gt;param('expires-in-future-in-304') || 0;
</span><ins>+my $delay = $query-&gt;param('delay') || 0;
+my $body = $query-&gt;param('body') || 0;
</ins><span class="cx"> 
</span><ins>+if ($body eq &quot;unique&quot;) {
+    $body = sprintf &quot;%08X\n&quot;, rand(0xffffffff)
+}
+
</ins><span class="cx"> my $hasStatusCode = 0;
</span><span class="cx"> my $hasExpiresHeader = 0;
</span><span class="cx"> if ($query-&gt;http &amp;&amp; $query-&gt;http(&quot;If-None-Match&quot;) eq &quot;match&quot;) {
</span><span class="lines">@@ -32,10 +37,18 @@
</span><span class="cx"> 
</span><span class="cx"> foreach (@names) {
</span><span class="cx">     next if ($_ eq &quot;uniqueId&quot;);
</span><del>-    next if ($_ eq &quot;include-body&quot;);
</del><ins>+    next if ($_ eq &quot;delay&quot;);
+    next if ($_ eq &quot;body&quot;);
</ins><span class="cx">     next if ($_ eq &quot;Status&quot; and $hasStatusCode);
</span><span class="cx">     next if ($_ eq &quot;Expires&quot; and $hasExpiresHeader);
</span><span class="cx">     print $_ . &quot;: &quot; . $query-&gt;param($_) . &quot;\n&quot;;
</span><span class="cx"> }
</span><span class="cx"> print &quot;\n&quot;;
</span><del>-print &quot;test&quot; if $includeBody;
</del><ins>+if ($delay) {
+    # Include some padding so headers and full body are sent separately.
+    for (my $i=0; $i &lt; 1024; $i++) {
+        print &quot;                                                                                &quot;;
+    }
+    sleep $delay;
+}
+print $body if $body;
</ins></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/Source/WebKit2/ChangeLog        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2015-08-31  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Network Cache: Stale content after back navigation
+        https://bugs.webkit.org/show_bug.cgi?id=148634
+
+        Reviewed by Chris Dumez.
+
+        It is possible to get an older version of the previous page when navigating back. This can happen
+        if the main resource load has not completed before navigating away from the page.
+
+        Network cache entry is normally updated when the load completes. In case of cancellation we would leave
+        any existing entry as-is. However we render incrementally and user might have seen some content from
+        the partial load already. Navigating back to the cached page could show older version of the content.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::abort):
+
+            If a network load is canceled by the client after receiving response but before the load has completed
+            remove any existing cache entry for it.
+
</ins><span class="cx"> 2015-08-28  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Migrate GraphicsContexts from pointers to references
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp (189176 => 189177)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2015-08-31 18:15:09 UTC (rev 189176)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2015-08-31 18:31:04 UTC (rev 189177)
</span><span class="lines">@@ -223,9 +223,18 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(RunLoop::isMain());
</span><span class="cx"> 
</span><del>-    if (m_handle &amp;&amp; !m_didConvertHandleToDownload)
</del><ins>+    if (m_handle &amp;&amp; !m_didConvertHandleToDownload) {
</ins><span class="cx">         m_handle-&gt;cancel();
</span><span class="cx"> 
</span><ins>+#if ENABLE(NETWORK_CACHE)
+        if (NetworkCache::singleton().isEnabled()) {
+            // We might already have used data from this incomplete load. Ensure older versions don't remain in the cache after cancel.
+            if (!m_response.isNull())
+                NetworkCache::singleton().remove(originalRequest());
+        }
+#endif
+    }
+
</ins><span class="cx">     cleanup();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>