diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 19:24:20 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 19:24:20 +0000 |
commit | 6b6c0acee895c03e9aa71bb99b40ffb1e1f6cd13 (patch) | |
tree | 32faf47c06f0b68bc3ec8688d093a3815e1d9526 /chrome/browser | |
parent | eba06dcf44a3538a6e413a6f3886b9bc561f0883 (diff) | |
download | chromium_src-6b6c0acee895c03e9aa71bb99b40ffb1e1f6cd13.zip chromium_src-6b6c0acee895c03e9aa71bb99b40ffb1e1f6cd13.tar.gz chromium_src-6b6c0acee895c03e9aa71bb99b40ffb1e1f6cd13.tar.bz2 |
Makes chrome://omnibox use mojo
For the time being I'm moving chrome://omnibox behind USE_MOJO. Dave
has a patch out to enable USE_MOJO for Mac, which means it's only
android that won't have it for the time being.
BUG=none
TEST=none
R=darin@chromium.org
Review URL: https://codereview.chromium.org/222543004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262176 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_resources.grd | 1 | ||||
-rw-r--r-- | chrome/browser/resources/omnibox/omnibox.js | 120 | ||||
-rw-r--r-- | chrome/browser/ui/webui/mojo_web_ui_controller.cc | 38 | ||||
-rw-r--r-- | chrome/browser/ui/webui/mojo_web_ui_controller.h | 53 | ||||
-rw-r--r-- | chrome/browser/ui/webui/mojo_web_ui_handler.h | 16 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox.mojom | 62 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox_ui.cc | 20 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox_ui.h | 8 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc | 246 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h | 63 |
10 files changed, 357 insertions, 270 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 1debfb8..2425213 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -208,6 +208,7 @@ <include name="IDR_OMNIBOX_HTML" file="resources\omnibox\omnibox.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_OMNIBOX_CSS" file="resources\omnibox\omnibox.css" type="BINDATA" /> <include name="IDR_OMNIBOX_JS" file="resources\omnibox\omnibox.js" type="BINDATA" /> + <include name="IDR_OMNIBOX_MOJO_JS" file="${omnibox_mojom_file}" use_base_dir="false" type="BINDATA"/> <if expr="not is_android"> <include name="IDR_PLUGINS_HTML" file="resources\plugins.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PLUGINS_JS" file="resources\plugins.js" type="BINDATA" /> diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js index f30bfc1..afde3e0 100644 --- a/chrome/browser/resources/omnibox/omnibox.js +++ b/chrome/browser/resources/omnibox/omnibox.js @@ -16,9 +16,15 @@ * results are available. When results (possibly intermediate ones) * are available, the Javascript formats them and displays them. */ -cr.define('omniboxDebug', function() { +define('main', [ + 'mojo/public/js/bindings/connection', + 'chrome/browser/ui/webui/omnibox/omnibox.mojom', +], function(connector, browser) { 'use strict'; + var connection; + var page; + /** * Register our event handlers. */ @@ -35,10 +41,9 @@ cr.define('omniboxDebug', function() { } /** - * @type {Array.<Object>} an array of all autocomplete results we've seen + * @type {OmniboxResultMojo} an array of all autocomplete results we've seen * for this query. We append to this list once for every call to - * handleNewAutocompleteResult. For details on the structure of - * the object inside, see the comments by addResultToOutput. + * handleNewAutocompleteResult. See omnibox.mojom for details.. */ var progressiveAutocompleteResults = []; @@ -65,12 +70,12 @@ cr.define('omniboxDebug', function() { // - forth element: the value of prefer-keyword // - fifth element: the value of page-classification cursorPositionUsed = $('input-text').selectionEnd; - chrome.send('startOmniboxQuery', [ + page.browser_.startOmniboxQuery( $('input-text').value, cursorPositionUsed, $('prevent-inline-autocomplete').checked, $('prefer-keyword').checked, - parseInt($('page-classification').value)]); + parseInt($('page-classification').value)); // Cancel the submit action. i.e., don't submit the form. (We handle // display the results solely with Javascript.) event.preventDefault(); @@ -152,8 +157,6 @@ cr.define('omniboxDebug', function() { 'A green checkmark indicates that the provider is done looking for ' + 'more results.'), new PresentationInfoRecord( - 'Template URL', '', 'template_url', false, ''), - new PresentationInfoRecord( 'Associated Keyword', '', 'associated_keyword', false, 'If non-empty, a "press tab to search" hint will be shown and will ' + 'engage this keyword.'), @@ -213,21 +216,22 @@ cr.define('omniboxDebug', function() { if (propertyName in autocompleteSuggestion) { if (propertyName == 'additional_info') { // |additional_info| embeds a two-column table of provider-specific data - // within this cell. + // within this cell. |additional_info| is an array of + // AutocompleteAdditionalInfo. var additionalInfoTable = document.createElement('table'); - for (var additionalInfoKey in autocompleteSuggestion[propertyName]) { + for (var i = 0; i < autocompleteSuggestion[propertyName].length; i++) { + var additionalInfo = autocompleteSuggestion[propertyName][i]; var additionalInfoRow = document.createElement('tr'); // Set the title (name of property) cell text. var propertyCell = document.createElement('td'); - propertyCell.textContent = additionalInfoKey + ':'; + propertyCell.textContent = additionalInfo.key + ':'; propertyCell.className = 'additional-info-property'; additionalInfoRow.appendChild(propertyCell); // Set the value of the property cell text. var valueCell = document.createElement('td'); - valueCell.textContent = - autocompleteSuggestion[propertyName][additionalInfoKey]; + valueCell.textContent = additionalInfo.value; valueCell.className = 'additional-info-value'; additionalInfoRow.appendChild(valueCell); @@ -264,59 +268,11 @@ cr.define('omniboxDebug', function() { } /** - * Called by C++ code when we get an update from the - * AutocompleteController. We simply append the result to - * progressiveAutocompleteResults and refresh the page. - */ - function handleNewAutocompleteResult(result) { - progressiveAutocompleteResults.push(result); - refresh(); - } - - /** * Appends some human-readable information about the provided * autocomplete result to the HTML node with id omnibox-debug-text. * The current human-readable form is a few lines about general * autocomplete result statistics followed by a table with one line - * for each autocomplete match. The input parameter result is a - * complex Object with lots of information about various - * autocomplete matches. Here's an example of what it looks like: - * <pre> - * {@code - * { - * 'done': false, - * 'time_since_omnibox_started_ms': 15, - * 'host': 'mai', - * 'is_typed_host': false, - * 'combined_results' : { - * 'num_items': 4, - * 'item_0': { - * 'destination_url': 'http://mail.google.com', - * 'provider_name': 'HistoryURL', - * 'relevance': 1410, - * ... - * } - * 'item_1: { - * ... - * } - * ... - * } - * 'results_by_provider': { - * 'HistoryURL' : { - * 'num_items': 3, - * ... - * } - * 'Search' : { - * 'num_items': 1, - * ... - * } - * ... - * } - * } - * } - * </pre> - * For more information on how the result is packed, see the - * corresponding code in chrome/browser/ui/webui/omnibox_ui.cc + * for each autocomplete match. The input parameter is an OmniboxResultMojo. */ function addResultToOutput(result) { var output = $('omnibox-debug-text'); @@ -377,23 +333,20 @@ cr.define('omniboxDebug', function() { // Add the per-provider result tables with labels. We do not append the // combined/merged result table since we already have the per provider // results. - for (var provider in result.results_by_provider) { - var results = result.results_by_provider[provider]; + for (var i = 0; i < result.results_by_provider.length; i++) { + var providerResults = result.results_by_provider[i]; // If we have no results we do not display anything. - if (results.num_items == 0) { + if (providerResults.results.length == 0) { continue; } var p = document.createElement('p'); - p.appendChild(addResultTableToOutput(results)); + p.appendChild(addResultTableToOutput(providerResults.results)); output.appendChild(p); } } /** - * @param {Object} result either the combined_results component of - * the structure described in the comment by addResultToOutput() - * above or one of the per-provider results in the structure. - * (Both have the same format). + * @param {Object} result an array of AutocompleteMatchMojos. * @return {HTMLTableCellElement} that is a user-readable HTML * representation of this object. */ @@ -404,8 +357,8 @@ cr.define('omniboxDebug', function() { table.className = 'autocomplete-results-table'; table.appendChild(createAutocompleteResultTableHeader()); // Loop over every autocomplete item and add it as a row in the table. - for (var i = 0; i < result.num_items; i++) { - var autocompleteSuggestion = result['item_' + i]; + for (var i = 0; i < result.length; i++) { + var autocompleteSuggestion = result[i]; var row = document.createElement('tr'); // Loop over all the columns/properties and output either them // all (if we're in detailed mode) or only the ones marked displayAlways. @@ -464,11 +417,22 @@ cr.define('omniboxDebug', function() { } } - return { - initialize: initialize, - startOmniboxQuery: startOmniboxQuery, - handleNewAutocompleteResult: handleNewAutocompleteResult + function OmniboxPageImpl(browser) { + this.browser_ = browser; + page = this; + initialize(); + } + + OmniboxPageImpl.prototype = + Object.create(browser.OmniboxPageStub.prototype); + + OmniboxPageImpl.prototype.handleNewAutocompleteResult = function(result) { + progressiveAutocompleteResults.push(result); + refresh(); }; -}); -document.addEventListener('DOMContentLoaded', omniboxDebug.initialize); + return function(handle) { + connection = new connector.Connection(handle, OmniboxPageImpl, + browser.OmniboxUIHandlerMojoProxy); + }; +}); diff --git a/chrome/browser/ui/webui/mojo_web_ui_controller.cc b/chrome/browser/ui/webui/mojo_web_ui_controller.cc new file mode 100644 index 0000000..099efaf --- /dev/null +++ b/chrome/browser/ui/webui/mojo_web_ui_controller.cc @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/mojo_web_ui_controller.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/mojo_web_ui_handler.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/bindings_policy.h" +#include "mojo/public/cpp/bindings/interface.h" + +MojoWebUIController::MojoWebUIController(content::WebUI* contents) + : WebUIController(contents), + mojo_data_source_(NULL) { +} + +MojoWebUIController::~MojoWebUIController() { +} + +void MojoWebUIController::RenderViewCreated( + content::RenderViewHost* render_view_host) { + render_view_host->AllowBindings(content::BINDINGS_POLICY_WEB_UI); + + mojo::InterfacePipe<mojo::AnyInterface, mojo::AnyInterface> pipe; + ui_handler_ = CreateUIHandler(pipe.handle_to_peer.Pass()); + render_view_host->SetWebUIHandle(pipe.handle_to_self.Pass()); +} + +void MojoWebUIController::AddMojoResourcePath(const std::string& path, + int resource_id) { + if (!mojo_data_source_) { + mojo_data_source_ = content::WebUIDataSource::AddMojoDataSource( + Profile::FromWebUI(web_ui())); + } + mojo_data_source_->AddResourcePath(path, resource_id); +} diff --git a/chrome/browser/ui/webui/mojo_web_ui_controller.h b/chrome/browser/ui/webui/mojo_web_ui_controller.h new file mode 100644 index 0000000..cf79861 --- /dev/null +++ b/chrome/browser/ui/webui/mojo_web_ui_controller.h @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_CONTROLLER_H_ +#define CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_CONTROLLER_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/web_ui_controller.h" +#include "mojo/public/cpp/system/core.h" + +class MojoWebUIHandler; + +namespace content { +class WebUIDataSource; +} + +// MojoWebUIController is intended for web ui pages that use mojo. It is +// expected that subclasses will do two things: +// . In the constructor invoke AddMojoResourcePath() to register the bindings +// files, eg: +// AddMojoResourcePath("chrome/browser/ui/webui/omnibox/omnibox.mojom", +// IDR_OMNIBOX_MOJO_JS); +// . Override CreateUIHandler() to create the implementation of the bindings. +class MojoWebUIController : public content::WebUIController { + public: + explicit MojoWebUIController(content::WebUI* contents); + virtual ~MojoWebUIController(); + + // WebUIController overrides: + virtual void RenderViewCreated( + content::RenderViewHost* render_view_host) OVERRIDE; + + protected: + // Invoke to register mapping between binding file and resource id (IDR_...). + void AddMojoResourcePath(const std::string& path, int resource_id); + + // Invoked to create the specific bindings implementation. + virtual scoped_ptr<MojoWebUIHandler> CreateUIHandler( + mojo::ScopedMessagePipeHandle handle_to_page) = 0; + + private: + // Bindings files are registered here. + content::WebUIDataSource* mojo_data_source_; + + scoped_ptr<MojoWebUIHandler> ui_handler_; + + DISALLOW_COPY_AND_ASSIGN(MojoWebUIController); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_CONTROLLER_H_ diff --git a/chrome/browser/ui/webui/mojo_web_ui_handler.h b/chrome/browser/ui/webui/mojo_web_ui_handler.h new file mode 100644 index 0000000..22d2ef0 --- /dev/null +++ b/chrome/browser/ui/webui/mojo_web_ui_handler.h @@ -0,0 +1,16 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_HANDLER_H_ + +// Bindings implementations must subclass this. Used so that MojoWebUIController +// can own the binding implementation. +class MojoWebUIHandler { + public: + MojoWebUIHandler() {} + virtual ~MojoWebUIHandler() {} +}; + +#endif // CHROME_BROWSER_UI_WEBUI_MOJO_WEB_UI_HANDLER_H_ diff --git a/chrome/browser/ui/webui/omnibox/omnibox.mojom b/chrome/browser/ui/webui/omnibox/omnibox.mojom new file mode 100644 index 0000000..5dcf32c --- /dev/null +++ b/chrome/browser/ui/webui/omnibox/omnibox.mojom @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The structures here roughly mirror those from autocomplete. + +struct AutocompleteAdditionalInfo { + string key; + string value; +}; + +struct AutocompleteMatchMojo { + string provider_name; + // Only meaningful if |provider_name| is valid. + bool provider_done; + int32 relevance; + bool deletable; + string fill_into_edit; + string inline_autocompletion; + string destination_url; + string contents; + string description; + int32 transition; + bool is_history_what_you_typed_match; + bool allowed_to_be_default_match; + string type; + string associated_keyword; + string keyword; + bool starred; + int32 duplicates; + bool from_previous; + AutocompleteAdditionalInfo[] additional_info; +}; + +struct AutocompleteResultsForProviderMojo { + string provider_name; + AutocompleteMatchMojo[] results; +}; + +struct OmniboxResultMojo { + bool done; + // Time delta since the request was started, in milliseconds. + int32 time_since_omnibox_started_ms; + string host; + bool is_typed_host; + AutocompleteMatchMojo[] combined_results; + AutocompleteResultsForProviderMojo[] results_by_provider; +}; + +[Peer=OmniboxPage] +interface OmniboxUIHandlerMojo { + StartOmniboxQuery(string input_string, + int32 cursor_position, + bool prevent_inline_autocomplete, + bool prefer_keyword, + int32 page_classification); +}; + +[Peer=OmniboxUIHandlerMojo] +interface OmniboxPage { + HandleNewAutocompleteResult(OmniboxResultMojo result); +}; diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui.cc b/chrome/browser/ui/webui/omnibox/omnibox_ui.cc index d677beb..b288fc3 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui.cc @@ -12,8 +12,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "grit/browser_resources.h" -OmniboxUI::OmniboxUI(content::WebUI* web_ui) - : content::WebUIController(web_ui) { +OmniboxUI::OmniboxUI(content::WebUI* web_ui) : MojoWebUIController(web_ui) { // Set up the chrome://omnibox/ source. content::WebUIDataSource* html_source = content::WebUIDataSource::Create(chrome::kChromeUIOmniboxHost); @@ -21,11 +20,18 @@ OmniboxUI::OmniboxUI(content::WebUI* web_ui) html_source->AddResourcePath("omnibox.js", IDR_OMNIBOX_JS); html_source->SetDefaultResource(IDR_OMNIBOX_HTML); - Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, html_source); + content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source); - // AddMessageHandler takes ownership of OmniboxUIHandler - web_ui->AddMessageHandler(new OmniboxUIHandler(profile)); + AddMojoResourcePath("chrome/browser/ui/webui/omnibox/omnibox.mojom", + IDR_OMNIBOX_MOJO_JS); } -OmniboxUI::~OmniboxUI() { } +OmniboxUI::~OmniboxUI() {} + +scoped_ptr<MojoWebUIHandler> OmniboxUI::CreateUIHandler( + mojo::ScopedMessagePipeHandle handle_to_page) { + return scoped_ptr<MojoWebUIHandler>( + new OmniboxUIHandler( + ScopedOmniboxPageHandle::From(handle_to_page.Pass()).Pass(), + Profile::FromWebUI(web_ui()))); +} diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui.h b/chrome/browser/ui/webui/omnibox/omnibox_ui.h index d8a17ba..e52b59b 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui.h +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui.h @@ -6,15 +6,19 @@ #define CHROME_BROWSER_UI_WEBUI_OMNIBOX_OMNIBOX_UI_H_ #include "base/basictypes.h" -#include "content/public/browser/web_ui_controller.h" +#include "chrome/browser/ui/webui/mojo_web_ui_controller.h" // The UI for chrome://omnibox/ -class OmniboxUI : public content::WebUIController { +class OmniboxUI : public MojoWebUIController { public: explicit OmniboxUI(content::WebUI* contents); virtual ~OmniboxUI(); private: + // MojoWebUIController overrides: + virtual scoped_ptr<MojoWebUIHandler> CreateUIHandler( + mojo::ScopedMessagePipeHandle handle_to_page) OVERRIDE; + DISALLOW_COPY_AND_ASSIGN(OmniboxUI); }; diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc index b33115b..1c123b2 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc @@ -24,140 +24,120 @@ #include "chrome/browser/search/search.h" #include "chrome/browser/search_engines/template_url.h" #include "content/public/browser/web_ui.h" +#include "mojo/common/common_type_converters.h" +#include "mojo/public/cpp/bindings/allocation_scope.h" -OmniboxUIHandler::OmniboxUIHandler(Profile* profile): profile_(profile) { +namespace mojo { + +template <> +class TypeConverter<mojo::Array<AutocompleteAdditionalInfo>, + AutocompleteMatch::AdditionalInfo> { + public: + static mojo::Array<AutocompleteAdditionalInfo> ConvertFrom( + const AutocompleteMatch::AdditionalInfo& input, + Buffer* buf) { + mojo::Array<AutocompleteAdditionalInfo>::Builder array_builder( + input.size(), buf); + size_t index = 0; + for (AutocompleteMatch::AdditionalInfo::const_iterator i = input.begin(); + i != input.end(); ++i, index++) { + AutocompleteAdditionalInfo::Builder item_builder(buf); + item_builder.set_key(i->first); + item_builder.set_value(i->second); + array_builder[index] = item_builder.Finish(); + } + return array_builder.Finish(); + } +}; + +template <> +class TypeConverter<AutocompleteMatchMojo, AutocompleteMatch> { + public: + static AutocompleteMatchMojo ConvertFrom(const AutocompleteMatch& input, + Buffer* buf) { + AutocompleteMatchMojo::Builder builder(buf); + if (input.provider != NULL) { + builder.set_provider_name(input.provider->GetName()); + builder.set_provider_done(input.provider->done()); + } + builder.set_relevance(input.relevance); + builder.set_deletable(input.deletable); + builder.set_fill_into_edit(input.fill_into_edit); + builder.set_inline_autocompletion(input.inline_autocompletion); + builder.set_destination_url(input.destination_url.spec()); + builder.set_contents(input.contents); + // At this time, we're not bothering to send along the long vector that + // represent contents classification. i.e., for each character, what + // type of text it is. + builder.set_description(input.description); + // At this time, we're not bothering to send along the long vector that + // represents description classification. i.e., for each character, what + // type of text it is. + builder.set_transition(input.transition); + builder.set_is_history_what_you_typed_match( + input.is_history_what_you_typed_match); + builder.set_allowed_to_be_default_match(input.allowed_to_be_default_match); + builder.set_type(AutocompleteMatchType::ToString(input.type)); + if (input.associated_keyword.get() != NULL) + builder.set_associated_keyword(input.associated_keyword->keyword); + builder.set_keyword(input.keyword); + builder.set_starred(input.starred); + builder.set_duplicates(static_cast<int32>(input.duplicate_matches.size())); + builder.set_from_previous(input.from_previous); + + builder.set_additional_info(input.additional_info); + return builder.Finish(); + } +}; + +template <> +class TypeConverter<AutocompleteResultsForProviderMojo, AutocompleteProvider*> { + public: + static AutocompleteResultsForProviderMojo ConvertFrom( + const AutocompleteProvider* input, + Buffer* buf) { + AutocompleteResultsForProviderMojo::Builder builder(buf); + builder.set_provider_name(input->GetName()); + builder.set_results(input->matches()); + return builder.Finish(); + } +}; + +} // namespace mojo + +OmniboxUIHandler::OmniboxUIHandler(ScopedOmniboxPageHandle handle, + Profile* profile) + : page_(handle.Pass(), this), + profile_(profile) { ResetController(); } OmniboxUIHandler::~OmniboxUIHandler() {} -void OmniboxUIHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback("startOmniboxQuery", - base::Bind(&OmniboxUIHandler::StartOmniboxQuery, - base::Unretained(this))); -} - -// This function gets called when the AutocompleteController possibly -// has new results. We package those results in a DictionaryValue -// object result_to_output and call the javascript function -// handleNewAutocompleteResult. Here's an example populated -// result_to_output object: -// { -// 'done': false, -// 'time_since_omnibox_started_ms': 15, -// 'host': 'mai', -// 'is_typed_host': false, -// 'combined_results' : { -// 'num_items': 4, -// 'item_0': { -// 'destination_url': 'http://mail.google.com', -// 'provider_name': 'HistoryURL', -// 'relevance': 1410, -// ... -// } -// 'item_1: { -// ... -// } -// ... -// } -// 'results_by_provider': { -// 'HistoryURL' : { -// 'num_items': 3, -// ... -// } -// 'Search' : { -// 'num_items': 1, -// ... -// } -// ... -// } -// } -// For reference, the javascript code that unpacks this object and -// displays it is in chrome/browser/resources/omnibox.js void OmniboxUIHandler::OnResultChanged(bool default_match_changed) { - base::DictionaryValue result_to_output; - // Fill in general information. - result_to_output.SetBoolean("done", controller_->done()); - result_to_output.SetInteger("time_since_omnibox_started_ms", + mojo::AllocationScope scope; + OmniboxResultMojo::Builder builder; + builder.set_done(controller_->done()); + builder.set_time_since_omnibox_started_ms( (base::Time::Now() - time_omnibox_started_).InMilliseconds()); - const base::string16& host = controller_->input().text().substr( + const base::string16 host = controller_->input().text().substr( controller_->input().parts().host.begin, controller_->input().parts().host.len); - result_to_output.SetString("host", host); + builder.set_host(host); bool is_typed_host; - if (LookupIsTypedHost(host, &is_typed_host)) { - // If we successfully looked up whether the host part of the omnibox - // input (this interprets the input as a host plus optional path) as - // a typed host, then record this information in the output. - result_to_output.SetBoolean("is_typed_host", is_typed_host); - } - // Fill in the merged/combined results the controller has provided. - AddResultToDictionary("combined_results", controller_->result().begin(), - controller_->result().end(), &result_to_output); - // Fill results from each individual provider as well. - for (ACProviders::const_iterator it(controller_->providers()->begin()); - it != controller_->providers()->end(); ++it) { - AddResultToDictionary( - std::string("results_by_provider.") + (*it)->GetName(), - (*it)->matches().begin(), (*it)->matches().end(), &result_to_output); - } - // Add done; send the results. - web_ui()->CallJavascriptFunction("omniboxDebug.handleNewAutocompleteResult", - result_to_output); -} + if (!LookupIsTypedHost(host, &is_typed_host)) + is_typed_host = false; + builder.set_is_typed_host(is_typed_host); -// For details on the format of the DictionaryValue that this function -// populates, see the comments by OnResultChanged(). -void OmniboxUIHandler::AddResultToDictionary(const std::string& prefix, - ACMatches::const_iterator it, - ACMatches::const_iterator end, - base::DictionaryValue* output) { - int i = 0; - for (; it != end; ++it, ++i) { - std::string item_prefix(prefix + base::StringPrintf(".item_%d", i)); - if (it->provider != NULL) { - output->SetString(item_prefix + ".provider_name", - it->provider->GetName()); - output->SetBoolean(item_prefix + ".provider_done", it->provider->done()); - } - output->SetInteger(item_prefix + ".relevance", it->relevance); - output->SetBoolean(item_prefix + ".deletable", it->deletable); - output->SetString(item_prefix + ".fill_into_edit", it->fill_into_edit); - output->SetString(item_prefix + ".inline_autocompletion", - it->inline_autocompletion); - output->SetString(item_prefix + ".destination_url", - it->destination_url.spec()); - output->SetString(item_prefix + ".contents", it->contents); - // At this time, we're not bothering to send along the long vector that - // represent contents classification. i.e., for each character, what - // type of text it is. - output->SetString(item_prefix + ".description", it->description); - // At this time, we're not bothering to send along the long vector that - // represents description classification. i.e., for each character, what - // type of text it is. - output->SetInteger(item_prefix + ".transition", it->transition); - output->SetBoolean(item_prefix + ".is_history_what_you_typed_match", - it->is_history_what_you_typed_match); - output->SetBoolean(item_prefix + ".allowed_to_be_default_match", - it->allowed_to_be_default_match); - output->SetString(item_prefix + ".type", - AutocompleteMatchType::ToString(it->type)); - if (it->associated_keyword.get() != NULL) { - output->SetString(item_prefix + ".associated_keyword", - it->associated_keyword->keyword); - } - output->SetString(item_prefix + ".keyword", it->keyword); - output->SetBoolean(item_prefix + ".starred", it->starred); - output->SetInteger(item_prefix + ".duplicates", - static_cast<int>(it->duplicate_matches.size())); - output->SetBoolean(item_prefix + ".from_previous", it->from_previous); - for (AutocompleteMatch::AdditionalInfo::const_iterator j = - it->additional_info.begin(); j != it->additional_info.end(); ++j) { - output->SetString(item_prefix + ".additional_info." + j->first, - j->second); - } + { + // Copy to an ACMatches to make conversion easier. Since this isn't + // performance critical we don't worry about the cost here. + ACMatches matches(controller_->result().begin(), + controller_->result().end()); + builder.set_combined_results(matches); } - output->SetInteger(prefix + ".num_items", i); + builder.set_results_by_provider(*controller_->providers()); + page_->HandleNewAutocompleteResult(builder.Finish()); } bool OmniboxUIHandler::LookupIsTypedHost(const base::string16& host, @@ -174,23 +154,11 @@ bool OmniboxUIHandler::LookupIsTypedHost(const base::string16& host, return true; } -void OmniboxUIHandler::StartOmniboxQuery(const base::ListValue* input) { - DCHECK_EQ(5u, input->GetSize()); - base::string16 input_string; - bool return_val = input->GetString(0, &input_string); - DCHECK(return_val); - int cursor_position; - return_val = input->GetInteger(1, &cursor_position); - DCHECK(return_val); - bool prevent_inline_autocomplete; - return_val = input->GetBoolean(2, &prevent_inline_autocomplete); - DCHECK(return_val); - bool prefer_keyword; - return_val = input->GetBoolean(3, &prefer_keyword); - DCHECK(return_val); - int current_page_classification; - return_val = input->GetInteger(4, ¤t_page_classification); - DCHECK(return_val); +void OmniboxUIHandler::StartOmniboxQuery(const mojo::String& input_string, + int32_t cursor_position, + bool prevent_inline_autocomplete, + bool prefer_keyword, + int32_t page_classification) { // Reset the controller. If we don't do this, then the // AutocompleteController might inappropriately set its |minimal_changes| // variable (or something else) and some providers will short-circuit @@ -204,7 +172,7 @@ void OmniboxUIHandler::StartOmniboxQuery(const base::ListValue* input) { base::string16(), // user's desired tld (top-level domain) GURL(), static_cast<AutocompleteInput::PageClassification>( - current_page_classification), + page_classification), prevent_inline_autocomplete, prefer_keyword, true, // allow exact keyword matches diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h index ff03065..e4a45e1 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h @@ -11,62 +11,35 @@ #include "base/time/time.h" #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" #include "chrome/browser/autocomplete/autocomplete_match.h" -#include "content/public/browser/web_ui_message_handler.h" +#include "chrome/browser/ui/webui/mojo_web_ui_handler.h" +#include "chrome/browser/ui/webui/omnibox/omnibox.mojom.h" +#include "mojo/public/cpp/bindings/remote_ptr.h" class AutocompleteController; class Profile; -namespace base { -class ListValue; -} - -// UI Handler for chrome://omnibox/ -// It listens for calls from javascript to StartOmniboxQuery() and -// passes those calls to its private AutocompleteController. It also -// listens for updates from the AutocompleteController to OnResultChanged() -// and passes those results on calling back into the Javascript to -// update the page. +// Implementation of OmniboxUIHandlerMojo. StartOmniboxQuery() calls to a +// private AutocompleteController. It also listens for updates from the +// AutocompleteController to OnResultChanged() and passes those results to +// the OmniboxPage. class OmniboxUIHandler : public AutocompleteControllerDelegate, - public content::WebUIMessageHandler { + public OmniboxUIHandlerMojo, + public MojoWebUIHandler { public: - explicit OmniboxUIHandler(Profile* profile); + OmniboxUIHandler(ScopedOmniboxPageHandle handle, Profile* profile); virtual ~OmniboxUIHandler(); - // AutocompleteControllerDelegate implementation. - // Gets called when the result set of the AutocompleteController changes. - // We transform the AutocompleteResult into a Javascript object and - // call the Javascript function gotNewAutocompleteResult with it. - // |default_match_changed| is given to us by the AutocompleteController - // but we don't need it. It's ignored. + // AutocompleteControllerDelegate overrides: virtual void OnResultChanged(bool default_match_changed) OVERRIDE; - protected: - // WebUIMessageHandler implementation. - // Register our handler to get callbacks from javascript for - // startOmniboxQuery(). - virtual void RegisterMessages() OVERRIDE; + // OmniboxUIHandlerMojo overrides: + virtual void StartOmniboxQuery(const mojo::String& input_string, + int32_t cursor_position, + bool prevent_inline_autocomplete, + bool prefer_keyword, + int32_t page_classification) OVERRIDE; private: - // Gets called from the javascript when a user enters text into the - // chrome://omnibox/ text box and clicks submit or hits enter. - // |input| is expected to be a four-element list: - // - first element: input string. - // - second element: the cursor position. - // - third element: boolean indicating whether we should set - // prevent_inline_autocomplete or not. - // - fourth element: boolean indicating whether we should set prefer_keyword - // - fifth element: current page classification value (enum - // PageClassification from omnibox_event.proto) - void StartOmniboxQuery(const base::ListValue* input); - - // Helper function for OnResultChanged(). - // Takes an iterator over AutocompleteMatches and packages them into - // the DictionaryValue output, all stored under the given prefix. - void AddResultToDictionary(const std::string& prefix, - ACMatches::const_iterator result_it, - ACMatches::const_iterator end, - base::DictionaryValue* output); - // Looks up whether the hostname is a typed host (i.e., has received // typed visits). Return true if the lookup succeeded; if so, the // value of |is_typed_host| is set appropriately. @@ -76,6 +49,8 @@ class OmniboxUIHandler : public AutocompleteControllerDelegate, // next query. void ResetController(); + mojo::RemotePtr<OmniboxPage> page_; + // The omnibox AutocompleteController that collects/sorts/dup- // eliminates the results as they come in. scoped_ptr<AutocompleteController> controller_; |