зеркало из 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.maxListItemCount", 7);
|
||||
pref("browser.taskbar.lists.tasks.enabled", true);
|
||||
pref("browser.taskbar.lists.refreshInSeconds", 30);
|
||||
pref("browser.taskbar.lists.refreshInSeconds", 120);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* 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
|
||||
* 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 Ci = Components.interfaces;
|
||||
|
||||
// Stop updating jumplists after some idle time.
|
||||
const IDLE_TIMEOUT_SECONDS = 5 * 60;
|
||||
|
||||
// Prefs
|
||||
const PREF_TASKBAR_BRANCH = "browser.taskbar.lists.";
|
||||
const PREF_TASKBAR_ENABLED = "enabled";
|
||||
|
@ -55,6 +59,12 @@ const PREF_TASKBAR_RECENT = "recent.enabled";
|
|||
const PREF_TASKBAR_TASKS = "tasks.enabled";
|
||||
const PREF_TASKBAR_REFRESH = "refreshInSeconds";
|
||||
|
||||
// Hash keys for pendingStatements.
|
||||
const LIST_TYPE = {
|
||||
FREQUENT: 0
|
||||
, RECENT: 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports
|
||||
*/
|
||||
|
@ -87,6 +97,10 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
|||
return NetUtil;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_idle",
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
"nsIIdleService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
|
||||
"@mozilla.org/windows-taskbar;1",
|
||||
"nsIWinTaskbar");
|
||||
|
@ -129,7 +143,9 @@ var tasksCfg = [
|
|||
args: "-new-tab about:blank",
|
||||
iconIndex: 0, // Fx app icon
|
||||
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
|
||||
|
@ -139,7 +155,8 @@ var tasksCfg = [
|
|||
args: "-browser",
|
||||
iconIndex: 0, // Fx app icon
|
||||
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
|
||||
|
@ -202,7 +219,7 @@ var WinTaskbarJumpList =
|
|||
this._initObs();
|
||||
|
||||
// jump list refresh timer
|
||||
this._initTimer();
|
||||
this._updateTimer();
|
||||
},
|
||||
|
||||
update: function WTBJL_update() {
|
||||
|
@ -216,7 +233,14 @@ var WinTaskbarJumpList =
|
|||
|
||||
_shutdown: function WTBJL__shutdown() {
|
||||
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();
|
||||
},
|
||||
|
||||
|
@ -226,9 +250,34 @@ var WinTaskbarJumpList =
|
|||
|
||||
/**
|
||||
* 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() {
|
||||
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?
|
||||
if (!this._showFrequent && !this._showRecent && !this._showTasks) {
|
||||
// don't leave the last list hanging on the taskbar.
|
||||
|
@ -269,8 +318,9 @@ var WinTaskbarJumpList =
|
|||
},
|
||||
|
||||
_commitBuild: function WTBJL__commitBuild() {
|
||||
if (!this._builder.commitListBuild())
|
||||
if (!this._hasPendingStatements() && !this._builder.commitListBuild()) {
|
||||
this._builder.abortListBuild();
|
||||
}
|
||||
},
|
||||
|
||||
_buildTasks: function WTBJL__buildTasks() {
|
||||
|
@ -301,46 +351,67 @@ var WinTaskbarJumpList =
|
|||
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
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
|
||||
// the recent list.
|
||||
this._frequentHashList = [];
|
||||
|
||||
list.forEach(function (entry) {
|
||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
||||
items.appendElement(shortcut, false);
|
||||
this._frequentHashList.push(entry.uri);
|
||||
}, this);
|
||||
this._buildCustom(_getString("taskbar.frequent.label"), items);
|
||||
this._pendingStatements[LIST_TYPE.FREQUENT] = this._getHistoryResults(
|
||||
Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING,
|
||||
this._maxItemCount,
|
||||
function (aResult) {
|
||||
if (!aResult) {
|
||||
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() {
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
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)
|
||||
return;
|
||||
this._pendingStatements[LIST_TYPE.RECENT] = this._getHistoryResults(
|
||||
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;
|
||||
for (let idx = 0; idx < list.length; idx++) {
|
||||
if (count >= this._maxItemCount)
|
||||
break;
|
||||
let entry = list[idx];
|
||||
// do not add items to recent that have already been added
|
||||
// to frequent.
|
||||
if (this._frequentHashList &&
|
||||
this._frequentHashList.indexOf(entry.uri) != -1)
|
||||
continue;
|
||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
||||
items.appendElement(shortcut, false);
|
||||
count++;
|
||||
}
|
||||
this._buildCustom(_getString("taskbar.recent.label"), items);
|
||||
if (count >= this._maxItemCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not add items to recent that have already been added to frequent.
|
||||
if (this._frequentHashList &&
|
||||
this._frequentHashList.indexOf(aResult.uri) != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let title = aResult.title || aResult.uri;
|
||||
let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
|
||||
items.appendElement(shortcut, false);
|
||||
count++;
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
_deleteActiveJumpList: function WTBJL__deleteAJL() {
|
||||
|
@ -381,79 +452,57 @@ var WinTaskbarJumpList =
|
|||
|
||||
/**
|
||||
* Nav history helpers
|
||||
*/
|
||||
*/
|
||||
|
||||
_getNavFrequent: function WTBJL__getNavFrequent(depth) {
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
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) {
|
||||
_getHistoryResults:
|
||||
function WTBLJL__getHistoryResults(aSortingMode, aLimit, aCallback, aScope) {
|
||||
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();
|
||||
|
||||
query.beginTimeReference = query.TIME_RELATIVE_NOW;
|
||||
query.beginTime = -48 * 60 * 60 * 1000000; // two days
|
||||
query.endTimeReference = query.TIME_RELATIVE_NOW;
|
||||
|
||||
options.maxResults = depth;
|
||||
options.queryType = options.QUERY_TYPE_HISTORY;
|
||||
options.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
|
||||
options.resultType = options.RESULT_TYPE_URI;
|
||||
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
|
||||
var list = [];
|
||||
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
for (var idx = 0; idx < rootNode.childCount; idx++) {
|
||||
var node = rootNode.getChild(idx);
|
||||
list.push({uri: node.uri, title: node.title});
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
return list;
|
||||
// Return the pending statement to the caller, to allow cancelation.
|
||||
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.asyncExecuteLegacyQueries([query], 1, options, {
|
||||
handleResult: function (aResultSet) {
|
||||
for (let row; (row = aResultSet.getNextRow());) {
|
||||
try {
|
||||
aCallback.call(aScope,
|
||||
{ uri: row.getResultByIndex(1)
|
||||
, title: row.getResultByIndex(2)
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
},
|
||||
handleError: function (aError) {
|
||||
Components.utils.reportError(
|
||||
"Async execution error (" + aError.result + "): " + aError.message);
|
||||
},
|
||||
handleCompletion: function (aReason) {
|
||||
aCallback.call(WinTaskbarJumpList, null);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
_clearHistory: function WTBJL__clearHistory(items) {
|
||||
if (!items)
|
||||
return;
|
||||
var URIsToRemove = [];
|
||||
var enum = items.enumerate();
|
||||
while (enum.hasMoreElements()) {
|
||||
let oldItem = enum.getNext().QueryInterface(Ci.nsIJumpListShortcut);
|
||||
if (oldItem) {
|
||||
try { // in case we get a bad uri
|
||||
let uriSpec = oldItem.app.getParameter(0);
|
||||
PlacesUtils.bhistory.removePage(NetUtil.newURI(uriSpec));
|
||||
URIsToRemove.push(NetUtil.newURI(uriSpec));
|
||||
} catch (err) { }
|
||||
}
|
||||
}
|
||||
if (URIsToRemove.length > 0) {
|
||||
PlacesUtils.bhistory.removePages(URIsToRemove, URIsToRemove.length, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -482,29 +531,51 @@ var WinTaskbarJumpList =
|
|||
|
||||
_initObs: function WTBJL__initObs() {
|
||||
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);
|
||||
_prefs.addObserver("", this, false);
|
||||
},
|
||||
|
||||
_freeObs: function WTBJL__freeObs() {
|
||||
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");
|
||||
_prefs.removeObserver("", this);
|
||||
},
|
||||
|
||||
_initTimer: function WTBJL__initTimer(aTimer) {
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._timer.initWithCallback(this,
|
||||
_prefs.getIntPref(PREF_TASKBAR_REFRESH)*1000,
|
||||
this._timer.TYPE_REPEATING_SLACK);
|
||||
_updateTimer: function WTBJL__updateTimer() {
|
||||
if (this._enabled && !this._shuttingDown && !this._timer) {
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._timer.initWithCallback(this,
|
||||
_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() {
|
||||
this._freeObs();
|
||||
this._updateTimer();
|
||||
this._updateIdleObserver();
|
||||
delete this._builder;
|
||||
delete this._timer;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -512,6 +583,8 @@ var WinTaskbarJumpList =
|
|||
*/
|
||||
|
||||
notify: function WTBJL_notify(aTimer) {
|
||||
// Add idle observer on the first notification so it doesn't hit startup.
|
||||
this._updateIdleObserver();
|
||||
this.update();
|
||||
},
|
||||
|
||||
|
@ -521,10 +594,12 @@ var WinTaskbarJumpList =
|
|||
if (this._enabled == true && !_prefs.getBoolPref(PREF_TASKBAR_ENABLED))
|
||||
this._deleteActiveJumpList();
|
||||
this._refreshPrefs();
|
||||
this._updateTimer();
|
||||
this._updateIdleObserver();
|
||||
this.update();
|
||||
break;
|
||||
|
||||
case "quit-application-granted":
|
||||
case "profile-before-change":
|
||||
this._shutdown();
|
||||
break;
|
||||
|
||||
|
@ -535,6 +610,17 @@ var WinTaskbarJumpList =
|
|||
case "private-browsing":
|
||||
this.update();
|
||||
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 "nsIArray.idl"
|
||||
#include "nsIURI.idl"
|
||||
#include "nsIVariant.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIURI;
|
||||
interface nsIVariant;
|
||||
interface nsIFile;
|
||||
|
||||
interface nsINavHistoryContainerResultNode;
|
||||
interface nsINavHistoryQueryResultNode;
|
||||
interface nsINavHistoryQuery;
|
||||
interface nsINavHistoryQueryOptions;
|
||||
interface nsINavHistoryResult;
|
||||
interface nsINavHistoryBatchCallback;
|
||||
interface nsITreeColumn;
|
||||
|
||||
[scriptable, uuid(081452e5-be5c-4038-a5ea-f1f34cb6fd81)]
|
||||
interface nsINavHistoryResultNode : nsISupports
|
||||
|
|
|
@ -40,17 +40,39 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIStorageConnection;
|
||||
interface nsINavHistoryQuery;
|
||||
interface nsINavHistoryQueryOptions;
|
||||
interface mozIStorageStatementCallback;
|
||||
interface mozIStoragePendingStatement;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
{
|
||||
/**
|
||||
* The database connection used by Places.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistory::AddObserver
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -5689,6 +5690,72 @@ nsNavHistory::FinalizeInternalStatements()
|
|||
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 ******************************************
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
Загрузка…
Ссылка в новой задаче