Bug 1348223 - Part 3 - Show and clear all site data in page info (not just cookies). r=florian draft
authorJohann Hofmann <jhofmann@mozilla.com>
Thu, 22 Mar 2018 17:26:52 +0100
changeset 778139 f88772b2275c97d30480a626e23a9d1875339b2b
parent 778138 2d48740a023f63a2ec7af06f4510ab9cbb91fc66
child 778140 8bc84de30f2168bd29def812f5a2550fb9c0e1a6
push id105397
push userjhofmann@mozilla.com
push dateThu, 05 Apr 2018 21:09:18 +0000
reviewersflorian
bugs1348223
milestone61.0a1
Bug 1348223 - Part 3 - Show and clear all site data in page info (not just cookies). r=florian This commit changes the way that the page info security section works to not only consider cookies when answering the question "Is this website storing information about me?". The associated button used to open the cookie manager. We would like to reduce the storage management UI surface (in the interest of having one great central location for managing storage), so that button was replaced with a simple "clear data" button that clears site data for all origins of the base domain of the site. Clearing for the entire range of that base domain is a trade off between (implicit) user privacy and the risk that the user accidentally deletes too much data. I prefer to choose increased privacy. MozReview-Commit-ID: BUgxJHBeFcQ
browser/base/content/pageinfo/pageInfo.xul
browser/base/content/pageinfo/security.js
browser/locales/en-US/chrome/browser/pageInfo.dtd
browser/locales/en-US/chrome/browser/pageInfo.properties
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -335,74 +335,71 @@
         <spacer flex="1"/>
         <!-- Cert button -->
         <hbox id="security-view-cert-box" pack="end">
           <button id="security-view-cert" label="&securityView.certView;"
                   accesskey="&securityView.accesskey;"
                   oncommand="security.viewCert();"/>
         </hbox>
       </groupbox>
-      
+
       <!-- Privacy & History section -->
       <groupbox id="security-privacy-groupbox" flex="1">
         <caption id="security-privacy" label="&securityView.privacy.header;" />
         <grid id="security-privacy-grid">
           <columns>
             <column flex="1"/>
             <column flex="1"/>
           </columns>
           <rows id="security-privacy-rows">
             <!-- History -->
             <row id="security-privacy-history-row">
               <label id="security-privacy-history-label"
                            control="security-privacy-history-value"
                            class="fieldLabel">&securityView.privacy.history;</label>
-              <textbox id="security-privacy-history-value"
-                       class="fieldValue"
-                       value="&securityView.unknown;"
-                       readonly="true"/>
+              <label id="security-privacy-history-value"
+                     class="fieldValue"
+                     value="&securityView.unknown;"/>
             </row>
-            <!-- Cookies -->
-            <row id="security-privacy-cookies-row">
-              <label id="security-privacy-cookies-label"
-                           control="security-privacy-cookies-value"
-                           class="fieldLabel">&securityView.privacy.cookies;</label>
-              <hbox id="security-privacy-cookies-box" align="center">
-                <textbox id="security-privacy-cookies-value"
-                         class="fieldValue"
-                         value="&securityView.unknown;"
-                         flex="1"
-                         readonly="true"/>
-                <button id="security-view-cookies"
-                        label="&securityView.privacy.viewCookies;"
-                        accesskey="&securityView.privacy.viewCookies.accessKey;"
-                        oncommand="security.viewCookies();"/>
+            <!-- Site Data & Cookies -->
+            <row id="security-privacy-sitedata-row">
+              <label id="security-privacy-sitedata-label"
+                           control="security-privacy-sitedata-value"
+                           class="fieldLabel">&securityView.privacy.siteData;</label>
+              <hbox id="security-privacy-sitedata-box" align="center">
+                <label id="security-privacy-sitedata-value"
+                       class="fieldValue"
+                       flex="1">&securityView.unknown;</label>
+                <button id="security-clear-sitedata"
+                        disabled="true"
+                        label="&securityView.privacy.clearSiteData;"
+                        accesskey="&securityView.privacy.clearSiteData.accessKey;"
+                        oncommand="security.clearSiteData();"/>
               </hbox>
             </row>
             <!-- Passwords -->
             <row id="security-privacy-passwords-row">
               <label id="security-privacy-passwords-label"
                             control="security-privacy-passwords-value"
                             class="fieldLabel">&securityView.privacy.passwords;</label>
               <hbox id="security-privacy-passwords-box" align="center">
