Bug 1309123 - Show persistent-storage permission request notification, r=florian draft
authorFischer.json <fischer.json@gmail.com>
Tue, 11 Apr 2017 12:07:29 +0800
changeset 560103 2cd8cabccff401af22a8311ef99fabdf4e108bf1
parent 560035 b5b5dbed1c409d96aa6b97f2036cd66312fc45ad
child 623608 197f500746934e8b0fb09dc6b3411ac1c74e97a8
push id53324
push userbmo:fliu@mozilla.com
push dateTue, 11 Apr 2017 04:18:52 +0000
reviewersflorian
bugs1309123
milestone55.0a1
Bug 1309123 - Show persistent-storage permission request notification, r=florian MozReview-Commit-ID: H3YAalEyWME
browser/base/content/browser.xul
browser/components/nsBrowserGlue.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
browser/locales/en-US/chrome/browser/sitePermissions.properties
browser/modules/PermissionUI.jsm
browser/modules/SitePermissions.jsm
browser/modules/test/browser/browser_PermissionUI_prompts.js
browser/modules/test/unit/test_SitePermissions.js
browser/themes/shared/notification-icons.inc.css
browser/themes/shared/notification-icons.svg
modules/libpref/init/all.js
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -714,16 +714,18 @@
                   <image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button"
                          tooltiptext="&urlbar.cameraBlocked.tooltip;"/>
                   <image data-permission-id="indexedDB" class="blocked-permission-icon indexedDB-icon" role="button"
                          tooltiptext="&urlbar.indexedDBBlocked.tooltip;"/>
                   <image data-permission-id="microphone" class="blocked-permission-icon microphone-icon" role="button"
                          tooltiptext="&urlbar.microphoneBlocked.tooltip;"/>
                   <image data-permission-id="screen" class="blocked-permission-icon screen-icon" role="button"
                          tooltiptext="&urlbar.screenBlocked.tooltip;"/>
+                  <image data-permission-id="persistent-storage" class="blocked-permission-icon persistent-storage-icon" role="button"
+                         tooltiptext="&urlbar.persistentStorageBlocked.tooltip;"/>
                 </box>
                 <box id="notification-popup-box"
                      hidden="true"
                      onmouseover="document.getElementById('identity-icon').classList.add('no-hover');"
                      onmouseout="document.getElementById('identity-icon').classList.remove('no-hover');"
                      align="center">
                   <image id="default-notification-icon" class="notification-anchor-icon" role="button"
                          tooltiptext="&urlbar.defaultNotificationAnchor.tooltip;"/>
@@ -748,16 +750,18 @@
                   <image id="servicesInstall-notification-icon" class="notification-anchor-icon service-icon" role="button"
                          tooltiptext="&urlbar.servicesNotificationAnchor.tooltip;"/>
                   <image id="translate-notification-icon" class="notification-anchor-icon translation-icon" role="button"
                          tooltiptext="&urlbar.translateNotificationAnchor.tooltip;"/>
                   <image id="translated-notification-icon" class="notification-anchor-icon translation-icon in-use" role="button"
                          tooltiptext="&urlbar.translatedNotificationAnchor.tooltip;"/>
                   <image id="eme-notification-icon" class="notification-anchor-icon drm-icon" role="button"
                          tooltiptext="&urlbar.emeNotificationAnchor.tooltip;"/>
