Bug 1421737 - Part 4 - Update site data manager tests to include cookies. r=Gijs
authorJohann Hofmann <jhofmann@mozilla.com>
Fri, 09 Feb 2018 00:04:03 +0100
changeset 403931 7fe3e62d6413a53e1ee4522b48a63af799b7acdb
parent 403930 d9aa01a177517a7b0bdf1fb18b3fa8b634b56584
child 403932 99dd8c88ef305a76954cc6f488cb9dde7030fd94
push id99888
push userjhofmann@mozilla.com
push dateThu, 15 Feb 2018 12:34:34 +0000
treeherdermozilla-inbound@7fe3e62d6413 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1421737
milestone60.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 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);