Bug 1105866 - Implement folderShorcutNode.targetFolderGuid (guid version of folderShortcutNode.folderItemId). r=mak

This commit is contained in:
Asaf Romano 2014-12-10 19:03:15 +02:00
Родитель 8358e1d6f7
Коммит 40a4768f10
8 изменённых файлов: 152 добавлений и 79 удалений

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

@ -266,7 +266,7 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
* generated this node, this item will report it has no children and never try * generated this node, this item will report it has no children and never try
* to populate itself. * to populate itself.
*/ */
[scriptable, uuid(91AC5E59-3F5C-4ACD-AB3B-325FC425A5A1)] [scriptable, uuid(62817759-4FEE-44A3-B58C-3E2F5AFC9D0A)]
interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode
{ {
/** /**
@ -283,10 +283,18 @@ interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode
readonly attribute nsINavHistoryQueryOptions queryOptions; readonly attribute nsINavHistoryQueryOptions queryOptions;
/** /**
* For both simple folder nodes and simple-folder-query nodes, this is set * For both simple folder queries and folder shortcut queries, this is set to
* to the concrete itemId of the folder. Otherwise, this is set to -1. * 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; 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;
}; };

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

@ -1629,6 +1629,7 @@ nsNavBookmarks::ResultNodeForContainer(int64_t aItemId,
(*aNode)->mDateAdded = bookmark.dateAdded; (*aNode)->mDateAdded = bookmark.dateAdded;
(*aNode)->mLastModified = bookmark.lastModified; (*aNode)->mLastModified = bookmark.lastModified;
(*aNode)->mBookmarkGuid = bookmark.guid; (*aNode)->mBookmarkGuid = bookmark.guid;
(*aNode)->GetAsFolder()->mTargetFolderGuid = bookmark.guid;
NS_ADDREF(*aNode); NS_ADDREF(*aNode);
return NS_OK; return NS_OK;
@ -1735,6 +1736,10 @@ nsNavBookmarks::ProcessFolderNodeRow(
node = new nsNavHistoryFolderResultNode(title, aOptions, id); 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, rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
reinterpret_cast<int64_t*>(&node->mDateAdded)); reinterpret_cast<int64_t*>(&node->mDateAdded));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -1750,6 +1755,8 @@ nsNavBookmarks::ProcessFolderNodeRow(
node = new nsNavHistorySeparatorResultNode(); node = new nsNavHistorySeparatorResultNode();
node->mItemId = id; node->mItemId = id;
rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, node->mBookmarkGuid);
NS_ENSURE_SUCCESS(rv, rv);
rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded, rv = aRow->GetInt64(nsNavHistory::kGetInfoIndex_ItemDateAdded,
reinterpret_cast<int64_t*>(&node->mDateAdded)); reinterpret_cast<int64_t*>(&node->mDateAdded));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -1762,11 +1769,7 @@ nsNavBookmarks::ProcessFolderNodeRow(
// moz_bookmarks.position. // moz_bookmarks.position.
node->mBookmarkIndex = aCurrentIndex; 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); NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
return NS_OK; return NS_OK;
} }

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

@ -3918,17 +3918,17 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsRefPtr<nsNavHistoryResultNode> resultNode; nsAutoCString guid;
rv = QueryRowToResult(itemId, url, title, accessCount, time, favicon,
getter_AddRefs(resultNode));
NS_ENSURE_SUCCESS(rv,rv);
if (itemId != -1) { if (itemId != -1) {
rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, rv = aRow->GetUTF8String(nsNavBookmarks::kGetChildrenIndex_Guid, guid);
resultNode->mBookmarkGuid);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsRefPtr<nsNavHistoryResultNode> resultNode;
rv = QueryRowToResult(itemId, guid, url, title, accessCount, time, favicon,
getter_AddRefs(resultNode));
NS_ENSURE_SUCCESS(rv, rv);
if (itemId != -1 || if (itemId != -1 ||
aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_TAG_QUERY) { aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_TAG_QUERY) {
// RESULTS_AS_TAG_QUERY has date columns // RESULTS_AS_TAG_QUERY has date columns
@ -4003,12 +4003,17 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
// folder or query node. // folder or query node.
nsresult nsresult
nsNavHistory::QueryRowToResult(int64_t itemId, const nsACString& aURI, nsNavHistory::QueryRowToResult(int64_t itemId,
const nsACString& aBookmarkGuid,
const nsACString& aURI,
const nsACString& aTitle, const nsACString& aTitle,
uint32_t aAccessCount, PRTime aTime, uint32_t aAccessCount, PRTime aTime,
const nsACString& aFavicon, const nsACString& aFavicon,
nsNavHistoryResultNode** aNode) nsNavHistoryResultNode** aNode)
{ {
MOZ_ASSERT((itemId != -1 && !aBookmarkGuid.IsEmpty()) ||
(itemId == -1 && aBookmarkGuid.IsEmpty()));
nsCOMArray<nsNavHistoryQuery> queries; nsCOMArray<nsNavHistoryQuery> queries;
nsCOMPtr<nsNavHistoryQueryOptions> options; nsCOMPtr<nsNavHistoryQueryOptions> options;
nsresult rv = QueryStringToQueryArray(aURI, &queries, nsresult rv = QueryStringToQueryArray(aURI, &queries,
@ -4019,18 +4024,23 @@ nsNavHistory::QueryRowToResult(int64_t itemId, const nsACString& aURI,
// handle it later. // handle it later.
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// Check if this is a folder shortcut, so we can take a faster path. // Check if this is a folder shortcut, so we can take a faster path.
int64_t folderId = GetSimpleBookmarksQueryFolder(queries, options); int64_t targetFolderId = GetSimpleBookmarksQueryFolder(queries, options);
if (folderId) { if (targetFolderId) {
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService(); nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
rv = bookmarks->ResultNodeForContainer(folderId, options, rv = bookmarks->ResultNodeForContainer(targetFolderId, options,
getter_AddRefs(resultNode)); getter_AddRefs(resultNode));
// If this failed the shortcut is pointing to nowhere, let the error pass // If this failed the shortcut is pointing to nowhere, let the error pass
// and handle it later. // and handle it later.
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// This is the query itemId, and is what is exposed by node.itemId. // At this point the node is set up like a regular folder node. Here
resultNode->GetAsFolder()->mQueryItemId = itemId; // 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 // Use the query item title, unless it's void (in that case use the
// concrete folder title). // concrete folder title).

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

@ -232,7 +232,9 @@ public:
nsresult RowToResult(mozIStorageValueArray* aRow, nsresult RowToResult(mozIStorageValueArray* aRow,
nsNavHistoryQueryOptions* aOptions, nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult); nsNavHistoryResultNode** aResult);
nsresult QueryRowToResult(int64_t aItemId, const nsACString& aURI, nsresult QueryRowToResult(int64_t aItemId,
const nsACString& aBookmarkGuid,
const nsACString& aURI,
const nsACString& aTitle, const nsACString& aTitle,
uint32_t aAccessCount, PRTime aTime, uint32_t aAccessCount, PRTime aTime,
const nsACString& aFavicon, const nsACString& aFavicon,

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

@ -1994,10 +1994,15 @@ nsNavHistoryQueryResultNode::GetUri(nsACString& aURI)
NS_IMETHODIMP NS_IMETHODIMP
nsNavHistoryQueryResultNode::GetFolderItemId(int64_t* aItemId) nsNavHistoryQueryResultNode::GetFolderItemId(int64_t* aItemId)
{ {
*aItemId = mItemId; *aItemId = -1;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsNavHistoryQueryResultNode::GetTargetFolderGuid(nsACString& aGuid) {
aGuid = EmptyCString();
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsNavHistoryQueryResultNode::GetQueries(uint32_t* queryCount, nsNavHistoryQueryResultNode::GetQueries(uint32_t* queryCount,
@ -2978,7 +2983,7 @@ nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode(
nsNavHistoryResultNode::RESULT_TYPE_FOLDER, nsNavHistoryResultNode::RESULT_TYPE_FOLDER,
aOptions), aOptions),
mContentsValid(false), mContentsValid(false),
mQueryItemId(-1), mTargetFolderItemId(aFolderId),
mIsRegisteredFolderObserver(false) mIsRegisteredFolderObserver(false)
{ {
mItemId = aFolderId; mItemId = aFolderId;
@ -2987,7 +2992,7 @@ nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode(
nsNavHistoryFolderResultNode::~nsNavHistoryFolderResultNode() nsNavHistoryFolderResultNode::~nsNavHistoryFolderResultNode()
{ {
if (mIsRegisteredFolderObserver && mResult) if (mIsRegisteredFolderObserver && mResult)
mResult->RemoveBookmarkFolderObserver(this, mItemId); mResult->RemoveBookmarkFolderObserver(this, mTargetFolderItemId);
} }
@ -3066,22 +3071,16 @@ nsNavHistoryFolderResultNode::GetHasChildren(bool* aHasChildren)
return NS_OK; 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 NS_IMETHODIMP
nsNavHistoryFolderResultNode::GetItemId(int64_t* aItemId) nsNavHistoryFolderResultNode::GetFolderItemId(int64_t* aItemId)
{ {
*aItemId = mQueryItemId == -1 ? mItemId : mQueryItemId; *aItemId = mTargetFolderItemId;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsNavHistoryFolderResultNode::GetFolderItemId(int64_t* aItemId) nsNavHistoryFolderResultNode::GetTargetFolderGuid(nsACString& aGuid) {
{ aGuid = mTargetFolderGuid;
*aItemId = mItemId;
return NS_OK; return NS_OK;
} }
@ -3129,7 +3128,7 @@ nsNavHistoryFolderResultNode::GetQueries(uint32_t* queryCount,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// query just has the folder ID set and nothing else // 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); NS_ENSURE_SUCCESS(rv, rv);
// make array of our 1 query // make array of our 1 query
@ -3171,7 +3170,7 @@ nsNavHistoryFolderResultNode::FillChildren()
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
// Actually get the folder children from the bookmark service. // 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); NS_ENSURE_SUCCESS(rv, rv);
// PERFORMANCE: it may be better to also fill any child folders at this point // PERFORMANCE: it may be better to also fill any child folders at this point
@ -3235,7 +3234,7 @@ void
nsNavHistoryFolderResultNode::EnsureRegisteredAsFolderObserver() nsNavHistoryFolderResultNode::EnsureRegisteredAsFolderObserver()
{ {
if (!mIsRegisteredFolderObserver && mResult) { if (!mIsRegisteredFolderObserver && mResult) {
mResult->AddBookmarkFolderObserver(this, mItemId); mResult->AddBookmarkFolderObserver(this, mTargetFolderItemId);
mIsRegisteredFolderObserver = true; mIsRegisteredFolderObserver = true;
} }
} }
@ -3260,7 +3259,7 @@ nsNavHistoryFolderResultNode::FillChildrenAsync()
nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService(); nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bmSvc, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(bmSvc, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = nsresult rv =
bmSvc->QueryFolderChildrenAsync(this, mItemId, bmSvc->QueryFolderChildrenAsync(this, mTargetFolderItemId,
getter_AddRefs(mAsyncPendingStmt)); getter_AddRefs(mAsyncPendingStmt));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -3358,7 +3357,7 @@ nsNavHistoryFolderResultNode::ClearChildren(bool unregister)
bool needsUnregister = unregister && (mContentsValid || mAsyncPendingStmt); bool needsUnregister = unregister && (mContentsValid || mAsyncPendingStmt);
if (needsUnregister && mResult && mIsRegisteredFolderObserver) { if (needsUnregister && mResult && mIsRegisteredFolderObserver) {
mResult->RemoveBookmarkFolderObserver(this, mItemId); mResult->RemoveBookmarkFolderObserver(this, mTargetFolderItemId);
mIsRegisteredFolderObserver = false; mIsRegisteredFolderObserver = false;
} }
mContentsValid = 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. * @return the node if found, null otherwise.
* @note Does not addref the node! * @note Does not addref the node!
@ -3462,7 +3461,7 @@ nsNavHistoryFolderResultNode::FindChildById(int64_t aItemId,
for (int32_t i = 0; i < mChildren.Count(); ++i) { for (int32_t i = 0; i < mChildren.Count(); ++i) {
if (mChildren[i]->mItemId == aItemId || if (mChildren[i]->mItemId == aItemId ||
(mChildren[i]->IsFolder() && (mChildren[i]->IsFolder() &&
mChildren[i]->GetAsFolder()->mQueryItemId == aItemId)) { mChildren[i]->GetAsFolder()->mTargetFolderItemId == aItemId)) {
*aNodeIndex = i; *aNodeIndex = i;
return mChildren[i]; return mChildren[i];
} }
@ -3506,7 +3505,7 @@ nsNavHistoryFolderResultNode::OnItemAdded(int64_t aItemId,
const nsACString& aGUID, const nsACString& aGUID,
const nsACString& aParentGUID) 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(); RESTART_AND_RETURN_IF_ASYNC_PENDING();
@ -3611,13 +3610,15 @@ nsNavHistoryFolderResultNode::OnItemRemoved(int64_t aItemId,
const nsACString& aGUID, const nsACString& aGUID,
const nsACString& aParentGUID) const nsACString& aParentGUID)
{ {
// We only care about notifications when a child changes. When the deleted // If this folder is a folder shortcut, we should never be notified for the
// item is us, our parent should also be registered and will remove us from // removal of the shortcut (the parent node would be).
// its list. MOZ_ASSERT(mItemId == mTargetFolderItemId || aItemId != mItemId);
if (mItemId == aItemId)
// In any case though, here we only care about the children removal.
if (mTargetFolderItemId == aItemId)
return NS_OK; 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(); RESTART_AND_RETURN_IF_ASYNC_PENDING();
@ -3756,15 +3757,6 @@ nsNavHistoryFolderResultNode::OnItemChanged(int64_t aItemId,
const nsACString& aGUID, const nsACString& aGUID,
const nsACString&aParentGUID) 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(); RESTART_AND_RETURN_IF_ASYNC_PENDING();
return nsNavHistoryResultNode::OnItemChanged(aItemId, aProperty, return nsNavHistoryResultNode::OnItemChanged(aItemId, aProperty,
@ -3864,7 +3856,7 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId,
const nsACString& aOldParentGUID, const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID) 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"); "Got a bookmark message that doesn't belong to us");
RESTART_AND_RETURN_IF_ASYNC_PENDING(); 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 // example the Library left pane could have refreshed and replaced the
// right pane as a consequence. In such a case our contents are already // right pane as a consequence. In such a case our contents are already
// up-to-date. That's OK. // up-to-date. That's OK.
if (node && aNewParent == mItemId && index == static_cast<uint32_t>(aNewIndex)) if (node && aNewParent == mTargetFolderItemId && index == static_cast<uint32_t>(aNewIndex))
return NS_OK; return NS_OK;
if (!node && aOldParent == mItemId) if (!node && aOldParent == mTargetFolderItemId)
return NS_OK; return NS_OK;
bool excludeItems = (mResult && mResult->mRootNode->mOptions->ExcludeItems()) || bool excludeItems = (mResult && mResult->mRootNode->mOptions->ExcludeItems()) ||
@ -3922,11 +3914,11 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId,
rv = bookmarks->GetItemTitle(aItemId, itemTitle); rv = bookmarks->GetItemTitle(aItemId, itemTitle);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (aOldParent == mItemId) { if (aOldParent == mTargetFolderItemId) {
OnItemRemoved(aItemId, aOldParent, aOldIndex, aItemType, itemURI, OnItemRemoved(aItemId, aOldParent, aOldIndex, aItemType, itemURI,
aGUID, aOldParentGUID); aGUID, aOldParentGUID);
} }
if (aNewParent == mItemId) { if (aNewParent == mTargetFolderItemId) {
OnItemAdded(aItemId, aNewParent, aNewIndex, aItemType, itemURI, itemTitle, OnItemAdded(aItemId, aNewParent, aNewIndex, aItemType, itemURI, itemTitle,
PR_Now(), // This is a dummy dateAdded, not the real value. PR_Now(), // This is a dummy dateAdded, not the real value.
aGUID, aNewParentGUID); aGUID, aNewParentGUID);

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

@ -203,7 +203,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
// implementation and all subclasses. More complex are GetIcon, GetParent // implementation and all subclasses. More complex are GetIcon, GetParent
// (which depends on the definition of container result node), and GetUri // (which depends on the definition of container result node), and GetUri
// (which is overridded for lazy construction for some containers). // (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) \ NS_IMETHOD GetTitle(nsACString& aTitle) \
{ aTitle = mTitle; return NS_OK; } \ { aTitle = mTitle; return NS_OK; } \
NS_IMETHOD GetAccessCount(uint32_t* aAccessCount) \ NS_IMETHOD GetAccessCount(uint32_t* aAccessCount) \
@ -217,10 +217,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
NS_IMETHOD GetDateAdded(PRTime* aDateAdded) \ NS_IMETHOD GetDateAdded(PRTime* aDateAdded) \
{ *aDateAdded = mDateAdded; return NS_OK; } \ { *aDateAdded = mDateAdded; return NS_OK; } \
NS_IMETHOD GetLastModified(PRTime* aLastModified) \ NS_IMETHOD GetLastModified(PRTime* aLastModified) \
{ *aLastModified = mLastModified; return NS_OK; } { *aLastModified = mLastModified; return NS_OK; } \
#define NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMPLEMENT_SIMPLE_RESULTNODE_NO_GETITEMMID \
NS_IMETHOD GetItemId(int64_t* aId) \ NS_IMETHOD GetItemId(int64_t* aId) \
{ *aId = mItemId; return NS_OK; } { *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 // (GetUri is redefined only by QueryResultNode and FolderResultNode because
// the queries might not necessarily be parsed. The rest just return the node's // the queries might not necessarily be parsed. The rest just return the node's
// buffer.) // buffer.)
#define NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID \ #define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \
NS_IMPLEMENT_SIMPLE_RESULTNODE_NO_GETITEMMID \ NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMETHOD GetIcon(nsACString& aIcon) \ NS_IMETHOD GetIcon(nsACString& aIcon) \
{ return nsNavHistoryResultNode::GetIcon(aIcon); } \ { return nsNavHistoryResultNode::GetIcon(aIcon); } \
NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) \ NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) \
@ -248,11 +245,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) \ NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) \
{ return nsNavHistoryResultNode::GetBookmarkGuid(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 class nsNavHistoryResultNode : public nsINavHistoryResultNode
{ {
public: public:
@ -711,9 +703,9 @@ public:
int64_t aFolderId); int64_t aFolderId);
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID NS_FORWARD_COMMON_RESULTNODE_TO_BASE
NS_IMETHOD GetType(uint32_t* type) { NS_IMETHOD GetType(uint32_t* type) {
if (mQueryItemId != -1) { if (mTargetFolderItemId != mItemId) {
*type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT; *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
} else { } else {
*type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER; *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER;
@ -723,7 +715,6 @@ public:
NS_IMETHOD GetUri(nsACString& aURI); NS_IMETHOD GetUri(nsACString& aURI);
NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
NS_IMETHOD GetHasChildren(bool* aHasChildren); NS_IMETHOD GetHasChildren(bool* aHasChildren);
NS_IMETHOD GetItemId(int64_t *aItemId);
NS_DECL_NSINAVHISTORYQUERYRESULTNODE NS_DECL_NSINAVHISTORYQUERYRESULTNODE
virtual nsresult OpenContainer(); virtual nsresult OpenContainer();
@ -741,9 +732,12 @@ public:
// after the container is closed until a notification comes in // after the container is closed until a notification comes in
bool mContentsValid; bool mContentsValid;
// If the node is generated from a place:folder=X query, this is the query's // If the node is generated from a place:folder=X query, this is the target
// itemId. // folder id and GUID. For regular folder nodes, they are set to the same
int64_t mQueryItemId; // values as mItemId and mBookmarkGuid. For more complex queries, they are set
// to -1/an empty string.
int64_t mTargetFolderItemId;
nsCString mTargetFolderGuid;
nsresult FillChildren(); nsresult FillChildren();
void ClearChildren(bool aUnregister); void ClearChildren(bool aUnregister);

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

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

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

@ -57,6 +57,7 @@ skip-if = os == "android"
[test_536081.js] [test_536081.js]
[test_1085291.js] [test_1085291.js]
[test_1105208.js] [test_1105208.js]
[test_1105866.js]
[test_adaptive.js] [test_adaptive.js]
# Bug 676989: test hangs consistently on Android # Bug 676989: test hangs consistently on Android
skip-if = os == "android" skip-if = os == "android"