+                  <image id="persistent-storage-notification-icon" class="notification-anchor-icon persistent-storage-icon" role="button"
+                         tooltiptext="&urlbar.persistentStorageNotificationAnchor.tooltip;"/>
                 </box>
                 <image id="connection-icon"/>
                 <hbox id="identity-icon-labels">
                   <label id="identity-icon-label" class="plain" flex="1"/>
                   <label id="identity-icon-country-label" class="plain"/>
                 </hbox>
               </box>
               <box id="urlbar-display-box" align="center">
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2310,16 +2310,21 @@ const ContentPermissionIntegration = {
   createPermissionPrompt(type, request) {
     switch (type) {
       case "geolocation": {
         return new PermissionUI.GeolocationPermissionPrompt(request);
       }
       case "desktop-notification": {
         return new PermissionUI.DesktopNotificationPermissionPrompt(request);
       }
+      case "persistent-storage": {
+        if (Services.prefs.getBoolPref("browser.storageManager.enabled")) {
+          return new PermissionUI.PersistentStoragePermissionPrompt(request);
+        }
+      }
     }
     return undefined;
   },
 };
 
 function ContentPermissionPrompt() {}
 
 ContentPermissionPrompt.prototype = {
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -208,38 +208,40 @@ These should match what Safari and other
 
 <!ENTITY urlbar.defaultNotificationAnchor.tooltip         "Open message panel">
 <!ENTITY urlbar.geolocationNotificationAnchor.tooltip     "Open location request panel">
 <!ENTITY urlbar.addonsNotificationAnchor.tooltip          "Open add-on installation message panel">
 <!ENTITY urlbar.indexedDBNotificationAnchor.tooltip       "Open offline storage message panel">
 <!ENTITY urlbar.passwordNotificationAnchor.tooltip        "Open save password message panel">
 <!ENTITY urlbar.pluginsNotificationAnchor.tooltip         "Manage plug-in use">
 <!ENTITY urlbar.webNotificationAnchor.tooltip             "Change whether you can receive notifications from the site">
+<!ENTITY urlbar.persistentStorageNotificationAnchor.tooltip     "Store data in Persistent Storage">
 
 <!ENTITY urlbar.webRTCShareDevicesNotificationAnchor.tooltip      "Manage sharing your camera and/or microphone with the site">
 <!ENTITY urlbar.webRTCShareMicrophoneNotificationAnchor.tooltip   "Manage sharing your microphone with the site">
 <!ENTITY urlbar.webRTCShareScreenNotificationAnchor.tooltip       "Manage sharing your windows or screen with the site">
 
 <!ENTITY urlbar.servicesNotificationAnchor.tooltip        "Open install message panel">
 <!ENTITY urlbar.translateNotificationAnchor.tooltip       "Translate this page">
 <!ENTITY urlbar.translatedNotificationAnchor.tooltip      "Manage page translation">
 <!ENTITY urlbar.emeNotificationAnchor.tooltip             "Manage use of DRM software">
 
 <!ENTITY urlbar.cameraBlocked.tooltip            "You have blocked your camera for this website.">
 <!ENTITY urlbar.microphoneBlocked.tooltip        "You have blocked your microphone for this website.">
 <!ENTITY urlbar.screenBlocked.tooltip            "You have blocked this website from sharing your screen.">
 <!ENTITY urlbar.geolocationBlocked.tooltip       "You have blocked location information for this website.">
 <!ENTITY urlbar.indexedDBBlocked.tooltip         "You have blocked data storage for this website.">
 <!ENTITY urlbar.webNotificationsBlocked.tooltip  "You have blocked notifications for this website.">
+<!ENTITY urlbar.persistentStorageBlocked.tooltip "You have blocked persistent storage for this website.">
 
 <!ENTITY urlbar.openHistoryPopup.tooltip                "Show history">
 
 <!ENTITY searchItem.title             "Search">
 
-<!-- Toolbar items --> 
+<!-- Toolbar items -->
 <!ENTITY homeButton.label             "Home">
 
 <!ENTITY bookmarksButton.label          "Bookmarks">
 <!ENTITY bookmarksCmd.commandkey "b">
 
 <!ENTITY bookmarksMenuButton.label          "Bookmarks">
 <!ENTITY bookmarksMenuButton.other.label "Other Bookmarks">
 <!ENTITY bookmarksMenuButton.mobile.label "Mobile Bookmarks">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -497,16 +497,24 @@ puAlertText=Click here for details
 geolocation.allowLocation=Allow Location Access
 geolocation.allowLocation.accesskey=A
 geolocation.dontAllowLocation=Don’t Allow
 geolocation.dontAllowLocation.accesskey=n
 geolocation.shareWithSite3=Will you allow %S to access your location?
 geolocation.shareWithFile3=Will you allow this local file to access your location?
 geolocation.remember=Remember this decision
 
+# Persistent storage UI
+persistentStorage.allow=Allow
+persistentStorage.allow.accesskey=A
+persistentStorage.dontAllow=Don’t Allow
+persistentStorage.dontAllow.accesskey=n
+persistentStorage.allowWithSite=Will you allow %S to store data in persistent storage?
+persistentStorage.remember=Remember this decision
+
 webNotifications.allow=Allow Notifications
 webNotifications.allow.accesskey=A
 webNotifications.notNow=Not Now
 webNotifications.notNow.accesskey=n
 webNotifications.never=Never Allow
 webNotifications.never.accesskey=v
 webNotifications.receiveFromSite2=Will you allow %S to send notifications?
 # LOCALIZATION NOTE (webNotifications.upgradeTitle): When using native notifications on OS X, the title may be truncated around 32 characters.
--- a/browser/locales/en-US/chrome/browser/sitePermissions.properties
+++ b/browser/locales/en-US/chrome/browser/sitePermissions.properties
@@ -31,8 +31,9 @@ permission.image.label = Load Images
 permission.camera.label = Use the Camera
 permission.microphone.label = Use the Microphone
 permission.screen.label = Share the Screen
 permission.install.label = Install Add-ons
 permission.popup.label = Open Pop-up Windows
 permission.geo.label = Access Your Location
 permission.indexedDB.label = Maintain Offline Storage
 permission.focus-tab-by-prompt.label = Switch to this Tab
+permission.persistent-storage.label = Store Data in Persistent Storage
--- a/browser/modules/PermissionUI.jsm
+++ b/browser/modules/PermissionUI.jsm
@@ -593,8 +593,80 @@ DesktopNotificationPermissionPrompt.prot
       });
     }
     return actions;
   },
 };
 
 PermissionUI.DesktopNotificationPermissionPrompt =
   DesktopNotificationPermissionPrompt;
