Bug 885366 - Show granted and refused site permissions in site identity panel. r=jaws

This commit is contained in:
Dão Gottwald 2013-07-02 02:42:48 +02:00
Родитель 35a5731f5d
Коммит 257f6fc7fe
11 изменённых файлов: 304 добавлений и 18 удалений

Просмотреть файл

@ -390,7 +390,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
#identity-popup-content-box:not(.chromeUI) > #identity-popup-chromeLabel, #identity-popup-content-box:not(.chromeUI) > #identity-popup-chromeLabel,
#identity-popup-content-box.chromeUI > .identity-popup-label:not(#identity-popup-brandName):not(#identity-popup-chromeLabel), #identity-popup-content-box.chromeUI > .identity-popup-label:not(#identity-popup-brandName):not(#identity-popup-chromeLabel),
#identity-popup-content-box.chromeUI > .identity-popup-description, #identity-popup-content-box.chromeUI > .identity-popup-description,
#identity-popup-content-box.chromeUI > #identity-popup-button-container, #identity-popup.chromeUI > #identity-popup-button-container,
#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel , #identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel ,
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel , #identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
#identity-popup-content-box.unknownIdentity > #identity-popup-content-host , #identity-popup-content-box.unknownIdentity > #identity-popup-content-host ,

Просмотреть файл

