| 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/autocomplete_match.h" | 5 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 6 | 6 |
| 7 #include "base/i18n/time_formatting.h" | 7 #include "base/i18n/time_formatting.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/strings/string16.h" | 9 #include "base/strings/string16.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1, | 189 bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1, |
| 190 const AutocompleteMatch& elem2) { | 190 const AutocompleteMatch& elem2) { |
| 191 if (elem1.stripped_destination_url.is_empty() && | 191 if (elem1.stripped_destination_url.is_empty() && |
| 192 elem2.stripped_destination_url.is_empty()) | 192 elem2.stripped_destination_url.is_empty()) |
| 193 return false; | 193 return false; |
| 194 return elem1.stripped_destination_url == elem2.stripped_destination_url; | 194 return elem1.stripped_destination_url == elem2.stripped_destination_url; |
| 195 } | 195 } |
| 196 | 196 |
| 197 // static | 197 // static |
| 198 void AutocompleteMatch::ClassifyMatchInString( | 198 void AutocompleteMatch::ClassifyMatchInString( |
| 199 const string16& find_text, | 199 const base::string16& find_text, |
| 200 const string16& text, | 200 const base::string16& text, |
| 201 int style, | 201 int style, |
| 202 ACMatchClassifications* classification) { | 202 ACMatchClassifications* classification) { |
| 203 ClassifyLocationInString(text.find(find_text), find_text.length(), | 203 ClassifyLocationInString(text.find(find_text), find_text.length(), |
| 204 text.length(), style, classification); | 204 text.length(), style, classification); |
| 205 } | 205 } |
| 206 | 206 |
| 207 // static | 207 // static |
| 208 void AutocompleteMatch::ClassifyLocationInString( | 208 void AutocompleteMatch::ClassifyLocationInString( |
| 209 size_t match_location, | 209 size_t match_location, |
| 210 size_t match_length, | 210 size_t match_length, |
| 211 size_t overall_length, | 211 size_t overall_length, |
| 212 int style, | 212 int style, |
| 213 ACMatchClassifications* classification) { | 213 ACMatchClassifications* classification) { |
| 214 classification->clear(); | 214 classification->clear(); |
| 215 | 215 |
| 216 // Don't classify anything about an empty string | 216 // Don't classify anything about an empty string |
| 217 // (AutocompleteMatch::Validate() checks this). | 217 // (AutocompleteMatch::Validate() checks this). |
| 218 if (overall_length == 0) | 218 if (overall_length == 0) |
| 219 return; | 219 return; |
| 220 | 220 |
| 221 // Mark pre-match portion of string (if any). | 221 // Mark pre-match portion of string (if any). |
| 222 if (match_location != 0) { | 222 if (match_location != 0) { |
| 223 classification->push_back(ACMatchClassification(0, style)); | 223 classification->push_back(ACMatchClassification(0, style)); |
| 224 } | 224 } |
| 225 | 225 |
| 226 // Mark matching portion of string. | 226 // Mark matching portion of string. |
| 227 if (match_location == string16::npos) { | 227 if (match_location == base::string16::npos) { |
| 228 // No match, above classification will suffice for whole string. | 228 // No match, above classification will suffice for whole string. |
| 229 return; | 229 return; |
| 230 } | 230 } |
| 231 // Classifying an empty match makes no sense and will lead to validation | 231 // Classifying an empty match makes no sense and will lead to validation |
| 232 // errors later. | 232 // errors later. |
| 233 DCHECK_GT(match_length, 0U); | 233 DCHECK_GT(match_length, 0U); |
| 234 classification->push_back(ACMatchClassification(match_location, | 234 classification->push_back(ACMatchClassification(match_location, |
| 235 (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM)); | 235 (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM)); |
| 236 | 236 |
| 237 // Mark post-match portion of string (if any). | 237 // Mark post-match portion of string (if any). |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 int style) { | 313 int style) { |
| 314 DCHECK(classifications); | 314 DCHECK(classifications); |
| 315 if (classifications->empty() || classifications->back().style != style) { | 315 if (classifications->empty() || classifications->back().style != style) { |
| 316 DCHECK(classifications->empty() || | 316 DCHECK(classifications->empty() || |
| 317 (offset > classifications->back().offset)); | 317 (offset > classifications->back().offset)); |
| 318 classifications->push_back(ACMatchClassification(offset, style)); | 318 classifications->push_back(ACMatchClassification(offset, style)); |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 | 321 |
| 322 // static | 322 // static |
| 323 string16 AutocompleteMatch::SanitizeString(const string16& text) { | 323 base::string16 AutocompleteMatch::SanitizeString(const base::string16& text) { |
| 324 // NOTE: This logic is mirrored by |sanitizeString()| in | 324 // NOTE: This logic is mirrored by |sanitizeString()| in |
| 325 // omnibox_custom_bindings.js. | 325 // omnibox_custom_bindings.js. |
| 326 string16 result; | 326 base::string16 result; |
| 327 TrimWhitespace(text, TRIM_LEADING, &result); | 327 TrimWhitespace(text, TRIM_LEADING, &result); |
| 328 base::RemoveChars(result, kInvalidChars, &result); | 328 base::RemoveChars(result, kInvalidChars, &result); |
| 329 return result; | 329 return result; |
| 330 } | 330 } |
| 331 | 331 |
| 332 // static | 332 // static |
| 333 bool AutocompleteMatch::IsSearchType(Type type) { | 333 bool AutocompleteMatch::IsSearchType(Type type) { |
| 334 return type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED || | 334 return type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED || |
| 335 type == AutocompleteMatchType::SEARCH_HISTORY || | 335 type == AutocompleteMatchType::SEARCH_HISTORY || |
| 336 type == AutocompleteMatchType::SEARCH_SUGGEST || | 336 type == AutocompleteMatchType::SEARCH_SUGGEST || |
| 337 type == AutocompleteMatchType::SEARCH_OTHER_ENGINE; | 337 type == AutocompleteMatchType::SEARCH_OTHER_ENGINE; |
| 338 } | 338 } |
| 339 | 339 |
| 340 void AutocompleteMatch::ComputeStrippedDestinationURL(Profile* profile) { | 340 void AutocompleteMatch::ComputeStrippedDestinationURL(Profile* profile) { |
| 341 stripped_destination_url = destination_url; | 341 stripped_destination_url = destination_url; |
| 342 if (!stripped_destination_url.is_valid()) | 342 if (!stripped_destination_url.is_valid()) |
| 343 return; | 343 return; |
| 344 | 344 |
| 345 // If the destination URL looks like it was generated from a TemplateURL, | 345 // If the destination URL looks like it was generated from a TemplateURL, |
| 346 // remove all substitutions other than the search terms. This allows us | 346 // remove all substitutions other than the search terms. This allows us |
| 347 // to eliminate cases like past search URLs from history that differ only | 347 // to eliminate cases like past search URLs from history that differ only |
| 348 // by some obscure query param from each other or from the search/keyword | 348 // by some obscure query param from each other or from the search/keyword |
| 349 // provider matches. | 349 // provider matches. |
| 350 TemplateURL* template_url = GetTemplateURL(profile, true); | 350 TemplateURL* template_url = GetTemplateURL(profile, true); |
| 351 if (template_url != NULL && template_url->SupportsReplacement()) { | 351 if (template_url != NULL && template_url->SupportsReplacement()) { |
| 352 string16 search_terms; | 352 base::string16 search_terms; |
| 353 if (template_url->ExtractSearchTermsFromURL(stripped_destination_url, | 353 if (template_url->ExtractSearchTermsFromURL(stripped_destination_url, |
| 354 &search_terms)) { | 354 &search_terms)) { |
| 355 stripped_destination_url = | 355 stripped_destination_url = |
| 356 GURL(template_url->url_ref().ReplaceSearchTerms( | 356 GURL(template_url->url_ref().ReplaceSearchTerms( |
| 357 TemplateURLRef::SearchTermsArgs(search_terms))); | 357 TemplateURLRef::SearchTermsArgs(search_terms))); |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 // |replacements| keeps all the substitions we're going to make to | 361 // |replacements| keeps all the substitions we're going to make to |
| 362 // from {destination_url} to {stripped_destination_url}. |need_replacement| | 362 // from {destination_url} to {stripped_destination_url}. |need_replacement| |
| (...skipping 19 matching lines...) Expand all Loading... |
| 382 url_parse::Component(0, strlen(content::kHttpScheme))); | 382 url_parse::Component(0, strlen(content::kHttpScheme))); |
| 383 needs_replacement = true; | 383 needs_replacement = true; |
| 384 } | 384 } |
| 385 | 385 |
| 386 if (needs_replacement) | 386 if (needs_replacement) |
| 387 stripped_destination_url = stripped_destination_url.ReplaceComponents( | 387 stripped_destination_url = stripped_destination_url.ReplaceComponents( |
| 388 replacements); | 388 replacements); |
| 389 } | 389 } |
| 390 | 390 |
| 391 void AutocompleteMatch::GetKeywordUIState(Profile* profile, | 391 void AutocompleteMatch::GetKeywordUIState(Profile* profile, |
| 392 string16* keyword, | 392 base::string16* keyword, |
| 393 bool* is_keyword_hint) const { | 393 bool* is_keyword_hint) const { |
| 394 *is_keyword_hint = associated_keyword.get() != NULL; | 394 *is_keyword_hint = associated_keyword.get() != NULL; |
| 395 keyword->assign(*is_keyword_hint ? associated_keyword->keyword : | 395 keyword->assign(*is_keyword_hint ? associated_keyword->keyword : |
| 396 GetSubstitutingExplicitlyInvokedKeyword(profile)); | 396 GetSubstitutingExplicitlyInvokedKeyword(profile)); |
| 397 } | 397 } |
| 398 | 398 |
| 399 string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword( | 399 base::string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword( |
| 400 Profile* profile) const { | 400 Profile* profile) const { |
| 401 if (transition != content::PAGE_TRANSITION_KEYWORD) | 401 if (transition != content::PAGE_TRANSITION_KEYWORD) |
| 402 return string16(); | 402 return base::string16(); |
| 403 const TemplateURL* t_url = GetTemplateURL(profile, false); | 403 const TemplateURL* t_url = GetTemplateURL(profile, false); |
| 404 return (t_url && t_url->SupportsReplacement()) ? keyword : string16(); | 404 return (t_url && t_url->SupportsReplacement()) ? keyword : base::string16(); |
| 405 } | 405 } |
| 406 | 406 |
| 407 TemplateURL* AutocompleteMatch::GetTemplateURL( | 407 TemplateURL* AutocompleteMatch::GetTemplateURL( |
| 408 Profile* profile, bool allow_fallback_to_destination_host) const { | 408 Profile* profile, bool allow_fallback_to_destination_host) const { |
| 409 DCHECK(profile); | 409 DCHECK(profile); |
| 410 TemplateURLService* template_url_service = | 410 TemplateURLService* template_url_service = |
| 411 TemplateURLServiceFactory::GetForProfile(profile); | 411 TemplateURLServiceFactory::GetForProfile(profile); |
| 412 if (template_url_service == NULL) | 412 if (template_url_service == NULL) |
| 413 return NULL; | 413 return NULL; |
| 414 TemplateURL* template_url = keyword.empty() ? NULL : | 414 TemplateURL* template_url = keyword.empty() ? NULL : |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 is_keyword_verbatim_match; | 454 is_keyword_verbatim_match; |
| 455 } | 455 } |
| 456 | 456 |
| 457 #ifndef NDEBUG | 457 #ifndef NDEBUG |
| 458 void AutocompleteMatch::Validate() const { | 458 void AutocompleteMatch::Validate() const { |
| 459 ValidateClassifications(contents, contents_class); | 459 ValidateClassifications(contents, contents_class); |
| 460 ValidateClassifications(description, description_class); | 460 ValidateClassifications(description, description_class); |
| 461 } | 461 } |
| 462 | 462 |
| 463 void AutocompleteMatch::ValidateClassifications( | 463 void AutocompleteMatch::ValidateClassifications( |
| 464 const string16& text, | 464 const base::string16& text, |
| 465 const ACMatchClassifications& classifications) const { | 465 const ACMatchClassifications& classifications) const { |
| 466 if (text.empty()) { | 466 if (text.empty()) { |
| 467 DCHECK(classifications.empty()); | 467 DCHECK(classifications.empty()); |
| 468 return; | 468 return; |
| 469 } | 469 } |
| 470 | 470 |
| 471 // The classifications should always cover the whole string. | 471 // The classifications should always cover the whole string. |
| 472 DCHECK(!classifications.empty()) << "No classification for \"" << text << '"'; | 472 DCHECK(!classifications.empty()) << "No classification for \"" << text << '"'; |
| 473 DCHECK_EQ(0U, classifications[0].offset) | 473 DCHECK_EQ(0U, classifications[0].offset) |
| 474 << "Classification misses beginning for \"" << text << '"'; | 474 << "Classification misses beginning for \"" << text << '"'; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 485 << " is unsorted in relation to last offset of " << last_offset | 485 << " is unsorted in relation to last offset of " << last_offset |
| 486 << ". Provider: " << provider_name << "."; | 486 << ". Provider: " << provider_name << "."; |
| 487 DCHECK_LT(i->offset, text.length()) | 487 DCHECK_LT(i->offset, text.length()) |
| 488 << " Classification of [" << i->offset << "," << text.length() | 488 << " Classification of [" << i->offset << "," << text.length() |
| 489 << "] is out of bounds for \"" << text << "\". Provider: " | 489 << "] is out of bounds for \"" << text << "\". Provider: " |
| 490 << provider_name << "."; | 490 << provider_name << "."; |
| 491 last_offset = i->offset; | 491 last_offset = i->offset; |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 #endif | 494 #endif |
| OLD | NEW |