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. 4 // 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. 10 11 #ifndef CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 12 #define CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 13 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 "chrome/browser/history/history_types.h" 21 #include "chrome/browser/search_engines/template_url.h" 22 #include "components/metrics/proto/omnibox_input_type.pb.h" 23 24 class Profile; 25 class SearchProviderTest; 26 class TemplateURLService; 27 28 namespace net { 29 class URLFetcher; 30 } 31 32 // Autocomplete provider for searches and suggestions from a search engine. 33 // 34 // After construction, the autocomplete controller repeatedly calls Start() 35 // with some user input, each time expecting to receive a small set of the best 36 // matches (either synchronously or asynchronously). 37 // 38 // Initially the provider creates a match that searches for the current input 39 // text. It also starts a task to query the Suggest servers. When that data 40 // comes back, the provider creates and returns matches for the best 41 // suggestions. 42 class SearchProvider : public BaseSearchProvider { 43 public: 44 SearchProvider(AutocompleteProviderListener* listener, Profile* profile); 45 46 // Extracts the suggest response metadata which SearchProvider previously 47 // stored for |match|. 48 static std::string GetSuggestMetadata(const AutocompleteMatch& match); 49 50 // AutocompleteProvider: 51 virtual void ResetSession() OVERRIDE; 52 53 // This URL may be sent with suggest requests; see comments on CanSendURL(). set_current_page_url(const GURL & current_page_url)54 void set_current_page_url(const GURL& current_page_url) { 55 current_page_url_ = current_page_url; 56 } 57 58 protected: 59 virtual ~SearchProvider(); 60 61 private: 62 friend class SearchProviderTest; 63 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, CanSendURL); 64 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInline); 65 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInlineDomainClassify); 66 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, NavigationInlineSchemeSubstring); 67 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, RemoveStaleResultsTest); 68 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestRelevanceExperiment); 69 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, TestDeleteMatch); 70 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestQueryUsesToken); 71 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SessionToken); 72 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL); 73 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest, ClearPrefetchedResults); 74 FRIEND_TEST_ALL_PREFIXES(InstantExtendedPrefetchTest, SetPrefetchQuery); 75 76 // Manages the providers (TemplateURLs) used by SearchProvider. Two providers 77 // may be used: 78 // . The default provider. This corresponds to the user's default search 79 // engine. This is always used, except for the rare case of no default 80 // engine. 81 // . The keyword provider. This is used if the user has typed in a keyword. 82 class Providers { 83 public: 84 explicit Providers(TemplateURLService* template_url_service); 85 86 // Returns true if the specified providers match the two providers cached 87 // by this class. equal(const base::string16 & default_provider,const base::string16 & keyword_provider)88 bool equal(const base::string16& default_provider, 89 const base::string16& keyword_provider) const { 90 return (default_provider == default_provider_) && 91 (keyword_provider == keyword_provider_); 92 } 93 94 // Resets the cached providers. set(const base::string16 & default_provider,const base::string16 & keyword_provider)95 void set(const base::string16& default_provider, 96 const base::string16& keyword_provider) { 97 default_provider_ = default_provider; 98 keyword_provider_ = keyword_provider; 99 } 100 template_url_service()101 TemplateURLService* template_url_service() { return template_url_service_; } default_provider()102 const base::string16& default_provider() const { return default_provider_; } keyword_provider()103 const base::string16& keyword_provider() const { return keyword_provider_; } 104 105 // NOTE: These may return NULL even if the provider members are nonempty! 106 const TemplateURL* GetDefaultProviderURL() const; 107 const TemplateURL* GetKeywordProviderURL() const; 108 109 // Returns true if there is a valid keyword provider. has_keyword_provider()110 bool has_keyword_provider() const { return !keyword_provider_.empty(); } 111 112 private: 113 TemplateURLService* template_url_service_; 114 115 // Cached across the life of a query so we behave consistently even if the 116 // user changes their default while the query is running. 117 base::string16 default_provider_; 118 base::string16 keyword_provider_; 119 120 DISALLOW_COPY_AND_ASSIGN(Providers); 121 }; 122 123 class CompareScoredResults; 124 125 typedef std::vector<history::KeywordSearchTermVisit> HistoryResults; 126 127 // Removes non-inlineable results until either the top result can inline 128 // autocomplete the current input or verbatim outscores the top result. 129 static void RemoveStaleResults(const base::string16& input, 130 int verbatim_relevance, 131 SuggestResults* suggest_results, 132 NavigationResults* navigation_results); 133 134 // Recalculates the match contents class of |results| to better display 135 // against the current input and user's language. 136 void UpdateMatchContentsClass(const base::string16& input_text, 137 Results* results); 138 139 // Calculates the relevance score for the keyword verbatim result (if the 140 // input matches one of the profile's keyword). 141 static int CalculateRelevanceForKeywordVerbatim( 142 metrics::OmniboxInputType::Type type, 143 bool prefer_keyword); 144 145 // AutocompleteProvider: 146 virtual void Start(const AutocompleteInput& input, 147 bool minimal_changes) OVERRIDE; 148 149 // BaseSearchProvider: 150 virtual void SortResults(bool is_keyword, 151 const base::ListValue* relevances, 152 Results* results) OVERRIDE; 153 virtual const TemplateURL* GetTemplateURL(bool is_keyword) const OVERRIDE; 154 virtual const AutocompleteInput GetInput(bool is_keyword) const OVERRIDE; 155 virtual Results* GetResultsToFill(bool is_keyword) OVERRIDE; 156 virtual bool ShouldAppendExtraParams( 157 const SuggestResult& result) const OVERRIDE; 158 virtual void StopSuggest() OVERRIDE; 159 virtual void ClearAllResults() OVERRIDE; 160 virtual int GetDefaultResultRelevance() const OVERRIDE; 161 virtual void RecordDeletionResult(bool success) OVERRIDE; 162 virtual void LogFetchComplete(bool success, bool is_keyword) OVERRIDE; 163 virtual bool IsKeywordFetcher(const net::URLFetcher* fetcher) const OVERRIDE; 164 virtual void UpdateMatches() OVERRIDE; 165 166 // Called when timer_ expires. 167 void Run(); 168 169 // Runs the history query, if necessary. The history query is synchronous. 170 // This does not update |done_|. 171 void DoHistoryQuery(bool minimal_changes); 172 173 // Determines whether an asynchronous subcomponent query should run for the 174 // current input. If so, starts it if necessary; otherwise stops it. 175 // NOTE: This function does not update |done_|. Callers must do so. 176 void StartOrStopSuggestQuery(bool minimal_changes); 177 178 // Returns true when the current query can be sent to the Suggest service. 179 // This will be false e.g. when Suggest is disabled, the query contains 180 // potentially private data, etc. 181 bool IsQuerySuitableForSuggest() const; 182 183 // Removes stale results for both default and keyword providers. See comments 184 // on RemoveStaleResults(). 185 void RemoveAllStaleResults(); 186 187 // Apply calculated relevance scores to the current results. 188 void ApplyCalculatedRelevance(); 189 void ApplyCalculatedSuggestRelevance(SuggestResults* list); 190 void ApplyCalculatedNavigationRelevance(NavigationResults* list); 191 192 // Starts a new URLFetcher requesting suggest results from |template_url|; 193 // callers own the returned URLFetcher, which is NULL for invalid providers. 194 net::URLFetcher* CreateSuggestFetcher(int id, 195 const TemplateURL* template_url, 196 const AutocompleteInput& input); 197 198 // Converts the parsed results to a set of AutocompleteMatches, |matches_|. 199 void ConvertResultsToAutocompleteMatches(); 200 201 // Returns an iterator to the first match in |matches_| which might 202 // be chosen as default. 203 ACMatches::const_iterator FindTopMatch() const; 204 205 // Checks if suggested relevances violate certain expected constraints. 206 // See UpdateMatches() for the use and explanation of these constraints. 207 bool HasKeywordDefaultMatchInKeywordMode() const; 208 bool IsTopMatchSearchWithURLInput() const; 209 210 // Converts an appropriate number of navigation results in 211 // |navigation_results| to matches and adds them to |matches|. 212 void AddNavigationResultsToMatches( 213 const NavigationResults& navigation_results, 214 ACMatches* matches); 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 // Calculates relevance scores for all |results|. 224 SuggestResults ScoreHistoryResults(const HistoryResults& results, 225 bool base_prevent_inline_autocomplete, 226 bool input_multiple_words, 227 const base::string16& input_text, 228 bool is_keyword); 229 230 // Adds matches for |results| to |map|. 231 void AddSuggestResultsToMap(const SuggestResults& results, 232 const std::string& metadata, 233 MatchMap* map); 234 235 // Gets the relevance score for the verbatim result. This value may be 236 // provided by the suggest server or calculated locally; if 237 // |relevance_from_server| is non-NULL, it will be set to indicate which of 238 // those is true. 239 int GetVerbatimRelevance(bool* relevance_from_server) const; 240 241 // Calculates the relevance score for the verbatim result from the 242 // default search engine. This version takes into account context: 243 // i.e., whether the user has entered a keyword-based search or not. 244 int CalculateRelevanceForVerbatim() const; 245 246 // Calculates the relevance score for the verbatim result from the default 247 // search engine *ignoring* whether the input is a keyword-based search 248 // or not. This function should only be used to determine the minimum 249 // relevance score that the best result from this provider should have. 250 // For normal use, prefer the above function. 251 int CalculateRelevanceForVerbatimIgnoringKeywordModeState() const; 252 253 // Gets the relevance score for the keyword verbatim result. 254 // |relevance_from_server| is handled as in GetVerbatimRelevance(). 255 // TODO(mpearson): Refactor so this duplication isn't necessary or 256 // restructure so one static function takes all the parameters it needs 257 // (rather than looking at internal state). 258 int GetKeywordVerbatimRelevance(bool* relevance_from_server) const; 259 260 // |time| is the time at which this query was last seen. |is_keyword| 261 // indicates whether the results correspond to the keyword provider or default 262 // provider. |use_aggressive_method| says whether this function can use a 263 // method that gives high scores (1200+) rather than one that gives lower 264 // scores. When using the aggressive method, scores may exceed 1300 265 // unless |prevent_search_history_inlining| is set. 266 int CalculateRelevanceForHistory(const base::Time& time, 267 bool is_keyword, 268 bool use_aggressive_method, 269 bool prevent_search_history_inlining) const; 270 271 // Returns an AutocompleteMatch for a navigational suggestion. 272 AutocompleteMatch NavigationToMatch(const NavigationResult& navigation); 273 274 // Updates the value of |done_| from the internal state. 275 void UpdateDone(); 276 277 // Obtains a session token, regenerating if necessary. 278 std::string GetSessionToken(); 279 280 // The amount of time to wait before sending a new suggest request after the 281 // previous one. Non-const because some unittests modify this value. 282 static int kMinimumTimeBetweenSuggestQueriesMs; 283 284 // Maintains the TemplateURLs used. 285 Providers providers_; 286 287 // The user's input. 288 AutocompleteInput input_; 289 290 // Input when searching against the keyword provider. 291 AutocompleteInput keyword_input_; 292 293 // Searches in the user's history that begin with the input text. 294 HistoryResults keyword_history_results_; 295 HistoryResults default_history_results_; 296 297 // A timer to start a query to the suggest server after the user has stopped 298 // typing for long enough. 299 base::OneShotTimer<SearchProvider> timer_; 300 301 // The time at which we sent a query to the suggest server. 302 base::TimeTicks time_suggest_request_sent_; 303 304 // Fetchers used to retrieve results for the keyword and default providers. 305 scoped_ptr<net::URLFetcher> keyword_fetcher_; 306 scoped_ptr<net::URLFetcher> default_fetcher_; 307 308 // Results from the default and keyword search providers. 309 Results default_results_; 310 Results keyword_results_; 311 312 GURL current_page_url_; 313 314 // Session token management. 315 std::string current_token_; 316 base::TimeTicks token_expiration_time_; 317 318 DISALLOW_COPY_AND_ASSIGN(SearchProvider); 319 }; 320 321 #endif // CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ 322