@ -141,6 +141,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "gBrowserNewTabPreloader",
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm"); "resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SitePermissions",
"resource:///modules/SitePermissions.jsm");
let gInitialPages = [ let gInitialPages = [
"about:blank", "about:blank",
"about:newtab", "about:newtab",
@ -6483,6 +6486,14 @@ var gIdentityHandler = {
delete this._identityIcon; delete this._identityIcon;
return this._identityIcon = document.getElementById("page-proxy-favicon"); return this._identityIcon = document.getElementById("page-proxy-favicon");
}, },
get _permissionsContainer () {
delete this._permissionsContainer;
return this._permissionsContainer = document.getElementById("identity-popup-permissions");
},
get _permissionList () {
delete this._permissionList;
return this._permissionList = document.getElementById("identity-popup-permission-list");
},
/** /**
* Rebuild cache of the elements that may or may not exist depending * Rebuild cache of the elements that may or may not exist depending
@ -6493,10 +6504,14 @@ var gIdentityHandler = {
delete this._identityIconLabel; delete this._identityIconLabel;
delete this._identityIconCountryLabel; delete this._identityIconCountryLabel;
delete this._identityIcon; delete this._identityIcon;
delete this._permissionsContainer;
delete this._permissionList;
this._identityBox = document.getElementById("identity-box"); this._identityBox = document.getElementById("identity-box");
this._identityIconLabel = document.getElementById("identity-icon-label"); this._identityIconLabel = document.getElementById("identity-icon-label");
this._identityIconCountryLabel = document.getElementById("identity-icon-country-label"); this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
this._identityIcon = document.getElementById("page-proxy-favicon"); this._identityIcon = document.getElementById("page-proxy-favicon");
this._permissionsContainer = document.getElementById("identity-popup-permissions");
this._permissionList = document.getElementById("identity-popup-permission-list");
}, },
/** /**
@ -6506,6 +6521,7 @@ var gIdentityHandler = {
handleMoreInfoClick : function(event) { handleMoreInfoClick : function(event) {
displaySecurityInfo(); displaySecurityInfo();
event.stopPropagation(); event.stopPropagation();
this._identityPopup.hidePopup();
}, },
/** /**
@ -6647,6 +6663,7 @@ var gIdentityHandler = {
return; return;
} }
this._identityPopup.className = newMode;
this._identityBox.className = newMode; this._identityBox.className = newMode;
this.setIdentityMessages(newMode); this.setIdentityMessages(newMode);
@ -6789,10 +6806,6 @@ var gIdentityHandler = {
this._identityPopupContentVerif.textContent = verifier; this._identityPopupContentVerif.textContent = verifier;
}, },
hideIdentityPopup : function() {
this._identityPopup.hidePopup();
},
/** /**
* Click handler for the identity-box element in primary chrome. * Click handler for the identity-box element in primary chrome.
*/ */
@ -6820,6 +6833,8 @@ var gIdentityHandler = {
// Update the popup strings // Update the popup strings
this.setPopupMessages(this._identityBox.className); this.setPopupMessages(this._identityBox.className);
this.updateSitePermissions();
// Add the "open" attribute to the identity box for styling // Add the "open" attribute to the identity box for styling
this._identityBox.setAttribute("open", "true"); this._identityBox.setAttribute("open", "true");
var self = this; var self = this;
@ -6834,7 +6849,11 @@ var gIdentityHandler = {
onPopupShown : function(event) { onPopupShown : function(event) {
TelemetryStopwatch.finish("FX_IDENTITY_POPUP_OPEN_MS"); TelemetryStopwatch.finish("FX_IDENTITY_POPUP_OPEN_MS");
document.getElementById('identity-popup-more-info-button').focus(); document.getElementById('identity-popup-more-info-button').focus();
this._identityPopup.addEventListener("blur", this, true);
this._identityPopup.addEventListener("popuphidden", this);
}, },
onDragStart: function (event) { onDragStart: function (event) {
@ -6851,6 +6870,72 @@ var gIdentityHandler = {
dt.setData("text/plain", value); dt.setData("text/plain", value);
dt.setData("text/html", htmlString); dt.setData("text/html", htmlString);
dt.setDragImage(gProxyFavIcon, 16, 16); dt.setDragImage(gProxyFavIcon, 16, 16);
},
handleEvent: function (event) {
switch (event.type) {
case "blur":
// Focus hasn't moved yet, need to wait until after the blur event.
setTimeout(() => {
if (document.activeElement &&
document.activeElement.compareDocumentPosition(this._identityPopup) &
Node.DOCUMENT_POSITION_CONTAINS)
return;
this._identityPopup.hidePopup();
}, 0);
break;
case "popuphidden":
this._identityPopup.removeEventListener("blur", this, true);
this._identityPopup.removeEventListener("popuphidden", this);
break;
}
},
updateSitePermissions: function () {
while (this._permissionList.hasChildNodes())
this._permissionList.removeChild(this._permissionList.lastChild);
let uri = gBrowser.currentURI;
for (let permission of SitePermissions.listPermissions()) {
let state = SitePermissions.get(uri, permission);
if (state == SitePermissions.UNKNOWN)
continue;
let item = this._createPermissionItem(permission, state);
this._permissionList.appendChild(item);
}
this._permissionsContainer.hidden = !this._permissionList.hasChildNodes();
},
_createPermissionItem: function (aPermission, aState) {
let menulist = document.createElement("menulist");
let menupopup = document.createElement("menupopup");
for (let state of SitePermissions.getAvailableStates(aPermission)) {
let menuitem = document.createElement("menuitem");
menuitem.setAttribute("value", state);
menuitem.setAttribute("label", SitePermissions.getStateLabel(state));
menupopup.appendChild(menuitem);
}
menulist.appendChild(menupopup);
menulist.setAttribute("value", aState);
menulist.setAttribute("oncommand", "SitePermissions.set(gBrowser.currentURI, '" +
aPermission + "', this.value)");
menulist.setAttribute("id", "identity-popup-permission:" + aPermission);
let label = document.createElement("label");
label.setAttribute("flex", "1");
label.setAttribute("control", menulist.getAttribute("id"));
label.setAttribute("value", SitePermissions.getPermissionLabel(aPermission));
let container = document.createElement("hbox");
container.setAttribute("align", "center");
container.appendChild(label);
container.appendChild(menulist);
return container;
} }
}; };

Просмотреть файл

@ -293,7 +293,9 @@
hidden="true" hidden="true"
noautofocus="true" noautofocus="true"
consumeoutsideclicks="true" consumeoutsideclicks="true"
onpopupshown="gIdentityHandler.onPopupShown(event);" onpopupshown="if (event.target == this)
gIdentityHandler.onPopupShown(event);"
orient="vertical"
level="top"> level="top">
<hbox id="identity-popup-container" align="top"> <hbox id="identity-popup-container" align="top">
<image id="identity-popup-icon"/> <image id="identity-popup-icon"/>
@ -327,15 +329,21 @@
<description id="identity-popup-encryption-label" flex="1" <description id="identity-popup-encryption-label" flex="1"
class="identity-popup-description"/> class="identity-popup-description"/>
</hbox> </hbox>
<vbox id="identity-popup-permissions">
<separator class="thin"/>
<label id="identity-popup-permissions"
class="identity-popup-label header"
value="&identity.permissions;"/>
<vbox id="identity-popup-permission-list" class="indent"/>
</vbox>
</vbox>
</hbox>
<!-- Footer button to open security page info --> <!-- Footer button to open security page info -->
<hbox id="identity-popup-button-container" pack="end"> <hbox id="identity-popup-button-container" pack="end">
<button id="identity-popup-more-info-button" <button id="identity-popup-more-info-button"
label="&identity.moreInfoLinkText;" label="&identity.moreInfoLinkText;"
onblur="gIdentityHandler.hideIdentityPopup();"
oncommand="gIdentityHandler.handleMoreInfoClick(event);"/> oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
</hbox> </hbox>
</vbox>
</hbox>
</panel> </panel>
<panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top"> <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top">

Просмотреть файл

@ -624,6 +624,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY identity.moreInfoLinkText "More Information…"> <!ENTITY identity.moreInfoLinkText "More Information…">
<!ENTITY identity.permissions "Permissions">
<!-- Name for the tabs toolbar as spoken by screen readers. <!-- Name for the tabs toolbar as spoken by screen readers.
The word "toolbar" is appended automatically and should not be contained below! --> The word "toolbar" is appended automatically and should not be contained below! -->
<!ENTITY tabsToolbar.label "Browser tabs"> <!ENTITY tabsToolbar.label "Browser tabs">

Просмотреть файл

@ -0,0 +1,18 @@
# 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/.
allow = Allow
allowForSession = Allow for Session
block = Block
permission.cookie.label = Set Cookies
permission.desktop-notification.label = Show Notifications
permission.image.label = Load Images
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.fullscreen.label = Enter Fullscreen
permission.pointerLock.label = Hide the Mouse Pointer

Просмотреть файл

@ -63,6 +63,7 @@
locale/browser/sanitize.dtd (%chrome/browser/sanitize.dtd) locale/browser/sanitize.dtd (%chrome/browser/sanitize.dtd)
locale/browser/search.properties (%chrome/browser/search.properties) locale/browser/search.properties (%chrome/browser/search.properties)
locale/browser/searchbar.dtd (%chrome/browser/searchbar.dtd) locale/browser/searchbar.dtd (%chrome/browser/searchbar.dtd)
locale/browser/sitePermissions.properties (%chrome/browser/sitePermissions.properties)
locale/browser/engineManager.dtd (%chrome/browser/engineManager.dtd) locale/browser/engineManager.dtd (%chrome/browser/engineManager.dtd)
locale/browser/engineManager.properties (%chrome/browser/engineManager.properties) locale/browser/engineManager.properties (%chrome/browser/engineManager.properties)
locale/browser/setDesktopBackground.dtd (%chrome/browser/setDesktopBackground.dtd) locale/browser/setDesktopBackground.dtd (%chrome/browser/setDesktopBackground.dtd)

Просмотреть файл

@ -17,6 +17,7 @@ EXTRA_JS_MODULES = \
NetworkPrioritizer.jsm \ NetworkPrioritizer.jsm \
offlineAppCache.jsm \ offlineAppCache.jsm \
SignInToWebsite.jsm \ SignInToWebsite.jsm \
SitePermissions.jsm \
webappsUI.jsm \ webappsUI.jsm \
webrtcUI.jsm \ webrtcUI.jsm \
Social.jsm \ Social.jsm \

Просмотреть файл

@ -0,0 +1,136 @@
/* 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/. */
this.EXPORTED_SYMBOLS = [ "SitePermissions" ];
Components.utils.import("resource://gre/modules/Services.jsm");
let gStringBundle =
Services.strings.createBundle("chrome://browser/locale/sitePermissions.properties");
this.SitePermissions = {
UNKNOWN: Services.perms.UNKNOWN_ACTION,
ALLOW: Services.perms.ALLOW_ACTION,
BLOCK: Services.perms.DENY_ACTION,
SESSION: Components.interfaces.nsICookiePermission.ACCESS_SESSION,
/* Checks whether a UI for managing permissions should be exposed for a given
* URI. This excludes file URIs, for instance, as they don't have a host,
* even though nsIPermissionManager can still handle them.
*/
isSupportedURI: function (aURI) {
return aURI.schemeIs("http") || aURI.schemeIs("https");
},
/* Returns an array of all permission IDs.
*/
listPermissions: function () {
return Object.keys(gPermissionObject);
},
/* Returns an array of permission states to be exposed to the user for a
* permission with the given ID.
*/
getAvailableStates: function (aPermissionID) {
return gPermissionObject[aPermissionID].states ||
[ SitePermissions.ALLOW, SitePermissions.BLOCK ];
},
/* Returns the state of a perticular permission for a given URI.
*/
get: function (aURI, aPermissionID) {
if (!this.isSupportedURI(aURI))
return this.UNKNOWN;
let state;
if (gPermissionObject[aPermissionID].exactHostMatch)
state = Services.perms.testExactPermission(aURI, aPermissionID);
else
state = Services.perms.testPermission(aURI, aPermissionID);
return state;
},
/* Sets the state of a perticular permission for a given URI.
*/
set: function (aURI, aPermissionID, aState) {
if (!this.isSupportedURI(aURI))
return;
Services.perms.add(aURI, aPermissionID, aState);
if (gPermissionObject[aPermissionID].onSet)
gPermissionObject[aPermissionID].onSet(aURI, aState);
},
/* Returns the localized label for the permission with the given ID, to be
* used in a UI for managing permissions.
*/
getPermissionLabel: function (aPermissionID) {
return gStringBundle.GetStringFromName("permission." + aPermissionID + ".label");
},
/* Returns the localized label for the given permission state, to be used in
* a UI for managing permissions.
*/
getStateLabel: function (aState) {
switch (aState) {
case this.ALLOW:
return gStringBundle.GetStringFromName("allow");
case this.SESSION:
return gStringBundle.GetStringFromName("allowForSession");
case this.BLOCK:
return gStringBundle.GetStringFromName("block");
default:
throw new Error("unknown permission state");
}
}
};
let gPermissionObject = {
/* Holds permission ID => options pairs.
*
* Supported options:
*
* - exactHostMatch
* Allows sub domains to have their own permissions.
* Defaults to false.
*
* - onSet
* Called when a permission state changes.
*
* - states
* Array of permission states to be exposed to the user.
* Defaults to ALLOW and BLOCK.
*/
"image": {},
"cookie": {
states: [ SitePermissions.ALLOW, SitePermissions.SESSION, SitePermissions.BLOCK ]
},
"desktop-notification": {},
"popup": {},
"install": {},
"geo": {
exactHostMatch: true
},
"indexedDB": {
onSet: function (aURI, aState) {
if (aState == SitePermissions.ALLOW || aState == SitePermissions.BLOCK)
Services.perms.remove(aURI.host, "indexedDB-unlimited");
}
},
"fullscreen": {},
"pointerLock": {
exactHostMatch: true
}
};

Просмотреть файл

@ -1117,9 +1117,19 @@ toolbar[iconsize="small"] #webrtc-status-button {
list-style-image: url("chrome://browser/skin/Secure.png"); list-style-image: url("chrome://browser/skin/Secure.png");
} }
/* Identity popup bounding box */ #identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#identity-popup-container { #identity-popup-container {
min-width: 280px; min-width: 280px;
padding: 10px;
}
#identity-popup-button-container {
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
padding: 10px;
margin-top: 5px;
} }
/* Notification popup */ /* Notification popup */

Просмотреть файл

@ -3012,6 +3012,20 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
} }
} }
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#identity-popup-container {
padding: 16px;
}
#identity-popup-button-container {
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
padding: 16px;
margin-top: 5px;
}
#notification-popup-box { #notification-popup-box {
position: relative; position: relative;
background-color: #fff; background-color: #fff;

Просмотреть файл

@ -2361,6 +2361,21 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
-moz-margin-end: 0; -moz-margin-end: 0;
} }
#identity-popup > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#identity-popup-container {
min-width: 280px;
padding: 10px;
}
#identity-popup-button-container {
background: linear-gradient(to bottom, rgba(0,0,0,0.04) 60%, transparent);
padding: 10px;
margin-top: 5px;
}
.popup-notification-icon { .popup-notification-icon {
width: 64px; width: 64px;
height: 64px; height: 64px;
@ -2578,10 +2593,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
margin: 0px; margin: 0px;
} }
#identity-popup-container {
min-width: 280px;
}
/* Bookmarks roots menu-items */ /* Bookmarks roots menu-items */
#appmenu_subscribeToPage:not([disabled]), #appmenu_subscribeToPage:not([disabled]),
#appmenu_subscribeToPageMenu, #appmenu_subscribeToPageMenu,