// Copyright (c) 2012 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 CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_ #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_ #include #include #include "base/basictypes.h" #include "chrome/browser/autocomplete/autocomplete_input.h" #include "chrome/browser/autocomplete/autocomplete_match.h" #include "url/gurl.h" class AutocompleteInput; class AutocompleteProvider; class Profile; // All matches from all providers for a particular query. This also tracks // what the default match should be if the user doesn't manually select another // match. class AutocompleteResult { public: typedef ACMatches::const_iterator const_iterator; typedef ACMatches::iterator iterator; // The "Selection" struct is the information we need to select the same match // in one result set that was selected in another. struct Selection { Selection() : provider_affinity(NULL), is_history_what_you_typed_match(false) { } // Clear the selection entirely. void Clear(); // True when the selection is empty. bool empty() const { return destination_url.is_empty() && !provider_affinity && !is_history_what_you_typed_match; } // The desired destination URL. GURL destination_url; // The desired provider. If we can't find a match with the specified // |destination_url|, we'll use the best match from this provider. const AutocompleteProvider* provider_affinity; // True when this is the HistoryURLProvider's "what you typed" match. This // can't be tracked using |destination_url| because its URL changes on every // keystroke, so if this is set, we'll preserve the selection by simply // choosing the new "what you typed" entry and ignoring |destination_url|. bool is_history_what_you_typed_match; }; // Max number of matches we'll show from the various providers. static const size_t kMaxMatches; // The lowest score a match can have and still potentially become the default // match for the result set. static const int kLowestDefaultScore; AutocompleteResult(); ~AutocompleteResult(); // Copies matches from |old_matches| to provide a consistant result set. See // comments in code for specifics. void CopyOldMatches(const AutocompleteInput& input, const AutocompleteResult& old_matches, Profile* profile); // Adds a new set of matches to the result set. Does not re-sort. void AppendMatches(const ACMatches& matches); // Removes duplicates, puts the list in sorted order and culls to leave only // the best kMaxMatches matches. Sets the default match to the best match // and updates the alternate nav URL. void SortAndCull(const AutocompleteInput& input, Profile* profile); // Returns true if at least one match was copied from the last result. bool HasCopiedMatches() const; // Vector-style accessors/operators. size_t size() const; bool empty() const; const_iterator begin() const; iterator begin(); const_iterator end() const; iterator end(); // Returns the match at the given index. const AutocompleteMatch& match_at(size_t index) const; AutocompleteMatch* match_at(size_t index); // Get the default match for the query (not necessarily the first). Returns // end() if there is no default match. const_iterator default_match() const { return default_match_; } // Returns true if the top match is a verbatim search or URL match (see // IsVerbatimType() in autocomplete_match.h), and the next match is not also // some kind of verbatim match. In this case, the top match will be hidden, // and nothing in the dropdown will appear selected by default; hitting enter // will navigate to the (hidden) default match, while pressing the down arrow // key will select the first visible match, which is actually the second match // in the result set. // // Hiding the top match in these cases is possible because users should // already know what will happen on hitting enter from the omnibox text // itself, without needing to see the same text appear again, selected, just // below their typing. Instead, by hiding the verbatim match, there is one // less line to skip over in order to visually scan downwards to see other // suggested matches. This makes it more likely that users will see and // select useful non-verbatim matches. (Note that hiding the verbatim match // this way is similar to how most other browsers' address bars behave.) // // We avoid hiding when the top two matches are both verbatim in order to // avoid potential confusion if a user were to see the second match just below // their typing and assume it would be the default action. // // Note that if the top match should be hidden and it is the only match, // the dropdown should be closed. bool ShouldHideTopMatch() const; const GURL& alternate_nav_url() const { return alternate_nav_url_; } // Clears the matches for this result set. void Reset(); void Swap(AutocompleteResult* other); #ifndef NDEBUG // Does a data integrity check on this result. void Validate() const; #endif // Compute the "alternate navigation URL" for a given match. This is obtained // by interpreting the user input directly as a URL. See comments on // |alternate_nav_url_|. static GURL ComputeAlternateNavUrl(const AutocompleteInput& input, const AutocompleteMatch& match); private: friend class AutocompleteProviderTest; typedef std::map ProviderToMatches; #if defined(OS_ANDROID) // iterator::difference_type is not defined in the STL that we compile with on // Android. typedef int matches_difference_type; #else typedef ACMatches::iterator::difference_type matches_difference_type; #endif // Returns true if |matches| contains a match with the same destination as // |match|. static bool HasMatchByDestination(const AutocompleteMatch& match, const ACMatches& matches); // operator=() by another name. void CopyFrom(const AutocompleteResult& rhs); // Adds a single match. The match is inserted at the appropriate position // based on relevancy and display order. This is ONLY for use after // SortAndCull() has been invoked, and preserves default_match_. void AddMatch(AutocompleteInput::PageClassification page_classification, const AutocompleteMatch& match); // Populates |provider_to_matches| from |matches_|. void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const; // Copies matches into this result. |old_matches| gives the matches from the // last result, and |new_matches| the results from this result. void MergeMatchesByProvider( AutocompleteInput::PageClassification page_classification, const ACMatches& old_matches, const ACMatches& new_matches); ACMatches matches_; const_iterator default_match_; // The "alternate navigation URL", if any, for this result set. This is a URL // to try offering as a navigational option in case the user navigated to the // URL of the default match but intended something else. For example, if the // user's local intranet contains site "foo", and the user types "foo", we // default to searching for "foo" when the user may have meant to navigate // there. In cases like this, the default match will point to the "search for // 'foo'" result, and this will contain "http://foo/". GURL alternate_nav_url_; DISALLOW_COPY_AND_ASSIGN(AutocompleteResult); }; #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_