<!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>[182059] 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/182059">182059</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2015-03-27 08:13:02 -0700 (Fri, 27 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Respect cache-control directives in request
https://bugs.webkit.org/show_bug.cgi?id=143121
Source/WebCore:

rdar://problem/19714040

Reviewed by Chris Dumez.

Test: http/tests/cache/disk-cache/disk-cache-request-headers.html

* loader/cache/CacheValidation.cpp:
(WebCore::isCacheHeaderSeparator):
(WebCore::isControlCharacter):
(WebCore::trimToNextSeparator):
(WebCore::parseCacheHeader):
(WebCore::parseCacheControlDirectives):

    Factor Cache-control parsing here so it can be used for both requests and responses.

* loader/cache/CacheValidation.h:
* platform/network/ResourceRequestBase.h:
* platform/network/ResourceResponseBase.cpp:
(WebCore::ResourceResponseBase::ResourceResponseBase):
(WebCore::ResourceResponseBase::parseCacheControlDirectives):
(WebCore::ResourceResponseBase::cacheControlContainsNoCache):
(WebCore::ResourceResponseBase::cacheControlContainsNoStore):
(WebCore::ResourceResponseBase::cacheControlContainsMustRevalidate):
(WebCore::ResourceResponseBase::cacheControlMaxAge):
(WebCore::isCacheHeaderSeparator): Deleted.
(WebCore::isControlCharacter): Deleted.
(WebCore::trimToNextSeparator): Deleted.
(WebCore::parseCacheHeader): Deleted.
* platform/network/ResourceResponseBase.h:

Source/WebKit2:

rdar://problem/19714040

Reviewed by Chris Dumez.

Better support for https://tools.ietf.org/html/rfc7234#section-5.2.1

* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::canUse):

    Consider requests with Cache-control: no-cache and max-age=0 expired.

(WebKit::NetworkCache::canStore):

    Don't store requests with Cache-control: no-store.

(WebKit::NetworkCache::Cache::store):
* NetworkProcess/cache/NetworkCache.h:
* NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm:
(WebKit::NetworkCache::storeDecisionToDiagnosticKey):

LayoutTests:


Reviewed by Chris Dumez.

