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
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_OMNIBOX_AUTOCOMPLETE_MATCH_H_
6 #define COMPONENTS_OMNIBOX_AUTOCOMPLETE_MATCH_H_
12 #include "base/memory/scoped_ptr.h"
13 #include "components/omnibox/autocomplete_match_type.h"
14 #include "components/search_engines/template_url.h"
15 #include "ui/base/page_transition_types.h"
18 class AutocompleteProvider
;
20 class TemplateURLService
;
26 const char kACMatchPropertyInputText
[] = "input text";
27 const char kACMatchPropertyContentsPrefix
[] = "match contents prefix";
28 const char kACMatchPropertyContentsStartIndex
[] = "match contents start index";
30 // AutocompleteMatch ----------------------------------------------------------
32 // A single result line with classified spans. The autocomplete popup displays
33 // the 'contents' and the 'description' (the description is optional) in the
34 // autocomplete dropdown, and fills in 'fill_into_edit' into the textbox when
35 // that line is selected. fill_into_edit may be the same as 'description' for
36 // things like URLs, but may be different for searches or other providers. For
37 // example, a search result may say "Search for asdf" as the description, but
38 // "asdf" should appear in the box.
39 struct AutocompleteMatch
{
40 // Autocomplete matches contain strings that are classified according to a
41 // separate vector of styles. This vector associates flags with particular
42 // string segments, and must be in sorted order. All text must be associated
43 // with some kind of classification. Even if a match has no distinct
44 // segments, its vector should contain an entry at offset 0 with no flags.
46 // Example: The user typed "goog"
47 // http://www.google.com/ Google
52 // This structure holds the classification information for each span.
53 struct ACMatchClassification
{
54 // The values in here are not mutually exclusive -- use them like a
55 // bitfield. This also means we use "int" instead of this enum type when
56 // passing the values around, so the compiler doesn't complain.
59 URL
= 1 << 0, // A URL
60 MATCH
= 1 << 1, // A match for the user's search term
61 DIM
= 1 << 2, // "Helper text"
64 ACMatchClassification(size_t offset
, int style
)
69 // Offset within the string that this classification starts
75 typedef std::vector
<ACMatchClassification
> ACMatchClassifications
;
77 // Type used by providers to attach additional, optional information to
78 // an AutocompleteMatch.
79 typedef std::map
<std::string
, std::string
> AdditionalInfo
;
81 // The type of this match.
82 typedef AutocompleteMatchType::Type Type
;
84 // Null-terminated array of characters that are not valid within |contents|
85 // and |description| strings.
86 static const base::char16 kInvalidChars
[];
89 AutocompleteMatch(AutocompleteProvider
* provider
,
93 AutocompleteMatch(const AutocompleteMatch
& match
);
96 // Converts |type| to a string representation. Used in logging and debugging.
97 AutocompleteMatch
& operator=(const AutocompleteMatch
& match
);
99 // Converts |type| to a resource identifier for the appropriate icon for this
100 // type to show in the completion popup.
101 static int TypeToIcon(Type type
);
103 // Comparison function for determining when one match is better than another.
104 static bool MoreRelevant(const AutocompleteMatch
& elem1
,
105 const AutocompleteMatch
& elem2
);
107 // Comparison function for removing matches with duplicate destinations.
108 // Destinations are compared using |stripped_destination_url|. Pairs of
109 // matches with empty destinations are treated as differing, since empty
110 // destinations are expected for non-navigable matches.
111 static bool DestinationsEqual(const AutocompleteMatch
& elem1
,
112 const AutocompleteMatch
& elem2
);
114 // Helper functions for classes creating matches:
115 // Fills in the classifications for |text|, using |style| as the base style
116 // and marking the first instance of |find_text| as a match. (This match
117 // will also not be dimmed, if |style| has DIM set.)
118 static void ClassifyMatchInString(const base::string16
& find_text
,
119 const base::string16
& text
,
121 ACMatchClassifications
* classifications
);
123 // Similar to ClassifyMatchInString(), but for cases where the range to mark
124 // as matching is already known (avoids calling find()). This can be helpful
125 // when find() would be misleading (e.g. you want to mark the second match in
126 // a string instead of the first).
127 static void ClassifyLocationInString(size_t match_location
,
129 size_t overall_length
,
131 ACMatchClassifications
* classifications
);
133 // Returns a new vector of classifications containing the merged contents of
134 // |classifications1| and |classifications2|.
135 static ACMatchClassifications
MergeClassifications(
136 const ACMatchClassifications
& classifications1
,
137 const ACMatchClassifications
& classifications2
);
139 // Converts classifications to and from a serialized string representation
140 // (using comma-separated integers to sequentially list positions and styles).
141 static std::string
ClassificationsToString(
142 const ACMatchClassifications
& classifications
);
143 static ACMatchClassifications
ClassificationsFromString(
144 const std::string
& serialized_classifications
);
146 // Adds a classification to the end of |classifications| iff its style is
147 // different from the last existing classification. |offset| must be larger
148 // than the offset of the last classification in |classifications|.
149 static void AddLastClassificationIfNecessary(
150 ACMatchClassifications
* classifications
,
154 // Removes invalid characters from |text|. Should be called on strings coming
155 // from external sources (such as extensions) before assigning to |contents|
157 static base::string16
SanitizeString(const base::string16
& text
);
159 // Convenience function to check if |type| is a search (as opposed to a URL or
161 static bool IsSearchType(Type type
);
163 // Convenience function to check if |type| is a special search suggest type -
164 // like entity, personalized, profile or postfix.
165 static bool IsSpecializedSearchType(Type type
);
167 // A static version GetTemplateURL() that takes the match's keyword and
168 // match's hostname as parameters. In short, returns the TemplateURL
169 // associated with |keyword| if it exists; otherwise returns the TemplateURL
170 // associated with |host| if it exists.
171 static TemplateURL
* GetTemplateURLWithKeyword(
172 TemplateURLService
* template_url_service
,
173 const base::string16
& keyword
,
174 const std::string
& host
);
176 // Returns |url| altered by stripping off "www.", converting https protocol
177 // to http, and stripping excess query parameters. These conversions are
178 // merely to allow comparisons to remove likely duplicates; these URLs are
179 // not used as actual destination URLs. If |template_url_service| is not
180 // NULL, it is used to get a template URL corresponding to this match. If
181 // the match's keyword is known, it can be passed in. Otherwise, it can be
182 // left empty and the template URL (if any) is determined from the
183 // destination's hostname. The template URL is used to strip off query args
184 // other than the search terms themselves that would otherwise prevent doing
186 static GURL
GURLToStrippedGURL(const GURL
& url
,
187 TemplateURLService
* template_url_service
,
188 const base::string16
& keyword
);
190 // Computes the stripped destination URL (via GURLToStrippedGURL()) and
191 // stores the result in |stripped_destination_url|.
192 void ComputeStrippedDestinationURL(TemplateURLService
* template_url_service
);
194 // Sets |allowed_to_be_default_match| to true if this match is effectively
195 // the URL-what-you-typed match (i.e., would be dupped against the UWYT
196 // match when AutocompleteResult merges matches). |canonical_input_url| is
197 // the AutocompleteInput interpreted as a URL (i.e.,
198 // AutocompleteInput::canonicalized_url()).
199 void EnsureUWYTIsAllowedToBeDefault(const GURL
& canonical_input_url
,
200 TemplateURLService
* template_url_service
);
202 // Gets data relevant to whether there should be any special keyword-related
203 // UI shown for this match. If this match represents a selected keyword, i.e.
204 // the UI should be "in keyword mode", |keyword| will be set to the keyword
205 // and |is_keyword_hint| will be set to false. If this match has a non-NULL
206 // |associated_keyword|, i.e. we should show a "Press [tab] to search ___"
207 // hint and allow the user to toggle into keyword mode, |keyword| will be set
208 // to the associated keyword and |is_keyword_hint| will be set to true. Note
209 // that only one of these states can be in effect at once. In all other
210 // cases, |keyword| will be cleared, even when our member variable |keyword|
211 // is non-empty -- such as with non-substituting keywords or matches that
212 // represent searches using the default search engine. See also
213 // GetSubstitutingExplicitlyInvokedKeyword().
214 void GetKeywordUIState(TemplateURLService
* template_url_service
,
215 base::string16
* keyword
,
216 bool* is_keyword_hint
) const;
218 // Returns |keyword|, but only if it represents a substituting keyword that
219 // the user has explicitly invoked. If for example this match represents a
220 // search with the default search engine (and the user didn't explicitly
221 // invoke its keyword), this returns the empty string. The result is that
222 // this function returns a non-empty string in the same cases as when the UI
223 // should show up as being "in keyword mode".
224 base::string16
GetSubstitutingExplicitlyInvokedKeyword(
225 TemplateURLService
* template_url_service
) const;
227 // Returns the TemplateURL associated with this match. This may be NULL if
228 // the match has no keyword OR if the keyword no longer corresponds to a valid
229 // TemplateURL. See comments on |keyword| below.
230 // If |allow_fallback_to_destination_host| is true and the keyword does
231 // not map to a valid TemplateURL, we'll then check for a TemplateURL that
232 // corresponds to the destination_url's hostname.
233 TemplateURL
* GetTemplateURL(TemplateURLService
* template_url_service
,
234 bool allow_fallback_to_destination_host
) const;
236 // Adds optional information to the |additional_info| dictionary.
237 void RecordAdditionalInfo(const std::string
& property
,
238 const std::string
& value
);
239 void RecordAdditionalInfo(const std::string
& property
, int value
);
240 void RecordAdditionalInfo(const std::string
& property
,
241 const base::Time
& value
);
243 // Returns the value recorded for |property| in the |additional_info|
244 // dictionary. Returns the empty string if no such value exists.
245 std::string
GetAdditionalInfo(const std::string
& property
) const;
247 // Returns whether this match is a "verbatim" match: a URL navigation directly
248 // to the user's input, a search for the user's input with the default search
249 // engine, or a "keyword mode" search for the query portion of the user's
250 // input. Note that rare or unusual types that could be considered verbatim,
251 // such as keyword engine matches or extension-provided matches, aren't
252 // detected by this IsVerbatimType, as the user will not be able to infer
253 // what will happen when he or she presses enter in those cases if the match
255 bool IsVerbatimType() const;
257 // Returns whether this match or any duplicate of this match can be deleted.
258 // This is used to decide whether we should call DeleteMatch().
259 bool SupportsDeletion() const;
261 // The provider of this match, used to remember which provider the user had
262 // selected when the input changes. This may be NULL, in which case there is
263 // no provider (or memory of the user's selection).
264 AutocompleteProvider
* provider
;
266 // The relevance of this match. See table in autocomplete.h for scores
267 // returned by various providers. This is used to rank matches among all
268 // responding providers, so different providers must be carefully tuned to
269 // supply matches with appropriate relevance.
271 // TODO(pkasting): http://b/1111299 This should be calculated algorithmically,
272 // rather than being a fairly fixed value defined by the table above.
275 // How many times this result was typed in / selected from the omnibox.
276 // Only set for some providers and result_types. If it is not set,
277 // its value is -1. At the time of writing this comment, it is only
278 // set for matches from HistoryURL and HistoryQuickProvider.
281 // True if the user should be able to delete this match.
284 // This string is loaded into the location bar when the item is selected
285 // by pressing the arrow keys. This may be different than a URL, for example,
286 // for search suggestions, this would just be the search terms.
287 base::string16 fill_into_edit
;
289 // The inline autocompletion to display after the user's typing in the
290 // omnibox, if this match becomes the default match. It may be empty.
291 base::string16 inline_autocompletion
;
293 // If false, the omnibox should prevent this match from being the
294 // default match. Providers should set this to true only if the
295 // user's input, plus any inline autocompletion on this match, would
296 // lead the user to expect a navigation to this match's destination.
297 // For example, with input "foo", a search for "bar" or navigation
298 // to "bar.com" should not set this flag; a navigation to "foo.com"
299 // should only set this flag if ".com" will be inline autocompleted;
300 // and a navigation to "foo/" (an intranet host) or search for "foo"
301 // should set this flag.
302 bool allowed_to_be_default_match
;
304 // The URL to actually load when the autocomplete item is selected. This URL
305 // should be canonical so we can compare URLs with strcmp to avoid dupes.
306 // It may be empty if there is no possible navigation.
307 GURL destination_url
;
309 // The destination URL with "www." stripped off for better dupe finding.
310 GURL stripped_destination_url
;
312 // The main text displayed in the address bar dropdown.
313 base::string16 contents
;
314 ACMatchClassifications contents_class
;
316 // Additional helper text for each entry, such as a title or description.
317 base::string16 description
;
318 ACMatchClassifications description_class
;
320 // A rich-format version of the display for the dropdown.
321 base::string16 answer_contents
;
322 base::string16 answer_type
;
324 // The transition type to use when the user opens this match. By default
325 // this is TYPED. Providers whose matches do not look like URLs should set
327 ui::PageTransition transition
;
329 // True when this match is the "what you typed" match from the history
331 bool is_history_what_you_typed_match
;
333 // Type of this match.
336 // Set with a keyword provider match if this match can show a keyword hint.
337 // For example, if this is a SearchProvider match for "www.amazon.com",
338 // |associated_keyword| could be a KeywordProvider match for "amazon.com".
339 scoped_ptr
<AutocompleteMatch
> associated_keyword
;
341 // The keyword of the TemplateURL the match originated from. This is nonempty
342 // for both explicit "keyword mode" matches as well as matches for the default
343 // search provider (so, any match for which we're doing substitution); it
344 // doesn't imply (alone) that the UI is going to show a keyword hint or
345 // keyword mode. For that, see GetKeywordUIState() or
346 // GetSubstitutingExplicitlyInvokedKeyword().
348 // CAUTION: The TemplateURL associated with this keyword may be deleted or
349 // modified while the AutocompleteMatch is alive. This means anyone who
350 // accesses it must perform any necessary sanity checks before blindly using
352 base::string16 keyword
;
354 // True if this match is from a previous result.
357 // Optional search terms args. If present,
358 // AutocompleteController::UpdateAssistedQueryStats() will incorporate this
359 // data with additional data it calculates and pass the completed struct to
360 // TemplateURLRef::ReplaceSearchTerms() to reset the match's |destination_url|
361 // after the complete set of matches in the AutocompleteResult has been chosen
362 // and sorted. Most providers will leave this as NULL, which will cause the
363 // AutocompleteController to do no additional transformations.
364 scoped_ptr
<TemplateURLRef::SearchTermsArgs
> search_terms_args
;
366 // Information dictionary into which each provider can optionally record a
367 // property and associated value and which is presented in chrome://omnibox.
368 AdditionalInfo additional_info
;
370 // A list of matches culled during de-duplication process, retained to
371 // ensure if a match is deleted, the duplicates are deleted as well.
372 std::vector
<AutocompleteMatch
> duplicate_matches
;
375 // Does a data integrity check on this match.
376 void Validate() const;
378 // Checks one text/classifications pair for valid values.
379 void ValidateClassifications(
380 const base::string16
& text
,
381 const ACMatchClassifications
& classifications
) const;
385 typedef AutocompleteMatch::ACMatchClassification ACMatchClassification
;
386 typedef std::vector
<ACMatchClassification
> ACMatchClassifications
;
387 typedef std::vector
<AutocompleteMatch
> ACMatches
;
389 #endif // COMPONENTS_OMNIBOX_AUTOCOMPLETE_MATCH_H_