zero_suggest_provider.h revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the zero-suggest autocomplete provider. This experimental
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provider is invoked when the user focuses in the omnibox prior to editing,
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and generates search query suggestions based on the current URL. To enable
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this provider, point --experimental-zero-suggest-url-prefix at an
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// appropriate suggestion service.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HUGE DISCLAIMER: This is just here for experimenting and will probably be
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleted entirely as we revise how suggestions work with the omnibox.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
22#include "base/compiler_specific.h"
23#include "base/memory/scoped_ptr.h"
24#include "base/strings/string16.h"
25#include "chrome/browser/autocomplete/autocomplete_provider.h"
26#include "chrome/browser/autocomplete/search_provider.h"
27#include "net/url_request/url_fetcher_delegate.h"
28
29class AutocompleteInput;
30class GURL;
31class TemplateURLService;
32
33namespace base {
34class ListValue;
35class Value;
36}
37
38namespace net {
39class URLFetcher;
40}
41
42// Autocomplete provider for searches based on the current URL.
43//
44// The controller will call StartZeroSuggest when the user focuses in the
45// omnibox. After construction, the autocomplete controller repeatedly calls
46// Start() with some user input, each time expecting to receive an updated
47// set of matches.
48//
49// TODO(jered): Consider deleting this class and building this functionality
50// into SearchProvider after dogfood and after we break the association between
51// omnibox text and suggestions.
52class ZeroSuggestProvider : public AutocompleteProvider,
53                            public net::URLFetcherDelegate {
54 public:
55  // Creates and returns an instance of this provider.
56  static ZeroSuggestProvider* Create(AutocompleteProviderListener* listener,
57                                     Profile* profile);
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
64  // Adds provider-specific information to omnibox event logs.
65  virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
66
67  // Sets |field_trial_triggered_| to false.
68  virtual void ResetSession() OVERRIDE;
69
70  // net::URLFetcherDelegate
71  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
72
73  // Initiates a new fetch for the given |url|, limiting suggestions to those
74  // matching |user_text|. |user_text| may be non-empty if the user previously
75  // interacted with zero-suggest suggestions and then unfocused the omnibox.
76  // TODO(jered): Rip out |user_text| once the first match is decoupled from
77  // the current typing in the omnibox.
78  void StartZeroSuggest(const GURL& url, const string16& user_text);
79
80 private:
81  ZeroSuggestProvider(AutocompleteProviderListener* listener,
82                      Profile* profile);
83
84  virtual ~ZeroSuggestProvider();
85
86  bool ShouldRunZeroSuggest(const GURL& url) const;
87
88  // The 4 functions below (that take classes defined in SearchProvider as
89  // arguments) were copied and trimmed from SearchProvider.
90  // TODO(hfung): Refactor them into a new base class common to both
91  // ZeroSuggestProvider and SearchProvider.
92
93  // From the OpenSearch formatted response |root_val|, populate query
94  // suggestions into |suggest_results|, navigation suggestions into
95  // |navigation_results|, and the verbatim relevance score into
96  // |verbatim_relevance|.
97  void FillResults(const base::Value& root_val,
98                   int* verbatim_relevance,
99                   SearchProvider::SuggestResults* suggest_results,
100                   SearchProvider::NavigationResults* navigation_results);
101
102  // Creates AutocompleteMatches for "Search |provider_keyword| for
103  // <suggestion>" for all suggestions in |results|, and adds them to |map|.
104  void AddSuggestResultsToMap(const SearchProvider::SuggestResults& results,
105                              const string16& provider_keyword,
106                              SearchProvider::MatchMap* map);
107
108  // Creates an AutocompleteMatch for "Search |provider_keyword| for
109  // |query_string|".  The supplied |relevance| and |type| and
110  // |accepted_suggestion| will also be used to create the AutocompleteMatch.
111  // Adds this match to |map|; if such a match already exists, whichever one
112  // has lower relevance is eliminated.
113  void AddMatchToMap(const string16& query_string,
114                     const string16& provider_keyword,
115                     int relevance,
116                     AutocompleteMatch::Type type,
117                     int accepted_suggestion,
118                     SearchProvider::MatchMap* map);
119
120  // Returns an AutocompleteMatch for a navigational suggestion |navigation|.
121  AutocompleteMatch NavigationToMatch(
122      const SearchProvider::NavigationResult& navigation);
123
124  // Sets |user_text_modified_| if the user has modified the omnibox text, based
125  // on the user input |user_text|.
126  void CheckIfTextModfied(const string16& user_text);
127
128  // Fetches zero-suggest suggestions for |current_query_|.
129  void Run();
130
131  // Parses results from the zero-suggest server and updates results.
132  void ParseSuggestResults(const base::Value& root_val);
133
134  // Converts the parsed results to a set of AutocompleteMatches, based on user
135  // input |user_text|, and adds them to |matches_|.  If |update_histograms| is
136  // true, also update the histograms for how many results were received.
137  void ConvertResultsToAutocompleteMatches(string16 user_text,
138                                           bool update_histograms);
139
140  // Returns an AutocompleteMatch for the current URL. The match should be in
141  // the top position so that pressing enter has the effect of reloading the
142  // page.
143  AutocompleteMatch MatchForCurrentURL();
144
145  // Used to build default search engine URLs for suggested queries.
146  TemplateURLService* template_url_service_;
147
148  // The URL for which a suggestion fetch is pending.
149  std::string current_query_;
150
151  // What the user has typed.
152  string16 original_user_text_;
153  // Whether the user has modified the omnibox since the zero suggest request.
154  bool user_text_modified_;
155
156  // Fetcher used to retrieve results.
157  scoped_ptr<net::URLFetcher> fetcher_;
158  // Whether there's a pending request in flight.
159  bool have_pending_request_;
160
161  // Suggestion for the current URL.
162  AutocompleteMatch current_url_match_;
163  // Navigation suggestions for the most recent ZeroSuggest input URL.
164  SearchProvider::NavigationResults navigation_results_;
165  // Query suggestions for the most recent ZeroSuggest input URL.
166  SearchProvider::MatchMap query_matches_map_;
167  // The relevance score for the URL of the current page.
168  int verbatim_relevance_;
169
170  // Whether a field trial, if any, has triggered in the most recent
171  // autocomplete query. This field is set to true if the last request
172  // was a zero suggest request, the provider has completed and their
173  // corresponding response contained '"google:fieldtrialtriggered":true'.
174  bool field_trial_triggered_;
175  // Whether a zero suggest request triggered a field trial in the omnibox
176  // session.  The user could have clicked on a suggestion when zero suggest
177  // triggered (same condition as field_trial_triggered_), or triggered zero
178  // suggest but kept typing.
179  bool field_trial_triggered_in_session_;
180
181  DISALLOW_COPY_AND_ASSIGN(ZeroSuggestProvider);
182};
183
184#endif  // CHROME_BROWSER_AUTOCOMPLETE_ZERO_SUGGEST_PROVIDER_H_
185