diff options
author | shaktisahu <shaktisahu@chromium.org> | 2016-03-24 21:36:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-25 04:37:59 +0000 |
commit | ded7b6ba488f2163e9588573cbb5e705222b9205 (patch) | |
tree | e30331a907a2baa1668d85f4408b04ff97f27ec5 /blimp | |
parent | 5bcc36b7bd9db878bb6d98aadf15a3a6c931df54 (diff) | |
download | chromium_src-ded7b6ba488f2163e9588573cbb5e705222b9205.zip chromium_src-ded7b6ba488f2163e9588573cbb5e705222b9205.tar.gz chromium_src-ded7b6ba488f2163e9588573cbb5e705222b9205.tar.bz2 |
Added network components for blimp text input feature
This is the third CL for enabling text input. Created protobuf ImeMessage containing text and IME related information to be sent over network. Added WebInputFeature and WebInputFeatureDelegate to handle these messages.
BUG=585646
Review URL: https://codereview.chromium.org/1779673003
Cr-Commit-Position: refs/heads/master@{#383242}
Diffstat (limited to 'blimp')
25 files changed, 722 insertions, 30 deletions
diff --git a/blimp/client/BUILD.gn b/blimp/client/BUILD.gn index 55a3285..0aa9255 100644 --- a/blimp/client/BUILD.gn +++ b/blimp/client/BUILD.gn @@ -110,6 +110,8 @@ source_set("feature") { "feature/compositor/blimp_output_surface.h", "feature/compositor/decoding_image_generator.cc", "feature/compositor/decoding_image_generator.h", + "feature/ime_feature.cc", + "feature/ime_feature.h", "feature/navigation_feature.cc", "feature/navigation_feature.h", "feature/render_widget_feature.cc", @@ -120,6 +122,7 @@ source_set("feature") { deps = [ "//blimp/common:blimp_common", + "//blimp/net:blimp_net", "//cc", "//cc/proto", "//gpu/command_buffer/client", @@ -127,6 +130,7 @@ source_set("feature") { "//gpu/command_buffer/common:gles2_utils", "//gpu/skia_bindings", "//skia", + "//ui/base/ime:text_input_types", "//ui/events/blink", "//ui/events/gestures/blink", "//ui/gl", @@ -353,6 +357,7 @@ if (is_android) { "//blimp/net:blimp_net", "//components/safe_json/android:safe_json_jni_headers", "//skia", + "//ui/base/ime:text_input_types", "//ui/gfx/geometry", "//ui/gl", "//url:url", diff --git a/blimp/client/DEPS b/blimp/client/DEPS index e1fa29a..dfa2aa1 100644 --- a/blimp/client/DEPS +++ b/blimp/client/DEPS @@ -12,6 +12,7 @@ include_rules = [ "+third_party/libwebp", "+third_party/skia", "+third_party/WebKit/public/web/WebInputEvent.h", + "+ui/base/ime/text_input_type.h", "+ui/events", "+ui/events/android", "+ui/events/blink", diff --git a/blimp/client/app/android/java/src/org/chromium/blimp/input/WebInputBox.java b/blimp/client/app/android/java/src/org/chromium/blimp/input/WebInputBox.java index 6cdc25f..84aff14 100644 --- a/blimp/client/app/android/java/src/org/chromium/blimp/input/WebInputBox.java +++ b/blimp/client/app/android/java/src/org/chromium/blimp/input/WebInputBox.java @@ -6,6 +6,7 @@ package org.chromium.blimp.input; import android.app.Activity; import android.content.Context; +import android.text.InputType; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; @@ -18,6 +19,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.blimp.session.BlimpClientSession; import org.chromium.ui.UiUtils; +import org.chromium.ui.base.ime.TextInputType; /** * A {@link View} that allows users to enter text into a web page. @@ -34,13 +36,17 @@ public class WebInputBox extends EditText { mContext = context; setOnEditorActionListener(new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_NEXT - || actionId == EditorInfo.IME_ACTION_DONE) { - onImeTextEntered(v.getText().toString()); - hideIme(); - return true; + switch (actionId) { + case EditorInfo.IME_ACTION_NEXT: + case EditorInfo.IME_ACTION_DONE: + case EditorInfo.IME_ACTION_SEARCH: + case EditorInfo.IME_ACTION_GO: + onImeTextEntered(v.getText().toString()); + hideIme(); + return true; + default: + return false; } - return false; } }); } @@ -82,7 +88,7 @@ public class WebInputBox extends EditText { /** * Brings up the IME along with the edit text above it. */ - public void showIme() { + private void showIme() { // TODO(shaktisahu): Find a better way to prevent resize (crbug/596653). ((Activity) mContext) .getWindow() @@ -115,11 +121,62 @@ public class WebInputBox extends EditText { } @CalledByNative - private void onImeRequested(boolean show) { - if (show) { - showIme(); - } else { - hideIme(); + private void onShowImeRequested(int inputType, String text) { + setEditorOptions(inputType); + setText(text); + // Set the cursor at the end. + setSelection(getText().length()); + showIme(); + } + + @CalledByNative + private void onHideImeRequested() { + hideIme(); + } + + /** + * Set the IME options and input type based on the input type received from engine. + * @param inputType text input type. + */ + private void setEditorOptions(int inputType) { + setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + switch (inputType) { + case TextInputType.TEXT: + setInputType(InputType.TYPE_CLASS_TEXT); + setImeOptions(EditorInfo.IME_ACTION_GO); + break; + case TextInputType.PASSWORD: + setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + setImeOptions(EditorInfo.IME_ACTION_GO); + break; + case TextInputType.SEARCH: + setImeOptions(EditorInfo.IME_ACTION_SEARCH); + break; + case TextInputType.EMAIL: + setInputType( + InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + setImeOptions(EditorInfo.IME_ACTION_GO); + break; + case TextInputType.NUMBER: + setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL + | InputType.TYPE_NUMBER_FLAG_DECIMAL); + setImeOptions(EditorInfo.IME_ACTION_NEXT); + break; + case TextInputType.TELEPHONE: + setInputType(InputType.TYPE_CLASS_PHONE); + setImeOptions(EditorInfo.IME_ACTION_NEXT); + break; + case TextInputType.URL: + setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); + setImeOptions(EditorInfo.IME_ACTION_GO); + break; + case TextInputType.TEXT_AREA: + case TextInputType.CONTENT_EDITABLE: + setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); + setImeOptions(EditorInfo.IME_ACTION_NONE); + break; + default: + setInputType(InputType.TYPE_CLASS_TEXT); } } diff --git a/blimp/client/app/android/web_input_box.cc b/blimp/client/app/android/web_input_box.cc index ffdf9cd..c20841c 100644 --- a/blimp/client/app/android/web_input_box.cc +++ b/blimp/client/app/android/web_input_box.cc @@ -5,7 +5,9 @@ #include "base/android/jni_string.h" #include "blimp/client/app/android/blimp_client_session_android.h" #include "blimp/client/app/android/web_input_box.h" +#include "blimp/client/feature/ime_feature.h" #include "jni/WebInputBox_jni.h" +#include "ui/base/ime/text_input_type.h" namespace blimp { namespace client { @@ -13,7 +15,11 @@ namespace client { static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& jobj, const JavaParamRef<jobject>& blimp_client_session) { - return reinterpret_cast<intptr_t>(new WebInputBox(env, jobj)); + BlimpClientSession* client_session = + BlimpClientSessionAndroid::FromJavaObject(env, + blimp_client_session.obj()); + return reinterpret_cast<intptr_t>( + new WebInputBox(env, jobj, client_session->GetImeFeature())); } // static @@ -22,25 +28,40 @@ bool WebInputBox::RegisterJni(JNIEnv* env) { } WebInputBox::WebInputBox(JNIEnv* env, - const base::android::JavaParamRef<jobject>& jobj) { + const base::android::JavaParamRef<jobject>& jobj, + ImeFeature* ime_feature) { java_obj_.Reset(env, jobj); + ime_feature_ = ime_feature; + ime_feature_->set_delegate(this); } -WebInputBox::~WebInputBox() {} +WebInputBox::~WebInputBox() { + ime_feature_->set_delegate(nullptr); +} void WebInputBox::Destroy(JNIEnv* env, const JavaParamRef<jobject>& jobj) { delete this; } -void WebInputBox::OnImeRequested(bool show) { +void WebInputBox::OnShowImeRequested(ui::TextInputType input_type, + const std::string& text) { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK_NE(ui::TEXT_INPUT_TYPE_NONE, input_type); + Java_WebInputBox_onShowImeRequested( + env, java_obj_.obj(), input_type, + base::android::ConvertUTF8ToJavaString(env, text).obj()); +} + +void WebInputBox::OnHideImeRequested() { JNIEnv* env = base::android::AttachCurrentThread(); - Java_WebInputBox_onImeRequested(env, java_obj_.obj(), show); + Java_WebInputBox_onHideImeRequested(env, java_obj_.obj()); } void WebInputBox::OnImeTextEntered(JNIEnv* env, const JavaParamRef<jobject>& jobj, const JavaParamRef<jstring>& text) { - // TODO(shaktisahu): Send text to browser. + std::string textInput = base::android::ConvertJavaStringToUTF8(env, text); + ime_feature_->OnImeTextEntered(textInput); } } // namespace client diff --git a/blimp/client/app/android/web_input_box.h b/blimp/client/app/android/web_input_box.h index 4166b1a..0756fdd 100644 --- a/blimp/client/app/android/web_input_box.h +++ b/blimp/client/app/android/web_input_box.h @@ -9,19 +9,28 @@ #include "base/android/jni_android.h" #include "base/macros.h" +#include "blimp/client/feature/ime_feature.h" +#include "ui/base/ime/text_input_type.h" namespace blimp { namespace client { // The native component of org.chromium.blimp.input.WebInputBox. -class WebInputBox { +class WebInputBox : public ImeFeature::Delegate { public: static bool RegisterJni(JNIEnv* env); - WebInputBox(JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj); + // |ime_feature| is expected to outlive the WebInputBox. + WebInputBox(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jobj, + ImeFeature* ime_feature); - // Brings up or hides the IME for user to enter text. - void OnImeRequested(bool show); + // Brings up IME for user to enter text. + void OnShowImeRequested(ui::TextInputType input_type, + const std::string& text) override; + + // Hides IME. + void OnHideImeRequested() override; // Methods called from Java via JNI. void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj); @@ -37,6 +46,10 @@ class WebInputBox { // Reference to the Java object which owns this class. base::android::ScopedJavaGlobalRef<jobject> java_obj_; + // A bridge to the network layer which does the work of (de)serializing the + // outgoing and incoming BlimpMessage::IME messages from the engine. + ImeFeature* ime_feature_; + DISALLOW_COPY_AND_ASSIGN(WebInputBox); }; diff --git a/blimp/client/feature/ime_feature.cc b/blimp/client/feature/ime_feature.cc new file mode 100644 index 0000000..2e69507 --- /dev/null +++ b/blimp/client/feature/ime_feature.cc @@ -0,0 +1,76 @@ +// Copyright 2016 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 <blimp/client/feature/ime_feature.h> +#include <string> + +#include "blimp/common/create_blimp_message.h" +#include "blimp/common/proto/blimp_message.pb.h" +#include "blimp/net/input_message_converter.h" +#include "net/base/net_errors.h" + +namespace blimp { +namespace client { + +ImeFeature::ImeFeature() {} + +ImeFeature::~ImeFeature() {} + +void ImeFeature::OnImeTextEntered(const std::string& text) { + DCHECK_LE(0, tab_id_); + DCHECK_LT(0, render_widget_id_); + + ImeMessage* ime_message; + scoped_ptr<BlimpMessage> blimp_message = + CreateBlimpMessage(&ime_message, tab_id_); + ime_message->set_render_widget_id(render_widget_id_); + ime_message->set_type(ImeMessage::SET_TEXT); + ime_message->set_ime_text(text); + + outgoing_message_processor_->ProcessMessage(std::move(blimp_message), + net::CompletionCallback()); +} + +void ImeFeature::ProcessMessage(scoped_ptr<BlimpMessage> message, + const net::CompletionCallback& callback) { + DCHECK(!callback.is_null()); + DCHECK_EQ(BlimpMessage::IME, message->type()); + + DCHECK(delegate_); + + const ImeMessage& ime_message = message->ime(); + + switch (ime_message.type()) { + case ImeMessage::SHOW_IME: + if (!message->has_target_tab_id() || message->target_tab_id() < 0 || + ime_message.render_widget_id() <= 0) { + callback.Run(net::ERR_INVALID_ARGUMENT); + return; + } + + tab_id_ = message->target_tab_id(); + render_widget_id_ = ime_message.render_widget_id(); + + delegate_->OnShowImeRequested( + InputMessageConverter::TextInputTypeFromProto( + ime_message.text_input_type()), + ime_message.ime_text()); + break; + case ImeMessage::HIDE_IME: + tab_id_ = -1; + render_widget_id_ = 0; + delegate_->OnHideImeRequested(); + break; + case ImeMessage::SET_TEXT: + case ImeMessage::UNKNOWN: + NOTREACHED(); + callback.Run(net::ERR_UNEXPECTED); + return; + } + + callback.Run(net::OK); +} + +} // namespace client +} // namespace blimp diff --git a/blimp/client/feature/ime_feature.h b/blimp/client/feature/ime_feature.h new file mode 100644 index 0000000..4db2cde --- /dev/null +++ b/blimp/client/feature/ime_feature.h @@ -0,0 +1,85 @@ +// Copyright 2016 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 BLIMP_CLIENT_FEATURE_IME_FEATURE_H_ +#define BLIMP_CLIENT_FEATURE_IME_FEATURE_H_ + +#include <map> +#include <string> + +#include "base/macros.h" +#include "blimp/client/blimp_client_export.h" +#include "blimp/net/blimp_message_processor.h" +#include "ui/base/ime/text_input_type.h" + +namespace blimp { +namespace client { + +// Handles all incoming and outgoing protobuf messages for text input of type +// BlimpMessage::IME for blimp client. +// Upon receiving a text input request from the engine, the ImeFeature caches +// the |tab_id_| and |render_widget_id_| for the request and +// delegates the request to the Delegate which then opens up the IME. +// After user is done typing, the text is passed back to ImeFeature, which then +// sends the text to the engine over network along with the same |tab_id_| and +// |render_widget_id_|. +// Any time user taps on an input text, ImeMessage::SHOW_IME message will be +// sent to client. Similarly, any time the text input is out of focus (e.g. if +// user navigates away from the currently page or the page loads for the first +// time), ImeMessage::HIDE_IME will be sent. + +class BLIMP_CLIENT_EXPORT ImeFeature : public BlimpMessageProcessor { + public: + // A delegate to be notified of text input requests. + class Delegate { + public: + virtual void OnShowImeRequested(ui::TextInputType input_type, + const std::string& text) = 0; + virtual void OnHideImeRequested() = 0; + }; + + ImeFeature(); + ~ImeFeature() override; + + // Set the BlimpMessageProcessor that will be used to send BlimpMessage::IME + // messages to the engine. + void set_outgoing_message_processor( + scoped_ptr<BlimpMessageProcessor> processor) { + outgoing_message_processor_ = std::move(processor); + } + + // Sets a Delegate to be notified of all text input messages. + // Passing a null |delegate| causes IME messages to be ignored. + void set_delegate(Delegate* delegate) { delegate_ = delegate; } + + // Sends text from IME to the blimp engine. + void OnImeTextEntered(const std::string& text); + + private: + // BlimpMessageProcessor implementation. + void ProcessMessage(scoped_ptr<BlimpMessage> message, + const net::CompletionCallback& callback) override; + + // Delegate for processing the text input related messages. |delegate_| must + // remain valid until the last message has been passed to ImeFeature. + Delegate* delegate_ = nullptr; + + // Tab id and render widget id for the input field for which user input is + // being requested. + // The values are cached from the ImeMessage::SHOW_IME message and sent back + // to engine in the subsequent ImeMessage::SET_TEXT message. + // The cached values are cleared on receiving ImeMessage::HIDE_IME request. + int tab_id_ = -1; + int render_widget_id_ = 0; + + // Used to send BlimpMessage::IME messages to the engine. + scoped_ptr<BlimpMessageProcessor> outgoing_message_processor_; + + DISALLOW_COPY_AND_ASSIGN(ImeFeature); +}; + +} // namespace client +} // namespace blimp + +#endif // BLIMP_CLIENT_FEATURE_IME_FEATURE_H_ diff --git a/blimp/client/session/blimp_client_session.cc b/blimp/client/session/blimp_client_session.cc index 226b625..615b3ef 100644 --- a/blimp/client/session/blimp_client_session.cc +++ b/blimp/client/session/blimp_client_session.cc @@ -12,6 +12,7 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h" #include "blimp/client/app/blimp_client_switches.h" +#include "blimp/client/feature/ime_feature.h" #include "blimp/client/feature/navigation_feature.h" #include "blimp/client/feature/render_widget_feature.h" #include "blimp/client/feature/tab_control_feature.h" @@ -149,6 +150,7 @@ BlimpClientSession::BlimpClientSession() : io_thread_("BlimpIOThread"), tab_control_feature_(new TabControlFeature), navigation_feature_(new NavigationFeature), + ime_feature_(new ImeFeature), render_widget_feature_(new RenderWidgetFeature), weak_factory_(this) { net_components_.reset(new ClientNetworkComponents( @@ -222,6 +224,10 @@ void BlimpClientSession::RegisterFeatures() { // outgoing BlimpMessageProcessor in the RenderWidgetFeature. thread_pipe_manager_->RegisterFeature(BlimpMessage::RENDER_WIDGET, render_widget_feature_.get()); + + ime_feature_->set_outgoing_message_processor( + thread_pipe_manager_->RegisterFeature(BlimpMessage::IME, + ime_feature_.get())); } void BlimpClientSession::OnConnected() {} @@ -236,6 +242,10 @@ NavigationFeature* BlimpClientSession::GetNavigationFeature() const { return navigation_feature_.get(); } +ImeFeature* BlimpClientSession::GetImeFeature() const { + return ime_feature_.get(); +} + RenderWidgetFeature* BlimpClientSession::GetRenderWidgetFeature() const { return render_widget_feature_.get(); } diff --git a/blimp/client/session/blimp_client_session.h b/blimp/client/session/blimp_client_session.h index d7ffa56..cea7062 100644 --- a/blimp/client/session/blimp_client_session.h +++ b/blimp/client/session/blimp_client_session.h @@ -32,6 +32,7 @@ namespace client { class ClientNetworkComponents; class NavigationFeature; +class ImeFeature; class RenderWidgetFeature; class TabControlFeature; @@ -65,6 +66,7 @@ class BLIMP_CLIENT_EXPORT BlimpClientSession : public NetworkEventObserver { TabControlFeature* GetTabControlFeature() const; NavigationFeature* GetNavigationFeature() const; + ImeFeature* GetImeFeature() const; RenderWidgetFeature* GetRenderWidgetFeature() const; // The AssignmentCallback for when an assignment is ready. This will trigger @@ -89,6 +91,7 @@ class BLIMP_CLIENT_EXPORT BlimpClientSession : public NetworkEventObserver { base::Thread io_thread_; scoped_ptr<TabControlFeature> tab_control_feature_; scoped_ptr<NavigationFeature> navigation_feature_; + scoped_ptr<ImeFeature> ime_feature_; scoped_ptr<RenderWidgetFeature> render_widget_feature_; // The AssignmentSource is used when the user of BlimpClientSession calls diff --git a/blimp/common/DEPS b/blimp/common/DEPS index 4c21ff3..321ac45 100644 --- a/blimp/common/DEPS +++ b/blimp/common/DEPS @@ -5,6 +5,7 @@ include_rules = [ "-content", "+third_party/libwebp", "+third_party/skia", + "+ui/base/ime/text_input_type.h", "+ui/gfx", "+ui/gl", ] diff --git a/blimp/common/create_blimp_message.cc b/blimp/common/create_blimp_message.cc index 09e6dea..ddb28dc 100644 --- a/blimp/common/create_blimp_message.cc +++ b/blimp/common/create_blimp_message.cc @@ -53,6 +53,16 @@ scoped_ptr<BlimpMessage> CreateBlimpMessage( return output; } +scoped_ptr<BlimpMessage> CreateBlimpMessage(ImeMessage** ime_message, + int target_tab_id) { + DCHECK(ime_message); + scoped_ptr<BlimpMessage> output(new BlimpMessage); + output->set_type(BlimpMessage::IME); + output->set_target_tab_id(target_tab_id); + *ime_message = output->mutable_ime(); + return output; +} + scoped_ptr<BlimpMessage> CreateBlimpMessage( RenderWidgetMessage** render_widget_message, int target_tab_id) { diff --git a/blimp/common/create_blimp_message.h b/blimp/common/create_blimp_message.h index 8a403d4..e328666 100644 --- a/blimp/common/create_blimp_message.h +++ b/blimp/common/create_blimp_message.h @@ -16,12 +16,13 @@ namespace blimp { class BlimpMessage; class CompositorMessage; -class TabControlMessage; +class ImeMessage; class InputMessage; class NavigationMessage; class RenderWidgetMessage; class SizeMessage; class StartConnectionMessage; +class TabControlMessage; // Suite of helper methods to simplify the repetitive task of creating // new BlimpMessages, initializing them, and extracting type-specific @@ -50,6 +51,10 @@ BLIMP_COMMON_EXPORT scoped_ptr<BlimpMessage> CreateBlimpMessage( int target_tab_id); BLIMP_COMMON_EXPORT scoped_ptr<BlimpMessage> CreateBlimpMessage( + ImeMessage** ime_message, + int target_tab_id); + +BLIMP_COMMON_EXPORT scoped_ptr<BlimpMessage> CreateBlimpMessage( RenderWidgetMessage** render_widget_message, int target_tab_id); diff --git a/blimp/common/proto/BUILD.gn b/blimp/common/proto/BUILD.gn index d14960a..3359066 100644 --- a/blimp/common/proto/BUILD.gn +++ b/blimp/common/proto/BUILD.gn @@ -27,6 +27,7 @@ proto_library("proto_internal") { sources = [ "blimp_message.proto", "compositor.proto", + "ime.proto", "input.proto", "navigation.proto", "protocol_control.proto", diff --git a/blimp/common/proto/blimp_message.proto b/blimp/common/proto/blimp_message.proto index db73e03..4618a4f 100644 --- a/blimp/common/proto/blimp_message.proto +++ b/blimp/common/proto/blimp_message.proto @@ -24,6 +24,7 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; import "compositor.proto"; +import "ime.proto"; import "input.proto"; import "navigation.proto"; import "render_widget.proto"; @@ -41,6 +42,7 @@ message BlimpMessage { INPUT = 4; COMPOSITOR = 5; PROTOCOL_CONTROL = 6; + IME = 7; } // Sequence number of this message, used for message acknowledgement. @@ -74,5 +76,6 @@ message BlimpMessage { optional InputMessage input = 1003; optional CompositorMessage compositor = 1004; optional ProtocolControlMessage protocol_control = 1005; + optional ImeMessage ime = 1006; } diff --git a/blimp/common/proto/ime.proto b/blimp/common/proto/ime.proto new file mode 100644 index 0000000..d40c1ed --- /dev/null +++ b/blimp/common/proto/ime.proto @@ -0,0 +1,51 @@ +// Copyright 2016 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. +// +// Message definitions for text input messages. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package blimp; + +message ImeMessage { + // Text input type for IME which should be kept in sync with + // ui::TextInputType. + enum InputType { + NONE = 0; + TEXT = 1; + PASSWORD = 2; + SEARCH = 3; + EMAIL = 4; + NUMBER = 5; + TELEPHONE = 6; + URL = 7; + DATE = 8; + DATE_TIME = 9; + DATE_TIME_LOCAL = 10; + MONTH = 11; + TIME = 12; + WEEK = 13; + TEXT_AREA = 14; + CONTENT_EDITABLE = 15; + DATE_TIME_FIELD = 16; + } + + enum Type { + UNKNOWN = 0; + + // Server => Client types. + SHOW_IME = 1; + HIDE_IME = 2; + + // Client => Server types. + SET_TEXT = 3; + } + + optional int32 render_widget_id = 1; + optional Type type = 2 [default = UNKNOWN]; + optional InputType text_input_type = 3; + optional string ime_text = 4; +} diff --git a/blimp/engine/feature/engine_render_widget_feature.cc b/blimp/engine/feature/engine_render_widget_feature.cc index 5fdec48..b5f2d58 100644 --- a/blimp/engine/feature/engine_render_widget_feature.cc +++ b/blimp/engine/feature/engine_render_widget_feature.cc @@ -5,12 +5,15 @@ #include "blimp/engine/feature/engine_render_widget_feature.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "blimp/common/create_blimp_message.h" #include "blimp/common/proto/blimp_message.pb.h" #include "blimp/common/proto/compositor.pb.h" #include "blimp/common/proto/input.pb.h" #include "blimp/common/proto/render_widget.pb.h" +#include "blimp/net/input_message_converter.h" #include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "net/base/net_errors.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -32,6 +35,12 @@ void EngineRenderWidgetFeature::set_input_message_sender( input_message_sender_ = std::move(message_processor); } +void EngineRenderWidgetFeature::set_ime_message_sender( + scoped_ptr<BlimpMessageProcessor> message_processor) { + DCHECK(message_processor); + ime_message_sender_ = std::move(message_processor); +} + void EngineRenderWidgetFeature::set_compositor_message_sender( scoped_ptr<BlimpMessageProcessor> message_processor) { DCHECK(message_processor); @@ -113,6 +122,49 @@ void EngineRenderWidgetFeature::SendCompositorMessage( net::CompletionCallback()); } +void EngineRenderWidgetFeature::SendShowImeRequest( + const int tab_id, + content::RenderWidgetHost* render_widget_host, + const ui::TextInputClient* client) { + DCHECK(client); + + ImeMessage* ime_message; + scoped_ptr<BlimpMessage> blimp_message = + CreateBlimpMessage(&ime_message, tab_id); + + int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); + DCHECK_GT(render_widget_id, 0); + ime_message->set_render_widget_id(render_widget_id); + ime_message->set_type(ImeMessage::SHOW_IME); + ime_message->set_text_input_type( + InputMessageConverter::TextInputTypeToProto(client->GetTextInputType())); + + gfx::Range text_range; + base::string16 existing_text; + client->GetTextRange(&text_range); + client->GetTextFromRange(text_range, &existing_text); + ime_message->set_ime_text(base::UTF16ToUTF8(existing_text)); + + ime_message_sender_->ProcessMessage(std::move(blimp_message), + net::CompletionCallback()); +} + +void EngineRenderWidgetFeature::SendHideImeRequest( + const int tab_id, + content::RenderWidgetHost* render_widget_host) { + ImeMessage* ime_message; + scoped_ptr<BlimpMessage> blimp_message = + CreateBlimpMessage(&ime_message, tab_id); + + int render_widget_id = GetRenderWidgetId(tab_id, render_widget_host); + DCHECK_GT(render_widget_id, 0); + ime_message->set_render_widget_id(render_widget_id); + ime_message->set_type(ImeMessage::HIDE_IME); + + ime_message_sender_->ProcessMessage(std::move(blimp_message), + net::CompletionCallback()); +} + void EngineRenderWidgetFeature::SetDelegate( const int tab_id, RenderWidgetMessageDelegate* delegate) { @@ -131,6 +183,7 @@ void EngineRenderWidgetFeature::ProcessMessage( const net::CompletionCallback& callback) { DCHECK(!callback.is_null()); DCHECK(message->type() == BlimpMessage::RENDER_WIDGET || + message->type() == BlimpMessage::IME || message->type() == BlimpMessage::INPUT || message->type() == BlimpMessage::COMPOSITOR); @@ -163,6 +216,15 @@ void EngineRenderWidgetFeature::ProcessMessage( delegate->OnCompositorMessageReceived(render_widget_host, payload); } break; + case BlimpMessage::IME: + DCHECK(message->ime().type() == ImeMessage::SET_TEXT); + render_widget_host = + GetRenderWidgetHost(target_tab_id, message->ime().render_widget_id()); + if (render_widget_host && render_widget_host->GetView()) { + SetTextFromIME(render_widget_host->GetView()->GetTextInputClient(), + message->ime().ime_text()); + } + break; default: NOTREACHED(); } @@ -170,6 +232,19 @@ void EngineRenderWidgetFeature::ProcessMessage( callback.Run(net::OK); } +void EngineRenderWidgetFeature::SetTextFromIME(ui::TextInputClient* client, + std::string text) { + if (client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) { + // Clear out any existing text first and then insert new text entered + // through IME. + gfx::Range text_range; + client->GetTextRange(&text_range); + client->ExtendSelectionAndDelete(text_range.length(), text_range.length()); + + client->InsertText(base::UTF8ToUTF16(text)); + } +} + EngineRenderWidgetFeature::RenderWidgetMessageDelegate* EngineRenderWidgetFeature::FindDelegate(const int tab_id) { DelegateMap::const_iterator it = delegates_.find(tab_id); diff --git a/blimp/engine/feature/engine_render_widget_feature.h b/blimp/engine/feature/engine_render_widget_feature.h index 155ad3e..2591b5a 100644 --- a/blimp/engine/feature/engine_render_widget_feature.h +++ b/blimp/engine/feature/engine_render_widget_feature.h @@ -16,6 +16,7 @@ #include "base/memory/scoped_ptr.h" #include "blimp/net/blimp_message_processor.h" #include "blimp/net/input_message_converter.h" +#include "ui/base/ime/text_input_client.h" namespace blink { class WebGestureEvent; @@ -63,6 +64,9 @@ class EngineRenderWidgetFeature : public BlimpMessageProcessor { void set_compositor_message_sender( scoped_ptr<BlimpMessageProcessor> message_processor); + void set_ime_message_sender( + scoped_ptr<BlimpMessageProcessor> message_processor); + // Notifes the client that a new RenderWidget for a particular WebContents has // been created. This will trigger the creation of the BlimpCompositor for // this widget on the client. @@ -83,6 +87,13 @@ class EngineRenderWidgetFeature : public BlimpMessageProcessor { void OnRenderWidgetDeleted(const int tab_id, content::RenderWidgetHost* render_widget_host); + // Notifies the client to show/hide IME. + void SendShowImeRequest(const int tab_id, + content::RenderWidgetHost* render_widget_host, + const ui::TextInputClient* client); + void SendHideImeRequest(const int tab_id, + content::RenderWidgetHost* render_widget_host); + // Sends a CompositorMessage for |tab_id| to the client. void SendCompositorMessage(const int tab_id, content::RenderWidgetHost* render_widget_host, @@ -134,6 +145,10 @@ class EngineRenderWidgetFeature : public BlimpMessageProcessor { content::RenderWidgetHost* GetRenderWidgetHost(const int tab_id, const int render_widget_id); + // Inserts the text entered by the user into the |client|. + // The existing text in the box gets replaced by the new text from IME. + void SetTextFromIME(ui::TextInputClient* client, std::string text); + DelegateMap delegates_; TabMap tabs_; @@ -155,6 +170,7 @@ class EngineRenderWidgetFeature : public BlimpMessageProcessor { scoped_ptr<BlimpMessageProcessor> render_widget_message_sender_; scoped_ptr<BlimpMessageProcessor> compositor_message_sender_; scoped_ptr<BlimpMessageProcessor> input_message_sender_; + scoped_ptr<BlimpMessageProcessor> ime_message_sender_; DISALLOW_COPY_AND_ASSIGN(EngineRenderWidgetFeature); }; diff --git a/blimp/engine/feature/engine_render_widget_feature_unittest.cc b/blimp/engine/feature/engine_render_widget_feature_unittest.cc index ad23d63..3d9c91a 100644 --- a/blimp/engine/feature/engine_render_widget_feature_unittest.cc +++ b/blimp/engine/feature/engine_render_widget_feature_unittest.cc @@ -5,6 +5,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "blimp/common/create_blimp_message.h" #include "blimp/common/proto/blimp_message.pb.h" #include "blimp/common/proto/compositor.pb.h" @@ -18,6 +19,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/base/ime/text_input_client.h" using testing::_; using testing::InSequence; @@ -97,6 +99,55 @@ class MockRenderWidgetHost bool Send(IPC::Message* msg) override { return false; } }; +class MockTextInputClient : public ui::TextInputClient { + ui::TextInputType text_input_type_; + + public: + MockTextInputClient() : text_input_type_(ui::TEXT_INPUT_TYPE_TEXT) {} + ~MockTextInputClient() override {} + + void SetCompositionText(const ui::CompositionText& composition) override {} + void ConfirmCompositionText() override {} + void ClearCompositionText() override {} + void InsertText(const base::string16& text) override {} + void InsertChar(const ui::KeyEvent& event) override {} + ui::TextInputType GetTextInputType() const override { + return text_input_type_; + } + ui::TextInputMode GetTextInputMode() const override { + return ui::TEXT_INPUT_MODE_DEFAULT; + } + int GetTextInputFlags() const override { return 0; } + bool CanComposeInline() const override { return false; } + gfx::Rect GetCaretBounds() const override { return gfx::Rect(); } + bool GetCompositionCharacterBounds(uint32_t index, + gfx::Rect* rect) const override { + return false; + } + bool HasCompositionText() const override { return false; } + bool GetTextRange(gfx::Range* range) const override { return false; } + bool GetCompositionTextRange(gfx::Range* range) const override { + return false; + } + bool GetSelectionRange(gfx::Range* range) const override { return false; } + bool SetSelectionRange(const gfx::Range& range) override { return false; } + bool DeleteRange(const gfx::Range& range) override { return false; } + void OnInputMethodChanged() override {} + bool ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection direction) override { + return false; + } + void ExtendSelectionAndDelete(size_t before, size_t after) override {} + void EnsureCaretInRect(const gfx::Rect& rect) override {} + bool IsEditCommandEnabled(int command_id) override { return false; } + void SetEditCommandForNextKeyEvent(int command_id) override {} + bool GetTextFromRange(const gfx::Range& range, + base::string16* text) const override { + *text = base::string16(base::ASCIIToUTF16("green apple")); + return false; + } +}; + MATCHER_P(CompMsgEquals, contents, "") { if (contents.size() != arg.size()) return false; @@ -124,6 +175,24 @@ MATCHER_P3(BlimpRWMsgEquals, tab_id, rw_id, message_type, "") { arg.render_widget().type() == message_type; } +MATCHER_P2(BlimpImeMsgEquals, tab_id, message_type, "") { + return arg.target_tab_id() == tab_id && arg.ime().type() == message_type; +} + +MATCHER_P5(BlimpImeMsgEquals, + tab_id, + rwid, + message_type, + text, + text_input_type, + "") { + return arg.target_tab_id() == tab_id && + arg.ime().render_widget_id() == rwid && + arg.ime().type() == message_type && + arg.ime().ime_text().compare(text) == 0 && + arg.ime().text_input_type() == text_input_type; +} + void SendInputMessage(BlimpMessageProcessor* processor, int tab_id, int rw_id) { @@ -167,6 +236,8 @@ class EngineRenderWidgetFeatureTest : public testing::Test { compositor_message_sender_ = new MockBlimpMessageProcessor; feature_.set_compositor_message_sender( make_scoped_ptr(compositor_message_sender_)); + ime_message_sender_ = new MockBlimpMessageProcessor; + feature_.set_ime_message_sender(make_scoped_ptr(ime_message_sender_)); feature_.SetDelegate(1, &delegate1_); feature_.SetDelegate(2, &delegate2_); } @@ -174,10 +245,12 @@ class EngineRenderWidgetFeatureTest : public testing::Test { protected: MockBlimpMessageProcessor* render_widget_message_sender_; MockBlimpMessageProcessor* compositor_message_sender_; + MockBlimpMessageProcessor* ime_message_sender_; MockRenderWidgetHost render_widget_host1_; MockRenderWidgetHost render_widget_host2_; MockHostRenderWidgetMessageDelegate delegate1_; MockHostRenderWidgetMessageDelegate delegate2_; + MockTextInputClient text_input_client_; EngineRenderWidgetFeature feature_; }; @@ -213,6 +286,22 @@ TEST_F(EngineRenderWidgetFeatureTest, DelegateCallsOK) { SendCompositorMessage(&feature_, 2, 2, payload); } +TEST_F(EngineRenderWidgetFeatureTest, ImeRequestSentCorrectly) { + EXPECT_CALL( + *ime_message_sender_, + MockableProcessMessage(BlimpImeMsgEquals(2, 1, ImeMessage::SHOW_IME, + std::string("green apple"), 1), + _)); + + EXPECT_CALL( + *ime_message_sender_, + MockableProcessMessage(BlimpImeMsgEquals(2, ImeMessage::HIDE_IME), _)); + + feature_.OnRenderWidgetCreated(2, &render_widget_host1_); + feature_.SendShowImeRequest(2, &render_widget_host1_, &text_input_client_); + feature_.SendHideImeRequest(2, &render_widget_host1_); +} + TEST_F(EngineRenderWidgetFeatureTest, DropsStaleMessages) { InSequence sequence; std::vector<uint8_t> payload = { 'f', 'u', 'n' }; diff --git a/blimp/engine/session/blimp_engine_session.cc b/blimp/engine/session/blimp_engine_session.cc index a1bfbbe..bd67782 100644 --- a/blimp/engine/session/blimp_engine_session.cc +++ b/blimp/engine/session/blimp_engine_session.cc @@ -31,6 +31,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "net/base/ip_address.h" #include "net/base/net_errors.h" @@ -38,6 +39,8 @@ #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/ime/input_method.h" +#include "ui/base/ime/text_input_client.h" #include "ui/gfx/geometry/size.h" #include "ui/wm/core/base_focus_rules.h" #include "ui/wm/core/default_activation_client.h" @@ -193,6 +196,8 @@ BlimpEngineSession::BlimpEngineSession( BlimpEngineSession::~BlimpEngineSession() { render_widget_feature_.RemoveDelegate(kDummyTabId); + window_tree_host_->GetInputMethod()->RemoveObserver(this); + // Ensure that all WebContents are torn down first, since teardown will // trigger RenderViewDeleted callbacks to their observers. web_contents_.reset(); @@ -220,6 +225,8 @@ void BlimpEngineSession::Initialize() { capture_client_.reset( new aura::client::DefaultCaptureClient(window_tree_host_->window())); + window_tree_host_->GetInputMethod()->AddObserver(this); + window_tree_host_->SetBounds(gfx::Rect(screen_->GetPrimaryDisplay().size())); RegisterFeatures(); @@ -255,6 +262,9 @@ void BlimpEngineSession::RegisterFeatures() { render_widget_feature_.set_compositor_message_sender( thread_pipe_manager_->RegisterFeature(BlimpMessage::COMPOSITOR, &render_widget_feature_)); + render_widget_feature_.set_ime_message_sender( + thread_pipe_manager_->RegisterFeature(BlimpMessage::IME, + &render_widget_feature_)); } bool BlimpEngineSession::CreateWebContents(const int target_tab_id) { @@ -339,6 +349,52 @@ void BlimpEngineSession::OnCompositorMessageReceived( render_widget_host->HandleCompositorProto(message); } +void BlimpEngineSession::OnTextInputTypeChanged( + const ui::TextInputClient* client) {} + +void BlimpEngineSession::OnFocus() {} + +void BlimpEngineSession::OnBlur() {} + +void BlimpEngineSession::OnCaretBoundsChanged( + const ui::TextInputClient* client) {} + +// Called when either: +// - the TextInputClient is changed (e.g. by a change of focus) +// - the TextInputType of the TextInputClient changes +void BlimpEngineSession::OnTextInputStateChanged( + const ui::TextInputClient* client) { + if (!web_contents_->GetRenderWidgetHostView()) + return; + + ui::TextInputType type = + client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; + + // TODO(shaktisahu): Propagate the new type to the client. + // Hide IME, when text input is out of focus, i.e. if the text input type + // changes to ui::TEXT_INPUT_TYPE_NONE. For other text input types, + // OnShowImeIfNeeded is used instead to send show IME request to client. + if (type == ui::TEXT_INPUT_TYPE_NONE) + render_widget_feature_.SendHideImeRequest( + kDummyTabId, + web_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost()); +} + +void BlimpEngineSession::OnInputMethodDestroyed( + const ui::InputMethod* input_method) {} + +// Called when a user input should trigger showing the IME. +void BlimpEngineSession::OnShowImeIfNeeded() { + if (!web_contents_->GetRenderWidgetHostView() || + !window_tree_host_->GetInputMethod()->GetTextInputClient()) + return; + + render_widget_feature_.SendShowImeRequest( + kDummyTabId, + web_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost(), + window_tree_host_->GetInputMethod()->GetTextInputClient()); +} + void BlimpEngineSession::ProcessMessage( scoped_ptr<BlimpMessage> message, const net::CompletionCallback& callback) { @@ -484,7 +540,7 @@ void BlimpEngineSession::LoadProgressChanged( if (source != web_contents_.get()) return; - bool page_load_completed = progress == 1.0 ? true : false; + bool page_load_completed = (progress == 1.0); // If the client has been notified of a page load completed change, avoid // sending another message. For the first navigation, the initial value used @@ -492,12 +548,12 @@ void BlimpEngineSession::LoadProgressChanged( if (last_page_load_completed_value_ == page_load_completed) return; - NavigationMessage* navigation_message; + NavigationMessage* navigation_message = nullptr; scoped_ptr<BlimpMessage> message = CreateBlimpMessage(&navigation_message, kDummyTabId); navigation_message->set_type(NavigationMessage::NAVIGATION_STATE_CHANGED); - NavigationStateChangeMessage* details = - navigation_message->mutable_navigation_state_changed(); + NavigationStateChangeMessage* details = + navigation_message->mutable_navigation_state_changed(); details->set_page_load_completed(page_load_completed); navigation_message_sender_->ProcessMessage(std::move(message), diff --git a/blimp/engine/session/blimp_engine_session.h b/blimp/engine/session/blimp_engine_session.h index 75bde2e..1b311ab 100644 --- a/blimp/engine/session/blimp_engine_session.h +++ b/blimp/engine/session/blimp_engine_session.h @@ -19,6 +19,7 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "net/base/completion_callback.h" +#include "ui/base/ime/input_method_observer.h" #include "ui/gfx/geometry/size.h" namespace aura { @@ -68,6 +69,7 @@ class BlimpEngineSession : public BlimpMessageProcessor, public content::WebContentsDelegate, public content::WebContentsObserver, + public ui::InputMethodObserver, public EngineRenderWidgetFeature::RenderWidgetMessageDelegate { public: BlimpEngineSession(scoped_ptr<BlimpBrowserContext> browser_context, @@ -138,6 +140,15 @@ class BlimpEngineSession void LoadProgressChanged(content::WebContents* source, double progress) override; + // ui::InputMethodObserver overrides. + void OnTextInputTypeChanged(const ui::TextInputClient* client) override; + void OnFocus() override; + void OnBlur() override; + void OnCaretBoundsChanged(const ui::TextInputClient* client) override; + void OnTextInputStateChanged(const ui::TextInputClient* client) override; + void OnInputMethodDestroyed(const ui::InputMethod* input_method) override; + void OnShowImeIfNeeded() override; + // content::WebContentsObserver implementation. void RenderViewCreated(content::RenderViewHost* render_view_host) override; void RenderViewHostChanged(content::RenderViewHost* old_host, diff --git a/blimp/net/BUILD.gn b/blimp/net/BUILD.gn index 0fe0cfd..00b771f 100644 --- a/blimp/net/BUILD.gn +++ b/blimp/net/BUILD.gn @@ -65,6 +65,7 @@ component("blimp_net") { "//blimp/common:blimp_common", "//blimp/common/proto", "//net", + "//ui/base/ime:text_input_types", ] } diff --git a/blimp/net/DEPS b/blimp/net/DEPS index 211c82c..b2abd3d 100644 --- a/blimp/net/DEPS +++ b/blimp/net/DEPS @@ -2,4 +2,5 @@ include_rules = [ "+net", "+third_party/WebKit/public/platform/WebGestureDevice.h", "+third_party/WebKit/public/web/WebInputEvent.h", + "+ui/base/ime/text_input_type.h", ] diff --git a/blimp/net/input_message_converter.cc b/blimp/net/input_message_converter.cc index 9cfd3c8..5f3854e 100644 --- a/blimp/net/input_message_converter.cc +++ b/blimp/net/input_message_converter.cc @@ -178,4 +178,87 @@ scoped_ptr<blink::WebGestureEvent> InputMessageConverter::ProcessMessage( return event; } +ui::TextInputType InputMessageConverter::TextInputTypeFromProto( + ImeMessage_InputType type) { + switch (type) { + case ImeMessage_InputType_NONE: + return ui::TEXT_INPUT_TYPE_NONE; + case ImeMessage_InputType_TEXT: + return ui::TEXT_INPUT_TYPE_TEXT; + case ImeMessage_InputType_PASSWORD: + return ui::TEXT_INPUT_TYPE_PASSWORD; + case ImeMessage_InputType_SEARCH: + return ui::TEXT_INPUT_TYPE_SEARCH; + case ImeMessage_InputType_EMAIL: + return ui::TEXT_INPUT_TYPE_EMAIL; + case ImeMessage_InputType_NUMBER: + return ui::TEXT_INPUT_TYPE_NUMBER; + case ImeMessage_InputType_TELEPHONE: + return ui::TEXT_INPUT_TYPE_TELEPHONE; + case ImeMessage_InputType_URL: + return ui::TEXT_INPUT_TYPE_URL; + case ImeMessage_InputType_DATE: + return ui::TEXT_INPUT_TYPE_DATE; + case ImeMessage_InputType_DATE_TIME: + return ui::TEXT_INPUT_TYPE_DATE_TIME; + case ImeMessage_InputType_DATE_TIME_LOCAL: + return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; + case ImeMessage_InputType_MONTH: + return ui::TEXT_INPUT_TYPE_MONTH; + case ImeMessage_InputType_TIME: + return ui::TEXT_INPUT_TYPE_TIME; + case ImeMessage_InputType_WEEK: + return ui::TEXT_INPUT_TYPE_WEEK; + case ImeMessage_InputType_TEXT_AREA: + return ui::TEXT_INPUT_TYPE_TEXT_AREA; + case ImeMessage_InputType_CONTENT_EDITABLE: + return ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE; + case ImeMessage_InputType_DATE_TIME_FIELD: + return ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD; + } + return ui::TEXT_INPUT_TYPE_NONE; +} + +ImeMessage_InputType InputMessageConverter::TextInputTypeToProto( + ui::TextInputType type) { + switch (type) { + case ui::TEXT_INPUT_TYPE_NONE: + NOTREACHED() << "IME needs an editable TextInputType"; + return ImeMessage_InputType_NONE; + case ui::TEXT_INPUT_TYPE_TEXT: + return ImeMessage_InputType_TEXT; + case ui::TEXT_INPUT_TYPE_PASSWORD: + return ImeMessage_InputType_PASSWORD; + case ui::TEXT_INPUT_TYPE_SEARCH: + return ImeMessage_InputType_SEARCH; + case ui::TEXT_INPUT_TYPE_EMAIL: + return ImeMessage_InputType_EMAIL; + case ui::TEXT_INPUT_TYPE_NUMBER: + return ImeMessage_InputType_NUMBER; + case ui::TEXT_INPUT_TYPE_TELEPHONE: + return ImeMessage_InputType_TELEPHONE; + case ui::TEXT_INPUT_TYPE_URL: + return ImeMessage_InputType_URL; + case ui::TEXT_INPUT_TYPE_DATE: + return ImeMessage_InputType_DATE; + case ui::TEXT_INPUT_TYPE_DATE_TIME: + return ImeMessage_InputType_DATE_TIME; + case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: + return ImeMessage_InputType_DATE_TIME_LOCAL; + case ui::TEXT_INPUT_TYPE_MONTH: + return ImeMessage_InputType_MONTH; + case ui::TEXT_INPUT_TYPE_TIME: + return ImeMessage_InputType_TIME; + case ui::TEXT_INPUT_TYPE_WEEK: + return ImeMessage_InputType_WEEK; + case ui::TEXT_INPUT_TYPE_TEXT_AREA: + return ImeMessage_InputType_TEXT_AREA; + case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE: + return ImeMessage_InputType_CONTENT_EDITABLE; + case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: + return ImeMessage_InputType_DATE_TIME_FIELD; + } + return ImeMessage_InputType_NONE; +} + } // namespace blimp diff --git a/blimp/net/input_message_converter.h b/blimp/net/input_message_converter.h index 53606c1..7d21216 100644 --- a/blimp/net/input_message_converter.h +++ b/blimp/net/input_message_converter.h @@ -7,7 +7,9 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "blimp/common/proto/ime.pb.h" #include "blimp/net/blimp_net_export.h" +#include "ui/base/ime/text_input_type.h" namespace blink { class WebGestureEvent; @@ -17,9 +19,12 @@ namespace blimp { class InputMessage; -// Handles creating WebGestureEvents from a stream of InputMessage protos. This -// class may be stateful to optimize the size of the serialized transmission -// data. See InputMessageConverter for the deserialize code. +// A generic class to provide conversion utilities for protos such as : +// 1) Creating WebGestureEvents from a stream of InputMessage protos. +// This class may be stateful to optimize the size of the serialized +// transmission +// data. See InputMessageConverter for the deserialize code. +// 2) Conversion between ui::TextInputType and ImeMessage proto. class BLIMP_NET_EXPORT InputMessageConverter { public: InputMessageConverter(); @@ -30,6 +35,10 @@ class BLIMP_NET_EXPORT InputMessageConverter { scoped_ptr<blink::WebGestureEvent> ProcessMessage( const InputMessage& message); + // Converts a ui::TextInputType to ImeMessage proto. + static ImeMessage_InputType TextInputTypeToProto(ui::TextInputType type); + static ui::TextInputType TextInputTypeFromProto(ImeMessage_InputType type); + private: DISALLOW_COPY_AND_ASSIGN(InputMessageConverter); }; diff --git a/blimp/net/input_message_unittest.cc b/blimp/net/input_message_unittest.cc index 6157f2b0..02579d7 100644 --- a/blimp/net/input_message_unittest.cc +++ b/blimp/net/input_message_unittest.cc @@ -130,4 +130,13 @@ TEST(InputMessageTest, TestUnsupportedInputEventSerializationFails) { EXPECT_EQ(nullptr, generator.GenerateMessage(event).get()); } +TEST(InputMessageConverterTest, TestTextInputTypeToProtoConversion) { + for (size_t i = ui::TextInputType::TEXT_INPUT_TYPE_TEXT; + i < ui::TextInputType::TEXT_INPUT_TYPE_MAX; i++) { + ui::TextInputType type = static_cast<ui::TextInputType>(i); + EXPECT_EQ(type, InputMessageConverter::TextInputTypeFromProto( + InputMessageConverter::TextInputTypeToProto(type))); + } +} + } // namespace blimp |