Bug 822710 (part 2) - Reduce annotations queries on downloads view first load.

r=Mano
This commit is contained in:
Marco Bonardo 2012-12-21 15:19:06 +01:00
parent ec97496687
commit d6034d0dd1

View File

@ -30,6 +30,8 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
"downloadsCmd_open", "downloadsCmd_show", "downloadsCmd_retry",
"downloadsCmd_openReferrer"];
const NOT_AVAILABLE = Number.MAX_VALUE;
function GetFileForFileURI(aFileURI)
Cc["@mozilla.org/network/protocol;1?name=file"]
.getService(Ci.nsIFileProtocolHandler)
@ -61,14 +63,18 @@ function GetFileForFileURI(aFileURI)
* The data item of a the session download. Required if aPlacesNode is not set
* @param [optional] aPlacesNode
* The places node for a past download. Required if aDataItem is not set.
* @param [optional] aAnnotations
* Map containing annotations values, to speed up the initial loading.
*/
function DownloadElementShell(aDataItem, aPlacesNode) {
function DownloadElementShell(aDataItem, aPlacesNode, aAnnotations) {
this._element = document.createElement("richlistitem");
this._element._shell = this;
this._element.classList.add("download");
this._element.classList.add("download-state");
if (aAnnotations)
this._annotations = aAnnotations;
if (aDataItem)
this.dataItem = aDataItem;
if (aPlacesNode)
@ -80,10 +86,11 @@ DownloadElementShell.prototype = {
get element() this._element,
// The data item for the download
_dataItem: null,
get dataItem() this._dataItem,
set dataItem(aValue) {
if (this._dataItem = aValue) {
if ((this._dataItem = aValue)) {
this._wasDone = this._dataItem.done;
this._wasInProgress = this._dataItem.inProgress;
}
@ -96,10 +103,15 @@ DownloadElementShell.prototype = {
return aValue;
},
_placesNode: null,
get placesNode() this._placesNode,
set placesNode(aNode) {
if (this._placesNode != aNode) {
this._annotations = new Map();
// Preserve the annotations map if this is the first loading and we got
// cached values.
if (this._placesNode || !this._annotations) {
this._annotations = new Map();
}
this._placesNode = aNode;
if (!this._dataItem && this._placesNode) {
this._wasInProgress = false;
@ -137,21 +149,30 @@ DownloadElementShell.prototype = {
// Helper for getting a places annotation set for the download.
_getAnnotation: function DES__getAnnotation(aAnnotation, aDefaultValue) {
if (this._annotations.has(aAnnotation))
return this._annotations.get(aAnnotation);
let value;
try {
value = PlacesUtils.annotations.getPageAnnotation(
this._downloadURIObj, aAnnotation);
if (this._annotations.has(aAnnotation))
value = this._annotations.get(aAnnotation);
// If the value is cached, or we know it doesn't exist, avoid a database
// lookup.
if (value === undefined) {
try {
value = PlacesUtils.annotations.getPageAnnotation(
this._downloadURIObj, aAnnotation);
}
catch(ex) {
value = NOT_AVAILABLE;
}
}
catch(ex) {
if (value === NOT_AVAILABLE) {
if (aDefaultValue === undefined) {
throw new Error("Could not get required annotation '" + aAnnotation +
"' for download with url '" + this.downloadURI + "'");
}
value = aDefaultValue;
}
this._annotations.set(aAnnotation, value);
return value;
},
@ -428,6 +449,7 @@ DownloadElementShell.prototype = {
case "downloadsCmd_cancel":
return this._dataItem != null;
}
return false;
},
_getTargetFileOrPartFileIfExists: function DES__getTargetFileOrPartFileIfExists() {
@ -523,6 +545,7 @@ DownloadElementShell.prototype = {
case nsIDM.DOWNLOAD_BLOCKED_POLICY:
return "downloadsCmd_openReferrer";
}
return "";
}
let command = getDefaultCommandForState(this._state);
if (this.isCommandEnabled(command))
@ -584,6 +607,38 @@ DownloadsPlacesView.prototype = {
}
},
_getAnnotationsFor: function DPV_getAnnotationsFor(aURI) {
if (!this._cachedAnnotations) {
this._cachedAnnotations = new Map();
for (let name of [ DESTINATION_FILE_URI_ANNO,
DESTINATION_FILE_NAME_ANNO,
DOWNLOAD_STATE_ANNO ]) {
let results = PlacesUtils.annotations.getAnnotationsWithName(name);
for (let result of results) {
let url = result.uri.spec;
if (!this._cachedAnnotations.has(url))
this._cachedAnnotations.set(url, new Map());
let m = this._cachedAnnotations.get(url);
m.set(result.annotationName, result.annotationValue);
}
}
}
let annotations = this._cachedAnnotations.get(aURI);
if (!annotations) {
// There are no annotations for this entry, that means it is quite old.
// Make up a fake annotations entry with default values.
annotations = new Map();
annotations.set(DESTINATION_FILE_URI_ANNO, NOT_AVAILABLE);
annotations.set(DESTINATION_FILE_NAME_ANNO, NOT_AVAILABLE);
}
// The state annotation has been added recently, so it's likely missing.
if (!annotations.has(DOWNLOAD_STATE_ANNO)) {
annotations.set(DOWNLOAD_STATE_ANNO, NOT_AVAILABLE);
}
return annotations;
},
/**
* Given a data item for a session download, or a places node for a past
* download, updates the view as necessary.
@ -612,7 +667,8 @@ DownloadsPlacesView.prototype = {
* to the richlistbox at the end.
*/
_addDownloadData:
function DPV_addDownload(aDataItem, aPlacesNode, aNewest = false, aDocumentFragment = null) {
function DPV_addDownloadData(aDataItem, aPlacesNode, aNewest = false,
aDocumentFragment = null) {
let downloadURI = aPlacesNode ? aPlacesNode.uri : aDataItem.uri;
let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI, null);
if (!shellsForURI) {
@ -658,9 +714,9 @@ DownloadsPlacesView.prototype = {
}
if (shouldCreateShell) {
let shell = new DownloadElementShell(aDataItem, aPlacesNode);
let shell = new DownloadElementShell(aDataItem, aPlacesNode,
this._getAnnotationsFor(downloadURI));
newOrUpdatedShell = shell;
element = shell.element;
shellsForURI.add(shell);
if (aDataItem)
this._viewItemsForDataItems.set(aDataItem, shell);
@ -763,8 +819,8 @@ DownloadsPlacesView.prototype = {
}
},
_place: "",
get place() this._place,
set place(val) {
// Don't reload everything if we don't have to.
if (this._place == val) {
@ -787,6 +843,7 @@ DownloadsPlacesView.prototype = {
return val;
},
_result: null,
get result() this._result,
set result(val) {
if (this._result == val)
@ -1023,6 +1080,7 @@ DownloadsPlacesView.prototype = {
// Set the state attribute so that only the appropriate items are displayed.
let contextMenu = document.getElementById("downloadsContextMenu");
contextMenu.setAttribute("state", element._shell._state);
return true;
},
onKeyPress: function DPV_onKeyPress(aEvent) {