Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 if (i.IsWord()) { | 90 if (i.IsWord()) { |
| 91 if (found_word) | 91 if (found_word) |
| 92 return true; | 92 return true; |
| 93 found_word = true; | 93 found_word = true; |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 } | 96 } |
| 97 return false; | 97 return false; |
| 98 } | 98 } |
| 99 | 99 |
| 100 // When displaying a match for |formatted_url| against omnibox input | |
| 101 // |input_text|, determine: | |
| 102 // * if Chrome should strip the http scheme | |
| 103 // * where |input_text| matches in |formatted_url| (if it does) | |
| 104 // * where |input_text| matches as an inline autocompletion in |formatted_url_| | |
| 105 // (if it does) | |
| 106 void GetTrimHttpAndOffsets(const string16& formatted_url, | |
|
msw
2013/08/26 22:57:15
Yeah, this wound up being slightly awkward, mostly
| |
| 107 const string16& input_text, | |
| 108 bool* trim_http, | |
| 109 size_t* match_start, | |
| 110 size_t* inline_autocomplete_offset) { | |
| 111 // Look for the user's input inside the formatted_url as it would be without | |
| 112 // trimming the scheme, so we can find matches at the beginning of the | |
| 113 // scheme. | |
| 114 const URLPrefix* prefix = URLPrefix::BestURLPrefix(formatted_url, input_text); | |
| 115 (*match_start) = (prefix == NULL) ? | |
| 116 formatted_url.find(input_text) : prefix->prefix.length(); | |
| 117 (*trim_http) = !AutocompleteProvider::HasHTTPScheme(input_text) && | |
| 118 (!prefix || (match_start != 0)); | |
| 119 (*inline_autocomplete_offset) = (prefix == NULL) ? | |
| 120 string16::npos : (*match_start + input_text.length()); | |
| 121 } | |
| 122 | |
| 100 } // namespace | 123 } // namespace |
| 101 | 124 |
| 102 | 125 |
| 103 // SearchProvider::Providers -------------------------------------------------- | 126 // SearchProvider::Providers -------------------------------------------------- |
| 104 | 127 |
| 105 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) | 128 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) |
| 106 : template_url_service_(template_url_service) { | 129 : template_url_service_(template_url_service) { |
| 107 } | 130 } |
| 108 | 131 |
| 109 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { | 132 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 126 relevance_(relevance), | 149 relevance_(relevance), |
| 127 relevance_from_server_(relevance_from_server) { | 150 relevance_from_server_(relevance_from_server) { |
| 128 } | 151 } |
| 129 | 152 |
| 130 SearchProvider::Result::~Result() { | 153 SearchProvider::Result::~Result() { |
| 131 } | 154 } |
| 132 | 155 |
| 133 | 156 |
| 134 // SearchProvider::SuggestResult ---------------------------------------------- | 157 // SearchProvider::SuggestResult ---------------------------------------------- |
| 135 | 158 |
| 136 SearchProvider::SuggestResult::SuggestResult(const string16& suggestion, | 159 SearchProvider::SuggestResult::SuggestResult( |
| 137 bool from_keyword_provider, | 160 const string16& suggestion, |
| 138 int relevance, | 161 bool from_keyword_provider, |
| 139 bool relevance_from_server) | 162 int relevance, |
| 163 bool relevance_from_server, | |
| 164 const string16& input_text) | |
| 140 : Result(from_keyword_provider, relevance, relevance_from_server), | 165 : Result(from_keyword_provider, relevance, relevance_from_server), |
| 141 suggestion_(suggestion) { | 166 suggestion_(suggestion) { |
| 167 CalculateContents(true, input_text); | |
| 142 } | 168 } |
| 143 | 169 |
| 144 SearchProvider::SuggestResult::~SuggestResult() { | 170 SearchProvider::SuggestResult::~SuggestResult() { |
| 145 } | 171 } |
| 146 | 172 |
| 147 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { | 173 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { |
| 148 return StartsWith(suggestion_, input, false); | 174 return StartsWith(suggestion_, input, false); |
| 149 } | 175 } |
| 150 | 176 |
| 151 int SearchProvider::SuggestResult::CalculateRelevance( | 177 int SearchProvider::SuggestResult::CalculateRelevance( |
| 152 const AutocompleteInput& input, | 178 const AutocompleteInput& input, |
| 153 bool keyword_provider_requested) const { | 179 bool keyword_provider_requested) const { |
| 154 if (!from_keyword_provider_ && keyword_provider_requested) | 180 if (!from_keyword_provider_ && keyword_provider_requested) |
| 155 return 100; | 181 return 100; |
| 156 return ((input.type() == AutocompleteInput::URL) ? 300 : 600); | 182 return ((input.type() == AutocompleteInput::URL) ? 300 : 600); |
| 157 } | 183 } |
| 158 | 184 |
| 185 void SearchProvider::SuggestResult::CalculateContents( | |
| 186 bool allow_bolding_all, | |
| 187 const string16& input_text) { | |
| 188 size_t input_position = suggestion_.find(input_text); | |
| 189 if (!allow_bolding_all && (input_text != suggestion_) && | |
| 190 (input_position == string16::npos)) { | |
| 191 // Bail if the code below to update the bolding would bold the whole | |
| 192 // string. Note that the string may already be entirely bolded; if | |
| 193 // so, leave it as is. | |
| 194 return; | |
| 195 } | |
| 196 contents_.assign(suggestion_); | |
| 197 contents_class_.clear(); | |
| 198 // We do intra-string highlighting for suggestions - the suggested segment | |
| 199 // will be highlighted, e.g. for input_text = "you" the suggestion may be | |
| 200 // "youtube", so we'll bold the "tube" section: you*tube*. | |
| 201 if (input_text != suggestion_) { | |
| 202 if (input_position == string16::npos) { | |
| 203 // The input text is not a substring of the query string, e.g. input | |
| 204 // text is "slasdot" and the query string is "slashdot", so we bold the | |
| 205 // whole thing. | |
| 206 contents_class_.push_back( | |
| 207 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
| 208 } else { | |
| 209 // TODO(beng): ACMatchClassification::MATCH now seems to just mean | |
| 210 // "bold" this. Consider modifying the terminology. | |
| 211 // We don't iterate over the string here annotating all matches because | |
| 212 // it looks odd to have every occurrence of a substring that may be as | |
| 213 // short as a single character highlighted in a query suggestion result, | |
| 214 // e.g. for input text "s" and query string "southwest airlines", it | |
| 215 // looks odd if both the first and last s are highlighted. | |
| 216 if (input_position != 0) { | |
| 217 contents_class_.push_back( | |
| 218 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
| 219 } | |
| 220 contents_class_.push_back( | |
| 221 ACMatchClassification(input_position, ACMatchClassification::NONE)); | |
| 222 size_t next_fragment_position = input_position + input_text.length(); | |
| 223 if (next_fragment_position < suggestion_.length()) { | |
| 224 contents_class_.push_back( | |
| 225 ACMatchClassification(next_fragment_position, | |
| 226 ACMatchClassification::MATCH)); | |
| 227 } | |
| 228 } | |
| 229 } else { | |
| 230 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the | |
| 231 // default provider or a keyword search provider. | |
| 232 contents_class_.push_back( | |
| 233 ACMatchClassification(0, ACMatchClassification::NONE)); | |
| 234 | |
| 235 } | |
| 236 } | |
| 159 | 237 |
| 160 // SearchProvider::NavigationResult ------------------------------------------- | 238 // SearchProvider::NavigationResult ------------------------------------------- |
| 161 | 239 |
| 162 SearchProvider::NavigationResult::NavigationResult( | 240 SearchProvider::NavigationResult::NavigationResult( |
| 163 const AutocompleteProvider& provider, | 241 const AutocompleteProvider& provider, |
| 164 const GURL& url, | 242 const GURL& url, |
| 165 const string16& description, | 243 const string16& description, |
| 166 bool from_keyword_provider, | 244 bool from_keyword_provider, |
| 167 int relevance, | 245 int relevance, |
| 168 bool relevance_from_server) | 246 bool relevance_from_server, |
| 247 const string16& input_text, | |
| 248 const std::string& languages) | |
| 169 : Result(from_keyword_provider, relevance, relevance_from_server), | 249 : Result(from_keyword_provider, relevance, relevance_from_server), |
| 170 url_(url), | 250 url_(url), |
| 171 formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( | 251 formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( |
| 172 url, provider.StringForURLDisplay(url, true, false))), | 252 url, provider.StringForURLDisplay(url, true, false))), |
| 173 description_(description) { | 253 description_(description) { |
| 174 DCHECK(url_.is_valid()); | 254 DCHECK(url_.is_valid()); |
| 255 CalculateContents(true, input_text, languages); | |
| 175 } | 256 } |
| 176 | 257 |
| 177 SearchProvider::NavigationResult::~NavigationResult() { | 258 SearchProvider::NavigationResult::~NavigationResult() { |
| 178 } | 259 } |
| 179 | 260 |
| 180 bool SearchProvider::NavigationResult::IsInlineable( | 261 bool SearchProvider::NavigationResult::IsInlineable( |
| 181 const string16& input) const { | 262 const string16& input) const { |
| 182 return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; | 263 return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; |
| 183 } | 264 } |
| 184 | 265 |
| 185 int SearchProvider::NavigationResult::CalculateRelevance( | 266 int SearchProvider::NavigationResult::CalculateRelevance( |
| 186 const AutocompleteInput& input, | 267 const AutocompleteInput& input, |
| 187 bool keyword_provider_requested) const { | 268 bool keyword_provider_requested) const { |
| 188 return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150; | 269 return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150; |
| 189 } | 270 } |
| 190 | 271 |
| 272 void SearchProvider::NavigationResult::CalculateContents( | |
| 273 bool allow_bolding_nothing, | |
| 274 const string16& input_text, | |
| 275 const std::string languages) { | |
| 276 bool trim_http; | |
|
msw
2013/08/26 22:57:15
nit: explicitly init to false.
| |
| 277 size_t match_start, inline_autocomplete_offset; | |
|
msw
2013/08/26 22:57:15
nit: declare each on separate lines; explicitly in
| |
| 278 GetTrimHttpAndOffsets(formatted_url_, input_text, &trim_http, &match_start, | |
| 279 &inline_autocomplete_offset); | |
| 280 if (!allow_bolding_nothing && (match_start == string16::npos)) { | |
| 281 // Bail if the code below to update the bolding would make the stirng | |
| 282 // entirely not bolded. Note that the string may already be entirely | |
| 283 // not bolded; if so, leave it as is. | |
| 284 return; | |
| 285 } | |
| 286 const net::FormatUrlTypes format_types = | |
| 287 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | |
| 288 contents_ = net::FormatUrl(url_, languages, | |
| 289 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | |
| 290 // If the first match in the untrimmed string was inside a scheme that we | |
| 291 // trimmed, look for a subsequent match. | |
| 292 if (match_start == string16::npos) | |
| 293 match_start = contents_.find(input_text); | |
| 294 // Safe if |match_start| is npos; also safe if the input is longer than the | |
| 295 // remaining contents after |match_start|. | |
| 296 AutocompleteMatch::ClassifyLocationInString(match_start, input_text.length(), | |
| 297 contents_.length(), ACMatchClassification::URL, | |
| 298 &contents_class_); | |
| 299 } | |
| 191 | 300 |
| 192 // SearchProvider::CompareScoredResults --------------------------------------- | 301 // SearchProvider::CompareScoredResults --------------------------------------- |
| 193 | 302 |
| 194 class SearchProvider::CompareScoredResults { | 303 class SearchProvider::CompareScoredResults { |
| 195 public: | 304 public: |
| 196 bool operator()(const Result& a, const Result& b) { | 305 bool operator()(const Result& a, const Result& b) { |
| 197 // Sort in descending relevance order. | 306 // Sort in descending relevance order. |
| 198 return a.relevance() > b.relevance(); | 307 return a.relevance() > b.relevance(); |
| 199 } | 308 } |
| 200 }; | 309 }; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 AutocompleteProvider::TYPE_SEARCH), | 361 AutocompleteProvider::TYPE_SEARCH), |
| 253 providers_(TemplateURLServiceFactory::GetForProfile(profile)), | 362 providers_(TemplateURLServiceFactory::GetForProfile(profile)), |
| 254 suggest_results_pending_(0), | 363 suggest_results_pending_(0), |
| 255 field_trial_triggered_(false), | 364 field_trial_triggered_(false), |
| 256 field_trial_triggered_in_session_(false) { | 365 field_trial_triggered_in_session_(false) { |
| 257 } | 366 } |
| 258 | 367 |
| 259 // static | 368 // static |
| 260 AutocompleteMatch SearchProvider::CreateSearchSuggestion( | 369 AutocompleteMatch SearchProvider::CreateSearchSuggestion( |
| 261 AutocompleteProvider* autocomplete_provider, | 370 AutocompleteProvider* autocomplete_provider, |
| 262 int relevance, | 371 const SuggestResult& result, |
| 263 AutocompleteMatch::Type type, | 372 AutocompleteMatch::Type type, |
| 264 const TemplateURL* template_url, | 373 const TemplateURL* template_url, |
| 265 const string16& query_string, | |
| 266 const string16& input_text, | 374 const string16& input_text, |
| 267 const AutocompleteInput& input, | 375 const AutocompleteInput& input, |
| 268 bool is_keyword, | |
| 269 int accepted_suggestion, | 376 int accepted_suggestion, |
| 270 int omnibox_start_margin, | 377 int omnibox_start_margin, |
| 271 bool append_extra_query_params) { | 378 bool append_extra_query_params) { |
| 272 AutocompleteMatch match(autocomplete_provider, relevance, false, type); | 379 AutocompleteMatch match( |
| 380 autocomplete_provider, result.relevance(), false, type); | |
| 273 | 381 |
| 274 if (!template_url) | 382 if (!template_url) |
| 275 return match; | 383 return match; |
| 276 match.keyword = template_url->keyword(); | 384 match.keyword = template_url->keyword(); |
| 277 | 385 |
| 278 match.contents.assign(query_string); | 386 match.contents = result.contents(); |
| 279 // We do intra-string highlighting for suggestions - the suggested segment | 387 match.contents_class = result.contents_class(); |
| 280 // will be highlighted, e.g. for input_text = "you" the suggestion may be | 388 if (input_text == result.suggestion()) |
| 281 // "youtube", so we'll bold the "tube" section: you*tube*. | |
| 282 if (input_text != query_string) { | |
| 283 size_t input_position = match.contents.find(input_text); | |
| 284 if (input_position == string16::npos) { | |
| 285 // The input text is not a substring of the query string, e.g. input | |
| 286 // text is "slasdot" and the query string is "slashdot", so we bold the | |
| 287 // whole thing. | |
| 288 match.contents_class.push_back( | |
| 289 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
| 290 } else { | |
| 291 // TODO(beng): ACMatchClassification::MATCH now seems to just mean | |
| 292 // "bold" this. Consider modifying the terminology. | |
| 293 // We don't iterate over the string here annotating all matches because | |
| 294 // it looks odd to have every occurrence of a substring that may be as | |
| 295 // short as a single character highlighted in a query suggestion result, | |
| 296 // e.g. for input text "s" and query string "southwest airlines", it | |
| 297 // looks odd if both the first and last s are highlighted. | |
| 298 if (input_position != 0) { | |
| 299 match.contents_class.push_back( | |
| 300 ACMatchClassification(0, ACMatchClassification::MATCH)); | |
| 301 } | |
| 302 match.contents_class.push_back( | |
| 303 ACMatchClassification(input_position, ACMatchClassification::NONE)); | |
| 304 size_t next_fragment_position = input_position + input_text.length(); | |
| 305 if (next_fragment_position < query_string.length()) { | |
| 306 match.contents_class.push_back( | |
| 307 ACMatchClassification(next_fragment_position, | |
| 308 ACMatchClassification::MATCH)); | |
| 309 } | |
| 310 } | |
| 311 } else { | |
| 312 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the | |
| 313 // default provider or a keyword search provider. | |
| 314 match.contents_class.push_back( | |
| 315 ACMatchClassification(0, ACMatchClassification::NONE)); | |
| 316 match.allowed_to_be_default_match = true; | 389 match.allowed_to_be_default_match = true; |
| 317 } | |
| 318 | 390 |
| 319 // When the user forced a query, we need to make sure all the fill_into_edit | 391 // When the user forced a query, we need to make sure all the fill_into_edit |
| 320 // values preserve that property. Otherwise, if the user starts editing a | 392 // values preserve that property. Otherwise, if the user starts editing a |
| 321 // suggestion, non-Search results will suddenly appear. | 393 // suggestion, non-Search results will suddenly appear. |
| 322 if (input.type() == AutocompleteInput::FORCED_QUERY) | 394 if (input.type() == AutocompleteInput::FORCED_QUERY) |
| 323 match.fill_into_edit.assign(ASCIIToUTF16("?")); | 395 match.fill_into_edit.assign(ASCIIToUTF16("?")); |
| 324 if (is_keyword) | 396 if (result.from_keyword_provider()) |
| 325 match.fill_into_edit.append(match.keyword + char16(' ')); | 397 match.fill_into_edit.append(match.keyword + char16(' ')); |
| 326 if (!input.prevent_inline_autocomplete() && | 398 if (!input.prevent_inline_autocomplete() && |
| 327 StartsWith(query_string, input_text, false)) { | 399 StartsWith(result.suggestion(), input_text, false)) { |
| 328 match.inline_autocompletion = query_string.substr(input_text.length()); | 400 match.inline_autocompletion = |
| 401 result.suggestion().substr(input_text.length()); | |
| 329 match.allowed_to_be_default_match = true; | 402 match.allowed_to_be_default_match = true; |
| 330 } | 403 } |
| 331 match.fill_into_edit.append(query_string); | 404 match.fill_into_edit.append(result.suggestion()); |
| 332 | 405 |
| 333 const TemplateURLRef& search_url = template_url->url_ref(); | 406 const TemplateURLRef& search_url = template_url->url_ref(); |
| 334 DCHECK(search_url.SupportsReplacement()); | 407 DCHECK(search_url.SupportsReplacement()); |
| 335 match.search_terms_args.reset( | 408 match.search_terms_args.reset( |
| 336 new TemplateURLRef::SearchTermsArgs(query_string)); | 409 new TemplateURLRef::SearchTermsArgs(result.suggestion())); |
| 337 match.search_terms_args->original_query = input_text; | 410 match.search_terms_args->original_query = input_text; |
| 338 match.search_terms_args->accepted_suggestion = accepted_suggestion; | 411 match.search_terms_args->accepted_suggestion = accepted_suggestion; |
| 339 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; | 412 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; |
| 340 match.search_terms_args->append_extra_query_params = | 413 match.search_terms_args->append_extra_query_params = |
| 341 append_extra_query_params; | 414 append_extra_query_params; |
| 342 // This is the destination URL sans assisted query stats. This must be set | 415 // This is the destination URL sans assisted query stats. This must be set |
| 343 // so the AutocompleteController can properly de-dupe; the controller will | 416 // so the AutocompleteController can properly de-dupe; the controller will |
| 344 // eventually overwrite it before it reaches the user. | 417 // eventually overwrite it before it reaches the user. |
| 345 match.destination_url = | 418 match.destination_url = |
| 346 GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get())); | 419 GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get())); |
| 347 | 420 |
| 348 // Search results don't look like URLs. | 421 // Search results don't look like URLs. |
| 349 match.transition = is_keyword ? | 422 match.transition = result.from_keyword_provider() ? |
| 350 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; | 423 content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; |
| 351 | 424 |
| 352 return match; | 425 return match; |
| 353 } | 426 } |
| 354 | 427 |
| 355 void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { | 428 void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { |
| 356 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); | 429 provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); |
| 357 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); | 430 metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); |
| 358 new_entry.set_provider(AsOmniboxEventProviderType()); | 431 new_entry.set_provider(AsOmniboxEventProviderType()); |
| 359 new_entry.set_provider_done(done_); | 432 new_entry.set_provider_done(done_); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 } else { | 496 } else { |
| 424 // The current top result is a navigational suggestion. | 497 // The current top result is a navigational suggestion. |
| 425 if (nav_it->IsInlineable(input)) | 498 if (nav_it->IsInlineable(input)) |
| 426 break; | 499 break; |
| 427 nav_it = navigation_results->erase(nav_it); | 500 nav_it = navigation_results->erase(nav_it); |
| 428 } | 501 } |
| 429 } | 502 } |
| 430 } | 503 } |
| 431 | 504 |
| 432 // static | 505 // static |
| 506 void SearchProvider::RecalculateBolding(const string16& input_text, | |
| 507 const std::string languages, | |
| 508 Results* results) { | |
| 509 for (SuggestResults::iterator sug_it = results->suggest_results.begin(); | |
| 510 sug_it != results->suggest_results.end(); ++sug_it) { | |
| 511 sug_it->CalculateContents(false, input_text); | |
| 512 } | |
| 513 for (NavigationResults::iterator nav_it = results->navigation_results.begin(); | |
| 514 nav_it != results->navigation_results.end(); ++nav_it) { | |
| 515 nav_it->CalculateContents(false, input_text, languages); | |
| 516 } | |
| 517 } | |
| 518 | |
| 519 // static | |
| 433 int SearchProvider::CalculateRelevanceForKeywordVerbatim( | 520 int SearchProvider::CalculateRelevanceForKeywordVerbatim( |
| 434 AutocompleteInput::Type type, | 521 AutocompleteInput::Type type, |
| 435 bool prefer_keyword) { | 522 bool prefer_keyword) { |
| 436 // This function is responsible for scoring verbatim query matches | 523 // This function is responsible for scoring verbatim query matches |
| 437 // for non-extension keywords. KeywordProvider::CalculateRelevance() | 524 // for non-extension keywords. KeywordProvider::CalculateRelevance() |
| 438 // scores verbatim query matches for extension keywords, as well as | 525 // scores verbatim query matches for extension keywords, as well as |
| 439 // for keyword matches (i.e., suggestions of a keyword itself, not a | 526 // for keyword matches (i.e., suggestions of a keyword itself, not a |
| 440 // suggestion of a query on a keyword search engine). These two | 527 // suggestion of a query on a keyword search engine). These two |
| 441 // functions are currently in sync, but there's no reason we | 528 // functions are currently in sync, but there's no reason we |
| 442 // couldn't decide in the future to score verbatim matches | 529 // couldn't decide in the future to score verbatim matches |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 (!done_ && | 765 (!done_ && |
| 679 input_.matches_requested() == AutocompleteInput::ALL_MATCHES))) | 766 input_.matches_requested() == AutocompleteInput::ALL_MATCHES))) |
| 680 return; | 767 return; |
| 681 | 768 |
| 682 // We can't keep running any previous query, so halt it. | 769 // We can't keep running any previous query, so halt it. |
| 683 StopSuggest(); | 770 StopSuggest(); |
| 684 | 771 |
| 685 // Remove existing results that cannot inline autocomplete the new input. | 772 // Remove existing results that cannot inline autocomplete the new input. |
| 686 RemoveAllStaleResults(); | 773 RemoveAllStaleResults(); |
| 687 | 774 |
| 775 // Revise the bolding of all results that remain so they look good against | |
| 776 // the current input. | |
| 777 const std::string languages = | |
| 778 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); | |
| 779 RecalculateBolding(input_.text(), languages, &default_results_); | |
| 780 RecalculateBolding(keyword_input_.text(), languages, &keyword_results_); | |
| 781 | |
| 688 // We can't start a new query if we're only allowed synchronous results. | 782 // We can't start a new query if we're only allowed synchronous results. |
| 689 if (input_.matches_requested() != AutocompleteInput::ALL_MATCHES) | 783 if (input_.matches_requested() != AutocompleteInput::ALL_MATCHES) |
| 690 return; | 784 return; |
| 691 | 785 |
| 692 // To avoid flooding the suggest server, don't send a query until at | 786 // To avoid flooding the suggest server, don't send a query until at |
| 693 // least 100 ms since the last query. | 787 // least 100 ms since the last query. |
| 694 base::TimeTicks next_suggest_time(time_suggest_request_sent_ + | 788 base::TimeTicks next_suggest_time(time_suggest_request_sent_ + |
| 695 base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs)); | 789 base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs)); |
| 696 base::TimeTicks now(base::TimeTicks::Now()); | 790 base::TimeTicks now(base::TimeTicks::Now()); |
| 697 if (now >= next_suggest_time) { | 791 if (now >= next_suggest_time) { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 field_trial_triggered_in_session_ |= triggered; | 993 field_trial_triggered_in_session_ |= triggered; |
| 900 } | 994 } |
| 901 | 995 |
| 902 // Clear the previous results now that new results are available. | 996 // Clear the previous results now that new results are available. |
| 903 results->suggest_results.clear(); | 997 results->suggest_results.clear(); |
| 904 results->navigation_results.clear(); | 998 results->navigation_results.clear(); |
| 905 | 999 |
| 906 string16 result, title; | 1000 string16 result, title; |
| 907 std::string type; | 1001 std::string type; |
| 908 int relevance = -1; | 1002 int relevance = -1; |
| 1003 const std::string& languages = | |
| 1004 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages); | |
| 909 for (size_t index = 0; results_list->GetString(index, &result); ++index) { | 1005 for (size_t index = 0; results_list->GetString(index, &result); ++index) { |
| 910 // Google search may return empty suggestions for weird input characters, | 1006 // Google search may return empty suggestions for weird input characters, |
| 911 // they make no sense at all and can cause problems in our code. | 1007 // they make no sense at all and can cause problems in our code. |
| 912 if (result.empty()) | 1008 if (result.empty()) |
| 913 continue; | 1009 continue; |
| 914 | 1010 |
| 915 // Apply valid suggested relevance scores; discard invalid lists. | 1011 // Apply valid suggested relevance scores; discard invalid lists. |
| 916 if (relevances != NULL && !relevances->GetInteger(index, &relevance)) | 1012 if (relevances != NULL && !relevances->GetInteger(index, &relevance)) |
| 917 relevances = NULL; | 1013 relevances = NULL; |
| 918 if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { | 1014 if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { |
| 919 // Do not blindly trust the URL coming from the server to be valid. | 1015 // Do not blindly trust the URL coming from the server to be valid. |
| 920 GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(result), std::string())); | 1016 GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(result), std::string())); |
| 921 if (url.is_valid()) { | 1017 if (url.is_valid()) { |
| 922 if (descriptions != NULL) | 1018 if (descriptions != NULL) |
| 923 descriptions->GetString(index, &title); | 1019 descriptions->GetString(index, &title); |
| 924 results->navigation_results.push_back(NavigationResult( | 1020 results->navigation_results.push_back(NavigationResult( |
| 925 *this, url, title, is_keyword, relevance, true)); | 1021 *this, url, title, is_keyword, relevance, true, input_text, |
| 1022 languages)); | |
| 926 } | 1023 } |
| 927 } else { | 1024 } else { |
| 928 // TODO(kochi): Improve calculator result presentation. | 1025 // TODO(kochi): Improve calculator result presentation. |
| 929 results->suggest_results.push_back( | 1026 results->suggest_results.push_back( |
| 930 SuggestResult(result, is_keyword, relevance, true)); | 1027 SuggestResult(result, is_keyword, relevance, true, input_text)); |
| 931 } | 1028 } |
| 932 } | 1029 } |
| 933 | 1030 |
| 934 // Apply calculated relevance scores if a valid list was not provided. | 1031 // Apply calculated relevance scores if a valid list was not provided. |
| 935 if (relevances == NULL) { | 1032 if (relevances == NULL) { |
| 936 ApplyCalculatedSuggestRelevance(&results->suggest_results); | 1033 ApplyCalculatedSuggestRelevance(&results->suggest_results); |
| 937 ApplyCalculatedNavigationRelevance(&results->navigation_results); | 1034 ApplyCalculatedNavigationRelevance(&results->navigation_results); |
| 938 } | 1035 } |
| 939 // Keep the result lists sorted. | 1036 // Keep the result lists sorted. |
| 940 const CompareScoredResults comparator = CompareScoredResults(); | 1037 const CompareScoredResults comparator = CompareScoredResults(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 957 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 1054 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 958 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 1055 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 959 | 1056 |
| 960 bool relevance_from_server; | 1057 bool relevance_from_server; |
| 961 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); | 1058 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); |
| 962 int did_not_accept_default_suggestion = | 1059 int did_not_accept_default_suggestion = |
| 963 default_results_.suggest_results.empty() ? | 1060 default_results_.suggest_results.empty() ? |
| 964 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 1061 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 965 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 1062 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 966 if (verbatim_relevance > 0) { | 1063 if (verbatim_relevance > 0) { |
| 967 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, | 1064 SuggestResult verbatim(input_.text(), false, verbatim_relevance, |
| 968 relevance_from_server, | 1065 relevance_from_server, input_.text()); |
| 1066 AddMatchToMap(verbatim, input_.text(), | |
| 969 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, | 1067 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
| 970 did_not_accept_default_suggestion, false, &map); | 1068 did_not_accept_default_suggestion, &map); |
| 971 } | 1069 } |
| 972 if (!keyword_input_.text().empty()) { | 1070 if (!keyword_input_.text().empty()) { |
| 973 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 1071 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 974 // We only create the verbatim search query match for a keyword | 1072 // We only create the verbatim search query match for a keyword |
| 975 // if it's not an extension keyword. Extension keywords are handled | 1073 // if it's not an extension keyword. Extension keywords are handled |
| 976 // in KeywordProvider::Start(). (Extensions are complicated...) | 1074 // in KeywordProvider::Start(). (Extensions are complicated...) |
| 977 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond | 1075 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond |
| 978 // to the keyword verbatim search query. Do not create other matches | 1076 // to the keyword verbatim search query. Do not create other matches |
| 979 // of type SEARCH_OTHER_ENGINE. | 1077 // of type SEARCH_OTHER_ENGINE. |
| 980 if (keyword_url && !keyword_url->IsExtensionKeyword()) { | 1078 if (keyword_url && !keyword_url->IsExtensionKeyword()) { |
| 981 bool keyword_relevance_from_server; | 1079 bool keyword_relevance_from_server; |
| 982 const int keyword_verbatim_relevance = | 1080 const int keyword_verbatim_relevance = |
| 983 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); | 1081 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); |
| 984 if (keyword_verbatim_relevance > 0) { | 1082 if (keyword_verbatim_relevance > 0) { |
| 985 AddMatchToMap(keyword_input_.text(), keyword_input_.text(), | 1083 SuggestResult keyword_verbatim( |
| 986 keyword_verbatim_relevance, keyword_relevance_from_server, | 1084 keyword_input_.text(), true, keyword_verbatim_relevance, |
| 1085 keyword_relevance_from_server, keyword_input_.text()); | |
| 1086 AddMatchToMap(keyword_verbatim, keyword_input_.text(), | |
| 987 AutocompleteMatchType::SEARCH_OTHER_ENGINE, | 1087 AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
| 988 did_not_accept_keyword_suggestion, true, &map); | 1088 did_not_accept_keyword_suggestion, &map); |
| 989 } | 1089 } |
| 990 } | 1090 } |
| 991 } | 1091 } |
| 992 AddHistoryResultsToMap(keyword_history_results_, true, | 1092 AddHistoryResultsToMap(keyword_history_results_, true, |
| 993 did_not_accept_keyword_suggestion, &map); | 1093 did_not_accept_keyword_suggestion, &map); |
| 994 AddHistoryResultsToMap(default_history_results_, false, | 1094 AddHistoryResultsToMap(default_history_results_, false, |
| 995 did_not_accept_default_suggestion, &map); | 1095 did_not_accept_default_suggestion, &map); |
| 996 | 1096 |
| 997 AddSuggestResultsToMap(keyword_results_.suggest_results, &map); | 1097 AddSuggestResultsToMap(keyword_results_.suggest_results, &map); |
| 998 AddSuggestResultsToMap(default_results_.suggest_results, &map); | 1098 AddSuggestResultsToMap(default_results_.suggest_results, &map); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1201 AutocompleteResult::kLowestDefaultScore) || | 1301 AutocompleteResult::kLowestDefaultScore) || |
| 1202 !HasMultipleWords(scored_results.front().suggestion())) | 1302 !HasMultipleWords(scored_results.front().suggestion())) |
| 1203 scored_results.clear(); // Didn't detect the case above, score normally. | 1303 scored_results.clear(); // Didn't detect the case above, score normally. |
| 1204 } | 1304 } |
| 1205 if (scored_results.empty()) | 1305 if (scored_results.empty()) |
| 1206 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 1306 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, |
| 1207 input_multiple_words, input_text, | 1307 input_multiple_words, input_text, |
| 1208 is_keyword); | 1308 is_keyword); |
| 1209 for (SuggestResults::const_iterator i(scored_results.begin()); | 1309 for (SuggestResults::const_iterator i(scored_results.begin()); |
| 1210 i != scored_results.end(); ++i) { | 1310 i != scored_results.end(); ++i) { |
| 1211 AddMatchToMap(i->suggestion(), input_text, i->relevance(), false, | 1311 AddMatchToMap(*i, input_text, |
| 1212 AutocompleteMatchType::SEARCH_HISTORY, | 1312 AutocompleteMatchType::SEARCH_HISTORY, |
| 1213 did_not_accept_suggestion, | 1313 did_not_accept_suggestion, map); |
| 1214 is_keyword, map); | |
| 1215 } | 1314 } |
| 1216 } | 1315 } |
| 1217 | 1316 |
| 1218 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( | 1317 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
| 1219 const HistoryResults& results, | 1318 const HistoryResults& results, |
| 1220 bool base_prevent_inline_autocomplete, | 1319 bool base_prevent_inline_autocomplete, |
| 1221 bool input_multiple_words, | 1320 bool input_multiple_words, |
| 1222 const string16& input_text, | 1321 const string16& input_text, |
| 1223 bool is_keyword) { | 1322 bool is_keyword) { |
| 1224 AutocompleteClassifier* classifier = | 1323 AutocompleteClassifier* classifier = |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1251 AutocompleteMatch match; | 1350 AutocompleteMatch match; |
| 1252 classifier->Classify(i->term, false, false, &match, NULL); | 1351 classifier->Classify(i->term, false, false, &match, NULL); |
| 1253 prevent_inline_autocomplete = | 1352 prevent_inline_autocomplete = |
| 1254 !AutocompleteMatch::IsSearchType(match.type); | 1353 !AutocompleteMatch::IsSearchType(match.type); |
| 1255 } | 1354 } |
| 1256 | 1355 |
| 1257 int relevance = CalculateRelevanceForHistory( | 1356 int relevance = CalculateRelevanceForHistory( |
| 1258 i->time, is_keyword, !prevent_inline_autocomplete, | 1357 i->time, is_keyword, !prevent_inline_autocomplete, |
| 1259 prevent_search_history_inlining); | 1358 prevent_search_history_inlining); |
| 1260 scored_results.push_back( | 1359 scored_results.push_back( |
| 1261 SuggestResult(i->term, is_keyword, relevance, false)); | 1360 SuggestResult(i->term, is_keyword, relevance, false, input_text)); |
| 1262 } | 1361 } |
| 1263 | 1362 |
| 1264 // History returns results sorted for us. However, we may have docked some | 1363 // History returns results sorted for us. However, we may have docked some |
| 1265 // results' scores, so things are no longer in order. Do a stable sort to get | 1364 // results' scores, so things are no longer in order. Do a stable sort to get |
| 1266 // things back in order without otherwise disturbing results with equal | 1365 // things back in order without otherwise disturbing results with equal |
| 1267 // scores, then force the scores to be unique, so that the order in which | 1366 // scores, then force the scores to be unique, so that the order in which |
| 1268 // they're shown is deterministic. | 1367 // they're shown is deterministic. |
| 1269 std::stable_sort(scored_results.begin(), scored_results.end(), | 1368 std::stable_sort(scored_results.begin(), scored_results.end(), |
| 1270 CompareScoredResults()); | 1369 CompareScoredResults()); |
| 1271 int last_relevance = 0; | 1370 int last_relevance = 0; |
| 1272 for (SuggestResults::iterator i(scored_results.begin()); | 1371 for (SuggestResults::iterator i(scored_results.begin()); |
| 1273 i != scored_results.end(); ++i) { | 1372 i != scored_results.end(); ++i) { |
| 1274 if ((i != scored_results.begin()) && (i->relevance() >= last_relevance)) | 1373 if ((i != scored_results.begin()) && (i->relevance() >= last_relevance)) |
| 1275 i->set_relevance(last_relevance - 1); | 1374 i->set_relevance(last_relevance - 1); |
| 1276 last_relevance = i->relevance(); | 1375 last_relevance = i->relevance(); |
| 1277 } | 1376 } |
| 1278 | 1377 |
| 1279 return scored_results; | 1378 return scored_results; |
| 1280 } | 1379 } |
| 1281 | 1380 |
| 1282 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, | 1381 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, |
| 1283 MatchMap* map) { | 1382 MatchMap* map) { |
| 1284 for (size_t i = 0; i < results.size(); ++i) { | 1383 for (size_t i = 0; i < results.size(); ++i) { |
| 1285 const bool is_keyword = results[i].from_keyword_provider(); | 1384 const string16& input = results[i].from_keyword_provider() ? |
| 1286 const string16& input = is_keyword ? keyword_input_.text() : input_.text(); | 1385 keyword_input_.text() : input_.text(); |
| 1287 AddMatchToMap(results[i].suggestion(), input, results[i].relevance(), | 1386 AddMatchToMap(results[i], input, |
| 1288 results[i].relevance_from_server(), | 1387 AutocompleteMatchType::SEARCH_SUGGEST, i, map); |
| 1289 AutocompleteMatchType::SEARCH_SUGGEST, i, is_keyword, map); | |
| 1290 } | 1388 } |
| 1291 } | 1389 } |
| 1292 | 1390 |
| 1293 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { | 1391 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { |
| 1294 // Use the suggested verbatim relevance score if it is non-negative (valid), | 1392 // Use the suggested verbatim relevance score if it is non-negative (valid), |
| 1295 // if inline autocomplete isn't prevented (always show verbatim on backspace), | 1393 // if inline autocomplete isn't prevented (always show verbatim on backspace), |
| 1296 // and if it won't suppress verbatim, leaving no default provider matches. | 1394 // and if it won't suppress verbatim, leaving no default provider matches. |
| 1297 // Otherwise, if the default provider returned no matches and was still able | 1395 // Otherwise, if the default provider returned no matches and was still able |
| 1298 // to suppress verbatim, the user would have no search/nav matches and may be | 1396 // to suppress verbatim, the user would have no search/nav matches and may be |
| 1299 // left unable to search using their default provider from the omnibox. | 1397 // left unable to search using their default provider from the omnibox. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1391 // Don't let scores go below 0. Negative relevance scores are meaningful in | 1489 // Don't let scores go below 0. Negative relevance scores are meaningful in |
| 1392 // a different way. | 1490 // a different way. |
| 1393 int base_score; | 1491 int base_score; |
| 1394 if (is_primary_provider) | 1492 if (is_primary_provider) |
| 1395 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; | 1493 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; |
| 1396 else | 1494 else |
| 1397 base_score = 200; | 1495 base_score = 200; |
| 1398 return std::max(0, base_score - score_discount); | 1496 return std::max(0, base_score - score_discount); |
| 1399 } | 1497 } |
| 1400 | 1498 |
| 1401 void SearchProvider::AddMatchToMap(const string16& query_string, | 1499 void SearchProvider::AddMatchToMap(const SuggestResult& result, |
| 1402 const string16& input_text, | 1500 const string16& input_text, |
| 1403 int relevance, | |
| 1404 bool relevance_from_server, | |
| 1405 AutocompleteMatch::Type type, | 1501 AutocompleteMatch::Type type, |
| 1406 int accepted_suggestion, | 1502 int accepted_suggestion, |
| 1407 bool is_keyword, | |
| 1408 MatchMap* map) { | 1503 MatchMap* map) { |
| 1409 // On non-mobile, ask the instant controller for the appropriate start margin. | 1504 // On non-mobile, ask the instant controller for the appropriate start margin. |
| 1410 // On mobile the start margin is unused, so leave the value as default there. | 1505 // On mobile the start margin is unused, so leave the value as default there. |
| 1411 int omnibox_start_margin = chrome::kDisableStartMargin; | 1506 int omnibox_start_margin = chrome::kDisableStartMargin; |
| 1412 #if !defined(OS_ANDROID) && !defined(IOS) | 1507 #if !defined(OS_ANDROID) && !defined(IOS) |
| 1413 if (chrome::IsInstantExtendedAPIEnabled()) { | 1508 if (chrome::IsInstantExtendedAPIEnabled()) { |
| 1414 Browser* browser = | 1509 Browser* browser = |
| 1415 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); | 1510 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); |
| 1416 if (browser && browser->instant_controller() && | 1511 if (browser && browser->instant_controller() && |
| 1417 browser->instant_controller()->instant()) { | 1512 browser->instant_controller()->instant()) { |
| 1418 omnibox_start_margin = | 1513 omnibox_start_margin = |
| 1419 browser->instant_controller()->instant()->omnibox_bounds().x(); | 1514 browser->instant_controller()->instant()->omnibox_bounds().x(); |
| 1420 } | 1515 } |
| 1421 } | 1516 } |
| 1422 #endif // !defined(OS_ANDROID) && !defined(IOS) | 1517 #endif // !defined(OS_ANDROID) && !defined(IOS) |
| 1423 | 1518 |
| 1424 const TemplateURL* template_url = is_keyword ? | 1519 const TemplateURL* template_url = result.from_keyword_provider() ? |
| 1425 providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL(); | 1520 providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL(); |
| 1426 AutocompleteMatch match = CreateSearchSuggestion(this, relevance, type, | 1521 AutocompleteMatch match = CreateSearchSuggestion(this, result, |
| 1427 template_url, query_string, input_text, input_, is_keyword, | 1522 type, template_url, input_text, input_, accepted_suggestion, |
| 1428 accepted_suggestion, omnibox_start_margin, | 1523 omnibox_start_margin, |
| 1429 !is_keyword || providers_.default_provider().empty()); | 1524 !result.from_keyword_provider() || providers_.default_provider().empty()); |
| 1430 if (!match.destination_url.is_valid()) | 1525 if (!match.destination_url.is_valid()) |
| 1431 return; | 1526 return; |
| 1432 match.RecordAdditionalInfo(kRelevanceFromServerKey, | 1527 match.RecordAdditionalInfo(kRelevanceFromServerKey, |
| 1433 relevance_from_server ? kTrue : kFalse); | 1528 result.relevance_from_server() ? kTrue : kFalse); |
| 1434 | 1529 |
| 1435 // Try to add |match| to |map|. If a match for |query_string| is already in | 1530 // Try to add |match| to |map|. If a match for |query_string| is already in |
| 1436 // |map|, replace it if |match| is more relevant. | 1531 // |map|, replace it if |match| is more relevant. |
| 1437 // NOTE: Keep this ToLower() call in sync with url_database.cc. | 1532 // NOTE: Keep this ToLower() call in sync with url_database.cc. |
| 1438 const std::pair<MatchMap::iterator, bool> i( | 1533 const std::pair<MatchMap::iterator, bool> i(map->insert(std::make_pair( |
| 1439 map->insert(std::make_pair(base::i18n::ToLower(query_string), match))); | 1534 base::i18n::ToLower(result.suggestion()), match))); |
| 1440 // NOTE: We purposefully do a direct relevance comparison here instead of | 1535 // NOTE: We purposefully do a direct relevance comparison here instead of |
| 1441 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added | 1536 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added |
| 1442 // first" rather than "items alphabetically first" when the scores are equal. | 1537 // first" rather than "items alphabetically first" when the scores are equal. |
| 1443 // The only case this matters is when a user has results with the same score | 1538 // The only case this matters is when a user has results with the same score |
| 1444 // that differ only by capitalization; because the history system returns | 1539 // that differ only by capitalization; because the history system returns |
| 1445 // results sorted by recency, this means we'll pick the most recent such | 1540 // results sorted by recency, this means we'll pick the most recent such |
| 1446 // result even if the precision of our relevance score is too low to | 1541 // result even if the precision of our relevance score is too low to |
| 1447 // distinguish the two. | 1542 // distinguish the two. |
| 1448 if (!i.second && (match.relevance > i.first->second.relevance)) | 1543 if (!i.second && (match.relevance > i.first->second.relevance)) |
| 1449 i.first->second = match; | 1544 i.first->second = match; |
| 1450 } | 1545 } |
| 1451 | 1546 |
| 1452 AutocompleteMatch SearchProvider::NavigationToMatch( | 1547 AutocompleteMatch SearchProvider::NavigationToMatch( |
| 1453 const NavigationResult& navigation) { | 1548 const NavigationResult& navigation) { |
| 1454 const string16& input = navigation.from_keyword_provider() ? | 1549 const string16& input = navigation.from_keyword_provider() ? |
| 1455 keyword_input_.text() : input_.text(); | 1550 keyword_input_.text() : input_.text(); |
| 1456 AutocompleteMatch match(this, navigation.relevance(), false, | 1551 AutocompleteMatch match(this, navigation.relevance(), false, |
| 1457 AutocompleteMatchType::NAVSUGGEST); | 1552 AutocompleteMatchType::NAVSUGGEST); |
| 1458 match.destination_url = navigation.url(); | 1553 match.destination_url = navigation.url(); |
| 1459 | 1554 |
| 1460 // First look for the user's input inside the fill_into_edit as it would be | 1555 bool trim_http; |
|
msw
2013/08/26 22:57:15
nit: explicitly init to false.
| |
| 1461 // without trimming the scheme, so we can find matches at the beginning of the | 1556 size_t match_start, inline_autocomplete_offset; |
|
msw
2013/08/26 22:57:15
nit: declare each on separate lines; explicitly in
| |
| 1462 // scheme. | 1557 GetTrimHttpAndOffsets(navigation.formatted_url(), input, &trim_http, |
| 1463 const string16& untrimmed_fill_into_edit = navigation.formatted_url(); | 1558 &match_start, &inline_autocomplete_offset); |
| 1464 const URLPrefix* prefix = | |
| 1465 URLPrefix::BestURLPrefix(untrimmed_fill_into_edit, input); | |
| 1466 size_t match_start = (prefix == NULL) ? | |
| 1467 untrimmed_fill_into_edit.find(input) : prefix->prefix.length(); | |
| 1468 size_t inline_autocomplete_offset = (prefix == NULL) ? | |
| 1469 string16::npos : (match_start + input.length()); | |
| 1470 bool trim_http = !HasHTTPScheme(input) && (!prefix || (match_start != 0)); | |
| 1471 | |
| 1472 // Preserve the forced query '?' prefix in |match.fill_into_edit|. | 1559 // Preserve the forced query '?' prefix in |match.fill_into_edit|. |
| 1473 // Otherwise, user edits to a suggestion would show non-Search results. | 1560 // Otherwise, user edits to a suggestion would show non-Search results. |
| 1474 if (input_.type() == AutocompleteInput::FORCED_QUERY) { | 1561 if (input_.type() == AutocompleteInput::FORCED_QUERY) { |
| 1475 match.fill_into_edit = ASCIIToUTF16("?"); | 1562 match.fill_into_edit = ASCIIToUTF16("?"); |
| 1476 if (inline_autocomplete_offset != string16::npos) | 1563 if (inline_autocomplete_offset != string16::npos) |
| 1477 ++inline_autocomplete_offset; | 1564 ++inline_autocomplete_offset; |
| 1478 } | 1565 } |
| 1479 | 1566 |
| 1480 const std::string languages( | 1567 const std::string languages( |
| 1481 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); | 1568 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
| 1482 const net::FormatUrlTypes format_types = | 1569 const net::FormatUrlTypes format_types = |
| 1483 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | 1570 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); |
| 1484 match.fill_into_edit += | 1571 match.fill_into_edit += |
| 1485 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), | 1572 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), |
| 1486 net::FormatUrl(navigation.url(), languages, format_types, | 1573 net::FormatUrl(navigation.url(), languages, format_types, |
| 1487 net::UnescapeRule::SPACES, NULL, NULL, | 1574 net::UnescapeRule::SPACES, NULL, NULL, |
| 1488 &inline_autocomplete_offset)); | 1575 &inline_autocomplete_offset)); |
| 1489 if (!input_.prevent_inline_autocomplete() && | 1576 if (!input_.prevent_inline_autocomplete() && |
| 1490 (inline_autocomplete_offset != string16::npos)) { | 1577 (inline_autocomplete_offset != string16::npos)) { |
| 1491 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1578 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
| 1492 match.allowed_to_be_default_match = true; | 1579 match.allowed_to_be_default_match = true; |
| 1493 match.inline_autocompletion = | 1580 match.inline_autocompletion = |
| 1494 match.fill_into_edit.substr(inline_autocomplete_offset); | 1581 match.fill_into_edit.substr(inline_autocomplete_offset); |
| 1495 } | 1582 } |
| 1496 | 1583 |
| 1497 match.contents = net::FormatUrl(navigation.url(), languages, | 1584 match.contents = navigation.contents(); |
| 1498 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | 1585 match.contents_class = navigation.contents_class(); |
| 1499 // If the first match in the untrimmed string was inside a scheme that we | |
| 1500 // trimmed, look for a subsequent match. | |
| 1501 if (match_start == string16::npos) | |
| 1502 match_start = match.contents.find(input); | |
| 1503 // Safe if |match_start| is npos; also safe if the input is longer than the | |
| 1504 // remaining contents after |match_start|. | |
| 1505 AutocompleteMatch::ClassifyLocationInString(match_start, input.length(), | |
| 1506 match.contents.length(), ACMatchClassification::URL, | |
| 1507 &match.contents_class); | |
| 1508 | |
| 1509 match.description = navigation.description(); | 1586 match.description = navigation.description(); |
| 1510 AutocompleteMatch::ClassifyMatchInString(input, match.description, | 1587 AutocompleteMatch::ClassifyMatchInString(input, match.description, |
| 1511 ACMatchClassification::NONE, &match.description_class); | 1588 ACMatchClassification::NONE, &match.description_class); |
| 1512 | 1589 |
| 1513 match.RecordAdditionalInfo( | 1590 match.RecordAdditionalInfo( |
| 1514 kRelevanceFromServerKey, | 1591 kRelevanceFromServerKey, |
| 1515 navigation.relevance_from_server() ? kTrue : kFalse); | 1592 navigation.relevance_from_server() ? kTrue : kFalse); |
| 1516 | 1593 |
| 1517 return match; | 1594 return match; |
| 1518 } | 1595 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1556 it->set_relevance(max_query_relevance); | 1633 it->set_relevance(max_query_relevance); |
| 1557 it->set_relevance_from_server(relevance_from_server); | 1634 it->set_relevance_from_server(relevance_from_server); |
| 1558 } | 1635 } |
| 1559 } | 1636 } |
| 1560 | 1637 |
| 1561 void SearchProvider::UpdateDone() { | 1638 void SearchProvider::UpdateDone() { |
| 1562 // We're done when the timer isn't running, there are no suggest queries | 1639 // We're done when the timer isn't running, there are no suggest queries |
| 1563 // pending, and we're not waiting on Instant. | 1640 // pending, and we're not waiting on Instant. |
| 1564 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); | 1641 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
| 1565 } | 1642 } |
| OLD | NEW |