Title: [211288] trunk
Revision
211288
Author
an...@apple.com
Date
2017-01-27 10:44:18 -0800 (Fri, 27 Jan 2017)

Log Message

Implement Cache-control: immutable
https://bugs.webkit.org/show_bug.cgi?id=167497

Reviewed by Chris Dumez.

Source/WebCore:

Cache-control value 'immutable' indicates that a subresource does not change and so does not need to be
revalidated on a normal reload. This can significantly speed up reloads and reduce network traffic.

It is has been implemented in Firefox and is already used by Facebook.

https://tools.ietf.org/html/draft-mcmanus-immutable-00
https://hacks.mozilla.org/2017/01/using-immutable-caching-to-speed-up-the-web/

This patch implements Cache-control: immutable for memory cache only. A disk cache implementation
doesn't seem necessary as the resource is basically always expected to be in memory cache on reload.

Immutable is only supported for https as suggested by the draft specification (and Gecko implementation).

Test: http/tests/cache/cache-control-immutable-http.html
      http/tests/cache/cache-control-immutable-https.html

* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::makeRevalidationDecision):

    On normal reloads (CachePolicyRevalidate) of https resources check for 'Cache-control: immutable'.
    If the resource is not expired don't revalidate it.

* platform/network/CacheValidation.cpp:
(WebCore::parseCacheControlDirectives):
* platform/network/CacheValidation.h:
* platform/network/ResourceResponseBase.cpp:
(WebCore::ResourceResponseBase::cacheControlContainsImmutable):
* platform/network/ResourceResponseBase.h:

LayoutTests:

* http/tests/cache/cache-control-immutable-http-expected.txt: Added.
* http/tests/cache/cache-control-immutable-http.html: Added.
* http/tests/cache/cache-control-immutable-https-expected.txt: Added.
* http/tests/cache/cache-control-immutable-https.html: Added.
* http/tests/cache/resources/cache-control-immutable.js: Added.
* http/tests/cache/resources/iframe-with-script.cgi: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (211287 => 211288)


--- trunk/LayoutTests/ChangeLog	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/LayoutTests/ChangeLog	2017-01-27 18:44:18 UTC (rev 211288)
@@ -1,3 +1,17 @@
+2017-01-27  Antti Koivisto  <an...@apple.com>
+
+        Implement Cache-control: immutable
+        https://bugs.webkit.org/show_bug.cgi?id=167497
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/cache/cache-control-immutable-http-expected.txt: Added.
+        * http/tests/cache/cache-control-immutable-http.html: Added.
+        * http/tests/cache/cache-control-immutable-https-expected.txt: Added.
+        * http/tests/cache/cache-control-immutable-https.html: Added.
+        * http/tests/cache/resources/cache-control-immutable.js: Added.
+        * http/tests/cache/resources/iframe-with-script.cgi: Added.
+
 2017-01-26  Ryan Haddad  <ryanhad...@apple.com>
 
         Marking media/modern-media-controls/layout-node/addChild.html as flaky.

