search_provider.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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// This file contains the Search autocomplete provider. This provider is 6// responsible for all non-keyword autocomplete entries that start with 7// "Search <engine> for ...", including searching for the current input string, 8// search history, and search suggestions. An instance of it gets created and 9// managed by the autocomplete controller. 10// 11// For more information on the autocomplete system in general, including how 12// the autocomplete controller and autocomplete providers work, see 13// chrome/browser/autocomplete.h. 14 15#ifndef CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 16#define CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 17#pragma once 18 19#include <map> 20#include <string> 21#include <vector> 22 23#include "base/scoped_ptr.h" 24#include "chrome/browser/autocomplete/autocomplete.h" 25#include "chrome/browser/cancelable_request.h" 26#include "chrome/browser/history/history_types.h" 27#include "chrome/browser/search_engines/template_url.h" 28#include "chrome/browser/search_engines/template_url_id.h" 29#include "chrome/common/net/url_fetcher.h" 30 31class Profile; 32class Value; 33 34// Autocomplete provider for searches and suggestions from a search engine. 35// 36// After construction, the autocomplete controller repeatedly calls Start() 37// with some user input, each time expecting to receive a small set of the best 38// matches (either synchronously or asynchronously). 39// 40// Initially the provider creates a match that searches for the current input 41// text. It also starts a task to query the Suggest servers. When that data 42// comes back, the provider creates and returns matches for the best 43// suggestions. 44class SearchProvider : public AutocompleteProvider, 45 public URLFetcher::Delegate { 46 public: 47 SearchProvider(ACProviderListener* listener, Profile* profile); 48 49#if defined(UNIT_TEST) 50 static void set_query_suggest_immediately(bool value) { 51 query_suggest_immediately_ = value; 52 } 53#endif 54 55 // AutocompleteProvider 56 virtual void Start(const AutocompleteInput& input, 57 bool minimal_changes); 58 virtual void Stop(); 59 60 // URLFetcher::Delegate 61 virtual void OnURLFetchComplete(const URLFetcher* source, 62 const GURL& url, 63 const URLRequestStatus& status, 64 int response_code, 65 const ResponseCookies& cookies, 66 const std::string& data); 67 68 // ID used in creating URLFetcher for default provider's suggest results. 69 static const int kDefaultProviderURLFetcherID; 70 71 // ID used in creating URLFetcher for keyword provider's suggest results. 72 static const int kKeywordProviderURLFetcherID; 73 74 private: 75 ~SearchProvider(); 76 77 // Manages the providers (TemplateURLs) used by SearchProvider. Two providers 78 // may be used: 79 // . The default provider. This corresponds to the user's default search 80 // engine. This is always used, except for the rare case of no default 81 // engine. 82 // . The keyword provider. This is used if the user has typed in a keyword. 83 class Providers { 84 public: 85 Providers() : default_provider_(NULL), keyword_provider_(NULL) {} 86 87 // Returns true if the specified providers match the two providers managed 88 // by this class. 89 bool equals(const TemplateURL* default_provider, 90 const TemplateURL* keyword_provider) { 91 return (default_provider == default_provider_ && 92 keyword_provider == keyword_provider_); 93 } 94 95 // Resets the providers. 96 void Set(const TemplateURL* default_provider, 97 const TemplateURL* keyword_provider); 98 99 const TemplateURL& default_provider() const { 100 DCHECK(valid_default_provider()); 101 return cached_default_provider_; 102 } 103 104 const TemplateURL& keyword_provider() const { 105 DCHECK(valid_keyword_provider()); 106 return cached_keyword_provider_; 107 } 108 109 // Returns true of the keyword provider is valid. 110 bool valid_keyword_provider() const { return !!keyword_provider_; } 111 112 // Returns true if the keyword provider is valid and has a valid suggest 113 // url. 114 bool valid_suggest_for_keyword_provider() const { 115 return keyword_provider_ && cached_keyword_provider_.suggestions_url(); 116 } 117 118 // Returns true of the default provider is valid. 119 bool valid_default_provider() const { return !!default_provider_; } 120 121 // Returns true if the default provider is valid and has a valid suggest 122 // url. 123 bool valid_suggest_for_default_provider() const { 124 return default_provider_ && cached_default_provider_.suggestions_url(); 125 } 126 127 // Returns true if |from_keyword_provider| is true, or 128 // the keyword provider is not valid. 129 bool is_primary_provider(bool from_keyword_provider) const { 130 return from_keyword_provider || !valid_keyword_provider(); 131 } 132 133 private: 134 // Cached across the life of a query so we behave consistently even if the 135 // user changes their default while the query is running. 136 TemplateURL cached_default_provider_; 137 TemplateURL cached_keyword_provider_; 138 139 // TODO(pkasting): http://b/1162970 We shouldn't need these. 140 const TemplateURL* default_provider_; 141 const TemplateURL* keyword_provider_; 142 }; 143 144 struct NavigationResult { 145 NavigationResult(const GURL& url, const std::wstring& site_name) 146 : url(url), 147 site_name(site_name) { 148 } 149 150 // The URL. 151 GURL url; 152 153 // Name for the site. 154 std::wstring site_name; 155 }; 156 157 typedef std::vector<std::wstring> SuggestResults; 158 typedef std::vector<NavigationResult> NavigationResults; 159 typedef std::vector<history::KeywordSearchTermVisit> HistoryResults; 160 typedef std::map<std::wstring, AutocompleteMatch> MatchMap; 161 162 // Called when timer_ expires. 163 void Run(); 164 165 // Determines whether an asynchronous subcomponent query should run for the 166 // current input. If so, starts it if necessary; otherwise stops it. 167 // NOTE: These functions do not update |done_|. Callers must do so. 168 void StartOrStopHistoryQuery(bool minimal_changes); 169 void StartOrStopSuggestQuery(bool minimal_changes); 170 171 // Returns true when the current query can be sent to the Suggest service. 172 // This will be false e.g. when Suggest is disabled, the query contains 173 // potentially private data, etc. 174 bool IsQuerySuitableForSuggest() const; 175 176 // Functions to stop the separate asynchronous subcomponents. 177 // NOTE: These functions do not update |done_|. Callers must do so. 178 void StopHistory(); 179 void StopSuggest(); 180 181 // Schedules a history query requesting past searches against the engine 182 // whose id is |search_id| and whose text starts with |text|. 183 void ScheduleHistoryQuery(TemplateURLID search_id, 184 const std::wstring& text); 185 186 // Called back by the history system to return searches that begin with the 187 // input text. 188 void OnGotMostRecentKeywordSearchTerms( 189 CancelableRequestProvider::Handle handle, 190 HistoryResults* results); 191 192 // Creates a URLFetcher requesting suggest results for the specified 193 // TemplateURL. Ownership of the returned URLFetchet passes to the caller. 194 URLFetcher* CreateSuggestFetcher(int id, 195 const TemplateURL& provider, 196 const std::wstring& text); 197 198 // Parses the results from the Suggest server and stores up to kMaxMatches of 199 // them in server_results_. Returns whether parsing succeeded. 200 bool ParseSuggestResults(Value* root_val, 201 bool is_keyword, 202 const std::wstring& input_text, 203 SuggestResults* suggest_results); 204 205 // Converts the parsed server results in server_results_ to a set of 206 // AutocompleteMatches and adds them to |matches_|. This also sets |done_| 207 // correctly. 208 void ConvertResultsToAutocompleteMatches(); 209 210 // Converts the first navigation result in |navigation_results| to an 211 // AutocompleteMatch and adds it to |matches_|. 212 void AddNavigationResultsToMatches( 213 const NavigationResults& navigation_results, 214 bool is_keyword); 215 216 // Adds a match for each result in |results| to |map|. |is_keyword| indicates 217 // whether the results correspond to the keyword provider or default provider. 218 void AddHistoryResultsToMap(const HistoryResults& results, 219 bool is_keyword, 220 int did_not_accept_suggestion, 221 MatchMap* map); 222 223 // Adds a match for each result in |suggest_results| to |map|. |is_keyword| 224 // indicates whether the results correspond to the keyword provider or default 225 // provider. 226 void AddSuggestResultsToMap(const SuggestResults& suggest_results, 227 bool is_keyword, 228 int did_not_accept_suggestion, 229 MatchMap* map); 230 231 // Determines the relevance for a particular match. We use different scoring 232 // algorithms for the different types of matches. 233 int CalculateRelevanceForWhatYouTyped() const; 234 // |time| is the time at which this query was last seen. |is_keyword| is true 235 // if the search is from the keyword provider. 236 int CalculateRelevanceForHistory(const base::Time& time, 237 bool is_keyword) const; 238 // |result_number| is the index of the suggestion in the result set from the 239 // server; the best suggestion is suggestion number 0. |is_keyword| is true 240 // if the search is from the keyword provider. 241 int CalculateRelevanceForSuggestion(size_t num_results, 242 size_t result_number, 243 bool is_keyword) const; 244 // |result_number| is same as above. |is_keyword| is true if the navigation 245 // result was suggested by the keyword provider. 246 int CalculateRelevanceForNavigation(size_t num_results, 247 size_t result_number, 248 bool is_keyword) const; 249 250 // Creates an AutocompleteMatch for "Search <engine> for |query_string|" with 251 // the supplied relevance. Adds this match to |map|; if such a match already 252 // exists, whichever one has lower relevance is eliminated. 253 void AddMatchToMap(const std::wstring& query_string, 254 int relevance, 255 AutocompleteMatch::Type type, 256 int accepted_suggestion, 257 bool is_keyword, 258 MatchMap* map); 259 // Returns an AutocompleteMatch for a navigational suggestion. 260 AutocompleteMatch NavigationToMatch(const NavigationResult& query_string, 261 int relevance, 262 bool is_keyword); 263 264 // Should we query for suggest results immediately? This is normally false, 265 // but may be set to true during testing. 266 static bool query_suggest_immediately_; 267 268 // Maintains the TemplateURLs used. 269 Providers providers_; 270 271 // The user's input. 272 AutocompleteInput input_; 273 274 // Input text when searching against the keyword provider. 275 std::wstring keyword_input_text_; 276 277 // An object we can use to cancel history requests. The client data 278 // corresponds to the id of the search engine and is used in the callback to 279 // determine whether the request corresponds to the keyword of default 280 // provider. 281 CancelableRequestConsumerTSimple<TemplateURLID> 282 history_request_consumer_; 283 284 // Searches in the user's history that begin with the input text. 285 HistoryResults keyword_history_results_; 286 HistoryResults default_history_results_; 287 288 // Whether history_results_ is valid (so we can tell invalid apart from 289 // empty). 290 bool have_history_results_; 291 292 // Whether we are waiting for a history request to finish. 293 bool history_request_pending_; 294 295 // Number of suggest results that haven't yet arrived. If greater than 0 it 296 // indicates either |timer_| or one of the URLFetchers is still running. 297 int suggest_results_pending_; 298 299 // A timer to start a query to the suggest server after the user has stopped 300 // typing for long enough. 301 base::OneShotTimer<SearchProvider> timer_; 302 303 // The fetcher that retrieves suggest results for the keyword from the server. 304 scoped_ptr<URLFetcher> keyword_fetcher_; 305 306 // The fetcher that retrieves suggest results for the default engine from the 307 // server. 308 scoped_ptr<URLFetcher> default_fetcher_; 309 310 // Suggestions returned by the Suggest server for the input text. 311 SuggestResults keyword_suggest_results_; 312 SuggestResults default_suggest_results_; 313 314 // Navigational suggestions returned by the server. 315 NavigationResults keyword_navigation_results_; 316 NavigationResults default_navigation_results_; 317 318 // Whether suggest_results_ is valid. 319 bool have_suggest_results_; 320 321 DISALLOW_COPY_AND_ASSIGN(SearchProvider); 322}; 323 324#endif // CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 325