Bug 1203292 - Replace permissions dropdown with 'x' icon r?paolo draft
authorRicky Chien <ricky060709@gmail.com>
Thu, 19 May 2016 18:18:03 +0800
changeset 390580 7fe573c7b40629c8f1502c2a9c496d7f6af5a816
parent 390029 d224fc999cb6accb208af0a105f14433375e2e77
child 526020 5d5dcdc87ff92c9dc6a71f7ae74df690557df761
push id23693
push userbmo:rchien@mozilla.com
push dateThu, 21 Jul 2016 10:43:39 +0000
reviewerspaolo
bugs1203292
milestone50.0a1
Bug 1203292 - Replace permissions dropdown with 'x' icon r?paolo MozReview-Commit-ID: LmdRlgzeW1c
browser/base/content/browser.js
browser/base/content/test/general/browser_permissions.js
browser/themes/shared/controlcenter/panel.inc.css
browser/themes/shared/jar.inc.mn
browser/themes/shared/notification-icons.svg
browser/themes/shared/panel-icons.svg
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7258,60 +7258,48 @@ var gIdentityHandler = {
     let uri = gBrowser.currentURI;
 
     for (let permission of SitePermissions.getPermissionDetailsByURI(uri)) {
       let item = this._createPermissionItem(permission);
       this._permissionList.appendChild(item);
     }
   },
 
