OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ | 5 #ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ |
6 #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ | 6 #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/logging.h" | |
13 #include "base/string16.h" | 12 #include "base/string16.h" |
14 #include "base/time.h" | |
15 #include "base/timer.h" | |
16 #include "chrome/browser/autocomplete/autocomplete_types.h" | |
17 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
18 #include "googleurl/src/url_parse.h" | 14 #include "googleurl/src/url_parse.h" |
19 | 15 |
20 // The AutocompleteController is the center of the autocomplete system. A | |
21 // class creates an instance of the controller, which in turn creates a set of | |
22 // AutocompleteProviders to serve it. The owning class can ask the controller | |
23 // to Start() a query; the controller in turn passes this call down to the | |
24 // providers, each of which keeps track of its own matches and whether it has | |
25 // finished processing the query. When a provider gets more matches or finishes | |
26 // processing, it notifies the controller, which merges the combined matches | |
27 // together and makes the result available to interested observers. | |
28 // | |
29 // The owner may also cancel the current query by calling Stop(), which the | |
30 // controller will in turn communicate to all the providers. No callbacks will | |
31 // happen after a request has been stopped. | |
32 // | |
33 // IMPORTANT: There is NO THREAD SAFETY built into this portion of the | |
34 // autocomplete system. All calls to and from the AutocompleteController should | |
35 // happen on the same thread. AutocompleteProviders are responsible for doing | |
36 // their own thread management when they need to return matches asynchronously. | |
37 // | |
38 // The AutocompleteProviders each return different kinds of matches, | |
39 // such as history or search matches. These matches are given | |
40 // "relevance" scores. Higher scores are better matches than lower | |
41 // scores. The relevance scores and classes providing the respective | |
42 // matches are as listed below. | |
43 // | |
44 // IMPORTANT CAVEAT: The tables below are NOT COMPLETE. Developers | |
45 // often forget to keep these tables in sync with the code when they | |
46 // change scoring algorithms or add new providers. For example, | |
47 // neither the HistoryQuickProvider (which is a provider that appears | |
48 // often) nor the ShortcutsProvider are listed here. For the best | |
49 // idea of how scoring works and what providers are affecting which | |
50 // queries, play with chrome://omnibox/ for a while. While the tables | |
51 // below may have some utility, nothing compares with first-hand | |
52 // investigation and experience. | |
53 // | |
54 // UNKNOWN input type: | |
55 // --------------------------------------------------------------------|----- | |
56 // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 | |
57 // Extension App (exact match) | 1425 | |
58 // HistoryURL (good exact or inline autocomplete matches, some inexact)| 1410++ | |
59 // HistoryURL (intranet url never visited match, some inexact matches) | 1400++ | |
60 // Search Primary Provider (past query in history within 2 days) | 1399** | |
61 // Search Primary Provider (what you typed) | 1300 | |
62 // HistoryURL (what you typed, some inexact matches) | 1200++ | |
63 // Extension App (inexact match) | 1175*~ | |
64 // Keyword (substituting, exact match) | 1100 | |
65 // Search Primary Provider (past query in history older than 2 days) | 1050-- | |
66 // HistoryContents (any match in title of starred page) | 1000++ | |
67 // HistoryURL (some inexact matches) | 900++ | |
68 // Search Primary Provider (navigational suggestion) | 800++ | |
69 // HistoryContents (any match in title of nonstarred page) | 700++ | |
70 // Search Primary Provider (suggestion) | 600++ | |
71 // Built-in | 575++ | |
72 // HistoryContents (any match in body of starred page) | 550++ | |
73 // HistoryContents (any match in body of nonstarred page) | 500++ | |
74 // Keyword (inexact match) | 450 | |
75 // Search Secondary Provider (what you typed) | 250 | |
76 // Search Secondary Provider (past query in history) | 200-- | |
77 // Search Secondary Provider (navigational suggestion) | 150++ | |
78 // Search Secondary Provider (suggestion) | 100++ | |
79 // | |
80 // REQUESTED_URL input type: | |
81 // --------------------------------------------------------------------|----- | |
82 // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 | |
83 // Extension App (exact match) | 1425 | |
84 // HistoryURL (good exact or inline autocomplete matches, some inexact)| 1410++ | |
85 // HistoryURL (intranet url never visited match, some inexact matches) | 1400++ | |
86 // Search Primary Provider (past query in history within 2 days) | 1399** | |
87 // HistoryURL (what you typed, some inexact matches) | 1200++ | |
88 // Extension App (inexact match) | 1175*~ | |
89 // Search Primary Provider (what you typed) | 1150 | |
90 // Keyword (substituting, exact match) | 1100 | |
91 // Search Primary Provider (past query in history older than 2 days) | 1050-- | |
92 // HistoryContents (any match in title of starred page) | 1000++ | |
93 // HistoryURL (some inexact matches) | 900++ | |
94 // Search Primary Provider (navigational suggestion) | 800++ | |
95 // HistoryContents (any match in title of nonstarred page) | 700++ | |
96 // Search Primary Provider (suggestion) | 600++ | |
97 // Built-in | 575++ | |
98 // HistoryContents (any match in body of starred page) | 550++ | |
99 // HistoryContents (any match in body of nonstarred page) | 500++ | |
100 // Keyword (inexact match) | 450 | |
101 // Search Secondary Provider (what you typed) | 250 | |
102 // Search Secondary Provider (past query in history) | 200-- | |
103 // Search Secondary Provider (navigational suggestion) | 150++ | |
104 // Search Secondary Provider (suggestion) | 100++ | |
105 // | |
106 // URL input type: | |
107 // --------------------------------------------------------------------|----- | |
108 // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 | |
109 // Extension App (exact match) | 1425 | |
110 // HistoryURL (good exact or inline autocomplete matches, some inexact)| 1410++ | |
111 // HistoryURL (intranet url never visited match, some inexact matches) | 1400++ | |
112 // HistoryURL (what you typed, some inexact matches) | 1200++ | |
113 // Extension App (inexact match) | 1175*~ | |
114 // Keyword (substituting, exact match) | 1100 | |
115 // HistoryURL (some inexact matches) | 900++ | |
116 // Search Primary Provider (what you typed) | 850 | |
117 // Search Primary Provider (navigational suggestion) | 800++ | |
118 // Search Primary Provider (past query in history) | 750-- | |
119 // Keyword (inexact match) | 700 | |
120 // Built-in | 575++ | |
121 // Search Primary Provider (suggestion) | 300++ | |
122 // Search Secondary Provider (what you typed) | 250 | |
123 // Search Secondary Provider (past query in history) | 200-- | |
124 // Search Secondary Provider (navigational suggestion) | 150++ | |
125 // Search Secondary Provider (suggestion) | 100++ | |
126 // | |
127 // QUERY input type: | |
128 // --------------------------------------------------------------------|----- | |
129 // Search Primary or Secondary (past query in history within 2 days) | 1599** | |
130 // Keyword (non-substituting or in keyword UI mode, exact match) | 1500 | |
131 // Keyword (substituting, exact match) | 1450 | |
132 // Extension App (exact match) | 1425 | |
133 // Search Primary Provider (past query in history within 2 days) | 1399** | |
134 // Search Primary Provider (what you typed) | 1300 | |
135 // Extension App (inexact match) | 1175*~ | |
136 // Search Primary Provider (past query in history older than 2 days) | 1050-- | |
137 // HistoryContents (any match in title of starred page) | 1000++ | |
138 // HistoryURL (inexact match) | 900++ | |
139 // Search Primary Provider (navigational suggestion) | 800++ | |
140 // HistoryContents (any match in title of nonstarred page) | 700++ | |
141 // Search Primary Provider (suggestion) | 600++ | |
142 // HistoryContents (any match in body of starred page) | 550++ | |
143 // HistoryContents (any match in body of nonstarred page) | 500++ | |
144 // Keyword (inexact match) | 450 | |
145 // Search Secondary Provider (what you typed) | 250 | |
146 // Search Secondary Provider (past query in history) | 200-- | |
147 // Search Secondary Provider (navigational suggestion) | 150++ | |
148 // Search Secondary Provider (suggestion) | 100++ | |
149 // | |
150 // FORCED_QUERY input type: | |
151 // --------------------------------------------------------------------|----- | |
152 // Extension App (exact match on title only, not url) | 1425 | |
153 // Search Primary Provider (past query in history within 2 days) | 1399** | |
154 // Search Primary Provider (what you typed) | 1300 | |
155 // Extension App (inexact match on title only, not url) | 1175*~ | |
156 // Search Primary Provider (past query in history older than 2 days) | 1050-- | |
157 // HistoryContents (any match in title of starred page) | 1000++ | |
158 // Search Primary Provider (navigational suggestion) | 800++ | |
159 // HistoryContents (any match in title of nonstarred page) | 700++ | |
160 // Search Primary Provider (suggestion) | 600++ | |
161 // HistoryContents (any match in body of starred page) | 550++ | |
162 // HistoryContents (any match in body of nonstarred page) | 500++ | |
163 // | |
164 // (A search keyword is a keyword with a replacement string; a bookmark keyword | |
165 // is a keyword with no replacement string, that is, a shortcut for a URL.) | |
166 // | |
167 // There are two possible providers for search suggestions. If the user has | |
168 // typed a keyword, then the primary provider is the keyword provider and the | |
169 // secondary provider is the default provider. If the user has not typed a | |
170 // keyword, then the primary provider corresponds to the default provider. | |
171 // | |
172 // Search providers may supply relevance values along with their results to be | |
173 // used in place of client-side calculated values. | |
174 // | |
175 // The value column gives the ranking returned from the various providers. | |
176 // ++: a series of matches with relevance from n up to (n + max_matches). | |
177 // --: relevance score falls off over time (discounted 50 points @ 15 minutes, | |
178 // 450 points @ two weeks) | |
179 // **: relevance score falls off over two days (discounted 99 points after two | |
180 // days). | |
181 // *~: Partial matches get a score on a sliding scale from about 575-1125 based | |
182 // on how many times the URL for the Extension App has been typed and how | |
183 // many of the letters match. | |
184 | |
185 struct AutocompleteMatch; | |
186 class AutocompleteProvider; | |
187 | |
188 // AutocompleteInput ---------------------------------------------------------- | |
189 | |
190 // The user input for an autocomplete query. Allows copying. | 16 // The user input for an autocomplete query. Allows copying. |
191 class AutocompleteInput { | 17 class AutocompleteInput { |
192 public: | 18 public: |
193 // Note that the type below may be misleading. For example, "http:/" alone | 19 // Note that the type below may be misleading. For example, "http:/" alone |
194 // cannot be opened as a URL, so it is marked as a QUERY; yet the user | 20 // cannot be opened as a URL, so it is marked as a QUERY; yet the user |
195 // probably intends to type more and have it eventually become a URL, so we | 21 // probably intends to type more and have it eventually become a URL, so we |
196 // need to make sure we still run it through inline autocomplete. | 22 // need to make sure we still run it through inline autocomplete. |
197 enum Type { | 23 enum Type { |
198 INVALID, // Empty input | 24 INVALID, // Empty input |
199 UNKNOWN, // Valid input whose type cannot be determined | 25 UNKNOWN, // Valid input whose type cannot be determined |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 Type type_; | 151 Type type_; |
326 url_parse::Parsed parts_; | 152 url_parse::Parsed parts_; |
327 string16 scheme_; | 153 string16 scheme_; |
328 GURL canonicalized_url_; | 154 GURL canonicalized_url_; |
329 bool prevent_inline_autocomplete_; | 155 bool prevent_inline_autocomplete_; |
330 bool prefer_keyword_; | 156 bool prefer_keyword_; |
331 bool allow_exact_keyword_match_; | 157 bool allow_exact_keyword_match_; |
332 MatchesRequested matches_requested_; | 158 MatchesRequested matches_requested_; |
333 }; | 159 }; |
334 | 160 |
335 // AutocompleteResult --------------------------------------------------------- | |
336 | |
337 // All matches from all providers for a particular query. This also tracks | |
338 // what the default match should be if the user doesn't manually select another | |
339 // match. | |
340 class AutocompleteResult { | |
341 public: | |
342 typedef ACMatches::const_iterator const_iterator; | |
343 typedef ACMatches::iterator iterator; | |
344 | |
345 // The "Selection" struct is the information we need to select the same match | |
346 // in one result set that was selected in another. | |
347 struct Selection { | |
348 Selection() | |
349 : provider_affinity(NULL), | |
350 is_history_what_you_typed_match(false) { | |
351 } | |
352 | |
353 // Clear the selection entirely. | |
354 void Clear(); | |
355 | |
356 // True when the selection is empty. | |
357 bool empty() const { | |
358 return destination_url.is_empty() && !provider_affinity && | |
359 !is_history_what_you_typed_match; | |
360 } | |
361 | |
362 // The desired destination URL. | |
363 GURL destination_url; | |
364 | |
365 // The desired provider. If we can't find a match with the specified | |
366 // |destination_url|, we'll use the best match from this provider. | |
367 const AutocompleteProvider* provider_affinity; | |
368 | |
369 // True when this is the HistoryURLProvider's "what you typed" match. This | |
370 // can't be tracked using |destination_url| because its URL changes on every | |
371 // keystroke, so if this is set, we'll preserve the selection by simply | |
372 // choosing the new "what you typed" entry and ignoring |destination_url|. | |
373 bool is_history_what_you_typed_match; | |
374 }; | |
375 | |
376 // Max number of matches we'll show from the various providers. | |
377 static const size_t kMaxMatches; | |
378 | |
379 // The lowest score a match can have and still potentially become the default | |
380 // match for the result set. | |
381 static const int kLowestDefaultScore; | |
382 | |
383 AutocompleteResult(); | |
384 ~AutocompleteResult(); | |
385 | |
386 // operator=() by another name. | |
387 void CopyFrom(const AutocompleteResult& rhs); | |
388 | |
389 // Copies matches from |old_matches| to provide a consistant result set. See | |
390 // comments in code for specifics. | |
391 void CopyOldMatches(const AutocompleteInput& input, | |
392 const AutocompleteResult& old_matches); | |
393 | |
394 // Adds a single match. The match is inserted at the appropriate position | |
395 // based on relevancy and display order. This is ONLY for use after | |
396 // SortAndCull() has been invoked, and preserves default_match_. | |
397 void AddMatch(const AutocompleteMatch& match); | |
398 | |
399 // Adds a new set of matches to the result set. Does not re-sort. | |
400 void AppendMatches(const ACMatches& matches); | |
401 | |
402 // Removes duplicates, puts the list in sorted order and culls to leave only | |
403 // the best kMaxMatches matches. Sets the default match to the best match | |
404 // and updates the alternate nav URL. | |
405 void SortAndCull(const AutocompleteInput& input); | |
406 | |
407 // Returns true if at least one match was copied from the last result. | |
408 bool HasCopiedMatches() const; | |
409 | |
410 // Vector-style accessors/operators. | |
411 size_t size() const; | |
412 bool empty() const; | |
413 const_iterator begin() const; | |
414 iterator begin(); | |
415 const_iterator end() const; | |
416 iterator end(); | |
417 | |
418 // Returns the match at the given index. | |
419 const AutocompleteMatch& match_at(size_t index) const; | |
420 AutocompleteMatch* match_at(size_t index); | |
421 | |
422 // Get the default match for the query (not necessarily the first). Returns | |
423 // end() if there is no default match. | |
424 const_iterator default_match() const { return default_match_; } | |
425 | |
426 const GURL& alternate_nav_url() const { return alternate_nav_url_; } | |
427 | |
428 // Clears the matches for this result set. | |
429 void Reset(); | |
430 | |
431 void Swap(AutocompleteResult* other); | |
432 | |
433 #ifndef NDEBUG | |
434 // Does a data integrity check on this result. | |
435 void Validate() const; | |
436 #endif | |
437 | |
438 private: | |
439 typedef std::map<AutocompleteProvider*, ACMatches> ProviderToMatches; | |
440 | |
441 #if defined(OS_ANDROID) | |
442 // iterator::difference_type is not defined in the STL that we compile with on | |
443 // Android. | |
444 typedef int matches_difference_type; | |
445 #else | |
446 typedef ACMatches::iterator::difference_type matches_difference_type; | |
447 #endif | |
448 | |
449 // Populates |provider_to_matches| from |matches_|. | |
450 void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const; | |
451 | |
452 // Returns true if |matches| contains a match with the same destination as | |
453 // |match|. | |
454 static bool HasMatchByDestination(const AutocompleteMatch& match, | |
455 const ACMatches& matches); | |
456 | |
457 // Copies matches into this result. |old_matches| gives the matches from the | |
458 // last result, and |new_matches| the results from this result. | |
459 void MergeMatchesByProvider(const ACMatches& old_matches, | |
460 const ACMatches& new_matches); | |
461 | |
462 ACMatches matches_; | |
463 | |
464 const_iterator default_match_; | |
465 | |
466 // The "alternate navigation URL", if any, for this result set. This is a URL | |
467 // to try offering as a navigational option in case the user navigated to the | |
468 // URL of the default match but intended something else. For example, if the | |
469 // user's local intranet contains site "foo", and the user types "foo", we | |
470 // default to searching for "foo" when the user may have meant to navigate | |
471 // there. In cases like this, the default match will point to the "search for | |
472 // 'foo'" result, and this will contain "http://foo/". | |
473 GURL alternate_nav_url_; | |
474 | |
475 DISALLOW_COPY_AND_ASSIGN(AutocompleteResult); | |
476 }; | |
477 | |
478 #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ | 161 #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H_ |
OLD | NEW |