diff options
Diffstat (limited to 'application/palemoon/components/downloads/DownloadsCommon.jsm')
-rw-r--r-- | application/palemoon/components/downloads/DownloadsCommon.jsm | 239 |
1 files changed, 113 insertions, 126 deletions
diff --git a/application/palemoon/components/downloads/DownloadsCommon.jsm b/application/palemoon/components/downloads/DownloadsCommon.jsm index aac43d1973..c2185f6236 100644 --- a/application/palemoon/components/downloads/DownloadsCommon.jsm +++ b/application/palemoon/components/downloads/DownloadsCommon.jsm @@ -379,6 +379,26 @@ this.DownloadsCommon = { }, /** + * Returns the highest number of bytes transferred or the known size of the + * given Download object, or -1 if the size is not available. Callers should + * use Download properties directly when possible. + */ + maxBytesOfDownload(download) { + if (download.succeeded) { + // If the download succeeded, show the final size if available, otherwise + // use the last known number of bytes transferred. The final size on disk + // will be available when bug 941063 is resolved. + return download.hasProgress ? download.totalBytes : download.currentBytes; + } else if (download.hasProgress) { + // If the final size and progress are known, use them. + return download.totalBytes; + } else { + // The download final size and progress percentage is unknown. + return -1; + } + }, + + /** * Given an iterable collection of DownloadDataItems, generates and returns * statistics about that collection. * @@ -418,8 +438,12 @@ this.DownloadsCommon = { } for (let dataItem of aDataItems) { + let download = dataItem.download; + let state = DownloadsCommon.stateOfDownload(download); + let maxBytes = DownloadsCommon.maxBytesOfDownload(download); + summary.numActive++; - switch (dataItem.state) { + switch (state) { case nsIDM.DOWNLOAD_PAUSED: summary.numPaused++; break; @@ -428,21 +452,20 @@ this.DownloadsCommon = { break; case nsIDM.DOWNLOAD_DOWNLOADING: summary.numDownloading++; - if (dataItem.maxBytes > 0 && dataItem.download.speed > 0) { - let sizeLeft = dataItem.maxBytes - dataItem.download.currentBytes; + if (maxBytes > 0 && download.speed > 0) { + let sizeLeft = maxBytes - download.currentBytes; summary.rawTimeLeft = Math.max(summary.rawTimeLeft, - sizeLeft / dataItem.download.speed); + sizeLeft / download.speed); summary.slowestSpeed = Math.min(summary.slowestSpeed, - dataItem.download.speed); + download.speed); } break; } // Only add to total values if we actually know the download size. - if (dataItem.maxBytes > 0 && - dataItem.state != nsIDM.DOWNLOAD_CANCELED && - dataItem.state != nsIDM.DOWNLOAD_FAILED) { - summary.totalSize += dataItem.maxBytes; - summary.totalTransferred += dataItem.download.currentBytes; + if (maxBytes > 0 && state != nsIDM.DOWNLOAD_CANCELED && + state != nsIDM.DOWNLOAD_FAILED) { + summary.totalSize += maxBytes; + summary.totalTransferred += download.currentBytes; } } @@ -498,7 +521,7 @@ this.DownloadsCommon = { /** * Opens a downloaded file. - * If you've a dataItem, you should call dataItem.openLocalFile. + * * @param aFile * the downloaded file to be opened. * @param aMimeInfo @@ -649,6 +672,7 @@ function DownloadsDataCtor(aPrivate) { // Contains all the available DownloadsDataItem objects. this.dataItems = new Set(); + this.oldDownloadStates = new Map(); // Array of view objects that should be notified when the available download // data changes. @@ -687,7 +711,9 @@ DownloadsDataCtor.prototype = { get canRemoveFinished() { for (let dataItem of this.dataItems) { - if (!dataItem.inProgress) { + let download = dataItem.download; + // Stopped, paused, and failed downloads with partial data are removed. + if (download.stopped && !(download.canceled && download.hasPartialData)) { return true; } } @@ -713,99 +739,97 @@ DownloadsDataCtor.prototype = { let dataItem = new DownloadsDataItem(aDownload); this._downloadToDataItemMap.set(aDownload, dataItem); this.dataItems.add(dataItem); + this.oldDownloadStates.set(aDownload, + DownloadsCommon.stateOfDownload(aDownload)); for (let view of this._views) { view.onDataItemAdded(dataItem, true); } - - this._updateDataItemState(dataItem); }, onDownloadChanged: function (aDownload) { - let dataItem = this._downloadToDataItemMap.get(aDownload); - if (!dataItem) { - Cu.reportError("Download doesn't exist."); - return; - } - - this._updateDataItemState(dataItem); - }, - - onDownloadRemoved: function (aDownload) - { - let dataItem = this._downloadToDataItemMap.get(aDownload); - if (!dataItem) { + let aDataItem = this._downloadToDataItemMap.get(aDownload); + if (!aDataItem) { Cu.reportError("Download doesn't exist."); return; } - this._downloadToDataItemMap.delete(aDownload); - this.dataItems.delete(dataItem); - for (let view of this._views) { - view.onDataItemRemoved(dataItem); - } - }, - - /** - * Updates the given data item and sends related notifications. - */ - _updateDataItemState: function (aDataItem) - { - let oldState = aDataItem.state; - let wasInProgress = aDataItem.inProgress; - let wasDone = aDataItem.done; - - aDataItem.updateFromJSDownload(); - - if (wasInProgress && !aDataItem.inProgress) { - aDataItem.endTime = Date.now(); - } + let oldState = this.oldDownloadStates.get(aDownload); + let newState = DownloadsCommon.stateOfDownload(aDownload); + this.oldDownloadStates.set(aDownload, newState); + + if (oldState != newState) { + if (aDownload.succeeded || + (aDownload.canceled && !aDownload.hasPartialData) || + aDownload.error) { + // Store the end time that may be displayed by the views. + aDownload.endTime = Date.now(); + + // This state transition code should actually be located in a Downloads + // API module (bug 941009). Moreover, the fact that state is stored as + // annotations should be ideally hidden behind methods of + // nsIDownloadHistory (bug 830415). + if (!this._isPrivate) { + try { + let downloadMetaData = { + state: DownloadsCommon.stateOfDownload(aDownload), + endTime: aDownload.endTime, + }; + if (aDownload.succeeded || + (aDownload.error && aDownload.error.becauseBlocked)) { + downloadMetaData.fileSize = + DownloadsCommon.maxBytesOfDownload(aDataItem.download); + } + + PlacesUtils.annotations.setPageAnnotation( + NetUtil.newURI(aDownload.source.url), + "downloads/metaData", + JSON.stringify(downloadMetaData), 0, + PlacesUtils.annotations.EXPIRE_WITH_HISTORY); + } catch (ex) { + Cu.reportError(ex); + } + } + } - if (oldState != aDataItem.state) { for (let view of this._views) { try { - view.onDataItemStateChanged(aDataItem, oldState); + view.onDataItemStateChanged(aDataItem); } catch (ex) { Cu.reportError(ex); } } - // This state transition code should actually be located in a Downloads - // API module (bug 941009). Moreover, the fact that state is stored as - // annotations should be ideally hidden behind methods of - // nsIDownloadHistory (bug 830415). - if (!this._isPrivate && !aDataItem.inProgress) { - try { - let downloadMetaData = { state: aDataItem.state, - endTime: aDataItem.endTime }; - if (aDataItem.done) { - downloadMetaData.fileSize = aDataItem.maxBytes; - } - - // RRR: Annotation service throws here. commented out for now. - /*PlacesUtils.annotations.setPageAnnotation( - NetUtil.newURI(aDataItem.download.source.url), - "downloads/metaData", - JSON.stringify(downloadMetaData), 0, - PlacesUtils.annotations.EXPIRE_WITH_HISTORY);*/ - } catch (ex) { - Cu.reportError(ex); - } + if (aDownload.succeeded || + (aDownload.error && aDownload.error.becauseBlocked)) { + this._notifyDownloadEvent("finish"); } } - if (!aDataItem.newDownloadNotified) { - aDataItem.newDownloadNotified = true; + if (!aDownload.newDownloadNotified) { + aDownload.newDownloadNotified = true; this._notifyDownloadEvent("start"); } - if (!wasDone && aDataItem.done) { - this._notifyDownloadEvent("finish"); + for (let view of this._views) { + view.onDataItemChanged(aDataItem); + } + }, + + onDownloadRemoved: function (aDownload) + { + let dataItem = this._downloadToDataItemMap.get(aDownload); + if (!dataItem) { + Cu.reportError("Download doesn't exist."); + return; } + this._downloadToDataItemMap.delete(aDownload); + this.dataItems.delete(dataItem); + this.oldDownloadStates.delete(aDownload); for (let view of this._views) { - view.onDataItemChanged(aDataItem); + view.onDataItemRemoved(dataItem); } }, @@ -1333,6 +1357,8 @@ function DownloadsDataItem(aSource) } DownloadsDataItem.prototype = { + get state() DownloadsCommon.stateOfDownload(this.download), + /** * Initializes this object from the JavaScript API for downloads. * @@ -1344,51 +1370,7 @@ DownloadsDataItem.prototype = { _initFromJSDownload: function (aDownload) { this.download = aDownload; - this.endTime = Date.now(); - - this.updateFromJSDownload(); - }, - - /** - * Updates this object from the JavaScript API for downloads. - */ - updateFromJSDownload: function () - { - // Collapse state using the correct priority. - if (this.download.succeeded) { - this.state = nsIDM.DOWNLOAD_FINISHED; - } else if (this.download.error && - this.download.error.becauseBlockedByParentalControls) { - this.state = nsIDM.DOWNLOAD_BLOCKED_PARENTAL; - } else if (this.download.error) { - this.state = nsIDM.DOWNLOAD_FAILED; - } else if (this.download.canceled && this.download.hasPartialData) { - this.state = nsIDM.DOWNLOAD_PAUSED; - } else if (this.download.canceled) { - this.state = nsIDM.DOWNLOAD_CANCELED; - } else if (this.download.stopped) { - this.state = nsIDM.DOWNLOAD_NOTSTARTED; - } else { - this.state = nsIDM.DOWNLOAD_DOWNLOADING; - } - - if (this.download.succeeded) { - // If the download succeeded, show the final size if available, otherwise - // use the last known number of bytes transferred. The final size on disk - // will be available when bug 941063 is resolved. - this.maxBytes = this.download.hasProgress ? - this.download.totalBytes : - this.download.currentBytes; - this.percentComplete = 100; - } else if (this.download.hasProgress) { - // If the final size and progress are known, use them. - this.maxBytes = this.download.totalBytes; - this.percentComplete = this.download.progress; - } else { - // The download final size and progress percentage is unknown. - this.maxBytes = -1; - this.percentComplete = -1; - } + this.download.endTime = Date.now(); }, /** @@ -1896,9 +1878,10 @@ DownloadsIndicatorDataCtor.prototype = { }, // DownloadsView - onDataItemStateChanged(aDataItem, aOldState) { - if (aDataItem.state == nsIDM.DOWNLOAD_FINISHED || - aDataItem.state == nsIDM.DOWNLOAD_FAILED) { + onDataItemStateChanged(aDataItem) { + let download = aDataItem.download; + + if (download.succeeded || download.error) { this.attention = true; } @@ -2010,7 +1993,11 @@ DownloadsIndicatorDataCtor.prototype = { let dataItems = this._isPrivate ? PrivateDownloadsData.dataItems : DownloadsData.dataItems; for (let dataItem of dataItems) { - if (dataItem && dataItem.inProgress) { + if (!dataItem) { + continue; + } + let download = dataItem.download; + if (!download.stopped || (download.canceled && download.hasPartialData)) { yield dataItem; } } @@ -2164,7 +2151,7 @@ DownloadsSummaryData.prototype = { }, // DownloadsView - onDataItemStateChanged(aOldState) { + onDataItemStateChanged() { // Since the state of a download changed, reset the estimated time left. this._lastRawTimeLeft = -1; this._lastTimeLeft = -1; |