+
+/**
+ * Creates a PermissionPrompt for a nsIContentPermissionRequest for
+ * the persistent-storage API.
+ *
+ * @param request (nsIContentPermissionRequest)
+ *        The request for a permission from content.
+ */
+function PersistentStoragePermissionPrompt(request) {
+  this.request = request;
+}
+
+PersistentStoragePermissionPrompt.prototype = {
+  __proto__: PermissionPromptForRequestPrototype,
+
+  get permissionKey() {
+    return "persistent-storage";
+  },
+
+  get popupOptions() {
+    let checkbox = {
+      // In PB mode, we don't want the "always remember" checkbox
+      show: !PrivateBrowsingUtils.isWindowPrivate(this.browser.ownerGlobal)
+    };
+    if (checkbox.show) {
+      checkbox.checked = true;
+      checkbox.label = gBrowserBundle.GetStringFromName("persistentStorage.remember");
+    }
+    let learnMoreURL =
+      Services.urlFormatter.formatURLPref("app.support.baseURL") + "storage-permissions";
+    return {
+      checkbox,
+      learnMoreURL
+    };
+  },
+
+  get notificationID() {
+    return "persistent-storage";
+  },
+
+  get anchorID() {
+    return "persistent-storage-notification-icon";
+  },
+
+  get message() {
+    let hostPort = "<>";
+    try {
+      hostPort = this.principal.URI.hostPort;
+    } catch (ex) {}
+    return gBrowserBundle.formatStringFromName(
+      "persistentStorage.allowWithSite", [hostPort], 1);
+  },
+
+  get promptActions() {
+    return [
+      {
+        label: gBrowserBundle.GetStringFromName("persistentStorage.allow"),
+        accessKey:
+          gBrowserBundle.GetStringFromName("persistentStorage.allow.accesskey"),
+        action: Ci.nsIPermissionManager.ALLOW_ACTION
+      },
+      {
+        label: gBrowserBundle.GetStringFromName("persistentStorage.dontAllow"),
+        accessKey:
+          gBrowserBundle.GetStringFromName("persistentStorage.dontAllow.accesskey"),
+        action: Ci.nsIPermissionManager.DENY_ACTION
+      }
+    ];
+  }
+};
+
+PermissionUI.PersistentStoragePermissionPrompt = PersistentStoragePermissionPrompt;
--- a/browser/modules/SitePermissions.jsm
+++ b/browser/modules/SitePermissions.jsm
@@ -609,13 +609,21 @@ var gPermissionObject = {
   },
 
   "indexedDB": {},
 
   "focus-tab-by-prompt": {
     exactHostMatch: true,
     states: [ SitePermissions.UNKNOWN, SitePermissions.ALLOW ],
   },
