Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/bookmarks/bookmark_index.cc

Issue 242693003: Introduce BookmarkClient interface to abstract embedder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing reviewer comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/bookmarks/bookmark_index.h" 5 #include "chrome/browser/bookmarks/bookmark_index.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <list> 9 #include <list>
10 10
11 #include "base/i18n/case_conversion.h" 11 #include "base/i18n/case_conversion.h"
12 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
13 #include "chrome/browser/bookmarks/bookmark_model.h" 13 #include "components/bookmarks/core/browser/bookmark_client.h"
14 #include "chrome/browser/history/history_service.h" 14 #include "components/bookmarks/core/browser/bookmark_node.h"
15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/history/url_database.h"
17 #include "components/bookmarks/core/browser/bookmark_title_match.h" 15 #include "components/bookmarks/core/browser/bookmark_title_match.h"
18 #include "components/query_parser/query_parser.h" 16 #include "components/query_parser/query_parser.h"
19 #include "third_party/icu/source/common/unicode/normalizer2.h" 17 #include "third_party/icu/source/common/unicode/normalizer2.h"
20 18
21 namespace { 19 namespace {
22 20
23 // Returns a normalized version of the UTF16 string |text|. If it fails to 21 // Returns a normalized version of the UTF16 string |text|. If it fails to
24 // normalize the string, returns |text| itself as a best-effort. 22 // normalize the string, returns |text| itself as a best-effort.
25 base::string16 Normalize(const base::string16& text) { 23 base::string16 Normalize(const base::string16& text) {
26 UErrorCode status = U_ZERO_ERROR; 24 UErrorCode status = U_ZERO_ERROR;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 62
65 BookmarkIndex::NodeSet::const_iterator 63 BookmarkIndex::NodeSet::const_iterator
66 BookmarkIndex::Match::nodes_begin() const { 64 BookmarkIndex::Match::nodes_begin() const {
67 return nodes.empty() ? terms.front()->second.begin() : nodes.begin(); 65 return nodes.empty() ? terms.front()->second.begin() : nodes.begin();
68 } 66 }
69 67
70 BookmarkIndex::NodeSet::const_iterator BookmarkIndex::Match::nodes_end() const { 68 BookmarkIndex::NodeSet::const_iterator BookmarkIndex::Match::nodes_end() const {
71 return nodes.empty() ? terms.front()->second.end() : nodes.end(); 69 return nodes.empty() ? terms.front()->second.end() : nodes.end();
72 } 70 }
73 71
74 BookmarkIndex::BookmarkIndex(content::BrowserContext* browser_context) 72 BookmarkIndex::BookmarkIndex() {
75 : browser_context_(browser_context) {
76 } 73 }
77 74
78 BookmarkIndex::~BookmarkIndex() { 75 BookmarkIndex::~BookmarkIndex() {
79 } 76 }
80 77
81 void BookmarkIndex::Add(const BookmarkNode* node) { 78 void BookmarkIndex::Add(const BookmarkNode* node) {
82 if (!node->is_url()) 79 if (!node->is_url())
83 return; 80 return;
84 std::vector<base::string16> terms = 81 std::vector<base::string16> terms =
85 ExtractQueryWords(Normalize(node->GetTitle())); 82 ExtractQueryWords(Normalize(node->GetTitle()));
86 for (size_t i = 0; i < terms.size(); ++i) 83 for (size_t i = 0; i < terms.size(); ++i)
87 RegisterNode(terms[i], node); 84 RegisterNode(terms[i], node);
88 } 85 }
89 86
90 void BookmarkIndex::Remove(const BookmarkNode* node) { 87 void BookmarkIndex::Remove(const BookmarkNode* node) {
91 if (!node->is_url()) 88 if (!node->is_url())
92 return; 89 return;
93 90
94 std::vector<base::string16> terms = 91 std::vector<base::string16> terms =
95 ExtractQueryWords(Normalize(node->GetTitle())); 92 ExtractQueryWords(Normalize(node->GetTitle()));
96 for (size_t i = 0; i < terms.size(); ++i) 93 for (size_t i = 0; i < terms.size(); ++i)
97 UnregisterNode(terms[i], node); 94 UnregisterNode(terms[i], node);
98 } 95 }
99 96
100 void BookmarkIndex::GetBookmarksWithTitlesMatching( 97 void BookmarkIndex::GetBookmarksWithTitlesMatching(
98 BookmarkClient* client,
101 const base::string16& input_query, 99 const base::string16& input_query,
102 size_t max_count, 100 size_t max_count,
103 std::vector<BookmarkTitleMatch>* results) { 101 std::vector<BookmarkTitleMatch>* results) {
104 const base::string16 query = Normalize(input_query); 102 const base::string16 query = Normalize(input_query);
105 std::vector<base::string16> terms = ExtractQueryWords(query); 103 std::vector<base::string16> terms = ExtractQueryWords(query);
106 if (terms.empty()) 104 if (terms.empty())
107 return; 105 return;
108 106
109 Matches matches; 107 Matches matches;
110 for (size_t i = 0; i < terms.size(); ++i) { 108 for (size_t i = 0; i < terms.size(); ++i) {
111 if (!GetBookmarksWithTitleMatchingTerm(terms[i], i == 0, &matches)) 109 if (!GetBookmarksWithTitleMatchingTerm(terms[i], i == 0, &matches))
112 return; 110 return;
113 } 111 }
114 112
115 NodeTypedCountPairs node_typed_counts; 113 NodeTypedCountPairs node_typed_counts;
116 SortMatches(matches, &node_typed_counts); 114 SortMatches(client, matches, &node_typed_counts);
117 115
118 // We use a QueryParser to fill in match positions for us. It's not the most 116 // We use a QueryParser to fill in match positions for us. It's not the most
119 // efficient way to go about this, but by the time we get here we know what 117 // efficient way to go about this, but by the time we get here we know what
120 // matches and so this shouldn't be performance critical. 118 // matches and so this shouldn't be performance critical.
121 query_parser::QueryParser parser; 119 query_parser::QueryParser parser;
122 ScopedVector<query_parser::QueryNode> query_nodes; 120 ScopedVector<query_parser::QueryNode> query_nodes;
123 parser.ParseQueryNodes(query, &query_nodes.get()); 121 parser.ParseQueryNodes(query, &query_nodes.get());
124 122
125 // The highest typed counts should be at the beginning of the results vector 123 // The highest typed counts should be at the beginning of the results vector
126 // so that the best matches will always be included in the results. The loop 124 // so that the best matches will always be included in the results. The loop
127 // that calculates result relevance in HistoryContentsProvider::ConvertResults 125 // that calculates result relevance in HistoryContentsProvider::ConvertResults
128 // will run backwards to assure higher relevance will be attributed to the 126 // will run backwards to assure higher relevance will be attributed to the
129 // best matches. 127 // best matches.
130 for (NodeTypedCountPairs::const_iterator i = node_typed_counts.begin(); 128 for (NodeTypedCountPairs::const_iterator i = node_typed_counts.begin();
131 i != node_typed_counts.end() && results->size() < max_count; ++i) 129 i != node_typed_counts.end() && results->size() < max_count; ++i)
132 AddMatchToResults(i->first, &parser, query_nodes.get(), results); 130 AddMatchToResults(i->first, &parser, query_nodes.get(), results);
133 } 131 }
134 132
135 void BookmarkIndex::SortMatches(const Matches& matches, 133 void BookmarkIndex::SortMatches(BookmarkClient* client,
134 const Matches& matches,
136 NodeTypedCountPairs* node_typed_counts) const { 135 NodeTypedCountPairs* node_typed_counts) const {
137 HistoryService* const history_service = browser_context_ ? 136 for (Matches::const_iterator i = matches.begin(); i != matches.end(); ++i) {
138 HistoryServiceFactory::GetForProfile( 137 const NodeSet& nodes =
139 Profile::FromBrowserContext(browser_context_), 138 i->nodes.empty() ? i->terms.front()->second : i->nodes;
140 Profile::EXPLICIT_ACCESS) : NULL; 139 client->GetTypedCountForNodes(nodes, node_typed_counts);
sky 2014/04/18 17:05:04 If the intention is that some clients don't suppor
sdefresne 2014/04/18 22:25:49 I think that exporting a SupportsTypedCountForNode
sky 2014/04/21 15:24:20 My thinking was that you can avoid this loop entir
141 140 }
142 history::URLDatabase* url_db = history_service ?
143 history_service->InMemoryDatabase() : NULL;
144
145 for (Matches::const_iterator i = matches.begin(); i != matches.end(); ++i)
146 ExtractBookmarkNodePairs(url_db, *i, node_typed_counts);
147 141
148 std::sort(node_typed_counts->begin(), node_typed_counts->end(), 142 std::sort(node_typed_counts->begin(), node_typed_counts->end(),
149 &NodeTypedCountPairSortFunc); 143 &NodeTypedCountPairSortFunc);
150 // Eliminate duplicates. 144 // Eliminate duplicates.
151 node_typed_counts->erase(std::unique(node_typed_counts->begin(), 145 node_typed_counts->erase(std::unique(node_typed_counts->begin(),
152 node_typed_counts->end()), 146 node_typed_counts->end()),
153 node_typed_counts->end()); 147 node_typed_counts->end());
154 } 148 }
155 149
156 void BookmarkIndex::ExtractBookmarkNodePairs(
157 history::URLDatabase* url_db,
158 const Match& match,
159 NodeTypedCountPairs* node_typed_counts) const {
160
161 for (NodeSet::const_iterator i = match.nodes_begin();
162 i != match.nodes_end(); ++i) {
163 int typed_count = 0;
164
165 // If |url_db| is the InMemoryDatabase, it might not cache all URLRows, but
166 // it guarantees to contain those with |typed_count| > 0. Thus, if we cannot
167 // fetch the URLRow, it is safe to assume that its |typed_count| is 0.
168 history::URLRow url;
169 if (url_db && url_db->GetRowForURL((*i)->url(), &url))
170 typed_count = url.typed_count();
171
172 NodeTypedCountPair pair(*i, typed_count);
173 node_typed_counts->push_back(pair);
174 }
175 }
176
177 void BookmarkIndex::AddMatchToResults( 150 void BookmarkIndex::AddMatchToResults(
178 const BookmarkNode* node, 151 const BookmarkNode* node,
179 query_parser::QueryParser* parser, 152 query_parser::QueryParser* parser,
180 const std::vector<query_parser::QueryNode*>& query_nodes, 153 const std::vector<query_parser::QueryNode*>& query_nodes,
181 std::vector<BookmarkTitleMatch>* results) { 154 std::vector<BookmarkTitleMatch>* results) {
182 BookmarkTitleMatch title_match; 155 BookmarkTitleMatch title_match;
183 // Check that the result matches the query. The previous search 156 // Check that the result matches the query. The previous search
184 // was a simple per-word search, while the more complex matching 157 // was a simple per-word search, while the more complex matching
185 // of QueryParser may filter it out. For example, the query 158 // of QueryParser may filter it out. For example, the query
186 // ["thi"] will match the bookmark titled [Thinking], but since 159 // ["thi"] will match the bookmark titled [Thinking], but since
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 Index::iterator i = index_.find(term); 267 Index::iterator i = index_.find(term);
295 if (i == index_.end()) { 268 if (i == index_.end()) {
296 // We can get here if the node has the same term more than once. For 269 // We can get here if the node has the same term more than once. For
297 // example, a bookmark with the title 'foo foo' would end up here. 270 // example, a bookmark with the title 'foo foo' would end up here.
298 return; 271 return;
299 } 272 }
300 i->second.erase(node); 273 i->second.erase(node);
301 if (i->second.empty()) 274 if (i->second.empty())
302 index_.erase(i); 275 index_.erase(i);
303 } 276 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698