blob: c879a9dbeab7d2c95f480367ce459e7ed6c10cea [file] [log] [blame]
[email protected]8f7405482011-04-13 11:08:521// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]9ac40092010-10-27 23:05:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/logging.h"
6#include "chrome/browser/autocomplete/autocomplete_match.h"
7#include "grit/theme_resources.h"
8
9// AutocompleteMatch ----------------------------------------------------------
10
11AutocompleteMatch::AutocompleteMatch()
12 : provider(NULL),
13 relevance(0),
14 deletable(false),
[email protected]a2fedb1e2011-01-25 15:23:3615 inline_autocomplete_offset(string16::npos),
[email protected]9ac40092010-10-27 23:05:2616 transition(PageTransition::GENERATED),
17 is_history_what_you_typed_match(false),
18 type(SEARCH_WHAT_YOU_TYPED),
19 template_url(NULL),
[email protected]7abfb3462011-01-31 16:43:0620 starred(false),
21 from_previous(false) {
[email protected]9ac40092010-10-27 23:05:2622}
23
24AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider,
25 int relevance,
26 bool deletable,
27 Type type)
28 : provider(provider),
29 relevance(relevance),
30 deletable(deletable),
[email protected]a2fedb1e2011-01-25 15:23:3631 inline_autocomplete_offset(string16::npos),
[email protected]9ac40092010-10-27 23:05:2632 transition(PageTransition::TYPED),
33 is_history_what_you_typed_match(false),
34 type(type),
35 template_url(NULL),
[email protected]7abfb3462011-01-31 16:43:0636 starred(false),
37 from_previous(false) {
[email protected]9ac40092010-10-27 23:05:2638}
39
40AutocompleteMatch::~AutocompleteMatch() {
41}
42
43// static
44std::string AutocompleteMatch::TypeToString(Type type) {
[email protected]fc65f272011-06-28 22:21:3045 const char* strings[] = {
[email protected]9ac40092010-10-27 23:05:2646 "url-what-you-typed",
47 "history-url",
48 "history-title",
49 "history-body",
50 "history-keyword",
51 "navsuggest",
52 "search-what-you-typed",
53 "search-history",
54 "search-suggest",
55 "search-other-engine",
[email protected]8f7405482011-04-13 11:08:5256 "extension-app",
[email protected]9ac40092010-10-27 23:05:2657 };
[email protected]fc65f272011-06-28 22:21:3058 COMPILE_ASSERT(arraysize(strings) == NUM_TYPES,
59 strings_array_must_match_type_enum);
[email protected]9ac40092010-10-27 23:05:2660 return strings[type];
61}
62
63// static
64int AutocompleteMatch::TypeToIcon(Type type) {
[email protected]fc65f272011-06-28 22:21:3065 int icons[] = {
[email protected]9ac40092010-10-27 23:05:2666 IDR_OMNIBOX_HTTP,
67 IDR_OMNIBOX_HTTP,
68 IDR_OMNIBOX_HISTORY,
69 IDR_OMNIBOX_HISTORY,
70 IDR_OMNIBOX_HISTORY,
71 IDR_OMNIBOX_HTTP,
72 IDR_OMNIBOX_SEARCH,
73 IDR_OMNIBOX_SEARCH,
74 IDR_OMNIBOX_SEARCH,
75 IDR_OMNIBOX_SEARCH,
[email protected]8f7405482011-04-13 11:08:5276 IDR_OMNIBOX_EXTENSION_APP,
[email protected]9ac40092010-10-27 23:05:2677 };
[email protected]fc65f272011-06-28 22:21:3078 COMPILE_ASSERT(arraysize(icons) == NUM_TYPES,
79 icons_array_must_match_type_enum);
[email protected]9ac40092010-10-27 23:05:2680 return icons[type];
81}
82
83// static
84bool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1,
85 const AutocompleteMatch& elem2) {
86 // For equal-relevance matches, we sort alphabetically, so that providers
87 // who return multiple elements at the same priority get a "stable" sort
88 // across multiple updates.
89 if (elem1.relevance == elem2.relevance)
90 return elem1.contents > elem2.contents;
91
[email protected]dff945e2011-01-20 17:45:0192 return elem1.relevance > elem2.relevance;
[email protected]9ac40092010-10-27 23:05:2693}
94
95// static
96bool AutocompleteMatch::DestinationSortFunc(const AutocompleteMatch& elem1,
97 const AutocompleteMatch& elem2) {
98 // Sort identical destination_urls together. Place the most relevant matches
99 // first, so that when we call std::unique(), these are the ones that get
100 // preserved.
101 return (elem1.destination_url != elem2.destination_url) ?
102 (elem1.destination_url < elem2.destination_url) :
103 MoreRelevant(elem1, elem2);
104}
105
106// static
107bool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1,
108 const AutocompleteMatch& elem2) {
109 return elem1.destination_url == elem2.destination_url;
110}
111
112// static
113void AutocompleteMatch::ClassifyMatchInString(
[email protected]a2fedb1e2011-01-25 15:23:36114 const string16& find_text,
115 const string16& text,
[email protected]9ac40092010-10-27 23:05:26116 int style,
117 ACMatchClassifications* classification) {
118 ClassifyLocationInString(text.find(find_text), find_text.length(),
119 text.length(), style, classification);
120}
121
[email protected]24d692aa2011-05-25 23:07:58122// static
[email protected]9ac40092010-10-27 23:05:26123void AutocompleteMatch::ClassifyLocationInString(
124 size_t match_location,
125 size_t match_length,
126 size_t overall_length,
127 int style,
128 ACMatchClassifications* classification) {
129 classification->clear();
130
131 // Don't classify anything about an empty string
132 // (AutocompleteMatch::Validate() checks this).
133 if (overall_length == 0)
134 return;
135
136 // Mark pre-match portion of string (if any).
137 if (match_location != 0) {
138 classification->push_back(ACMatchClassification(0, style));
139 }
140
141 // Mark matching portion of string.
[email protected]a2fedb1e2011-01-25 15:23:36142 if (match_location == string16::npos) {
[email protected]9ac40092010-10-27 23:05:26143 // No match, above classification will suffice for whole string.
144 return;
145 }
146 // Classifying an empty match makes no sense and will lead to validation
147 // errors later.
148 DCHECK(match_length > 0);
149 classification->push_back(ACMatchClassification(match_location,
150 (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM));
151
152 // Mark post-match portion of string (if any).
153 const size_t after_match(match_location + match_length);
154 if (after_match < overall_length) {
155 classification->push_back(ACMatchClassification(after_match, style));
156 }
157}
158
159#ifndef NDEBUG
160void AutocompleteMatch::Validate() const {
161 ValidateClassifications(contents, contents_class);
162 ValidateClassifications(description, description_class);
163}
164
165void AutocompleteMatch::ValidateClassifications(
[email protected]a2fedb1e2011-01-25 15:23:36166 const string16& text,
[email protected]9ac40092010-10-27 23:05:26167 const ACMatchClassifications& classifications) const {
168 if (text.empty()) {
[email protected]37b95732011-05-26 23:11:09169 DCHECK(classifications.empty());
[email protected]9ac40092010-10-27 23:05:26170 return;
171 }
172
173 // The classifications should always cover the whole string.
[email protected]6775e40a2011-03-04 21:03:47174 DCHECK(!classifications.empty()) << "No classification for text";
[email protected]9ac40092010-10-27 23:05:26175 DCHECK(classifications[0].offset == 0) << "Classification misses beginning";
176 if (classifications.size() == 1)
177 return;
178
179 // The classifications should always be sorted.
180 size_t last_offset = classifications[0].offset;
181 for (ACMatchClassifications::const_iterator i(classifications.begin() + 1);
182 i != classifications.end(); ++i) {
183 DCHECK(i->offset > last_offset) << "Classification unsorted";
184 DCHECK(i->offset < text.length()) << "Classification out of bounds";
185 last_offset = i->offset;
186 }
187}
188#endif