Index: content/browser/renderer_host/render_widget_host_view_aura_unittest.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc |
index 645811806fa018b40d1c18f75ce8c6b2608c297b..ec18b8c9cc23435e2eb85547f3981720816b2e9e 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc |
@@ -42,11 +42,13 @@ |
#include "content/browser/renderer_host/render_widget_host_delegate.h" |
#include "content/browser/renderer_host/render_widget_host_impl.h" |
#include "content/browser/renderer_host/resize_lock.h" |
+#include "content/browser/renderer_host/text_input_manager.h" |
#include "content/browser/web_contents/web_contents_view_aura.h" |
#include "content/common/host_shared_bitmap_manager.h" |
#include "content/common/input/input_event_utils.h" |
#include "content/common/input/synthetic_web_input_event_builders.h" |
#include "content/common/input_messages.h" |
+#include "content/common/text_input_state.h" |
#include "content/common/view_messages.h" |
#include "content/public/browser/render_widget_host_view.h" |
#include "content/public/browser/render_widget_host_view_frame_subscriber.h" |
@@ -56,6 +58,7 @@ |
#include "content/public/test/test_browser_context.h" |
#include "content/test/test_render_view_host.h" |
#include "content/test/test_web_contents.h" |
+#include "ipc/ipc_message.h" |
#include "ipc/ipc_test_sink.h" |
#include "media/base/video_frame.h" |
#include "testing/gmock/include/gmock/gmock.h" |
@@ -163,6 +166,7 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { |
const NativeWebKeyboardEvent* last_event() const { return last_event_.get(); } |
void set_widget_host(RenderWidgetHostImpl* rwh) { rwh_ = rwh; } |
void set_is_fullscreen(bool is_fullscreen) { is_fullscreen_ = is_fullscreen; } |
+ TextInputManager* GetTextInputManager() { return &text_input_manager_; } |
protected: |
// RenderWidgetHostDelegate: |
@@ -185,6 +189,7 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { |
std::unique_ptr<NativeWebKeyboardEvent> last_event_; |
RenderWidgetHostImpl* rwh_; |
bool is_fullscreen_; |
+ TextInputManager text_input_manager_; |
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHostDelegate); |
}; |
@@ -544,6 +549,13 @@ class RenderWidgetHostViewAuraTest : public testing::Test { |
} |
protected: |
+ void SetTextInputTypeForView(RenderWidgetHostViewBase* view, |
+ ui::TextInputType type) { |
+ TextInputState state; |
+ state.type = type; |
+ view->TextInputStateChanged(state); |
+ } |
+ |
// If true, then calls RWH::Shutdown() instead of deleting RWH. |
bool widget_host_uses_shutdown_to_destroy_; |
@@ -1081,6 +1093,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PopupClosesWhenParentLosesFocus) { |
TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) { |
view_->InitAsChild(NULL); |
view_->Show(); |
+ SetTextInputTypeForView(view_, ui::TEXT_INPUT_TYPE_TEXT); |
EhsanK
2016/06/08 16:58:43
Changes such as this are needed in the new archite
|
ui::CompositionText composition_text; |
composition_text.text = base::ASCIIToUTF16("|a|b"); |
@@ -1135,6 +1148,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) { |
TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) { |
view_->InitAsChild(NULL); |
view_->Show(); |
+ SetTextInputTypeForView(view_, ui::TEXT_INPUT_TYPE_TEXT); |
ui::CompositionText composition_text; |
composition_text.text = base::ASCIIToUTF16("|a|b"); |
@@ -4490,4 +4504,210 @@ TEST_F(RenderWidgetHostViewAuraWithViewHarnessTest, |
RenderViewHostFactory::set_is_real_render_view_host(false); |
} |
+// ---------------------------------------------------------------------------- |
+// TextInputManager and IME-Related Tests |
+ |
+class TextInputManagerTestBase : public RenderWidgetHostViewAuraTest { |
kenrb
2016/06/13 19:37:47
Is this needed, or is it feasible to roll this int
EhsanK
2016/06/17 22:36:20
Moved into the actual test class which was subclas
|
+ public: |
+ TextInputManagerTestBase(){}; |
+ ~TextInputManagerTestBase() override {} |
+ |
+ void SetUp() override { |
+ RenderWidgetHostViewAuraTest::SetUp(); |
+ InitializeAura(); |
+ text_input_manager_ = render_widget_host_delegate()->GetTextInputManager(); |
+ } |
+ |
+ protected: |
+ MockRenderProcessHost* CreateNewProcessHost() { |
+ MockRenderProcessHost* process_host = |
+ new MockRenderProcessHost(&test_browser_context_); |
+ return process_host; |
+ } |
+ |
+ RenderWidgetHostImpl* CreateRenderWidgetHostForProcess( |
+ MockRenderProcessHost* process_host) { |
+ RenderWidgetHostImpl* render_widget_host = |
+ new RenderWidgetHostImpl(render_widget_host_delegate(), process_host, |
+ process_host->GetNextRoutingID(), false); |
+ return render_widget_host; |
+ } |
+ |
+ TestRenderWidgetHostView* CreateViewForProcess( |
+ MockRenderProcessHost* process_host) { |
+ RenderWidgetHostImpl* host = CreateRenderWidgetHostForProcess(process_host); |
+ TestRenderWidgetHostView* view = new TestRenderWidgetHostView(host); |
+ host->SetView(view); |
+ return view; |
+ } |
+ |
+ TextInputManager* text_input_manager() const { return text_input_manager_; } |
+ |
+ MockRenderProcessHost* tab_process() const { return process_host_; } |
+ |
+ RenderWidgetHostViewAura* tab_view() const { return view_; } |
+ |
+ MockRenderWidgetHostDelegate* render_widget_host_delegate() const { |
+ return delegates_.back().get(); |
+ } |
+ |
+ bool has_composition_text() const { |
+ return tab_view()->has_composition_text_; |
+ } |
+ |
+ private: |
+ // This will initialize |window_| in RenderWidgetHostViewAura. It is needed |
+ // for RenderWidgetHostViewAura::GetInputMethod() to work. |
+ void InitializeAura() { |
+ view_->InitAsChild(nullptr); |
+ view_->Show(); |
+ } |
+ |
+ TextInputManager* text_input_manager_; |
+ TestBrowserContext test_browser_context_; |
+ MockRenderProcessHost* tab_process_; |
+ RenderWidgetHostViewAura* tab_view_; |
+}; |
+ |
+// A group of tests which veirfy the correctness of routing of the IME method |
+// results. This category of tests creates a scenario with two out of process |
+// renderers, each with a view, and a child frame view in process with the tab |
+// (a total of four RWHV with the tab. This makes a total of four RWHV for |
+// testing. Then, in each test one of the IME result methods are called on the |
+// ui::TextInputClient (RenderWidgetHostViewAura) and then the tests verify that |
+// the call leads to sending an IPC to the corresponding renderer process. |
kenrb
2016/06/13 19:37:47
A couple of typos in this paragraph: 'veirfy', and
EhsanK
2016/06/17 22:36:20
Acknowledged.
|
+class InputMethodResultAuraTest : public TextInputManagerTestBase { |
+ public: |
+ InputMethodResultAuraTest() {} |
+ ~InputMethodResultAuraTest() override {} |
+ |
+ void SetUp() override { |
+ TextInputManagerTestBase::SetUp(); |
+ |
+ MockRenderProcessHost* second_process_host = CreateNewProcessHost(); |
+ MockRenderProcessHost* third_process_host = CreateNewProcessHost(); |
+ |
+ TestRenderWidgetHostView* second_process_view = |
+ CreateViewForProcess(second_process_host); |
+ TestRenderWidgetHostView* third_process_view = |
+ CreateViewForProcess(third_process_host); |
+ TestRenderWidgetHostView* tab_process_child_view = |
+ CreateViewForProcess(tab_process()); |
+ |
+ views_.insert(views_.begin(), {tab_view(), second_process_view, |
+ third_process_view, tab_process_child_view}); |
+ processes_.insert(processes_.begin(), {tab_process(), second_process_host, |
+ third_process_host, tab_process()}); |
+ } |
+ |
+ void TearDown() override { |
+ RenderWidgetHost* host = views_[1]->GetRenderWidgetHost(); |
+ views_[1]->Destroy(); |
+ delete host; |
+ |
+ host = views_[2]->GetRenderWidgetHost(); |
+ views_[2]->Destroy(); |
+ delete host; |
+ |
+ // This one is in-process with tab. The base class will clean the widget. |
+ views_[3]->Destroy(); |
+ |
+ TextInputManagerTestBase::TearDown(); |
+ } |
+ |
+ const IPC::Message* RunAndReturnIPCSent(const base::Closure closure, |
+ MockRenderProcessHost* process, |
+ int32_t message_id) { |
+ process->sink().ClearMessages(); |
+ closure.Run(); |
+ return process->sink().GetFirstMessageMatching(message_id); |
+ } |
+ |
+ void ActivateView(RenderWidgetHostViewBase* view) { |
+ if (text_input_manager()->GetActiveView()) { |
+ text_input_manager()->GetActiveView()->TextInputStateChanged( |
+ TextInputState()); |
+ } |
+ |
+ if (!view) |
+ return; |
+ |
+ TextInputState state_with_type_text; |
+ state_with_type_text.type = ui::TEXT_INPUT_TYPE_TEXT; |
+ view->TextInputStateChanged(state_with_type_text); |
+ } |
+ |
+ ui::TextInputClient* text_input_client() const { return tab_view(); } |
+ |
+ protected: |
+ void SetHasCompositionTextToTrue() { |
+ ui::CompositionText composition_text; |
+ composition_text.text = base::ASCIIToUTF16("text"); |
+ tab_view()->SetCompositionText(composition_text); |
+ EXPECT_TRUE(has_composition_text()); |
+ } |
+ std::vector<RenderWidgetHostViewBase*> views_; |
+ std::vector<MockRenderProcessHost*> processes_; |
+}; |
+ |
+// This test verifies that ui::TextInputClient::SetCompositionText call leads to |
+// IPC message InputMsg_ImeSetComposition sent to the right RendererProcess. |
+TEST_F(InputMethodResultAuraTest, SetCompositionText) { |
+ std::vector<size_t> activation_sequence{0, 1, 2, 1, 1, 3, 0, 3, 1}; |
+ base::Closure ime_call = |
+ base::Bind(&ui::TextInputClient::SetCompositionText, |
+ base::Unretained(text_input_client()), ui::CompositionText()); |
+ for (auto index : activation_sequence) { |
+ ActivateView(views_[index]); |
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index], |
+ InputMsg_ImeSetComposition::ID)); |
+ } |
+} |
+ |
+// This test verifies that ui::TextInputClient::ConfirmCompositionText call |
+// leads to IPC message InputMsg_ImeConfirmComposition sent to the right |
+// RendererProcess. |
+TEST_F(InputMethodResultAuraTest, ConfirmCompositionText) { |
+ std::vector<size_t> activation_sequence{0, 1, 2, 1, 1, 3, 0, 3, 1}; |
+ base::Closure ime_call = |
+ base::Bind(&ui::TextInputClient::ConfirmCompositionText, |
+ base::Unretained(text_input_client())); |
+ for (auto index : activation_sequence) { |
+ ActivateView(views_[index]); |
+ SetHasCompositionTextToTrue(); |
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index], |
+ InputMsg_ImeConfirmComposition::ID)); |
+ } |
+} |
+ |
+// This test verifies that ui::TextInputClient::ConfirmCompositionText call |
+// leads to IPC message InputMsg_ImeSetComposition sent to the right |
+// RendererProcess. |
+TEST_F(InputMethodResultAuraTest, ClearCompositionText) { |
+ std::vector<size_t> activation_sequence{0, 1, 2, 1, 1, 3, 0, 3, 1}; |
+ base::Closure ime_call = |
+ base::Bind(&ui::TextInputClient::ClearCompositionText, |
+ base::Unretained(text_input_client())); |
+ for (auto index : activation_sequence) { |
+ ActivateView(views_[index]); |
+ SetHasCompositionTextToTrue(); |
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index], |
+ InputMsg_ImeSetComposition::ID)); |
+ } |
+} |
+ |
+// This test verifies that ui::TextInputClient::InsertText call leads to IPC |
+// message InputMsg_ImeSetComposition sent to the right RendererProcess. |
+TEST_F(InputMethodResultAuraTest, InsertText) { |
+ std::vector<size_t> activation_sequence{0, 1, 2, 1, 1, 3, 0, 3, 1}; |
+ base::Closure ime_call = |
+ base::Bind(&ui::TextInputClient::InsertText, |
+ base::Unretained(text_input_client()), base::string16()); |
+ for (auto index : activation_sequence) { |
+ ActivateView(views_[index]); |
+ EXPECT_TRUE(!!RunAndReturnIPCSent(ime_call, processes_[index], |
+ InputMsg_ImeConfirmComposition::ID)); |
+ } |
+} |
+ |
} // namespace content |