Bug 824502 - Change folder=<id> to parent=<guid> in Places' bookmark queries. r=mak

This allows queries to be stable across devices, and requires less work to obtain the ids.

MozReview-Commit-ID: 5KAKKags7o9

--HG--
extra : rebase_source : 22c01cf5b24468dd76dabe63fa9d1033d4138e54
This commit is contained in:
Mark Banner 2018-04-26 09:05:00 +01:00
Родитель ed86544f35
Коммит 11e49d2982
16 изменённых файлов: 252 добавлений и 225 удалений

Просмотреть файл

@ -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">
<menuitem id="bookmarksShowAll"
label="&showAllBookmarks2.label;"
@ -433,7 +433,7 @@
#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"
@ -445,7 +445,7 @@
#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"
@ -458,7 +458,7 @@
#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 -->

Просмотреть файл

@ -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"

Просмотреть файл

@ -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);">
<menuitem id="BMB_viewBookmarksToolbar"
class="menuitem-iconic subviewbutton"
@ -1149,7 +1149,7 @@
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"
@ -1161,7 +1161,7 @@
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>

Просмотреть файл

@ -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",

Просмотреть файл

@ -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";

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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"

Просмотреть файл

@ -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.

Просмотреть файл

@ -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<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,
@ -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<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);
}

Просмотреть файл

@ -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);
@ -176,6 +176,17 @@ public:
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.
*

Просмотреть файл

@ -191,7 +191,7 @@ NS_IMPL_CI_INTERFACE_GETTER(nsNavHistory,
namespace {
static int64_t GetSimpleBookmarksQueryFolder(const RefPtr<nsNavHistoryQuery>& aQuery,
static nsCString GetSimpleBookmarksQueryParent(const RefPtr<nsNavHistoryQuery>& aQuery,
const RefPtr<nsNavHistoryQueryOptions>& aOptions);
static void ParseSearchTermsFromQuery(const RefPtr<nsNavHistoryQuery>& aQuery,
nsTArray<nsString>* aTerms);
@ -1041,14 +1041,14 @@ nsNavHistory::ExecuteQuery(nsINavHistoryQuery *aQuery,
// 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();
@ -1130,7 +1130,7 @@ bool IsOptimizableHistoryQuery(const RefPtr<nsNavHistoryQuery>& 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<nsNavHistoryQuery>& aQuery,
.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 "
@ -2917,11 +2919,11 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageBaseStatement* statement,
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);
}
@ -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<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];
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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<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
@ -552,7 +464,7 @@ nsNavHistory::TokensToQuery(const nsTArray<QueryKeyValuePair>& aTokens,
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 ++) {
@ -612,18 +524,9 @@ nsNavHistory::TokensToQuery(const nsTArray<QueryKeyValuePair>& 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
} else if (kvp.key.EqualsLiteral(QUERYKEY_URI)) {
@ -733,8 +636,10 @@ nsNavHistory::TokensToQuery(const nsTArray<QueryKeyValuePair>& 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,38 +1036,40 @@ 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<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)) {
mParents.Clear();
for (size_t i = 0; i < aGuidCount; i++) {
if (!mParents.AppendElement(aGuids[i])) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
return NS_OK;
}

Просмотреть файл

@ -45,7 +45,14 @@ public:
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)
{
@ -85,7 +92,7 @@ protected:
nsCOMPtr<nsIURI> mUri;
bool mAnnotationIsNot;
nsCString mAnnotation;
nsTArray<int64_t> mFolders;
nsTArray<nsCString> mParents;
nsTArray<nsString> mTags;
bool mTagsAreNot;
nsTArray<uint32_t> mTransitions;

Просмотреть файл

@ -99,7 +99,7 @@ getUpdateRequirements(const RefPtr<nsNavHistoryQuery>& 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<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);
@ -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);

Просмотреть файл

@ -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;
});