1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file.
4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h"
6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "grit/theme_resources.h"
8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// AutocompleteMatch ----------------------------------------------------------
10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
11513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::AutocompleteMatch()
12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : provider(NULL),
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      relevance(0),
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      deletable(false),
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      inline_autocomplete_offset(string16::npos),
16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      transition(PageTransition::GENERATED),
17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      is_history_what_you_typed_match(false),
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      type(SEARCH_WHAT_YOU_TYPED),
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      template_url(NULL),
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      starred(false),
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      from_previous(false) {
22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
24513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                     int relevance,
26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                     bool deletable,
27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                     Type type)
28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : provider(provider),
29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      relevance(relevance),
30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      deletable(deletable),
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      inline_autocomplete_offset(string16::npos),
32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      transition(PageTransition::TYPED),
33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      is_history_what_you_typed_match(false),
34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      type(type),
35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      template_url(NULL),
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      starred(false),
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      from_previous(false) {
38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
40513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::~AutocompleteMatch() {
41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
44513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstd::string AutocompleteMatch::TypeToString(Type type) {
45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* strings[NUM_TYPES] = {
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "url-what-you-typed",
47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "history-url",
48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "history-title",
49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "history-body",
50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "history-keyword",
51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "navsuggest",
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "search-what-you-typed",
53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "search-history",
54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "search-suggest",
55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "search-other-engine",
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "extension-app",
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(arraysize(strings) == NUM_TYPES);
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return strings[type];
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint AutocompleteMatch::TypeToIcon(Type type) {
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int icons[NUM_TYPES] = {
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HTTP,
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HTTP,
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HISTORY,
68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HISTORY,
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HISTORY,
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_HTTP,
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_SEARCH,
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_SEARCH,
73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_SEARCH,
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    IDR_OMNIBOX_SEARCH,
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    IDR_OMNIBOX_EXTENSION_APP,
76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(arraysize(icons) == NUM_TYPES);
78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return icons[type];
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1,
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                     const AutocompleteMatch& elem2) {
84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // For equal-relevance matches, we sort alphabetically, so that providers
85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // who return multiple elements at the same priority get a "stable" sort
86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // across multiple updates.
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (elem1.relevance == elem2.relevance)
88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return elem1.contents > elem2.contents;
89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return elem1.relevance > elem2.relevance;
91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
94513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::DestinationSortFunc(const AutocompleteMatch& elem1,
95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                            const AutocompleteMatch& elem2) {
96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Sort identical destination_urls together.  Place the most relevant matches
97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // first, so that when we call std::unique(), these are the ones that get
98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // preserved.
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return (elem1.destination_url != elem2.destination_url) ?
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      (elem1.destination_url < elem2.destination_url) :
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      MoreRelevant(elem1, elem2);
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1,
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                          const AutocompleteMatch& elem2) {
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return elem1.destination_url == elem2.destination_url;
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ClassifyMatchInString(
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& find_text,
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& text,
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int style,
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    ACMatchClassifications* classification) {
116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ClassifyLocationInString(text.find(find_text), find_text.length(),
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                           text.length(), style, classification);
118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ClassifyLocationInString(
121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    size_t match_location,
122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    size_t match_length,
123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    size_t overall_length,
124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int style,
125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    ACMatchClassifications* classification) {
126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  classification->clear();
127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Don't classify anything about an empty string
129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // (AutocompleteMatch::Validate() checks this).
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (overall_length == 0)
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Mark pre-match portion of string (if any).
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (match_location != 0) {
135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    classification->push_back(ACMatchClassification(0, style));
136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Mark matching portion of string.
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (match_location == string16::npos) {
140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // No match, above classification will suffice for whole string.
141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Classifying an empty match makes no sense and will lead to validation
144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // errors later.
145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(match_length > 0);
146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  classification->push_back(ACMatchClassification(match_location,
147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM));
148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Mark post-match portion of string (if any).
150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const size_t after_match(match_location + match_length);
151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (after_match < overall_length) {
152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    classification->push_back(ACMatchClassification(after_match, style));
153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#ifndef NDEBUG
157513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::Validate() const {
158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ValidateClassifications(contents, contents_class);
159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ValidateClassifications(description, description_class);
160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
162513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ValidateClassifications(
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& text,
164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const ACMatchClassifications& classifications) const {
165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (text.empty()) {
166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DCHECK(classifications.size() == 0);
167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The classifications should always cover the whole string.
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!classifications.empty()) << "No classification for text";
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(classifications[0].offset == 0) << "Classification misses beginning";
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (classifications.size() == 1)
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The classifications should always be sorted.
177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  size_t last_offset = classifications[0].offset;
178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (ACMatchClassifications::const_iterator i(classifications.begin() + 1);
179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       i != classifications.end(); ++i) {
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DCHECK(i->offset > last_offset) << "Classification unsorted";
181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DCHECK(i->offset < text.length()) << "Classification out of bounds";
182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    last_offset = i->offset;
183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif
186