Bug 1442183 - Allow multiple selection in the site data manager list. r=prathiksha draft
authorJohann Hofmann <jhofmann@mozilla.com>
Wed, 11 Apr 2018 08:59:49 +0200
changeset 780595 e6e04f7295c7fc354b1c4049d37f943354d6476c
parent 779997 0528a414c2a86dad0623779abde5301d37337934
push id106032
push userjhofmann@mozilla.com
push dateWed, 11 Apr 2018 15:38:42 +0000
reviewersprathiksha
bugs1442183
milestone61.0a1
Bug 1442183 - Allow multiple selection in the site data manager list. r=prathiksha MozReview-Commit-ID: D1u3963xC6C
browser/components/preferences/in-content/tests/siteData/browser.ini
browser/components/preferences/in-content/tests/siteData/browser_siteData2.js
browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js
browser/components/preferences/in-content/tests/siteData/head.js
browser/components/preferences/siteDataSettings.js
browser/components/preferences/siteDataSettings.xul
--- a/browser/components/preferences/in-content/tests/siteData/browser.ini
+++ b/browser/components/preferences/in-content/tests/siteData/browser.ini
@@ -7,8 +7,9 @@ support-files =
   offline/offline.html
   offline/manifest.appcache
 
 [browser_clearSiteData.js]
 [browser_siteData.js]
 skip-if = (os == 'linux' && debug) # Bug 1439332
 [browser_siteData2.js]
 [browser_siteData3.js]
+[browser_siteData_multi_select.js]
--- a/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js
+++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData2.js
@@ -1,24 +1,10 @@
 "use strict";
 
