OLD | NEW |
---|---|
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/autocomplete/shortcuts_provider.h" | 5 #include "chrome/browser/autocomplete/shortcuts_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <map> | 9 #include <map> |
10 #include <vector> | 10 #include <vector> |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "chrome/browser/prefs/pref_service.h" | 23 #include "chrome/browser/prefs/pref_service.h" |
24 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/common/guid.h" | 25 #include "chrome/common/guid.h" |
26 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
27 #include "chrome/common/url_constants.h" | 27 #include "chrome/common/url_constants.h" |
28 #include "googleurl/src/url_parse.h" | 28 #include "googleurl/src/url_parse.h" |
29 #include "googleurl/src/url_util.h" | 29 #include "googleurl/src/url_util.h" |
30 #include "net/base/escape.h" | 30 #include "net/base/escape.h" |
31 #include "net/base/net_util.h" | 31 #include "net/base/net_util.h" |
32 | 32 |
33 using shortcuts_provider::Shortcut; | |
34 using shortcuts_provider::ShortcutMap; | |
35 | |
36 namespace { | 33 namespace { |
37 | 34 |
38 class RemoveMatchPredicate { | 35 class RemoveMatchPredicate { |
39 public: | 36 public: |
40 explicit RemoveMatchPredicate(const std::set<GURL>& urls) | 37 explicit RemoveMatchPredicate(const std::set<GURL>& urls) |
41 : urls_(urls) { | 38 : urls_(urls) { |
42 } | 39 } |
43 bool operator()(const AutocompleteMatch& match) { | 40 bool operator()(const AutocompleteMatch& match) { |
44 return urls_.find(match.destination_url) != urls_.end(); | 41 return urls_.find(match.destination_url) != urls_.end(); |
45 } | 42 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 ++url) | 127 ++url) |
131 shortcuts_backend_->DeleteShortcutsWithUrl(*url); | 128 shortcuts_backend_->DeleteShortcutsWithUrl(*url); |
132 } | 129 } |
133 | 130 |
134 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) { | 131 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) { |
135 // Get the URLs from the shortcuts database with keys that partially or | 132 // Get the URLs from the shortcuts database with keys that partially or |
136 // completely match the search term. | 133 // completely match the search term. |
137 string16 term_string(base::i18n::ToLower(input.text())); | 134 string16 term_string(base::i18n::ToLower(input.text())); |
138 DCHECK(!term_string.empty()); | 135 DCHECK(!term_string.empty()); |
139 | 136 |
140 for (ShortcutMap::const_iterator it = FindFirstMatch(term_string); | 137 for (history::ShortcutsBackend::ShortcutMap::const_iterator it = |
138 FindFirstMatch(term_string); | |
141 it != shortcuts_backend_->shortcuts_map().end() && | 139 it != shortcuts_backend_->shortcuts_map().end() && |
142 StartsWith(it->first, term_string, true); ++it) | 140 StartsWith(it->first, term_string, true); ++it) |
143 matches_.push_back(ShortcutToACMatch(input, term_string, it)); | 141 matches_.push_back(ShortcutToACMatch(input, term_string, it->second)); |
144 std::partial_sort(matches_.begin(), | 142 std::partial_sort(matches_.begin(), |
145 matches_.begin() + | 143 matches_.begin() + |
146 std::min(AutocompleteProvider::kMaxMatches, matches_.size()), | 144 std::min(AutocompleteProvider::kMaxMatches, matches_.size()), |
147 matches_.end(), &AutocompleteMatch::MoreRelevant); | 145 matches_.end(), &AutocompleteMatch::MoreRelevant); |
148 if (matches_.size() > AutocompleteProvider::kMaxMatches) { | 146 if (matches_.size() > AutocompleteProvider::kMaxMatches) { |
149 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches, | 147 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches, |
150 matches_.end()); | 148 matches_.end()); |
151 } | 149 } |
152 } | 150 } |
153 | 151 |
154 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( | 152 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( |
155 const AutocompleteInput& input, | 153 const AutocompleteInput& input, |
156 const string16& term_string, | 154 const string16& term_string, |
157 ShortcutMap::const_iterator it) { | 155 const history::ShortcutsBackend::Shortcut& shortcut) { |
158 AutocompleteMatch match(this, CalculateScore(term_string, it->second), | 156 AutocompleteMatch match(this, CalculateScore(term_string, shortcut), |
159 true, AutocompleteMatch::HISTORY_TITLE); | 157 true, AutocompleteMatch::HISTORY_TITLE); |
160 match.destination_url = it->second.url; | 158 match.destination_url = shortcut.url; |
161 DCHECK(match.destination_url.is_valid()); | 159 DCHECK(match.destination_url.is_valid()); |
162 match.fill_into_edit = UTF8ToUTF16(it->second.url.spec()); | 160 match.fill_into_edit = UTF8ToUTF16(shortcut.url.spec()); |
163 | 161 |
164 match.contents = it->second.contents; | 162 match.contents = shortcut.contents; |
165 match.contents_class = ClassifyAllMatchesInString(term_string, | 163 match.contents_class = ClassifyAllMatchesInString(term_string, |
166 match.contents, | 164 match.contents, |
167 it->second.contents_class); | 165 shortcut.contents_class); |
168 | 166 |
169 match.description = it->second.description; | 167 match.description = shortcut.description; |
170 match.description_class = ClassifyAllMatchesInString( | 168 match.description_class = ClassifyAllMatchesInString( |
171 term_string, match.description, it->second.description_class); | 169 term_string, match.description, shortcut.description_class); |
172 | 170 |
173 return match; | 171 return match; |
174 } | 172 } |
175 | 173 |
176 // static | 174 // static |
177 ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString( | 175 ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString( |
178 const string16& find_text, | 176 const string16& find_text, |
179 const string16& text, | 177 const string16& text, |
180 const ACMatchClassifications& original_class) { | 178 const ACMatchClassifications& original_class) { |
181 DCHECK(!find_text.empty()); | 179 DCHECK(!find_text.empty()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 } | 214 } |
217 } | 215 } |
218 | 216 |
219 if (match_start >= match_end) | 217 if (match_start >= match_end) |
220 break; | 218 break; |
221 | 219 |
222 // Collapse adjacent ranges into one. | 220 // Collapse adjacent ranges into one. |
223 if (!match_class.empty() && match_class.back().offset == match_start) | 221 if (!match_class.empty() && match_class.back().offset == match_start) |
224 match_class.pop_back(); | 222 match_class.pop_back(); |
225 | 223 |
226 shortcuts_provider::AddLastMatchIfNeeded(&match_class, match_start, | 224 AutocompleteMatch::AddLastClassificationIfNecessary(&match_class, |
227 ACMatchClassification::MATCH); | 225 match_start, ACMatchClassification::MATCH); |
GeorgeY
2012/03/14 19:59:49
May be move &match_class, to the same line as the
Peter Kasting
2012/03/14 20:37:34
This is explicitly OK: search for the "AndAnotherL
| |
228 if (match_end < text_lowercase.length()) { | 226 if (match_end < text_lowercase.length()) { |
229 shortcuts_provider::AddLastMatchIfNeeded(&match_class, match_end, | 227 AutocompleteMatch::AddLastClassificationIfNecessary(&match_class, |
230 ACMatchClassification::NONE); | 228 match_end, ACMatchClassification::NONE); |
GeorgeY
2012/03/14 19:59:49
Here is well
| |
231 } | 229 } |
232 | 230 |
233 last_position = match_end; | 231 last_position = match_end; |
234 } | 232 } |
235 | 233 |
236 // Merge match-marking data with original classifications. | 234 // Merge match-marking data with original classifications. |
237 if (match_class.empty()) | 235 if (match_class.empty()) |
238 return original_class; | 236 return original_class; |
239 | 237 |
240 ACMatchClassifications output; | 238 ACMatchClassifications output; |
241 for (ACMatchClassifications::const_iterator i = original_class.begin(), | 239 for (ACMatchClassifications::const_iterator i = original_class.begin(), |
242 j = match_class.begin(); i != original_class.end();) { | 240 j = match_class.begin(); i != original_class.end();) { |
243 shortcuts_provider::AddLastMatchIfNeeded(&output, | 241 AutocompleteMatch::AddLastClassificationIfNecessary(&output, |
244 std::max(i->offset, j->offset), | 242 std::max(i->offset, j->offset), i->style | j->style); |
GeorgeY
2012/03/14 19:59:49
and here
| |
245 i->style | j->style); | |
246 const size_t next_i_offset = (i + 1) == original_class.end() ? | 243 const size_t next_i_offset = (i + 1) == original_class.end() ? |
247 static_cast<size_t>(-1) : (i + 1)->offset; | 244 static_cast<size_t>(-1) : (i + 1)->offset; |
248 const size_t next_j_offset = (j + 1) == match_class.end() ? | 245 const size_t next_j_offset = (j + 1) == match_class.end() ? |
249 static_cast<size_t>(-1) : (j + 1)->offset; | 246 static_cast<size_t>(-1) : (j + 1)->offset; |
250 if (next_i_offset >= next_j_offset) | 247 if (next_i_offset >= next_j_offset) |
251 ++j; | 248 ++j; |
252 if (next_j_offset >= next_i_offset) | 249 if (next_j_offset >= next_i_offset) |
253 ++i; | 250 ++i; |
254 } | 251 } |
255 | 252 |
256 return output; | 253 return output; |
257 } | 254 } |
258 | 255 |
259 ShortcutMap::const_iterator ShortcutsProvider::FindFirstMatch( | 256 history::ShortcutsBackend::ShortcutMap::const_iterator |
260 const string16& keyword) { | 257 ShortcutsProvider::FindFirstMatch(const string16& keyword) { |
261 ShortcutMap::const_iterator it = | 258 history::ShortcutsBackend::ShortcutMap::const_iterator it = |
262 shortcuts_backend_->shortcuts_map().lower_bound(keyword); | 259 shortcuts_backend_->shortcuts_map().lower_bound(keyword); |
263 // Lower bound not necessarily matches the keyword, check for item pointed by | 260 // Lower bound not necessarily matches the keyword, check for item pointed by |
264 // the lower bound iterator to at least start with keyword. | 261 // the lower bound iterator to at least start with keyword. |
265 return ((it == shortcuts_backend_->shortcuts_map().end()) || | 262 return ((it == shortcuts_backend_->shortcuts_map().end()) || |
266 StartsWith(it->first, keyword, true)) ? it : | 263 StartsWith(it->first, keyword, true)) ? it : |
267 shortcuts_backend_->shortcuts_map().end(); | 264 shortcuts_backend_->shortcuts_map().end(); |
268 } | 265 } |
269 | 266 |
270 // static | 267 // static |
271 int ShortcutsProvider::CalculateScore(const string16& terms, | 268 int ShortcutsProvider::CalculateScore( |
272 const Shortcut& shortcut) { | 269 const string16& terms, |
270 const history::ShortcutsBackend::Shortcut& shortcut) { | |
273 DCHECK(!terms.empty()); | 271 DCHECK(!terms.empty()); |
274 DCHECK_LE(terms.length(), shortcut.text.length()); | 272 DCHECK_LE(terms.length(), shortcut.text.length()); |
275 | 273 |
276 // The initial score is based on how much of the shortcut the user has typed. | 274 // The initial score is based on how much of the shortcut the user has typed. |
277 // Using the square root of the typed fraction boosts the base score rapidly | 275 // Using the square root of the typed fraction boosts the base score rapidly |
278 // as characters are typed, compared with simply using the typed fraction | 276 // as characters are typed, compared with simply using the typed fraction |
279 // directly. This makes sense since the first characters typed are much more | 277 // directly. This makes sense since the first characters typed are much more |
280 // important for determining how likely it is a user wants a particular | 278 // important for determining how likely it is a user wants a particular |
281 // shortcut than are the remaining continued characters. | 279 // shortcut than are the remaining continued characters. |
282 double base_score = (AutocompleteResult::kLowestDefaultScore - 1) * | 280 double base_score = (AutocompleteResult::kLowestDefaultScore - 1) * |
(...skipping 21 matching lines...) Expand all Loading... | |
304 } | 302 } |
305 | 303 |
306 void ShortcutsProvider::set_shortcuts_backend( | 304 void ShortcutsProvider::set_shortcuts_backend( |
307 history::ShortcutsBackend* shortcuts_backend) { | 305 history::ShortcutsBackend* shortcuts_backend) { |
308 DCHECK(shortcuts_backend); | 306 DCHECK(shortcuts_backend); |
309 shortcuts_backend_ = shortcuts_backend; | 307 shortcuts_backend_ = shortcuts_backend; |
310 shortcuts_backend_->AddObserver(this); | 308 shortcuts_backend_->AddObserver(this); |
311 if (shortcuts_backend_->initialized()) | 309 if (shortcuts_backend_->initialized()) |
312 initialized_ = true; | 310 initialized_ = true; |
313 } | 311 } |
OLD | NEW |