--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -382,17 +382,17 @@
#endif
context="placesContext"
openInTabs="children"
onmouseup="BookmarksEventHandler.onMouseUp(event);"
oncommand="BookmarksEventHandler.onCommand(event);"
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">
<menuitem id="bookmarksShowAll"
label="&showAllBookmarks2.label;"
command="Browser:ShowAllBookmarks"
key="manBookmarkKb"/>
<menuseparator id="organizeBookmarksSeparator"/>
<menuitem id="menu_bookmarkThisPage"
command="Browser:AddBookmarkAs"
@@ -428,42 +428,42 @@
label="&personalbarCmd.label;"
container="true">
<menupopup id="bookmarksToolbarFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
- new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
+ new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.toolbarGuid}`);"/>
</menu>
<menu id="menu_unsortedBookmarks"
class="menu-iconic bookmark-item"
label="&otherBookmarksCmd.label;"
container="true">
<menupopup id="otherBookmarksFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
- new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS');"/>
+ new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.unfiledGuid}`);"/>
</menu>
<menu id="menu_mobileBookmarks"
class="menu-iconic bookmark-item"
label="&mobileBookmarksCmd.label;"
hidden="true"
container="true">
<menupopup id="mobileBookmarksFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
- new PlacesMenu(event, 'place:folder=MOBILE_BOOKMARKS');"/>
+ new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.mobileGuid}`);"/>
</menu>
<menuseparator id="bookmarksMenuItemsSeparator"/>
<!-- Bookmarks menu items -->
</menupopup>
</menu>
<menu id="tools-menu"
label="&toolsMenu.label;"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -993,18 +993,16 @@ var PlacesMenuDNDHandler = {
}
};
/**
* This object handles the initialization and uninitialization of the bookmarks
* toolbar.
*/
var PlacesToolbarHelper = {
- _place: "place:folder=TOOLBAR",
-
get _viewElt() {
return document.getElementById("PlacesToolbar");
},
init: function PTH_init() {
let viewElt = this._viewElt;
if (!viewElt || viewElt._placesView)
return;
@@ -1025,17 +1023,17 @@ var PlacesToolbarHelper = {
// don't initialize. Also, there is no need to initialize the toolbar if
// customizing, because that will happen when the customization is done.
let toolbar = this._getParentToolbar(viewElt);
if (!toolbar || toolbar.collapsed || this._isCustomizing ||
getComputedStyle(toolbar, "").display == "none") {
return;
}
- new PlacesToolbar(this._place);
+ new PlacesToolbar(`place:parent=${PlacesUtils.bookmarks.toolbarGuid}`);
},
handleEvent(event) {
switch (event.type) {
case "toolbarvisibilitychange":
if (event.target == this._getParentToolbar(this._viewElt))
this._resetView();
break;
@@ -1330,17 +1328,17 @@ var BookmarkingUI = {
document.getElementById("PersonalToolbar").collapsed);
},
attachPlacesView(event, node) {
// If the view is already there, bail out early.
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"
},
insertionPoint: ".panel-subview-footer"
});
},
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -1125,17 +1125,17 @@
<menu id="BMB_bookmarksToolbar"
class="menu-iconic bookmark-item subviewbutton"
label="&personalbarCmd.label;"
container="true">
<menupopup id="BMB_bookmarksToolbarPopup"
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);">
<menuitem id="BMB_viewBookmarksToolbar"
class="menuitem-iconic subviewbutton"
label-show="&viewBookmarksToolbar.label;"
label-hide="&hideBookmarksToolbar.label;"
oncommand="BookmarkingUI.toggleBookmarksToolbar();"/>
<menuseparator/>
<!-- Bookmarks toolbar items -->
@@ -1144,29 +1144,29 @@
<menu id="BMB_unsortedBookmarks"
class="menu-iconic bookmark-item subviewbutton"
label="&bookmarksMenuButton.other.label;"
container="true">
<menupopup id="BMB_unsortedBookmarksPopup"
placespopup="true"
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
- new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS',
+ new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.unfiledGuid}`,
PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
</menu>
<menu id="BMB_mobileBookmarks"
class="menu-iconic bookmark-item subviewbutton"
label="&bookmarksMenuButton.mobile.label;"
hidden="true"
container="true">
<menupopup id="BMB_mobileBookmarksPopup"
placespopup="true"
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
- new PlacesMenu(event, 'place:folder=MOBILE_BOOKMARKS',
+ new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.mobileGuid}`,
PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
</menu>
<menuseparator/>
<!-- Bookmarks menu items will go here -->
<menuitem id="BMB_bookmarksShowAll"
class="subviewbutton panel-subview-footer"
label="&showAllBookmarks2.label;"
--- a/browser/components/places/content/bookmarksSidebar.js
+++ b/browser/components/places/content/bookmarksSidebar.js
@@ -16,16 +16,13 @@ function init() {
}
function searchBookmarks(aSearchString) {
var tree = document.getElementById("bookmarks-view");
if (!aSearchString)
tree.place = tree.place;
else
tree.applyFilter(aSearchString,
- [PlacesUtils.bookmarksMenuFolderId,
- PlacesUtils.unfiledBookmarksFolderId,
- PlacesUtils.toolbarFolderId,
- PlacesUtils.mobileFolderId]);
+ PlacesUtils.bookmarks.userContentRoots);
}
window.addEventListener("SidebarFocused",
() => document.getElementById("search-box").focus());
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -748,20 +748,17 @@ var PlacesSearchBox = {
},
/**
* Folders to include when searching.
*/
_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;
},
set folders(aFolders) {
this._folders = aFolders;
return aFolders;
},
@@ -926,20 +923,17 @@ var PlacesQueryBuilder = {
var filterCollection;
var folders = [];
switch (aScope) {
case "history":
filterCollection = "history";
break;
case "bookmarks":
filterCollection = "bookmarks";
- folders.push(PlacesUtils.bookmarksMenuFolderId,
- PlacesUtils.toolbarFolderId,
- PlacesUtils.unfiledBookmarksFolderId,
- PlacesUtils.mobileFolderId);
+ folders = PlacesUtils.bookmarks.userContentRoots;
break;
case "downloads":
filterCollection = "downloads";
break;
default:
throw "Invalid search scope";
}
--- a/browser/components/places/content/tree.xml
+++ b/browser/components/places/content/tree.xml
@@ -87,17 +87,17 @@
options.resultType == options.RESULTS_AS_TAGS_ROOT ||
options.resultType == options.RESULTS_AS_ROOTS_QUERY)
options.resultType = options.RESULTS_AS_URI;
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
if (folderRestrict) {
- query.setFolders(folderRestrict, folderRestrict.length);
+ query.setParents(folderRestrict, folderRestrict.length);
options.queryType = options.QUERY_TYPE_BOOKMARKS;
}
options.includeHidden = !!includeHidden;
this.load(query, options);
]]></body>
</method>
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -102,22 +102,16 @@
// Places string bundle, contains internationalized bookmark root names.
#define PLACES_BUNDLE "chrome://places/locale/places.properties"
// Livemarks annotations.
#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"
// We use a fixed title for the mobile root to avoid marking the database as
// corrupt if we can't look up the localized title in the string bundle. Sync
// sets the title to the localized version when it creates the left pane query.
#define MOBILE_ROOT_TITLE "mobile"
--- a/toolkit/components/places/nsINavHistoryService.idl
+++ b/toolkit/components/places/nsINavHistoryService.idl
@@ -951,26 +951,26 @@ interface nsINavHistoryQuery : nsISuppor
* are not tagged with any of the given tags. This attribute is used in
* conjunction with the 'tags' attribute.
*/
attribute boolean tagsAreNot;
/**
* 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.
*/
nsINavHistoryQuery clone();
};
/**
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -1107,16 +1107,90 @@ nsNavBookmarks::FetchItemInfo(int64_t aI
_bookmark.grandParentId = -1;
}
rv = stmt->GetInt32(12, &_bookmark.syncStatus);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
+
+nsresult
+nsNavBookmarks::FetchItemInfo(const nsCString& aGUID,
+ BookmarkData& _bookmark)
+{
+ // LEFT JOIN since not all bookmarks have an associated place.
+ nsCOMPtr<mozIStorageStatement> 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<int64_t*>(&_bookmark.dateAdded));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = stmt->GetInt64(8, reinterpret_cast<int64_t*>(&_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,
int64_t aItemId,
PRTime aValue)
{
aValue = RoundToMilliseconds(aValue);
@@ -1495,22 +1569,22 @@ nsNavBookmarks::GetBookmarkURI(int64_t a
rv = NS_NewURI(_URI, bookmark.url);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
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
*aNode = new nsNavHistoryFolderResultNode(bookmark.title,
aOptions,
bookmark.id);
}
else {
@@ -2082,19 +2156,19 @@ nsNavBookmarks::OnPageChanged(nsIURI* aU
nsCOMPtr<nsINavHistoryQuery> query;
nsCOMPtr<nsINavHistoryQueryOptions> options;
rv = history->QueryStringToQuery(changeData.bookmark.url,
getter_AddRefs(query),
getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<nsNavHistoryQuery> 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);
}
}
else {
RefPtr< AsyncGetBookmarksForURI<ItemChangeMethod, ItemChangeData> > notifier =
new AsyncGetBookmarksForURI<ItemChangeMethod, ItemChangeData>(this, &nsNavBookmarks::NotifyItemChanged, changeData);
notifier->Init();
--- a/toolkit/components/places/nsNavBookmarks.h
+++ b/toolkit/components/places/nsNavBookmarks.h
@@ -116,17 +116,17 @@ public:
nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
int64_t aSessionId, int64_t aReferringId,
uint32_t aTransitionType, const nsACString& aGUID,
bool aHidden, uint32_t aVisitCount,
uint32_t aTyped, const nsAString& aLastKnownTitle);
nsresult GetBookmarkURI(int64_t aItemId, nsIURI** _URI);
- nsresult ResultNodeForContainer(int64_t aID,
+ nsresult ResultNodeForContainer(const nsCString& aGUID,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aNode);
// Find all the children of a folder, using the given query and options.
// For each child, a ResultNode is created and added to |children|.
// The results are ordered by folder position.
nsresult QueryFolderChildren(int64_t aFolderId,
nsNavHistoryQueryOptions* aOptions,
@@ -172,16 +172,27 @@ public:
* Id of the item to fetch information for.
* @param aBookmark
* BookmarkData to store the information.
*/
nsresult FetchItemInfo(int64_t aItemId,
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
* The visited item id.
* @param aData
* Details about the new visit.
*/
void NotifyItemVisited(const ItemVisitData& aData);
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -186,18 +186,18 @@ NS_INTERFACE_MAP_BEGIN(nsNavHistory)
NS_INTERFACE_MAP_END
// We don't care about flattening everything
NS_IMPL_CI_INTERFACE_GETTER(nsNavHistory,
nsINavHistoryService)
namespace {
-static int64_t GetSimpleBookmarksQueryFolder(const RefPtr<nsNavHistoryQuery>& aQuery,
- const RefPtr<nsNavHistoryQueryOptions>& aOptions);
+static nsCString GetSimpleBookmarksQueryParent(const RefPtr<nsNavHistoryQuery>& aQuery,
+ const RefPtr<nsNavHistoryQueryOptions>& aOptions);
static void ParseSearchTermsFromQuery(const RefPtr<nsNavHistoryQuery>& aQuery,
nsTArray<nsString>* aTerms);
void GetTagsSqlFragment(int64_t aTagsFolder,
const nsACString& aRelation,
bool aHasSearchTerms,
nsACString& _sqlFragment) {
if (!aHasSearchTerms)
@@ -1036,24 +1036,24 @@ nsNavHistory::ExecuteQuery(nsINavHistory
aOptions->Clone(getter_AddRefs(optionsClone));
NS_ENSURE_STATE(optionsClone);
RefPtr<nsNavHistoryQueryOptions> options = do_QueryObject(optionsClone);
NS_ENSURE_STATE(options);
// Create the root node.
RefPtr<nsNavHistoryContainerResultNode> 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<nsNavHistoryResultNode> tempRootNode;
- nsresult rv = bookmarks->ResultNodeForContainer(folderId, options,
+ nsresult rv = bookmarks->ResultNodeForContainer(folderGuid, options,
getter_AddRefs(tempRootNode));
if (NS_SUCCEEDED(rv)) {
rootNode = tempRootNode->GetAsContainer();
}
else {
NS_WARNING("Generating a generic empty node for a broken query!");
// This is a perf hack to generate an empty query that skips filtering.
options->SetExcludeItems(true);
@@ -1125,17 +1125,17 @@ bool IsOptimizableHistoryQuery(const Ref
return false;
if (aQuery->DomainIsHost() || !aQuery->Domain().IsEmpty())
return false;
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)
return false;
if (aQuery->Transitions().Length() > 0)
return false;
@@ -1689,27 +1689,27 @@ PlacesSQLQueryBuilder::SelectAsRoots()
nsAutoCString mobileString;
if (Preferences::GetBool(MOBILE_BOOKMARKS_PREF, false)) {
nsAutoCString mobileTitle;
history->GetStringFromName("MobileBookmarksFolderTitle", mobileTitle);
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(")");
return NS_OK;
}
nsresult
PlacesSQLQueryBuilder::SelectAsLeftPane()
@@ -2762,31 +2762,33 @@ nsNavHistory::QueryToSelectClause(const
for (uint32_t i = 0; i < transitions.Length(); ++i) {
nsPrintfCString param(":transition%d_", i);
clause.Condition("h.id IN (SELECT place_id FROM moz_historyvisits "
"WHERE visit_type = ")
.Param(param.get())
.Str(")");
}
- // folders
- const nsTArray<int64_t>& folders = aQuery->Folders();
- if (folders.Length() > 0) {
+ // parents
+ const nsTArray<nsCString>& 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 "
"WHERE b2.type = 2 "
") "
"SELECT id FROM parents "
")");
}
@@ -2912,21 +2914,21 @@ nsNavHistory::BindQueryClauseParameters(
// transitions
const nsTArray<uint32_t>& transitions = aQuery->Transitions();
for (uint32_t i = 0; i < transitions.Length(); ++i) {
nsPrintfCString paramName("transition%d_", i);
rv = statement->BindInt64ByName(paramName, transitions[i]);
NS_ENSURE_SUCCESS(rv, rv);
}
- // folders
- const nsTArray<int64_t>& 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<nsCString>& 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);
}
return NS_OK;
}
// nsNavHistory::ResultsAsList
@@ -3345,31 +3347,29 @@ nsNavHistory::QueryRowToResult(int64_t i
RefPtr<nsNavHistoryQuery> queryObj = do_QueryObject(query);
NS_ENSURE_STATE(queryObj);
RefPtr<nsNavHistoryQueryOptions> optionsObj = do_QueryObject(options);
NS_ENSURE_STATE(optionsObj);
// If this failed the query does not parse correctly, let the error pass and
// 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;
// Use the query item title, unless it's empty (in that case use the
// concrete folder title).
if (!aTitle.IsEmpty()) {
resultNode->mTitle = aTitle;
}
@@ -3624,53 +3624,53 @@ nsNavHistory::GetMonthYear(const PRExplo
return;
}
CopyUTF16toUTF8(monthYear, 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
// efficiently compute the results.
//
// A simple bookmarks query will result in a hierarchical tree of
// 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<nsNavHistoryQuery>& aQuery,
+static nsCString
+GetSimpleBookmarksQueryParent(const RefPtr<nsNavHistoryQuery>& aQuery,
const RefPtr<nsNavHistoryQueryOptions>& 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];
}
// ParseSearchTermsFromQuery
//
// Construct an array of search terms from the given query.
// Within a query, all the terms are ANDed together.
//
--- a/toolkit/components/places/nsNavHistory.h
+++ b/toolkit/components/places/nsNavHistory.h
@@ -60,16 +60,23 @@
// The preference we watch to know when the mobile bookmarks folder is filled by
// sync.
#define MOBILE_BOOKMARKS_PREF "browser.bookmarks.showMobileBookmarks"
// 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;
class nsNavHistory;
class PlacesDecayFrecencyCallback;
class PlacesSQLQueryBuilder;
class QueryKeyValuePair;
--- a/toolkit/components/places/nsNavHistoryQuery.cpp
+++ b/toolkit/components/places/nsNavHistoryQuery.cpp
@@ -105,17 +105,17 @@ static void SetOptionsKeyUint32(const ns
#define QUERYKEY_END_TIME "endTime"
#define QUERYKEY_END_TIME_REFERENCE "endTimeRef"
#define QUERYKEY_SEARCH_TERMS "terms"
#define QUERYKEY_MIN_VISITS "minVisits"
#define QUERYKEY_MAX_VISITS "maxVisits"
#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"
#define QUERYKEY_GROUP "group"
#define QUERYKEY_SORT "sort"
#define QUERYKEY_SORTING_ANNOTATION "sortingAnnotation"
#define QUERYKEY_RESULT_TYPE "type"
#define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
@@ -150,103 +150,16 @@ inline void AppendInt32(nsACString& str,
}
inline void AppendInt64(nsACString& str, int64_t i)
{
nsCString tmp;
tmp.AppendInt(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,
nsINavHistoryQueryOptions** _options)
{
NS_ENSURE_ARG_POINTER(_query);
NS_ENSURE_ARG_POINTER(_options);
@@ -381,23 +294,22 @@ nsNavHistory::QueryToQueryString(nsINavH
}
const nsCString& annot = query->Annotation();
nsAutoCString escaped;
bool success = NS_Escape(annot, escaped, url_XAlphas);
NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
queryString.Append(escaped);
}
- // folders
- const nsTArray<int64_t>& folders = query->Folders();
- for (uint32_t i = 0; i < folders.Length(); ++i) {
+ // parents
+ const nsTArray<nsCString>& 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
const nsTArray<nsString>& tags = query->Tags();
for (uint32_t i = 0; i < tags.Length(); ++i) {
nsAutoCString escapedTag;
if (!NS_Escape(NS_ConvertUTF16toUTF8(tags[i]), escapedTag, url_XAlphas))
return NS_ERROR_OUT_OF_MEMORY;
@@ -547,17 +459,17 @@ nsNavHistory::TokensToQuery(const nsTArr
nsNavHistoryQuery* aQuery,
nsNavHistoryQueryOptions* aOptions)
{
nsresult rv;
if (aTokens.Length() == 0)
return NS_OK;
- nsTArray<int64_t> folders;
+ nsTArray<nsCString> parents;
nsTArray<nsString> tags;
nsTArray<uint32_t> transitions;
for (uint32_t i = 0; i < aTokens.Length(); i ++) {
const QueryKeyValuePair& kvp = aTokens[i];
// begin time
if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME)) {
SetQueryKeyInt64(kvp.value, aQuery, &nsINavHistoryQuery::SetBeginTime);
@@ -607,30 +519,21 @@ nsNavHistory::TokensToQuery(const nsTArr
// domain string
} else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN)) {
nsAutoCString unescapedDomain(kvp.value);
NS_UnescapeURL(unescapedDomain); // modifies input
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
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), unescapedUri);
if (NS_FAILED(rv)) {
NS_WARNING("Unable to parse URI");
}
@@ -728,18 +631,20 @@ nsNavHistory::TokensToQuery(const nsTArr
&nsINavHistoryQueryOptions::SetAsyncEnabled);
// unknown key
} else {
NS_WARNING("TokensToQueries(), ignoring unknown key: ");
NS_WARNING(kvp.key.get());
}
}
- 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);
NS_ENSURE_SUCCESS(rv, rv);
}
if (transitions.Length() > 0) {
rv = aQuery->SetTransitions(transitions);
@@ -794,17 +699,17 @@ nsNavHistoryQuery::nsNavHistoryQuery()
nsNavHistoryQuery::nsNavHistoryQuery(const nsNavHistoryQuery& aOther)
: mMinVisits(aOther.mMinVisits), mMaxVisits(aOther.mMaxVisits),
mBeginTime(aOther.mBeginTime), mBeginTimeReference(aOther.mBeginTimeReference),
mEndTime(aOther.mEndTime), mEndTimeReference(aOther.mEndTimeReference),
mSearchTerms(aOther.mSearchTerms), mOnlyBookmarked(aOther.mOnlyBookmarked),
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)
{
}
NS_IMETHODIMP nsNavHistoryQuery::GetBeginTime(PRTime *aBeginTime)
{
*aBeginTime = mBeginTime;
@@ -1126,47 +1031,49 @@ NS_IMETHODIMP nsNavHistoryQuery::GetTags
}
NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot)
{
mTagsAreNot = 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<int64_t*>
- (moz_xmalloc(count * sizeof(int64_t)));
- NS_ENSURE_TRUE(folders, NS_ERROR_OUT_OF_MEMORY);
+ guids = static_cast<char**>
+ (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;
}
NS_IMETHODIMP nsNavHistoryQuery::GetTransitions(uint32_t* aCount,
uint32_t** aTransitions)
{
--- a/toolkit/components/places/nsNavHistoryQuery.h
+++ b/toolkit/components/places/nsNavHistoryQuery.h
@@ -40,17 +40,24 @@ public:
uint32_t EndTimeReference() { return mEndTimeReference; }
const nsString& SearchTerms() { return mSearchTerms; }
bool OnlyBookmarked() { return mOnlyBookmarked; }
bool DomainIsHost() { return mDomainIsHost; }
const nsCString& Domain() { return mDomain; }
nsIURI* Uri() { return mUri; } // NOT AddRef-ed!
bool AnnotationIsNot() { return mAnnotationIsNot; }
const nsCString& Annotation() { return mAnnotation; }
- const nsTArray<int64_t>& Folders() const { return mFolders; }
+ const nsTArray<nsCString>& Parents() { return mParents; }
+ nsresult SetParents(const nsTArray<nsCString>& aParents)
+ {
+ if (!mParents.ReplaceElementsAt(0, mParents.Length(), aParents))
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+ }
+
const nsTArray<nsString>& Tags() const { return mTags; }
nsresult SetTags(const nsTArray<nsString>& aTags)
{
if (!mTags.ReplaceElementsAt(0, mTags.Length(), aTags))
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
bool TagsAreNot() { return mTagsAreNot; }
@@ -80,17 +87,17 @@ protected:
uint32_t mEndTimeReference;
nsString mSearchTerms;
bool mOnlyBookmarked;
bool mDomainIsHost;
nsCString mDomain; // Default is IsVoid, empty string is valid query
nsCOMPtr<nsIURI> mUri;
bool mAnnotationIsNot;
nsCString mAnnotation;
- nsTArray<int64_t> mFolders;
+ nsTArray<nsCString> mParents;
nsTArray<nsString> mTags;
bool mTagsAreNot;
nsTArray<uint32_t> mTransitions;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryQuery, NS_NAVHISTORYQUERY_IID)
// nsNavHistoryQueryOptions
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -94,17 +94,17 @@ getUpdateRequirements(const RefPtr<nsNav
bool* aHasSearchTerms)
{
// first check if there are search terms
bool hasSearchTerms = *aHasSearchTerms = !aQuery->SearchTerms().IsEmpty();
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 &&
hasSearchTerms)) {
return QUERYUPDATE_COMPLEX_WITH_BOOKMARKS;
}
// Note: we don't currently have any complex non-bookmarked items, but these
@@ -3213,24 +3213,24 @@ nsNavHistoryFolderResultNode::GetUri(nsA
/**
* @return the queries that give you this bookmarks folder
*/
NS_IMETHODIMP
nsNavHistoryFolderResultNode::GetQuery(nsINavHistoryQuery** _query)
{
// get the query object
- nsCOMPtr<nsINavHistoryQuery> 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<nsNavHistoryQuery> query = new nsNavHistoryQuery();
+
+ nsTArray<nsCString> 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);
return NS_OK;
}
/**
@@ -3673,17 +3673,17 @@ nsNavHistoryFolderResultNode::OnItemAdde
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
rv = history->BookmarkIdToResultNode(aItemId, mOptions, getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
}
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);
}
else if (aItemType == nsINavBookmarksService::TYPE_SEPARATOR) {
node = new nsNavHistorySeparatorResultNode();
node->mItemId = aItemId;
node->mBookmarkGuid = aGUID;
--- a/toolkit/components/places/tests/queries/test_queryMultipleFolder.js
+++ b/toolkit/components/places/tests/queries/test_queryMultipleFolder.js
@@ -1,58 +1,96 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"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) {
let bm = await PlacesUtils.bookmarks.insert({
parentGuid: (await PlacesUtils.promiseItemGuid(folderIds[i])),
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;
let queryString = `place:${folderIds.map((id) => "folder=" + id).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(bookmarkIds[i], node.itemId, node.uri);
+ Assert.equal(bookmarkGuids[i], node.bookmarkGuid, node.uri);
}
rootNode.containerOpen = false;
// using getNewQuery and getNewQueryOptions
query = PlacesUtils.history.getNewQuery();
options = PlacesUtils.history.getNewQueryOptions();
query.setFolders(folderIds, folderIds.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(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;
+});