Bug 1312372 - List sites using storage in Settings of Site Data, r=jaws
authorFischer.json <fischer.json@gmail.com>
Fri, 25 Nov 2016 17:35:25 +0800
changeset 450589 74f4edb0d09dbb7809eadaff9d321d61203bbaf1
parent 450588 111b09bfa3161cc7a752fe22cd62be173bfba8ad
child 450590 119f24606f99d82c6539763a778bb24f9df28037
child 450716 a04031da95dc1440246fe758af1ed77c0bf02ff4
child 458106 c2588c15e70f6865ea3bc6dd21e91f6a587ba3a7
push id38911
push userbmo:cku@mozilla.com
push dateSat, 17 Dec 2016 03:26:49 +0000
reviewersjaws
bugs1312372
milestone53.0a1
Bug 1312372 - List sites using storage in Settings of Site Data, r=jaws MozReview-Commit-ID: HqaiLW5R8Qv
browser/components/preferences/SiteDataManager.jsm
browser/components/preferences/in-content/advanced.js
browser/components/preferences/in-content/advanced.xul
browser/components/preferences/jar.mn
browser/components/preferences/siteDataSettings.css
browser/components/preferences/siteDataSettings.js
browser/components/preferences/siteDataSettings.xul
browser/components/preferences/siteListItem.xml
browser/locales/en-US/chrome/browser/preferences/advanced.dtd
browser/locales/en-US/chrome/browser/preferences/preferences.properties
browser/locales/en-US/chrome/browser/preferences/siteDataSettings.dtd
browser/locales/jar.mn
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/components/preferences/SiteDataManager.jsm
@@ -1,14 +1,15 @@
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper",
                                   "resource:///modules/offlineAppCache.jsm");
 
 this.EXPORTED_SYMBOLS = [
   "SiteDataManager"
 ];
 
@@ -172,10 +173,33 @@ this.SiteDataManager = {
     for (let site of this._sites.values()) {
       this._removePermission(site);
       this._removeQuotaUsage(site);
     }
     Services.cache2.clear();
     Services.cookies.removeAll();
     OfflineAppCacheHelper.clear();
     this.updateSites();
+  },
+
+  getSites() {
+    return Promise.all([this._updateQuotaPromise, this._updateDiskCachePromise])
+                  .then(() => {
+                    let list = [];
+                    for (let [origin, site] of this._sites) {
+                      let cache = null;
+                      let usage = site.quotaUsage;
+                      for (cache of site.appCacheList) {
+                        usage += cache.usage;
+                      }
+                      for (cache of site.diskCacheList) {
+                        usage += cache.dataSize;
+                      }
+                      list.push({
+                        usage,
+                        status: site.status,
+                        uri: NetUtil.newURI(origin)
+                      });
+                    }
+                    return list;
+                  });
   }
 };