-  setPermission: function (aPermission, aState) {
-    if (aState == SitePermissions.getDefault(aPermission))
-      SitePermissions.remove(gBrowser.currentURI, aPermission);
-    else
-      SitePermissions.set(gBrowser.currentURI, aPermission, aState);
-  },
-
   _createPermissionItem: function (aPermission) {
-    let menulist = document.createElement("menulist");
-    let menupopup = document.createElement("menupopup");
-    for (let state of aPermission.availableStates) {
-      let menuitem = document.createElement("menuitem");
-      menuitem.setAttribute("value", state.id);
-      menuitem.setAttribute("label", state.label);
-      menupopup.appendChild(menuitem);
-    }
-    menulist.appendChild(menupopup);
-    menulist.setAttribute("value", aPermission.state);
-    menulist.setAttribute("oncommand", "gIdentityHandler.setPermission('" +
-                                       aPermission.id + "', this.value)");
-    menulist.setAttribute("id", "identity-popup-permission:" + aPermission.id);
-
-    let label = document.createElement("label");
-    label.setAttribute("flex", "1");
-    label.setAttribute("class", "identity-popup-permission-label");
-    label.setAttribute("control", menulist.getAttribute("id"));
-    label.textContent = aPermission.label;
+    let container = document.createElement("hbox");
+    let permLabel = document.createElement("label");
+    permLabel.setAttribute("flex", "1");
+    permLabel.setAttribute("class", "identity-popup-permission-label");
+    permLabel.textContent = SitePermissions.getPermissionLabel(aPermission.id);
+
+    let stateLabel = document.createElement("label");
+    stateLabel.setAttribute("class", "identity-popup-permission-label");
+    stateLabel.setAttribute("align", "right");
+    stateLabel.textContent = SitePermissions.getStateLabel(
+      aPermission.id, aPermission.state);
+
+    let button = document.createElement("button");
+    button.setAttribute("align", "right");
+    button.setAttribute("class", "identity-popup-permission-remove-button");
+    button.addEventListener("click", () => {
+      this._permissionList.removeChild(container);
+      SitePermissions.remove(gBrowser.currentURI, aPermission.id);
+    });
 
     let img = document.createElement("image");
     let isBlocked = (aPermission.state == SitePermissions.BLOCK) ? " blocked" : "";
     img.setAttribute("class",
       "identity-popup-permission-icon " + aPermission.id + "-icon" + isBlocked);
 
-    let container = document.createElement("hbox");
+    container.setAttribute("class", "identity-popup-permission-item");
     container.setAttribute("align", "center");
     container.appendChild(img);
-    container.appendChild(label);
-    container.appendChild(menulist);
-
-    // The menuitem text can be long and we don't want the dropdown
-    // to expand to the width of unselected labels.
-    // Need to set this attribute after it's appended, otherwise it gets
-    // overridden with sizetopopup="pref".
-    menulist.setAttribute("sizetopopup", "none");
+    container.appendChild(permLabel);
+    container.appendChild(stateLabel);
+    container.appendChild(button);
 
     return container;
   }
 };
 
 function getNotificationBox(aWindow) {
   var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
   if (foundBrowser)
--- a/browser/base/content/test/general/browser_permissions.js
+++ b/browser/base/content/test/general/browser_permissions.js
@@ -2,63 +2,55 @@
  * Test the Permissions section in the Control Center.
  */
 
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 const PERMISSIONS_PAGE = "http://example.com/browser/browser/base/content/test/general/permissions.html";
 var {SitePermissions} = Cu.import("resource:///modules/SitePermissions.jsm", {});
 
 registerCleanupFunction(function() {
-  SitePermissions.remove(gBrowser.currentURI, "install");
-  SitePermissions.remove(gBrowser.currentURI, "cookie");
   SitePermissions.remove(gBrowser.currentURI, "geo");
   SitePermissions.remove(gBrowser.currentURI, "camera");
   SitePermissions.remove(gBrowser.currentURI, "microphone");
 
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
 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;
+  let emptyDescription = permissionsList.nextSibling;
 
   gIdentityHandler._identityBox.click();
-  ok(!is_hidden(emptyLabel), "List of permissions is empty");
+  ok(!is_hidden(emptyDescription), "List of permissions is empty");
   gIdentityHandler._identityPopup.hidden = true;
 
-  gIdentityHandler.setPermission("install", SitePermissions.ALLOW);
+  SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.ALLOW);
 
   gIdentityHandler._identityBox.click();
-  ok(is_hidden(emptyLabel), "List of permissions is not empty");
+  ok(is_hidden(emptyDescription), "List of permissions is not empty");
 
-  let labelText = SitePermissions.getPermissionLabel("install");
+  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 menulists = permissionsList.querySelectorAll("menulist");
-  is(menulists.length, 1, "One permission visible in main view");
-  is(menulists[0].id, "identity-popup-permission:install", "Install permission visible");
-  is(menulists[0].value, "1", "Correct value on install menulist");
-  gIdentityHandler._identityPopup.hidden = true;
+  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");
 
-  let img = menulists[0].parentNode.querySelector("image");
-  ok(img, "There is an image for the permissions");
-  ok(img.classList.contains("install-icon"), "proper class is in image class");
-
-  gIdentityHandler.setPermission("install", SitePermissions.getDefault("install"));
+  SitePermissions.remove(gBrowser.currentURI, "camera");
 
   gIdentityHandler._identityBox.click();
-  ok(!is_hidden(emptyLabel), "List of permissions is empty");
+  ok(!is_hidden(emptyDescription), "List of permissions is empty");
   gIdentityHandler._identityPopup.hidden = true;
 });
 
 add_task(function* testIdentityIcon() {
   let {gIdentityHandler} = gBrowser.ownerGlobal;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   yield promiseTabLoadEvent(tab, PERMISSIONS_PAGE);
 
@@ -67,22 +59,29 @@ add_task(function* testIdentityIcon() {
   ok(gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
     "identity-box signals granted permissions");
 
   gIdentityHandler.setPermission("geo", SitePermissions.getDefault("geo"));
 
   ok(!gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
     "identity-box doesn't signal granted permissions");
 
-  gIdentityHandler.setPermission("camera", SitePermissions.BLOCK);
+  gIdentityHandler._identityBox.click();
+  ok(is_hidden(emptyDescription), "List of permissions is not empty");
 
   ok(!gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
     "identity-box doesn't signal granted permissions");
 
-  gIdentityHandler.setPermission("cookie", SitePermissions.SESSION);
+  let cancelButtons = permissionsList.querySelectorAll('button.cancel');
+  cancelButtons[0].click();
+  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");
 
   ok(gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
     "identity-box signals granted permissions");
 });
 
 add_task(function* testPermissionIcons() {
   let {gIdentityHandler} = gBrowser.ownerGlobal;
   let tab = gBrowser.selectedTab = gBrowser.addTab();
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -357,18 +357,18 @@ description#identity-popup-content-verif
 
 #identity-popup-permission-list {
   /* Offset the padding set on #identity-popup-permissions-content so that it
      shows up just below the section. The permission icons are 16px wide and
      should be right aligned with the section icon. */
   margin-inline-start: calc(-1em - 16px);
 }
 
-#identity-popup-permission-list menulist {
-  min-width: 60px;
+#identity-popup-permission-list .identity-popup-permission-item {
+  min-height: 20px;
 }
 
 #identity-popup-permission-list:not(:empty) {
   margin-top: 5px;
 }
 
 #identity-popup-permission-list:not(:empty) + description {
   display: none;
@@ -378,8 +378,47 @@ description#identity-popup-content-verif
   width: 16px;
   height: 16px;
 }
 
 .identity-popup-permission-label {
   margin-inline-start: 1em;
   word-wrap: break-word;
 }