-                <textbox id="security-privacy-passwords-value"
-                         class="fieldValue"
-                         value="&securityView.unknown;"
-                         flex="1"
-                         readonly="true"/>
+                <label id="security-privacy-passwords-value"
+                       class="fieldValue"
+                       value="&securityView.unknown;"
+                       flex="1"/>
                 <button id="security-view-password"
                         label="&securityView.privacy.viewPasswords;"
                         accesskey="&securityView.privacy.viewPasswords.accessKey;"
                         oncommand="security.viewPasswords();"/>
               </hbox>
             </row>
           </rows>
         </grid>
       </groupbox>
-      
+
       <!-- Technical Details section -->
       <groupbox id="security-technical-groupbox" flex="1">
         <caption id="security-technical" label="&securityView.technical.header;" />
         <vbox id="security-technical-box" flex="1">
           <label id="security-technical-shortform" class="fieldValue"/>
           <description id="security-technical-longform1" class="fieldLabel"/>
           <description id="security-technical-longform2" class="fieldLabel"/>
           <description id="security-technical-certificate-transparency" class="fieldLabel"/>
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -1,14 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm");
+ChromeUtils.import("resource:///modules/SiteDataManager.jsm");
+ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm");
 
 /* import-globals-from pageInfo.js */
 
 ChromeUtils.defineModuleGetter(this, "LoginHelper",
                                "resource://gre/modules/LoginHelper.jsm");
 ChromeUtils.defineModuleGetter(this, "PluralForm",
                                "resource://gre/modules/PluralForm.jsm");
 
