--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1384,18 +1384,16 @@ pref("image.mem.max_decoded_image_kb", 2
pref("social.sidebar.unload_timeout_ms", 10000);
// Activation from inside of share panel is possible if activationPanelEnabled
// is true. Pref'd off for release while usage testing is done through beta.
pref("social.share.activationPanelEnabled", true);
pref("social.shareDirectory", "https://activations.cdn.mozilla.net/sharePanel.html");
-pref("dom.identity.enabled", false);
-
// Block insecure active content on https pages
pref("security.mixed_content.block_active_content", true);
// Show degraded UI for http pages with password fields.
// Only for Nightly and Dev Edition for not, not for beta or release.
#ifndef RELEASE_BUILD
pref("security.insecure_password.ui.enabled", true);
#else
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -732,41 +732,32 @@ html|*#fullscreen-exit-button {
.notification-anchor-icon {
-moz-user-focus: normal;
}
.notification-anchor-icon:not([showing]) {
display: none;
}
-#notification-popup .text-link.custom-link {
- -moz-binding: url("chrome://global/content/bindings/text.xml#text-label");
- text-decoration: none;
-}
-
#invalid-form-popup > description {
max-width: 280px;
}
.form-validation-anchor {
/* should occupy space but not be visible */
opacity: 0;
visibility: hidden;
pointer-events: none;
-moz-stack-sizing: ignore;
}
#addon-progress-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
}
-#identity-request-notification {
- -moz-binding: url("chrome://browser/content/urlbarBindings.xml#identity-request-notification");
-}
-
#click-to-play-plugins-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
}
#login-fill-notification {
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#login-fill-notification");
}
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -665,20 +665,16 @@
ontextentered="this.handleCommand(param);"
ontextreverted="return this.handleRevert();"
pageproxystate="invalid"
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
onblur="setTimeout(() => { document.getElementById('identity-box').style.MozUserFocus = ''; }, 0);">
<box id="notification-popup-box" hidden="true" align="center">
<image id="default-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.defaultNotificationAnchor.label;"/>
- <!-- NB: the identity-notification-icon is used for persona-based auth and preffed
- off by default. It hasn't been updated for some time and liable to being
- removed.-->
- <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.geolocationNotificationAnchor.label;"/>
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.addonsNotificationAnchor.label;"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.indexedDBNotificationAnchor.label;"/>
<image id="login-fill-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.loginFillNotificationAnchor.label;"/>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1734,270 +1734,16 @@ file, You can obtain one at http://mozil
<method name="onDownloadEnded">
<body><![CDATA[
this.updateProgress();
]]></body>
</method>
</implementation>
</binding>
- <binding id="identity-request-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
- <content align="start">
-
- <xul:image class="popup-notification-icon"
- xbl:inherits="popupid,src=icon"/>
-
- <xul:vbox flex="1">
- <xul:vbox anonid="identity-deck">
- <xul:vbox flex="1" pack="center"> <!-- 1: add an email -->
- <html:input type="email" anonid="email" required="required" size="30"/>
- <xul:description anonid="newidentitydesc"/>
- <xul:spacer flex="1"/>
- <xul:label class="text-link custom-link small-margin" anonid="chooseemail" hidden="true"/>
- </xul:vbox>
- <xul:vbox flex="1" hidden="true"> <!-- 2: choose an email -->
- <xul:description anonid="chooseidentitydesc"/>
- <xul:radiogroup anonid="identities">
- </xul:radiogroup>
- <xul:label class="text-link custom-link" anonid="newemail"/>
- </xul:vbox>
- </xul:vbox>
- <xul:hbox class="popup-notification-button-container"
- pack="end" align="center">
- <xul:label anonid="tos" class="text-link" hidden="true"/>
- <xul:label anonid="privacypolicy" class="text-link" hidden="true"/>
- <xul:spacer flex="1"/>
- <xul:image anonid="throbber" src="chrome://browser/skin/tabbrowser/loading.png"
- style="visibility:hidden" width="16" height="16"/>
- <xul:button anonid="button"
- type="menu-button"
- class="popup-notification-menubutton"
- xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
- <xul:menupopup anonid="menupopup"
- xbl:inherits="oncommand=menucommand">
- <children/>
- <xul:menuitem class="menuitem-iconic popup-notification-closeitem close-icon"
- label="&closeNotificationItem.label;"
- xbl:inherits="oncommand=closeitemcommand"/>
- </xul:menupopup>
- </xul:button>
- </xul:hbox>
- </xul:vbox>
- <xul:vbox pack="start">
- <xul:toolbarbutton anonid="closebutton"
- class="messageCloseButton close-icon popup-notification-closebutton tabbable"
- xbl:inherits="oncommand=closebuttoncommand"
- tooltiptext="&closeNotification.tooltip;"/>
- </xul:vbox>
- </content>
- <implementation>
- <constructor><![CDATA[
- // this.notification.options.identity is used to pass identity-specific info to the binding
- let origin = this.identity.origin
-
- // Populate text
- this.emailField.placeholder = gNavigatorBundle.
- getString("identity.newIdentity.email.placeholder");
- this.newIdentityDesc.textContent = gNavigatorBundle.getFormattedString(
- "identity.newIdentity.description", [origin]);
- this.chooseIdentityDesc.textContent = gNavigatorBundle.getFormattedString(
- "identity.chooseIdentity.description", [origin]);
-
- // Show optional terms of service and privacy policy links
- this._populateLink(this.identity.termsOfService, "tos", "identity.termsOfService");
- this._populateLink(this.identity.privacyPolicy, "privacypolicy", "identity.privacyPolicy");
-
- // Populate the list of identities to choose from. The origin is used to provide
- // better suggestions.
- let identities = this.SignInToWebsiteUX.getIdentitiesForSite(origin);
-
- this._populateIdentityList(identities);
-
- if (typeof this.step == "undefined") {
- // First opening of this notification
- // Show the add email pane (0) if there are no existing identities otherwise show the list
- this.step = "result" in identities && identities.result.length ? 1 : 0;
- } else {
- // Already opened so restore previous state
- if (this.identity.typedEmail) {
- this.emailField.value = this.identity.typedEmail;
- }
- if (this.identity.selected) {
- // If the user already chose an identity then update the UI to reflect that
- this.onIdentitySelected();
- }
- // Update the view for the step
- this.step = this.step;
- }
-
- // Fire notification with the chosen identity when main button is clicked
- this.button.addEventListener("command", this._onButtonCommand.bind(this), true);
-
- // Do the same if enter is pressed in the email field
- this.emailField.addEventListener("keypress", function emailFieldKeypress(aEvent) {
- if (aEvent.keyCode != aEvent.DOM_VK_RETURN)
- return;
- this._onButtonCommand(aEvent);
- }.bind(this));
-
- this.addEmailLink.value = gNavigatorBundle.getString("identity.newIdentity.label");
- this.addEmailLink.accessKey = gNavigatorBundle.getString("identity.newIdentity.accessKey");
- this.addEmailLink.addEventListener("click", function addEmailClick(evt) {
- this.step = 0;
- }.bind(this));
-
- this.chooseEmailLink.value = gNavigatorBundle.getString("identity.chooseIdentity.label");
- this.chooseEmailLink.hidden = !("result" in identities && identities.result.length);
- this.chooseEmailLink.addEventListener("click", function chooseEmailClick(evt) {
- this.step = 1;
- }.bind(this));
-
- this.emailField.addEventListener("blur", function onEmailBlur() {
- this.identity.typedEmail = this.emailField.value;
- }.bind(this));
- ]]></constructor>
-
- <field name="SignInToWebsiteUX" readonly="true">
- let sitw = {};
- Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
- sitw.SignInToWebsiteUX;
- </field>
-
- <field name="newIdentityDesc" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "newidentitydesc");
- </field>
-
- <field name="chooseIdentityDesc" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "chooseidentitydesc");
- </field>
-
- <field name="identityList" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "identities");
- </field>
-
- <field name="emailField" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "email");
- </field>
-
- <field name="addEmailLink" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "newemail");
- </field>
-
- <field name="chooseEmailLink" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "chooseemail");
- </field>
-
- <field name="throbber" readonly="true">
- document.getAnonymousElementByAttribute(this, "anonid", "throbber");
- </field>
-
- <field name="identity" readonly="true">
- this.notification.options.identity;
- </field>
-
- <!-- persist the state on the identity object so we can re-create the
- notification state upon re-opening -->
- <property name="step">
- <getter>
- return this.identity.step;
- </getter>
- <setter><![CDATA[
- let deck = document.getAnonymousElementByAttribute(this, "anonid", "identity-deck");
- for (let i = 0; i < deck.children.length; i++) {
- deck.children[i].hidden = (val != i);
- }
- this.identity.step = val;
- switch (val) {
- case 0:
- this.emailField.focus();
- break;
- }]]>
- </setter>
- </property>
-
- <method name="onIdentitySelected">
- <body><![CDATA[
- this.throbber.style.visibility = "visible";
- this.button.disabled = true;
- this.emailField.value = this.identity.selected
- this.emailField.disabled = true;
- this.identityList.disabled = true;
- ]]></body>
- </method>
-
- <method name="_populateLink">
- <parameter name="aURL"/>
- <parameter name="aLinkId"/>
- <parameter name="aStringId"/>
- <body><![CDATA[
- if (aURL) {
- // Show optional link to aURL
- let link = document.getAnonymousElementByAttribute(this, "anonid", aLinkId);
- link.value = gNavigatorBundle.getString(aStringId);
- link.href = aURL;
- link.hidden = false;
- }
- ]]></body>
- </method>
-
- <method name="_populateIdentityList">
- <parameter name="aIdentities"/>
- <body><![CDATA[
- let foundLastUsed = false;
- let lastUsed = this.identity.selected || aIdentities.lastUsed;
- for (let id in aIdentities.result) {
- let label = aIdentities.result[id];
- let opt = this.identityList.appendItem(label);
- if (label == lastUsed) {
- this.identityList.selectedItem = opt;
- foundLastUsed = true;
- }
- }
- if (!foundLastUsed) {
- this.identityList.selectedIndex = -1;
- }
- ]]></body>
- </method>
-
- <method name="_onButtonCommand">
- <parameter name="aEvent"/>
- <body><![CDATA[
- if (aEvent.target != aEvent.currentTarget)
- return;
- let chosenId;
- switch (this.step) {
- case 0:
- aEvent.stopPropagation();
- if (!this.emailField.validity.valid) {
- this.emailField.focus();
- return;
- }
- chosenId = this.emailField.value;
- break;
- case 1:
- aEvent.stopPropagation();
- let selectedItem = this.identityList.selectedItem
- chosenId = selectedItem ? selectedItem.label : null;
- if (!chosenId)
- return;
- break;
- default:
- throw new Error("Unknown case");
- return;
- }
- // Actually select the identity
- this.SignInToWebsiteUX.selectIdentity(this.identity.rpId, chosenId);
- this.identity.selected = chosenId;
- this.onIdentitySelected();
- ]]></body>
- </method>
-
- </implementation>
- </binding>
-
<binding id="plugin-popupnotification-center-item">
<content align="center">
<xul:vbox pack="center" anonid="itemBox" class="itemBox">
<xul:description anonid="center-item-label" class="center-item-label" />
<xul:hbox flex="1" pack="start" align="center" anonid="center-item-warning">
<xul:image anonid="center-item-warning-icon" class="center-item-warning-icon"/>
<xul:label anonid="center-item-warning-label"/>
<xul:label anonid="center-item-link" value="&checkForUpdates;" class="text-link"/>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -115,21 +115,16 @@ XPCOMUtils.defineLazyModuleGetter(this,
"resource://gre/modules/AsyncShutdown.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
"resource://gre/modules/LoginManagerParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
"resource://gre/modules/SimpleServiceDiscovery.jsm");
-#ifdef NIGHTLY_BUILD
-XPCOMUtils.defineLazyModuleGetter(this, "SignInToWebsiteUX",
- "resource:///modules/SignInToWebsite.jsm");
-#endif
-
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
#ifdef E10S_TESTING_ONLY
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
#endif
@@ -743,21 +738,16 @@ BrowserGlue.prototype = {
// prefs are applied in _onAppDefaults()
this._distributionCustomizer.applyCustomizations();
// handle any UI migration
this._migrateUI();
WebappManager.init();
PageThumbs.init();
-#ifdef NIGHTLY_BUILD
- if (Services.prefs.getBoolPref("dom.identity.enabled")) {
- SignInToWebsiteUX.init();
- }
-#endif
webrtcUI.init();
AboutHome.init();
DirectoryLinksProvider.init();
NewTabUtils.init();
NewTabUtils.links.addProvider(DirectoryLinksProvider);
AboutNewTab.init();
@@ -1075,21 +1065,16 @@ BrowserGlue.prototype = {
SelfSupportBackend.uninit();
CustomizationTabPreloader.uninit();
WebappManager.uninit();
NewTabPrefsProvider.prefs.uninit();
AboutNewTab.uninit();
-#ifdef NIGHTLY_BUILD
- if (Services.prefs.getBoolPref("dom.identity.enabled")) {
- SignInToWebsiteUX.uninit();
- }
-#endif
webrtcUI.uninit();
FormValidationHandler.uninit();
#ifdef NIGHTLY_BUILD
AddonWatcher.uninit();
#endif
},
_initServiceDiscovery: function () {
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -509,35 +509,16 @@ social.error.message=%1$S is unable to c
social.error.tryAgain.label=Try Again
social.error.tryAgain.accesskey=T
social.error.closeSidebar.label=Close This Sidebar
social.error.closeSidebar.accesskey=C
# LOCALIZATION NOTE: %1$S is the label for the toolbar button, %2$S is the associated badge numbering that the social provider may provide.
social.aria.toolbarButtonBadgeText=%1$S (%2$S)
-# Identity notifications popups
-identity.termsOfService = Terms of Service
-identity.privacyPolicy = Privacy Policy
-# LOCALIZATION NOTE (identity.chooseIdentity.description): %S is the website origin (e.g. https://www.mozilla.org) shown in popup notifications.
-identity.chooseIdentity.description = Sign in to %S
-identity.chooseIdentity.label = Use an existing email
-identity.newIdentity.label = Use a different email
-identity.newIdentity.accessKey = e
-identity.newIdentity.email.placeholder = Email
-# LOCALIZATION NOTE (identity.newIdentity.description): %S is the website origin (e.g. https://www.mozilla.org) shown in popup notifications.
-identity.newIdentity.description = Enter your email address to sign in to %S
-identity.next.label = Next
-identity.next.accessKey = n
-# LOCALIZATION NOTE: shown in the popup notification when a user successfully logs into a website
-# LOCALIZATION NOTE (identity.loggedIn.description): %S is the user's identity (e.g. user@example.com)
-identity.loggedIn.description = Signed in as: %S
-identity.loggedIn.signOut.label = Sign Out
-identity.loggedIn.signOut.accessKey = O
-
# LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message,
# getUserMedia.shareScreen.message, getUserMedia.shareCameraAndMicrophone.message,
# getUserMedia.shareScreenAndMicrophone.message, getUserMedia.shareCameraAndAudioCapture.message,
# getUserMedia.shareAudioCapture.message, getUserMedia.shareScreenAndAudioCapture.message):
# %S is the website origin (e.g. www.mozilla.org)
getUserMedia.shareCamera.message = Would you like to share your camera with %S?
getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S?
getUserMedia.shareScreen.message = Would you like to share your screen with %S?
deleted file mode 100644
--- a/browser/modules/SignInToWebsite.jsm
+++ /dev/null
@@ -1,227 +0,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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["SignInToWebsiteUX"];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
- "resource://gre/modules/identity/Identity.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Logger",
- "resource://gre/modules/identity/LogUtils.jsm");
-
-function log(...aMessageArgs) {
- Logger.log.apply(Logger, ["SignInToWebsiteUX"].concat(aMessageArgs));
-}
-
-this.SignInToWebsiteUX = {
-
- init: function SignInToWebsiteUX_init() {
-
- Services.obs.addObserver(this, "identity-request", false);
- Services.obs.addObserver(this, "identity-auth", false);
- Services.obs.addObserver(this, "identity-auth-complete", false);
- Services.obs.addObserver(this, "identity-login-state-changed", false);
- },
-
- uninit: function SignInToWebsiteUX_uninit() {
- Services.obs.removeObserver(this, "identity-request");
- Services.obs.removeObserver(this, "identity-auth");
- Services.obs.removeObserver(this, "identity-auth-complete");
- Services.obs.removeObserver(this, "identity-login-state-changed");
- },
-
- observe: function SignInToWebsiteUX_observe(aSubject, aTopic, aData) {
- log("observe: received", aTopic, "with", aData, "for", aSubject);
- let options = null;
- if (aSubject) {
- options = aSubject.wrappedJSObject;
- }
- switch(aTopic) {
- case "identity-request":
- this.requestLogin(options);
- break;
- case "identity-auth":
- this._openAuthenticationUI(aData, options);
- break;
- case "identity-auth-complete":
- this._closeAuthenticationUI(aData);
- break;
- case "identity-login-state-changed":
- let emailAddress = aData;
- if (emailAddress) {
- this._removeRequestUI(options);
- this._showLoggedInUI(emailAddress, options);
- } else {
- this._removeLoggedInUI(options);
- }
- break;
- default:
- Logger.reportError("SignInToWebsiteUX", "Unknown observer notification:", aTopic);
- break;
- }
- },
-
- /**
- * The website is requesting login so the user must choose an identity to use.
- */
- requestLogin: function SignInToWebsiteUX_requestLogin(aOptions) {
- let windowID = aOptions.rpId;
- log("requestLogin", aOptions);
- let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
-
- // message is not shown in the UI but is required
- let message = aOptions.origin;
- let mainAction = {
- label: chromeWin.gNavigatorBundle.getString("identity.next.label"),
- accessKey: chromeWin.gNavigatorBundle.getString("identity.next.accessKey"),
- callback: function() {}, // required
- };
- let options = {
- identity: {
- origin: aOptions.origin,
- },
- };
- let secondaryActions = [];
-
- // add some extra properties to the notification to store some identity-related state
- for (let opt in aOptions) {
- options.identity[opt] = aOptions[opt];
- }
- log("requestLogin: rpId: ", options.identity.rpId);
-
- chromeWin.PopupNotifications.show(browserEl, "identity-request", message,
- "identity-notification-icon", mainAction,
- [], options);
- },
-
- /**
- * Get the list of possible identities to login to the given origin.
- */
- getIdentitiesForSite: function SignInToWebsiteUX_getIdentitiesForSite(aOrigin) {
- return IdentityService.RP.getIdentitiesForSite(aOrigin);
- },
-
- /**
- * User chose a new or existing identity from the doorhanger after a request() call
- */
- selectIdentity: function SignInToWebsiteUX_selectIdentity(aRpId, aIdentity) {
- log("selectIdentity: rpId: ", aRpId, " identity: ", aIdentity);
- IdentityService.selectIdentity(aRpId, aIdentity);
- },
-
- // Private
-
- /**
- * Return the chrome window and <browser> for the given outer window ID.
- */
- _getUIForWindowID: function(aWindowID) {
- let content = Services.wm.getOuterWindowWithId(aWindowID);
- if (content) {
- let browser = content.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell).chromeEventHandler;
- let chromeWin = browser.ownerDocument.defaultView;
- return [chromeWin, browser];
- }
-
- Logger.reportError("SignInToWebsiteUX", "no content");
- return [null, null];
- },
-
- /**
- * Open UI with a content frame displaying aAuthURI so that the user can authenticate with their
- * IDP. Then tell Identity.jsm the identifier for the window so that it knows that the DOM API
- * calls are for this authentication flow.
- */
- _openAuthenticationUI: function _openAuthenticationUI(aAuthURI, aContext) {
- // Open a tab/window with aAuthURI with an identifier (aID) attached so that the DOM APIs know this is an auth. window.
- let chromeWin = Services.wm.getMostRecentWindow('navigator:browser');
- let features = "chrome=false,width=640,height=480,centerscreen,location=yes,resizable=yes,scrollbars=yes,status=yes";
- log("aAuthURI: ", aAuthURI);
- let authWin = Services.ww.openWindow(chromeWin, "about:blank", "", features, null);
- let windowID = authWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
- log("authWin outer id: ", windowID);
-
- let provId = aContext.provId;
- // Tell the ID service about the id before loading the url
- IdentityService.IDP.setAuthenticationFlow(windowID, provId);
-
- authWin.location = aAuthURI;
- },
-
- _closeAuthenticationUI: function _closeAuthenticationUI(aAuthId) {
- log("_closeAuthenticationUI:", aAuthId);
- let [chromeWin, browserEl] = this._getUIForWindowID(aAuthId);
- if (chromeWin)
- chromeWin.close();
- else
- Logger.reportError("SignInToWebsite", "Could not close window with ID", aAuthId);
- },
-
- /**
- * Show a doorhanger indicating the currently logged-in user.
- */
- _showLoggedInUI: function _showLoggedInUI(aIdentity, aContext) {
- let windowID = aContext.rpId;
- log("_showLoggedInUI for ", windowID);
- let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
-
- let message = chromeWin.gNavigatorBundle.getFormattedString("identity.loggedIn.description",
- [aIdentity]);
- let mainAction = {
- label: chromeWin.gNavigatorBundle.getString("identity.loggedIn.signOut.label"),
- accessKey: chromeWin.gNavigatorBundle.getString("identity.loggedIn.signOut.accessKey"),
- callback: function() {
- log("sign out callback fired");
- IdentityService.RP.logout(windowID);
- },
- };
- let secondaryActions = [];
- let options = {
- dismissed: true,
- };
- let loggedInNot = chromeWin.PopupNotifications.show(browserEl, "identity-logged-in", message,
- "identity-notification-icon", mainAction,
- secondaryActions, options);
- loggedInNot.rpId = windowID;
- },
-
- /**
- * Remove the doorhanger indicating the currently logged-in user.
- */
- _removeLoggedInUI: function _removeLoggedInUI(aContext) {
- let windowID = aContext.rpId;
- log("_removeLoggedInUI for ", windowID);
- if (!windowID)
- throw "_removeLoggedInUI: Invalid RP ID";
- let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
-
- let loggedInNot = chromeWin.PopupNotifications.getNotification("identity-logged-in", browserEl);
- if (loggedInNot)
- chromeWin.PopupNotifications.remove(loggedInNot);
- },
-
- /**
- * Remove the doorhanger indicating the currently logged-in user.
- */
- _removeRequestUI: function _removeRequestUI(aContext) {
- let windowID = aContext.rpId;
- log("_removeRequestUI for ", windowID);
- let [chromeWin, browserEl] = this._getUIForWindowID(windowID);
-
- let requestNot = chromeWin.PopupNotifications.getNotification("identity-request", browserEl);
- if (requestNot)
- chromeWin.PopupNotifications.remove(requestNot);
- },
-
-};
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -49,13 +49,8 @@ EXTRA_JS_MODULES += [
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXTRA_JS_MODULES += [
'Windows8WindowFrameColor.jsm',
'WindowsJumpLists.jsm',
'WindowsPreviewPerTab.jsm',
]
-
-if CONFIG['NIGHTLY_BUILD']:
- EXTRA_JS_MODULES += [
- 'SignInToWebsite.jsm',
- ]
--- a/browser/modules/test/browser.ini
+++ b/browser/modules/test/browser.ini
@@ -13,12 +13,10 @@ support-files =
contentSearchSuggestions.sjs
contentSearchSuggestions.xml
[browser_NetworkPrioritizer.js]
skip-if = e10s # Bug 666804 - Support NetworkPrioritizer in e10s
[browser_SelfSupportBackend.js]
support-files =
../../components/uitour/test/uitour.html
../../components/uitour/UITour-lib.js
-[browser_SignInToWebsite.js]
-skip-if = e10s # Bug 941426 - SignIntoWebsite.jsm not e10s friendly
[browser_taskbar_preview.js]
skip-if = os != "win"
deleted file mode 100644
--- a/browser/modules/test/browser_SignInToWebsite.js
+++ /dev/null
@@ -1,565 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-/**
- * TO TEST:
- * - test state saved on doorhanger dismissal
- * - links to switch steps
- * - TOS and PP link clicks
- * - identityList is populated correctly
- */
-
-Services.prefs.setBoolPref("toolkit.identity.debug", true);
-
-XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
- "resource://gre/modules/identity/Identity.jsm");
-
-const TEST_ORIGIN = "https://example.com";
-const TEST_EMAIL = "user@example.com";
-
-var gTestIndex = 0;
-var outerWinId = gBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
-
-function NotificationBase(aNotId) {
- this.id = aNotId;
-}
-NotificationBase.prototype = {
- message: TEST_ORIGIN,
- mainAction: {
- label: "",
- callback: function() {
- this.mainActionClicked = true;
- }.bind(this),
- },
- secondaryActions: [],
- options: {
- "identity": {
- origin: TEST_ORIGIN,
- rpId: outerWinId,
- },
- },
-};
-
-var tests = [
- {
- name: "test_request_required_typed",
-
- run: function() {
- setupRPFlow();
- this.notifyOptions = {
- rpId: outerWinId,
- origin: TEST_ORIGIN,
- };
- this.notifyObj = new NotificationBase("identity-request");
- Services.obs.notifyObservers({wrappedJSObject: this.notifyOptions},
- "identity-request", null);
- },
-
- onShown: function(popup) {
- checkPopup(popup, this.notifyObj);
- let notification = popup.childNodes[0];
-
- // Check identity popup state
- let state = notification.identity;
- ok(!state.typedEmail, "Nothing should be typed yet");
- ok(!state.selected, "Identity should not be selected yet");
- ok(!state.termsOfService, "No TOS specified");
- ok(!state.privacyPolicy, "No PP specified");
- is(state.step, 0, "Step should be persisted with default value");
- is(state.rpId, outerWinId, "Check rpId");
- is(state.origin, TEST_ORIGIN, "Check origin");
-
- is(notification.step, 0, "Should be on the new email step");
- is(notification.chooseEmailLink.hidden, true, "Identity list is empty so link to list view should be hidden");
- is(notification.addEmailLink.parentElement.hidden, true, "We are already on the email input step so choose email pane should be hidden");
- is(notification.emailField.value, "", "Email field should default to empty on a new notification");
- let notifDoc = notification.ownerDocument;
- ok(notifDoc.getAnonymousElementByAttribute(notification, "anonid", "tos").hidden,
- "TOS link should be hidden");
- ok(notifDoc.getAnonymousElementByAttribute(notification, "anonid", "privacypolicy").hidden,
- "PP link should be hidden");
-
- // Try to continue with a missing email address
- triggerMainCommand(popup);
- is(notification.throbber.style.visibility, "hidden", "is throbber visible");
- ok(!notification.button.disabled, "Button should not be disabled");
- is(window.gIdentitySelected, null, "Check no identity selected");
-
- // Fill in an invalid email address and try again
- notification.emailField.value = "foo";
- triggerMainCommand(popup);
- is(notification.throbber.style.visibility, "hidden", "is throbber visible");
- ok(!notification.button.disabled, "Button should not be disabled");
- is(window.gIdentitySelected, null, "Check no identity selected");
-
- // Fill in an email address and try again
- notification.emailField.value = TEST_EMAIL;
- triggerMainCommand(popup);
- is(window.gIdentitySelected.rpId, outerWinId, "Check identity selected rpId");
- is(window.gIdentitySelected.identity, TEST_EMAIL, "Check identity selected email");
- is(notification.identity.selected, TEST_EMAIL, "Check persisted email");
- is(notification.throbber.style.visibility, "visible", "is throbber visible");
- ok(notification.button.disabled, "Button should be disabled");
- ok(notification.emailField.disabled, "Email field should be disabled");
- ok(notification.identityList.disabled, "Identity list should be disabled");
-
- PopupNotifications.getNotification("identity-request").remove();
- },
-
- onHidden: function(popup) { },
- },
- {
- name: "test_request_optional",
-
- run: function() {
- this.notifyOptions = {
- rpId: outerWinId,
- origin: TEST_ORIGIN,
- privacyPolicy: TEST_ORIGIN + "/pp.txt",
- termsOfService: TEST_ORIGIN + "/tos.tzt",
- };
- this.notifyObj = new NotificationBase("identity-request");
- Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
- "identity-request", null);
- },
-
- onShown: function(popup) {
- checkPopup(popup, this.notifyObj);
- let notification = popup.childNodes[0];
-
- // Check identity popup state
- let state = notification.identity;
- ok(!state.typedEmail, "Nothing should be typed yet");
- ok(!state.selected, "Identity should not be selected yet");
- is(state.termsOfService, this.notifyOptions.termsOfService, "Check TOS URL");
- is(state.privacyPolicy, this.notifyOptions.privacyPolicy, "Check PP URL");
- is(state.step, 0, "Step should be persisted with default value");
- is(state.rpId, outerWinId, "Check rpId");
- is(state.origin, TEST_ORIGIN, "Check origin");
-
- is(notification.step, 0, "Should be on the new email step");
- is(notification.chooseEmailLink.hidden, true, "Identity list is empty so link to list view should be hidden");
- is(notification.addEmailLink.parentElement.hidden, true, "We are already on the email input step so choose email pane should be hidden");
- is(notification.emailField.value, "", "Email field should default to empty on a new notification");
- let notifDoc = notification.ownerDocument;
- let tosLink = notifDoc.getAnonymousElementByAttribute(notification, "anonid", "tos");
- ok(!tosLink.hidden, "TOS link should be visible");
- is(tosLink.href, this.notifyOptions.termsOfService, "Check TOS link URL");
- let ppLink = notifDoc.getAnonymousElementByAttribute(notification, "anonid", "privacypolicy");
- ok(!ppLink.hidden, "PP link should be visible");
- is(ppLink.href, this.notifyOptions.privacyPolicy, "Check PP link URL");
-
- // Try to continue with a missing email address
- triggerMainCommand(popup);
- is(notification.throbber.style.visibility, "hidden", "is throbber visible");
- ok(!notification.button.disabled, "Button should not be disabled");
- is(window.gIdentitySelected, null, "Check no identity selected");
-
- // Fill in an invalid email address and try again
- notification.emailField.value = "foo";
- triggerMainCommand(popup);
- is(notification.throbber.style.visibility, "hidden", "is throbber visible");
- ok(!notification.button.disabled, "Button should not be disabled");
- is(window.gIdentitySelected, null, "Check no identity selected");
-
- // Fill in an email address and try again
- notification.emailField.value = TEST_EMAIL;
- triggerMainCommand(popup);
- is(window.gIdentitySelected.rpId, outerWinId, "Check identity selected rpId");
- is(window.gIdentitySelected.identity, TEST_EMAIL, "Check identity selected email");
- is(notification.identity.selected, TEST_EMAIL, "Check persisted email");
- is(notification.throbber.style.visibility, "visible", "is throbber visible");
- ok(notification.button.disabled, "Button should be disabled");
- ok(notification.emailField.disabled, "Email field should be disabled");
- ok(notification.identityList.disabled, "Identity list should be disabled");
-
- PopupNotifications.getNotification("identity-request").remove();
- },
-
- onHidden: function(popup) {},
- },
- {
- name: "test_login_state_changed",
- run: function () {
- this.notifyOptions = {
- rpId: outerWinId,
- };
- this.notifyObj = new NotificationBase("identity-logged-in");
- this.notifyObj.message = "Signed in as: user@example.com";
- this.notifyObj.mainAction.label = "Sign Out";
- this.notifyObj.mainAction.accessKey = "O";
- Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
- "identity-login-state-changed", TEST_EMAIL);
- executeSoon(function() {
- PopupNotifications.getNotification("identity-logged-in").anchorElement.click();
- });
- },
-
- onShown: function(popup) {
- checkPopup(popup, this.notifyObj);
-
- // Fire the notification that the user is no longer logged-in to close the UI.
- Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
- "identity-login-state-changed", null);
- },
-
- onHidden: function(popup) {},
- },
- {
- name: "test_login_state_changed_logout",
- run: function () {
- this.notifyOptions = {
- rpId: outerWinId,
- };
- this.notifyObj = new NotificationBase("identity-logged-in");
- this.notifyObj.message = "Signed in as: user@example.com";
- this.notifyObj.mainAction.label = "Sign Out";
- this.notifyObj.mainAction.accessKey = "O";
- Services.obs.notifyObservers({ wrappedJSObject: this.notifyOptions },
- "identity-login-state-changed", TEST_EMAIL);
- executeSoon(function() {
- PopupNotifications.getNotification("identity-logged-in").anchorElement.click();
- });
- },
-
- onShown: function(popup) {
- checkPopup(popup, this.notifyObj);
-
- // This time trigger the Sign Out button and make sure the UI goes away.
- triggerMainCommand(popup);
- },
-
- onHidden: function(popup) {},
- },
-];
-
-function test_auth() {
- let notifyOptions = {
- provId: outerWinId,
- origin: TEST_ORIGIN,
- };
-
- Services.obs.addObserver(function() {
- // prepare to send auth-complete and close the window
- let winCloseObs = new WindowObserver(function(closedWin) {
- info("closed window");
- finish();
- }, "domwindowclosed");
- Services.ww.registerNotification(winCloseObs);
- Services.obs.notifyObservers(null, "identity-auth-complete", IdentityService.IDP.authenticationFlowSet.authId);
-
- }, "test-identity-auth-window", false);
-
- let winObs = new WindowObserver(function(authWin) {
- ok(authWin, "Authentication window opened");
- // See bug 1063404.
- // ok(authWin.location);
- });
-
- Services.ww.registerNotification(winObs);
-
- Services.obs.notifyObservers({ wrappedJSObject: notifyOptions },
- "identity-auth", TEST_ORIGIN + "/auth");
-}
-
-function test() {
- waitForExplicitFinish();
-
- let sitw = {};
- try {
- Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
- } catch (ex) {
- ok(true, "Skip the test since SignInToWebsite.jsm isn't packaged outside outside mozilla-central");
- finish();
- return;
- }
-
-
- registerCleanupFunction(cleanUp);
-
- ok(sitw.SignInToWebsiteUX, "SignInToWebsiteUX object exists");
- if (!Services.prefs.getBoolPref("dom.identity.enabled")) {
- // If the pref isn't enabled then init wasn't called so do that for the test.
- sitw.SignInToWebsiteUX.init();
- }
-
- // Replace implementation of ID Service functions for testing
- window.selectIdentity = sitw.SignInToWebsiteUX.selectIdentity;
- sitw.SignInToWebsiteUX.selectIdentity = function(aRpId, aIdentity) {
- info("Identity selected: " + aIdentity);
- window.gIdentitySelected = {rpId: aRpId, identity: aIdentity};
- };
-
- window.setAuthenticationFlow = IdentityService.IDP.setAuthenticationFlow;
- IdentityService.IDP.setAuthenticationFlow = function(aAuthId, aProvId) {
- info("setAuthenticationFlow: " + aAuthId + " : " + aProvId);
- this.authenticationFlowSet = { authId: aAuthId, provId: aProvId };
- Services.obs.notifyObservers(null, "test-identity-auth-window", aAuthId);
- };
-
- runNextTest();
-}
-
-// Cleanup between tests
-function resetState() {
- delete window.gIdentitySelected;
- delete IdentityService.IDP.authenticationFlowSet;
- IdentityService.reset();
-}
-
-// Cleanup after all tests
-function cleanUp() {
- info("cleanup");
- resetState();
-
-
- for (let topic in gActiveObservers)
- Services.obs.removeObserver(gActiveObservers[topic], topic);
- for (let eventName in gActiveListeners)
- PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
- delete IdentityService.RP._rpFlows[outerWinId];
-
- // Put the JSM functions back to how they were
- IdentityService.IDP.setAuthenticationFlow = window.setAuthenticationFlow;
- delete window.setAuthenticationFlow;
-
- let sitw = {};
- Components.utils.import("resource:///modules/SignInToWebsite.jsm", sitw);
- sitw.SignInToWebsiteUX.selectIdentity = window.selectIdentity;
- delete window.selectIdentity;
- if (!Services.prefs.getBoolPref("dom.identity.enabled")) {
- sitw.SignInToWebsiteUX.uninit();
- }
-
- Services.prefs.clearUserPref("toolkit.identity.debug");
-}
-
-var gActiveListeners = {};
-var gActiveObservers = {};
-var gShownState = {};
-
-function runNextTest() {
- let nextTest = tests[gTestIndex];
-
- function goNext() {
- resetState();
- if (++gTestIndex == tests.length)
- executeSoon(test_auth);
- else
- executeSoon(runNextTest);
- }
-
- function addObserver(topic) {
- function observer() {
- Services.obs.removeObserver(observer, "PopupNotifications-" + topic);
- delete gActiveObservers["PopupNotifications-" + topic];
-
- info("[Test #" + gTestIndex + "] observer for " + topic + " called");
- nextTest[topic]();
- goNext();
- }
- Services.obs.addObserver(observer, "PopupNotifications-" + topic, false);
- gActiveObservers["PopupNotifications-" + topic] = observer;
- }
-
- if (nextTest.backgroundShow) {
- addObserver("backgroundShow");
- } else if (nextTest.updateNotShowing) {
- addObserver("updateNotShowing");
- } else {
- doOnPopupEvent("popupshowing", function () {
- info("[Test #" + gTestIndex + "] popup showing");
- });
- doOnPopupEvent("popupshown", function () {
- gShownState[gTestIndex] = true;
- info("[Test #" + gTestIndex + "] popup shown");
- nextTest.onShown(this);
- });
-
- // We allow multiple onHidden functions to be defined in an array. They're
- // called in the order they appear.
- let onHiddenArray = nextTest.onHidden instanceof Array ?
- nextTest.onHidden :
- [nextTest.onHidden];
- doOnPopupEvent("popuphidden", function () {
- if (!gShownState[gTestIndex]) {
- // TODO: needed?
- info("Popup from test " + gTestIndex + " was hidden before its popupshown fired");
- }
-
- let onHidden = onHiddenArray.shift();
- info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
- executeSoon(function () {
- onHidden.call(nextTest, this);
- if (!onHiddenArray.length)
- goNext();
- }.bind(this));
- }, onHiddenArray.length);
- info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
- }
-
- info("[Test #" + gTestIndex + "] running test");
- nextTest.run();
-}
-
-function doOnPopupEvent(eventName, callback, numExpected) {
- gActiveListeners[eventName] = function (event) {
- if (event.target != PopupNotifications.panel)
- return;
- if (typeof(numExpected) === "number")
- numExpected--;
- if (!numExpected) {
- PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
- delete gActiveListeners[eventName];
- }
-
- callback.call(PopupNotifications.panel);
- };
- PopupNotifications.panel.addEventListener(eventName, gActiveListeners[eventName], false);
-}
-
-function checkPopup(popup, notificationObj) {
- info("[Test #" + gTestIndex + "] checking popup");
-
- let notifications = popup.childNodes;
- is(notifications.length, 1, "only one notification displayed");
- let notification = notifications[0];
- let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
- is(notification.getAttribute("label"), notificationObj.message, "message matches");
- is(notification.id, notificationObj.id + "-notification", "id matches");
- if (notificationObj.id != "identity-request" && notificationObj.mainAction) {
- is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
- is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
- }
- let actualSecondaryActions = notification.childNodes;
- let secondaryActions = notificationObj.secondaryActions || [];
- let actualSecondaryActionsCount = actualSecondaryActions.length;
- if (secondaryActions.length) {
- let lastChild = actualSecondaryActions.item(actualSecondaryActions.length - 1);
- is(lastChild.tagName, "menuseparator", "menuseparator exists");
- actualSecondaryActionsCount--;
- }
- is(actualSecondaryActionsCount, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
- secondaryActions.forEach(function (a, i) {
- is(actualSecondaryActions[i].getAttribute("label"), a.label, "label for secondary action " + i + " matches");
- is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey, "accessKey for secondary action " + i + " matches");
- });
-}
-
-function triggerMainCommand(popup) {
- info("[Test #" + gTestIndex + "] triggering main command");
- let notifications = popup.childNodes;
- ok(notifications.length > 0, "at least one notification displayed");
- let notification = notifications[0];
-
- // 20, 10 so that the inner button is hit
- EventUtils.synthesizeMouse(notification.button, 20, 10, {});
-}
-
-function triggerSecondaryCommand(popup, index) {
- info("[Test #" + gTestIndex + "] triggering secondary command");
- let notifications = popup.childNodes;
- ok(notifications.length > 0, "at least one notification displayed");
- let notification = notifications[0];
-
- notification.button.focus();
-
- popup.addEventListener("popupshown", function () {
- popup.removeEventListener("popupshown", arguments.callee, false);
-
- // Press down until the desired command is selected
- for (let i = 0; i <= index; i++)
- EventUtils.synthesizeKey("VK_DOWN", {});
-
- // Activate
- EventUtils.synthesizeKey("VK_RETURN", {});
- }, false);
-
- // One down event to open the popup
- EventUtils.synthesizeKey("VK_DOWN", { altKey: (navigator.platform.indexOf("Mac") == -1) });
-}
-
-function dismissNotification(popup) {
- info("[Test #" + gTestIndex + "] dismissing notification");
- executeSoon(function () {
- EventUtils.synthesizeKey("VK_ESCAPE", {});
- });
-}
-
-function partial(fn) {
- let args = Array.prototype.slice.call(arguments, 1);
- return function() {
- return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));
- };
-}
-
-// create a mock "doc" object, which the Identity Service
-// uses as a pointer back into the doc object
-function mock_doc(aIdentity, aOrigin, aDoFunc) {
- let mockedDoc = {};
- mockedDoc.id = outerWinId;
- mockedDoc.loggedInEmail = aIdentity;
- mockedDoc.origin = aOrigin;
- mockedDoc['do'] = aDoFunc;
- mockedDoc.doReady = partial(aDoFunc, 'ready');
- mockedDoc.doLogin = partial(aDoFunc, 'login');
- mockedDoc.doLogout = partial(aDoFunc, 'logout');
- mockedDoc.doError = partial(aDoFunc, 'error');
- mockedDoc.doCancel = partial(aDoFunc, 'cancel');
- mockedDoc.doCoffee = partial(aDoFunc, 'coffee');
-
- return mockedDoc;
-}
-
-// takes a list of functions and returns a function that
-// when called the first time, calls the first func,
-// then the next time the second, etc.
-function call_sequentially() {
- let numCalls = 0;
- let funcs = arguments;
-
- return function() {
- if (!funcs[numCalls]) {
- let argString = Array.prototype.slice.call(arguments).join(",");
- ok(false, "Too many calls: " + argString);
- return;
- }
- funcs[numCalls].apply(funcs[numCalls], arguments);
- numCalls += 1;
- };
-}
-
-function setupRPFlow(aIdentity) {
- IdentityService.RP.watch(mock_doc(aIdentity, TEST_ORIGIN, call_sequentially(
- function(action, params) {
- is(action, "ready", "1st callback");
- is(params, null);
- },
- function(action, params) {
- is(action, "logout", "2nd callback");
- is(params, null);
- },
- function(action, params) {
- is(action, "ready", "3rd callback");
- is(params, null);
- }
- )));
-}
-
-function WindowObserver(aCallback, aObserveTopic = "domwindowopened") {
- this.observe = function(aSubject, aTopic, aData) {
- if (aTopic != aObserveTopic) {
- return;
- }
- info(aObserveTopic);
- Services.ww.unregisterNotification(this);
-
- SimpleTest.executeSoon(function() {
- let domWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
- aCallback(domWin);
- });
- };
-}
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -122,22 +122,16 @@
%else
list-style-image: url(chrome://global/skin/icons/information-16.png);
%endif
width: 16px;
height: 16px;
margin: 0 2px;
}
-.identity-notification-icon,
-#identity-notification-icon {
- list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
- /* XXX: need HiDPI version */
-}
-
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
}
#addons-notification-icon {
list-style-image: url(chrome://browser/skin/addons/addon-install-anchor.svg#default);
}