зеркало из https://github.com/mozilla/gecko-dev.git
Bug 598229 (part 2) - Increase performance of Win7 JumpList favorites queries. r=sdwilsh,jimm sr=rstrong a=blocking
This commit is contained in:
Родитель
f0e456d04f
Коммит
00b2650bc7
|
@ -961,7 +961,7 @@ pref("browser.taskbar.lists.frequent.enabled", true);
|
||||||
pref("browser.taskbar.lists.recent.enabled", false);
|
pref("browser.taskbar.lists.recent.enabled", false);
|
||||||
pref("browser.taskbar.lists.maxListItemCount", 7);
|
pref("browser.taskbar.lists.maxListItemCount", 7);
|
||||||
pref("browser.taskbar.lists.tasks.enabled", true);
|
pref("browser.taskbar.lists.tasks.enabled", true);
|
||||||
pref("browser.taskbar.lists.refreshInSeconds", 30);
|
pref("browser.taskbar.lists.refreshInSeconds", 120);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Jim Mathies <jmathies@mozilla.com> (Original author)
|
* Jim Mathies <jmathies@mozilla.com> (Original author)
|
||||||
|
* Marco Bonardo <mak77@bonardo.net>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
@ -46,6 +47,9 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
|
// Stop updating jumplists after some idle time.
|
||||||
|
const IDLE_TIMEOUT_SECONDS = 5 * 60;
|
||||||
|
|
||||||
// Prefs
|
// Prefs
|
||||||
const PREF_TASKBAR_BRANCH = "browser.taskbar.lists.";
|
const PREF_TASKBAR_BRANCH = "browser.taskbar.lists.";
|
||||||
const PREF_TASKBAR_ENABLED = "enabled";
|
const PREF_TASKBAR_ENABLED = "enabled";
|
||||||
|
@ -55,6 +59,12 @@ const PREF_TASKBAR_RECENT = "recent.enabled";
|
||||||
const PREF_TASKBAR_TASKS = "tasks.enabled";
|
const PREF_TASKBAR_TASKS = "tasks.enabled";
|
||||||
const PREF_TASKBAR_REFRESH = "refreshInSeconds";
|
const PREF_TASKBAR_REFRESH = "refreshInSeconds";
|
||||||
|
|
||||||
|
// Hash keys for pendingStatements.
|
||||||
|
const LIST_TYPE = {
|
||||||
|
FREQUENT: 0
|
||||||
|
, RECENT: 1
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports
|
* Exports
|
||||||
*/
|
*/
|
||||||
|
@ -87,6 +97,10 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||||
return NetUtil;
|
return NetUtil;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "_idle",
|
||||||
|
"@mozilla.org/widget/idleservice;1",
|
||||||
|
"nsIIdleService");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
|
XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
|
||||||
"@mozilla.org/windows-taskbar;1",
|
"@mozilla.org/windows-taskbar;1",
|
||||||
"nsIWinTaskbar");
|
"nsIWinTaskbar");
|
||||||
|
@ -129,7 +143,9 @@ var tasksCfg = [
|
||||||
args: "-new-tab about:blank",
|
args: "-new-tab about:blank",
|
||||||
iconIndex: 0, // Fx app icon
|
iconIndex: 0, // Fx app icon
|
||||||
open: true,
|
open: true,
|
||||||
close: false, // The jump list already has an app launch icon
|
close: true, // The jump list already has an app launch icon, but
|
||||||
|
// we don't always update the list on shutdown.
|
||||||
|
// Thus true for consistency.
|
||||||
},
|
},
|
||||||
|
|
||||||
// Open new tab
|
// Open new tab
|
||||||
|
@ -139,7 +155,8 @@ var tasksCfg = [
|
||||||
args: "-browser",
|
args: "-browser",
|
||||||
iconIndex: 0, // Fx app icon
|
iconIndex: 0, // Fx app icon
|
||||||
open: true,
|
open: true,
|
||||||
close: false, // no point
|
close: true, // No point, but we don't always update the list on
|
||||||
|
// shutdown. Thus true for consistency.
|
||||||
},
|
},
|
||||||
|
|
||||||
// Toggle the Private Browsing mode
|
// Toggle the Private Browsing mode
|
||||||
|
@ -202,7 +219,7 @@ var WinTaskbarJumpList =
|
||||||
this._initObs();
|
this._initObs();
|
||||||
|
|
||||||
// jump list refresh timer
|
// jump list refresh timer
|
||||||
this._initTimer();
|
this._updateTimer();
|
||||||
},
|
},
|
||||||
|
|
||||||
update: function WTBJL_update() {
|
update: function WTBJL_update() {
|
||||||
|
@ -216,7 +233,14 @@ var WinTaskbarJumpList =
|
||||||
|
|
||||||
_shutdown: function WTBJL__shutdown() {
|
_shutdown: function WTBJL__shutdown() {
|
||||||
this._shuttingDown = true;
|
this._shuttingDown = true;
|
||||||
this.update();
|
|
||||||
|
// Correctly handle a clear history on shutdown. If there are no
|
||||||
|
// entries be sure to empty all history lists. Luckily Places caches
|
||||||
|
// this value, so it's a pretty fast call.
|
||||||
|
if (!PlacesUtils.history.hasHistoryEntries) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
this._free();
|
this._free();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -226,9 +250,34 @@ var WinTaskbarJumpList =
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List building
|
* List building
|
||||||
*/
|
*
|
||||||
|
* @note Async builders must add their mozIStoragePendingStatement to
|
||||||
|
* _pendingStatements object, using a different LIST_TYPE entry for
|
||||||
|
* each statement. Once finished they must remove it and call
|
||||||
|
* commitBuild(). When there will be no more _pendingStatements,
|
||||||
|
* commitBuild() will commit for real.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_pendingStatements: {},
|
||||||
|
_hasPendingStatements: function WTBJL__hasPendingStatements() {
|
||||||
|
for (let listType in this._pendingStatements) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
_buildList: function WTBJL__buildList() {
|
_buildList: function WTBJL__buildList() {
|
||||||
|
if (this._hasPendingStatements()) {
|
||||||
|
// We were requested to update the list while another update was in
|
||||||
|
// progress, this could happen at shutdown, idle or privatebrowsing.
|
||||||
|
// Abort the current list building.
|
||||||
|
for (let listType in this._pendingStatements) {
|
||||||
|
this._pendingStatements[listType].cancel();
|
||||||
|
delete this._pendingStatements[listType];
|
||||||
|
}
|
||||||
|
this._builder.abortListBuild();
|
||||||
|
}
|
||||||
|
|
||||||
// anything to build?
|
// anything to build?
|
||||||
if (!this._showFrequent && !this._showRecent && !this._showTasks) {
|
if (!this._showFrequent && !this._showRecent && !this._showTasks) {
|
||||||
// don't leave the last list hanging on the taskbar.
|
// don't leave the last list hanging on the taskbar.
|
||||||
|
@ -269,8 +318,9 @@ var WinTaskbarJumpList =
|
||||||
},
|
},
|
||||||
|
|
||||||
_commitBuild: function WTBJL__commitBuild() {
|
_commitBuild: function WTBJL__commitBuild() {
|
||||||
if (!this._builder.commitListBuild())
|
if (!this._hasPendingStatements() && !this._builder.commitListBuild()) {
|
||||||
this._builder.abortListBuild();
|
this._builder.abortListBuild();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_buildTasks: function WTBJL__buildTasks() {
|
_buildTasks: function WTBJL__buildTasks() {
|
||||||
|
@ -301,46 +351,67 @@ var WinTaskbarJumpList =
|
||||||
|
|
||||||
var items = Cc["@mozilla.org/array;1"].
|
var items = Cc["@mozilla.org/array;1"].
|
||||||
createInstance(Ci.nsIMutableArray);
|
createInstance(Ci.nsIMutableArray);
|
||||||
var list = this._getNavFrequent(this._maxItemCount);
|
|
||||||
|
|
||||||
if (!list || list.length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// track frequent items so that we don't add them to
|
// track frequent items so that we don't add them to
|
||||||
// the recent list.
|
// the recent list.
|
||||||
this._frequentHashList = [];
|
this._frequentHashList = [];
|
||||||
|
|
||||||
list.forEach(function (entry) {
|
this._pendingStatements[LIST_TYPE.FREQUENT] = this._getHistoryResults(
|
||||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING,
|
||||||
items.appendElement(shortcut, false);
|
this._maxItemCount,
|
||||||
this._frequentHashList.push(entry.uri);
|
function (aResult) {
|
||||||
}, this);
|
if (!aResult) {
|
||||||
this._buildCustom(_getString("taskbar.frequent.label"), items);
|
delete this._pendingStatements[LIST_TYPE.FREQUENT];
|
||||||
|
// The are no more results, build the list.
|
||||||
|
this._buildCustom(_getString("taskbar.frequent.label"), items);
|
||||||
|
this._commitBuild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = aResult.title || aResult.uri;
|
||||||
|
let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
|
||||||
|
items.appendElement(shortcut, false);
|
||||||
|
this._frequentHashList.push(aResult.uri);
|
||||||
|
},
|
||||||
|
this
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_buildRecent: function WTBJL__buildRecent() {
|
_buildRecent: function WTBJL__buildRecent() {
|
||||||
var items = Cc["@mozilla.org/array;1"].
|
var items = Cc["@mozilla.org/array;1"].
|
||||||
createInstance(Ci.nsIMutableArray);
|
createInstance(Ci.nsIMutableArray);
|
||||||
var list = this._getNavRecent(this._maxItemCount*2);
|
// Frequent items will be skipped, so we select a double amount of
|
||||||
|
// entries and stop fetching results at _maxItemCount.
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
if (!list || list.length == 0)
|
this._pendingStatements[LIST_TYPE.RECENT] = this._getHistoryResults(
|
||||||
return;
|
Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING,
|
||||||
|
this._maxItemCount * 2,
|
||||||
|
function (aResult) {
|
||||||
|
if (!aResult) {
|
||||||
|
// The are no more results, build the list.
|
||||||
|
this._buildCustom(_getString("taskbar.recent.label"), items);
|
||||||
|
delete this._pendingStatements[LIST_TYPE.RECENT];
|
||||||
|
this._commitBuild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let count = 0;
|
if (count >= this._maxItemCount) {
|
||||||
for (let idx = 0; idx < list.length; idx++) {
|
return;
|
||||||
if (count >= this._maxItemCount)
|
}
|
||||||
break;
|
|
||||||
let entry = list[idx];
|
// Do not add items to recent that have already been added to frequent.
|
||||||
// do not add items to recent that have already been added
|
if (this._frequentHashList &&
|
||||||
// to frequent.
|
this._frequentHashList.indexOf(aResult.uri) != -1) {
|
||||||
if (this._frequentHashList &&
|
return;
|
||||||
this._frequentHashList.indexOf(entry.uri) != -1)
|
}
|
||||||
continue;
|
|
||||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
let title = aResult.title || aResult.uri;
|
||||||
items.appendElement(shortcut, false);
|
let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
|
||||||
count++;
|
items.appendElement(shortcut, false);
|
||||||
}
|
count++;
|
||||||
this._buildCustom(_getString("taskbar.recent.label"), items);
|
},
|
||||||
|
this
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_deleteActiveJumpList: function WTBJL__deleteAJL() {
|
_deleteActiveJumpList: function WTBJL__deleteAJL() {
|
||||||
|
@ -381,79 +452,57 @@ var WinTaskbarJumpList =
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nav history helpers
|
* Nav history helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_getNavFrequent: function WTBJL__getNavFrequent(depth) {
|
_getHistoryResults:
|
||||||
var options = PlacesUtils.history.getNewQueryOptions();
|
function WTBLJL__getHistoryResults(aSortingMode, aLimit, aCallback, aScope) {
|
||||||
var query = PlacesUtils.history.getNewQuery();
|
|
||||||
|
|
||||||
query.beginTimeReference = query.TIME_RELATIVE_NOW;
|
|
||||||
query.beginTime = -24 * 30 * 60 * 60 * 1000000; // one month
|
|
||||||
query.endTimeReference = query.TIME_RELATIVE_NOW;
|
|
||||||
|
|
||||||
options.maxResults = depth;
|
|
||||||
options.queryType = options.QUERY_TYPE_HISTORY;
|
|
||||||
options.sortingMode = options.SORT_BY_VISITCOUNT_DESCENDING;
|
|
||||||
options.resultType = options.RESULT_TYPE_URI;
|
|
||||||
|
|
||||||
var result = PlacesUtils.history.executeQuery(query, options);
|
|
||||||
|
|
||||||
var list = [];
|
|
||||||
|
|
||||||
var rootNode = result.root;
|
|
||||||
rootNode.containerOpen = true;
|
|
||||||
|
|
||||||
for (let idx = 0; idx < rootNode.childCount; idx++) {
|
|
||||||
let node = rootNode.getChild(idx);
|
|
||||||
list.push({uri: node.uri, title: node.title});
|
|
||||||
}
|
|
||||||
rootNode.containerOpen = false;
|
|
||||||
|
|
||||||
return list;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getNavRecent: function WTBJL__getNavRecent(depth) {
|
|
||||||
var options = PlacesUtils.history.getNewQueryOptions();
|
var options = PlacesUtils.history.getNewQueryOptions();
|
||||||
|
options.maxResults = aLimit;
|
||||||
|
options.sortingMode = aSortingMode;
|
||||||
|
// We don't want source redirects for these queries.
|
||||||
|
options.redirectsMode = Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET;
|
||||||
var query = PlacesUtils.history.getNewQuery();
|
var query = PlacesUtils.history.getNewQuery();
|
||||||
|
|
||||||
query.beginTimeReference = query.TIME_RELATIVE_NOW;
|
// Return the pending statement to the caller, to allow cancelation.
|
||||||
query.beginTime = -48 * 60 * 60 * 1000000; // two days
|
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||||
query.endTimeReference = query.TIME_RELATIVE_NOW;
|
.asyncExecuteLegacyQueries([query], 1, options, {
|
||||||
|
handleResult: function (aResultSet) {
|
||||||
options.maxResults = depth;
|
for (let row; (row = aResultSet.getNextRow());) {
|
||||||
options.queryType = options.QUERY_TYPE_HISTORY;
|
try {
|
||||||
options.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
|
aCallback.call(aScope,
|
||||||
options.resultType = options.RESULT_TYPE_URI;
|
{ uri: row.getResultByIndex(1)
|
||||||
|
, title: row.getResultByIndex(2)
|
||||||
var result = PlacesUtils.history.executeQuery(query, options);
|
});
|
||||||
|
} catch (e) {}
|
||||||
var list = [];
|
}
|
||||||
|
},
|
||||||
var rootNode = result.root;
|
handleError: function (aError) {
|
||||||
rootNode.containerOpen = true;
|
Components.utils.reportError(
|
||||||
|
"Async execution error (" + aError.result + "): " + aError.message);
|
||||||
for (var idx = 0; idx < rootNode.childCount; idx++) {
|
},
|
||||||
var node = rootNode.getChild(idx);
|
handleCompletion: function (aReason) {
|
||||||
list.push({uri: node.uri, title: node.title});
|
aCallback.call(WinTaskbarJumpList, null);
|
||||||
}
|
},
|
||||||
rootNode.containerOpen = false;
|
});
|
||||||
|
|
||||||
return list;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_clearHistory: function WTBJL__clearHistory(items) {
|
_clearHistory: function WTBJL__clearHistory(items) {
|
||||||
if (!items)
|
if (!items)
|
||||||
return;
|
return;
|
||||||
|
var URIsToRemove = [];
|
||||||
var enum = items.enumerate();
|
var enum = items.enumerate();
|
||||||
while (enum.hasMoreElements()) {
|
while (enum.hasMoreElements()) {
|
||||||
let oldItem = enum.getNext().QueryInterface(Ci.nsIJumpListShortcut);
|
let oldItem = enum.getNext().QueryInterface(Ci.nsIJumpListShortcut);
|
||||||
if (oldItem) {
|
if (oldItem) {
|
||||||
try { // in case we get a bad uri
|
try { // in case we get a bad uri
|
||||||
let uriSpec = oldItem.app.getParameter(0);
|
let uriSpec = oldItem.app.getParameter(0);
|
||||||
PlacesUtils.bhistory.removePage(NetUtil.newURI(uriSpec));
|
URIsToRemove.push(NetUtil.newURI(uriSpec));
|
||||||
} catch (err) { }
|
} catch (err) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (URIsToRemove.length > 0) {
|
||||||
|
PlacesUtils.bhistory.removePages(URIsToRemove, URIsToRemove.length, true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -482,29 +531,51 @@ var WinTaskbarJumpList =
|
||||||
|
|
||||||
_initObs: function WTBJL__initObs() {
|
_initObs: function WTBJL__initObs() {
|
||||||
Services.obs.addObserver(this, "private-browsing", false);
|
Services.obs.addObserver(this, "private-browsing", false);
|
||||||
Services.obs.addObserver(this, "quit-application-granted", false);
|
// If the browser is closed while in private browsing mode, the "exit"
|
||||||
|
// notification is fired on quit-application-granted.
|
||||||
|
// History cleanup can happen at profile-change-teardown.
|
||||||
|
Services.obs.addObserver(this, "profile-before-change", false);
|
||||||
Services.obs.addObserver(this, "browser:purge-session-history", false);
|
Services.obs.addObserver(this, "browser:purge-session-history", false);
|
||||||
_prefs.addObserver("", this, false);
|
_prefs.addObserver("", this, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_freeObs: function WTBJL__freeObs() {
|
_freeObs: function WTBJL__freeObs() {
|
||||||
Services.obs.removeObserver(this, "private-browsing");
|
Services.obs.removeObserver(this, "private-browsing");
|
||||||
Services.obs.removeObserver(this, "quit-application-granted");
|
Services.obs.removeObserver(this, "profile-before-change");
|
||||||
Services.obs.removeObserver(this, "browser:purge-session-history");
|
Services.obs.removeObserver(this, "browser:purge-session-history");
|
||||||
_prefs.removeObserver("", this);
|
_prefs.removeObserver("", this);
|
||||||
},
|
},
|
||||||
|
|
||||||
_initTimer: function WTBJL__initTimer(aTimer) {
|
_updateTimer: function WTBJL__updateTimer() {
|
||||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
if (this._enabled && !this._shuttingDown && !this._timer) {
|
||||||
this._timer.initWithCallback(this,
|
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
_prefs.getIntPref(PREF_TASKBAR_REFRESH)*1000,
|
this._timer.initWithCallback(this,
|
||||||
this._timer.TYPE_REPEATING_SLACK);
|
_prefs.getIntPref(PREF_TASKBAR_REFRESH)*1000,
|
||||||
|
this._timer.TYPE_REPEATING_SLACK);
|
||||||
|
}
|
||||||
|
else if ((!this._enabled || this._shuttingDown) && this._timer) {
|
||||||
|
this._timer.cancel();
|
||||||
|
delete this._timer;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_hasIdleObserver: false,
|
||||||
|
_updateIdleObserver: function WTBJL__updateIdleObserver() {
|
||||||
|
if (this._enabled && !this._shuttingDown && !this._hasIdleObserver) {
|
||||||
|
_idle.addIdleObserver(this, IDLE_TIMEOUT_SECONDS);
|
||||||
|
this._hasIdleObserver = true;
|
||||||
|
}
|
||||||
|
else if ((!this._enabled || this._shuttingDown) && this._hasIdleObserver) {
|
||||||
|
_idle.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS);
|
||||||
|
this._hasIdleObserver = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_free: function WTBJL__free() {
|
_free: function WTBJL__free() {
|
||||||
this._freeObs();
|
this._freeObs();
|
||||||
|
this._updateTimer();
|
||||||
|
this._updateIdleObserver();
|
||||||
delete this._builder;
|
delete this._builder;
|
||||||
delete this._timer;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -512,6 +583,8 @@ var WinTaskbarJumpList =
|
||||||
*/
|
*/
|
||||||
|
|
||||||
notify: function WTBJL_notify(aTimer) {
|
notify: function WTBJL_notify(aTimer) {
|
||||||
|
// Add idle observer on the first notification so it doesn't hit startup.
|
||||||
|
this._updateIdleObserver();
|
||||||
this.update();
|
this.update();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -521,10 +594,12 @@ var WinTaskbarJumpList =
|
||||||
if (this._enabled == true && !_prefs.getBoolPref(PREF_TASKBAR_ENABLED))
|
if (this._enabled == true && !_prefs.getBoolPref(PREF_TASKBAR_ENABLED))
|
||||||
this._deleteActiveJumpList();
|
this._deleteActiveJumpList();
|
||||||
this._refreshPrefs();
|
this._refreshPrefs();
|
||||||
|
this._updateTimer();
|
||||||
|
this._updateIdleObserver();
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "quit-application-granted":
|
case "profile-before-change":
|
||||||
this._shutdown();
|
this._shutdown();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -535,6 +610,17 @@ var WinTaskbarJumpList =
|
||||||
case "private-browsing":
|
case "private-browsing":
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "idle":
|
||||||
|
if (this._timer) {
|
||||||
|
this._timer.cancel();
|
||||||
|
delete this._timer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "back":
|
||||||
|
this._updateTimer();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,18 +47,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIArray.idl"
|
|
||||||
#include "nsIURI.idl"
|
|
||||||
#include "nsIVariant.idl"
|
|
||||||
|
|
||||||
|
interface nsIArray;
|
||||||
|
interface nsIURI;
|
||||||
|
interface nsIVariant;
|
||||||
interface nsIFile;
|
interface nsIFile;
|
||||||
|
|
||||||
interface nsINavHistoryContainerResultNode;
|
interface nsINavHistoryContainerResultNode;
|
||||||
interface nsINavHistoryQueryResultNode;
|
interface nsINavHistoryQueryResultNode;
|
||||||
interface nsINavHistoryQuery;
|
interface nsINavHistoryQuery;
|
||||||
interface nsINavHistoryQueryOptions;
|
interface nsINavHistoryQueryOptions;
|
||||||
interface nsINavHistoryResult;
|
interface nsINavHistoryResult;
|
||||||
interface nsINavHistoryBatchCallback;
|
interface nsINavHistoryBatchCallback;
|
||||||
interface nsITreeColumn;
|
|
||||||
|
|
||||||
[scriptable, uuid(081452e5-be5c-4038-a5ea-f1f34cb6fd81)]
|
[scriptable, uuid(081452e5-be5c-4038-a5ea-f1f34cb6fd81)]
|
||||||
interface nsINavHistoryResultNode : nsISupports
|
interface nsINavHistoryResultNode : nsISupports
|
||||||
|
|
|
@ -40,17 +40,39 @@
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
interface mozIStorageConnection;
|
interface mozIStorageConnection;
|
||||||
|
interface nsINavHistoryQuery;
|
||||||
|
interface nsINavHistoryQueryOptions;
|
||||||
|
interface mozIStorageStatementCallback;
|
||||||
|
interface mozIStoragePendingStatement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a private interface used by Places components to get access to the
|
* This is a private interface used by Places components to get access to the
|
||||||
* database. If outside consumers wish to use this, they should only read from
|
* database. If outside consumers wish to use this, they should only read from
|
||||||
* the database so they do not break any internal invariants.
|
* the database so they do not break any internal invariants.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(5fd91813-229c-4d30-851b-700afa39a987)]
|
[scriptable, uuid(6eb7ed3d-13ca-450b-b370-15c75e2f3dab)]
|
||||||
interface nsPIPlacesDatabase : nsISupports
|
interface nsPIPlacesDatabase : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The database connection used by Places.
|
* The database connection used by Places.
|
||||||
*/
|
*/
|
||||||
readonly attribute mozIStorageConnection DBConnection;
|
readonly attribute mozIStorageConnection DBConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously executes the statement created from queries.
|
||||||
|
*
|
||||||
|
* @see nsINavHistoryService::executeQueries
|
||||||
|
* @note THIS IS A TEMPORARY API. Don't rely on it, since it will be replaced
|
||||||
|
* in future versions by a real async querying API.
|
||||||
|
* @note Results obtained from this method differ from results obtained from
|
||||||
|
* executeQueries, because there is additional filtering and sorting
|
||||||
|
* done by the latter. Thus you should use executeQueries, unless you
|
||||||
|
* are absolutely sure that the returned results are fine for
|
||||||
|
* your use-case.
|
||||||
|
*/
|
||||||
|
mozIStoragePendingStatement asyncExecuteLegacyQueries(
|
||||||
|
[array, size_is(aQueryCount)] in nsINavHistoryQuery aQueries,
|
||||||
|
in unsigned long aQueryCount,
|
||||||
|
in nsINavHistoryQueryOptions aOptions,
|
||||||
|
in mozIStorageStatementCallback aCallback);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4340,6 +4340,7 @@ nsNavHistory::GetQueryResults(nsNavHistoryQueryResultNode *aResultNode,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// nsNavHistory::AddObserver
|
// nsNavHistory::AddObserver
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -5689,6 +5690,72 @@ nsNavHistory::FinalizeInternalStatements()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNavHistory::AsyncExecuteLegacyQueries(nsINavHistoryQuery** aQueries,
|
||||||
|
PRUint32 aQueryCount,
|
||||||
|
nsINavHistoryQueryOptions* aOptions,
|
||||||
|
mozIStorageStatementCallback* aCallback,
|
||||||
|
mozIStoragePendingStatement** _stmt)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
|
||||||
|
NS_ENSURE_ARG(aQueries);
|
||||||
|
NS_ENSURE_ARG(aOptions);
|
||||||
|
NS_ENSURE_ARG(aCallback);
|
||||||
|
NS_ENSURE_ARG_POINTER(_stmt);
|
||||||
|
|
||||||
|
nsCOMArray<nsNavHistoryQuery> queries;
|
||||||
|
for (PRUint32 i = 0; i < aQueryCount; i ++) {
|
||||||
|
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface(aQueries[i]);
|
||||||
|
NS_ENSURE_STATE(query);
|
||||||
|
queries.AppendObject(query);
|
||||||
|
}
|
||||||
|
NS_ENSURE_ARG_MIN(queries.Count(), 1);
|
||||||
|
|
||||||
|
nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions);
|
||||||
|
NS_ENSURE_ARG(options);
|
||||||
|
|
||||||
|
nsCString queryString;
|
||||||
|
PRBool paramsPresent = PR_FALSE;
|
||||||
|
nsNavHistory::StringHash addParams;
|
||||||
|
addParams.Init(HISTORY_DATE_CONT_MAX);
|
||||||
|
nsresult rv = ConstructQueryString(queries, options, queryString,
|
||||||
|
paramsPresent, addParams);
|
||||||
|
NS_ENSURE_SUCCESS(rv,rv);
|
||||||
|
|
||||||
|
nsCOMPtr<mozIStorageStatement> statement;
|
||||||
|
rv = mDBConn->CreateStatement(queryString, getter_AddRefs(statement));
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
nsCAutoString lastErrorString;
|
||||||
|
(void)mDBConn->GetLastErrorString(lastErrorString);
|
||||||
|
PRInt32 lastError = 0;
|
||||||
|
(void)mDBConn->GetLastError(&lastError);
|
||||||
|
printf("Places failed to create a statement from this query:\n%s\nStorage error (%d): %s\n",
|
||||||
|
PromiseFlatCString(queryString).get(),
|
||||||
|
lastError,
|
||||||
|
PromiseFlatCString(lastErrorString).get());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (paramsPresent) {
|
||||||
|
// bind parameters
|
||||||
|
PRInt32 i;
|
||||||
|
for (i = 0; i < queries.Count(); i++) {
|
||||||
|
rv = BindQueryClauseParameters(statement, i, queries[i], options);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addParams.EnumerateRead(BindAdditionalParameter, statement.get());
|
||||||
|
|
||||||
|
rv = statement->ExecuteAsync(aCallback, _stmt);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// nsPIPlacesHistoryListenersNotifier ******************************************
|
// nsPIPlacesHistoryListenersNotifier ******************************************
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This is a test for asyncExecuteLegacyQueries API.
|
||||||
|
|
||||||
|
let tests = [
|
||||||
|
|
||||||
|
function test_history_query() {
|
||||||
|
let uri = NetUtil.newURI("http://test.visit.mozilla.com/");
|
||||||
|
let title = "Test visit";
|
||||||
|
visit(uri, title);
|
||||||
|
let options = PlacesUtils.history.getNewQueryOptions();
|
||||||
|
options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
|
||||||
|
let query = PlacesUtils.history.getNewQuery();
|
||||||
|
|
||||||
|
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||||
|
.asyncExecuteLegacyQueries([query], 1, options, {
|
||||||
|
handleResult: function (aResultSet) {
|
||||||
|
for (let row; (row = aResultSet.getNextRow());) {
|
||||||
|
try {
|
||||||
|
do_check_eq(row.getResultByIndex(1), uri.spec);
|
||||||
|
do_check_eq(row.getResultByIndex(2), title);
|
||||||
|
} catch (e) {
|
||||||
|
do_throw("Error while fetching page data.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError: function (aError) {
|
||||||
|
do_throw("Async execution error (" + aError.result + "): " + aError.message);
|
||||||
|
},
|
||||||
|
handleCompletion: function (aReason) {
|
||||||
|
run_next_test();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function test_bookmarks_query() {
|
||||||
|
let uri = NetUtil.newURI("http://test.bookmark.mozilla.com/");
|
||||||
|
let title = "Test bookmark";
|
||||||
|
bookmark(uri, title);
|
||||||
|
let options = PlacesUtils.history.getNewQueryOptions();
|
||||||
|
options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_LASMODIFIED_DESCENDING;
|
||||||
|
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||||
|
let query = PlacesUtils.history.getNewQuery();
|
||||||
|
|
||||||
|
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||||
|
.asyncExecuteLegacyQueries([query], 1, options, {
|
||||||
|
handleResult: function (aResultSet) {
|
||||||
|
for (let row; (row = aResultSet.getNextRow());) {
|
||||||
|
try {
|
||||||
|
do_check_eq(row.getResultByIndex(1), uri.spec);
|
||||||
|
do_check_eq(row.getResultByIndex(2), title);
|
||||||
|
} catch (e) {
|
||||||
|
do_throw("Error while fetching page data.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError: function (aError) {
|
||||||
|
do_throw("Async execution error (" + aError.result + "): " + aError.message);
|
||||||
|
},
|
||||||
|
handleCompletion: function (aReason) {
|
||||||
|
run_next_test();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
function visit(aURI, aTitle)
|
||||||
|
{
|
||||||
|
PlacesUtils.history.addVisit(aURI, Date.now() * 1000, null,
|
||||||
|
PlacesUtils.history.TRANSITION_TYPED, false, 0);
|
||||||
|
setPageTitle(aURI, aTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bookmark(aURI, aTitle)
|
||||||
|
{
|
||||||
|
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||||
|
aURI,
|
||||||
|
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||||
|
aTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
do_test_pending();
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_next_test() {
|
||||||
|
if (tests.length == 0) {
|
||||||
|
do_test_finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let test = tests.shift();
|
||||||
|
waitForClearHistory(function() {
|
||||||
|
remove_all_bookmarks();
|
||||||
|
do_execute_soon(test);
|
||||||
|
});
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче