[PALEMOON] Bug 1117139 - Move code controlling the "download.xml" binding to a common place

This commit is contained in:
janekptacijarabaci 2018-07-29 10:27:51 +02:00 • committed by Roy Tam
commit c66a3e8d83
5 changed files with 60 additions and 429 deletions

View file

@ -7,6 +7,7 @@
<script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/> <script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/> <script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/>
<script type="application/javascript" src="chrome://browser/content/browser.js"/> <script type="application/javascript" src="chrome://browser/content/browser.js"/>
<script type="application/javascript" src="chrome://browser/content/downloads/downloadsViewCommon.js"/>
<script type="application/javascript" src="chrome://browser/content/downloads/downloads.js"/> <script type="application/javascript" src="chrome://browser/content/downloads/downloads.js"/>
<script type="application/javascript" src="chrome://browser/content/downloads/indicator.js"/> <script type="application/javascript" src="chrome://browser/content/downloads/indicator.js"/>
<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/> <script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>

View file

@ -2,31 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/** XPCOMUtils.defineLazyModuleGetter(this, "DownloadsDataItem",
* THE PLACES VIEW IMPLEMENTED IN THIS FILE HAS A VERY PARTICULAR USE CASE. "resource:///modules/DownloadsCommon.jsm");
* IT IS HIGHLY RECOMMENDED NOT TO EXTEND IT FOR ANY OTHER USE CASES OR RELY
* ON IT AS AN API.
*/
var Cu = Components.utils;
var Ci = Components.interfaces;
var Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/DownloadUtils.jsm");
Cu.import("resource:///modules/DownloadsCommon.jsm");
Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow", XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm"); "resource:///modules/RecentWindow.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
const nsIDM = Ci.nsIDownloadManager; const nsIDM = Ci.nsIDownloadManager;
@ -153,12 +132,12 @@ DownloadsHistoryDataItem.prototype = {
* @param [optional] aHistoryDataItem * @param [optional] aHistoryDataItem
* The history download, required if aSessionDataItem is not set. * The history download, required if aSessionDataItem is not set.
*/ */
function DownloadElementShell(aSessionDataItem, aHistoryDataItem) { function HistoryDownloadElementShell(aSessionDataItem, aHistoryDataItem) {
this._element = document.createElement("richlistitem"); this.element = document.createElement("richlistitem");
this._element._shell = this; this.element._shell = this;
this._element.classList.add("download"); this.element.classList.add("download");
this._element.classList.add("download-state"); this.element.classList.add("download-state");
if (aSessionDataItem) { if (aSessionDataItem) {
this.sessionDataItem = aSessionDataItem; this.sessionDataItem = aSessionDataItem;
@ -168,11 +147,8 @@ function DownloadElementShell(aSessionDataItem, aHistoryDataItem) {
} }
} }
DownloadElementShell.prototype = { HistoryDownloadElementShell.prototype = {
/** __proto__: DownloadElementShell.prototype,
* The richlistitem for the download.
*/
get element() this._element,
/** /**
* Manages the "active" state of the shell. By default all the shells without * Manages the "active" state of the shell. By default all the shells without
@ -183,18 +159,12 @@ DownloadElementShell.prototype = {
ensureActive: function DES_ensureActive() { ensureActive: function DES_ensureActive() {
if (!this._active) { if (!this._active) {
this._active = true; this._active = true;
this._element.setAttribute("active", true); this.element.setAttribute("active", true);
this._updateUI(); this._updateUI();
} }
}, },
get active() !!this._active, get active() !!this._active,
/**
* Download or HistoryDownload object to use for displaying information and
* for executing commands in the user interface.
*/
get download() this.dataItem.download,
/** /**
* DownloadsDataItem or DownloadsHistoryDataItem object to use for displaying * DownloadsDataItem or DownloadsHistoryDataItem object to use for displaying
* information and for executing commands in the user interface. * information and for executing commands in the user interface.
@ -236,16 +206,6 @@ DownloadElementShell.prototype = {
return aValue; return aValue;
}, },
// The progressmeter element for the download
get _progressElement() {
if (!("__progressElement" in this)) {
this.__progressElement =
document.getAnonymousElementByAttribute(this._element, "anonid",
"progressmeter");
}
return this.__progressElement;
},
_updateUI() { _updateUI() {
// There is nothing to do if the item has always been invisible. // There is nothing to do if the item has always been invisible.
if (!this.active) { if (!this.active) {
@ -255,168 +215,20 @@ DownloadElementShell.prototype = {
// Since the state changed, we may need to check the target file again. // Since the state changed, we may need to check the target file again.
this._targetFileChecked = false; this._targetFileChecked = false;
this._element.setAttribute("displayName", this.displayName); this._updateState();
this._element.setAttribute("extendedDisplayName", this.extendedDisplayName);
this._element.setAttribute("extendedDisplayNameTip", this.extendedDisplayNameTip);
this._element.setAttribute("image", this.image);
this._updateActiveStatusUI();
}, },
// Updates the download state attribute (and by that hide/unhide the get statusTextAndTip() {
// appropriate buttons and context menu items), the status text label, let status = this.rawStatusTextAndTip;
// and the progress meter.
_updateActiveStatusUI() {
if (!this.active)
throw new Error("_updateActiveStatusUI called for an inactive item.");
this._element.setAttribute("state", this.dataItem.state); // The base object would show extended progress information in the tooltip,
this._element.setAttribute("status", this.statusText); // but we move this to the main view and never display a tooltip.
if (this.dataItem.state == nsIDM.DOWNLOAD_DOWNLOADING) {
// We have update the progress meter only for session downloads. status.text = status.tip;
if (!this._sessionDataItem) {
return;
} }
status.tip = "";
// Copied from updateProgress in downloads.js. return status;
if (this.dataItem.starting) {
// Before the download starts, the progress meter has its initial value.
this._element.setAttribute("progressmode", "normal");
this._element.setAttribute("progress", "0");
} else if (this.dataItem.state == nsIDM.DOWNLOAD_SCANNING ||
this.dataItem.percentComplete == -1) {
// We might not know the progress of a running download, and we don't know
// the remaining time during the malware scanning phase.
this._element.setAttribute("progressmode", "undetermined");
} else {
// This is a running download of which we know the progress.
this._element.setAttribute("progressmode", "normal");
this._element.setAttribute("progress", this.dataItem.percentComplete);
}
// Dispatch the ValueChange event for accessibility, if possible.
if (this._progressElement) {
let event = document.createEvent("Events");
event.initEvent("ValueChange", true, true);
this._progressElement.dispatchEvent(event);
}
},
/**
* URI string for the file type icon displayed in the download element.
*/
get image() {
if (this.download.target.path) {
return "moz-icon://" + this.download.target.path + "?size=32";
}
// Old history downloads may not have a target path.
return "moz-icon://.unknown?size=32";
},
// The status text for the download
/**
* The user-facing label for the download. This is normally the leaf name of
* download target file. In case this is a very old history download for
* which the target file is unknown, the download source URI is displayed.
*/
get displayName() {
if (!this.download.target.path) {
return this.download.source.url;
}
return OS.Path.basename(this.download.target.path);
},
get extendedDisplayName() {
let s = DownloadsCommon.strings;
let referrer = this.dataItem.download.source.referrer ||
this.dataItem.download.source.url;
let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
return s.statusSeparator(this.displayName, displayHost);
},
get extendedDisplayNameTip() {
let s = DownloadsCommon.strings;
let referrer = this.dataItem.download.source.referrer ||
this.dataItem.download.source.url;
let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
return s.statusSeparator(this.displayName, fullHost);
},
get statusText() {
let s = DownloadsCommon.strings;
if (this.dataItem.inProgress) {
if (this.dataItem.paused) {
let transfer =
DownloadUtils.getTransferTotal(this.download.currentBytes,
this.dataItem.maxBytes);
// We use the same XUL label to display both the state and the amount
// transferred, for example "Paused - 1.1 MB".
return s.statusSeparatorBeforeNumber(s.statePaused, transfer);
}
if (this.dataItem.state == nsIDM.DOWNLOAD_DOWNLOADING) {
let [status, newEstimatedSecondsLeft] =
DownloadUtils.getDownloadStatus(this.download.currentBytes,
this.dataItem.maxBytes,
this.download.speed,
this._lastEstimatedSecondsLeft || Infinity);
this._lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
return status;
}
if (this.dataItem.starting) {
return s.stateStarting;
}
if (this.dataItem.state == nsIDM.DOWNLOAD_SCANNING) {
return s.stateScanning;
}
throw new Error("_getStatusText called with a bogus download state");
}
// This is a not-in-progress or history download.
let stateLabel = "";
switch (this.dataItem.state) {
case nsIDM.DOWNLOAD_FAILED:
stateLabel = s.stateFailed;
break;
case nsIDM.DOWNLOAD_CANCELED:
stateLabel = s.stateCanceled;
break;
case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
stateLabel = s.stateBlockedParentalControls;
break;
case nsIDM.DOWNLOAD_BLOCKED_POLICY:
stateLabel = s.stateBlockedPolicy;
break;
case nsIDM.DOWNLOAD_DIRTY:
stateLabel = s.stateDirty;
break;
case nsIDM.DOWNLOAD_FINISHED:
// For completed downloads, show the file size (e.g. "1.5 MB")
if (this.dataItem.maxBytes !== undefined) {
let [size, unit] =
DownloadUtils.convertByteUnits(this.dataItem.maxBytes);
stateLabel = s.sizeWithUnits(size, unit);
break;
}
// Fallback to default unknown state.
default:
stateLabel = s.sizeUnknown;
break;
}
let referrer = this.download.source.referrer ||
this.download.source.url;
let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
let date = new Date(this.dataItem.endTime);
let [displayDate, fullDate] = DownloadUtils.getReadableDates(date);
// We use the same XUL label to display the state, the host name, and the
// end time.
let firstPart = s.statusSeparator(stateLabel, displayHost);
return s.statusSeparator(firstPart, displayDate);
}, },
onStateChanged() { onStateChanged() {
@ -427,17 +239,20 @@ DownloadElementShell.prototype = {
// scheme, this only works if we add one of the parameters explicitly // scheme, this only works if we add one of the parameters explicitly
// supported by the nsIMozIconURI interface. // supported by the nsIMozIconURI interface.
if (this.dataItem.state == nsIDM.DOWNLOAD_FINISHED) { if (this.dataItem.state == nsIDM.DOWNLOAD_FINISHED) {
this._element.setAttribute("image", this.image + "&state=normal"); this.element.setAttribute("image", this.image + "&state=normal");
} }
if (this._element.selected) // Update the user interface after switching states.
this.element.setAttribute("state", this.dataItem.state);
if (this.element.selected) {
goUpdateDownloadCommands(); goUpdateDownloadCommands();
else else
goUpdateCommand("downloadsCmd_clearDownloads"); goUpdateCommand("downloadsCmd_clearDownloads");
}, },
onChanged() { onChanged() {
this._updateActiveStatusUI(); this._updateProgress();
}, },
/* nsIController */ /* nsIController */
@ -615,7 +430,7 @@ DownloadElementShell.prototype = {
} }
// Update the commands only if the element is still selected. // Update the commands only if the element is still selected.
if (this._element.selected) { if (this.element.selected) {
goUpdateDownloadCommands(); goUpdateDownloadCommands();
} }
}), }),
@ -861,7 +676,7 @@ DownloadsPlacesView.prototype = {
historyDataItem = new DownloadsHistoryDataItem(aPlacesNode); historyDataItem = new DownloadsHistoryDataItem(aPlacesNode);
historyDataItem.updateFromMetaData(metaData); historyDataItem.updateFromMetaData(metaData);
} }
let shell = new DownloadElementShell(aDataItem, historyDataItem); let shell = new HistoryDownloadElementShell(aDataItem, historyDataItem);
shell.element._placesNode = aPlacesNode; shell.element._placesNode = aPlacesNode;
newOrUpdatedShell = shell; newOrUpdatedShell = shell;
shellsForURI.add(shell); shellsForURI.add(shell);

