Upstream version 7.36.149.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/autocomplete_match.h"
19 #include "chrome/browser/autocomplete/autocomplete_provider.h"
20 #include "chrome/browser/history/history_service.h"
21 #include "chrome/browser/history/history_service_factory.h"
22 #include "chrome/browser/history/url_database.h"
23 #include "chrome/browser/search/search.h"
24 #include "chrome/browser/search_engines/template_url.h"
25 #include "content/public/browser/web_ui.h"
26 #include "mojo/common/common_type_converters.h"
27 #include "mojo/public/cpp/bindings/allocation_scope.h"
28
29 namespace mojo {
30
31 template <>
32 class TypeConverter<mojo::Array<AutocompleteAdditionalInfo>,
33                     AutocompleteMatch::AdditionalInfo> {
34  public:
35   static mojo::Array<AutocompleteAdditionalInfo> ConvertFrom(
36       const AutocompleteMatch::AdditionalInfo& input,
37       Buffer* buf) {
38     mojo::Array<AutocompleteAdditionalInfo>::Builder array_builder(
39         input.size(), buf);
40     size_t index = 0;
41     for (AutocompleteMatch::AdditionalInfo::const_iterator i = input.begin();
42          i != input.end(); ++i, index++) {
43       AutocompleteAdditionalInfo::Builder item_builder(buf);
44       item_builder.set_key(i->first);
45       item_builder.set_value(i->second);
46       array_builder[index] = item_builder.Finish();
47     }
48     return array_builder.Finish();
49   }
50
51   MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
52 };
53
54 template <>
55 class TypeConverter<AutocompleteMatchMojo, AutocompleteMatch> {
56  public:
57   static AutocompleteMatchMojo ConvertFrom(const AutocompleteMatch& input,
58                                            Buffer* buf) {
59     AutocompleteMatchMojo::Builder builder(buf);
60     if (input.provider != NULL) {
61       builder.set_provider_name(input.provider->GetName());
62       builder.set_provider_done(input.provider->done());
63     }
64     builder.set_relevance(input.relevance);
65     builder.set_deletable(input.deletable);
66     builder.set_fill_into_edit(input.fill_into_edit);
67     builder.set_inline_autocompletion(input.inline_autocompletion);
68     builder.set_destination_url(input.destination_url.spec());
69     builder.set_contents(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     builder.set_description(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     builder.set_transition(input.transition);
78     builder.set_is_history_what_you_typed_match(
79         input.is_history_what_you_typed_match);
80     builder.set_allowed_to_be_default_match(input.allowed_to_be_default_match);
81     builder.set_type(AutocompleteMatchType::ToString(input.type));
82     if (input.associated_keyword.get() != NULL)
83       builder.set_associated_keyword(input.associated_keyword->keyword);
84     builder.set_keyword(input.keyword);
85     builder.set_starred(input.starred);
86     builder.set_duplicates(static_cast<int32>(input.duplicate_matches.size()));
87     builder.set_from_previous(input.from_previous);
88
89     builder.set_additional_info(input.additional_info);
90     return builder.Finish();
91   }
92
93   MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
94 };
95
96 template <>
97 class TypeConverter<AutocompleteResultsForProviderMojo, AutocompleteProvider*> {
98  public:
99   static AutocompleteResultsForProviderMojo ConvertFrom(
100       const AutocompleteProvider* input,
101       Buffer* buf) {
102     AutocompleteResultsForProviderMojo::Builder builder(buf);
103     builder.set_provider_name(input->GetName());
104     builder.set_results(
105         mojo::Array<AutocompleteMatchMojo>::From(input->matches()));
106     return builder.Finish();
107   }
108
109   MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
110 };
111
112 }  // namespace mojo
113
114 OmniboxUIHandler::OmniboxUIHandler(Profile* profile)
115     : page_(NULL),
116       profile_(profile) {
117   ResetController();
118 }
119
120 OmniboxUIHandler::~OmniboxUIHandler() {}
121
122 void OmniboxUIHandler::OnResultChanged(bool default_match_changed) {
123   mojo::AllocationScope scope;
124   OmniboxResultMojo::Builder builder;
125   builder.set_done(controller_->done());
126   builder.set_time_since_omnibox_started_ms(
127       (base::Time::Now() - time_omnibox_started_).InMilliseconds());
128   const base::string16 host = input_.text().substr(
129       input_.parts().host.begin,
130       input_.parts().host.len);
131   builder.set_host(host);
132   bool is_typed_host;
133   if (!LookupIsTypedHost(host, &is_typed_host))
134     is_typed_host = false;
135   builder.set_is_typed_host(is_typed_host);
136
137   {
138     // Copy to an ACMatches to make conversion easier. Since this isn't
139     // performance critical we don't worry about the cost here.
140     ACMatches matches(controller_->result().begin(),
141                       controller_->result().end());
142     builder.set_combined_results(
143         mojo::Array<AutocompleteMatchMojo>::From(matches));
144   }
145   builder.set_results_by_provider(
146       mojo::Array<AutocompleteResultsForProviderMojo>::From(
147           *controller_->providers()));
148   page_->HandleNewAutocompleteResult(builder.Finish());
149 }
150
151 bool OmniboxUIHandler::LookupIsTypedHost(const base::string16& host,
152                                          bool* is_typed_host) const {
153   HistoryService* const history_service =
154       HistoryServiceFactory::GetForProfile(profile_,
155                                            Profile::EXPLICIT_ACCESS);
156   if (!history_service)
157     return false;
158   history::URLDatabase* url_db = history_service->InMemoryDatabase();
159   if (!url_db)
160     return false;
161   *is_typed_host = url_db->IsTypedHost(base::UTF16ToUTF8(host));
162   return true;
163 }
164
165 void OmniboxUIHandler::SetClient(OmniboxPage* page) {
166   page_ = page;
167 }
168
169 void OmniboxUIHandler::StartOmniboxQuery(const mojo::String& input_string,
170                                          int32_t cursor_position,
171                                          bool prevent_inline_autocomplete,
172                                          bool prefer_keyword,
173                                          int32_t page_classification) {
174   // Reset the controller.  If we don't do this, then the
175   // AutocompleteController might inappropriately set its |minimal_changes|
176   // variable (or something else) and some providers will short-circuit
177   // important logic and return stale results.  In short, we want the
178   // actual results to not depend on the state of the previous request.
179   ResetController();
180   time_omnibox_started_ = base::Time::Now();
181   input_ = AutocompleteInput(
182       input_string,
183       cursor_position,
184       base::string16(),  // user's desired tld (top-level domain)
185       GURL(),
186       static_cast<AutocompleteInput::PageClassification>(
187           page_classification),
188       prevent_inline_autocomplete,
189       prefer_keyword,
190       true,  // allow exact keyword matches
191       true);
192   controller_->Start(input_);  // want all matches
193 }
194
195 void OmniboxUIHandler::ResetController() {
196   controller_.reset(new AutocompleteController(profile_, this,
197           AutocompleteClassifier::kDefaultOmniboxProviders));
198 }