Bug 1348252 - Disable buttons and display loading message in Site Data section while loading data, r=Gijs draft
authorFischer.json <fischer.json@gmail.com>
Wed, 05 Apr 2017 22:28:30 +0800
changeset 558883 bed4ac7fffe9e2c5b95803fcbc620d0ffedd3e0d
parent 556265 3854bcf837a729374b4d345910c274fed12cffe4
child 623290 00f81d4aa8b2f9281ca93a31812cc0d727cd6110
push id52977
push userbmo:fliu@mozilla.com
push dateSat, 08 Apr 2017 10:28:05 +0000
reviewersGijs
bugs1348252
milestone55.0a1
Bug 1348252 - Disable buttons and display loading message in Site Data section while loading data, r=Gijs MozReview-Commit-ID: 9EfG71hRoDe
browser/components/preferences/SiteDataManager.jsm
browser/components/preferences/in-content-old/advanced.js
browser/components/preferences/in-content-old/tests/browser_advanced_siteData.js
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/tests/browser_siteData.js
browser/locales/en-US/chrome/browser/preferences-old/preferences.properties
browser/locales/en-US/chrome/browser/preferences/preferences.properties
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/components/preferences/SiteDataManager.jsm
@@ -38,16 +38,18 @@ this.SiteDataManager = {
 
   _updateQuotaPromise: null,
 
   _updateDiskCachePromise: null,
 
   _quotaUsageRequests: null,
 
   updateSites() {
+    Services.obs.notifyObservers(null, "sitedatamanager:updating-sites", null);
+
     // Clear old data and requests first
     this._sites.clear();
     this._cancelQuotaUpdate();
 
     // Collect sites granted/rejected with the persistent-storage permission
     let perm = null;
     let status = null;
     let e = Services.perms.enumerator;
--- a/browser/components/preferences/in-content-old/advanced.js
+++ b/browser/components/preferences/in-content-old/advanced.js
@@ -50,29 +50,33 @@ var gAdvancedPane = {
       this.initSubmitHealthReport();
     }
     this.updateOnScreenKeyboardVisibility();
     this.updateCacheSizeInputField();
     this.updateActualCacheSize();
 
     if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
       Services.obs.addObserver(this, "sitedatamanager:sites-updated", false);
+      Services.obs.addObserver(this, "sitedatamanager:updating-sites", false);
       let unload = () => {
         window.removeEventListener("unload", unload);
         Services.obs.removeObserver(this, "sitedatamanager:sites-updated");
+        Services.obs.removeObserver(this, "sitedatamanager:updating-sites");
       };
       window.addEventListener("unload", unload);
       SiteDataManager.updateSites();
       setEventListener("clearSiteDataButton", "command",
                        gAdvancedPane.clearSiteData);
       setEventListener("siteDataSettings", "command",
                        gAdvancedPane.showSiteDataSettings);
 
       let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "storage-permissions";
       document.getElementById("siteDataLearnMoreLink").setAttribute("href", url);
+      let siteDataGroup = document.getElementById("siteDataGroup");
+      siteDataGroup.hidden = false;
     }
 
     setEventListener("layers.acceleration.disabled", "change",
                      gAdvancedPane.updateHardwareAcceleration);
     setEventListener("advancedPrefs", "select",
                      gAdvancedPane.tabSelectionChanged);
     if (AppConstants.MOZ_TELEMETRY_REPORTING) {
       setEventListener("submitHealthReportBox", "command",
@@ -353,26 +357,32 @@ var gAdvancedPane = {
   showConnections() {
     gSubDialog.open("chrome://browser/content/preferences/connection.xul");
   },
 
   showSiteDataSettings() {
     gSubDialog.open("chrome://browser/content/preferences/siteDataSettings.xul");
   },
 
-  updateTotalSiteDataSize() {
-    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");
-        siteDataGroup.hidden = false;
-      });
+  toggleSiteData(shouldShow) {
+    let clearButton = document.getElementById("clearSiteDataButton");
+    let settingsButton = document.getElementById("siteDataSettings");
+    clearButton.disabled = !shouldShow;
+    settingsButton.disabled = !shouldShow;
+  },
+
+  updateTotalDataSizeLabel(usage) {
+    let prefStrBundle = document.getElementById("bundlePreferences");
+    let totalSiteDataSizeLabel = document.getElementById("totalSiteDataSize");
+    if (usage < 0) {
+      totalSiteDataSizeLabel.textContent = prefStrBundle.getString("loadingSiteDataSize");
+    } else {
+      let size = DownloadUtils.convertByteUnits(usage);
+      totalSiteDataSizeLabel.textContent = prefStrBundle.getFormattedString("totalSiteDataSize", size);
+    }
   },
 
   // Retrieves the amount of space currently used by disk cache
   updateActualCacheSize() {
     var actualSizeLabel = document.getElementById("actualDiskCacheSize");
     var prefStrBundle = document.getElementById("bundlePreferences");
 
     // Needs to root the observer since cache service keeps only a weak reference.
@@ -786,21 +796,27 @@ var gAdvancedPane = {
   /**
    * Displays a dialog from which the user can manage his security devices.
    */
   showSecurityDevices() {
     gSubDialog.open("chrome://pippki/content/device_manager.xul");
   },
 
   observe(aSubject, aTopic, aData) {
-    if (AppConstants.MOZ_UPDATER) {
-      switch (aTopic) {
-        case "nsPref:changed":
-          this.updateReadPrefs();
-          break;
+    switch (aTopic) {
+      case "nsPref:changed":
+        this.updateReadPrefs();
+        break;
 
-        case "sitedatamanager:sites-updated":
-          this.updateTotalSiteDataSize();
-          break;
-      }
+      case "sitedatamanager:updating-sites":
+        // While updating, we want to disable this section and display loading message until updated
+        this.toggleSiteData(false);
+        this.updateTotalDataSizeLabel(-1);
+        break;
+
+      case "sitedatamanager:sites-updated":
+        this.toggleSiteData(true);
+        SiteDataManager.getTotalUsage()
+          .then(this.updateTotalDataSizeLabel.bind(this));
+        break;
     }
   },
 };
--- a/browser/components/preferences/in-content-old/tests/browser_advanced_siteData.js
+++ b/browser/components/preferences/in-content-old/tests/browser_advanced_siteData.js
@@ -10,16 +10,17 @@ Cu.import("resource://gre/modules/XPCOMU
 Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js");
 
 const TEST_HOST = "example.com";
 const TEST_ORIGIN = "http://" + TEST_HOST;
 const TEST_BASE_URL = TEST_ORIGIN + "/browser/browser/components/preferences/in-content-old/tests/";
 const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
 
 const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+const { DownloadUtils } = Cu.import("resource://gre/modules/DownloadUtils.jsm", {});
 const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {});
 const { OfflineAppCacheHelper } = Cu.import("resource:///modules/offlineAppCache.jsm", {});
 
 const mockOfflineAppCacheHelper = {
   clear: null,
 
   originalClear: null,
 
@@ -220,16 +221,59 @@ function assertSitesListed(doc, origins)
 
 registerCleanupFunction(function() {
   delete window.sinon;
   delete window.setImmediate;
   delete window.clearImmediate;
   mockOfflineAppCacheHelper.unregister();
 });
 
+// Test buttons are disabled and loading message shown while updating sites
+add_task(function *() {
+  yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
+  let updatedPromise = promiseSitesUpdated();
+  yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
+  yield updatedPromise;
+
+  let doc = gBrowser.selectedBrowser.contentDocument;
+  let clearBtn = doc.getElementById("clearSiteDataButton");
+  let settingsButton = doc.getElementById("siteDataSettings");
+  let prefStrBundle = doc.getElementById("bundlePreferences");
+  let totalSiteDataSizeLabel = doc.getElementById("totalSiteDataSize");
+  is(clearBtn.disabled, false, "Should enable clear button after sites updated");
+  is(settingsButton.disabled, false, "Should enable settings button after sites updated");
+  yield SiteDataManager.getTotalUsage()
+                       .then(usage => {
+                         let actual = totalSiteDataSizeLabel.textContent;
+                         let expected = prefStrBundle.getFormattedString(
+                           "totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
+                          is(actual, expected, "Should show the right total site data size");
+                       });
+
+  Services.obs.notifyObservers(null, "sitedatamanager:updating-sites", null);
+  is(clearBtn.disabled, true, "Should disable clear button while updating sites");
+  is(settingsButton.disabled, true, "Should disable settings button while updating sites");
+  let actual = totalSiteDataSizeLabel.textContent;
+  let expected = prefStrBundle.getString("loadingSiteDataSize");
+  is(actual, expected, "Should show the loading message while updating");
+
+  Services.obs.notifyObservers(null, "sitedatamanager:sites-updated", null);
+  is(clearBtn.disabled, false, "Should enable clear button after sites updated");
+  is(settingsButton.disabled, false, "Should enable settings button after sites updated");
+  yield SiteDataManager.getTotalUsage()
+                       .then(usage => {
+                         let actual = totalSiteDataSizeLabel.textContent;
+                         let expected = prefStrBundle.getFormattedString(
+                           "totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
+                          is(actual, expected, "Should show the right total site data size");
+                       });
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
 add_task(function* () {
   yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
   addPersistentStoragePerm(TEST_ORIGIN);
 
   yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_BASE_URL + "site_data_test.html");
   yield waitForEvent(gBrowser.selectedBrowser.contentWindow, "test-indexedDB-done");
   yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -262,19 +262,21 @@ var gPrivacyPane = {
               .style.height = bundlePrefs.getString("offlineAppsList.height");
       let offlineGroup = document.getElementById("offlineGroup");
       offlineGroup.hidden = false;
       offlineGroup.removeAttribute("data-hidden-from-search");
     }
 
     if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
       Services.obs.addObserver(this, "sitedatamanager:sites-updated", false);
+      Services.obs.addObserver(this, "sitedatamanager:updating-sites", false);
       let unload = () => {
         window.removeEventListener("unload", unload);
         Services.obs.removeObserver(this, "sitedatamanager:sites-updated");
+        Services.obs.removeObserver(this, "sitedatamanager:updating-sites");
       };
       window.addEventListener("unload", unload);
       SiteDataManager.updateSites();
       setEventListener("clearSiteDataButton", "command",
                        gPrivacyPane.clearSiteData);
       setEventListener("siteDataSettings", "command",
                        gPrivacyPane.showSiteDataSettings);
       let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "storage-permissions";
@@ -1175,24 +1177,32 @@ var gPrivacyPane = {
       removeButton.setAttribute("disabled", "true");
     }
   },
 
   showSiteDataSettings() {
     gSubDialog.open("chrome://browser/content/preferences/siteDataSettings.xul");
   },
 
-  updateTotalSiteDataSize() {
-    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);
-      });
+  toggleSiteData(shouldShow) {
+    let clearButton = document.getElementById("clearSiteDataButton");
+    let settingsButton = document.getElementById("siteDataSettings");
+    clearButton.disabled = !shouldShow;
+    settingsButton.disabled = !shouldShow;
+  },
+
+  updateTotalDataSizeLabel(usage) {
+    let prefStrBundle = document.getElementById("bundlePreferences");
+    let totalSiteDataSizeLabel = document.getElementById("totalSiteDataSize");
+    if (usage < 0) {
+      totalSiteDataSizeLabel.textContent = prefStrBundle.getString("loadingSiteDataSize");
+    } else {
+      let size = DownloadUtils.convertByteUnits(usage);
+      totalSiteDataSizeLabel.textContent = prefStrBundle.getFormattedString("totalSiteDataSize", size);
+    }
   },
 
   // Retrieves the amount of space currently used by disk cache
   updateActualCacheSize() {
     var actualSizeLabel = document.getElementById("actualDiskCacheSize");
     var prefStrBundle = document.getElementById("bundlePreferences");
 
     // Needs to root the observer since cache service keeps only a weak reference.
@@ -1442,14 +1452,22 @@ var gPrivacyPane = {
     list.removeChild(item);
     gPrivacyPane.offlineAppSelected();
     this.updateActualAppCacheSize();
   },
   // Methods for Offline Apps (AppCache) end
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
+      case "sitedatamanager:updating-sites":
+        // While updating, we want to disable this section and display loading message until updated
+        this.toggleSiteData(false);
+        this.updateTotalDataSizeLabel(-1);
+        break;
+
       case "sitedatamanager:sites-updated":
-        this.updateTotalSiteDataSize();
+        this.toggleSiteData(true);
+        SiteDataManager.getTotalUsage()
+          .then(this.updateTotalDataSizeLabel.bind(this));
         break;
     }
   },
 };
--- a/browser/components/preferences/in-content/tests/browser_siteData.js
+++ b/browser/components/preferences/in-content/tests/browser_siteData.js
@@ -10,16 +10,17 @@ Cu.import("resource://gre/modules/XPCOMU
 Services.scriptloader.loadSubScript("resource://testing-common/sinon-1.16.1.js");
 
 const TEST_HOST = "example.com";
 const TEST_ORIGIN = "http://" + TEST_HOST;
 const TEST_BASE_URL = TEST_ORIGIN + "/browser/browser/components/preferences/in-content/tests/";
 const REMOVE_DIALOG_URL = "chrome://browser/content/preferences/siteDataRemoveSelected.xul";
 
 const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+const { DownloadUtils } = Cu.import("resource://gre/modules/DownloadUtils.jsm", {});
 const { SiteDataManager } = Cu.import("resource:///modules/SiteDataManager.jsm", {});
 const { OfflineAppCacheHelper } = Cu.import("resource:///modules/offlineAppCache.jsm", {});
 
 const mockOfflineAppCacheHelper = {
   clear: null,
 
   originalClear: null,
 
@@ -161,16 +162,59 @@ function promiseCookiesCleared() {
 
 registerCleanupFunction(function() {
   delete window.sinon;
   delete window.setImmediate;
   delete window.clearImmediate;
   mockOfflineAppCacheHelper.unregister();
 });
 
+// Test buttons are disabled and loading message shown while updating sites
+add_task(function *() {
+  yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
+
+  let updatedPromise = promiseSiteDataManagerSitesUpdated();
+  yield openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
+  yield updatedPromise;
+  let doc = gBrowser.selectedBrowser.contentDocument;
+  let clearBtn = doc.getElementById("clearSiteDataButton");
+  let settingsButton = doc.getElementById("siteDataSettings");
+  let prefStrBundle = doc.getElementById("bundlePreferences");
+  let totalSiteDataSizeLabel = doc.getElementById("totalSiteDataSize");
+  is(clearBtn.disabled, false, "Should enable clear button after sites updated");
+  is(settingsButton.disabled, false, "Should enable settings button after sites updated");
+  yield SiteDataManager.getTotalUsage()
+                       .then(usage => {
+                         let actual = totalSiteDataSizeLabel.textContent;
+                         let expected = prefStrBundle.getFormattedString(
+                           "totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
+                          is(actual, expected, "Should show the right total site data size");
+                       });
+
+  Services.obs.notifyObservers(null, "sitedatamanager:updating-sites", null);
+  is(clearBtn.disabled, true, "Should disable clear button while updating sites");
+  is(settingsButton.disabled, true, "Should disable settings button while updating sites");
+  let actual = totalSiteDataSizeLabel.textContent;
+  let expected = prefStrBundle.getString("loadingSiteDataSize");
+  is(actual, expected, "Should show the loading message while updating");
+
+  Services.obs.notifyObservers(null, "sitedatamanager:sites-updated", null);
+  is(clearBtn.disabled, false, "Should enable clear button after sites updated");
+  is(settingsButton.disabled, false, "Should enable settings button after sites updated");
+  yield SiteDataManager.getTotalUsage()
+                       .then(usage => {
+                         let actual = totalSiteDataSizeLabel.textContent;
+                         let expected = prefStrBundle.getFormattedString(
+                           "totalSiteDataSize", DownloadUtils.convertByteUnits(usage));
+                          is(actual, expected, "Should show the right total site data size");
+                       });
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
 add_task(function* () {
   yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
   addPersistentStoragePerm(TEST_ORIGIN);
 
   yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_BASE_URL + "site_data_test.html");
   yield waitForEvent(gBrowser.selectedBrowser.contentWindow, "test-indexedDB-done");
   yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
--- a/browser/locales/en-US/chrome/browser/preferences-old/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences-old/preferences.properties
@@ -179,16 +179,17 @@ actualDiskCacheSizeCalculated=Calculating web content cache size…
 actualAppCacheSize=Your application cache is currently using %1$S %2$S of disk space
 
 ####Preferences::Advanced::Network
 #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
+loadingSiteDataSize=Calculating site data size…
 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
 # LOCALIZATION NOTE (removeAllSiteData, removeAllSiteDataShown):
 # removeAllSiteData and removeAllSiteDataShown are both used on the same one button,
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -179,16 +179,17 @@ actualDiskCacheSizeCalculated=Calculating web content cache size…
 actualAppCacheSize=Your application cache is currently using %1$S %2$S of disk space
 
 ####Preferences::Advanced::Network
 #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
+loadingSiteDataSize=Calculating site data size…
 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
 # LOCALIZATION NOTE (removeAllSiteData, removeAllSiteDataShown):
 # removeAllSiteData and removeAllSiteDataShown are both used on the same one button,