-function promiseSettingsDialogClose() {
-  return new Promise(resolve => {
-    let win = gBrowser.selectedBrowser.contentWindow;
-    let dialogOverlay = win.gSubDialog._topDialog._overlay;
-    let dialogWin = win.gSubDialog._topDialog._frame.contentWindow;
-    dialogWin.addEventListener("unload", function unload() {
-      if (dialogWin.document.documentURI === "chrome://browser/content/preferences/siteDataSettings.xul") {
-        isnot(dialogOverlay.style.visibility, "visible", "The Settings dialog should be hidden");
-        resolve();
-      }
-    }, { once: true });
-  });
-}
-
 function assertAllSitesNotListed(win) {
   let frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
   let removeBtn = frameDoc.getElementById("removeSelected");
   let removeAllBtn = frameDoc.getElementById("removeAll");
   let sitesList = frameDoc.getElementById("sitesList");
   let sites = sitesList.getElementsByTagName("richlistitem");
   is(sites.length, 0, "Should not list all sites");
   is(removeBtn.disabled, true, "Should disable the removeSelected button");
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/siteData/browser_siteData_multi_select.js
@@ -0,0 +1,84 @@
+"use strict";
+
+// Test selecting and removing partial sites
+add_task(async function() {
+  mockSiteDataManager.register(SiteDataManager, [
+    {
+      usage: 1024,
+      origin: "https://account.xyz.com",
+      persisted: true
+    },
+    {
+      usage: 1024,
+      origin: "https://shopping.xyz.com",
+      persisted: false
+    },
+    {
+      usage: 1024,
+      origin: "http://cinema.bar.com",
+      persisted: true
+    },
+    {
+      usage: 1024,
+      origin: "http://email.bar.com",
+      persisted: false
+    },
+    {
+      usage: 1024,
+      origin: "https://s3-us-west-2.amazonaws.com",
+      persisted: true
+    },
+    {
+      usage: 1024,
+      origin: "https://127.0.0.1",
+      persisted: false
+    },
+    {
+      usage: 1024,
+      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 doc = gBrowser.selectedBrowser.contentDocument;
+
+  // Test the initial state
+  assertSitesListed(doc, fakeHosts);
+
+  let removeDialogOpenPromise = BrowserTestUtils.promiseAlertDialogOpen("accept", REMOVE_DIALOG_URL);
+  let settingsDialogClosePromise = promiseSettingsDialogClose();
+
+  let win = gBrowser.selectedBrowser.contentWindow;
+  let frameDoc = win.gSubDialog._topDialog._frame.contentDocument;
+
+  // Select some sites to remove.
+  let sitesList = frameDoc.getElementById("sitesList");
+  fakeHosts.slice(0, 2).forEach(host => {
+    let site = sitesList.querySelector(`richlistitem[host="${host}"]`);
+    sitesList.addItemToSelection(site);
+  });
+
+  let removeBtn = frameDoc.getElementById("removeSelected");
+  is(removeBtn.disabled, false, "Should enable the removeSelected button");
+  removeBtn.doCommand();
+  is(removeBtn.disabled, true, "Should disable the removeSelected button");
+
+  let saveBtn = frameDoc.getElementById("save");
+  assertSitesListed(doc, fakeHosts.slice(2));
+  saveBtn.doCommand();
+
+  await removeDialogOpenPromise;
+  await settingsDialogClosePromise;
+  await openSiteDataSettingsDialog();
+
+  assertSitesListed(doc, fakeHosts.slice(2));
+
+  await mockSiteDataManager.unregister();
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
--- a/browser/components/preferences/in-content/tests/siteData/head.js
+++ b/browser/components/preferences/in-content/tests/siteData/head.js
@@ -110,16 +110,30 @@ function openSiteDataSettingsDialog() {
   let dialogInitPromise = TestUtils.topicObserved("sitedata-settings-init", () => true);
   let fullyLoadPromise = Promise.all([dialogLoadPromise, dialogInitPromise]).then(() => {
     is(dialogOverlay.style.visibility, "visible", "The Settings dialog should be visible");
   });
   settingsBtn.doCommand();
   return fullyLoadPromise;
 }
 
+function promiseSettingsDialogClose() {
+  return new Promise(resolve => {
+    let win = gBrowser.selectedBrowser.contentWindow;
+    let dialogOverlay = win.gSubDialog._topDialog._overlay;
+    let dialogWin = win.gSubDialog._topDialog._frame.contentWindow;
+    dialogWin.addEventListener("unload", function unload() {
+      if (dialogWin.document.documentURI === "chrome://browser/content/preferences/siteDataSettings.xul") {
+        isnot(dialogOverlay.style.visibility, "visible", "The Settings dialog should be hidden");
+        resolve();
+      }
+    }, { once: true });
+  });
+}
+
 function assertSitesListed(doc, hosts) {
   let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
   let removeBtn = frameDoc.getElementById("removeSelected");
   let removeAllBtn = frameDoc.getElementById("removeAll");
   let sitesList = frameDoc.getElementById("sitesList");
   let totalSitesNumber = sitesList.getElementsByTagName("richlistitem").length;
   is(totalSitesNumber, hosts.length, "Should list the right sites number");
   hosts.forEach(host => {
--- a/browser/components/preferences/siteDataSettings.js
+++ b/browser/components/preferences/siteDataSettings.js
@@ -254,20 +254,17 @@ let gSiteDataSettings = {
   },
 
   onCommandSearch() {
     this._buildSitesList(this._sites);
     this._list.clearSelection();
   },
 
   onClickRemoveSelected() {
-    let selected = this._list.selectedItem;
-    if (selected) {
-      this._removeSiteItems([selected]);
-    }
+    this._removeSiteItems(this._list.selectedItems);
     this._list.clearSelection();
   },
 
   onClickRemoveAll() {
     let siteItems = this._list.getElementsByTagName("richlistitem");
     if (siteItems.length > 0) {
       this._removeSiteItems(siteItems);
     }
--- a/browser/components/preferences/siteDataSettings.xul
+++ b/browser/components/preferences/siteDataSettings.xul
@@ -30,17 +30,17 @@
     <separator class="thin"/>
 
     <hbox id="searchBoxContainer">
       <textbox id="searchBox" type="search" flex="1"
         placeholder="&searchTextboxPlaceHolder;" accesskey="&searchTextboxPlaceHolder.accesskey;"/>
     </hbox>
     <separator class="thin"/>
 
-    <richlistbox id="sitesList" orient="vertical" flex="1">
+    <richlistbox seltype="multiple" id="sitesList" orient="vertical" flex="1">
       <listheader>
         <treecol flex="4" width="50" label="&hostCol.label;" id="hostCol"/>
         <treecol flex="1" width="50" label="&cookiesCol.label;" id="cookiesCol"/>
         <!-- Sorted by usage so the user can quickly see which sites use the most data. -->
         <treecol flex="2" width="50" label="&usageCol.label;" id="usageCol" data-isCurrentSortCol="true"/>
         <treecol flex="2" width="50" label="&lastAccessedCol.label;" id="lastAccessedCol" />
       </listheader>
     </richlistbox>