diff options
Diffstat (limited to 'chrome/browser/autocomplete/search_provider.h')
-rw-r--r-- | chrome/browser/autocomplete/search_provider.h | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h new file mode 100644 index 0000000..f59dc26 --- /dev/null +++ b/chrome/browser/autocomplete/search_provider.h @@ -0,0 +1,328 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This file contains the Search autocomplete provider. This provider is +// responsible for all non-keyword autocomplete entries that start with +// "Search <engine> for ...", including searching for the current input string, +// search history, and search suggestions. An instance of it gets created and +// managed by the autocomplete controller. +// +// For more information on the autocomplete system in general, including how +// the autocomplete controller and autocomplete providers work, see +// chrome/browser/autocomplete.h. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/scoped_ptr.h" +#include "chrome/browser/autocomplete/autocomplete.h" +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/browser/search_engines/template_url.h" +#include "chrome/common/net/url_fetcher.h" + +class Profile; +class Value; + +// Autocomplete provider for searches and suggestions from a search engine. +// +// After construction, the autocomplete controller repeatedly calls Start() +// with some user input, each time expecting to receive a small set of the best +// matches (either synchronously or asynchronously). +// +// Initially the provider creates a match that searches for the current input +// text. It also starts a task to query the Suggest servers. When that data +// comes back, the provider creates and returns matches for the best +// suggestions. +class SearchProvider : public AutocompleteProvider, + public URLFetcher::Delegate { + public: + SearchProvider(ACProviderListener* listener, Profile* profile) + : AutocompleteProvider(listener, profile, "Search"), + have_history_results_(false), + history_request_pending_(false), + suggest_results_pending_(0), + have_suggest_results_(false) { + } + +#if defined(UNIT_TEST) + static void set_query_suggest_immediately(bool value) { + query_suggest_immediately_ = value; + } +#endif + + // AutocompleteProvider + virtual void Start(const AutocompleteInput& input, + bool minimal_changes); + virtual void Stop(); + + // URLFetcher::Delegate + virtual void OnURLFetchComplete(const URLFetcher* source, + const GURL& url, + const URLRequestStatus& status, + int response_code, + const ResponseCookies& cookies, + const std::string& data); + + // ID used in creating URLFetcher for default provider's suggest results. + static const int kDefaultProviderURLFetcherID; + + // ID used in creating URLFetcher for keyword provider's suggest results. + static const int kKeywordProviderURLFetcherID; + + private: + ~SearchProvider() {} + + // Manages the providers (TemplateURLs) used by SearchProvider. Two providers + // may be used: + // . The default provider. This corresponds to the user's default search + // engine. This is always used, except for the rare case of no default + // engine. + // . The keyword provider. This is used if the user has typed in a keyword. + class Providers { + public: + Providers() : default_provider_(NULL), keyword_provider_(NULL) {} + + // Returns true if the specified providers match the two providers managed + // by this class. + bool equals(const TemplateURL* default_provider, + const TemplateURL* keyword_provider) { + return (default_provider == default_provider_ && + keyword_provider == keyword_provider_); + } + + // Resets the providers. + void Set(const TemplateURL* default_provider, + const TemplateURL* keyword_provider); + + const TemplateURL& default_provider() const { + DCHECK(valid_default_provider()); + return cached_default_provider_; + } + + const TemplateURL& keyword_provider() const { + DCHECK(valid_keyword_provider()); + return cached_keyword_provider_; + } + + // Returns true of the keyword provider is valid. + bool valid_keyword_provider() const { return !!keyword_provider_; } + + // Returns true if the keyword provider is valid and has a valid suggest + // url. + bool valid_suggest_for_keyword_provider() const { + return keyword_provider_ && cached_keyword_provider_.suggestions_url(); + } + + // Returns true of the default provider is valid. + bool valid_default_provider() const { return !!default_provider_; } + + // Returns true if the default provider is valid and has a valid suggest + // url. + bool valid_suggest_for_default_provider() const { + return default_provider_ && cached_default_provider_.suggestions_url(); + } + + // Returns true if |from_keyword_provider| is true, or + // the keyword provider is not valid. + bool is_primary_provider(bool from_keyword_provider) const { + return from_keyword_provider || !valid_keyword_provider(); + } + + private: + // Cached across the life of a query so we behave consistently even if the + // user changes their default while the query is running. + TemplateURL cached_default_provider_; + TemplateURL cached_keyword_provider_; + + // TODO(pkasting): http://b/1162970 We shouldn't need these. + const TemplateURL* default_provider_; + const TemplateURL* keyword_provider_; + }; + + struct NavigationResult { + NavigationResult(const GURL& url, const std::wstring& site_name) + : url(url), + site_name(site_name) { + } + + // The URL. + GURL url; + + // Name for the site. + std::wstring site_name; + }; + + typedef std::vector<std::wstring> SuggestResults; + typedef std::vector<NavigationResult> NavigationResults; + typedef std::vector<history::KeywordSearchTermVisit> HistoryResults; + typedef std::map<std::wstring, AutocompleteMatch> MatchMap; + + // Called when timer_ expires. + void Run(); + + // Determines whether an asynchronous subcomponent query should run for the + // current input. If so, starts it if necessary; otherwise stops it. + // NOTE: These functions do not update |done_|. Callers must do so. + void StartOrStopHistoryQuery(bool minimal_changes); + void StartOrStopSuggestQuery(bool minimal_changes); + + // Returns true when the current query can be sent to the Suggest service. + // This will be false e.g. when Suggest is disabled, the query contains + // potentially private data, etc. + bool IsQuerySuitableForSuggest() const; + + // Functions to stop the separate asynchronous subcomponents. + // NOTE: These functions do not update |done_|. Callers must do so. + void StopHistory(); + void StopSuggest(); + + // Schedules a history query requesting past searches against the engine + // whose id is |search_id| and whose text starts with |text|. + void ScheduleHistoryQuery(TemplateURL::IDType search_id, + const std::wstring& text); + + // Called back by the history system to return searches that begin with the + // input text. + void OnGotMostRecentKeywordSearchTerms( + CancelableRequestProvider::Handle handle, + HistoryResults* results); + + // Creates a URLFetcher requesting suggest results for the specified + // TemplateURL. Ownership of the returned URLFetchet passes to the caller. + URLFetcher* CreateSuggestFetcher(int id, + const TemplateURL& provider, + const std::wstring& text); + + // Parses the results from the Suggest server and stores up to kMaxMatches of + // them in server_results_. Returns whether parsing succeeded. + bool ParseSuggestResults(Value* root_val, + bool is_keyword, + const std::wstring& input_text, + SuggestResults* suggest_results); + + // Converts the parsed server results in server_results_ to a set of + // AutocompleteMatches and adds them to |matches_|. This also sets |done_| + // correctly. + void ConvertResultsToAutocompleteMatches(); + + // Converts the first navigation result in |navigation_results| to an + // AutocompleteMatch and adds it to |matches_|. + void AddNavigationResultsToMatches( + const NavigationResults& navigation_results, + bool is_keyword); + + // Adds a match for each result in |results| to |map|. |is_keyword| indicates + // whether the results correspond to the keyword provider or default provider. + void AddHistoryResultsToMap(const HistoryResults& results, + bool is_keyword, + int did_not_accept_suggestion, + MatchMap* map); + + // Adds a match for each result in |suggest_results| to |map|. |is_keyword| + // indicates whether the results correspond to the keyword provider or default + // provider. + void AddSuggestResultsToMap(const SuggestResults& suggest_results, + bool is_keyword, + int did_not_accept_suggestion, + MatchMap* map); + + // Determines the relevance for a particular match. We use different scoring + // algorithms for the different types of matches. + int CalculateRelevanceForWhatYouTyped() const; + // |time| is the time at which this query was last seen. |is_keyword| is true + // if the search is from the keyword provider. + int CalculateRelevanceForHistory(const base::Time& time, + bool is_keyword) const; + // |result_number| is the index of the suggestion in the result set from the + // server; the best suggestion is suggestion number 0. |is_keyword| is true + // if the search is from the keyword provider. + int CalculateRelevanceForSuggestion(size_t num_results, + size_t result_number, + bool is_keyword) const; + // |result_number| is same as above. |is_keyword| is true if the navigation + // result was suggested by the keyword provider. + int CalculateRelevanceForNavigation(size_t num_results, + size_t result_number, + bool is_keyword) const; + + // Creates an AutocompleteMatch for "Search <engine> for |query_string|" with + // the supplied relevance. Adds this match to |map|; if such a match already + // exists, whichever one has lower relevance is eliminated. + void AddMatchToMap(const std::wstring& query_string, + int relevance, + AutocompleteMatch::Type type, + int accepted_suggestion, + bool is_keyword, + MatchMap* map); + // Returns an AutocompleteMatch for a navigational suggestion. + AutocompleteMatch NavigationToMatch(const NavigationResult& query_string, + int relevance, + bool is_keyword); + + // Should we query for suggest results immediately? This is normally false, + // but may be set to true during testing. + static bool query_suggest_immediately_; + + // Maintains the TemplateURLs used. + Providers providers_; + + // The user's input. + AutocompleteInput input_; + + // Input text when searching against the keyword provider. + std::wstring keyword_input_text_; + + // An object we can use to cancel history requests. The client data + // corresponds to the id of the search engine and is used in the callback to + // determine whether the request corresponds to the keyword of default + // provider. + CancelableRequestConsumerTSimple<TemplateURL::IDType> + history_request_consumer_; + + // Searches in the user's history that begin with the input text. + HistoryResults keyword_history_results_; + HistoryResults default_history_results_; + + // Whether history_results_ is valid (so we can tell invalid apart from + // empty). + bool have_history_results_; + + // Whether we are waiting for a history request to finish. + bool history_request_pending_; + + // Number of suggest results that haven't yet arrived. If greater than 0 it + // indicates either |timer_| or one of the URLFetchers is still running. + int suggest_results_pending_; + + // A timer to start a query to the suggest server after the user has stopped + // typing for long enough. + base::OneShotTimer<SearchProvider> timer_; + + // The fetcher that retrieves suggest results for the keyword from the server. + scoped_ptr<URLFetcher> keyword_fetcher_; + + // The fetcher that retrieves suggest results for the default engine from the + // server. + scoped_ptr<URLFetcher> default_fetcher_; + + // Suggestions returned by the Suggest server for the input text. + SuggestResults keyword_suggest_results_; + SuggestResults default_suggest_results_; + + // Navigational suggestions returned by the server. + NavigationResults keyword_navigation_results_; + NavigationResults default_navigation_results_; + + // Whether suggest_results_ is valid. + bool have_suggest_results_; + + DISALLOW_COPY_AND_ASSIGN(SearchProvider); +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_SEARCH_PROVIDER_H_ |