Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / omnibox / omnibox_ui_handler.cc
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 #include "chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h"
6
7 #include <string>
8
9 #include "base/auto_reset.h"
10 #include "base/bind.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
17 #include "chrome/browser/autocomplete/autocomplete_controller.h"
18 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
19 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
20 #include "chrome/browser/history/history_service.h"
21 #include "chrome/browser/history/history_service_factory.h"
22 #include "chrome/browser/search/search.h"
23 #include "chrome/browser/search_engines/template_url_service_factory.h"
24 #include "components/bookmarks/browser/bookmark_model.h"
25 #include "components/history/core/browser/url_database.h"
26 #include "components/metrics/proto/omnibox_event.pb.h"
27 #include "components/omnibox/autocomplete_match.h"
28 #include "components/omnibox/autocomplete_provider.h"
29 #include "components/search_engines/template_url.h"
30 #include "content/public/browser/web_ui.h"
31 #include "mojo/common/common_type_converters.h"
32
33 namespace mojo {
34
35 template <>
36 class TypeConverter<mojo::Array<AutocompleteAdditionalInfoPtr>,
37                     AutocompleteMatch::AdditionalInfo> {
38  public:
39   static mojo::Array<AutocompleteAdditionalInfoPtr> ConvertFrom(
40       const AutocompleteMatch::AdditionalInfo& input) {
41     mojo::Array<AutocompleteAdditionalInfoPtr> array(input.size());
42     size_t index = 0;
43     for (AutocompleteMatch::AdditionalInfo::const_iterator i = input.begin();
44          i != input.end(); ++i, index++) {
45       AutocompleteAdditionalInfoPtr item(AutocompleteAdditionalInfo::New());
46       item->key = i->first;
47       item->value = i->second;
48       array[index] = item.Pass();
49     }
50     return array.Pass();
51   }
52 };
53
54 template <>
55 class TypeConverter<AutocompleteMatchMojoPtr, AutocompleteMatch> {
56  public:
57   static AutocompleteMatchMojoPtr ConvertFrom(const AutocompleteMatch& input) {
58     AutocompleteMatchMojoPtr result(AutocompleteMatchMojo::New());
59     if (input.provider != NULL) {
60       result->provider_name = input.provider->GetName();
61       result->provider_done = input.provider->done();
62     }
63     result->relevance = input.relevance;
64     result->deletable = input.deletable;
65     result->fill_into_edit = mojo::String::From(input.fill_into_edit);
66     result->inline_autocompletion =
67         mojo::String::From(input.inline_autocompletion);
68     result->destination_url = input.destination_url.spec();
69     result->contents = mojo::String::From(input.contents);
70     // At this time, we're not bothering to send along the long vector that
71     // represent contents classification.  i.e., for each character, what
72     // type of text it is.
73     result->description = mojo::String::From(input.description);
74     // At this time, we're not bothering to send along the long vector that
75     // represents description classification.  i.e., for each character, what
76     // type of text it is.
77     result->transition = input.transition;
78     result->is_history_what_you_typed_match =
79         input.is_history_what_you_typed_match;
80     result->allowed_to_be_default_match = input.allowed_to_be_default_match;
81     result->type = AutocompleteMatchType::ToString(input.type);
82     if (input.associated_keyword.get() != NULL) {
83       result->associated_keyword =
84           mojo::String::From(input.associated_keyword->keyword);
85     }
86     result->keyword = mojo::String::From(input.keyword);
87     result->duplicates = static_cast<int32>(input.duplicate_matches.size());
88     result->from_previous = input.from_previous;
89
90     result->additional_info =
91         mojo::Array<AutocompleteAdditionalInfoPtr>::From(input.additional_info);
92     return result.Pass();
93   }
94 };
95
96 template <>
97 class TypeConverter<AutocompleteResultsForProviderMojoPtr,
98                     scoped_refptr<AutocompleteProvider> > {
99  public:
100   static AutocompleteResultsForProviderMojoPtr ConvertFrom(
101       const scoped_refptr<AutocompleteProvider>& input) {
102     AutocompleteResultsForProviderMojoPtr result(
103         AutocompleteResultsForProviderMojo::New());
104     result->provider_name = input->GetName();
105     result->results =
106         mojo::Array<AutocompleteMatchMojoPtr>::From(input->matches());
107     return result.Pass();
108   }
109 };
110
111 }  // namespace mojo
112
113 OmniboxUIHandler::OmniboxUIHandler(Profile* profile)
114     : profile_(profile) {
115   ResetController();
116 }
117
118 OmniboxUIHandler::~OmniboxUIHandler() {}
119
120 void OmniboxUIHandler::OnResultChanged(bool default_match_changed) {
121   OmniboxResultMojoPtr result(OmniboxResultMojo::New());
122   result->done = controller_->done();
123   result->time_since_omnibox_started_ms =
124       (base::Time::Now() - time_omnibox_started_).InMilliseconds();
125   const base::string16 host = input_.text().substr(
126       input_.parts().host.begin,
127       input_.parts().host.len);
128   result->host = mojo::String::From(host);
129   bool is_typed_host;
130   if (!LookupIsTypedHost(host, &is_typed_host))
131     is_typed_host = false;
132   result->is_typed_host = is_typed_host;
133
134   {
135     // Copy to an ACMatches to make conversion easier. Since this isn't
136     // performance critical we don't worry about the cost here.
137     ACMatches matches(controller_->result().begin(),
138                       controller_->result().end());
139     result->combined_results =
140         mojo::Array<AutocompleteMatchMojoPtr>::From(matches);
141   }
142   result->results_by_provider =
143       mojo::Array<AutocompleteResultsForProviderMojoPtr>::From(
144           controller_->providers());
145
146   // Fill AutocompleteMatchMojo::starred.
147   BookmarkModel* bookmark_model = BookmarkModelFactory::GetForProfile(profile_);
148   if (bookmark_model) {
149     for (size_t i =  0; i < result->combined_results.size(); ++i) {
150       result->combined_results[i]->starred = bookmark_model->IsBookmarked(
151           GURL(result->combined_results[i]->destination_url));
152     }
153     for (size_t i = 0; i < result->results_by_provider.size(); ++i) {
154       const AutocompleteResultsForProviderMojo& result_by_provider =
155           *result->results_by_provider[i];
156       for (size_t j = 0; j < result_by_provider.results.size(); ++j) {
157         result_by_provider.results[j]->starred = bookmark_model->IsBookmarked(
158             GURL(result_by_provider.results[j]->destination_url));
159       }
160     }
161   }
162
163   client()->HandleNewAutocompleteResult(result.Pass());
164 }
165
166 bool OmniboxUIHandler::LookupIsTypedHost(const base::string16& host,
167                                          bool* is_typed_host) const {
168   HistoryService* const history_service =
169       HistoryServiceFactory::GetForProfile(profile_,
170                                            Profile::EXPLICIT_ACCESS);
171   if (!history_service)
172     return false;
173   history::URLDatabase* url_db = history_service->InMemoryDatabase();
174   if (!url_db)
175     return false;
176   *is_typed_host = url_db->IsTypedHost(base::UTF16ToUTF8(host));
177   return true;
178 }
179
180 void OmniboxUIHandler::StartOmniboxQuery(const mojo::String& input_string,
181                                          int32_t cursor_position,
182                                          bool prevent_inline_autocomplete,
183                                          bool prefer_keyword,
184                                          int32_t page_classification) {
185   // Reset the controller.  If we don't do this, then the
186   // AutocompleteController might inappropriately set its |minimal_changes|
187   // variable (or something else) and some providers will short-circuit
188   // important logic and return stale results.  In short, we want the
189   // actual results to not depend on the state of the previous request.
190   ResetController();
191   time_omnibox_started_ = base::Time::Now();
192   input_ = AutocompleteInput(
193       input_string.To<base::string16>(), cursor_position, base::string16(),
194       GURL(),
195       static_cast<metrics::OmniboxEventProto::PageClassification>(
196           page_classification),
197       prevent_inline_autocomplete, prefer_keyword, true, true,
198       ChromeAutocompleteSchemeClassifier(profile_));
199   controller_->Start(input_);
200 }
201
202 void OmniboxUIHandler::ResetController() {
203   controller_.reset(new AutocompleteController(profile_,
204           TemplateURLServiceFactory::GetForProfile(profile_),
205           this,
206           AutocompleteClassifier::kDefaultOmniboxProviders));
207 }