Bug 1421737 - Part 4 - Update site data manager tests to include cookies. r=Gijs draft
authorJohann Hofmann <jhofmann@mozilla.com>
Fri, 09 Feb 2018 00:04:03 +0100
changeset 755539 04fdb5c952a676cc99d73f2c7dfa54300682b977
parent 755538 bc202a92d62ff8d4ddfd40ff4096c9ad1fdb0735
push id99178
push userjhofmann@mozilla.com
push dateThu, 15 Feb 2018 11:57:05 +0000
reviewersGijs
bugs1421737
milestone60.0a1
Bug 1421737 - Part 4 - Update site data manager tests to include cookies. r=Gijs This adds a dedicated test for showing and deleting cookies in site data management as well as amending tests for sorting, grouping, etc. MozReview-Commit-ID: 59mN3uASwPP
browser/components/preferences/in-content/tests/browser_siteData.js
browser/components/preferences/in-content/tests/browser_siteData2.js
browser/components/preferences/in-content/tests/browser_siteData3.js
browser/components/preferences/in-content/tests/head.js
--- a/browser/components/preferences/in-content/tests/browser_siteData.js
+++ b/browser/components/preferences/in-content/tests/browser_siteData.js
@@ -5,16 +5,17 @@
 
 const TEST_QUOTA_USAGE_HOST = "example.com";
 const TEST_QUOTA_USAGE_ORIGIN = "https://" + TEST_QUOTA_USAGE_HOST;
 const TEST_QUOTA_USAGE_URL = TEST_QUOTA_USAGE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/site_data_test.html";
 const TEST_OFFLINE_HOST = "example.org";
 const TEST_OFFLINE_ORIGIN = "https://" + TEST_OFFLINE_HOST;
 const TEST_OFFLINE_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/offline/offline.html";
 const TEST_SERVICE_WORKER_URL = TEST_OFFLINE_ORIGIN + "/browser/browser/components/preferences/in-content/tests/service_worker_test.html";
