summaryrefslogtreecommitdiffstats
path: root/application/palemoon/components/downloads
diff options
context:
space:
mode:
Diffstat (limited to 'application/palemoon/components/downloads')
-rw-r--r--application/palemoon/components/downloads/DownloadsCommon.jsm69
-rw-r--r--application/palemoon/components/downloads/content/allDownloadsViewOverlay.js69
-rw-r--r--application/palemoon/components/downloads/content/downloads.js33
-rw-r--r--application/palemoon/components/downloads/content/downloadsViewCommon.js28
4 files changed, 79 insertions, 120 deletions
diff --git a/application/palemoon/components/downloads/DownloadsCommon.jsm b/application/palemoon/components/downloads/DownloadsCommon.jsm
index 652d2433b..73467e813 100644
--- a/application/palemoon/components/downloads/DownloadsCommon.jsm
+++ b/application/palemoon/components/downloads/DownloadsCommon.jsm
@@ -373,26 +373,6 @@ 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 Download objects, generates and returns
* statistics about that collection.
*
@@ -431,38 +411,31 @@ this.DownloadsCommon = {
}
for (let download of downloads) {
- let state = DownloadsCommon.stateOfDownload(download);
- let maxBytes = DownloadsCommon.maxBytesOfDownload(download);
-
summary.numActive++;
- switch (state) {
- case nsIDM.DOWNLOAD_PAUSED:
- summary.numPaused++;
- break;
- case nsIDM.DOWNLOAD_SCANNING:
- summary.numScanning++;
- break;
- case nsIDM.DOWNLOAD_DOWNLOADING:
- summary.numDownloading++;
- if (maxBytes > 0 && download.speed > 0) {
- let sizeLeft = maxBytes - download.currentBytes;
- summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
- sizeLeft / download.speed);
- summary.slowestSpeed = Math.min(summary.slowestSpeed,
- download.speed);
- }
- break;
+
+ if (!download.stopped) {
+ summary.numDownloading++;
+ if (download.hasProgress && download.speed > 0) {
+ let sizeLeft = download.totalBytes - download.currentBytes;
+ summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
+ sizeLeft / download.speed);
+ summary.slowestSpeed = Math.min(summary.slowestSpeed,
+ download.speed);
+ }
+ } else if (download.canceled && download.hasPartialData) {
+ summary.numPaused++;
}
// Only add to total values if we actually know the download size.
- if (maxBytes > 0 && state != nsIDM.DOWNLOAD_CANCELED &&
- state != nsIDM.DOWNLOAD_FAILED) {
- summary.totalSize += maxBytes;
+ if (download.succeeded) {
+ summary.totalSize += download.target.size;
+ summary.totalTransferred += download.target.size;
+ } else if (download.hasProgress) {
+ summary.totalSize += download.totalBytes;
summary.totalTransferred += download.currentBytes;
}
}
- if (summary.numActive != 0 && summary.totalSize != 0 &&
- summary.numActive != summary.numScanning) {
+ if (summary.totalSize != 0) {
summary.percentComplete = (summary.totalTransferred /
summary.totalSize) * 100;
}
@@ -764,10 +737,8 @@ DownloadsDataCtor.prototype = {
state: DownloadsCommon.stateOfDownload(download),
endTime: download.endTime,
};
- if (download.succeeded ||
- (download.error && download.error.becauseBlocked)) {
- downloadMetaData.fileSize =
- DownloadsCommon.maxBytesOfDownload(download);
+ if (download.succeeded) {
+ downloadMetaData.fileSize = download.target.size;
}
PlacesUtils.annotations.setPageAnnotation(
diff --git a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
index a5cbb3a5f..50f77041b 100644
--- a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
+++ b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js
@@ -28,8 +28,14 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
*/
function HistoryDownload(aPlacesNode) {
// TODO (bug 829201): history downloads should get the referrer from Places.
- this.source = { url: aPlacesNode.uri };
- this.target = { path: undefined, size: undefined };
+ this.source = {
+ url: aPlacesNode.uri,
+ };
+ this.target = {
+ path: undefined,
+ exists: false,
+ size: undefined,
+ };
// In case this download cannot obtain its end time from the Places metadata,
// use the time from the Places node, that is the start time of the download.
@@ -63,6 +69,10 @@ HistoryDownload.prototype = {
this.canceled = metaData.state == nsIDM.DOWNLOAD_CANCELED ||
metaData.state == nsIDM.DOWNLOAD_PAUSED;
this.endTime = metaData.endTime;
+
+ // Normal history downloads are assumed to exist until the user interface
+ // is refreshed, at which point these values may be updated.
+ this.target.exists = true;
this.target.size = metaData.fileSize;
} catch (ex) {
// Metadata might be missing from a download that has started but hasn't
@@ -78,13 +88,11 @@ HistoryDownload.prototype = {
this.succeeded = !this.target.path;
this.error = this.target.path ? { message: "Unstarted download." } : null;
this.canceled = false;
- this.target.size = -1;
- }
- // This property is currently used to get the size of downloads, but will be
- // replaced by download.target.size when available for session downloads.
- this.totalBytes = this.target.size;
- this.currentBytes = this.target.size;
+ // These properties may be updated if the user interface is refreshed.
+ this.exists = false;
+ this.target.size = undefined;
+ }
},
/**
@@ -123,6 +131,20 @@ HistoryDownload.prototype = {
return Promise.resolve();
},
+
+ /**
+ * This method mimicks the "refresh" method of session downloads, except that
+ * it cannot notify that the data changed to the Downloads View.
+ */
+ refresh: Task.async(function* () {
+ try {
+ this.target.size = (yield OS.File.stat(this.target.path)).size;
+ this.target.exists = true;
+ } catch (ex) {
+ // We keep the known file size from the metadata, if any.
+ this.target.exists = false;
+ }
+ }),
};
/**
@@ -267,20 +289,8 @@ HistoryDownloadElementShell.prototype = {
return false;
switch (aCommand) {
case "downloadsCmd_open":
- // We cannot open a session download file unless it's succeeded.
- // If it's succeeded, we need to make sure the file was not removed,
- // as we do for past downloads.
- if (this._sessionDownload && !this.download.succeeded) {
- return false;
- }
-
- if (this._targetFileChecked) {
- return this._targetFileExists;
- }
-
- // If the target file information is not yet fetched,
- // temporarily assume that the file is in place.
- return this.download.succeeded;
+ // This property is false if the download did not succeed.
+ return this.download.target.exists;
case "downloadsCmd_show":
// TODO: Bug 827010 - Handle part-file asynchronously.
if (this._sessionDownload && this.download.target.partFilePath) {
@@ -290,13 +300,8 @@ HistoryDownloadElementShell.prototype = {
}
}
- if (this._targetFileChecked) {
- return this._targetFileExists;
- }
-
- // If the target file information is not yet fetched,
- // temporarily assume that the file is in place.
- return this.download.succeeded;
+ // This property is false if the download did not succeed.
+ return this.download.target.exists;
case "downloadsCmd_pauseResume":
return this.download.hasPartialData && !this.download.error;
case "downloadsCmd_retry":
@@ -430,7 +435,7 @@ HistoryDownloadElementShell.prototype = {
_checkTargetFileOnSelect: Task.async(function* () {
try {
- this._targetFileExists = yield OS.File.exists(this.download.target.path);
+ yield this.download.refresh();
} finally {
// Do not try to check for existence again if this failed once.
this._targetFileChecked = true;
@@ -440,6 +445,10 @@ HistoryDownloadElementShell.prototype = {
if (this.element.selected) {
goUpdateDownloadCommands();
}
+
+ // Ensure the interface has been updated based on the new values. We need to
+ // do this because history downloads can't trigger update notifications.
+ this._updateProgress();
}),
};
diff --git a/application/palemoon/components/downloads/content/downloads.js b/application/palemoon/components/downloads/content/downloads.js
index 01682d325..199324b6b 100644
--- a/application/palemoon/components/downloads/content/downloads.js
+++ b/application/palemoon/components/downloads/content/downloads.js
@@ -555,7 +555,7 @@ const DownloadsPanel = {
// do these checks on a background thread, and don't prevent the panel to
// be displayed while these checks are being performed.
for (let viewItem of DownloadsView._visibleViewItems.values()) {
- viewItem.verifyTargetExists();
+ viewItem.download.refresh().catch(Cu.reportError);
}
if (aAnchor) {
@@ -1063,7 +1063,6 @@ function DownloadsViewItem(download, aElement) {
this.element.classList.add("download-state");
this._updateState();
- this.verifyTargetExists();
}
DownloadsViewItem.prototype = {
@@ -1078,41 +1077,11 @@ DownloadsViewItem.prototype = {
this.element.setAttribute("image", this.image);
this.element.setAttribute("state",
DownloadsCommon.stateOfDownload(this.download));
-
- if (this.download.succeeded) {
- // We assume the existence of the target of a download that just completed
- // successfully, without checking the condition in the background. If the
- // panel is already open, this will take effect immediately. If the panel
- // is opened later, a new background existence check will be performed.
- this.element.setAttribute("exists", "true");
- }
},
onChanged() {
this._updateProgress();
},
-
- /**
- * 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
- * presented visually.
- *
- * The existence check is executed on a background thread.
- */
- verifyTargetExists: function DVI_verifyTargetExists() {
- // We don't need to check if the download is not finished successfully.
- if (!this.download.succeeded) {
- return;
- }
-
- OS.File.exists(this.download.target.path).then(aExists => {
- if (aExists) {
- this.element.setAttribute("exists", "true");
- } else {
- this.element.removeAttribute("exists");
- }
- }).catch(Cu.reportError);
- },
};
////////////////////////////////////////////////////////////////////////////////
diff --git a/application/palemoon/components/downloads/content/downloadsViewCommon.js b/application/palemoon/components/downloads/content/downloadsViewCommon.js
index 999d82317..7ae3eb850 100644
--- a/application/palemoon/components/downloads/content/downloadsViewCommon.js
+++ b/application/palemoon/components/downloads/content/downloadsViewCommon.js
@@ -142,6 +142,15 @@ DownloadElementShell.prototype = {
* namely the progress bar and the status line.
*/
_updateProgress() {
+ if (this.download.succeeded) {
+ // We only need to add or remove this attribute for succeeded downloads.
+ if (this.download.target.exists) {
+ this.element.setAttribute("exists", "true");
+ } else {
+ this.element.removeAttribute("exists");
+ }
+ }
+
// The progress bar is only displayed for in-progress downloads.
if (this.download.hasProgress) {
this.element.setAttribute("progressmode", "normal");
@@ -182,26 +191,26 @@ DownloadElementShell.prototype = {
let tip = "";
if (!this.download.stopped) {
- let maxBytes = DownloadsCommon.maxBytesOfDownload(this.download);
+ let total = this.download.hasProgress ? this.download.totalBytes : -1;
// By default, extended status information including the individual
// download rate is displayed in the tooltip. The history view overrides
// the getter and displays the detials in the main area instead.
[text] = DownloadUtils.getDownloadStatusNoRate(
this.download.currentBytes,
- maxBytes,
+ total,
this.download.speed,
this.lastEstimatedSecondsLeft);
let newEstimatedSecondsLeft;
[tip, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
this.download.currentBytes,
- maxBytes,
+ total,
this.download.speed,
this.lastEstimatedSecondsLeft);
this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
} else if (this.download.canceled && this.download.hasPartialData) {
- let maxBytes = DownloadsCommon.maxBytesOfDownload(this.download);
+ let total = this.download.hasProgress ? this.download.totalBytes : -1;
let transfer = DownloadUtils.getTransferTotal(this.download.currentBytes,
- maxBytes);
+ total);
// We use the same XUL label to display both the state and the amount
// transferred, for example "Paused - 1.1 MB".
@@ -213,12 +222,13 @@ DownloadElementShell.prototype = {
let stateLabel;
if (this.download.succeeded) {
- // For completed downloads, show the file size (e.g. "1.5 MB")
- let maxBytes = DownloadsCommon.maxBytesOfDownload(this.download);
- if (maxBytes >= 0) {
- let [size, unit] = DownloadUtils.convertByteUnits(maxBytes);
+ // For completed downloads, show the file size (e.g. "1.5 MB").
+ if (this.download.target.size !== undefined) {
+ let [size, unit] = DownloadUtils.convertByteUnits(
+ this.download.target.size);
stateLabel = s.sizeWithUnits(size, unit);
} else {
+ // History downloads may not have a size defined.
stateLabel = s.sizeUnknown;
}
} else if (this.download.canceled) {