diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 04:11:48 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-01 04:11:48 +0000 |
commit | 447a7e9d1e4a1fcf34c669fd724e5bb1858fd11f (patch) | |
tree | 8f02ed12fe2e9eead4b376da7e2a30427a06726e | |
parent | 6f6e42e0e2faa6d455d87e2e122c2adbadbc2cef (diff) | |
download | chromium_src-447a7e9d1e4a1fcf34c669fd724e5bb1858fd11f.zip chromium_src-447a7e9d1e4a1fcf34c669fd724e5bb1858fd11f.tar.gz chromium_src-447a7e9d1e4a1fcf34c669fd724e5bb1858fd11f.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
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=262176
Review URL: https://codereview.chromium.org/222543004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267414 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/DEPS | 2 | ||||
-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 | 256 | ||||
-rw-r--r-- | chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h | 63 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 4 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 8 | ||||
-rw-r--r-- | chrome/chrome_resources.gyp | 3 | ||||
-rw-r--r-- | chrome/chrome_web_ui_mojo_bindings.gyp | 21 |
15 files changed, 404 insertions, 271 deletions
diff --git a/chrome/DEPS b/chrome/DEPS index 9e8cd4d..69f7d97 100644 --- a/chrome/DEPS +++ b/chrome/DEPS @@ -21,6 +21,8 @@ include_rules = [ "+components/variations", "+content/public/common", "+content/public/test", + "+mojo/common", + "+mojo/public", # Don't allow inclusion of these other libs we shouldn't be calling directly. "-webkit", diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 0a2e6d7..4a8b005 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -203,6 +203,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 0382b20..14b0de7 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.cc @@ -23,140 +23,130 @@ #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(); + } + + MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); +}; + +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(); + } + + MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); +}; + +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( + mojo::Array<AutocompleteMatchMojo>::From(input->matches())); + return builder.Finish(); + } + + MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION(); +}; + +} // 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 = input_.text().substr( + const base::string16 host = input_.text().substr( input_.parts().host.begin, 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( + mojo::Array<AutocompleteMatchMojo>::From(matches)); } - output->SetInteger(prefix + ".num_items", i); + builder.set_results_by_provider( + mojo::Array<AutocompleteResultsForProviderMojo>::From( + *controller_->providers())); + page_->HandleNewAutocompleteResult(builder.Finish()); } bool OmniboxUIHandler::LookupIsTypedHost(const base::string16& host, @@ -173,23 +163,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 @@ -203,7 +181,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 de477f1..9538110 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h +++ b/chrome/browser/ui/webui/omnibox/omnibox_ui_handler.h @@ -12,62 +12,35 @@ #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" #include "chrome/browser/autocomplete/autocomplete_input.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. @@ -77,6 +50,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_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 851ab1aa..7b9d6d7 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2582,6 +2582,10 @@ '../components/components.gyp:web_modal', '../media/cast/cast.gyp:cast_transport', '../media/media.gyp:media', + '../mojo/mojo.gyp:mojo_cpp_bindings', + '../mojo/mojo.gyp:mojo_environment_chromium', + '../mojo/mojo.gyp:mojo_js_bindings', + '../mojo/mojo.gyp:mojo_system_impl', '../net/net.gyp:net_with_v8', # TODO(tonyg): Remove this dependency (crbug.com/280157). '../testing/perf/perf_test.gyp:*', diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index ca7c696..4008b56 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -25,10 +25,10 @@ 'chrome_resources.gyp:theme_resources', 'common', 'common_net', + 'feedback_proto', 'in_memory_url_index_cache_proto', 'safe_browsing_proto', 'safe_browsing_report_proto', - 'feedback_proto', '../components/components.gyp:auto_login_parser', '../components/components.gyp:dom_distiller_core', '../components/components.gyp:dom_distiller_webui', @@ -2180,6 +2180,9 @@ 'browser/ui/webui/memory_internals/memory_internals_ui.h', 'browser/ui/webui/metrics_handler.cc', 'browser/ui/webui/metrics_handler.h', + 'browser/ui/webui/mojo_web_ui_controller.cc', + 'browser/ui/webui/mojo_web_ui_controller.h', + 'browser/ui/webui/mojo_web_ui_handler.h', 'browser/ui/webui/nacl_ui.cc', 'browser/ui/webui/nacl_ui.h', 'browser/ui/webui/net_export_ui.cc', @@ -2438,15 +2441,18 @@ 'browser/ui/zoom/zoom_controller.cc', 'browser/ui/zoom/zoom_controller.h', 'browser/ui/zoom/zoom_observer.h', + '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.cc', ], 'conditions': [ ['OS != "ios"', { 'dependencies': [ 'browser_extensions', 'browser/performance_monitor/performance_monitor.gyp:performance_monitor', + 'chrome_web_ui_mojo_bindings.gyp:web_ui_mojo_bindings', 'common/extensions/api/api.gyp:chrome_api', 'debugger', 'installer_util', + '../mojo/mojo.gyp:mojo_common_lib', '../third_party/re2/re2.gyp:re2', '../components/components.gyp:autofill_content_risk_proto', '../device/bluetooth/bluetooth.gyp:device_bluetooth', diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp index a299f1e..ea06883 100644 --- a/chrome/chrome_resources.gyp +++ b/chrome/chrome_resources.gyp @@ -6,6 +6,7 @@ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome', 'about_credits_file': '<(SHARED_INTERMEDIATE_DIR)/about_credits.html', 'additional_modules_list_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/internal/additional_modules_list.txt', + 'omnibox_mojom_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.js', }, 'targets': [ { @@ -162,6 +163,7 @@ 'dependencies': [ 'about_credits', 'chrome_internal_resources_gen', + 'chrome_web_ui_mojo_bindings.gyp:web_ui_mojo_bindings', ], 'actions': [ # Data resources. @@ -172,6 +174,7 @@ 'grit_additional_defines': [ '-E', 'about_credits_file=<(about_credits_file)', '-E', 'additional_modules_list_file=<(additional_modules_list_file)', + '-E', 'omnibox_mojom_file=<(omnibox_mojom_file)', ], }, 'includes': [ '../build/grit_action.gypi' ], diff --git a/chrome/chrome_web_ui_mojo_bindings.gyp b/chrome/chrome_web_ui_mojo_bindings.gyp new file mode 100644 index 0000000..0dca218 --- /dev/null +++ b/chrome/chrome_web_ui_mojo_bindings.gyp @@ -0,0 +1,21 @@ +# 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. +{ + 'targets': [ + { + 'target_name': 'web_ui_mojo_bindings', + # The type of this target must be none. This is so that resources can + # depend upon this target for generating the js bindings files. Any + # generated cpp files be listed explicitly in browser_ui. + 'type': 'none', + 'sources': [ + 'browser/ui/webui/omnibox/omnibox.mojom', + ], + 'includes': [ '../mojo/public/tools/bindings/mojom_bindings_generator.gypi' ], + 'variables': { + 'mojom_base_output_dir': 'chrome', + }, + }, + ], +} |