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 zero-suggest autocomplete provider. This experimental
6// provider is invoked when the user focuses in the omnibox prior to editing,
7// and generates search query suggestions based on the current URL.
8
9#ifndef CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
10#define CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
11
12#include "base/basictypes.h"
13#include "base/compiler_specific.h"
14#include "base/memory/scoped_ptr.h"
15#include "components/history/core/browser/history_types.h"
16#include "components/metrics/proto/omnibox_event.pb.h"
17#include "components/omnibox/base_search_provider.h"
18#include "components/omnibox/search_provider.h"
19#include "net/url_request/url_fetcher_delegate.h"
20
21class AutocompleteProviderListener;
22class Profile;
23class TemplateURLService;
24
25namespace base {
26class ListValue;
27class Value;
28}
29
30namespace net {
31class URLFetcher;
32}
33
34namespace user_prefs {
35class PrefRegistrySyncable;
36}
37
38// Autocomplete provider for searches based on the current URL.
39//
40// The controller will call StartZeroSuggest when the user focuses in the
41// omnibox. After construction, the autocomplete controller repeatedly calls
42// Start() with some user input, each time expecting to receive an updated
43// set of matches.
44//
45// TODO(jered): Consider deleting this class and building this functionality
46// into SearchProvider after dogfood and after we break the association between
47// omnibox text and suggestions.
48class ZeroSuggestProvider : public BaseSearchProvider,
49                            public net::URLFetcherDelegate {
50 public:
51  // Creates and returns an instance of this provider.
52  static ZeroSuggestProvider* Create(AutocompleteProviderListener* listener,
53                                     TemplateURLService* template_url_service,
54                                     Profile* profile);
55
56  // Registers a preference used to cache zero suggest results.
57  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
58
59  // AutocompleteProvider:
60  virtual void Start(const AutocompleteInput& input,
61                     bool minimal_changes) OVERRIDE;
62  virtual void Stop(bool clear_cached_results) OVERRIDE;
63  virtual void DeleteMatch(const AutocompleteMatch& match) OVERRIDE;
64  virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
65
66  // Sets |field_trial_triggered_| to false.
67  virtual void ResetSession() OVERRIDE;
68
69 private:
70  ZeroSuggestProvider(AutocompleteProviderListener* listener,
71                      TemplateURLService* template_url_service,
72                      Profile* profile);
73
74  virtual ~ZeroSuggestProvider();
75
76  // BaseSearchProvider:
77  virtual const TemplateURL* GetTemplateURL(bool is_keyword) const OVERRIDE;
78  virtual const AutocompleteInput GetInput(bool is_keyword) const OVERRIDE;
79  virtual bool ShouldAppendExtraParams(
80      const SearchSuggestionParser::SuggestResult& result) const OVERRIDE;
81  virtual void RecordDeletionResult(bool success) OVERRIDE;
82
83  // net::URLFetcherDelegate:
84  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
85
86  // Optionally, cache the received |json_data| and return true if we want
87  // to stop processing results at this point. The |parsed_data| is the parsed
88  // version of |json_data| used to determine if we received an empty result.
89  bool StoreSuggestionResponse(const std::string& json_data,
90                               const base::Value& parsed_data);
91
92  // Adds AutocompleteMatches for each of the suggestions in |results| to
93  // |map|.
94  void AddSuggestResultsToMap(
95      const SearchSuggestionParser::SuggestResults& results,
96      MatchMap* map);
97
98  // Returns an AutocompleteMatch for a navigational suggestion |navigation|.
99  AutocompleteMatch NavigationToMatch(
100      const SearchSuggestionParser::NavigationResult& navigation);
101
102  // Fetches zero-suggest suggestions by sending a request using |suggest_url|.
103  void Run(const GURL& suggest_url);
104
105  // Converts the parsed results to a set of AutocompleteMatches and adds them
106  // to |matches_|.  Also update the histograms for how many results were
107  // received.
108  void ConvertResultsToAutocompleteMatches();
109
110  // Returns an AutocompleteMatch for the current URL. The match should be in
111  // the top position so that pressing enter has the effect of reloading the
112  // page.
113  AutocompleteMatch MatchForCurrentURL();
114
115  // When the user is in the Most Visited field trial, we ask the TopSites
116  // service for the most visited URLs during Run().  It calls back to this
117  // function to return those |urls|.
118  void OnMostVisitedUrlsAvailable(const history::MostVisitedURLList& urls);
119
120  // Returns the relevance score for the verbatim result.
121  int GetVerbatimRelevance() const;
122
123  // Whether we can show zero suggest on |current_page_url| without
124  // sending |current_page_url| as a parameter to the server at |suggest_url|.
125  bool CanShowZeroSuggestWithoutSendingURL(const GURL& suggest_url,
126                                           const GURL& current_page_url) const;
127
128  // Checks whether we have a set of zero suggest results cached, and if so
129  // populates |matches_| with cached results.
130  void MaybeUseCachedSuggestions();
131
132  AutocompleteProviderListener* listener_;
133  Profile* profile_;
134
135  // The URL for which a suggestion fetch is pending.
136  std::string current_query_;
137
138  // The type of page the user is viewing (a search results page doing search
139  // term replacement, an arbitrary URL, etc.).
140  metrics::OmniboxEventProto::PageClassification current_page_classification_;
141
142  // Copy of OmniboxEditModel::permanent_text_.
143  base::string16 permanent_text_;
144
145  // Fetcher used to retrieve results.
146  scoped_ptr<net::URLFetcher> fetcher_;
147
148  // Suggestion for the current URL.
149  AutocompleteMatch current_url_match_;
150
151  // Contains suggest and navigation results as well as relevance parsed from
152  // the response for the most recent zero suggest input URL.
153  SearchSuggestionParser::Results results_;
154
155  // Whether we are currently showing cached zero suggest results.
156  bool results_from_cache_;
157
158  history::MostVisitedURLList most_visited_urls_;
159
160  // For callbacks that may be run after destruction.
161  base::WeakPtrFactory<ZeroSuggestProvider> weak_ptr_factory_;
162
163  DISALLOW_COPY_AND_ASSIGN(ZeroSuggestProvider);
164};
165
166#endif  // CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
167