Executing a query
Places queries have several basic parts:
- The query object:
nsINavHistoryQuery
, holds the search parameters - The query options:
nsINavHistoryQueryOptions
, allows configuration of the search result - The history service:
nsINavHistoryService
, executes the query
The first first step is to create the query and options, and fill them with the parameters you want. Use nsINavHistoryService.getNewQuery()
and nsINavHistoryService.getNewQueryOptions()
to retrieve empty objects. The defaults for these objects will result in a query that returns all of your browser history in a flat list:
var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] .getService(Components.interfaces.nsINavHistoryService); // No query options set will get all history, sorted in database order, // which is nsINavHistoryQueryOptions.SORT_BY_NONE. var options = historyService.getNewQueryOptions(); // No query parameters will return everything var query = historyService.getNewQuery(); // execute the query var result = historyService.executeQuery(query, options);
Result types
nsINavHistoryQueryOptions
has a resultType
property that allows configuration of the grouping and level of detail to be returned in the results. The different values for this property are listed below. These values are also properties of nsINavHistoryQueryOptions
, and are accessed like this: Components.interfaces.nsINavHistoryQueryOptions.RESULTS_AS_VISIT
.
- RESULTS_AS_URI: This is the default, and returns one result node of type
RESULT_TYPE_URI
for each URI that matches the query. The visit date for each node will be the last visit date for that URL. - RESULTS_AS_VISIT: This option returns one entry for each time a page was visited matching the given query. The result may contain duplicate entries for URLs, each with a different date. The nodes are of type
RESULT_TYPE_VISIT
, and provide a session ID for each visit. This session ID is the same for all pages that were reached by clicking links. A new session starts when the user types a new URL or follows a bookmark (XXX link to more details about what constitutes a session). - RESULTS_AS_FULL_VISIT: This is an extended version of
RESULT_TYPE_VISIT
. The results are of typeRESULT_TYPE_FULL_VISIT
and have additional information about the visit, such as the referring visit, and how the transition happened (typed, redirect, link, etc). Not yet implemented -- see bug 320831.
Basic Query Search Parameters
- const unsigned long TIME_RELATIVE_EPOCH = 0
- const unsigned long TIME_RELATIVE_TODAY = 1
- const unsigned long TIME_RELATIVE_NOW = 2
- attribute PRTime beginTime
- attribute unsigned long beginTimeReference
- readonly attribute boolean hasBeginTime
- readonly attribute PRTime absoluteBeginTime
- attribute PRTime endTime
- attribute unsigned long endTimeReference
- readonly attribute boolean hasEndTime
- readonly attribute PRTime absoluteEndTime
- attribute AString searchTerms readonly
- attribute boolean hasSearchTerms
- attribute long minVisits
- attribute long maxVisits
- attribute boolean onlyBookmarked
- attribute boolean domainIsHost
- attribute AUTF8String domain
- readonly attribute boolean hasDomain
- attribute boolean uriIsPrefix
- attribute nsIURI uri
- readonly attribute boolean hasUri
- attribute boolean annotationIsNot
- attribute AUTF8String annotation
- readonly attribute boolean hasAnnotation
- readonly attribute unsigned long folderCount
Basic Query Configuration Options
- const unsigned short GROUP_BY_DAY = 0
- const unsigned short GROUP_BY_HOST = 1
- const unsigned short GROUP_BY_DOMAIN = 2
- const unsigned short GROUP_BY_FOLDER = 3
- const unsigned short SORT_BY_NONE = 0
- const unsigned short SORT_BY_TITLE_ASCENDING = 1
- const unsigned short SORT_BY_TITLE_DESCENDING = 2
- const unsigned short SORT_BY_DATE_ASCENDING = 3
- const unsigned short SORT_BY_DATE_DESCENDING = 4
- const unsigned short SORT_BY_URI_ASCENDING = 5
- const unsigned short SORT_BY_URI_DESCENDING = 6
- const unsigned short SORT_BY_VISITCOUNT_ASCENDING = 7
- const unsigned short SORT_BY_VISITCOUNT_DESCENDING = 8
- const unsigned short SORT_BY_KEYWORD_ASCENDING = 9
- const unsigned short SORT_BY_KEYWORD_DESCENDING = 10
- const unsigned short SORT_BY_DATEADDED_ASCENDING = 11
- const unsigned short SORT_BY_DATEADDED_DESCENDING = 12
- const unsigned short SORT_BY_LASTMODIFIED_ASCENDING = 13
- const unsigned short SORT_BY_LASTMODIFIED_DESCENDING = 14
- const unsigned short SORT_BY_ANNOTATION_ASCENDING = 15
- const unsigned short SORT_BY_ANNOTATION_DESCENDING = 16
- const unsigned short RESULTS_AS_URI = 0
- const unsigned short RESULTS_AS_VISIT = 1
- const unsigned short RESULTS_AS_FULL_VISIT = 2 (Not yet implemented -- see bug 320831)
- attribute unsigned short sortingMode
- attribute AUTF8String sortingAnnotation
- attribute unsigned short resultType
- attribute boolean excludeItems
- attribute boolean excludeQueries
- attribute boolean excludeReadOnlyFolders
- attribute boolean expandQueries
- attribute boolean includeHidden
- attribute boolean showSessions
- attribute unsigned long maxResults
- const unsigned short QUERY_TYPE_HISTORY = 0
- const unsigned short QUERY_TYPE_BOOKMARKS = 1
- const unsigned short QUERY_TYPE_UNIFIED = 2 (Not yet implemented -- see bug 378798)
- attribute unsigned short queryType
Complex Queries
You can pass one or more nsINavHistoryQuery
objects to executeQueries()
. Within one query object, all parameters are ANDed together. The conditions for different query objects are then ORed together. This allows for a simpler implementation and interface than a full logical operation with nested clauses while still being expressive.
Example of querying for any pages I've visited that contain the word "firefox" in the title/URL or that I've visited today from mozilla.org.
// first query object searches for "firefox" in title/URL var query1 = historyService.getNewQuery(); query1.searchTerms = "firefox"; // second query object searches for visited in past 24 hours AND from mozilla.org var query2 = historyService.getNewQuery(); query2.beginTimeReference = query2.TIME_RELATIVE_NOW; query2.beginTime = -24 * 60 * 60 * 1000000; // 24 hours ago in microseconds query2.endTimeReference = query2.TIME_RELATIVE_NOW; query2.endTime = 0; // now query2.domain = "mozilla.org"; var result = historyService.executeQueries([query1, query2], 2, options);
Bookmark queries
There is a quick-start for doing simple bookmark queries in Retrieving part of the bookmarks tree.
The contents of bookmark folders can be retrieved by setting the "folders" member in the query object. This item is an array of folder IDs from the bookmark service. Typically, you will only have one folder ID in this list, which will given you the contents of that folder. You can set multiple folders and the result will be the intersection of all the folders.
For sorting, you will generally want to use SORT_BY_NONE
(the default) since this will return items in their "natural" order as specified by the user in the bookmarks manager. Other sortings will work, however.
For bookmark queries you will generally want no query parameters to retrieve all items from the requested folder(s). When you specify exactly one folder and no query parameters, the system will be more efficient querying and keeping the results up-to-date since this maps to exactly one bookmark folder.
var bookmarkService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"] .getService(Components.interfaces.nsINavBookmarksService); // |query| and |options| are objects created in the previous section query.setFolders([bookmarkService.toolbarFolder], 1); var result = historyService.executeQuery(query, options);
Serializing queries
Query and options objects can be serialized into a string starting with "place:" using queriesToQueryString
. The resulting string can be stored or bookmarked. When a "place:" URI is bookmarked, it will expand to the results of the query when it is opened by the user. The original objects can be deserialized from the string using queryStringToQueries
.
Be careful, queryStringToQueries
may not return any query objects if the string was empty. Your code should handle this case. There will always be an options structure returned. If no options were specified, it will have the default values. If there were no query parameters specified but the input string was not empty (there were options) you may get one query object returned, containing the default query values.
Example of serializing and deserializing two queries and an options object:
var queryString = historyService.queriesToQueryString([query1, query2], 2, options); var queriesRef = { }; var queryCountRef = { }; var optionsRef = { }; historyService.queryStringToQueries(queryString, queriesRef, queryCountRef, optionsRef); // now use queriesRef.value, optionsRef.value
See Places query URIs for more information about the terms available for "place:" URIs.
Using the results
The most common way to use results is to implement a view. There is a built-in view that will put results in tree controls, and you can also implement your own. See Displaying Places information using views for more on this. This section discusses how to access the result directly, for example, if you are creating your own view or are processing the results instead of displaying them.
The nsINavHistoryResult
object returned by executeQuery()
/executeQueries()
contains the list of matches to the given history or bookmarks query. These results are contained in a tree structure made up of nodes. A node's type can be retrieved using its type
attribute. This type tells you what interface you can QueryInterface
the node to in order to get at more detailed information:
- nsINavHistoryResultNode: Base class for all nodes. Contains URI, title, and other general info.
- nsINavHistoryVisitResultNode: Derived from
nsINavHistoryResultNode
, contains session information. - nsINavHistoryFullVisitResultNode: Derived from
nsINavHistoryVisitResultNode
, contains information about how the user navigated to this page. Note: currently unimplemented, see bug 320831. - nsINavHistoryContainerResultNode: General container node giving access to its children. Derived from
nsINavHistoryResultNode
. Bookmark folders are of this type. - nsINavHistoryQueryResultNode: A type of container representing a query of the history system. It allows you to get the query options and parameters.
Example of detecting the type of a node
var Ci = Components.interfaces; switch(node.type) { case node.RESULT_TYPE_URI: dump("URI result " + node.uri + "\n"); break; case node.RESULT_TYPE_VISIT: var visit = node.QueryInterface(Ci.nsINavHistoryVisitResultNode); dump("Visit result " + node.uri + " session = " + visit.sessionId + "\n"); break; case node.RESULT_TYPE_FULL_VISIT: var fullVisit = node.QueryInterface(Ci.nsINavHistoryFullVisitResultNode); dump("Full visit result " + node.uri + " session = " + fullVisit.sessionId + " transitionType = " + fullVisit.transitionType + "\n"); break; case node.RESULT_TYPE_HOST: var container = node.QueryInterface(Ci.nsINavHistoryContainerResultNode); dump("Host " + container.title + "\n"); break; case node.RESULT_TYPE_REMOTE_CONTAINER: var container = node.QueryInterface(Ci.nsINavHistoryContainerResultNode); dump("Remote container " + container.title + " type = " + container.remoteContainerType + "\n"); break; case node.RESULT_TYPE_QUERY: var query = node.QueryInterface(Ci.nsINavHistoryQueryResultNode); dump("Query, place URI = " + query.uri + "\n"); break; case node.RESULT_TYPE_FOLDER: // Note that folder nodes are of type nsINavHistoryContainerResultNode by default, but // can be QI'd to nsINavHistoryQueryResultNode to access the query and options that // created it. dump("Folder " + node.title + " id = " + node.itemId + "\n"); break; case node.RESULT_TYPE_SEPARATOR: dump("-----------\n"); break; }
The result view interface
If you are mapping a result into UI, you can implement the nsINavHistoryResultViewer
interface and attach it to the result with the nsINavHistoryResult.viewer
attribute. This viewer will be called when the result tree changes, either as a result of user action or as a result of notifications from the bookmarks and history systems. Your implementation would then reflect these changes in the UI.
A prepackaged view interface for a nsITreeBoxObject
is provided that manages the complex view requirements of a tree. This object's interface is nsINavHistoryResultTreeViewer
(a descendent of nsINavHistoryResultViewer
). See Displaying Places information using views for more information and examples.
Containers
Containers hold lists of other containers and result nodes. Each result has a container representing the root of the query. It can be retrieved using the root
attribute of the result. For general queries, this root container is a nsINavHistoryQueryResultNode
with the query parameters and options that you supplied in the original query. For queries mapping to one bookmark folder, this will be a nsINavHistoryContainerResultNode
.
Containers can be open or closed. This corresponds to the open and closed state in a tree view, and can also be mapped to showing and hiding menus. To get at a container's contents, you must first open the container. Most container types populate themselves lazily, so opening a container actually corresponds to executing the given query. While a container is open, it will listen to the history and bookmarks systems' notifications and modify their contents to keep themselves up-to-date. For this reason, it is best to close a container as soon as you are done with it, since it will give better performance. If you close a container and re-open it before any history or bookmark change notifications come, the results will generally still be there and this operation will be fast.
This example uses the Places history service to display all the titles of the history pages.
var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] .getService(Components.interfaces.nsINavHistoryService); // queries parameters (e.g. domain name matching, text terms matching, time range...) // see : https://developer.mozilla.org/en/nsINavHistoryQuery var query = historyService.getNewQuery(); // options parameters (e.g. ordering mode and sorting mode...) // see : https://developer.mozilla.org/en/nsINavHistoryQueryOptions var options = historyService.getNewQueryOptions(); // execute the query // see : https://developer.mozilla.org/en/nsINavHistoryService#executeQuery() var result = historyService.executeQuery(query, options); // Using the results by traversing a container // see : https://developer.mozilla.org/en/nsINavHistoryContainerResultNode var cont = result.root; cont.containerOpen = true; for (var i = 0; i < cont.childCount; i ++) { var node = cont.getChild(i); // "node" attributes contains the information (e.g. uri, title, time, icon...) // see : https://developer.mozilla.org/en/nsINavHistoryResultNode dump(node.title+ "\n"); } // Close container when done // see : https://developer.mozilla.org/en/nsINavHistoryContainerResultNode cont.containerOpen = false;