| 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/history_quick_provider.h" | 5 #include "chrome/browser/autocomplete/history_quick_provider.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/i18n/break_iterator.h" | 11 #include "base/i18n/break_iterator.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/metrics/field_trial.h" | 13 #include "base/metrics/field_trial.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 20 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" | 20 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" |
| 21 #include "chrome/browser/autocomplete/history_url_provider.h" | 21 #include "chrome/browser/autocomplete/history_url_provider.h" |
| 22 #include "chrome/browser/autocomplete/scored_history_match_builder_impl.h" |
| 23 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| 22 #include "chrome/browser/history/history_service.h" | 24 #include "chrome/browser/history/history_service.h" |
| 23 #include "chrome/browser/history/history_service_factory.h" | 25 #include "chrome/browser/history/history_service_factory.h" |
| 24 #include "chrome/browser/history/in_memory_url_index.h" | 26 #include "chrome/browser/history/in_memory_url_index.h" |
| 25 #include "chrome/browser/history/scored_history_match.h" | |
| 26 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
| 27 #include "chrome/browser/search_engines/template_url_service_factory.h" | 28 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 28 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" |
| 29 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
| 30 #include "chrome/common/url_constants.h" | 31 #include "chrome/common/url_constants.h" |
| 32 #include "components/bookmarks/browser/bookmark_model.h" |
| 31 #include "components/history/core/browser/history_database.h" | 33 #include "components/history/core/browser/history_database.h" |
| 32 #include "components/history/core/browser/in_memory_url_index_types.h" | 34 #include "components/history/core/browser/in_memory_url_index_types.h" |
| 33 #include "components/metrics/proto/omnibox_input_type.pb.h" | 35 #include "components/metrics/proto/omnibox_input_type.pb.h" |
| 34 #include "components/omnibox/autocomplete_match_type.h" | 36 #include "components/omnibox/autocomplete_match_type.h" |
| 35 #include "components/omnibox/autocomplete_result.h" | 37 #include "components/omnibox/autocomplete_result.h" |
| 36 #include "components/omnibox/omnibox_field_trial.h" | 38 #include "components/omnibox/omnibox_field_trial.h" |
| 37 #include "components/search_engines/template_url.h" | 39 #include "components/search_engines/template_url.h" |
| 38 #include "components/search_engines/template_url_service.h" | 40 #include "components/search_engines/template_url_service.h" |
| 39 #include "content/public/browser/notification_source.h" | 41 #include "content/public/browser/notification_source.h" |
| 40 #include "content/public/browser/notification_types.h" | 42 #include "content/public/browser/notification_types.h" |
| 41 #include "net/base/escape.h" | 43 #include "net/base/escape.h" |
| 42 #include "net/base/net_util.h" | 44 #include "net/base/net_util.h" |
| 43 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 45 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 44 #include "url/url_parse.h" | 46 #include "url/url_parse.h" |
| 45 #include "url/url_util.h" | 47 #include "url/url_util.h" |
| 46 | 48 |
| 47 using history::InMemoryURLIndex; | 49 using history::InMemoryURLIndex; |
| 48 using history::ScoredHistoryMatch; | 50 using history::ScoredHistoryMatch; |
| 49 using history::ScoredHistoryMatches; | 51 using history::ScoredHistoryMatches; |
| 50 | 52 |
| 53 namespace { |
| 54 |
| 55 // Returns whether |url| is bookmarked in |bookmark_model| (which can be null |
| 56 // during testing). Used for ScoredHistoryMatchBuilderImpl. |
| 57 bool IsBookmarked(bookmarks::BookmarkModel* bookmark_model, const GURL& url) { |
| 58 return bookmark_model && bookmark_model->IsBookmarked(url); |
| 59 } |
| 60 |
| 61 } // namespace |
| 62 |
| 51 bool HistoryQuickProvider::disabled_ = false; | 63 bool HistoryQuickProvider::disabled_ = false; |
| 52 | 64 |
| 53 HistoryQuickProvider::HistoryQuickProvider(Profile* profile) | 65 HistoryQuickProvider::HistoryQuickProvider(Profile* profile) |
| 54 : HistoryProvider(profile, AutocompleteProvider::TYPE_HISTORY_QUICK), | 66 : HistoryProvider(profile, AutocompleteProvider::TYPE_HISTORY_QUICK), |
| 55 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) { | 67 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) { |
| 56 } | 68 } |
| 57 | 69 |
| 58 void HistoryQuickProvider::Start(const AutocompleteInput& input, | 70 void HistoryQuickProvider::Start(const AutocompleteInput& input, |
| 59 bool minimal_changes, | 71 bool minimal_changes, |
| 60 bool called_due_to_focus) { | 72 bool called_due_to_focus) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 83 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); | 95 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); |
| 84 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); | 96 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); |
| 85 } | 97 } |
| 86 } | 98 } |
| 87 } | 99 } |
| 88 | 100 |
| 89 HistoryQuickProvider::~HistoryQuickProvider() {} | 101 HistoryQuickProvider::~HistoryQuickProvider() {} |
| 90 | 102 |
| 91 void HistoryQuickProvider::DoAutocomplete() { | 103 void HistoryQuickProvider::DoAutocomplete() { |
| 92 // Get the matching URLs from the DB. | 104 // Get the matching URLs from the DB. |
| 93 ScoredHistoryMatches matches = GetIndex()->HistoryItemsForTerms( | 105 ScoredHistoryMatches matches; |
| 94 autocomplete_input_.text(), | 106 { |
| 95 autocomplete_input_.cursor_position(), | 107 ScoredHistoryMatchBuilderImpl builder(base::Bind( |
| 96 AutocompleteProvider::kMaxMatches); | 108 &IsBookmarked, |
| 109 base::Unretained(BookmarkModelFactory::GetForProfile(profile_)))); |
| 110 matches = GetIndex()->HistoryItemsForTerms( |
| 111 autocomplete_input_.text(), autocomplete_input_.cursor_position(), |
| 112 AutocompleteProvider::kMaxMatches, builder); |
| 113 } |
| 97 if (matches.empty()) | 114 if (matches.empty()) |
| 98 return; | 115 return; |
| 99 | 116 |
| 100 // Figure out if HistoryURL provider has a URL-what-you-typed match | 117 // Figure out if HistoryURL provider has a URL-what-you-typed match |
| 101 // that ought to go first and what its score will be. | 118 // that ought to go first and what its score will be. |
| 102 bool will_have_url_what_you_typed_match_first = false; | 119 bool will_have_url_what_you_typed_match_first = false; |
| 103 int url_what_you_typed_match_score = -1; // undefined | 120 int url_what_you_typed_match_score = -1; // undefined |
| 104 // These are necessary (but not sufficient) conditions for the omnibox | 121 // These are necessary (but not sufficient) conditions for the omnibox |
| 105 // input to be a URL-what-you-typed match. The username test checks that | 122 // input to be a URL-what-you-typed match. The username test checks that |
| 106 // either the username does not exist (a regular URL such as http://site/) | 123 // either the username does not exist (a regular URL such as http://site/) |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 // a URL-what-you-typed match. (We want URL-what-you-typed matches for | 209 // a URL-what-you-typed match. (We want URL-what-you-typed matches for |
| 193 // visited URLs to beat out any longer URLs, no matter how frequently | 210 // visited URLs to beat out any longer URLs, no matter how frequently |
| 194 // they're visited.) The strength of this reduction depends on the | 211 // they're visited.) The strength of this reduction depends on the |
| 195 // likely score for the URL-what-you-typed result. | 212 // likely score for the URL-what-you-typed result. |
| 196 | 213 |
| 197 // |template_url_service| or |template_url| can be NULL in unit tests. | 214 // |template_url_service| or |template_url| can be NULL in unit tests. |
| 198 TemplateURLService* template_url_service = | 215 TemplateURLService* template_url_service = |
| 199 TemplateURLServiceFactory::GetForProfile(profile_); | 216 TemplateURLServiceFactory::GetForProfile(profile_); |
| 200 TemplateURL* template_url = template_url_service ? | 217 TemplateURL* template_url = template_url_service ? |
| 201 template_url_service->GetDefaultSearchProvider() : NULL; | 218 template_url_service->GetDefaultSearchProvider() : NULL; |
| 202 int max_match_score = matches.begin()->raw_score(); | 219 int max_match_score = matches.begin()->raw_score; |
| 203 if (will_have_url_what_you_typed_match_first) { | 220 if (will_have_url_what_you_typed_match_first) { |
| 204 max_match_score = std::min(max_match_score, | 221 max_match_score = std::min(max_match_score, |
| 205 url_what_you_typed_match_score - 1); | 222 url_what_you_typed_match_score - 1); |
| 206 } | 223 } |
| 207 for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); | 224 for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); |
| 208 match_iter != matches.end(); ++match_iter) { | 225 match_iter != matches.end(); ++match_iter) { |
| 209 const ScoredHistoryMatch& history_match(*match_iter); | 226 const ScoredHistoryMatch& history_match(*match_iter); |
| 210 // Culls results corresponding to queries from the default search engine. | 227 // Culls results corresponding to queries from the default search engine. |
| 211 // These are low-quality, difficult-to-understand matches for users, and the | 228 // These are low-quality, difficult-to-understand matches for users, and the |
| 212 // SearchProvider should surface past queries in a better way anyway. | 229 // SearchProvider should surface past queries in a better way anyway. |
| 213 if (!template_url || | 230 if (!template_url || |
| 214 !template_url->IsSearchURL(history_match.url_info.url(), | 231 !template_url->IsSearchURL(history_match.url_info.url(), |
| 215 template_url_service->search_terms_data())) { | 232 template_url_service->search_terms_data())) { |
| 216 // Set max_match_score to the score we'll assign this result: | 233 // Set max_match_score to the score we'll assign this result: |
| 217 max_match_score = std::min(max_match_score, history_match.raw_score()); | 234 max_match_score = std::min(max_match_score, history_match.raw_score); |
| 218 matches_.push_back(QuickMatchToACMatch(history_match, max_match_score)); | 235 matches_.push_back(QuickMatchToACMatch(history_match, max_match_score)); |
| 219 // Mark this max_match_score as being used: | 236 // Mark this max_match_score as being used: |
| 220 max_match_score--; | 237 max_match_score--; |
| 221 } | 238 } |
| 222 } | 239 } |
| 223 } | 240 } |
| 224 | 241 |
| 225 AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( | 242 AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( |
| 226 const ScoredHistoryMatch& history_match, | 243 const ScoredHistoryMatch& history_match, |
| 227 int score) { | 244 int score) { |
| 228 const history::URLRow& info = history_match.url_info; | 245 const history::URLRow& info = history_match.url_info; |
| 229 AutocompleteMatch match( | 246 AutocompleteMatch match( |
| 230 this, score, !!info.visit_count(), | 247 this, score, !!info.visit_count(), |
| 231 history_match.url_matches().empty() ? | 248 history_match.url_matches.empty() ? |
| 232 AutocompleteMatchType::HISTORY_TITLE : | 249 AutocompleteMatchType::HISTORY_TITLE : |
| 233 AutocompleteMatchType::HISTORY_URL); | 250 AutocompleteMatchType::HISTORY_URL); |
| 234 match.typed_count = info.typed_count(); | 251 match.typed_count = info.typed_count(); |
| 235 match.destination_url = info.url(); | 252 match.destination_url = info.url(); |
| 236 DCHECK(match.destination_url.is_valid()); | 253 DCHECK(match.destination_url.is_valid()); |
| 237 | 254 |
| 238 // Format the URL autocomplete presentation. | 255 // Format the URL autocomplete presentation. |
| 239 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & | 256 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & |
| 240 ~(!history_match.match_in_scheme ? 0 : net::kFormatUrlOmitHTTP); | 257 ~(!history_match.match_in_scheme ? 0 : net::kFormatUrlOmitHTTP); |
| 241 match.fill_into_edit = | 258 match.fill_into_edit = |
| 242 AutocompleteInput::FormattedStringWithEquivalentMeaning( | 259 AutocompleteInput::FormattedStringWithEquivalentMeaning( |
| 243 info.url(), | 260 info.url(), |
| 244 net::FormatUrl(info.url(), languages_, format_types, | 261 net::FormatUrl(info.url(), languages_, format_types, |
| 245 net::UnescapeRule::SPACES, NULL, NULL, NULL), | 262 net::UnescapeRule::SPACES, NULL, NULL, NULL), |
| 246 ChromeAutocompleteSchemeClassifier(profile_)); | 263 ChromeAutocompleteSchemeClassifier(profile_)); |
| 247 std::vector<size_t> offsets = | 264 std::vector<size_t> offsets = |
| 248 OffsetsFromTermMatches(history_match.url_matches()); | 265 OffsetsFromTermMatches(history_match.url_matches); |
| 249 base::OffsetAdjuster::Adjustments adjustments; | 266 base::OffsetAdjuster::Adjustments adjustments; |
| 250 match.contents = net::FormatUrlWithAdjustments( | 267 match.contents = net::FormatUrlWithAdjustments( |
| 251 info.url(), languages_, format_types, net::UnescapeRule::SPACES, NULL, | 268 info.url(), languages_, format_types, net::UnescapeRule::SPACES, NULL, |
| 252 NULL, &adjustments); | 269 NULL, &adjustments); |
| 253 base::OffsetAdjuster::AdjustOffsets(adjustments, &offsets); | 270 base::OffsetAdjuster::AdjustOffsets(adjustments, &offsets); |
| 254 history::TermMatches new_matches = | 271 history::TermMatches new_matches = |
| 255 ReplaceOffsetsInTermMatches(history_match.url_matches(), offsets); | 272 ReplaceOffsetsInTermMatches(history_match.url_matches, offsets); |
| 256 match.contents_class = | 273 match.contents_class = |
| 257 SpansFromTermMatch(new_matches, match.contents.length(), true); | 274 SpansFromTermMatch(new_matches, match.contents.length(), true); |
| 258 | 275 |
| 259 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible. | 276 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible. |
| 260 if (history_match.can_inline()) { | 277 if (history_match.can_inline) { |
| 261 DCHECK(!new_matches.empty()); | 278 DCHECK(!new_matches.empty()); |
| 262 size_t inline_autocomplete_offset = new_matches[0].offset + | 279 size_t inline_autocomplete_offset = new_matches[0].offset + |
| 263 new_matches[0].length; | 280 new_matches[0].length; |
| 264 // |inline_autocomplete_offset| may be beyond the end of the | 281 // |inline_autocomplete_offset| may be beyond the end of the |
| 265 // |fill_into_edit| if the user has typed an URL with a scheme and the | 282 // |fill_into_edit| if the user has typed an URL with a scheme and the |
| 266 // last character typed is a slash. That slash is removed by the | 283 // last character typed is a slash. That slash is removed by the |
| 267 // FormatURLWithOffsets call above. | 284 // FormatURLWithOffsets call above. |
| 268 if (inline_autocomplete_offset < match.fill_into_edit.length()) { | 285 if (inline_autocomplete_offset < match.fill_into_edit.length()) { |
| 269 match.inline_autocompletion = | 286 match.inline_autocompletion = |
| 270 match.fill_into_edit.substr(inline_autocomplete_offset); | 287 match.fill_into_edit.substr(inline_autocomplete_offset); |
| 271 } | 288 } |
| 272 match.allowed_to_be_default_match = match.inline_autocompletion.empty() || | 289 match.allowed_to_be_default_match = match.inline_autocompletion.empty() || |
| 273 !PreventInlineAutocomplete(autocomplete_input_); | 290 !PreventInlineAutocomplete(autocomplete_input_); |
| 274 } | 291 } |
| 275 match.EnsureUWYTIsAllowedToBeDefault( | 292 match.EnsureUWYTIsAllowedToBeDefault( |
| 276 autocomplete_input_.canonicalized_url(), | 293 autocomplete_input_.canonicalized_url(), |
| 277 TemplateURLServiceFactory::GetForProfile(profile_)); | 294 TemplateURLServiceFactory::GetForProfile(profile_)); |
| 278 | 295 |
| 279 // Format the description autocomplete presentation. | 296 // Format the description autocomplete presentation. |
| 280 match.description = info.title(); | 297 match.description = info.title(); |
| 281 match.description_class = SpansFromTermMatch( | 298 match.description_class = SpansFromTermMatch( |
| 282 history_match.title_matches(), match.description.length(), false); | 299 history_match.title_matches, match.description.length(), false); |
| 283 | 300 |
| 284 match.RecordAdditionalInfo("typed count", info.typed_count()); | 301 match.RecordAdditionalInfo("typed count", info.typed_count()); |
| 285 match.RecordAdditionalInfo("visit count", info.visit_count()); | 302 match.RecordAdditionalInfo("visit count", info.visit_count()); |
| 286 match.RecordAdditionalInfo("last visit", info.last_visit()); | 303 match.RecordAdditionalInfo("last visit", info.last_visit()); |
| 287 | 304 |
| 288 return match; | 305 return match; |
| 289 } | 306 } |
| 290 | 307 |
| 291 history::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { | 308 history::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { |
| 292 if (index_for_testing_.get()) | 309 if (index_for_testing_.get()) |
| 293 return index_for_testing_.get(); | 310 return index_for_testing_.get(); |
| 294 | 311 |
| 295 HistoryService* const history_service = HistoryServiceFactory::GetForProfile( | 312 HistoryService* const history_service = HistoryServiceFactory::GetForProfile( |
| 296 profile_, ServiceAccessType::EXPLICIT_ACCESS); | 313 profile_, ServiceAccessType::EXPLICIT_ACCESS); |
| 297 if (!history_service) | 314 if (!history_service) |
| 298 return NULL; | 315 return NULL; |
| 299 | 316 |
| 300 return history_service->InMemoryIndex(); | 317 return history_service->InMemoryIndex(); |
| 301 } | 318 } |
| OLD | NEW |