Bug 1206229 - Inform the user that changes may require a page reload r?paolo draft
authorRicky Chien <ricky060709@gmail.com>
Thu, 11 Aug 2016 11:52:47 +0800
changeset 404373 6531b66c87482ea8012325c831de8000bd4e990b
parent 404131 24763f58772d45279a935790f732d80851924b46
child 529180 a7f5336e4829e676ce54bab98fc37f446f2db329
push id27205
push userbmo:rchien@mozilla.com
push dateTue, 23 Aug 2016 12:42:40 +0000
reviewerspaolo
bugs1206229
milestone51.0a1
Bug 1206229 - Inform the user that changes may require a page reload r?paolo MozReview-Commit-ID: 3tJRhxeDnUb
browser/base/content/browser.js
browser/base/content/test/general/browser_permissions.js
browser/components/controlcenter/content/panel.inc.xul
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/shared/controlcenter/panel.inc.css
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4468,16 +4468,18 @@ var XULBrowserWindow = {
       } else {
         this.reloadCommand.removeAttribute("disabled");
       }
 
       URLBarSetURI(aLocationURI);
 
       BookmarkingUI.onLocationChange();
 
+      gIdentityHandler.onLocationChange();
+
       SocialUI.updateState();
 
       UITour.onLocationChange(location);
 
       gTabletModePageCounter.inc();
 
       // Utility functions for disabling find
       var shouldDisableFind = function shouldDisableFind(aDocument) {
@@ -6546,16 +6548,21 @@ var gIdentityHandler = {
    */
   _sslStatus: null,
 
   /**
    * Bitmask provided by nsIWebProgressListener.onSecurityChange.
    */
   _state: 0,
 
+  /**
+   * Whether a permission is just removed from permission list.
+   */
+  _permissionJustRemoved: false,
+
   get _isBroken() {
     return this._state & Ci.nsIWebProgressListener.STATE_IS_BROKEN;
   },
 
   get _isSecure() {
     // If a <browser> is included within a chrome document, then this._state
     // will refer to the security state for the <browser> and not the top level
     // document. In this case, don't upgrade the security state in the UI
@@ -6672,16 +6679,24 @@ var gIdentityHandler = {
   get _identityIcon () {
     delete this._identityIcon;
     return this._identityIcon = document.getElementById("identity-icon");
   },
   get _permissionList () {
     delete this._permissionList;
     return this._permissionList = document.getElementById("identity-popup-permission-list");
   },
+  get _permissionEmptyHint() {
+    delete this._permissionEmptyHint;
+    return this._permissionEmptyHint = document.getElementById("identity-popup-permission-empty-hint");
+  },
+  get _permissionReloadHint () {
+    delete this._permissionReloadHint;
+    return this._permissionReloadHint = document.getElementById("identity-popup-permission-reload-hint");
+  },
   get _permissionAnchors () {
     delete this._permissionAnchors;
     let permissionAnchors = {};
     for (let anchor of document.getElementById("blocked-permissions-container").children) {
       permissionAnchors[anchor.getAttribute("data-permission-id")] = anchor;
     }
     return this._permissionAnchors = permissionAnchors;
   },
@@ -7291,16 +7306,35 @@ var gIdentityHandler = {
     let dt = event.dataTransfer;
     dt.setData("text/x-moz-url", urlString);
     dt.setData("text/uri-list", value);
     dt.setData("text/plain", value);
     dt.setData("text/html", htmlString);
     dt.setDragImage(this._identityIcon, 16, 16);
   },
 
+  onLocationChange: function () {
+    this._permissionJustRemoved = false;
+    this.updatePermissionHint();
+  },
+
+  updatePermissionHint: function () {
+    if (!this._permissionList.hasChildNodes() && !this._permissionJustRemoved) {
+      this._permissionEmptyHint.removeAttribute("hidden");
+    } else {
+      this._permissionEmptyHint.setAttribute("hidden", "true");
+    }
+
+    if (this._permissionJustRemoved) {
+      this._permissionReloadHint.removeAttribute("hidden");
+    } else {
+      this._permissionReloadHint.setAttribute("hidden", "true");
+    }
+  },
+
   updateSitePermissions: function () {
     while (this._permissionList.hasChildNodes())
       this._permissionList.removeChild(this._permissionList.lastChild);
 
     let uri = gBrowser.currentURI;
 
     let permissions = SitePermissions.getPermissionDetailsByURI(uri);
     if (this._sharingState) {
@@ -7326,16 +7360,18 @@ var gIdentityHandler = {
           }
         }
       }
     }
     for (let permission of permissions) {
       let item = this._createPermissionItem(permission);
       this._permissionList.appendChild(item);
     }
+
+    this.updatePermissionHint();
   },
 
   _createPermissionItem: function (aPermission) {
     let container = document.createElement("hbox");
     container.setAttribute("class", "identity-popup-permission-item");
     container.setAttribute("align", "center");
 
     let img = document.createElement("image");
@@ -7380,16 +7416,18 @@ var gIdentityHandler = {
                 SitePermissions.remove(uri, id);
             }
           }
         }
         let mm = gBrowser.selectedBrowser.messageManager;
         mm.sendAsyncMessage("webrtc:StopSharing", windowId);
       }
       SitePermissions.remove(gBrowser.currentURI, aPermission.id);