@@ -128,36 +130,61 @@ var security = {
 
   // Find the secureBrowserUI object (if present)
   _getSecurityUI() {
     if (window.opener.gBrowser)
       return window.opener.gBrowser.securityUI;
     return null;
   },
 
-  /**
-   * Open the cookie manager window
-   */
-  viewCookies() {
-    var win = Services.wm.getMostRecentWindow("Browser:Cookies");
+  async _updateSiteDataInfo() {
+    // Save site data info for deleting.
+    this.siteData = await SiteDataManager.getSites(
+      SiteDataManager.getBaseDomainFromHost(this.uri.host));
 
-    var eTLD;
-    try {
-      eTLD = Services.eTLD.getBaseDomain(this.uri);
-    } catch (e) {
-      // getBaseDomain will fail if the host is an IP address or is empty
-      eTLD = this.uri.asciiHost;
+    let pageInfoBundle = document.getElementById("pageinfobundle");
+    let clearSiteDataButton = document.getElementById("security-clear-sitedata");
+    let siteDataLabel = document.getElementById("security-privacy-sitedata-value");
+
+    if (!this.siteData.length) {
+      let noStr = pageInfoBundle.getString("securitySiteDataNo");
+      siteDataLabel.textContent = noStr;
+      clearSiteDataButton.setAttribute("disabled", "true");
+      return;
     }
 
-    if (win) {
-      win.gCookiesWindow.setFilter(eTLD);
-      win.focus();
-    } else
-      window.openDialog("chrome://browser/content/preferences/cookies.xul",
-                        "Browser:Cookies", "", {filterString: eTLD});
+    let usageText;
+    let usage = this.siteData.reduce((acc, site) => acc + site.usage, 0);
+    if (usage > 0) {
+      let size = DownloadUtils.convertByteUnits(usage);
+      let hasCookies = this.siteData.some(site => site.cookies.length > 0);
+      if (hasCookies) {
+        usageText = pageInfoBundle.getFormattedString("securitySiteDataCookies", size);
+      } else {
+        usageText = pageInfoBundle.getFormattedString("securitySiteDataOnly", size);
+      }
+    } else {
+      // We're storing cookies, else the list would have been empty.
+      usageText = pageInfoBundle.getString("securitySiteDataCookiesOnly");
+    }
+
+    clearSiteDataButton.removeAttribute("disabled");
+    siteDataLabel.textContent = usageText;
+  },
+
+  /**
+   * Clear Site Data and Cookies
+   */
+  clearSiteData() {
+    if (this.siteData && this.siteData.length) {
+      let hosts = this.siteData.map(site => site.host);
+      if (SiteDataManager.promptSiteDataRemoval(window, hosts)) {
+        SiteDataManager.remove(hosts).then(() => this._updateSiteDataInfo());
+      }
+    }
   },
 
   /**
    * Open the login manager window
    */
   viewPasswords() {
     LoginHelper.openPasswordManager(window, this._getSecurityInfo().hostName);
   },
@@ -220,18 +247,23 @@ function securityOnLoad(uri, windowInfo)
     viewCert.collapsed = false;
   } else
     viewCert.collapsed = true;
 
   /* Set Privacy & History section text */
   var yesStr = pageInfoBundle.getString("yes");
   var noStr = pageInfoBundle.getString("no");
 
-  setText("security-privacy-cookies-value",
-          hostHasCookies(uri) ? yesStr : noStr);
+  // Only show quota usage data for websites, not internal sites.
+  if (uri.scheme == "http" || uri.scheme == "https") {
+    SiteDataManager.updateSites().then(() => security._updateSiteDataInfo());
+  } else {
+    document.getElementById("security-privacy-sitedata-row").hidden = true;
+  }
+
   setText("security-privacy-passwords-value",
           realmHasPasswords(uri) ? yesStr : noStr);
 
   var visitCount = previousVisitCount(info.hostName);
 
   let visitCountStr = visitCount > 0
     ? PluralForm.get(visitCount, pageInfoBundle.getString("securityVisitsNumber"))
         .replace("#1", visitCount.toLocaleString())
@@ -302,23 +334,16 @@ function viewCertHelper(parent, cert) {
   if (!cert)
     return;
 
   var cd = Cc[CERTIFICATEDIALOGS_CONTRACTID].getService(nsICertificateDialogs);
   cd.viewCert(parent, cert);
 }
 
 /**
- * Return true iff we have cookies for uri
- */
-function hostHasCookies(uri) {
-  return Services.cookies.countCookiesFromHost(uri.asciiHost) > 0;
-}
-
-/**
  * Return true iff realm (proto://host:port) (extracted from uri) has
  * saved passwords
  */
 function realmHasPasswords(uri) {
   return Services.logins.countLogins(uri.prePath, "", "") > 0;
 }
 
 /**
--- a/browser/locales/en-US/chrome/browser/pageInfo.dtd
+++ b/browser/locales/en-US/chrome/browser/pageInfo.dtd
@@ -61,18 +61,18 @@
 <!ENTITY  securityView.identity.header   "Website Identity">
 <!ENTITY  securityView.identity.owner    "Owner:">
 <!ENTITY  securityView.identity.domain   "Website:">
 <!ENTITY  securityView.identity.verifier "Verified by:">
 <!ENTITY  securityView.identity.validity "Expires on:">
 
 <!ENTITY  securityView.privacy.header                   "Privacy &amp; History">
 <!ENTITY  securityView.privacy.history                  "Have I visited this website prior to today?">
-<!ENTITY  securityView.privacy.cookies                  "Is this website storing information (cookies) on my computer?">
-<!ENTITY  securityView.privacy.viewCookies              "View Cookies">
-<!ENTITY  securityView.privacy.viewCookies.accessKey    "k">
+<!ENTITY  securityView.privacy.siteData                 "Is this website storing information on my computer?">
+<!ENTITY  securityView.privacy.clearSiteData            "Clear Cookies and Site Data">
+<!ENTITY  securityView.privacy.clearSiteData.accessKey  "C">
 <!ENTITY  securityView.privacy.passwords                "Have I saved any passwords for this website?">
 <!ENTITY  securityView.privacy.viewPasswords            "View Saved Passwords">
 <!ENTITY  securityView.privacy.viewPasswords.accessKey  "w">
 
 <!ENTITY  securityView.technical.header                 "Technical Details">
 
 <!ENTITY  helpButton.label                              "Help">
--- a/browser/locales/en-US/chrome/browser/pageInfo.properties
+++ b/browser/locales/en-US/chrome/browser/pageInfo.properties
@@ -48,16 +48,21 @@ securityNoOwner=This website does not su
 # LOCALIZATION NOTE (securityVisitsNumber):
 # Semi-colon list of plural forms.
 # See: https://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #1 is the number of visits and can be used in all plural forms as needed, e.g.
 # for '1': 'Yes, #1 time'
 securityVisitsNumber=Yes, once;Yes, #1 times
 securityNoVisits=No
 
-# LOCALIZATION NOTE: The next string is for the disk usage of the
-# database
-#   e.g. indexedDBUsage : "50.23 MB"
+# LOCALIZATION NOTE(securitySiteDataCookies,securitySiteDataOnly): This is for site data disk usage.
+#   It confirms that a website is indeed using this much space.
+#   e.g. Is this website storing site data? "Yes, 50.23 MB"
 #   %1$S = size (in bytes or megabytes, ...)
 #   %2$S = unit of measure (bytes, KB, MB, ...)
-indexedDBUsage=This website is using %1$S %2$S
+securitySiteDataCookies=Yes, cookies and %1$S %2$S of site data
+securitySiteDataOnly=Yes, %1$S %2$S of site data
+# LOCALIZATION NOTE(securitySiteDataCookiesOnly,securitySiteDataNo):
+# This is for site data and cookies usage. It answers the question "Is this website storing cookies and/or site data?"
+securitySiteDataCookiesOnly=Yes, cookies
+securitySiteDataNo=No
 
 permissions.useDefault=Use Default