--- a/browser/components/preferences/in-content/advanced.js
+++ b/browser/components/preferences/in-content/advanced.js
@@ -55,16 +55,18 @@ var gAdvancedPane = {
     this.updateActualCacheSize();
     this.updateActualAppCacheSize();
 
     if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
       Services.obs.addObserver(this, "sitedatamanager:sites-updated", false);
       SiteDataManager.updateSites();
       setEventListener("clearSiteDataButton", "command",
                        gAdvancedPane.clearSiteData);
+      setEventListener("siteDataSettings", "command",
+                       gAdvancedPane.showSiteDataSettings);
     }
 
     setEventListener("layers.acceleration.disabled", "change",
                      gAdvancedPane.updateHardwareAcceleration);
     setEventListener("advancedPrefs", "select",
                      gAdvancedPane.tabSelectionChanged);
     if (AppConstants.MOZ_TELEMETRY_REPORTING) {
       setEventListener("submitHealthReportBox", "command",
@@ -334,16 +336,20 @@ var gAdvancedPane = {
   /**
    * Displays a dialog in which proxy settings may be changed.
    */
   showConnections: function()
   {
     gSubDialog.open("chrome://browser/content/preferences/connection.xul");
   },
 
+  showSiteDataSettings: function() {
+    gSubDialog.open("chrome://browser/content/preferences/siteDataSettings.xul");
+  },
+
   updateTotalSiteDataSize: function() {
     SiteDataManager.getTotalUsage()
       .then(usage => {
         let size = DownloadUtils.convertByteUnits(usage);
         let prefStrBundle = document.getElementById("bundlePreferences");
         let totalSiteDataSizeLabel = document.getElementById("totalSiteDataSize");
         totalSiteDataSizeLabel.textContent = prefStrBundle.getFormattedString("totalSiteDataSize", size);
         let siteDataGroup = document.getElementById("siteDataGroup");
--- a/browser/components/preferences/in-content/advanced.xul
+++ b/browser/components/preferences/in-content/advanced.xul
@@ -333,16 +333,21 @@
       <groupbox id="siteDataGroup" hidden="true">
         <caption><label>&siteData.label;</label></caption>
 
         <hbox align="center">
           <label id="totalSiteDataSize" flex="1"></label>
           <button id="clearSiteDataButton" icon="clear"
                   label="&clearSiteData.label;" accesskey="&clearSiteData.accesskey;"/>
         </hbox>
+        <vbox align="end">
+          <button id="siteDataSettings"
+                  label="&siteDataSettings.label;"
+                  accesskey="&siteDataSettings.accesskey;"/>
+        </vbox>
       </groupbox>
     </tabpanel>
 
     <!-- Update -->
     <tabpanel id="updatePanel" orient="vertical">
 #ifdef MOZ_UPDATER
       <groupbox id="updateApp" align="start">
         <caption><label>&updateApp.label;</label></caption>
--- a/browser/components/preferences/jar.mn
+++ b/browser/components/preferences/jar.mn
@@ -22,10 +22,14 @@ browser.jar:
     content/browser/preferences/permissions.xul
     content/browser/preferences/containers.xul
     content/browser/preferences/containers.js
     content/browser/preferences/permissions.js
     content/browser/preferences/sanitize.xul
     content/browser/preferences/sanitize.js
     content/browser/preferences/selectBookmark.xul
     content/browser/preferences/selectBookmark.js
+    content/browser/preferences/siteDataSettings.xul
+    content/browser/preferences/siteDataSettings.js
+    content/browser/preferences/siteDataSettings.css
+    content/browser/preferences/siteListItem.xml
     content/browser/preferences/translation.xul
     content/browser/preferences/translation.js
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/siteDataSettings.css
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#sitesList {
+  min-height: 20em;
+}
+
+#sitesList > richlistitem {
+  -moz-binding: url("chrome://browser/content/preferences/siteListItem.xml#siteListItem");
+}
+
+.item-box {
+  padding: 5px 8px;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/siteDataSettings.js
@@ -0,0 +1,69 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+const { interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "SiteDataManager",
+                                  "resource:///modules/SiteDataManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
+                                  "resource://gre/modules/DownloadUtils.jsm");
+
+"use strict";
+
+let gSiteDataSettings = {
+
+  // Array of meatdata of sites. Each array element is object holding:
+  // - uri: uri of site; instance of nsIURI
+  // - status: persistent-storage permission status
+  // - usage: disk usage which site uses
+  _sites: null,
+
+  _list: null,
+
+  init() {
+    this._list = document.getElementById("sitesList");
+    SiteDataManager.getSites().then(sites => {
+      this._sites = sites;
+      this._sortSites(this._sites, "decending");
+      this._buildSitesList(this._sites);
+    });
+  },
+
+  /**
+   * Sort sites by usages
+   *
+   * @param sites {Array}
+   * @param order {String} indicate to sort in the "decending" or "ascending" order
+   */
+  _sortSites(sites, order) {
+    sites.sort((a, b) => {
+      if (order === "ascending") {
+        return a.usage - b.usage;
+      }
+      return b.usage - a.usage;
+    });
+  },
+
+  _buildSitesList(sites) {
+    // Clear old entries.
+    while (this._list.childNodes.length > 1) {
+      this._list.removeChild(this._list.lastChild);
+    }
+
+    let prefStrBundle = document.getElementById("bundlePreferences");
+    for (let data of sites) {
+      let statusStrId = data.status === Ci.nsIPermissionManager.ALLOW_ACTION ? "important" : "default";
+      let size = DownloadUtils.convertByteUnits(data.usage);
+      let item = document.createElement("richlistitem");
+      item.setAttribute("data-origin", data.uri.spec);
+      item.setAttribute("host", data.uri.host);
+      item.setAttribute("status", prefStrBundle.getString(statusStrId));
+      item.setAttribute("usage", prefStrBundle.getFormattedString("siteUsage", size));
+      this._list.appendChild(item);
+    }
+  }
+};
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/siteDataSettings.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/preferences/siteDataSettings.css" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/siteDataSettings.dtd" >
+
+<window id="SiteDataSettingsDialog" windowtype="Browser:SiteDataSettings"
+        class="windowDialog" title="&window.title;"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        style="width: 45em;"
+        onload="gSiteDataSettings.init();"
+        persist="screenX screenY width height">
+
+  <script src="chrome://browser/content/preferences/siteDataSettings.js"/>
+
+  <stringbundle id="bundlePreferences"
+                src="chrome://browser/locale/preferences/preferences.properties"/>
+
+  <vbox flex="1">
+    <description>&settings.description;</description>
+    <separator class="thin"/>
+
+    <richlistbox id="sitesList" orient="vertical" flex="1">
+      <listheader>
+        <treecol flex="4" width="50" label="&hostCol.label;"/>
+        <treecol flex="2" width="50" label="&statusCol.label;"/>
+        <treecol flex="1" width="50" label="&usageCol.label;"/>
+      </listheader>
+    </richlistbox>
+  </vbox>
+
+</window>
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/siteListItem.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<!-- import-globals-from siteDataSettings.js -->
+
+<!DOCTYPE overlay [
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  <!ENTITY % applicationsDTD SYSTEM "chrome://browser/locale/preferences/siteDataSettings.dtd">
+  %brandDTD;
+  %applicationsDTD;
+]>
+
+<bindings id="siteListItemBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+
+  <binding id="siteListItem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
+    <content>
+      <xul:hbox flex="1">
+        <xul:hbox flex="4" width="50" class="item-box" align="center" xbl:inherits="tooltiptext=host">
+          <xul:label flex="1" crop="end" xbl:inherits="value=host"/>
+        </xul:hbox>
+        <xul:hbox flex="2" width="50" class="item-box" align="center" xbl:inherits="tooltiptext=status">
+          <xul:label flex="1" crop="end" xbl:inherits="value=status"/>
+        </xul:hbox>
+        <xul:hbox flex="1" width="50" class="item-box" align="center" xbl:inherits="tooltiptext=usage">
+          <xul:label flex="1" crop="end" xbl:inherits="value=usage"/>
+        </xul:hbox>
+      </xul:hbox>
+    </content>
+  </binding>
+
+</bindings>
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -56,16 +56,18 @@
 <!ENTITY httpCache.label                 "Cached Web Content">
 
 <!ENTITY offlineStorage2.label           "Offline Web Content and User Data">
 
 <!--  Site Data section manages sites using Storage API and is under Network -->
 <!ENTITY siteData.label                  "Site Data">
 <!ENTITY clearSiteData.label             "Clear All Data">
 <!ENTITY clearSiteData.accesskey         "l">
+<!ENTITY siteDataSettings.label          "Settings…">
+<!ENTITY siteDataSettings.accesskey      "i">
 
 <!-- LOCALIZATION NOTE:
   The entities limitCacheSizeBefore.label and limitCacheSizeAfter.label appear on a single
   line in preferences as follows:
 
   &limitCacheSizeBefore.label [textbox for cache size in MB] &limitCacheSizeAfter.label;
 -->
 <!ENTITY limitCacheSizeBefore.label      "Limit cache to">
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -168,16 +168,19 @@ actualAppCacheSize=Your application cach
 #LOCALIZATION NOTE: The next string is for the total usage of site data.
 #   e.g., "The total usage is currently using 200 MB"
 #   %1$S = size
 #   %2$S = unit (MB, KB, etc.)
 totalSiteDataSize=Your stored site data is currently using %1$S %2$S of disk space
 clearSiteDataPromptTitle=Clear all cookies and site data
 clearSiteDataPromptText=Selecting ‘Clear Now’ will clear all cookies and site data stored by Firefox. This may sign you out of websites and remove offline web content.
 clearSiteDataNow=Clear Now
+important=Important
+default=Default
+siteUsage=%1$S %2$S
 
 syncUnlink.title=Do you want to unlink your device?
 syncUnlink.label=This device will no longer be associated with your Sync account. All of your personal data, both on this device and in your Sync account, will remain intact.
 syncUnlinkConfirm.label=Unlink
 
 # LOCALIZATION NOTE (featureEnableRequiresRestart, featureDisableRequiresRestart, restartTitle): %S = brandShortName
 featureEnableRequiresRestart=%S must restart to enable this feature.
 featureDisableRequiresRestart=%S must restart to disable this feature.
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/preferences/siteDataSettings.dtd
@@ -0,0 +1,9 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!ENTITY     window.title                  "Settings - Site Data">
+<!ENTITY     settings.description          "The following websites asked to store site data in your disk. You can specify which websites are allowed to store site data. Default site data is temporary and could be deleted automatically.">
+<!ENTITY     hostCol.label                 "Site">
+<!ENTITY     statusCol.label               "Status">
+<!ENTITY     usageCol.label                "Storage">
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -77,16 +77,17 @@
     locale/browser/preferences/preferences.properties (%chrome/browser/preferences/preferences.properties)
     locale/browser/preferences/containers.properties  (%chrome/browser/preferences/containers.properties)
     locale/browser/preferences/privacy.dtd            (%chrome/browser/preferences/privacy.dtd)
     locale/browser/preferences/security.dtd           (%chrome/browser/preferences/security.dtd)
     locale/browser/preferences/containers.dtd         (%chrome/browser/preferences/containers.dtd)
     locale/browser/preferences/sync.dtd               (%chrome/browser/preferences/sync.dtd)
     locale/browser/preferences/tabs.dtd               (%chrome/browser/preferences/tabs.dtd)
     locale/browser/preferences/search.dtd             (%chrome/browser/preferences/search.dtd)
+    locale/browser/preferences/siteDataSettings.dtd   (%chrome/browser/preferences/siteDataSettings.dtd)
     locale/browser/preferences/translation.dtd        (%chrome/browser/preferences/translation.dtd)
     locale/browser/syncBrand.dtd                (%chrome/browser/syncBrand.dtd)
     locale/browser/syncSetup.dtd                (%chrome/browser/syncSetup.dtd)
     locale/browser/syncSetup.properties         (%chrome/browser/syncSetup.properties)
     locale/browser/syncGenericChange.properties         (%chrome/browser/syncGenericChange.properties)
     locale/browser/syncKey.dtd                  (%chrome/browser/syncKey.dtd)
     locale/browser/syncQuota.dtd                (%chrome/browser/syncQuota.dtd)
     locale/browser/syncQuota.properties         (%chrome/browser/syncQuota.properties)