1// Copyright (c) 2012 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. 4 5#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_ 6#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_ 7 8#include <stddef.h> 9 10#include <map> 11 12#include "base/basictypes.h" 13#include "chrome/browser/autocomplete/autocomplete_input.h" 14#include "chrome/browser/autocomplete/autocomplete_match.h" 15#include "url/gurl.h" 16 17class AutocompleteInput; 18class AutocompleteProvider; 19class Profile; 20 21// All matches from all providers for a particular query. This also tracks 22// what the default match should be if the user doesn't manually select another 23// match. 24class AutocompleteResult { 25 public: 26 typedef ACMatches::const_iterator const_iterator; 27 typedef ACMatches::iterator iterator; 28 29 // The "Selection" struct is the information we need to select the same match 30 // in one result set that was selected in another. 31 struct Selection { 32 Selection() 33 : provider_affinity(NULL), 34 is_history_what_you_typed_match(false) { 35 } 36 37 // Clear the selection entirely. 38 void Clear(); 39 40 // True when the selection is empty. 41 bool empty() const { 42 return destination_url.is_empty() && !provider_affinity && 43 !is_history_what_you_typed_match; 44 } 45 46 // The desired destination URL. 47 GURL destination_url; 48 49 // The desired provider. If we can't find a match with the specified 50 // |destination_url|, we'll use the best match from this provider. 51 const AutocompleteProvider* provider_affinity; 52 53 // True when this is the HistoryURLProvider's "what you typed" match. This 54 // can't be tracked using |destination_url| because its URL changes on every 55 // keystroke, so if this is set, we'll preserve the selection by simply 56 // choosing the new "what you typed" entry and ignoring |destination_url|. 57 bool is_history_what_you_typed_match; 58 }; 59 60 // Max number of matches we'll show from the various providers. 61 static const size_t kMaxMatches; 62 63 // The lowest score a match can have and still potentially become the default 64 // match for the result set. 65 static const int kLowestDefaultScore; 66 67 AutocompleteResult(); 68 ~AutocompleteResult(); 69 70 // Copies matches from |old_matches| to provide a consistant result set. See 71 // comments in code for specifics. 72 void CopyOldMatches(const AutocompleteInput& input, 73 const AutocompleteResult& old_matches, 74 Profile* profile); 75 76 // Adds a new set of matches to the result set. Does not re-sort. 77 void AppendMatches(const ACMatches& matches); 78 79 // Removes duplicates, puts the list in sorted order and culls to leave only 80 // the best kMaxMatches matches. Sets the default match to the best match 81 // and updates the alternate nav URL. 82 void SortAndCull(const AutocompleteInput& input, Profile* profile); 83 84 // Returns true if at least one match was copied from the last result. 85 bool HasCopiedMatches() const; 86 87 // Vector-style accessors/operators. 88 size_t size() const; 89 bool empty() const; 90 const_iterator begin() const; 91 iterator begin(); 92 const_iterator end() const; 93 iterator end(); 94 95 // Returns the match at the given index. 96 const AutocompleteMatch& match_at(size_t index) const; 97 AutocompleteMatch* match_at(size_t index); 98 99 // Get the default match for the query (not necessarily the first). Returns 100 // end() if there is no default match. 101 const_iterator default_match() const { return default_match_; } 102 103 // Returns true if the top match is a verbatim search or URL match (see 104 // IsVerbatimType() in autocomplete_match.h), and the next match is not also 105 // some kind of verbatim match. In this case, the top match will be hidden, 106 // and nothing in the dropdown will appear selected by default; hitting enter 107 // will navigate to the (hidden) default match, while pressing the down arrow 108 // key will select the first visible match, which is actually the second match 109 // in the result set. 110 // 111 // Hiding the top match in these cases is possible because users should 112 // already know what will happen on hitting enter from the omnibox text 113 // itself, without needing to see the same text appear again, selected, just 114 // below their typing. Instead, by hiding the verbatim match, there is one 115 // less line to skip over in order to visually scan downwards to see other 116 // suggested matches. This makes it more likely that users will see and 117 // select useful non-verbatim matches. (Note that hiding the verbatim match 118 // this way is similar to how most other browsers' address bars behave.) 119 // 120 // We avoid hiding when the top two matches are both verbatim in order to 121 // avoid potential confusion if a user were to see the second match just below 122 // their typing and assume it would be the default action. 123 // 124 // Note that if the top match should be hidden and it is the only match, 125 // the dropdown should be closed. 126 bool ShouldHideTopMatch() const; 127 128 // Returns true if the top match is a verbatim search or URL match (see 129 // IsVerbatimType() in autocomplete_match.h), and the next match is not also 130 // some kind of verbatim match. 131 bool TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches() const; 132 133 const GURL& alternate_nav_url() const { return alternate_nav_url_; } 134 135 // Clears the matches for this result set. 136 void Reset(); 137 138 void Swap(AutocompleteResult* other); 139 140#ifndef NDEBUG 141 // Does a data integrity check on this result. 142 void Validate() const; 143#endif 144 145 // Compute the "alternate navigation URL" for a given match. This is obtained 146 // by interpreting the user input directly as a URL. See comments on 147 // |alternate_nav_url_|. 148 static GURL ComputeAlternateNavUrl(const AutocompleteInput& input, 149 const AutocompleteMatch& match); 150 151 private: 152 friend class AutocompleteProviderTest; 153 154 typedef std::map<AutocompleteProvider*, ACMatches> ProviderToMatches; 155 156#if defined(OS_ANDROID) 157 // iterator::difference_type is not defined in the STL that we compile with on 158 // Android. 159 typedef int matches_difference_type; 160#else 161 typedef ACMatches::iterator::difference_type matches_difference_type; 162#endif 163 164 // Returns true if |matches| contains a match with the same destination as 165 // |match|. 166 static bool HasMatchByDestination(const AutocompleteMatch& match, 167 const ACMatches& matches); 168 169 // operator=() by another name. 170 void CopyFrom(const AutocompleteResult& rhs); 171 172 // Adds a single match. The match is inserted at the appropriate position 173 // based on relevancy and display order. This is ONLY for use after 174 // SortAndCull() has been invoked, and preserves default_match_. 175 void AddMatch(AutocompleteInput::PageClassification page_classification, 176 const AutocompleteMatch& match); 177 178 // Populates |provider_to_matches| from |matches_|. 179 void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const; 180 181 // Copies matches into this result. |old_matches| gives the matches from the 182 // last result, and |new_matches| the results from this result. 183 void MergeMatchesByProvider( 184 AutocompleteInput::PageClassification page_classification, 185 const ACMatches& old_matches, 186 const ACMatches& new_matches); 187 188 ACMatches matches_; 189 190 const_iterator default_match_; 191 192 // The "alternate navigation URL", if any, for this result set. This is a URL 193 // to try offering as a navigational option in case the user navigated to the 194 // URL of the default match but intended something else. For example, if the 195 // user's local intranet contains site "foo", and the user types "foo", we 196 // default to searching for "foo" when the user may have meant to navigate 197 // there. In cases like this, the default match will point to the "search for 198 // 'foo'" result, and this will contain "http://foo/". 199 GURL alternate_nav_url_; 200 201 DISALLOW_COPY_AND_ASSIGN(AutocompleteResult); 202}; 203 204#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_ 205