Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / athena / extensions / shell / url_search_provider.cc
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 #include "athena/extensions/shell/url_search_provider.h"
6
7 #include "athena/activity/public/activity.h"
8 #include "athena/activity/public/activity_factory.h"
9 #include "athena/extensions/shell/athena_shell_scheme_classifier.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "components/metrics/proto/omnibox_event.pb.h"
13 #include "components/metrics/proto/omnibox_input_type.pb.h"
14 #include "components/omnibox/autocomplete_input.h"
15 #include "components/omnibox/autocomplete_provider_client.h"
16 #include "components/omnibox/search_provider.h"
17 #include "components/search_engines/search_terms_data.h"
18 #include "components/search_engines/template_url_service.h"
19 #include "components/search_engines/template_url_service_client.h"
20 #include "content/public/browser/browser_context.h"
21 #include "ui/app_list/search_result.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "url/gurl.h"
24
25 namespace athena {
26
27 namespace {
28
29 // This constant was copied from HistoryURLProvider.
30 // TODO(hashimoto): Componentize HistoryURLProvider and delete this.
31 const int kScoreForWhatYouTypedResult = 1203;
32
33 // The SearchTermsData implementation for Athena.
34 class AthenaSearchTermsData : public SearchTermsData {
35  public:
36   // SearchTermsData:
37   virtual std::string GetSuggestClient() const override { return "chrome"; }
38 };
39
40 // The templateURLServiceClient for Athena. Mainly for the interaction with
41 // history module (see chrome/browser/search_engines for Chrome implementation).
42 // TODO(mukai): Implement the contents of this class when it's necessary.
43 class AthenaTemplateURLServiceClient : public TemplateURLServiceClient {
44  public:
45   AthenaTemplateURLServiceClient() {}
46   ~AthenaTemplateURLServiceClient() override {}
47
48  private:
49   // TemplateURLServiceClient:
50   void Shutdown() override {}
51   void SetOwner(TemplateURLService* owner) override {}
52   void DeleteAllSearchTermsForKeyword(TemplateURLID id) override {}
53   void SetKeywordSearchTermsForURL(const GURL& url,
54                                    TemplateURLID id,
55                                    const base::string16& term) override {}
56   void AddKeywordGeneratedVisit(const GURL& url) override {}
57   void RestoreExtensionInfoIfNecessary(TemplateURL* template_url) override {}
58
59   DISALLOW_COPY_AND_ASSIGN(AthenaTemplateURLServiceClient);
60 };
61
62 // The AutocompleteProviderClient for Athena.
63 class AthenaAutocompleteProviderClient : public AutocompleteProviderClient {
64  public:
65   explicit AthenaAutocompleteProviderClient(
66       content::BrowserContext* browser_context)
67       : browser_context_(browser_context) {}
68   ~AthenaAutocompleteProviderClient() override {}
69
70   net::URLRequestContextGetter* RequestContext() override {
71     return browser_context_->GetRequestContext();
72   }
73   bool IsOffTheRecord() override { return browser_context_->IsOffTheRecord(); }
74   std::string AcceptLanguages() override {
75     // TODO(hashimoto): Return the value stored in the prefs.
76     return "en-US";
77   }
78   bool SearchSuggestEnabled() override { return true; }
79   bool ShowBookmarkBar() override { return false; }
80   const AutocompleteSchemeClassifier& SchemeClassifier() override {
81     return scheme_classifier_;
82   }
83   void Classify(
84       const base::string16& text,
85       bool prefer_keyword,
86       bool allow_exact_keyword_match,
87       metrics::OmniboxEventProto::PageClassification page_classification,
88       AutocompleteMatch* match,
89       GURL* alternate_nav_url) override {}
90   history::URLDatabase* InMemoryDatabase() override { return nullptr; }
91   void DeleteMatchingURLsForKeywordFromHistory(
92       history::KeywordID keyword_id,
93       const base::string16& term) override {}
94   bool TabSyncEnabledAndUnencrypted() override { return false; }
95   void PrefetchImage(const GURL& url) override {}
96
97  private:
98   content::BrowserContext* browser_context_;
99   AthenaShellSchemeClassifier scheme_classifier_;
100
101   DISALLOW_COPY_AND_ASSIGN(AthenaAutocompleteProviderClient);
102 };
103
104 int ACMatchStyleToTagStyle(int styles) {
105   int tag_styles = 0;
106   if (styles & ACMatchClassification::URL)
107     tag_styles |= app_list::SearchResult::Tag::URL;
108   if (styles & ACMatchClassification::MATCH)
109     tag_styles |= app_list::SearchResult::Tag::MATCH;
110   if (styles & ACMatchClassification::DIM)
111     tag_styles |= app_list::SearchResult::Tag::DIM;
112
113   return tag_styles;
114 }
115
116 // Translates ACMatchClassifications into SearchResult tags.
117 void ACMatchClassificationsToTags(const base::string16& text,
118                                   const ACMatchClassifications& text_classes,
119                                   app_list::SearchResult::Tags* tags) {
120   int tag_styles = app_list::SearchResult::Tag::NONE;
121   size_t tag_start = 0;
122
123   for (size_t i = 0; i < text_classes.size(); ++i) {
124     const ACMatchClassification& text_class = text_classes[i];
125
126     // Closes current tag.
127     if (tag_styles != app_list::SearchResult::Tag::NONE) {
128       tags->push_back(app_list::SearchResult::Tag(
129           tag_styles, tag_start, text_class.offset));
130       tag_styles = app_list::SearchResult::Tag::NONE;
131     }
132
133     if (text_class.style == ACMatchClassification::NONE)
134       continue;
135
136     tag_start = text_class.offset;
137     tag_styles = ACMatchStyleToTagStyle(text_class.style);
138   }
139
140   if (tag_styles != app_list::SearchResult::Tag::NONE) {
141     tags->push_back(
142         app_list::SearchResult::Tag(tag_styles, tag_start, text.length()));
143   }
144 }
145
146 class UrlSearchResult : public app_list::SearchResult {
147  public:
148   UrlSearchResult(content::BrowserContext* browser_context,
149                   const AutocompleteMatch& match)
150       : browser_context_(browser_context), match_(match) {
151     set_id(match_.destination_url.spec());
152
153     // Derive relevance from omnibox relevance and normalize it to [0, 1].
154     // The magic number 1500 is the highest score of an omnibox result.
155     // See comments in autocomplete_provider.h.
156     set_relevance(match_.relevance / 1500.0);
157
158     UpdateIcon();
159     UpdateTitleAndDetails();
160   }
161
162   ~UrlSearchResult() override {}
163
164  private:
165   // Overridden from app_list::SearchResult:
166   scoped_ptr<app_list::SearchResult> Duplicate() override {
167     return make_scoped_ptr(new UrlSearchResult(browser_context_, match_));
168   }
169
170   void Open(int event_flags) override {
171     Activity* activity = ActivityFactory::Get()->CreateWebActivity(
172         browser_context_, base::string16(), match_.destination_url);
173     Activity::Show(activity);
174   }
175
176   void UpdateIcon() {
177     SetIcon(*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
178         AutocompleteMatch::TypeToIcon(match_.type)));
179   }
180
181   void UpdateTitleAndDetails() {
182     set_title(match_.contents);
183     SearchResult::Tags title_tags;
184     ACMatchClassificationsToTags(
185         match_.contents, match_.contents_class, &title_tags);
186     set_title_tags(title_tags);
187
188     set_details(match_.description);
189     SearchResult::Tags details_tags;
190     ACMatchClassificationsToTags(
191         match_.description, match_.description_class, &details_tags);
192     set_details_tags(details_tags);
193   }
194
195   content::BrowserContext* browser_context_;
196   AutocompleteMatch match_;
197
198   DISALLOW_COPY_AND_ASSIGN(UrlSearchResult);
199 };
200
201 }  // namespace
202
203 UrlSearchProvider::UrlSearchProvider(content::BrowserContext* browser_context)
204     : browser_context_(browser_context),
205       // TODO(mukai): introduce the real parameters when it's necessary.
206       template_url_service_(new TemplateURLService(
207           nullptr /* prefs */,
208           scoped_ptr<SearchTermsData>(new AthenaSearchTermsData()),
209           nullptr /* KeywordWebDataService */,
210           scoped_ptr<TemplateURLServiceClient>(
211               new AthenaTemplateURLServiceClient()),
212           nullptr /*GoogleURLTracker */,
213           nullptr /* RapporService */,
214           base::Closure() /* dsp_change_callback */)),
215       provider_(new ::SearchProvider(
216           this,
217           template_url_service_.get(),
218           scoped_ptr<AutocompleteProviderClient>(
219               new AthenaAutocompleteProviderClient(browser_context_)))) {
220   template_url_service_->Load();
221 }
222
223 UrlSearchProvider::~UrlSearchProvider() {
224 }
225
226 void UrlSearchProvider::Start(const base::string16& query) {
227   const bool minimal_changes = query == input_.text();
228   input_ = AutocompleteInput(query,
229                              base::string16::npos /* cursor_position */,
230                              std::string() /* desired_tld */,
231                              GURL() /* current_url */,
232                              metrics::OmniboxEventProto::INVALID_SPEC,
233                              false /* prevent_inline_autocomplete */,
234                              false /* prefer_keyword */,
235                              true /* allow_extract_keyword_match */,
236                              true /* want_asynchronous_matches */,
237                              AthenaShellSchemeClassifier());
238
239   // Clearing results here may cause unexpected results.
240   // TODO(mukai): fix this by fixing crbug.com/415500
241   if (!minimal_changes)
242     ClearResults();
243
244   if (input_.type() == metrics::OmniboxInputType::URL) {
245     // TODO(hashimoto): Componentize HistoryURLProvider and remove this code.
246     AutocompleteMatch what_you_typed_match(
247         nullptr, 0, false, AutocompleteMatchType::URL_WHAT_YOU_TYPED);
248     what_you_typed_match.destination_url = input_.canonicalized_url();
249     what_you_typed_match.contents = input_.text();
250     what_you_typed_match.relevance = kScoreForWhatYouTypedResult;
251     Add(scoped_ptr<app_list::SearchResult>(
252         new UrlSearchResult(browser_context_, what_you_typed_match)));
253   }
254
255   provider_->Start(input_, minimal_changes);
256 }
257
258 void UrlSearchProvider::Stop() {
259   provider_->Stop(false);
260 }
261
262 void UrlSearchProvider::OnProviderUpdate(bool updated_matches) {
263   if (!updated_matches)
264     return;
265
266   const ACMatches& matches = provider_->matches();
267   for (ACMatches::const_iterator it = matches.begin(); it != matches.end();
268        ++it) {
269     if (!it->destination_url.is_valid())
270       continue;
271
272     Add(scoped_ptr<app_list::SearchResult>(
273         new UrlSearchResult(browser_context_, *it)));
274   }
275 }
276
277 }  // namespace athena