• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 #ifndef COMPONENTS_OMNIBOX_SEARCH_SUGGESTION_PARSER_H_
6 #define COMPONENTS_OMNIBOX_SEARCH_SUGGESTION_PARSER_H_
7 
8 #include <string>
9 #include <vector>
10 
11 #include "base/basictypes.h"
12 #include "base/gtest_prod_util.h"
13 #include "base/strings/string16.h"
14 #include "components/omnibox/autocomplete_match.h"
15 #include "components/omnibox/autocomplete_match_type.h"
16 #include "url/gurl.h"
17 
18 class AutocompleteInput;
19 class AutocompleteSchemeClassifier;
20 
21 namespace base {
22 class DictionaryValue;
23 class Value;
24 }
25 
26 namespace net {
27 class URLFetcher;
28 }
29 
30 class SearchSuggestionParser {
31  public:
32   // The Result classes are intermediate representations of AutocompleteMatches,
33   // simply containing relevance-ranked search and navigation suggestions.
34   // They may be cached to provide some synchronous matches while requests for
35   // new suggestions from updated input are in flight.
36   // TODO(msw) Extend these classes to generate their corresponding matches and
37   //           other requisite data, in order to consolidate and simplify the
38   //           highly fragmented SearchProvider logic for each Result type.
39   class Result {
40    public:
41     Result(bool from_keyword_provider,
42            int relevance,
43            bool relevance_from_server,
44            AutocompleteMatchType::Type type,
45            const std::string& deletion_url);
46     virtual ~Result();
47 
from_keyword_provider()48     bool from_keyword_provider() const { return from_keyword_provider_; }
49 
match_contents()50     const base::string16& match_contents() const { return match_contents_; }
match_contents_class()51     const ACMatchClassifications& match_contents_class() const {
52       return match_contents_class_;
53     }
54 
type()55     AutocompleteMatchType::Type type() const { return type_; }
relevance()56     int relevance() const { return relevance_; }
set_relevance(int relevance)57     void set_relevance(int relevance) { relevance_ = relevance; }
received_after_last_keystroke()58     bool received_after_last_keystroke() const {
59       return received_after_last_keystroke_;
60     }
set_received_after_last_keystroke(bool received_after_last_keystroke)61     void set_received_after_last_keystroke(
62         bool received_after_last_keystroke) {
63       received_after_last_keystroke_ = received_after_last_keystroke;
64     }
65 
relevance_from_server()66     bool relevance_from_server() const { return relevance_from_server_; }
set_relevance_from_server(bool relevance_from_server)67     void set_relevance_from_server(bool relevance_from_server) {
68       relevance_from_server_ = relevance_from_server;
69     }
70 
deletion_url()71     const std::string& deletion_url() const { return deletion_url_; }
72 
73     // Returns the default relevance value for this result (which may
74     // be left over from a previous omnibox input) given the current
75     // input and whether the current input caused a keyword provider
76     // to be active.
77     virtual int CalculateRelevance(const AutocompleteInput& input,
78                                    bool keyword_provider_requested) const = 0;
79 
80    protected:
81     // The contents to be displayed and its style info.
82     base::string16 match_contents_;
83     ACMatchClassifications match_contents_class_;
84 
85     // True if the result came from the keyword provider.
86     bool from_keyword_provider_;
87 
88     AutocompleteMatchType::Type type_;
89 
90     // The relevance score.
91     int relevance_;
92 
93    private:
94     // Whether this result's relevance score was fully or partly calculated
95     // based on server information, and thus is assumed to be more accurate.
96     // This is ultimately used in
97     // SearchProvider::ConvertResultsToAutocompleteMatches(), see comments
98     // there.
99     bool relevance_from_server_;
100 
101     // Whether this result was received asynchronously after the last
102     // keystroke, otherwise it must have come from prior cached results
103     // or from a synchronous provider.
104     bool received_after_last_keystroke_;
105 
106     // Optional deletion URL provided with suggestions. Fetching this URL
107     // should result in some reasonable deletion behaviour on the server,
108     // e.g. deleting this term out of a user's server-side search history.
109     std::string deletion_url_;
110   };
111 
112   class SuggestResult : public Result {
113    public:
114     SuggestResult(const base::string16& suggestion,
115                   AutocompleteMatchType::Type type,
116                   const base::string16& match_contents,
117                   const base::string16& match_contents_prefix,
118                   const base::string16& annotation,
119                   const base::string16& answer_contents,
120                   const base::string16& answer_type,
121                   const std::string& suggest_query_params,
122                   const std::string& deletion_url,
123                   bool from_keyword_provider,
124                   int relevance,
125                   bool relevance_from_server,
126                   bool should_prefetch,
127                   const base::string16& input_text);
128     virtual ~SuggestResult();
129 
suggestion()130     const base::string16& suggestion() const { return suggestion_; }
match_contents_prefix()131     const base::string16& match_contents_prefix() const {
132       return match_contents_prefix_;
133     }
annotation()134     const base::string16& annotation() const { return annotation_; }
suggest_query_params()135     const std::string& suggest_query_params() const {
136       return suggest_query_params_;
137     }
138 
answer_contents()139     const base::string16& answer_contents() const { return answer_contents_; }
answer_type()140     const base::string16& answer_type() const { return answer_type_; }
141 
should_prefetch()142     bool should_prefetch() const { return should_prefetch_; }
143 
144     // Fills in |match_contents_class_| to reflect how |match_contents_| should
145     // be displayed and bolded against the current |input_text|.  If
146     // |allow_bolding_all| is false and |match_contents_class_| would have all
147     // of |match_contents_| bolded, do nothing.
148     void ClassifyMatchContents(const bool allow_bolding_all,
149                                const base::string16& input_text);
150 
151     // Result:
152     virtual int CalculateRelevance(
153         const AutocompleteInput& input,
154         bool keyword_provider_requested) const OVERRIDE;
155 
156    private:
157     // The search terms to be used for this suggestion.
158     base::string16 suggestion_;
159 
160     // The contents to be displayed as prefix of match contents.
161     // Used for postfix suggestions to display a leading ellipsis (or some
162     // equivalent character) to indicate omitted text.
163     // Only used to pass this information to about:omnibox's "Additional Info".
164     base::string16 match_contents_prefix_;
165 
166     // Optional annotation for the |match_contents_| for disambiguation.
167     // This may be displayed in the autocomplete match contents, but is defined
168     // separately to facilitate different formatting.
169     base::string16 annotation_;
170 
171     // Optional additional parameters to be added to the search URL.
172     std::string suggest_query_params_;
173 
174     // Optional formatted Answers result.
175     base::string16 answer_contents_;
176 
177     // Type of optional formatted Answers result.
178     base::string16 answer_type_;
179 
180     // Should this result be prefetched?
181     bool should_prefetch_;
182   };
183 
184   class NavigationResult : public Result {
185    public:
186     NavigationResult(const AutocompleteSchemeClassifier& scheme_classifier,
187                      const GURL& url,
188                      AutocompleteMatchType::Type type,
189                      const base::string16& description,
190                      const std::string& deletion_url,
191                      bool from_keyword_provider,
192                      int relevance,
193                      bool relevance_from_server,
194                      const base::string16& input_text,
195                      const std::string& languages);
196     virtual ~NavigationResult();
197 
url()198     const GURL& url() const { return url_; }
description()199     const base::string16& description() const { return description_; }
formatted_url()200     const base::string16& formatted_url() const { return formatted_url_; }
201 
202     // Fills in |match_contents_| and |match_contents_class_| to reflect how
203     // the URL should be displayed and bolded against the current |input_text|
204     // and user |languages|.  If |allow_bolding_nothing| is false and
205     // |match_contents_class_| would result in an entirely unbolded
206     // |match_contents_|, do nothing.
207     void CalculateAndClassifyMatchContents(const bool allow_bolding_nothing,
208                                            const base::string16& input_text,
209                                            const std::string& languages);
210 
211     // Result:
212     virtual int CalculateRelevance(
213         const AutocompleteInput& input,
214         bool keyword_provider_requested) const OVERRIDE;
215 
216    private:
217     // The suggested url for navigation.
218     GURL url_;
219 
220     // The properly formatted ("fixed up") URL string with equivalent meaning
221     // to the one in |url_|.
222     base::string16 formatted_url_;
223 
224     // The suggested navigational result description; generally the site name.
225     base::string16 description_;
226   };
227 
228   typedef std::vector<SuggestResult> SuggestResults;
229   typedef std::vector<NavigationResult> NavigationResults;
230 
231   // A simple structure bundling most of the information (including
232   // both SuggestResults and NavigationResults) returned by a call to
233   // the suggest server.
234   //
235   // This has to be declared after the typedefs since it relies on some of them.
236   struct Results {
237     Results();
238     ~Results();
239 
240     // Clears |suggest_results| and |navigation_results| and resets
241     // |verbatim_relevance| to -1 (implies unset).
242     void Clear();
243 
244     // Returns whether any of the results (including verbatim) have
245     // server-provided scores.
246     bool HasServerProvidedScores() const;
247 
248     // Query suggestions sorted by relevance score.
249     SuggestResults suggest_results;
250 
251     // Navigational suggestions sorted by relevance score.
252     NavigationResults navigation_results;
253 
254     // The server supplied verbatim relevance scores. Negative values
255     // indicate that there is no suggested score; a value of 0
256     // suppresses the verbatim result.
257     int verbatim_relevance;
258 
259     // The JSON metadata associated with this server response.
260     std::string metadata;
261 
262     // If the active suggest field trial (if any) has triggered.
263     bool field_trial_triggered;
264 
265     // If the relevance values of the results are from the server.
266     bool relevances_from_server;
267 
268     // URLs of any images in Answers results.
269     std::vector<GURL> answers_image_urls;
270 
271    private:
272     DISALLOW_COPY_AND_ASSIGN(Results);
273   };
274 
275   // Extracts JSON data fetched by |source| and converts it to UTF-8.
276   static std::string ExtractJsonData(const net::URLFetcher* source);
277 
278   // Parses JSON response received from the provider, stripping XSSI
279   // protection if needed. Returns the parsed data if successful, NULL
280   // otherwise.
281   static scoped_ptr<base::Value> DeserializeJsonData(std::string json_data);
282 
283   // Parses results from the suggest server and updates the appropriate suggest
284   // and navigation result lists in |results|. |is_keyword_result| indicates
285   // whether the response was received from the keyword provider.
286   // Returns whether the appropriate result list members were updated.
287   static bool ParseSuggestResults(
288       const base::Value& root_val,
289       const AutocompleteInput& input,
290       const AutocompleteSchemeClassifier& scheme_classifier,
291       int default_result_relevance,
292       const std::string& languages,
293       bool is_keyword_result,
294       Results* results);
295 
296  private:
297   FRIEND_TEST_ALL_PREFIXES(SearchSuggestionParser,
298                            GetAnswersImageURLsWithoutImagelines);
299   FRIEND_TEST_ALL_PREFIXES(SearchSuggestionParser,
300                            GetAnswersImageURLsWithValidImage);
301 
302   // Gets URLs of any images in Answers results.
303   static void GetAnswersImageURLs(const base::DictionaryValue* answer_json,
304                                   std::vector<GURL>* urls);
305 
306   DISALLOW_COPY_AND_ASSIGN(SearchSuggestionParser);
307 };
308 
309 #endif  // COMPONENTS_OMNIBOX_SEARCH_SUGGESTION_PARSER_H_
310