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

Side by Side Diff: chrome/browser/autocomplete/bookmark_provider.cc

Issue 184663002: Omnibox: Make URLs of Bookmarks Searchable (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tested; works 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 | Annotate | Revision Log
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/autocomplete/bookmark_provider.h" 5 #include "chrome/browser/autocomplete/bookmark_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/prefs/pref_service.h" 11 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/autocomplete/autocomplete_result.h" 13 #include "chrome/browser/autocomplete/autocomplete_result.h"
14 #include "chrome/browser/autocomplete/history_provider.h" 14 #include "chrome/browser/autocomplete/history_provider.h"
15 #include "chrome/browser/autocomplete/url_prefix.h" 15 #include "chrome/browser/autocomplete/url_prefix.h"
16 #include "chrome/browser/bookmarks/bookmark_match.h"
16 #include "chrome/browser/bookmarks/bookmark_model.h" 17 #include "chrome/browser/bookmarks/bookmark_model.h"
17 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 18 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
18 #include "chrome/browser/bookmarks/bookmark_title_match.h" 19 #include "chrome/browser/omnibox/omnibox_field_trial.h"
19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/pref_names.h" 21 #include "chrome/common/pref_names.h"
21 #include "net/base/net_util.h" 22 #include "net/base/net_util.h"
22 23
23 typedef std::vector<BookmarkTitleMatch> TitleMatches; 24 typedef std::vector<BookmarkMatch> BookmarkMatches;
24 25
25 // BookmarkProvider ------------------------------------------------------------ 26 // BookmarkProvider ------------------------------------------------------------
26 27
27 BookmarkProvider::BookmarkProvider( 28 BookmarkProvider::BookmarkProvider(
28 AutocompleteProviderListener* listener, 29 AutocompleteProviderListener* listener,
29 Profile* profile) 30 Profile* profile)
30 : AutocompleteProvider(listener, profile, 31 : AutocompleteProvider(listener, profile,
31 AutocompleteProvider::TYPE_BOOKMARK), 32 AutocompleteProvider::TYPE_BOOKMARK),
32 bookmark_model_(NULL) { 33 bookmark_model_(NULL),
34 score_using_url_matches_(OmniboxFieldTrial::BookmarksIndexURLsValue()) {
33 if (profile) { 35 if (profile) {
34 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile); 36 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile);
35 languages_ = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); 37 languages_ = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
36 } 38 }
37 } 39 }
38 40
39 void BookmarkProvider::Start(const AutocompleteInput& input, 41 void BookmarkProvider::Start(const AutocompleteInput& input,
40 bool minimal_changes) { 42 bool minimal_changes) {
41 if (minimal_changes) 43 if (minimal_changes)
42 return; 44 return;
43 matches_.clear(); 45 matches_.clear();
44 46
45 if (input.text().empty() || 47 if (input.text().empty() ||
46 ((input.type() != AutocompleteInput::UNKNOWN) && 48 (input.type() == AutocompleteInput::FORCED_QUERY))
47 (input.type() != AutocompleteInput::QUERY)))
48 return; 49 return;
49 50
50 DoAutocomplete(input, 51 DoAutocomplete(input,
51 input.matches_requested() == AutocompleteInput::BEST_MATCH); 52 input.matches_requested() == AutocompleteInput::BEST_MATCH);
52 } 53 }
53 54
54 BookmarkProvider::~BookmarkProvider() {} 55 BookmarkProvider::~BookmarkProvider() {}
55 56
56 void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input, 57 void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input,
57 bool best_match) { 58 bool best_match) {
58 // We may not have a bookmark model for some unit tests. 59 // We may not have a bookmark model for some unit tests.
59 if (!bookmark_model_) 60 if (!bookmark_model_)
60 return; 61 return;
61 62
62 TitleMatches matches; 63 BookmarkMatches matches;
63 // Retrieve enough bookmarks so that we have a reasonable probability of 64 // Retrieve enough bookmarks so that we have a reasonable probability of
64 // suggesting the one that the user desires. 65 // suggesting the one that the user desires.
65 const size_t kMaxBookmarkMatches = 50; 66 const size_t kMaxBookmarkMatches = 50;
66 67
67 // GetBookmarksWithTitlesMatching returns bookmarks matching the user's 68 // GetBookmarksMatching returns bookmarks matching the user's
68 // search terms using the following rules: 69 // search terms using the following rules:
69 // - The search text is broken up into search terms. Each term is searched 70 // - The search text is broken up into search terms. Each term is searched
70 // for separately. 71 // for separately.
71 // - Term matches are always performed against the start of a word. 'def' 72 // - Term matches are always performed against the start of a word. 'def'
72 // will match against 'define' but not against 'indefinite'. 73 // will match against 'define' but not against 'indefinite'.
73 // - Terms must be at least three characters in length in order to perform 74 // - Terms must be at least three characters in length in order to perform
74 // partial word matches. Any term of lesser length will only be used as an 75 // partial word matches. Any term of lesser length will only be used as an
75 // exact match. 'def' will match against 'define' but 'de' will not match. 76 // exact match. 'def' will match against 'define' but 'de' will not match.
76 // - A search containing multiple terms will return results with those words 77 // - A search containing multiple terms will return results with those words
77 // occuring in any order. 78 // occuring in any order.
78 // - Terms enclosed in quotes comprises a phrase that must match exactly. 79 // - Terms enclosed in quotes comprises a phrase that must match exactly.
79 // - Multiple terms enclosed in quotes will require those exact words in that 80 // - Multiple terms enclosed in quotes will require those exact words in that
80 // exact order to match. 81 // exact order to match.
81 // 82 //
82 // Note: GetBookmarksWithTitlesMatching() will never return a match span 83 // Please refer to the code for BookmarkIndex::GetBookmarksMatching for
83 // greater than the length of the title against which it is being matched, 84 // complete details of how searches are performed against the user's
84 // nor can those spans ever overlap because the match spans are coalesced
85 // for all matched terms.
86 //
87 // Please refer to the code for BookmarkIndex::GetBookmarksWithTitlesMatching
88 // for complete details of how title searches are performed against the user's
89 // bookmarks. 85 // bookmarks.
90 bookmark_model_->GetBookmarksWithTitlesMatching(input.text(), 86 bookmark_model_->GetBookmarksMatching(input.text(),
91 kMaxBookmarkMatches, 87 kMaxBookmarkMatches,
92 &matches); 88 &matches);
93 if (matches.empty()) 89 if (matches.empty())
94 return; // There were no matches. 90 return; // There were no matches.
95 AutocompleteInput fixed_up_input(input); 91 AutocompleteInput fixed_up_input(input);
96 FixupUserInput(&fixed_up_input); 92 FixupUserInput(&fixed_up_input);
97 for (TitleMatches::const_iterator i = matches.begin(); i != matches.end(); 93 for (BookmarkMatches::const_iterator i = matches.begin(); i != matches.end();
98 ++i) { 94 ++i) {
99 // Create and score the AutocompleteMatch. If its score is 0 then the 95 // Create and score the AutocompleteMatch. If its score is 0 then the
100 // match is discarded. 96 // match is discarded.
101 AutocompleteMatch match(TitleMatchToACMatch(input, fixed_up_input, *i)); 97 AutocompleteMatch match(BookmarkMatchToACMatch(input, fixed_up_input, *i));
102 if (match.relevance > 0) 98 if (match.relevance > 0)
103 matches_.push_back(match); 99 matches_.push_back(match);
104 } 100 }
105 101
106 // Sort and clip the resulting matches. 102 // Sort and clip the resulting matches.
107 size_t max_matches = best_match ? 1 : AutocompleteProvider::kMaxMatches; 103 size_t max_matches = best_match ? 1 : AutocompleteProvider::kMaxMatches;
108 if (matches_.size() > max_matches) { 104 if (matches_.size() > max_matches) {
109 std::partial_sort(matches_.begin(), 105 std::partial_sort(matches_.begin(),
110 matches_.begin() + max_matches, 106 matches_.begin() + max_matches,
111 matches_.end(), 107 matches_.end(),
112 AutocompleteMatch::MoreRelevant); 108 AutocompleteMatch::MoreRelevant);
113 matches_.resize(max_matches); 109 matches_.resize(max_matches);
114 } else { 110 } else {
115 std::sort(matches_.begin(), matches_.end(), 111 std::sort(matches_.begin(), matches_.end(),
116 AutocompleteMatch::MoreRelevant); 112 AutocompleteMatch::MoreRelevant);
117 } 113 }
118 } 114 }
119 115
120 namespace { 116 namespace {
121 117
122 // for_each helper functor that calculates a match factor for each query term 118 // for_each helper functor that calculates a match factor for each query term
123 // when calculating the final score. 119 // when calculating the final score.
124 // 120 //
125 // Calculate a 'factor' from 0.0 to 1.0 based on 1) how much of the bookmark's 121 // Calculate a 'factor' from 0 to the bookmark's title length for a match
126 // title the term matches, and 2) where the match is positioned within the 122 // based on 1) how many characters match and 2) where the match is positioned.
127 // bookmark's title. A full length match earns a 1.0. A half-length match earns
128 // at most a 0.5 and at least a 0.25. A single character match against a title
129 // that is 100 characters long where the match is at the first character will
130 // earn a 0.01 and at the last character will earn a 0.0001.
131 class ScoringFunctor { 123 class ScoringFunctor {
132 public: 124 public:
133 // |title_length| is the length of the bookmark title against which this 125 // |title_length| is the length of the bookmark title against which this
134 // match will be scored. 126 // match will be scored.
135 explicit ScoringFunctor(size_t title_length) 127 explicit ScoringFunctor(size_t title_length)
136 : title_length_(static_cast<double>(title_length)), 128 : title_length_(static_cast<double>(title_length)),
137 scoring_factor_(0.0) { 129 scoring_factor_(0.0) {
138 } 130 }
139 131
140 void operator()(const Snippet::MatchPosition& match) { 132 void operator()(const Snippet::MatchPosition& match) {
141 double term_length = static_cast<double>(match.second - match.first); 133 double term_length = static_cast<double>(match.second - match.first);
142 scoring_factor_ += term_length / title_length_ * 134 scoring_factor_ += term_length *
143 (title_length_ - match.first) / title_length_; 135 (title_length_ - match.first) / title_length_;
144 } 136 }
145 137
146 double ScoringFactor() { return scoring_factor_; } 138 double ScoringFactor() { return scoring_factor_; }
147 139
148 private: 140 private:
149 double title_length_; 141 double title_length_;
150 double scoring_factor_; 142 double scoring_factor_;
151 }; 143 };
152 144
153 } // namespace 145 } // namespace
154 146
155 AutocompleteMatch BookmarkProvider::TitleMatchToACMatch( 147 AutocompleteMatch BookmarkProvider::BookmarkMatchToACMatch(
156 const AutocompleteInput& input, 148 const AutocompleteInput& input,
157 const AutocompleteInput& fixed_up_input, 149 const AutocompleteInput& fixed_up_input,
158 const BookmarkTitleMatch& title_match) { 150 const BookmarkMatch& bookmark_match) {
159 // The AutocompleteMatch we construct is non-deletable because the only 151 // The AutocompleteMatch we construct is non-deletable because the only
160 // way to support this would be to delete the underlying bookmark, which is 152 // way to support this would be to delete the underlying bookmark, which is
161 // unlikely to be what the user intends. 153 // unlikely to be what the user intends.
162 AutocompleteMatch match(this, 0, false, 154 AutocompleteMatch match(this, 0, false,
163 AutocompleteMatchType::BOOKMARK_TITLE); 155 AutocompleteMatchType::BOOKMARK_TITLE);
164 const base::string16& title(title_match.node->GetTitle()); 156 base::string16 title(bookmark_match.node->GetTitle());
165 DCHECK(!title.empty()); 157 const GURL& url(bookmark_match.node->url());
166
167 const GURL& url(title_match.node->url());
168 const base::string16& url_utf16 = base::UTF8ToUTF16(url.spec()); 158 const base::string16& url_utf16 = base::UTF8ToUTF16(url.spec());
169 size_t match_start, inline_autocomplete_offset; 159 size_t inline_autocomplete_offset = URLPrefix::GetInlineAutocompleteOffset(
170 URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset( 160 input, fixed_up_input, false, url_utf16);
171 input, fixed_up_input, false, url_utf16, &match_start,
172 &inline_autocomplete_offset);
173 match.destination_url = url; 161 match.destination_url = url;
162 const size_t match_start = !bookmark_match.url_match_positions.empty() ?
Peter Kasting 2014/04/16 23:44:25 Tiny nit: Remove "!" and reverse arms
Mark P 2014/04/17 20:24:18 Done.
163 bookmark_match.url_match_positions[0].first : 0;
174 const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text()) && 164 const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text()) &&
175 ((match_start == base::string16::npos) || (match_start != 0)); 165 ((match_start == base::string16::npos) || (match_start != 0));
176 match.contents = net::FormatUrl(url, languages_, 166 std::vector<size_t> offsets = BookmarkMatch::OffsetsFromMatchPositions(
Peter Kasting 2014/04/16 23:44:25 Nit: Consider using a typedef here/elsewhere
Mark P 2014/04/17 20:24:18 I prefer to keep it this way for consistency with
Peter Kasting 2014/04/17 22:30:37 Right, I really intended for things like FormatURL
Mark P 2014/04/18 14:52:43 Filed crbug.com/364840
167 bookmark_match.url_match_positions);
168 // In addition to knowing how |offsets| is transformed, we need to know how
169 // |inline_autocomplete_offset| is transformed. We add it to the end of
170 // |offsets|, compute how everything is transformed, then remove it from the
171 // end.
172 offsets.push_back(inline_autocomplete_offset);
173 match.contents = net::FormatUrlWithOffsets(url, languages_,
177 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP), 174 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP),
178 net::UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset); 175 net::UnescapeRule::SPACES, NULL, NULL, &offsets);
179 match.contents_class.push_back( 176 inline_autocomplete_offset = offsets.back();
180 ACMatchClassification(0, ACMatchClassification::URL)); 177 offsets.pop_back();
178 BookmarkMatch::MatchPositions new_url_match_positions =
179 BookmarkMatch::ReplaceOffsetsInMatchPositions(
180 bookmark_match.url_match_positions, offsets);
181 // *** test this
Peter Kasting 2014/04/16 23:44:25 ^^^ ?
Mark P 2014/04/17 20:24:18 Oops, forgot to remove the note that I should test
182 match.contents_class =
183 ClassificationsFromMatch(new_url_match_positions,
184 match.contents.size(),
185 true);
181 match.fill_into_edit = 186 match.fill_into_edit =
182 AutocompleteInput::FormattedStringWithEquivalentMeaning(url, 187 AutocompleteInput::FormattedStringWithEquivalentMeaning(url,
183 match.contents); 188 match.contents);
184 if (inline_autocomplete_offset != base::string16::npos) { 189 if (inline_autocomplete_offset != base::string16::npos) {
185 // |inline_autocomplete_offset| may be beyond the end of the 190 // |inline_autocomplete_offset| may be beyond the end of the
186 // |fill_into_edit| if the user has typed an URL with a scheme and the 191 // |fill_into_edit| if the user has typed an URL with a scheme and the
187 // last character typed is a slash. That slash is removed by the 192 // last character typed is a slash. That slash is removed by the
188 // FormatURLWithOffsets call above. 193 // FormatURLWithOffsets call above.
189 if (inline_autocomplete_offset < match.fill_into_edit.length()) { 194 if (inline_autocomplete_offset < match.fill_into_edit.length()) {
190 match.inline_autocompletion = 195 match.inline_autocompletion =
191 match.fill_into_edit.substr(inline_autocomplete_offset); 196 match.fill_into_edit.substr(inline_autocomplete_offset);
192 } 197 }
193 match.allowed_to_be_default_match = match.inline_autocompletion.empty() || 198 match.allowed_to_be_default_match = match.inline_autocompletion.empty() ||
194 !HistoryProvider::PreventInlineAutocomplete(input); 199 !HistoryProvider::PreventInlineAutocomplete(input);
195 } 200 }
196 match.description = title; 201 match.description = title;
197 match.description_class = 202 match.description_class =
198 ClassificationsFromMatch(title_match.match_positions, 203 ClassificationsFromMatch(bookmark_match.title_match_positions,
199 match.description.size()); 204 match.description.size(),
205 false);
200 match.starred = true; 206 match.starred = true;
201 207
202 // Summary on how a relevance score is determined for the match: 208 // Summary on how a relevance score is determined for the match:
203 // 209 //
204 // For each term matching within the bookmark's title (as given by the set of 210 // For each match within the bookmark's title or URL (or both), calculate a
205 // Snippet::MatchPositions) calculate a 'factor', sum up those factors, then 211 // 'factor', sum up those factors, then use the sum to figure out a value
206 // use the sum to figure out a value between the base score and the maximum 212 // between the base score and the maximum score.
207 // score.
208 // 213 //
209 // The factor for each term is the product of: 214 // The factor for each match is the product of:
210 // 215 //
211 // 1) how much of the bookmark's title has been matched by the term: 216 // 1) how many characters in the bookmark's title/URL is part of this match.
Peter Kasting 2014/04/16 23:44:25 Nit: is -> are
Mark P 2014/04/17 20:24:18 Done.
212 // (term length / title length). 217 // This is capped at the length of the bookmark's title
218 // to prevent terms that match in both the title and the URL from
219 // scoring too strongly.
213 // 220 //
214 // Example: Given a bookmark title 'abcde fghijklm', with a title length 221 // 2) where the match occurs within the bookmark's title or URL,
215 // of 14, and two different search terms, 'abcde' and 'fghijklm', with 222 // giving more points for matches that appear earlier in the title:
216 // term lengths of 5 and 8, respectively, 'fghijklm' will score higher 223 // ((title_length - position of match start) / title_length).
217 // (with a partial factor of 8/14 = 0.571) than 'abcde' (5/14 = 0.357). 224 // For matches in the URL, we still use the title_length in the above
218 // 225 // formula.
Peter Kasting 2014/04/16 23:44:25 This is really confusing. Why are URL matches sco
Mark P 2014/04/17 20:24:18 You're right, this part doesn't make much sense.
219 // 2) where the term match occurs within the bookmark's title, giving more
220 // points for matches that appear earlier in the title:
221 // ((title length - position of match start) / title_length).
222 // 226 //
223 // Example: Given a bookmark title of 'abcde fghijklm', with a title length 227 // Example: Given a bookmark title of 'abcde fghijklm', with a title length
224 // of 14, and two different search terms, 'abcde' and 'fghij', with 228 // of 14, and two different search terms, 'abcde' and 'fghij', with
225 // start positions of 0 and 6, respectively, 'abcde' will score higher 229 // start positions of 0 and 6, respectively, 'abcde' will score higher
226 // (with a a partial factor of (14-0)/14 = 1.000 ) than 'fghij' (with 230 // (with a a partial factor of (14-0)/14 = 1.000 ) than 'fghij' (with
227 // a partial factor of (14-6)/14 = 0.571 ). 231 // a partial factor of (14-6)/14 = 0.571 ). (In this example neither
232 // term matches in the URL.)
228 // 233 //
229 // Once all term factors have been calculated they are summed. The resulting 234 // Once all match factors have been calculated they are summed. If URL
230 // sum will never be greater than 1.0 because of the way the bookmark model 235 // matches are not considered, the resulting sum will never be greater than
231 // matches and removes overlaps. (In particular, the bookmark model only 236 // the length of the bookmark title because of the way the bookmark model
237 // matches and removes overlaps. (In particular, the bookmark model only
232 // matches terms to the beginning of words and it removes all overlapping 238 // matches terms to the beginning of words and it removes all overlapping
233 // matches, keeping only the longest. Together these mean that each 239 // matches, keeping only the longest. Together these mean that each
234 // character is included in at most one match. This property ensures the 240 // character is included in at most one match.) If URL matches are
235 // sum of factors is at most 1.) This sum is then multiplied against the 241 // considered, the sum can be greater.
236 // scoring range available, which is 299. The 299 is calculated by 242 //
237 // subtracting the minimum possible score, 900, from the maximum possible 243 // This sum is then normalized by the length of the bookmark title (if URL
238 // score, 1199. This product, ranging from 0 to 299, is added to the minimum 244 // matches are not considered) or by the length of the bookmark title + 10
239 // possible score, 900, giving the preliminary score. 245 // (if URL matches are considered) and capped at 1.0. (If URL matches
246 // are considered, we want to expand the scoring range so fewer bookmarks
247 // will hit the 1.0 cap and hence lose all ability to distinguish between
248 // these high-quality bookmarks.)
249 //
250 // The normalized value is multiplied against the scoring range available,
251 // which is 299. The 299 is calculated by subtracting the minimum possible
252 // score, 900, from the maximum possible score, 1199. This product, ranging
253 // from 0 to 299, is added to the minimum possible score, 900, giving the
254 // preliminary score.
240 // 255 //
241 // If the preliminary score is less than the maximum possible score, 1199, 256 // If the preliminary score is less than the maximum possible score, 1199,
242 // it can be boosted up to that maximum possible score if the URL referenced 257 // it can be boosted up to that maximum possible score if the URL referenced
243 // by the bookmark is also referenced by any of the user's other bookmarks. 258 // by the bookmark is also referenced by any of the user's other bookmarks.
244 // A count of how many times the bookmark's URL is referenced is determined 259 // A count of how many times the bookmark's URL is referenced is determined
245 // and, for each additional reference beyond the one for the bookmark being 260 // and, for each additional reference beyond the one for the bookmark being
246 // scored up to a maximum of three, the score is boosted by a fixed amount 261 // scored up to a maximum of three, the score is boosted by a fixed amount
247 // given by |kURLCountBoost|, below. 262 // given by |kURLCountBoost|, below.
248 // 263 //
249 ScoringFunctor position_functor = 264 if (score_using_url_matches_) {
250 for_each(title_match.match_positions.begin(), 265 // Pretend empty titles are identical to the URL.
251 title_match.match_positions.end(), ScoringFunctor(title.size())); 266 if (title.empty())
267 title = base::ASCIIToUTF16(url.spec());
268 } else {
269 DCHECK(!title.empty());
270 }
271 ScoringFunctor title_position_functor =
272 for_each(bookmark_match.title_match_positions.begin(),
273 bookmark_match.title_match_positions.end(),
274 ScoringFunctor(title.size()));
275 ScoringFunctor url_position_functor =
276 for_each(bookmark_match.url_match_positions.begin(),
277 bookmark_match.url_match_positions.end(),
278 ScoringFunctor(title.size()));
279 const double summed_factors = title_position_functor.ScoringFactor() +
280 (score_using_url_matches_ ? url_position_functor.ScoringFactor() : 0);
281 const double normalized_sum = std::min(
282 summed_factors / (title.size() + (score_using_url_matches_ ? 10 : 0)),
283 1.0);
252 const int kBaseBookmarkScore = 900; 284 const int kBaseBookmarkScore = 900;
253 const int kMaxBookmarkScore = AutocompleteResult::kLowestDefaultScore - 1; 285 const int kMaxBookmarkScore = AutocompleteResult::kLowestDefaultScore - 1;
254 const double kBookmarkScoreRange = 286 const double kBookmarkScoreRange =
255 static_cast<double>(kMaxBookmarkScore - kBaseBookmarkScore); 287 static_cast<double>(kMaxBookmarkScore - kBaseBookmarkScore);
256 // It's not likely that GetBookmarksWithTitlesMatching will return overlapping 288 match.relevance = static_cast<int>(normalized_sum * kBookmarkScoreRange) +
257 // matches but let's play it safe. 289 kBaseBookmarkScore;
258 match.relevance = std::min(kMaxBookmarkScore,
259 static_cast<int>(position_functor.ScoringFactor() * kBookmarkScoreRange) +
260 kBaseBookmarkScore);
261 // Don't waste any time searching for additional referenced URLs if we 290 // Don't waste any time searching for additional referenced URLs if we
262 // already have a perfect title match. 291 // already have a perfect title match.
263 if (match.relevance >= kMaxBookmarkScore) 292 if (match.relevance >= kMaxBookmarkScore)
264 return match; 293 return match;
265 // Boost the score if the bookmark's URL is referenced by other bookmarks. 294 // Boost the score if the bookmark's URL is referenced by other bookmarks.
266 const int kURLCountBoost[4] = { 0, 75, 125, 150 }; 295 const int kURLCountBoost[4] = { 0, 75, 125, 150 };
267 std::vector<const BookmarkNode*> nodes; 296 std::vector<const BookmarkNode*> nodes;
268 bookmark_model_->GetNodesByURL(url, &nodes); 297 bookmark_model_->GetNodesByURL(url, &nodes);
269 DCHECK_GE(std::min(arraysize(kURLCountBoost), nodes.size()), 1U); 298 DCHECK_GE(std::min(arraysize(kURLCountBoost), nodes.size()), 1U);
270 match.relevance += 299 match.relevance +=
271 kURLCountBoost[std::min(arraysize(kURLCountBoost), nodes.size()) - 1]; 300 kURLCountBoost[std::min(arraysize(kURLCountBoost), nodes.size()) - 1];
272 match.relevance = std::min(kMaxBookmarkScore, match.relevance); 301 match.relevance = std::min(kMaxBookmarkScore, match.relevance);
273 return match; 302 return match;
274 } 303 }
275 304
276 // static 305 // static
277 ACMatchClassifications BookmarkProvider::ClassificationsFromMatch( 306 ACMatchClassifications BookmarkProvider::ClassificationsFromMatch(
278 const Snippet::MatchPositions& positions, 307 const Snippet::MatchPositions& positions,
279 size_t text_length) { 308 size_t text_length,
309 bool is_url) {
310 ACMatchClassification::Style url_style =
311 is_url ? ACMatchClassification::URL : ACMatchClassification::NONE;
280 ACMatchClassifications classifications; 312 ACMatchClassifications classifications;
281 if (positions.empty()) { 313 if (positions.empty()) {
282 classifications.push_back( 314 classifications.push_back(
283 ACMatchClassification(0, ACMatchClassification::NONE)); 315 ACMatchClassification(0, url_style));
284 return classifications; 316 return classifications;
285 } 317 }
286 318
287 for (Snippet::MatchPositions::const_iterator i = positions.begin(); 319 for (Snippet::MatchPositions::const_iterator i = positions.begin();
288 i != positions.end(); ++i) { 320 i != positions.end(); ++i) {
289 AutocompleteMatch::ACMatchClassifications new_class; 321 AutocompleteMatch::ACMatchClassifications new_class;
290 AutocompleteMatch::ClassifyLocationInString(i->first, i->second - i->first, 322 AutocompleteMatch::ClassifyLocationInString(i->first, i->second - i->first,
291 text_length, 0, &new_class); 323 text_length, url_style, &new_class);
292 classifications = AutocompleteMatch::MergeClassifications( 324 classifications = AutocompleteMatch::MergeClassifications(
293 classifications, new_class); 325 classifications, new_class);
294 } 326 }
295 return classifications; 327 return classifications;
296 } 328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698