--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -989,26 +989,26 @@ chatbar[customSize] > .chatbar-innerbox
-moz-binding: url("chrome://browser/content/downloads/download.xml#download-toolbarbutton");
}
/*** Visibility of downloads indicator controls ***/
/* Bug 924050: If we've loaded the indicator, for now we hide it in the menu panel,
and just show the icon. This is a hack to side-step very weird layout bugs that
seem to be caused by the indicator stack interacting with the menu panel. */
-#downloads-button[indicator]:not([cui-areatype="menu-panel"]) > image.toolbarbutton-icon,
+#downloads-button[indicator]:not([cui-areatype="menu-panel"]) > .toolbarbutton-badge-stack > image.toolbarbutton-icon,
#downloads-button[indicator][cui-areatype="menu-panel"] > #downloads-indicator-anchor {
display: none;
}
-toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > image.toolbarbutton-icon {
+toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbutton-badge-stack > image.toolbarbutton-icon {
display: -moz-box;
}
-toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > stack.toolbarbutton-icon {
+toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-indicator-anchor {
display: none;
}
#downloads-button:-moz-any([progress], [counter], [paused]) #downloads-indicator-icon,
#downloads-button:not(:-moz-any([progress], [counter], [paused]))
#downloads-indicator-progress-area
{
visibility: hidden;
@@ -1021,17 +1021,17 @@ toolbar[mode="text"] > #downloads-button
-moz-box-orient: vertical;
-moz-box-pack: center;
}
toolbar[mode="text"] > #downloads-button > .toolbarbutton-text {
-moz-box-ordinal-group: 1;
}
-toolbar[mode="text"] > #downloads-button > .toolbarbutton-icon {
+toolbar[mode="text"] > #downloads-button > .toolbarbutton-badge-stack > .toolbarbutton-icon {
display: -moz-box;
-moz-box-ordinal-group: 2;
visibility: collapse;
}
/* hide chat chrome when chat is fullscreen */
#chat-window[sizemode="fullscreen"] chatbox > .chat-titlebar {
display: none;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2492,19 +2492,21 @@ function SetPageProxyState(aState)
function PageProxyClickHandler(aEvent)
{
if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
middleMousePaste(aEvent);
}
var gMenuButtonBadgeManager = {
BADGEID_APPUPDATE: "update",
+ BADGEID_DOWNLOAD: "download",
BADGEID_FXA: "fxa",
fxaBadge: null,
+ downloadBadge: null,
appUpdateBadge: null,
init: function () {
PanelUI.panel.addEventListener("popupshowing", this, true);
},
uninit: function () {
PanelUI.panel.removeEventListener("popupshowing", this, true);
@@ -2512,32 +2514,34 @@ var gMenuButtonBadgeManager = {
handleEvent: function (e) {
if (e.type === "popupshowing") {
this.clearBadges();
}
},
_showBadge: function () {
- let badgeToShow = this.appUpdateBadge || this.fxaBadge;
+ let badgeToShow = this.downloadBadge || this.appUpdateBadge || this.fxaBadge;
if (badgeToShow) {
PanelUI.menuButton.setAttribute("badge-status", badgeToShow);
} else {
PanelUI.menuButton.removeAttribute("badge-status");
}
},
_changeBadge: function (badgeId, badgeStatus = null) {
if (badgeId == this.BADGEID_APPUPDATE) {
this.appUpdateBadge = badgeStatus;
+ } else if (badgeId == this.BADGEID_DOWNLOAD) {
+ this.downloadBadge = badgeStatus;
} else if (badgeId == this.BADGEID_FXA) {
this.fxaBadge = badgeStatus;
} else {
- Cu.reportError("This badge ID is unknown!");
+ Cu.reportError("The badge ID '" + badgeId + "' is unknown!");
}
this._showBadge();
},
addBadge: function (badgeId, badgeStatus) {
if (!badgeStatus) {
Cu.reportError("badgeStatus must be defined");
return;
@@ -2546,16 +2550,17 @@ var gMenuButtonBadgeManager = {
},
removeBadge: function (badgeId) {
this._changeBadge(badgeId);
},
clearBadges: function () {
this.appUpdateBadge = null;
+ this.downloadBadge = null;
this.fxaBadge = null;
this._showBadge();
}
};
// Setup the hamburger button badges for updates, if enabled.
var gMenuButtonUpdateBadge = {
enabled: false,
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -895,17 +895,18 @@
command="Browser:ShowAllBookmarks"
key="manBookmarkKb"/>
</menupopup>
</toolbarbutton>
<!-- This is a placeholder for the Downloads Indicator. It is visible
during the customization of the toolbar, in the palette, and before
the Downloads Indicator overlay is loaded. -->
- <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+ <toolbarbutton id="downloads-button"
+ class="toolbarbutton-1 chromeclass-toolbar-additional badged-button"
key="key_openDownloads"
oncommand="DownloadsIndicatorView.onCommand(event);"
ondrop="DownloadsIndicatorView.onDrop(event);"
ondragover="DownloadsIndicatorView.onDragOver(event);"
ondragenter="DownloadsIndicatorView.onDragOver(event);"
label="&downloads.label;"
removable="true"
cui-areatype="toolbar"
--- a/browser/base/content/test/general/browser_menuButtonBadgeManager.js
+++ b/browser/base/content/test/general/browser_menuButtonBadgeManager.js
@@ -12,26 +12,35 @@ add_task(function* testButtonActivities(
is(menuButton.getAttribute("badge-status"), "fxa-needs-authentication", "Should have fxa-needs-authentication badge status");
gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_APPUPDATE, "update-succeeded");
is(menuButton.getAttribute("badge-status"), "update-succeeded", "Should have update-succeeded badge status (update > fxa)");
gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_APPUPDATE, "update-failed");
is(menuButton.getAttribute("badge-status"), "update-failed", "Should have update-failed badge status");
+ gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_DOWNLOAD, "download-severe");
+ is(menuButton.getAttribute("badge-status"), "download-severe", "Should have download-severe badge status");
+
+ gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_DOWNLOAD, "download-warning");
+ is(menuButton.getAttribute("badge-status"), "download-warning", "Should have download-warning badge status");
+
gMenuButtonBadgeManager.addBadge("unknownbadge", "attr");
- is(menuButton.getAttribute("badge-status"), "update-failed", "Should not have changed badge status");
+ is(menuButton.getAttribute("badge-status"), "download-warning", "Should not have changed badge status");
+
+ gMenuButtonBadgeManager.removeBadge(gMenuButtonBadgeManager.BADGEID_DOWNLOAD);
+ is(menuButton.getAttribute("badge-status"), "update-failed", "Should have update-failed badge status");
gMenuButtonBadgeManager.removeBadge(gMenuButtonBadgeManager.BADGEID_APPUPDATE);
is(menuButton.getAttribute("badge-status"), "fxa-needs-authentication", "Should have fxa-needs-authentication badge status");
gMenuButtonBadgeManager.removeBadge(gMenuButtonBadgeManager.BADGEID_FXA);
is(menuButton.hasAttribute("badge-status"), false, "Should not have a badge status");
yield PanelUI.show();
is(menuButton.hasAttribute("badge-status"), false, "Should not have a badge status (Hamburger menu opened)");
PanelUI.hide();
gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_FXA, "fxa-needs-authentication");
- gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_UPDATE, "update-succeeded");
+ gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_APPUPDATE, "update-succeeded");
gMenuButtonBadgeManager.clearBadges();
is(menuButton.hasAttribute("badge-status"), false, "Should not have a badge status (clearBadges called)");
});
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -135,16 +135,21 @@ PrefObserver.register({
////////////////////////////////////////////////////////////////////////////////
//// DownloadsCommon
/**
* This object is exposed directly to the consumers of this JavaScript module,
* and provides shared methods for all the instances of the user interface.
*/
this.DownloadsCommon = {
+ ATTENTION_NONE: "",
+ ATTENTION_SUCCESS: "success",
+ ATTENTION_WARNING: "warning",
+ ATTENTION_SEVERE: "severe",
+
/**
* Returns an object whose keys are the string names from the downloads string
* bundle, and whose values are either the translated strings or functions
* returning formatted strings.
*/
get strings() {
let strings = {};
let sb = Services.strings.createBundle(kDownloadsStringBundleUrl);
@@ -717,17 +722,17 @@ DownloadsDataCtor.prototype = {
*/
removeFinished() {
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
: Downloads.PUBLIC);
promiseList.then(list => list.removeFinished())
.then(null, Cu.reportError);
let indicatorData = this._isPrivate ? PrivateDownloadsIndicatorData
: DownloadsIndicatorData;
- indicatorData.attention = false;
+ indicatorData.attention = DownloadsCommon.ATTENTION_NONE;
},
//////////////////////////////////////////////////////////////////////////////
//// Integration with the asynchronous Downloads back-end
onDownloadAdded(download) {
// Download objects do not store the end time of downloads, as the Downloads
// API does not need to persist this information for all platforms. Once a
@@ -1148,18 +1153,39 @@ DownloadsIndicatorDataCtor.prototype = {
},
onDownloadAdded(download, newest) {
this._itemCount++;
this._updateViews();
},
onDownloadStateChanged(download) {
- if (download.succeeded || download.error) {
- this.attention = true;
+ if (!download.succeeded && download.error && download.error.reputationCheckVerdict) {
+ switch (download.error.reputationCheckVerdict) {
+ case Downloads.Error.BLOCK_VERDICT_UNCOMMON: // fall-through
+ case Downloads.Error.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
+ // Existing higher level attention indication trumps ATTENTION_WARNING.
+ if (this._attention != DownloadsCommon.ATTENTION_SEVERE) {
+ this.attention = DownloadsCommon.ATTENTION_WARNING;
+ }
+ break;
+ case Downloads.Error.BLOCK_VERDICT_MALWARE:
+ this.attention = DownloadsCommon.ATTENTION_SEVERE;
+ break;
+ default:
+ this.attention = DownloadsCommon.ATTENTION_SEVERE;
+ Cu.reportError("Unknown reputation verdict: " +
+ download.error.reputationCheckVerdict);
+ }
+ } else if (download.succeeded || download.error) {
+ // Existing higher level attention indication trumps ATTENTION_SUCCESS.
+ if (this._attention != DownloadsCommon.ATTENTION_SEVERE &&
+ this._attention != DownloadsCommon.ATTENTION_WARNING) {
+ this.attention = DownloadsCommon.ATTENTION_SUCCESS;
+ }
}
// Since the state of a download changed, reset the estimated time left.
this._lastRawTimeLeft = -1;
this._lastTimeLeft = -1;
},
onDownloadChanged(download) {
@@ -1184,25 +1210,25 @@ DownloadsIndicatorDataCtor.prototype = {
/**
* Indicates whether the download indicators should be highlighted.
*/
set attention(aValue) {
this._attention = aValue;
this._updateViews();
return aValue;
},
- _attention: false,
+ _attention: DownloadsCommon.ATTENTION_NONE,
/**
* Indicates whether the user is interacting with downloads, thus the
* attention indication should not be shown even if requested.
*/
set attentionSuppressed(aValue) {
this._attentionSuppressed = aValue;
- this._attention = false;
+ this._attention = DownloadsCommon.ATTENTION_NONE;
this._updateViews();
return aValue;
},
_attentionSuppressed: false,
/**
* Computes aggregate values and propagates the changes to our views.
*/
@@ -1222,17 +1248,18 @@ DownloadsIndicatorDataCtor.prototype = {
* @param aView
* DownloadsIndicatorView object to be updated.
*/
_updateView(aView) {
aView.hasDownloads = this._hasDownloads;
aView.counter = this._counter;
aView.percentComplete = this._percentComplete;
aView.paused = this._paused;
- aView.attention = this._attention && !this._attentionSuppressed;
+ aView.attention = this._attentionSuppressed ? DownloadsCommon.ATTENTION_NONE
+ : this._attention;
},
//////////////////////////////////////////////////////////////////////////////
//// Property updating based on current download status
/**
* Number of download items that are available to be displayed.
*/
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -497,17 +497,17 @@ function DownloadsPlacesView(aRichListBo
// Register as a downloads view. The places data will be initialized by
// the places setter.
this._initiallySelectedElement = null;
this._downloadsData = DownloadsCommon.getData(window.opener || window);
this._downloadsData.addView(this);
// Get the Download button out of the attention state since we're about to
// view all downloads.
- DownloadsCommon.getIndicatorData(window).attention = false;
+ DownloadsCommon.getIndicatorData(window).attention = DownloadsCommon.ATTENTION_NONE;
// Make sure to unregister the view if the window is closed.
window.addEventListener("unload", () => {
window.controllers.removeController(this);
this._downloadsData.removeView(this);
this.result = null;
}, true);
// Resizing the window may change items visibility.
--- a/browser/components/downloads/content/download.xml
+++ b/browser/components/downloads/content/download.xml
@@ -69,19 +69,22 @@
<xul:button class="downloadButton downloadChooseOpen downloadIconShow"
tooltiptext="&cmd.chooseOpen.label;"
oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_chooseOpen');"/>
</xul:stack>
</content>
</binding>
<binding id="download-toolbarbutton"
- extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
+ extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged">
<content>
- <children />
- <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
+ <xul:stack class="toolbarbutton-badge-stack">
+ <children />
+ <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
+ <xul:label class="toolbarbutton-badge" xbl:inherits="value=badge" top="0" end="0" crop="none"/>
+ </xul:stack>
<xul:label class="toolbarbutton-text" crop="right" flex="1"
xbl:inherits="value=label,accesskey,crop,wrap"/>
<xul:label class="toolbarbutton-multiline-text" flex="1"
xbl:inherits="xbl:text=label,accesskey,wrap"/>
</content>
</binding>
</bindings>
--- a/browser/components/downloads/content/indicator.js
+++ b/browser/components/downloads/content/indicator.js
@@ -233,17 +233,17 @@ const DownloadsIndicatorView = {
window.removeEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.getIndicatorData(window).removeView(this);
// Reset the view properties, so that a neutral indicator is displayed if we
// are visible only temporarily as an anchor.
this.counter = "";
this.percentComplete = 0;
this.paused = false;
- this.attention = false;
+ this.attention = DownloadsCommon.ATTENTION_NONE;
},
/**
* Ensures that the user interface elements required to display the indicator
* are loaded, then invokes the given callback.
*/
_ensureOperational(aCallback) {
if (this._operational) {
@@ -461,25 +461,38 @@ const DownloadsIndicatorView = {
*/
set attention(aValue) {
if (!this._operational) {
return this._attention;
}
if (this._attention != aValue) {
this._attention = aValue;
- if (aValue) {
- this.indicator.setAttribute("attention", "true");
+
+ // Check if the downloads button is in the menu panel, to determine which
+ // button needs to get a badge.
+ let widgetGroup = CustomizableUI.getWidget("downloads-button");
+ let inMenu = widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL;
+
+ if (aValue == DownloadsCommon.ATTENTION_NONE) {
+ this.indicator.removeAttribute("attention");
+ if (inMenu) {
+ gMenuButtonBadgeManager.removeBadge(gMenuButtonBadgeManager.BADGEID_DOWNLOAD);
+ }
} else {
- this.indicator.removeAttribute("attention");
+ this.indicator.setAttribute("attention", aValue);
+ if (inMenu) {
+ let badgeClass = "download-" + aValue;
+ gMenuButtonBadgeManager.addBadge(gMenuButtonBadgeManager.BADGEID_DOWNLOAD, badgeClass);
+ }
}
}
return aValue;
},
- _attention: false,
+ _attention: DownloadsCommon.ATTENTION_NONE,
//////////////////////////////////////////////////////////////////////////////
//// User interface event functions
onWindowUnload() {
// This function is registered as an event listener, we can't use "this".
DownloadsIndicatorView.ensureTerminated();
},
--- a/browser/components/downloads/content/indicatorOverlay.xul
+++ b/browser/components/downloads/content/indicatorOverlay.xul
@@ -18,17 +18,17 @@
<!-- We dynamically add the stack with the progress meter and notification icon,
originally loaded lazily because of performance reasons, to the existing
downloads-button. -->
<toolbarbutton id="downloads-button" indicator="true">
<!-- The panel's anchor area is smaller than the outer button, but must
always be visible and must not move or resize when the indicator
state changes, otherwise the panel could change its position or lose
its arrow unexpectedly. -->
- <stack id="downloads-indicator-anchor" class="toolbarbutton-icon"
+ <stack id="downloads-indicator-anchor"
consumeanchor="downloads-button">
<vbox id="downloads-indicator-progress-area" pack="center">
<description id="downloads-indicator-counter"/>
<progressmeter id="downloads-indicator-progress" class="plain"
min="0" max="100"/>
</vbox>
<vbox id="downloads-indicator-icon"/>
</stack>
--- a/browser/themes/linux/downloads/indicator.css
+++ b/browser/themes/linux/downloads/indicator.css
@@ -21,52 +21,76 @@
#downloads-button[cui-areatype="toolbar"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 198, 18, 180) center no-repeat;
min-width: 18px;
min-height: 18px;
}
-toolbar[brighttext] #downloads-button[cui-areatype="toolbar"]:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon {
+toolbar[brighttext] #downloads-button[cui-areatype="toolbar"]:not([attention="success"]) > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 198, 18, 180) center no-repeat;
}
-#downloads-button[cui-areatype="toolbar"][attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+#downloads-button[cui-areatype="toolbar"][attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
+#downloads-button[cui-areatype="toolbar"][attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ display: -moz-box;
+ height: 13px;
+ width: 13px;
+ background-size: contain;
+ border: none;
+ box-shadow: none;
+ filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
+}
+
+#downloads-button[cui-areatype="toolbar"][attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #D90000 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[cui-areatype="toolbar"][attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[cui-areatype="toolbar"][attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
+#downloads-button[cui-areatype="toolbar"][attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
+ filter: none;
+}
+
+#downloads-button[cui-areatype="toolbar"][attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 18, 198, 36, 180);
}
-toolbar[brighttext] #downloads-button[cui-areatype="toolbar"][attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+toolbar[brighttext] #downloads-button[cui-areatype="toolbar"][attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 18, 198, 36, 180);
}
-#downloads-button[cui-areatype="menu-panel"][attention] {
+#downloads-button[cui-areatype="menu-panel"][attention="success"] {
list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel.png");
-moz-image-region: auto;
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-button:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
background-size: 12px;
}
-toolbar[brighttext] #downloads-button:not([counter]):not([attention]) > #downloads-indicator-anchor > #downloads-button-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter]):not([attention="success"]) > #downloads-indicator-anchor > #downloads-button-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 198, 18, 180);
}
-#downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+#downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 18, 198, 36, 180);
}
-toolbar[brighttext] #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 18, 198, 36, 180);
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -1058,16 +1058,17 @@ toolbar .toolbarbutton-1 > .toolbarbutto
}
@media (-moz-mac-lion-theme) {
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-menu-dropmarker,
#main-window:not([customizing]) .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-dropmarker,
+ .toolbarbutton-1:not(:hover):-moz-window-inactive > #downloads-indicator-anchor,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-text,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-badge-stack > .toolbarbutton-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menu-dropmarker,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
.toolbarbutton-1:not(:hover):-moz-window-inactive > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
opacity: .5;
}
--- a/browser/themes/osx/downloads/indicator.css
+++ b/browser/themes/osx/downloads/indicator.css
@@ -28,47 +28,71 @@
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 198, 18, 180) center no-repeat;
}
toolbar[brighttext] #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 198, 18, 180);
}
-#downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ display: -moz-box;
+ height: 13px;
+ width: 13px;
+ background-size: contain;
+ border: none;
+ box-shadow: none;
+ filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
+}
+
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #D90000 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
+ filter: none;
+}
+
+#downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 36, 198, 54, 180);
}
-toolbar[brighttext] #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+toolbar[brighttext] #downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 36, 198, 54, 180);
}
-#downloads-button[cui-areatype="menu-panel"][attention] {
+#downloads-button[cui-areatype="menu-panel"][attention="success"] {
list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel.png");
-moz-image-region: auto;
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-button:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 198, 18, 180) center no-repeat;
background-size: 12px;
}
-toolbar[brighttext] #downloads-button:not([counter]):not([attention]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter]):not([attention="success"]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 198, 18, 180);
}
-#downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+#downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"), 36, 198, 54, 180);
}
-toolbar[brighttext] #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 36, 198, 54, 180);
}
@media (min-resolution: 2dppx) {
#downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 396, 36, 360);
background-size: 18px;
}
@@ -81,33 +105,33 @@ toolbar[brighttext] #downloads-button:no
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 396, 36, 360);
}
toolbar[brighttext] #downloads-button:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted@2x.png"),
0, 396, 36, 360);
}
- #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+ #downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 72, 396, 108, 360);
}
- toolbar[brighttext] #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+ toolbar[brighttext] #downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted@2x.png"), 72, 396, 108, 360);
}
- #downloads-button[cui-areatype="menu-panel"][attention] {
+ #downloads-button[cui-areatype="menu-panel"][attention="success"] {
list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel@2x.png");
}
- #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+ #downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 72, 396, 108, 360);
}
- toolbar[brighttext] #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+ toolbar[brighttext] #downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted@2x.png"), 72, 396, 108, 360);
}
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -106,28 +106,38 @@
border: none;
}
#PanelUI-menu-button[badge-status="update-succeeded"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
height: 13px;
}
+#PanelUI-menu-button[badge-status="download-severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="update-failed"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background: #D90000 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
height: 13px;
}
+#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
- background: transparent url(chrome://browser/skin/warning.svg) no-repeat center;
height: 13px;
box-shadow: none;
filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
}
+#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: transparent url(chrome://browser/skin/warning.svg) no-repeat center;
+}
+
+#PanelUI-menu-button[badge-status="download-warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: none;
}
.panel-subviews {
padding: 4px;
background-clip: padding-box;
border-left: 1px solid hsla(210,4%,10%,.3);
--- a/browser/themes/windows/downloads/indicator.css
+++ b/browser/themes/windows/downloads/indicator.css
@@ -39,50 +39,74 @@
#downloads-indicator-icon {
background: var(--downloads-indicator-icon) center no-repeat;
width: 18px;
height: 18px;
background-size: 18px;
}
-toolbar[brighttext] #downloads-button:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon {
+toolbar[brighttext] #downloads-button:not([attention="success"]) > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: var(--downloads-indicator-icon-inverted);
}
-#downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ display: -moz-box;
+ height: 13px;
+ width: 13px;
+ background-size: contain;
+ border: none;
+ box-shadow: none;
+ filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
+}
+
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #D90000 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+ background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
+}
+
+#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
+#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
+ filter: none;
+}
+
+#downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: var(--downloads-indicator-icon-attention);
}
-toolbar[brighttext] #downloads-button[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
+toolbar[brighttext] #downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: var(--downloads-indicator-icon-attention-inverted);
}
-#downloads-button[cui-areatype="menu-panel"][attention] {
+#downloads-button[cui-areatype="menu-panel"][attention="success"] {
list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel.png");
-moz-image-region: auto;
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-button:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: var(--downloads-indicator-icon) center no-repeat;
background-size: 12px;
}
-toolbar[brighttext] #downloads-button:not([counter]):not([attention]) > #downloads-indicator-anchor > #downloads-button-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter]):not([attention="success"]) > #downloads-indicator-anchor > #downloads-button-progress-area > #downloads-indicator-counter {
background-image: var(--downloads-indicator-icon-inverted);
}
-#downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+#downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: var(--downloads-indicator-icon-attention);
}
-toolbar[brighttext] #downloads-button:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
+toolbar[brighttext] #downloads-button:not([counter])[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: var(--downloads-indicator-icon-attention-inverted);
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;