[PALEMOON] Bug 1117141 - Part 2 of 2 - Refactor notifications and remove the DownloadsDataItem object

This commit is contained in:
janekptacijarabaci 2018-07-29 11:41:22 +02:00 • committed by Roy Tam
commit 63e8a36496
4 changed files with 234 additions and 593 deletions

View file

@ -2,8 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsDataItem",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
@ -127,21 +125,6 @@ HistoryDownload.prototype = {
},
};
/**
* Represents a download from the browser history. It uses the same interface as
* the DownloadsDataItem object.
*
* @param aPlacesNode
* The Places node for the history download.
*/
function DownloadsHistoryDataItem(aPlacesNode) {
this.download = new HistoryDownload(aPlacesNode);
}
DownloadsHistoryDataItem.prototype = {
__proto__: DownloadsDataItem.prototype,
};
/**
* A download element shell is responsible for handling the commands and the
* displayed data for a single download view element.
@ -157,23 +140,23 @@ DownloadsHistoryDataItem.prototype = {
* The caller is also responsible for forwarding status notifications for
* session downloads, calling the onStateChanged and onChanged methods.
*
* @param [optional] aSessionDataItem
* The session download, required if aHistoryDataItem is not set.
* @param [optional] aHistoryDataItem
* The history download, required if aSessionDataItem is not set.
* @param [optional] aSessionDownload
* The session download, required if aHistoryDownload is not set.
* @param [optional] aHistoryDownload
* The history download, required if aSessionDownload is not set.
*/
function HistoryDownloadElementShell(aSessionDataItem, aHistoryDataItem) {
function HistoryDownloadElementShell(aSessionDownload, aHistoryDownload) {
this.element = document.createElement("richlistitem");
this.element._shell = this;
this.element.classList.add("download");
this.element.classList.add("download-state");
if (aSessionDataItem) {
this.sessionDataItem = aSessionDataItem;
if (aSessionDownload) {
this.sessionDownload = aSessionDownload;
}
if (aHistoryDataItem) {
this.historyDataItem = aHistoryDataItem;
if (aHistoryDownload) {
this.historyDownload = aHistoryDownload;
}
}
@ -196,20 +179,20 @@ HistoryDownloadElementShell.prototype = {
get active() !!this._active,
/**
* DownloadsDataItem or DownloadsHistoryDataItem object to use for displaying
* information and for executing commands in the user interface.
* Overrides the base getter to return the Download or HistoryDownload object
* for displaying information and executing commands in the user interface.
*/
get dataItem() this._sessionDataItem || this._historyDataItem,
get download() this._sessionDownload || this._historyDownload,
_sessionDataItem: null,
get sessionDataItem() this._sessionDataItem,
set sessionDataItem(aValue) {
if (this._sessionDataItem != aValue) {
if (!aValue && !this._historyDataItem) {
throw new Error("Should always have either a dataItem or a historyDataItem");
_sessionDownload: null,
get sessionDownload() this._sessionDownload,
set sessionDownload(aValue) {
if (this._sessionDownload != aValue) {
if (!aValue && !this._historyDownload) {
throw new Error("Should always have either a Download or a HistoryDownload");
}
this._sessionDataItem = aValue;
this._sessionDownload = aValue;
this.ensureActive();
this._updateUI();
@ -217,19 +200,19 @@ HistoryDownloadElementShell.prototype = {
return aValue;
},
_historyDataItem: null,
get historyDataItem() this._historyDataItem,
set historyDataItem(aValue) {
if (this._historyDataItem != aValue) {
if (!aValue && !this._sessionDataItem) {
throw new Error("Should always have either a dataItem or a historyDataItem");
_historyDownload: null,
get historyDownload() this._historyDownload,
set historyDownload(aValue) {
if (this._historyDownload != aValue) {
if (!aValue && !this._sessionDownload) {
throw new Error("Should always have either a Download or a HistoryDownload");
}
this._historyDataItem = aValue;
this._historyDownload = aValue;
// We don't need to update the UI if we had a session data item, because
// the places information isn't used in this case.
if (!this._sessionDataItem) {
if (!this._sessionDownload) {
this._updateUI();
}
}
@ -286,7 +269,7 @@ HistoryDownloadElementShell.prototype = {
// 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._sessionDataItem && !this.download.succeeded) {
if (this._sessionDownload && !this.download.succeeded) {
return false;
}
@ -299,7 +282,7 @@ HistoryDownloadElementShell.prototype = {
return this.download.succeeded;
case "downloadsCmd_show":
// TODO: Bug 827010 - Handle part-file asynchronously.
if (this._sessionDataItem && this.download.target.partFilePath) {
if (this._sessionDownload && this.download.target.partFilePath) {
let partFile = new FileUtils.File(this.download.target.partFilePath);
if (partFile.exists()) {
return true;
@ -323,7 +306,7 @@ HistoryDownloadElementShell.prototype = {
// We don't want in-progress downloads to be removed accidentally.
return this.download.stopped;
case "downloadsCmd_cancel":
return !!this._sessionDataItem;
return !!this._sessionDownload;
}
return false;
},
@ -351,13 +334,13 @@ HistoryDownloadElementShell.prototype = {
break;
}
case "cmd_delete": {
if (this._sessionDataItem) {
if (this._sessionDownload) {
Downloads.getList(Downloads.ALL)
.then(list => list.remove(this.download))
.then(() => this.download.finalize(true))
.catch(Cu.reportError);
}
if (this._historyDataItem) {
if (this._historyDownload) {
let uri = NetUtil.newURI(this.download.source.url);
PlacesUtils.bhistory.removePage(uri);
}
@ -480,7 +463,7 @@ function DownloadsPlacesView(aRichListBox, aActive = true) {
this._downloadElementsShellsForURI = new Map();
// Map download data items to their element shells.
this._viewItemsForDataItems = new WeakMap();
this._viewItemsForDownloads = new WeakMap();
// Points to the last session download element. We keep track of this
// in order to keep all session downloads above past downloads.
@ -626,14 +609,12 @@ DownloadsPlacesView.prototype = {
* alongside the other session downloads. If we don't, then we go ahead
* and create a new element for the download.
*
* @param aDataItem
* The data item of a session download. Set to null for history
* downloads data.
* @param [optional] sessionDownload
* A Download object, or null for history downloads.
* @param [optional] aPlacesNode
* The places node for a history download. Required if there's no data
* item.
* The Places node for a history download, or null for session downloads.
* @param [optional] aNewest
* @see onDataItemAdded. Ignored for history downloads.
* @see onDownloadAdded. Ignored for history downloads.
* @param [optional] aDocumentFragment
* To speed up the appending of multiple elements to the end of the
* list which are coming in a single batch (i.e. invalidateContainer),
@ -641,10 +622,8 @@ DownloadsPlacesView.prototype = {
* be appended. It's the caller's job to ensure the fragment is merged
* to the richlistbox at the end.
*/
_addDownloadData:
function DPV_addDownloadData(aDataItem, aPlacesNode, aNewest = false,
_addDownloadData(sessionDownload, aPlacesNode, aNewest = false,
aDocumentFragment = null) {
let sessionDownload = aDataItem && aDataItem.download;
let downloadURI = aPlacesNode ? aPlacesNode.uri
: sessionDownload.source.url;
let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI);
@ -670,21 +649,21 @@ DownloadsPlacesView.prototype = {
// item).
//
// Note: If a cancelled session download is already in the list, and the
// download is retired, onDataItemAdded is called again for the same
// download is retried, onDownloadAdded is called again for the same
// data item. Thus, we also check that we make sure we don't have a view item
// already.
if (!shouldCreateShell &&
aDataItem && !this._viewItemsForDataItems.has(aDataItem)) {
sessionDownload && !this._viewItemsForDownloads.has(sessionDownload)) {
// If there's a past-download-only shell for this download-uri with no
// associated data item, use it for the new data item. Otherwise, go ahead
// and create another shell.
shouldCreateShell = true;
for (let shell of shellsForURI) {
if (!shell.sessionDataItem) {
if (!shell.sessionDownload) {
shouldCreateShell = false;
shell.sessionDataItem = aDataItem;
shell.sessionDownload = sessionDownload;
newOrUpdatedShell = shell;
this._viewItemsForDataItems.set(aDataItem, shell);
this._viewItemsForDownloads.set(sessionDownload, shell);
break;
}
}
@ -694,18 +673,20 @@ DownloadsPlacesView.prototype = {
// If we are adding a new history download here, it means there is no
// associated session download, thus we must read the Places metadata,
// because it will not be obscured by the session download.
let historyDataItem = null;
let historyDownload = null;
if (aPlacesNode) {
let metaData = this._getCachedPlacesMetaDataFor(aPlacesNode.uri);
historyDataItem = new DownloadsHistoryDataItem(aPlacesNode);
historyDataItem.download.updateFromMetaData(metaData);
historyDownload = new HistoryDownload(aPlacesNode);
historyDownload.updateFromMetaData(metaData);
}
let shell = new HistoryDownloadElementShell(aDataItem, historyDataItem);
let shell = new HistoryDownloadElementShell(sessionDownload,
historyDownload);
shell.element._placesNode = aPlacesNode;
newOrUpdatedShell = shell;
shellsForURI.add(shell);
if (aDataItem)
this._viewItemsForDataItems.set(aDataItem, shell);
if (sessionDownload) {
this._viewItemsForDownloads.set(sessionDownload, shell);
}
}
else if (aPlacesNode) {
// We are updating information for a history download for which we have
@ -720,9 +701,9 @@ DownloadsPlacesView.prototype = {
// changed, just the reference to the Places node object is different.
// So, we update all the node references and keep the metadata intact.
for (let shell of shellsForURI) {
if (!shell.historyDataItem) {
if (!shell.historyDownload) {
// Create the element to host the metadata when needed.
shell.historyDataItem = new DownloadsHistoryDataItem(aPlacesNode);
shell.historyDownload = new HistoryDownload(aPlacesNode);
}
shell.element._placesNode = aPlacesNode;
}
@ -740,7 +721,7 @@ DownloadsPlacesView.prototype = {
// More generally, if a new download is added, should be made visible.
this._richlistbox.ensureElementIsVisible(newOrUpdatedShell.element);
}
else if (aDataItem) {
} else if (sessionDownload) {
let before = this._lastSessionDownloadElement ?
this._lastSessionDownloadElement.nextSibling : this._richlistbox.firstChild;
this._richlistbox.insertBefore(newOrUpdatedShell.element, before);
@ -791,8 +772,8 @@ DownloadsPlacesView.prototype = {
let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI);
if (shellsForURI) {
for (let shell of shellsForURI) {
if (shell.sessionDataItem) {
shell.historyDataItem = null;
if (shell.sessionDownload) {
shell.historyDownload = null;
}
else {
this._removeElement(shell.element);
@ -804,15 +785,13 @@ DownloadsPlacesView.prototype = {
}
},
_removeSessionDownloadFromView:
function DPV__removeSessionDownloadFromView(aDataItem) {
let download = aDataItem.download;
_removeSessionDownloadFromView(download) {
let shells = this._downloadElementsShellsForURI
.get(download.source.url);
if (shells.size == 0)
throw new Error("Should have had at leaat one shell for this uri");
let shell = this._viewItemsForDataItems.get(aDataItem);
let shell = this._viewItemsForDownloads.get(download);
if (!shells.has(shell))
throw new Error("Missing download element shell in shells list for url");
@ -820,7 +799,7 @@ DownloadsPlacesView.prototype = {
// view item for this this particular data item go away.
// If there's only one item for this download uri, we should only
// keep it if it is associated with a history download.
if (shells.size > 1 || !shell.historyDataItem) {
if (shells.size > 1 || !shell.historyDownload) {
this._removeElement(shell.element);
shells.delete(shell);
if (shells.size == 0)
@ -832,10 +811,10 @@ DownloadsPlacesView.prototype = {
// Previously, we did not use the Places metadata because it was obscured
// by the session download. Since this is no longer the case, we have to
// read the latest metadata before removing the session download.
let url = shell.historyDataItem.download.source.url;
let url = shell.historyDownload.source.url;
let metaData = this._getPlacesMetaDataFor(url);
shell.historyDataItem.download.updateFromMetaData(metaData);
shell.sessionDataItem = null;
shell.historyDownload.updateFromMetaData(metaData);
shell.sessionDownload = null;
// Move it below the session-download items;
if (this._lastSessionDownloadElement == shell.element) {
this._lastSessionDownloadElement = shell.element.previousSibling;
@ -1108,22 +1087,20 @@ DownloadsPlacesView.prototype = {
this._ensureInitialSelection();
},
onDataItemAdded: function DPV_onDataItemAdded(aDataItem, aNewest) {
this._addDownloadData(aDataItem, null, aNewest);
onDownloadAdded(download, newest) {
this._addDownloadData(download, null, newest);
},
onDataItemRemoved: function DPV_onDataItemRemoved(aDataItem) {
this._removeSessionDownloadFromView(aDataItem);
onDownloadStateChanged(download) {
this._viewItemsForDownloads.get(download).onStateChanged();
},
// DownloadsView
onDataItemStateChanged(aDataItem) {
this._viewItemsForDataItems.get(aDataItem).onStateChanged();
onDownloadChanged(download) {
this._viewItemsForDownloads.get(download).onChanged();
},
// DownloadsView
onDataItemChanged(aDataItem) {
this._viewItemsForDataItems.get(aDataItem).onChanged();
onDownloadRemoved(download) {
this._removeSessionDownloadFromView(download);
},
supportsCommand: function DPV_supportsCommand(aCommand) {