+  "persistent-storage": {
+    exactHostMatch: true
+  }
 };
 
+// Delete this entry while being pre-off
+// or the persistent-storage permission would appear in Page info's Permission section
+if (!Services.prefs.getBoolPref("browser.storageManager.enabled")) {
+  delete gPermissionObject["persistent-storage"];
+}
+
 XPCOMUtils.defineLazyPreferenceGetter(SitePermissions, "temporaryPermissionExpireTime",
                                       "privacy.temporary_permission_expire_time_ms", 3600 * 1000);
-
--- a/browser/modules/test/browser/browser_PermissionUI_prompts.js
+++ b/browser/modules/test/browser/browser_PermissionUI_prompts.js
@@ -15,16 +15,21 @@ add_task(function* test_geo_permission_p
   yield testPrompt(PermissionUI.GeolocationPermissionPrompt);
 });
 
 // Tests that DesktopNotificationPermissionPrompt works as expected
 add_task(function* test_desktop_notification_permission_prompt() {
   yield testPrompt(PermissionUI.DesktopNotificationPermissionPrompt);
 });
 
+// Tests that PersistentStoragePermissionPrompt works as expected
+add_task(function* test_persistent_storage_permission_prompt() {
+  yield testPrompt(PermissionUI.PersistentStoragePermissionPrompt);
+});
+
 function* testPrompt(Prompt) {
   yield BrowserTestUtils.withNewTab({
     gBrowser,
     url: "http://example.com",
   }, function*(browser) {
     let mockRequest = makeMockPermissionRequest(browser);
     let principal = mockRequest.principal;
     let TestPrompt = new Prompt(mockRequest);
--- a/browser/modules/test/unit/test_SitePermissions.js
+++ b/browser/modules/test/unit/test_SitePermissions.js
@@ -4,17 +4,17 @@
 "use strict";
 
 Components.utils.import("resource:///modules/SitePermissions.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 add_task(function* testPermissionsListing() {
   Assert.deepEqual(SitePermissions.listPermissions().sort(),
     ["camera", "cookie", "desktop-notification", "focus-tab-by-prompt", "geo", "image",
-     "indexedDB", "install", "microphone", "popup", "screen"],
+     "indexedDB", "install", "microphone", "persistent-storage", "popup", "screen"],
     "Correct list of all permissions");
 });
 
 add_task(function* testGetAllByURI() {
   // check that it returns an empty array on an invalid URI
   // like a file URI, which doesn't support site permissions
   let wrongURI = Services.io.newURI("file:///example.js")
   Assert.deepEqual(SitePermissions.getAllByURI(wrongURI), []);
@@ -67,17 +67,18 @@ add_task(function* testGetAvailableState
                    [ SitePermissions.ALLOW,
                      SitePermissions.BLOCK ]);
 });
 
 add_task(function* testExactHostMatch() {
   let uri = Services.io.newURI("https://example.com");
   let subUri = Services.io.newURI("https://test1.example.com");
 
-  let exactHostMatched = ["desktop-notification", "focus-tab-by-prompt", "camera", "microphone", "screen", "geo"];
+  let exactHostMatched = ["desktop-notification", "focus-tab-by-prompt", "camera",
+                          "microphone", "screen", "geo", "persistent-storage"];
   let nonExactHostMatched = ["image", "cookie", "popup", "install", "indexedDB"];
 
   let permissions = SitePermissions.listPermissions();
   for (let permission of permissions) {
     SitePermissions.set(uri, permission, SitePermissions.ALLOW);
 
     if (exactHostMatched.includes(permission)) {
       // Check that the sub-origin does not inherit the permission from its parent.
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -32,16 +32,25 @@
 }
 
 /* INDIVIDUAL NOTIFICATIONS */
 
 .focus-tab-by-prompt-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#focus-tab-by-prompt);
 }
 
+.popup-notification-icon[popupid="persistent-storage"],
+.persistent-storage-icon {
+  list-style-image: url(chrome://browser/skin/notification-icons.svg#persistent-storage);
+}
+
+.persistent-storage-icon.blocked-permission-icon {
+  list-style-image: url(chrome://browser/skin/notification-icons.svg#persistent-storage-blocked);
+}
+
 .popup-notification-icon[popupid="web-notifications"],
 .desktop-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification);
 }
 
 .desktop-notification-icon.blocked-permission-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification-blocked);
 }
--- a/browser/themes/shared/notification-icons.svg
+++ b/browser/themes/shared/notification-icons.svg
@@ -61,16 +61,17 @@
     <path id="geo-osx-icon" d="m 0,16 16,0 0,16 12,-28 z" />
     <path id="geo-windows-icon" d="m 2,14 0,4 2,0 a 12,12 0 0 0 10,10 l 0,2 4,0 0,-2 a 12,12 0 0 0 10,-10 l 2,0 0,-4 -2,0 a 12,12 0 0 0 -10,-10 l 0,-2 -4,0 0,2 a 12,12 0 0 0 -10,10 z m 4,1.9 a 10,10 0 1 1 0,0.2 z m 4,0 a 6,6 0 1 1 0,0.2 z" />
     <path id="geo-windows-detailed-icon" d="m 2,14.5 0,3 2,0.5 a 12,12 0 0 0 10,10 l 0.5,2 3,0 0.5,-2 a 12,12 0 0 0 10,-10 l 2,-0.5 0,-3 -2,-0.5 a 12,12 0 0 0 -10,-10 l -0.5,-2 -3,0 -0.5,2 a 12,12 0 0 0 -10,10 z m 4,1.4 a 10,10 0 1 1 0,0.2 z m 3,0 a 7,7 0 1 1 0,0.2 z" />
     <path id="indexedDB-icon" d="m 2,24 a 4,4 0 0 0 4,4 l 2,0 0,-4 -2,0 0,-16 20,0 0,16 -2,0 0,4 2,0 a 4,4 0 0 0 4,-4 l 0,-16 a 4,4 0 0 0 -4,-4 l -20,0 a 4,4 0 0 0 -4,4 z m 8,-2 6,7 6,-7 -4,0 0,-8 -4,0 0,8 z" />
     <path id="login-icon" d="m 2,26 0,4 6,0 0,-2 2,0 0,-2 1,0 0,-1 2,0 0,-3 2,0 2.5,-2.5 1.5,1.5 3,-3 a 8,8 0 1 0 -8,-8 l -3,3 2,2 z m 20,-18.1 a 2,2 0 1 1 0,0.2 z" />
     <path id="login-detailed-icon" d="m 1,27 0,3.5 a 0.5,0.5 0 0 0 0.5,0.5 l 5,0 a 0.5,0.5 0 0 0 0.5,-0.5 l 0,-1.5 1.5,0 a 0.5,0.5 0 0 0 0.5,-0.5 l 0,-1.5 1,0 a 0.5,0.5 0 0 0 0.5,-0.5 l 0,-1 1,0 a 0.5,0.5 0 0 0 0.5,-0.5 l 0,-2 2,0 2.5,-2.5 q 0.5,-0.5 1,0 l 1,1 c 0.5,0.5 1,0.5 1.5,-0.5 l 1,-2 a 9,9 0 1 0 -8,-8 l -2,1 c -1,0.5 -1,1 -0.5,1.5 l 1.5,1.5 q 0.5,0.5 0,1 z m 21,-19.1 a 2,2 0 1 1 0,0.2 z" />
     <path id="microphone-icon" d="m 8,14 0,4 a 8,8 0 0 0 6,7.7 l 0,2.3 -2,0 a 2,2 0 0 0 -2,2 l 12,0 a 2,2 0 0 0 -2,-2 l -2,0 0,-2.3 a 8,8 0 0 0 6,-7.7 l 0,-4 -2,0 0,4 a 6,6 0 0 1 -12,0 l 0,-4 z m 4,4 a 4,4 0 0 0 8,0 l 0,-12 a 4,4 0 0 0 -8,0 z" />
     <path id="microphone-detailed-icon" d="m 8,18 a 8,8 0 0 0 6,7.7 l 0,2.3 -1,0 a 3,2 0 0 0 -3,2 l 12,0 a 3,2 0 0 0 -3,-2 l -1,0 0,-2.3 a 8,8 0 0 0 6,-7.7 l 0,-4 a 1,1 0 0 0 -2,0 l 0,4 a 6,6 0 0 1 -12,0 l 0,-4 a 1,1 0 0 0 -2,0 z m 4,0 a 4,4 0 0 0 8,0 l 0,-12 a 4,4 0 0 0 -8,0 z" />
+    <path id="persistent-storage-icon" d="M26 21.1H6c-1.1 0-2 .9-2 2V27c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2v-3.9c0-1.1-.9-2-2-2zM24.1 27c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM25 3H7C5.3 3 4 4.4 4 6.2v13.3c.6-.3 1.3-.5 2-.5h20c.7 0 1.4.2 2 .5V6.2C28 4.4 26.7 3 25 3z"/>
     <path id="plugin-icon" d="m 2,26 a 2,2 0 0 0 2,2 l 24,0 a 2,2 0 0 0 2,-2 l 0,-16 a 2,2 0 0 0 -2,-2 l -24,0 a 2,2 0 0 0 -2,2 z m 2,-20 10,0 0,-2 a 2,2 0 0 0 -2,-2 l -6,0 a 2,2 0 0 0 -2,2 z m 14,0 10,0 0,-2 a 2,2 0 0 0 -2,-2 l -6,0 a 2,2 0 0 0 -2,2 z" />
     <path id="popup-icon" d="m 2,24 a 4,4 0 0 0 4,4 l 8,0 a 10,10 0 0 1 -2,-4 l -4,0 a 2,2 0 0 1 -2,-2 l 0,-12 18,0 0,2 a 10,10 0 0 1 4,2 l 0,-8 a 4,4 0 0 0 -4,-4 l -18,0 a 4,4 0 0 0 -4,4 z m 12,-2.1 a 8,8 0 1 1 0,0.2 m 10.7,-4.3 a 5,5 0 0 0 -6.9,6.9 z m -5.4,8.4 a 5,5 0 0 0 6.9,-6.9 z" />
     <path id="screen-icon" d="m 2,18 a 2,2 0 0 0 2,2 l 2,0 0,-6 a 4,4 0 0 1 4,-4 l 14,0 0,-6 a 2,2 0 0 0 -2,-2 l -18,0 a 2,2 0 0 0 -2,2 z m 6,10 a 2,2 0 0 0 2,2 l 18,0 a 2,2 0 0 0 2,-2 l 0,-14 a 2,2 0 0 0 -2,-2 l -18,0 a 2,2 0 0 0 -2,2 z" />
     <path id="update-icon" d="M 16,9 L 16,24 M 16,9 L 11,14 M 16,9 L 21,14" />
 
     <clipPath id="blocked-clipPath">
       <path d="m 0,0 0,31 31,-31 z m 6,32 26,0 0,-26 z"/>
     </clipPath>
@@ -106,16 +107,18 @@
   <use id="login" xlink:href="#login-icon" />
   <use id="login-highlighted" class="highlighted" xlink:href="#login-icon" />
   <use id="login-detailed" xlink:href="#login-detailed-icon" />
   <use id="microphone" xlink:href="#microphone-icon" />
   <use id="microphone-sharing" xlink:href="#microphone-icon"/>
   <use id="microphone-indicator" xlink:href="#microphone-icon"/>
   <use id="microphone-blocked" class="blocked" xlink:href="#microphone-icon" />
   <use id="microphone-detailed" xlink:href="#microphone-detailed-icon" />
+  <use id="persistent-storage" xlink:href="#persistent-storage-icon" />
+  <use id="persistent-storage-blocked" class="blocked" xlink:href="#persistent-storage-icon" />
   <use id="plugin" xlink:href="#plugin-icon" />
   <use id="plugin-blocked" class="blocked" xlink:href="#plugin-icon" />
   <use id="popup" xlink:href="#popup-icon" />
   <use id="screen" xlink:href="#screen-icon" />
   <use id="screen-sharing" xlink:href="#screen-icon"/>
   <use id="screen-indicator" xlink:href="#screen-icon"/>
   <use id="screen-blocked" class="blocked" xlink:href="#screen-icon" />
   <use id="update" xlink:href="#update-icon" />
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5641,27 +5641,32 @@ pref ("security.data_uri.inherit_securit
 
 // Disable Storage api in release builds.
 #if defined(NIGHTLY_BUILD) && !defined(MOZ_WIDGET_ANDROID)
 pref("dom.storageManager.enabled", true);
 #else
 pref("dom.storageManager.enabled", false);
 #endif
 
+// Enable the Storage management in about:preferences and persistent-storage permission request
+// To enable the DOM implementation, turn on "dom.storageManager.enabled"
+#ifdef NIGHTLY_BUILD
+pref("browser.storageManager.enabled", true);
+#else
+pref("browser.storageManager.enabled", false);
+#endif
+pref("browser.storageManager.pressureNotification.minIntervalMS", 1200000);
+pref("browser.storageManager.pressureNotification.usageThresholdGB", 5);
+
 // When a user cancels this number of authentication dialogs coming from
 // a single web page in a row, all following authentication dialogs will
 // be blocked (automatically canceled) for that page. The counter resets
 // when the page is reloaded. To turn this feature off, just set the limit to 0.
 pref("prompts.authentication_dialog_abuse_limit", 3);
 
-// Enable the Storage management in about:preferences and persistent-storage permission request
-// To enable the DOM implementation, turn on "dom.storageManager.enabled"
-pref("browser.storageManager.enabled", false);
-pref("browser.storageManager.pressureNotification.minIntervalMS", 1200000);
-pref("browser.storageManager.pressureNotification.usageThresholdGB", 5);
 pref("dom.IntersectionObserver.enabled", false);
 
 // Whether module scripts (<script type="module">) are enabled for content.
 pref("dom.moduleScripts.enabled", false);
 
 // Maximum number of setTimeout()/setInterval() callbacks to run in a single
 // event loop runnable. Minimum value of 1.
 pref("dom.timeout.max_consecutive_callbacks", 5);