autocomplete_match.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/time_formatting.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_provider.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_service.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "grit/components_scaled_resources.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsTrivialClassification(const ACMatchClassifications& classifications) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return classifications.empty() ||
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((classifications.size() == 1) &&
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (classifications.back().style == ACMatchClassification::NONE));
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AutocompleteMatch ----------------------------------------------------------
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const base::char16 AutocompleteMatch::kInvalidChars[] = {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  '\n', '\r', '\t',
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2028,  // Line separator
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2029,  // Paragraph separator
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch::AutocompleteMatch()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : provider(NULL),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      relevance(0),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typed_count(-1),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deletable(false),
44c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      allowed_to_be_default_match(false),
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      transition(ui::PAGE_TRANSITION_GENERATED),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_history_what_you_typed_match(false),
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      type(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      from_previous(false) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     int relevance,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     bool deletable,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     Type type)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : provider(provider),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      relevance(relevance),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typed_count(-1),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deletable(deletable),
59c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      allowed_to_be_default_match(false),
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      transition(ui::PAGE_TRANSITION_TYPED),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_history_what_you_typed_match(false),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type(type),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      from_previous(false) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch::AutocompleteMatch(const AutocompleteMatch& match)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : provider(match.provider),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      relevance(match.relevance),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typed_count(match.typed_count),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deletable(match.deletable),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fill_into_edit(match.fill_into_edit),
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      inline_autocompletion(match.inline_autocompletion),
73c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      allowed_to_be_default_match(match.allowed_to_be_default_match),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      destination_url(match.destination_url),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stripped_destination_url(match.stripped_destination_url),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contents(match.contents),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      contents_class(match.contents_class),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      description(match.description),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      description_class(match.description_class),
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      answer_contents(match.answer_contents),
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      answer_type(match.answer_type),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transition(match.transition),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_history_what_you_typed_match(match.is_history_what_you_typed_match),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type(match.type),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      associated_keyword(match.associated_keyword.get() ?
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new AutocompleteMatch(*match.associated_keyword) : NULL),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword(match.keyword),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      from_previous(match.from_previous),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      search_terms_args(match.search_terms_args.get() ?
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) :
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL),
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      additional_info(match.additional_info),
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      duplicate_matches(match.duplicate_matches) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch::~AutocompleteMatch() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch& AutocompleteMatch::operator=(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const AutocompleteMatch& match) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &match)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider = match.provider;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  relevance = match.relevance;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typed_count = match.typed_count;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deletable = match.deletable;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fill_into_edit = match.fill_into_edit;
109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  inline_autocompletion = match.inline_autocompletion;
110c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  allowed_to_be_default_match = match.allowed_to_be_default_match;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  destination_url = match.destination_url;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stripped_destination_url = match.stripped_destination_url;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents = match.contents;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents_class = match.contents_class;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  description = match.description;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  description_class = match.description_class;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  answer_contents = match.answer_contents;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  answer_type = match.answer_type;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transition = match.transition;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_history_what_you_typed_match = match.is_history_what_you_typed_match;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type = match.type;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  associated_keyword.reset(match.associated_keyword.get() ?
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new AutocompleteMatch(*match.associated_keyword) : NULL);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keyword = match.keyword;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  from_previous = match.from_previous;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  search_terms_args.reset(match.search_terms_args.get() ?
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : NULL);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  additional_info = match.additional_info;
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  duplicate_matches = match.duplicate_matches;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AutocompleteMatch::TypeToIcon(Type type) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int icons[] = {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_EXTENSION_APP,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IDR_OMNIBOX_HTTP,
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    IDR_OMNIBOX_HTTP,
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IDR_OMNIBOX_SEARCH,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  COMPILE_ASSERT(arraysize(icons) == AutocompleteMatchType::NUM_TYPES,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 icons_array_must_match_type_enum);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return icons[type];
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const AutocompleteMatch& elem2) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For equal-relevance matches, we sort alphabetically, so that providers
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // who return multiple elements at the same priority get a "stable" sort
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // across multiple updates.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (elem1.relevance == elem2.relevance) ?
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (elem1.contents < elem2.contents) : (elem1.relevance > elem2.relevance);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const AutocompleteMatch& elem2) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elem1.stripped_destination_url.is_empty() &&
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elem2.stripped_destination_url.is_empty())
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return elem1.stripped_destination_url == elem2.stripped_destination_url;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::ClassifyMatchInString(
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& find_text,
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& text,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int style,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACMatchClassifications* classification) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassifyLocationInString(text.find(find_text), find_text.length(),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           text.length(), style, classification);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::ClassifyLocationInString(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t match_location,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t match_length,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t overall_length,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int style,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACMatchClassifications* classification) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  classification->clear();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't classify anything about an empty string
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (AutocompleteMatch::Validate() checks this).
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (overall_length == 0)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark pre-match portion of string (if any).
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_location != 0) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classification->push_back(ACMatchClassification(0, style));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark matching portion of string.
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (match_location == base::string16::npos) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No match, above classification will suffice for whole string.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Classifying an empty match makes no sense and will lead to validation
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // errors later.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(match_length, 0U);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  classification->push_back(ACMatchClassification(match_location,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark post-match portion of string (if any).
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t after_match(match_location + match_length);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (after_match < overall_length) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classification->push_back(ACMatchClassification(after_match, style));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch::ACMatchClassifications
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteMatch::MergeClassifications(
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatchClassifications& classifications1,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatchClassifications& classifications2) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We must return the empty vector only if both inputs are truly empty.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The result of merging an empty vector with a single (0, NONE)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // classification is the latter one-entry vector.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsTrivialClassification(classifications1))
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return classifications2.empty() ? classifications1 : classifications2;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsTrivialClassification(classifications2))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return classifications1;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ACMatchClassifications output;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ACMatchClassifications::const_iterator i = classifications1.begin(),
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       j = classifications2.begin(); i != classifications1.end();) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteMatch::AddLastClassificationIfNecessary(&output,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::max(i->offset, j->offset), i->style | j->style);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t next_i_offset = (i + 1) == classifications1.end() ?
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<size_t>(-1) : (i + 1)->offset;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t next_j_offset = (j + 1) == classifications2.end() ?
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<size_t>(-1) : (j + 1)->offset;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_i_offset >= next_j_offset)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++j;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_j_offset >= next_i_offset)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string AutocompleteMatch::ClassificationsToString(
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatchClassifications& classifications) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string serialized_classifications;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < classifications.size(); ++i) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      serialized_classifications += ',';
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    serialized_classifications += base::IntToString(classifications[i].offset) +
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ',' + base::IntToString(classifications[i].style);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return serialized_classifications;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACMatchClassifications AutocompleteMatch::ClassificationsFromString(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& serialized_classifications) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ACMatchClassifications classifications;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> tokens;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tokenize(serialized_classifications, ",", &tokens);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!(tokens.size() & 1));  // The number of tokens should be even.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < tokens.size(); i += 2) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int classification_offset = 0;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int classification_style = ACMatchClassification::NONE;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::StringToInt(tokens[i], &classification_offset) ||
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !base::StringToInt(tokens[i + 1], &classification_style)) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return classifications;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classifications.push_back(ACMatchClassification(classification_offset,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    classification_style));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return classifications;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::AddLastClassificationIfNecessary(
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACMatchClassifications* classifications,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t offset,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int style) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(classifications);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (classifications->empty() || classifications->back().style != style) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(classifications->empty() ||
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (offset > classifications->back().offset));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classifications->push_back(ACMatchClassification(offset, style));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 AutocompleteMatch::SanitizeString(const base::string16& text) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: This logic is mirrored by |sanitizeString()| in
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // omnibox_custom_bindings.js.
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 result;
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TrimWhitespace(text, base::TRIM_LEADING, &result);
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RemoveChars(result, kInvalidChars, &result);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AutocompleteMatch::IsSearchType(Type type) {
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED ||
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         type == AutocompleteMatchType::SEARCH_HISTORY ||
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         type == AutocompleteMatchType::SEARCH_SUGGEST ||
320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         type == AutocompleteMatchType::SEARCH_OTHER_ENGINE ||
321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         IsSpecializedSearchType(type);
322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool AutocompleteMatch::IsSpecializedSearchType(Type type) {
326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return type == AutocompleteMatchType::SEARCH_SUGGEST_ENTITY ||
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         type == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE ||
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         type == AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED ||
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         type == AutocompleteMatchType::SEARCH_SUGGEST_PROFILE ||
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         type == AutocompleteMatchType::SEARCH_SUGGEST_ANSWER;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
334116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTemplateURL* AutocompleteMatch::GetTemplateURLWithKeyword(
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service,
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::string16& keyword,
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::string& host) {
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (template_url_service == NULL)
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TemplateURL* template_url = keyword.empty() ?
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NULL : template_url_service->GetTemplateURLForKeyword(keyword);
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return (template_url || host.empty()) ?
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      template_url : template_url_service->GetTemplateURLForHost(host);
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
347116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGURL AutocompleteMatch::GURLToStrippedGURL(
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& url,
349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service,
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::string16& keyword) {
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!url.is_valid())
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return url;
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL stripped_destination_url = url;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the destination URL looks like it was generated from a TemplateURL,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remove all substitutions other than the search terms.  This allows us
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to eliminate cases like past search URLs from history that differ only
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by some obscure query param from each other or from the search/keyword
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provider matches.
361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TemplateURL* template_url = GetTemplateURLWithKeyword(
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      template_url_service, keyword, stripped_destination_url.host());
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (template_url != NULL &&
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      template_url->SupportsReplacement(
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          template_url_service->search_terms_data())) {
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 search_terms;
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (template_url->ExtractSearchTermsFromURL(
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        stripped_destination_url,
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        template_url_service->search_terms_data(),
370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        &search_terms)) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stripped_destination_url =
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GURL(template_url->url_ref().ReplaceSearchTerms(
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              TemplateURLRef::SearchTermsArgs(search_terms),
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              template_url_service->search_terms_data()));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |replacements| keeps all the substitions we're going to make to
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from {destination_url} to {stripped_destination_url}.  |need_replacement|
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a helper variable that helps us keep track of whether we need
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to apply the replacement.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool needs_replacement = false;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the www. prefix from the host.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char prefix[] = "www.";
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t prefix_len = arraysize(prefix) - 1;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host = stripped_destination_url.host();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host.compare(0, prefix_len, prefix) == 0) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = host.substr(prefix_len);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    replacements.SetHostStr(host);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    needs_replacement = true;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace https protocol with http protocol.
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (stripped_destination_url.SchemeIs(url::kHttpsScheme)) {
397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    replacements.SetScheme(url::kHttpScheme,
398010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           url::Component(0, strlen(url::kHttpScheme)));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    needs_replacement = true;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (needs_replacement)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stripped_destination_url = stripped_destination_url.ReplaceComponents(
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        replacements);
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return stripped_destination_url;
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
408116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AutocompleteMatch::ComputeStrippedDestinationURL(
409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service) {
410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  stripped_destination_url =
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GURLToStrippedGURL(destination_url, template_url_service, keyword);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AutocompleteMatch::EnsureUWYTIsAllowedToBeDefault(
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& canonical_input_url,
416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service) {
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!allowed_to_be_default_match) {
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& stripped_canonical_input_url =
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        AutocompleteMatch::GURLToStrippedGURL(
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            canonical_input_url, template_url_service, base::string16());
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ComputeStrippedDestinationURL(template_url_service);
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    allowed_to_be_default_match =
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        stripped_canonical_input_url == stripped_destination_url;
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AutocompleteMatch::GetKeywordUIState(
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service,
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::string16* keyword,
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool* is_keyword_hint) const {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_keyword_hint = associated_keyword.get() != NULL;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keyword->assign(*is_keyword_hint ? associated_keyword->keyword :
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetSubstitutingExplicitlyInvokedKeyword(template_url_service));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 AutocompleteMatch::GetSubstitutingExplicitlyInvokedKeyword(
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service) const {
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (transition != ui::PAGE_TRANSITION_KEYWORD ||
439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      template_url_service == NULL) {
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const TemplateURL* t_url = GetTemplateURL(template_url_service, false);
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (t_url &&
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          t_url->SupportsReplacement(
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              template_url_service->search_terms_data())) ?
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      keyword : base::string16();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* AutocompleteMatch::GetTemplateURL(
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    TemplateURLService* template_url_service,
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool allow_fallback_to_destination_host) const {
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return GetTemplateURLWithKeyword(
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      template_url_service, keyword,
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      allow_fallback_to_destination_host ?
456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          destination_url.host() : std::string());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const std::string& value) {
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!property.empty());
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!value.empty());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  additional_info[property] = value;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int value) {
468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RecordAdditionalInfo(property, base::IntToString(value));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::Time& value) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordAdditionalInfo(property,
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       base::UTF16ToUTF8(
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           base::TimeFormatShortDateAndTime(value)));
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string AutocompleteMatch::GetAdditionalInfo(
479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& property) const {
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AdditionalInfo::const_iterator i(additional_info.find(property));
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return (i == additional_info.end()) ? std::string() : i->second;
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool AutocompleteMatch::IsVerbatimType() const {
4852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const bool is_keyword_verbatim_match =
4862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      (type == AutocompleteMatchType::SEARCH_OTHER_ENGINE &&
4872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       provider != NULL &&
4882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       provider->type() == AutocompleteProvider::TYPE_SEARCH);
4892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED ||
4902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      type == AutocompleteMatchType::URL_WHAT_YOU_TYPED ||
4912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      is_keyword_verbatim_match;
4922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
4932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AutocompleteMatch::SupportsDeletion() const {
495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (deletable)
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (ACMatches::const_iterator it(duplicate_matches.begin());
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != duplicate_matches.end(); ++it) {
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (it->deletable)
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return true;
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return false;
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::Validate() const {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateClassifications(contents, contents_class);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ValidateClassifications(description, description_class);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AutocompleteMatch::ValidateClassifications(
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& text,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ACMatchClassifications& classifications) const {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text.empty()) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(classifications.empty());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The classifications should always cover the whole string.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!classifications.empty()) << "No classification for \"" << text << '"';
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0U, classifications[0].offset)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Classification misses beginning for \"" << text << '"';
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (classifications.size() == 1)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The classifications should always be sorted.
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t last_offset = classifications[0].offset;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ACMatchClassifications::const_iterator i(classifications.begin() + 1);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != classifications.end(); ++i) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* provider_name = provider ? provider->GetName() : "None";
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GT(i->offset, last_offset)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << " Classification for \"" << text << "\" with offset of " << i->offset
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << " is unsorted in relation to last offset of " << last_offset
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << ". Provider: " << provider_name << ".";
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(i->offset, text.length())
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << " Classification of [" << i->offset << "," << text.length()
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "] is out of bounds for \"" << text << "\". Provider: "
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << provider_name << ".";
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_offset = i->offset;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
544