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 CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_
12 #define CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_
14 #include "base/basictypes.h"
15 #include "base/compiler_specific.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/time/time.h"
18 #include "base/timer/timer.h"
19 #include "chrome/browser/autocomplete/base_search_provider.h"
20 #include "components/metrics/proto/omnibox_input_type.pb.h"
21 #include "components/search_engines/template_url.h"
22 #include "net/url_request/url_fetcher_delegate.h"
24 class AutocompleteProviderListener;
25 class AutocompleteResult;
27 class SearchProviderTest;
28 class TemplateURLService;
31 struct KeywordSearchTermVisit;
38 // Autocomplete provider for searches and suggestions from a search engine.
40 // After construction, the autocomplete controller repeatedly calls Start()
41 // with some user input, each time expecting to receive a small set of the best
42 // matches (either synchronously or asynchronously).
44 // Initially the provider creates a match that searches for the current input
45 // text. It also starts a task to query the Suggest servers. When that data
46 // comes back, the provider creates and returns matches for the best
48 class SearchProvider : public BaseSearchProvider,
49 public net::URLFetcherDelegate {
51 SearchProvider(AutocompleteProviderListener* listener,
52 TemplateURLService* template_url_service,
55 // Extracts the suggest response metadata which SearchProvider previously
56 // stored for |match|.
57 static std::string GetSuggestMetadata(const AutocompleteMatch& match);
59 // Answers prefetch handling - register displayed answers. Takes the top
60 // match for Autocomplete and registers the contained answer data, if any.
61 void RegisterDisplayedAnswers(const AutocompleteResult& result);
63 // AutocompleteProvider:
64 virtual void ResetSession() OVERRIDE;
66 // This URL may be sent with suggest requests; see comments on CanSendURL().
67 void set_current_page_url(const GURL& current_page_url) {
68 current_page_url_ = current_page_url;
72 virtual ~SearchProvider();
75 friend class SearchProviderTest;
76 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, CanSendURL);
77 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInline);
78 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInlineDomainClassify);
79 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInlineSchemeSubstring);
80 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, RemoveStaleResultsTest);
81 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestRelevanceExperiment);
82 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, TestDeleteMatch);
83 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestQueryUsesToken);
84 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SessionToken);
85 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, AnswersCache);
86 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL);
87 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest, ClearPrefetchedResults);
88 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest, SetPrefetchQuery);
90 // Manages the providers (TemplateURLs) used by SearchProvider. Two providers
92 // . The default provider. This corresponds to the user's default search
93 // engine. This is always used, except for the rare case of no default
95 // . The keyword provider. This is used if the user has typed in a keyword.
98 explicit Providers(TemplateURLService* template_url_service);
100 // Returns true if the specified providers match the two providers cached
102 bool equal(const base::string16& default_provider,
103 const base::string16& keyword_provider) const {
104 return (default_provider == default_provider_) &&
105 (keyword_provider == keyword_provider_);
108 // Resets the cached providers.
109 void set(const base::string16& default_provider,
110 const base::string16& keyword_provider) {
111 default_provider_ = default_provider;
112 keyword_provider_ = keyword_provider;
115 TemplateURLService* template_url_service() { return template_url_service_; }
116 const base::string16& default_provider() const { return default_provider_; }
117 const base::string16& keyword_provider() const { return keyword_provider_; }
119 // NOTE: These may return NULL even if the provider members are nonempty!
120 const TemplateURL* GetDefaultProviderURL() const;
121 const TemplateURL* GetKeywordProviderURL() const;
123 // Returns true if there is a valid keyword provider.
124 bool has_keyword_provider() const { return !keyword_provider_.empty(); }
127 TemplateURLService* template_url_service_;
129 // Cached across the life of a query so we behave consistently even if the
130 // user changes their default while the query is running.
131 base::string16 default_provider_;
132 base::string16 keyword_provider_;
134 DISALLOW_COPY_AND_ASSIGN(Providers);
137 class CompareScoredResults;
139 struct AnswersQueryData {
140 base::string16 full_query_text;
141 base::string16 query_type;
144 typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
146 // Removes non-inlineable results until either the top result can inline
147 // autocomplete the current input or verbatim outscores the top result.
148 static void RemoveStaleResults(
149 const base::string16& input,
150 int verbatim_relevance,
151 SearchSuggestionParser::SuggestResults* suggest_results,
152 SearchSuggestionParser::NavigationResults* navigation_results);
154 // Calculates the relevance score for the keyword verbatim result (if the
155 // input matches one of the profile's keyword).
156 static int CalculateRelevanceForKeywordVerbatim(
157 metrics::OmniboxInputType::Type type,
158 bool prefer_keyword);
160 // AutocompleteProvider:
161 virtual void Start(const AutocompleteInput& input,
162 bool minimal_changes) OVERRIDE;
164 // BaseSearchProvider:
165 virtual const TemplateURL* GetTemplateURL(bool is_keyword) const OVERRIDE;
166 virtual const AutocompleteInput GetInput(bool is_keyword) const OVERRIDE;
167 virtual bool ShouldAppendExtraParams(
168 const SearchSuggestionParser::SuggestResult& result) const OVERRIDE;
169 virtual void StopSuggest() OVERRIDE;
170 virtual void ClearAllResults() OVERRIDE;
171 virtual void RecordDeletionResult(bool success) OVERRIDE;
173 // net::URLFetcherDelegate:
174 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
176 // Recalculates the match contents class of |results| to better display
177 // against the current input and user's language.
178 void UpdateMatchContentsClass(const base::string16& input_text,
179 SearchSuggestionParser::Results* results);
181 // Called after ParseSuggestResults to rank the |results|.
182 void SortResults(bool is_keyword, SearchSuggestionParser::Results* results);
184 // Records UMA statistics about a suggest server response.
185 void LogFetchComplete(bool success, bool is_keyword);
187 // Updates |matches_| from the latest results; applies calculated relevances
188 // if suggested relevances cause undesirable behavior. Updates |done_|.
189 void UpdateMatches();
191 // Called when timer_ expires.
194 // Runs the history query, if necessary. The history query is synchronous.
195 // This does not update |done_|.
196 void DoHistoryQuery(bool minimal_changes);
198 // Determines whether an asynchronous subcomponent query should run for the
199 // current input. If so, starts it if necessary; otherwise stops it.
200 // NOTE: This function does not update |done_|. Callers must do so.
201 void StartOrStopSuggestQuery(bool minimal_changes);
203 // Returns true when the current query can be sent to the Suggest service.
204 // This will be false e.g. when Suggest is disabled, the query contains
205 // potentially private data, etc.
206 bool IsQuerySuitableForSuggest() const;
208 // Removes stale results for both default and keyword providers. See comments
209 // on RemoveStaleResults().
210 void RemoveAllStaleResults();
212 // Apply calculated relevance scores to the current results.
213 void ApplyCalculatedRelevance();
214 void ApplyCalculatedSuggestRelevance(
215 SearchSuggestionParser::SuggestResults* list);
216 void ApplyCalculatedNavigationRelevance(
217 SearchSuggestionParser::NavigationResults* list);
219 // Starts a new URLFetcher requesting suggest results from |template_url|;
220 // callers own the returned URLFetcher, which is NULL for invalid providers.
221 net::URLFetcher* CreateSuggestFetcher(int id,
222 const TemplateURL* template_url,
223 const AutocompleteInput& input);
225 // Converts the parsed results to a set of AutocompleteMatches, |matches_|.
226 void ConvertResultsToAutocompleteMatches();
228 // Returns an iterator to the first match in |matches_| which might
229 // be chosen as default.
230 ACMatches::const_iterator FindTopMatch() const;
232 // Checks if suggested relevances violate an expected constraint.
233 // See UpdateMatches() for the use and explanation of this constraint
234 // and other constraints enforced without the use of helper functions.
235 bool IsTopMatchSearchWithURLInput() const;
237 // Converts an appropriate number of navigation results in
238 // |navigation_results| to matches and adds them to |matches|.
239 void AddNavigationResultsToMatches(
240 const SearchSuggestionParser::NavigationResults& navigation_results,
243 // Adds a match for each result in |results| to |map|. |is_keyword| indicates
244 // whether the results correspond to the keyword provider or default provider.
245 void AddHistoryResultsToMap(const HistoryResults& results,
247 int did_not_accept_suggestion,
250 // Calculates relevance scores for all |results|.
251 SearchSuggestionParser::SuggestResults ScoreHistoryResults(
252 const HistoryResults& results,
253 bool base_prevent_inline_autocomplete,
254 bool input_multiple_words,
255 const base::string16& input_text,
258 // Adds matches for |results| to |map|.
259 void AddSuggestResultsToMap(
260 const SearchSuggestionParser::SuggestResults& results,
261 const std::string& metadata,
264 // Gets the relevance score for the verbatim result. This value may be
265 // provided by the suggest server or calculated locally; if
266 // |relevance_from_server| is non-NULL, it will be set to indicate which of
268 int GetVerbatimRelevance(bool* relevance_from_server) const;
270 // Calculates the relevance score for the verbatim result from the
271 // default search engine. This version takes into account context:
272 // i.e., whether the user has entered a keyword-based search or not.
273 int CalculateRelevanceForVerbatim() const;
275 // Calculates the relevance score for the verbatim result from the default
276 // search engine *ignoring* whether the input is a keyword-based search
277 // or not. This function should only be used to determine the minimum
278 // relevance score that the best result from this provider should have.
279 // For normal use, prefer the above function.
280 int CalculateRelevanceForVerbatimIgnoringKeywordModeState() const;
282 // Gets the relevance score for the keyword verbatim result.
283 // |relevance_from_server| is handled as in GetVerbatimRelevance().
284 // TODO(mpearson): Refactor so this duplication isn't necessary or
285 // restructure so one static function takes all the parameters it needs
286 // (rather than looking at internal state).
287 int GetKeywordVerbatimRelevance(bool* relevance_from_server) const;
289 // |time| is the time at which this query was last seen. |is_keyword|
290 // indicates whether the results correspond to the keyword provider or default
291 // provider. |use_aggressive_method| says whether this function can use a
292 // method that gives high scores (1200+) rather than one that gives lower
293 // scores. When using the aggressive method, scores may exceed 1300
294 // unless |prevent_search_history_inlining| is set.
295 int CalculateRelevanceForHistory(const base::Time& time,
297 bool use_aggressive_method,
298 bool prevent_search_history_inlining) const;
300 // Returns an AutocompleteMatch for a navigational suggestion.
301 AutocompleteMatch NavigationToMatch(
302 const SearchSuggestionParser::NavigationResult& navigation);
304 // Updates the value of |done_| from the internal state.
307 // Obtains a session token, regenerating if necessary.
308 std::string GetSessionToken();
310 // Answers prefetch handling - finds previously displayed answer matching the
311 // current |input| and sets |prefetch_data_|.
312 void DoAnswersQuery(const AutocompleteInput& input);
314 // The amount of time to wait before sending a new suggest request after the
315 // previous one. Non-const because some unittests modify this value.
316 static int kMinimumTimeBetweenSuggestQueriesMs;
318 AutocompleteProviderListener* listener_;
320 // The number of suggest results that haven't yet arrived. If it's greater
321 // than 0, it indicates that one of the URLFetchers is still running.
322 int suggest_results_pending_;
324 // Maintains the TemplateURLs used.
325 Providers providers_;
328 AutocompleteInput input_;
330 // Input when searching against the keyword provider.
331 AutocompleteInput keyword_input_;
333 // Searches in the user's history that begin with the input text.
334 HistoryResults keyword_history_results_;
335 HistoryResults default_history_results_;
337 // A timer to start a query to the suggest server after the user has stopped
338 // typing for long enough.
339 base::OneShotTimer<SearchProvider> timer_;
341 // The time at which we sent a query to the suggest server.
342 base::TimeTicks time_suggest_request_sent_;
344 // Fetchers used to retrieve results for the keyword and default providers.
345 scoped_ptr<net::URLFetcher> keyword_fetcher_;
346 scoped_ptr<net::URLFetcher> default_fetcher_;
348 // Results from the default and keyword search providers.
349 SearchSuggestionParser::Results default_results_;
350 SearchSuggestionParser::Results keyword_results_;
352 GURL current_page_url_;
354 // Session token management.
355 std::string current_token_;
356 base::TimeTicks token_expiration_time_;
358 // Answers prefetch management.
359 AnswersQueryData prefetch_data_; // Data to use for query prefetching.
360 AnswersQueryData last_answer_seen_; // Last answer seen.
362 DISALLOW_COPY_AND_ASSIGN(SearchProvider);
365 #endif // CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_