<!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 <antti@apple.com>
+
+ 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 <msaboff@apple.com>
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+running 24 tests
+
+response headers: {"Cache-control":"max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache, no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache, no-store"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-store, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-store, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache, no-store, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache, no-store, max-age=0"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"max-age=100"}
+response source: Disk cache
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache, max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache, max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-store, max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-store, max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=0"}
+request headers: {"Cache-control":"no-cache, no-store, max-age=100"}
+response source: Network
+
+response headers: {"Cache-control":"max-age=100"}
+request headers: {"Cache-control":"no-cache, no-store, max-age=100"}
+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>+<script src="/js-test-resources/js-test-pre.js"></script>
+<script src="resources/cache-test.js"></script>
+<body>
+<script>
+
+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("Test permutations of various cache headers");
+
+var tests = generateTests(testMatrix);
+
+debug("running " + tests.length + " tests");
+debug("");
+
+runTests(tests);
+
+</script>
+<script src="/js-test-resources/js-test-post.js"></script>
</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 <antti@apple.com>
+
+ 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 <vjaquez@igalia.com>
</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 "config.h"
</span><span class="cx"> #include "CacheValidation.h"
</span><span class="cx">
</span><ins>+#include "HTTPHeaderMap.h"
</ins><span class="cx"> #include "ResourceResponse.h"
</span><span class="cx"> #include <wtf/CurrentTime.h>
</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 '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '\\':
+ case '"':
+ 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 < ' ' || c == 127;
+}
+
+inline String trimToNextSeparator(const String& str)
+{
+ return str.substring(0, str.find(isCacheHeaderSeparator));
+}
+
+static Vector<std::pair<String, String>> parseCacheHeader(const String& header)
+{
+ Vector<std::pair<String, String>> result;
+
+ const String safeHeader = header.removeCharacters(isControlCharacter);
+ unsigned max = safeHeader.length();
+ unsigned pos = 0;
+ while (pos < max) {
+ size_t nextCommaPosition = safeHeader.find(',', pos);
+ size_t nextEqualSignPosition = safeHeader.find('=', pos);
+ if (nextEqualSignPosition == notFound && nextCommaPosition == notFound) {
+ // Add last directive to map with empty string as value
+ result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
+ return result;
+ }
+ if (nextCommaPosition != notFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == notFound)) {
+ // Add directive to map with empty string as value
+ result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
+ 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] == '"') {
+ // The value is a quoted string
+ size_t nextDoubleQuotePosition = value.find('"', 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('"', 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& 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 < 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, "no-cache") && directives[i].second.isEmpty())
+ result.noCache = true;
+ else if (equalIgnoringCase(directives[i].first, "no-store"))
+ result.noStore = true;
+ else if (equalIgnoringCase(directives[i].first, "must-revalidate"))
+ result.mustRevalidate = true;
+ else if (equalIgnoringCase(directives[i].first, "max-age")) {
+ if (!std::isnan(result.maxAge)) {
+ // First max-age directive wins if there are multiple ones.
+ continue;
+ }
+ bool ok;
+ double maxAge = directives[i].second.toDouble(&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("no-cache", 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<double>::quiet_NaN() };
+ bool noCache { false };
+ bool noStore { false };
+ bool mustRevalidate { false };
+};
+WEBCORE_EXPORT CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&);
+
</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& httpMethod() const;
</span><span class="cx"> WEBCORE_EXPORT void setHTTPMethod(const String& httpMethod);
</span><span class="cx">
</span><del>- const HTTPHeaderMap& httpHeaderFields() const;
</del><ins>+ WEBCORE_EXPORT const HTTPHeaderMap& 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& 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 "config.h"
</span><span class="cx"> #include "ResourceResponseBase.h"
</span><span class="cx">
</span><ins>+#include "CacheValidation.h"
</ins><span class="cx"> #include "HTTPHeaderNames.h"
</span><span class="cx"> #include "HTTPParsers.h"
</span><span class="cx"> #include "ResourceResponse.h"
</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& header, Vector<std::pair<String, String>>& result);
-
</del><span class="cx"> inline const ResourceResponse& ResourceResponseBase::asResourceResponse() const
</span><span class="cx"> {
</span><span class="cx"> return *static_cast<const ResourceResponse*>(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<double>::quiet_NaN();
-
- String cacheControlValue = m_httpHeaderFields.get(HTTPHeaderName::CacheControl);
- if (!cacheControlValue.isEmpty()) {
- Vector<std::pair<String, String>> directives;
- parseCacheHeader(cacheControlValue, directives);
-
- size_t directivesSize = directives.size();
- for (size_t i = 0; i < 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, "no-cache") && directives[i].second.isEmpty())
- m_cacheControlContainsNoCache = true;
- else if (equalIgnoringCase(directives[i].first, "no-store"))
- m_cacheControlContainsNoStore = true;
- else if (equalIgnoringCase(directives[i].first, "must-revalidate"))
- m_cacheControlContainsMustRevalidate = true;
- else if (equalIgnoringCase(directives[i].first, "max-age")) {
- if (!std::isnan(m_cacheControlMaxAge)) {
- // First max-age directive wins if there are multiple ones.
- continue;
- }
- bool ok;
- double maxAge = directives[i].second.toDouble(&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("no-cache", 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& 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 '<':
- case '>':
- case '@':
- case ',':
- case ';':
- case ':':
- case '\\':
- case '"':
- 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 < ' ' || c == 127;
-}
-
-static inline String trimToNextSeparator(const String& str)
-{
- return str.substring(0, str.find(isCacheHeaderSeparator));
-}
-
-static void parseCacheHeader(const String& header, Vector<std::pair<String, String>>& result)
-{
- const String safeHeader = header.removeCharacters(isControlCharacter);
- unsigned max = safeHeader.length();
- for (unsigned pos = 0; pos < max; /* pos incremented in loop */) {
- size_t nextCommaPosition = safeHeader.find(',', pos);
- size_t nextEqualSignPosition = safeHeader.find('=', pos);
- if (nextEqualSignPosition != notFound && (nextEqualSignPosition < 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] == '"') {
- // The value is a quoted string
- size_t nextDoubleQuotePosition = value.find('"', 1);
- if (nextDoubleQuotePosition != notFound) {
- // Store the value as a quoted string without quotes
- result.append(std::pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
- pos += (safeHeader.find('"', 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<String, String>(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<String, String>(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<String, String>(directive, trimToNextSeparator(value)));
- return;
- }
- }
- } else if (nextCommaPosition != notFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == notFound)) {
- // Add directive to map with empty string as value
- result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
- pos += nextCommaPosition - pos + 1;
- } else {
- // Add last directive to map with empty string as value
- result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
- 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 "CacheValidation.h"
</ins><span class="cx"> #include "CertificateInfo.h"
</span><span class="cx"> #include "HTTPHeaderMap.h"
</span><span class="cx"> #include "URL.h"
</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 <antti@apple.com>
+
+ 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 <jhoneycutt@apple.com>
</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& response, std::chrono::milliseconds timestamp)
</del><ins>+static bool responseHasExpired(const WebCore::ResourceResponse& 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& 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& entry, const WebCore::ResourceRequest& 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()) && 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& originalRequest, const WebCore::ResourceResponse& response)
</span><span class="cx"> {
</span><del>- if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP()) {
- LOG(NetworkCache, "(NetworkProcess) not HTTP");
</del><ins>+ if (!originalRequest.url().protocolIsInHTTPFamily() || !response.isHTTP())
</ins><span class="cx"> return StoreDecision::NoDueToProtocol;
</span><del>- }
- if (originalRequest.httpMethod() != "GET") {
- LOG(NetworkCache, "(NetworkProcess) method %s", originalRequest.httpMethod().utf8().data());
</del><ins>+
+ if (originalRequest.httpMethod() != "GET")
</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, "(NetworkProcess) Cache-control:no-store");
- return StoreDecision::NoDueToNoStoreResponse;
- }
</del><span class="cx"> return StoreDecision::Yes;
</span><span class="cx"> default:
</span><span class="cx"> LOG(NetworkCache, "(NetworkProcess) status code %d", 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, "(NetworkProcess) didn't store");
</del><ins>+ LOG(NetworkCache, "(NetworkProcess) didn't store, storeDecision=%d", storeDecision);
</ins><span class="cx"> if (m_statistics) {
</span><span class="cx"> auto key = makeCacheKey(originalRequest);
</span><span class="cx"> m_statistics->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>