Bug 1115364 - Downloads Panel code style refresh. r=jaws

This commit is contained in:
Paolo Amadini 2014-12-29 12:35:27 +00:00
Родитель 4b1683e16c
Коммит d4c5c8ca0b
7 изменённых файлов: 571 добавлений и 713 удалений

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

@ -104,7 +104,7 @@ const kPrefBranch = Services.prefs.getBranch("browser.download.");
let PrefObserver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
getPref: function PO_getPref(name) {
getPref(name) {
try {
switch (typeof this.prefs[name]) {
case "boolean":
@ -113,12 +113,13 @@ let PrefObserver = {
} catch (ex) { }
return this.prefs[name];
},
observe: function PO_observe(aSubject, aTopic, aData) {
observe(aSubject, aTopic, aData) {
if (this.prefs.hasOwnProperty(aData)) {
delete this[aData];
return this[aData] = this.getPref(aData);
}
},
register: function PO_register(prefs) {
register(prefs) {
this.prefs = prefs;
kPrefBranch.addObserver("", this, true);
for (let key in prefs) {
@ -152,34 +153,26 @@ this.DownloadsCommon = {
BLOCK_VERDICT_POTENTIALLY_UNWANTED: "PotentiallyUnwanted",
BLOCK_VERDICT_UNCOMMON: "Uncommon",
log: function DC_log(...aMessageArgs) {
delete this.log;
this.log = function DC_log(...aMessageArgs) {
if (!PrefObserver.debug) {
return;
}
DownloadsLogger.log.apply(DownloadsLogger, aMessageArgs);
log(...aMessageArgs) {
if (!PrefObserver.debug) {
return;
}
this.log.apply(this, aMessageArgs);
DownloadsLogger.log(...aMessageArgs);
},
error: function DC_error(...aMessageArgs) {
delete this.error;
this.error = function DC_error(...aMessageArgs) {
if (!PrefObserver.debug) {
return;
}
DownloadsLogger.reportError.apply(DownloadsLogger, aMessageArgs);
error(...aMessageArgs) {
if (!PrefObserver.debug) {
return;
}
this.error.apply(this, aMessageArgs);
DownloadsLogger.reportError(...aMessageArgs);
},
/**
* 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()
{
get strings() {
let strings = {};
let sb = Services.strings.createBundle(kDownloadsStringBundleUrl);
let enumerator = sb.getSimpleEnumeration();
@ -219,8 +212,7 @@ this.DownloadsCommon = {
* @return Formatted string, for example "30s" or "2h". The returned value is
* maximum three characters long, at least in English.
*/
formatTimeLeft: function DC_formatTimeLeft(aSeconds)
{
formatTimeLeft(aSeconds) {
// Decide what text to show for the time
let seconds = Math.round(aSeconds);
if (!seconds) {
@ -244,8 +236,7 @@ this.DownloadsCommon = {
* Indicates whether we should show visual notification on the indicator
* when a download event is triggered.
*/
get animateNotifications()
{
get animateNotifications() {
return PrefObserver.animateNotifications;
},
@ -256,7 +247,7 @@ this.DownloadsCommon = {
* @param aWindow
* The browser window which owns the download button.
*/
getData: function DC_getData(aWindow) {
getData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsData;
} else {
@ -268,7 +259,7 @@ this.DownloadsCommon = {
* Initializes the Downloads back-end and starts receiving events for both the
* private and non-private downloads data objects.
*/
initializeAllDataLinks: function () {
initializeAllDataLinks() {
DownloadsData.initializeDataLink();
PrivateDownloadsData.initializeDataLink();
},
@ -278,7 +269,7 @@ this.DownloadsCommon = {
* PrivateDownloadsIndicatorData objects, depending on the privacy status of
* the window in question.
*/
getIndicatorData: function DC_getIndicatorData(aWindow) {
getIndicatorData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsIndicatorData;
} else {
@ -296,8 +287,7 @@ this.DownloadsCommon = {
* The number of items on the top of the downloads list to exclude
* from the summary.
*/
getSummary: function DC_getSummary(aWindow, aNumToExclude)
{
getSummary(aWindow, aNumToExclude) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
if (this._privateSummary) {
return this._privateSummary;
@ -334,8 +324,7 @@ this.DownloadsCommon = {
* complete.
* percentComplete : The percentage of bytes successfully downloaded.
*/
summarizeDownloads: function DC_summarizeDownloads(aDataItems)
{
summarizeDownloads(aDataItems) {
let summary = {
numActive: 0,
numPaused: 0,
@ -403,8 +392,7 @@ this.DownloadsCommon = {
* downloads. This is a floating point value to help get sub-second
* accuracy for current and future estimates.
*/
smoothSeconds: function DC_smoothSeconds(aSeconds, aLastSeconds)
{
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 something if the new value is less than half the previous value.
@ -441,13 +429,16 @@ this.DownloadsCommon = {
* @param aOwnerWindow
* the window with which this action is associated.
*/
openDownloadedFile: function DC_openDownloadedFile(aFile, aMimeInfo, aOwnerWindow) {
if (!(aFile instanceof Ci.nsIFile))
openDownloadedFile(aFile, aMimeInfo, aOwnerWindow) {
if (!(aFile instanceof Ci.nsIFile)) {
throw new Error("aFile must be a nsIFile object");
if (aMimeInfo && !(aMimeInfo instanceof Ci.nsIMIMEInfo))
}
if (aMimeInfo && !(aMimeInfo instanceof Ci.nsIMIMEInfo)) {
throw new Error("Invalid value passed for aMimeInfo");
if (!(aOwnerWindow instanceof Ci.nsIDOMWindow))
}
if (!(aOwnerWindow instanceof Ci.nsIDOMWindow)) {
throw new Error("aOwnerWindow must be a dom-window object");
}
let promiseShouldLaunch;
if (aFile.isExecutable()) {
@ -471,15 +462,13 @@ this.DownloadsCommon = {
aMimeInfo.launchWithFile(aFile);
return;
}
}
catch(ex) { }
} catch (ex) { }
// If either we don't have the mime info, or the preferred action failed,
// attempt to launch the file directly.
try {
aFile.launch();
}
catch(ex) {
} catch (ex) {
// If launch fails, try sending it through the system's external "file:"
// URL handler.
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
@ -496,9 +485,10 @@ this.DownloadsCommon = {
* @param aFile
* a downloaded file.
*/
showDownloadedFile: function DC_showDownloadedFile(aFile) {
if (!(aFile instanceof Ci.nsIFile))
showDownloadedFile(aFile) {
if (!(aFile instanceof Ci.nsIFile)) {
throw new Error("aFile must be a nsIFile object");
}
try {
// Show the directory containing the file and select the file.
aFile.reveal();
@ -533,7 +523,7 @@ this.DownloadsCommon = {
* @return True to unblock the file, false to keep the user safe and
* cancel the operation.
*/
confirmUnblockDownload: Task.async(function* DP_confirmUnblockDownload(aType, aOwnerWindow) {
confirmUnblockDownload: Task.async(function* (aType, aOwnerWindow) {
let s = DownloadsCommon.strings;
let title = s.unblockHeader;
let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
@ -640,8 +630,7 @@ DownloadsDataCtor.prototype = {
/**
* Starts receiving events for current downloads.
*/
initializeDataLink: function ()
{
initializeDataLink() {
if (!this._dataLinkInitialized) {
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
: Downloads.PUBLIC);
@ -654,8 +643,7 @@ DownloadsDataCtor.prototype = {
/**
* True if there are finished downloads that can be removed from the list.
*/
get canRemoveFinished()
{
get canRemoveFinished() {
for (let [, dataItem] of Iterator(this.dataItems)) {
if (dataItem && !dataItem.inProgress) {
return true;
@ -667,8 +655,7 @@ DownloadsDataCtor.prototype = {
/**
* Asks the back-end to remove finished downloads from the list.
*/
removeFinished: function DD_removeFinished()
{
removeFinished() {
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
: Downloads.PUBLIC);
promiseList.then(list => list.removeFinished())
@ -678,8 +665,7 @@ DownloadsDataCtor.prototype = {
//////////////////////////////////////////////////////////////////////////////
//// Integration with the asynchronous Downloads back-end
onDownloadAdded: function (aDownload)
{
onDownloadAdded(aDownload) {
let dataItem = new DownloadsDataItem(aDownload);
this._downloadToDataItemMap.set(aDownload, dataItem);
this.dataItems[dataItem.downloadGuid] = dataItem;
@ -691,8 +677,7 @@ DownloadsDataCtor.prototype = {
this._updateDataItemState(dataItem);
},
onDownloadChanged: function (aDownload)
{
onDownloadChanged(aDownload) {
let dataItem = this._downloadToDataItemMap.get(aDownload);
if (!dataItem) {
Cu.reportError("Download doesn't exist.");
@ -702,8 +687,7 @@ DownloadsDataCtor.prototype = {
this._updateDataItemState(dataItem);
},
onDownloadRemoved: function (aDownload)
{
onDownloadRemoved(aDownload) {
let dataItem = this._downloadToDataItemMap.get(aDownload);
if (!dataItem) {
Cu.reportError("Download doesn't exist.");
@ -720,8 +704,7 @@ DownloadsDataCtor.prototype = {
/**
* Updates the given data item and sends related notifications.
*/
_updateDataItemState: function (aDataItem)
{
_updateDataItemState(aDataItem) {
let oldState = aDataItem.state;
let wasInProgress = aDataItem.inProgress;
let wasDone = aDataItem.done;
@ -788,8 +771,7 @@ DownloadsDataCtor.prototype = {
* DownloadsView object to be added. This reference must be passed to
* removeView before termination.
*/
addView: function DD_addView(aView)
{
addView(aView) {
this._views.push(aView);
this._updateView(aView);
},
@ -800,8 +782,7 @@ DownloadsDataCtor.prototype = {
* @param aView
* DownloadsView object to be removed.
*/
removeView: function DD_removeView(aView)
{
removeView(aView) {
let index = this._views.indexOf(aView);
if (index != -1) {
this._views.splice(index, 1);
@ -814,8 +795,7 @@ DownloadsDataCtor.prototype = {
* @param aView
* DownloadsView object to be initialized.
*/
_updateView: function DD_updateView(aView)
{
_updateView(aView) {
// Indicate to the view that a batch loading operation is in progress.
aView.onDataLoadStarting();
@ -824,10 +804,8 @@ DownloadsDataCtor.prototype = {
let loadedItemsArray = [dataItem
for each (dataItem in this.dataItems)
if (dataItem)];
loadedItemsArray.sort(function(a, b) b.startTime - a.startTime);
loadedItemsArray.forEach(
function (dataItem) aView.onDataItemAdded(dataItem, false)
);
loadedItemsArray.sort((a, b) => b.startTime - a.startTime);
loadedItemsArray.forEach(dataItem => aView.onDataItemAdded(dataItem, false));
// Notify the view that all data is available.
aView.onDataLoadCompleted();
@ -859,8 +837,7 @@ DownloadsDataCtor.prototype = {
* @param aType
* Set to "start" for new downloads, "finish" for completed downloads.
*/
_notifyDownloadEvent: function DD_notifyDownloadEvent(aType)
{
_notifyDownloadEvent(aType) {
DownloadsCommon.log("Attempting to notify that a new download has started or finished.");
// Show the panel in the most recent browser window, if present.
@ -901,8 +878,7 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
* @param aDownload
* The Download object with the current state.
*/
function DownloadsDataItem(aDownload)
{
function DownloadsDataItem(aDownload) {
this._download = aDownload;
this.downloadGuid = "id:" + this._autoIncrementId;
@ -925,8 +901,7 @@ DownloadsDataItem.prototype = {
/**
* Updates this object from the underlying Download object.
*/
updateFromDownload: function ()
{
updateFromDownload() {
// Collapse state using the correct priority.
if (this._download.succeeded) {
this.state = nsIDM.DOWNLOAD_FINISHED;
@ -978,8 +953,7 @@ DownloadsDataItem.prototype = {
* yet. This includes paused downloads. When this property is true, the
* "progress" property represents the current progress of the download.
*/
get inProgress()
{
get inProgress() {
return [
nsIDM.DOWNLOAD_NOTSTARTED,
nsIDM.DOWNLOAD_QUEUED,
@ -993,8 +967,7 @@ DownloadsDataItem.prototype = {
* This is true during the initial phases of a download, before the actual
* download of data bytes starts.
*/
get starting()
{
get starting() {
return this.state == nsIDM.DOWNLOAD_NOTSTARTED ||
this.state == nsIDM.DOWNLOAD_QUEUED;
},
@ -1002,8 +975,7 @@ DownloadsDataItem.prototype = {
/**
* Indicates whether the download is paused.
*/
get paused()
{
get paused() {
return this.state == nsIDM.DOWNLOAD_PAUSED;
},
@ -1011,8 +983,7 @@ DownloadsDataItem.prototype = {
* Indicates whether the download is in a final state, either because it
* completed successfully or because it was blocked.
*/
get done()
{
get done() {
return [
nsIDM.DOWNLOAD_FINISHED,
nsIDM.DOWNLOAD_BLOCKED_PARENTAL,
@ -1024,8 +995,7 @@ DownloadsDataItem.prototype = {
/**
* Indicates whether the download is finished and can be opened.
*/
get openable()
{
get openable() {
return this.state == nsIDM.DOWNLOAD_FINISHED;
},
@ -1033,8 +1003,7 @@ DownloadsDataItem.prototype = {
* Indicates whether the download stopped because of an error, and can be
* resumed manually.
*/
get canRetry()
{
get canRetry() {
return this.state == nsIDM.DOWNLOAD_CANCELED ||
this.state == nsIDM.DOWNLOAD_FAILED;
},
@ -1046,8 +1015,7 @@ DownloadsDataItem.prototype = {
* profile is used on different platforms, for example if a native
* Windows path is stored and then the item is accessed on a Mac.
*/
get localFile()
{
get localFile() {
return this._getFile(this.file);
},
@ -1058,8 +1026,7 @@ DownloadsDataItem.prototype = {
* profile is used on different platforms, for example if a native
* Windows path is stored and then the item is accessed on a Mac.
*/
get partFile()
{
get partFile() {
return this._getFile(this.file + kPartialDownloadSuffix);
},
@ -1075,8 +1042,7 @@ DownloadsDataItem.prototype = {
* @note This function makes no guarantees about the file's existence -
* callers should check that the returned file exists.
*/
_getFile: function DDI__getFile(aFilename)
{
_getFile(aFilename) {
// The download database may contain targets stored as file URLs or native
// paths. This can still be true for previously stored items, even if new
// items are stored using their file URL. See also bug 239948 comment 12.
@ -1095,14 +1061,14 @@ DownloadsDataItem.prototype = {
/**
* Open the target file for this download.
*/
openLocalFile: function () {
openLocalFile() {
this._download.launch().then(null, Cu.reportError);
},
/**
* Show the downloaded file in the system file manager.
*/
showLocalFile: function DDI_showLocalFile() {
showLocalFile() {
DownloadsCommon.showDownloadedFile(this.localFile);
},
@ -1110,7 +1076,7 @@ DownloadsDataItem.prototype = {
* Resumes the download if paused, pauses it if active.
* @throws if the download is not resumable or if has already done.
*/
togglePauseResume: function DDI_togglePauseResume() {
togglePauseResume() {
if (this._download.stopped) {
this._download.start();
} else {
@ -1122,14 +1088,14 @@ DownloadsDataItem.prototype = {
* Attempts to retry the download.
* @throws if we cannot.
*/
retry: function DDI_retry() {
retry() {
this._download.start();
},
/**
* Cancels the download.
*/
cancel: function() {
cancel() {
this._download.cancel();
this._download.removePartialData().then(null, Cu.reportError);
},
@ -1137,12 +1103,12 @@ DownloadsDataItem.prototype = {
/**
* Remove the download.
*/
remove: function DDI_remove() {
remove() {
Downloads.getList(Downloads.ALL)
.then(list => list.remove(this._download))
.then(() => this._download.finalize(true))
.then(null, Cu.reportError);
}
},
};
////////////////////////////////////////////////////////////////////////////////
@ -1180,8 +1146,7 @@ const DownloadsViewPrototype = {
* View object to be added. This reference must be
* passed to removeView before termination.
*/
addView: function DVP_addView(aView)
{
addView(aView) {
// Start receiving events when the first of our views is registered.
if (this._views.length == 0) {
if (this._isPrivate) {
@ -1201,8 +1166,7 @@ const DownloadsViewPrototype = {
* @param aView
* View object to be updated.
*/
refreshView: function DVP_refreshView(aView)
{
refreshView(aView) {
// Update immediately even if we are still loading data asynchronously.
// Subclasses must provide these two functions!
this._refreshProperties();
@ -1215,8 +1179,7 @@ const DownloadsViewPrototype = {
* @param aView
* View object to be removed.
*/
removeView: function DVP_removeView(aView)
{
removeView(aView) {
let index = this._views.indexOf(aView);
if (index != -1) {
this._views.splice(index, 1);
@ -1243,16 +1206,14 @@ const DownloadsViewPrototype = {
/**
* Called before multiple downloads are about to be loaded.
*/
onDataLoadStarting: function DVP_onDataLoadStarting()
{
onDataLoadStarting() {
this._loading = true;
},
/**
* Called after data loading finished.
*/
onDataLoadCompleted: function DVP_onDataLoadCompleted()
{
onDataLoadCompleted() {
this._loading = false;
},
@ -1271,8 +1232,7 @@ const DownloadsViewPrototype = {
*
* @note Subclasses should override this.
*/
onDataItemAdded: function DVP_onDataItemAdded(aDataItem, aNewest)
{
onDataItemAdded(aDataItem, aNewest) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
@ -1285,8 +1245,7 @@ const DownloadsViewPrototype = {
*
* @note Subclasses should override this.
*/
onDataItemRemoved: function DVP_onDataItemRemoved(aDataItem)
{
onDataItemRemoved(aDataItem) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
@ -1300,8 +1259,7 @@ const DownloadsViewPrototype = {
*
* @note Subclasses should override this.
*/
getViewItem: function DID_getViewItem(aDataItem)
{
getViewItem(aDataItem) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
@ -1311,8 +1269,7 @@ const DownloadsViewPrototype = {
*
* @note Subclasses should override this.
*/
_refreshProperties: function DID_refreshProperties()
{
_refreshProperties() {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
@ -1321,10 +1278,9 @@ const DownloadsViewPrototype = {
*
* @note Subclasses should override this.
*/
_updateView: function DID_updateView()
{
_updateView() {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}
},
};
////////////////////////////////////////////////////////////////////////////////
@ -1353,8 +1309,7 @@ DownloadsIndicatorDataCtor.prototype = {
* @param aView
* DownloadsIndicatorView object to be removed.
*/
removeView: function DID_removeView(aView)
{
removeView(aView) {
DownloadsViewPrototype.removeView.call(this, aView);
if (this._views.length == 0) {
@ -1368,8 +1323,7 @@ DownloadsIndicatorDataCtor.prototype = {
/**
* Called after data loading finished.
*/
onDataLoadCompleted: function DID_onDataLoadCompleted()
{
onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this);
this._updateViews();
},
@ -1387,8 +1341,7 @@ DownloadsIndicatorDataCtor.prototype = {
* with regard to the items that have been already added. The latter
* generally happens during the asynchronous data load.
*/
onDataItemAdded: function DID_onDataItemAdded(aDataItem, aNewest)
{
onDataItemAdded(aDataItem, aNewest) {
this._itemCount++;
this._updateViews();
},
@ -1400,8 +1353,7 @@ DownloadsIndicatorDataCtor.prototype = {
* @param aDataItem
* DownloadsDataItem object that is being removed.
*/
onDataItemRemoved: function DID_onDataItemRemoved(aDataItem)
{
onDataItemRemoved(aDataItem) {
this._itemCount--;
this._updateViews();
},
@ -1414,13 +1366,11 @@ DownloadsIndicatorDataCtor.prototype = {
*
* @return Object that can be used to notify item status events.
*/
getViewItem: function DID_getViewItem(aDataItem)
{
getViewItem(aDataItem) {
let data = this._isPrivate ? PrivateDownloadsIndicatorData
: DownloadsIndicatorData;
return Object.freeze({
onStateChange: function DIVI_onStateChange(aOldState)
{
onStateChange(aOldState) {
if (aDataItem.state == nsIDM.DOWNLOAD_FINISHED ||
aDataItem.state == nsIDM.DOWNLOAD_FAILED) {
data.attention = true;
@ -1432,8 +1382,7 @@ DownloadsIndicatorDataCtor.prototype = {
data._updateViews();
},
onProgressChange: function DIVI_onProgressChange()
{
onProgressChange() {
data._updateViews();
}
});
@ -1452,8 +1401,7 @@ DownloadsIndicatorDataCtor.prototype = {
/**
* Indicates whether the download indicators should be highlighted.
*/
set attention(aValue)
{
set attention(aValue) {
this._attention = aValue;
this._updateViews();
return aValue;
@ -1464,8 +1412,7 @@ DownloadsIndicatorDataCtor.prototype = {
* Indicates whether the user is interacting with downloads, thus the
* attention indication should not be shown even if requested.
*/
set attentionSuppressed(aValue)
{
set attentionSuppressed(aValue) {
this._attentionSuppressed = aValue;
this._attention = false;
this._updateViews();
@ -1476,8 +1423,7 @@ DownloadsIndicatorDataCtor.prototype = {
/**
* Computes aggregate values and propagates the changes to our views.
*/
_updateViews: function DID_updateViews()
{
_updateViews() {
// Do not update the status indicators during batch loads of download items.
if (this._loading) {
return;
@ -1493,8 +1439,7 @@ DownloadsIndicatorDataCtor.prototype = {
* @param aView
* DownloadsIndicatorView object to be updated.
*/
_updateView: function DID_updateView(aView)
{
_updateView(aView) {
aView.hasDownloads = this._hasDownloads;
aView.counter = this._counter;
aView.percentComplete = this._percentComplete;
@ -1532,8 +1477,7 @@ DownloadsIndicatorDataCtor.prototype = {
* to generate statistics about the dataItems we care about - in this case,
* it's all dataItems for active downloads.
*/
_activeDataItems: function DID_activeDataItems()
{
_activeDataItems() {
let dataItems = this._isPrivate ? PrivateDownloadsData.dataItems
: DownloadsData.dataItems;
for each (let dataItem in dataItems) {
@ -1546,8 +1490,7 @@ DownloadsIndicatorDataCtor.prototype = {
/**
* Computes aggregate values based on the current state of downloads.
*/
_refreshProperties: function DID_refreshProperties()
{
_refreshProperties() {
let summary =
DownloadsCommon.summarizeDownloads(this._activeDataItems());
@ -1645,8 +1588,7 @@ DownloadsSummaryData.prototype = {
* @param aView
* DownloadsSummary view to be removed.
*/
removeView: function DSD_removeView(aView)
{
removeView(aView) {
DownloadsViewPrototype.removeView.call(this, aView);
if (this._views.length == 0) {
@ -1661,14 +1603,12 @@ DownloadsSummaryData.prototype = {
//// DownloadsViewPrototype for more information on what these functions
//// are used for.
onDataLoadCompleted: function DSD_onDataLoadCompleted()
{
onDataLoadCompleted() {
DownloadsViewPrototype.onDataLoadCompleted.call(this);
this._updateViews();
},
onDataItemAdded: function DSD_onDataItemAdded(aDataItem, aNewest)
{
onDataItemAdded(aDataItem, aNewest) {
if (aNewest) {
this._dataItems.unshift(aDataItem);
} else {
@ -1678,26 +1618,22 @@ DownloadsSummaryData.prototype = {
this._updateViews();
},
onDataItemRemoved: function DSD_onDataItemRemoved(aDataItem)
{
onDataItemRemoved(aDataItem) {
let itemIndex = this._dataItems.indexOf(aDataItem);
this._dataItems.splice(itemIndex, 1);
this._updateViews();
},
getViewItem: function DSD_getViewItem(aDataItem)
{
getViewItem(aDataItem) {
let self = this;
return Object.freeze({
onStateChange: function DIVI_onStateChange(aOldState)
{
onStateChange(aOldState) {
// Since the state of a download changed, reset the estimated time left.
self._lastRawTimeLeft = -1;
self._lastTimeLeft = -1;
self._updateViews();
},
onProgressChange: function DIVI_onProgressChange()
{
onProgressChange() {
self._updateViews();
}
});
@ -1709,8 +1645,7 @@ DownloadsSummaryData.prototype = {
/**
* Computes aggregate values and propagates the changes to our views.
*/
_updateViews: function DSD_updateViews()
{
_updateViews() {
// Do not update the status indicators during batch loads of download items.
if (this._loading) {
return;
@ -1726,8 +1661,7 @@ DownloadsSummaryData.prototype = {
* @param aView
* DownloadsIndicatorView object to be updated.
*/
_updateView: function DSD_updateView(aView)
{
_updateView(aView) {
aView.showingProgress = this._showingProgress;
aView.percentComplete = this._percentComplete;
aView.description = this._description;
@ -1744,8 +1678,7 @@ DownloadsSummaryData.prototype = {
* it's the dataItems in this._dataItems after the first few to exclude,
* which was set when constructing this DownloadsSummaryData instance.
*/
_dataItemsForSummary: function DSD_dataItemsForSummary()
{
_dataItemsForSummary() {
if (this._dataItems.length > 0) {
for (let i = this._numToExclude; i < this._dataItems.length; ++i) {
yield this._dataItems[i];
@ -1756,8 +1689,7 @@ DownloadsSummaryData.prototype = {
/**
* Computes aggregate values based on the current state of downloads.
*/
_refreshProperties: function DSD_refreshProperties()
{
_refreshProperties() {
// Pre-load summary with default values.
let summary =
DownloadsCommon.summarizeDownloads(this._dataItemsForSummary());
@ -1787,5 +1719,5 @@ DownloadsSummaryData.prototype = {
summary.totalTransferred, summary.totalSize, summary.slowestSpeed,
this._lastTimeLeft);
}
}
},
}

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

@ -24,7 +24,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
this.DownloadsLogger = {
_generateLogMessage: function _generateLogMessage(args) {
_generateLogMessage(args) {
// create a string representation of a list of arbitrary things
let strings = [];
@ -51,7 +51,7 @@ this.DownloadsLogger = {
*
* Enable with about:config pref browser.download.debug
*/
log: function DL_log(...args) {
log(...args) {
let output = this._generateLogMessage(args);
dump(output + "\n");
@ -63,7 +63,7 @@ this.DownloadsLogger = {
* reportError() - report an error through component utils as well as
* our log function
*/
reportError: function DL_reportError(...aArgs) {
reportError(...aArgs) {
// Report the error in the browser
let output = this._generateLogMessage(aArgs);
Cu.reportError(output);
@ -71,6 +71,5 @@ this.DownloadsLogger = {
for (let frame = Components.stack.caller; frame; frame = frame.caller) {
dump("\t" + frame + "\n");
}
}
},
};

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

@ -82,8 +82,7 @@ this.DownloadsTaskbar = {
* nsIDOMWindow object of the newly opened browser window to which the
* indicator may be attached.
*/
registerIndicator: function (aBrowserWindow)
{
registerIndicator(aBrowserWindow) {
if (!this._taskbarProgress) {
if (gMacTaskbarProgress) {
// On Mac OS X, we have to register the global indicator only once.
@ -120,8 +119,7 @@ this.DownloadsTaskbar = {
/**
* On Windows, attaches the taskbar indicator to the specified browser window.
*/
_attachIndicator: function (aWindow)
{
_attachIndicator(aWindow) {
// Activate the indicator on the specified window.
let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
@ -155,8 +153,7 @@ this.DownloadsTaskbar = {
//////////////////////////////////////////////////////////////////////////////
//// DownloadSummary view
onSummaryChanged: function ()
{
onSummaryChanged() {
// If the last browser window has been closed, we have no indicator any more.
if (!this._taskbarProgress) {
return;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -5,11 +5,11 @@
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
let ContentAreaDownloadsView = {
init: function CADV_init() {
init() {
let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
// Do not display the Places downloads in private windows
if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
view.place = "place:transition=7&sort=4";
}
}
},
};

321
browser/components/downloads/content/downloads.js Normal file → Executable file
Просмотреть файл

@ -121,8 +121,7 @@ const DownloadsPanel = {
* @param aCallback
* Called when initialization is complete.
*/
initialize: function DP_initialize(aCallback)
{
initialize(aCallback) {
DownloadsCommon.log("Attempting to initialize DownloadsPanel for a window.");
if (this._state != this.kStateUninitialized) {
DownloadsCommon.log("DownloadsPanel is already initialized.");
@ -141,8 +140,7 @@ const DownloadsPanel = {
// Now that data loading has eventually started, load the required XUL
// elements and initialize our views.
DownloadsCommon.log("Ensuring DownloadsPanel overlay loaded.");
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
function DP_I_callback() {
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay, () => {
DownloadsViewController.initialize();
DownloadsCommon.log("Attaching DownloadsView...");
DownloadsCommon.getData(window).addView(DownloadsView);
@ -161,8 +159,7 @@ const DownloadsPanel = {
* downloads. The downloads panel can be reopened later, even after this
* function has been called.
*/
terminate: function DP_terminate()
{
terminate() {
DownloadsCommon.log("Attempting to terminate DownloadsPanel for a window.");
if (this._state == this.kStateUninitialized) {
DownloadsCommon.log("DownloadsPanel was never initialized. Nothing to do.");
@ -193,8 +190,7 @@ const DownloadsPanel = {
* Main panel element in the browser window, or null if the panel overlay
* hasn't been loaded yet.
*/
get panel()
{
get panel() {
// If the downloads panel overlay hasn't loaded yet, just return null
// without resetting this.panel.
let downloadsPanel = document.getElementById("downloadsPanel");
@ -211,8 +207,7 @@ const DownloadsPanel = {
* initialized the first time this method is called, and the panel is shown
* only when data is ready.
*/
showPanel: function DP_showPanel()
{
showPanel() {
DownloadsCommon.log("Opening the downloads panel.");
if (this.isPanelShowing) {
@ -221,13 +216,13 @@ const DownloadsPanel = {
return;
}
this.initialize(function DP_SP_callback() {
this.initialize(() => {
// Delay displaying the panel because this function will sometimes be
// called while another window is closing (like the window for selecting
// whether to save or open the file), and that would cause the panel to
// close immediately.
setTimeout(function () DownloadsPanel._openPopupIfDataReady(), 0);
}.bind(this));
setTimeout(() => this._openPopupIfDataReady(), 0);
});
DownloadsCommon.log("Waiting for the downloads panel to appear.");
this._state = this.kStateWaitingData;
@ -237,8 +232,7 @@ const DownloadsPanel = {
* Hides the downloads panel, if visible, but keeps the internal state so that
* the panel can be reopened quickly if required.
*/
hidePanel: function DP_hidePanel()
{
hidePanel() {
DownloadsCommon.log("Closing the downloads panel.");
if (!this.isPanelShowing) {
@ -258,8 +252,7 @@ const DownloadsPanel = {
/**
* Indicates whether the panel is shown or will be shown.
*/
get isPanelShowing()
{
get isPanelShowing() {
return this._state == this.kStateWaitingData ||
this._state == this.kStateWaitingAnchor ||
this._state == this.kStateShown;
@ -268,8 +261,7 @@ const DownloadsPanel = {
/**
* Returns whether the user has started keyboard navigation.
*/
get keyFocusing()
{
get keyFocusing() {
return this.panel.hasAttribute("keyfocus");
},
@ -278,8 +270,7 @@ const DownloadsPanel = {
* showing focusrings in the panel. Also adds a mousemove event handler to
* the panel which disables keyFocusing.
*/
set keyFocusing(aValue)
{
set keyFocusing(aValue) {
if (aValue) {
this.panel.setAttribute("keyfocus", "true");
this.panel.addEventListener("mousemove", this);
@ -294,8 +285,7 @@ const DownloadsPanel = {
* Handles the mousemove event for the panel, which disables focusring
* visualization.
*/
handleEvent: function DP_handleEvent(aEvent)
{
handleEvent(aEvent) {
if (aEvent.type == "mousemove") {
this.keyFocusing = false;
}
@ -307,22 +297,19 @@ const DownloadsPanel = {
/**
* Called after data loading finished.
*/
onViewLoadCompleted: function DP_onViewLoadCompleted()
{
onViewLoadCompleted() {
this._openPopupIfDataReady();
},
//////////////////////////////////////////////////////////////////////////////
//// User interface event functions
onWindowUnload: function DP_onWindowUnload()
{
onWindowUnload() {
// This function is registered as an event listener, we can't use "this".
DownloadsPanel.terminate();
},
onPopupShown: function DP_onPopupShown(aEvent)
{
onPopupShown(aEvent) {
// Ignore events raised by nested popups.
if (aEvent.target != aEvent.currentTarget) {
return;
@ -343,8 +330,7 @@ const DownloadsPanel = {
this._focusPanel();
},
onPopupHidden: function DP_onPopupHidden(aEvent)
{
onPopupHidden(aEvent) {
// Ignore events raised by nested popups.
if (aEvent.target != aEvent.currentTarget) {
return;
@ -372,8 +358,7 @@ const DownloadsPanel = {
/**
* Shows or focuses the user interface dedicated to downloads history.
*/
showDownloadsHistory: function DP_showDownloadsHistory()
{
showDownloadsHistory() {
DownloadsCommon.log("Showing download history.");
// Hide the panel before showing another window, otherwise focus will return
// to the browser window when the panel closes automatically.
@ -390,8 +375,7 @@ const DownloadsPanel = {
* removed in _unattachEventListeners. This is called automatically after the
* panel has successfully loaded.
*/
_attachEventListeners: function DP__attachEventListeners()
{
_attachEventListeners() {
// Handle keydown to support accel-V.
this.panel.addEventListener("keydown", this._onKeyDown.bind(this), false);
// Handle keypress to be able to preventDefault() events before they reach
@ -403,16 +387,14 @@ const DownloadsPanel = {
* Unattach event listeners that were added in _attachEventListeners. This
* is called automatically on panel termination.
*/
_unattachEventListeners: function DP__unattachEventListeners()
{
_unattachEventListeners() {
this.panel.removeEventListener("keydown", this._onKeyDown.bind(this),
false);
this.panel.removeEventListener("keypress", this._onKeyPress.bind(this),
false);
},
_onKeyPress: function DP__onKeyPress(aEvent)
{
_onKeyPress(aEvent) {
// Handle unmodified keys only.
if (aEvent.altKey || aEvent.ctrlKey || aEvent.shiftKey || aEvent.metaKey) {
return;
@ -431,8 +413,9 @@ const DownloadsPanel = {
this.keyFocusing = true;
// Ensure there's a selection, we will show the focus ring around it and
// prevent the richlistbox from changing the selection.
if (DownloadsView.richListBox.selectedIndex == -1)
if (DownloadsView.richListBox.selectedIndex == -1) {
DownloadsView.richListBox.selectedIndex = 0;
}
aEvent.preventDefault();
return;
}
@ -459,8 +442,7 @@ const DownloadsPanel = {
* as the the accel-V "paste" event, which initiates a file download if the
* pasted item can be resolved to a URI.
*/
_onKeyDown: function DP__onKeyDown(aEvent)
{
_onKeyDown(aEvent) {
// If the footer is focused and the downloads list has at least 1 element
// in it, focus the last element in the list when going up.
if (aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_UP &&
@ -513,8 +495,7 @@ const DownloadsPanel = {
* Move focus to the main element in the downloads panel, unless another
* element in the panel is already focused.
*/
_focusPanel: function DP_focusPanel()
{
_focusPanel() {
// We may be invoked while the panel is still waiting to be shown.
if (this._state != this.kStateShown) {
return;
@ -536,8 +517,7 @@ const DownloadsPanel = {
/**
* Opens the downloads panel when data is ready to be displayed.
*/
_openPopupIfDataReady: function DP_openPopupIfDataReady()
{
_openPopupIfDataReady() {
// We don't want to open the popup if we already displayed it, or if we are
// still loading data.
if (this._state != this.kStateWaitingData || DownloadsView.loading) {
@ -548,11 +528,12 @@ const DownloadsPanel = {
// Ensure the anchor is visible. If that is not possible, show the panel
// anchored to the top area of the window, near the default anchor position.
DownloadsButton.getAnchor(function DP_OPIDR_callback(aAnchor) {
DownloadsButton.getAnchor(anchor => {
// If somehow we've switched states already (by getting a panel hiding
// event before an overlay is loaded, for example), bail out.
if (this._state != this.kStateWaitingAnchor)
if (this._state != this.kStateWaitingAnchor) {
return;
}
// At this point, if the window is minimized, opening the panel could fail
// without any notification, and there would be no way to either open or
@ -564,6 +545,11 @@ const DownloadsPanel = {
return;
}
if (!anchor) {
DownloadsCommon.error("Downloads button cannot be found.");
return;
}
// When the panel is opened, we check if the target files of visible items
// still exist, and update the allowed items interactions accordingly. We
// do these checks on a background thread, and don't prevent the panel to
@ -572,19 +558,10 @@ const DownloadsPanel = {
viewItem.verifyTargetExists();
}
if (aAnchor) {
DownloadsCommon.log("Opening downloads panel popup.");
this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
null);
} else {
DownloadsCommon.error("We can't find the anchor! Failure case - opening",
"downloads panel on TabsToolbar. We should never",
"get here!");
Components.utils.reportError(
"Downloads button cannot be found");
}
}.bind(this));
}
DownloadsCommon.log("Opening downloads panel popup.");
this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, null);
});
},
};
////////////////////////////////////////////////////////////////////////////////
@ -622,8 +599,7 @@ const DownloadsOverlayLoader = {
* Invoked when loading is completed. If the overlay is already
* loaded, the function is called immediately.
*/
ensureOverlayLoaded: function DOL_ensureOverlayLoaded(aOverlay, aCallback)
{
ensureOverlayLoaded(aOverlay, aCallback) {
// The overlay is already loaded, invoke the callback immediately.
if (aOverlay in this._loadedOverlays) {
aCallback();
@ -636,16 +612,14 @@ const DownloadsOverlayLoader = {
return;
}
function DOL_EOL_loadCallback() {
this._overlayLoading = true;
DownloadsCommon.log("Loading overlay ", aOverlay);
document.loadOverlay(aOverlay, () => {
this._overlayLoading = false;
this._loadedOverlays[aOverlay] = true;
this.processPendingRequests();
}
this._overlayLoading = true;
DownloadsCommon.log("Loading overlay ", aOverlay);
document.loadOverlay(aOverlay, DOL_EOL_loadCallback.bind(this));
});
},
/**
@ -653,8 +627,7 @@ const DownloadsOverlayLoader = {
* and/or loading more overlays as needed. In most cases, there will be a
* single request for one overlay, that will be processed immediately.
*/
processPendingRequests: function DOL_processPendingRequests()
{
processPendingRequests() {
// Re-process all the currently pending requests, yet allow more requests
// to be appended at the end of the array if we're not ready for them.
let currentLength = this._loadRequests.length;
@ -666,7 +639,7 @@ const DownloadsOverlayLoader = {
// for the associated overlay to load.
this.ensureOverlayLoaded(request.overlay, request.callback);
}
}
},
};
////////////////////////////////////////////////////////////////////////////////
@ -709,8 +682,7 @@ const DownloadsView = {
/**
* Called when the number of items in the list changes.
*/
_itemCountChanged: function DV_itemCountChanged()
{
_itemCountChanged() {
DownloadsCommon.log("The downloads item count has changed - we are tracking",
this._dataItems.length, "downloads in total.");
let count = this._dataItems.length;
@ -733,8 +705,7 @@ const DownloadsView = {
/**
* Element corresponding to the list of downloads.
*/
get richListBox()
{
get richListBox() {
delete this.richListBox;
return this.richListBox = document.getElementById("downloadsListBox");
},
@ -742,8 +713,7 @@ const DownloadsView = {
/**
* Element corresponding to the button for showing more downloads.
*/
get downloadsHistory()
{
get downloadsHistory() {
delete this.downloadsHistory;
return this.downloadsHistory = document.getElementById("downloadsHistory");
},
@ -754,8 +724,7 @@ const DownloadsView = {
/**
* Called before multiple downloads are about to be loaded.
*/
onDataLoadStarting: function DV_onDataLoadStarting()
{
onDataLoadStarting() {
DownloadsCommon.log("onDataLoadStarting called for DownloadsView.");
this.loading = true;
},
@ -763,8 +732,7 @@ const DownloadsView = {
/**
* Called after data loading finished.
*/
onDataLoadCompleted: function DV_onDataLoadCompleted()
{
onDataLoadCompleted() {
DownloadsCommon.log("onDataLoadCompleted called for DownloadsView.");
this.loading = false;
@ -791,8 +759,7 @@ const DownloadsView = {
* and should be appended. The latter generally happens during the
* asynchronous data load.
*/
onDataItemAdded: function DV_onDataItemAdded(aDataItem, aNewest)
{
onDataItemAdded(aDataItem, aNewest) {
DownloadsCommon.log("A new download data item was added - aNewest =",
aNewest);
@ -829,8 +796,7 @@ const DownloadsView = {
* @param aDataItem
* DownloadsDataItem object that is being removed.
*/
onDataItemRemoved: function DV_onDataItemRemoved(aDataItem)
{
onDataItemRemoved(aDataItem) {
DownloadsCommon.log("A download data item was removed.");
let itemIndex = this._dataItems.indexOf(aDataItem);
@ -856,8 +822,7 @@ const DownloadsView = {
*
* @return Object that can be used to notify item status events.
*/
getViewItem: function DV_getViewItem(aDataItem)
{
getViewItem(aDataItem) {
// If the item is visible, just return it, otherwise return a mock object
// that doesn't react to notifications.
if (aDataItem.downloadGuid in this._viewItems) {
@ -870,15 +835,15 @@ const DownloadsView = {
* Mock DownloadsDataItem object that doesn't react to notifications.
*/
_invisibleViewItem: Object.freeze({
onStateChange: function () { },
onProgressChange: function () { }
onStateChange() {},
onProgressChange() {},
}),
/**
* Creates a new view item associated with the specified data item, and adds
* it to the top or the bottom of the list.
*/
_addViewItem: function DV_addViewItem(aDataItem, aNewest)
_addViewItem(aDataItem, aNewest)
{
DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.",
"aNewest =", aNewest);
@ -896,8 +861,7 @@ const DownloadsView = {
/**
* Removes the view item associated with the specified data item.
*/
_removeViewItem: function DV_removeViewItem(aDataItem)
{
_removeViewItem(aDataItem) {
DownloadsCommon.log("Removing a DownloadsViewItem from the downloads list.");
let element = this.getViewItem(aDataItem)._element;
let previousSelectedIndex = this.richListBox.selectedIndex;
@ -922,8 +886,7 @@ const DownloadsView = {
* @param aCommand
* The command to be performed.
*/
onDownloadCommand: function DV_onDownloadCommand(aEvent, aCommand)
{
onDownloadCommand(aEvent, aCommand) {
let target = aEvent.target;
while (target.nodeName != "richlistitem") {
target = target.parentNode;
@ -931,8 +894,7 @@ const DownloadsView = {
new DownloadsViewItemController(target).doCommand(aCommand);
},
onDownloadClick: function DV_onDownloadClick(aEvent)
{
onDownloadClick(aEvent) {
// Handle primary clicks only, and exclude the action button.
if (aEvent.button == 0 &&
!aEvent.originalTarget.hasAttribute("oncommand")) {
@ -943,8 +905,7 @@ const DownloadsView = {
/**
* Handles keypress events on a download item.
*/
onDownloadKeyPress: function DV_onDownloadKeyPress(aEvent)
{
onDownloadKeyPress(aEvent) {
// Pressing the key on buttons should not invoke the action because the
// event has already been handled by the button itself.
if (aEvent.originalTarget.hasAttribute("command") ||
@ -962,17 +923,16 @@ const DownloadsView = {
}
},
/**
* Mouse listeners to handle selection on hover.
*/
onDownloadMouseOver: function DV_onDownloadMouseOver(aEvent)
{
if (aEvent.originalTarget.parentNode == this.richListBox)
onDownloadMouseOver(aEvent) {
if (aEvent.originalTarget.parentNode == this.richListBox) {
this.richListBox.selectedItem = aEvent.originalTarget;
}
},
onDownloadMouseOut: function DV_onDownloadMouseOut(aEvent)
{
onDownloadMouseOut(aEvent) {
if (aEvent.originalTarget.parentNode == this.richListBox) {
// If the destination element is outside of the richlistitem, clear the
// selection.
@ -980,13 +940,13 @@ const DownloadsView = {
while (element && element != aEvent.originalTarget) {
element = element.parentNode;
}
if (!element)
if (!element) {
this.richListBox.selectedIndex = -1;
}
}
},
onDownloadContextMenu: function DV_onDownloadContextMenu(aEvent)
{
onDownloadContextMenu(aEvent) {
let element = this.richListBox.selectedItem;
if (!element) {
return;
@ -999,8 +959,7 @@ const DownloadsView = {
contextMenu.setAttribute("state", element.getAttribute("state"));
},
onDownloadDragStart: function DV_onDownloadDragStart(aEvent)
{
onDownloadDragStart(aEvent) {
let element = this.richListBox.selectedItem;
if (!element) {
return;
@ -1021,7 +980,7 @@ const DownloadsView = {
dataTransfer.addElement(element);
aEvent.stopPropagation();
}
},
}
////////////////////////////////////////////////////////////////////////////////
@ -1036,8 +995,7 @@ const DownloadsView = {
* @param aElement
* XUL element corresponding to the single download item in the view.
*/
function DownloadsViewItem(aDataItem, aElement)
{
function DownloadsViewItem(aDataItem, aElement) {
this._element = aElement;
this.dataItem = aDataItem;
@ -1094,8 +1052,7 @@ DownloadsViewItem.prototype = {
* the download might be the same as before, if the data layer received
* multiple events for the same download.
*/
onStateChange: function DVI_onStateChange(aOldState)
{
onStateChange(aOldState) {
// 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
// is reloaded, we must change the URI used by the XUL image element, for
@ -1122,7 +1079,7 @@ DownloadsViewItem.prototype = {
/**
* Called when the download progress has changed.
*/
onProgressChange: function DVI_onProgressChange() {
onProgressChange() {
this._updateProgress();
this._updateStatusLine();
},
@ -1133,7 +1090,7 @@ DownloadsViewItem.prototype = {
/**
* Updates the progress bar.
*/
_updateProgress: function DVI_updateProgress() {
_updateProgress() {
if (this.dataItem.starting) {
// Before the download starts, the progress meter has its initial value.
this._element.setAttribute("progressmode", "normal");
@ -1168,7 +1125,7 @@ DownloadsViewItem.prototype = {
* Updates the main status line, including bytes transferred, bytes total,
* download rate, and time remaining.
*/
_updateStatusLine: function DVI_updateStatusLine() {
_updateStatusLine() {
const nsIDM = Ci.nsIDownloadManager;
let status = "";
@ -1243,8 +1200,7 @@ DownloadsViewItem.prototype = {
* Localized string representing the total size of completed downloads, for
* example "1.5 MB" or "Unknown size".
*/
get _fileSizeText()
{
get _fileSizeText() {
// Display the file size, but show "Unknown" for negative sizes.
let fileSize = this.dataItem.maxBytes;
if (fileSize < 0) {
@ -1264,20 +1220,19 @@ DownloadsViewItem.prototype = {
*
* The existence check is executed on a background thread.
*/
verifyTargetExists: function DVI_verifyTargetExists() {
verifyTargetExists() {
// We don't need to check if the download is not finished successfully.
if (!this.dataItem.openable) {
return;
}
OS.File.exists(this.dataItem.localFile.path).then(
function DVI_RTE_onSuccess(aExists) {
if (aExists) {
this._element.setAttribute("exists", "true");
} else {
this._element.removeAttribute("exists");
}
}.bind(this), Cu.reportError);
OS.File.exists(this.dataItem.localFile.path).then(aExists => {
if (aExists) {
this._element.setAttribute("exists", "true");
} else {
this._element.removeAttribute("exists");
}
}).catch(Cu.reportError);
},
};
@ -1293,21 +1248,18 @@ const DownloadsViewController = {
//////////////////////////////////////////////////////////////////////////////
//// Initialization and termination
initialize: function DVC_initialize()
{
initialize() {
window.controllers.insertControllerAt(0, this);
},
terminate: function DVC_terminate()
{
terminate() {
window.controllers.removeController(this);
},
//////////////////////////////////////////////////////////////////////////////
//// nsIController
supportsCommand: function DVC_supportsCommand(aCommand)
{
supportsCommand(aCommand) {
// Firstly, determine if this is a command that we can handle.
if (!(aCommand in this.commands) &&
!(aCommand in DownloadsViewItemController.prototype.commands)) {
@ -1323,8 +1275,7 @@ const DownloadsViewController = {
return !!element;
},
isCommandEnabled: function DVC_isCommandEnabled(aCommand)
{
isCommandEnabled(aCommand) {
// Handle commands that are not selection-specific.
if (aCommand == "downloadsCmd_clearList") {
return DownloadsCommon.getData(window).canRemoveFinished;
@ -1336,8 +1287,7 @@ const DownloadsViewController = {
new DownloadsViewItemController(element).isCommandEnabled(aCommand);
},
doCommand: function DVC_doCommand(aCommand)
{
doCommand(aCommand) {
// If this command is not selection-specific, execute it.
if (aCommand in this.commands) {
this.commands[aCommand].apply(this);
@ -1352,13 +1302,12 @@ const DownloadsViewController = {
}
},
onEvent: function () { },
onEvent() {},
//////////////////////////////////////////////////////////////////////////////
//// Other functions
updateCommands: function DVC_updateCommands()
{
updateCommands() {
Object.keys(this.commands).forEach(goUpdateCommand);
Object.keys(DownloadsViewItemController.prototype.commands)
.forEach(goUpdateCommand);
@ -1372,8 +1321,7 @@ const DownloadsViewController = {
* the currently selected item in the list.
*/
commands: {
downloadsCmd_clearList: function DVC_downloadsCmd_clearList()
{
downloadsCmd_clearList() {
DownloadsCommon.getData(window).removeFinished();
}
}
@ -1400,8 +1348,7 @@ DownloadsViewItemController.prototype = {
*/
dataItem: null,
isCommandEnabled: function DVIC_isCommandEnabled(aCommand)
{
isCommandEnabled(aCommand) {
switch (aCommand) {
case "downloadsCmd_open": {
return this.dataItem.openable && this.dataItem.localFile.exists();
@ -1425,8 +1372,7 @@ DownloadsViewItemController.prototype = {
return false;
},
doCommand: function DVIC_doCommand(aCommand)
{
doCommand(aCommand) {
if (this.isCommandEnabled(aCommand)) {
this.commands[aCommand].apply(this);
}
@ -1441,19 +1387,16 @@ DownloadsViewItemController.prototype = {
* In commands, the "this" identifier points to the controller item.
*/
commands: {
cmd_delete: function DVIC_cmd_delete()
{
cmd_delete() {
this.dataItem.remove();
PlacesUtils.bhistory.removePage(NetUtil.newURI(this.dataItem.uri));
},
downloadsCmd_cancel: function DVIC_downloadsCmd_cancel()
{
downloadsCmd_cancel() {
this.dataItem.cancel();
},
downloadsCmd_open: function DVIC_downloadsCmd_open()
{
downloadsCmd_open() {
this.dataItem.openLocalFile();
// We explicitly close the panel here to give the user the feedback that
@ -1464,8 +1407,7 @@ DownloadsViewItemController.prototype = {
DownloadsPanel.hidePanel();
},
downloadsCmd_show: function DVIC_downloadsCmd_show()
{
downloadsCmd_show() {
this.dataItem.showLocalFile();
// We explicitly close the panel here to give the user the feedback that
@ -1476,30 +1418,25 @@ DownloadsViewItemController.prototype = {
DownloadsPanel.hidePanel();
},
downloadsCmd_pauseResume: function DVIC_downloadsCmd_pauseResume()
{
downloadsCmd_pauseResume() {
this.dataItem.togglePauseResume();
},
downloadsCmd_retry: function DVIC_downloadsCmd_retry()
{
downloadsCmd_retry() {
this.dataItem.retry();
},
downloadsCmd_openReferrer: function DVIC_downloadsCmd_openReferrer()
{
downloadsCmd_openReferrer() {
openURL(this.dataItem.referrer);
},
downloadsCmd_copyLocation: function DVIC_downloadsCmd_copyLocation()
{
downloadsCmd_copyLocation() {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper);
clipboard.copyString(this.dataItem.uri, document);
},
downloadsCmd_doDefault: function DVIC_downloadsCmd_doDefault()
{
downloadsCmd_doDefault() {
const nsIDM = Ci.nsIDownloadManager;
// Determine the default command for the current item.
@ -1518,10 +1455,11 @@ DownloadsViewItemController.prototype = {
}
return "";
}.apply(this);
if (defaultCommand && this.isCommandEnabled(defaultCommand))
if (defaultCommand && this.isCommandEnabled(defaultCommand)) {
this.doCommand(defaultCommand);
}
}
}
},
},
};
@ -1541,8 +1479,7 @@ const DownloadsSummary = {
* @param aActive
* Set to true to activate the summary.
*/
set active(aActive)
{
set active(aActive) {
if (aActive == this._active || !this._summaryNode) {
return this._active;
}
@ -1569,8 +1506,7 @@ const DownloadsSummary = {
* @param aShowingProgress
* True if we should show the progress bar.
*/
set showingProgress(aShowingProgress)
{
set showingProgress(aShowingProgress) {
if (aShowingProgress) {
this._summaryNode.setAttribute("inprogress", "true");
} else {
@ -1587,8 +1523,7 @@ const DownloadsSummary = {
* A value between 0 and 100 to represent the progress of the
* summarized downloads.
*/
set percentComplete(aValue)
{
set percentComplete(aValue) {
if (this._progressNode) {
this._progressNode.setAttribute("value", aValue);
}
@ -1602,8 +1537,7 @@ const DownloadsSummary = {
* A string representing the description of the summarized
* downloads.
*/
set description(aValue)
{
set description(aValue) {
if (this._descriptionNode) {
this._descriptionNode.setAttribute("value", aValue);
this._descriptionNode.setAttribute("tooltiptext", aValue);
@ -1619,8 +1553,7 @@ const DownloadsSummary = {
* A string representing the details of the summarized
* downloads.
*/
set details(aValue)
{
set details(aValue) {
if (this._detailsNode) {
this._detailsNode.setAttribute("value", aValue);
this._detailsNode.setAttribute("tooltiptext", aValue);
@ -1631,8 +1564,7 @@ const DownloadsSummary = {
/**
* Focuses the root element of the summary.
*/
focus: function()
{
focus() {
if (this._summaryNode) {
this._summaryNode.focus();
}
@ -1644,8 +1576,7 @@ const DownloadsSummary = {
* @param aEvent
* The keydown event being handled.
*/
onKeyDown: function DS_onKeyDown(aEvent)
{
onKeyDown(aEvent) {
if (aEvent.charCode == " ".charCodeAt(0) ||
aEvent.keyCode == KeyEvent.DOM_VK_RETURN) {
DownloadsPanel.showDownloadsHistory();
@ -1658,16 +1589,14 @@ const DownloadsSummary = {
* @param aEvent
* The click event being handled.
*/
onClick: function DS_onClick(aEvent)
{
onClick(aEvent) {
DownloadsPanel.showDownloadsHistory();
},
/**
* Element corresponding to the root of the downloads summary.
*/
get _summaryNode()
{
get _summaryNode() {
let node = document.getElementById("downloadsSummary");
if (!node) {
return null;
@ -1679,8 +1608,7 @@ const DownloadsSummary = {
/**
* Element corresponding to the progress bar in the downloads summary.
*/
get _progressNode()
{
get _progressNode() {
let node = document.getElementById("downloadsSummaryProgress");
if (!node) {
return null;
@ -1693,8 +1621,7 @@ const DownloadsSummary = {
* Element corresponding to the main description of the downloads
* summary.
*/
get _descriptionNode()
{
get _descriptionNode() {
let node = document.getElementById("downloadsSummaryDescription");
if (!node) {
return null;
@ -1707,8 +1634,7 @@ const DownloadsSummary = {
* Element corresponding to the secondary description of the downloads
* summary.
*/
get _detailsNode()
{
get _detailsNode() {
let node = document.getElementById("downloadsSummaryDetails");
if (!node) {
return null;
@ -1732,8 +1658,7 @@ const DownloadsFooter = {
* is visible, focus it. If not, focus the "Show All Downloads"
* button.
*/
focus: function DF_focus()
{
focus() {
if (this._showingSummary) {
DownloadsSummary.focus();
} else {
@ -1747,8 +1672,7 @@ const DownloadsFooter = {
* Sets whether or not the Downloads Summary should be displayed in the
* footer. If not, the "Show All Downloads" button is shown instead.
*/
set showingSummary(aValue)
{
set showingSummary(aValue) {
if (this._footerNode) {
if (aValue) {
this._footerNode.setAttribute("showingsummary", "true");
@ -1763,8 +1687,7 @@ const DownloadsFooter = {
/**
* Element corresponding to the footer of the downloads panel.
*/
get _footerNode()
{
get _footerNode() {
let node = document.getElementById("downloadsFooter");
if (!node) {
return null;

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

@ -47,8 +47,7 @@ const DownloadsButton = {
* Returns a reference to the downloads button position placeholder, or null
* if not available because it has been removed from the toolbars.
*/
get _placeholder()
{
get _placeholder() {
return document.getElementById("downloads-button");
},
@ -58,8 +57,7 @@ const DownloadsButton = {
* NOTE: This function should limit the input/output it performs to improve
* startup time.
*/
initializeIndicator: function DB_initializeIndicator()
{
initializeIndicator() {
DownloadsIndicatorView.ensureInitialized();
},
@ -76,8 +74,7 @@ const DownloadsButton = {
* placeholder is an ordinary button defined in the browser window that can be
* moved freely between the toolbars and the customization palette.
*/
customizeStart: function DB_customizeStart()
{
customizeStart() {
// Prevent the indicator from being displayed as a temporary anchor
// during customization, even if requested using the getAnchor method.
this._customizing = true;
@ -87,8 +84,7 @@ const DownloadsButton = {
/**
* This function is called when toolbar customization ends.
*/
customizeDone: function DB_customizeDone()
{
customizeDone() {
this._customizing = false;
DownloadsIndicatorView.afterCustomize();
},
@ -99,8 +95,7 @@ const DownloadsButton = {
*
* @return Anchor element, or null if the indicator is not visible.
*/
_getAnchorInternal: function DB_getAnchorInternal()
{
_getAnchorInternal() {
let indicator = DownloadsIndicatorView.indicator;
if (!indicator) {
// Exit now if the indicator overlay isn't loaded yet, or if the button
@ -128,18 +123,15 @@ const DownloadsButton = {
* Called once the indicator overlay has loaded. Gets a boolean
* argument representing the indicator visibility.
*/
checkIsVisible: function DB_checkIsVisible(aCallback)
{
function DB_CEV_callback() {
checkIsVisible(aCallback) {
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => {
if (!this._placeholder) {
aCallback(false);
} else {
let element = DownloadsIndicatorView.indicator || this._placeholder;
aCallback(isElementVisible(element.parentNode));
}
}
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay,
DB_CEV_callback.bind(this));
});
},
/**
@ -156,40 +148,33 @@ const DownloadsButton = {
* panel should be anchored, or null if an anchor is not available (for
* example because both the tab bar and the navigation bar are hidden).
*/
getAnchor: function DB_getAnchor(aCallback)
{
getAnchor(aCallback) {
// Do not allow anchoring the panel to the element while customizing.
if (this._customizing) {
aCallback(null);
return;
}
function DB_GA_callback() {
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => {
this._anchorRequested = true;
aCallback(this._getAnchorInternal());
}
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay,
DB_GA_callback.bind(this));
});
},
/**
* Allows the temporary anchor to be hidden.
*/
releaseAnchor: function DB_releaseAnchor()
{
releaseAnchor() {
this._anchorRequested = false;
this._getAnchorInternal();
},
get _tabsToolbar()
{
get _tabsToolbar() {
delete this._tabsToolbar;
return this._tabsToolbar = document.getElementById("TabsToolbar");
},
get _navBar()
{
get _navBar() {
delete this._navBar;
return this._navBar = document.getElementById("nav-bar");
}
@ -219,8 +204,7 @@ const DownloadsIndicatorView = {
/**
* Prepares the downloads indicator to be displayed.
*/
ensureInitialized: function DIV_ensureInitialized()
{
ensureInitialized() {
if (this._initialized) {
return;
}
@ -233,8 +217,7 @@ const DownloadsIndicatorView = {
/**
* Frees the internal resources related to the indicator.
*/
ensureTerminated: function DIV_ensureTerminated()
{
ensureTerminated() {
if (!this._initialized) {
return;
}
@ -255,8 +238,7 @@ const DownloadsIndicatorView = {
* Ensures that the user interface elements required to display the indicator
* are loaded, then invokes the given callback.
*/
_ensureOperational: function DIV_ensureOperational(aCallback)
{
_ensureOperational(aCallback) {
if (this._operational) {
if (aCallback) {
aCallback();
@ -270,23 +252,21 @@ const DownloadsIndicatorView = {
return;
}
function DIV_EO_callback() {
this._operational = true;
// If the view is initialized, we need to update the elements now that
// they are finally available in the document.
if (this._initialized) {
DownloadsCommon.getIndicatorData(window).refreshView(this);
}
if (aCallback) {
aCallback();
}
}
DownloadsOverlayLoader.ensureOverlayLoaded(
DownloadsButton.kIndicatorOverlay,
DIV_EO_callback.bind(this));
DownloadsButton.kIndicatorOverlay,
() => {
this._operational = true;
// If the view is initialized, we need to update the elements now that
// they are finally available in the document.
if (this._initialized) {
DownloadsCommon.getIndicatorData(window).refreshView(this);
}
if (aCallback) {
aCallback();
}
});
},
//////////////////////////////////////////////////////////////////////////////
@ -302,8 +282,7 @@ const DownloadsIndicatorView = {
* @param aNode
* the node whose panel we're interested in.
*/
_isAncestorPanelOpen: function DIV_isAncestorPanelOpen(aNode)
{
_isAncestorPanelOpen(aNode) {
while (aNode && aNode.localName != "panel") {
aNode = aNode.parentNode;
}
@ -317,8 +296,7 @@ const DownloadsIndicatorView = {
* @param aType
* Set to "start" for new downloads, "finish" for completed downloads.
*/
showEventNotification: function DIV_showEventNotification(aType)
{
showEventNotification(aType) {
if (!this._initialized) {
return;
}
@ -373,7 +351,7 @@ const DownloadsIndicatorView = {
notifier.style.transform = "translate(" + translateX + ", " + translateY + ")";
}
notifier.setAttribute("notification", aType);
this._notificationTimeout = setTimeout(function () {
this._notificationTimeout = setTimeout(() => {
notifier.removeAttribute("notification");
notifier.style.transform = '';
}, 1000);
@ -386,8 +364,7 @@ const DownloadsIndicatorView = {
* Indicates whether the indicator should be shown because there are some
* downloads to be displayed.
*/
set hasDownloads(aValue)
{
set hasDownloads(aValue) {
if (this._hasDownloads != aValue || (!this._operational && aValue)) {
this._hasDownloads = aValue;
@ -398,8 +375,7 @@ const DownloadsIndicatorView = {
}
return aValue;
},
get hasDownloads()
{
get hasDownloads() {
return this._hasDownloads;
},
_hasDownloads: false,
@ -408,8 +384,7 @@ const DownloadsIndicatorView = {
* Status text displayed in the indicator. If this is set to an empty value,
* then the small downloads icon is displayed instead of the text.
*/
set counter(aValue)
{
set counter(aValue) {
if (!this._operational) {
return this._counter;
}
@ -433,8 +408,7 @@ const DownloadsIndicatorView = {
* progress bar is hidden if the current progress is unknown and no status
* text is set in the "counter" property.
*/
set percentComplete(aValue)
{
set percentComplete(aValue) {
if (!this._operational) {
return this._percentComplete;
}
@ -458,8 +432,7 @@ const DownloadsIndicatorView = {
* Setting this property forces a paused progress bar to be displayed, even if
* the current progress information is unavailable.
*/
set paused(aValue)
{
set paused(aValue) {
if (!this._operational) {
return this._paused;
}
@ -479,8 +452,7 @@ const DownloadsIndicatorView = {
/**
* Set when the indicator should draw user attention to itself.
*/
set attention(aValue)
{
set attention(aValue) {
if (!this._operational) {
return this._attention;
}
@ -500,14 +472,12 @@ const DownloadsIndicatorView = {
//////////////////////////////////////////////////////////////////////////////
//// User interface event functions
onWindowUnload: function DIV_onWindowUnload()
{
onWindowUnload() {
// This function is registered as an event listener, we can't use "this".
DownloadsIndicatorView.ensureTerminated();
},
onCommand: function DIV_onCommand(aEvent)
{
onCommand(aEvent) {
// If the downloads button is in the menu panel, open the Library
let widgetGroup = CustomizableUI.getWidget("downloads-button");
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
@ -519,13 +489,11 @@ const DownloadsIndicatorView = {
aEvent.stopPropagation();
},
onDragOver: function DIV_onDragOver(aEvent)
{
onDragOver(aEvent) {
browserDragAndDrop.dragOver(aEvent);
},
onDrop: function DIV_onDrop(aEvent)
{
onDrop(aEvent) {
let dt = aEvent.dataTransfer;
// If dragged item is from our source, do not try to
// redownload already downloaded file.
@ -553,8 +521,7 @@ const DownloadsIndicatorView = {
* Returns a reference to the main indicator element, or null if the element
* is not present in the browser window yet.
*/
get indicator()
{
get indicator() {
if (this._indicator) {
return this._indicator;
}
@ -567,8 +534,7 @@ const DownloadsIndicatorView = {
return this._indicator = indicator;
},
get indicatorAnchor()
{
get indicatorAnchor() {
let widget = CustomizableUI.getWidget("downloads-button")
.forWindow(window);
if (widget.overflowed) {
@ -577,31 +543,28 @@ const DownloadsIndicatorView = {
return document.getElementById("downloads-indicator-anchor");
},
get _indicatorCounter()
{
get _indicatorCounter() {
return this.__indicatorCounter ||
(this.__indicatorCounter = document.getElementById("downloads-indicator-counter"));
},
get _indicatorProgress()
{
get _indicatorProgress() {
return this.__indicatorProgress ||
(this.__indicatorProgress = document.getElementById("downloads-indicator-progress"));
},
get notifier()
{
get notifier() {
return this._notifier ||
(this._notifier = document.getElementById("downloads-notification-anchor"));
},
_onCustomizedAway: function() {
_onCustomizedAway() {
this._indicator = null;
this.__indicatorCounter = null;
this.__indicatorProgress = null;
},
afterCustomize: function() {
afterCustomize() {
// If the cached indicator is not the one currently in the document,
// invalidate our references
if (this._indicator != document.getElementById("downloads-button")) {
@ -610,6 +573,6 @@ const DownloadsIndicatorView = {
this.ensureTerminated();
this.ensureInitialized();
}
}
},
};