Chromium Code Reviews| 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..0a84fc9f6469df8d6c1b1d36377d5d213fcce37c 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,9 @@ 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() override { |
| + return &text_input_manager_; |
| + } |
| protected: |
| // RenderWidgetHostDelegate: |
| @@ -185,6 +191,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 +551,15 @@ class RenderWidgetHostViewAuraTest : public testing::Test { |
| } |
| protected: |
| + BrowserContext* browser_context() { return browser_context_.get(); } |
| + |
| + 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 +1097,7 @@ TEST_F(RenderWidgetHostViewAuraTest, PopupClosesWhenParentLosesFocus) { |
| TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) { |
| view_->InitAsChild(NULL); |
| view_->Show(); |
| + SetTextInputTypeForView(view_, ui::TEXT_INPUT_TYPE_TEXT); |
| ui::CompositionText composition_text; |
| composition_text.text = base::ASCIIToUTF16("|a|b"); |
| @@ -1135,6 +1152,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 +4508,206 @@ TEST_F(RenderWidgetHostViewAuraWithViewHarnessTest, |
| RenderViewHostFactory::set_is_real_render_view_host(false); |
| } |
| +// ---------------------------------------------------------------------------- |
| +// TextInputManager and IME-Related Tests |
| + |
| +// A group of tests which verify thatthe IME method results are routed to the |
|
kenrb
2016/06/20 16:04:06
nit: "thatthe"
EhsanK
2016/06/22 18:26:32
Done.
|
| +// right RenderWidget in the OOPIF structure. |
| +// In each test, 3 views are created where one is in process with main frame and |
| +// the other two are in distinct processes. This makes a total of 4 RWHV. Then, |
| +// each tests is about one of the IME result methods. The method is called on |
|
kenrb
2016/06/20 16:04:06
I am not clear what this sentence is trying to say
EhsanK
2016/06/22 18:26:33
Acknowledged.
|
| +// ui::TextInputClient (i.e., RWHV for the tab in aura) and then the test |
| +// verifies that the IPC is routed to the RenderWidget corresponding to the |
| +// active view (i.e., the RenderWidget with focused <input>). |
| +class InputMethodResultAuraTest : public RenderWidgetHostViewAuraTest { |
| + public: |
| + InputMethodResultAuraTest() {} |
| + ~InputMethodResultAuraTest() override {} |
| + |
| + void SetUp() override { |
| + RenderWidgetHostViewAuraTest::SetUp(); |
| + InitializeAura(); |
| + text_input_manager_ = render_widget_host_delegate()->GetTextInputManager(); |
| + |
| + view_for_first_process_ = CreateViewForProcess(tab_process()); |
| + |
| + second_process_host_ = CreateNewProcessHost(); |
| + view_for_second_process_ = CreateViewForProcess(second_process_host_); |
| + |
| + third_process_host_ = CreateNewProcessHost(); |
| + view_for_third_process_ = CreateViewForProcess(third_process_host_); |
| + |
| + views_.insert(views_.begin(), |
| + {tab_view(), view_for_first_process_, |
| + view_for_second_process_, view_for_third_process_}); |
| + processes_.insert(processes_.begin(), |
| + {tab_process(), tab_process(), second_process_host_, |
| + third_process_host_}); |
| + } |
| + |
| + void TearDown() override { |
| + RenderWidgetHost* host_for_second_process = |
| + view_for_second_process_->GetRenderWidgetHost(); |
| + view_for_second_process_->Destroy(); |
| + delete host_for_second_process; |
| + |
| + RenderWidgetHost* host_for_third_process = |
| + view_for_third_process_->GetRenderWidgetHost(); |
| + view_for_third_process_->Destroy(); |
| + delete host_for_third_process; |
| + |
| + // This one is in-process with tab. The base class will clean the widget. |
| + view_for_first_process_->Destroy(); |
| + |
| + RenderWidgetHostViewAuraTest::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()->GetActiveWidget()) { |
| + text_input_manager()->GetActiveWidget()->GetView()->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); |
| + } |
| + |
| + TextInputManager* text_input_manager() { 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(); |
| + } |
| + |
| + ui::TextInputClient* text_input_client() const { return view_; } |
| + |
| + bool has_composition_text() const { |
| + return tab_view()->has_composition_text_; |
| + } |
| + |
| + MockRenderProcessHost* CreateNewProcessHost() { |
| + MockRenderProcessHost* process_host = |
| + new MockRenderProcessHost(browser_context()); |
| + return process_host; |
| + } |
| + |
| + RenderWidgetHostImpl* CreateRenderWidgetHostForProcess( |
| + MockRenderProcessHost* process_host) { |
| + RenderWidgetHostImpl* render_widget_host = |
|
Charlie Reis
2016/06/21 21:13:56
Might be easier to read if you avoid declaring it
EhsanK
2016/06/22 18:26:32
Acknowledged.
|
| + 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; |
| + } |
| + |
| + 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_; |
| + |
| + 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_; |
| + TestRenderWidgetHostView* view_for_first_process_; |
| + MockRenderProcessHost* second_process_host_; |
| + TestRenderWidgetHostView* view_for_second_process_; |
| + MockRenderProcessHost* third_process_host_; |
| + TestRenderWidgetHostView* view_for_third_process_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(InputMethodResultAuraTest); |
| +}; |
| + |
| +// This test verifies that ui::TextInputClient::SetCompositionText call leads to |
| +// IPC message InputMsg_ImeSetComposition sent to the right RendererProcess. |
|
Charlie Reis
2016/06/21 21:13:56
nit: being sent
nit: renderer process (since Rende
EhsanK
2016/06/22 18:26:33
Done.
|
| +TEST_F(InputMethodResultAuraTest, SetCompositionText) { |
| + std::vector<size_t> activation_sequence{0, 1, 2, 1, 1, 3, 0, 3, 1}; |
|
Charlie Reis
2016/06/21 21:13:56
nit: This needs a comment and/or a clearer name.
EhsanK
2016/06/22 18:26:33
Acknowledged.
|
| + 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 |