+
+.identity-popup-permission-remove-button {
+  -moz-appearance: none;
+  margin: 0;
+  border: none;
+  border-radius: 50%;
+  min-width: 0;
+  padding: 2px;
+}
+
+.identity-popup-permission-remove-button > .button-box {
+  border: none;
+  padding: 0;
+}
+
+.identity-popup-permission-remove-button > .button-box > .button-icon {
+  margin: 0;
+  width: 16px;
+  height: 16px;
+  list-style-image: url(chrome://browser/skin/panel-icons.svg#cancel);
+  filter: url(chrome://browser/skin/filters.svg#fill);
+  fill: #999;
+}
+
+.identity-popup-permission-remove-button > .button-box > .button-text {
+  display: none;
+}
+
+.identity-popup-permission-remove-button:hover {
+  background-color: #999;
+}
+
+.identity-popup-permission-remove-button:hover > .button-box > .button-icon {
+  fill: #fff;
+}
+
+.identity-popup-permission-remove-button:hover:active {
+  background-color: #808080;
+}
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -67,16 +67,17 @@
   skin/classic/browser/identity-mixed-active-loaded.svg        (../shared/identity-block/identity-mixed-active-loaded.svg)
   skin/classic/browser/info.svg                                (../shared/info.svg)
   skin/classic/browser/notification-icons.svg                  (../shared/notification-icons.svg)
   skin/classic/browser/tracking-protection-16.svg              (../shared/identity-block/tracking-protection-16.svg)
   skin/classic/browser/tracking-protection-disabled-16.svg     (../shared/identity-block/tracking-protection-disabled-16.svg)
   skin/classic/browser/newtab/close.png                        (../shared/newtab/close.png)
   skin/classic/browser/newtab/controls.svg                     (../shared/newtab/controls.svg)
   skin/classic/browser/newtab/whimsycorn.png                   (../shared/newtab/whimsycorn.png)
+  skin/classic/browser/panel-icons.svg                         (../shared/panel-icons.svg)
   skin/classic/browser/preferences/in-content/favicon.ico      (../shared/incontentprefs/favicon.ico)
   skin/classic/browser/preferences/in-content/icons.svg        (../shared/incontentprefs/icons.svg)
   skin/classic/browser/preferences/in-content/search.css       (../shared/incontentprefs/search.css)
   skin/classic/browser/fxa/default-avatar.svg                  (../shared/fxa/default-avatar.svg)
   skin/classic/browser/fxa/logo.png                            (../shared/fxa/logo.png)
   skin/classic/browser/fxa/logo@2x.png                         (../shared/fxa/logo@2x.png)
   skin/classic/browser/fxa/sync-illustration.png               (../shared/fxa/sync-illustration.png)
   skin/classic/browser/fxa/sync-illustration@2x.png            (../shared/fxa/sync-illustration@2x.png)
--- a/browser/themes/shared/notification-icons.svg
+++ b/browser/themes/shared/notification-icons.svg
@@ -13,16 +13,22 @@
       display: none;
     }
     .blocked:target ~ #strikeout {
       display: block;
     }
     .blocked {
       clip-path: url(#clip);
     }
+    .button {
+      fill: #999;
+    }
+    .button-hover {
+      fill: #fff;
+    }
   </style>
 
   <defs>
     <path id="camera-icon" d="m 2,23 a 3,3 0 0 0 3,3 l 14,0 a 3,3 0 0 0 3,-3 l 0,-4 6,5.5 c 0.5,0.5 1,0.7 2,0.5 l 0,-18 c -1,-0.2 -1.5,0 -2,0.5 l -6,5.5 0,-4 a 3,3 0 0 0 -3,-3 l -14,0 a 3,3 0 0 0 -3,3 z" />
     <path id="desktop-notification-icon" d="m 2,20 a 4,4 0 0 0 4,4 l 13,0 7,7 0,-7 a 4,4 0 0 0 4,-4 l 0,-12 a 4,4 0 0 0 -4,-4 l -20,0 a 4,4 0 0 0 -4,4 z m 5,-2 a 1,1 0 1 1 0,-2 l 10,0 a 1,1 0 1 1 0,2 z m 0,-4 a 1,1 0 1 1 0,-2 l 14,0 a 1,1 0 1 1 0,2 z m 0,-4 a 1,1 0 1 1 0,-2 l 18,0 a 1,1 0 1 1 0,2 z" />
     <path id="geo-linux-icon" d="m 2,15.9 a 14,14 0 1 1 0,0.2 z m 4,2.1 a 10,10 0 0 0 8,8 l 0,-4 4,0 0,4 a 10,10 0 0 0 8,-8 l -4,0 0,-4 4,0 a 10,10 0 0 0 -8,-8 l 0,4 -4,0 0,-4 a 10,10 0 0 0 -8,8 l 4,0 0,4 z" />
     <path id="geo-linux-detailed-icon" d="m 2,15.9 a 14,14 0 1 1 0,0.2 z m 3,2.1 a 11,11 0 0 0 9,9 l 1,-5 2,0 1,5 a 11,11 0 0 0 9,-9 l -5,-1 0,-2 5,-1 a 11,11 0 0 0 -9,-9 l -1,5 -2,0 -1,-5 a 11,11 0 0 0 -9,9 l 5,1 0,2 z" />
     <path id="geo-osx-icon" d="m 0,16 16,0 0,16 12,-28 z" />
@@ -32,16 +38,17 @@
     <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="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="pointerLock-icon" d="m 8,24 6,-5 5,10 4,-2 -5,-10 7,-1 -17,-14 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="cancel-icon" d="m 21,12.7-3.32,3.32,3.3,3.3-1.67,1.67-3.3-3.3-3.27,3.27-1.67-1.67,3.27-3.27-3.37-3.37,1.67-1.67,3.37,3.37,3.32-3.32 z"/>
 
     <clipPath id="clip">
       <path d="m 0,0 0,31 31,-31 z m 6,32 26,0 0,-26 z"/>
     </clipPath>
   </defs>
 
   <use id="camera" xlink:href="#camera-icon" />
   <use id="camera-blocked" class="blocked" xlink:href="#camera-icon" />
@@ -64,11 +71,13 @@
   <use id="microphone-detailed" xlink:href="#microphone-detailed-icon" />
   <use id="plugin" xlink:href="#plugin-icon" />
   <use id="plugin-blocked" class="blocked" xlink:href="#plugin-icon" />
   <use id="pointerLock" xlink:href="#pointerLock-icon" />
   <use id="pointerLock-blocked" class="blocked" xlink:href="#pointerLock-icon" />
   <use id="popup" xlink:href="#popup-icon" />
   <use id="screen" xlink:href="#screen-icon" />
   <use id="screen-blocked" class="blocked" xlink:href="#screen-icon" />
+  <use id="cancel" class="button" xlink:href="#cancel-icon" />
+  <use id="cancel-hover" class="button-hover" xlink:href="#cancel-icon" />
 
   <path id="strikeout" d="m 2,28 2,2 26,-26 -2,-2 z"/>
 </svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/panel-icons.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg"
+     width="32" height="32" viewBox="0 0 32 32">
+  <path id="cancel" d="m 6,9.5 6.5,6.5 -6.5,6.5 3.5,3.5 6.5,-6.5 6.5,6.5 3.5,-3.5 -6.5,-6.5 6.5,-6.5 -3.5,-3.5 -6.5,6.5 -6.5,-6.5 z" />
+</svg>