commit 583e83c688f1d7634aba71d4fe4dec2df0b0adf0
parent 8fe34ccdcd91786074f3da375024470c0effa510
Author: Daisuke Akatsuka <daisuke@birchill.co.jp>
Date: Fri, 21 Nov 2025 06:13:49 +0000
Bug 1846461: Move logic that appends children of folder to nsNavHistoryResult r=places-reviewers,mak
Differential Revision: https://phabricator.services.mozilla.com/D273158
Diffstat:
4 files changed, 192 insertions(+), 246 deletions(-)
diff --git a/toolkit/components/places/nsNavBookmarks.cpp b/toolkit/components/places/nsNavBookmarks.cpp
@@ -1504,182 +1504,6 @@ nsNavBookmarks::GetItemTitle(int64_t aItemId, nsACString& _title) {
return NS_OK;
}
-nsresult nsNavBookmarks::QueryFolderChildren(
- int64_t aFolderId, nsNavHistoryQueryOptions* aOptions,
- nsCOMArray<nsNavHistoryResultNode>* aChildren) {
- NS_ENSURE_ARG_POINTER(aOptions);
- NS_ENSURE_ARG_POINTER(aChildren);
-
- // Select all children of a given folder, sorted by position.
- // This is a LEFT JOIN because not all bookmarks types have a place.
- // We construct a result where the first columns exactly match those returned
- // by mDBGetURLPageInfo, and additionally contains columns for position,
- // item_child, and folder_child from moz_bookmarks.
- nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
- nsNavHistory::GetTagsSqlFragment(
- nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS,
- aOptions->ExcludeItems()) +
- "SELECT "
- " h.id, h.url, b.title, h.rev_host, h.visit_count, "
- " h.last_visit_date, null, b.id, b.dateAdded, b.lastModified, b.parent, "
- " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, "
- " h.frecency, h.hidden, h.guid, null, null, null, "
- " b.guid, b.position, b.type, b.fk, t.guid, t.id, t.title "
- "FROM moz_bookmarks b "
- "LEFT JOIN moz_places h ON b.fk = h.id "
- "LEFT JOIN moz_bookmarks t ON t.guid = target_folder_guid(h.url) "
- "WHERE b.parent = :parent "
- "AND (NOT :excludeItems OR "
- "b.type = :folder OR "
- "h.url_hash BETWEEN hash('place', 'prefix_lo') "
- " AND hash('place', 'prefix_hi')) "
- "ORDER BY b.position ASC"_ns);
- NS_ENSURE_STATE(stmt);
- mozStorageStatementScoper scoper(stmt);
-
- nsresult rv = stmt->BindInt64ByName("parent"_ns, aFolderId);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->BindInt32ByName("folder"_ns, TYPE_FOLDER);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->BindInt32ByName("excludeItems"_ns, aOptions->ExcludeItems());
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<mozIStorageValueArray> row = do_QueryInterface(stmt, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- int32_t index = -1;
- bool hasResult;
- while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
- rv = ProcessFolderNodeRow(row, aOptions, aChildren, index);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- return NS_OK;
-}
-
-nsresult nsNavBookmarks::ProcessFolderNodeRow(
- mozIStorageValueArray* aRow, nsNavHistoryQueryOptions* aOptions,
- nsCOMArray<nsNavHistoryResultNode>* aChildren, int32_t& aCurrentIndex) {
- NS_ENSURE_ARG_POINTER(aRow);
- NS_ENSURE_ARG_POINTER(aOptions);
- NS_ENSURE_ARG_POINTER(aChildren);
-
- // The results will be in order of aCurrentIndex. Even if we don't add a node
- // because it was excluded, we need to count its index, so do that before
- // doing anything else.
- aCurrentIndex++;
-
- int32_t itemType;
- nsresult rv = aRow->GetInt32(kGetChildrenIndex_Type, &itemType);
- NS_ENSURE_SUCCESS(rv, rv);
- int64_t id;
- rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemId, &id);
- NS_ENSURE_SUCCESS(rv, rv);
-
- RefPtr<nsNavHistoryResultNode> node;
-
- if (itemType == TYPE_BOOKMARK) {
- nsNavHistory* history = nsNavHistory::GetHistoryService();
- NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
- rv = history->RowToResult(aRow, aOptions, getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
- uint32_t nodeType;
- node->GetType(&nodeType);
- if (nodeType == nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
- aOptions->ExcludeQueries()) {
- return NS_OK;
- }
- } else if (itemType == TYPE_FOLDER) {
- nsAutoCString title;
- bool isNull;
- rv = aRow->GetIsNull(nsNavHistory::kGetInfoIndex_Title, &isNull);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!isNull) {
- rv = aRow->GetUTF8String(nsNavHistory::kGetInfoIndex_Title, title);
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- nsAutoCString guid;
- rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, guid);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Don't use options from the parent to build the new folder node, it will
- // inherit those later when it's inserted in the result.
- node = new nsNavHistoryFolderResultNode(id, guid, id, guid, title,
- new nsNavHistoryQueryOptions());
-
- rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
- reinterpret_cast<int64_t*>(&node->mDateAdded));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemLastModified,
- reinterpret_cast<int64_t*>(&node->mLastModified));
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
- // This is a separator.
- node = new nsNavHistorySeparatorResultNode();
-
- node->mItemId = id;
- rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, node->mBookmarkGuid);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
- reinterpret_cast<int64_t*>(&node->mDateAdded));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemLastModified,
- reinterpret_cast<int64_t*>(&node->mLastModified));
- NS_ENSURE_SUCCESS(rv, rv);
- }
-
- // Store the index of the node within this container. Note that this is not
- // moz_bookmarks.position.
- node->mBookmarkIndex = aCurrentIndex;
-
- NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
- return NS_OK;
-}
-
-nsresult nsNavBookmarks::QueryFolderChildrenAsync(
- nsNavHistoryFolderResultNode* aNode,
- mozIStoragePendingStatement** _pendingStmt) {
- NS_ENSURE_ARG_POINTER(aNode);
- NS_ENSURE_ARG_POINTER(_pendingStmt);
-
- // Select all children of a given folder, sorted by position.
- // This is a LEFT JOIN because not all bookmarks types have a place.
- // We construct a result where the first columns exactly match those returned
- // by mDBGetURLPageInfo, and additionally contains columns for position,
- // item_child, and folder_child from moz_bookmarks.
- nsCOMPtr<mozIStorageAsyncStatement> stmt = mDB->GetAsyncStatement(
- "SELECT h.id, h.url, b.title, h.rev_host, h.visit_count, "
- "h.last_visit_date, null, b.id, b.dateAdded, b.lastModified, "
- "b.parent, null, h.frecency, h.hidden, h.guid, null, null, null, "
- "b.guid, b.position, b.type, b.fk, t.guid, t.id, t.title "
- "FROM moz_bookmarks b "
- "LEFT JOIN moz_places h ON b.fk = h.id "
- "LEFT JOIN moz_bookmarks t ON t.guid = target_folder_guid(h.url) "
- "WHERE b.parent = :parent "
- "AND (NOT :excludeItems OR "
- "b.type = :folder OR "
- "h.url_hash BETWEEN hash('place', 'prefix_lo') AND hash('place', "
- "'prefix_hi')) "
- "ORDER BY b.position ASC");
- NS_ENSURE_STATE(stmt);
-
- nsresult rv = stmt->BindInt64ByName("parent"_ns, aNode->mTargetFolderItemId);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = stmt->BindInt32ByName("folder"_ns, TYPE_FOLDER);
- NS_ENSURE_SUCCESS(rv, rv);
- rv =
- stmt->BindInt32ByName("excludeItems"_ns, aNode->mOptions->ExcludeItems());
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<mozIStoragePendingStatement> pendingStmt;
- rv = stmt->ExecuteAsync(aNode, getter_AddRefs(pendingStmt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- NS_IF_ADDREF(*_pendingStmt = pendingStmt);
- return NS_OK;
-}
-
nsresult nsNavBookmarks::FetchFolderInfo(int64_t aFolderId,
int32_t* _folderCount,
nsACString& _guid,
diff --git a/toolkit/components/places/nsNavBookmarks.h b/toolkit/components/places/nsNavBookmarks.h
@@ -101,46 +101,6 @@ class nsNavBookmarks final : public nsINavBookmarksService,
bool aHidden, uint32_t aVisitCount, uint32_t aTyped,
const nsAString& aLastKnownTitle);
- // 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,
- nsCOMArray<nsNavHistoryResultNode>* children);
-
- /**
- * Turns aRow into a node and appends it to aChildren if it is appropriate to
- * do so.
- *
- * @param aRow
- * A Storage statement (in the case of synchronous execution) or row of
- * a result set (in the case of asynchronous execution).
- * @param aOptions
- * The options of the parent folder node. These are the options used
- * to fill the parent node.
- * @param aChildren
- * The children of the parent folder node.
- * @param aCurrentIndex
- * The index of aRow within the results. When called on the first row,
- * this should be set to -1.
- */
- nsresult ProcessFolderNodeRow(mozIStorageValueArray* aRow,
- nsNavHistoryQueryOptions* aOptions,
- nsCOMArray<nsNavHistoryResultNode>* aChildren,
- int32_t& aCurrentIndex);
-
- /**
- * The async version of QueryFolderChildren.
- *
- * @param aNode
- * The folder node that will receive the children.
- * @param _pendingStmt
- * The Storage pending statement that will be used to control async
- * execution.
- */
- nsresult QueryFolderChildrenAsync(nsNavHistoryFolderResultNode* aNode,
- mozIStoragePendingStatement** _pendingStmt);
-
/**
* Fetches information about the specified id from the database.
*
diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -2689,17 +2689,7 @@ nsNavHistoryFolderResultNode::GetQueryOptions(
}
nsresult nsNavHistoryFolderResultNode::FillChildren() {
- NS_ASSERTION(!mContentsValid,
- "Don't call FillChildren when contents are valid");
- NS_ASSERTION(mChildren.Count() == 0,
- "We are trying to fill children when there already are some");
-
- nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
- NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
-
- // Actually get the folder children from the bookmark service.
- nsresult rv =
- bookmarks->QueryFolderChildren(mTargetFolderItemId, mOptions, &mChildren);
+ nsresult rv = FillChildrenInternal();
NS_ENSURE_SUCCESS(rv, rv);
// PERFORMANCE: it may be better to also fill any child folders at this point
@@ -2761,23 +2751,16 @@ void nsNavHistoryFolderResultNode::EnsureRegisteredAsFolderObserver() {
}
/**
- * The async version of FillChildren. This begins asynchronous execution by
- * calling nsNavBookmarks::QueryFolderChildrenAsync. During execution, this
- * node's async Storage callbacks, HandleResult and HandleCompletion, will be
- * called.
+ * The async version of FillChildren. This begins asynchronous execution by
+ * calling FillChildrenInternal. During execution, this node's async Storage
+ * callbacks, HandleResult and HandleCompletion, will be called.
*/
nsresult nsNavHistoryFolderResultNode::FillChildrenAsync() {
- NS_ASSERTION(!mContentsValid, "FillChildrenAsync when contents are valid");
- NS_ASSERTION(mChildren.Count() == 0, "FillChildrenAsync when children exist");
-
// ProcessFolderNodeChild, called in HandleResult, increments this for every
// result row it processes. Initialize it here as we begin async execution.
mAsyncBookmarkIndex = -1;
- nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService();
- NS_ENSURE_TRUE(bmSvc, NS_ERROR_OUT_OF_MEMORY);
- nsresult rv =
- bmSvc->QueryFolderChildrenAsync(this, getter_AddRefs(mAsyncPendingStmt));
+ nsresult rv = FillChildrenInternal(getter_AddRefs(mAsyncPendingStmt));
NS_ENSURE_SUCCESS(rv, rv);
// Register with the result for updates. All updates during async execution
@@ -2787,6 +2770,168 @@ nsresult nsNavHistoryFolderResultNode::FillChildrenAsync() {
return NS_OK;
}
+nsresult nsNavHistoryFolderResultNode::FillChildrenInternal(
+ mozIStoragePendingStatement** aPendingStmt) {
+ NS_ASSERTION(!mContentsValid,
+ "Don't call FillChildrenInternal when contents are valid");
+ NS_ASSERTION(mChildren.Count() == 0,
+ "We are trying to fill children when there already are some");
+
+ // Select all children of a given folder, sorted by position.
+ // This is a LEFT JOIN because not all bookmarks types have a place.
+ // We construct a result where the first columns exactly match those returned
+ // by mDBGetURLPageInfo, and additionally contains columns for position,
+ // item_child, and folder_child from moz_bookmarks.
+ bool isAsync = !!aPendingStmt;
+ nsCString sql =
+ "SELECT "
+ " h.id, h.url, b.title, h.rev_host, h.visit_count, h.last_visit_date, "
+ " null, b.id, b.dateAdded, b.lastModified, b.parent, "_ns +
+ nsCString(
+ isAsync
+ ? " null, "
+ : " (SELECT tags FROM tagged WHERE place_id = h.id) AS tags, ") +
+ " h.frecency, h.hidden, h.guid, null, null, null, b.guid, b.position, "
+ " b.type, b.fk, t.guid, t.id, t.title "
+ "FROM moz_bookmarks b "
+ "LEFT JOIN moz_places h ON b.fk = h.id "
+ "LEFT JOIN moz_bookmarks t ON t.guid = target_folder_guid(h.url) "
+ "WHERE b.parent = :parent "
+ " AND ("
+ " NOT :excludeItems OR "
+ " b.type = :folder OR "
+ " h.url_hash BETWEEN "
+ " hash('place', 'prefix_lo') AND hash('place', 'prefix_hi')"
+ " ) "
+ "ORDER BY b.position ASC"_ns;
+
+ RefPtr<Database> db = Database::GetDatabase();
+ NS_ENSURE_STATE(db);
+ nsCOMPtr<mozIStorageBaseStatement> stmt;
+ if (isAsync) {
+ stmt = db->GetAsyncStatement(sql);
+ NS_ENSURE_STATE(stmt);
+ } else {
+ stmt = db->GetStatement(nsNavHistory::GetTagsSqlFragment(
+ nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS,
+ mOptions->ExcludeItems()) +
+ sql);
+ NS_ENSURE_STATE(stmt);
+ }
+
+ nsresult rv = stmt->BindInt64ByName("parent"_ns, mTargetFolderItemId);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = stmt->BindInt32ByName("folder"_ns, nsINavBookmarksService::TYPE_FOLDER);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = stmt->BindInt32ByName("excludeItems"_ns, mOptions->ExcludeItems());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (isAsync) {
+ nsCOMPtr<mozIStorageAsyncStatement> async = do_QueryInterface(stmt, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<mozIStoragePendingStatement> pendingStmt;
+ rv = async->ExecuteAsync(this, getter_AddRefs(pendingStmt));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_IF_ADDREF(*aPendingStmt = pendingStmt);
+ } else {
+ nsCOMPtr<mozIStorageStatement> sync = do_QueryInterface(stmt, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mozStorageStatementScoper scoper(sync);
+ nsCOMPtr<mozIStorageValueArray> row = do_QueryInterface(sync, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t index = -1;
+ bool hasResult;
+ while (NS_SUCCEEDED(sync->ExecuteStep(&hasResult)) && hasResult) {
+ rv = AppendRowAsChild(row, index);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult nsNavHistoryFolderResultNode::AppendRowAsChild(
+ mozIStorageValueArray* aRow, int32_t& aCurrentIndex) {
+ NS_ENSURE_ARG_POINTER(aRow);
+
+ // The results will be in order of aCurrentIndex. Even if we don't add a node
+ // because it was excluded, we need to count its index, so do that before
+ // doing anything else.
+ aCurrentIndex++;
+
+ int32_t itemType;
+ nsresult rv =
+ aRow->GetInt32(nsNavBookmarks::kGetChildrenIndex_Type, &itemType);
+ NS_ENSURE_SUCCESS(rv, rv);
+ int64_t id;
+ rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemId, &id);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ RefPtr<nsNavHistoryResultNode> node;
+
+ if (itemType == nsINavBookmarksService::TYPE_BOOKMARK) {
+ nsNavHistory* history = nsNavHistory::GetHistoryService();
+ NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
+ rv = history->RowToResult(aRow, mOptions, getter_AddRefs(node));
+ NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t nodeType;
+ node->GetType(&nodeType);
+ if (nodeType == nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
+ mOptions->ExcludeQueries()) {
+ return NS_OK;
+ }
+ } else if (itemType == nsINavBookmarksService::TYPE_FOLDER) {
+ nsAutoCString title;
+ bool isNull;
+ rv = aRow->GetIsNull(nsNavHistory::kGetInfoIndex_Title, &isNull);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!isNull) {
+ rv = aRow->GetUTF8String(nsNavHistory::kGetInfoIndex_Title, title);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsAutoCString guid;
+ rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, guid);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Don't use options from the parent to build the new folder node, it will
+ // inherit those later when it's inserted in the result.
+ node = new nsNavHistoryFolderResultNode(id, guid, id, guid, title,
+ new nsNavHistoryQueryOptions());
+
+ rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
+ reinterpret_cast<int64_t*>(&node->mDateAdded));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemLastModified,
+ reinterpret_cast<int64_t*>(&node->mLastModified));
+ NS_ENSURE_SUCCESS(rv, rv);
+ } else {
+ // This is a separator.
+ node = new nsNavHistorySeparatorResultNode();
+
+ node->mItemId = id;
+ rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid,
+ node->mBookmarkGuid);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
+ reinterpret_cast<int64_t*>(&node->mDateAdded));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemLastModified,
+ reinterpret_cast<int64_t*>(&node->mLastModified));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // Store the index of the node within this container. Note that this is not
+ // moz_bookmarks.position.
+ node->mBookmarkIndex = aCurrentIndex;
+
+ NS_ENSURE_TRUE(mChildren.AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
+ return NS_OK;
+}
+
/**
* A mozIStorageStatementCallback method. Called during the async execution
* begun by FillChildrenAsync.
@@ -2798,17 +2943,10 @@ NS_IMETHODIMP
nsNavHistoryFolderResultNode::HandleResult(mozIStorageResultSet* aResultSet) {
NS_ENSURE_ARG_POINTER(aResultSet);
- nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService();
- if (!bmSvc) {
- CancelAsyncOpen(false);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
// Consume all the currently available rows of the result set.
nsCOMPtr<mozIStorageRow> row;
while (NS_SUCCEEDED(aResultSet->GetNextRow(getter_AddRefs(row))) && row) {
- nsresult rv = bmSvc->ProcessFolderNodeRow(row, mOptions, &mChildren,
- mAsyncBookmarkIndex);
+ nsresult rv = AppendRowAsChild(row, mAsyncBookmarkIndex);
if (NS_FAILED(rv)) {
CancelAsyncOpen(false);
return rv;
diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h
@@ -21,6 +21,7 @@
#include "nsTHashMap.h"
#include "nsCycleCollectionParticipant.h"
#include "mozIStoragePendingStatement.h"
+#include "mozIStorageValueArray.h"
#include "Helpers.h"
class nsNavHistory;
@@ -797,6 +798,29 @@ class nsNavHistoryFolderResultNode final
nsresult OnChildrenFilled();
void EnsureRegisteredAsFolderObserver();
nsresult FillChildrenAsync();
+ /*
+ * Fill children of this folder by the current query.
+ *
+ * @param aPendingStmt
+ * The Storage pending statement that will be used to control async
+ * execution. If this is nullptr, this method processes as sync.
+ */
+ nsresult FillChildrenInternal(
+ mozIStoragePendingStatement** aPendingStmt = nullptr);
+
+ /**
+ * Turns aRow into a node and appends it as a child of this node if it is
+ * appropriate to do so.
+ *
+ * @param aRow
+ * A Storage statement (in the case of synchronous execution) or row of
+ * a result set (in the case of asynchronous execution).
+ * @param aCurrentIndex
+ * The index of aRow within the results. When called on the first row,
+ * this should be set to -1.
+ */
+ nsresult AppendRowAsChild(mozIStorageValueArray* aRow,
+ int32_t& aCurrentIndex);
bool mIsRegisteredFolderObserver;
int32_t mAsyncBookmarkIndex;