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