diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 4195e6295ec..10fa720b870 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -332,7 +332,7 @@ var gBookmarksObserver = { onItemRemoved: function() { }, onItemChanged: - function G_BO_onItemChanged(aID, aBookmark, aProperty, aValue) { + function G_BO_onItemChanged(aID, aProperty, aIsAnnotationProperty, aValue) { if (aProperty == "became_toolbar_folder" && this.toolbar) this.toolbar.place = PlacesUtils.getQueryStringForFolder(aID); }, diff --git a/browser/components/microsummaries/public/Makefile.in b/browser/components/microsummaries/public/Makefile.in index 3ade224a15b..48f877c98a8 100644 --- a/browser/components/microsummaries/public/Makefile.in +++ b/browser/components/microsummaries/public/Makefile.in @@ -44,6 +44,10 @@ include $(DEPTH)/config/autoconf.mk MODULE = microsummaries XPIDL_MODULE = microsummaries +ifdef MOZ_PLACES_BOOKMARKS XPIDLSRCS = nsIMicrosummaryService.idl +else +XPIDLSRCS = nsIMicrosummaryServiceNonPlaces.idl +endif include $(topsrcdir)/config/rules.mk diff --git a/browser/components/microsummaries/public/nsIMicrosummaryService.idl b/browser/components/microsummaries/public/nsIMicrosummaryService.idl index a0253736bd7..83dbd64ed2e 100644 --- a/browser/components/microsummaries/public/nsIMicrosummaryService.idl +++ b/browser/components/microsummaries/public/nsIMicrosummaryService.idl @@ -253,7 +253,7 @@ interface nsIMicrosummaryService : nsISupports * */ nsIMicrosummarySet getMicrosummaries(in nsIURI pageURI, - in nsISupports bookmarkID); + in long long bookmarkID); /** * Get the current microsummary for the given bookmark. @@ -265,7 +265,7 @@ interface nsIMicrosummaryService : nsISupports * if the bookmark does not have a current microsummary * */ - nsIMicrosummary getMicrosummary(in nsISupports bookmarkID); + nsIMicrosummary getMicrosummary(in long long bookmarkID); /** * Set the current microsummary for the given bookmark. @@ -277,7 +277,7 @@ interface nsIMicrosummaryService : nsISupports * the microsummary to set as the current one * */ - void setMicrosummary(in nsISupports bookmarkID, + void setMicrosummary(in long long bookmarkID, in nsIMicrosummary microsummary); /** @@ -287,7 +287,7 @@ interface nsIMicrosummaryService : nsISupports * the bookmark for which to remove the current microsummary * */ - void removeMicrosummary(in nsISupports bookmarkID); + void removeMicrosummary(in long long bookmarkID); /** * Whether or not the given bookmark has a current microsummary. @@ -299,7 +299,7 @@ interface nsIMicrosummaryService : nsISupports * has a current microsummary * */ - boolean hasMicrosummary(in nsISupports bookmarkID); + boolean hasMicrosummary(in long long bookmarkID); /** * Whether or not the given microsummary is the current microsummary @@ -315,7 +315,7 @@ interface nsIMicrosummaryService : nsISupports * for the bookmark * */ - boolean isMicrosummary(in nsISupports bookmarkID, + boolean isMicrosummary(in long long bookmarkID, in nsIMicrosummary microsummary); /** @@ -336,7 +336,7 @@ interface nsIMicrosummaryService : nsISupports * @returns the microsummary being refreshed * */ - nsIMicrosummary refreshMicrosummary(in nsISupports bookmarkID); + nsIMicrosummary refreshMicrosummary(in long long bookmarkID); }; [scriptable, uuid(f9e577a8-19d9-4ca0-a140-b9e43f014470)] @@ -346,7 +346,7 @@ interface nsILiveTitleNotificationSubject : nsISupports // Note: in the old bookmarks code, this is an RDF resource. In Places // it is currently a URI, but after the fix for bug 360133 lands it will // become an integer. - readonly attribute nsISupports bookmarkID; + readonly attribute long long bookmarkID; // The microsummary being displayed as the live title for the bookmark. // The actual value of the microsummary (i.e. the string that gets displayed diff --git a/browser/components/microsummaries/src/nsMicrosummaryService.js b/browser/components/microsummaries/src/nsMicrosummaryService.js index e1e81c9b5dd..66e862962eb 100644 --- a/browser/components/microsummaries/src/nsMicrosummaryService.js +++ b/browser/components/microsummaries/src/nsMicrosummaryService.js @@ -302,11 +302,10 @@ MicrosummaryService.prototype = { oldValue = this._getField(bookmarkID, FIELD_GENERATED_TITLE); // A string identifying the bookmark to use when logging the update. - var bookmarkIdentity = #ifdef MOZ_PLACES_BOOKMARKS - bookmarkID.spec; + var bookmarkIdentity = bookmarkID; #else - bookmarkID.Value + " (" + microsummary.pageURI.spec + ")"; + var bookmarkIdentity = bookmarkID.Value + " (" + microsummary.pageURI.spec + ")"; #endif if (oldValue == null || oldValue != microsummary.content) { @@ -613,7 +612,11 @@ MicrosummaryService.prototype = { // If this is the current microsummary for this bookmark, load the content // from the datastore so it shows up immediately in microsummary picking UI. +#ifdef MOZ_PLACES_BOOKMARKS + if (bookmarkID != -1 && this.isMicrosummary(bookmarkID, microsummary)) +#else if (bookmarkID && this.isMicrosummary(bookmarkID, microsummary)) +#endif microsummary._content = this._getField(bookmarkID, FIELD_GENERATED_TITLE); microsummaries.AppendElement(microsummary); @@ -622,7 +625,11 @@ MicrosummaryService.prototype = { // If a bookmark identifier has been provided, list its microsummary // synchronously, if any. +#ifdef MOZ_PLACES_BOOKMARKS + if (bookmarkID != -1 && this.hasMicrosummary(bookmarkID)) { +#else if (bookmarkID && this.hasMicrosummary(bookmarkID)) { +#endif var currentMicrosummary = this.getMicrosummary(bookmarkID); if (!microsummaries.hasItemForMicrosummary(currentMicrosummary)) microsummaries.AppendElement(currentMicrosummary); @@ -699,7 +706,7 @@ MicrosummaryService.prototype = { // This try/catch block is a temporary workaround for bug 336194. try { - bookmarks = this._ans.getPagesWithAnnotation(FIELD_MICSUM_GEN_URI, {}); + bookmarks = this._ans.getItemsWithAnnotation(FIELD_MICSUM_GEN_URI, {}); } catch(e) { bookmarks = []; @@ -708,71 +715,56 @@ MicrosummaryService.prototype = { return bookmarks; }, - _getField: function MSS__getField(aPlaceURI, aFieldName) { - aPlaceURI.QueryInterface(Ci.nsIURI); + _getField: function MSS__getField(aBookmarkId, aFieldName) { var fieldValue; switch(aFieldName) { case FIELD_MICSUM_EXPIRATION: - fieldValue = this._ans.getAnnotationInt64(aPlaceURI, aFieldName); + fieldValue = this._ans.getItemAnnotationInt64(aBookmarkId, aFieldName); break; case FIELD_MICSUM_GEN_URI: case FIELD_GENERATED_TITLE: case FIELD_CONTENT_TYPE: default: - fieldValue = this._ans.getAnnotationString(aPlaceURI, aFieldName); + fieldValue = this._ans.getItemAnnotationString(aBookmarkId, aFieldName); break; } return fieldValue; }, - _setField: function MSS__setField(aPlaceURI, aFieldName, aFieldValue) { - aPlaceURI.QueryInterface(Ci.nsIURI); - + _setField: function MSS__setField(aBookmarkId, aFieldName, aFieldValue) { switch(aFieldName) { case FIELD_MICSUM_EXPIRATION: - this._ans.setAnnotationInt64(aPlaceURI, - aFieldName, - aFieldValue, - 0, - this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationInt64(aBookmarkId, + aFieldName, + aFieldValue, + 0, + this._ans.EXPIRE_NEVER); break; case FIELD_MICSUM_GEN_URI: case FIELD_GENERATED_TITLE: case FIELD_CONTENT_TYPE: default: - this._ans.setAnnotationString(aPlaceURI, - aFieldName, - aFieldValue, - 0, - this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationString(aBookmarkId, + aFieldName, + aFieldValue, + 0, + this._ans.EXPIRE_NEVER); break; } }, - _clearField: function MSS__clearField(aPlaceURI, aFieldName) { - aPlaceURI.QueryInterface(Ci.nsIURI); - this._ans.removeAnnotation(aPlaceURI, aFieldName); + _clearField: function MSS__clearField(aBookmarkId, aFieldName) { + this._ans.removeItemAnnotation(aBookmarkId, aFieldName); }, - _hasField: function MSS__hasField(aPlaceURI, fieldName) { - aPlaceURI.QueryInterface(Ci.nsIURI); - return this._ans.hasAnnotation(aPlaceURI, fieldName); + _hasField: function MSS__hasField(aBookmarkId, fieldName) { + return this._ans.itemHasAnnotation(aBookmarkId, fieldName); }, - _getPageForBookmark: function MSS__getPageForBookmark(aPlaceURI) { - aPlaceURI.QueryInterface(Ci.nsIURI); - - // Manually get the bookmark identifier out of the place uri until - // the query system supports parsing this sort of place: uris - var matches = /moz_bookmarks.id=([0-9]+)/.exec(aPlaceURI.spec); - if (matches) { - var bookmarkId = parseInt(matches[1]); - return this._bms.getBookmarkURI(bookmarkId); - } - - return null; + _getPageForBookmark: function MSS__getPageForBookmark(aBookmarkId) { + return this._bms.getBookmarkURI(aBookmarkId); }, #else diff --git a/browser/components/places/content/bookmarkProperties.js b/browser/components/places/content/bookmarkProperties.js index 5be5dacb199..60708c5fc34 100755 --- a/browser/components/places/content/bookmarkProperties.js +++ b/browser/components/places/content/bookmarkProperties.js @@ -125,7 +125,7 @@ var BookmarkPropertiesPanel = { _action: null, _itemType: null, _folderId: null, - _bookmarkId: null, + _bookmarkId: -1, _bookmarkURI: null, _loadBookmarkInSidebar: false, _itemTitle: "", @@ -267,7 +267,6 @@ var BookmarkPropertiesPanel = { const annos = PlacesUtils.annotations; const bookmarks = PlacesUtils.bookmarks; - var placeURI; switch (dialogInfo.type) { case "bookmark": NS_ASSERT("bookmarkId" in dialogInfo); @@ -275,7 +274,6 @@ var BookmarkPropertiesPanel = { this._action = ACTION_EDIT; this._itemType = BOOKMARK_ITEM; this._bookmarkId = dialogInfo.bookmarkId; - placeURI = bookmarks.getItemURI(this._bookmarkId); this._bookmarkURI = bookmarks.getBookmarkURI(this._bookmarkId); this._itemTitle = bookmarks.getItemTitle(this._bookmarkId); @@ -286,7 +284,7 @@ var BookmarkPropertiesPanel = { // Load In Sidebar this._loadBookmarkInSidebar = - annos.hasAnnotation(placeURI, LOAD_IN_SIDEBAR_ANNO); + annos.itemHasAnnotation(this._bookmarkId, LOAD_IN_SIDEBAR_ANNO); break; case "folder": @@ -294,7 +292,6 @@ var BookmarkPropertiesPanel = { this._action = ACTION_EDIT; this._folderId = dialogInfo.folderId; - placeURI = bookmarks.getFolderURI(this._folderId); const livemarks = PlacesUtils.livemarks; if (livemarks.isLivemark(this._folderId)) { @@ -309,9 +306,11 @@ var BookmarkPropertiesPanel = { } // Description - if (annos.hasAnnotation(placeURI, DESCRIPTION_ANNO)) { - this._itemDescription = - annos.getAnnotationString(placeURI, DESCRIPTION_ANNO); + // XXXmano: unify the two id fields + var itemId = dialogInfo.type == "bookmark" ? this._bookmarkId : this._folderId; + if (annos.itemHasAnnotation(itemId, DESCRIPTION_ANNO)) { + this._itemDescription = annos.getItemAnnotationString(itemId, + DESCRIPTION_ANNO); } } }, @@ -382,10 +381,10 @@ var BookmarkPropertiesPanel = { _initFolderMenuList: function BPP__initFolderMenuList() { // List of recently used folders: var annos = PlacesUtils.annotations; - var folderURIs = annos.getPagesWithAnnotation(LAST_USED_ANNO, { }); + var folderIds = annos.getItemsWithAnnotation(LAST_USED_ANNO, { }); // Hide the folders-separator if no folder is annotated as recently-used - if (folderURIs.length == 0) { + if (folderIds.length == 0) { this._element("foldersSeparator").hidden = true; return; } @@ -399,17 +398,9 @@ var BookmarkPropertiesPanel = { * set. Then we sort it descendingly based on the time field. */ var folders = []; - var history = PlacesUtils.history; - for (var i=0; i < folderURIs.length; i++) { - var queryString = folderURIs[i].spec; - var queries = { }; - history.queryStringToQueries(queryString, queries, { /* length */ }, - { /* options */ }); - var folderId = queries.value[0].getFolders({})[0]; - NS_ASSERT(queries.value[0].folderCount == 1, - "Bogus uri is annotated with the LAST_USED_ANNO annotation"); - var lastUsed = annos.getAnnotationInt64(folderURIs[i], LAST_USED_ANNO); - folders.push({ folderId: folderId, lastUsed: lastUsed }); + for (var i=0; i < folderIds.length; i++) { + var lastUsed = annos.getItemAnnotationInt64(folderIds[i], LAST_USED_ANNO); + folders.push({ folderId: folderIds[i], lastUsed: lastUsed }); } folders.sort(function(a, b) { if (b.lastUsed < a.lastUsed) @@ -551,14 +542,9 @@ var BookmarkPropertiesPanel = { } var itemToSelect = userEnteredNameField; - var placeURI = null; - if (this._action == ACTION_EDIT) { - NS_ASSERT(this._bookmarkId, "No bookmark identifier"); - placeURI = PlacesUtils.bookmarks.getItemURI(this._bookmarkId); - } try { this._microsummaries = this._mss.getMicrosummaries(this._bookmarkURI, - placeURI); + this._bookmarkId); } catch(ex) { // getMicrosummaries will throw an exception in at least two cases: @@ -583,7 +569,7 @@ var BookmarkPropertiesPanel = { var menuItem = this._createMicrosummaryMenuItem(microsummary); if (this._action == ACTION_EDIT && - this._mss.isMicrosummary(placeURI, microsummary)) + this._mss.isMicrosummary(this._bookmarkId, microsummary)) itemToSelect = menuItem; menupopup.appendChild(menuItem); @@ -824,10 +810,9 @@ var BookmarkPropertiesPanel = { // microsummary, but the bookmark previously had one, or the user // selected a microsummary which is not the one the bookmark previously // had. - var placeURI = PlacesUtils.bookmarks.getItemURI(itemId); - if ((newMicrosummary == null && this._mss.hasMicrosummary(placeURI)) || + if ((newMicrosummary == null && this._mss.hasMicrosummary(itemId)) || (newMicrosummary != null && - !this._mss.isMicrosummary(placeURI, newMicrosummary))) { + !this._mss.isMicrosummary(itemId, newMicrosummary))) { transactions.push( new PlacesEditBookmarkMicrosummaryTransaction(itemId, newMicrosummary)); @@ -1112,11 +1097,10 @@ var BookmarkPropertiesPanel = { function BPP__markFolderAsRecentlyUsed(aFolderId) { // We'll figure out when/if to expire the annotation if it turns out // we keep this recently-used-folders implementation - var folderURI = PlacesUtils.bookmarks.getFolderURI(aFolderId); PlacesUtils.annotations - .setAnnotationInt64(folderURI, LAST_USED_ANNO, - new Date().getTime(), 0, - Ci.nsIAnnotationService.EXPIRE_NEVER); + .setItemAnnotationInt64(aFolderId, LAST_USED_ANNO, + new Date().getTime(), 0, + Ci.nsIAnnotationService.EXPIRE_NEVER); }, newFolder: function BPP_newFolder() { diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 1429860ccb0..676a654e0ea 100755 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -594,10 +594,10 @@ PlacesController.prototype = { for (var j = 0; j < names.length; ++j) nodeData[names[j]] = true; - // For bookmark-items also include the bookmark-specific annotations - if ("bookmark" in nodeData) { - var placeURI = PlacesUtils.bookmarks.getItemURI(node.bookmarkId); - names = PlacesUtils.annotations.getPageAnnotationNames(placeURI, {}); + // For items also include the item-specific annotations + if ("bookmark" in nodeData || "folder" in nodeData) { + names = PlacesUtils.annotations + .getItemAnnotationNames(node.itemId, {}); for (j = 0; j < names.length; ++j) nodeData[names[j]] = true; } @@ -766,9 +766,8 @@ PlacesController.prototype = { // Check whether the node is a bookmark which should be opened as // a web panel if (aWhere == "current" && PlacesUtils.nodeIsBookmark(node)) { - var placeURI = PlacesUtils.bookmarks.getItemURI(node.bookmarkId); if (PlacesUtils.annotations - .hasAnnotation(placeURI, LOAD_IN_SIDEBAR_ANNO)) { + .itemHasAnnotation(node.itemId, LOAD_IN_SIDEBAR_ANNO)) { var w = getTopWin(); if (w) { w.openWebPanel(node.title, node.uri); @@ -792,7 +791,7 @@ PlacesController.prototype = { if (PlacesUtils.nodeIsFolder(node)) PlacesUtils.showFolderProperties(asFolder(node).folderId); else if (PlacesUtils.nodeIsBookmark(node)) - PlacesUtils.showBookmarkProperties(node.bookmarkId); + PlacesUtils.showBookmarkProperties(node.itemId); }, /** @@ -1121,7 +1120,7 @@ PlacesController.prototype = { } else if (PlacesUtils.nodeIsFolder(node.parent)) { // A Bookmark in a Bookmark Folder. - transactions.push(new PlacesRemoveItemTransaction(node.bookmarkId, + transactions.push(new PlacesRemoveItemTransaction(node.itemId, PlacesUtils._uri(node.uri), asFolder(node.parent).folderId, index)); } } @@ -1645,10 +1644,9 @@ PlacesCreateFolderTransaction.prototype = { doTransaction: function PCFT_doTransaction() { var bookmarks = this.utils.bookmarks; this._id = bookmarks.createFolder(this._container, this._name, this._index); - if (this._annotations.length > 0) { - var placeURI = bookmarks.getFolderURI(this._id); - this.utils.setAnnotationsForURI(placeURI, this._annotations); - } + if (this._annotations.length > 0) + this.utils.setAnnotationsForItem(this._id, this._annotations); + for (var i = 0; i < this._childItemsTransactions.length; ++i) { var txn = this._childItemsTransactions[i]; txn.container = this._id; @@ -1715,10 +1713,8 @@ PlacesCreateItemTransaction.prototype = { bookmarks.setItemTitle(this._id, this._title); if (this._keyword) bookmarks.setKeywordForBookmark(this._id, this._keyword); - if (this._annotations && this._annotations.length > 0) { - var placeURI = bookmarks.getItemURI(this._id); - this.utils.setAnnotationsForURI(placeURI, this._annotations); - } + if (this._annotations && this._annotations.length > 0) + this.utils.setAnnotationsForItem(this._id, this._annotations); for (var i = 0; i < this._childTransactions.length; ++i) { var txn = this._childTransactions[i]; @@ -1804,10 +1800,8 @@ PlacesCreateLivemarkTransaction.prototype = { this._id = this.utils.livemarks .createLivemark(this._container, this._name, this._siteURI, this._feedURI, this._index); - if (this._annotations) { - var placeURI = this.utils.bookmarks.getFolderURI(this._id); - this.utils.setAnnotationsForURI(placeURI, this._annotations); - } + if (this._annotations) + this.utils.setAnnotationsForItem(this._id, this._annotations); }, undoTransaction: function PCLT_undoTransaction() { @@ -1860,26 +1854,21 @@ PlacesMoveItemTransaction.prototype = { doTransaction: function PMIT_doTransaction() { this.LOG("Move Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex + " to: " + this._newContainer + "," + this._newIndex); var title = this.bookmarks.getItemTitle(this._id); - var placeURI = this.bookmarks.getItemURI(this._id); - var annotations = this.utils.getAnnotationsForURI(placeURI); + var annotations = this.utils.getAnnotationsForItem(this._id); this.bookmarks.removeItem(this._id); this._id = this.bookmarks.insertItem(this._newContainer, this._uri, this._newIndex); this.bookmarks.setItemTitle(this._id, title); - this.utils.setAnnotationsForURI(this.bookmarks.getItemURI(this._id), - annotations); + this.utils.setAnnotationsForItem(this._id, annotations); }, undoTransaction: function PMIT_undoTransaction() { this.LOG("UNMove Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex + " to: " + this._newContainer + "," + this._newIndex); var title = this.bookmarks.getItemTitle(this._id); - var placeURI = this.bookmarks.getItemURI(this._id); - var annotations = this.utils.getAnnotationsForURI(placeURI); + var annotations = this.utils.getAnnotationsForItem(this._id); this.bookmarks.removeItem(this._id); this._id = this.bookmarks.insertItem(this._oldContainer, this._uri, this._oldIndex); this.bookmarks.setItemTitle(this._id, title); - placeURI = this.bookmarks.getItemURI(this._id); - this.utils.setAnnotationsForURI(this.bookmarks.getItemURI(this._id), - annotations); + this.utils.setAnnotationsForItem(this._id, annotations); } }; @@ -1925,7 +1914,7 @@ PlacesRemoveFolderTransaction.prototype = { txn = new PlacesRemoveSeparatorTransaction(this._id, i); } else { - txn = new PlacesRemoveItemTransaction(child.bookmarkId, + txn = new PlacesRemoveItemTransaction(child.itemId, ios.newURI(child.uri, null, null), this._id, i); } @@ -1976,18 +1965,15 @@ PlacesRemoveItemTransaction.prototype = { doTransaction: function PRIT_doTransaction() { this.LOG("Remove Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex); this._title = this.bookmarks.getItemTitle(this._id); - this._placeURI = this.bookmarks.getItemURI(this._id); - this._annotations = this.utils.getAnnotationsForURI(this._placeURI); - PlacesUtils.annotations.removePageAnnotations(this._placeURI); - this.bookmarks.removeItem(this._id); + this._annotations = this.utils.getAnnotationsForItem(this._id); + this.utils.bookmarks.removeItem(this._id); }, undoTransaction: function PRIT_undoTransaction() { this.LOG("UNRemove Item: " + this._uri.spec + " from: " + this._oldContainer + "," + this._oldIndex); this._id = this.bookmarks.insertItem(this._oldContainer, this._uri, this._oldIndex); this.bookmarks.setItemTitle(this._id, this._title); - this._placeURI = this.bookmarks.getItemURI(this._id); - this.utils.setAnnotationsForURI(this._placeURI, this._annotations); + this.utils.setAnnotationsForItem(this._id, this._annotations); } }; @@ -2075,19 +2061,14 @@ PlacesSetLoadInSidebarTransaction.prototype = { }, doTransaction: function PSLIST_doTransaction() { - if (!("_placeURI" in this)) - this._placeURI = this.utils.bookmarks.getItemURI(this.id); - this._wasSet = this.utils.annotations - .hasAnnotation(this._placeURI, this._anno.name); + .itemHasAnnotation(this.id, this._anno.name); if (this._loadInSidebar) { - this.utils.setAnnotationsForURI(this._placeURI, - [this._anno]); + this.utils.setAnnotationsForItem(this.id, [this._anno]); } else { try { - this.utils.annotations.removeAnnotation(this._placeURI, - this._anno.name); + this.utils.annotations.removeItemAnnotation(this.id, this._anno.name); } catch(ex) { } } }, @@ -2103,12 +2084,10 @@ PlacesSetLoadInSidebarTransaction.prototype = { /** * Edit a the description of a bookmark or a folder * - * XXXmano: aIsFolder is a temporary workaround for bug 372508 */ -function PlacesEditItemDescriptionTransaction(aBookmarkId, aDescription, aIsFolder) { - this.id = aBookmarkId; +function PlacesEditItemDescriptionTransaction(aItemId, aDescription) { + this.id = aItemId; this._newDescription = aDescription; - this._isFolder = aIsFolder; this.redoTransaction = this.doTransaction; } PlacesEditItemDescriptionTransaction.prototype = { @@ -2120,37 +2099,30 @@ PlacesEditItemDescriptionTransaction.prototype = { doTransaction: function PSLIST_doTransaction() { const annos = this.utils.annotations; - if (!("_placeURI" in this)) { - if (this._isFolder) - this._placeURI = this.utils.bookmarks.getFolderURI(this.id); - else - this._placeURI = this.utils.bookmarks.getItemURI(this.id); - } - - if (annos.hasAnnotation(this._placeURI, this.DESCRIPTION_ANNO)) { + if (annos.itemHasAnnotation(this.id, this.DESCRIPTION_ANNO)) { this._oldDescription = - annos.getAnnotationString(this._placeURI, this.DESCRIPTION_ANNO); + annos.getItemAnnotationString(this.id, this.DESCRIPTION_ANNO); } if (this._newDescription) { - annos.setAnnotationString(this._placeURI, this.DESCRIPTION_ANNO, - this._newDescription, 0, - this.nsIAnnotationService.EXPIRE_NEVER); + annos.setItemAnnotationString(this.id, this.DESCRIPTION_ANNO, + this._newDescription, 0, + this.nsIAnnotationService.EXPIRE_NEVER); } else if (this._oldDescription) - annos.removeAnnotation(this._placeURI, this.DESCRIPTION_ANNO); + annos.removeItemAnnotation(this.id, this.DESCRIPTION_ANNO); }, undoTransaction: function PSLIST_undoTransaction() { const annos = this.utils.annotations; if (this._oldDescription) { - annos.setAnnotationString(this._placeURI, this.DESCRIPTION_ANNO, - this._oldDescription, 0, - this.nsIAnnotationService.EXPIRE_NEVER); + annos.setItemAnnotationString(this.id, this.DESCRIPTION_ANNO, + this._oldDescription, 0, + this.nsIAnnotationService.EXPIRE_NEVER); } - else if (this.utils.hasAnnotation(this._placeURI, this.DESCRIPTION_ANNO)) - annos.removeAnnotation(this._placeURI, this.DESCRIPTION_ANNO); + else if (annos.itemHasAnnotation(this.id, this.DESCRIPTION_ANNO)) + annos.removeItemAnnotation(this.id, this.DESCRIPTION_ANNO); } }; @@ -2260,20 +2232,18 @@ PlacesEditBookmarkMicrosummaryTransaction.prototype = { getService(Ci.nsIMicrosummaryService), doTransaction: function PEBMT_doTransaction() { - var placeURI = this.bookmarks.getItemURI(this.id); - this._oldMicrosummary = this.mss.getMicrosummary(placeURI); + this._oldMicrosummary = this.mss.getMicrosummary(this.id); if (this._newMicrosummary) - this.mss.setMicrosummary(placeURI, this._newMicrosummary); + this.mss.setMicrosummary(this.id, this._newMicrosummary); else - this.mss.removeMicrosummary(placeURI); + this.mss.removeMicrosummary(this.id); }, undoTransaction: function PEBMT_undoTransaction() { - var placeURI = this.bookmarks.getItemURI(this.id); if (this._oldMicrosummary) - this.mss.setMicrosummary(placeURI, this._oldMicrosummary); + this.mss.setMicrosummary(this.id, this._oldMicrosummary); else - this.mss.removeMicrosummary(placeURI); + this.mss.removeMicrosummary(this.id); } }; diff --git a/browser/components/places/content/moveBookmarks.js b/browser/components/places/content/moveBookmarks.js index 5a95d2e0e78..9752aef717b 100644 --- a/browser/components/places/content/moveBookmarks.js +++ b/browser/components/places/content/moveBookmarks.js @@ -83,7 +83,7 @@ var gMoveBookmarksDialog = { } else if (PlacesUtils.nodeIsBookmark(this._nodes[i])) { transactions.push(new - PlacesMoveItemTransaction(this._nodes[i].bookmarkId, + PlacesMoveItemTransaction(this._nodes[i].itemId, PlacesUtils._uri(this._nodes[i].uri), parentId, nodeIndex, selectedFolderID, -1)); } diff --git a/browser/components/places/content/toolbar.xml b/browser/components/places/content/toolbar.xml index 017788347ec..0bc9e9ece78 100755 --- a/browser/components/places/content/toolbar.xml +++ b/browser/components/places/content/toolbar.xml @@ -162,20 +162,19 @@ var annotations = PlacesUtils.annotations; // This try/catch block is a temporary workaround for bug 336194. - var placeURIs; + var bookmarks = []; try { - placeURIs = annotations.getPagesWithAnnotation("bookmarks/generatedTitle", {}); - } - catch(e) { - placeURIs = []; + bookmarks = annotations.getItemsWithAnnotation("bookmarks/generatedTitle", {}); } + catch(e) { } // XXX It'd be faster to grab the annotations in a single query // instead of querying separately for each one, but the annotation // service provides no mechanism for doing so. - for ( var i = 0; i < placeURIs.length; i++) - this.__generatedTitles[placeURIs[i].spec] = - annotations.getAnnotationString(placeURIs[i], "bookmarks/generatedTitle"); + for (var i = 0; i < bookmarks.length; i++) { + this.__generatedTitles[bookmarks[i]] = + annotations.getItemAnnotationString(bookmarks[i], "bookmarks/generatedTitle"); + } } return this.__generatedTitles; @@ -247,9 +246,8 @@ if (PlacesUtils.nodeIsBookmark(child)) { // If the item has a generated title, use that instead. - var placeURI = PlacesUtils.bookmarks.getItemURI(child.bookmarkId); - if (this._generatedTitles[placeURI.spec]) - title = this._generatedTitles[placeURI.spec]; + if (this._generatedTitles[child.itemId]) + title = this._generatedTitles[child.itemId]; } } else if (PlacesUtils.nodeIsSeparator(child)) { button = document.createElementNS(XULNS, "toolbarseparator"); @@ -263,11 +261,10 @@ // duplicate nsLivemarkService.getSiteURI to avoid instantiating // the service on startup. - var containerURI = PlacesUtils.bookmarks.getFolderURI(folder); var siteURIString; try { siteURIString = - this._anno.getAnnotationString(containerURI, "livemark/siteURI"); + this._anno.getItemAnnotationString(folder, "livemark/siteURI"); } catch (ex) {} // end duplication @@ -776,18 +773,25 @@ // observer object, while "_self" points to the toolbar XBL object. _self: this, - onAnnotationSet: function TBV_GTAO_onAnnotationSet(uri, annoName) { - NS_ASSERT(annoName == "bookmarks/generatedTitle", - "annotation " + annoName + ", is not 'bookmarks/generatedTitle'"); - var newTitle = PlacesUtils.annotations.getAnnotationString(uri, annoName); - this._self._generatedTitles[uri.spec] = newTitle; + onPageAnnotationSet: function() { }, + + onPageAnnotationRemoved: function() { }, + + onItemAnnotationSet: + function TBV_GTAO_onItemAnnotationSet(aItemId, aAnnoName) { + NS_ASSERT(aAnnoName == "bookmarks/generatedTitle", + "annotation " + aAnnoName + ", is not 'bookmarks/generatedTitle'"); + var newTitle = + PlacesUtils.annotations.getItemAnnotationString(aItemId, aAnnoName); + this._self._generatedTitles[aItemId] = newTitle; this._doRebuild(); }, - onAnnotationRemoved: function TBV_GTAO_onAnnotationRemoved(uri, annoName) { - NS_ASSERT(annoName == "bookmarks/generatedTitle", - "annotation " + annoName + ", is not 'bookmarks/generatedTitle'"); - delete this._self._generatedTitles[uri.spec]; + onItemAnnotationRemoved: + function TBV_GTAO_onItemAnnotationRemoved(aItemId, aAnnoName) { + NS_ASSERT(aAnnoName == "bookmarks/generatedTitle", + "annotation " + aAnnoName + ", is not 'bookmarks/generatedTitle'"); + delete this._self._generatedTitles[aItemId]; this._doRebuild(); }, @@ -797,7 +801,6 @@ } setTimeout(hitch(this._self, this._self._rebuild), 1); } - })]]> @@ -830,7 +833,7 @@ this._observers[annoName] = this._observers[annoName].filter(function(i) { observer != i }); - + if (this._observers[annoName].length == 0) delete this._observers[annoName]; }, @@ -846,22 +849,45 @@ return true; }, - onAnnotationSet: function TBV_GAO_onAnnotationSet(uri, annoName) { + onPageAnnotationSet: + function TBV_GAO_onPageAnnotationSet(uri, annoName) { if (!this._applies(uri, annoName)) return; - for ( var i = 0; i < this._observers[annoName].length; i++) - this._observers[annoName][i].onAnnotationSet(uri, annoName); + for (var i = 0; i < this._observers[annoName].length; i++) + this._observers[annoName][i].onPageAnnotationSet(uri, annoName); }, - onAnnotationRemoved: function TBV_GAO_onAnnotationRemoved(uri, annoName) { + onPageAnnotationRemoved: + function TBV_GAO_onPageAnnotationRemoved(uri, annoName) { if (!this._applies(uri, annoName)) return; for ( var i = 0; i < this._observers[annoName].length; i++) - this._observers[annoName][i].onAnnotationRemoved(uri, annoName); - } + this._observers[annoName][i].onPageAnnotationRemoved(uri, annoName); + }, + onItemAnnotationSet: + function TBV_GAO_onItemAnnotationSet(aItemId, aAnnoName) { + if (!this._applies(aItemId, aAnnoName)) + return; + + for (var i = 0; i < this._observers[aAnnoName].length; i++) { + this._observers[aAnnoName][i] + .onItemAnnotationSet(aItemId, aAnnoName); + } + }, + + onItemAnnotationRemoved: + function TBV_GAO_onItemAnnotationRemoved(aItemId, aAnnoName) { + if (!this._applies(aItemId, aAnnoName)) + return; + + for (var i = 0; i < this._observers[aAnnoName].length; i++) { + this._observers[aAnnoName][i] + .onItemAnnotationRemoved(aItemId, aAnnoName); + } + } })]]> diff --git a/browser/components/places/content/utils.js b/browser/components/places/content/utils.js index 0258d9b7869..da782141140 100644 --- a/browser/components/places/content/utils.js +++ b/browser/components/places/content/utils.js @@ -218,7 +218,8 @@ var PlacesUtils = { */ nodeIsBookmark: function PU_nodeIsBookmark(aNode) { NS_ASSERT(aNode, "null node"); - return aNode.bookmarkId > 0; + return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI && + aNode.itemId != -1; }, /** @@ -369,8 +370,8 @@ var PlacesUtils = { */ nodeIsLivemarkItem: function PU_nodeIsLivemarkItem(aNode) { if (this.nodeIsBookmark(aNode)) { - var placeURI = this.bookmarks.getItemURI(aNode.bookmarkId); - if (this.annotations.hasAnnotation(placeURI, "livemark/bookmarkFeedURI")) + if (this.annotations + .itemHasAnnotation(aNode.itemId, "livemark/bookmarkFeedURI")) return true; } @@ -430,15 +431,15 @@ var PlacesUtils = { case this.TYPE_X_MOZ_PLACE: case this.TYPE_X_MOZ_PLACE_SEPARATOR: // Data is encoded like this: - // bookmarks folder: \n<>\n\n + // bookmarks folder: \n<>\n\n // uri: 0\n\n\n - // bookmark: \n\n\n + // bookmark: \n\n\n // separator: 0\n<>\n\n var wrapped = ""; if (this.nodeIsFolder(aNode)) wrapped += asFolder(aNode).folderId + NEWLINE; else if (this.nodeIsBookmark(aNode)) - wrapped += aNode.bookmarkId + NEWLINE; + wrapped += aNode.itemId + NEWLINE; else wrapped += "0" + NEWLINE; @@ -538,6 +539,7 @@ var PlacesUtils = { if (self.nodeIsFolder(node)) { var nodeFolderId = asFolder(node).folderId; var title = self.bookmarks.getFolderTitle(nodeFolderId); + // XXXmano: use item-annotations once bug 372508 is fixed var annos = self.getAnnotationsForURI(self._uri(node.uri)); var folderItemsTransactions = getChildItemsTransactions(nodeFolderId); @@ -545,7 +547,7 @@ var PlacesUtils = { folderItemsTransactions); } else if (self.nodeIsBookmark(node)) { - txn = self._getBookmarkItemCopyTransaction(node.bookmarkId, -1, + txn = self._getBookmarkItemCopyTransaction(node.itemId, -1, aIndex); } else if (self.nodeIsURI(node) || self.nodeIsQuery(node)) { @@ -564,8 +566,7 @@ var PlacesUtils = { } var title = this.bookmarks.getFolderTitle(aData.id); - var annos = - this.getAnnotationsForURI(this.bookmarks.getFolderURI(aData.id)); + var annos = this.getAnnotationsForItem(aData.id); var createTxn = new PlacesCreateFolderTransaction(title, aContainer, aIndex, annos, getChildItemsTransactions(aData.id)); @@ -1112,23 +1113,69 @@ var PlacesUtils = { var annoNames = annosvc.getPageAnnotationNames(aURI, {}); for (var i = 0; i < annoNames.length; i++) { var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(aURI, annoNames[i], flags, exp, mimeType, storageType); + annosvc.getPageAnnotationInfo(aURI, annoNames[i], flags, exp, mimeType, storageType); switch (storageType.value) { case annosvc.TYPE_INT32: - val = annosvc.getAnnotationInt32(aURI, annoNames[i]); + val = annosvc.getPageAnnotationInt32(aURI, annoNames[i]); break; case annosvc.TYPE_INT64: - val = annosvc.getAnnotationInt64(aURI, annoNames[i]); + val = annosvc.getPageAnnotationInt64(aURI, annoNames[i]); break; case annosvc.TYPE_DOUBLE: - val = annosvc.getAnnotationDouble(aURI, annoNames[i]); + val = annosvc.getPageAnnotationDouble(aURI, annoNames[i]); break; case annosvc.TYPE_STRING: - val = annosvc.getAnnotationString(aURI, annoNames[i]); + val = annosvc.getPageAnnotationString(aURI, annoNames[i]); break; case annosvc.TYPE_BINARY: var data = {}, length = {}, mimeType = {}; - annosvc.getAnnotationBinary(aURI, annoNames[i], data, length, mimeType); + annosvc.getPageAnnotationBinary(aURI, annoNames[i], data, length, mimeType); + val = data.value; + break; + } + annos.push({name: annoNames[i], + flags: flags.value, + expires: exp.value, + mimeType: mimeType.value, + type: storageType.value, + value: val}); + } + return annos; + }, + + /** + * Fetch all annotations for a URI, including all properties of each + * annotation which would be required to recreate it. + * @param aItemId + * The identifier of the itme for which annotations are to be + * retrieved. + * @return Array of objects, each containing the following properties: + * name, flags, expires, mimeType, type, value + */ + getAnnotationsForItem: function PU_getAnnotationsForItem(aItemId) { + var annosvc = this.annotations; + var annos = [], val = null; + var annoNames = annosvc.getItemAnnotationNames(aItemId, {}); + for (var i = 0; i < annoNames.length; i++) { + var flags = {}, exp = {}, mimeType = {}, storageType = {}; + annosvc.getItemAnnotationInfo(aItemId, annoNames[i], flags, exp, + mimeType, storageType); + switch (storageType.value) { + case annosvc.TYPE_INT32: + val = annosvc.getItemAnnotationInt32(aItemId, annoNames[i]); + break; + case annosvc.TYPE_INT64: + val = annosvc.getItemAnnotationInt64(aItemId, annoNames[i]); + break; + case annosvc.TYPE_DOUBLE: + val = annosvc.getItemAnnotationDouble(aItemId, annoNames[i]); + break; + case annosvc.TYPE_STRING: + val = annosvc.getItemAnnotationString(aItemId, annoNames[i]); + break; + case annosvc.TYPE_BINARY: + var data = {}, length = {}, mimeType = {}; + annosvc.getItemAnnotationBinary(aItemId, annoNames[i], data, length, mimeType); val = data.value; break; } @@ -1145,7 +1192,7 @@ var PlacesUtils = { /** * Annotate a URI with a batch of annotations. * @param aURI - * The URI for which annotations are to be retrieved. + * The URI for which annotations are to be set. * @param aAnnotations * Array of objects, each containing the following properties: * name, flags, expires, type, mimeType (only used for binary @@ -1156,25 +1203,63 @@ var PlacesUtils = { aAnnos.forEach(function(anno) { switch (anno.type) { case annosvc.TYPE_INT32: - annosvc.setAnnotationInt32(aURI, anno.name, anno.value, - anno.flags, anno.expires); + annosvc.setPageAnnotationInt32(aURI, anno.name, anno.value, + anno.flags, anno.expires); break; case annosvc.TYPE_INT64: - annosvc.setAnnotationInt64(aURI, anno.name, anno.value, - anno.flags, anno.expires); + annosvc.setPageAnnotationInt64(aURI, anno.name, anno.value, + anno.flags, anno.expires); break; case annosvc.TYPE_DOUBLE: - annosvc.setAnnotationDouble(aURI, anno.name, anno.value, - anno.flags, anno.expires); + annosvc.setPageAnnotationDouble(aURI, anno.name, anno.value, + anno.flags, anno.expires); break; case annosvc.TYPE_STRING: - annosvc.setAnnotationString(aURI, anno.name, anno.value, - anno.flags, anno.expires); + annosvc.setPageAnnotationString(aURI, anno.name, anno.value, + anno.flags, anno.expires); break; case annosvc.TYPE_BINARY: - annosvc.setAnnotationBinary(aURI, anno.name, anno.value, - anno.value.length, anno.mimeType, - anno.flags, anno.expires); + annosvc.setPageAnnotationBinary(aURI, anno.name, anno.value, + anno.value.length, anno.mimeType, + anno.flags, anno.expires); + break; + } + }); + }, + + /** + * Annotate a URI with a batch of annotations. + * @param aItemId + * The identifier of the item for which annotations are to be set + * @param aAnnotations + * Array of objects, each containing the following properties: + * name, flags, expires, type, mimeType (only used for binary + * annotations) value. + */ + setAnnotationsForItem: function PU_setAnnotationsForItem(aItemId, aAnnos) { + var annosvc = this.annotations; + aAnnos.forEach(function(anno) { + switch (anno.type) { + case annosvc.TYPE_INT32: + annosvc.setItemAnnotationInt32(aItemId, anno.name, anno.value, + anno.flags, anno.expires); + break; + case annosvc.TYPE_INT64: + annosvc.setItemAnnotationInt64(aItemId, anno.name, anno.value, + anno.flags, anno.expires); + break; + case annosvc.TYPE_DOUBLE: + annosvc.setItemAnnotationDouble(aItemId, anno.name, anno.value, + anno.flags, anno.expires); + break; + case annosvc.TYPE_STRING: + annosvc.setItemAnnotationString(aItemId, anno.name, anno.value, + anno.flags, anno.expires); + break; + case annosvc.TYPE_BINARY: + annosvc.setItemAnnotationBinary(aItemId, anno.name, anno.value, + anno.value.length, anno.mimeType, + anno.flags, anno.expires); break; } }); diff --git a/browser/components/places/src/nsPlacesImportExportService.cpp b/browser/components/places/src/nsPlacesImportExportService.cpp index 741df21aeb2..e3625f902d6 100644 --- a/browser/components/places/src/nsPlacesImportExportService.cpp +++ b/browser/components/places/src/nsPlacesImportExportService.cpp @@ -824,16 +824,9 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node) if (webPanel.LowerCaseEqualsLiteral("true")) { // set load-in-sidebar annotation for the bookmark - nsCOMPtr placeURI; - rv = mBookmarksService->GetItemURI(frame.mPreviousId, - getter_AddRefs(placeURI)); - NS_ASSERTION(NS_SUCCEEDED(rv), - "failed to get a place: uri for a new bookmark"); - if (NS_SUCCEEDED(rv)) { - mAnnotationService->SetAnnotationInt32(placeURI, LOAD_IN_SIDEBAR_ANNO, - 1, 0, - nsIAnnotationService::EXPIRE_NEVER); - } + mAnnotationService->SetItemAnnotationInt32(frame.mPreviousId, LOAD_IN_SIDEBAR_ANNO, + 1, 0, + nsIAnnotationService::EXPIRE_NEVER); } // FIXME bug 334408: save the last charset } @@ -1515,16 +1508,16 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem, rv = WriteFaviconAttribute(uri, aOutput); NS_ENSURE_SUCCESS(rv, rv); - // get bookmark id - PRInt64 bookmarkId; - rv = aItem->GetBookmarkId(&bookmarkId); + // get item id + PRInt64 itemId; + rv = aItem->GetItemId(&itemId); NS_ENSURE_SUCCESS(rv, rv); // write id rv = aOutput->Write(kIdAttribute, sizeof(kIdAttribute)-1, &dummy); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString id; - id.AppendInt(bookmarkId); + id.AppendInt(itemId); rv = aOutput->Write(id.get(), id.Length(), &dummy); NS_ENSURE_SUCCESS(rv, rv); rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy); @@ -1532,7 +1525,7 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem, // keyword (shortcuturl) nsAutoString keyword; - rv = mBookmarksService->GetKeywordForBookmark(bookmarkId, keyword); + rv = mBookmarksService->GetKeywordForBookmark(itemId, keyword); NS_ENSURE_SUCCESS(rv, rv); if (!keyword.IsEmpty()) { rv = aOutput->Write(kKeywordAttribute, sizeof(kKeywordAttribute)-1, &dummy); @@ -1545,15 +1538,11 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem, NS_ENSURE_SUCCESS(rv, rv); } - // get bookmark place URI for annotations - nsCOMPtr placeURI; - rv = mBookmarksService->GetItemURI(bookmarkId, getter_AddRefs(placeURI)); - NS_ENSURE_SUCCESS(rv, rv); - // Write WEB_PANEL="true" if the load-in-sidebar annotation is set for the // item PRBool loadInSidebar = PR_FALSE; - rv = mAnnotationService->HasAnnotation(placeURI, LOAD_IN_SIDEBAR_ANNO, &loadInSidebar); + rv = mAnnotationService->ItemHasAnnotation(itemId, LOAD_IN_SIDEBAR_ANNO, + &loadInSidebar); NS_ENSURE_SUCCESS(rv, rv); if (loadInSidebar) aOutput->Write(kWebPanelAttribute, sizeof(kWebPanelAttribute)-1, &dummy); diff --git a/browser/components/places/tests/unit/test_bookmarks_html.js b/browser/components/places/tests/unit/test_bookmarks_html.js index dc1bf13c8f9..62095729504 100644 --- a/browser/components/places/tests/unit/test_bookmarks_html.js +++ b/browser/components/places/tests/unit/test_bookmarks_html.js @@ -142,7 +142,7 @@ function testCanonicalBookmarks(aFolder) { // title do_check_eq("test post keyword", testBookmark1.title); // keyword - do_check_eq("test", bmsvc.getKeywordForBookmark(testBookmark1.bookmarkId)); + do_check_eq("test", bmsvc.getKeywordForBookmark(testBookmark1.itemId)); // sidebar // add date // last modified diff --git a/toolkit/components/places/public/nsIAnnotationService.idl b/toolkit/components/places/public/nsIAnnotationService.idl index bf8d9981ad3..e0ab7b14d58 100644 --- a/toolkit/components/places/public/nsIAnnotationService.idl +++ b/toolkit/components/places/public/nsIAnnotationService.idl @@ -38,34 +38,29 @@ #include "nsISupports.idl" -%{C++ -#include "nsTArray.h" -#include "nsCOMArray.h" -%} - interface nsIURI; interface nsIVariant; -[ptr] native URIArray(nsCOMArray); - -[scriptable, uuid(d41c9510-2377-4728-b275-bdad6a0521f8)] +[scriptable, uuid(63fe98e0-6889-4c2c-ac9f-703e4bc25027)] interface nsIAnnotationObserver : nsISupports { /** * Called when an annotation value is set. It could be a new annotation, * or it could be a new value for an existing annotation. */ - void onAnnotationSet(in nsIURI aURI, in AUTF8String aName); + void onPageAnnotationSet(in nsIURI aPage, in AUTF8String aName); + void onItemAnnotationSet(in long long aItemId, in AUTF8String aName); /** * Called when an annotation is deleted. If aName is empty, then ALL * annotations for the given URI have been deleted. This is not called when * annotations are expired (normally happens when the app exits). */ - void onAnnotationRemoved(in nsIURI aURI, in AUTF8String aName); + void onPageAnnotationRemoved(in nsIURI aURI, in AUTF8String aName); + void onItemAnnotationRemoved(in long long aItemId, in AUTF8String aName); }; -[scriptable, uuid(15999472-f158-11db-8314-0800200c9a66)] +[scriptable, uuid(1e2f77a8-7923-4c3d-9100-965687740acd)] interface nsIAnnotationService : nsISupports { /** @@ -80,31 +75,31 @@ interface nsIAnnotationService : nsISupports expiration policy. May be changed. Currently, use 0 for expiration. */ // For temporary stuff that can be discarded when the user exists - const PRInt32 EXPIRE_SESSION = 0; + const unsigned short EXPIRE_SESSION = 0; // for short-lived temporary data that you still want to outlast a session - const PRInt32 EXPIRE_DAYS = 1; + const unsigned short EXPIRE_DAYS = 1; // for general page settings, things the user is interested in seeing // if they come back to this page some time in the future. - const PRInt32 EXPIRE_WEEKS = 2; + const unsigned short EXPIRE_WEEKS = 2; // Something that the user will be interested in seeing in their // history like favicons. If they haven't visited a page in a couple // of months, they probably aren't interested in much other annotation, // the positions of things, or other stuff you create, so put that in // the weeks policy. - const PRInt32 EXPIRE_MONTHS = 3; + const unsigned short EXPIRE_MONTHS = 3; // For small, user-entered data like notes that should never expire. - const PRInt32 EXPIRE_NEVER = 4; + const unsigned short EXPIRE_NEVER = 4; // type constants - const PRInt32 TYPE_INT32 = 1; - const PRInt32 TYPE_DOUBLE = 2; - const PRInt32 TYPE_STRING = 3; - const PRInt32 TYPE_BINARY = 4; - const PRInt32 TYPE_INT64 = 5; + const unsigned short TYPE_INT32 = 1; + const unsigned short TYPE_DOUBLE = 2; + const unsigned short TYPE_STRING = 3; + const unsigned short TYPE_BINARY = 4; + const unsigned short TYPE_INT64 = 5; /** * Sets an annotation, overwriting any previous annotation with the same @@ -133,42 +128,61 @@ interface nsIAnnotationService : nsISupports * service, but are special cased in the protocol handler so they look like * annotations. Do not set favicons using this service, it will not work. */ - void setAnnotationString(in nsIURI aURI, in AUTF8String aName, - in AString aValue, in PRInt32 aFlags, - in PRInt32 aExpiration); + void setPageAnnotationString(in nsIURI aURI, in AUTF8String aName, + in AString aValue, in long aFlags, + in unsigned short aExpiration); + void setItemAnnotationString(in long long aItemId, in AUTF8String aName, + in AString aValue, in long aFlags, + in unsigned short aExpiration); /** * Sets an annotation just like setAnnotationString, but takes an Int32 as * input. */ - void setAnnotationInt32(in nsIURI aURI, in AUTF8String aName, - in PRInt32 aValue, in PRInt32 aFlags, - in PRInt32 aExpiration); + void setPageAnnotationInt32(in nsIURI aURI, in AUTF8String aName, + in long aValue, in long aFlags, + in unsigned short aExpiration); + void setItemAnnotationInt32(in long long aItemId, in AUTF8String aName, + in long aValue, in long aFlags, + in unsigned short aExpiration); /** * Sets an annotation just like setAnnotationString, but takes an Int64 as * input. */ - void setAnnotationInt64(in nsIURI aURI, in AUTF8String aName, - in PRInt64 aValue, in PRInt32 aFlags, - in PRInt32 aExpiration); + void setPageAnnotationInt64(in nsIURI aURI, in AUTF8String aName, + in long long aValue, in long aFlags, + in unsigned short aExpiration); + void setItemAnnotationInt64(in long long aItemId, in AUTF8String aName, + in long long aValue, in long aFlags, + in unsigned short aExpiration); /** * Sets an annotation just like setAnnotationString, but takes a double as * input. */ - void setAnnotationDouble(in nsIURI aURI, in AUTF8String aName, - in double aValue, in PRInt32 aFlags, - in PRInt32 aExpiration); - + void setPageAnnotationDouble(in nsIURI aURI, in AUTF8String aName, + in double aValue, in long aFlags, + in unsigned short aExpiration); + void setItemAnnotationDouble(in long long aItemId, in AUTF8String aName, + in double aValue, in long aFlags, + in unsigned short aExpiration); /* * Sets an annotation just like setAnnotationString, but takes binary data * as input. You MUST supply a valid MIME type. */ - void setAnnotationBinary(in nsIURI aURI, in AUTF8String aName, - [const,array,size_is(aDataLen)] in octet aData, - in PRUint32 aDataLen, in AUTF8String aMimeType, - in PRInt32 aFlags, in PRInt32 aExpiration); + void setPageAnnotationBinary(in nsIURI aURI, in AUTF8String aName, + [const,array,size_is(aDataLen)] in octet aData, + in unsigned long aDataLen, + in AUTF8String aMimeType, + in long aFlags, + in unsigned short aExpiration); + void setItemAnnotationBinary(in long long aItemId, in AUTF8String aName, + [const,array,size_is(aDataLen)] in octet aData, + in unsigned long aDataLen, + in AUTF8String aMimeType, + in long aFlags, + in unsigned short aExpiration); /** * Retrieves the string value of a given annotation. Throws an error if the @@ -178,7 +192,8 @@ interface nsIAnnotationService : nsISupports * and errors will not be thrown in this case. (For example, doubles will * lose precision when stringified.) */ - AString getAnnotationString(in nsIURI aURI, in AUTF8String aName); + AString getPageAnnotationString(in nsIURI aURI, in AUTF8String aName); + AString getItemAnnotationString(in long long aItemId, in AUTF8String aName); /** * Same as getAnnotationString but for ints. If the value doesn't look like @@ -186,7 +201,8 @@ interface nsIAnnotationService : nsISupports * int when there is not one, it will possibly change in the future if we * start caching stuff). */ - PRInt32 getAnnotationInt32(in nsIURI aURI, in AUTF8String aName); + long getPageAnnotationInt32(in nsIURI aURI, in AUTF8String aName); + long getItemAnnotationInt32(in long long aItemId, in AUTF8String aName); /** * Same as getAnnotationString for Int64s. If the value doesn't look like @@ -194,7 +210,8 @@ interface nsIAnnotationService : nsISupports * int when there is not one, it will possibly change in the future if we * start caching stuff). */ - PRInt64 getAnnotationInt64(in nsIURI aURI, in AUTF8String aName); + long long getPageAnnotationInt64(in nsIURI aURI, in AUTF8String aName); + long long getItemAnnotationInt64(in long long aItemId, in AUTF8String aName); /** * Same as getAnnotationString but returns a double-precision float. If the @@ -202,16 +219,21 @@ interface nsIAnnotationService : nsISupports * behavior when asking for an number when there is not one, it will * possibly change in the future if we start caching stuff). */ - double getAnnotationDouble(in nsIURI aURI, in AUTF8String aName); + double getPageAnnotationDouble(in nsIURI aURI, in AUTF8String aName); + double getItemAnnotationDouble(in long long aItemId, in AUTF8String aName); /** * Same as getAnnotationString but for binary data. This also returns the * MIME type. */ - void getAnnotationBinary(in nsIURI aURI, in AUTF8String aName, + void getPageAnnotationBinary(in nsIURI aURI, in AUTF8String aName, [array,size_is(aDataLen)] out octet aData, - out PRUint32 aDataLen, + out unsigned long aDataLen, out AUTF8String aMimeType); + void getItemAnnotationBinary(in long long aItemId, in AUTF8String aName, + [array,size_is(aDataLen)] out octet aData, + out unsigned long aDataLen, + out AUTF8String aMimeType); /** * Retrieves info about an existing annotation. aMimeType will be empty @@ -224,9 +246,14 @@ interface nsIAnnotationService : nsISupports * annotator.getAnnotationInfo(myURI, "foo", flags, exp, mimeType); * // now you can use 'exp.value' and 'flags.value' */ - void getAnnotationInfo(in nsIURI aURI, in AUTF8String aName, - out PRInt32 aFlags, out PRInt32 aExpiration, - out AUTF8String aMimeType, out PRInt32 aType); + void getPageAnnotationInfo(in nsIURI aURI, in AUTF8String aName, + out PRInt32 aFlags, out unsigned short aExpiration, + out AUTF8String aMimeType, + out unsigned short aType); + void getItemAnnotationInfo(in long long aItemId, in AUTF8String aName, + out long aFlags, out unsigned short aExpiration, + out AUTF8String aMimeType, + out unsigned short aType); /** * Retrieves the type of an existing annotation @@ -239,62 +266,65 @@ interface nsIAnnotationService : nsISupports * @return one of the TYPE_* constants above * @throws if the annotation is not set */ - PRInt32 getAnnotationType(in nsIURI aURI, in AUTF8String aName); + PRUint16 getPageAnnotationType(in nsIURI aURI, in AUTF8String aName); + PRUint16 getItemAnnotationType(in long long aItemId, in AUTF8String aName); /** * Returns a list of all URIs having a given annotation. */ void getPagesWithAnnotation(in AUTF8String name, - out PRUint32 resultCount, + out unsigned long resultCount, [retval, array, size_is(resultCount)] out nsIURI results); - - /** - * COMArray version of getPagesWithAnnotation for easier memory - * management from C++ code; - */ - [noscript] void GetPagesWithAnnotationCOMArray(in AUTF8String aName, - in URIArray aResults); + void getItemsWithAnnotation(in AUTF8String name, + out unsigned long resultCount, + [retval, array, size_is(resultCount)] out long long results); /** * Get the names of all annotations for this URI. * * example JS: * var annotations = annotator.getPageAnnotations(myURI, {}); - * You probably don't want to use this from C++, use - * GetPageAnnotationsTArray instead. */ - void getPageAnnotationNames(in nsIURI aURI, out PRUint32 count, + void getPageAnnotationNames(in nsIURI aURI, out unsigned long count, + [retval, array, size_is(count)] out nsIVariant result); + void getItemAnnotationNames(in long long aItemId, out unsigned long count, [retval, array, size_is(count)] out nsIVariant result); /** * Test for annotation existance. */ - boolean hasAnnotation(in nsIURI aURI, in AUTF8String aName); + boolean pageHasAnnotation(in nsIURI aURI, in AUTF8String aName); + boolean itemHasAnnotation(in long long aItemId, in AUTF8String aName); /** * Removes a specific annotation. Succeeds even if the annotation is * not found. */ - void removeAnnotation(in nsIURI aURI, in AUTF8String aName); + void removePageAnnotation(in nsIURI aURI, in AUTF8String aName); + void removeItemAnnotation(in long long aItemId, in AUTF8String aName); /** - * Removes all annotations for the given page. + * Removes all annotations for the given page/item. * We may want some other similar functions to get annotations with given * flags (once we have flags defined). */ void removePageAnnotations(in nsIURI aURI); + void removeItemAnnotations(in long long aItemId); /** - * Copies all annotations from the source to the destination URI. If the - * destination already has an annotation with the same name as one on the - * source, it will be overwritten if aOverwriteDest is set. Otherwise, + * Copies all annotations from the source to the destination URI/item. If + * the destination already has an annotation with the same name as one on + * the source, it will be overwritten if aOverwriteDest is set. Otherwise, * the destination URIs will be preferred. * * All the source annotations will stay as-is. If you don't want them * any more, use removePageAnnotations on that URI. */ - void copyAnnotations(in nsIURI aSourceURI, in nsIURI aDestURI, - in boolean aOverwriteDest); + void copyPageAnnotations(in nsIURI aSourceURI, in nsIURI aDestURI, + in boolean aOverwriteDest); + void copyItemAnnotations(in long long aSourceItemId, + in long long aDestItemId, + in boolean aOverwriteDest); /** * Adds an annotation observer. The annotation service will keep an owning diff --git a/toolkit/components/places/public/nsINavBookmarksService.idl b/toolkit/components/places/public/nsINavBookmarksService.idl index 95efe51d8a3..f384aa56538 100644 --- a/toolkit/components/places/public/nsINavBookmarksService.idl +++ b/toolkit/components/places/public/nsINavBookmarksService.idl @@ -54,7 +54,7 @@ interface nsITransaction; * Observer for bookmark changes. */ -[scriptable, uuid(860d786d-9bba-4011-a396-486a87af8f07)] +[scriptable, uuid(582af67b-cde2-4dc2-9ef5-9eb79e224135)] interface nsINavBookmarkObserver : nsISupports { /** @@ -75,42 +75,52 @@ interface nsINavBookmarkObserver : nsISupports * add took place. The rest of the bookmarks will be shifted down, but no * additional notifications will be sent. * - * @param bookmarkId The id of the bookmark that was added. - * @param bookmark The URI that was bookmarked. - * @param folder The folder that the item was added to. - * @param index The item's index in the folder. + * @param aBookmarkId + * The id of the bookmark that was added. + * @param aFolder + * The folder that the item was added to. + * @param aIndex + * The item's index in the folder. */ - void onItemAdded(in PRInt64 bookmarkId, in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); + void onItemAdded(in long long aBookmarkId, in long long aFolder, + in long aIndex); /** * Notify this observer that the bookmark was removed. Called after the * actual remove took place. The bookmarks following the index will be * shifted up, but no additional notifications will be sent. * - * @param bookmarkId The id of the bookmark that was removed. - * @param bookmark The URI of the bookmark that will be removed. - * @param folder The folder that the item was removed from. - * @param index The bookmark's index in the folder. + * @param aBookmarkId + * The id of the bookmark that was removed. + * @param aFolder + * The folder that the item was removed from. + * @param aIndex + * The bookmark's index in the folder. */ - void onItemRemoved(in PRInt64 bookmarkId, in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); + void onItemRemoved(in long long aBookmarkId, in long long aFolder, + in long aIndex); /** * Notify this observer that a bookmark's information has changed. This * will be called whenever any attributes like "title" are changed. * - * @param bookmarkId The id of the bookmark that was changed. - * @param bookmark The URI of the bookmark which changed. - * @param property The property which changed. + * @param aBookmarkId + * The id of the bookmark that was changed. + * @param aProperty + * The property which changed. + * @param aIsAnnotationProperty + * Is aProperty the name of an item annotation * * property = "cleartime": (history was deleted, there is no last visit date): * value = none * property = "title": value = new title * property = "favicon": value = new "moz-anno" URL of favicon image - * property = "uri": value = empty, get the value of the changed bookmark URI - * from the |bookmark| parameter. + * property = "uri": value = new uri spec + * aIsAnnotationProperty = true: value = empty string */ - void onItemChanged(in PRInt64 bookmarkId, in nsIURI bookmark, in ACString property, - in AString value); + void onItemChanged(in long long aBookmarkId, in ACString aProperty, + in boolean aIsAnnotationProperty, + in AUTF8String aValue); /** * Notify that the item was visited. Normally in bookmarks we use the last @@ -118,61 +128,82 @@ interface nsINavBookmarkObserver : nsISupports * recent, but this is not guaranteed. You should check to see if it's * actually more recent before using this new time. * - * @param bookmarkId The id of the bookmark that was visited. - * @see onItemChanged properth = "cleartime" for when all visit dates are + * @param aBookmarkId + * The id of the bookmark that was visited. + * @see onItemChanged property = "cleartime" for when all visit dates are * deleted for the URI. */ - void onItemVisited(in PRInt64 bookmarkId, in nsIURI bookmark, in PRInt64 aVisitID, in PRTime time); + void onItemVisited(in long long aBookmarkId, in long long aVisitID, + in PRTime time); /** * Notify this observer that a bookmark folder has been added. - * @param folder The id of the folder that was added. - * @param parent The id of the folder's parent. - * @param index The folder's index inside its parent. + * @param aFolder + * The id of the folder that was added. + * @param aParent + * The id of the folder's parent. + * @param aIndex + * The folder's index inside its parent. */ - void onFolderAdded(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); + void onFolderAdded(in long long aFolder, in long long aParent, + in long aIndex); /** * Notify this observer that a bookmark folder has been removed. - * @param folder The id of the folder that was removed. - * @param parent The id of the folder's old parent. - * @param index The folder's old index in its parent. + * @param aFolder + * The id of the folder that was removed. + * @param aParent + * The id of the folder's old parent. + * @param aIndex + * The folder's old index in its parent. */ - void onFolderRemoved(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); + void onFolderRemoved(in long long aFolder, in long long aParent, + in long aIndex); /** * Notify this observer that a bookmark folder has been moved. - * @param folder The id of the folder that was moved. - * @param oldParent The id of the folder's old parent. - * @param oldIndex The folder's old index inside oldParent. - * @param newParent The id of the folder's new parent. - * @param newIndex The folder's index inside newParent. + * @param aFolder + * The id of the folder that was moved. + * @param aOldParent + * The id of the folder's old parent. + * @param aOldIndex + * The folder's old index inside oldParent. + * @param aNewParent + * The id of the folder's new parent. + * @param aNewIndex + * The folder's index inside newParent. */ - void onFolderMoved(in PRInt64 folder, - in PRInt64 oldParent, in PRInt32 oldIndex, - in PRInt64 newParent, in PRInt32 newIndex); + void onFolderMoved(in long long aFolder, + in long long aOldParent, in long aOldIndex, + in long long aNewParent, in long aNewIndex); /** * Notify this observer that a bookmark folder's information has changed. * This will be called whenever any attributes like "title" are changed. - * @param folder The id of the folder that was changed. - * @param property The property that was changed. + * @param aFolder + * The id of the folder that was changed. + * @param aProperty + * The property that was changed. */ - void onFolderChanged(in PRInt64 folder, in ACString property); + void onFolderChanged(in long long aFolder, in ACString aProperty); /** * Notify this observer that a separator has been added. - * @param parent The id of the separator's parent. - * @param index The separator's index inside its parent. + * @param aParent + * The id of the separator's parent. + * @param aIndex + * The separator's index inside its parent. */ - void onSeparatorAdded(in PRInt64 parent, in PRInt32 index); + void onSeparatorAdded(in long long aParent, in long aIndex); /** * Notify this observer that a separator has been removed. - * @param parent The id of the separator's parent. - * @param index The separator's old index in its parent. + * @param aParent + * The id of the separator's parent. + * @param aIndex + * The separator's old index in its parent. */ - void onSeparatorRemoved(in PRInt64 parent, in PRInt32 index); + void onSeparatorRemoved(in long long aParent, in long aIndex); }; /** diff --git a/toolkit/components/places/public/nsINavHistoryService.idl b/toolkit/components/places/public/nsINavHistoryService.idl index fe5051cda43..8c43029e22a 100644 --- a/toolkit/components/places/public/nsINavHistoryService.idl +++ b/toolkit/components/places/public/nsINavHistoryService.idl @@ -50,7 +50,7 @@ interface nsINavHistoryResult; interface nsITreeColumn; interface nsIWritablePropertyBag; -[scriptable, uuid(b21008ef-995d-4bd9-97ae-1f23868930ed)] +[scriptable, uuid(2cce631e-d7dd-4162-a05b-e8ecfbc34367)] interface nsINavHistoryResultNode : nsISupports { /** @@ -159,10 +159,11 @@ interface nsINavHistoryResultNode : nsISupports readonly attribute PRInt32 bookmarkIndex; /** - * If the node is a bookmark, this value is the row ID of that bookmark - * in the database. For items not in a bookmark folder, this value is -1. + * If the node is an item (bookmark, folder or a separator) this value is the + * row ID of that bookmark in the database. For other nodes, this value is + * set to -1. */ - readonly attribute PRInt64 bookmarkId; + readonly attribute PRInt64 itemId; }; diff --git a/toolkit/components/places/src/nsAnnoProtocolHandler.cpp b/toolkit/components/places/src/nsAnnoProtocolHandler.cpp index 7264b391228..dc6e743c804 100644 --- a/toolkit/components/places/src/nsAnnoProtocolHandler.cpp +++ b/toolkit/components/places/src/nsAnnoProtocolHandler.cpp @@ -157,8 +157,8 @@ nsAnnoProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval) } } else { // normal handling for annotations - rv = annotationService->GetAnnotationBinary(annoURI, annoName, &data, - &dataLen, mimeType); + rv = annotationService->GetPageAnnotationBinary(annoURI, annoName, &data, + &dataLen, mimeType); NS_ENSURE_SUCCESS(rv, rv); // disallow annotations with no MIME types diff --git a/toolkit/components/places/src/nsAnnotationService.cpp b/toolkit/components/places/src/nsAnnotationService.cpp index 5d1bc45185f..60d1451f6e9 100644 --- a/toolkit/components/places/src/nsAnnotationService.cpp +++ b/toolkit/components/places/src/nsAnnotationService.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Brett Wilson (original author) + * Asaf Romano * * 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 @@ -50,7 +51,7 @@ #include "nsVariant.h" const PRInt32 nsAnnotationService::kAnnoIndex_ID = 0; -const PRInt32 nsAnnotationService::kAnnoIndex_Page = 1; +const PRInt32 nsAnnotationService::kAnnoIndex_PageOrItem = 1; const PRInt32 nsAnnotationService::kAnnoIndex_Name = 2; const PRInt32 nsAnnotationService::kAnnoIndex_MimeType = 3; const PRInt32 nsAnnotationService::kAnnoIndex_Content = 4; @@ -109,6 +110,14 @@ nsAnnotationService::Init() getter_AddRefs(mDBSetAnnotation)); NS_ENSURE_SUCCESS(rv, rv); + // mDBSetItemAnnotation + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "UPDATE moz_items_annos " + "SET mime_type = ?4, content = ?5, flags = ?6, expiration = ?7, type = ?8 " + "WHERE id = ?1"), + getter_AddRefs(mDBSetItemAnnotation)); + NS_ENSURE_SUCCESS(rv, rv); + // mDBGetAnnotation rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT * " @@ -118,6 +127,15 @@ nsAnnotationService::Init() getter_AddRefs(mDBGetAnnotation)); NS_ENSURE_SUCCESS(rv, rv); + // mDBGetItemAnnotation + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * " + "FROM moz_items_annos " + "WHERE item_id = ?1 AND anno_attribute_id = " + "(SELECT id FROM moz_anno_attributes WHERE name = ?2)"), + getter_AddRefs(mDBGetItemAnnotation)); + NS_ENSURE_SUCCESS(rv, rv); + // mDBGetAnnotationNames rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT n.name " @@ -126,6 +144,14 @@ nsAnnotationService::Init() getter_AddRefs(mDBGetAnnotationNames)); NS_ENSURE_SUCCESS(rv, rv); + // mDBGetItemAnnotationNames + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT n.name " + "FROM moz_items_annos a LEFT JOIN moz_anno_attributes n ON a.anno_attribute_id = n.id " + "WHERE a.item_id = ?1"), + getter_AddRefs(mDBGetItemAnnotationNames)); + NS_ENSURE_SUCCESS(rv, rv); + // mDBGetAnnotationFromURI rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT a.id, a.place_id, ?2, a.mime_type, a.content, a.flags, " @@ -136,6 +162,16 @@ nsAnnotationService::Init() getter_AddRefs(mDBGetAnnotationFromURI)); NS_ENSURE_SUCCESS(rv, rv); + // mDBGetAnnotationFromItemId + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT a.id, a.item_id, ?2, a.mime_type, a.content, a.flags, " + "a.expiration, a.type " + "FROM moz_items_annos a " + "WHERE a.item_id = ?1 AND a.anno_attribute_id = " + "(SELECT id FROM moz_anno_attributes WHERE name = ?2)"), + getter_AddRefs(mDBGetAnnotationFromItemId)); + NS_ENSURE_SUCCESS(rv, rv); + // mDBGetAnnotationNameID rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT id FROM moz_anno_attributes WHERE name = ?1"), @@ -157,6 +193,15 @@ nsAnnotationService::Init() getter_AddRefs(mDBAddAnnotation)); NS_ENSURE_SUCCESS(rv, rv); + // mDBAddItemAnnotation + // Note: kAnnoIndex_Name here is a name ID and not a string like the getters + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO moz_items_annos " + "(item_id, anno_attribute_id, mime_type, content, flags, expiration, type) " + "VALUES (?2, ?3, ?4, ?5, ?6, ?7, ?8)"), + getter_AddRefs(mDBAddItemAnnotation)); + NS_ENSURE_SUCCESS(rv, rv); + // mDBRemoveAnnotation rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( "DELETE FROM moz_annos WHERE place_id = ?1 AND anno_attribute_id = " @@ -164,6 +209,13 @@ nsAnnotationService::Init() getter_AddRefs(mDBRemoveAnnotation)); NS_ENSURE_SUCCESS(rv, rv); + // mDBRemoveItemAnnotation + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "DELETE FROM moz_items_annos WHERE item_id = ?1 AND anno_attribute_id = " + "(SELECT id FROM moz_anno_attributes WHERE name = ?2)"), + getter_AddRefs(mDBRemoveItemAnnotation)); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -215,22 +267,46 @@ nsAnnotationService::InitTables(mozIStorageConnection* aDBConn) NS_ENSURE_SUCCESS(rv, rv); } + rv = aDBConn->TableExists(NS_LITERAL_CSTRING("moz_items_annos"), &exists); + NS_ENSURE_SUCCESS(rv, rv); + if (! exists) { + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_items_annos (" + "id INTEGER PRIMARY KEY," + "item_id INTEGER NOT NULL," + "anno_attribute_id INTEGER," + "mime_type VARCHAR(32) DEFAULT NULL," + "content LONGVARCHAR, flags INTEGER DEFAULT 0," + "expiration INTEGER DEFAULT 0, " + "type INTEGER DEFAULT 0)")); + NS_ENSURE_SUCCESS(rv, rv); + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX moz_annos_item_idindex ON moz_items_annos (item_id)")); + NS_ENSURE_SUCCESS(rv, rv); + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE INDEX moz_items_annos_attributesindex ON moz_items_annos (anno_attribute_id)")); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; } -// nsAnnotationService::SetAnnotationString +// nsAnnotationService::SetAnnotationStringInternal -NS_IMETHODIMP -nsAnnotationService::SetAnnotationString(nsIURI* aURI, - const nsACString& aName, - const nsAString& aValue, - PRInt32 aFlags, PRInt32 aExpiration) +nsresult +nsAnnotationService::SetAnnotationStringInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + const nsAString& aValue, + PRInt32 aFlags, + PRUint16 aExpiration) { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, - nsIAnnotationService::TYPE_STRING, &statement); + nsresult rv = StartSetAnnotation(aFkId, aIsItemAnnotation, aName, aFlags, + aExpiration, + nsIAnnotationService::TYPE_STRING, + &statement); NS_ENSURE_SUCCESS(rv, rv); mozStorageStatementScoper statementResetter(statement); @@ -247,22 +323,62 @@ nsAnnotationService::SetAnnotationString(nsIURI* aURI, // annotation values! statement->Reset(); statementResetter.Abandon(); - CallSetObservers(aURI, aName); + return NS_OK; +} + +// nsAnnotationService::SetPageAnnotationString + +NS_IMETHODIMP +nsAnnotationService::SetPageAnnotationString(nsIURI* aURI, + const nsACString& aName, + const nsAString& aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetAnnotationStringInternal(placeId, PR_FALSE, aName, aValue, aFlags, + aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForPageObservers(aURI, aName); return NS_OK; } -// nsAnnotationService::SetAnnotationInt32 +// nsAnnotationService::SetItemAnnotationString NS_IMETHODIMP -nsAnnotationService::SetAnnotationInt32(nsIURI* aURI, - const nsACString& aName, - PRInt32 aValue, - PRInt32 aFlags, PRInt32 aExpiration) +nsAnnotationService::SetItemAnnotationString(PRInt64 aItemId, + const nsACString& aName, + const nsAString& aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + nsresult rv = SetAnnotationStringInternal(aItemId, PR_TRUE, aName, aValue, + aFlags, aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForItemObservers(aItemId, aName); + return NS_OK; +} + +// nsAnnotationService::SetAnnotationInt32Internal + +nsresult +nsAnnotationService::SetAnnotationInt32Internal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + PRInt32 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsresult rv = StartSetAnnotation(aFkId, aIsItemAnnotation, aName, aFlags, + aExpiration, nsIAnnotationService::TYPE_INT32, &statement); NS_ENSURE_SUCCESS(rv, rv); @@ -281,22 +397,61 @@ nsAnnotationService::SetAnnotationInt32(nsIURI* aURI, // annotation values! statement->Reset(); statementResetter.Abandon(); - CallSetObservers(aURI, aName); return NS_OK; } - -// nsAnnotationService::SetAnnotationInt64 +// nsAnnotationService::SetPageAnnotationInt32 NS_IMETHODIMP -nsAnnotationService::SetAnnotationInt64(nsIURI* aURI, - const nsACString& aName, - PRInt64 aValue, - PRInt32 aFlags, PRInt32 aExpiration) +nsAnnotationService::SetPageAnnotationInt32(nsIURI* aURI, + const nsACString& aName, + PRInt32 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetAnnotationInt32Internal(placeId, PR_FALSE, aName, aValue, aFlags, + aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForPageObservers(aURI, aName); + return NS_OK; +} + +// nsAnnotationService::SetItemAnnotationInt32 + +NS_IMETHODIMP +nsAnnotationService::SetItemAnnotationInt32(PRInt64 aItemId, + const nsACString& aName, + PRInt32 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + nsresult rv = SetAnnotationInt32Internal(aItemId, PR_TRUE, aName, aValue, + aFlags, aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForItemObservers(aItemId, aName); + return NS_OK; +} + +// nsAnnotationService::SetAnnotationInt64Internal + +nsresult +nsAnnotationService::SetAnnotationInt64Internal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + PRInt64 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsresult rv = StartSetAnnotation(aFkId, aIsItemAnnotation, aName, aFlags, + aExpiration, nsIAnnotationService::TYPE_INT64, &statement); NS_ENSURE_SUCCESS(rv, rv); @@ -315,22 +470,61 @@ nsAnnotationService::SetAnnotationInt64(nsIURI* aURI, // annotation values! statement->Reset(); statementResetter.Abandon(); - CallSetObservers(aURI, aName); return NS_OK; } - -// nsAnnotationService::SetAnnotationDouble +// nsAnnotationService::SetPageAnnotationInt64 NS_IMETHODIMP -nsAnnotationService::SetAnnotationDouble(nsIURI* aURI, - const nsACString& aName, - double aValue, - PRInt32 aFlags, PRInt32 aExpiration) +nsAnnotationService::SetPageAnnotationInt64(nsIURI* aURI, + const nsACString& aName, + PRInt64 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetAnnotationInt64Internal(placeId, PR_FALSE, aName, aValue, aFlags, + aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForPageObservers(aURI, aName); + return NS_OK; +} + +// nsAnnotationService::SetItemAnnotationInt64 + +NS_IMETHODIMP +nsAnnotationService::SetItemAnnotationInt64(PRInt64 aItemId, + const nsACString& aName, + PRInt64 aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + nsresult rv = SetAnnotationInt64Internal(aItemId, PR_TRUE, aName, aValue, + aFlags, aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForItemObservers(aItemId, aName); + return NS_OK; +} + +// nsAnnotationService::SetAnnotationDoubleInternal + +nsresult +nsAnnotationService::SetAnnotationDoubleInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + double aValue, + PRInt32 aFlags, + PRUint16 aExpiration) { mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsresult rv = StartSetAnnotation(aFkId, aIsItemAnnotation, aName, aFlags, + aExpiration, nsIAnnotationService::TYPE_DOUBLE, &statement); NS_ENSURE_SUCCESS(rv, rv); @@ -349,27 +543,66 @@ nsAnnotationService::SetAnnotationDouble(nsIURI* aURI, // annotation values! statement->Reset(); statementResetter.Abandon(); - CallSetObservers(aURI, aName); return NS_OK; } - -// nsAnnotationService::SetAnnotationBinary +// nsAnnotationService::SetPageAnnotationDouble NS_IMETHODIMP -nsAnnotationService::SetAnnotationBinary(nsIURI* aURI, - const nsACString& aName, - const PRUint8 *aData, - PRUint32 aDataLen, - const nsACString& aMimeType, - PRInt32 aFlags, PRInt32 aExpiration) +nsAnnotationService::SetPageAnnotationDouble(nsIURI* aURI, + const nsACString& aName, + double aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetAnnotationDoubleInternal(placeId, PR_FALSE, aName, aValue, aFlags, + aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForPageObservers(aURI, aName); + return NS_OK; +} + +// nsAnnotationService::SetItemAnnotationDouble + +NS_IMETHODIMP +nsAnnotationService::SetItemAnnotationDouble(PRInt64 aItemId, + const nsACString& aName, + double aValue, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + nsresult rv = SetAnnotationDoubleInternal(aItemId, PR_TRUE, aName, aValue, + aFlags, aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + + CallSetForItemObservers(aItemId, aName); + return NS_OK; +} + +// nsAnnotationService::SetAnnotationBinaryInternal + +nsresult +nsAnnotationService::SetAnnotationBinaryInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + const PRUint8 *aData, + PRUint32 aDataLen, + const nsACString& aMimeType, + PRInt32 aFlags, + PRUint16 aExpiration) { if (aMimeType.Length() == 0) return NS_ERROR_INVALID_ARG; mozStorageTransaction transaction(mDBConn, PR_FALSE); mozIStorageStatement* statement; // class var, not owned by this function - nsresult rv = StartSetAnnotation(aURI, aName, aFlags, aExpiration, + nsresult rv = StartSetAnnotation(aFkId, aIsItemAnnotation, aName, aFlags, + aExpiration, nsIAnnotationService::TYPE_BINARY, &statement); NS_ENSURE_SUCCESS(rv, rv); @@ -388,67 +621,160 @@ nsAnnotationService::SetAnnotationBinary(nsIURI* aURI, // annotation values! statement->Reset(); statementResetter.Abandon(); - CallSetObservers(aURI, aName); return NS_OK; } - -// nsAnnotationService::GetAnnotationString +// nsAnnotationService::SetAnnotationBinary NS_IMETHODIMP -nsAnnotationService::GetAnnotationString(nsIURI* aURI, - const nsACString& aName, - nsAString& _retval) +nsAnnotationService::SetPageAnnotationBinary(nsIURI* aURI, + const nsACString& aName, + const PRUint8 *aData, + PRUint32 aDataLen, + const nsACString& aMimeType, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetAnnotationBinaryInternal(placeId, PR_FALSE, aName, aData, aDataLen, + aMimeType, aFlags, aExpiration); + CallSetForPageObservers(aURI, aName); + return NS_OK; +} + +// nsAnnotationService::SetItemAnnotationBinary + +NS_IMETHODIMP +nsAnnotationService::SetItemAnnotationBinary(PRInt64 aItemId, + const nsACString& aName, + const PRUint8 *aData, + PRUint32 aDataLen, + const nsACString& aMimeType, + PRInt32 aFlags, + PRUint16 aExpiration) +{ + nsresult rv = SetAnnotationBinaryInternal(aItemId, PR_TRUE, aName, aData, + aDataLen, aMimeType, aFlags, + aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + CallSetForItemObservers(aItemId, aName); + return NS_OK; +} + +#define ENSURE_ANNO_TYPE(aType, aStatement) \ + PRInt32 type = aStatement->AsInt32(kAnnoIndex_Type); \ + if (type != nsIAnnotationService::aType) { \ + aStatement->Reset(); \ + return NS_ERROR_INVALID_ARG; \ + } + + +// nsAnnotationService::GetPageAnnotationString + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationString(nsIURI* aURI, + const nsACString& aName, + nsAString& _retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); - NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_STRING, NS_ERROR_INVALID_ARG); + ENSURE_ANNO_TYPE(TYPE_STRING, mDBGetAnnotationFromURI) rv = mDBGetAnnotationFromURI->GetString(kAnnoIndex_Content, _retval); mDBGetAnnotationFromURI->Reset(); return rv; } -// nsAnnotationService::GetAnnotationInt32 +// nsAnnotationService::GetItemAnnotationString NS_IMETHODIMP -nsAnnotationService::GetAnnotationInt32(nsIURI* aURI, +nsAnnotationService::GetItemAnnotationString(PRInt64 aItemId, + const nsACString& aName, + nsAString& _retval) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (NS_FAILED(rv)) + return rv; + ENSURE_ANNO_TYPE(TYPE_STRING, mDBGetAnnotationFromItemId) + rv = mDBGetAnnotationFromItemId->GetString(kAnnoIndex_Content, _retval); + mDBGetAnnotationFromItemId->Reset(); + return rv; +} + + +// nsAnnotationService::GetPageAnnotationInt32 + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationInt32(nsIURI* aURI, const nsACString& aName, PRInt32 *_retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); - NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_INT32, NS_ERROR_INVALID_ARG); + ENSURE_ANNO_TYPE(TYPE_INT32, mDBGetAnnotationFromURI) *_retval = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; } -// nsAnnotationService::GetAnnotationInt64 +// nsAnnotationService::GetItemAnnotationInt32 NS_IMETHODIMP -nsAnnotationService::GetAnnotationInt64(nsIURI* aURI, - const nsACString& aName, - PRInt64 *_retval) +nsAnnotationService::GetItemAnnotationInt32(PRInt64 aItemId, + const nsACString& aName, + PRInt32 *_retval) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (NS_FAILED(rv)) + return rv; + ENSURE_ANNO_TYPE(TYPE_INT32, mDBGetAnnotationFromItemId) + *_retval = mDBGetAnnotationFromItemId->AsInt32(kAnnoIndex_Content); + mDBGetAnnotationFromItemId->Reset(); + return NS_OK; +} + +// nsAnnotationService::GetPageAnnotationInt64 + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationInt64(nsIURI* aURI, + const nsACString& aName, + PRInt64 *_retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); NS_ENSURE_SUCCESS(rv, rv); - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); - NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_INT64, NS_ERROR_INVALID_ARG); + ENSURE_ANNO_TYPE(TYPE_INT64, mDBGetAnnotationFromURI) *_retval = mDBGetAnnotationFromURI->AsInt64(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; } +// nsAnnotationService::GetItemAnnotationInt64 + NS_IMETHODIMP -nsAnnotationService::GetAnnotationType(nsIURI* aURI, - const nsACString& aName, - PRInt32* _retval) +nsAnnotationService::GetItemAnnotationInt64(PRInt64 aItemId, + const nsACString& aName, + PRInt64 *_retval) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + NS_ENSURE_SUCCESS(rv, rv); + ENSURE_ANNO_TYPE(TYPE_INT64, mDBGetAnnotationFromItemId) + *_retval = mDBGetAnnotationFromItemId->AsInt64(kAnnoIndex_Content); + mDBGetAnnotationFromItemId->Reset(); + return NS_OK; +} + +// nsAnnotationService::GetPageAnnotationType + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationType(nsIURI* aURI, + const nsACString& aName, + PRUint16* _retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); NS_ENSURE_SUCCESS(rv, rv); @@ -457,37 +783,65 @@ nsAnnotationService::GetAnnotationType(nsIURI* aURI, return NS_OK; } -// nsAnnotationService::GetAnnotationDouble +// nsAnnotationService::GetItemAnnotationType NS_IMETHODIMP -nsAnnotationService::GetAnnotationDouble(nsIURI* aURI, - const nsACString& aName, - double *_retval) +nsAnnotationService::GetItemAnnotationType(PRInt64 aItemId, + const nsACString& aName, + PRUint16* _retval) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + NS_ENSURE_SUCCESS(rv, rv); + *_retval = mDBGetAnnotationFromItemId->AsInt32(kAnnoIndex_Type); + mDBGetAnnotationFromItemId->Reset(); + return NS_OK; +} + +// nsAnnotationService::GetPageAnnotationDouble + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationDouble(nsIURI* aURI, + const nsACString& aName, + double *_retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); - NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_DOUBLE, NS_ERROR_INVALID_ARG); + ENSURE_ANNO_TYPE(TYPE_DOUBLE, mDBGetAnnotationFromURI) *_retval = mDBGetAnnotationFromURI->AsDouble(kAnnoIndex_Content); mDBGetAnnotationFromURI->Reset(); return NS_OK; } - -// nsAnnotationService::GetAnnotationBinary +// nsAnnotationService::GetItemAnnotationDouble NS_IMETHODIMP -nsAnnotationService::GetAnnotationBinary(nsIURI* aURI, - const nsACString& aName, - PRUint8** aData, PRUint32* aDataLen, - nsACString& aMimeType) +nsAnnotationService::GetItemAnnotationDouble(PRInt64 aItemId, + const nsACString& aName, + double *_retval) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (NS_FAILED(rv)) + return rv; + ENSURE_ANNO_TYPE(TYPE_DOUBLE, mDBGetAnnotationFromItemId) + *_retval = mDBGetAnnotationFromItemId->AsDouble(kAnnoIndex_Content); + mDBGetAnnotationFromItemId->Reset(); + return NS_OK; +} + +// nsAnnotationService::GetPageAnnotationBinary + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationBinary(nsIURI* aURI, + const nsACString& aName, + PRUint8** aData, + PRUint32* aDataLen, + nsACString& aMimeType) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) return rv; - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); - NS_ENSURE_TRUE(type == nsIAnnotationService::TYPE_BINARY, NS_ERROR_INVALID_ARG); + ENSURE_ANNO_TYPE(TYPE_BINARY, mDBGetAnnotationFromURI) rv = mDBGetAnnotationFromURI->GetBlob(kAnnoIndex_Content, aDataLen, aData); if (NS_FAILED(rv)) { mDBGetAnnotationFromURI->Reset(); @@ -498,15 +852,38 @@ nsAnnotationService::GetAnnotationBinary(nsIURI* aURI, return rv; } - -// nsAnnotationService::GetAnnotationInfo +// nsAnnotationService::GetItemAnnotationBinary NS_IMETHODIMP -nsAnnotationService::GetAnnotationInfo(nsIURI* aURI, - const nsACString& aName, - PRInt32 *aFlags, PRInt32 *aExpiration, - nsACString& aMimeType, - PRInt32 *aStorageType) +nsAnnotationService::GetItemAnnotationBinary(PRInt64 aItemId, + const nsACString& aName, + PRUint8** aData, + PRUint32* aDataLen, + nsACString& aMimeType) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (NS_FAILED(rv)) + return rv; + ENSURE_ANNO_TYPE(TYPE_BINARY, mDBGetAnnotationFromItemId) + rv = mDBGetAnnotationFromItemId->GetBlob(kAnnoIndex_Content, aDataLen, aData); + if (NS_FAILED(rv)) { + mDBGetAnnotationFromItemId->Reset(); + return rv; + } + rv = mDBGetAnnotationFromItemId->GetUTF8String(kAnnoIndex_MimeType, aMimeType); + mDBGetAnnotationFromItemId->Reset(); + return rv; +} + +// nsAnnotationService::GetPageAnnotationInfo + +NS_IMETHODIMP +nsAnnotationService::GetPageAnnotationInfo(nsIURI* aURI, + const nsACString& aName, + PRInt32 *aFlags, + PRUint16 *aExpiration, + nsACString& aMimeType, + PRUint16 *aStorageType) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (NS_FAILED(rv)) @@ -514,10 +891,10 @@ nsAnnotationService::GetAnnotationInfo(nsIURI* aURI, mozStorageStatementScoper resetter(mDBGetAnnotationFromURI); *aFlags = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Flags); - *aExpiration = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Expiration); + *aExpiration = (PRUint16)mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Expiration); rv = mDBGetAnnotationFromURI->GetUTF8String(kAnnoIndex_MimeType, aMimeType); NS_ENSURE_SUCCESS(rv, rv); - PRInt32 type = mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); + PRInt32 type = (PRUint16)mDBGetAnnotationFromURI->AsInt32(kAnnoIndex_Type); if (type == 0) { // For annotations created before explicit typing, // we can't determine type, just return as string type. @@ -528,6 +905,35 @@ nsAnnotationService::GetAnnotationInfo(nsIURI* aURI, return rv; } +// nsAnnotationService::GetAnnotationInfo + +NS_IMETHODIMP +nsAnnotationService::GetItemAnnotationInfo(PRInt64 aItemId, + const nsACString& aName, + PRInt32 *aFlags, + PRUint16 *aExpiration, + nsACString& aMimeType, + PRUint16 *aStorageType) +{ + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (NS_FAILED(rv)) + return rv; + mozStorageStatementScoper resetter(mDBGetAnnotationFromItemId); + + *aFlags = mDBGetAnnotationFromItemId->AsInt32(kAnnoIndex_Flags); + *aExpiration = (PRUint16)mDBGetAnnotationFromItemId->AsInt32(kAnnoIndex_Expiration); + rv = mDBGetAnnotationFromItemId->GetUTF8String(kAnnoIndex_MimeType, aMimeType); + NS_ENSURE_SUCCESS(rv, rv); + PRInt32 type = (PRUint16)mDBGetAnnotationFromItemId->AsInt32(kAnnoIndex_Type); + if (type == 0) { + // For annotations created before explicit typing, + // we can't determine type, just return as string type. + *aStorageType = nsIAnnotationService::TYPE_STRING; + } else { + *aStorageType = type; + } + return rv; +} // nsAnnotationService::GetPagesWithAnnotation @@ -560,9 +966,9 @@ nsAnnotationService::GetPagesWithAnnotation(const nsACString& aName, return NS_OK; } -// nsAnnotationService::GetPagesWithAnnotationTArray +// nsAnnotationService::GetPagesWithAnnotationCOMArray -NS_IMETHODIMP +nsresult nsAnnotationService::GetPagesWithAnnotationCOMArray( const nsACString& aName, nsCOMArray* aResults){ // this probably isn't a common operation, so we don't have a precompiled @@ -597,6 +1003,62 @@ nsAnnotationService::GetPagesWithAnnotationCOMArray( return NS_OK; } + +// nsIAnnotationService::GetItemsWithAnnotation + +NS_IMETHODIMP +nsAnnotationService::GetItemsWithAnnotation(const nsACString& aName, + PRUint32* aResultCount, + PRInt64** aResults) +{ + if (aName.IsEmpty() || !aResultCount || !aResults) + return NS_ERROR_INVALID_ARG; + + *aResultCount = 0; + *aResults = nsnull; + nsTArray results; + + nsresult rv = GetItemsWithAnnotationTArray(aName, &results); + NS_ENSURE_SUCCESS(rv, rv); + + // convert to raw array + if (results.Length() == 0) + return NS_OK; + + *aResults = NS_STATIC_CAST(PRInt64*, + nsMemory::Alloc(results.Length() * sizeof(PRInt64))); + if (!aResults) + return NS_ERROR_OUT_OF_MEMORY; + + *aResultCount = results.Length(); + for (PRUint32 i = 0; i < *aResultCount; i ++) { + (*aResults)[i] = results[i]; + } + return NS_OK; +} + +nsresult +nsAnnotationService::GetItemsWithAnnotationTArray(const nsACString& aName, + nsTArray* aResults) { + nsCOMPtr statement; + nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT a.item_id FROM moz_anno_attributes n " + "LEFT JOIN moz_items_annos a ON n.id = a.anno_attribute_id " + "WHERE n.name = ?1"), + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = statement->BindUTF8StringParameter(0, aName); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(rv = statement->ExecuteStep(&hasMore)) && hasMore) { + if (!aResults->AppendElement(statement->AsInt64(0))) + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + // nsAnnotationService::GetPageAnnotationNames NS_IMETHODIMP @@ -606,8 +1068,14 @@ nsAnnotationService::GetPageAnnotationNames(nsIURI* aURI, PRUint32* aCount, *aCount = 0; *_result = nsnull; + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + if (placeId == 0) // Check if URI exists. + return NS_OK; + nsTArray names; - nsresult rv = GetPageAnnotationNamesTArray(aURI, &names); + rv = GetAnnotationNamesTArray(placeId, &names, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); if (names.Length() == 0) return NS_OK; @@ -624,7 +1092,7 @@ nsAnnotationService::GetPageAnnotationNames(nsIURI* aURI, PRUint32* aCount, NS_RELEASE((*_result)[j]); nsMemory::Free(*_result); *_result = nsnull; - return rv; + return NS_ERROR_OUT_OF_MEMORY; } var->SetAsAUTF8String(names[i]); NS_ADDREF((*_result)[i] = var); @@ -635,34 +1103,29 @@ nsAnnotationService::GetPageAnnotationNames(nsIURI* aURI, PRUint32* aCount, } -// nsAnnotationService::GetPageAnnotationNamesTArray +// nsAnnotationService::GetAnnotationNamesTArray nsresult -nsAnnotationService::GetPageAnnotationNamesTArray(nsIURI* aURI, - nsTArray* aResult) +nsAnnotationService::GetAnnotationNamesTArray(PRInt64 aFkId, + nsTArray* aResult, + PRBool aIsFkItemId) { + mozIStorageStatement* statement = aIsFkItemId ? + mDBGetItemAnnotationNames.get() : mDBGetAnnotationNames.get(); + aResult->Clear(); - nsNavHistory* history = nsNavHistory::GetHistoryService(); - NS_ENSURE_TRUE(history, NS_ERROR_FAILURE); - - PRInt64 uriID; - nsresult rv = history->GetUrlIdFor(aURI, &uriID, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - if (uriID == 0) // Check if URI exists. - return NS_OK; - - mozStorageStatementScoper scoper(mDBGetAnnotationNames); - rv = mDBGetAnnotationNames->BindInt64Parameter(0, uriID); + mozStorageStatementScoper scoper(statement); + nsresult rv = statement->BindInt64Parameter(0, aFkId); NS_ENSURE_SUCCESS(rv, rv); PRBool hasResult; nsCAutoString name; - while (NS_SUCCEEDED(mDBGetAnnotationNames->ExecuteStep(&hasResult)) && + while (NS_SUCCEEDED(statement->ExecuteStep(&hasResult)) && hasResult) { - rv = mDBGetAnnotationNames->GetUTF8String(0, name); + rv = statement->GetUTF8String(0, name); NS_ENSURE_SUCCESS(rv, rv); - if (! aResult->AppendElement(name)) + if (!aResult->AppendElement(name)) return NS_ERROR_OUT_OF_MEMORY; } @@ -670,12 +1133,47 @@ nsAnnotationService::GetPageAnnotationNamesTArray(nsIURI* aURI, } +NS_IMETHODIMP +nsAnnotationService::GetItemAnnotationNames(PRInt64 aItemId, PRUint32* aCount, + nsIVariant*** _result) +{ + *aCount = 0; + *_result = nsnull; + + nsTArray names; + nsresult rv = GetAnnotationNamesTArray(aItemId, &names, PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + if (names.Length() == 0) + return NS_OK; + + *_result = NS_STATIC_CAST(nsIVariant**, + nsMemory::Alloc(sizeof(nsIVariant*) * names.Length())); + NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY); + + for (PRUint32 i = 0; i < names.Length(); i ++) { + nsCOMPtr var = new nsVariant; + if (! var) { + // need to release all the variants we've already created + for (PRUint32 j = 0; j < i; j ++) + NS_RELEASE((*_result)[j]); + nsMemory::Free(*_result); + *_result = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + var->SetAsAUTF8String(names[i]); + NS_ADDREF((*_result)[i] = var); + } + *aCount = names.Length(); + + return NS_OK; +} + // nsAnnotationService::HasAnnotation NS_IMETHODIMP -nsAnnotationService::HasAnnotation(nsIURI* aURI, - const nsACString& aName, - PRBool *_retval) +nsAnnotationService::PageHasAnnotation(nsIURI* aURI, + const nsACString& aName, + PRBool *_retval) { nsresult rv = StartGetAnnotationFromURI(aURI, aName); if (rv == NS_ERROR_NOT_AVAILABLE) { @@ -689,46 +1187,91 @@ nsAnnotationService::HasAnnotation(nsIURI* aURI, } -// nsAnnotationService::RemoveAnnotation -// -// We don't remove anything from the moz_anno_attributes table. If we delete the -// last item of a given name, that item really should go away. It will get -// cleaned up on the next shutdown. +// nsAnnotationService::ItemHasAnnotation NS_IMETHODIMP -nsAnnotationService::RemoveAnnotation(nsIURI* aURI, - const nsACString& aName) +nsAnnotationService::ItemHasAnnotation(PRInt64 aItemId, + const nsACString& aName, + PRBool *_retval) { - nsresult rv; - nsNavHistory* history = nsNavHistory::GetHistoryService(); - NS_ENSURE_TRUE(history, NS_ERROR_FAILURE); + nsresult rv = StartGetAnnotationFromItemId(aItemId, aName); + if (rv == NS_ERROR_NOT_AVAILABLE) { + *_retval = PR_FALSE; + rv = NS_OK; + } else if (NS_SUCCEEDED(rv)) { + *_retval = PR_TRUE; + } + mDBGetAnnotationFromItemId->Reset(); + return rv; +} - PRInt64 uriID; - rv = history->GetUrlIdFor(aURI, &uriID, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); - if (uriID == 0) // Check if URI exists. - return NS_OK; +// nsAnnotationService::RemoveAnnotationInternal +// +// We don't remove anything from the moz_anno_attributes table. If we delete +// the last item of a given name, that item really should go away. It will +// get cleaned up on the next shutdown. +// +// XXX NOT REALLY, see nsNavHistoryExpire::ExpireAnnotationsParanoid +nsresult +nsAnnotationService::RemoveAnnotationInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName) +{ + mozIStorageStatement* statement = aIsItemAnnotation ? + mDBRemoveItemAnnotation.get() : mDBRemoveAnnotation.get(); - mozStorageStatementScoper resetter(mDBRemoveAnnotation); + mozStorageStatementScoper resetter(statement); - rv = mDBRemoveAnnotation->BindInt64Parameter(0, uriID); + nsresult rv = statement->BindInt64Parameter(0, aFkId); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBRemoveAnnotation->BindUTF8StringParameter(1, aName); + rv = statement->BindUTF8StringParameter(1, aName); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBRemoveAnnotation->Execute(); + rv = statement->Execute(); NS_ENSURE_SUCCESS(rv, rv); resetter.Abandon(); + return NS_OK; +} + +// nsAnnotationService::RemovePageAnnotation + +NS_IMETHODIMP +nsAnnotationService::RemovePageAnnotation(nsIURI* aURI, + const nsACString& aName) +{ + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + if (placeId == 0) + return NS_OK; // URI doesn't exist, nothing to delete + + rv = RemoveAnnotationInternal(placeId, PR_FALSE, aName); + NS_ENSURE_SUCCESS(rv, rv); // Update observers for (PRInt32 i = 0; i < mObservers.Count(); i ++) - mObservers[i]->OnAnnotationRemoved(aURI, aName); + mObservers[i]->OnPageAnnotationRemoved(aURI, aName); return NS_OK; } +// nsAnnotationService::RemoveItemAnnotation + +NS_IMETHODIMP +nsAnnotationService::RemoveItemAnnotation(PRInt64 aItemId, + const nsACString& aName) +{ + nsresult rv = RemoveAnnotationInternal(aItemId, PR_TRUE, aName); + NS_ENSURE_SUCCESS(rv, rv); + + // Update observers + for (PRInt32 i = 0; i < mObservers.Count(); i ++) + mObservers[i]->OnItemAnnotationRemoved(aItemId, aName); + + return NS_OK; +} // nsAnnotationSerivce::RemovePageAnnotations // @@ -739,14 +1282,10 @@ nsAnnotationService::RemoveAnnotation(nsIURI* aURI, NS_IMETHODIMP nsAnnotationService::RemovePageAnnotations(nsIURI* aURI) { - nsresult rv; - nsNavHistory* history = nsNavHistory::GetHistoryService(); - NS_ENSURE_TRUE(history, NS_ERROR_UNEXPECTED); - - PRInt64 uriID; - rv = history->GetUrlIdFor(aURI, &uriID, PR_FALSE); + PRInt64 placeId; + nsresult rv = GetPlaceIdForURI(aURI, &placeId, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); - if (uriID == 0) + if (placeId == 0) return NS_OK; // URI doesn't exist, nothing to delete nsCOMPtr statement; @@ -754,7 +1293,7 @@ nsAnnotationService::RemovePageAnnotations(nsIURI* aURI) "DELETE FROM moz_annos WHERE place_id = ?1"), getter_AddRefs(statement)); NS_ENSURE_SUCCESS(rv, rv); - rv = statement->BindInt64Parameter(0, uriID); + rv = statement->BindInt64Parameter(0, placeId); NS_ENSURE_SUCCESS(rv, rv); rv = statement->Execute(); @@ -762,12 +1301,34 @@ nsAnnotationService::RemovePageAnnotations(nsIURI* aURI) // Update observers for (PRInt32 i = 0; i < mObservers.Count(); i ++) - mObservers[i]->OnAnnotationRemoved(aURI, EmptyCString()); + mObservers[i]->OnPageAnnotationRemoved(aURI, EmptyCString()); return NS_OK; } -// nsAnnotationService::CopyAnnotations +// nsAnnotationSerivce::RemoveItemAnnotations + +NS_IMETHODIMP +nsAnnotationService::RemoveItemAnnotations(PRInt64 aItemId) +{ + nsCOMPtr statement; + nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "DELETE FROM moz_items_annos WHERE item_id = ?1"), + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + rv = statement->BindInt64Parameter(0, aItemId); + NS_ENSURE_SUCCESS(rv, rv); + + rv = statement->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + + // Update observers + for (PRInt32 i = 0; i < mObservers.Count(); i ++) + mObservers[i]->OnItemAnnotationRemoved(aItemId, EmptyCString()); + return NS_OK; +} + +// nsAnnotationService::CopyPageAnnotations // // This function currently assumes there are very few annotations per // URI and that brute-force is therefore a good strategy for intersecting @@ -783,21 +1344,32 @@ nsAnnotationService::RemovePageAnnotations(nsIURI* aURI) // is too slow. NS_IMETHODIMP -nsAnnotationService::CopyAnnotations(nsIURI* aSourceURI, nsIURI* aDestURI, - PRBool aOverwriteDest) +nsAnnotationService::CopyPageAnnotations(nsIURI* aSourceURI, + nsIURI* aDestURI, + PRBool aOverwriteDest) { mozStorageTransaction transaction(mDBConn, PR_FALSE); // source + PRInt64 sourcePlaceId; + nsresult rv = GetPlaceIdForURI(aSourceURI, &sourcePlaceId, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + if (sourcePlaceId == 0) // Check if URI exists. + return NS_OK; + nsTArray sourceNames; - nsresult rv = GetPageAnnotationNamesTArray(aSourceURI, &sourceNames); + rv = GetAnnotationNamesTArray(sourcePlaceId, &sourceNames, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); if (sourceNames.Length() == 0) return NS_OK; // nothing to copy // dest + PRInt64 destPlaceId; + rv = GetPlaceIdForURI(aSourceURI, &destPlaceId); + NS_ENSURE_SUCCESS(rv, rv); + nsTArray destNames; - rv = GetPageAnnotationNamesTArray(aDestURI, &destNames); + rv = GetAnnotationNamesTArray(destPlaceId, &destNames, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // we assume you will only have a couple annotations max per URI @@ -813,7 +1385,7 @@ nsAnnotationService::CopyAnnotations(nsIURI* aSourceURI, nsIURI* aDestURI, PRUint32 destIndex = destNames.IndexOf(sourceNames[i]); if (destIndex != destNames.NoIndex) { destNames.RemoveElementAt(destIndex); - RemoveAnnotation(aDestURI, sourceNames[i]); + RemovePageAnnotation(aDestURI, sourceNames[i]); } } } else { @@ -866,6 +1438,16 @@ nsAnnotationService::CopyAnnotations(nsIURI* aSourceURI, nsIURI* aDestURI, return NS_OK; } +// nsAnnotationService::CopyItemAnnotations + +NS_IMETHODIMP +nsAnnotationService::CopyItemAnnotations(PRInt64 aSourceItemId, + PRInt64 aDestItemId, + PRBool aOverwriteDest) +{ + // XXX: Implment Me! + return NS_ERROR_NOT_IMPLEMENTED; +} // nsAnnotationService::AddObserver @@ -892,6 +1474,8 @@ nsAnnotationService::RemoveObserver(nsIAnnotationObserver* aObserver) // nsAnnotationService::GetAnnotationURI +// +// XXX: does not support item-annotations NS_IMETHODIMP nsAnnotationService::GetAnnotationURI(nsIURI* aURI, const nsACString& aName, @@ -913,38 +1497,40 @@ nsAnnotationService::GetAnnotationURI(nsIURI* aURI, const nsACString& aName, return NS_NewURI(_result, spec); } - // nsAnnotationService::HasAnnotationInternal // -// This is just like HasAnnotation but takes a URL ID. It will also give -// you the ID of the annotation, if it exists. This value can be NULL and -// it won't retrieve the annotation ID. If it doesn't exist, annotationID -// is not touched. +// This is just like Has[Item]Annotation but takes the foreign key +// directly (i.e. the places or item id). It will also give you the ID of +// the annotation, if it exists. This value can be NULL and it won't +// retrieve the annotation ID. If it doesn't exist, annotationID is not +// touched. nsresult -nsAnnotationService::HasAnnotationInternal(PRInt64 aURLID, +nsAnnotationService::HasAnnotationInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, const nsACString& aName, PRBool* hasAnnotation, PRInt64* annotationID) { - mozStorageStatementScoper resetter(mDBGetAnnotation); + mozIStorageStatement* statement = + aIsItemAnnotation ? mDBGetItemAnnotation.get() : mDBGetAnnotation.get(); + mozStorageStatementScoper resetter(statement); nsresult rv; - rv = mDBGetAnnotation->BindInt64Parameter(0, aURLID); + rv = statement->BindInt64Parameter(0, aFkId); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBGetAnnotation->BindUTF8StringParameter(1, aName); + rv = statement->BindUTF8StringParameter(1, aName); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBGetAnnotation->ExecuteStep(hasAnnotation); + rv = statement->ExecuteStep(hasAnnotation); NS_ENSURE_SUCCESS(rv, rv); if (! annotationID || ! *hasAnnotation) return NS_OK; - return mDBGetAnnotation->GetInt64(0, annotationID); + return statement->GetInt64(0, annotationID); } - // nsAnnotationService::StartGetAnnotationFromURI // // This loads the statement GetAnnotationFromURI and steps it once so you @@ -975,6 +1561,46 @@ nsAnnotationService::StartGetAnnotationFromURI(nsIURI* aURI, return NS_OK; } +// nsAnnotationService::StartGetAnnotationFromItemId +// +// This loads the statement GetAnnotationFromItemId and steps it once so you +// can get data out of it. YOU NEED TO RESET THIS STATEMENT WHEN YOU ARE +// DONE! Returns error if the annotation is not found, in which case you +// don't need to reset anything. + +nsresult +nsAnnotationService::StartGetAnnotationFromItemId(PRInt64 aItemId, + const nsACString& aName) +{ + mozStorageStatementScoper statementResetter(mDBGetAnnotationFromItemId); + nsresult rv; + + rv = mDBGetAnnotationFromItemId->BindInt64Parameter(0, aItemId); + NS_ENSURE_SUCCESS(rv, rv); + rv = mDBGetAnnotationFromItemId->BindUTF8StringParameter(1, aName); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasResult = PR_FALSE; + rv = mDBGetAnnotationFromItemId->ExecuteStep(&hasResult); + if (NS_FAILED(rv) || ! hasResult) + return NS_ERROR_NOT_AVAILABLE; + + // on success, DON'T reset the statement, the caller needs to read from it, + // and it is the caller's job to do the reseting. + statementResetter.Abandon(); + return NS_OK; +} + + +nsresult +nsAnnotationService::GetPlaceIdForURI(nsIURI* aURI, PRInt64* _retval, + PRBool aAutoCreate) +{ + nsNavHistory* history = nsNavHistory::GetHistoryService(); + NS_ENSURE_TRUE(history, NS_ERROR_FAILURE); + + return history->GetUrlIdFor(aURI, _retval, aAutoCreate); +} // nsAnnotationService::StartSetAnnotation // @@ -990,32 +1616,27 @@ nsAnnotationService::StartGetAnnotationFromURI(nsIURI* aURI, // statement will not need reseting. nsresult -nsAnnotationService::StartSetAnnotation(nsIURI* aURI, +nsAnnotationService::StartSetAnnotation(PRInt64 aFkId, + PRBool aIsItemAnnotation, const nsACString& aName, - PRInt32 aFlags, PRInt32 aExpiration, - PRInt32 aType, + PRInt32 aFlags, + PRUint16 aExpiration, + PRUint16 aType, mozIStorageStatement** aStatement) { - nsresult rv; - nsNavHistory* history = nsNavHistory::GetHistoryService(); - NS_ENSURE_TRUE(history, NS_ERROR_FAILURE); - - PRInt64 uriID; - rv = history->GetUrlIdFor(aURI, &uriID, PR_TRUE); - NS_ENSURE_SUCCESS(rv, rv); - PRBool hasAnnotation; PRInt64 annotationID; - rv = HasAnnotationInternal(uriID, aName, &hasAnnotation, &annotationID); + nsresult rv = HasAnnotationInternal(aFkId, aIsItemAnnotation, aName, + &hasAnnotation, &annotationID); NS_ENSURE_SUCCESS(rv, rv); // either update the existing annotation (using the old annotation's ID) // or insert a new one tied to the URI. if (hasAnnotation) { - *aStatement = mDBSetAnnotation; + *aStatement = aIsItemAnnotation ? mDBSetItemAnnotation : mDBSetAnnotation; rv = (*aStatement)->BindInt64Parameter(kAnnoIndex_ID, annotationID); } else { - *aStatement = mDBAddAnnotation; + *aStatement = aIsItemAnnotation ? mDBAddItemAnnotation : mDBAddAnnotation; // make sure the name exists { @@ -1038,7 +1659,7 @@ nsAnnotationService::StartSetAnnotation(nsIURI* aURI, } else { nameID = mDBGetAnnotationNameID->AsInt64(0); } - rv = (*aStatement)->BindInt64Parameter(kAnnoIndex_Page, uriID); + rv = (*aStatement)->BindInt64Parameter(kAnnoIndex_PageOrItem, aFkId); NS_ENSURE_SUCCESS(rv, rv); rv = (*aStatement)->BindInt64Parameter(kAnnoIndex_Name, nameID); NS_ENSURE_SUCCESS(rv, rv); @@ -1060,11 +1681,20 @@ nsAnnotationService::StartSetAnnotation(nsIURI* aURI, } -// nsAnnotationService::CallSetObservers +// nsAnnotationService::CallSetForPageObservers void -nsAnnotationService::CallSetObservers(nsIURI* aURI, const nsACString& aName) +nsAnnotationService::CallSetForPageObservers(nsIURI* aURI, const nsACString& aName) { for (PRInt32 i = 0; i < mObservers.Count(); i ++) - mObservers[i]->OnAnnotationSet(aURI, aName); + mObservers[i]->OnPageAnnotationSet(aURI, aName); +} + +// nsAnnotationService::CallSetForItemObservers + +void +nsAnnotationService::CallSetForItemObservers(PRInt64 aItemId, const nsACString& aName) +{ + for (PRInt32 i = 0; i < mObservers.Count(); i ++) + mObservers[i]->OnItemAnnotationSet(aItemId, aName); } diff --git a/toolkit/components/places/src/nsAnnotationService.h b/toolkit/components/places/src/nsAnnotationService.h index 3e2828b5d76..6fe59ade069 100644 --- a/toolkit/components/places/src/nsAnnotationService.h +++ b/toolkit/components/places/src/nsAnnotationService.h @@ -40,6 +40,7 @@ #define nsAnnotationService_h___ #include "nsIAnnotationService.h" +#include "nsTArray.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "mozIStorageService.h" @@ -88,20 +89,26 @@ protected: nsCOMPtr mDBConn; nsCOMPtr mDBSetAnnotation; + nsCOMPtr mDBSetItemAnnotation; nsCOMPtr mDBGetAnnotation; + nsCOMPtr mDBGetItemAnnotation; nsCOMPtr mDBGetAnnotationNames; + nsCOMPtr mDBGetItemAnnotationNames; nsCOMPtr mDBGetAnnotationFromURI; + nsCOMPtr mDBGetAnnotationFromItemId; nsCOMPtr mDBGetAnnotationNameID; nsCOMPtr mDBAddAnnotationName; nsCOMPtr mDBAddAnnotation; + nsCOMPtr mDBAddItemAnnotation; nsCOMPtr mDBRemoveAnnotation; + nsCOMPtr mDBRemoveItemAnnotation; nsCOMArray mObservers; static nsAnnotationService* gAnnotationService; static const int kAnnoIndex_ID; - static const int kAnnoIndex_Page; + static const int kAnnoIndex_PageOrItem; static const int kAnnoIndex_Name; static const int kAnnoIndex_MimeType; static const int kAnnoIndex_Content; @@ -109,18 +116,67 @@ protected: static const int kAnnoIndex_Expiration; static const int kAnnoIndex_Type; - nsresult HasAnnotationInternal(PRInt64 aURLID, const nsACString& aName, - PRBool* hasAnnotation, PRInt64* annotationID); + nsresult HasAnnotationInternal(PRInt64 aFkId, PRBool aIsBookmarkId, + const nsACString& aName, PRBool* hasAnnotation, + PRInt64* annotationID); nsresult StartGetAnnotationFromURI(nsIURI* aURI, const nsACString& aName); - nsresult StartSetAnnotation(nsIURI* aURI, + nsresult StartGetAnnotationFromItemId(PRInt64 aItemId, + const nsACString& aName); + nsresult StartSetAnnotation(PRInt64 aFkId, + PRBool aIsItemAnnotation, const nsACString& aName, - PRInt32 aFlags, PRInt32 aExpiration, - PRInt32 aType, mozIStorageStatement** aStatement); - void CallSetObservers(nsIURI* aURI, const nsACString& aName); + PRInt32 aFlags, + PRUint16 aExpiration, + PRUint16 aType, + mozIStorageStatement** aStatement); + nsresult SetAnnotationStringInternal(PRInt64 aItemId, + PRBool aIsItemAnnotation, + const nsACString& aName, + const nsAString& aValue, + PRInt32 aFlags, + PRUint16 aExpiration); + nsresult SetAnnotationInt32Internal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + PRInt32 aValue, + PRInt32 aFlags, + PRUint16 aExpiration); + nsresult SetAnnotationInt64Internal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + PRInt64 aValue, + PRInt32 aFlags, + PRUint16 aExpiration); + nsresult SetAnnotationDoubleInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + double aValue, + PRInt32 aFlags, + PRUint16 aExpiration); + nsresult SetAnnotationBinaryInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName, + const PRUint8 *aData, + PRUint32 aDataLen, + const nsACString& aMimeType, + PRInt32 aFlags, + PRUint16 aExpiration); + nsresult RemoveAnnotationInternal(PRInt64 aFkId, + PRBool aIsItemAnnotation, + const nsACString& aName); + static nsresult GetPlaceIdForURI(nsIURI* aURI, PRInt64* _retval, + PRBool aAutoCreate = PR_TRUE); - static nsresult MigrateFromAlpha1(mozIStorageConnection* aDBConn); - nsresult GetPageAnnotationNamesTArray(nsIURI* aURI, nsTArray* aResult); + void CallSetForPageObservers(nsIURI* aURI, const nsACString& aName); + void CallSetForItemObservers(PRInt64 aItemId, const nsACString& aName); + + nsresult GetPagesWithAnnotationCOMArray(const nsACString& aName, + nsCOMArray* aResults); + nsresult GetItemsWithAnnotationTArray(const nsACString& aName, + nsTArray* aResult); + nsresult GetAnnotationNamesTArray(PRInt64 aFkId, nsTArray* aResult, + PRBool aIsFkItemId); }; #endif /* nsAnnotationService_h___ */ diff --git a/toolkit/components/places/src/nsLivemarkService.js b/toolkit/components/places/src/nsLivemarkService.js index c6104a86a83..9da92ae5390 100644 --- a/toolkit/components/places/src/nsLivemarkService.js +++ b/toolkit/components/places/src/nsLivemarkService.js @@ -124,21 +124,14 @@ function LivemarkService() { // this is giving a reentrant getService warning in XPCShell. bug 194568. this._ans = Cc[AS_CONTRACTID].getService(Ci.nsIAnnotationService); - var livemarks = this._ans.getPagesWithAnnotation(LMANNO_FEEDURI, {}); + var livemarks = this._ans.getItemsWithAnnotation(LMANNO_FEEDURI, {}); for (var i = 0; i < livemarks.length; i++) { var feedURI = gIoService.newURI( - this._ans.getAnnotationString(livemarks[i], LMANNO_FEEDURI), + this._ans.getItemAnnotationString(livemarks[i], LMANNO_FEEDURI), null, null ); - var queries = { }, options = { }; - this._history.queryStringToQueries(livemarks[i].spec, queries, {}, options); - var count = {}; - var folders = queries.value[0].getFolders(count); - if (!(queries.value.length && queries.value.length == 1) && - count.value != 1) - continue; // invalid folder URI (should identify exactly one folder) - this._pushLivemark(folders[0], livemarks[i], feedURI); + this._pushLivemark(livemarks[i], feedURI); } } @@ -157,9 +150,8 @@ LivemarkService.prototype = { }, // returns new length of _livemarks - _pushLivemark: function LS__pushLivemark(folderId, folderURI, feedURI) { - return this._livemarks.push({folderId: folderId, folderURI: folderURI, - feedURI: feedURI}); + _pushLivemark: function LS__pushLivemark(folderId, feedURI) { + return this._livemarks.push({folderId: folderId, feedURI: feedURI}); }, _getLivemarkIndex: function LS__getLivemarkIndex(folderId) { @@ -184,25 +176,6 @@ LivemarkService.prototype = { }, deleteLivemarkChildren: function LS_deleteLivemarkChildren(folderId) { - var query = this._history.getNewQuery(); - query.setFolders([folderId], 1); - var options = this._history.getNewQueryOptions(); - options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1); - var result = this._history.executeQuery(query, options); - var root = result.root; - root.containerOpen = true; - var cc = root.childCount; - for (var i=0; i < cc; ++i) { - try { - var node = root.getChild(i); - var placeURI = this._bms.getItemURI(node.bookmarkId); - this._ans.removeAnnotation(placeURI, LMANNO_BMANNO); - } - catch (ex) { - // continue - } - } - this._bms.removeFolderChildren(folderId); }, @@ -224,8 +197,8 @@ LivemarkService.prototype = { // then we assume it's never been loaded. We perform this // check even when the update is being forced, in case the // livemark has somehow never been loaded. - var exprTime = this._ans.getAnnotationInt64(livemark.feedURI, - LMANNO_EXPIRATION); + var exprTime = this._ans.getPageAnnotationInt64(livemark.feedURI, + LMANNO_EXPIRATION); if (!forceUpdate && exprTime > Date.now()) { // no need to refresh livemark.locked = false; @@ -268,12 +241,12 @@ LivemarkService.prototype = { // Don't add livemarks to livemarks if (this.isLivemark(folder)) throw Cr.NS_ERROR_INVALID_ARG; - var [livemarkID, livemarkURI] = - this._createFolder(this._bms, folder, name, siteURI, feedURI, index); + var livemarkID = this._createFolder(this._bms, folder, name, siteURI, + feedURI, index); // kick off http fetch this._updateLivemarkChildren( - this._pushLivemark(livemarkID, livemarkURI, feedURI) - 1, + this._pushLivemark(livemarkID, feedURI) - 1, false ); @@ -283,10 +256,10 @@ LivemarkService.prototype = { createLivemarkFolderOnly: function LS_createLivemarkFolderOnly(bms, folder, name, siteURI, feedURI, index) { - var [livemarkID, livemarkURI] = - this._createFolder(bms, folder, name, siteURI, feedURI, index); + var livemarkID = this._createFolder(bms, folder, name, siteURI, feedURI, + index); this.insertLivemarkLoadingItem(bms, livemarkID); - this._pushLivemark(livemarkID, livemarkURI, feedURI); + this._pushLivemark(livemarkID, feedURI); return livemarkID; }, @@ -294,27 +267,26 @@ LivemarkService.prototype = { _createFolder: function LS__createFolder(bms, folder, name, siteURI, feedURI, index) { var livemarkID = bms.createContainer(folder, name, LS_CONTRACTID, index); - var livemarkURI = bms.getFolderURI(livemarkID); // Add an annotation to map the folder URI to the livemark feed URI - this._ans.setAnnotationString(livemarkURI, LMANNO_FEEDURI, feedURI.spec, 0, - this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationString(livemarkID, LMANNO_FEEDURI, feedURI.spec, 0, + this._ans.EXPIRE_NEVER); // Set the favicon var faviconService = Cc[FAV_CONTRACTID].getService(Ci.nsIFaviconService); + var livemarkURI = bms.getFolderURI(livemarkID); faviconService.setFaviconUrlForPage(livemarkURI, this._iconURI); if (siteURI) { // Add an annotation to map the folder URI to the livemark site URI - this._ans.setAnnotationString(livemarkURI, LMANNO_SITEURI, siteURI.spec, - 0, this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationString(livemarkID, LMANNO_SITEURI, siteURI.spec, + 0, this._ans.EXPIRE_NEVER); } - return [livemarkID, livemarkURI]; + return livemarkID; }, isLivemark: function LS_isLivemark(folder) { - var folderURI = this._bms.getFolderURI(folder); - return this._ans.hasAnnotation(folderURI, LMANNO_FEEDURI); + return this._ans.itemHasAnnotation(folder, LMANNO_FEEDURI); }, _ensureLivemark: function LS__ensureLivemark(container) { @@ -330,11 +302,10 @@ LivemarkService.prototype = { */ getSiteURI: function LS_getSiteURI(container) { this._ensureLivemark(container); - var containerURI = this._bms.getFolderURI(container); var siteURIString; try { siteURIString = - this._ans.getAnnotationString(containerURI, LMANNO_SITEURI); + this._ans.getItemAnnotationString(container, LMANNO_SITEURI); } catch (ex) { return null; @@ -345,31 +316,28 @@ LivemarkService.prototype = { setSiteURI: function LS_setSiteURI(container, siteURI) { this._ensureLivemark(container); - var containerURI = this._bms.getFolderURI(container); if (!siteURI) { - this._ans.removeAnnotation(containerURI, LMANNO_SITEURI); + this._ans.removeItemAnnotation(container, LMANNO_SITEURI); return; } - this._ans.setAnnotationString(containerURI, LMANNO_SITEURI, siteURI.spec, - 0, this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationString(container, LMANNO_SITEURI, siteURI.spec, + 0, this._ans.EXPIRE_NEVER); }, getFeedURI: function LS_getFeedURI(container) { - var containerURI = this._bms.getFolderURI(container); - return gIoService.newURI(this._ans.getAnnotationString(containerURI, - LMANNO_FEEDURI), + return gIoService.newURI(this._ans.getItemAnnotationString(container, + LMANNO_FEEDURI), null, null); }, setFeedURI: function LS_setFeedURI(container, feedURI) { if (!feedURI) throw Cr.NS_ERROR_INVALID_ARG; - - var containerURI = this._bms.getFolderURI(container); - this._ans.setAnnotationString(containerURI, LMANNO_FEEDURI, feedURI.spec, - 0, this._ans.EXPIRE_NEVER); + + this._ans.setItemAnnotationString(container, LMANNO_FEEDURI, feedURI.spec, + 0, this._ans.EXPIRE_NEVER); // now update our internal table var livemarkIndex = this._getLivemarkIndex(container); @@ -391,11 +359,7 @@ LivemarkService.prototype = { onContainerRemoving: function LS_onContainerRemoving(container) { var livemarkIndex = this._getLivemarkIndex(container); var livemark = this._livemarks[livemarkIndex]; - - // Remove the annotations that link the folder URI to the - // Feed URI and Site URI - this._ans.removeAnnotation(livemark.folderURI, LMANNO_FEEDURI); - this._ans.removeAnnotation(livemark.folderURI, LMANNO_SITEURI); + var stillInUse = false; stillInUse = this._livemarks.some( function(mark) { return mark.feedURI.equals(livemark.feedURI) } @@ -403,7 +367,7 @@ LivemarkService.prototype = { if (!stillInUse) { // ??? the code in the C++ had "livemark_expiration" as // the second arg... that must be wrong - this._ans.removeAnnotation(livemark.feedURI, LMANNO_EXPIRATION); + this._ans.removePageAnnotation(livemark.feedURI, LMANNO_EXPIRATION); } if (livemark.loadGroup) @@ -412,35 +376,8 @@ LivemarkService.prototype = { this.deleteLivemarkChildren(container); }, - // XXXdietrich seems like the mutability of "place:" URIs is the only reason - // this code has to exist, which is kinda high-maintenance. onContainerMoved: - function LS_onContainerMoved(container, newFolder, newIndex) { - var index = this._getLivemarkIndex(container); - - // Update the annotation that maps the folder URI to the livemark feed URI - var newURI = this._bms.getFolderURI(container); - var oldURI = this._livemarks[index].folderURI; - var feedURIString = this._ans.getAnnotationString(oldURI, LMANNO_FEEDURI); - this._ans.removeAnnotation(oldURI, LMANNO_FEEDURI); - this._ans.setAnnotationString(newURI, LMANNO_FEEDURI, feedURIString, 0, - this._ans.EXPIRE_NEVER); - - // Update the annotation that maps the folder URI to the livemark site URI - var siteURIString; - try { - siteURIString = this._ans.getAnnotationString(oldURI, LMANNO_SITEURI); - } - catch (ex) { - // will throw if no annotation - } - - if (siteURIString) { - this._ans.removeAnnotation(oldURI, LMANNO_SITEURI); - this._ans.setAnnotationString(newURI, LMANNO_SITEURI, siteURIString, 0, - this._ans.EXPIRE_NEVER); - } - }, + function LS_onContainerMoved(container, newFolder, newIndex) { }, childrenReadOnly: true, @@ -561,9 +498,8 @@ LivemarkLoadListener.prototype = { function LS_insertLivemarkChild(folderId, uri, title) { var id = this._bms.insertItem(folderId, uri, this._bms.DEFAULT_INDEX); this._bms.setItemTitle(id, title); - var placeURI = this._bms.getItemURI(id); - this._ans.setAnnotationString(placeURI, LMANNO_BMANNO, uri.spec, 0, - this._ans.EXPIRE_NEVER); + this._ans.setItemAnnotationString(id, LMANNO_BMANNO, uri.spec, 0, + this._ans.EXPIRE_NEVER); }, /** @@ -633,9 +569,9 @@ LivemarkLoadListener.prototype = { _setResourceTTL: function LLL__setResourceTTL(seconds) { var exptime = Date.now() + seconds; - this._ans.setAnnotationInt64(this._livemark.feedURI, - LMANNO_EXPIRATION, exptime, 0, - Ci.nsIAnnotationService.EXPIRE_NEVER); + this._ans.setPageAnnotationInt64(this._livemark.feedURI, + LMANNO_EXPIRATION, exptime, 0, + Ci.nsIAnnotationService.EXPIRE_NEVER); }, /** diff --git a/toolkit/components/places/src/nsNavBookmarks.cpp b/toolkit/components/places/src/nsNavBookmarks.cpp index 21e8cb37f7f..e1061ed2629 100644 --- a/toolkit/components/places/src/nsNavBookmarks.cpp +++ b/toolkit/components/places/src/nsNavBookmarks.cpp @@ -89,8 +89,10 @@ nsNavBookmarks::~nsNavBookmarks() sInstance = nsnull; } -NS_IMPL_ISUPPORTS2(nsNavBookmarks, - nsINavBookmarksService, nsINavHistoryObserver) +NS_IMPL_ISUPPORTS3(nsNavBookmarks, + nsINavBookmarksService, + nsINavHistoryObserver, + nsIAnnotationObserver) nsresult nsNavBookmarks::Init() @@ -263,10 +265,14 @@ nsNavBookmarks::Init() rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); + nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService(); + NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY); + // allows us to notify on title changes. MUST BE LAST so it is impossible // to fail after this call, or the history service will have a reference to // us and we won't go away. history->AddObserver(this, PR_FALSE); + annosvc->AddObserver(this); // DO NOT PUT STUFF HERE that can fail. See observer comment above. @@ -865,11 +871,9 @@ nsNavBookmarks::SetToolbarFolder(PRInt64 aFolderId) mToolbarFolder = aFolderId; // notify observers - nsCOMPtr folderURI; - rv = GetFolderURI(aFolderId, getter_AddRefs(folderURI)); ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemChanged(mToolbarFolder, folderURI, NS_LITERAL_CSTRING("became_toolbar_folder"), - EmptyString())); + OnItemChanged(mToolbarFolder, NS_LITERAL_CSTRING("became_toolbar_folder"), + PR_FALSE, EmptyCString())); return NS_OK; } @@ -926,7 +930,7 @@ nsNavBookmarks::InsertItem(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex, PRInt AddBookmarkToHash(childID, 0); ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemAdded(rowId, aItem, aFolder, index)) + OnItemAdded(rowId, aFolder, index)) return NS_OK; } @@ -937,11 +941,16 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId) mozIStorageConnection *dbConn = DBConn(); mozStorageTransaction transaction(dbConn, PR_FALSE); - nsresult rv; PRInt32 childIndex; PRInt64 placeId, folderId; - nsCOMPtr uri; - nsCAutoString buffer, spec; + nsCAutoString buffer; + + // First, remove item annotations + nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService(); + NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY); + nsresult rv = annosvc->RemoveItemAnnotations(aItemId); + NS_ENSURE_SUCCESS(rv, rv); + { // scoping to ensure the statement gets reset mozStorageStatementScoper scope(mDBGetItemProperties); mDBGetItemProperties->BindInt64Parameter(0, aItemId); @@ -956,10 +965,6 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId) childIndex = mDBGetItemProperties->AsInt32(kGetItemPropertiesIndex_Position); placeId = mDBGetItemProperties->AsInt64(kGetItemPropertiesIndex_PlaceID); folderId = mDBGetItemProperties->AsInt64(kGetItemPropertiesIndex_Parent); - rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_URI, spec); - NS_ENSURE_SUCCESS(rv, rv); - rv = NS_NewURI(getter_AddRefs(uri), spec); - NS_ENSURE_SUCCESS(rv, rv); } buffer.AssignLiteral("DELETE FROM moz_bookmarks WHERE id = "); @@ -980,7 +985,7 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId) NS_ENSURE_SUCCESS(rv, rv); ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemRemoved(aItemId, uri, folderId, childIndex)) + OnItemRemoved(aItemId, folderId, childIndex)) return NS_OK; } @@ -1241,7 +1246,12 @@ nsNavBookmarks::GetParentAndIndexOfFolder(PRInt64 aFolder, PRInt64* aParent, NS_IMETHODIMP nsNavBookmarks::RemoveFolder(PRInt64 aFolder) { - nsresult rv; + // First, remove item annotations + nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService(); + NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY); + nsresult rv = annosvc->RemoveItemAnnotations(aFolder); + NS_ENSURE_SUCCESS(rv, rv); + PRInt64 parent; PRInt32 index; nsCAutoString folderType; @@ -1334,9 +1344,8 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder) { mozStorageTransaction transaction(DBConn(), PR_FALSE); - nsTArray separatorChildren; // separator indices nsTArray folderChildren; - nsTArray itemChildren; + nsTArray itemChildren; // bookmarks / separators nsresult rv; { mozStorageStatementScoper scope(mDBGetChildren); @@ -1353,26 +1362,15 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder) if (type == TYPE_FOLDER) { // folder folderChildren.AppendElement( - mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_BookmarkItemId)); - } else if (type == TYPE_SEPARATOR) { - // separator - // XXXDietrich - could merge this and item, fetch both by id? - separatorChildren.AppendElement(mDBGetChildren->AsInt32(kGetChildrenIndex_Position)); + mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_ItemId)); } else { - // item - itemChildren.AppendElement(mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_BookmarkItemId)); + // bookmarks / separators + itemChildren.AppendElement(mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_ItemId)); } } } - // Remove separators. The list of separators will already be sorted since - // we order by position, so by enumerating it backwards, we avoid having to - // deal with shifting indices. PRUint32 i; - for (i = separatorChildren.Length() - 1; i != PRInt32(-1); --i) { - rv = RemoveChildAt(aFolder, separatorChildren[i]); - NS_ENSURE_SUCCESS(rv, rv); - } // remove folders for (i = 0; i < folderChildren.Length(); ++i) { @@ -1592,25 +1590,9 @@ nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsAString &aTitle) rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); - // get URI - nsCOMPtr uri; - nsCAutoString spec; - PRBool results; - { - mozStorageStatementScoper scope(mDBGetItemProperties); - rv = mDBGetItemProperties->BindInt64Parameter(0, aItemId); - NS_ENSURE_SUCCESS(rv, rv); - rv = mDBGetItemProperties->ExecuteStep(&results); - NS_ENSURE_SUCCESS(rv, rv); - mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_URI, spec); - NS_ENSURE_SUCCESS(rv, rv); - rv = NS_NewURI(getter_AddRefs(uri), spec); - NS_ENSURE_SUCCESS(rv, rv); - } - ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemChanged(aItemId, uri, NS_LITERAL_CSTRING("title"), - aTitle)); + OnItemChanged(aItemId, NS_LITERAL_CSTRING("title"), + PR_FALSE, NS_ConvertUTF16toUTF8(aTitle))); return NS_OK; } @@ -1850,7 +1832,7 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId, index ++; PRBool isFolder = mDBGetChildren->AsInt32(kGetChildrenIndex_Type) == TYPE_FOLDER; - PRInt64 id = mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_BookmarkItemId); + PRInt64 id = mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_ItemId); nsCOMPtr node; if (isFolder) { @@ -1873,10 +1855,10 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId, node = new nsNavHistorySeparatorResultNode(); NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY); - // add the bookmark identifier (RowToResult does so for bookmark items in + // add the item identifier (RowToResult does so for bookmark items in // the next else block); - node->mBookmarkId = - mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_BookmarkItemId); + node->mItemId = + mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_ItemId); } else { rv = History()->RowToResult(mDBGetChildren, options, getter_AddRefs(node)); @@ -1994,6 +1976,8 @@ nsNavBookmarks::GetBookmarkedURIFor(nsIURI* aURI, nsIURI** _retval) NS_IMETHODIMP nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI *aNewURI) { + NS_ENSURE_ARG(aNewURI); + mozIStorageConnection *dbConn = DBConn(); mozStorageTransaction transaction(dbConn, PR_FALSE); @@ -2015,13 +1999,13 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI *aNewURI) rv = transaction.Commit(); NS_ENSURE_SUCCESS(rv, rv); + nsCAutoString spec; + rv = aNewURI->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + // Pass the new URI to OnItemChanged. - // Observers can fetch the changed value from the URI. - // XXXDietrich - would be more explicit, yet redundant - // to pass the string spec as the changed value. ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemChanged(aBookmarkId, aNewURI, NS_LITERAL_CSTRING("uri"), - EmptyString())) + OnItemChanged(aBookmarkId, NS_LITERAL_CSTRING("uri"), PR_FALSE, spec)) return NS_OK; } @@ -2330,7 +2314,7 @@ nsNavBookmarks::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime, if (bookmarks.Length()) { for (PRUint32 i = 0; i < bookmarks.Length(); i++) ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemVisited(bookmarks[i], aURI, aVisitID, aTime)) + OnItemVisited(bookmarks[i], aVisitID, aTime)) } } return NS_OK; @@ -2352,8 +2336,8 @@ nsNavBookmarks::OnDeleteURI(nsIURI *aURI) if (bookmarks.Length()) { for (PRUint32 i = 0; i < bookmarks.Length(); i ++) ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemChanged(bookmarks[i], aURI, NS_LITERAL_CSTRING("cleartime"), - EmptyString())) + OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("cleartime"), + PR_FALSE, EmptyCString())) } } return NS_OK; @@ -2394,8 +2378,8 @@ nsNavBookmarks::OnPageChanged(nsIURI *aURI, PRUint32 aWhat, if (bookmarks.Length()) { for (PRUint32 i = 0; i < bookmarks.Length(); i ++) ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, - OnItemChanged(bookmarks[i], aURI, NS_LITERAL_CSTRING("favicon"), - aValue)); + OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("favicon"), + PR_FALSE, NS_ConvertUTF16toUTF8(aValue))); } } } @@ -2409,3 +2393,34 @@ nsNavBookmarks::OnPageExpired(nsIURI* aURI, PRTime aVisitTime, // pages that are bookmarks shouldn't expire, so we don't need to handle it return NS_OK; } + +// nsIAnnotationObserver + +NS_IMETHODIMP +nsNavBookmarks::OnPageAnnotationSet(nsIURI* aPage, const nsACString& aName) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsNavBookmarks::OnItemAnnotationSet(PRInt64 aItemId, const nsACString& aName) +{ + ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, + OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString())); + return NS_OK; +} + + +NS_IMETHODIMP +nsNavBookmarks::OnPageAnnotationRemoved(nsIURI* aPage, const nsACString& aName) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsNavBookmarks::OnItemAnnotationRemoved(PRInt64 aItemId, const nsACString& aName) +{ + ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver, + OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString())); + return NS_OK; +} diff --git a/toolkit/components/places/src/nsNavBookmarks.h b/toolkit/components/places/src/nsNavBookmarks.h index 221f8ca0dd6..9033f4ab481 100644 --- a/toolkit/components/places/src/nsNavBookmarks.h +++ b/toolkit/components/places/src/nsNavBookmarks.h @@ -40,6 +40,7 @@ #define nsNavBookmarks_h_ #include "nsINavBookmarksService.h" +#include "nsIAnnotationService.h" #include "nsIStringBundle.h" #include "nsITransaction.h" #include "nsNavHistory.h" @@ -49,12 +50,14 @@ class nsIOutputStream; class nsNavBookmarks : public nsINavBookmarksService, - public nsINavHistoryObserver + public nsINavHistoryObserver, + public nsIAnnotationObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSINAVBOOKMARKSSERVICE NS_DECL_NSINAVHISTORYOBSERVER + NS_DECL_NSIANNOTATIONOBSERVER nsNavBookmarks(); nsresult Init(); diff --git a/toolkit/components/places/src/nsNavHistory.cpp b/toolkit/components/places/src/nsNavHistory.cpp index cfc57c3fa59..58e4f8e6f00 100644 --- a/toolkit/components/places/src/nsNavHistory.cpp +++ b/toolkit/components/places/src/nsNavHistory.cpp @@ -207,7 +207,7 @@ const PRInt32 nsNavHistory::kGetInfoIndex_VisitCount = 4; const PRInt32 nsNavHistory::kGetInfoIndex_VisitDate = 5; const PRInt32 nsNavHistory::kGetInfoIndex_FaviconURL = 6; const PRInt32 nsNavHistory::kGetInfoIndex_SessionId = 7; -const PRInt32 nsNavHistory::kGetInfoIndex_BookmarkItemId = 8; +const PRInt32 nsNavHistory::kGetInfoIndex_ItemId = 8; const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0; const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1; @@ -3933,9 +3933,9 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, return NS_ERROR_OUT_OF_MEMORY; PRBool isNull; - if (NS_SUCCEEDED(aRow->GetIsNull(kGetInfoIndex_BookmarkItemId, &isNull)) && + if (NS_SUCCEEDED(aRow->GetIsNull(kGetInfoIndex_ItemId, &isNull)) && !isNull) { - (*aResult)->mBookmarkId = aRow->AsInt64(kGetInfoIndex_BookmarkItemId); + (*aResult)->mItemId = aRow->AsInt64(kGetInfoIndex_ItemId); } NS_ADDREF(*aResult); return NS_OK; diff --git a/toolkit/components/places/src/nsNavHistory.h b/toolkit/components/places/src/nsNavHistory.h index af1005d1468..6970356f8f5 100644 --- a/toolkit/components/places/src/nsNavHistory.h +++ b/toolkit/components/places/src/nsNavHistory.h @@ -220,7 +220,7 @@ public: static const PRInt32 kGetInfoIndex_Title; static const PRInt32 kGetInfoIndex_RevHost; static const PRInt32 kGetInfoIndex_VisitCount; - static const PRInt32 kGetInfoIndex_BookmarkItemId; + static const PRInt32 kGetInfoIndex_ItemId; // select a history row by URL, with visit date info (extra work) mozIStorageStatement* DBGetURLPageInfoFull() diff --git a/toolkit/components/places/src/nsNavHistoryResult.cpp b/toolkit/components/places/src/nsNavHistoryResult.cpp index 5232880eca8..3f4b26d282b 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.cpp +++ b/toolkit/components/places/src/nsNavHistoryResult.cpp @@ -115,7 +115,7 @@ nsNavHistoryResultNode::nsNavHistoryResultNode( mTime(aTime), mFaviconURI(aIconURI), mBookmarkIndex(-1), - mBookmarkId(-1), + mItemId(-1), mIndentLevel(-1), mViewIndex(-1) { @@ -827,73 +827,120 @@ PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_AnnotationLe nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, 0); - // Get the annotating-uris for both nodes - nsCOMPtr a_uri; - if (a->mBookmarkId != -1) { - bookmarks->GetItemURI(a->mBookmarkId, getter_AddRefs(a_uri)); + PRBool a_itemAnno = PR_FALSE; + PRBool b_itemAnno = PR_FALSE; + + // Not used for item annos + nsCOMPtr a_uri, b_uri; + if (a->mItemId != -1) { + a_itemAnno = PR_TRUE; } else { nsCAutoString spec; if (NS_SUCCEEDED(a->GetUri(spec))) NS_NewURI(getter_AddRefs(a_uri), spec); + NS_ENSURE_TRUE(a_uri, 0); } - NS_ENSURE_TRUE(a_uri, 0); - nsCOMPtr b_uri; - if (b->mBookmarkId != -1) { - bookmarks->GetItemURI(b->mBookmarkId, getter_AddRefs(b_uri)); + if (b->mItemId != -1) { + b_itemAnno = PR_TRUE; } else { nsCAutoString spec; if (NS_SUCCEEDED(b->GetUri(spec))) NS_NewURI(getter_AddRefs(b_uri), spec); + NS_ENSURE_TRUE(b_uri, 0); } - NS_ENSURE_TRUE(b_uri, 0); nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService(); NS_ENSURE_TRUE(annosvc, 0); PRBool a_hasAnno, b_hasAnno; - NS_ENSURE_SUCCESS(annosvc->HasAnnotation(a_uri, annoName, &a_hasAnno), 0); - NS_ENSURE_SUCCESS(annosvc->HasAnnotation(b_uri, annoName, &b_hasAnno), 0); + if (a_itemAnno) { + NS_ENSURE_SUCCESS(annosvc->ItemHasAnnotation(a->mItemId, annoName, + &a_hasAnno), 0); + } else { + NS_ENSURE_SUCCESS(annosvc->PageHasAnnotation(a_uri, annoName, + &a_hasAnno), 0); + } + if (b_itemAnno) { + NS_ENSURE_SUCCESS(annosvc->ItemHasAnnotation(b->mItemId, annoName, + &b_hasAnno), 0); + } else { + NS_ENSURE_SUCCESS(annosvc->PageHasAnnotation(b_uri, annoName, + &b_hasAnno), 0); + } PRInt32 value = 0; - if (a_hasAnno && b_hasAnno) { - PRInt32 a_type, b_type; - NS_ENSURE_SUCCESS(annosvc->GetAnnotationType(a_uri, annoName, &a_type), 0); - NS_ENSURE_SUCCESS(annosvc->GetAnnotationType(b_uri, annoName, &b_type), 0); + if (a_hasAnno || b_hasAnno) { + PRUint16 annoType; + if (a_hasAnno) { + if (a_itemAnno) { + NS_ENSURE_SUCCESS(annosvc->GetItemAnnotationType(a->mItemId, + annoName, + &annoType), 0); + } else { + NS_ENSURE_SUCCESS(annosvc->GetPageAnnotationType(a_uri, annoName, + &annoType), 0); + } + } + if (b_hasAnno) { + PRUint16 b_type; + if (b_itemAnno) { + NS_ENSURE_SUCCESS(annosvc->GetItemAnnotationType(b->mItemId, + annoName, + &b_type), 0); + } else { + NS_ENSURE_SUCCESS(annosvc->GetPageAnnotationType(b_uri, annoName, + &b_type), 0); + } + // We better make the API not support this state, really + if (b_type != annoType) + return 0; + } + +#define GET_ANNOTATIONS_VALUES(METHOD_ITEM, METHOD_PAGE, A_VAL, B_VAL) \ + if (a_hasAnno) { \ + if (a_itemAnno) { \ + NS_ENSURE_SUCCESS(annosvc->METHOD_ITEM(a->mItemId, annoName, \ + A_VAL), 0); \ + } else { \ + NS_ENSURE_SUCCESS(annosvc->METHOD_PAGE(a_uri, annoName, \ + A_VAL), 0); \ + } \ + } \ + if (b_hasAnno) { \ + if (b_itemAnno) { \ + NS_ENSURE_SUCCESS(annosvc->METHOD_ITEM(b->mItemId, annoName, \ + B_VAL), 0); \ + } else { \ + NS_ENSURE_SUCCESS(annosvc->METHOD_PAGE(b_uri, annoName, \ + B_VAL), 0); \ + } \ + } // Surprising as it is, we don't support sorting by a binary annotation - if (a_type == b_type && - a_type != nsIAnnotationService::TYPE_BINARY) { - if (a_type == nsIAnnotationService::TYPE_STRING) { + if (annoType != nsIAnnotationService::TYPE_BINARY) { + if (annoType == nsIAnnotationService::TYPE_STRING) { nsAutoString a_val, b_val; - NS_ENSURE_SUCCESS(annosvc->GetAnnotationString(a_uri, annoName, a_val), - 0); - NS_ENSURE_SUCCESS(annosvc->GetAnnotationString(b_uri, annoName, b_val), - 0); + GET_ANNOTATIONS_VALUES(GetItemAnnotationString, + GetPageAnnotationString, a_val, b_val); value = SortComparison_StringLess(a_val, b_val); } - else if (a_type == nsIAnnotationService::TYPE_INT32) { - PRInt32 a_val, b_val; - NS_ENSURE_SUCCESS(annosvc->GetAnnotationInt32(a_uri, annoName, &a_val), - 0); - NS_ENSURE_SUCCESS(annosvc->GetAnnotationInt32(b_uri, annoName, &b_val), - 0); + else if (annoType == nsIAnnotationService::TYPE_INT32) { + PRInt32 a_val = 0, b_val = 0; + GET_ANNOTATIONS_VALUES(GetItemAnnotationInt32, + GetPageAnnotationInt32, &a_val, &b_val); value = (a < b) ? -1 : (a > b) ? 1 : 0; } - else if (a_type == nsIAnnotationService::TYPE_INT64) { - PRInt64 a_val, b_val; - NS_ENSURE_SUCCESS(annosvc->GetAnnotationInt64(a_uri, annoName, &a_val), - 0); - NS_ENSURE_SUCCESS(annosvc->GetAnnotationInt64(b_uri, annoName, &b_val), - 0); + else if (annoType == nsIAnnotationService::TYPE_INT64) { + PRInt64 a_val = 0, b_val = 0; + GET_ANNOTATIONS_VALUES(GetItemAnnotationInt64, + GetPageAnnotationInt64, &a_val, &b_val); value = (a < b) ? -1 : (a > b) ? 1 : 0; } - else if (a_type == nsIAnnotationService::TYPE_DOUBLE) { - double a_val, b_val; - NS_ENSURE_SUCCESS(annosvc->GetAnnotationDouble(a_uri, annoName, &a_val), - 0); - NS_ENSURE_SUCCESS(annosvc->GetAnnotationDouble(b_uri, annoName, &b_val), - 0); + else if (annoType == nsIAnnotationService::TYPE_DOUBLE) { + double a_val = 0, b_val = 0; + GET_ANNOTATIONS_VALUES(GetItemAnnotationDouble, + GetPageAnnotationDouble, &a_val, &b_val); value = (a < b) ? -1 : (a > b) ? 1 : 0; } } @@ -968,7 +1015,7 @@ nsNavHistoryContainerResultNode::FindChildFolder(PRInt64 aFolderId, for (PRInt32 i = 0; i < mChildren.Count(); i ++) { if (mChildren[i]->IsFolder()) { nsNavHistoryFolderResultNode* folder = mChildren[i]->GetAsFolder(); - if (folder->mFolderId == aFolderId) { + if (folder->mItemId == aFolderId) { *aNodeIndex = i; return folder; } @@ -2403,7 +2450,7 @@ nsNavHistoryQueryResultNode::OnPageExpired(nsIURI* aURI, PRTime aVisitTime, // the bookmark system. NS_IMETHODIMP -nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aBookmarkId, nsIURI* aBookmark, PRInt64 aFolder, +nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { if (mLiveUpdate == QUERYUPDATE_COMPLEX_WITH_BOOKMARKS) @@ -2411,7 +2458,7 @@ nsNavHistoryQueryResultNode::OnItemAdded(PRInt64 aBookmarkId, nsIURI* aBookmark, return NS_OK; } NS_IMETHODIMP -nsNavHistoryQueryResultNode::OnItemRemoved(PRInt64 aBookmarkId, nsIURI* aBookmark, PRInt64 aFolder, +nsNavHistoryQueryResultNode::OnItemRemoved(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { if (mLiveUpdate == QUERYUPDATE_COMPLEX_WITH_BOOKMARKS) @@ -2419,15 +2466,16 @@ nsNavHistoryQueryResultNode::OnItemRemoved(PRInt64 aBookmarkId, nsIURI* aBookmar return NS_OK; } NS_IMETHODIMP -nsNavHistoryQueryResultNode::OnItemChanged(PRInt64 aBookmarkId, nsIURI* aBookmark, - const nsACString& aProperty, - const nsAString& aValue) +nsNavHistoryQueryResultNode::OnItemChanged(PRInt64 aItemId, + const nsACString& aProperty, + PRBool aIsAnnotationProperty, + const nsACString& aValue) { NS_NOTREACHED("Everything observers should not get OnItemChanged, but should get the corresponding history notifications instead"); return NS_OK; } NS_IMETHODIMP -nsNavHistoryQueryResultNode::OnItemVisited(PRInt64 aBookmarkId, nsIURI* aBookmark, +nsNavHistoryQueryResultNode::OnItemVisited(PRInt64 aItemId, PRInt64 aVisitId, PRTime aTime) { NS_NOTREACHED("Everything observers should not get OnItemVisited, but should get OnVisit instead"); @@ -2524,9 +2572,10 @@ nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode( nsNavHistoryResultNode::RESULT_TYPE_FOLDER, PR_FALSE, aRemoteContainerType), mContentsValid(PR_FALSE), - mOptions(aOptions), - mFolderId(aFolderId) + mOptions(aOptions) { + mItemId = aFolderId; + // Get the favicon, if any, for this folder. Errors aren't too important // here, so just give up if anything bad happens. // @@ -2648,7 +2697,7 @@ nsNavHistoryFolderResultNode::GetChildrenReadOnly(PRBool *aChildrenReadOnly) { nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED); - return bookmarks->GetFolderReadonly(mFolderId, aChildrenReadOnly); + return bookmarks->GetFolderReadonly(mItemId, aChildrenReadOnly); } @@ -2695,7 +2744,7 @@ nsNavHistoryFolderResultNode::GetQueries(PRUint32* queryCount, NS_ENSURE_SUCCESS(rv, rv); // query just has the folder ID set and nothing else - rv = query->SetFolders(&mFolderId, 1); + rv = query->SetFolders(&mItemId, 1); NS_ENSURE_SUCCESS(rv, rv); // make array of our 1 query @@ -2742,7 +2791,7 @@ nsNavHistoryFolderResultNode::FillChildren() NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); // actually get the folder children from the bookmark service - nsresult rv = bookmarks->QueryFolderChildren(mFolderId, mOptions, &mChildren); + nsresult rv = bookmarks->QueryFolderChildren(mItemId, mOptions, &mChildren); NS_ENSURE_SUCCESS(rv, rv); // PERFORMANCE: it may be better to also fill any child folders at this point @@ -2767,7 +2816,7 @@ nsNavHistoryFolderResultNode::FillChildren() // register with the result for updates nsNavHistoryResult* result = GetResult(); NS_ENSURE_TRUE(result, NS_ERROR_FAILURE); - result->AddBookmarkObserver(this, mFolderId); + result->AddBookmarkObserver(this, mItemId); mContentsValid = PR_TRUE; return NS_OK; @@ -2788,7 +2837,7 @@ nsNavHistoryFolderResultNode::ClearChildren(PRBool unregister) if (unregister && mContentsValid) { nsNavHistoryResult* result = GetResult(); if (result) - result->RemoveBookmarkObserver(this, mFolderId); + result->RemoveBookmarkObserver(this, mItemId); } mContentsValid = PR_FALSE; } @@ -2882,11 +2931,11 @@ nsNavHistoryFolderResultNode::ReindexRange(PRInt32 aStartIndex, // found. Does not addref the node! nsNavHistoryResultNode* -nsNavHistoryFolderResultNode::FindChildURIById(PRInt64 aBookmarkId, +nsNavHistoryFolderResultNode::FindChildURIById(PRInt64 aItemId, PRUint32* aNodeIndex) { for (PRInt32 i = 0; i < mChildren.Count(); i ++) { - if (mChildren[i]->mBookmarkId == aBookmarkId) { + if (mChildren[i]->mItemId == aItemId) { *aNodeIndex = i; return mChildren[i]; } @@ -2916,10 +2965,10 @@ nsNavHistoryFolderResultNode::OnEndUpdateBatch() // nsNavHistoryFolderResultNode::OnItemAdded (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aBookmarkId, nsIURI* aBookmark, +nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { - NS_ASSERTION(aFolder == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aFolder == mItemId, "Got wrong bookmark update"); if (mOptions->ExcludeItems()) { // don't update items when we aren't displaying them, but we still need // to adjust bookmark indices to account for the insertion @@ -2946,10 +2995,10 @@ nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aBookmarkId, nsIURI* aBookmark NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY); nsNavHistoryResultNode* node; - nsresult rv = history->BookmarkIdToResultNode(aBookmarkId, mOptions, &node); + nsresult rv = history->BookmarkIdToResultNode(aItemId, mOptions, &node); NS_ENSURE_SUCCESS(rv, rv); node->mBookmarkIndex = aIndex; - node->mBookmarkId = aBookmarkId; + node->mItemId = aItemId; if (GetSortType() == nsINavHistoryQueryOptions::SORT_BY_NONE) { // insert at natural bookmarks position @@ -2963,10 +3012,10 @@ nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aBookmarkId, nsIURI* aBookmark // nsNavHistoryFolderResultNode::OnItemRemoved (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryFolderResultNode::OnItemRemoved(PRInt64 aBookmarkId, nsIURI* aBookmark, +nsNavHistoryFolderResultNode::OnItemRemoved(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { - NS_ASSERTION(aFolder == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aFolder == mItemId, "Got wrong bookmark update"); if (mOptions->ExcludeItems()) { // don't update items when we aren't displaying them, but we do need to // adjust everybody's bookmark indices to account for the removal @@ -2983,7 +3032,7 @@ nsNavHistoryFolderResultNode::OnItemRemoved(PRInt64 aBookmarkId, nsIURI* aBookma // sorting could be different, or the bookmark services indices and ours might // be out of sync somehow. PRUint32 nodeIndex; - nsNavHistoryResultNode* node = FindChildURIById(aBookmarkId, &nodeIndex); + nsNavHistoryResultNode* node = FindChildURIById(aItemId, &nodeIndex); if (! node) return NS_ERROR_FAILURE; // can't find it @@ -2994,9 +3043,10 @@ nsNavHistoryFolderResultNode::OnItemRemoved(PRInt64 aBookmarkId, nsIURI* aBookma // nsNavHistoryFolderResultNode::OnItemChanged (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aBookmarkId, nsIURI* aBookmark, +nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aItemId, const nsACString& aProperty, - const nsAString& aValue) + PRBool aIsAnnotationProperty, + const nsACString& aValue) { if (mOptions->ExcludeItems()) return NS_OK; // don't update items when we aren't displaying them @@ -3004,26 +3054,23 @@ nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aBookmarkId, nsIURI* aBookma return NS_OK; PRUint32 nodeIndex; - nsNavHistoryResultNode* node = FindChildURIById(aBookmarkId, &nodeIndex); + nsNavHistoryResultNode* node = FindChildURIById(aItemId, &nodeIndex); if (!node) return NS_ERROR_FAILURE; if (aProperty.EqualsLiteral("title")) { - node->mTitle = NS_ConvertUTF16toUTF8(aValue); + node->mTitle = aValue; } else if (aProperty.EqualsLiteral("uri")) { - nsCAutoString spec; - nsresult rv = aBookmark->GetSpec(spec); - NS_ENSURE_SUCCESS(rv, rv); - node->mURI = spec; + node->mURI = aValue; } else if (aProperty.EqualsLiteral("favicon")) { - node->mFaviconURI = NS_ConvertUTF16toUTF8(aValue); + node->mFaviconURI = aValue; } else if (aProperty.EqualsLiteral("cleartime")) { node->mTime = 0; } - else { + else if (!aIsAnnotationProperty){ NS_NOTREACHED("Unknown bookmark property changing."); } @@ -3056,7 +3103,7 @@ nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aBookmarkId, nsIURI* aBookma // Update visit count and last visit time and refresh. NS_IMETHODIMP -nsNavHistoryFolderResultNode::OnItemVisited(PRInt64 aBookmarkId, nsIURI* aBookmark, +nsNavHistoryFolderResultNode::OnItemVisited(PRInt64 aItemId, PRInt64 aVisitId, PRTime aTime) { if (mOptions->ExcludeItems()) @@ -3065,7 +3112,7 @@ nsNavHistoryFolderResultNode::OnItemVisited(PRInt64 aBookmarkId, nsIURI* aBookma return NS_OK; PRUint32 nodeIndex; - nsNavHistoryResultNode* node = FindChildURIById(aBookmarkId, &nodeIndex); + nsNavHistoryResultNode* node = FindChildURIById(aItemId, &nodeIndex); if (! node) return NS_ERROR_FAILURE; @@ -3117,7 +3164,7 @@ NS_IMETHODIMP nsNavHistoryFolderResultNode::OnFolderAdded(PRInt64 aFolder, PRInt64 aParent, PRInt32 aIndex) { - NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aParent == mItemId, "Got wrong bookmark update"); if (! StartIncrementalUpdate()) return NS_OK; // folder was completely refreshed for us @@ -3150,10 +3197,10 @@ nsNavHistoryFolderResultNode::OnFolderRemoved(PRInt64 aFolder, PRInt64 aParent, // We only care about notifications when a child changes. When the deleted // folder is us, our parent should also be registered and will remove us from // its list. - if (mFolderId == aFolder) + if (mItemId == aFolder) return NS_OK; - NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aParent == mItemId, "Got wrong bookmark update"); if (! StartIncrementalUpdate()) return NS_OK; // we are completely refreshed @@ -3177,7 +3224,7 @@ nsNavHistoryFolderResultNode::OnFolderMoved(PRInt64 aFolder, PRInt64 aOldParent, PRInt32 aOldIndex, PRInt64 aNewParent, PRInt32 aNewIndex) { - NS_ASSERTION(aOldParent == mFolderId || aNewParent == mFolderId, + NS_ASSERTION(aOldParent == mItemId || aNewParent == mItemId, "Got a bookmark message that doesn't belong to us"); if (! StartIncrementalUpdate()) return NS_OK; // entire container was refreshed for us @@ -3218,9 +3265,9 @@ nsNavHistoryFolderResultNode::OnFolderMoved(PRInt64 aFolder, PRInt64 aOldParent, } else { // moving between two different folders, just do a remove and an add - if (aOldParent == mFolderId) + if (aOldParent == mItemId) OnFolderRemoved(aFolder, aOldParent, aOldIndex); - if (aNewParent == mFolderId) + if (aNewParent == mItemId) OnFolderAdded(aFolder, aNewParent, aNewIndex); } return NS_OK; @@ -3247,7 +3294,7 @@ nsNavHistoryFolderResultNode::OnFolderChanged(PRInt64 aFolder, NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); nsAutoString title; - bookmarks->GetFolderTitle(mFolderId, title); + bookmarks->GetFolderTitle(mItemId, title); mTitle = NS_ConvertUTF16toUTF8(title); PRInt32 sortType = GetSortType(); @@ -3288,7 +3335,7 @@ nsNavHistoryFolderResultNode::OnFolderChanged(PRInt64 aFolder, NS_IMETHODIMP nsNavHistoryFolderResultNode::OnSeparatorAdded(PRInt64 aParent, PRInt32 aIndex) { - NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aParent == mItemId, "Got wrong bookmark update"); if (mOptions->ExcludeItems()) { // don't update items when we aren't displaying them, except we need to // update the indices @@ -3317,7 +3364,7 @@ NS_IMETHODIMP nsNavHistoryFolderResultNode::OnSeparatorRemoved(PRInt64 aParent, PRInt32 aIndex) { - NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update"); + NS_ASSERTION(aParent == mItemId, "Got wrong bookmark update"); if (mOptions->ExcludeItems()) { // don't update items when we aren't displaying them, except we need to // update everybody's indices @@ -3716,14 +3763,13 @@ nsNavHistoryResult::OnEndUpdateBatch() // nsNavHistoryResult::OnItemAdded (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryResult::OnItemAdded(PRInt64 aBookmarkId, - nsIURI *aBookmark, +nsNavHistoryResult::OnItemAdded(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(aFolder, - OnItemAdded(aBookmarkId, aBookmark, aFolder, aIndex)); - ENUMERATE_HISTORY_OBSERVERS(OnItemAdded(aBookmarkId, aBookmark, aFolder, aIndex)); + OnItemAdded(aItemId, aFolder, aIndex)); + ENUMERATE_HISTORY_OBSERVERS(OnItemAdded(aItemId, aFolder, aIndex)); return NS_OK; } @@ -3731,12 +3777,12 @@ nsNavHistoryResult::OnItemAdded(PRInt64 aBookmarkId, // nsNavHistoryResult::OnItemRemoved (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryResult::OnItemRemoved(PRInt64 aBookmarkId, nsIURI *aBookmark, +nsNavHistoryResult::OnItemRemoved(PRInt64 aItemId, PRInt64 aFolder, PRInt32 aIndex) { ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(aFolder, - OnItemRemoved(aBookmarkId, aBookmark, aFolder, aIndex)); - ENUMERATE_HISTORY_OBSERVERS(OnItemRemoved(aBookmarkId, aBookmark, aFolder, aIndex)); + OnItemRemoved(aItemId, aFolder, aIndex)); + ENUMERATE_HISTORY_OBSERVERS(OnItemRemoved(aItemId, aFolder, aIndex)); return NS_OK; } @@ -3744,9 +3790,10 @@ nsNavHistoryResult::OnItemRemoved(PRInt64 aBookmarkId, nsIURI *aBookmark, // nsNavHistoryResult::OnItemChanged (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryResult::OnItemChanged(PRInt64 aBookmarkId, nsIURI *aBookmark, +nsNavHistoryResult::OnItemChanged(PRInt64 aItemId, const nsACString &aProperty, - const nsAString &aValue) + PRBool aIsAnnotationProperty, + const nsACString &aValue) { nsresult rv; nsNavBookmarks* bookmarkService = nsNavBookmarks::GetBookmarksService(); @@ -3754,10 +3801,10 @@ nsNavHistoryResult::OnItemChanged(PRInt64 aBookmarkId, nsIURI *aBookmark, // find the folder to notify about this item PRInt64 folderId; - rv = bookmarkService->GetFolderIdForItem(aBookmarkId, &folderId); + rv = bookmarkService->GetFolderIdForItem(aItemId, &folderId); NS_ENSURE_SUCCESS(rv, rv); ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(folderId, - OnItemChanged(aBookmarkId, aBookmark, aProperty, aValue)); + OnItemChanged(aItemId, aProperty, aIsAnnotationProperty, aValue)); // Note: we do NOT call history observers in this case. This notification is // the same as other history notification, except that here we know the item @@ -3770,8 +3817,8 @@ nsNavHistoryResult::OnItemChanged(PRInt64 aBookmarkId, nsIURI *aBookmark, // nsNavHistoryResult::OnItemVisited (nsINavBookmarkObserver) NS_IMETHODIMP -nsNavHistoryResult::OnItemVisited(PRInt64 aBookmarkId, nsIURI* aBookmark, - PRInt64 aVisitId, PRTime aVisitTime) +nsNavHistoryResult::OnItemVisited(PRInt64 aItemId, PRInt64 aVisitId, + PRTime aVisitTime) { nsresult rv; nsNavBookmarks* bookmarkService = nsNavBookmarks::GetBookmarksService(); @@ -3779,10 +3826,10 @@ nsNavHistoryResult::OnItemVisited(PRInt64 aBookmarkId, nsIURI* aBookmark, // find the folder to notify about this item PRInt64 folderId; - rv = bookmarkService->GetFolderIdForItem(aBookmarkId, &folderId); + rv = bookmarkService->GetFolderIdForItem(aItemId, &folderId); NS_ENSURE_SUCCESS(rv, rv); ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(folderId, - OnItemVisited(aBookmarkId, aBookmark, aVisitId, aVisitTime)); + OnItemVisited(aItemId, aVisitId, aVisitTime)); // Note: we do NOT call history observers in this case. This notification is // the same as OnVisit, except that here we know the item is a bookmark. diff --git a/toolkit/components/places/src/nsNavHistoryResult.h b/toolkit/components/places/src/nsNavHistoryResult.h index 1694cc52db1..51d46ce1ea4 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.h +++ b/toolkit/components/places/src/nsNavHistoryResult.h @@ -224,8 +224,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) { mViewIndex = aViewIndex; return NS_OK; } \ NS_IMETHOD GetBookmarkIndex(PRInt32* aIndex) \ { *aIndex = mBookmarkIndex; return NS_OK; } \ - NS_IMETHOD GetBookmarkId(PRInt64* aId) \ - { *aId= mBookmarkId; return NS_OK; } + NS_IMETHOD GetItemId(PRInt64* aId) \ + { *aId= mItemId; return NS_OK; } // This is used by the base classes instead of // NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they @@ -364,7 +364,7 @@ public: PRInt64 mTime; nsCString mFaviconURI; PRInt32 mBookmarkIndex; - PRInt64 mBookmarkId; + PRInt64 mItemId; // The indent level of this node. The root node will have a value of -1. The // root's children will have a value of 0, and so on. @@ -707,7 +707,7 @@ public: NS_DECL_NSINAVHISTORYQUERYRESULTNODE NS_IMETHOD GetFolderId(PRInt64* aFolderId) - { *aFolderId = mFolderId; return NS_OK; } + { *aFolderId = mItemId; return NS_OK; } virtual nsresult OpenContainer(); @@ -725,7 +725,6 @@ public: PRBool mContentsValid; nsCOMPtr mOptions; - PRInt64 mFolderId; nsresult FillChildren(); void ClearChildren(PRBool aUnregister); @@ -734,7 +733,7 @@ public: PRBool StartIncrementalUpdate(); void ReindexRange(PRInt32 aStartIndex, PRInt32 aEndIndex, PRInt32 aDelta); - nsNavHistoryResultNode* FindChildURIById(PRInt64 aBookmarkId, + nsNavHistoryResultNode* FindChildURIById(PRInt64 aItemId, PRUint32* aNodeIndex); }; diff --git a/toolkit/components/places/tests/bookmarks/test_bookmarks.js b/toolkit/components/places/tests/bookmarks/test_bookmarks.js index c936eb806b0..0dee7284ae2 100644 --- a/toolkit/components/places/tests/bookmarks/test_bookmarks.js +++ b/toolkit/components/places/tests/bookmarks/test_bookmarks.js @@ -51,6 +51,13 @@ try { do_throw("Could not get history service\n"); } +// Get annotation service +try { + var annosvc= Cc["@mozilla.org/browser/annotation-service;1"].getService(Ci.nsIAnnotationService); +} catch(ex) { + do_throw("Could not get annotation service\n"); +} + // create and add bookmarks observer var observer = { onBeginUpdateBatch: function() { @@ -59,27 +66,25 @@ var observer = { onEndUpdateBatch: function() { this._endUpdateBatch = true; }, - onItemAdded: function(id, uri, folder, index) { - this._itemAdded = uri; + onItemAdded: function(id, folder, index) { this._itemAddedId = id; this._itemAddedFolder = folder; this._itemAddedIndex = index; }, - onItemRemoved: function(id, uri, folder, index) { - this._itemRemoved = uri; + onItemRemoved: function(id, folder, index) { this._itemRemovedId = id; this._itemRemovedFolder = folder; this._itemRemovedIndex = index; }, - onItemChanged: function(id, uri, property, value) { + onItemChanged: function(id, property, isAnnotationProperty, value) { this._itemChangedId = id; - this._itemChanged = uri; this._itemChangedProperty = property; + this._itemChanged_isAnnotationProperty = isAnnotationProperty; this._itemChangedValue = value; }, - onItemVisited: function(uri, visitID, time) { - this._itemVisited = uri; - this._itemVisitedID = visitID; + onItemVisited: function(id, visitID, time) { + this._itemVisitedId = id; + this._itemVisitedVistId = visitID; this._itemVisitedTime = time; }, onFolderAdded: function(folder, parent, index) { @@ -151,14 +156,13 @@ function run_test() { // insert a bookmark var newId = bmsvc.insertItem(testRoot, uri("http://google.com/"), bmsvc.DEFAULT_INDEX); do_check_eq(observer._itemAddedId, newId); - do_check_eq(observer._itemAdded.spec, "http://google.com/"); do_check_eq(observer._itemAddedFolder, testRoot); do_check_eq(observer._itemAddedIndex, testStartIndex); + do_check_eq(bmsvc.getBookmarkURI(newId).spec, "http://google.com/"); // set bookmark title bmsvc.setItemTitle(newId, "Google"); do_check_eq(observer._itemChangedId, newId); - do_check_eq(observer._itemChanged.spec, "http://google.com/"); do_check_eq(observer._itemChangedProperty, "title"); do_check_eq(observer._itemChangedValue, "Google"); @@ -196,38 +200,32 @@ function run_test() { // add item into subfolder, specifying index var newId2 = bmsvc.insertItem(workFolder, uri("http://developer.mozilla.org/"), 0); do_check_eq(observer._itemAddedId, newId2); - do_check_eq(observer._itemAdded.spec, "http://developer.mozilla.org/"); do_check_eq(observer._itemAddedFolder, workFolder); do_check_eq(observer._itemAddedIndex, 0); // change item bmsvc.setItemTitle(newId2, "DevMo"); - do_check_eq(observer._itemChanged.spec, "http://developer.mozilla.org/"); do_check_eq(observer._itemChangedProperty, "title"); // insert item into subfolder var newId3 = bmsvc.insertItem(workFolder, uri("http://msdn.microsoft.com/"), bmsvc.DEFAULT_INDEX); do_check_eq(observer._itemAddedId, newId3); - do_check_eq(observer._itemAdded.spec, "http://msdn.microsoft.com/"); do_check_eq(observer._itemAddedFolder, workFolder); do_check_eq(observer._itemAddedIndex, 1); // change item bmsvc.setItemTitle(newId3, "MSDN"); - do_check_eq(observer._itemChanged.spec, "http://msdn.microsoft.com/"); do_check_eq(observer._itemChangedProperty, "title"); // remove item bmsvc.removeItem(newId2); do_check_eq(observer._itemRemovedId, newId2); - do_check_eq(observer._itemRemoved.spec, "http://developer.mozilla.org/"); do_check_eq(observer._itemRemovedFolder, workFolder); do_check_eq(observer._itemRemovedIndex, 0); // insert item into subfolder var newId4 = bmsvc.insertItem(workFolder, uri("http://developer.mozilla.org/"), bmsvc.DEFAULT_INDEX); do_check_eq(observer._itemAddedId, newId4); - do_check_eq(observer._itemAdded.spec, "http://developer.mozilla.org/"); do_check_eq(observer._itemAddedFolder, workFolder); do_check_eq(observer._itemAddedIndex, 1); @@ -240,24 +238,21 @@ function run_test() { // insert item var newId5 = bmsvc.insertItem(homeFolder, uri("http://espn.com/"), bmsvc.DEFAULT_INDEX); do_check_eq(observer._itemAddedId, newId5); - do_check_eq(observer._itemAdded.spec, "http://espn.com/"); do_check_eq(observer._itemAddedFolder, homeFolder); do_check_eq(observer._itemAddedIndex, 0); // change item bmsvc.setItemTitle(newId5, "ESPN"); - do_check_eq(observer._itemChanged.spec, "http://espn.com/"); + do_check_eq(observer._itemChangedId, newId5); do_check_eq(observer._itemChangedProperty, "title"); // insert query item var newId6 = bmsvc.insertItem(testRoot, uri("place:domain=google.com&group=1"), bmsvc.DEFAULT_INDEX); - do_check_eq(observer._itemAdded.spec, "place:domain=google.com&group=1"); do_check_eq(observer._itemAddedFolder, testRoot); do_check_eq(observer._itemAddedIndex, 3); // change item bmsvc.setItemTitle(newId6, "Google Sites"); - do_check_eq(observer._itemChanged.spec, "place:domain=google.com&group=1"); do_check_eq(observer._itemChangedProperty, "title"); // move folder, appending, to different folder @@ -396,9 +391,9 @@ function run_test() { for (var i=0; i < cc; ++i) { var node = rootNode.getChild(i); if (node.type == node.RESULT_TYPE_FOLDER) - do_check_eq(node.bookmarkId, -1); + do_check_eq(node.itemId, -1); else - do_check_true(node.bookmarkId > 0); + do_check_true(node.itemId > 0); } rootNode.containerOpen = false; } @@ -441,9 +436,8 @@ function run_test() { var newId10 = bmsvc.insertItem(testRoot, uri("http://foo10.com/"), bmsvc.DEFAULT_INDEX); bmsvc.changeBookmarkURI(newId10, uri("http://foo11.com/")); do_check_eq(observer._itemChangedId, newId10); - do_check_eq(observer._itemChanged.spec, "http://foo11.com/"); do_check_eq(observer._itemChangedProperty, "uri"); - do_check_eq(observer._itemChangedValue, ""); + do_check_eq(observer._itemChangedValue, "http://foo11.com/"); // test getBookmarkURI var newId11 = bmsvc.insertItem(testRoot, uri("http://foo11.com/"), bmsvc.DEFAULT_INDEX); @@ -467,7 +461,6 @@ function run_test() { bmsvc.toolbarFolder = newToolbarFolderId; do_check_eq(bmsvc.toolbarFolder, newToolbarFolderId); do_check_eq(observer._itemChangedId, newToolbarFolderId); - do_check_eq(observer._itemChanged.spec, bmsvc.getFolderURI(newToolbarFolderId).spec); do_check_eq(observer._itemChangedProperty, "became_toolbar_folder"); do_check_eq(observer._itemChangedValue, ""); @@ -477,17 +470,23 @@ function run_test() { // see bug #369887 for more details var newId13 = bmsvc.insertItem(testRoot, uri("http://foobarcheese.com/"), bmsvc.DEFAULT_INDEX); do_check_eq(observer._itemAddedId, newId13); - do_check_eq(observer._itemAdded.spec, "http://foobarcheese.com/"); do_check_eq(observer._itemAddedFolder, testRoot); do_check_eq(observer._itemAddedIndex, 13); // set bookmark title bmsvc.setItemTitle(newId13, "ZZZXXXYYY"); do_check_eq(observer._itemChangedId, newId13); - do_check_eq(observer._itemChanged.spec, "http://foobarcheese.com/"); do_check_eq(observer._itemChangedProperty, "title"); do_check_eq(observer._itemChangedValue, "ZZZXXXYYY"); + // check if setting an item annotation triggers onItemChanged + observer._itemChangedId = -1; + annosvc.setItemAnnotationString(newId3, "test-annotation", "foo", 0, 0); + do_check_eq(observer._itemChangedId, newId3); + do_check_eq(observer._itemChangedProperty, "test-annotation"); + do_check_true(observer._itemChanged_isAnnotationProperty); + do_check_eq(observer._itemChangedValue, ""); + // test search on bookmark title ZZZXXXYYY try { var options = histsvc.getNewQueryOptions(); @@ -503,13 +502,18 @@ function run_test() { do_check_eq(cc, 1); var node = rootNode.getChild(0); do_check_eq(node.title, "ZZZXXXYYY"); - do_check_true(node.bookmarkId > 0); + do_check_true(node.itemId > 0); rootNode.containerOpen = false; } catch(ex) { do_throw("bookmarks query: " + ex); } + // ensure that removing an item removes its annotations + do_check_true(annosvc.itemHasAnnotation(newId3, "test-annotation")); + bmsvc.removeItem(newId3); + do_check_false(annosvc.itemHasAnnotation(newId3, "test-annotation")); + // bug 378820 var uri1 = uri("http://foo.tld/a"); bmsvc.insertItem(testRoot, uri1, bmsvc.DEFAULT_INDEX); diff --git a/toolkit/components/places/tests/chrome/test_371798.xul b/toolkit/components/places/tests/chrome/test_371798.xul index 3183d8e5ac1..0105c4699a6 100644 --- a/toolkit/components/places/tests/chrome/test_371798.xul +++ b/toolkit/components/places/tests/chrome/test_371798.xul @@ -62,7 +62,7 @@ var observer = onEndUpdateBatch: function(){}, onItemAdded: function(bookmarkId, bookmark, folder, index) {}, onItemRemoved: function(bookmarkId, bookmark, folder, index){}, - onItemChanged: function(bookmarkId, bookmark, property, value){ + onItemChanged: function(bookmarkId, property, isAnnotationProperty, value){ runTest(); bmsvc.removeObserver(this); }, @@ -93,7 +93,7 @@ function runTest() { for (var i=0; i < cc; ++i) { var node = rootNode.getChild(i); // test that bm1 does not have new title - if (node.bookmarkId == bm1) + if (node.itemId == bm1) ok(node.title != newTitle, "Changing a bookmark's title did not affect the title of other bookmarks with the same URI"); } diff --git a/toolkit/components/places/tests/chrome/test_add_livemark.xul b/toolkit/components/places/tests/chrome/test_add_livemark.xul index 7883efdc7eb..6bd5cff79fa 100644 --- a/toolkit/components/places/tests/chrome/test_add_livemark.xul +++ b/toolkit/components/places/tests/chrome/test_add_livemark.xul @@ -49,16 +49,16 @@ var observer = // nsINavBookmarkObserve onBeginUpdateBatch: function(){}, onEndUpdateBatch: function(){}, - onItemAdded: function(bookmarkId, bookmark, folder, index) { - if (bookmark.spec == "http://example.org/2003/12/13/atom03") { + onItemAdded: function(itemId, folder, index) { + if (bmsvc.getBookmarkURI(itemId).spec == "http://example.org/2003/12/13/atom03") { is(folder, gLivemarkId, "Livemark added to correct folder"); - this._lastBookmarkId = bookmarkId; + this._lastBookmarkId = itemId; bmsvc.removeObserver(this); } }, - onItemRemoved: function(bookmarkId, bookmark, folder, index){}, - onItemChanged: function(bookmarkId, bookmark, property, value){}, - onItemVisited: function(bookmarkId, bookmark, aVisitID, time){}, + onItemRemoved: function(itemId, folder, index){}, + onItemChanged: function(itemId, property, isAnnotationProperty, value){}, + onItemVisited: function(itemId, aVisitID, time){}, onFolderAdded: function(folder, parent, index){}, onFolderRemoved: function(folder, parent, index){}, onFolderMoved: function(folder, oldParent, oldIndex, newParent, newIndex){}, @@ -67,18 +67,20 @@ var observer = onSeparatorRemoved: function(parent, index){}, // nsIAnnotationObserver - onAnnotationSet: function(uri, name) { - if (name == "livemark/bookmarkFeedURI") { + onItemAnnotationSet: function(aItemId, aAnnotationName) { + if (aAnnotationName == "livemark/bookmarkFeedURI") { ok("_lastBookmarkId" in this, "Unexpected livemark/bookmarkFeedURI annotation set"); - var placeURI = bmsvc.getItemURI(this._lastBookmarkId); - ok(placeURI.equals(uri), - "livemark/bookmarkFeedURI annotation set on the wrong URI"); + ok(this._lastBookmarkId == aItemId, + "livemark/bookmarkFeedURI annotation set on the wrong item"); annosvc.removeObserver(this); SimpleTest.finish(); } }, - onAnnotationRemoved: function(uri, name) { } + + onItemAnnotationRemoved: function(aItemId, aAnnotationName) { }, + onPageAnnotationSet: function(uri, name) { }, + onPageAnnotationRemoved: function(uri, name) { } }; var root = bmsvc.bookmarksRoot; diff --git a/toolkit/components/places/tests/unit/test_annotations.js b/toolkit/components/places/tests/unit/test_annotations.js index 8275ff03711..d4ad7577717 100644 --- a/toolkit/components/places/tests/unit/test_annotations.js +++ b/toolkit/components/places/tests/unit/test_annotations.js @@ -22,6 +22,7 @@ * Contributor(s): * Darin Fisher * Dietrich Ayala + * Asaf Romano * * 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 @@ -42,42 +43,123 @@ try { var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService); } catch(ex) { do_throw("Could not get history service\n"); -} +} + +// Get bookmark service +try { + var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService); +} catch(ex) { + do_throw("Could not get nav-bookmarks-service\n"); +} // Get annotation service try { var annosvc= Cc["@mozilla.org/browser/annotation-service;1"].getService(Ci.nsIAnnotationService); } catch(ex) { do_throw("Could not get annotation service\n"); -} +} + +var annoObserver = { + PAGE_lastSet_URI: "", + PAGE_lastSet_AnnoName: "", + + onPageAnnotationSet: function(aURI, aName) { + this.PAGE_lastSet_URI = aURI.spec; + this.PAGE_lastSet_AnnoName = aName; + }, + + ITEM_lastSet_Id: -1, + ITEM_lastSet_AnnoName: "", + onItemAnnotationSet: function(aItemId, aName) { + this.ITEM_lastSet_Id = aItemId; + this.ITEM_lastSet_AnnoName = aName; + }, + + PAGE_lastRemoved_URI: "", + PAGE_lastRemoved_AnnoName: "", + onPageAnnotationRemoved: function(aURI, aName) { + this.PAGE_lastRemoved_URI = aURI.spec; + this.PAGE_lastRemoved_AnnoName = aName; + }, + + ITEM_lastRemoved_Id: -1, + ITEM_lastRemoved_AnnoName: "", + onItemAnnotationRemoved: function(aItemId, aName) { + this.ITEM_lastRemoved_Id = aItemId; + this.ITEM_lastRemoved_AnnoName = aName; + } +}; // main function run_test() { - // test URI var testURI = uri("http://mozilla.com/"); + var testItemId = bmsvc.insertItem(bmsvc.bookmarksRoot, testURI, -1); var testAnnoName = "moz-test-places/annotations"; var testAnnoVal = "test"; + annosvc.addObserver(annoObserver); + // create new string annotation try { - annosvc.setAnnotationString(testURI, testAnnoName, testAnnoVal, 0, 0); + annosvc.setPageAnnotationString(testURI, testAnnoName, testAnnoVal, 0, 0); } catch(ex) { - do_throw("unable to add annotation"); + do_throw("unable to add page-annotation"); } + do_check_eq(annoObserver.PAGE_lastSet_URI, testURI.spec); + do_check_eq(annoObserver.PAGE_lastSet_AnnoName, testAnnoName); // get string annotation - var storedAnnoVal = annosvc.getAnnotationString(testURI, testAnnoName); + do_check_true(annosvc.pageHasAnnotation(testURI, testAnnoName)); + var storedAnnoVal = annosvc.getPageAnnotationString(testURI, testAnnoName); do_check_eq(testAnnoVal, storedAnnoVal); + // string item-annotation + try { + annosvc.setItemAnnotationString(testItemId, testAnnoName, testAnnoVal, 0, 0); + } catch(ex) { + do_throw("unable to add item annotation"); + } + do_check_eq(annoObserver.ITEM_lastSet_Id, testItemId); + do_check_eq(annoObserver.ITEM_lastSet_AnnoName, testAnnoName); + + // test getPagesWithAnnotation + var uri2 = uri("http://www.tests.tld"); + annosvc.setPageAnnotationString(uri2, testAnnoName, testAnnoVal, 0, 0); + var pages = annosvc.getPagesWithAnnotation(testAnnoName, { }); + do_check_eq(pages.length, 2); + // Don't rely on the order + do_check_false(pages[0].equals(pages[1])); + do_check_true(pages[0].equals(testURI) || pages[1].equals(testURI)); + do_check_true(pages[0].equals(uri2) || pages[1].equals(uri2)); + + // test getItemsWithAnnotation + var testItemId2 = bmsvc.insertItem(bmsvc.bookmarksRoot, uri2, -1); + annosvc.setItemAnnotationString(testItemId2, testAnnoName, testAnnoVal, 0, 0); + var items = annosvc.getItemsWithAnnotation(testAnnoName, { }); + do_check_eq(items.length, 2); + // Don't rely on the order + do_check_true(items[0] != items[1]); + do_check_true(items[0] == testItemId || items[1] == testItemId); + do_check_true(items[0] == testItemId2 || items[1] == testItemId2); + // get annotation that doesn't exist try { - annosvc.getAnnotationString(testURI, "blah"); - do_throw("fetching annotation that doesn't exist, should've thrown"); + annosvc.getPageAnnotationString(testURI, "blah"); + do_throw("fetching page-annotation that doesn't exist, should've thrown"); + } catch(ex) {} + try { + annosvc.getItemAnnotationString(testURI, "blah"); + do_throw("fetching item-annotation that doesn't exist, should've thrown"); } catch(ex) {} // get annotation info var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(testURI, testAnnoName, flags, exp, mimeType, storageType); + annosvc.getPageAnnotationInfo(testURI, testAnnoName, flags, exp, mimeType, storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_STRING); + annosvc.getItemAnnotationInfo(testItemId, testAnnoName, flags, exp, mimeType, storageType); do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, null); @@ -88,6 +170,11 @@ function run_test() { do_check_eq(annoNames.length, 1); do_check_eq(annoNames[0], "moz-test-places/annotations"); + // get annotation names for an item + var annoNames = annosvc.getItemAnnotationNames(testItemId, {}); + do_check_eq(annoNames.length, 1); + do_check_eq(annoNames[0], "moz-test-places/annotations"); + /* copy annotations to another uri var newURI = uri("http://mozilla.org"); var oldAnnoNames = annosvc.getPageAnnotationNames(testURI, {}); @@ -99,84 +186,143 @@ function run_test() { // test int32 anno type var int32Key = testAnnoName + "/types/Int32"; var int32Val = 23; - annosvc.setAnnotationInt32(testURI, int32Key, int32Val, 0, 0); + annosvc.setPageAnnotationInt32(testURI, int32Key, int32Val, 0, 0); + do_check_true(annosvc.pageHasAnnotation(testURI, int32Key)); var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(testURI, int32Key, flags, exp, mimeType, storageType); + annosvc.getPageAnnotationInfo(testURI, int32Key, flags, exp, mimeType, + storageType); do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, null); do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT32); - var storedVal = annosvc.getAnnotationInt32(testURI, int32Key); - do_check_eq(int32Val, storedVal); - do_check_eq(typeof storedVal, "number"); + var storedVal = annosvc.getPageAnnotationInt32(testURI, int32Key); + do_check_true(int32Val === storedVal); + annosvc.setItemAnnotationInt32(testItemId, int32Key, int32Val, 0, 0); + do_check_true(annosvc.itemHasAnnotation(testItemId, int32Key)); + annosvc.getItemAnnotationInfo(testItemId, int32Key, flags, exp, mimeType, + storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT32); + storedVal = annosvc.getItemAnnotationInt32(testItemId, int32Key); + do_check_true(int32Val === storedVal); // test int64 anno type var int64Key = testAnnoName + "/types/Int64"; var int64Val = 4294967296; - annosvc.setAnnotationInt64(testURI, int64Key, int64Val, 0, 0); - var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(testURI, int64Key, flags, exp, mimeType, storageType); + annosvc.setPageAnnotationInt64(testURI, int64Key, int64Val, 0, 0); + annosvc.getPageAnnotationInfo(testURI, int64Key, flags, exp, mimeType, storageType); do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, null); do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT64); - var storedVal = annosvc.getAnnotationInt64(testURI, int64Key); - do_check_eq(int64Val, storedVal); - do_check_eq(typeof storedVal, "number"); + storedVal = annosvc.getPageAnnotationInt64(testURI, int64Key); + do_check_true(int64Val === storedVal); + annosvc.setItemAnnotationInt64(testItemId, int64Key, int64Val, 0, 0); + do_check_true(annosvc.itemHasAnnotation(testItemId, int64Key)); + annosvc.getItemAnnotationInfo(testItemId, int64Key, flags, exp, mimeType, + storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_INT64); + storedVal = annosvc.getItemAnnotationInt64(testItemId, int64Key); + do_check_true(int64Val === storedVal); // test double anno type var doubleKey = testAnnoName + "/types/Double"; var doubleVal = 0.000002342; - annosvc.setAnnotationDouble(testURI, doubleKey, doubleVal, 0, 0); - var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(testURI, doubleKey, flags, exp, mimeType, storageType); + annosvc.setPageAnnotationDouble(testURI, doubleKey, doubleVal, 0, 0); + annosvc.getPageAnnotationInfo(testURI, doubleKey, flags, exp, mimeType, storageType); do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, null); do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_DOUBLE); - var storedVal = annosvc.getAnnotationDouble(testURI, doubleKey); - do_check_eq(doubleVal, storedVal); - do_check_true(Math.round(storedVal) != storedVal); + storedVal = annosvc.getPageAnnotationDouble(testURI, doubleKey); + do_check_true(doubleVal === storedVal); + annosvc.setItemAnnotationDouble(testItemId, doubleKey, doubleVal, 0, 0); + do_check_true(annosvc.itemHasAnnotation(testItemId, doubleKey)); + annosvc.getItemAnnotationInfo(testItemId, doubleKey, flags, exp, mimeType, + storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, null); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_DOUBLE); + storedVal = annosvc.getItemAnnotationDouble(testItemId, doubleKey); + do_check_true(doubleVal === storedVal); // test binary anno type var binaryKey = testAnnoName + "/types/Binary"; var binaryVal = Array.prototype.map.call("splarg", function(x) { return x.charCodeAt(0); }); - annosvc.setAnnotationBinary(testURI, binaryKey, binaryVal, binaryVal.length, "text/plain", 0, 0); - var flags = {}, exp = {}, mimeType = {}, storageType = {}; - annosvc.getAnnotationInfo(testURI, binaryKey, flags, exp, mimeType, storageType); + annosvc.setPageAnnotationBinary(testURI, binaryKey, binaryVal, binaryVal.length, "text/plain", 0, 0); + annosvc.getPageAnnotationInfo(testURI, binaryKey, flags, exp, mimeType, storageType); do_check_eq(flags.value, 0); do_check_eq(exp.value, 0); do_check_eq(mimeType.value, "text/plain"); do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_BINARY); - var data = {}, length = {}, mimeType = {}; - annosvc.getAnnotationBinary(testURI, binaryKey, data, length, mimeType); + var data = {}, length = {}; + annosvc.getPageAnnotationBinary(testURI, binaryKey, data, length, mimeType); + do_check_eq(binaryVal.toString(), data.value.toString()); + do_check_eq(typeof data.value, "object"); + annosvc.setItemAnnotationBinary(testItemId, binaryKey, binaryVal, + binaryVal.length, "text/plain", 0, 0); + annosvc.getItemAnnotationInfo(testItemId, binaryKey, flags, exp, mimeType, + storageType); + do_check_eq(flags.value, 0); + do_check_eq(exp.value, 0); + do_check_eq(mimeType.value, "text/plain"); + do_check_eq(storageType.value, Ci.nsIAnnotationService.TYPE_BINARY); + annosvc.getItemAnnotationBinary(testItemId, binaryKey, data, length, + mimeType); do_check_eq(binaryVal.toString(), data.value.toString()); do_check_eq(typeof data.value, "object"); // test that accessors throw for wrong types try { - annosvc.getAnnotationString(testURI, int32Key); - do_throw("annotation string accessor didn't throw for a wrong type!"); + annosvc.getPageAnnotationString(testURI, int32Key); + do_throw("page-annotation string accessor didn't throw for a wrong type!"); + annosvc.getItemAnnotationString(testItemId, int32Key); + do_throw("item-annotation string accessor didn't throw for a wrong type!"); } catch(ex) {} try { - annosvc.getAnnotationInt32(testURI, int64Key); - do_throw("annotation int32 accessor didn't throw for a wrong type!"); + annosvc.getPageAnnotationInt32(testURI, int64Key); + do_throw("page-annotation int32 accessor didn't throw for a wrong type!"); + annosvc.getItemAnnotationInt32(testItemId, int64Key); + do_throw("item-annotation int32 accessor didn't throw for a wrong type!"); } catch(ex) {} try { - annosvc.getAnnotationInt64(testURI, int32Key); - do_throw("annotation int64 accessor didn't throw for a wrong type!"); + annosvc.getPageAnnotationInt64(testURI, int32Key); + do_throw("page-annotation int64 accessor didn't throw for a wrong type!"); + annosvc.getItemAnnotationInt64(testItemId, int32Key); + do_throw("item-annotation int64 accessor didn't throw for a wrong type!"); } catch(ex) {} try { - annosvc.getAnnotationDouble(testURI, int32Key); - do_throw("annotation double accessor didn't throw for a wrong type!"); + annosvc.getPageAnnotationDouble(testURI, int32Key); + do_throw("page-annotation double accessor didn't throw for a wrong type!"); + annosvc.getItemAnnotationDouble(testItemId, int32Key); + do_throw("item-annotation double accessor didn't throw for a wrong type!"); } catch(ex) {} try { var data = {}, length = {}, mimeType = {}; - annosvc.getAnnotationBinary(testURI, int32Key, data, length, mimeType); - do_throw("annotation binary accessor didn't throw for a wrong type!"); + annosvc.getPageAnnotationBinary(testURI, int32Key, data, length, mimeType); + do_throw("page-annotation binary accessor didn't throw for a wrong type!"); + annosvc.getItemAnnotationBinary(testItemId, int32Key, data, length, + mimeType); + do_throw("item-annotation binary accessor didn't throw for a wrong type!"); } catch(ex) {} + + // test annotation removal + annosvc.removePageAnnotation(testURI, int32Key); + annosvc.removeItemAnnotation(testItemId, int32Key); + do_check_eq(annoObserver.PAGE_lastRemoved_URI, testURI.spec); + do_check_eq(annoObserver.PAGE_lastRemoved_AnnoName, int32Key); + do_check_eq(annoObserver.ITEM_lastRemoved_Id, testItemId); + do_check_eq(annoObserver.ITEM_lastRemoved_AnnoName, int32Key); + + annosvc.removeObserver(annoObserver); } diff --git a/toolkit/components/places/tests/unit/test_history.js b/toolkit/components/places/tests/unit/test_history.js index 65695d44f30..a0c419a0784 100644 --- a/toolkit/components/places/tests/unit/test_history.js +++ b/toolkit/components/places/tests/unit/test_history.js @@ -138,8 +138,8 @@ function run_test() { // test annotation-based queries var annos = Cc["@mozilla.org/browser/annotation-service;1"]. getService(Ci.nsIAnnotationService); - annos.setAnnotationInt32(uri("http://mozilla.com/"), "testAnno", 0, 0, - Ci.nsIAnnotationService.EXPIRE_NEVER); + annos.setPageAnnotationInt32(uri("http://mozilla.com/"), "testAnno", 0, 0, + Ci.nsIAnnotationService.EXPIRE_NEVER); query.annotation = "testAnno"; result = histsvc.executeQuery(query, options); result.root.containerOpen = true; diff --git a/toolkit/components/places/tests/unit/test_result_sort.js b/toolkit/components/places/tests/unit/test_result_sort.js index ee95c4244c5..4754c5f0749 100644 --- a/toolkit/components/places/tests/unit/test_result_sort.js +++ b/toolkit/components/places/tests/unit/test_result_sort.js @@ -100,9 +100,9 @@ function run_test() { const NHQO = Ci.nsINavHistoryQueryOptions; function checkOrder(a, b, c) { - do_check_eq(root.getChild(0).bookmarkId, a); - do_check_eq(root.getChild(1).bookmarkId, b); - do_check_eq(root.getChild(2).bookmarkId, c); + do_check_eq(root.getChild(0).itemId, a); + do_check_eq(root.getChild(1).itemId, b); + do_check_eq(root.getChild(2).itemId, c); } // natural order @@ -128,20 +128,17 @@ function run_test() { // XXXtodo: test history sortings (visit count, visit date) // XXXtodo: test different item types once folderId and bookmarkId are merged. + // XXXtodo: test sortingAnnotation functionality with non-bookmark nodes - annosvc.setAnnotationString(bmsvc.getItemURI(id1), "testAnno", "a", 0, 0); - annosvc.setAnnotationString(bmsvc.getItemURI(id3), "testAnno", "b", 0, 0); + annosvc.setItemAnnotationString(id1, "testAnno", "a", 0, 0); + annosvc.setItemAnnotationString(id3, "testAnno", "b", 0, 0); result.sortingAnnotation = "testAnno"; result.sortingMode = NHQO.SORT_BY_ANNOTATION_DESCENDING; // id1 precedes id2 per title-descending fallback checkOrder(id3, id1, id2); - - // different annotation types, we fall back to the title sorting route - annosvc.setAnnotationInt32(bmsvc.getItemURI(id3), "testAnno", 10, 0, 0); - // XXXtodo: test live update for sortingAnnotation (not yet implemented); - // manually force sort for now... - result.sortingMode = result.sortingMode; - checkOrder(id1, id2, id3); + // test live update + annosvc.setItemAnnotationString(id1, "testAnno", "c", 0, 0); + checkOrder(id1, id3, id2); }