Bug 1206229 - Inform the user that changes may require a page reload r=Paolo
authorRicky Chien <ricky060709@gmail.com>
Thu, 11 Aug 2016 11:52:47 +0800
changeset 311067 d1380b51b174d6c16db0995551dc5024fddf986f
parent 311066 bbe3a00528ed2b0731854fafc25963f08be9218c
child 311068 79c7fe81fe5a856ea321e1046d4bd2371eccad91
push id81034
push userryanvm@gmail.com
push dateThu, 25 Aug 2016 12:27:32 +0000
treeherdermozilla-inbound@87049fc2117f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersPaolo
bugs1206229
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
@@ -4456,16 +4456,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) {
@@ -6534,16 +6536,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
@@ -6660,16 +6667,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;
   },
@@ -7279,16 +7294,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) {
@@ -7314,16 +7348,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");
@@ -7368,16 +7404,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
@@ -725,16 +725,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;