+      this._permissionJustRemoved = true;
+      this.updatePermissionHint();
     });
 
     container.appendChild(img);
     container.appendChild(nameLabel);
     container.appendChild(stateLabel);
     container.appendChild(button);
 
     return container;
--- a/browser/base/content/test/general/browser_permissions.js
+++ b/browser/base/content/test/general/browser_permissions.js
@@ -12,47 +12,68 @@ registerCleanupFunction(function() {
   SitePermissions.remove(gBrowser.currentURI, "camera");
   SitePermissions.remove(gBrowser.currentURI, "microphone");
 
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
+function* openIdentityPopup() {
+  let {gIdentityHandler} = gBrowser.ownerGlobal;
+  let promise = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
+  gIdentityHandler._identityBox.click();
+  return promise;
+}
+
+function* closeIdentityPopup() {
+  let {gIdentityHandler} = gBrowser.ownerGlobal;
+  let promise = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
+  gIdentityHandler._identityPopup.hidePopup();
+  return promise;
+}
+
 add_task(function* testMainViewVisible() {
   let {gIdentityHandler} = gBrowser.ownerGlobal;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
 
   let permissionsList = document.getElementById("identity-popup-permission-list");
   let emptyLabel = permissionsList.nextSibling;
 
-  gIdentityHandler._identityBox.click();
+  yield openIdentityPopup();
+
   ok(!is_hidden(emptyLabel), "List of permissions is empty");
-  gIdentityHandler._identityPopup.hidden = true;
+
+  yield closeIdentityPopup();
 
   SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.ALLOW);
 
-  gIdentityHandler._identityBox.click();
+  yield openIdentityPopup();
+
   ok(is_hidden(emptyLabel), "List of permissions is not empty");
 
   let labelText = SitePermissions.getPermissionLabel("camera");
   let labels = permissionsList.querySelectorAll(".identity-popup-permission-label");
   is(labels.length, 1, "One permission visible in main view");
   is(labels[0].textContent, labelText, "Correct value");
 
   let img = permissionsList.querySelector("image.identity-popup-permission-icon");
   ok(img, "There is an image for the permissions");
   ok(img.classList.contains("camera-icon"), "proper class is in image class");
 
+  yield closeIdentityPopup();
+
   SitePermissions.remove(gBrowser.currentURI, "camera");
 
-  gIdentityHandler._identityBox.click();
+  yield openIdentityPopup();
+
   ok(!is_hidden(emptyLabel), "List of permissions is empty");
-  gIdentityHandler._identityPopup.hidden = true;
+
+  yield closeIdentityPopup();
 });
 
 add_task(function* testIdentityIcon() {
   let {gIdentityHandler} = gBrowser.ownerGlobal;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
 
   SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
@@ -86,31 +107,77 @@ add_task(function* testCancelPermission(
   yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
 
   let permissionsList = document.getElementById("identity-popup-permission-list");
   let emptyLabel = permissionsList.nextSibling;
 
   SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
   SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.BLOCK);
 
-  gIdentityHandler._identityBox.click();
+  yield openIdentityPopup();
 
   ok(is_hidden(emptyLabel), "List of permissions is not empty");
 
   let cancelButtons = permissionsList
     .querySelectorAll(".identity-popup-permission-remove-button");
 
   cancelButtons[0].click();
   let labels = permissionsList.querySelectorAll(".identity-popup-permission-label");
   is(labels.length, 1, "One permission should be removed");
   cancelButtons[1].click();
   labels = permissionsList.querySelectorAll(".identity-popup-permission-label");
   is(labels.length, 0, "One permission should be removed");
 
-  gIdentityHandler._identityPopup.hidden = true;
+  yield closeIdentityPopup();
+});
+
+add_task(function* testPermissionHints() {
+  let {gIdentityHandler} = gBrowser.ownerGlobal;
+  let tab = gBrowser.selectedTab = gBrowser.addTab();
+  yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
+
+  let permissionsList = document.getElementById("identity-popup-permission-list");
+  let emptyHint = document.getElementById("identity-popup-permission-empty-hint");
+  let reloadHint = document.getElementById("identity-popup-permission-reload-hint");
+
+  yield openIdentityPopup();
+
+  ok(!is_hidden(emptyHint), "Empty hint is visible");
+  ok(is_hidden(reloadHint), "Reload hint is hidden");
+
+  yield closeIdentityPopup();
+
+  SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
+  SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.BLOCK);
+
+  yield openIdentityPopup();
+
+  ok(is_hidden(emptyHint), "Empty hint is hidden");
+  ok(is_hidden(reloadHint), "Reload hint is hidden");
+
+  let cancelButtons = permissionsList
+    .querySelectorAll(".identity-popup-permission-remove-button");
+  SitePermissions.remove(gBrowser.currentURI, "camera");
+
+  cancelButtons[0].click();
+  ok(is_hidden(emptyHint), "Empty hint is hidden");
+  ok(!is_hidden(reloadHint), "Reload hint is visible");
+
+  cancelButtons[1].click();
+  ok(is_hidden(emptyHint), "Empty hint is hidden");
+  ok(!is_hidden(reloadHint), "Reload hint is visible");
+
+  yield closeIdentityPopup();
+  yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
+  yield openIdentityPopup();
+
+  ok(!is_hidden(emptyHint), "Empty hint is visible after reloading");
+  ok(is_hidden(reloadHint), "Reload hint is hidden after reloading");
+
+  yield closeIdentityPopup();
 });
 
 add_task(function* testPermissionIcons() {
   let {gIdentityHandler} = gBrowser.ownerGlobal;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
 
   SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.ALLOW);
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -86,17 +86,18 @@
 
       <!-- Permissions Section -->
       <hbox class="identity-popup-section">
         <vbox id="identity-popup-permissions-content" flex="1">
           <label id="identity-popup-permissions-headline"
                  class="identity-popup-headline"
                  value="&identity.permissions;"/>
           <vbox id="identity-popup-permission-list"/>
-          <description>&identity.permissionsEmpty;</description>
+          <description id="identity-popup-permission-empty-hint">&identity.permissionsEmpty;</description>
+          <description id="identity-popup-permission-reload-hint">&identity.permissionsReloadHint;</description>
         </vbox>
       </hbox>
     </panelview>
 
     <!-- Security SubView -->
     <panelview id="identity-popup-securityView" flex="1">
       <vbox id="identity-popup-securityView-header">
         <label class="plain">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -726,16 +726,17 @@ you can use these alternative items. Oth
 
 <!ENTITY identity.removeCertException.label "Remove Exception">
 <!ENTITY identity.removeCertException.accesskey "R">
 
 <!ENTITY identity.moreInfoLinkText2 "More Information">
 
 <!ENTITY identity.permissions "Permissions">
 <!ENTITY identity.permissionsEmpty "You have not granted this site any special permissions.">
+<!ENTITY identity.permissionsReloadHint "You may need to reload the page for changes to apply.">
 
 <!-- Name for the tabs toolbar as spoken by screen readers.
      The word "toolbar" is appended automatically and should not be contained below! -->
 <!ENTITY tabsToolbar.label "Browser tabs">
 
 <!-- LOCALIZATION NOTE (syncTabsMenu3.label): This appears in the history menu -->
 <!ENTITY syncTabsMenu3.label     "Synced Tabs">
 
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -367,20 +367,16 @@ description#identity-popup-content-verif
 .identity-popup-permission-item {
   min-height: 24px;
 }
 
 #identity-popup-permission-list:not(:empty) {
   margin-top: 5px;
 }
 
-#identity-popup-permission-list:not(:empty) + description {
-  display: none;
-}
-
 .identity-popup-permission-icon {
   width: 16px;
   height: 16px;
 }
 
 .identity-popup-permission-icon.in-use {
   fill: rgb(224, 41, 29);
   animation: 1.5s ease in-use-blink infinite;