diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index 84540b459fc6..37603234564e 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -387,7 +387,7 @@ onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);" onpopupshowing="BookmarkingUI.onMainMenuPopupShowing(event); if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');" + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.menuGuid}`);" tooltip="bhTooltip" popupsinherittooltip="true"> + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`);"/> + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.unfiledGuid}`);"/> + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.mobileGuid}`);"/> diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 8a5ece9d5010..ed52678fb95f 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -998,8 +998,6 @@ var PlacesMenuDNDHandler = { * toolbar. */ var PlacesToolbarHelper = { - _place: "place:folder=TOOLBAR", - get _viewElt() { return document.getElementById("PlacesToolbar"); }, @@ -1030,7 +1028,7 @@ var PlacesToolbarHelper = { return; } - new PlacesToolbar(this._place); + new PlacesToolbar(`place:parent=${PlacesUtils.bookmarks.toolbarGuid}`); }, handleEvent(event) { @@ -1335,7 +1333,7 @@ var BookmarkingUI = { if (node.parentNode._placesView) return; - new PlacesMenu(event, "place:folder=BOOKMARKS_MENU", { + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.menuGuid}`, { extraClasses: { entry: "subviewbutton", footer: "panel-subview-footer" diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 74d1c07615e8..8e454cff2997 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -1130,7 +1130,7 @@ placespopup="true" context="placesContext" onpopupshowing="if (!this.parentNode._placesView) - new PlacesMenu(event, 'place:folder=TOOLBAR', + new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`, PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"> diff --git a/browser/components/places/content/bookmarksSidebar.js b/browser/components/places/content/bookmarksSidebar.js index 290a97f19ae8..3b59c1815b42 100644 --- a/browser/components/places/content/bookmarksSidebar.js +++ b/browser/components/places/content/bookmarksSidebar.js @@ -21,10 +21,7 @@ function searchBookmarks(aSearchString) { tree.place = tree.place; else tree.applyFilter(aSearchString, - [PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.unfiledBookmarksFolderId, - PlacesUtils.toolbarFolderId, - PlacesUtils.mobileFolderId]); + PlacesUtils.bookmarks.userContentRoots); } window.addEventListener("SidebarFocused", diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index a9202ec5eea7..be526cf533a9 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -753,10 +753,7 @@ var PlacesSearchBox = { _folders: [], get folders() { if (this._folders.length == 0) { - this._folders.push(PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.unfiledBookmarksFolderId, - PlacesUtils.toolbarFolderId, - PlacesUtils.mobileFolderId); + this._folders = PlacesUtils.bookmarks.userContentRoots; } return this._folders; }, @@ -931,10 +928,7 @@ var PlacesQueryBuilder = { break; case "bookmarks": filterCollection = "bookmarks"; - folders.push(PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.toolbarFolderId, - PlacesUtils.unfiledBookmarksFolderId, - PlacesUtils.mobileFolderId); + folders = PlacesUtils.bookmarks.userContentRoots; break; case "downloads": filterCollection = "downloads"; diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml index 1948890c4543..bc425dde47dc 100644 --- a/browser/components/places/content/tree.xml +++ b/browser/components/places/content/tree.xml @@ -92,7 +92,7 @@ query.searchTerms = filterString; if (folderRestrict) { - query.setFolders(folderRestrict, folderRestrict.length); + query.setParents(folderRestrict, folderRestrict.length); options.queryType = options.QUERY_TYPE_BOOKMARKS; } diff --git a/toolkit/components/places/Database.cpp b/toolkit/components/places/Database.cpp index 73502f36ea55..21d4e283605e 100644 --- a/toolkit/components/places/Database.cpp +++ b/toolkit/components/places/Database.cpp @@ -107,12 +107,6 @@ #define LMANNO_FEEDURI "livemark/feedURI" #define LMANNO_SITEURI "livemark/siteURI" -#define ROOT_GUID "root________" -#define MENU_ROOT_GUID "menu________" -#define TOOLBAR_ROOT_GUID "toolbar_____" -#define UNFILED_ROOT_GUID "unfiled_____" -#define TAGS_ROOT_GUID "tags________" -#define MOBILE_ROOT_GUID "mobile______" // This is no longer used & obsolete except for during migration. // Note: it may still be found in older places databases. #define MOBILE_ROOT_ANNO "mobile/bookmarksRoot" diff --git a/toolkit/components/places/nsINavHistoryService.idl b/toolkit/components/places/nsINavHistoryService.idl index cdf2244a6346..89aa937e23f7 100644 --- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -956,16 +956,16 @@ interface nsINavHistoryQuery : nsISupports /** * Limit results to items that are in all of the given folders. */ - void getFolders([optional] out unsigned long count, - [retval,array,size_is(count)] out long long folders); - readonly attribute unsigned long folderCount; + void getParents([optional] out unsigned long aGuidCount, + [retval,array,size_is(aGuidCount)] out string aGuids); + readonly attribute unsigned long parentCount; /** * This is not recursive so results will be returned from the first level of * that folder. */ - void setFolders([const,array, size_is(folderCount)] in long long folders, - in unsigned long folderCount); + void setParents([array, size_is(aGuidCount)] in string aGuids, + in unsigned long aGuidCount); /** * Creates a new query item with the same parameters of this one. diff --git a/toolkit/components/places/nsNavBookmarks.cpp b/toolkit/components/places/nsNavBookmarks.cpp index 64ea616c2987..9e2cdd207640 100644 --- a/toolkit/components/places/nsNavBookmarks.cpp +++ b/toolkit/components/places/nsNavBookmarks.cpp @@ -1112,6 +1112,80 @@ nsNavBookmarks::FetchItemInfo(int64_t aItemId, return NS_OK; } + +nsresult +nsNavBookmarks::FetchItemInfo(const nsCString& aGUID, + BookmarkData& _bookmark) +{ + // LEFT JOIN since not all bookmarks have an associated place. + nsCOMPtr stmt = mDB->GetStatement( + "SELECT b.id, h.url, b.title, b.position, b.fk, b.parent, b.type, " + "b.dateAdded, b.lastModified, t.guid, t.parent, " + "b.syncStatus " + "FROM moz_bookmarks b " + "LEFT JOIN moz_bookmarks t ON t.id = b.parent " + "LEFT JOIN moz_places h ON h.id = b.fk " + "WHERE b.guid = :item_guid" + ); + NS_ENSURE_STATE(stmt); + mozStorageStatementScoper scoper(stmt); + + nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("item_guid"), aGUID); + NS_ENSURE_SUCCESS(rv, rv); + + _bookmark.guid = aGUID; + + bool hasResult; + rv = stmt->ExecuteStep(&hasResult); + NS_ENSURE_SUCCESS(rv, rv); + if (!hasResult) { + return NS_ERROR_INVALID_ARG; + } + + rv = stmt->GetInt64(0, &_bookmark.id); + NS_ENSURE_SUCCESS(rv, rv); + + rv = stmt->GetUTF8String(1, _bookmark.url); + NS_ENSURE_SUCCESS(rv, rv); + + bool isNull; + rv = stmt->GetIsNull(2, &isNull); + NS_ENSURE_SUCCESS(rv, rv); + if (!isNull) { + rv = stmt->GetUTF8String(2, _bookmark.title); + NS_ENSURE_SUCCESS(rv, rv); + } + rv = stmt->GetInt32(3, &_bookmark.position); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt64(4, &_bookmark.placeId); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt64(5, &_bookmark.parentId); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt32(6, &_bookmark.type); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt64(7, reinterpret_cast(&_bookmark.dateAdded)); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt64(8, reinterpret_cast(&_bookmark.lastModified)); + NS_ENSURE_SUCCESS(rv, rv); + // Getting properties of the root would show no parent. + rv = stmt->GetIsNull(9, &isNull); + NS_ENSURE_SUCCESS(rv, rv); + if (!isNull) { + rv = stmt->GetUTF8String(9, _bookmark.parentGuid); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->GetInt64(10, &_bookmark.grandParentId); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + _bookmark.grandParentId = -1; + } + rv = stmt->GetInt32(11, &_bookmark.syncStatus); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + + nsresult nsNavBookmarks::SetItemDateInternal(enum BookmarkDate aDateType, int64_t aSyncChangeDelta, @@ -1500,12 +1574,12 @@ nsNavBookmarks::GetBookmarkURI(int64_t aItemId, nsresult -nsNavBookmarks::ResultNodeForContainer(int64_t aItemId, +nsNavBookmarks::ResultNodeForContainer(const nsCString& aGUID, nsNavHistoryQueryOptions* aOptions, nsNavHistoryResultNode** aNode) { BookmarkData bookmark; - nsresult rv = FetchItemInfo(aItemId, bookmark); + nsresult rv = FetchItemInfo(aGUID, bookmark); NS_ENSURE_SUCCESS(rv, rv); if (bookmark.type == TYPE_FOLDER) { // TYPE_FOLDER @@ -2087,9 +2161,9 @@ nsNavBookmarks::OnPageChanged(nsIURI* aURI, NS_ENSURE_SUCCESS(rv, rv); RefPtr queryObj = do_QueryObject(query); - if (queryObj->Folders().Length() == 1) { + if (queryObj->Parents().Length() == 1) { // Fetch missing data. - rv = FetchItemInfo(queryObj->Folders()[0], changeData.bookmark); + rv = FetchItemInfo(queryObj->Parents()[0], changeData.bookmark); NS_ENSURE_SUCCESS(rv, rv); NotifyItemChanged(changeData); } diff --git a/toolkit/components/places/nsNavBookmarks.h b/toolkit/components/places/nsNavBookmarks.h index 06bfadb2eb01..b99507b84304 100644 --- a/toolkit/components/places/nsNavBookmarks.h +++ b/toolkit/components/places/nsNavBookmarks.h @@ -121,7 +121,7 @@ public: nsresult GetBookmarkURI(int64_t aItemId, nsIURI** _URI); - nsresult ResultNodeForContainer(int64_t aID, + nsresult ResultNodeForContainer(const nsCString& aGUID, nsNavHistoryQueryOptions* aOptions, nsNavHistoryResultNode** aNode); @@ -177,6 +177,17 @@ public: BookmarkData& _bookmark); /** + * Fetches information about the specified GUID from the database. + * + * @param aGUID + * GUID of the item to fetch information for. + * @param aBookmark + * BookmarkData to store the information. + */ + nsresult FetchItemInfo(const nsCString &aGUID, + BookmarkData& _bookmark); + +/** * Notifies that a bookmark has been visited. * * @param aItemId diff --git a/toolkit/components/places/nsNavHistory.cpp b/toolkit/components/places/nsNavHistory.cpp index 37307d6b6e3b..ab6c0355e0dc 100644 --- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -191,8 +191,8 @@ NS_IMPL_CI_INTERFACE_GETTER(nsNavHistory, namespace { -static int64_t GetSimpleBookmarksQueryFolder(const RefPtr& aQuery, - const RefPtr& aOptions); +static nsCString GetSimpleBookmarksQueryParent(const RefPtr& aQuery, + const RefPtr& aOptions); static void ParseSearchTermsFromQuery(const RefPtr& aQuery, nsTArray* aTerms); @@ -1041,14 +1041,14 @@ nsNavHistory::ExecuteQuery(nsINavHistoryQuery *aQuery, // Create the root node. RefPtr rootNode; - int64_t folderId = GetSimpleBookmarksQueryFolder(query, options); - if (folderId) { + nsCString folderGuid = GetSimpleBookmarksQueryParent(query, options); + if (!folderGuid.IsEmpty()) { // In the simple case where we're just querying children of a single // bookmark folder, we can more efficiently generate results. nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); RefPtr tempRootNode; - nsresult rv = bookmarks->ResultNodeForContainer(folderId, options, + nsresult rv = bookmarks->ResultNodeForContainer(folderGuid, options, getter_AddRefs(tempRootNode)); if (NS_SUCCEEDED(rv)) { rootNode = tempRootNode->GetAsContainer(); @@ -1130,7 +1130,7 @@ bool IsOptimizableHistoryQuery(const RefPtr& aQuery, if (aQuery->AnnotationIsNot() || !aQuery->Annotation().IsEmpty()) return false; - if (aQuery->Folders().Length() > 0) + if (aQuery->Parents().Length() > 0) return false; if (aQuery->Tags().Length() > 0) @@ -1694,17 +1694,17 @@ PlacesSQLQueryBuilder::SelectAsRoots() mAddParams.Put(NS_LITERAL_CSTRING("MobileBookmarksFolderTitle"), mobileTitle); mobileString = NS_LITERAL_CSTRING("," - "(null, 'place:folder=MOBILE_BOOKMARKS', :MobileBookmarksFolderTitle, null, null, null, " + "(null, 'place:parent=" MOBILE_ROOT_GUID "', :MobileBookmarksFolderTitle, null, null, null, " "null, null, 0, 0, null, null, null, null, '" MOBILE_BOOKMARKS_VIRTUAL_GUID "', null) "); } mQueryString = NS_LITERAL_CSTRING( "SELECT * FROM (" - "VALUES(null, 'place:folder=TOOLBAR', :BookmarksToolbarFolderTitle, null, null, null, " + "VALUES(null, 'place:parent=" TOOLBAR_ROOT_GUID "', :BookmarksToolbarFolderTitle, null, null, null, " "null, null, 0, 0, null, null, null, null, 'toolbar____v', null), " - "(null, 'place:folder=BOOKMARKS_MENU', :BookmarksMenuFolderTitle, null, null, null, " + "(null, 'place:parent=" MENU_ROOT_GUID "', :BookmarksMenuFolderTitle, null, null, null, " "null, null, 0, 0, null, null, null, null, 'menu_______v', null), " - "(null, 'place:folder=UNFILED_BOOKMARKS', :OtherBookmarksFolderTitle, null, null, null, " + "(null, 'place:parent=" UNFILED_ROOT_GUID "', :OtherBookmarksFolderTitle, null, null, null, " "null, null, 0, 0, null, null, null, null, 'unfiled___v', null) ") + mobileString + NS_LITERAL_CSTRING(")"); @@ -2767,21 +2767,23 @@ nsNavHistory::QueryToSelectClause(const RefPtr& aQuery, .Str(")"); } - // folders - const nsTArray& folders = aQuery->Folders(); - if (folders.Length() > 0) { + // parents + const nsTArray& parents = aQuery->Parents(); + if (parents.Length() > 0) { aOptions->SetQueryType(nsNavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS); clause.Condition("b.parent IN( " "WITH RECURSIVE parents(id) AS ( " - "VALUES "); - for (uint32_t i = 0; i < folders.Length(); ++i) { - nsPrintfCString param("(:parent%d_)", i); + "SELECT id FROM moz_bookmarks WHERE GUID IN ("); + + for (uint32_t i = 0; i < parents.Length(); ++i) { + nsPrintfCString param(":parentguid%d_", i); clause.Param(param.get()); - if (i < folders.Length() - 1) { + if (i < parents.Length() - 1) { clause.Str(","); } } - clause.Str( "UNION ALL " + clause.Str( ") " + "UNION ALL " "SELECT b2.id " "FROM moz_bookmarks b2 " "JOIN parents p ON b2.parent = p.id " @@ -2917,11 +2919,11 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageBaseStatement* statement, NS_ENSURE_SUCCESS(rv, rv); } - // folders - const nsTArray& folders = aQuery->Folders(); - for (uint32_t i = 0; i < folders.Length(); ++i) { - nsPrintfCString paramName("parent%d_", i); - rv = statement->BindInt64ByName(paramName, folders[i]); + // parents + const nsTArray& parents = aQuery->Parents(); + for (uint32_t i = 0; i < parents.Length(); ++i) { + nsPrintfCString paramName("parentguid%d_", i); + rv = statement->BindUTF8StringByName(paramName, parents[i]); NS_ENSURE_SUCCESS(rv, rv); } @@ -3350,21 +3352,19 @@ nsNavHistory::QueryRowToResult(int64_t itemId, // handle it later. if (NS_SUCCEEDED(rv)) { // Check if this is a folder shortcut, so we can take a faster path. - int64_t targetFolderId = GetSimpleBookmarksQueryFolder(queryObj, optionsObj); - if (targetFolderId) { + nsCString targetFolderGuid = GetSimpleBookmarksQueryParent(queryObj, optionsObj); + if (!targetFolderGuid.IsEmpty()) { nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); - rv = bookmarks->ResultNodeForContainer(targetFolderId, optionsObj, + rv = bookmarks->ResultNodeForContainer(targetFolderGuid, optionsObj, getter_AddRefs(resultNode)); // If this failed the shortcut is pointing to nowhere, let the error pass // and handle it later. if (NS_SUCCEEDED(rv)) { // At this point the node is set up like a regular folder node. Here // we make the necessary change to make it a folder shortcut. - resultNode->GetAsFolder()->mTargetFolderItemId = targetFolderId; resultNode->mItemId = itemId; - nsAutoCString targetFolderGuid(resultNode->GetAsFolder()->mBookmarkGuid); resultNode->mBookmarkGuid = aBookmarkGuid; resultNode->GetAsFolder()->mTargetFolderGuid = targetFolderGuid; @@ -3629,7 +3629,7 @@ nsNavHistory::GetMonthYear(const PRExplodedTime& aTime, nsACString& aResult) namespace { -// GetSimpleBookmarksQueryFolder +// GetSimpleBookmarksQueryParent // // Determines if this is a simple bookmarks query for a // folder with no other constraints. In these common cases, we can more @@ -3639,33 +3639,33 @@ namespace { // bookmark items, folders and separators. // // Returns the folder ID if it is a simple folder query, 0 if not. -static int64_t -GetSimpleBookmarksQueryFolder(const RefPtr& aQuery, +static nsCString +GetSimpleBookmarksQueryParent(const RefPtr& aQuery, const RefPtr& aOptions) { - if (aQuery->Folders().Length() != 1) - return 0; + if (aQuery->Parents().Length() != 1) + return EmptyCString(); bool hasIt; if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt)) && hasIt) - return 0; + return EmptyCString(); if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt)) && hasIt) - return 0; + return EmptyCString(); if (!aQuery->Domain().IsVoid()) - return 0; + return EmptyCString(); if (aQuery->Uri()) - return 0; + return EmptyCString(); if (!aQuery->SearchTerms().IsEmpty()) - return 0; + return EmptyCString(); if (aQuery->Tags().Length() > 0) - return 0; + return EmptyCString(); if (aOptions->MaxResults() > 0) - return 0; + return EmptyCString(); // Don't care about onlyBookmarked flag, since specifying a bookmark // folder is inferring onlyBookmarked. - return aQuery->Folders()[0]; + return aQuery->Parents()[0]; } diff --git a/toolkit/components/places/nsNavHistory.h b/toolkit/components/places/nsNavHistory.h index 753960ca9865..e3127ccee751 100644 --- a/toolkit/components/places/nsNavHistory.h +++ b/toolkit/components/places/nsNavHistory.h @@ -65,6 +65,13 @@ // The guid of the mobile bookmarks virtual query. #define MOBILE_BOOKMARKS_VIRTUAL_GUID "mobile____v" +#define ROOT_GUID "root________" +#define MENU_ROOT_GUID "menu________" +#define TOOLBAR_ROOT_GUID "toolbar_____" +#define UNFILED_ROOT_GUID "unfiled_____" +#define TAGS_ROOT_GUID "tags________" +#define MOBILE_ROOT_GUID "mobile______" + class nsIAutoCompleteController; class nsIEffectiveTLDService; class nsIIDNService; diff --git a/toolkit/components/places/nsNavHistoryQuery.cpp b/toolkit/components/places/nsNavHistoryQuery.cpp index 58b7f18d4ad2..36b91e5b7604 100644 --- a/toolkit/components/places/nsNavHistoryQuery.cpp +++ b/toolkit/components/places/nsNavHistoryQuery.cpp @@ -110,7 +110,7 @@ static void SetOptionsKeyUint32(const nsCString& aValue, #define QUERYKEY_ONLY_BOOKMARKED "onlyBookmarked" #define QUERYKEY_DOMAIN_IS_HOST "domainIsHost" #define QUERYKEY_DOMAIN "domain" -#define QUERYKEY_FOLDER "folder" +#define QUERYKEY_PARENT "parent" #define QUERYKEY_NOTANNOTATION "!annotation" #define QUERYKEY_ANNOTATION "annotation" #define QUERYKEY_URI "uri" @@ -155,93 +155,6 @@ inline void AppendInt64(nsACString& str, int64_t i) str.Append(tmp); } -namespace PlacesFolderConversion { - #define PLACES_ROOT_FOLDER "PLACES_ROOT" - #define BOOKMARKS_MENU_FOLDER "BOOKMARKS_MENU" - #define TAGS_FOLDER "TAGS" - #define UNFILED_BOOKMARKS_FOLDER "UNFILED_BOOKMARKS" - #define TOOLBAR_FOLDER "TOOLBAR" - #define MOBILE_BOOKMARKS_FOLDER "MOBILE_BOOKMARKS" - - /** - * Converts a folder name to a folder id. - * - * @param aName - * The name of the folder to convert to a folder id. - * @returns the folder id if aName is a recognizable name, -1 otherwise. - */ - inline int64_t DecodeFolder(const nsCString &aName) - { - nsNavBookmarks *bs = nsNavBookmarks::GetBookmarksService(); - NS_ENSURE_TRUE(bs, false); - int64_t folderID = -1; - - if (aName.EqualsLiteral(PLACES_ROOT_FOLDER)) - (void)bs->GetPlacesRoot(&folderID); - else if (aName.EqualsLiteral(BOOKMARKS_MENU_FOLDER)) - (void)bs->GetBookmarksMenuFolder(&folderID); - else if (aName.EqualsLiteral(TAGS_FOLDER)) - (void)bs->GetTagsFolder(&folderID); - else if (aName.EqualsLiteral(UNFILED_BOOKMARKS_FOLDER)) - (void)bs->GetUnfiledBookmarksFolder(&folderID); - else if (aName.EqualsLiteral(TOOLBAR_FOLDER)) - (void)bs->GetToolbarFolder(&folderID); - else if (aName.EqualsLiteral(MOBILE_BOOKMARKS_FOLDER)) - (void)bs->GetMobileFolder(&folderID); - - return folderID; - } - - /** - * Converts a folder id to a named constant, or a string representation of the - * folder id if there is no named constant for the folder, and appends it to - * aQuery. - * - * @param aQuery - * The string to append the folder string to. This is generally a - * query string, but could really be anything. - * @param aFolderID - * The folder ID to convert to the proper named constant. - */ - inline nsresult AppendFolder(nsCString &aQuery, int64_t aFolderID) - { - nsNavBookmarks *bs = nsNavBookmarks::GetBookmarksService(); - NS_ENSURE_STATE(bs); - int64_t folderID = -1; - - if (NS_SUCCEEDED(bs->GetPlacesRoot(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(PLACES_ROOT_FOLDER); - } - else if (NS_SUCCEEDED(bs->GetBookmarksMenuFolder(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(BOOKMARKS_MENU_FOLDER); - } - else if (NS_SUCCEEDED(bs->GetTagsFolder(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(TAGS_FOLDER); - } - else if (NS_SUCCEEDED(bs->GetUnfiledBookmarksFolder(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(UNFILED_BOOKMARKS_FOLDER); - } - else if (NS_SUCCEEDED(bs->GetToolbarFolder(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(TOOLBAR_FOLDER); - } - else if (NS_SUCCEEDED(bs->GetMobileFolder(&folderID)) && - aFolderID == folderID) { - aQuery.AppendLiteral(MOBILE_BOOKMARKS_FOLDER); - } - else { - // It wasn't one of our named constants, so just convert it to a string. - aQuery.AppendInt(aFolderID); - } - - return NS_OK; - } -} // namespace PlacesFolderConversion - NS_IMETHODIMP nsNavHistory::QueryStringToQuery(const nsACString& aQueryString, nsINavHistoryQuery** _query, @@ -386,13 +299,12 @@ nsNavHistory::QueryToQueryString(nsINavHistoryQuery *aQuery, queryString.Append(escaped); } - // folders - const nsTArray& folders = query->Folders(); - for (uint32_t i = 0; i < folders.Length(); ++i) { + // parents + const nsTArray& parents = query->Parents(); + for (uint32_t i = 0; i < parents.Length(); ++i) { AppendAmpersandIfNonempty(queryString); - queryString += NS_LITERAL_CSTRING(QUERYKEY_FOLDER "="); - nsresult rv = PlacesFolderConversion::AppendFolder(queryString, folders[i]); - NS_ENSURE_SUCCESS(rv, rv); + queryString += NS_LITERAL_CSTRING(QUERYKEY_PARENT "="); + queryString += parents[i]; } // tags @@ -552,7 +464,7 @@ nsNavHistory::TokensToQuery(const nsTArray& aTokens, if (aTokens.Length() == 0) return NS_OK; - nsTArray folders; + nsTArray parents; nsTArray tags; nsTArray transitions; for (uint32_t i = 0; i < aTokens.Length(); i ++) { @@ -612,20 +524,11 @@ nsNavHistory::TokensToQuery(const nsTArray& aTokens, rv = aQuery->SetDomain(unescapedDomain); NS_ENSURE_SUCCESS(rv, rv); - // folders - } else if (kvp.key.EqualsLiteral(QUERYKEY_FOLDER)) { - int64_t folder; - if (PR_sscanf(kvp.value.get(), "%lld", &folder) == 1) { - NS_ENSURE_TRUE(folders.AppendElement(folder), NS_ERROR_OUT_OF_MEMORY); - } else { - folder = PlacesFolderConversion::DecodeFolder(kvp.value); - if (folder != -1) - NS_ENSURE_TRUE(folders.AppendElement(folder), NS_ERROR_OUT_OF_MEMORY); - else - NS_WARNING("folders value in query is invalid, ignoring"); - } + // parent folders (guids) + } else if (kvp.key.EqualsLiteral(QUERYKEY_PARENT)) { + NS_ENSURE_TRUE(parents.AppendElement(kvp.value), NS_ERROR_OUT_OF_MEMORY); - // uri + // uri } else if (kvp.key.EqualsLiteral(QUERYKEY_URI)) { nsAutoCString unescapedUri(kvp.value); NS_UnescapeURL(unescapedUri); // modifies input @@ -733,8 +636,10 @@ nsNavHistory::TokensToQuery(const nsTArray& aTokens, } } - if (folders.Length() != 0) - aQuery->SetFolders(folders.Elements(), folders.Length()); + if (parents.Length() != 0) { + rv = aQuery->SetParents(parents); + NS_ENSURE_SUCCESS(rv, rv); + } if (tags.Length() > 0) { rv = aQuery->SetTags(tags); @@ -799,7 +704,7 @@ nsNavHistoryQuery::nsNavHistoryQuery(const nsNavHistoryQuery& aOther) mDomainIsHost(aOther.mDomainIsHost), mDomain(aOther.mDomain), mUri(aOther.mUri), mAnnotationIsNot(aOther.mAnnotationIsNot), mAnnotation(aOther.mAnnotation), - mFolders(aOther.mFolders), + mParents(aOther.mParents), mTags(aOther.mTags), mTagsAreNot(aOther.mTagsAreNot), mTransitions(aOther.mTransitions) { @@ -1131,37 +1036,39 @@ NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot) return NS_OK; } -NS_IMETHODIMP nsNavHistoryQuery::GetFolders(uint32_t *aCount, - int64_t **aFolders) +NS_IMETHODIMP nsNavHistoryQuery::GetParents(uint32_t *aGuidCount, + char ***aGuids) { - uint32_t count = mFolders.Length(); - int64_t *folders = nullptr; + uint32_t count = mParents.Length(); + char **guids = nullptr; if (count > 0) { - folders = static_cast - (moz_xmalloc(count * sizeof(int64_t))); - NS_ENSURE_TRUE(folders, NS_ERROR_OUT_OF_MEMORY); + guids = static_cast + (moz_xmalloc(count * sizeof(char*))); + NS_ENSURE_TRUE(guids, NS_ERROR_OUT_OF_MEMORY); for (uint32_t i = 0; i < count; ++i) { - folders[i] = mFolders[i]; + guids[i] = ToNewCString(mParents[i]); } } - *aCount = count; - *aFolders = folders; + *aGuidCount = count; + *aGuids = guids; return NS_OK; } -NS_IMETHODIMP nsNavHistoryQuery::GetFolderCount(uint32_t *aCount) +NS_IMETHODIMP nsNavHistoryQuery::GetParentCount(uint32_t *aGuidCount) { - *aCount = mFolders.Length(); + *aGuidCount = mParents.Length(); return NS_OK; } -NS_IMETHODIMP nsNavHistoryQuery::SetFolders(const int64_t *aFolders, - uint32_t aFolderCount) +NS_IMETHODIMP nsNavHistoryQuery::SetParents(const char** aGuids, + uint32_t aGuidCount) { - if (!mFolders.ReplaceElementsAt(0, mFolders.Length(), - aFolders, aFolderCount)) { - return NS_ERROR_OUT_OF_MEMORY; + mParents.Clear(); + for (size_t i = 0; i < aGuidCount; i++) { + if (!mParents.AppendElement(aGuids[i])) { + return NS_ERROR_OUT_OF_MEMORY; + } } return NS_OK; diff --git a/toolkit/components/places/nsNavHistoryQuery.h b/toolkit/components/places/nsNavHistoryQuery.h index 5a96e716d1ef..c5e791afd33c 100644 --- a/toolkit/components/places/nsNavHistoryQuery.h +++ b/toolkit/components/places/nsNavHistoryQuery.h @@ -45,7 +45,14 @@ public: nsIURI* Uri() { return mUri; } // NOT AddRef-ed! bool AnnotationIsNot() { return mAnnotationIsNot; } const nsCString& Annotation() { return mAnnotation; } - const nsTArray& Folders() const { return mFolders; } + const nsTArray& Parents() { return mParents; } + nsresult SetParents(const nsTArray& aParents) + { + if (!mParents.ReplaceElementsAt(0, mParents.Length(), aParents)) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; + } + const nsTArray& Tags() const { return mTags; } nsresult SetTags(const nsTArray& aTags) { @@ -85,7 +92,7 @@ protected: nsCOMPtr mUri; bool mAnnotationIsNot; nsCString mAnnotation; - nsTArray mFolders; + nsTArray mParents; nsTArray mTags; bool mTagsAreNot; nsTArray mTransitions; diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp index 5f431e9c0ec0..6ce374e558ce 100644 --- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -99,7 +99,7 @@ getUpdateRequirements(const RefPtr& aQuery, bool nonTimeBasedItems = false; bool domainBasedItems = false; - if (aQuery->Folders().Length() > 0 || + if (aQuery->Parents().Length() > 0 || aQuery->OnlyBookmarked() || aQuery->Tags().Length() > 0 || (aOptions->QueryType() == nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS && @@ -3218,14 +3218,14 @@ NS_IMETHODIMP nsNavHistoryFolderResultNode::GetQuery(nsINavHistoryQuery** _query) { // get the query object - nsCOMPtr query; - nsNavHistory* history = nsNavHistory::GetHistoryService(); - NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY); - nsresult rv = history->GetNewQuery(getter_AddRefs(query)); - NS_ENSURE_SUCCESS(rv, rv); + RefPtr query = new nsNavHistoryQuery(); + nsTArray parents; // query just has the folder ID set and nothing else - rv = query->SetFolders(&mTargetFolderItemId, 1); + if (!parents.AppendElement(mTargetFolderGuid)) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = query->SetParents(parents); NS_ENSURE_SUCCESS(rv, rv); query.forget(_query); @@ -3678,7 +3678,7 @@ nsNavHistoryFolderResultNode::OnItemAdded(int64_t aItemId, else if (aItemType == nsINavBookmarksService::TYPE_FOLDER) { nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); - rv = bookmarks->ResultNodeForContainer(aItemId, + rv = bookmarks->ResultNodeForContainer(PromiseFlatCString(aGUID), new nsNavHistoryQueryOptions(), getter_AddRefs(node)); NS_ENSURE_SUCCESS(rv, rv); diff --git a/toolkit/components/places/tests/queries/test_queryMultipleFolder.js b/toolkit/components/places/tests/queries/test_queryMultipleFolder.js index 0d12cf761d7a..1229227c4771 100644 --- a/toolkit/components/places/tests/queries/test_queryMultipleFolder.js +++ b/toolkit/components/places/tests/queries/test_queryMultipleFolder.js @@ -3,16 +3,19 @@ "use strict"; -add_task(async function test_queryMultipleFolders() { +var folderIds = []; +var folderGuids = []; +var bookmarkGuids = []; + +add_task(async function setup() { // adding bookmarks in the folders - let folderIds = []; - let bookmarkIds = []; for (let i = 0; i < 3; ++i) { let folder = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title: `Folder${i}` }); + folderGuids.push(folder.guid); folderIds.push(await PlacesUtils.promiseItemId(folder.guid)); for (let j = 0; j < 7; ++j) { @@ -21,10 +24,12 @@ add_task(async function test_queryMultipleFolders() { url: `http://Bookmark${i}_${j}.com`, title: "" }); - bookmarkIds.push(await PlacesUtils.promiseItemId(bm.guid)); + bookmarkGuids.push(bm.guid); } } +}); +add_task(async function test_queryMultipleFolders_ids() { // using queryStringToQuery let query = {}, options = {}; let maxResults = 20; @@ -36,7 +41,7 @@ add_task(async function test_queryMultipleFolders() { Assert.equal(resultLength, maxResults); for (let i = 0; i < resultLength; ++i) { let node = rootNode.getChild(i); - Assert.equal(bookmarkIds[i], node.itemId, node.uri); + Assert.equal(bookmarkGuids[i], node.bookmarkGuid, node.uri); } rootNode.containerOpen = false; @@ -52,7 +57,40 @@ add_task(async function test_queryMultipleFolders() { Assert.equal(resultLength, maxResults); for (let i = 0; i < resultLength; ++i) { let node = rootNode.getChild(i); - Assert.equal(bookmarkIds[i], node.itemId, node.uri); + Assert.equal(bookmarkGuids[i], node.bookmarkGuid, node.uri); + } + rootNode.containerOpen = false; +}); + +add_task(async function test_queryMultipleFolders_guids() { + // using queryStringToQuery + let query = {}, options = {}; + let maxResults = 20; + let queryString = `place:${folderGuids.map((guid) => "parent=" + guid).join("&")}&sort=5&maxResults=${maxResults}`; + PlacesUtils.history.queryStringToQuery(queryString, query, options); + let rootNode = PlacesUtils.history.executeQuery(query.value, options.value).root; + rootNode.containerOpen = true; + let resultLength = rootNode.childCount; + Assert.equal(resultLength, maxResults); + for (let i = 0; i < resultLength; ++i) { + let node = rootNode.getChild(i); + Assert.equal(bookmarkGuids[i], node.bookmarkGuid, node.uri); + } + rootNode.containerOpen = false; + + // using getNewQuery and getNewQueryOptions + query = PlacesUtils.history.getNewQuery(); + options = PlacesUtils.history.getNewQueryOptions(); + query.setParents(folderGuids, folderGuids.length); + options.sortingMode = options.SORT_BY_URI_ASCENDING; + options.maxResults = maxResults; + rootNode = PlacesUtils.history.executeQuery(query, options).root; + rootNode.containerOpen = true; + resultLength = rootNode.childCount; + Assert.equal(resultLength, maxResults); + for (let i = 0; i < resultLength; ++i) { + let node = rootNode.getChild(i); + Assert.equal(bookmarkGuids[i], node.bookmarkGuid, node.uri); } rootNode.containerOpen = false; });