mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 11:37:30 +09:00
[PALEMOON] Bug 1127867 - Use the new back-end property to get the size of downloads asynchronously
This commit is contained in:
parent
ad8a1e1f50
commit
53aa070170
4 changed files with 79 additions and 120 deletions
|
|
@ -372,26 +372,6 @@ this.DownloadsCommon = {
|
||||||
return nsIDM.DOWNLOAD_NOTSTARTED;
|
return nsIDM.DOWNLOAD_NOTSTARTED;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Given an iterable collection of Download objects, generates and returns
|
||||||
* statistics about that collection.
|
* statistics about that collection.
|
||||||
|
|
@ -431,38 +411,31 @@ this.DownloadsCommon = {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let download of downloads) {
|
for (let download of downloads) {
|
||||||
let state = DownloadsCommon.stateOfDownload(download);
|
|
||||||
let maxBytes = DownloadsCommon.maxBytesOfDownload(download);
|
|
||||||
|
|
||||||
summary.numActive++;
|
summary.numActive++;
|
||||||
switch (state) {
|
|
||||||
case nsIDM.DOWNLOAD_PAUSED:
|
if (!download.stopped) {
|
||||||
summary.numPaused++;
|
summary.numDownloading++;
|
||||||
break;
|
if (download.hasProgress && download.speed > 0) {
|
||||||
case nsIDM.DOWNLOAD_SCANNING:
|
let sizeLeft = download.totalBytes - download.currentBytes;
|
||||||
summary.numScanning++;
|
summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
|
||||||
break;
|
sizeLeft / download.speed);
|
||||||
case nsIDM.DOWNLOAD_DOWNLOADING:
|
summary.slowestSpeed = Math.min(summary.slowestSpeed,
|
||||||
summary.numDownloading++;
|
download.speed);
|
||||||
if (maxBytes > 0 && download.speed > 0) {
|
}
|
||||||
let sizeLeft = maxBytes - download.currentBytes;
|
} else if (download.canceled && download.hasPartialData) {
|
||||||
summary.rawTimeLeft = Math.max(summary.rawTimeLeft,
|
summary.numPaused++;
|
||||||
sizeLeft / download.speed);
|
|
||||||
summary.slowestSpeed = Math.min(summary.slowestSpeed,
|
|
||||||
download.speed);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// Only add to total values if we actually know the download size.
|
// Only add to total values if we actually know the download size.
|
||||||
if (maxBytes > 0 && state != nsIDM.DOWNLOAD_CANCELED &&
|
if (download.succeeded) {
|
||||||
state != nsIDM.DOWNLOAD_FAILED) {
|
summary.totalSize += download.target.size;
|
||||||
summary.totalSize += maxBytes;
|
summary.totalTransferred += download.target.size;
|
||||||
|
} else if (download.hasProgress) {
|
||||||
|
summary.totalSize += download.totalBytes;
|
||||||
summary.totalTransferred += download.currentBytes;
|
summary.totalTransferred += download.currentBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (summary.numActive != 0 && summary.totalSize != 0 &&
|
if (summary.totalSize != 0) {
|
||||||
summary.numActive != summary.numScanning) {
|
|
||||||
summary.percentComplete = (summary.totalTransferred /
|
summary.percentComplete = (summary.totalTransferred /
|
||||||
summary.totalSize) * 100;
|
summary.totalSize) * 100;
|
||||||
}
|
}
|
||||||
|
|
@ -764,10 +737,8 @@ DownloadsDataCtor.prototype = {
|
||||||
state: DownloadsCommon.stateOfDownload(download),
|
state: DownloadsCommon.stateOfDownload(download),
|
||||||
endTime: download.endTime,
|
endTime: download.endTime,
|
||||||
};
|
};
|
||||||
if (download.succeeded ||
|
if (download.succeeded) {
|
||||||
(download.error && download.error.becauseBlocked)) {
|
downloadMetaData.fileSize = download.target.size;
|
||||||
downloadMetaData.fileSize =
|
|
||||||
DownloadsCommon.maxBytesOfDownload(download);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlacesUtils.annotations.setPageAnnotation(
|
PlacesUtils.annotations.setPageAnnotation(
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,14 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
|
||||||
*/
|
*/
|
||||||
function HistoryDownload(aPlacesNode) {
|
function HistoryDownload(aPlacesNode) {
|
||||||
// TODO (bug 829201): history downloads should get the referrer from Places.
|
// TODO (bug 829201): history downloads should get the referrer from Places.
|
||||||
this.source = { url: aPlacesNode.uri };
|
this.source = {
|
||||||
this.target = { path: undefined, size: undefined };
|
url: aPlacesNode.uri,
|
||||||
|
};
|
||||||
|
this.target = {
|
||||||
|
path: undefined,
|
||||||
|
exists: false,
|
||||||
|
size: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
// In case this download cannot obtain its end time from the Places metadata,
|
// 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.
|
// 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 ||
|
this.canceled = metaData.state == nsIDM.DOWNLOAD_CANCELED ||
|
||||||
metaData.state == nsIDM.DOWNLOAD_PAUSED;
|
metaData.state == nsIDM.DOWNLOAD_PAUSED;
|
||||||
this.endTime = metaData.endTime;
|
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;
|
this.target.size = metaData.fileSize;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// Metadata might be missing from a download that has started but hasn't
|
// 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.succeeded = !this.target.path;
|
||||||
this.error = this.target.path ? { message: "Unstarted download." } : null;
|
this.error = this.target.path ? { message: "Unstarted download." } : null;
|
||||||
this.canceled = false;
|
this.canceled = false;
|
||||||
this.target.size = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This property is currently used to get the size of downloads, but will be
|
// These properties may be updated if the user interface is refreshed.
|
||||||
// replaced by download.target.size when available for session downloads.
|
this.exists = false;
|
||||||
this.totalBytes = this.target.size;
|
this.target.size = undefined;
|
||||||
this.currentBytes = this.target.size;
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -123,6 +131,20 @@ HistoryDownload.prototype = {
|
||||||
|
|
||||||
return Promise.resolve();
|
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;
|
return false;
|
||||||
switch (aCommand) {
|
switch (aCommand) {
|
||||||
case "downloadsCmd_open":
|
case "downloadsCmd_open":
|
||||||
// We cannot open a session download file unless it's succeeded.
|
// This property is false if the download did not succeed.
|
||||||
// If it's succeeded, we need to make sure the file was not removed,
|
return this.download.target.exists;
|
||||||
// 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;
|
|
||||||
case "downloadsCmd_show":
|
case "downloadsCmd_show":
|
||||||
// TODO: Bug 827010 - Handle part-file asynchronously.
|
// TODO: Bug 827010 - Handle part-file asynchronously.
|
||||||
if (this._sessionDownload && this.download.target.partFilePath) {
|
if (this._sessionDownload && this.download.target.partFilePath) {
|
||||||
|
|
@ -290,13 +300,8 @@ HistoryDownloadElementShell.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._targetFileChecked) {
|
// This property is false if the download did not succeed.
|
||||||
return this._targetFileExists;
|
return this.download.target.exists;
|
||||||
}
|
|
||||||
|
|
||||||
// If the target file information is not yet fetched,
|
|
||||||
// temporarily assume that the file is in place.
|
|
||||||
return this.download.succeeded;
|
|
||||||
case "downloadsCmd_pauseResume":
|
case "downloadsCmd_pauseResume":
|
||||||
return this.download.hasPartialData && !this.download.error;
|
return this.download.hasPartialData && !this.download.error;
|
||||||
case "downloadsCmd_retry":
|
case "downloadsCmd_retry":
|
||||||
|
|
@ -430,7 +435,7 @@ HistoryDownloadElementShell.prototype = {
|
||||||
|
|
||||||
_checkTargetFileOnSelect: Task.async(function* () {
|
_checkTargetFileOnSelect: Task.async(function* () {
|
||||||
try {
|
try {
|
||||||
this._targetFileExists = yield OS.File.exists(this.download.target.path);
|
yield this.download.refresh();
|
||||||
} finally {
|
} finally {
|
||||||
// Do not try to check for existence again if this failed once.
|
// Do not try to check for existence again if this failed once.
|
||||||
this._targetFileChecked = true;
|
this._targetFileChecked = true;
|
||||||
|
|
@ -440,6 +445,10 @@ HistoryDownloadElementShell.prototype = {
|
||||||
if (this.element.selected) {
|
if (this.element.selected) {
|
||||||
goUpdateDownloadCommands();
|
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();
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,7 @@ const DownloadsPanel = {
|
||||||
// do these checks on a background thread, and don't prevent the panel to
|
// do these checks on a background thread, and don't prevent the panel to
|
||||||
// be displayed while these checks are being performed.
|
// be displayed while these checks are being performed.
|
||||||
for (let viewItem of DownloadsView._visibleViewItems.values()) {
|
for (let viewItem of DownloadsView._visibleViewItems.values()) {
|
||||||
viewItem.verifyTargetExists();
|
viewItem.download.refresh().catch(Cu.reportError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aAnchor) {
|
if (aAnchor) {
|
||||||
|
|
@ -1063,7 +1063,6 @@ function DownloadsViewItem(download, aElement) {
|
||||||
this.element.classList.add("download-state");
|
this.element.classList.add("download-state");
|
||||||
|
|
||||||
this._updateState();
|
this._updateState();
|
||||||
this.verifyTargetExists();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadsViewItem.prototype = {
|
DownloadsViewItem.prototype = {
|
||||||
|
|
@ -1078,41 +1077,11 @@ DownloadsViewItem.prototype = {
|
||||||
this.element.setAttribute("image", this.image);
|
this.element.setAttribute("image", this.image);
|
||||||
this.element.setAttribute("state",
|
this.element.setAttribute("state",
|
||||||
DownloadsCommon.stateOfDownload(this.download));
|
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() {
|
onChanged() {
|
||||||
this._updateProgress();
|
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);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,15 @@ DownloadElementShell.prototype = {
|
||||||
* namely the progress bar and the status line.
|
* namely the progress bar and the status line.
|
||||||
*/
|
*/
|
||||||
_updateProgress() {
|
_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.
|
// The progress bar is only displayed for in-progress downloads.
|
||||||
if (this.download.hasProgress) {
|
if (this.download.hasProgress) {
|
||||||
this.element.setAttribute("progressmode", "normal");
|
this.element.setAttribute("progressmode", "normal");
|
||||||
|
|
@ -182,26 +191,26 @@ DownloadElementShell.prototype = {
|
||||||
let tip = "";
|
let tip = "";
|
||||||
|
|
||||||
if (!this.download.stopped) {
|
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
|
// By default, extended status information including the individual
|
||||||
// download rate is displayed in the tooltip. The history view overrides
|
// download rate is displayed in the tooltip. The history view overrides
|
||||||
// the getter and displays the detials in the main area instead.
|
// the getter and displays the detials in the main area instead.
|
||||||
[text] = DownloadUtils.getDownloadStatusNoRate(
|
[text] = DownloadUtils.getDownloadStatusNoRate(
|
||||||
this.download.currentBytes,
|
this.download.currentBytes,
|
||||||
maxBytes,
|
total,
|
||||||
this.download.speed,
|
this.download.speed,
|
||||||
this.lastEstimatedSecondsLeft);
|
this.lastEstimatedSecondsLeft);
|
||||||
let newEstimatedSecondsLeft;
|
let newEstimatedSecondsLeft;
|
||||||
[tip, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
|
[tip, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
|
||||||
this.download.currentBytes,
|
this.download.currentBytes,
|
||||||
maxBytes,
|
total,
|
||||||
this.download.speed,
|
this.download.speed,
|
||||||
this.lastEstimatedSecondsLeft);
|
this.lastEstimatedSecondsLeft);
|
||||||
this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
|
this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
|
||||||
} else if (this.download.canceled && this.download.hasPartialData) {
|
} 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,
|
let transfer = DownloadUtils.getTransferTotal(this.download.currentBytes,
|
||||||
maxBytes);
|
total);
|
||||||
|
|
||||||
// We use the same XUL label to display both the state and the amount
|
// We use the same XUL label to display both the state and the amount
|
||||||
// transferred, for example "Paused - 1.1 MB".
|
// transferred, for example "Paused - 1.1 MB".
|
||||||
|
|
@ -213,12 +222,13 @@ DownloadElementShell.prototype = {
|
||||||
let stateLabel;
|
let stateLabel;
|
||||||
|
|
||||||
if (this.download.succeeded) {
|
if (this.download.succeeded) {
|
||||||
// For completed downloads, show the file size (e.g. "1.5 MB")
|
// For completed downloads, show the file size (e.g. "1.5 MB").
|
||||||
let maxBytes = DownloadsCommon.maxBytesOfDownload(this.download);
|
if (this.download.target.size !== undefined) {
|
||||||
if (maxBytes >= 0) {
|
let [size, unit] = DownloadUtils.convertByteUnits(
|
||||||
let [size, unit] = DownloadUtils.convertByteUnits(maxBytes);
|
this.download.target.size);
|
||||||
stateLabel = s.sizeWithUnits(size, unit);
|
stateLabel = s.sizeWithUnits(size, unit);
|
||||||
} else {
|
} else {
|
||||||
|
// History downloads may not have a size defined.
|
||||||
stateLabel = s.sizeUnknown;
|
stateLabel = s.sizeUnknown;
|
||||||
}
|
}
|
||||||
} else if (this.download.canceled) {
|
} else if (this.download.canceled) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue