Bug 1348223 - Part 2 - Move SiteDataManager.jsm to components and improve functionality for getting and removing by host. r=florian draft
authorJohann Hofmann <jhofmann@mozilla.com>
Thu, 22 Mar 2018 17:48:13 +0100
changeset 778138 2d48740a023f63a2ec7af06f4510ab9cbb91fc66
parent 778137 e515a1a12f6a665f6a4b96deec73790540755189
child 778139 f88772b2275c97d30480a626e23a9d1875339b2b
push id105397
push userjhofmann@mozilla.com
push dateThu, 05 Apr 2018 21:09:18 +0000
reviewersflorian
bugs1348223
milestone61.0a1
Bug 1348223 - Part 2 - Move SiteDataManager.jsm to components and improve functionality for getting and removing by host. r=florian This commit is in preparation of using SiteDataManager in the page info window to display site data information for a individual hosts. MozReview-Commit-ID: 3YmUZInvoAT
browser/components/preferences/SiteDataManager.jsm
browser/components/preferences/moz.build
browser/components/preferences/siteDataSettings.js
browser/modules/SiteDataManager.jsm
browser/modules/moz.build
--- a/browser/components/preferences/moz.build
+++ b/browser/components/preferences/moz.build
@@ -16,14 +16,10 @@ BROWSER_CHROME_MANIFESTS += [
 for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
     DEFINES[var] = CONFIG[var]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
     DEFINES['HAVE_SHELL_SERVICE'] = 1
 
 JAR_MANIFESTS += ['jar.mn']
 
-EXTRA_JS_MODULES += [
-    'SiteDataManager.jsm'
-]
-
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Preferences')
--- a/browser/components/preferences/siteDataSettings.js
+++ b/browser/components/preferences/siteDataSettings.js
@@ -224,32 +224,19 @@ let gSiteDataSettings = {
 
     if (removals.length > 0) {
       if (this._sites.length == removals.length) {
         allowed = SiteDataManager.promptSiteDataRemoval(window);
         if (allowed) {
           SiteDataManager.removeAll();
         }
       } else {
-        let args = {
-          hosts: removals,
-          allowed: false
-        };
-        let features = "centerscreen,chrome,modal,resizable=no";
-        window.openDialog("chrome://browser/content/preferences/siteDataRemoveSelected.xul", "", features, args);
-        allowed = args.allowed;
+        allowed = SiteDataManager.promptSiteDataRemoval(window, removals);
         if (allowed) {
-          try {
-            SiteDataManager.remove(removals);
-          } catch (e) {
-            // Hit error, maybe remove unknown site.
-            // Let's print out the error, then proceed to close this settings dialog.
-            // When we next open again we will once more get sites from the SiteDataManager and refresh the list.
-            Cu.reportError(e);
-          }
+          SiteDataManager.remove(removals).catch(Cu.reportError);
         }
       }
     }
 
     // If the user cancelled the confirm dialog keep the site data window open,
     // they can still press cancel again to exit.
     if (allowed) {
       this.close();
rename from browser/components/preferences/SiteDataManager.jsm
rename to browser/modules/SiteDataManager.jsm
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/modules/SiteDataManager.jsm
@@ -49,17 +49,17 @@ var SiteDataManager = {
     // Clear old data and requests first
     this._sites.clear();
     this._getAllCookies();
     await this._getQuotaUsage();
     this._updateAppCache();
     Services.obs.notifyObservers(null, "sitedatamanager:sites-updated");
   },
 
-  _getBaseDomainFromHost(host) {
+  getBaseDomainFromHost(host) {
     let result = host;
     try {
       result = Services.eTLD.getBaseDomainFromHost(host);
     } catch (e) {
       if (e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS ||
           e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
         // For these 2 expected errors, just take the host as the result.
         // - NS_ERROR_HOST_IS_IP_ADDRESS: the host is in ipv4/ipv6.
@@ -71,17 +71,17 @@ var SiteDataManager = {
     }
     return result;
   },
 
   _getOrInsertSite(host) {
     let site = this._sites.get(host);
     if (!site) {
       site = {
-        baseDomain: this._getBaseDomainFromHost(host),
+        baseDomain: this.getBaseDomainFromHost(host),
         cookies: [],
         persisted: false,
         quotaUsage: 0,
         lastAccessed: 0,
         principals: [],
         appCacheList: [],
       };
       this._sites.set(host, site);
@@ -217,20 +217,38 @@ var SiteDataManager = {
           usage += cache.usage;
         }
         usage += site.quotaUsage;
       }
       return usage;
     });
   },
 
-  getSites() {
+  /**
+   * Gets all sites that are currently storing site data.
+   *
+   * The list is not automatically up-to-date.
+   * You need to call SiteDataManager.updateSites() before you
+   * can use this method for the first time (and whenever you want
+   * to get an updated set of list.)
+   *
+   * @param {String} [optional] baseDomain - if specified, it will
+   *                            only return data for sites with
+   *                            the specified base domain.
+   *
+   * @returns a Promise that resolves with the list of all sites.
+   */
+  getSites(baseDomain) {
     return this._getQuotaUsagePromise.then(() => {
       let list = [];
       for (let [host, site] of this._sites) {
+        if (baseDomain && site.baseDomain != baseDomain) {
+          continue;
+        }
+
         let usage = site.quotaUsage;
         for (let cache of site.appCacheList) {
           usage += cache.usage;
         }
         list.push({
           baseDomain: site.baseDomain,
           cookies: site.cookies,
           host,
@@ -316,17 +334,28 @@ var SiteDataManager = {
       // Sites are grouped and removed by host so we unregister service workers by the same host as well
       if (sites.has(sw.principal.URI.host)) {
         promises.push(this._unregisterServiceWorker(sw));
       }
     }
     return Promise.all(promises);
   },
 
-  remove(hosts) {
+  /**
+   * Removes all site data for the specified list of hosts.
+   *
+   * @param {Array} a list of hosts to match for removal.
+   * @returns a Promise that resolves when data is removed and the site data
+   *          manager has been updated.
+   */
+  async remove(hosts) {
+    // Make sure we have up-to-date information.
+    await this._getQuotaUsage();
+    this._updateAppCache();
+
     let unknownHost = "";
     let targetSites = new Map();
     for (let host of hosts) {
       let site = this._sites.get(host);
       if (site) {
         this._removePermission(site);
         this._removeAppCache(site);
         this._removeCookies(site);
@@ -334,40 +363,51 @@ var SiteDataManager = {
         targetSites.set(host, site);
       } else {
         unknownHost = host;
         break;
       }
     }
 
     if (targetSites.size > 0) {
-      this._removeServiceWorkersForSites(targetSites)
-          .then(() => {
-            let promises = [];
-            for (let [, site] of targetSites) {
-              promises.push(this._removeQuotaUsage(site));
-            }
-            return Promise.all(promises);
-          })
-          .then(() => this.updateSites());
+      await this._removeServiceWorkersForSites(targetSites);
+      let promises = [];
+      for (let [, site] of targetSites) {
+        promises.push(this._removeQuotaUsage(site));
+      }
+      await Promise.all(promises);
     }
+
     if (unknownHost) {
       throw `SiteDataManager: removing unknown site of ${unknownHost}`;
     }
+
+    return this.updateSites();
   },
 
   /**
    * In the specified window, shows a prompt for removing
-   * all site data, warning the user that this may log them
-   * out of websites.
+   * all site data or the specified list of hosts, warning the
+   * user that this may log them out of websites.
    *
    * @param {mozIDOMWindowProxy} a parent DOM window to host the dialog.
+   * @param {Array} [optional] an array of host name strings that will be removed.
    * @returns a boolean whether the user confirmed the prompt.
    */
-  promptSiteDataRemoval(win) {
+  promptSiteDataRemoval(win, removals) {
+    if (removals) {
+      let args = {
+        hosts: removals,
+        allowed: false
+      };
+      let features = "centerscreen,chrome,modal,resizable=no";
+      win.openDialog("chrome://browser/content/preferences/siteDataRemoveSelected.xul", "", features, args);
+      return args.allowed;
+    }
+
     let brandName = gBrandBundle.GetStringFromName("brandShortName");
     let flags =
       Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
       Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
       Services.prompt.BUTTON_POS_0_DEFAULT;
     let title = gStringBundle.GetStringFromName("clearSiteDataPromptTitle");
     let text = gStringBundle.formatStringFromName("clearSiteDataPromptText", [brandName], 1);
     let btn0Label = gStringBundle.GetStringFromName("clearSiteDataNow");
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -77,16 +77,19 @@ with Files("ProcessHangMonitor.jsm"):
     BUG_COMPONENT = ("Core", "DOM: Content Processes")
 
 with Files("ReaderParent.jsm"):
     BUG_COMPONENT = ("Toolkit", "Reader Mode")
 
 with Files("Sanitizer.jsm"):
     BUG_COMPONENT = ("Firefox", "Preferences")
 
+with Files("SiteDataManager.jsm"):
+    BUG_COMPONENT = ("Firefox", "Preferences")
+
 with Files("SitePermissions.jsm"):
     BUG_COMPONENT = ("Firefox", "Site Identity and Permission Panels")
 
 with Files("OpenInTabsUtils.jsm"):
     BUG_COMPONENT = ("Firefox", "Tabbed Browser")
 
 with Files("ThemeVariableMap.jsm"):
     BUG_COMPONENT = ("Toolkit", "WebExtensions: Themes")
@@ -150,16 +153,17 @@ EXTRA_JS_MODULES += [
     'PingCentre.jsm',
     'PluginContent.jsm',
     'ProcessHangMonitor.jsm',
     'ReaderParent.jsm',
     'RecentWindow.jsm',
     'RemotePrompt.jsm',
     'Sanitizer.jsm',
     'SchedulePressure.jsm',
+    'SiteDataManager.jsm',
     'SitePermissions.jsm',
     'ThemeVariableMap.jsm',
     'TransientPrefs.jsm',
     'UpdateTopLevelContentWindowIDHelper.jsm',
     'webrtcUI.jsm',
     'ZoomUI.jsm',
 ]