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 // This file contains the Search autocomplete provider. This provider is
6 // responsible for all autocomplete entries that start with "Search <engine>
7 // for ...", including searching for the current input string, search
8 // history, and search suggestions. An instance of it gets created and
9 // managed by the autocomplete controller.
11 #ifndef COMPONENTS_OMNIBOX_SEARCH_PROVIDER_H_
12 #define COMPONENTS_OMNIBOX_SEARCH_PROVIDER_H_
17 #include "base/basictypes.h"
18 #include "base/compiler_specific.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/time/time.h"
21 #include "base/timer/timer.h"
22 #include "components/metrics/proto/omnibox_input_type.pb.h"
23 #include "components/omnibox/answers_cache.h"
24 #include "components/omnibox/base_search_provider.h"
25 #include "components/search_engines/template_url.h"
26 #include "components/search_engines/template_url_service_observer.h"
27 #include "net/url_request/url_fetcher_delegate.h"
29 class AutocompleteProviderClient
;
30 class AutocompleteProviderListener
;
31 class AutocompleteResult
;
32 class SearchProviderTest
;
33 class TemplateURLService
;
36 struct KeywordSearchTermVisit
;
43 // Autocomplete provider for searches and suggestions from a search engine.
45 // After construction, the autocomplete controller repeatedly calls Start()
46 // with some user input, each time expecting to receive a small set of the best
47 // matches (either synchronously or asynchronously).
49 // Initially the provider creates a match that searches for the current input
50 // text. It also starts a task to query the Suggest servers. When that data
51 // comes back, the provider creates and returns matches for the best
53 class SearchProvider
: public BaseSearchProvider
,
54 public TemplateURLServiceObserver
,
55 public net::URLFetcherDelegate
{
57 SearchProvider(AutocompleteProviderListener
* listener
,
58 TemplateURLService
* template_url_service
,
59 scoped_ptr
<AutocompleteProviderClient
> client
);
61 // Extracts the suggest response metadata which SearchProvider previously
62 // stored for |match|.
63 static std::string
GetSuggestMetadata(const AutocompleteMatch
& match
);
65 // Answers prefetch handling - register displayed answers. Takes the top
66 // match for Autocomplete and registers the contained answer data, if any.
67 void RegisterDisplayedAnswers(const AutocompleteResult
& result
);
69 // AutocompleteProvider:
70 void ResetSession() override
;
72 // This URL may be sent with suggest requests; see comments on CanSendURL().
73 void set_current_page_url(const GURL
& current_page_url
) {
74 current_page_url_
= current_page_url
;
78 ~SearchProvider() override
;
81 friend class AutocompleteProviderTest
;
82 friend class SearchProviderTest
;
83 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, CanSendURL
);
84 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
,
85 DontInlineAutocompleteAsynchronously
);
86 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, NavigationInline
);
87 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, NavigationInlineDomainClassify
);
88 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, NavigationInlineSchemeSubstring
);
89 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, SuggestRelevanceExperiment
);
90 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, TestDeleteMatch
);
91 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, SuggestQueryUsesToken
);
92 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, SessionToken
);
93 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, AnswersCache
);
94 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, RemoveExtraAnswers
);
95 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest
, DoesNotProvideOnFocus
);
96 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest
, ClearPrefetchedResults
);
97 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest
, SetPrefetchQuery
);
99 // Manages the providers (TemplateURLs) used by SearchProvider. Two providers
101 // . The default provider. This corresponds to the user's default search
102 // engine. This is always used, except for the rare case of no default
104 // . The keyword provider. This is used if the user has typed in a keyword.
107 explicit Providers(TemplateURLService
* template_url_service
);
109 // Returns true if the specified providers match the two providers cached
111 bool equal(const base::string16
& default_provider
,
112 const base::string16
& keyword_provider
) const {
113 return (default_provider
== default_provider_
) &&
114 (keyword_provider
== keyword_provider_
);
117 // Resets the cached providers.
118 void set(const base::string16
& default_provider
,
119 const base::string16
& keyword_provider
) {
120 default_provider_
= default_provider
;
121 keyword_provider_
= keyword_provider
;
124 TemplateURLService
* template_url_service() { return template_url_service_
; }
125 const base::string16
& default_provider() const { return default_provider_
; }
126 const base::string16
& keyword_provider() const { return keyword_provider_
; }
128 // NOTE: These may return NULL even if the provider members are nonempty!
129 const TemplateURL
* GetDefaultProviderURL() const;
130 const TemplateURL
* GetKeywordProviderURL() const;
132 // Returns true if there is a valid keyword provider.
133 bool has_keyword_provider() const { return !keyword_provider_
.empty(); }
136 TemplateURLService
* template_url_service_
;
138 // Cached across the life of a query so we behave consistently even if the
139 // user changes their default while the query is running.
140 base::string16 default_provider_
;
141 base::string16 keyword_provider_
;
143 DISALLOW_COPY_AND_ASSIGN(Providers
);
146 class CompareScoredResults
;
148 typedef std::vector
<history::KeywordSearchTermVisit
> HistoryResults
;
150 // Calculates the relevance score for the keyword verbatim result (if the
151 // input matches one of the profile's keyword).
152 static int CalculateRelevanceForKeywordVerbatim(
153 metrics::OmniboxInputType::Type type
,
154 bool prefer_keyword
);
156 // A helper function for UpdateAllOldResults().
157 static void UpdateOldResults(bool minimal_changes
,
158 SearchSuggestionParser::Results
* results
);
160 // Returns the first match in |matches| which might be chosen as default.
161 static ACMatches::iterator
FindTopMatch(ACMatches
* matches
);
163 // AutocompleteProvider:
164 void Start(const AutocompleteInput
& input
,
165 bool minimal_changes
,
166 bool called_due_to_focus
) override
;
167 void Stop(bool clear_cached_results
,
168 bool due_to_user_inactivity
) override
;
170 // BaseSearchProvider:
171 const TemplateURL
* GetTemplateURL(bool is_keyword
) const override
;
172 const AutocompleteInput
GetInput(bool is_keyword
) const override
;
173 bool ShouldAppendExtraParams(
174 const SearchSuggestionParser::SuggestResult
& result
) const override
;
175 void RecordDeletionResult(bool success
) override
;
177 // TemplateURLServiceObserver:
178 void OnTemplateURLServiceChanged() override
;
180 // net::URLFetcherDelegate:
181 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
183 // Stops the suggest query.
184 // NOTE: This does not update |done_|. Callers must do so.
187 // Clears the current results.
188 void ClearAllResults();
190 // Recalculates the match contents class of |results| to better display
191 // against the current input and user's language.
192 void UpdateMatchContentsClass(const base::string16
& input_text
,
193 SearchSuggestionParser::Results
* results
);
195 // Called after ParseSuggestResults to rank the |results|.
196 void SortResults(bool is_keyword
, SearchSuggestionParser::Results
* results
);
198 // Records UMA statistics about a suggest server response.
199 void LogFetchComplete(bool success
, bool is_keyword
);
201 // Updates |matches_| from the latest results; applies calculated relevances
202 // if suggested relevances cause undesirable behavior. Updates |done_|.
203 void UpdateMatches();
205 // Called when |timer_| expires. Sends the suggest requests.
206 // If |query_is_private|, the function doesn't send this query to the default
208 void Run(bool query_is_private
);
210 // Runs the history query, if necessary. The history query is synchronous.
211 // This does not update |done_|.
212 void DoHistoryQuery(bool minimal_changes
);
214 // Returns the time to delay before sending the Suggest request.
215 base::TimeDelta
GetSuggestQueryDelay() const;
217 // Determines whether an asynchronous subcomponent query should run for the
218 // current input. If so, starts it if necessary; otherwise stops it.
219 // NOTE: This function does not update |done_|. Callers must do so.
220 void StartOrStopSuggestQuery(bool minimal_changes
);
222 // Stops |fetcher| if it's running. This includes resetting the scoped_ptr.
223 void CancelFetcher(scoped_ptr
<net::URLFetcher
>* fetcher
);
225 // Returns true when the current query can be sent to at least one suggest
226 // service. This will be false for example when suggest is disabled. In
227 // the process, calculates whether the query may contain potentionally
228 // private data and stores the result in |is_query_private|; such queries
229 // should not be sent to the default search engine.
230 bool IsQuerySuitableForSuggest(bool* query_is_private
) const;
232 // Returns true if sending the query to a suggest server may leak sensitive
233 // information (and hence the suggest request shouldn't be sent).
234 bool IsQueryPotentionallyPrivate() const;
236 // Remove existing keyword results if the user is no longer in keyword mode,
237 // and, if |minimal_changes| is false, revise the existing results to
238 // indicate they were received before the last keystroke.
239 void UpdateAllOldResults(bool minimal_changes
);
241 // Given new asynchronous results, ensure that we don't clobber the current
242 // top results, which were determined synchronously on the last keystroke.
243 void PersistTopSuggestions(SearchSuggestionParser::Results
* results
);
245 // Apply calculated relevance scores to the current results.
246 void ApplyCalculatedSuggestRelevance(
247 SearchSuggestionParser::SuggestResults
* list
);
248 void ApplyCalculatedNavigationRelevance(
249 SearchSuggestionParser::NavigationResults
* list
);
251 // Starts a new URLFetcher requesting suggest results from |template_url|;
252 // callers own the returned URLFetcher, which is NULL for invalid providers.
253 net::URLFetcher
* CreateSuggestFetcher(int id
,
254 const TemplateURL
* template_url
,
255 const AutocompleteInput
& input
);
257 // Converts the parsed results to a set of AutocompleteMatches, |matches_|.
258 void ConvertResultsToAutocompleteMatches();
260 // Remove answer contents from each match in |matches| other than the first
262 static void RemoveExtraAnswers(ACMatches
* matches
);
264 // Returns an iterator to the first match in |matches_| which might
265 // be chosen as default.
266 ACMatches::const_iterator
FindTopMatch() const;
268 // Checks if suggested relevances violate an expected constraint.
269 // See UpdateMatches() for the use and explanation of this constraint
270 // and other constraints enforced without the use of helper functions.
271 bool IsTopMatchSearchWithURLInput() const;
273 // Converts an appropriate number of navigation results in
274 // |navigation_results| to matches and adds them to |matches|.
275 void AddNavigationResultsToMatches(
276 const SearchSuggestionParser::NavigationResults
& navigation_results
,
279 // Adds a match for each result in |raw_default_history_results_| or
280 // |raw_keyword_history_results_| to |map|. |is_keyword| indicates
281 // which one of the two.
282 void AddRawHistoryResultsToMap(bool is_keyword
,
283 int did_not_accept_suggestion
,
286 // Adds a match for each transformed result in |results| to |map|.
287 void AddTransformedHistoryResultsToMap(
288 const SearchSuggestionParser::SuggestResults
& results
,
289 int did_not_accept_suggestion
,
292 // Calculates relevance scores for all |results|.
293 SearchSuggestionParser::SuggestResults
ScoreHistoryResultsHelper(
294 const HistoryResults
& results
,
295 bool base_prevent_inline_autocomplete
,
296 bool input_multiple_words
,
297 const base::string16
& input_text
,
300 // Calculates relevance scores for |results|, adjusting for boundary
301 // conditions around multi-word queries. (See inline comments in function
302 // definition for more details.)
303 void ScoreHistoryResults(
304 const HistoryResults
& results
,
306 SearchSuggestionParser::SuggestResults
* scored_results
);
308 // Adds matches for |results| to |map|.
309 void AddSuggestResultsToMap(
310 const SearchSuggestionParser::SuggestResults
& results
,
311 const std::string
& metadata
,
314 // Gets the relevance score for the verbatim result. This value may be
315 // provided by the suggest server or calculated locally; if
316 // |relevance_from_server| is non-null, it will be set to indicate which of
318 int GetVerbatimRelevance(bool* relevance_from_server
) const;
320 // Calculates the relevance score for the verbatim result from the
321 // default search engine. This version takes into account context:
322 // i.e., whether the user has entered a keyword-based search or not.
323 int CalculateRelevanceForVerbatim() const;
325 // Calculates the relevance score for the verbatim result from the default
326 // search engine *ignoring* whether the input is a keyword-based search
327 // or not. This function should only be used to determine the minimum
328 // relevance score that the best result from this provider should have.
329 // For normal use, prefer the above function.
330 int CalculateRelevanceForVerbatimIgnoringKeywordModeState() const;
332 // Gets the relevance score for the keyword verbatim result.
333 // |relevance_from_server| is handled as in GetVerbatimRelevance().
334 // TODO(mpearson): Refactor so this duplication isn't necessary or
335 // restructure so one static function takes all the parameters it needs
336 // (rather than looking at internal state).
337 int GetKeywordVerbatimRelevance(bool* relevance_from_server
) const;
339 // |time| is the time at which this query was last seen. |is_keyword|
340 // indicates whether the results correspond to the keyword provider or default
341 // provider. |use_aggressive_method| says whether this function can use a
342 // method that gives high scores (1200+) rather than one that gives lower
343 // scores. When using the aggressive method, scores may exceed 1300
344 // unless |prevent_search_history_inlining| is set.
345 int CalculateRelevanceForHistory(const base::Time
& time
,
347 bool use_aggressive_method
,
348 bool prevent_search_history_inlining
) const;
350 // Returns an AutocompleteMatch for a navigational suggestion.
351 AutocompleteMatch
NavigationToMatch(
352 const SearchSuggestionParser::NavigationResult
& navigation
);
354 // Updates the value of |done_| from the internal state.
357 // Obtains a session token, regenerating if necessary.
358 std::string
GetSessionToken();
360 // Answers prefetch handling - finds the previously displayed answer matching
361 // the current top-scoring history result. If there is a previous answer,
362 // returns the query data associated with it. Otherwise, returns an empty
364 AnswersQueryData
FindAnswersPrefetchData();
366 AutocompleteProviderListener
* listener_
;
368 // Maintains the TemplateURLs used.
369 Providers providers_
;
372 AutocompleteInput input_
;
374 // Input when searching against the keyword provider.
375 AutocompleteInput keyword_input_
;
377 // Searches in the user's history that begin with the input text.
378 HistoryResults raw_keyword_history_results_
;
379 HistoryResults raw_default_history_results_
;
381 // Scored searches in the user's history - based on |keyword_history_results_|
382 // or |default_history_results_| as appropriate.
383 SearchSuggestionParser::SuggestResults transformed_keyword_history_results_
;
384 SearchSuggestionParser::SuggestResults transformed_default_history_results_
;
386 // A timer to start a query to the suggest server after the user has stopped
387 // typing for long enough.
388 base::OneShotTimer
<SearchProvider
> timer_
;
390 // The time at which we sent a query to the suggest server.
391 base::TimeTicks time_suggest_request_sent_
;
393 // Fetchers used to retrieve results for the keyword and default providers.
394 // After a fetcher's results are returned, it gets reset, so a non-null
395 // fetcher indicates that fetcher is still in flight.
396 scoped_ptr
<net::URLFetcher
> keyword_fetcher_
;
397 scoped_ptr
<net::URLFetcher
> default_fetcher_
;
399 // Results from the default and keyword search providers.
400 SearchSuggestionParser::Results default_results_
;
401 SearchSuggestionParser::Results keyword_results_
;
403 // The top query suggestion, left blank if none.
404 base::string16 top_query_suggestion_match_contents_
;
405 // The top navigation suggestion, left blank/invalid if none.
406 GURL top_navigation_suggestion_
;
408 GURL current_page_url_
;
410 // Session token management.
411 std::string current_token_
;
412 base::TimeTicks token_expiration_time_
;
414 // Answers prefetch management.
415 AnswersCache answers_cache_
; // Cache for last answers seen.
416 AnswersQueryData prefetch_data_
; // Data to use for query prefetching.
418 DISALLOW_COPY_AND_ASSIGN(SearchProvider
);
421 #endif // COMPONENTS_OMNIBOX_SEARCH_PROVIDER_H_