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.
5 #ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_
6 #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_
12 #include "base/basictypes.h"
13 #include "chrome/browser/autocomplete/autocomplete_input.h"
14 #include "chrome/browser/autocomplete/autocomplete_match.h"
17 class AutocompleteInput
;
18 class AutocompleteProvider
;
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
24 class AutocompleteResult
{
26 typedef ACMatches::const_iterator const_iterator
;
27 typedef ACMatches::iterator iterator
;
29 // The "Selection" struct is the information we need to select the same match
30 // in one result set that was selected in another.
33 : provider_affinity(NULL
),
34 is_history_what_you_typed_match(false) {
37 // Clear the selection entirely.
40 // True when the selection is empty.
42 return destination_url
.is_empty() && !provider_affinity
&&
43 !is_history_what_you_typed_match
;
46 // The desired destination URL.
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
;
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
;
60 // Max number of matches we'll show from the various providers.
61 static const size_t kMaxMatches
;
64 ~AutocompleteResult();
66 // Copies matches from |old_matches| to provide a consistant result set. See
67 // comments in code for specifics.
68 void CopyOldMatches(const AutocompleteInput
& input
,
69 const AutocompleteResult
& old_matches
,
72 // Adds a new set of matches to the result set. Does not re-sort.
73 void AppendMatches(const ACMatches
& matches
);
75 // Removes duplicates, puts the list in sorted order and culls to leave only
76 // the best kMaxMatches matches. Sets the default match to the best match
77 // and updates the alternate nav URL.
78 void SortAndCull(const AutocompleteInput
& input
, Profile
* profile
);
80 // Returns true if at least one match was copied from the last result.
81 bool HasCopiedMatches() const;
83 // Vector-style accessors/operators.
86 const_iterator
begin() const;
88 const_iterator
end() const;
91 // Returns the match at the given index.
92 const AutocompleteMatch
& match_at(size_t index
) const;
93 AutocompleteMatch
* match_at(size_t index
);
95 // Get the default match for the query (not necessarily the first). Returns
96 // end() if there is no default match.
97 const_iterator
default_match() const { return default_match_
; }
99 // Returns true if the top match is a verbatim search or URL match (see
100 // IsVerbatimType() in autocomplete_match.h), and the next match is not also
101 // some kind of verbatim match. In this case, the top match will be hidden,
102 // and nothing in the dropdown will appear selected by default; hitting enter
103 // will navigate to the (hidden) default match, while pressing the down arrow
104 // key will select the first visible match, which is actually the second match
105 // in the result set.
107 // Hiding the top match in these cases is possible because users should
108 // already know what will happen on hitting enter from the omnibox text
109 // itself, without needing to see the same text appear again, selected, just
110 // below their typing. Instead, by hiding the verbatim match, there is one
111 // less line to skip over in order to visually scan downwards to see other
112 // suggested matches. This makes it more likely that users will see and
113 // select useful non-verbatim matches. (Note that hiding the verbatim match
114 // this way is similar to how most other browsers' address bars behave.)
116 // We avoid hiding when the top two matches are both verbatim in order to
117 // avoid potential confusion if a user were to see the second match just below
118 // their typing and assume it would be the default action.
120 // Note that if the top match should be hidden and it is the only match,
121 // the dropdown should be closed.
122 bool ShouldHideTopMatch() const;
124 // Returns true if the top match is a verbatim search or URL match (see
125 // IsVerbatimType() in autocomplete_match.h), and the next match is not also
126 // some kind of verbatim match.
127 bool TopMatchIsStandaloneVerbatimMatch() const;
129 const GURL
& alternate_nav_url() const { return alternate_nav_url_
; }
131 // Clears the matches for this result set.
134 void Swap(AutocompleteResult
* other
);
137 // Does a data integrity check on this result.
138 void Validate() const;
141 // Compute the "alternate navigation URL" for a given match. This is obtained
142 // by interpreting the user input directly as a URL. See comments on
143 // |alternate_nav_url_|.
144 static GURL
ComputeAlternateNavUrl(const AutocompleteInput
& input
,
145 const AutocompleteMatch
& match
);
147 // Sort |matches| by destination, taking into account demotions based on
148 // |page_classification| when resolving ties about which of several
149 // duplicates to keep. The matches are also deduplicated. If
150 // |set_duplicate_matches| is true, the duplicate matches are stored in the
151 // |duplicate_matches| vector of the corresponding AutocompleteMatch.
152 static void DedupMatchesByDestination(
153 AutocompleteInput::PageClassification page_classification
,
154 bool set_duplicate_matches
,
158 friend class AutocompleteProviderTest
;
160 typedef std::map
<AutocompleteProvider
*, ACMatches
> ProviderToMatches
;
162 #if defined(OS_ANDROID)
163 // iterator::difference_type is not defined in the STL that we compile with on
165 typedef int matches_difference_type
;
167 typedef ACMatches::iterator::difference_type matches_difference_type
;
170 // Returns true if |matches| contains a match with the same destination as
172 static bool HasMatchByDestination(const AutocompleteMatch
& match
,
173 const ACMatches
& matches
);
175 // operator=() by another name.
176 void CopyFrom(const AutocompleteResult
& rhs
);
178 // Adds a single match. The match is inserted at the appropriate position
179 // based on relevancy and display order. This is ONLY for use after
180 // SortAndCull() has been invoked, and preserves default_match_.
181 void AddMatch(AutocompleteInput::PageClassification page_classification
,
182 const AutocompleteMatch
& match
);
184 // Populates |provider_to_matches| from |matches_|.
185 void BuildProviderToMatches(ProviderToMatches
* provider_to_matches
) const;
187 // Copies matches into this result. |old_matches| gives the matches from the
188 // last result, and |new_matches| the results from this result.
189 void MergeMatchesByProvider(
190 AutocompleteInput::PageClassification page_classification
,
191 const ACMatches
& old_matches
,
192 const ACMatches
& new_matches
);
196 const_iterator default_match_
;
198 // The "alternate navigation URL", if any, for this result set. This is a URL
199 // to try offering as a navigational option in case the user navigated to the
200 // URL of the default match but intended something else. For example, if the
201 // user's local intranet contains site "foo", and the user types "foo", we
202 // default to searching for "foo" when the user may have meant to navigate
203 // there. In cases like this, the default match will point to the "search for
204 // 'foo'" result, and this will contain "http://foo/".
205 GURL alternate_nav_url_
;
207 DISALLOW_COPY_AND_ASSIGN(AutocompleteResult
);
210 #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_RESULT_H_