<!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>[236216] 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/236216">236216</a></dd>
<dt>Author</dt> <dd>wilander@apple.com</dd>
<dt>Date</dt> <dd>2018-09-19 12:19:56 -0700 (Wed, 19 Sep 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>Resource Load Statistics: Add optional cap on partitioned cache max age
https://bugs.webkit.org/show_bug.cgi?id=189711
<rdar://problem/39246837>

Reviewed by Antti Koivisto and Chris Dumez.

Source/WebCore:

Test: http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html

* platform/network/NetworkStorageSession.h:
* platform/network/cf/NetworkStorageSessionCFNet.cpp:
(WebCore::NetworkStorageSession::maxAgeCacheCap):
    Checks if a max age cap is set and returns it if the request
    represents a prevalent resource.
(WebCore::NetworkStorageSession::setCacheMaxAgeCapForPrevalentResources):
(WebCore::NetworkStorageSession::resetCacheMaxAgeCapForPrevalentResources):
    New functionality to receive a max age cap setting in the session.

Source/WebKit:

These changes add the capability to set a max age cap for prevalent resources
and consults it when retrieving cache entries. If an entry is capped and found
to be too old, it will not be used but instead removed from the cache.

This functionality is off by default because no cap is set by default.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::setCacheMaxAgeCapForPrevalentResources):
(WebKit::NetworkProcess::resetCacheMaxAgeCapForPrevalentResources):
    Infrastructure for testing.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::retrieveCacheEntry):
    Now sends in the session ID in the retrieve call.
* NetworkProcess/cache/NetworkCache.cpp:
(WebKit::NetworkCache::hasReachedPrevalentResourceAgeCap):
    Static convenience function.
(WebKit::NetworkCache::makeUseDecision):
    Now receives an optional maxAge parameter and checks
    hasReachedPrevalentResourceAgeCap() first.
(WebKit::NetworkCache::Cache::retrieve):
    Now takes a session ID.
* NetworkProcess/cache/NetworkCache.h:
* NetworkProcess/cache/NetworkCacheStatistics.cpp:
(WebKit::NetworkCache::cachedEntryReuseFailureToDiagnosticKey):
    Added UseDecision::NoDueToPrevalentResourceAgeCap which causes a
    return of WebCore::DiagnosticLoggingKeys::otherKey().
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap):
(WKWebsiteDataStoreStatisticsResetToConsistentState):
    Infrastructure for testing.
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm:
(WebKit::ResourceLoadStatisticsMemoryStore::registerUserDefaultsIfNeeded):
    Now supports a user default ResourceLoadStatisticsCacheMaxAgeCap.
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::hasStorageAccessForFrame):
(WebKit::NetworkProcessProxy::grantStorageAccess):
(WebKit::NetworkProcessProxy::removeAllStorageAccess):
(WebKit::NetworkProcessProxy::getAllStorageAccessEntries):
(WebKit::NetworkProcessProxy::setCacheMaxAgeCapForPrevalentResources):
(WebKit::NetworkProcessProxy::didSetCacheMaxAgeCapForPrevalentResources):
(WebKit::NetworkProcessProxy::resetCacheMaxAgeCapForPrevalentResources):
(WebKit::NetworkProcessProxy::didResetCacheMaxAgeCapForPrevalentResources):
(WebKit::nextRequestStorageAccessContextId): Deleted.
    Deleted this to make all code use the generic generateCallbackID().
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
    Used to transfer the setting from the UI process to the network process.
* UIProcess/ResourceLoadStatisticsMemoryStore.cpp:
(WebKit::ResourceLoadStatisticsMemoryStore::setCacheMaxAgeCap):
* UIProcess/ResourceLoadStatisticsMemoryStore.h:
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::setCacheMaxAgeCap):
* UIProcess/WebResourceLoadStatisticsStore.h:
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources):
(WebKit::WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources):
* UIProcess/WebsiteData/WebsiteDataStore.h:

Tools:

This change adds infrastructure for layout tests of capped cache max age.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setStatisticsCacheMaxAgeCap):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::setStatisticsCacheMaxAgeCap):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

* http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt: Added.
* http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html: Added.
* http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php: Added.
* http/tests/resourceLoadStatistics/resources/echo-query.php: Added.
* platform/ios/TestExpectations:
    New test marked as [ Pass ].
* platform/mac-wk2/TestExpectations:
    New test marked as [ Pass ].
* platform/wk2/TestExpectations:
    New test marked as [ Skip ] because it's not supported on non-Cocoa platforms.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformiosTestExpectations">trunk/LayoutTests/platform/ios/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsplatformmacwk2TestExpectations">trunk/LayoutTests/platform/mac-wk2/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsplatformwk2TestExpectations">trunk/LayoutTests/platform/wk2/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkNetworkStorageSessionh">trunk/Source/WebCore/platform/network/NetworkStorageSession.h</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkcfNetworkStorageSessionCFNetcpp">trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitNetworkProcessNetworkProcesscpp">trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp</a></li>
