diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 3e444746785..67c53144e3c 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -771,7 +771,8 @@ var PlacesStarButton = { return; var uri = getBrowser().currentURI; - this._starred = uri && (PlacesUtils.getMostRecentBookmarkForURI(uri) != -1); + this._starred = uri && (PlacesUtils.getMostRecentBookmarkForURI(uri) != -1 || + PlacesUtils.getMostRecentFolderForFeedURI(uri) != -1); if (this._starred) starIcon.setAttribute("starred", "true"); else diff --git a/browser/components/places/content/utils.js b/browser/components/places/content/utils.js index 91ea449d714..90173b388c4 100644 --- a/browser/components/places/content/utils.js +++ b/browser/components/places/content/utils.js @@ -51,6 +51,7 @@ Components.utils.import("resource://gre/modules/JSON.jsm"); const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar"; const DESCRIPTION_ANNO = "bookmarkProperties/description"; const POST_DATA_ANNO = "URIProperties/POSTData"; +const LMANNO_FEEDURI = "livemark/feedURI"; #ifdef XP_MACOSX // On Mac OSX, the transferable system converts "\r\n" to "\n\n", where we @@ -398,7 +399,7 @@ var PlacesUtils = { */ nodeIsLivemarkContainer: function PU_nodeIsLivemarkContainer(aNode) { return this.nodeIsFolder(aNode) && - this.annotations.itemHasAnnotation(aNode.itemId, "livemark/feedURI"); + this.annotations.itemHasAnnotation(aNode.itemId, LMANNO_FEEDURI); }, /** @@ -1507,12 +1508,24 @@ var PlacesUtils = { return bk; var grandparent = this.bookmarks.getFolderIdForItem(parent); if (grandparent != this.tagRootId && - !this.annotations.itemHasAnnotation(parent, "livemark/feedURI")) + !this.annotations.itemHasAnnotation(parent, LMANNO_FEEDURI)) return bk; } return -1; }, + getMostRecentFolderForFeedURI: + function PU_getMostRecentFolderForFeedURI(aURI) { + var feedSpec = aURI.spec + var annosvc = this.annotations; + var livemarks = annosvc.getItemsWithAnnotation(LMANNO_FEEDURI, {}); + for (var i = 0; i < livemarks.length; i++) { + if (annosvc.getItemAnnotation(livemarks[i], LMANNO_FEEDURI) == feedSpec) + return livemarks[i]; + } + return -1; + }, + getURLsForContainerNode: function PU_getURLsForContainerNode(aNode) { let urls = []; if (this.nodeIsFolder(aNode) && asQuery(aNode).queryOptions.excludeItems) { diff --git a/toolkit/components/places/src/nsNavHistory.h b/toolkit/components/places/src/nsNavHistory.h index 0fb5d7f4d75..d287b576b09 100644 --- a/toolkit/components/places/src/nsNavHistory.h +++ b/toolkit/components/places/src/nsNavHistory.h @@ -580,7 +580,8 @@ protected: PRTime mCurrentOldestVisit; PRBool mFirstChunk; - nsDataHashtable mLivemarkFeedItemIds; + nsDataHashtable mLivemarkFeedItemIds; + nsDataHashtable mLivemarkFeedURIs; nsCOMPtr mLivemarkFeedsQuery; nsresult AutoCompleteTypedSearch(); diff --git a/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp b/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp index a261f59900f..cbedb9eccbc 100644 --- a/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp +++ b/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp @@ -84,6 +84,9 @@ nsNavHistory::InitAutoComplete() if (!mLivemarkFeedItemIds.Init(128)) return NS_ERROR_OUT_OF_MEMORY; + if (!mLivemarkFeedURIs.Init(128)) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; } @@ -97,9 +100,9 @@ nsresult nsNavHistory::CreateAutoCompleteQueries() { nsCString sql = NS_LITERAL_CSTRING( - "SELECT annos.item_id FROM moz_anno_attributes attrs " - "JOIN moz_items_annos annos WHERE attrs.name = \"" LMANNO_FEEDURI "\" " - "AND attrs.id = annos.anno_attribute_id;"); + "SELECT annos.item_id, annos.content FROM moz_anno_attributes attrs " + "JOIN moz_items_annos annos ON attrs.id = annos.anno_attribute_id " + "WHERE attrs.name = \"" LMANNO_FEEDURI "\";"); nsresult rv = mDBConn->CreateStatement(sql, getter_AddRefs(mLivemarkFeedsQuery)); NS_ENSURE_SUCCESS(rv, rv); @@ -279,18 +282,30 @@ nsNavHistory::StartSearch(const nsAString & aSearchString, NS_ENSURE_SUCCESS(rv, rv); mCurrentResultURLs.Clear(); - mLivemarkFeedItemIds.Clear(); - // find all the items that have the "livemark/feedURI" annotation - // and save off their item ids. when doing autocomplete, - // if a result's parent item id matches a saved item id, the result - // it is not really a bookmark, but a rss feed item. - mozStorageStatementScoper scope(mLivemarkFeedsQuery); - PRBool hasMore = PR_FALSE; - while (NS_SUCCEEDED(mLivemarkFeedsQuery->ExecuteStep(&hasMore)) && hasMore) { - PRInt64 itemId = 0; - mLivemarkFeedsQuery->GetInt64(0, &itemId); - mLivemarkFeedItemIds.Put(itemId, PR_TRUE); + // if we are searching through our previous results, + // we don't need to regenerate these hash tables + if (!searchPrevious) { + mLivemarkFeedItemIds.Clear(); + mLivemarkFeedURIs.Clear(); + + // find all the items that have the "livemark/feedURI" annotation + // and save off their item ids and URIs. when doing autocomplete, + // if a result's parent item id matches a saved item id, the result + // it is not really a bookmark, but a rss feed item. + // if a results URI matches a saved URI, the result is a bookmark, + // so we should show the star. + mozStorageStatementScoper scope(mLivemarkFeedsQuery); + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(mLivemarkFeedsQuery->ExecuteStep(&hasMore)) && hasMore) { + PRInt64 itemId = 0; + mLivemarkFeedsQuery->GetInt64(0, &itemId); + mLivemarkFeedItemIds.Put(itemId, PR_TRUE); + nsAutoString feedURI; + // no need to worry about duplicates. + mLivemarkFeedsQuery->GetString(1, feedURI); + mLivemarkFeedURIs.Put(feedURI, PR_TRUE); + } } // Search through the previous result @@ -335,6 +350,15 @@ nsNavHistory::StartSearch(const nsAString & aSearchString, } } } + // if we found some results, announce them now instead of waiting + // to do the first db search. + PRUint32 count; + mCurrentResult->GetMatchCount(&count); + + if (count > 0) { + mCurrentResult->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING); + mCurrentResult->SetDefaultIndex(0); + } } else if (!mCurrentSearchString.IsEmpty()) { // reset to mCurrentChunkEndTime @@ -424,9 +448,11 @@ nsresult nsNavHistory::AutoCompleteTypedSearch() dbSelectStatement->GetInt64(kAutoCompleteIndex_ParentId, &parentId); PRBool dummy; - // don't show rss feed items as bookmarked - PRBool isBookmark = (itemId != 0) && - !mLivemarkFeedItemIds.Get(parentId, &dummy); + // don't show rss feed items as bookmarked, + // but do show rss feed URIs as bookmarked. + PRBool isBookmark = (itemId != 0 && + !mLivemarkFeedItemIds.Get(parentId, &dummy)) || + mLivemarkFeedURIs.Get(entryURL, &dummy); nsCAutoString imageSpec; faviconService->GetFaviconSpecForIconString( @@ -548,9 +574,11 @@ nsNavHistory::AutoCompleteFullHistorySearch() NS_ENSURE_SUCCESS(rv, rv); PRBool dummy; - // don't show rss feed items as bookmarked - PRBool isBookmark = (itemId != 0) && - !mLivemarkFeedItemIds.Get(parentId, &dummy); + // don't show rss feed items as bookmarked, + // but do show rss feed URIs as bookmarked. + PRBool isBookmark = (itemId != 0 && + !mLivemarkFeedItemIds.Get(parentId, &dummy)) || + mLivemarkFeedURIs.Get(entryURL, &dummy); // prevent duplicates. this can happen when chunking as we // may have already seen this URL from an earlier chunk of time