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/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 "chrome/browser/autocomplete/autocomplete_result.h" | 13 #include "chrome/browser/autocomplete/autocomplete_result.h" |
14 #include "chrome/browser/autocomplete/url_prefix.h" | |
13 #include "chrome/browser/bookmarks/bookmark_model.h" | 15 #include "chrome/browser/bookmarks/bookmark_model.h" |
14 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 16 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
15 #include "chrome/browser/bookmarks/bookmark_title_match.h" | 17 #include "chrome/browser/bookmarks/bookmark_title_match.h" |
16 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
18 #include "net/base/net_util.h" | 20 #include "net/base/net_util.h" |
19 | 21 |
20 typedef std::vector<BookmarkTitleMatch> TitleMatches; | 22 typedef std::vector<BookmarkTitleMatch> TitleMatches; |
21 | 23 |
22 // BookmarkProvider ------------------------------------------------------------ | 24 // BookmarkProvider ------------------------------------------------------------ |
23 | 25 |
24 BookmarkProvider::BookmarkProvider( | 26 BookmarkProvider::BookmarkProvider( |
25 AutocompleteProviderListener* listener, | 27 AutocompleteProviderListener* listener, |
26 Profile* profile) | 28 Profile* profile) |
27 : AutocompleteProvider(listener, profile, | 29 : AutocompleteProvider(listener, profile, |
28 AutocompleteProvider::TYPE_BOOKMARK), | 30 AutocompleteProvider::TYPE_BOOKMARK), |
29 bookmark_model_(NULL) { | 31 bookmark_model_(NULL) { |
30 if (profile) { | 32 if (profile) { |
31 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile); | 33 bookmark_model_ = BookmarkModelFactory::GetForProfile(profile); |
32 languages_ = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); | 34 languages_ = profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); |
33 } | 35 } |
34 } | 36 } |
35 | 37 |
36 void BookmarkProvider::Start(const AutocompleteInput& input, | 38 void BookmarkProvider::Start(const AutocompleteInput& input, |
37 bool minimal_changes) { | 39 bool minimal_changes) { |
38 if (minimal_changes) | 40 if (minimal_changes) |
39 return; | 41 return; |
40 matches_.clear(); | 42 matches_.clear(); |
41 | 43 |
42 // Short-circuit any matching when inline autocompletion is disabled and | |
43 // we're looking for BEST_MATCH because none of the BookmarkProvider's | |
44 // matches can score high enough to qualify. | |
45 if (input.text().empty() || | 44 if (input.text().empty() || |
46 ((input.type() != AutocompleteInput::UNKNOWN) && | 45 ((input.type() != AutocompleteInput::UNKNOWN) && |
47 (input.type() != AutocompleteInput::QUERY)) || | 46 (input.type() != AutocompleteInput::QUERY))) |
48 ((input.matches_requested() == AutocompleteInput::BEST_MATCH) && | |
49 input.prevent_inline_autocomplete())) | |
50 return; | 47 return; |
51 | 48 |
52 DoAutocomplete(input, | 49 DoAutocomplete(input, |
53 input.matches_requested() == AutocompleteInput::BEST_MATCH); | 50 input.matches_requested() == AutocompleteInput::BEST_MATCH); |
54 } | 51 } |
55 | 52 |
56 BookmarkProvider::~BookmarkProvider() {} | 53 BookmarkProvider::~BookmarkProvider() {} |
57 | 54 |
58 void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input, | 55 void BookmarkProvider::DoAutocomplete(const AutocompleteInput& input, |
59 bool best_match) { | 56 bool best_match) { |
(...skipping 27 matching lines...) Expand all Loading... | |
87 // for all matched terms. | 84 // for all matched terms. |
88 // | 85 // |
89 // Please refer to the code for BookmarkIndex::GetBookmarksWithTitlesMatching | 86 // Please refer to the code for BookmarkIndex::GetBookmarksWithTitlesMatching |
90 // for complete details of how title searches are performed against the user's | 87 // for complete details of how title searches are performed against the user's |
91 // bookmarks. | 88 // bookmarks. |
92 bookmark_model_->GetBookmarksWithTitlesMatching(input.text(), | 89 bookmark_model_->GetBookmarksWithTitlesMatching(input.text(), |
93 kMaxBookmarkMatches, | 90 kMaxBookmarkMatches, |
94 &matches); | 91 &matches); |
95 if (matches.empty()) | 92 if (matches.empty()) |
96 return; // There were no matches. | 93 return; // There were no matches. |
94 AutocompleteInput fixed_up_input; | |
95 // If the input fails to get fixed up, pretend the fixed up version is the | |
96 // original. | |
97 if (!FixupUserInput(&fixed_up_input)) | |
98 fixed_up_input = input; | |
97 for (TitleMatches::const_iterator i = matches.begin(); i != matches.end(); | 99 for (TitleMatches::const_iterator i = matches.begin(); i != matches.end(); |
98 ++i) { | 100 ++i) { |
99 // Create and score the AutocompleteMatch. If its score is 0 then the | 101 // Create and score the AutocompleteMatch. If its score is 0 then the |
100 // match is discarded. | 102 // match is discarded. |
101 AutocompleteMatch match(TitleMatchToACMatch(*i)); | 103 AutocompleteMatch match(TitleMatchToACMatch(input, fixed_up_input, *i)); |
102 if (match.relevance > 0) | 104 if (match.relevance > 0) |
103 matches_.push_back(match); | 105 matches_.push_back(match); |
104 } | 106 } |
105 | 107 |
106 // Sort and clip the resulting matches. | 108 // Sort and clip the resulting matches. |
107 size_t max_matches = best_match ? 1 : AutocompleteProvider::kMaxMatches; | 109 size_t max_matches = best_match ? 1 : AutocompleteProvider::kMaxMatches; |
108 if (matches_.size() > max_matches) { | 110 if (matches_.size() > max_matches) { |
109 std::partial_sort(matches_.begin(), | 111 std::partial_sort(matches_.begin(), |
110 matches_.begin() + max_matches, | 112 matches_.begin() + max_matches, |
111 matches_.end(), | 113 matches_.end(), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 double ScoringFactor() { return scoring_factor_; } | 148 double ScoringFactor() { return scoring_factor_; } |
147 | 149 |
148 private: | 150 private: |
149 double title_length_; | 151 double title_length_; |
150 double scoring_factor_; | 152 double scoring_factor_; |
151 }; | 153 }; |
152 | 154 |
153 } // namespace | 155 } // namespace |
154 | 156 |
155 AutocompleteMatch BookmarkProvider::TitleMatchToACMatch( | 157 AutocompleteMatch BookmarkProvider::TitleMatchToACMatch( |
158 const AutocompleteInput& input, | |
159 const AutocompleteInput& fixed_up_input, | |
156 const BookmarkTitleMatch& title_match) { | 160 const BookmarkTitleMatch& title_match) { |
157 // The AutocompleteMatch we construct is non-deletable because the only | 161 // The AutocompleteMatch we construct is non-deletable because the only |
158 // way to support this would be to delete the underlying bookmark, which is | 162 // way to support this would be to delete the underlying bookmark, which is |
159 // unlikely to be what the user intends. | 163 // unlikely to be what the user intends. |
160 AutocompleteMatch match(this, 0, false, | 164 AutocompleteMatch match(this, 0, false, |
161 AutocompleteMatchType::BOOKMARK_TITLE); | 165 AutocompleteMatchType::BOOKMARK_TITLE); |
162 const base::string16& title(title_match.node->GetTitle()); | 166 const base::string16& title(title_match.node->GetTitle()); |
163 DCHECK(!title.empty()); | 167 DCHECK(!title.empty()); |
168 | |
169 // Determine |inline_autocomplete_offset|. | |
Peter Kasting
2014/04/09 00:53:32
This whole block looks suspiciously similar to wha
Mark P
2014/04/09 02:44:42
I thought about this as I was transferred code her
Mark P
2014/04/09 20:21:41
I found a bug this code, causing me to change my m
| |
164 const GURL& url(title_match.node->url()); | 170 const GURL& url(title_match.node->url()); |
171 const base::string16& url_utf16 = base::UTF8ToUTF16(url.spec()); | |
172 const URLPrefix* best_prefix = URLPrefix::BestURLPrefix(url_utf16, | |
173 input.text()); | |
174 base::string16 matching_string = input.text(); | |
175 // If we failed to find a best_prefix initially, try again using a fixed-up | |
176 // version of the user input. This is especially useful to get about: URLs | |
177 // to inline against chrome:// URLs. (about: URLs are fixed up to the | |
178 // chrome:// scheme.) | |
179 if ((best_prefix == NULL) && !fixed_up_input.text().empty() && | |
180 (fixed_up_input.text() != input.text())) { | |
181 best_prefix = URLPrefix::BestURLPrefix(url_utf16, fixed_up_input.text()); | |
182 matching_string = fixed_up_input.text(); | |
183 } | |
184 size_t inline_autocomplete_offset = | |
185 (best_prefix != NULL) ? | |
186 (best_prefix->prefix.length() + matching_string.length()) : | |
187 base::string16::npos; | |
188 | |
165 match.destination_url = url; | 189 match.destination_url = url; |
190 const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text()) && | |
191 ((best_prefix != NULL) || (inline_autocomplete_offset != 0)); | |
Peter Kasting
2014/04/09 00:53:32
I don't think I understand this conditional.
Woul
Mark P
2014/04/09 02:44:42
Oops, you're right. It should be best_prefix == N
| |
166 match.contents = net::FormatUrl(url, languages_, | 192 match.contents = net::FormatUrl(url, languages_, |
167 net::kFormatUrlOmitAll & net::kFormatUrlOmitHTTP, | 193 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP), |
168 net::UnescapeRule::SPACES, NULL, NULL, NULL); | 194 net::UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset); |
169 match.contents_class.push_back( | 195 match.contents_class.push_back( |
170 ACMatchClassification(0, ACMatchClassification::URL)); | 196 ACMatchClassification(0, ACMatchClassification::URL)); |
171 match.fill_into_edit = | 197 match.fill_into_edit = |
172 AutocompleteInput::FormattedStringWithEquivalentMeaning(url, | 198 AutocompleteInput::FormattedStringWithEquivalentMeaning(url, |
173 match.contents); | 199 match.contents); |
200 if (inline_autocomplete_offset != base::string16::npos) { | |
201 // |inline_autocomplete_offset| may be beyond the end of the | |
202 // |fill_into_edit| if the user has typed an URL with a scheme and the | |
203 // last character typed is a slash. That slash is removed by the | |
204 // FormatURLWithOffsets call above. | |
205 if (inline_autocomplete_offset < match.fill_into_edit.length()) { | |
206 match.inline_autocompletion = | |
207 match.fill_into_edit.substr(inline_autocomplete_offset); | |
208 } | |
209 match.allowed_to_be_default_match = match.inline_autocompletion.empty() || | |
210 !input.prevent_inline_autocomplete(); | |
211 } | |
174 match.description = title; | 212 match.description = title; |
175 match.description_class = | 213 match.description_class = |
176 ClassificationsFromMatch(title_match.match_positions, | 214 ClassificationsFromMatch(title_match.match_positions, |
177 match.description.size()); | 215 match.description.size()); |
178 match.starred = true; | 216 match.starred = true; |
179 | 217 |
180 // Summary on how a relevance score is determined for the match: | 218 // Summary on how a relevance score is determined for the match: |
181 // | 219 // |
182 // For each term matching within the bookmark's title (as given by the set of | 220 // For each term matching within the bookmark's title (as given by the set of |
183 // Snippet::MatchPositions) calculate a 'factor', sum up those factors, then | 221 // Snippet::MatchPositions) calculate a 'factor', sum up those factors, then |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 for (Snippet::MatchPositions::const_iterator i = positions.begin(); | 303 for (Snippet::MatchPositions::const_iterator i = positions.begin(); |
266 i != positions.end(); ++i) { | 304 i != positions.end(); ++i) { |
267 AutocompleteMatch::ACMatchClassifications new_class; | 305 AutocompleteMatch::ACMatchClassifications new_class; |
268 AutocompleteMatch::ClassifyLocationInString(i->first, i->second - i->first, | 306 AutocompleteMatch::ClassifyLocationInString(i->first, i->second - i->first, |
269 text_length, 0, &new_class); | 307 text_length, 0, &new_class); |
270 classifications = AutocompleteMatch::MergeClassifications( | 308 classifications = AutocompleteMatch::MergeClassifications( |
271 classifications, new_class); | 309 classifications, new_class); |
272 } | 310 } |
273 return classifications; | 311 return classifications; |
274 } | 312 } |
OLD | NEW |