1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/shell.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/test/base/interactive_test_utils.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "ui/aura/client/aura_constants.h"
16 #include "ui/aura/window_event_dispatcher.h"
17 #include "ui/base/ime/input_method_factory.h"
18
19 namespace chromeos {
20 namespace {
GetInputMethod()21 ui::MockInputMethod* GetInputMethod() {
22 ui::MockInputMethod* input_method = static_cast<ui::MockInputMethod*>(
23 ash::Shell::GetPrimaryRootWindow()->GetProperty(
24 aura::client::kRootWindowInputMethodKey));
25 CHECK(input_method);
26 return input_method;
27 }
28 } // namespace
29
SetUpInProcessBrowserTestFixture()30 void TextInputTestBase::SetUpInProcessBrowserTestFixture() {
31 ui::SetUpInputMethodFactoryForTesting();
32 }
33
TextInputTestHelper()34 TextInputTestHelper::TextInputTestHelper()
35 : waiting_type_(NO_WAIT),
36 selection_range_(gfx::Range::InvalidRange()),
37 focus_state_(false),
38 latest_text_input_type_(ui::TEXT_INPUT_TYPE_NONE) {
39 GetInputMethod()->AddObserver(this);
40 }
41
~TextInputTestHelper()42 TextInputTestHelper::~TextInputTestHelper() {
43 GetInputMethod()->RemoveObserver(this);
44 }
45
GetSurroundingText() const46 base::string16 TextInputTestHelper::GetSurroundingText() const {
47 return surrounding_text_;
48 }
49
GetCaretRect() const50 gfx::Rect TextInputTestHelper::GetCaretRect() const {
51 return caret_rect_;
52 }
53
GetCompositionHead() const54 gfx::Rect TextInputTestHelper::GetCompositionHead() const {
55 return composition_head_;
56 }
57
GetSelectionRange() const58 gfx::Range TextInputTestHelper::GetSelectionRange() const {
59 return selection_range_;
60 }
61
GetFocusState() const62 bool TextInputTestHelper::GetFocusState() const {
63 return focus_state_;
64 }
65
GetTextInputType() const66 ui::TextInputType TextInputTestHelper::GetTextInputType() const {
67 return latest_text_input_type_;
68 }
69
GetTextInputClient() const70 ui::TextInputClient* TextInputTestHelper::GetTextInputClient() const {
71 return GetInputMethod()->GetTextInputClient();
72 }
73
OnTextInputTypeChanged(const ui::TextInputClient * client)74 void TextInputTestHelper::OnTextInputTypeChanged(
75 const ui::TextInputClient* client) {
76 latest_text_input_type_ =
77 client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
78 if (waiting_type_ == WAIT_ON_TEXT_INPUT_TYPE_CHANGED)
79 base::MessageLoop::current()->Quit();
80 }
81
OnShowImeIfNeeded()82 void TextInputTestHelper::OnShowImeIfNeeded() {
83 }
84
OnInputMethodDestroyed(const ui::InputMethod * input_method)85 void TextInputTestHelper::OnInputMethodDestroyed(
86 const ui::InputMethod* input_method) {
87 }
88
OnFocus()89 void TextInputTestHelper::OnFocus() {
90 focus_state_ = true;
91 if (waiting_type_ == WAIT_ON_FOCUS)
92 base::MessageLoop::current()->Quit();
93 }
94
OnBlur()95 void TextInputTestHelper::OnBlur() {
96 focus_state_ = false;
97 if (waiting_type_ == WAIT_ON_BLUR)
98 base::MessageLoop::current()->Quit();
99 }
100
OnCaretBoundsChanged(const ui::TextInputClient * client)101 void TextInputTestHelper::OnCaretBoundsChanged(
102 const ui::TextInputClient* client) {
103 gfx::Range text_range;
104 if (GetTextInputClient()) {
105 if (!GetTextInputClient()->GetTextRange(&text_range) ||
106 !GetTextInputClient()->GetTextFromRange(text_range,
107 &surrounding_text_) ||
108 !GetTextInputClient()->GetSelectionRange(&selection_range_))
109 return;
110 }
111 if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
112 base::MessageLoop::current()->Quit();
113 }
114
OnTextInputStateChanged(const ui::TextInputClient * client)115 void TextInputTestHelper::OnTextInputStateChanged(
116 const ui::TextInputClient* client) {
117 }
118
WaitForTextInputStateChanged(ui::TextInputType expected_type)119 void TextInputTestHelper::WaitForTextInputStateChanged(
120 ui::TextInputType expected_type) {
121 CHECK_EQ(NO_WAIT, waiting_type_);
122 waiting_type_ = WAIT_ON_TEXT_INPUT_TYPE_CHANGED;
123 while (latest_text_input_type_ != expected_type)
124 content::RunMessageLoop();
125 waiting_type_ = NO_WAIT;
126 }
127
WaitForFocus()128 void TextInputTestHelper::WaitForFocus() {
129 CHECK_EQ(NO_WAIT, waiting_type_);
130 waiting_type_ = WAIT_ON_FOCUS;
131 while (focus_state_)
132 content::RunMessageLoop();
133 waiting_type_ = NO_WAIT;
134 }
135
WaitForBlur()136 void TextInputTestHelper::WaitForBlur() {
137 CHECK_EQ(NO_WAIT, waiting_type_);
138 waiting_type_ = WAIT_ON_BLUR;
139 while (!focus_state_)
140 content::RunMessageLoop();
141 waiting_type_ = NO_WAIT;
142 }
143
WaitForCaretBoundsChanged(const gfx::Rect & expected_caret_rect,const gfx::Rect & expected_composition_head)144 void TextInputTestHelper::WaitForCaretBoundsChanged(
145 const gfx::Rect& expected_caret_rect,
146 const gfx::Rect& expected_composition_head) {
147 waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED;
148 while (expected_caret_rect != caret_rect_ ||
149 expected_composition_head != composition_head_)
150 content::RunMessageLoop();
151 waiting_type_ = NO_WAIT;
152 }
153
WaitForSurroundingTextChanged(const base::string16 & expected_text,const gfx::Range & expected_selection)154 void TextInputTestHelper::WaitForSurroundingTextChanged(
155 const base::string16& expected_text,
156 const gfx::Range& expected_selection) {
157 waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED;
158 while (expected_text != surrounding_text_ ||
159 expected_selection != selection_range_)
160 content::RunMessageLoop();
161 waiting_type_ = NO_WAIT;
162 }
163
164 // static
ConvertRectFromString(const std::string & str,gfx::Rect * rect)165 bool TextInputTestHelper::ConvertRectFromString(const std::string& str,
166 gfx::Rect* rect) {
167 DCHECK(rect);
168 std::vector<std::string> rect_piece;
169 if (Tokenize(str, ",", &rect_piece) != 4UL)
170 return false;
171 int x, y, width, height;
172 if (!base::StringToInt(rect_piece[0], &x))
173 return false;
174 if (!base::StringToInt(rect_piece[1], &y))
175 return false;
176 if (!base::StringToInt(rect_piece[2], &width))
177 return false;
178 if (!base::StringToInt(rect_piece[3], &height))
179 return false;
180 *rect = gfx::Rect(x, y, width, height);
181 return true;
182 }
183
184 // static
ClickElement(const std::string & id,content::WebContents * tab)185 bool TextInputTestHelper::ClickElement(const std::string& id,
186 content::WebContents* tab) {
187 std::string coordinate;
188 if (!content::ExecuteScriptAndExtractString(
189 tab,
190 "textinput_helper.retrieveElementCoordinate('" + id + "')",
191 &coordinate))
192 return false;
193 gfx::Rect rect;
194 if (!ConvertRectFromString(coordinate, &rect))
195 return false;
196
197 blink::WebMouseEvent mouse_event;
198 mouse_event.type = blink::WebInputEvent::MouseDown;
199 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
200 mouse_event.x = rect.CenterPoint().x();
201 mouse_event.y = rect.CenterPoint().y();
202 mouse_event.clickCount = 1;
203 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
204
205 mouse_event.type = blink::WebInputEvent::MouseUp;
206 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
207 return true;
208 }
209
210 } // namespace chromeos
211