mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 19:38:13 +00:00
Backed out changesets c2ea3fb28c45 (bug 812343), 68e26307643e (bug 812345), 15eaadc2cd9a (bug 811076), and 5a98a1662e64 (bug 808277) for mochitest-1 failures.
CLOSED TREE
This commit is contained in:
parent
8a64b526bc
commit
2006509e4a
@ -24,16 +24,8 @@
|
||||
<xul:image class="downloadTypeIcon blockedIcon"/>
|
||||
<xul:vbox pack="center"
|
||||
flex="1">
|
||||
<!-- We're letting localizers put a min-width in here primarily
|
||||
because of the downloads summary at the bottom of the list of
|
||||
download items. An element in the summary has the same min-width
|
||||
on a description, and we don't want the panel to change size if the
|
||||
summary isn't being displayed, so we ensure that items share the
|
||||
same minimum width.
|
||||
-->
|
||||
<xul:description class="downloadTarget"
|
||||
crop="center"
|
||||
style="min-width: &downloadsSummary.minWidth;"
|
||||
xbl:inherits="value=target,tooltiptext=target"/>
|
||||
<xul:progressmeter anonid="progressmeter"
|
||||
class="downloadProgress"
|
||||
|
@ -89,8 +89,3 @@ richlistitem[type="download"]:not([selected]) button {
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#downloadsSummary:not([inprogress="true"]) #downloadsSummaryProgress,
|
||||
#downloadsSummary:not([inprogress="true"]) #downloadsSummaryDetails {
|
||||
display: none;
|
||||
}
|
||||
|
@ -540,10 +540,11 @@ const DownloadsView = {
|
||||
DownloadsPanel.panel.removeAttribute("hasdownloads");
|
||||
}
|
||||
|
||||
// If we've got some hidden downloads, we should show the summary just
|
||||
// below the list.
|
||||
this.downloadsHistory.collapsed = hiddenCount > 0;
|
||||
DownloadsSummary.visible = this.downloadsHistory.collapsed;
|
||||
let s = DownloadsCommon.strings;
|
||||
this.downloadsHistory.label = (hiddenCount > 0)
|
||||
? s.showMoreDownloads(hiddenCount)
|
||||
: s.showAllDownloads;
|
||||
this.downloadsHistory.accessKey = s.showDownloadsAccessKey;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1408,155 +1409,3 @@ DownloadsViewItemController.prototype = {
|
||||
protocolSvc.loadUrl(makeFileURI(aFile));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsSummary
|
||||
|
||||
/**
|
||||
* Manages the summary at the bottom of the downloads panel list if the number
|
||||
* of items in the list exceeds the panels limit.
|
||||
*/
|
||||
const DownloadsSummary = {
|
||||
|
||||
/**
|
||||
* Sets the collapsed state of the summary, and automatically subscribes or
|
||||
* unsubscribes from the DownloadsCommon DownloadsSummaryData singleton.
|
||||
*
|
||||
* @param aVisible
|
||||
* True if the summary should be shown.
|
||||
*/
|
||||
set visible(aVisible)
|
||||
{
|
||||
if (aVisible == this._visible || !this._summaryNode) {
|
||||
return;
|
||||
}
|
||||
if (aVisible) {
|
||||
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
|
||||
.addView(this);
|
||||
} else {
|
||||
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
|
||||
.removeView(this);
|
||||
}
|
||||
this._summaryNode.collapsed = !aVisible;
|
||||
return this._visible = aVisible;
|
||||
},
|
||||
_visible: false,
|
||||
|
||||
/**
|
||||
* Sets whether or not we show the progress bar.
|
||||
*
|
||||
* @param aShowingProgress
|
||||
* True if we should show the progress bar.
|
||||
*/
|
||||
set showingProgress(aShowingProgress)
|
||||
{
|
||||
if (aShowingProgress) {
|
||||
this._summaryNode.setAttribute("inprogress", "true");
|
||||
} else {
|
||||
this._summaryNode.removeAttribute("inprogress");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the amount of progress that is visible in the progress bar.
|
||||
*
|
||||
* @param aValue
|
||||
* A value between 0 and 100 to represent the progress of the
|
||||
* summarized downloads.
|
||||
*/
|
||||
set percentComplete(aValue)
|
||||
{
|
||||
if (this._progressNode) {
|
||||
this._progressNode.setAttribute("value", aValue);
|
||||
}
|
||||
return aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the description for the download summary.
|
||||
*
|
||||
* @param aValue
|
||||
* A string representing the description of the summarized
|
||||
* downloads.
|
||||
*/
|
||||
set description(aValue)
|
||||
{
|
||||
if (this._descriptionNode) {
|
||||
this._descriptionNode.setAttribute("value", aValue);
|
||||
this._descriptionNode.setAttribute("tooltiptext", aValue);
|
||||
}
|
||||
return aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the details for the download summary, such as the time remaining,
|
||||
* the amount of bytes transferred, etc.
|
||||
*
|
||||
* @param aValue
|
||||
* A string representing the details of the summarized
|
||||
* downloads.
|
||||
*/
|
||||
set details(aValue)
|
||||
{
|
||||
if (this._detailsNode) {
|
||||
this._detailsNode.setAttribute("value", aValue);
|
||||
this._detailsNode.setAttribute("tooltiptext", aValue);
|
||||
}
|
||||
return aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Element corresponding to the root of the downloads summary.
|
||||
*/
|
||||
get _summaryNode()
|
||||
{
|
||||
let node = document.getElementById("downloadsSummary");
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
delete this._summaryNode;
|
||||
return this._summaryNode = node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Element corresponding to the progress bar in the downloads summary.
|
||||
*/
|
||||
get _progressNode()
|
||||
{
|
||||
let node = document.getElementById("downloadsSummaryProgress");
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
delete this._progressNode;
|
||||
return this._progressNode = node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Element corresponding to the main description of the downloads
|
||||
* summary.
|
||||
*/
|
||||
get _descriptionNode()
|
||||
{
|
||||
let node = document.getElementById("downloadsSummaryDescription");
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
delete this._descriptionNode;
|
||||
return this._descriptionNode = node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Element corresponding to the secondary description of the downloads
|
||||
* summary.
|
||||
*/
|
||||
get _detailsNode()
|
||||
{
|
||||
let node = document.getElementById("downloadsSummaryDetails");
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
delete this._detailsNode;
|
||||
return this._detailsNode = node;
|
||||
}
|
||||
}
|
||||
|
@ -105,32 +105,8 @@
|
||||
oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
|
||||
ondragstart="DownloadsView.onDownloadDragStart(event);"/>
|
||||
|
||||
<hbox id="downloadsSummary"
|
||||
collapsed="true"
|
||||
align="center"
|
||||
orient="horizontal"
|
||||
onclick="DownloadsPanel.showDownloadsHistory();">
|
||||
<image class="downloadTypeIcon" />
|
||||
<vbox>
|
||||
<description id="downloadsSummaryDescription"
|
||||
class="downloadTarget"
|
||||
style="min-width: &downloadsSummary.minWidth;"/>
|
||||
<progressmeter id="downloadsSummaryProgress"
|
||||
class="downloadProgress"
|
||||
min="0"
|
||||
max="100"
|
||||
mode="normal" />
|
||||
<description id="downloadsSummaryDetails"
|
||||
class="downloadDetails"
|
||||
style="width: &downloadDetails.width;"
|
||||
crop="end"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<button id="downloadsHistory"
|
||||
class="plain"
|
||||
label="&downloadsHistory.label;"
|
||||
accesskey="&downloadsHistory.accesskey;"
|
||||
oncommand="DownloadsPanel.showDownloadsHistory();"/>
|
||||
</panel>
|
||||
</popupset>
|
||||
|
@ -54,8 +54,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||
"resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
const nsIDM = Ci.nsIDownloadManager;
|
||||
|
||||
@ -74,7 +72,7 @@ const kDownloadsStringsRequiringFormatting = {
|
||||
};
|
||||
|
||||
const kDownloadsStringsRequiringPluralForm = {
|
||||
otherDownloads: true
|
||||
showMoreDownloads: true
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DownloadsLocalFileCtor", function () {
|
||||
@ -186,145 +184,7 @@ this.DownloadsCommon = {
|
||||
* This does not need to be a lazy getter, since no initialization is required
|
||||
* at present.
|
||||
*/
|
||||
get indicatorData() DownloadsIndicatorData,
|
||||
|
||||
/**
|
||||
* Returns a reference to the DownloadsSummaryData singleton - creating one
|
||||
* in the process if one hasn't been instantiated yet.
|
||||
*
|
||||
* @param aNumToExclude
|
||||
* The number of items on the top of the downloads list to exclude
|
||||
* from the summary.
|
||||
*/
|
||||
_summary: null,
|
||||
getSummary: function DC_getSummary(aNumToExclude)
|
||||
{
|
||||
if (this._summary) {
|
||||
return this._summary;
|
||||
}
|
||||
return this._summary = new DownloadsSummaryData(aNumToExclude);
|
||||
},
|
||||
|
||||
/**
|
||||
* Given an iterable collection of nsIDownload's, generates and returns
|
||||
* statistics about that collection.
|
||||
*
|
||||
* @param aDownloads An iterable collection of nsIDownloads.
|
||||
*
|
||||
* @return Object whose properties are the generated statistics. Currently,
|
||||
* we return the following properties:
|
||||
*
|
||||
* numActive : The total number of downloads.
|
||||
* numPaused : The total number of paused downloads.
|
||||
* numScanning : The total number of downloads being scanned.
|
||||
* numDownloading : The total number of downloads being downloaded.
|
||||
* totalSize : The total size of all downloads once completed.
|
||||
* totalTransferred: The total amount of transferred data for these
|
||||
* downloads.
|
||||
* slowestSpeed : The slowest download rate.
|
||||
* rawTimeLeft : The estimated time left for the downloads to
|
||||
* complete.
|
||||
* percentComplete : The percentage of bytes successfully downloaded.
|
||||
*/
|
||||
summarizeDownloads: function DC_summarizeDownloads(aDownloads)
|
||||
{
|
||||
let summary = {
|
||||
numActive: 0,
|
||||
numPaused: 0,
|
||||
numScanning: 0,
|
||||
numDownloading: 0,
|
||||
totalSize: 0,
|
||||
totalTransferred: 0,
|
||||
// slowestSpeed is Infinity so that we can use Math.min to
|
||||
// find the slowest speed. We'll set this to 0 afterwards if
|
||||
// it's still at Infinity by the time we're done iterating all
|
||||
// downloads.
|
||||
slowestSpeed: Infinity,
|
||||
rawTimeLeft: -1,
|
||||
percentComplete: -1
|
||||
}
|
||||
|
||||
// If no download has been loaded, don't use the methods of the Download
|
||||
// Manager service, so that it is not initialized unnecessarily.
|
||||
for (let download of aDownloads) {
|
||||
summary.numActive++;
|
||||
switch (download.state) {
|
||||
case nsIDM.DOWNLOAD_PAUSED:
|
||||
summary.numPaused++;
|
||||
break;
|
||||
case nsIDM.DOWNLOAD_SCANNING:
|
||||
summary.numScanning++;
|
||||
break;
|
||||
case nsIDM.DOWNLOAD_DOWNLOADING:
|
||||
summary.numDownloading++;
|
||||
if (download.size > 0 && download.speed > 0) {
|
||||
let sizeLeft = download.size - download.amountTransferred;
|
||||
summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
|
||||
sizeLeft / download.speed);
|
||||
summary.slowestSpeed = Math.min(summary.slowestSpeed,
|
||||
download.speed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Only add to total values if we actually know the download size.
|
||||
if (download.size > 0 &&
|
||||
download.state != nsIDM.DOWNLOAD_CANCELED &&
|
||||
download.state != nsIDM.DOWNLOAD_FAILED) {
|
||||
summary.totalSize += download.size;
|
||||
summary.totalTransferred += download.amountTransferred;
|
||||
}
|
||||
}
|
||||
|
||||
if (summary.numActive != 0 && summary.totalSize != 0 &&
|
||||
summary.numActive != summary.numScanning) {
|
||||
summary.percentComplete = (summary.totalTransferred /
|
||||
summary.totalSize) * 100;
|
||||
}
|
||||
|
||||
if (summary.slowestSpeed == Infinity) {
|
||||
summary.slowestSpeed = 0;
|
||||
}
|
||||
|
||||
return summary;
|
||||
},
|
||||
|
||||
/**
|
||||
* If necessary, smooths the estimated number of seconds remaining for one
|
||||
* or more downloads to complete.
|
||||
*
|
||||
* @param aSeconds
|
||||
* Current raw estimate on number of seconds left for one or more
|
||||
* downloads. This is a floating point value to help get sub-second
|
||||
* accuracy for current and future estimates.
|
||||
*/
|
||||
smoothSeconds: function DC_smoothSeconds(aSeconds, aLastSeconds)
|
||||
{
|
||||
// We apply an algorithm similar to the DownloadUtils.getTimeLeft function,
|
||||
// though tailored to a single time estimation for all downloads. We never
|
||||
// apply sommothing if the new value is less than half the previous value.
|
||||
let shouldApplySmoothing = aLastSeconds >= 0 &&
|
||||
aSeconds > aLastSeconds / 2;
|
||||
if (shouldApplySmoothing) {
|
||||
// Apply hysteresis to favor downward over upward swings. Trust only 30%
|
||||
// of the new value if lower, and 10% if higher (exponential smoothing).
|
||||
let (diff = aSeconds - aLastSeconds) {
|
||||
aSeconds = aLastSeconds + (diff < 0 ? .3 : .1) * diff;
|
||||
}
|
||||
|
||||
// If the new time is similar, reuse something close to the last time
|
||||
// left, but subtract a little to provide forward progress.
|
||||
let diff = aSeconds - aLastSeconds;
|
||||
let diffPercent = diff / aLastSeconds * 100;
|
||||
if (Math.abs(diff) < 5 || Math.abs(diffPercent) < 5) {
|
||||
aSeconds = aLastSeconds - (diff < 0 ? .4 : .2);
|
||||
}
|
||||
}
|
||||
|
||||
// In the last few seconds of downloading, we are always subtracting and
|
||||
// never adding to the time left. Ensure that we never fall below one
|
||||
// second left until all downloads are actually finished.
|
||||
return aLastSeconds = Math.max(aSeconds, 1);
|
||||
}
|
||||
get indicatorData() DownloadsIndicatorData
|
||||
};
|
||||
|
||||
/**
|
||||
@ -753,7 +613,6 @@ const DownloadsData = {
|
||||
dataItem.startTime = Math.round(aDownload.startTime / 1000);
|
||||
dataItem.currBytes = aDownload.amountTransferred;
|
||||
dataItem.maxBytes = aDownload.size;
|
||||
dataItem.download = aDownload;
|
||||
|
||||
this._views.forEach(
|
||||
function (view) view.getViewItem(dataItem).onStateChange()
|
||||
@ -1060,13 +919,19 @@ DownloadsDataItem.prototype = {
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsViewPrototype
|
||||
//// DownloadsIndicatorData
|
||||
|
||||
/**
|
||||
* A prototype for an object that registers itself with DownloadsData as soon
|
||||
* as a view is registered with it.
|
||||
* This object registers itself with DownloadsData as a view, and transforms the
|
||||
* notifications it receives into overall status data, that is then broadcast to
|
||||
* the registered download status indicators.
|
||||
*
|
||||
* Note that using this object does not automatically start the Download Manager
|
||||
* service. Consumers will see an empty list of downloads until the service is
|
||||
* actually started. This is useful to display a neutral progress indicator in
|
||||
* the main browser window until the autostart timeout elapses.
|
||||
*/
|
||||
const DownloadsViewPrototype = {
|
||||
const DownloadsIndicatorData = {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Registration of views
|
||||
|
||||
@ -1081,10 +946,10 @@ const DownloadsViewPrototype = {
|
||||
* The specified object is initialized with the currently available status.
|
||||
*
|
||||
* @param aView
|
||||
* View object to be added. This reference must be
|
||||
* DownloadsIndicatorView object to be added. This reference must be
|
||||
* passed to removeView before termination.
|
||||
*/
|
||||
addView: function DVP_addView(aView)
|
||||
addView: function DID_addView(aView)
|
||||
{
|
||||
// Start receiving events when the first of our views is registered.
|
||||
if (this._views.length == 0) {
|
||||
@ -1099,12 +964,11 @@ const DownloadsViewPrototype = {
|
||||
* Updates the properties of an object previously added using addView.
|
||||
*
|
||||
* @param aView
|
||||
* View object to be updated.
|
||||
* DownloadsIndicatorView object to be updated.
|
||||
*/
|
||||
refreshView: function DVP_refreshView(aView)
|
||||
refreshView: function DID_refreshView(aView)
|
||||
{
|
||||
// Update immediately even if we are still loading data asynchronously.
|
||||
// Subclasses must provide these two functions!
|
||||
this._refreshProperties();
|
||||
this._updateView(aView);
|
||||
},
|
||||
@ -1113,9 +977,9 @@ const DownloadsViewPrototype = {
|
||||
* Removes an object previously added using addView.
|
||||
*
|
||||
* @param aView
|
||||
* View object to be removed.
|
||||
* DownloadsIndicatorView object to be removed.
|
||||
*/
|
||||
removeView: function DVP_removeView(aView)
|
||||
removeView: function DID_removeView(aView)
|
||||
{
|
||||
let index = this._views.indexOf(aView);
|
||||
if (index != -1) {
|
||||
@ -1125,6 +989,7 @@ const DownloadsViewPrototype = {
|
||||
// Stop receiving events when the last of our views is unregistered.
|
||||
if (this._views.length == 0) {
|
||||
DownloadsCommon.data.removeView(this);
|
||||
this._itemCount = 0;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1139,142 +1004,17 @@ const DownloadsViewPrototype = {
|
||||
/**
|
||||
* Called before multiple downloads are about to be loaded.
|
||||
*/
|
||||
onDataLoadStarting: function DVP_onDataLoadStarting()
|
||||
onDataLoadStarting: function DID_onDataLoadStarting()
|
||||
{
|
||||
this._loading = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called after data loading finished.
|
||||
*/
|
||||
onDataLoadCompleted: function DVP_onDataLoadCompleted()
|
||||
{
|
||||
this._loading = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the downloads database becomes unavailable (for example, we
|
||||
* entered Private Browsing Mode and the database backend changed).
|
||||
* References to existing data should be discarded.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
onDataInvalidated: function DVP_onDataInvalidated()
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new download data item is available, either during the
|
||||
* asynchronous data load or when a new download is started.
|
||||
*
|
||||
* @param aDataItem
|
||||
* DownloadsDataItem object that was just added.
|
||||
* @param aNewest
|
||||
* When true, indicates that this item is the most recent and should be
|
||||
* added in the topmost position. This happens when a new download is
|
||||
* started. When false, indicates that the item is the least recent
|
||||
* with regard to the items that have been already added. The latter
|
||||
* generally happens during the asynchronous data load.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
onDataItemAdded: function DVP_onDataItemAdded(aDataItem, aNewest)
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a data item is removed, ensures that the widget associated with
|
||||
* the view item is removed from the user interface.
|
||||
*
|
||||
* @param aDataItem
|
||||
* DownloadsDataItem object that is being removed.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
onDataItemRemoved: function DVP_onDataItemRemoved(aDataItem)
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the view item associated with the provided data item for this view.
|
||||
*
|
||||
* @param aDataItem
|
||||
* DownloadsDataItem object for which the view item is requested.
|
||||
*
|
||||
* @return Object that can be used to notify item status events.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
getViewItem: function DID_getViewItem(aDataItem)
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Private function used to refresh the internal properties being sent to
|
||||
* each registered view.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
_refreshProperties: function DID_refreshProperties()
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Private function used to refresh an individual view.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
_updateView: function DID_updateView()
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsIndicatorData
|
||||
|
||||
/**
|
||||
* This object registers itself with DownloadsData as a view, and transforms the
|
||||
* notifications it receives into overall status data, that is then broadcast to
|
||||
* the registered download status indicators.
|
||||
*
|
||||
* Note that using this object does not automatically start the Download Manager
|
||||
* service. Consumers will see an empty list of downloads until the service is
|
||||
* actually started. This is useful to display a neutral progress indicator in
|
||||
* the main browser window until the autostart timeout elapses.
|
||||
*/
|
||||
const DownloadsIndicatorData = {
|
||||
__proto__: DownloadsViewPrototype,
|
||||
|
||||
/**
|
||||
* Removes an object previously added using addView.
|
||||
*
|
||||
* @param aView
|
||||
* DownloadsIndicatorView object to be removed.
|
||||
*/
|
||||
removeView: function DID_removeView(aView)
|
||||
{
|
||||
DownloadsViewPrototype.removeView.call(this, aView);
|
||||
|
||||
if (this._views.length == 0) {
|
||||
this._itemCount = 0;
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Callback functions from DownloadsData
|
||||
|
||||
/**
|
||||
* Called after data loading finished.
|
||||
*/
|
||||
onDataLoadCompleted: function DID_onDataLoadCompleted()
|
||||
{
|
||||
DownloadsViewPrototype.onDataLoadCompleted.call(this);
|
||||
this._loading = false;
|
||||
this._updateViews();
|
||||
},
|
||||
|
||||
@ -1439,21 +1179,40 @@ const DownloadsIndicatorData = {
|
||||
_lastTimeLeft: -1,
|
||||
|
||||
/**
|
||||
* A generator function for the downloads that this summary is currently
|
||||
* interested in. This generator is passed off to summarizeDownloads in order
|
||||
* to generate statistics about the downloads we care about - in this case,
|
||||
* it's all active downloads.
|
||||
* Update the estimated time until all in-progress downloads will finish.
|
||||
*
|
||||
* @param aSeconds
|
||||
* Current raw estimate on number of seconds left for all downloads.
|
||||
* This is a floating point value to help get sub-second accuracy for
|
||||
* current and future estimates.
|
||||
*/
|
||||
_activeDownloads: function DID_activeDownloads()
|
||||
_updateTimeLeft: function DID_updateTimeLeft(aSeconds)
|
||||
{
|
||||
// If no download has been loaded, don't use the methods of the Download
|
||||
// Manager service, so that it is not initialized unnecessarily.
|
||||
if (this._itemCount > 0) {
|
||||
let downloads = Services.downloads.activeDownloads;
|
||||
while (downloads.hasMoreElements()) {
|
||||
yield downloads.getNext().QueryInterface(Ci.nsIDownload);
|
||||
// We apply an algorithm similar to the DownloadUtils.getTimeLeft function,
|
||||
// though tailored to a single time estimation for all downloads. We never
|
||||
// apply sommothing if the new value is less than half the previous value.
|
||||
let shouldApplySmoothing = this._lastTimeLeft >= 0 &&
|
||||
aSeconds > this._lastTimeLeft / 2;
|
||||
if (shouldApplySmoothing) {
|
||||
// Apply hysteresis to favor downward over upward swings. Trust only 30%
|
||||
// of the new value if lower, and 10% if higher (exponential smoothing).
|
||||
let (diff = aSeconds - this._lastTimeLeft) {
|
||||
aSeconds = this._lastTimeLeft + (diff < 0 ? .3 : .1) * diff;
|
||||
}
|
||||
|
||||
// If the new time is similar, reuse something close to the last time
|
||||
// left, but subtract a little to provide forward progress.
|
||||
let diff = aSeconds - this._lastTimeLeft;
|
||||
let diffPercent = diff / this._lastTimeLeft * 100;
|
||||
if (Math.abs(diff) < 5 || Math.abs(diffPercent) < 5) {
|
||||
aSeconds = this._lastTimeLeft - (diff < 0 ? .4 : .2);
|
||||
}
|
||||
}
|
||||
|
||||
// In the last few seconds of downloading, we are always subtracting and
|
||||
// never adding to the time left. Ensure that we never fall below one
|
||||
// second left until all downloads are actually finished.
|
||||
this._lastTimeLeft = Math.max(aSeconds, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1461,236 +1220,69 @@ const DownloadsIndicatorData = {
|
||||
*/
|
||||
_refreshProperties: function DID_refreshProperties()
|
||||
{
|
||||
let summary =
|
||||
DownloadsCommon.summarizeDownloads(this._activeDownloads());
|
||||
let numActive = 0;
|
||||
let numPaused = 0;
|
||||
let numScanning = 0;
|
||||
let totalSize = 0;
|
||||
let totalTransferred = 0;
|
||||
let rawTimeLeft = -1;
|
||||
|
||||
// If no download has been loaded, don't use the methods of the Download
|
||||
// Manager service, so that it is not initialized unnecessarily.
|
||||
if (this._itemCount > 0) {
|
||||
let downloads = Services.downloads.activeDownloads;
|
||||
while (downloads.hasMoreElements()) {
|
||||
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
|
||||
numActive++;
|
||||
switch (download.state) {
|
||||
case nsIDM.DOWNLOAD_PAUSED:
|
||||
numPaused++;
|
||||
break;
|
||||
case nsIDM.DOWNLOAD_SCANNING:
|
||||
numScanning++;
|
||||
break;
|
||||
case nsIDM.DOWNLOAD_DOWNLOADING:
|
||||
if (download.size > 0 && download.speed > 0) {
|
||||
let sizeLeft = download.size - download.amountTransferred;
|
||||
rawTimeLeft = Math.max(rawTimeLeft, sizeLeft / download.speed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Only add to total values if we actually know the download size.
|
||||
if (download.size > 0) {
|
||||
totalSize += download.size;
|
||||
totalTransferred += download.amountTransferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if the indicator should be shown or get attention.
|
||||
this._hasDownloads = (this._itemCount > 0);
|
||||
|
||||
// If all downloads are paused, show the progress indicator as paused.
|
||||
this._paused = summary.numActive > 0 &&
|
||||
summary.numActive == summary.numPaused;
|
||||
if (numActive == 0 || totalSize == 0 || numActive == numScanning) {
|
||||
// Don't display the current progress.
|
||||
this._percentComplete = -1;
|
||||
} else {
|
||||
// Display the current progress.
|
||||
this._percentComplete = (totalTransferred / totalSize) * 100;
|
||||
}
|
||||
|
||||
this._percentComplete = summary.percentComplete;
|
||||
// If all downloads are paused, show the progress indicator as paused.
|
||||
this._paused = numActive > 0 && numActive == numPaused;
|
||||
|
||||
// Display the estimated time left, if present.
|
||||
if (summary.rawTimeLeft == -1) {
|
||||
if (rawTimeLeft == -1) {
|
||||
// There are no downloads with a known time left.
|
||||
this._lastRawTimeLeft = -1;
|
||||
this._lastTimeLeft = -1;
|
||||
this._counter = "";
|
||||
} else {
|
||||
// Compute the new time left only if state actually changed.
|
||||
if (this._lastRawTimeLeft != summary.rawTimeLeft) {
|
||||
this._lastRawTimeLeft = summary.rawTimeLeft;
|
||||
this._lastTimeLeft = DownloadsCommon.smoothSeconds(summary.rawTimeLeft,
|
||||
this._lastTimeLeft);
|
||||
if (this._lastRawTimeLeft != rawTimeLeft) {
|
||||
this._lastRawTimeLeft = rawTimeLeft;
|
||||
this._updateTimeLeft(rawTimeLeft);
|
||||
}
|
||||
this._counter = DownloadsCommon.formatTimeLeft(this._lastTimeLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsSummaryData
|
||||
|
||||
/**
|
||||
* DownloadsSummaryData is a view for DownloadsData that produces a summary
|
||||
* of all downloads after a certain exclusion point aNumToExclude. For example,
|
||||
* if there were 5 downloads in progress, and a DownloadsSummaryData was
|
||||
* constructed with aNumToExclude equal to 3, then that DownloadsSummaryData
|
||||
* would produce a summary of the last 2 downloads.
|
||||
*
|
||||
* @param aNumToExclude
|
||||
* The number of items to exclude from the summary, starting from the
|
||||
* top of the list.
|
||||
*/
|
||||
function DownloadsSummaryData(aNumToExclude) {
|
||||
this._numToExclude = aNumToExclude;
|
||||
// Since we can have multiple instances of DownloadsSummaryData, we
|
||||
// override these values from the prototype so that each instance can be
|
||||
// completely separated from one another.
|
||||
this._views = [];
|
||||
this._loading = false;
|
||||
|
||||
this._dataItems = [];
|
||||
|
||||
// Floating point value indicating the last number of seconds estimated until
|
||||
// the longest download will finish. We need to store this value so that we
|
||||
// don't continuously apply smoothing if the actual download state has not
|
||||
// changed. This is set to -1 if the previous value is unknown.
|
||||
this._lastRawTimeLeft = -1;
|
||||
|
||||
// Last number of seconds estimated until all in-progress downloads with a
|
||||
// known size and speed will finish. This value is stored to allow smoothing
|
||||
// in case of small variations. This is set to -1 if the previous value is
|
||||
// unknown.
|
||||
this._lastTimeLeft = -1;
|
||||
|
||||
// The following properties are updated by _refreshProperties and are then
|
||||
// propagated to the views.
|
||||
this._showingProgress = false;
|
||||
this._details = "";
|
||||
this._description = "";
|
||||
this._numActive = 0;
|
||||
this._percentComplete = -1;
|
||||
}
|
||||
|
||||
DownloadsSummaryData.prototype = {
|
||||
__proto__: DownloadsViewPrototype,
|
||||
|
||||
/**
|
||||
* Removes an object previously added using addView.
|
||||
*
|
||||
* @param aView
|
||||
* DownloadsSummary view to be removed.
|
||||
*/
|
||||
removeView: function DSD_removeView(aView)
|
||||
{
|
||||
DownloadsViewPrototype.removeView.call(this, aView);
|
||||
|
||||
if (this._views.length == 0) {
|
||||
// Clear out our collection of DownloadsDataItems. If we ever have
|
||||
// another view registered with us, this will get re-populated.
|
||||
this._dataItems = [];
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Callback functions from DownloadsData - see the documentation in
|
||||
//// DownloadsViewPrototype for more information on what these functions
|
||||
//// are used for.
|
||||
|
||||
onDataLoadCompleted: function DSD_onDataLoadCompleted()
|
||||
{
|
||||
DownloadsViewPrototype.onDataLoadCompleted.call(this);
|
||||
this._updateViews();
|
||||
},
|
||||
|
||||
onDataInvalidated: function DSD_onDataInvalidated()
|
||||
{
|
||||
this._dataItems = [];
|
||||
},
|
||||
|
||||
onDataItemAdded: function DSD_onDataItemAdded(aDataItem, aNewest)
|
||||
{
|
||||
if (aNewest) {
|
||||
this._dataItems.unshift(aDataItem);
|
||||
} else {
|
||||
this._dataItems.push(aDataItem);
|
||||
}
|
||||
|
||||
this._updateViews();
|
||||
},
|
||||
|
||||
onDataItemRemoved: function DSD_onDataItemRemoved(aDataItem)
|
||||
{
|
||||
let itemIndex = this._dataItems.indexOf(aDataItem);
|
||||
this._dataItems.splice(itemIndex, 1);
|
||||
this._updateViews();
|
||||
},
|
||||
|
||||
getViewItem: function DSD_getViewItem(aDataItem)
|
||||
{
|
||||
let self = this;
|
||||
return Object.freeze({
|
||||
onStateChange: function DIVI_onStateChange()
|
||||
{
|
||||
// Since the state of a download changed, reset the estimated time left.
|
||||
self._lastRawTimeLeft = -1;
|
||||
self._lastTimeLeft = -1;
|
||||
self._updateViews();
|
||||
},
|
||||
onProgressChange: function DIVI_onProgressChange()
|
||||
{
|
||||
self._updateViews();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Propagation of properties to our views
|
||||
|
||||
/**
|
||||
* Computes aggregate values and propagates the changes to our views.
|
||||
*/
|
||||
_updateViews: function DSD_updateViews()
|
||||
{
|
||||
// Do not update the status indicators during batch loads of download items.
|
||||
if (this._loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._refreshProperties();
|
||||
this._views.forEach(this._updateView, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the specified view with the current aggregate values.
|
||||
*
|
||||
* @param aView
|
||||
* DownloadsIndicatorView object to be updated.
|
||||
*/
|
||||
_updateView: function DSD_updateView(aView)
|
||||
{
|
||||
aView.showingProgress = this._showingProgress;
|
||||
aView.percentComplete = this._percentComplete;
|
||||
aView.description = this._description;
|
||||
aView.details = this._details;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Property updating based on current download status
|
||||
|
||||
/**
|
||||
* A generator function for the downloads that this summary is currently
|
||||
* interested in. This generator is passed off to summarizeDownloads in order
|
||||
* to generate statistics about the downloads we care about - in this case,
|
||||
* it's the downloads in this._dataItems after the first few to exclude,
|
||||
* which was set when constructing this DownloadsSummaryData instance.
|
||||
*/
|
||||
_downloadsForSummary: function DSD_downloadsForSummary()
|
||||
{
|
||||
if (this._dataItems.length > 0) {
|
||||
for (let i = this._numToExclude; i < this._dataItems.length; ++i) {
|
||||
yield this._dataItems[i].download;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Computes aggregate values based on the current state of downloads.
|
||||
*/
|
||||
_refreshProperties: function DSD_refreshProperties()
|
||||
{
|
||||
// Pre-load summary with default values.
|
||||
let summary =
|
||||
DownloadsCommon.summarizeDownloads(this._downloadsForSummary());
|
||||
|
||||
this._description = DownloadsCommon.strings
|
||||
.otherDownloads(summary.numActive);
|
||||
this._percentComplete = summary.percentComplete;
|
||||
|
||||
// If all downloads are paused, show the progress indicator as paused.
|
||||
this._showingProgress = summary.numDownloading > 0 ||
|
||||
summary.numPaused > 0;
|
||||
|
||||
// Display the estimated time left, if present.
|
||||
if (summary.rawTimeLeft == -1) {
|
||||
// There are no downloads with a known time left.
|
||||
this._lastRawTimeLeft = -1;
|
||||
this._lastTimeLeft = -1;
|
||||
this._details = "";
|
||||
} else {
|
||||
// Compute the new time left only if state actually changed.
|
||||
if (this._lastRawTimeLeft != summary.rawTimeLeft) {
|
||||
this._lastRawTimeLeft = summary.rawTimeLeft;
|
||||
this._lastTimeLeft = DownloadsCommon.smoothSeconds(summary.rawTimeLeft,
|
||||
this._lastTimeLeft);
|
||||
}
|
||||
[this._details] = DownloadUtils.getDownloadStatusNoRate(
|
||||
summary.totalTransferred, summary.totalSize, summary.slowestSpeed,
|
||||
this._lastTimeLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,21 +25,6 @@
|
||||
-->
|
||||
<!ENTITY downloadDetails.width "50ch">
|
||||
|
||||
<!-- LOCALIZATION NOTE (downloadsSummary.minWidth):
|
||||
Minimum width for the main description of the downloads summary,
|
||||
which is displayed at the bottom of the Downloads Panel if the
|
||||
number of downloads exceeds the limit that the panel can display.
|
||||
|
||||
A good rule of thumb here is to look at the otherDownloads string
|
||||
in downloads.properties, and make a reasonable estimate of its
|
||||
maximum length. For English, this seems like a reasonable limit:
|
||||
|
||||
+999 other current downloads
|
||||
|
||||
that's 28 characters, so we set the minimum width to 28ch.
|
||||
-->
|
||||
<!ENTITY downloadsSummary.minWidth "28ch">
|
||||
|
||||
<!ENTITY cmd.pause.label "Pause">
|
||||
<!ENTITY cmd.pause.accesskey "P">
|
||||
<!ENTITY cmd.resume.label "Resume">
|
||||
@ -65,10 +50,3 @@
|
||||
<!ENTITY cmd.clearList.label "Clear List">
|
||||
<!ENTITY cmd.clearList.accesskey "a">
|
||||
|
||||
<!-- LOCALIZATION NOTE (downloadsHistory.label, downloadsHistory.accesskey):
|
||||
This string is shown at the bottom of the Downloads Panel when all the
|
||||
downloads fit in the available space, or when there are no downloads in
|
||||
the panel at all.
|
||||
-->
|
||||
<!ENTITY downloadsHistory.label "Show All Downloads">
|
||||
<!ENTITY downloadsHistory.accesskey "S">
|
||||
|
@ -67,13 +67,20 @@ shortTimeLeftDays=%1$Sd
|
||||
statusSeparator=%1$S \u2014 %2$S
|
||||
statusSeparatorBeforeNumber=%1$S \u2014 %2$S
|
||||
|
||||
# LOCALIZATION NOTE (showMoreDownloads):
|
||||
# This string is shown in the Downloads Panel when there are more active
|
||||
# downloads than can fit in the available space. The phrase should be read as
|
||||
# "Show N more of my recent downloads". Use a semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/Localization_and_Plurals
|
||||
showMoreDownloads=Show 1 More Recent Download;Show %1$S More Recent Downloads
|
||||
# LOCALIZATION NOTE (showAllDownloads):
|
||||
# This string is shown in place of showMoreDownloads when all the downloads fit
|
||||
# in the available space, or when there are no downloads in the panel at all.
|
||||
showAllDownloads=Show All Downloads
|
||||
# LOCALIZATION NOTE (showDownloadsAccessKey):
|
||||
# This access key applies to both showMoreDownloads and showAllDownloads.
|
||||
showDownloadsAccessKey=S
|
||||
|
||||
fileExecutableSecurityWarning="%S" is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch "%S"?
|
||||
fileExecutableSecurityWarningTitle=Open Executable File?
|
||||
fileExecutableSecurityWarningDontAsk=Don't ask me this again
|
||||
|
||||
# LOCALIZATION NOTE (otherDownloads):
|
||||
# This is displayed in an item at the bottom of the Downloads Panel when
|
||||
# there are more downloads than can fit in the list in the panel. Use a
|
||||
# semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/Localization_and_Plurals
|
||||
otherDownloads=+%1$S other current download; +%1$S other current downloads
|
||||
|
@ -1,4 +1,4 @@
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/* 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/. */
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadsSummary,
|
||||
#downloadsPanel[hasdownloads] > #downloadsHistory {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
|
||||
@ -38,36 +37,17 @@
|
||||
outline: 1px -moz-dialogtext dotted;
|
||||
}
|
||||
|
||||
/*** Downloads Summary and List items ***/
|
||||
/*** List items ***/
|
||||
|
||||
#downloadsSummary,
|
||||
richlistitem[type="download"] {
|
||||
height: 6em;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
padding: 8px 38px 8px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadsSummary > .downloadTypeIcon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
list-style-image: url("chrome://mozapps/skin/downloads/downloadIcon.png");
|
||||
}
|
||||
|
||||
#downloadsSummaryDescription {
|
||||
color: -moz-nativehyperlinktext;
|
||||
}
|
||||
|
||||
richlistitem[type="download"] {
|
||||
margin: 0;
|
||||
border-top: 1px solid hsla(0,0%,100%,.2);
|
||||
border-bottom: 1px solid hsla(0,0%,0%,.15);
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
richlistitem[type="download"]:first-child {
|
||||
@ -284,7 +264,7 @@ toolbar[iconsize="large"] #downloads-indicator[attention] > #downloads-indicator
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-color: rgb(255, 135, 94);
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
|
@ -31,7 +31,6 @@
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
#downloadsSummary,
|
||||
#downloadsPanel[hasdownloads] > #downloadsHistory {
|
||||
background: #e5e5e5;
|
||||
border-top: 1px solid hsla(0,0%,0%,.1);
|
||||
@ -54,34 +53,17 @@
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
||||
|
||||
/*** Downloads Summary and List items ***/
|
||||
/*** List items ***/
|
||||
|
||||
#downloadsSummary,
|
||||
richlistitem[type="download"] {
|
||||
height: 7em;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
padding: 8px 38px 8px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadsSummary > .downloadTypeIcon {
|
||||
list-style-image: url("chrome://mozapps/skin/downloads/downloadIcon.png");
|
||||
}
|
||||
|
||||
#downloadsSummaryDescription {
|
||||
color: -moz-nativehyperlinktext;
|
||||
}
|
||||
|
||||
richlistitem[type="download"] {
|
||||
margin: 0;
|
||||
border-top: 1px solid hsla(0,0%,100%,.07);
|
||||
border-bottom: 1px solid hsla(0,0%,0%,.2);
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
richlistitem[type="download"]:first-child {
|
||||
|
@ -42,7 +42,3 @@
|
||||
0 1px 1.5px rgba(0,0,0,.5);
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-indicator-counter {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
@ -14,10 +14,6 @@
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#downloadsPanel:not([hasdownloads]) > #downloadsListBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downloadsHistory {
|
||||
background: transparent;
|
||||
color: -moz-nativehyperlinktext;
|
||||
@ -29,43 +25,23 @@
|
||||
}
|
||||
|
||||
@media (-moz-windows-default-theme) {
|
||||
#downloadsSummary,
|
||||
#downloadsPanel[hasdownloads] > #downloadsHistory {
|
||||
background-color: hsla(216,45%,88%,.98);
|
||||
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
|
||||
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
|
||||
}
|
||||
}
|
||||
|
||||
/*** Downloads Summary and List items ***/
|
||||
/*** List items ***/
|
||||
|
||||
#downloadsSummary,
|
||||
richlistitem[type="download"] {
|
||||
height: 7em;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
padding: 8px 38px 8px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#downloadsSummary > .downloadTypeIcon {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
list-style-image: url("chrome://mozapps/skin/downloads/downloadIcon.png");
|
||||
}
|
||||
|
||||
#downloadsSummaryDescription {
|
||||
color: -moz-nativehyperlinktext;
|
||||
}
|
||||
|
||||
richlistitem[type="download"] {
|
||||
margin: 0;
|
||||
border-top: 1px solid hsla(0,0%,100%,.3);
|
||||
border-bottom: 1px solid hsla(220,18%,51%,.25);
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
-moz-padding-end: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
richlistitem[type="download"]:first-child {
|
||||
@ -251,12 +227,12 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
/*** Progress bar and text ***/
|
||||
|
||||
#downloads-indicator-counter {
|
||||
height: 9px;
|
||||
margin: -3px 0px 0px 0px;
|
||||
height: 10px;
|
||||
margin: 0;
|
||||
color: hsl(0,0%,30%);
|
||||
text-shadow: hsla(0,0%,100%,.5) 0 1px;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
font-size: 10px;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -268,7 +244,7 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
|
||||
#downloads-indicator-progress {
|
||||
width: 16px;
|
||||
height: 5px;
|
||||
height: 6px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin-top: 1px;
|
||||
@ -281,7 +257,7 @@ richlistitem[type="download"][state="1"]:hover > .downloadButton.downloadShow:ac
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background-color: rgb(90, 201, 66);
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
|
Loading…
Reference in New Issue
Block a user