Added: trunk/LayoutTests/http/tests/cache/cache-control-immutable-http-expected.txt (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/cache-control-immutable-http-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/cache-control-immutable-http-expected.txt	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,3 @@
+HTTP: Test if non-expired subresource with Cache-control: immutable is revalidated: YES (expected YES)
+HTTP: Test if expired subresource with Cache-control: immutable is revalidated: YES (expected YES)
+

Added: trunk/LayoutTests/http/tests/cache/cache-control-immutable-http.html (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/cache-control-immutable-http.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/cache-control-immutable-http.html	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,19 @@
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+</script>
+<script src=""
+<body>
+<div id=logdiv><div>
+<script>
+test(1000, (revalidated) => {
+    log("HTTP: Test if non-expired subresource with Cache-control: immutable is revalidated", true, revalidated);
+    test(0, (revalidated) => {
+        log("HTTP: Test if expired subresource with Cache-control: immutable is revalidated", true, revalidated);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+});
+</script>

Added: trunk/LayoutTests/http/tests/cache/cache-control-immutable-https-expected.txt (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/cache-control-immutable-https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/cache-control-immutable-https-expected.txt	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,3 @@
+HTTPS: Test if non-expired subresource with Cache-control: immutable is revalidated: NO (expected NO)
+HTTPS: Test if expired subresource with Cache-control: immutable is revalidated: YES (expected YES)
+

Added: trunk/LayoutTests/http/tests/cache/cache-control-immutable-https.html (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/cache-control-immutable-https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/cache-control-immutable-https.html	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,21 @@
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+if (window.location.protocol == "http:")
+    window.location = "https://127.0.0.1:8443/cache/cache-control-immutable-https.html";
+</script>
+<script src=""
+<body>
+<div id=logdiv><div>
+<script>
+test(1000, (revalidated) => {
+    log("HTTPS: Test if non-expired subresource with Cache-control: immutable is revalidated", false, revalidated);
+    test(0, (revalidated) => {
+        log("HTTPS: Test if expired subresource with Cache-control: immutable is revalidated", true, revalidated);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+});
+</script>

Added: trunk/LayoutTests/http/tests/cache/resources/cache-control-immutable.js (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/resources/cache-control-immutable.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/cache-control-immutable.js	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,19 @@
+function log(text, expected, result)
+{
+    logdiv.innerText += text + ": " + (result ? "YES" : "NO") + " (expected " + (expected ? "YES" : "NO") + ")\n";
+}
+
+function insertIframe(maxAge, loaded) {
+    const iframe = document.createElement('iframe');
+    document.body.appendChild(iframe);
+    iframe.src = "" + maxAge;
+    iframe._onload_ = () => loaded(iframe);
+}
+
+function test(maxAge, callback) {
+    insertIframe(maxAge, (iframe) => {
+        const firstNumber = iframe.contentWindow.randomNumber;
+        iframe._onload_ = () => callback(firstNumber != iframe.contentWindow.randomNumber);
+        iframe.contentWindow.location.reload();
+    });
+}

Added: trunk/LayoutTests/http/tests/cache/resources/iframe-with-script.cgi (0 => 211288)


--- trunk/LayoutTests/http/tests/cache/resources/iframe-with-script.cgi	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/iframe-with-script.cgi	2017-01-27 18:44:18 UTC (rev 211288)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+use CGI;
+
+print "Content-type: text/html\n";
+print "Cache-control: no-cache\n";
+print "\n";
+
+my $query = new CGI;
+my $scriptCacheControl = $query->param("script-cache-control");
+
+print "<script src=''></script>\n";
Property changes on: trunk/LayoutTests/http/tests/cache/resources/iframe-with-script.cgi
___________________________________________________________________

Added: svn:executable

+* \ No newline at end of property

Modified: trunk/Source/WebCore/ChangeLog (211287 => 211288)


--- trunk/Source/WebCore/ChangeLog	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/ChangeLog	2017-01-27 18:44:18 UTC (rev 211288)
@@ -1,3 +1,39 @@
+2017-01-27  Antti Koivisto  <an...@apple.com>
+
+        Implement Cache-control: immutable
+        https://bugs.webkit.org/show_bug.cgi?id=167497
+
+        Reviewed by Chris Dumez.
+
+        Cache-control value 'immutable' indicates that a subresource does not change and so does not need to be
+        revalidated on a normal reload. This can significantly speed up reloads and reduce network traffic.
+
+        It is has been implemented in Firefox and is already used by Facebook.
+
+        https://tools.ietf.org/html/draft-mcmanus-immutable-00
+        https://hacks.mozilla.org/2017/01/using-immutable-caching-to-speed-up-the-web/
+
+        This patch implements Cache-control: immutable for memory cache only. A disk cache implementation
+        doesn't seem necessary as the resource is basically always expected to be in memory cache on reload.
+
+        Immutable is only supported for https as suggested by the draft specification (and Gecko implementation).
+
+        Test: http/tests/cache/cache-control-immutable-http.html
+              http/tests/cache/cache-control-immutable-https.html
+
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::makeRevalidationDecision):
+
+            On normal reloads (CachePolicyRevalidate) of https resources check for 'Cache-control: immutable'.
+            If the resource is not expired don't revalidate it.
+
+        * platform/network/CacheValidation.cpp:
+        (WebCore::parseCacheControlDirectives):
+        * platform/network/CacheValidation.h:
+        * platform/network/ResourceResponseBase.cpp:
+        (WebCore::ResourceResponseBase::cacheControlContainsImmutable):
+        * platform/network/ResourceResponseBase.h:
+
 2017-01-27  Youenn Fablet  <youe...@gmail.com>
 
         [WebRTC] Use MediaEndPointPeerConnection if not using libwebrtc

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (211287 => 211288)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-01-27 18:44:18 UTC (rev 211288)
@@ -748,7 +748,14 @@
         return RevalidationDecision::No;
 
     case CachePolicyReload:
+        return RevalidationDecision::YesDueToCachePolicy;
+
     case CachePolicyRevalidate:
+        if (m_response.cacheControlContainsImmutable() && m_response.url().protocolIs("https")) {
+            if (isExpired())
+                return RevalidationDecision::YesDueToExpired;
+            return RevalidationDecision::No;
+        }
         return RevalidationDecision::YesDueToCachePolicy;
 
     case CachePolicyVerify:

Modified: trunk/Source/WebCore/platform/network/CacheValidation.cpp (211287 => 211288)


--- trunk/Source/WebCore/platform/network/CacheValidation.cpp	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/platform/network/CacheValidation.cpp	2017-01-27 18:44:18 UTC (rev 211288)
@@ -316,7 +316,8 @@
                 double maxStale = directives[i].second.toDouble(&ok);
                 if (ok)
                     result.maxStale = duration_cast<microseconds>(duration<double>(maxStale));
-            }
+            } else if (equalLettersIgnoringASCIICase(directives[i].first, "immutable"))
+                result.immutable = true;
         }
     }
 

Modified: trunk/Source/WebCore/platform/network/CacheValidation.h (211287 => 211288)


--- trunk/Source/WebCore/platform/network/CacheValidation.h	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/platform/network/CacheValidation.h	2017-01-27 18:44:18 UTC (rev 211288)
@@ -66,6 +66,7 @@
     bool noCache { false };
     bool noStore { false };
     bool mustRevalidate { false };
+    bool immutable { false };
 };
 WEBCORE_EXPORT CacheControlDirectives parseCacheControlDirectives(const HTTPHeaderMap&);
 

Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp (211287 => 211288)


--- trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp	2017-01-27 18:44:18 UTC (rev 211288)
@@ -425,6 +425,13 @@
         parseCacheControlDirectives();
     return m_cacheControlDirectives.mustRevalidate;
 }
+    
+bool ResourceResponseBase::cacheControlContainsImmutable() const
+{
+    if (!m_haveParsedCacheControlHeader)
+        parseCacheControlDirectives();
+    return m_cacheControlDirectives.immutable;
+}
 
 bool ResourceResponseBase::hasCacheValidatorFields() const
 {

Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.h (211287 => 211288)


--- trunk/Source/WebCore/platform/network/ResourceResponseBase.h	2017-01-27 18:39:16 UTC (rev 211287)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.h	2017-01-27 18:44:18 UTC (rev 211288)
@@ -119,10 +119,10 @@
     const std::optional<CertificateInfo>& certificateInfo() const { return m_certificateInfo; };
     
     // These functions return parsed values of the corresponding response headers.
-    // NaN means that the header was not present or had invalid value.
     WEBCORE_EXPORT bool cacheControlContainsNoCache() const;
     WEBCORE_EXPORT bool cacheControlContainsNoStore() const;
     WEBCORE_EXPORT bool cacheControlContainsMustRevalidate() const;
+    WEBCORE_EXPORT bool cacheControlContainsImmutable() const;
     WEBCORE_EXPORT bool hasCacheValidatorFields() const;
     WEBCORE_EXPORT std::optional<std::chrono::microseconds> cacheControlMaxAge() const;
     WEBCORE_EXPORT std::optional<std::chrono::system_clock::time_point> date() const;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to