Bug 1503696: Cache cookies in the same way we did before Firefox 63. r=mak a=jcristau
authorDave Townsend <dtownsend@oxymoronical.com>
Thu, 15 Nov 2018 20:46:32 +0000
changeset 501306 5021562e6baf153b5ff398b8315f4497b6ed3a64
parent 501305 71f865d66e8eb1743330c7aba42bc27472299c89
child 501307 e68e1025c02887a9e0a419f166ddf02118b1b427
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak, jcristau
bugs1503696, 1453751
milestone64.0
Bug 1503696: Cache cookies in the same way we did before Firefox 63. r=mak a=jcristau Previous to bug 1453751 favicons were loaded from the network by a <xul:image> tag with validate="never". This caused us to always use any cached version if possible. Bug 1453751 used a normal load type causing us to revalidate with the server for each request. This switches the loader to using the cache if possible. Differential Revision: https://phabricator.services.mozilla.com/D11402
browser/base/content/test/favicons/browser.ini
browser/base/content/test/favicons/browser_favicon_cache.js
browser/base/content/test/favicons/cookie_favicon.html
browser/base/content/test/favicons/cookie_favicon.sjs
browser/modules/FaviconLoader.jsm
--- a/browser/base/content/test/favicons/browser.ini
+++ b/browser/base/content/test/favicons/browser.ini
@@ -58,8 +58,12 @@ support-files =
 support-files =
   file_insecure_favicon.html
   file_favicon.png
 [browser_title_flicker.js]
 support-files =
   file_with_slow_favicon.html
   blank.html
   file_favicon.png
+[browser_favicon_cache.js]
+support-files =
+  cookie_favicon.sjs
+  cookie_favicon.html
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/favicons/browser_favicon_cache.js
@@ -0,0 +1,40 @@
+add_task(async () => {
+  const testPath = "http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.html";
+  const resetPath = "http://example.com/browser/browser/base/content/test/favicons/cookie_favicon.sjs?reset";
+
+  let tab = BrowserTestUtils.addTab(gBrowser, testPath);
+  gBrowser.selectedTab = tab;
+  let browser = tab.linkedBrowser;
+
+  let faviconPromise = waitForLinkAvailable(browser);
+  await BrowserTestUtils.browserLoaded(browser);
+  await faviconPromise;
+  let cookies = Services.cookies.getCookiesFromHost("example.com", browser.contentPrincipal.originAttributes);
+  let seenCookie = false;
+  for (let cookie of cookies) {
+    if (cookie.name == "faviconCookie") {
+      seenCookie = true;
+      is(cookie.value, 1, "Should have seen the right initial cookie.");
+    }
+  }
+  ok(seenCookie, "Should have seen the cookie.");
+
+  faviconPromise = waitForLinkAvailable(browser);
+  BrowserTestUtils.loadURI(browser, testPath);
+  await BrowserTestUtils.browserLoaded(browser);
+  await faviconPromise;
+  cookies = Services.cookies.getCookiesFromHost("example.com", browser.contentPrincipal.originAttributes);
+  seenCookie = false;
+  for (let cookie of cookies) {
+    if (cookie.name == "faviconCookie") {
+      seenCookie = true;
+      is(cookie.value, 1, "Should have seen the cached cookie.");
+    }
+  }
+  ok(seenCookie, "Should have seen the cookie.");
+
+  // Reset the cookie so if this test is run again it will still pass.
+  await fetch(resetPath);
+
+  BrowserTestUtils.removeTab(tab);
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/favicons/cookie_favicon.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <title>Favicon Test for caching</title>
+    <link rel="icon" type="image/png" href="cookie_favicon.sjs" />
+  </head>
+  <body>
+    Favicon!!
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/favicons/cookie_favicon.sjs
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  if (request.queryString == "reset") {
+    setState("cache_cookie", "0");
+    response.setStatusLine(request.httpVersion, 200, "Ok");
+    response.write("Reset");
+    return;
+  }
+
+  let state = getState("cache_cookie");
+  if (!state) {
+    state = 0;
+  }
+
+  response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
+  response.setHeader("Set-Cookie", `faviconCookie=${++state}`);
+  response.setHeader("Location", "http://example.com/browser/browser/base/content/test/favicons/moz.png");
+  setState("cache_cookie", `${state}`);
+}
--- a/browser/modules/FaviconLoader.jsm
+++ b/browser/modules/FaviconLoader.jsm
@@ -73,17 +73,19 @@ class FaviconLoad {
       iconInfo.node,
       iconInfo.node.nodePrincipal,
       iconInfo.node.nodePrincipal,
       (Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
        Ci.nsILoadInfo.SEC_ALLOW_CHROME |
        Ci.nsILoadInfo.SEC_DISALLOW_SCRIPT),
       Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE_FAVICON);
 
-    this.channel.loadFlags |= Ci.nsIRequest.LOAD_BACKGROUND;
+    this.channel.loadFlags |= Ci.nsIRequest.LOAD_BACKGROUND |
+                              Ci.nsIRequest.VALIDATE_NEVER |
+                              Ci.nsIRequest.LOAD_FROM_CACHE;
     // Sometimes node is a document and sometimes it is an element. This is
     // the easiest single way to get to the load group in both those cases.
     this.channel.loadGroup = iconInfo.node.ownerGlobal.document.documentLoadGroup;
     this.channel.notificationCallbacks = this;
 
     if (Services.prefs.getBoolPref("network.http.tailing.enabled", true) &&
         this.channel instanceof Ci.nsIClassOfService) {
       this.channel.addClassFlags(Ci.nsIClassOfService.Tail | Ci.nsIClassOfService.Throttleable);