Bug 1238183 - Part 2 - Add a test case for testing the ForgetAboutSite with userContextId. r=jimm
☠☠ backed out by bd4f86754707 ☠ ☠
authorTim Huang <tihuang@mozilla.com>
Mon, 04 Jul 2016 00:36:00 +0200
changeset 303507 1207df32d737779bfd78f6c4f374ca6dbaf2685e
parent 303506 663a083774f4fe879fc4270774205cdde074918a
child 303508 066be6391756b49ee36358a34c8b7ee34ed1f82f
push id79110
push usercbook@mozilla.com
push dateMon, 04 Jul 2016 14:21:35 +0000
treeherdermozilla-inbound@066be6391756 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1238183
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1238183 - Part 2 - Add a test case for testing the ForgetAboutSite with userContextId. r=jimm
browser/components/contextualidentity/test/browser/browser.ini
browser/components/contextualidentity/test/browser/browser_forgetaboutsite.js
browser/components/contextualidentity/test/browser/file_set_storages.html
dom/push/test/xpcshell/xpcshell.ini
toolkit/forgetaboutsite/test/unit/xpcshell.ini
--- a/browser/components/contextualidentity/test/browser/browser.ini
+++ b/browser/components/contextualidentity/test/browser/browser.ini
@@ -1,19 +1,21 @@
 [DEFAULT]
 skip-if = buildapp == "mulet"
 support-files =
   empty_file.html
   file_reflect_cookie_into_title.html
   favicon-normal32.png
+  file_set_storages.html
   serviceworker.html
   worker.js
 
 [browser_aboutURLs.js]
 [browser_favicon.js]
