OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/omnibox/autocomplete_match.h" | 5 #include "components/omnibox/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" |
11 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
12 #include "base/strings/string_split.h" | |
12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
14 #include "base/time/time.h" | 15 #include "base/time/time.h" |
15 #include "components/omnibox/autocomplete_provider.h" | 16 #include "components/omnibox/autocomplete_provider.h" |
16 #include "components/omnibox/suggestion_answer.h" | 17 #include "components/omnibox/suggestion_answer.h" |
17 #include "components/search_engines/template_url.h" | 18 #include "components/search_engines/template_url.h" |
18 #include "components/search_engines/template_url_service.h" | 19 #include "components/search_engines/template_url_service.h" |
19 #include "grit/components_scaled_resources.h" | 20 #include "grit/components_scaled_resources.h" |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 bool IsTrivialClassification(const ACMatchClassifications& classifications) { | 24 bool IsTrivialClassification(const ACMatchClassifications& classifications) { |
24 return classifications.empty() || | 25 return classifications.empty() || |
25 ((classifications.size() == 1) && | 26 ((classifications.size() == 1) && |
26 (classifications.back().style == ACMatchClassification::NONE)); | 27 (classifications.back().style == ACMatchClassification::NONE)); |
27 } | 28 } |
28 | 29 |
30 // Returns true if one of the input words includes a scheme and followed by | |
31 // something that matches at the beginning of the URL's hostname. This | |
32 // indicates that the user desires this URL loaded with this scheme in | |
Peter Kasting
2015/06/06 01:31:24
Nit: "This suggests that the user may want this pa
Mark P
2015/06/09 19:29:38
Done.
| |
33 // particular. | |
34 bool InputIncludesSchemePlusPartOfHost( | |
35 const std::vector<base::string16>& input_words, | |
36 const GURL& url) { | |
37 // Find scheme separator and see if the stuff following it matches the | |
38 // beginning of the URL (after the scheme). | |
39 const base::string16& separator_as_utf16 = | |
40 base::UTF8ToUTF16(url::kStandardSchemeSeparator); | |
41 const base::string16& url_spec_without_scheme_as_utf16 = | |
42 base::UTF8ToUTF16(url.spec().substr( | |
43 url.scheme().length() + | |
44 std::string(url::kStandardSchemeSeparator).length())); | |
45 for (auto it : input_words) { | |
46 const size_t pos = it.find(separator_as_utf16); | |
47 if ((pos != base::string16::npos) && (pos > 0) && | |
Peter Kasting
2015/06/06 01:31:23
I'm still thinking about this (pos > 0) check.
I
Mark P
2015/06/06 17:10:11
Your proposal requires explicitly looking at the s
Peter Kasting
2015/06/06 18:38:16
Yes. This should be in sync with the actual schem
Mark P
2015/06/09 19:29:38
Acknowledged.
| |
48 StartsWith(url_spec_without_scheme_as_utf16, | |
49 it.substr(pos + separator_as_utf16.length()), false)) { | |
50 return true; | |
51 } | |
52 } | |
53 return false; | |
54 } | |
55 | |
29 } // namespace | 56 } // namespace |
30 | 57 |
31 // AutocompleteMatch ---------------------------------------------------------- | 58 // AutocompleteMatch ---------------------------------------------------------- |
32 | 59 |
33 // static | 60 // static |
34 const base::char16 AutocompleteMatch::kInvalidChars[] = { | 61 const base::char16 AutocompleteMatch::kInvalidChars[] = { |
35 '\n', '\r', '\t', | 62 '\n', '\r', '\t', |
36 0x2028, // Line separator | 63 0x2028, // Line separator |
37 0x2029, // Paragraph separator | 64 0x2029, // Paragraph separator |
38 0 | 65 0 |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 return NULL; | 390 return NULL; |
364 TemplateURL* template_url = keyword.empty() ? | 391 TemplateURL* template_url = keyword.empty() ? |
365 NULL : template_url_service->GetTemplateURLForKeyword(keyword); | 392 NULL : template_url_service->GetTemplateURLForKeyword(keyword); |
366 return (template_url || host.empty()) ? | 393 return (template_url || host.empty()) ? |
367 template_url : template_url_service->GetTemplateURLForHost(host); | 394 template_url : template_url_service->GetTemplateURLForHost(host); |
368 } | 395 } |
369 | 396 |
370 // static | 397 // static |
371 GURL AutocompleteMatch::GURLToStrippedGURL( | 398 GURL AutocompleteMatch::GURLToStrippedGURL( |
372 const GURL& url, | 399 const GURL& url, |
400 const std::vector<base::string16>& input_words, | |
373 TemplateURLService* template_url_service, | 401 TemplateURLService* template_url_service, |
374 const base::string16& keyword) { | 402 const base::string16& keyword) { |
375 if (!url.is_valid()) | 403 if (!url.is_valid()) |
376 return url; | 404 return url; |
377 | 405 |
378 GURL stripped_destination_url = url; | 406 GURL stripped_destination_url = url; |
379 | 407 |
380 // If the destination URL looks like it was generated from a TemplateURL, | 408 // If the destination URL looks like it was generated from a TemplateURL, |
381 // remove all substitutions other than the search terms. This allows us | 409 // remove all substitutions other than the search terms. This allows us |
382 // to eliminate cases like past search URLs from history that differ only | 410 // to eliminate cases like past search URLs from history that differ only |
(...skipping 25 matching lines...) Expand all Loading... | |
408 | 436 |
409 // Remove the www. prefix from the host. | 437 // Remove the www. prefix from the host. |
410 static const char prefix[] = "www."; | 438 static const char prefix[] = "www."; |
411 static const size_t prefix_len = arraysize(prefix) - 1; | 439 static const size_t prefix_len = arraysize(prefix) - 1; |
412 std::string host = stripped_destination_url.host(); | 440 std::string host = stripped_destination_url.host(); |
413 if (host.compare(0, prefix_len, prefix) == 0) { | 441 if (host.compare(0, prefix_len, prefix) == 0) { |
414 replacements.SetHostStr(base::StringPiece(host).substr(prefix_len)); | 442 replacements.SetHostStr(base::StringPiece(host).substr(prefix_len)); |
415 needs_replacement = true; | 443 needs_replacement = true; |
416 } | 444 } |
417 | 445 |
418 // Replace https protocol with http protocol. | 446 // Possibly replace https protocol with http protocol. |
Peter Kasting
2015/06/06 01:31:23
Nit: "Replace https protocol with http, as long as
Mark P
2015/06/09 19:29:38
Done.
| |
419 if (stripped_destination_url.SchemeIs(url::kHttpsScheme)) { | 447 if (!InputIncludesSchemePlusPartOfHost(input_words, url) && |
448 stripped_destination_url.SchemeIs(url::kHttpsScheme)) { | |
420 replacements.SetScheme(url::kHttpScheme, | 449 replacements.SetScheme(url::kHttpScheme, |
421 url::Component(0, strlen(url::kHttpScheme))); | 450 url::Component(0, strlen(url::kHttpScheme))); |
422 needs_replacement = true; | 451 needs_replacement = true; |
423 } | 452 } |
424 | 453 |
425 if (needs_replacement) | 454 if (needs_replacement) |
426 stripped_destination_url = stripped_destination_url.ReplaceComponents( | 455 stripped_destination_url = stripped_destination_url.ReplaceComponents( |
427 replacements); | 456 replacements); |
428 return stripped_destination_url; | 457 return stripped_destination_url; |
429 } | 458 } |
430 | 459 |
431 void AutocompleteMatch::ComputeStrippedDestinationURL( | 460 void AutocompleteMatch::ComputeStrippedDestinationURL( |
461 const std::vector<base::string16>& input_words, | |
432 TemplateURLService* template_url_service) { | 462 TemplateURLService* template_url_service) { |
433 stripped_destination_url = | 463 stripped_destination_url = GURLToStrippedGURL( |
434 GURLToStrippedGURL(destination_url, template_url_service, keyword); | 464 destination_url, input_words, template_url_service, keyword); |
435 } | 465 } |
436 | 466 |
437 void AutocompleteMatch::EnsureUWYTIsAllowedToBeDefault( | 467 void AutocompleteMatch::EnsureUWYTIsAllowedToBeDefault( |
438 const GURL& canonical_input_url, | 468 const GURL& canonical_input_url, |
469 const std::vector<base::string16>& input_words, | |
439 TemplateURLService* template_url_service) { | 470 TemplateURLService* template_url_service) { |
440 if (!allowed_to_be_default_match) { | 471 if (!allowed_to_be_default_match) { |
441 const GURL& stripped_canonical_input_url = | 472 const GURL& stripped_canonical_input_url = |
442 AutocompleteMatch::GURLToStrippedGURL( | 473 AutocompleteMatch::GURLToStrippedGURL( |
443 canonical_input_url, template_url_service, base::string16()); | 474 canonical_input_url, input_words, |
444 ComputeStrippedDestinationURL(template_url_service); | 475 template_url_service, base::string16()); |
476 ComputeStrippedDestinationURL(input_words, template_url_service); | |
445 allowed_to_be_default_match = | 477 allowed_to_be_default_match = |
446 stripped_canonical_input_url == stripped_destination_url; | 478 stripped_canonical_input_url == stripped_destination_url; |
447 } | 479 } |
448 } | 480 } |
449 | 481 |
482 void AutocompleteMatch::EnsureUWYTIsAllowedToBeDefault( | |
483 const AutocompleteInput& input, | |
484 TemplateURLService* template_url_service) { | |
485 std::vector<base::string16> words; | |
486 base::SplitString(input.text(), ' ', &words); | |
487 EnsureUWYTIsAllowedToBeDefault( | |
488 input.canonicalized_url(), words, template_url_service); | |
489 } | |
490 | |
450 void AutocompleteMatch::GetKeywordUIState( | 491 void AutocompleteMatch::GetKeywordUIState( |
451 TemplateURLService* template_url_service, | 492 TemplateURLService* template_url_service, |
452 base::string16* keyword, | 493 base::string16* keyword, |
453 bool* is_keyword_hint) const { | 494 bool* is_keyword_hint) const { |
454 *is_keyword_hint = associated_keyword.get() != NULL; | 495 *is_keyword_hint = associated_keyword.get() != NULL; |
455 keyword->assign(*is_keyword_hint ? associated_keyword->keyword : | 496 keyword->assign(*is_keyword_hint ? associated_keyword->keyword : |
456 GetSubstitutingExplicitlyInvokedKeyword(template_url_service)); | 497 GetSubstitutingExplicitlyInvokedKeyword(template_url_service)); |
457 } | 498 } |
458 | 499 |
459 base::string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword( | 500 base::string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword( |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 << " is unsorted in relation to last offset of " << last_offset | 598 << " is unsorted in relation to last offset of " << last_offset |
558 << ". Provider: " << provider_name << "."; | 599 << ". Provider: " << provider_name << "."; |
559 DCHECK_LT(i->offset, text.length()) | 600 DCHECK_LT(i->offset, text.length()) |
560 << " Classification of [" << i->offset << "," << text.length() | 601 << " Classification of [" << i->offset << "," << text.length() |
561 << "] is out of bounds for \"" << text << "\". Provider: " | 602 << "] is out of bounds for \"" << text << "\". Provider: " |
562 << provider_name << "."; | 603 << provider_name << "."; |
563 last_offset = i->offset; | 604 last_offset = i->offset; |
564 } | 605 } |
565 } | 606 } |
566 #endif | 607 #endif |
OLD | NEW |