L'historique et les marque-pages de Firefox sont accessibles à l'aide des API de requêtes « Places ». Ces API permettent d'exécuter des requêtes complexes sur l'historique, les marque pages ou les deux à la fois (à partir de Firefox 3 Alpha 6). Le résultat d'une requête est un objet qui contiendra une liste à plat ou une structure arborescente des données correspondantes. Les définitions de l'API de requête et des structures de données résultantes sont accessibles dans toolkit/components/places/public/nsINavHistoryService.idl
. Cette page fournit une introduction à certaines opérations courantes, et des exemples d'utilisation des API principales.
Exécution d'une requête
Les requêtes Places sont formées de plusieurs parties basiques :
- L'objet de requête :
nsINavHistoryQuery
, stocke les paramètres de recherche - Les options de requête :
nsINavHistoryQueryOptions
, permet de configurer les résultats de la recherche - Le service d'historique :
nsINavHistoryService
, exécute la requête
La première étape est de créer la requête et ses options, et de les remplir avec les paramètres désirés. Utilisez nsINavHistoryService.getNewQuery()
et nsINavHistoryService.getNewQueryOptions()
pour obtenir des objets vides. Les valeurs par défaut pour ces objets résulteront en une requête renvoyant tout l'historique de votre navigateur dans une liste à plat :
var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"] .getService(Components.interfaces.nsINavHistoryService); // en l'absence de paramètres de requête, on obtiendra tout l'historique // XXX l'ordre de tri par défaut est... ? var options = historyService.getNewQueryOptions(); // en l'absence de paramètres de requête, on obtiendra tout var query = historyService.getNewQuery(); // exécution de la requête var result = historyService.executeQuery(query, options);
Types de résultats
nsINavHistoryQueryOptions
dispose d'une propriété resultType
permettant de configurer le groupement et niveau de détail à renvoyer dans les résultats. Les différentes valeurs pour cette propriété sont listées ci-dessous. Ces valeurs sont également des propriétés de nsINavHistoryQueryOptions
, et l'on y accède de la manière suivante : Components.interfaces.nsINavHistoryQueryOptions.RESULTS_AS_VISIT
.
- RESULTS_AS_URI : C'est la valeur par défaut, et elle renvoie un nœud de résultat de type
RESULT_TYPE_URI
pour chaque URI correspondant à la requête. La date de visite pour chaque nœud sera celle de la dernière visite pour cette URL. - RESULTS_AS_VISIT : Cette option renvoie une entrée pour chaque fois qu'une page a été visitée selon la requête formulée. Le résultat peut contenir plusieurs entrées par URL, chacune avec une date différente. Les nœuds sont de type
RESULT_TYPE_VISIT
, et fournissent un ID de session pour chaque visite. Cet ID de session est identique pour toutes les pages qui ont été atteintes en cliquant sur des liens. Une nouvelle session démarre lorsque l'utilisateur entre une nouvelle URL ou suit un marque-page (XXX lier vers des détails supplémentaires concernant ce qui constitue une session). - RESULTS_AS_FULL_VISIT : Il s'agit d'une version étendue de
RESULT_TYPE_VISIT
. Les résultats sont de typeRESULT_TYPE_FULL_VISIT
et fournissent des informations supplémentaires concernant la visite, comme la référence suivie et la manière dont la transition s'est faite (entrée manuelle, redirection, lien, etc.)
Paramètres de recherche basiques d'une requête
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
Options de configuration basiques d'une requête
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 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 attribute unsigned short queryType
Requêtes complexes
Il est possible de passer un ou plusieurs objets nsINavHistoryQuery
à executeQueries()
. Au sein d'un objet de requête, tous les paramètres sont combinés ensemble avec l'opérateur ET. Les conditions pour différents objets de requête sont ensuite combinées avec l'opérateur OU. Ceci permet une implémentation et une interface plus simples qu'une opération logique complète avec des clauses imbriquées tout en restant expressif.
Voici un exemple de requête pour toutes les pages visitées qui contiennent le mot « firefox » dans le titre/l'URL ou qui ont été visitées aujourd'hui sur le site mozilla.org.
// le premier objet de requête cherche « firefox » dans le titre/l'URL var query1 = historyService.getNewQuery(); query1.searchTerms = "firefox"; // le second objet de requête cherche des pages visitées dans les dernières 24 heures ET provenant de mozilla.org var query2 = historyService.getNewQuery(); query2.beginTimeReference = query2.TIME_RELATIVE_NOW; query2.beginTime = -24 * 60 * 60 * 1000000; // 24 heures en microsecondes query2.endTimeReference = query2.TIME_RELATIVE_NOW; query2.endTime = 0; // maintenant query2.domain = "mozilla.org"; var result = historyService.executeQueries([query1, query2], 2, options);
Requêtes de marque-pages
Un guide expliquant comment effectuer rapidement des requêtes simples sur les marque-pages se trouve dans Accès aux marque-pages.
Le contenu des dossiers de marque-pages peut être obtenu en définissant le membre « folders » dans l'objet de requête. Cet élément est un tableau d'ID de dossiers venant du service de marque-pages. Typiquement, vous ne donnerez qu'un ID de dossier dans cette liste, ce qui vous fournira le contenu de ce dossier. Vous pouvez cependant définir plusieurs dossiers et le résultat sera l'union de tous ces dossiers.
Pour le tri, vous utiliserez généralement SORT_BY_NONE
(la valeur par défaut), puisque celle-ci renverra les éléments dans leur ordre « naturel » tel que spécifié par l'utilisateur dans le gestionnaire de marque-pages. D'autres tris fonctionneront cependant.
Pour les requêtes de marque-pages, vous ne voudrez généralement pas de paramètres de requête pour obtenir tous les éléments des dossiers demandés. C'est lorsque vous spécifiez exactement un dossier, GROUP_BY_FOLDER
et aucun paramètre de requête que le système sera le plus efficient dans la recherche et la maintenance à jour des résultats, puisque cela correspond exactement à un dossier de marque-pages.
var bookmarkService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"] .getService(Components.interfaces.nsINavBookmarksService); // |query| et |options| sont des objets créés dans la section précédente query.setFolders([bookmarkService.toolbarRoot], 1); options.setGroupingMode([options.GROUP_BY_FOLDER], 1); var result = historyService.executeQuery(query, options);
Sérialisation des requêtes
Les requêtes et objets d'options peuvent être sérialisées en une chaîne commençant par « place: » à l'aide de queriesToQueryString
. La chaîne résultante peut être enregistrée ou ajoutée aux marque-pages. Lorsqu'une URI « place: » est ajoutée aux marque-pages, elle permettra l'affichage des résultats de la requête lorsqu'elle sera ouverte par l'utilisateur. Les objets originaux peuvent être retirés de la chaîne avec queryStringToQueries
.
Faites attention, queryStringToQueries
peut ne renvoyer aucun objet de requête si la chaîne est vide. Votre code doit gérer ce cas. Il y aura par contre toujours une structure d'options renvoyée. Si aucune option n'a été spécifiée, elle aura les valeurs par défaut. S'il aucun paramètre de requête n'avait été spécifié mais que la chaîne n'était pas vide (il y avait des options), il est possible que vous obteniez un objet de requête contenant les valeurs de requête par défaut.
Voici un exemple de sérialisation et désérialisation de deux requêtes et d'un objet d'options :
var queryString = historyService.queriesToQueryStrings([query1, query2], 2, options); var queriesRef = { }; var queryCountRef = { }; var optionsRef = { }; historyService.queryStringToQueries(queryString, queriesRef, queryCountRef, optionsRef); // utilisez maintenant queriesRef.value, optionsRef.value
Une référence des termes disponibles pour les URI « place: » est disponible dans PlaceURI.
Utilisation des résultats
La manière la plus courante d'utiliser les résultats et d'implémenter une vie. Une vue intégrée mettant les résultats dans des contrôles d'arbres existent, mais vous pouvez également implémenter la vôtre. Consultez Places:Vues pour plus de détails. Cette section explique comment accéder aux résultats directement, par exemple si vous créez votre propre vue ou désirez simplement y accéder sans les afficher.
Note : faites attention lorsque vous accédez à des nœuds sans conserver de références à ceux-ci. Les notifications envoyées à l'historique et au système de marque-pages, ainsi que les commandes exécutées par le programmeur comme un tri peuvent provoquer un changement dans la structure et des nœuds peuvent être insérés, retirés ou remplacés.
L'objet nsINavHistoryResult
renvoyé par executeQuery()
/executeQueries()
contient la liste des correspondances de la requête de marque-pages ou d'historique donnée. Ces résultats sont conservés dans une structure arborescente de nœuds. Le type d'un nœud peut être obtenu à l'aide de son attribut type
. Celui-ci indique l'interface à utiliser avec QueryInterface
sur le nœud afin d'en obtenir des informations plus détaillées :
- nsINavHistoryResultNode : Classe de base pour tous les nœuds. Contient une URI, un titre et d'autres informations générales.
- nsINavHistoryVisitResultNode : Dérivée de
nsINavHistoryResultNode
, contient des informations de session. - nsINavHistoryFullVisitResultNode : Dérivée de
nsINavHistoryVisitResultNode
, contient des informations concernant la manière dont l'utilisateur a atteint la page. Note : actuellement non implémentée, voir le bug 320831. - nsINavHistoryContainerResultNode : Nœud conteneur général donnant accès à ses enfants. Dérivé de
nsINavHistoryResultNode
. Les dossiers de marque-pages sont de ce type. - nsINavHistoryQueryResultNode : Un type de conteneur représentant une requête du système d'historique. Il permet d'obtenir les options et paramètres de requête.
- nsINavHistoryFolderResultNode : Dérivée de
nsINavHistoryQueryResultNode
, ceci représente un type spécial de requête correspondant au contenu exact d'un des dossiers de marque-âges. Elle donne accès à son ID de dossier et se met à jour plus rapidement qu'une requête générale.
Exemple de détection du type d'un nœud
var Ci = Components.interfaces; switch(node.type) case node.RESULT_TYPE_URI: dump("Résultat URI " + node.uri + "\n"); break; case node.RESULT_TYPE_VISIT: var visit = node.QueryInterface(Ci.nsINavHistoryVisitResultNode); dump("Résultat de visite " + node.uri + " session = " + visit.sessionId + "\n"); break; case node.RESULT_TYPE_FULL_VISIT: var fullVisit = node.QueryInterface(Ci.nsINavHistoryFullVisitResultNode); dump("Résultat complet de visite " + node.uri + " session = " + fullVisit.sessionId + " transitionType = " + fullVisit.transitionType + "\n"); break; case node.RESULT_TYPE_HOST: var container = node.QueryInterface(Ci.nsINavHistoryContainerResultNode); dump("Hôte " + container.title + "\n"); break; case node.RESULT_TYPE_REMOTE_CONTAINER: var container = node.QueryInterface(Ci.nsINavHistoryContainerResultNode); dump("Conteneur distant " + container.title + " type = " + container.remoteContainerType + "\n"); break; case node.RESULT_TYPE_QUERY: var query = node.QueryInterface(Ci.nsINavHistoryQueryResultNode); dump("Requête, URI place = " + query.uri + "\n"); break; case node.RESULT_TYPE_FOLDER: // Notez que le dossier est également de type type nsINavHistoryContainerResultNode par défaut, // mais qu'il n'est pas possible de faire un QI sur nsINavHistoryQueryResultNode pour accéder // à la requête et aux options qui l'ont créé. dump("Dossier " + node.title + " id = " + node.itemId + "\n"); break; case node.RESULT_TYPE_SEPARATOR: dump("-----------\n"); break; }
Conteneurs
Les conteneurs conservent des listes d'autres conteneurs et de nœuds de résultats. Chaque résultat a un conteneur représentant la racine de la requête. Il peut être obtenu à l'aide de l'attribut root
du résultat. Pour les requêtes générales, ce conteneur racine est un nsINavHistoryQueryResultNode
avec les paramètres de requête et options fournis dans la requête d'origine. Pour les requêtes correspondant à un dossier de marque-pages, il s'agira d'un nsINavHistoryContainerResultNode
.
Les conteneurs peuvent être ouverts ou fermés. Ceci correspond aux états open
et closed
dans une vue arborescente, et peut également correspondre à l'affichage et le masquage de menus. Pour obtenir le contenu d'un conteneur, il faut d'abord l'ouvrir. La plupart des conteneurs se remplissent d'eux-mêmes paresseusement, ouvrir un conteneur correspond donc à exécuter la requête donnée. Tant qu'un conteneur est ouvert, il écoutera les nofifications du système d'historique et de marque-pages et modifiera son contenu pour rester à jour. Pour cette raison, il vaut mieux fermer un conteneur dès que vous en avez terminé avec lui, car cela amènera de meilleures performances. Si vous fermez un conteneur et le rouvrez avant qu'aucune notification de changement d'historique ou de marque-pages se fasse, les résultats seront généralement encore là et l'opération sera rapide.
Exemple d'examen d'un conteneur :
var cont = result.root; cont.containerOpen = true; for (var i = 0; i < cont.childCount; i ++) { var node = cont.getChild(i); dump(node.title + "\n"); } cont.containerOpen = false;
L'interface de visualisation des résultats
Si vous faites correspondre un résultat à une interface utilisateur, vous pouvez implémenter l'interface nsINavHistoryResultViewer
et l'attacher au résultat avec l'attribut nsINavHistoryResult.viewer
. Cet afficheur sera appelé lorsque l'arbre des résultats change, que ce soit le résultat d'une action de l'utilisateur ou de notifications des systèmes de marque-pages et d'historique. Votre implémentation pourra alors refléter ces changement dans l'interface utilisateur.
Une interface de visualisation toute faite pour un nsITreeBoxObject
est fournie, elle gère les nécessités d'affichage complexes d'un arbre. Cette interface d'objet est nsINavHistoryResultTreeViewer
(un descendant de nsINavHistoryResultViewer
) et peut être créée à l'aide du contrat @mozilla.org/browser/nav-history/result-tree-viewer;1
.
var treeviewer = Components.classes["@mozilla.org/browser/nav-history/result-tree-viewer;1"] .createInstance(Components.interfaces.nsINavHistoryResultTreeViewer); result.viewer = treeviewer; mytree.view = treeviewer.QueryInterface(Components.interfaces.nsITreeView);
Tant le résultat que l'arbre s'enregistreront automatiquement auprès de l'objet de visualisation, respectivement à l'aide de l'attribut result
et de la méthode setTree
. Ne le faites pas explicitement.