diff --git a/toolkit/components/places/nsINavHistoryService.idl b/toolkit/components/places/nsINavHistoryService.idl index 7f2043be780f..484c2ac17ea9 100644 --- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -266,7 +266,7 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode * generated this node, this item will report it has no children and never try * to populate itself. */ -[scriptable, uuid(91AC5E59-3F5C-4ACD-AB3B-325FC425A5A1)] +[scriptable, uuid(62817759-4FEE-44A3-B58C-3E2F5AFC9D0A)] interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode { /** @@ -283,10 +283,18 @@ interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode readonly attribute nsINavHistoryQueryOptions queryOptions; /** - * For both simple folder nodes and simple-folder-query nodes, this is set - * to the concrete itemId of the folder. Otherwise, this is set to -1. + * For both simple folder queries and folder shortcut queries, this is set to + * the concrete itemId of the folder (i.e. for folder shortcuts it's the + * target folder id). Otherwise, this is set to -1. */ readonly attribute long long folderItemId; + + /** + * For both simple folder queries and folder shortcut queries, this is set to + * the concrete guid of the folder (i.e. for folder shortcuts it's the target + * folder guid). Otherwise, this is set to an empty string. + */ + readonly attribute ACString targetFolderGuid; }; diff --git a/toolkit/components/places/nsNavBookmarks.cpp b/toolkit/components/places/nsNavBookmarks.cpp index 09ba90249498..7278ef47c60c 100644 --- a/toolkit/components/places/nsNavBookmarks.cpp +++ b/toolkit/components/places/nsNavBookmarks.cpp @@ -1629,6 +1629,7 @@ nsNavBookmarks::ResultNodeForContainer(int64_t aItemId, (*aNode)->mDateAdded = bookmark.dateAdded; (*aNode)->mLastModified = bookmark.lastModified; (*aNode)->mBookmarkGuid = bookmark.guid; + (*aNode)->GetAsFolder()->mTargetFolderGuid = bookmark.guid; NS_ADDREF(*aNode); return NS_OK; @@ -1735,6 +1736,10 @@ nsNavBookmarks::ProcessFolderNodeRow( node = new nsNavHistoryFolderResultNode(title, aOptions, id); + rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, node->mBookmarkGuid); + NS_ENSURE_SUCCESS(rv, rv); + node->GetAsFolder()->mTargetFolderGuid = node->mBookmarkGuid; + rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded, reinterpret_cast(&node->mDateAdded)); NS_ENSURE_SUCCESS(rv, rv); @@ -1750,6 +1755,8 @@ nsNavBookmarks::ProcessFolderNodeRow( 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(&node->mDateAdded)); NS_ENSURE_SUCCESS(rv, rv); @@ -1762,11 +1769,7 @@ nsNavBookmarks::ProcessFolderNodeRow( // moz_bookmarks.position. node->mBookmarkIndex = aCurrentIndex; - rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, node->mBookmarkGuid); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY); - return NS_OK; } diff --git a/toolkit/components/places/nsNavHistory.cpp b/toolkit/components/places/nsNavHistory.cpp index 5cf12a6e4dd7..603ab056d82a 100644 --- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -3918,17 +3918,17 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, NS_ENSURE_SUCCESS(rv, rv); } - nsRefPtr resultNode; - rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon, - getter_AddRefs(resultNode)); - NS_ENSURE_SUCCESS(rv,rv); - + nsAutoCString guid; if (itemId != -1) { - rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, - resultNode->mBookmarkGuid); + rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, guid); NS_ENSURE_SUCCESS(rv, rv); } + nsRefPtr resultNode; + rv = QueryRowToResult(itemId, guid, url, title, accessCount, time, favicon, + getter_AddRefs(resultNode)); + NS_ENSURE_SUCCESS(rv, rv); + if (itemId != -1 || aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_TAG_QUERY) { // RESULTS_AS_TAG_QUERY has date columns @@ -4003,12 +4003,17 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, // folder or query node. nsresult -nsNavHistory::QueryRowToResult(int64_t itemId, const nsACString& aURI, +nsNavHistory::QueryRowToResult(int64_t itemId, + const nsACString& aBookmarkGuid, + const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, PRTime aTime, const nsACString& aFavicon, nsNavHistoryResultNode** aNode) { + MOZ_ASSERT((itemId != -1 && !aBookmarkGuid.IsEmpty()) || + (itemId == -1 && aBookmarkGuid.IsEmpty())); + nsCOMArray queries; nsCOMPtr options; nsresult rv = QueryStringToQueryArray(aURI, &queries, @@ -4019,18 +4024,23 @@ nsNavHistory::QueryRowToResult(int64_t itemId, const nsACString& aURI, // handle it later. if (NS_SUCCEEDED(rv)) { // Check if this is a folder shortcut, so we can take a faster path. - int64_t folderId = GetSimpleBookmarksQueryFolder(queries, options); - if (folderId) { + int64_t targetFolderId = GetSimpleBookmarksQueryFolder(queries, options); + if (targetFolderId) { nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); - rv = bookmarks->ResultNodeForContainer(folderId, options, + rv = bookmarks->ResultNodeForContainer(targetFolderId, options, getter_AddRefs(resultNode)); // If this failed the shortcut is pointing to nowhere, let the error pass // and handle it later. if (NS_SUCCEEDED(rv)) { - // This is the query itemId, and is what is exposed by node.itemId. - resultNode->GetAsFolder()->mQueryItemId = itemId; + // 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 void (in that case use the // concrete folder title). diff --git a/toolkit/components/places/nsNavHistory.h b/toolkit/components/places/nsNavHistory.h index 7233734f52ec..4ab4c2599989 100644 --- a/toolkit/components/places/nsNavHistory.h +++ b/toolkit/components/places/nsNavHistory.h @@ -232,7 +232,9 @@ public: nsresult RowToResult(mozIStorageValueArray* aRow, nsNavHistoryQueryOptions* aOptions, nsNavHistoryResultNode** aResult); - nsresult QueryRowToResult(int64_t aItemId, const nsACString& aURI, + nsresult QueryRowToResult(int64_t aItemId, + const nsACString& aBookmarkGuid, + const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, PRTime aTime, const nsACString& aFavicon, diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp index 1d90b77ca1b6..1ee768644dba 100644 --- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -1994,10 +1994,15 @@ nsNavHistoryQueryResultNode::GetUri(nsACString& aURI) NS_IMETHODIMP nsNavHistoryQueryResultNode::GetFolderItemId(int64_t* aItemId) { - *aItemId = mItemId; + *aItemId = -1; return NS_OK; } +NS_IMETHODIMP +nsNavHistoryQueryResultNode::GetTargetFolderGuid(nsACString& aGuid) { + aGuid = EmptyCString(); + return NS_OK; +} NS_IMETHODIMP nsNavHistoryQueryResultNode::GetQueries(uint32_t* queryCount, @@ -2978,7 +2983,7 @@ nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode( nsNavHistoryResultNode::RESULT_TYPE_FOLDER, aOptions), mContentsValid(false), - mQueryItemId(-1), + mTargetFolderItemId(aFolderId), mIsRegisteredFolderObserver(false) { mItemId = aFolderId; @@ -2987,7 +2992,7 @@ nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode( nsNavHistoryFolderResultNode::~nsNavHistoryFolderResultNode() { if (mIsRegisteredFolderObserver && mResult) - mResult->RemoveBookmarkFolderObserver(this, mItemId); + mResult->RemoveBookmarkFolderObserver(this, mTargetFolderItemId); } @@ -3066,22 +3071,16 @@ nsNavHistoryFolderResultNode::GetHasChildren(bool* aHasChildren) return NS_OK; } -/** - * @return the id of the item from which the folder node was generated, it - * could be either a concrete folder-itemId or the id used in a - * simple-folder-query-bookmark (place:folder=X). - */ NS_IMETHODIMP -nsNavHistoryFolderResultNode::GetItemId(int64_t* aItemId) +nsNavHistoryFolderResultNode::GetFolderItemId(int64_t* aItemId) { - *aItemId = mQueryItemId == -1 ? mItemId : mQueryItemId; + *aItemId = mTargetFolderItemId; return NS_OK; } NS_IMETHODIMP -nsNavHistoryFolderResultNode::GetFolderItemId(int64_t* aItemId) -{ - *aItemId = mItemId; +nsNavHistoryFolderResultNode::GetTargetFolderGuid(nsACString& aGuid) { + aGuid = mTargetFolderGuid; return NS_OK; } @@ -3129,7 +3128,7 @@ nsNavHistoryFolderResultNode::GetQueries(uint32_t* queryCount, NS_ENSURE_SUCCESS(rv, rv); // query just has the folder ID set and nothing else - rv = query->SetFolders(&mItemId, 1); + rv = query->SetFolders(&mTargetFolderItemId, 1); NS_ENSURE_SUCCESS(rv, rv); // make array of our 1 query @@ -3171,7 +3170,7 @@ nsNavHistoryFolderResultNode::FillChildren() NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); // Actually get the folder children from the bookmark service. - nsresult rv = bookmarks->QueryFolderChildren(mItemId, mOptions, &mChildren); + nsresult rv = bookmarks->QueryFolderChildren(mTargetFolderItemId, mOptions, &mChildren); NS_ENSURE_SUCCESS(rv, rv); // PERFORMANCE: it may be better to also fill any child folders at this point @@ -3235,7 +3234,7 @@ void nsNavHistoryFolderResultNode::EnsureRegisteredAsFolderObserver() { if (!mIsRegisteredFolderObserver && mResult) { - mResult->AddBookmarkFolderObserver(this, mItemId); + mResult->AddBookmarkFolderObserver(this, mTargetFolderItemId); mIsRegisteredFolderObserver = true; } } @@ -3260,7 +3259,7 @@ nsNavHistoryFolderResultNode::FillChildrenAsync() nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bmSvc, NS_ERROR_OUT_OF_MEMORY); nsresult rv = - bmSvc->QueryFolderChildrenAsync(this, mItemId, + bmSvc->QueryFolderChildrenAsync(this, mTargetFolderItemId, getter_AddRefs(mAsyncPendingStmt)); NS_ENSURE_SUCCESS(rv, rv); @@ -3358,7 +3357,7 @@ nsNavHistoryFolderResultNode::ClearChildren(bool unregister) bool needsUnregister = unregister && (mContentsValid || mAsyncPendingStmt); if (needsUnregister && mResult && mIsRegisteredFolderObserver) { - mResult->RemoveBookmarkFolderObserver(this, mItemId); + mResult->RemoveBookmarkFolderObserver(this, mTargetFolderItemId); mIsRegisteredFolderObserver = false; } mContentsValid = false; @@ -3450,7 +3449,7 @@ nsNavHistoryFolderResultNode::ReindexRange(int32_t aStartIndex, /** - * Searches this folder for a node with the given id. + * Searches this folder for a node with the given id/target-folder-id. * * @return the node if found, null otherwise. * @note Does not addref the node! @@ -3462,7 +3461,7 @@ nsNavHistoryFolderResultNode::FindChildById(int64_t aItemId, for (int32_t i = 0; i < mChildren.Count(); ++i) { if (mChildren[i]->mItemId == aItemId || (mChildren[i]->IsFolder() && - mChildren[i]->GetAsFolder()->mQueryItemId == aItemId)) { + mChildren[i]->GetAsFolder()->mTargetFolderItemId == aItemId)) { *aNodeIndex = i; return mChildren[i]; } @@ -3506,7 +3505,7 @@ nsNavHistoryFolderResultNode::OnItemAdded(int64_t aItemId, const nsACString& aGUID, const nsACString& aParentGUID) { - NS_ASSERTION(aParentFolder == mItemId, "Got wrong bookmark update"); + MOZ_ASSERT(aParentFolder == mTargetFolderItemId, "Got wrong bookmark update"); RESTART_AND_RETURN_IF_ASYNC_PENDING(); @@ -3611,13 +3610,15 @@ nsNavHistoryFolderResultNode::OnItemRemoved(int64_t aItemId, const nsACString& aGUID, const nsACString& aParentGUID) { - // We only care about notifications when a child changes. When the deleted - // item is us, our parent should also be registered and will remove us from - // its list. - if (mItemId == aItemId) + // If this folder is a folder shortcut, we should never be notified for the + // removal of the shortcut (the parent node would be). + MOZ_ASSERT(mItemId == mTargetFolderItemId || aItemId != mItemId); + + // In any case though, here we only care about the children removal. + if (mTargetFolderItemId == aItemId) return NS_OK; - NS_ASSERTION(aParentFolder == mItemId, "Got wrong bookmark update"); + MOZ_ASSERT(aParentFolder == mTargetFolderItemId, "Got wrong bookmark update"); RESTART_AND_RETURN_IF_ASYNC_PENDING(); @@ -3756,15 +3757,6 @@ nsNavHistoryFolderResultNode::OnItemChanged(int64_t aItemId, const nsACString& aGUID, const nsACString&aParentGUID) { - // The query-item's title is used for simple-query nodes - if (mQueryItemId != -1) { - bool isTitleChange = aProperty.EqualsLiteral("title"); - if ((mQueryItemId == aItemId && !isTitleChange) || - (mQueryItemId != aItemId && isTitleChange)) { - return NS_OK; - } - } - RESTART_AND_RETURN_IF_ASYNC_PENDING(); return nsNavHistoryResultNode::OnItemChanged(aItemId, aProperty, @@ -3864,7 +3856,7 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId, const nsACString& aOldParentGUID, const nsACString& aNewParentGUID) { - NS_ASSERTION(aOldParent == mItemId || aNewParent == mItemId, + NS_ASSERTION(aOldParent == mTargetFolderItemId || aNewParent == mTargetFolderItemId, "Got a bookmark message that doesn't belong to us"); RESTART_AND_RETURN_IF_ASYNC_PENDING(); @@ -3876,9 +3868,9 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId, // example the Library left pane could have refreshed and replaced the // right pane as a consequence. In such a case our contents are already // up-to-date. That's OK. - if (node && aNewParent == mItemId && index == static_cast(aNewIndex)) + if (node && aNewParent == mTargetFolderItemId && index == static_cast(aNewIndex)) return NS_OK; - if (!node && aOldParent == mItemId) + if (!node && aOldParent == mTargetFolderItemId) return NS_OK; bool excludeItems = (mResult && mResult->mRootNode->mOptions->ExcludeItems()) || @@ -3922,11 +3914,11 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId, rv = bookmarks->GetItemTitle(aItemId, itemTitle); NS_ENSURE_SUCCESS(rv, rv); } - if (aOldParent == mItemId) { + if (aOldParent == mTargetFolderItemId) { OnItemRemoved(aItemId, aOldParent, aOldIndex, aItemType, itemURI, aGUID, aOldParentGUID); } - if (aNewParent == mItemId) { + if (aNewParent == mTargetFolderItemId) { OnItemAdded(aItemId, aNewParent, aNewIndex, aItemType, itemURI, itemTitle, PR_Now(), // This is a dummy dateAdded, not the real value. aGUID, aNewParentGUID); diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index 9490bf6b02f9..97e62a97a765 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -203,7 +203,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) // implementation and all subclasses. More complex are GetIcon, GetParent // (which depends on the definition of container result node), and GetUri // (which is overridded for lazy construction for some containers). -#define NS_IMPLEMENT_SIMPLE_RESULTNODE_NO_GETITEMMID \ +#define NS_IMPLEMENT_SIMPLE_RESULTNODE \ NS_IMETHOD GetTitle(nsACString& aTitle) \ { aTitle = mTitle; return NS_OK; } \ NS_IMETHOD GetAccessCount(uint32_t* aAccessCount) \ @@ -217,10 +217,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) NS_IMETHOD GetDateAdded(PRTime* aDateAdded) \ { *aDateAdded = mDateAdded; return NS_OK; } \ NS_IMETHOD GetLastModified(PRTime* aLastModified) \ - { *aLastModified = mLastModified; return NS_OK; } - -#define NS_IMPLEMENT_SIMPLE_RESULTNODE \ - NS_IMPLEMENT_SIMPLE_RESULTNODE_NO_GETITEMMID \ + { *aLastModified = mLastModified; return NS_OK; } \ NS_IMETHOD GetItemId(int64_t* aId) \ { *aId = mItemId; return NS_OK; } @@ -233,8 +230,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) // (GetUri is redefined only by QueryResultNode and FolderResultNode because // the queries might not necessarily be parsed. The rest just return the node's // buffer.) -#define NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID \ - NS_IMPLEMENT_SIMPLE_RESULTNODE_NO_GETITEMMID \ +#define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \ + NS_IMPLEMENT_SIMPLE_RESULTNODE \ NS_IMETHOD GetIcon(nsACString& aIcon) \ { return nsNavHistoryResultNode::GetIcon(aIcon); } \ NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) \ @@ -248,11 +245,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) \ { return nsNavHistoryResultNode::GetBookmarkGuid(aBookmarkGuid); } -#define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \ - NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID \ - NS_IMETHOD GetItemId(int64_t* aId) \ - { *aId = mItemId; return NS_OK; } - class nsNavHistoryResultNode : public nsINavHistoryResultNode { public: @@ -711,9 +703,9 @@ public: int64_t aFolderId); NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID + NS_FORWARD_COMMON_RESULTNODE_TO_BASE NS_IMETHOD GetType(uint32_t* type) { - if (mQueryItemId != -1) { + if (mTargetFolderItemId != mItemId) { *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT; } else { *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER; @@ -723,7 +715,6 @@ public: NS_IMETHOD GetUri(nsACString& aURI); NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN NS_IMETHOD GetHasChildren(bool* aHasChildren); - NS_IMETHOD GetItemId(int64_t *aItemId); NS_DECL_NSINAVHISTORYQUERYRESULTNODE virtual nsresult OpenContainer(); @@ -741,9 +732,12 @@ public: // after the container is closed until a notification comes in bool mContentsValid; - // If the node is generated from a place:folder=X query, this is the query's - // itemId. - int64_t mQueryItemId; + // If the node is generated from a place:folder=X query, this is the target + // folder id and GUID. For regular folder nodes, they are set to the same + // values as mItemId and mBookmarkGuid. For more complex queries, they are set + // to -1/an empty string. + int64_t mTargetFolderItemId; + nsCString mTargetFolderGuid; nsresult FillChildren(); void ClearChildren(bool aUnregister); diff --git a/toolkit/components/places/tests/unit/test_1105866.js b/toolkit/components/places/tests/unit/test_1105866.js new file mode 100644 index 000000000000..eb376bbe205c --- /dev/null +++ b/toolkit/components/places/tests/unit/test_1105866.js @@ -0,0 +1,63 @@ +add_task(function* test_folder_shortcuts() { + let shortcutInfo = yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "place:folder=TOOLBAR" + }); + + let unfiledRoot = + PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root; + let shortcutNode = unfiledRoot.getChild(unfiledRoot.childCount - 1); + Assert.strictEqual(shortcutNode.itemId, + yield PlacesUtils.promiseItemId(shortcutInfo.guid)); + Assert.strictEqual(PlacesUtils.asQuery(shortcutNode).folderItemId, + PlacesUtils.toolbarFolderId); + Assert.strictEqual(shortcutNode.bookmarkGuid, shortcutInfo.guid); + Assert.strictEqual(PlacesUtils.asQuery(shortcutNode).targetFolderGuid, + PlacesUtils.bookmarks.toolbarGuid); + + // test that a node added incrementally also behaves just as well. + shortcutInfo = yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + url: "place:folder=BOOKMARKS_MENU" + }); + shortcutNode = unfiledRoot.getChild(unfiledRoot.childCount - 1); + Assert.strictEqual(shortcutNode.itemId, + yield PlacesUtils.promiseItemId(shortcutInfo.guid)); + Assert.strictEqual(PlacesUtils.asQuery(shortcutNode).folderItemId, + PlacesUtils.bookmarksMenuFolderId); + Assert.strictEqual(shortcutNode.bookmarkGuid, shortcutInfo.guid); + Assert.strictEqual(PlacesUtils.asQuery(shortcutNode).targetFolderGuid, + PlacesUtils.bookmarks.menuGuid); + + unfiledRoot.containerOpen = false; +}); + +add_task(function* test_plain_folder() { + let folderInfo = yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_FOLDER, + parentGuid: PlacesUtils.bookmarks.unfiledGuid + }); + + let unfiledRoot = + PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root; + let lastChild = unfiledRoot.getChild(unfiledRoot.childCount - 1); + Assert.strictEqual(lastChild.bookmarkGuid, folderInfo.guid); + Assert.strictEqual(PlacesUtils.asQuery(lastChild).targetFolderGuid, + folderInfo.guid); +}); + +add_task(function* test_non_item_query() { + let options = PlacesUtils.history.getNewQueryOptions(); + let root = PlacesUtils.history.executeQuery( + PlacesUtils.history.getNewQuery(), options).root; + Assert.strictEqual(root.itemId, -1); + Assert.strictEqual(PlacesUtils.asQuery(root).folderItemId, -1); + Assert.strictEqual(root.bookmarkGuid, ""); + Assert.strictEqual(PlacesUtils.asQuery(root).targetFolderGuid, ""); +}); + +function run_test() { + run_next_test(); +} diff --git a/toolkit/components/places/tests/unit/xpcshell.ini b/toolkit/components/places/tests/unit/xpcshell.ini index 46411e04f951..d14ded8dc548 100644 --- a/toolkit/components/places/tests/unit/xpcshell.ini +++ b/toolkit/components/places/tests/unit/xpcshell.ini @@ -57,6 +57,7 @@ skip-if = os == "android" [test_536081.js] [test_1085291.js] [test_1105208.js] +[test_1105866.js] [test_adaptive.js] # Bug 676989: test hangs consistently on Android skip-if = os == "android"