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.
5 #include "chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h"
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"
32 class TypeConverter<mojo::Array<AutocompleteAdditionalInfo>,
33 AutocompleteMatch::AdditionalInfo> {
35 static mojo::Array<AutocompleteAdditionalInfo> ConvertFrom(
36 const AutocompleteMatch::AdditionalInfo& input,
38 mojo::Array<AutocompleteAdditionalInfo>::Builder array_builder(
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();
48 return array_builder.Finish();
51 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
55 class TypeConverter<AutocompleteMatchMojo, AutocompleteMatch> {
57 static AutocompleteMatchMojo ConvertFrom(const AutocompleteMatch& input,
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());
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);
89 builder.set_additional_info(input.additional_info);
90 return builder.Finish();
93 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
97 class TypeConverter<AutocompleteResultsForProviderMojo, AutocompleteProvider*> {
99 static AutocompleteResultsForProviderMojo ConvertFrom(
100 const AutocompleteProvider* input,
102 AutocompleteResultsForProviderMojo::Builder builder(buf);
103 builder.set_provider_name(input->GetName());
105 mojo::Array<AutocompleteMatchMojo>::From(input->matches()));
106 return builder.Finish();
109 MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
114 OmniboxUIHandler::OmniboxUIHandler(Profile* profile)
120 OmniboxUIHandler::~OmniboxUIHandler() {}
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);
133 if (!LookupIsTypedHost(host, &is_typed_host))
134 is_typed_host = false;
135 builder.set_is_typed_host(is_typed_host);
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));
145 builder.set_results_by_provider(
146 mojo::Array<AutocompleteResultsForProviderMojo>::From(
147 *controller_->providers()));
148 page_->HandleNewAutocompleteResult(builder.Finish());
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)
158 history::URLDatabase* url_db = history_service->InMemoryDatabase();
161 *is_typed_host = url_db->IsTypedHost(base::UTF16ToUTF8(host));
165 void OmniboxUIHandler::SetClient(OmniboxPage* page) {
169 void OmniboxUIHandler::StartOmniboxQuery(const mojo::String& input_string,
170 int32_t cursor_position,
171 bool prevent_inline_autocomplete,
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.
180 time_omnibox_started_ = base::Time::Now();
181 input_ = AutocompleteInput(
184 base::string16(), // user's desired tld (top-level domain)
186 static_cast<AutocompleteInput::PageClassification>(
187 page_classification),
188 prevent_inline_autocomplete,
190 true, // allow exact keyword matches
192 controller_->Start(input_); // want all matches
195 void OmniboxUIHandler::ResetController() {
196 controller_.reset(new AutocompleteController(profile_, this,
197 AutocompleteClassifier::kDefaultOmniboxProviders));