+const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
 
 const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {});
 const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
 const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
 const { OfflineAppCacheHelper } = ChromeUtils.import("resource:///modules/offlineAppCache.jsm", {});
 
 function getPersistentStoragePermStatus(origin) {
   let uri = NetUtil.newURI(origin);
@@ -137,8 +138,99 @@ add_task(async function() {
       ok(false, `Should have one site of ${host}`);
     }
   });
   await acceptRemovePromise;
   await updatePromise;
   await promiseServiceWorkersCleared();
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
+
+// Test showing and removing sites with cookies.
+add_task(async function() {
+  SiteDataManager.removeAll();
+
+  // Add some test cookies.
+  let uri = Services.io.newURI("https://example.com");
+  let uri2 = Services.io.newURI("https://example.org");
+  Services.cookies.add(uri.host, uri.pathQueryRef, "test1", "1",
+    false, false, false, Date.now() + 1000 * 60 * 60);
+  Services.cookies.add(uri.host, uri.pathQueryRef, "test2", "2",
+    false, false, false, Date.now() + 1000 * 60 * 60);
+  Services.cookies.add(uri2.host, uri2.pathQueryRef, "test1", "1",
+    false, false, false, Date.now() + 1000 * 60 * 60);
+
+  // Ensure that private browsing cookies are ignored.
+  Services.cookies.add(uri.host, uri.pathQueryRef, "test3", "3",
+    false, false, false, Date.now() + 1000 * 60 * 60, { privateBrowsingId: 1 });
+
+  await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
+
+  // Open the site data manager and remove one site.
+  await openSiteDataSettingsDialog();
+  let removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
+  ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
+    let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
+
+    let siteItems = frameDoc.getElementsByTagName("richlistitem");
+    is(siteItems.length, 2, "Should list two sites with cookies");
+    let sitesList = frameDoc.getElementById("sitesList");
+    let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`);
+    let site2 = sitesList.querySelector(`richlistitem[host="example.org"]`);
+
+    let columns = site1.querySelectorAll(".item-box > label");
+    is(columns[0].value, "example.com", "Should show the correct host.");
+    is(columns[2].value, "2", "Should show the correct number of cookies.");
+    is(columns[3].value, "", "Should show no site data.");
+
+    columns = site2.querySelectorAll(".item-box > label");
+    is(columns[0].value, "example.org", "Should show the correct host.");
+    is(columns[2].value, "1", "Should show the correct number of cookies.");
+    is(columns[3].value, "", "Should show no site data.");
+
+    let removeBtn = frameDoc.getElementById("removeSelected");
+    let saveBtn = frameDoc.getElementById("save");
+    site2.click();
+    removeBtn.doCommand();
+    saveBtn.doCommand();
+  });
+  await removeDialogOpenPromise;
+
+  await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri2.host) == 0, "Cookies from the first host should be cleared");
+  is(Services.cookies.countCookiesFromHost(uri.host), 2, "Cookies from the second host should not be cleared");
+
+  // Open the site data manager and remove another site.
+  await openSiteDataSettingsDialog();
+  let acceptRemovePromise = promiseAlertDialogOpen("accept");
+  ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
+    let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
+
+    let siteItems = frameDoc.getElementsByTagName("richlistitem");
+    is(siteItems.length, 1, "Should list one site with cookies");
+    let sitesList = frameDoc.getElementById("sitesList");
+    let site1 = sitesList.querySelector(`richlistitem[host="example.com"]`);
+
+    let columns = site1.querySelectorAll(".item-box > label");
+    is(columns[0].value, "example.com", "Should show the correct host.");
+    is(columns[2].value, "2", "Should show the correct number of cookies.");
+    is(columns[3].value, "", "Should show no site data.");
+
+    let removeBtn = frameDoc.getElementById("removeSelected");
+    let saveBtn = frameDoc.getElementById("save");
+    site1.click();
+    removeBtn.doCommand();
+    saveBtn.doCommand();
+  });
+  await acceptRemovePromise;
+
+  await TestUtils.waitForCondition(() => Services.cookies.countCookiesFromHost(uri.host) == 0, "Cookies from the second host should be cleared");
+
+  await openSiteDataSettingsDialog();
+
+  ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
+    let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
+
+    let siteItems = frameDoc.getElementsByTagName("richlistitem");
+    is(siteItems.length, 0, "Should list no sites with cookies");
+  });
+
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
--- a/browser/components/preferences/in-content/tests/browser_siteData2.js
+++ b/browser/components/preferences/in-content/tests/browser_siteData2.js
@@ -27,43 +27,38 @@ function assertAllSitesNotListed(win) {
   is(sites.length, 0, "Should not list all sites");
   is(removeBtn.disabled, true, "Should disable the removeSelected button");
   is(removeAllBtn.disabled, true, "Should disable the removeAllBtn button");
 }
 
 // Test selecting and removing all sites one by one
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"),
+      origin: "https://shopping.xyz.com",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
+      origin: "http://cinema.bar.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://email.bar.com"),
+      origin: "http://email.bar.com",
       persisted: false
     },
-  ];
+  ]);
   let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
 
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
 
   let win = gBrowser.selectedBrowser.contentWindow;
@@ -87,20 +82,22 @@ add_task(async function() {
   await openSiteDataSettingsDialog();
   assertSitesListed(doc, fakeHosts);
 
   // Test the "Save Changes" button but cancelling save
   let cancelPromise = promiseAlertDialogOpen("cancel");
   settingsDialogClosePromise = promiseSettingsDialogClose();
   frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
   saveBtn = frameDoc.getElementById("save");
+  cancelBtn = frameDoc.getElementById("cancel");
   removeAllSitesOneByOne();
   assertAllSitesNotListed(win);
   saveBtn.doCommand();
   await cancelPromise;
+  cancelBtn.doCommand();
   await settingsDialogClosePromise;
   await openSiteDataSettingsDialog();
   assertSitesListed(doc, fakeHosts);
 
   // Test the "Save Changes" button and accepting save
   let acceptPromise = promiseAlertDialogOpen("accept");
   settingsDialogClosePromise = promiseSettingsDialogClose();
   updatePromise = promiseSiteDataManagerSitesUpdated();
@@ -128,61 +125,53 @@ add_task(async function() {
       removeBtn.doCommand();
     }
   }
 });
 
 // Test selecting and removing partial sites
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"),
+      origin: "https://shopping.xyz.com",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
+      origin: "http://cinema.bar.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://email.bar.com"),
+      origin: "http://email.bar.com",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://s3-us-west-2.amazonaws.com"),
+      origin: "https://s3-us-west-2.amazonaws.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://127.0.0.1"),
+      origin: "https://127.0.0.1",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://[0:0:0:0:0:0:0:1]"),
+      origin: "https://[0:0:0:0:0:0:0:1]",
       persisted: true
     },
-  ];
+  ]);
   let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
 
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
 
   let win = gBrowser.selectedBrowser.contentWindow;
@@ -207,20 +196,22 @@ add_task(async function() {
   await openSiteDataSettingsDialog();
   assertSitesListed(doc, fakeHosts);
 
   // Test the "Save Changes" button but canceling save
   removeDialogOpenPromise = promiseWindowDialogOpen("cancel", REMOVE_DIALOG_URL);
   settingsDialogClosePromise = promiseSettingsDialogClose();
   frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
   saveBtn = frameDoc.getElementById("save");
+  cancelBtn = frameDoc.getElementById("cancel");
   removeSelectedSite(fakeHosts.slice(0, 2));
   assertSitesListed(doc, fakeHosts.slice(2));
   saveBtn.doCommand();
   await removeDialogOpenPromise;
+  cancelBtn.doCommand();
   await settingsDialogClosePromise;
   await openSiteDataSettingsDialog();
   assertSitesListed(doc, fakeHosts);
 
   // Test the "Save Changes" button and accepting save
   removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
   settingsDialogClosePromise = promiseSettingsDialogClose();
   frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
@@ -252,43 +243,38 @@ add_task(async function() {
       }
     });
   }
 });
 
 // Test searching and then removing only visible sites
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"),
+      origin: "https://shopping.xyz.com",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
+      origin: "http://cinema.bar.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://email.bar.com"),
+      origin: "http://email.bar.com",
       persisted: false
     },
-  ];
+  ]);
   let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
 
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
 
   // Search "foo" to only list foo.com sites
@@ -316,31 +302,28 @@ add_task(async function() {
 
   mockSiteDataManager.unregister();
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 // Test dynamically clearing all site data
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"),
+      origin: "https://shopping.xyz.com",
       persisted: false
     },
-  ];
+  ]);
   let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
 
   // Test the initial state
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
   let doc = gBrowser.selectedBrowser.contentDocument;
--- a/browser/components/preferences/in-content/tests/browser_siteData3.js
+++ b/browser/components/preferences/in-content/tests/browser_siteData3.js
@@ -1,42 +1,43 @@
 "use strict";
 const { SiteDataManager } = ChromeUtils.import("resource:///modules/SiteDataManager.jsm", {});
 const { DownloadUtils } = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm", {});
 
 // Test not displaying sites which store 0 byte and don't have persistent storage.
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({ set: [["browser.storageManager.enabled", true]] });
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 0,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
       persisted: true
     },
     {
       usage: 0,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("https://shopping.xyz.com"),
+      origin: "https://shopping.xyz.com",
       persisted: false
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
+      origin: "http://cinema.bar.com",
       persisted: true
     },
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("http://email.bar.com"),
+      origin: "http://email.bar.com",
       persisted: false
     },
-  ];
+    {
+      usage: 0,
+      origin: "http://cookies.bar.com",
+      cookies: 5,
+      persisted: false
+    },
+  ]);
   let fakeHosts = mockSiteDataManager.fakeSites.map(site => site.principal.URI.host);
 
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   let doc = gBrowser.selectedBrowser.contentDocument;
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
   assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com"));
@@ -44,143 +45,151 @@ add_task(async function() {
   mockSiteDataManager.unregister();
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 // Test grouping and listing sites across scheme, port and origin attributes by host
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({ set: [["browser.storageManager.enabled", true]] });
   const quotaUsage = 1024;
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: quotaUsage,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("https://account.xyz.com^userContextId=1"),
+      origin: "https://account.xyz.com^userContextId=1",
+      cookies: 2,
       persisted: true
     },
     {
       usage: quotaUsage,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
+      cookies: 1,
       persisted: false
     },
     {
       usage: quotaUsage,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("https://account.xyz.com:123"),
+      origin: "https://account.xyz.com:123",
+      cookies: 1,
       persisted: false
     },
     {
       usage: quotaUsage,
-      principal: Services.scriptSecurityManager
-        .createCodebasePrincipalFromOrigin("http://account.xyz.com"),
+      origin: "http://account.xyz.com",
+      cookies: 1,
       persisted: false
     },
-  ];
+  ]);
 
   let updatedPromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatedPromise;
   await openSiteDataSettingsDialog();
   // eslint-disable-next-line mozilla/no-cpows-in-tests
   let win = gBrowser.selectedBrowser.contentWindow;
   let dialogFrame = win.gSubDialog._topDialog._frame;
   let frameDoc = dialogFrame.contentDocument;
 
   let siteItems = frameDoc.getElementsByTagName("richlistitem");
   is(siteItems.length, 1, "Should group sites across scheme, port and origin attributes");
 
+  let columns = siteItems[0].querySelectorAll(".item-box > label");
+
   let expected = "account.xyz.com";
-  let host = siteItems[0].getAttribute("host");
-  is(host, expected, "Should group and list sites by host");
+  is(columns[0].value, expected, "Should group and list sites by host");
 
   let prefStrBundle = frameDoc.getElementById("bundlePreferences");
+  expected = prefStrBundle.getString("persistent");
+  is(columns[1].value, expected, "Should mark persisted status across scheme, port and origin attributes");
+
+  is(columns[2].value, "5", "Should group cookies across scheme, port and origin attributes");
+
   expected = prefStrBundle.getFormattedString("siteUsage",
     DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length));
-  let usage = siteItems[0].getAttribute("usage");
-  is(usage, expected, "Should sum up usages across scheme, port and origin attributes");
-
-  expected = prefStrBundle.getString("persistent");
-  let status = siteItems[0].getAttribute("status");
-  is(status, expected, "Should mark persisted status across scheme, port and origin attributes");
+  is(columns[3].value, expected, "Should sum up usages across scheme, port and origin attributes");
 
   mockSiteDataManager.unregister();
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 // Test sorting
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
-  mockSiteDataManager.register(SiteDataManager);
-  mockSiteDataManager.fakeSites = [
+  mockSiteDataManager.register(SiteDataManager, [
     {
       usage: 1024,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://account.xyz.com"),
+      origin: "https://account.xyz.com",
+      cookies: 6,
       persisted: true
     },
     {
       usage: 1024 * 2,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("https://books.foo.com"),
+      origin: "https://books.foo.com",
+      cookies: 0,
       persisted: false
     },
     {
       usage: 1024 * 3,
-      principal: Services.scriptSecurityManager
-                         .createCodebasePrincipalFromOrigin("http://cinema.bar.com"),
+      origin: "http://cinema.bar.com",
+      cookies: 3,
       persisted: true
     },
-  ];
+  ]);
 
   let updatePromise = promiseSiteDataManagerSitesUpdated();
   await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
   await updatePromise;
   await openSiteDataSettingsDialog();
 
   // eslint-disable-next-line mozilla/no-cpows-in-tests
   let dialog = content.gSubDialog._topDialog;
   let dialogFrame = dialog._frame;
   let frameDoc = dialogFrame.contentDocument;
   let hostCol = frameDoc.getElementById("hostCol");
   let usageCol = frameDoc.getElementById("usageCol");
   let statusCol = frameDoc.getElementById("statusCol");
+  let cookiesCol = frameDoc.getElementById("cookiesCol");
   let sitesList = frameDoc.getElementById("sitesList");
 
   // Test default sorting
   assertSortByUsage("descending");
 
   // Test sorting on the usage column
   usageCol.click();
   assertSortByUsage("ascending");
   usageCol.click();
   assertSortByUsage("descending");
 
   // Test sorting on the host column
   hostCol.click();
-  assertSortByHost("ascending");
+  assertSortByBaseDomain("ascending");
   hostCol.click();
-  assertSortByHost("descending");
+  assertSortByBaseDomain("descending");
 
   // Test sorting on the permission status column
+  cookiesCol.click();
+  assertSortByCookies("ascending");
+  cookiesCol.click();
+  assertSortByCookies("descending");
+
+  // Test sorting on the cookies column
   statusCol.click();
   assertSortByStatus("ascending");
   statusCol.click();
   assertSortByStatus("descending");
 
   mockSiteDataManager.unregister();
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
-  function assertSortByHost(order) {
+  function assertSortByBaseDomain(order) {
     let siteItems = sitesList.getElementsByTagName("richlistitem");
     for (let i = 0; i < siteItems.length - 1; ++i) {
       let aHost = siteItems[i].getAttribute("host");
       let bHost = siteItems[i + 1].getAttribute("host");
-      let result = aHost.localeCompare(bHost);
+      let a = findSiteByHost(aHost);
+      let b = findSiteByHost(bHost);
+      let result = a.baseDomain.localeCompare(b.baseDomain);
       if (order == "ascending") {
         Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by host");
       } else {
         Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by host");
       }
     }
   }
 
@@ -216,12 +225,28 @@ add_task(async function() {
       if (order == "ascending") {
         Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by usage");
       } else {
         Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by usage");
       }
     }
   }
 
+  function assertSortByCookies(order) {
+    let siteItems = sitesList.getElementsByTagName("richlistitem");
+    for (let i = 0; i < siteItems.length - 1; ++i) {
+      let aHost = siteItems[i].getAttribute("host");
+      let bHost = siteItems[i + 1].getAttribute("host");
+      let a = findSiteByHost(aHost);
+      let b = findSiteByHost(bHost);
+      let result = a.cookies.length - b.cookies.length;
+      if (order == "ascending") {
+        Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by number of cookies");
+      } else {
+        Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order by number of cookies");
+      }
+    }
+  }
+
   function findSiteByHost(host) {
     return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
   }
 });
--- a/browser/components/preferences/in-content/tests/head.js
+++ b/browser/components/preferences/in-content/tests/head.js
@@ -236,26 +236,48 @@ const mockSiteDataManager = {
 
   _removeQuotaUsage(site) {
     var target = site.principals[0].URI.host;
     this.fakeSites = this.fakeSites.filter(fakeSite => {
       return fakeSite.principal.URI.host != target;
     });
   },
 
-  register(SiteDataManager) {
+  register(SiteDataManager, fakeSites) {
     this._SiteDataManager = SiteDataManager;
     this._originalQMS = this._SiteDataManager._qms;
     this._SiteDataManager._qms = this;
     this._originalRemoveQuotaUsage = this._SiteDataManager._removeQuotaUsage;
     this._SiteDataManager._removeQuotaUsage = this._removeQuotaUsage.bind(this);
-    this.fakeSites = null;
+    // Add some fake data.
+    this.fakeSites = fakeSites;
+    for (let site of fakeSites) {
+      if (!site.principal) {
+        site.principal = Services.scriptSecurityManager
+          .createCodebasePrincipalFromOrigin(site.origin);
+      }
+
+      let uri = site.principal.URI;
+      try {
+        site.baseDomain = Services.eTLD.getBaseDomainFromHost(uri.host);
+      } catch (e) {
+        site.baseDomain = uri.host;
+      }
+
+      // Add some cookies if needed.
+      for (let i = 0; i < (site.cookies || 0); i++) {
+        Services.cookies.add(uri.host, uri.pathQueryRef, Cu.now(), i,
+          false, false, false, Date.now() + 1000 * 60 * 60);
+      }
+    }
   },
 
   unregister() {
+    this.fakeSites = null;
+    this._SiteDataManager.removeAll();
     this._SiteDataManager._qms = this._originalQMS;
     this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage;
   }
 };
 
 function getQuotaUsage(origin) {
   return new Promise(resolve => {
     let uri = NetUtil.newURI(origin);