* http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt: Added.
* http/tests/cache/disk-cache/disk-cache-request-headers.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCacheValidationcpp">trunk/Source/WebCore/loader/cache/CacheValidation.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCacheValidationh">trunk/Source/WebCore/loader/cache/CacheValidation.h</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkResourceRequestBaseh">trunk/Source/WebCore/platform/network/ResourceRequestBase.h</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkResourceResponseBasecpp">trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkResourceResponseBaseh">trunk/Source/WebCore/platform/network/ResourceResponseBase.h</a></li>
<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="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsCocoamm">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestscachediskcachediskcacherequestheadersexpectedtxt">trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestscachediskcachediskcacherequestheadershtml">trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/LayoutTests/ChangeLog        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-03-26  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Respect cache-control directives in request
+        https://bugs.webkit.org/show_bug.cgi?id=143121
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt: Added.
+        * http/tests/cache/disk-cache/disk-cache-request-headers.html: Added.
+
</ins><span class="cx"> 2015-03-27  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Objects with numeric properties intermittently get a phantom 'length' property
</span></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachediskcacherequestheadersexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt (0 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers-expected.txt        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -0,0 +1,105 @@
</span><ins>+Test permutations of various cache headers
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+running 24 tests
+
+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: Disk cache
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store, max-age=0&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+response source: Disk cache
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store, max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-store, max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=0&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store, max-age=100&quot;}
+response source: Network
+
+response headers: {&quot;Cache-control&quot;:&quot;max-age=100&quot;}
+request headers: {&quot;Cache-control&quot;:&quot;no-cache, no-store, max-age=100&quot;}
+response source: Network
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestscachediskcachediskcacherequestheadershtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers.html (0 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/cache/disk-cache/disk-cache-request-headers.html        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -0,0 +1,37 @@
</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 testMatrix =
+[
+ [
+  { responseHeaders: {'Cache-control': 'max-age=0' } },
+  { responseHeaders: {'Cache-control': 'max-age=100' } },
+  ],
+ [
+  {},
+  { requestHeaders: {'Cache-control': 'no-cache' } },
+  ],
+ [
+  {},
+  { requestHeaders: {'Cache-control': 'no-store' } },
+  ],
+ [
+  {},
+  { requestHeaders: {'Cache-control': 'max-age=0' } },
+  { requestHeaders: {'Cache-control': 'max-age=100' } },
+  ],
+ ];
+
+description(&quot;Test permutations of various cache headers&quot;);
+
+var tests = generateTests(testMatrix);
+
+debug(&quot;running &quot; + tests.length + &quot; tests&quot;);
+debug(&quot;&quot;);
+
+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="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/ChangeLog        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2015-03-26  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Respect cache-control directives in request
+        https://bugs.webkit.org/show_bug.cgi?id=143121
+        rdar://problem/19714040
+
+        Reviewed by Chris Dumez.
+
+        Test: http/tests/cache/disk-cache/disk-cache-request-headers.html
+
+        * loader/cache/CacheValidation.cpp:
+        (WebCore::isCacheHeaderSeparator):
+        (WebCore::isControlCharacter):
+        (WebCore::trimToNextSeparator):
+        (WebCore::parseCacheHeader):
+        (WebCore::parseCacheControlDirectives):
+
+            Factor Cache-control parsing here so it can be used for both requests and responses.
+
+        * loader/cache/CacheValidation.h:
+        * platform/network/ResourceRequestBase.h:
+        * platform/network/ResourceResponseBase.cpp:
+        (WebCore::ResourceResponseBase::ResourceResponseBase):
+        (WebCore::ResourceResponseBase::parseCacheControlDirectives):
+        (WebCore::ResourceResponseBase::cacheControlContainsNoCache):
+        (WebCore::ResourceResponseBase::cacheControlContainsNoStore):
+        (WebCore::ResourceResponseBase::cacheControlContainsMustRevalidate):
+        (WebCore::ResourceResponseBase::cacheControlMaxAge):
+        (WebCore::isCacheHeaderSeparator): Deleted.
+        (WebCore::isControlCharacter): Deleted.
+        (WebCore::trimToNextSeparator): Deleted.
+        (WebCore::parseCacheHeader): Deleted.
+        * platform/network/ResourceResponseBase.h:
+
</ins><span class="cx"> 2015-03-27  Víctor Manuel Jáquez Leal  &lt;vjaquez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GStreamer] share GL context in pipeline, part 2
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCacheValidationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CacheValidation.cpp (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CacheValidation.cpp        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/loader/cache/CacheValidation.cpp        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;CacheValidation.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;HTTPHeaderMap.h&quot;
</ins><span class="cx"> #include &quot;ResourceResponse.h&quot;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -149,4 +150,144 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isCacheHeaderSeparator(UChar c)
+{
+    // See RFC 2616, Section 2.2
+    switch (c) {
+    case '(':
+    case ')':
+    case '&lt;':
+    case '&gt;':
+    case '@':
+    case ',':
+    case ';':
+    case ':':
+    case '\\':
+    case '&quot;':
+    case '/':
+    case '[':
+    case ']':
+    case '?':
+    case '=':
+    case '{':
+    case '}':
+    case ' ':
+    case '\t':
+        return true;
+    default:
+        return false;
+    }
</ins><span class="cx"> }
</span><ins>+
+inline bool isControlCharacter(UChar c)
+{
+    return c &lt; ' ' || c == 127;
+}
+
+inline String trimToNextSeparator(const String&amp; str)
+{
+    return str.substring(0, str.find(isCacheHeaderSeparator));
+}
+
+static Vector&lt;std::pair&lt;String, String&gt;&gt; parseCacheHeader(const String&amp; header)
+{
+    Vector&lt;std::pair&lt;String, String&gt;&gt; result;
+
+    const String safeHeader = header.removeCharacters(isControlCharacter);
+    unsigned max = safeHeader.length();
+    unsigned pos = 0;
+    while (pos &lt; max) {
+        size_t nextCommaPosition = safeHeader.find(',', pos);
+        size_t nextEqualSignPosition = safeHeader.find('=', pos);
+        if (nextEqualSignPosition == notFound &amp;&amp; nextCommaPosition == notFound) {
+            // Add last directive to map with empty string as value
+            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), &quot;&quot;));
+            return result;
+        }
+        if (nextCommaPosition != notFound &amp;&amp; (nextCommaPosition &lt; nextEqualSignPosition || nextEqualSignPosition == notFound)) {
+            // Add directive to map with empty string as value
+            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), &quot;&quot;));
+            pos += nextCommaPosition - pos + 1;
+            continue;
+        }
+        // Get directive name, parse right hand side of equal sign, then add to map
+        String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
+        pos += nextEqualSignPosition - pos + 1;
+
+        String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
+        if (value[0] == '&quot;') {
+            // The value is a quoted string
+            size_t nextDoubleQuotePosition = value.find('&quot;', 1);
+            if (nextDoubleQuotePosition == notFound) {
+                // Parse error; just use the rest as the value
+                result.append(std::make_pair(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
+                return result;
+            }
+            // Store the value as a quoted string without quotes
+            result.append(std::make_pair(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
+            pos += (safeHeader.find('&quot;', pos) - pos) + nextDoubleQuotePosition + 1;
+            // Move past next comma, if there is one
+            size_t nextCommaPosition2 = safeHeader.find(',', pos);
+            if (nextCommaPosition2 == notFound)
+                return result; // Parse error if there is anything left with no comma
+            pos += nextCommaPosition2 - pos + 1;
+            continue;
+        }
+        // The value is a token until the next comma
+        size_t nextCommaPosition2 = value.find(',');
+        if (nextCommaPosition2 == notFound) {
+            // The rest is the value; no change to value needed
+            result.append(std::make_pair(directive, trimToNextSeparator(value)));
+            return result;
+        }
+        // The value is delimited by the next comma
+        result.append(std::make_pair(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
+        pos += (safeHeader.find(',', pos) - pos) + 1;
+    }
+    return result;
+}
+
+CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&amp; headers)
+{
+    CacheControlDirectives result;
+
+    String cacheControlValue = headers.get(HTTPHeaderName::CacheControl);
+    if (!cacheControlValue.isEmpty()) {
+        auto directives = parseCacheHeader(cacheControlValue);
+
+        size_t directivesSize = directives.size();
+        for (size_t i = 0; i &lt; directivesSize; ++i) {
+            // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
+            // It should be ignored by a browser level cache.
+            if (equalIgnoringCase(directives[i].first, &quot;no-cache&quot;) &amp;&amp; directives[i].second.isEmpty())
+                result.noCache = true;
+            else if (equalIgnoringCase(directives[i].first, &quot;no-store&quot;))
+                result.noStore = true;
+            else if (equalIgnoringCase(directives[i].first, &quot;must-revalidate&quot;))
+                result.mustRevalidate = true;
+            else if (equalIgnoringCase(directives[i].first, &quot;max-age&quot;)) {
+                if (!std::isnan(result.maxAge)) {
+                    // First max-age directive wins if there are multiple ones.
+                    continue;
+                }
+                bool ok;
+                double maxAge = directives[i].second.toDouble(&amp;ok);
+                if (ok)
+                    result.maxAge = maxAge;
+            }
+        }
+    }
+
+    if (!result.noCache) {
+        // Handle Pragma: no-cache
+        // This is deprecated and equivalent to Cache-control: no-cache
+        // Don't bother tokenizing the value, it is not important
+        String pragmaValue = headers.get(HTTPHeaderName::Pragma);
+
+        result.noCache = pragmaValue.contains(&quot;no-cache&quot;, false);
+    }
+
+    return result;
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCacheValidationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CacheValidation.h (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CacheValidation.h        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/loader/cache/CacheValidation.h        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class HTTPHeaderMap;
</ins><span class="cx"> class ResourceResponse;
</span><span class="cx"> 
</span><span class="cx"> struct RedirectChainCacheStatus {
</span><span class="lines">@@ -52,6 +53,14 @@
</span><span class="cx"> enum ReuseExpiredRedirectionOrNot { DoNotReuseExpiredRedirection, ReuseExpiredRedirection };
</span><span class="cx"> WEBCORE_EXPORT bool redirectChainAllowsReuse(RedirectChainCacheStatus, ReuseExpiredRedirectionOrNot);
</span><span class="cx"> 
</span><ins>+struct CacheControlDirectives {
+    double maxAge { std::numeric_limits&lt;double&gt;::quiet_NaN() };
+    bool noCache { false };
+    bool noStore { false };
+    bool mustRevalidate { false };
+};
+WEBCORE_EXPORT CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&amp;);
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkResourceRequestBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/ResourceRequestBase.h (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/ResourceRequestBase.h        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/platform/network/ResourceRequestBase.h        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx">         WEBCORE_EXPORT const String&amp; httpMethod() const;
</span><span class="cx">         WEBCORE_EXPORT void setHTTPMethod(const String&amp; httpMethod);
</span><span class="cx">         
</span><del>-        const HTTPHeaderMap&amp; httpHeaderFields() const;
</del><ins>+        WEBCORE_EXPORT const HTTPHeaderMap&amp; httpHeaderFields() const;
</ins><span class="cx">         WEBCORE_EXPORT void setHTTPHeaderFields(HTTPHeaderMap);
</span><span class="cx"> 
</span><span class="cx">         WEBCORE_EXPORT String httpHeaderField(const String&amp; name) const;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkResourceResponseBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ResourceResponseBase.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CacheValidation.h&quot;
</ins><span class="cx"> #include &quot;HTTPHeaderNames.h&quot;
</span><span class="cx"> #include &quot;HTTPParsers.h&quot;
</span><span class="cx"> #include &quot;ResourceResponse.h&quot;
</span><span class="lines">@@ -37,8 +38,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static void parseCacheHeader(const String&amp; header, Vector&lt;std::pair&lt;String, String&gt;&gt;&amp; result);
-
</del><span class="cx"> inline const ResourceResponse&amp; ResourceResponseBase::asResourceResponse() const
</span><span class="cx"> {
</span><span class="cx">     return *static_cast&lt;const ResourceResponse*&gt;(this);
</span><span class="lines">@@ -48,7 +47,6 @@
</span><span class="cx">     : m_expectedContentLength(0)
</span><span class="cx">     , m_includesCertificateInfo(false)
</span><span class="cx">     , m_httpStatusCode(0)
</span><del>-    , m_cacheControlMaxAge(0)
</del><span class="cx">     , m_age(0)
</span><span class="cx">     , m_date(0)
</span><span class="cx">     , m_expires(0)
</span><span class="lines">@@ -59,9 +57,6 @@
</span><span class="cx">     , m_haveParsedDateHeader(false)
</span><span class="cx">     , m_haveParsedExpiresHeader(false)
</span><span class="cx">     , m_haveParsedLastModifiedHeader(false)
</span><del>-    , m_cacheControlContainsNoCache(false)
-    , m_cacheControlContainsNoStore(false)
-    , m_cacheControlContainsMustRevalidate(false)
</del><span class="cx">     , m_source(Source::Unknown)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -73,7 +68,6 @@
</span><span class="cx">     , m_textEncodingName(textEncodingName)
</span><span class="cx">     , m_includesCertificateInfo(true) // Empty but valid for synthetic responses.
</span><span class="cx">     , m_httpStatusCode(0)
</span><del>-    , m_cacheControlMaxAge(0)
</del><span class="cx">     , m_age(0)
</span><span class="cx">     , m_date(0)
</span><span class="cx">     , m_expires(0)
</span><span class="lines">@@ -84,9 +78,6 @@
</span><span class="cx">     , m_haveParsedDateHeader(false)
</span><span class="cx">     , m_haveParsedExpiresHeader(false)
</span><span class="cx">     , m_haveParsedLastModifiedHeader(false)
</span><del>-    , m_cacheControlContainsNoCache(false)
-    , m_cacheControlContainsNoStore(false)
-    , m_cacheControlContainsMustRevalidate(false)
</del><span class="cx">     , m_source(Source::Unknown)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -358,69 +349,29 @@
</span><span class="cx"> 
</span><span class="cx">     lazyInit(CommonFieldsOnly);
</span><span class="cx"> 
</span><ins>+    m_cacheControlDirectives = WebCore::parseCacheControlDirectives(m_httpHeaderFields);
</ins><span class="cx">     m_haveParsedCacheControlHeader = true;
</span><del>-
-    m_cacheControlContainsMustRevalidate = false;
-    m_cacheControlContainsNoCache = false;
-    m_cacheControlMaxAge = std::numeric_limits&lt;double&gt;::quiet_NaN();
-
-    String cacheControlValue = m_httpHeaderFields.get(HTTPHeaderName::CacheControl);
-    if (!cacheControlValue.isEmpty()) {
-        Vector&lt;std::pair&lt;String, String&gt;&gt; directives;
-        parseCacheHeader(cacheControlValue, directives);
-
-        size_t directivesSize = directives.size();
-        for (size_t i = 0; i &lt; directivesSize; ++i) {
-            // RFC2616 14.9.1: A no-cache directive with a value is only meaningful for proxy caches.
-            // It should be ignored by a browser level cache.
-            if (equalIgnoringCase(directives[i].first, &quot;no-cache&quot;) &amp;&amp; directives[i].second.isEmpty())
-                m_cacheControlContainsNoCache = true;
-            else if (equalIgnoringCase(directives[i].first, &quot;no-store&quot;))
-                m_cacheControlContainsNoStore = true;
-            else if (equalIgnoringCase(directives[i].first, &quot;must-revalidate&quot;))
-                m_cacheControlContainsMustRevalidate = true;
-            else if (equalIgnoringCase(directives[i].first, &quot;max-age&quot;)) {
-                if (!std::isnan(m_cacheControlMaxAge)) {
-                    // First max-age directive wins if there are multiple ones.
-                    continue;
-                }
-                bool ok;
-                double maxAge = directives[i].second.toDouble(&amp;ok);
-                if (ok)
-                    m_cacheControlMaxAge = maxAge;
-            }
-        }
-    }
-
-    if (!m_cacheControlContainsNoCache) {
-        // Handle Pragma: no-cache
-        // This is deprecated and equivalent to Cache-control: no-cache
-        // Don't bother tokenizing the value, it is not important
-        String pragmaValue = m_httpHeaderFields.get(HTTPHeaderName::Pragma);
-
-        m_cacheControlContainsNoCache = pragmaValue.contains(&quot;no-cache&quot;, false);
-    }
</del><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> bool ResourceResponseBase::cacheControlContainsNoCache() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_haveParsedCacheControlHeader)
</span><span class="cx">         parseCacheControlDirectives();
</span><del>-    return m_cacheControlContainsNoCache;
</del><ins>+    return m_cacheControlDirectives.noCache;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ResourceResponseBase::cacheControlContainsNoStore() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_haveParsedCacheControlHeader)
</span><span class="cx">         parseCacheControlDirectives();
</span><del>-    return m_cacheControlContainsNoStore;
</del><ins>+    return m_cacheControlDirectives.noStore;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ResourceResponseBase::cacheControlContainsMustRevalidate() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_haveParsedCacheControlHeader)
</span><span class="cx">         parseCacheControlDirectives();
</span><del>-    return m_cacheControlContainsMustRevalidate;
</del><ins>+    return m_cacheControlDirectives.mustRevalidate;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ResourceResponseBase::hasCacheValidatorFields() const
</span><span class="lines">@@ -434,7 +385,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (!m_haveParsedCacheControlHeader)
</span><span class="cx">         parseCacheControlDirectives();
</span><del>-    return m_cacheControlMaxAge;
</del><ins>+    return m_cacheControlDirectives.maxAge;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static double parseDateValueInHeader(const HTTPHeaderMap&amp; headers, HTTPHeaderName headerName)
</span><span class="lines">@@ -555,99 +506,4 @@
</span><span class="cx">     return ResourceResponse::platformCompare(a, b);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool isCacheHeaderSeparator(UChar c)
-{
-    // See RFC 2616, Section 2.2
-    switch (c) {
-        case '(':
-        case ')':
-        case '&lt;':
-        case '&gt;':
-        case '@':
-        case ',':
-        case ';':
-        case ':':
-        case '\\':
-        case '&quot;':
-        case '/':
-        case '[':
-        case ']':
-        case '?':
-        case '=':
-        case '{':
-        case '}':
-        case ' ':
-        case '\t':
-            return true;
-        default:
-            return false;
-    }
</del><span class="cx"> }
</span><del>-
-static bool isControlCharacter(UChar c)
-{
-    return c &lt; ' ' || c == 127;
-}
-
-static inline String trimToNextSeparator(const String&amp; str)
-{
-    return str.substring(0, str.find(isCacheHeaderSeparator));
-}
-
-static void parseCacheHeader(const String&amp; header, Vector&lt;std::pair&lt;String, String&gt;&gt;&amp; result)
-{
-    const String safeHeader = header.removeCharacters(isControlCharacter);
-    unsigned max = safeHeader.length();
-    for (unsigned pos = 0; pos &lt; max; /* pos incremented in loop */) {
-        size_t nextCommaPosition = safeHeader.find(',', pos);
-        size_t nextEqualSignPosition = safeHeader.find('=', pos);
-        if (nextEqualSignPosition != notFound &amp;&amp; (nextEqualSignPosition &lt; nextCommaPosition || nextCommaPosition == notFound)) {
-            // Get directive name, parse right hand side of equal sign, then add to map
-            String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
-            pos += nextEqualSignPosition - pos + 1;
-
-            String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
-            if (value[0] == '&quot;') {
-                // The value is a quoted string
-                size_t nextDoubleQuotePosition = value.find('&quot;', 1);
-                if (nextDoubleQuotePosition != notFound) {
-                    // Store the value as a quoted string without quotes
-                    result.append(std::pair&lt;String, String&gt;(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
-                    pos += (safeHeader.find('&quot;', pos) - pos) + nextDoubleQuotePosition + 1;
-                    // Move past next comma, if there is one
-                    size_t nextCommaPosition2 = safeHeader.find(',', pos);
-                    if (nextCommaPosition2 != notFound)
-                        pos += nextCommaPosition2 - pos + 1;
-                    else
-                        return; // Parse error if there is anything left with no comma
-                } else {
-                    // Parse error; just use the rest as the value
-                    result.append(std::pair&lt;String, String&gt;(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
-                    return;
-                }
-            } else {
-                // The value is a token until the next comma
-                size_t nextCommaPosition2 = value.find(',');
-                if (nextCommaPosition2 != notFound) {
-                    // The value is delimited by the next comma
-                    result.append(std::pair&lt;String, String&gt;(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
-                    pos += (safeHeader.find(',', pos) - pos) + 1;
-                } else {
-                    // The rest is the value; no change to value needed
-                    result.append(std::pair&lt;String, String&gt;(directive, trimToNextSeparator(value)));
-                    return;
-                }
-            }
-        } else if (nextCommaPosition != notFound &amp;&amp; (nextCommaPosition &lt; nextEqualSignPosition || nextEqualSignPosition == notFound)) {
-            // Add directive to map with empty string as value
-            result.append(std::pair&lt;String, String&gt;(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), &quot;&quot;));
-            pos += nextCommaPosition - pos + 1;
-        } else {
-            // Add last directive to map with empty string as value
-            result.append(std::pair&lt;String, String&gt;(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), &quot;&quot;));
-            return;
-        }
-    }
-}
-
-}
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkResourceResponseBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.h (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/ResourceResponseBase.h        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.h        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #ifndef ResourceResponseBase_h
</span><span class="cx"> #define ResourceResponseBase_h
</span><span class="cx"> 
</span><ins>+#include &quot;CacheValidation.h&quot;
</ins><span class="cx"> #include &quot;CertificateInfo.h&quot;
</span><span class="cx"> #include &quot;HTTPHeaderMap.h&quot;
</span><span class="cx"> #include &quot;URL.h&quot;
</span><span class="lines">@@ -160,11 +161,11 @@
</span><span class="cx">     int m_httpStatusCode;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    mutable double m_cacheControlMaxAge;
</del><span class="cx">     mutable double m_age;
</span><span class="cx">     mutable double m_date;
</span><span class="cx">     mutable double m_expires;
</span><span class="cx">     mutable double m_lastModified;
</span><ins>+    mutable CacheControlDirectives m_cacheControlDirectives;
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     bool m_isNull : 1;
</span><span class="lines">@@ -180,10 +181,6 @@
</span><span class="cx">     mutable bool m_haveParsedExpiresHeader : 1;
</span><span class="cx">     mutable bool m_haveParsedLastModifiedHeader : 1;
</span><span class="cx"> 
</span><del>-    mutable bool m_cacheControlContainsNoCache : 1;
-    mutable bool m_cacheControlContainsNoStore : 1;
-    mutable bool m_cacheControlContainsMustRevalidate : 1;
-
</del><span class="cx">     Source m_source;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebKit2/ChangeLog        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2015-03-26  Antti Koivisto  &lt;antti@apple.com&gt;
+
+        Respect cache-control directives in request
+        https://bugs.webkit.org/show_bug.cgi?id=143121
+        rdar://problem/19714040
+
+        Reviewed by Chris Dumez.
+
+        Better support for https://tools.ietf.org/html/rfc7234#section-5.2.1
+
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::canUse):
+
+            Consider requests with Cache-control: no-cache and max-age=0 expired.
+
+        (WebKit::NetworkCache::canStore):
+
+            Don't store requests with Cache-control: no-store.
+
+        (WebKit::NetworkCache::Cache::store):
+        * NetworkProcess/cache/NetworkCache.h:
+        * NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm:
+        (WebKit::NetworkCache::storeDecisionToDiagnosticKey):
+
</ins><span class="cx"> 2015-03-25  Jon Honeycutt  &lt;jhoneycutt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         iOS file upload panel menu items need icons
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool responseHasExpired(const WebCore::ResourceResponse&amp; response, std::chrono::milliseconds timestamp)
</del><ins>+static bool responseHasExpired(const WebCore::ResourceResponse&amp; response, std::chrono::milliseconds timestamp)
</ins><span class="cx"> {
</span><span class="cx">     if (response.cacheControlContainsNoCache())
</span><span class="cx">         return true;
</span><span class="lines">@@ -169,6 +169,18 @@
</span><span class="cx">     return hasExpired;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool requestNeedsRevalidation(const WebCore::ResourceRequest&amp; request)
+{
+    auto requestDirectives = WebCore::parseCacheControlDirectives(request.httpHeaderFields());
+    if (requestDirectives.noCache)
+        return true;
+    // For requests we ignore max-age values other than zero.
+    if (requestDirectives.maxAge == 0)
+        return true;
+
+    return false;
+}
+
</ins><span class="cx"> static UseDecision canUse(const Entry&amp; entry, const WebCore::ResourceRequest&amp; request)
</span><span class="cx"> {
</span><span class="cx">     if (!verifyVaryingRequestHeaders(entry.varyingRequestHeaders(), request)) {
</span><span class="lines">@@ -176,8 +188,11 @@
</span><span class="cx">         return UseDecision::NoDueToVaryingHeaderMismatch;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // We never revalidate in the case of a history navigation (i.e. cachePolicyAllowsExpired() returns true).
-    bool needsRevalidation = !cachePolicyAllowsExpired(request.cachePolicy()) &amp;&amp; responseHasExpired(entry.response(), entry.timeStamp());
</del><ins>+    // We never revalidate in the case of a history navigation.
+    if (cachePolicyAllowsExpired(request.cachePolicy()))
+        return UseDecision::Use;
+
+    bool needsRevalidation = requestNeedsRevalidation(request) || responseHasExpired(entry.response(), entry.timeStamp());
</ins><span class="cx">     if (!needsRevalidation)
</span><span class="cx">         return UseDecision::Use;
</span><span class="cx"> 
</span><span class="lines">@@ -266,15 +281,19 @@
</span><span class="cx"> 
</span><span class="cx"> static StoreDecision canStore(const WebCore::ResourceRequest&amp; originalRequest, const WebCore::ResourceResponse&amp; response)
</span><span class="cx"> {
</span><del>-    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP()) {
-        LOG(NetworkCache, &quot;(NetworkProcess) not HTTP&quot;);
</del><ins>+    if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
</ins><span class="cx">         return StoreDecision::NoDueToProtocol;
</span><del>-    }
-    if (originalRequest.httpMethod() != &quot;GET&quot;) {
-        LOG(NetworkCache, &quot;(NetworkProcess) method %s&quot;, originalRequest.httpMethod().utf8().data());
</del><ins>+
+    if (originalRequest.httpMethod() != &quot;GET&quot;)
</ins><span class="cx">         return StoreDecision::NoDueToHTTPMethod;
</span><del>-    }
</del><span class="cx"> 
</span><ins>+    auto requestDirectives = WebCore::parseCacheControlDirectives(originalRequest.httpHeaderFields());
+    if (requestDirectives.noStore)
+        return StoreDecision::NoDueToNoStoreRequest;
+
+    if (response.cacheControlContainsNoStore())
+        return StoreDecision::NoDueToNoStoreResponse;
+
</ins><span class="cx">     switch (response.httpStatusCode()) {
</span><span class="cx">     case 200: // OK
</span><span class="cx">     case 203: // Non-Authoritative Information
</span><span class="lines">@@ -284,10 +303,6 @@
</span><span class="cx">     case 307: // Temporary Redirect
</span><span class="cx">     case 404: // Not Found
</span><span class="cx">     case 410: // Gone
</span><del>-        if (response.cacheControlContainsNoStore()) {
-            LOG(NetworkCache, &quot;(NetworkProcess) Cache-control:no-store&quot;);
-            return StoreDecision::NoDueToNoStoreResponse;
-        }
</del><span class="cx">         return StoreDecision::Yes;
</span><span class="cx">     default:
</span><span class="cx">         LOG(NetworkCache, &quot;(NetworkProcess) status code %d&quot;, response.httpStatusCode());
</span><span class="lines">@@ -305,7 +320,7 @@
</span><span class="cx"> 
</span><span class="cx">     StoreDecision storeDecision = canStore(originalRequest, response);
</span><span class="cx">     if (storeDecision != StoreDecision::Yes) {
</span><del>-        LOG(NetworkCache, &quot;(NetworkProcess) didn't store&quot;);
</del><ins>+        LOG(NetworkCache, &quot;(NetworkProcess) didn't store, storeDecision=%d&quot;, storeDecision);
</ins><span class="cx">         if (m_statistics) {
</span><span class="cx">             auto key = makeCacheKey(originalRequest);
</span><span class="cx">             m_statistics-&gt;recordNotCachingResponse(key, storeDecision);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -68,7 +68,8 @@
</span><span class="cx">     NoDueToHTTPMethod,
</span><span class="cx">     NoDueToAttachmentResponse,
</span><span class="cx">     NoDueToNoStoreResponse,
</span><del>-    NoDueToHTTPStatusCode
</del><ins>+    NoDueToHTTPStatusCode,
+    NoDueToNoStoreRequest
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> enum class UseDecision {
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm (182058 => 182059)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm        2015-03-27 14:28:34 UTC (rev 182058)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm        2015-03-27 15:13:02 UTC (rev 182059)
</span><span class="lines">@@ -236,6 +236,7 @@
</span><span class="cx">     case StoreDecision::NoDueToAttachmentResponse:
</span><span class="cx">         return WebCore::DiagnosticLoggingKeys::isAttachmentKey();
</span><span class="cx">     case StoreDecision::NoDueToNoStoreResponse:
</span><ins>+    case StoreDecision::NoDueToNoStoreRequest:
</ins><span class="cx">         return WebCore::DiagnosticLoggingKeys::cacheControlNoStoreKey();
</span><span class="cx">     case StoreDecision::NoDueToHTTPStatusCode:
</span><span class="cx">         return WebCore::DiagnosticLoggingKeys::uncacheableStatusCodeKey();
</span></span></pre>
</div>
</div>

</body>
</html>