View file

@ -34,6 +34,8 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://browser/content/downloads/downloadsViewCommon.js"/>
<script type="application/javascript" <script type="application/javascript"
src="chrome://browser/content/downloads/allDownloadsViewOverlay.js"/> src="chrome://browser/content/downloads/allDownloadsViewOverlay.js"/>
<script type="application/javascript" <script type="application/javascript"

View file

@ -64,22 +64,6 @@
"use strict"; "use strict";
////////////////////////////////////////////////////////////////////////////////
//// Globals
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// DownloadsPanel //// DownloadsPanel
@ -932,7 +916,7 @@ const DownloadsView = {
_removeViewItem: function DV_removeViewItem(aDataItem) _removeViewItem: function DV_removeViewItem(aDataItem)
{ {
DownloadsCommon.log("Removing a DownloadsViewItem from the downloads list."); DownloadsCommon.log("Removing a DownloadsViewItem from the downloads list.");
let element = this._visibleViewItems.get(aDataItem)._element; let element = this._visibleViewItems.get(aDataItem).element;
let previousSelectedIndex = this.richListBox.selectedIndex; let previousSelectedIndex = this.richListBox.selectedIndex;
this.richListBox.removeChild(element); this.richListBox.removeChild(element);
if (previousSelectedIndex != -1) { if (previousSelectedIndex != -1) {
@ -1075,45 +1059,21 @@ XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView);
*/ */
function DownloadsViewItem(aDataItem, aElement) function DownloadsViewItem(aDataItem, aElement)
{ {
this._element = aElement;
this.dataItem = aDataItem; this.dataItem = aDataItem;
this.lastEstimatedSecondsLeft = Infinity; this.element = aElement;
this.element._shell = this;
// Set the URI that represents the correct icon for the target file. As soon this.element.setAttribute("type", "download");
// as bug 239948 comment 12 is handled, the "file" property will be always a this.element.classList.add("download-state");
// file URL rather than a file name. At that point we should remove the "//"
// (double slash) from the icon URI specification (see test_moz_icon_uri.js).
this.image = "moz-icon://" + this.dataItem.download.target.path + "?size=32";
let s = DownloadsCommon.strings; this._updateState();
let [displayHost, fullHost] =
DownloadUtils.getURIHost(this.dataItem.download.source.referrer ||
this.dataItem.download.source.url);
let target = OS.Path.basename(this.dataItem.download.target.path);
let attributes = {
"type": "download",
"class": "download-state",
"state": this.dataItem.state,
"progress": this.dataItem.inProgress ? this.dataItem.percentComplete : 100,
"displayName": target,
"extendedDisplayName": s.statusSeparator(target, displayHost),
"extendedDisplayNameTip": s.statusSeparator(target, fullHost),
"image": this.image
};
for (let attributeName in attributes) {
this._element.setAttribute(attributeName, attributes[attributeName]);
}
// Initialize more complex attributes.
this._updateProgress();
this._updateStatusLine();
this.verifyTargetExists(); this.verifyTargetExists();
} }
DownloadsViewItem.prototype = { DownloadsViewItem.prototype = {
__proto__: DownloadElementShell.prototype,
/** /**
* The DownloadDataItem associated with this view item. * The DownloadDataItem associated with this view item.
*/ */
@ -1124,19 +1084,6 @@ DownloadsViewItem.prototype = {
*/ */
_element: null, _element: null,
/**
* The inner XUL element for the progress bar, or null if not available.
*/
_progressElement: null,
//////////////////////////////////////////////////////////////////////////////
//// Callback functions from DownloadsData
/**
* Called when the download state might have changed. Sometimes the state of
* the download might be the same as before, if the data layer received
* multiple events for the same download.
*/
onStateChanged() { onStateChanged() {
// If a download just finished successfully, it means that the target file // If a download just finished successfully, it means that the target file
// now exists and we can extract its specific icon. To ensure that the icon // now exists and we can extract its specific icon. To ensure that the icon
@ -1145,158 +1092,23 @@ DownloadsViewItem.prototype = {
// scheme, this only works if we add one of the parameters explicitly // scheme, this only works if we add one of the parameters explicitly
// supported by the nsIMozIconURI interface. // supported by the nsIMozIconURI interface.
if (this.dataItem.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) { if (this.dataItem.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) {
this._element.setAttribute("image", this.image + "&state=normal"); this.element.setAttribute("image", this.image + "&state=normal");
// We assume the existence of the target of a download that just completed // We assume the existence of the target of a download that just completed
// successfully, without checking the condition in the background. If the // successfully, without checking the condition in the background. If the
// panel is already open, this will take effect immediately. If the panel // panel is already open, this will take effect immediately. If the panel
// is opened later, a new background existence check will be performed. // is opened later, a new background existence check will be performed.
this._element.setAttribute("exists", "true"); this.element.setAttribute("exists", "true");
} }
// Update the user interface after switching states. // Update the user interface after switching states.
this._element.setAttribute("state", this.dataItem.state); this.element.setAttribute("state", this.dataItem.state);
}, },
/**
* Called when the download progress has changed.
*/
onChanged() { onChanged() {
this._updateProgress(); this._updateProgress();
this._updateStatusLine();
}, },
//////////////////////////////////////////////////////////////////////////////
//// Functions for updating the user interface
/**
* Updates the progress bar.
*/
_updateProgress: function DVI_updateProgress() {
if (this.dataItem.starting) {
// Before the download starts, the progress meter has its initial value.
this._element.setAttribute("progressmode", "normal");
this._element.setAttribute("progress", "0");
} else if (this.dataItem.state == Ci.nsIDownloadManager.DOWNLOAD_SCANNING ||
this.dataItem.percentComplete == -1) {
// We might not know the progress of a running download, and we don't know
// the remaining time during the malware scanning phase.
this._element.setAttribute("progressmode", "undetermined");
} else {
// This is a running download of which we know the progress.
this._element.setAttribute("progressmode", "normal");
this._element.setAttribute("progress", this.dataItem.percentComplete);
}
// Find the progress element as soon as the download binding is accessible.
if (!this._progressElement) {
this._progressElement =
document.getAnonymousElementByAttribute(this._element, "anonid",
"progressmeter");
}
// Dispatch the ValueChange event for accessibility, if possible.
if (this._progressElement) {
let event = document.createEvent("Events");
event.initEvent("ValueChange", true, true);
this._progressElement.dispatchEvent(event);
}
},
/**
* Updates the main status line, including bytes transferred, bytes total,
* download rate, and time remaining.
*/
_updateStatusLine: function DVI_updateStatusLine() {
const nsIDM = Ci.nsIDownloadManager;
let status = "";
let statusTip = "";
if (this.dataItem.paused) {
let transfer = DownloadUtils.getTransferTotal(this.dataItem.download.currentBytes,
this.dataItem.maxBytes);
// We use the same XUL label to display both the state and the amount
// transferred, for example "Paused - 1.1 MB".
status = DownloadsCommon.strings.statusSeparatorBeforeNumber(
DownloadsCommon.strings.statePaused,
transfer);
} else if (this.dataItem.state == nsIDM.DOWNLOAD_DOWNLOADING) {
// We don't show the rate for each download in order to reduce clutter.
// The remaining time per download is likely enough information for the
// panel.
[status] =
DownloadUtils.getDownloadStatusNoRate(this.dataItem.download.currentBytes,
this.dataItem.maxBytes,
this.dataItem.download.speed,
this.lastEstimatedSecondsLeft);
// We are, however, OK with displaying the rate in the tooltip.
let newEstimatedSecondsLeft;
[statusTip, newEstimatedSecondsLeft] =
DownloadUtils.getDownloadStatus(this.dataItem.download.currentBytes,
this.dataItem.maxBytes,
this.dataItem.download.speed,
this.lastEstimatedSecondsLeft);
this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
} else if (this.dataItem.starting) {
status = DownloadsCommon.strings.stateStarting;
} else if (this.dataItem.state == nsIDM.DOWNLOAD_SCANNING) {
status = DownloadsCommon.strings.stateScanning;
} else if (!this.dataItem.inProgress) {
let stateLabel = function () {
let s = DownloadsCommon.strings;
switch (this.dataItem.state) {
case nsIDM.DOWNLOAD_FAILED: return s.stateFailed;
case nsIDM.DOWNLOAD_CANCELED: return s.stateCanceled;
case nsIDM.DOWNLOAD_BLOCKED_PARENTAL: return s.stateBlockedParentalControls;
case nsIDM.DOWNLOAD_BLOCKED_POLICY: return s.stateBlockedPolicy;
case nsIDM.DOWNLOAD_DIRTY: return s.stateDirty;
case nsIDM.DOWNLOAD_FINISHED: return this._fileSizeText;
}
return null;
}.apply(this);
let [displayHost, fullHost] =
DownloadUtils.getURIHost(this.dataItem.download.source.referrer ||
this.dataItem.download.source.url);
let end = new Date(this.dataItem.endTime);
let [displayDate, fullDate] = DownloadUtils.getReadableDates(end);
// We use the same XUL label to display the state, the host name, and the
// end time, for example "Canceled - 222.net - 11:15" or "1.1 MB -
// website2.com - Yesterday". We show the full host and the complete date
// in the tooltip.
let firstPart = DownloadsCommon.strings.statusSeparator(stateLabel,
displayHost);
status = DownloadsCommon.strings.statusSeparator(firstPart, displayDate);
statusTip = DownloadsCommon.strings.statusSeparator(fullHost, fullDate);
}
this._element.setAttribute("status", status);
this._element.setAttribute("statusTip", statusTip || status);
},
/**
* Localized string representing the total size of completed downloads, for
* example "1.5 MB" or "Unknown size".
*/
get _fileSizeText()
{
// Display the file size, but show "Unknown" for negative sizes.
let fileSize = this.dataItem.maxBytes;
if (fileSize < 0) {
return DownloadsCommon.strings.sizeUnknown;
}
let [size, unit] = DownloadUtils.convertByteUnits(fileSize);
return DownloadsCommon.strings.sizeWithUnits(size, unit);
},
//////////////////////////////////////////////////////////////////////////////
//// Functions called by the panel
/** /**
* Starts checking whether the target file of a finished download is still * Starts checking whether the target file of a finished download is still
* available on disk, and sets an attribute that controls how the item is * available on disk, and sets an attribute that controls how the item is
@ -1306,15 +1118,15 @@ DownloadsViewItem.prototype = {
*/ */
verifyTargetExists: function DVI_verifyTargetExists() { verifyTargetExists: function DVI_verifyTargetExists() {
// We don't need to check if the download is not finished successfully. // We don't need to check if the download is not finished successfully.
if (!this.dataItem.download.succeeded) { if (!this.download.succeeded) {
return; return;
} }
OS.File.exists(this.dataItem.download.target.path).then(aExists => { OS.File.exists(this.download.target.path).then(aExists => {
if (aExists) { if (aExists) {
this._element.setAttribute("exists", "true"); this.element.setAttribute("exists", "true");
} else { } else {
this._element.removeAttribute("exists"); this.element.removeAttribute("exists");
} }
}).catch(Cu.reportError); }).catch(Cu.reportError);
}, },

View file

@ -3,16 +3,17 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar: browser.jar:
* content/browser/downloads/download.xml (content/download.xml) * content/browser/downloads/download.xml (content/download.xml)
content/browser/downloads/download.css (content/download.css) content/browser/downloads/download.css (content/download.css)
content/browser/downloads/downloads.css (content/downloads.css) content/browser/downloads/downloads.css (content/downloads.css)
* content/browser/downloads/downloads.js (content/downloads.js) * content/browser/downloads/downloads.js (content/downloads.js)
* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul) content/browser/downloads/downloadsViewCommon.js (content/downloadsViewCommon.js)
content/browser/downloads/indicator.js (content/indicator.js) * content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul) content/browser/downloads/indicator.js (content/indicator.js)
* content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul) content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)
content/browser/downloads/allDownloadsViewOverlay.js (content/allDownloadsViewOverlay.js) * content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul)
content/browser/downloads/allDownloadsViewOverlay.css (content/allDownloadsViewOverlay.css) content/browser/downloads/allDownloadsViewOverlay.js (content/allDownloadsViewOverlay.js)
* content/browser/downloads/contentAreaDownloadsView.xul (content/contentAreaDownloadsView.xul) content/browser/downloads/allDownloadsViewOverlay.css (content/allDownloadsViewOverlay.css)
content/browser/downloads/contentAreaDownloadsView.js (content/contentAreaDownloadsView.js) * content/browser/downloads/contentAreaDownloadsView.xul (content/contentAreaDownloadsView.xul)
content/browser/downloads/contentAreaDownloadsView.css (content/contentAreaDownloadsView.css) content/browser/downloads/contentAreaDownloadsView.js (content/contentAreaDownloadsView.js)
content/browser/downloads/contentAreaDownloadsView.css (content/contentAreaDownloadsView.css)