1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_MATCH_H_
#define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_MATCH_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match_type.h"
#include "components/search_engines/template_url.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
class AutocompleteProvider;
class SuggestionAnswer;
class TemplateURL;
class TemplateURLService;
namespace base {
class Time;
} // namespace base
namespace gfx {
enum class VectorIconId;
} // namespace gfx
const char kACMatchPropertyInputText[] = "input text";
const char kACMatchPropertyContentsPrefix[] = "match contents prefix";
const char kACMatchPropertyContentsStartIndex[] = "match contents start index";
// AutocompleteMatch ----------------------------------------------------------
// A single result line with classified spans. The autocomplete popup displays
// the 'contents' and the 'description' (the description is optional) in the
// autocomplete dropdown, and fills in 'fill_into_edit' into the textbox when
// that line is selected. fill_into_edit may be the same as 'description' for
// things like URLs, but may be different for searches or other providers. For
// example, a search result may say "Search for asdf" as the description, but
// "asdf" should appear in the box.
struct AutocompleteMatch {
// Autocomplete matches contain strings that are classified according to a
// separate vector of styles. This vector associates flags with particular
// string segments, and must be in sorted order. All text must be associated
// with some kind of classification. Even if a match has no distinct
// segments, its vector should contain an entry at offset 0 with no flags.
//
// Example: The user typed "goog"
// http://www.google.com/ Google
// ^ ^ ^ ^ ^
// 0, | 15, | 4,
// 11,match 0,match
//
// This structure holds the classification information for each span.
struct ACMatchClassification {
// The values in here are not mutually exclusive -- use them like a
// bitfield. This also means we use "int" instead of this enum type when
// passing the values around, so the compiler doesn't complain.
//
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.omnibox
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: MatchClassificationStyle
enum Style {
NONE = 0,
URL = 1 << 0, // A URL
MATCH = 1 << 1, // A match for the user's search term
DIM = 1 << 2, // "Helper text"
};
ACMatchClassification(size_t offset, int style)
: offset(offset),
style(style) {
}
// Offset within the string that this classification starts
size_t offset;
int style;
};
typedef std::vector<ACMatchClassification> ACMatchClassifications;
// Type used by providers to attach additional, optional information to
// an AutocompleteMatch.
typedef std::map<std::string, std::string> AdditionalInfo;
// The type of this match.
typedef AutocompleteMatchType::Type Type;
// Null-terminated array of characters that are not valid within |contents|
// and |description| strings.
static const base::char16 kInvalidChars[];
AutocompleteMatch();
AutocompleteMatch(AutocompleteProvider* provider,
int relevance,
bool deletable,
Type type);
AutocompleteMatch(const AutocompleteMatch& match);
~AutocompleteMatch();
// Converts |type| to a string representation. Used in logging and debugging.
AutocompleteMatch& operator=(const AutocompleteMatch& match);
// Gets the vector icon identifier for the icon to be shown for |type|.
static gfx::VectorIconId TypeToVectorIcon(Type type);
// Comparison function for determining when one match is better than another.
static bool MoreRelevant(const AutocompleteMatch& elem1,
const AutocompleteMatch& elem2);
// Comparison function for removing matches with duplicate destinations.
// Destinations are compared using |stripped_destination_url|. Pairs of
// matches with empty destinations are treated as differing, since empty
// destinations are expected for non-navigable matches.
static bool DestinationsEqual(const AutocompleteMatch& elem1,
const AutocompleteMatch& elem2);
// Helper functions for classes creating matches:
// Fills in the classifications for |text|, using |style| as the base style
// and marking the first instance of |find_text| as a match. (This match
// will also not be dimmed, if |style| has DIM set.)
static void ClassifyMatchInString(const base::string16& find_text,
const base::string16& text,
int style,
ACMatchClassifications* classifications);
// Similar to ClassifyMatchInString(), but for cases where the range to mark
// as matching is already known (avoids calling find()). This can be helpful
// when find() would be misleading (e.g. you want to mark the second match in
// a string instead of the first).
static void ClassifyLocationInString(size_t match_location,
size_t match_length,
size_t overall_length,
int style,
ACMatchClassifications* classifications);
// Returns a new vector of classifications containing the merged contents of
// |classifications1| and |classifications2|.
static ACMatchClassifications MergeClassifications(
const ACMatchClassifications& classifications1,
const ACMatchClassifications& classifications2);
// Converts classifications to and from a serialized string representation
// (using comma-separated integers to sequentially list positions and styles).
static std::string ClassificationsToString(
const ACMatchClassifications& classifications);
static ACMatchClassifications ClassificationsFromString(
const std::string& serialized_classifications);
// Adds a classification to the end of |classifications| iff its style is
// different from the last existing classification. |offset| must be larger
// than the offset of the last classification in |classifications|.
static void AddLastClassificationIfNecessary(
ACMatchClassifications* classifications,
size_t offset,
int style);
// Returns true if at least one style in |classifications| is of type MATCH.
static bool HasMatchStyle(const ACMatchClassifications& classifications);
// Removes invalid characters from |text|. Should be called on strings coming
// from external sources (such as extensions) before assigning to |contents|
// or |description|.
static base::string16 SanitizeString(const base::string16& text);
// Convenience function to check if |type| is a search (as opposed to a URL or
// an extension).
static bool IsSearchType(Type type);
// Convenience function to check if |type| is a special search suggest type -
// like entity, personalized, profile or postfix.
static bool IsSpecializedSearchType(Type type);
// A static version GetTemplateURL() that takes the match's keyword and
// match's hostname as parameters. In short, returns the TemplateURL
// associated with |keyword| if it exists; otherwise returns the TemplateURL
// associated with |host| if it exists.
static TemplateURL* GetTemplateURLWithKeyword(
TemplateURLService* template_url_service,
const base::string16& keyword,
const std::string& host);
// Returns |url| altered by stripping off "www.", converting https protocol
// to http, and stripping excess query parameters. These conversions are
// merely to allow comparisons to remove likely duplicates; these URLs are
// not used as actual destination URLs. If |template_url_service| is not
// NULL, it is used to get a template URL corresponding to this match. If
// the match's keyword is known, it can be passed in. Otherwise, it can be
// left empty and the template URL (if any) is determined from the
// destination's hostname. The template URL is used to strip off query args
// other than the search terms themselves that would otherwise prevent doing
// proper deduping. |input| is used to decide if the scheme is allowed to
// be altered during stripping. If this URL, minus the scheme and separator,
// starts with any the terms in input.terms_prefixed_by_http_or_https(), we
// avoid converting an HTTPS scheme to HTTP. This means URLs that differ
// only by these schemes won't be marked as dupes, since the distinction
// seems to matter to the user.
static GURL GURLToStrippedGURL(const GURL& url,
const AutocompleteInput& input,
TemplateURLService* template_url_service,
const base::string16& keyword);
// Computes the stripped destination URL (via GURLToStrippedGURL()) and
// stores the result in |stripped_destination_url|. |input| is used for the
// same purpose as in GURLToStrippedGURL().
void ComputeStrippedDestinationURL(const AutocompleteInput& input,
TemplateURLService* template_url_service);
// Sets |allowed_to_be_default_match| to true if this match is effectively
// the URL-what-you-typed match (i.e., would be dupped against the UWYT
// match when AutocompleteResult merges matches).
void EnsureUWYTIsAllowedToBeDefault(
const AutocompleteInput& input,
TemplateURLService* template_url_service);
// Gets data relevant to whether there should be any special keyword-related
// UI shown for this match. If this match represents a selected keyword, i.e.
// the UI should be "in keyword mode", |keyword| will be set to the keyword
// and |is_keyword_hint| will be set to false. If this match has a non-NULL
// |associated_keyword|, i.e. we should show a "Press [tab] to search ___"
// hint and allow the user to toggle into keyword mode, |keyword| will be set
// to the associated keyword and |is_keyword_hint| will be set to true. Note
// that only one of these states can be in effect at once. In all other
// cases, |keyword| will be cleared, even when our member variable |keyword|
// is non-empty -- such as with non-substituting keywords or matches that
// represent searches using the default search engine. See also
// GetSubstitutingExplicitlyInvokedKeyword().
void GetKeywordUIState(TemplateURLService* template_url_service,
base::string16* keyword,
bool* is_keyword_hint) const;
// Returns |keyword|, but only if it represents a substituting keyword that
// the user has explicitly invoked. If for example this match represents a
// search with the default search engine (and the user didn't explicitly
// invoke its keyword), this returns the empty string. The result is that
// this function returns a non-empty string in the same cases as when the UI
// should show up as being "in keyword mode".
base::string16 GetSubstitutingExplicitlyInvokedKeyword(
TemplateURLService* template_url_service) const;
// Returns the TemplateURL associated with this match. This may be NULL if
// the match has no keyword OR if the keyword no longer corresponds to a valid
// TemplateURL. See comments on |keyword| below.
// If |allow_fallback_to_destination_host| is true and the keyword does
// not map to a valid TemplateURL, we'll then check for a TemplateURL that
// corresponds to the destination_url's hostname.
TemplateURL* GetTemplateURL(TemplateURLService* template_url_service,
bool allow_fallback_to_destination_host) const;
// Adds optional information to the |additional_info| dictionary.
void RecordAdditionalInfo(const std::string& property,
const std::string& value);
void RecordAdditionalInfo(const std::string& property, int value);
void RecordAdditionalInfo(const std::string& property,
const base::Time& value);
// Returns the value recorded for |property| in the |additional_info|
// dictionary. Returns the empty string if no such value exists.
std::string GetAdditionalInfo(const std::string& property) const;
// Returns whether this match is a "verbatim" match: a URL navigation directly
// to the user's input, a search for the user's input with the default search
// engine, or a "keyword mode" search for the query portion of the user's
// input. Note that rare or unusual types that could be considered verbatim,
// such as keyword engine matches or extension-provided matches, aren't
// detected by this IsVerbatimType, as the user will not be able to infer
// what will happen when they press enter in those cases if the match is not
// shown.
bool IsVerbatimType() const;
// Returns whether this match or any duplicate of this match can be deleted.
// This is used to decide whether we should call DeleteMatch().
bool SupportsDeletion() const;
// Swaps the contents and description fields, and their associated
// classifications, if this is a match for which we should emphasize the
// title (stored in the description field) over the URL (in the contents
// field). Intended to only be used at the UI level before displaying, lest
// other omnibox systems get confused about which is which. See the code
// that sets |swap_contents_and_description| for conditions under which
// it is true.
void PossiblySwapContentsAndDescriptionForDisplay();
// The provider of this match, used to remember which provider the user had
// selected when the input changes. This may be NULL, in which case there is
// no provider (or memory of the user's selection).
AutocompleteProvider* provider;
// The relevance of this match. See table in autocomplete.h for scores
// returned by various providers. This is used to rank matches among all
// responding providers, so different providers must be carefully tuned to
// supply matches with appropriate relevance.
//
// TODO(pkasting): http://b/1111299 This should be calculated algorithmically,
// rather than being a fairly fixed value defined by the table above.
int relevance;
// How many times this result was typed in / selected from the omnibox.
// Only set for some providers and result_types. If it is not set,
// its value is -1. At the time of writing this comment, it is only
// set for matches from HistoryURL and HistoryQuickProvider.
int typed_count;
// True if the user should be able to delete this match.
bool deletable;
// This string is loaded into the location bar when the item is selected
// by pressing the arrow keys. This may be different than a URL, for example,
// for search suggestions, this would just be the search terms.
base::string16 fill_into_edit;
// The inline autocompletion to display after the user's typing in the
// omnibox, if this match becomes the default match. It may be empty.
base::string16 inline_autocompletion;
// If false, the omnibox should prevent this match from being the
// default match. Providers should set this to true only if the
// user's input, plus any inline autocompletion on this match, would
// lead the user to expect a navigation to this match's destination.
// For example, with input "foo", a search for "bar" or navigation
// to "bar.com" should not set this flag; a navigation to "foo.com"
// should only set this flag if ".com" will be inline autocompleted;
// and a navigation to "foo/" (an intranet host) or search for "foo"
// should set this flag.
bool allowed_to_be_default_match;
// The URL to actually load when the autocomplete item is selected. This URL
// should be canonical so we can compare URLs with strcmp to avoid dupes.
// It may be empty if there is no possible navigation.
GURL destination_url;
// The destination URL modified for better dupe finding. The result may not
// be navigable or even valid; it's only meant to be used for detecting
// duplicates.
GURL stripped_destination_url;
// The main text displayed in the address bar dropdown.
base::string16 contents;
ACMatchClassifications contents_class;
// Additional helper text for each entry, such as a title or description.
base::string16 description;
ACMatchClassifications description_class;
// If true, UI-level code should swap the contents and description fields
// before displaying.
bool swap_contents_and_description;
// TODO(jdonnelly): Remove the first two properties once the downstream
// clients are using the SuggestionAnswer.
// A rich-format version of the display for the dropdown.
base::string16 answer_contents;
base::string16 answer_type;
std::unique_ptr<SuggestionAnswer> answer;
// The transition type to use when the user opens this match. By default
// this is TYPED. Providers whose matches do not look like URLs should set
// it to GENERATED.
ui::PageTransition transition;
// Type of this match.
Type type;
// Set with a keyword provider match if this match can show a keyword hint.
// For example, if this is a SearchProvider match for "www.amazon.com",
// |associated_keyword| could be a KeywordProvider match for "amazon.com".
//
// When this is set, the popup will show a ">" symbol at the right edge of the
// line for this match, and tab/shift-tab will toggle in and out of keyword
// mode without disturbing the rest of the popup. See also
// OmniboxPopupModel::SetSelectedLineState().
std::unique_ptr<AutocompleteMatch> associated_keyword;
// The keyword of the TemplateURL the match originated from. This is nonempty
// for both explicit "keyword mode" matches as well as matches for the default
// search provider (so, any match for which we're doing substitution); it
// doesn't imply (alone) that the UI is going to show a keyword hint or
// keyword mode. For that, see GetKeywordUIState() or
// GetSubstitutingExplicitlyInvokedKeyword().
//
// CAUTION: The TemplateURL associated with this keyword may be deleted or
// modified while the AutocompleteMatch is alive. This means anyone who
// accesses it must perform any necessary sanity checks before blindly using
// it!
base::string16 keyword;
// True if this match is from a previous result.
bool from_previous;
// Optional search terms args. If present,
// AutocompleteController::UpdateAssistedQueryStats() will incorporate this
// data with additional data it calculates and pass the completed struct to
// TemplateURLRef::ReplaceSearchTerms() to reset the match's |destination_url|
// after the complete set of matches in the AutocompleteResult has been chosen
// and sorted. Most providers will leave this as NULL, which will cause the
// AutocompleteController to do no additional transformations.
std::unique_ptr<TemplateURLRef::SearchTermsArgs> search_terms_args;
// Information dictionary into which each provider can optionally record a
// property and associated value and which is presented in chrome://omnibox.
AdditionalInfo additional_info;
// A list of matches culled during de-duplication process, retained to
// ensure if a match is deleted, the duplicates are deleted as well.
std::vector<AutocompleteMatch> duplicate_matches;
#ifndef NDEBUG
// Does a data integrity check on this match.
void Validate() const;
// Checks one text/classifications pair for valid values.
void ValidateClassifications(
const base::string16& text,
const ACMatchClassifications& classifications) const;
#endif
};
typedef AutocompleteMatch::ACMatchClassification ACMatchClassification;
typedef std::vector<ACMatchClassification> ACMatchClassifications;
typedef std::vector<AutocompleteMatch> ACMatches;
#endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_MATCH_H_
|