<li><a href="#trunkSourceWebKitNetworkProcessNetworkProcessh">trunk/Source/WebKit/NetworkProcess/NetworkProcess.h</a></li>
<li><a href="#trunkSourceWebKitNetworkProcessNetworkProcessmessagesin">trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in</a></li>
<li><a href="#trunkSourceWebKitNetworkProcessNetworkResourceLoadercpp">trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp</a></li>
<li><a href="#trunkSourceWebKitNetworkProcesscacheNetworkCachecpp">trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp</a></li>
<li><a href="#trunkSourceWebKitNetworkProcesscacheNetworkCacheh">trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.h</a></li>
<li><a href="#trunkSourceWebKitNetworkProcesscacheNetworkCacheStatisticscpp">trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStatistics.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICWKWebsiteDataStoreRefcpp">trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICWKWebsiteDataStoreRefh">trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessCocoaResourceLoadStatisticsMemoryStoreCocoamm">trunk/Source/WebKit/UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessNetworkNetworkProcessProxycpp">trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessNetworkNetworkProcessProxyh">trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessNetworkNetworkProcessProxymessagesin">trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKitUIProcessResourceLoadStatisticsMemoryStorecpp">trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessResourceLoadStatisticsMemoryStoreh">trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebResourceLoadStatisticsStorecpp">trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebResourceLoadStatisticsStoreh">trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebsiteDataWebsiteDataStorecpp">trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebsiteDataWebsiteDataStoreh">trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleBindingsTestRunneridl">trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleTestRunnercpp">trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleTestRunnerh">trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnerTestControllercpp">trunk/Tools/WebKitTestRunner/TestController.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerTestControllerh">trunk/Tools/WebKitTestRunner/TestController.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnerTestInvocationcpp">trunk/Tools/WebKitTestRunner/TestInvocation.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestshttptestsresourceLoadStatisticscapcachemaxageforprevalentresourceexpectedtxt">trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt</a></li>
<li><a href="#trunkLayoutTestshttptestsresourceLoadStatisticscapcachemaxageforprevalentresourcehtml">trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html</a></li>
<li><a href="#trunkLayoutTestshttptestsresourceLoadStatisticsresourcescachedpermanentredirectphp">trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php</a></li>
<li><a href="#trunkLayoutTestshttptestsresourceLoadStatisticsresourcesechoqueryphp">trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/echo-query.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/LayoutTests/ChangeLog 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2018-09-19  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Add optional cap on partitioned cache max age
+        https://bugs.webkit.org/show_bug.cgi?id=189711
+        <rdar://problem/39246837>
+
+        Reviewed by Antti Koivisto and Chris Dumez.
+
+        * http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt: Added.
+        * http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html: Added.
+        * http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php: Added.
+        * http/tests/resourceLoadStatistics/resources/echo-query.php: Added.
+        * platform/ios/TestExpectations:
+            New test marked as [ Pass ].
+        * platform/mac-wk2/TestExpectations:
+            New test marked as [ Pass ].
+        * platform/wk2/TestExpectations:
+            New test marked as [ Skip ] because it's not supported on non-Cocoa platforms.
+
</ins><span class="cx"> 2018-09-19  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Layout Test webrtc/video-mute.html is flaky.
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsresourceLoadStatisticscapcachemaxageforprevalentresourceexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt (0 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt                                (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource-expected.txt   2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Tests that cache max-age is capped for prevalent resources.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS loadedUrl is "http://localhost:8000/resourceLoadStatistics/resources/echo-query.php?value=1234"
+PASS loadedUrl is "http://localhost:8000/resourceLoadStatistics/resources/echo-query.php?value="
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsresourceLoadStatisticscapcachemaxageforprevalentresourcehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html (0 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html                                (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html   2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/js-test-resources/js-test.js"></script>
+    <script src="resources/util.js"></script>
+    <title>Tests for Capped Cache Max-Age</title>
+</head>
+<body>
+<script>
+    description("Tests that cache max-age is capped for prevalent resources.");
+    jsTestIsAsync = true;
+
+    var loadedUrl;
+    function firstFetch() {
+        // This should create a capped cache entry.
+        fetch("http://localhost:8000/resourceLoadStatistics/resources/cached-permanent-redirect.php",
+            {
+                cache: "reload",
+                headers: {
+                    "X-WebKit": "1234",
+                }
+            }
+        ).then(function(response) {
+            loadedUrl = response.url;
+            shouldBeEqualToString("loadedUrl", "http://localhost:8000/resourceLoadStatistics/resources/echo-query.php?value=1234");
+            secondFetch();
+        }).catch(function(error) {
+            testFailed(error.message);
+            setEnableFeature(false, finishJSTest);
+        });
+    }
+
+    function secondFetch() {
+        // This should not trigger a successful cache hit.
+        fetch("http://localhost:8000/resourceLoadStatistics/resources/cached-permanent-redirect.php",
+            {
+                cache: "force-cache",
+            }
+        ).then(function(response) {
+            loadedUrl = response.url;
+            shouldBeEqualToString("loadedUrl", "http://localhost:8000/resourceLoadStatistics/resources/echo-query.php?value=");
+            setEnableFeature(false, finishJSTest);
+        }).catch(function(error) {
+            testFailed(error.message);
+            setEnableFeature(false, finishJSTest);
+        });
+    }
+
+    setEnableFeature(true, function() {
+        if (testRunner.isStatisticsPrevalentResource("http://localhost"))
+            testFailed("Localhost was classified as prevalent resource before the test started.");
+
+        testRunner.setStatisticsCacheMaxAgeCap(0);
+        testRunner.setStatisticsPrevalentResource("http://localhost", true, function() {
+            testRunner.statisticsUpdateCookieBlocking(firstFetch);
+        });
+    });
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestshttptestsresourceLoadStatisticsresourcescachedpermanentredirectphp"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php (0 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php                              (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/cached-permanent-redirect.php 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<?php
+header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
+header("Access-Control-Allow-Headers: X-WebKit");
+if ($_SERVER["REQUEST_METHOD"] == "OPTIONS" && isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]) && $_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"] == "GET") {
+  exit;
+}
+$headerStringValue = $_SERVER["HTTP_X_WEBKIT"];
+header("HTTP/1.1 301 Moved Permanently");
+header("Cache-Control: private, max-age=31536000", true);
+header('ETag: "WebKitTest"', true);
+header("Location: http://localhost:8000/resourceLoadStatistics/resources/echo-query.php?value=" . $headerStringValue);
+?>
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsresourceLoadStatisticsresourcesechoqueryphp"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/echo-query.php (0 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/echo-query.php                             (rev 0)
+++ trunk/LayoutTests/http/tests/resourceLoadStatistics/resources/echo-query.php        2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+<?php
+header("Access-Control-Allow-Origin: http://127.0.0.1:8000");
+header("Access-Control-Allow-Headers: X-WebKit");
+if(isset($_GET["value"])) {
+  echo $_GET["value"];
+} else {
+  echo "No query parameter named 'value.'";
+}
+?>
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiosTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios/TestExpectations (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios/TestExpectations  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/LayoutTests/platform/ios/TestExpectations     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -2830,6 +2830,7 @@
</span><span class="cx"> http/tests/resourceLoadStatistics/strip-referrer-to-origin-for-prevalent-subresource-requests.html [ Pass ]
</span><span class="cx"> http/tests/storageAccess/deny-storage-access-under-opener.html [ Pass ]
</span><span class="cx"> http/tests/storageAccess/grant-storage-access-under-opener.html [ Pass ]
</span><ins>+http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Pass ]
</ins><span class="cx"> 
</span><span class="cx"> # Skipped in general expectations since they only work on iOS and Mac, WK2.
</span><span class="cx"> http/tests/security/strip-referrer-to-origin-for-third-party-redirects-in-private-mode.html [ Pass ]
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacwk2TestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-wk2/TestExpectations      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -763,6 +763,7 @@
</span><span class="cx"> [ HighSierra+ ] http/tests/resourceLoadStatistics/grandfathering.html [ Pass ]
</span><span class="cx"> [ HighSierra+ ] http/tests/resourceLoadStatistics/strip-referrer-to-origin-for-prevalent-subresource-redirects.html [ Pass ]
</span><span class="cx"> [ HighSierra+ ] http/tests/resourceLoadStatistics/strip-referrer-to-origin-for-prevalent-subresource-requests.html [ Pass ]
</span><ins>+[ HighSierra+ ] http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Pass ]
</ins><span class="cx"> 
</span><span class="cx"> # Skipped in general expectations since they only work on iOS and Mac, WK2.
</span><span class="cx"> http/tests/security/strip-referrer-to-origin-for-third-party-redirects-in-private-mode.html [ Pass ]
</span></span></pre></div>
<a id="trunkLayoutTestsplatformwk2TestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/wk2/TestExpectations (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/wk2/TestExpectations  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/LayoutTests/platform/wk2/TestExpectations     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -730,6 +730,7 @@
</span><span class="cx"> http/tests/resourceLoadStatistics/add-blocking-to-redirect.html [ Skip ]
</span><span class="cx"> http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [ Skip ]
</span><span class="cx"> http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Skip ]
</span><ins>+http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Skip ]
</ins><span class="cx"> 
</span><span class="cx"> # Process swapping is only implemented on WebKit2.
</span><span class="cx"> http/tests/navigation/process-swap-window-open.html [ Pass ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebCore/ChangeLog      2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2018-09-19  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Add optional cap on partitioned cache max age
+        https://bugs.webkit.org/show_bug.cgi?id=189711
+        <rdar://problem/39246837>
+
+        Reviewed by Antti Koivisto and Chris Dumez.
+
+        Test: http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html
+
+        * platform/network/NetworkStorageSession.h:
+        * platform/network/cf/NetworkStorageSessionCFNet.cpp:
+        (WebCore::NetworkStorageSession::maxAgeCacheCap):
+            Checks if a max age cap is set and returns it if the request
+            represents a prevalent resource.
+        (WebCore::NetworkStorageSession::setCacheMaxAgeCapForPrevalentResources):
+        (WebCore::NetworkStorageSession::resetCacheMaxAgeCapForPrevalentResources):
+            New functionality to receive a max age cap setting in the session.
+
</ins><span class="cx"> 2018-09-19  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Layout Test webrtc/video-mute.html is flaky.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkNetworkStorageSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/NetworkStorageSession.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/NetworkStorageSession.h    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebCore/platform/network/NetworkStorageSession.h       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -110,6 +110,9 @@
</span><span class="cx">     WEBCORE_EXPORT void removeStorageAccessForFrame(uint64_t frameID, uint64_t pageID);
</span><span class="cx">     WEBCORE_EXPORT void removeStorageAccessForAllFramesOnPage(uint64_t pageID);
</span><span class="cx">     WEBCORE_EXPORT void removeAllStorageAccess();
</span><ins>+    WEBCORE_EXPORT void setCacheMaxAgeCapForPrevalentResources(Seconds);
+    WEBCORE_EXPORT void resetCacheMaxAgeCapForPrevalentResources();
+    WEBCORE_EXPORT std::optional<Seconds> maxAgeCacheCap(const ResourceRequest&);
</ins><span class="cx"> #endif
</span><span class="cx"> #elif USE(SOUP)
</span><span class="cx">     NetworkStorageSession(PAL::SessionID, std::unique_ptr<SoupNetworkSession>&&);
</span><span class="lines">@@ -187,6 +190,7 @@
</span><span class="cx">     HashSet<String> m_topPrivatelyControlledDomainsToBlock;
</span><span class="cx">     HashMap<uint64_t, HashMap<uint64_t, String, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> m_framesGrantedStorageAccess;
</span><span class="cx">     HashMap<uint64_t, HashMap<String, String>, DefaultHash<uint64_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> m_pagesGrantedStorageAccess;
</span><ins>+    std::optional<Seconds> m_cacheMaxAgeCapForPrevalentResources { };
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkcfNetworkStorageSessionCFNetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebCore/platform/network/cf/NetworkStorageSessionCFNet.cpp     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -266,6 +266,13 @@
</span><span class="cx">     return shouldBlockThirdPartyCookies(resourceDomain);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+std::optional<Seconds> NetworkStorageSession::maxAgeCacheCap(const ResourceRequest& request)
+{
+    if (m_cacheMaxAgeCapForPrevalentResources && shouldBlockCookies(request, std::nullopt, std::nullopt))
+        return m_cacheMaxAgeCapForPrevalentResources;
+    return std::nullopt;
+}
+
</ins><span class="cx"> void NetworkStorageSession::setPrevalentDomainsToBlockCookiesFor(const Vector<String>& domains, bool clearFirst)
</span><span class="cx"> {
</span><span class="cx">     if (clearFirst) {
</span><span class="lines">@@ -370,6 +377,15 @@
</span><span class="cx">     m_framesGrantedStorageAccess.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkStorageSession::setCacheMaxAgeCapForPrevalentResources(Seconds seconds)
+{
+    m_cacheMaxAgeCapForPrevalentResources = seconds;
+}
+    
+void NetworkStorageSession::resetCacheMaxAgeCapForPrevalentResources()
+{
+    m_cacheMaxAgeCapForPrevalentResources = std::nullopt;
+}
</ins><span class="cx"> #endif // HAVE(CFNETWORK_STORAGE_PARTITIONING)
</span><span class="cx"> 
</span><span class="cx"> #if !PLATFORM(COCOA)
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/ChangeLog       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1,3 +1,72 @@
</span><ins>+2018-09-19  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Add optional cap on partitioned cache max age
+        https://bugs.webkit.org/show_bug.cgi?id=189711
+        <rdar://problem/39246837>
+
+        Reviewed by Antti Koivisto and Chris Dumez.
+
+        These changes add the capability to set a max age cap for prevalent resources
+        and consults it when retrieving cache entries. If an entry is capped and found
+        to be too old, it will not be used but instead removed from the cache.
+
+        This functionality is off by default because no cap is set by default.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::setCacheMaxAgeCapForPrevalentResources):
+        (WebKit::NetworkProcess::resetCacheMaxAgeCapForPrevalentResources):
+            Infrastructure for testing.
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::retrieveCacheEntry):
+            Now sends in the session ID in the retrieve call.
+        * NetworkProcess/cache/NetworkCache.cpp:
+        (WebKit::NetworkCache::hasReachedPrevalentResourceAgeCap):
+            Static convenience function.
+        (WebKit::NetworkCache::makeUseDecision):
+            Now receives an optional maxAge parameter and checks
+            hasReachedPrevalentResourceAgeCap() first.
+        (WebKit::NetworkCache::Cache::retrieve):
+            Now takes a session ID.
+        * NetworkProcess/cache/NetworkCache.h:
+        * NetworkProcess/cache/NetworkCacheStatistics.cpp:
+        (WebKit::NetworkCache::cachedEntryReuseFailureToDiagnosticKey):
+            Added UseDecision::NoDueToPrevalentResourceAgeCap which causes a
+            return of WebCore::DiagnosticLoggingKeys::otherKey().
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap):
+        (WKWebsiteDataStoreStatisticsResetToConsistentState):
+            Infrastructure for testing.
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm:
+        (WebKit::ResourceLoadStatisticsMemoryStore::registerUserDefaultsIfNeeded):
+            Now supports a user default ResourceLoadStatisticsCacheMaxAgeCap.
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::hasStorageAccessForFrame):
+        (WebKit::NetworkProcessProxy::grantStorageAccess):
+        (WebKit::NetworkProcessProxy::removeAllStorageAccess):
+        (WebKit::NetworkProcessProxy::getAllStorageAccessEntries):
+        (WebKit::NetworkProcessProxy::setCacheMaxAgeCapForPrevalentResources):
+        (WebKit::NetworkProcessProxy::didSetCacheMaxAgeCapForPrevalentResources):
+        (WebKit::NetworkProcessProxy::resetCacheMaxAgeCapForPrevalentResources):
+        (WebKit::NetworkProcessProxy::didResetCacheMaxAgeCapForPrevalentResources):
+        (WebKit::nextRequestStorageAccessContextId): Deleted.
+            Deleted this to make all code use the generic generateCallbackID().
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+            Used to transfer the setting from the UI process to the network process. 
+        * UIProcess/ResourceLoadStatisticsMemoryStore.cpp:
+        (WebKit::ResourceLoadStatisticsMemoryStore::setCacheMaxAgeCap):
+        * UIProcess/ResourceLoadStatisticsMemoryStore.h:
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::setCacheMaxAgeCap):
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources):
+        (WebKit::WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+
</ins><span class="cx"> 2018-09-18  Brent Fulgham  <bfulgham@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [iOS] Allow WebContent process to check the "Protocol Characteristics" of files to which it has access
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcessNetworkProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -473,6 +473,24 @@
</span><span class="cx">     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
</span><span class="cx">         networkStorageSession->removePrevalentDomains(domains);
</span><span class="cx"> }
</span><ins>+
+void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, uint64_t contextId)
+{
+    if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
+        networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
+    else
+        ASSERT_NOT_REACHED();
+    parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSetCacheMaxAgeCapForPrevalentResources(contextId), 0);
+}
+
+void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, uint64_t contextId)
+{
+    if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
+        networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
+    else
+        ASSERT_NOT_REACHED();
+    parentProcessConnection()->send(Messages::NetworkProcessProxy::DidResetCacheMaxAgeCapForPrevalentResources(contextId), 0);
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcessNetworkProcessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -146,6 +146,8 @@
</span><span class="cx">     void grantStorageAccess(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId);
</span><span class="cx">     void removeAllStorageAccess(PAL::SessionID, uint64_t contextId);
</span><span class="cx">     void removePrevalentDomains(PAL::SessionID, const Vector<String>& domains);
</span><ins>+    void setCacheMaxAgeCapForPrevalentResources(PAL::SessionID, Seconds, uint64_t contextId);
+    void resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID, uint64_t contextId);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     Seconds loadThrottleLatency() const { return m_loadThrottleLatency; }
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcessNetworkProcessmessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -87,7 +87,9 @@
</span><span class="cx">     GetAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
</span><span class="cx">     GrantStorageAccess(PAL::SessionID sessionID, String resourceDomain, String firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
</span><span class="cx">     RemoveAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
</span><del>-    RemovePrevalentDomains(PAL::SessionID sessionID, Vector<String> domainsWithInteraction);
</del><ins>+    RemovePrevalentDomains(PAL::SessionID sessionID, Vector<String> domainsWithInteraction)
+    SetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, uint64_t contextId)
+    ResetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, uint64_t contextId)
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     SetSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled);
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcessNetworkResourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp     2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp        2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -214,7 +214,7 @@
</span><span class="cx">     ASSERT(canUseCache(request));
</span><span class="cx"> 
</span><span class="cx">     RefPtr<NetworkResourceLoader> loader(this);
</span><del>-    m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry, auto info) mutable {
</del><ins>+    m_cache->retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, sessionID(), [this, loader = WTFMove(loader), request = ResourceRequest { request }](auto entry, auto info) mutable {
</ins><span class="cx">         if (loader->hasOneRef()) {
</span><span class="cx">             // The loader has been aborted and is only held alive by this lambda.
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp        2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.cpp   2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -152,6 +152,11 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool hasReachedPrevalentResourceAgeCap(const WebCore::ResourceResponse& response, WallTime timestamp, const Seconds maxAge)
+{
+    return WebCore::computeCurrentAge(response, timestamp) > maxAge;
+}
+
</ins><span class="cx"> static bool responseHasExpired(const WebCore::ResourceResponse& response, WallTime timestamp, std::optional<Seconds> maxStale)
</span><span class="cx"> {
</span><span class="cx">     if (response.cacheControlContainsNoCache())
</span><span class="lines">@@ -183,8 +188,11 @@
</span><span class="cx">     return responseHasExpired(response, timestamp, requestDirectives.maxStale);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static UseDecision makeUseDecision(const Entry& entry, const WebCore::ResourceRequest& request)
</del><ins>+static UseDecision makeUseDecision(const Entry& entry, const WebCore::ResourceRequest& request, std::optional<Seconds> maxAge)
</ins><span class="cx"> {
</span><ins>+    if (maxAge && hasReachedPrevalentResourceAgeCap(entry.response(), entry.timeStamp(), maxAge.value()))
+        return UseDecision::NoDueToPrevalentResourceAgeCap;
+    
</ins><span class="cx">     // The request is conditional so we force revalidation from the network. We merely check the disk cache
</span><span class="cx">     // so we can update the cache entry.
</span><span class="cx">     if (request.isConditional() && !entry.redirectRequest())
</span><span class="lines">@@ -271,7 +279,7 @@
</span><span class="cx">     return StoreDecision::Yes;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, RetrieveCompletionHandler&& completionHandler)
</del><ins>+void Cache::retrieve(const WebCore::ResourceRequest& request, const GlobalFrameID& frameID, PAL::SessionID sessionID, RetrieveCompletionHandler&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(request.url().protocolIsInHTTPFamily());
</span><span class="cx"> 
</span><span class="lines">@@ -315,7 +323,7 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), info = WTFMove(info), storageKey, frameID](auto record, auto timings) mutable {
</del><ins>+    m_storage->retrieve(storageKey, priority, [this, protectedThis = makeRef(*this), request, completionHandler = WTFMove(completionHandler), info = WTFMove(info), storageKey, frameID, sessionID](auto record, auto timings) mutable {
</ins><span class="cx">         info.storageTimings = timings;
</span><span class="cx"> 
</span><span class="cx">         if (!record) {
</span><span class="lines">@@ -332,7 +340,12 @@
</span><span class="cx"> 
</span><span class="cx">         auto entry = Entry::decodeStorageRecord(*record);
</span><span class="cx"> 
</span><del>-        auto useDecision = entry ? makeUseDecision(*entry, request) : UseDecision::NoDueToDecodeFailure;
</del><ins>+        std::optional<Seconds> maxAgeCap;
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+        if (auto networkStorageSession = WebCore::NetworkStorageSession::storageSession(sessionID))
+            maxAgeCap = networkStorageSession->maxAgeCacheCap(request);
+#endif
+        auto useDecision = entry ? makeUseDecision(*entry, request, maxAgeCap) : UseDecision::NoDueToDecodeFailure;
</ins><span class="cx">         switch (useDecision) {
</span><span class="cx">         case UseDecision::Use:
</span><span class="cx">             break;
</span><span class="lines">@@ -339,6 +352,10 @@
</span><span class="cx">         case UseDecision::Validate:
</span><span class="cx">             entry->setNeedsValidation(true);
</span><span class="cx">             break;
</span><ins>+        case UseDecision::NoDueToPrevalentResourceAgeCap:
+            entry = nullptr;
+            m_storage->remove(storageKey);
+            break;
</ins><span class="cx">         default:
</span><span class="cx">             entry = nullptr;
</span><span class="cx">         };
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcesscacheNetworkCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.h  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/cache/NetworkCache.h     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     NoDueToMissingValidatorFields,
</span><span class="cx">     NoDueToDecodeFailure,
</span><span class="cx">     NoDueToExpiredRedirect,
</span><ins>+    NoDueToPrevalentResourceAgeCap
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> using GlobalFrameID = std::pair<uint64_t /*webPageID*/, uint64_t /*webFrameID*/>;
</span><span class="lines">@@ -112,7 +113,7 @@
</span><span class="cx">         WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">     };
</span><span class="cx">     using RetrieveCompletionHandler = Function<void (std::unique_ptr<Entry>, const RetrieveInfo&)>;
</span><del>-    void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, RetrieveCompletionHandler&&);
</del><ins>+    void retrieve(const WebCore::ResourceRequest&, const GlobalFrameID&, PAL::SessionID, RetrieveCompletionHandler&&);
</ins><span class="cx">     std::unique_ptr<Entry> store(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, RefPtr<WebCore::SharedBuffer>&&, Function<void (MappedBody&)>&&);
</span><span class="cx">     std::unique_ptr<Entry> storeRedirect(const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, const WebCore::ResourceRequest& redirectRequest);
</span><span class="cx">     std::unique_ptr<Entry> update(const WebCore::ResourceRequest&, const GlobalFrameID&, const Entry&, const WebCore::ResourceResponse& validatingResponse);
</span></span></pre></div>
<a id="trunkSourceWebKitNetworkProcesscacheNetworkCacheStatisticscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStatistics.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStatistics.cpp      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStatistics.cpp 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -282,6 +282,7 @@
</span><span class="cx">         return WebCore::DiagnosticLoggingKeys::missingValidatorFieldsKey();
</span><span class="cx">     case UseDecision::NoDueToDecodeFailure:
</span><span class="cx">     case UseDecision::NoDueToExpiredRedirect:
</span><ins>+    case UseDecision::NoDueToPrevalentResourceAgeCap:
</ins><span class="cx">         return WebCore::DiagnosticLoggingKeys::otherKey();
</span><span class="cx">     case UseDecision::Use:
</span><span class="cx">     case UseDecision::Validate:
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICWKWebsiteDataStoreRefcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -462,6 +462,13 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction callback)
+{
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().setCacheMaxAgeCapForPrevalentResources(Seconds { seconds }, [context, callback] {
+        callback(context);
+    });
+}
+
</ins><span class="cx"> void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsResetToConsistentStateFunction completionHandler)
</span><span class="cx"> {
</span><span class="cx">     auto callbackAggregator = CallbackAggregator::create([context, completionHandler]() {
</span><span class="lines">@@ -470,6 +477,7 @@
</span><span class="cx"> 
</span><span class="cx">     auto& store = WebKit::toImpl(dataStoreRef)->websiteDataStore();
</span><span class="cx">     store.clearResourceLoadStatisticsInWebProcesses([callbackAggregator = callbackAggregator.copyRef()] { });
</span><ins>+    store.resetCacheMaxAgeCapForPrevalentResources([callbackAggregator = callbackAggregator.copyRef()] { });
</ins><span class="cx"> 
</span><span class="cx">     auto* statisticsStore = store.resourceLoadStatistics();
</span><span class="cx">     if (!statisticsStore)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICWKWebsiteDataStoreRefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -91,6 +91,8 @@
</span><span class="cx"> WK_EXPORT void WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHours(WKWebsiteDataStoreRef dataStoreRef, unsigned hours, void* context, WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifiedSinceHoursFunction callback);
</span><span class="cx"> typedef void (*WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction)(void* functionContext);
</span><span class="cx"> WK_EXPORT void WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction callback);
</span><ins>+typedef void (*WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction)(void* functionContext);
+WK_EXPORT void WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(WKWebsiteDataStoreRef dataStoreRef, double seconds, void* context, WKWebsiteDataStoreSetStatisticsCacheMaxAgeCapFunction);
</ins><span class="cx"> typedef void (*WKWebsiteDataStoreStatisticsResetToConsistentStateFunction)(void* functionContext);
</span><span class="cx"> WK_EXPORT void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsResetToConsistentStateFunction completionHandler);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessCocoaResourceLoadStatisticsMemoryStoreCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/Cocoa/ResourceLoadStatisticsMemoryStoreCocoa.mm       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -52,6 +52,10 @@
</span><span class="cx">         if (debugManualPrevalentResource)
</span><span class="cx">             setPrevalentResourceForDebugMode(debugManualPrevalentResource);
</span><span class="cx">         setStorageAccessPromptsEnabled([[NSUserDefaults standardUserDefaults] boolForKey:@"ExperimentalStorageAccessPromptsEnabled"]);
</span><ins>+
+        Seconds cacheMaxAgeCapForPrevalentResources([[NSUserDefaults standardUserDefaults] doubleForKey:@"ResourceLoadStatisticsCacheMaxAgeCap"]);
+        if (cacheMaxAgeCapForPrevalentResources > 0_s && cacheMaxAgeCapForPrevalentResources <= 24_h * 365)
+            setCacheMaxAgeCap(cacheMaxAgeCapForPrevalentResources);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessNetworkNetworkProcessProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -404,15 +404,9 @@
</span><span class="cx">     m_updateBlockCookiesCallbackMap.take(callbackId)();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static uint64_t nextRequestStorageAccessContextId()
-{
-    static uint64_t nextContextId = 0;
-    return ++nextContextId;
-}
-
</del><span class="cx"> void NetworkProcessProxy::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool)>&& callback)
</span><span class="cx"> {
</span><del>-    auto contextId = nextRequestStorageAccessContextId();
</del><ins>+    auto contextId = generateCallbackID();
</ins><span class="cx">     auto addResult = m_storageAccessResponseCallbackMap.add(contextId, WTFMove(callback));
</span><span class="cx">     ASSERT_UNUSED(addResult, addResult.isNewEntry);
</span><span class="cx">     send(Messages::NetworkProcess::HasStorageAccessForFrame(sessionID, resourceDomain, firstPartyDomain, frameID, pageID, contextId), 0);
</span><span class="lines">@@ -420,7 +414,7 @@
</span><span class="cx"> 
</span><span class="cx"> void NetworkProcessProxy::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, WTF::CompletionHandler<void(bool)>&& callback)
</span><span class="cx"> {
</span><del>-    auto contextId = nextRequestStorageAccessContextId();
</del><ins>+    auto contextId = generateCallbackID();
</ins><span class="cx">     auto addResult = m_storageAccessResponseCallbackMap.add(contextId, WTFMove(callback));
</span><span class="cx">     ASSERT_UNUSED(addResult, addResult.isNewEntry);
</span><span class="cx">     send(Messages::NetworkProcess::GrantStorageAccess(sessionID, resourceDomain, firstPartyDomain, frameID, pageID, contextId), 0);
</span><span class="lines">@@ -439,7 +433,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto contextId = nextRequestStorageAccessContextId();
</del><ins>+    auto contextId = generateCallbackID();
</ins><span class="cx">     auto addResult = m_removeAllStorageAccessCallbackMap.add(contextId, WTFMove(completionHandler));
</span><span class="cx">     ASSERT_UNUSED(addResult, addResult.isNewEntry);
</span><span class="cx">     send(Messages::NetworkProcess::RemoveAllStorageAccess(sessionID, contextId), 0);
</span><span class="lines">@@ -453,7 +447,7 @@
</span><span class="cx"> 
</span><span class="cx"> void NetworkProcessProxy::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String>&& domains)>&& callback)
</span><span class="cx"> {
</span><del>-    auto contextId = nextRequestStorageAccessContextId();
</del><ins>+    auto contextId = generateCallbackID();
</ins><span class="cx">     auto addResult = m_allStorageAccessEntriesCallbackMap.add(contextId, WTFMove(callback));
</span><span class="cx">     ASSERT_UNUSED(addResult, addResult.isNewEntry);
</span><span class="cx">     send(Messages::NetworkProcess::GetAllStorageAccessEntries(sessionID, contextId), 0);
</span><span class="lines">@@ -464,6 +458,44 @@
</span><span class="cx">     auto callback = m_allStorageAccessEntriesCallbackMap.take(contextId);
</span><span class="cx">     callback(WTFMove(domains));
</span><span class="cx"> }
</span><ins>+
+void NetworkProcessProxy::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
+{
+    if (!canSendMessage()) {
+        completionHandler();
+        return;
+    }
+    
+    auto contextId = generateCallbackID();
+    auto addResult = m_updateRuntimeSettingsCallbackMap.add(contextId, WTFMove(completionHandler));
+    ASSERT_UNUSED(addResult, addResult.isNewEntry);
+    send(Messages::NetworkProcess::SetCacheMaxAgeCapForPrevalentResources(sessionID, seconds, contextId), 0);
+}
+
+void NetworkProcessProxy::didSetCacheMaxAgeCapForPrevalentResources(uint64_t contextId)
+{
+    auto completionHandler = m_updateRuntimeSettingsCallbackMap.take(contextId);
+    completionHandler();
+}
+
+void NetworkProcessProxy::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
+{
+    if (!canSendMessage()) {
+        completionHandler();
+        return;
+    }
+    
+    auto contextId = generateCallbackID();
+    auto addResult = m_updateRuntimeSettingsCallbackMap.add(contextId, WTFMove(completionHandler));
+    ASSERT_UNUSED(addResult, addResult.isNewEntry);
+    send(Messages::NetworkProcess::ResetCacheMaxAgeCapForPrevalentResources(sessionID, contextId), 0);
+}
+
+void NetworkProcessProxy::didResetCacheMaxAgeCapForPrevalentResources(uint64_t contextId)
+{
+    auto completionHandler = m_updateRuntimeSettingsCallbackMap.take(contextId);
+    completionHandler();
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> void NetworkProcessProxy::sendProcessWillSuspendImminently()
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessNetworkNetworkProcessProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -83,6 +83,8 @@
</span><span class="cx">     void getAllStorageAccessEntries(PAL::SessionID, CompletionHandler<void(Vector<String>&& domains)>&&);
</span><span class="cx">     void grantStorageAccess(PAL::SessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, CompletionHandler<void(bool)>&& callback);
</span><span class="cx">     void removeAllStorageAccess(PAL::SessionID, CompletionHandler<void()>&&);
</span><ins>+    void setCacheMaxAgeCapForPrevalentResources(PAL::SessionID, Seconds, CompletionHandler<void()>&&);
+    void resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID, CompletionHandler<void()>&&);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void writeBlobToFilePath(const WebCore::URL&, const String& path, CompletionHandler<void(bool)>&& callback);
</span><span class="lines">@@ -147,6 +149,8 @@
</span><span class="cx">     void storageAccessRequestResult(bool wasGranted, uint64_t contextId);
</span><span class="cx">     void allStorageAccessEntriesResult(Vector<String>&& domains, uint64_t contextId);
</span><span class="cx">     void didRemoveAllStorageAccess(uint64_t contextId);
</span><ins>+    void didSetCacheMaxAgeCapForPrevalentResources(uint64_t contextId);
+    void didResetCacheMaxAgeCapForPrevalentResources(uint64_t contextId);
</ins><span class="cx"> #endif
</span><span class="cx">     void retrieveCacheStorageParameters(PAL::SessionID);
</span><span class="cx"> 
</span><span class="lines">@@ -186,6 +190,8 @@
</span><span class="cx">     HashMap<uint64_t, CompletionHandler<void()>> m_removeAllStorageAccessCallbackMap;
</span><span class="cx">     HashMap<uint64_t, CompletionHandler<void(Vector<String>&& domains)>> m_allStorageAccessEntriesCallbackMap;
</span><span class="cx"> 
</span><ins>+    HashMap<uint64_t, CompletionHandler<void()>> m_updateRuntimeSettingsCallbackMap;
+
</ins><span class="cx"> #if ENABLE(CONTENT_EXTENSIONS)
</span><span class="cx">     HashSet<WebUserContentControllerProxy*> m_webUserContentControllerProxies;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessNetworkNetworkProcessProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -46,6 +46,8 @@
</span><span class="cx">     StorageAccessRequestResult(bool wasGranted, uint64_t contextId)
</span><span class="cx">     AllStorageAccessEntriesResult(Vector<String> domains, uint64_t contextId)
</span><span class="cx">     DidRemoveAllStorageAccess(uint64_t contextId)
</span><ins>+    DidSetCacheMaxAgeCapForPrevalentResources(uint64_t contextId)
+    DidResetCacheMaxAgeCapForPrevalentResources(uint64_t contextId)
</ins><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(CONTENT_EXTENSIONS)
</span><span class="cx">     ContentExtensionRules(WebKit::UserContentControllerIdentifier identifier)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessResourceLoadStatisticsMemoryStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.cpp 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -832,6 +832,16 @@
</span><span class="cx">     m_parameters.grandfatheringTime = seconds;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ResourceLoadStatisticsMemoryStore::setCacheMaxAgeCap(Seconds seconds)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(seconds >= 0_s);
+
+    RunLoop::main().dispatch([store = makeRef(m_store), seconds] () {
+        store->setCacheMaxAgeCap(seconds, [] { });
+    });
+}
+
</ins><span class="cx"> bool ResourceLoadStatisticsMemoryStore::shouldRemoveDataRecords() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!RunLoop::isMain());
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessResourceLoadStatisticsMemoryStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h        2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/ResourceLoadStatisticsMemoryStore.h   2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -113,6 +113,7 @@
</span><span class="cx">     void setTimeToLiveUserInteraction(Seconds);
</span><span class="cx">     void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
</span><span class="cx">     void setGrandfatheringTime(Seconds);
</span><ins>+    void setCacheMaxAgeCap(Seconds);
</ins><span class="cx">     void setResourceLoadStatisticsDebugMode(bool);
</span><span class="cx">     bool isDebugModeEnabled() const { return m_debugModeEnabled; };
</span><span class="cx">     void setPrevalentResourceForDebugMode(const String& domain);
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebResourceLoadStatisticsStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp 2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp    2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -833,6 +833,20 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebResourceLoadStatisticsStore::setCacheMaxAgeCap(Seconds seconds, CompletionHandler<void()>&& completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+    ASSERT(seconds >= 0_s);
+    
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    if (m_websiteDataStore) {
+        m_websiteDataStore->setCacheMaxAgeCapForPrevalentResources(seconds, WTFMove(completionHandler));
+        return;
+    }
+#endif
+    completionHandler();
+}
+
</ins><span class="cx"> void WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler(const Vector<String>& domainsToBlock, ShouldClearFirst shouldClearFirst, CompletionHandler<void()>&& completionHandler)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(RunLoop::isMain());
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebResourceLoadStatisticsStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h   2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h      2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -125,6 +125,7 @@
</span><span class="cx">     void setTimeToLiveUserInteraction(Seconds);
</span><span class="cx">     void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
</span><span class="cx">     void setGrandfatheringTime(Seconds);
</span><ins>+    void setCacheMaxAgeCap(Seconds, CompletionHandler<void()>&&);
</ins><span class="cx">     void setMaxStatisticsEntries(size_t);
</span><span class="cx">     void setPruneEntriesDownTo(size_t);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebsiteDataWebsiteDataStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp   2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp      2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1342,6 +1342,35 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
+{
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    
+    for (auto& processPool : processPools()) {
+        if (auto* networkProcess = processPool->networkProcess())
+            networkProcess->setCacheMaxAgeCapForPrevalentResources(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
+    }
+#else
+    UNUSED_PARAM(seconds);
+    completionHandler();
+#endif
+}
+
+void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&& completionHandler)
+{
+#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    
+    for (auto& processPool : processPools()) {
+        if (auto* networkProcess = processPool->networkProcess())
+            networkProcess->resetCacheMaxAgeCapForPrevalentResources(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
+    }
+#else
+    completionHandler();
+#endif
+}
+
</ins><span class="cx"> void WebsiteDataStore::networkProcessDidCrash()
</span><span class="cx"> {
</span><span class="cx"> #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebsiteDataWebsiteDataStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h     2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h        2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -143,6 +143,8 @@
</span><span class="cx">     void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool promptEnabled, CompletionHandler<void(StorageAccessStatus)>&&);
</span><span class="cx">     void grantStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool userWasPrompted, CompletionHandler<void(bool)>&&);
</span><span class="cx"> #endif
</span><ins>+    void setCacheMaxAgeCapForPrevalentResources(Seconds, CompletionHandler<void()>&&);
+    void resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&&);
</ins><span class="cx">     void networkProcessDidCrash();
</span><span class="cx">     void resolveDirectoriesIfNecessary();
</span><span class="cx">     const String& resolvedApplicationCacheDirectory() const { return m_resolvedConfiguration.applicationCacheDirectory; }
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/ChangeLog       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2018-09-19  John Wilander  <wilander@apple.com>
+
+        Resource Load Statistics: Add optional cap on partitioned cache max age
+        https://bugs.webkit.org/show_bug.cgi?id=189711
+        <rdar://problem/39246837>
+
+        Reviewed by Antti Koivisto and Chris Dumez.
+
+        This change adds infrastructure for layout tests of capped cache max age.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::setStatisticsCacheMaxAgeCap):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::setStatisticsCacheMaxAgeCap):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
</ins><span class="cx"> 2018-09-19  Dawei Fenton  <realdawei@apple.com>
</span><span class="cx"> 
</span><span class="cx">        Unreviewed. Update my email and alias in list of contributors.
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleBindingsTestRunneridl"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl      2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -307,6 +307,7 @@
</span><span class="cx">     void statisticsClearInMemoryAndPersistentStore(object callback);
</span><span class="cx">     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned long hours, object callback);
</span><span class="cx">     void statisticsClearThroughWebsiteDataRemoval(object callback);
</span><ins>+    void setStatisticsCacheMaxAgeCap(double seconds);
</ins><span class="cx">     void statisticsResetToConsistentState(object completionHandler);
</span><span class="cx"> 
</span><span class="cx">     // Injected bundle form client.
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleTestRunnercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp       2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp  2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1945,6 +1945,13 @@
</span><span class="cx">     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void TestRunner::setStatisticsCacheMaxAgeCap(double seconds)
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsCacheMaxAgeCap"));
+    WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds));
+    WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
+}
+
</ins><span class="cx"> void TestRunner::statisticsCallClearThroughWebsiteDataRemovalCallback()
</span><span class="cx"> {
</span><span class="cx">     callTestRunnerCallback(StatisticsDidClearThroughWebsiteDataRemovalCallbackID);
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleTestRunnerh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h    2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -421,6 +421,7 @@
</span><span class="cx">     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned hours, JSValueRef callback);
</span><span class="cx">     void statisticsClearThroughWebsiteDataRemoval(JSValueRef callback);
</span><span class="cx">     void statisticsCallClearThroughWebsiteDataRemovalCallback();
</span><ins>+    void setStatisticsCacheMaxAgeCap(double seconds);
</ins><span class="cx">     void statisticsResetToConsistentState(JSValueRef completionHandler);
</span><span class="cx">     void statisticsCallDidResetToConsistentStateCallback();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerTestControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/TestController.cpp  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -3122,6 +3122,14 @@
</span><span class="cx">     m_currentInvocation->didClearStatisticsThroughWebsiteDataRemoval();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void TestController::setStatisticsCacheMaxAgeCap(double seconds)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    ResourceStatisticsCallbackContext context(*this);
+    WKWebsiteDataStoreSetStatisticsCacheMaxAgeCap(dataStore, seconds, &context, resourceStatisticsVoidResultCallback);
+    runUntil(context.done, noTimeout);
+}
+
</ins><span class="cx"> void TestController::statisticsResetToConsistentState()
</span><span class="cx"> {
</span><span class="cx">     auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerTestControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/TestController.h (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/TestController.h    2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/TestController.h       2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -221,6 +221,7 @@
</span><span class="cx">     void statisticsClearInMemoryAndPersistentStore();
</span><span class="cx">     void statisticsClearInMemoryAndPersistentStoreModifiedSinceHours(unsigned);
</span><span class="cx">     void statisticsClearThroughWebsiteDataRemoval();
</span><ins>+    void setStatisticsCacheMaxAgeCap(double seconds);
</ins><span class="cx">     void statisticsResetToConsistentState();
</span><span class="cx"> 
</span><span class="cx">     void getAllStorageAccessEntries();
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerTestInvocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (236215 => 236216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp  2018-09-19 19:13:36 UTC (rev 236215)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp     2018-09-19 19:19:56 UTC (rev 236216)
</span><span class="lines">@@ -1358,6 +1358,13 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (WKStringIsEqualToUTF8CString(messageName, "SetStatisticsCacheMaxAgeCap")) {
+        ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
+        WKDoubleRef seconds = static_cast<WKDoubleRef>(messageBody);
+        TestController::singleton().setStatisticsCacheMaxAgeCap(WKDoubleGetValue(seconds));
+        return nullptr;
+    }
+
</ins><span class="cx">     if (WKStringIsEqualToUTF8CString(messageName, "StatisticsResetToConsistentState")) {
</span><span class="cx">         if (m_shouldDumpResourceLoadStatistics)
</span><span class="cx">             m_savedResourceLoadStatistics = TestController::singleton().dumpResourceLoadStatistics();
</span></span></pre>
</div>
</div>

</body>
</html>