+[browser_forgetaboutsite.js]
 [browser_usercontext.js]
 [browser_usercontextid_tabdrop.js]
 skip-if = os == "mac" || os == "win" # Intermittent failure - bug 1268276
 [browser_windowName.js]
 tags = openwindow
 [browser_windowOpen.js]
 tags = openwindow
 [browser_serviceworkers.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/contextualidentity/test/browser/browser_forgetaboutsite.js
@@ -0,0 +1,353 @@
+/*
+ * Bug 1238183 - Test cases for forgetAboutSite with userContextId.
+ */
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+let {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
+let LoadContextInfo = Cc["@mozilla.org/load-context-info-factory;1"]
+                      .getService(Ci.nsILoadContextInfoFactory);
+let css = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+           .getService(Ci.nsICacheStorageService);
+
+const USER_CONTEXTS = [
+  "default",
+  "personal",
+  "work",
+];
+const TEST_HOST = "example.com";
+const TEST_URL = "http://" + TEST_HOST + "/browser/browser/components/contextualidentity/test/browser/";
+const COOKIE_NAME = "userContextId";
+
+// Counter for image load hits.
+let gHits = 0;
+
+let gHttpServer = null;
+
+function imageHandler(metadata, response) {
+  // A 1x1 PNG image.
+  // Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
+  const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
+                     "ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
+  gHits++;
+  response.setHeader("Cache-Control", "max-age=10000", false);
+  response.setStatusLine(metadata.httpVersion, 200, "OK");
+  response.setHeader("Content-Type", "image/png", false);
+  response.write(IMAGE);
+}
+
+function loadImagePageHandler(metadata, response) {
+  response.setHeader("Cache-Control", "max-age=10000", false);
+  response.setStatusLine(metadata.httpVersion, 200, "Ok");
+  response.setHeader("Content-Type", "text/html", false);
+  let body = "<!DOCTYPE HTML>\
+              <html>\
+                <head>\
+                  <meta charset='utf-8'>\
+                  <title>Load Image</title>\
+                </head>\
+                <body>\
+                <img src='image.png'>\
+                </body>\
+              </html>";
+  response.bodyOutputStream.write(body, body.length);
+}
+
+function* openTabInUserContext(uri, userContextId) {
+  // Open the tab in the correct userContextId.
+  let tab = gBrowser.addTab(uri, {userContextId});
+
+  // Select tab and make sure its browser is focused.
+  gBrowser.selectedTab = tab;
+  tab.ownerDocument.defaultView.focus();
+
+  let browser = gBrowser.getBrowserForTab(tab);
+  yield BrowserTestUtils.browserLoaded(browser);
+  return {tab, browser};
+}
+
+function getCookiesForOA(host, userContextId) {
+  return Services.cookies.getCookiesFromHost(host, {userContextId});
+}
+
+function createURI(uri)
+{
+  let ioServ = Cc["@mozilla.org/network/io-service;1"]
+                  .getService(Components.interfaces.nsIIOService);
+  return ioServ.newURI(uri, null, null);
+}
+
+function getCacheStorage(where, lci, appcache)
+{
+  if (!lci) lci = LoadContextInfo.default;
+  switch (where) {
+    case "disk": return css.diskCacheStorage(lci, false);
+    case "memory": return css.memoryCacheStorage(lci);
+    case "appcache": return css.appCacheStorage(lci, appcache);
+    case "pin": return css.pinningCacheStorage(lci);
+  }
+  return null;
+}
+
+function OpenCacheEntry(key, where, flags, lci)
+{
+  return new Promise(resolve => {
+    key = createURI(key);
+    function CacheListener() { }
+    CacheListener.prototype = {
+      _appCache: null,
+
+      QueryInterface: function (iid) {
+        if (iid.equals(Components.interfaces.nsICacheEntryOpenCallback) ||
+            iid.equals(Components.interfaces.nsISupports))
+          return this;
+        throw Components.results.NS_ERROR_NO_INTERFACE;
+      },
+
+      onCacheEntryCheck: function(entry, appCache) {
+        return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
+      },
+
+      onCacheEntryAvailable: function (entry, isnew, appCache, status) {
+        resolve();
+      },
+
+      run: function () {
+        let storage = getCacheStorage(where, lci, this._appCache);
+        storage.asyncOpenURI(key, "", flags, this);
+      }
+    };
+
+    (new CacheListener()).run();
+  });
+}
+
+//
+// Test functions.
+//
+
+// Cookies
+function* test_cookie_cleared() {
+  let tabs = [];
+
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    // Load the page in 3 different contexts and set a cookie
+    // which should only be visible in that context.
+    let value = USER_CONTEXTS[userContextId];
+
+    // Open our tab in the given user context.
+    tabs[userContextId] = yield* openTabInUserContext(TEST_URL+ "file_set_storages.html?" + value, userContextId);
+  }
+  // Check that cookies have been set properly.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    let enumerator = getCookiesForOA(TEST_HOST, userContextId);
+    ok(enumerator.hasMoreElements(), "Cookies available");
+
+    let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+    Assert.equal(foundCookie["name"], COOKIE_NAME, "Check cookie name");
+    Assert.equal(foundCookie["value"], USER_CONTEXTS[userContextId], "Check cookie value");
+  }
+
+  // Forget the site.
+  ForgetAboutSite.removeDataFromDomain(TEST_HOST);
+
+  // Check that whether cookies has been cleared or not.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    let enumerator = getCookiesForOA(TEST_HOST, userContextId);
+    ok(!enumerator.hasMoreElements(), "No Cookie should be here");
+  }
+
+  // Clear Tabs
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    yield BrowserTestUtils.removeTab(tabs[userContextId].tab);
+  }
+}
+
+// Cache
+function* test_cache_cleared() {
+  // First, add some caches.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    yield OpenCacheEntry("http://" + TEST_HOST + "/",
+                         "disk",
+                         Ci.nsICacheStorage.OPEN_NORMALLY,
+                         LoadContextInfo.custom(false, false, {userContextId}));
+
+    yield OpenCacheEntry("http://" + TEST_HOST + "/",
+                         "memory",
+                         Ci.nsICacheStorage.OPEN_NORMALLY,
+                         LoadContextInfo.custom(false, false, {userContextId}));
+  }
+
+
+  // Check that caches have been set correctly.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    let mem = getCacheStorage("memory");
+    let disk = getCacheStorage("disk");
+
+    Assert.ok(mem.exists(createURI("http://" + TEST_HOST + "/"), ""), "The memory cache has been set correctly");
+    Assert.ok(disk.exists(createURI("http://" + TEST_HOST + "/"), ""), "The disk cache has been set correctly");
+  }
+
+  // Forget the site.
+  ForgetAboutSite.removeDataFromDomain(TEST_HOST);
+
+  // Check that do caches be removed or not?
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    let mem = getCacheStorage("memory");
+    let disk = getCacheStorage("disk");
+
+    Assert.ok(!mem.exists(createURI("http://" + TEST_HOST + "/"), ""), "The memory cache is cleared");
+    Assert.ok(!disk.exists(createURI("http://" + TEST_HOST + "/"), ""), "The disk cache is cleared");
+  }
+}
+
+// Image Cache
+function* test_image_cache_cleared() {
+  let tabs = [];
+
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    // Open our tab in the given user context to cache image.
+    tabs[userContextId] = yield* openTabInUserContext('http://localhost:' + gHttpServer.identity.primaryPort + '/loadImage.html',
+                                                      userContextId);
+    yield BrowserTestUtils.removeTab(tabs[userContextId].tab);
+  }
+
+  // Check that image cache works with the userContextId.
+  todo_is(gHits, 3, "The image should be loaded three times. This test should be enabled after the bug 1270680 landed");
+
+  // Reset the cache count.
+  gHits = 0;
+
+  // Forget the site.
+  ForgetAboutSite.removeDataFromDomain("localhost:" + gHttpServer.identity.primaryPort + "/");
+
+  // Load again.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    // Open our tab in the given user context to cache image.
+    tabs[userContextId] = yield* openTabInUserContext('http://localhost:' + gHttpServer.identity.primaryPort + '/loadImage.html',
+                                                      userContextId);
+    yield BrowserTestUtils.removeTab(tabs[userContextId].tab);
+  }
+
+  // Check that image cache was cleared and the server gets another three hits.
+  todo_is(gHits, 3, "The image should be loaded three times. This test should be enabled after the bug 1270680 landed");
+}
+
+// Offline Storage
+function* test_storage_cleared() {
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    // Load the page in 3 different contexts and set the local storage
+    // which should only be visible in that context.
+    let value = USER_CONTEXTS[userContextId];
+
+    // Open our tab in the given user context.
+    let tabInfo = yield* openTabInUserContext(TEST_URL+ "file_set_storages.html?" + value, userContextId);
+
+    // Check that the local storage has been set correctly.
+    let win = tabInfo.browser.contentWindow;
+    Assert.equal(win.localStorage.getItem("userContext"), USER_CONTEXTS[userContextId], "Check the local storage value");
+
+    // Check that the session storage has been set correctly.
+    Assert.equal(win.sessionStorage.getItem("userContext"), USER_CONTEXTS[userContextId], "Check the session storage value");
+
+    // Check that the indexedDB has been set correctly.
+    yield ContentTask.spawn(tabInfo.browser, { userContext: USER_CONTEXTS[userContextId] }, function* (arg) {
+      let request = content.indexedDB.open("idb", 1);
+
+      let db = yield new Promise(done => {
+        request.onsuccess = event => {
+          done(event.target.result);
+        };
+      });
+
+      let transaction = db.transaction(["obj"], "readonly");
+      let store = transaction.objectStore("obj");
+      let storeRequest = store.get(1);
+
+      yield new Promise(done => {
+        storeRequest.onsuccess = event => {
+          let res = storeRequest.result;
+          Assert.equal(res.userContext, arg.userContext, "Check the indexedDB value");
+          done();
+        };
+      });
+    });
+
+    // Close this tab.
+    yield BrowserTestUtils.removeTab(tabInfo.tab);
+  }
+
+  // Forget the site.
+  ForgetAboutSite.removeDataFromDomain(TEST_HOST);
+
+  // Open the tab again without setting the localStorage and check that the
+  // local storage has been cleared or not.
+  for (let userContextId of Object.keys(USER_CONTEXTS)) {
+    // Open our tab in the given user context without setting local storage.
+    let tabInfo = yield* openTabInUserContext(TEST_URL+ "file_set_storages.html", userContextId);
+    let win = tabInfo.browser.contentWindow;
+
+    // Check that does the local storage be cleared or not.
+    Assert.ok(!win.localStorage.getItem("userContext"), "The local storage has been cleared");
+
+    // Check that does the session storage be cleared or not.
+    Assert.ok(!win.sessionStorage.getItem("userContext"), "The session storage has been cleared");
+
+    // Check that does the indexedDB be cleared or not.
+    yield ContentTask.spawn(tabInfo.browser, null, function* () {
+      let request = content.indexedDB.open("idb", 1);
+
+      let db = yield new Promise(done => {
+        request.onsuccess = event => {
+          done(event.target.result);
+        };
+      });
+      try {
+        let transaction = db.transaction(["obj"], "readonly");
+        Assert.ok(false, "The indexedDB should not exist");
+      } catch (e) {
+        Assert.equal(e.name, "NotFoundError", "The indexedDB does not exist as expected");
+      }
+    });
+
+    // Close the tab.
+    yield BrowserTestUtils.removeTab(tabInfo.tab);
+  }
+}
+
+add_task(function* setup() {
+  // Make sure userContext is enabled.
+  yield new Promise(resolve => {
+    SpecialPowers.pushPrefEnv({"set": [
+      ["privacy.userContext.enabled", true]
+    ]}, resolve);
+  });
+
+  // Create a http server for the image cache test.
+  if (!gHttpServer) {
+    gHttpServer = new HttpServer();
+    gHttpServer.registerPathHandler('/image.png', imageHandler);
+    gHttpServer.registerPathHandler('/loadImage.html', loadImagePageHandler);
+    gHttpServer.start(-1);
+  }
+});
+
+let tests = [
+  test_cookie_cleared,
+  test_cache_cleared,
+  test_image_cache_cleared,
+  test_storage_cleared,
+];
+
+add_task(function* test() {
+  for (let i = 0; i < tests.length; i++)
+    add_task(tests[i]);
+});
+
+registerCleanupFunction(() => {
+  gHttpServer.stop(() => {
+    gHttpServer = null;
+  });
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/contextualidentity/test/browser/file_set_storages.html
@@ -0,0 +1,42 @@
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title>Bug 1238183</title>
+  </head>
+  <body>
+    <script type="application/javascript;version=1.7">
+      "use strict";
+
+      // if we have a query string, use it to set storages
+      if (window.location.search.length > 0) {
+        let context_name = window.location.search.substr(1);
+        document.cookie = "userContextId=" + context_name;
+        localStorage.setItem("userContext", context_name);
+        sessionStorage.setItem("userContext", context_name);
+
+        let request = indexedDB.open("idb", 1);
+
+        request.onerror = function() {
+          throw new Error("error opening db connection");
+        };
+
+        request.onupgradeneeded = event => {
+          let db = event.target.result;
+          let store = db.createObjectStore("obj", { keyPath: "id" });
+          store.createIndex("userContext", "userContext", { unique: false });
+        };
+
+        request.onsuccess = event => {
+          let db = request.result;
+          let transaction = db.transaction(["obj"], "readwrite");
+          let store = transaction.objectStore("obj");
+          store.add({id: 1, userContext: context_name});
+
+          transaction.oncomplete = () => {
+            db.close();
+          };
+        };
+      }
+    </script>
+  </body>
+</html>
--- a/dom/push/test/xpcshell/xpcshell.ini
+++ b/dom/push/test/xpcshell/xpcshell.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 head = head.js head-http2.js
 tail =
+firefox-appdir = browser
 # Push notifications and alarms are currently disabled on Android.
 skip-if = toolkit == 'android'
 
 [test_clear_forgetAboutSite.js]
 [test_clear_origin_data.js]
 [test_crypto.js]
 [test_drop_expired.js]
 [test_handler_service.js]
--- a/toolkit/forgetaboutsite/test/unit/xpcshell.ini
+++ b/toolkit/forgetaboutsite/test/unit/xpcshell.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 head = head_forgetaboutsite.js ../../../../dom/push/test/xpcshell/head.js
 tail =
+firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 support-files =
   !/dom/push/test/xpcshell/head.js
 
 [test_removeDataFromDomain.js]