textinput_test_helper.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/root_window.h"
17#include "ui/base/ime/input_method_factory.h"
18
19namespace chromeos {
20namespace {
21ui::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
30void TextInputTestBase::SetUpInProcessBrowserTestFixture() {
31  ui::SetUpInputMethodFactoryForTesting();
32}
33
34TextInputTestHelper::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
42TextInputTestHelper::~TextInputTestHelper() {
43  GetInputMethod()->RemoveObserver(this);
44}
45
46string16 TextInputTestHelper::GetSurroundingText() const {
47  return surrounding_text_;
48}
49
50gfx::Rect TextInputTestHelper::GetCaretRect() const {
51  return caret_rect_;
52}
53
54gfx::Rect TextInputTestHelper::GetCompositionHead() const {
55  return composition_head_;
56}
57
58gfx::Range TextInputTestHelper::GetSelectionRange() const {
59  return selection_range_;
60}
61
62bool TextInputTestHelper::GetFocusState() const {
63  return focus_state_;
64}
65
66ui::TextInputType TextInputTestHelper::GetTextInputType() const {
67  return latest_text_input_type_;
68}
69
70ui::TextInputClient* TextInputTestHelper::GetTextInputClient() const {
71  return GetInputMethod()->GetTextInputClient();
72}
73
74void TextInputTestHelper::OnTextInputTypeChanged(
75    const ui::TextInputClient* client) {
76  latest_text_input_type_ = client->GetTextInputType();
77  if (waiting_type_ == WAIT_ON_TEXT_INPUT_TYPE_CHANGED)
78    base::MessageLoop::current()->Quit();
79}
80
81void TextInputTestHelper::OnInputMethodDestroyed(
82    const ui::InputMethod* input_method) {
83}
84
85void TextInputTestHelper::OnFocus() {
86  focus_state_ = true;
87  if (waiting_type_ == WAIT_ON_FOCUS)
88    base::MessageLoop::current()->Quit();
89}
90
91void TextInputTestHelper::OnBlur() {
92  focus_state_ = false;
93  if (waiting_type_ == WAIT_ON_BLUR)
94    base::MessageLoop::current()->Quit();
95}
96
97void TextInputTestHelper::OnCaretBoundsChanged(
98    const ui::TextInputClient* client) {
99  gfx::Range text_range;
100  if (!GetTextInputClient()->GetTextRange(&text_range) ||
101      !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text_) ||
102      !GetTextInputClient()->GetSelectionRange(&selection_range_))
103      return;
104  if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
105    base::MessageLoop::current()->Quit();
106}
107
108void TextInputTestHelper::OnTextInputStateChanged(
109    const ui::TextInputClient* client) {
110}
111
112void TextInputTestHelper::WaitForTextInputStateChanged(
113    ui::TextInputType expected_type) {
114  CHECK_EQ(NO_WAIT, waiting_type_);
115  waiting_type_ = WAIT_ON_TEXT_INPUT_TYPE_CHANGED;
116  while (latest_text_input_type_ != expected_type)
117    content::RunMessageLoop();
118  waiting_type_ = NO_WAIT;
119}
120
121void TextInputTestHelper::WaitForFocus() {
122  CHECK_EQ(NO_WAIT, waiting_type_);
123  waiting_type_ = WAIT_ON_FOCUS;
124  while (focus_state_)
125    content::RunMessageLoop();
126  waiting_type_ = NO_WAIT;
127}
128
129void TextInputTestHelper::WaitForBlur() {
130  CHECK_EQ(NO_WAIT, waiting_type_);
131  waiting_type_ = WAIT_ON_BLUR;
132  while (!focus_state_)
133    content::RunMessageLoop();
134  waiting_type_ = NO_WAIT;
135}
136
137void TextInputTestHelper::WaitForCaretBoundsChanged(
138    const gfx::Rect& expected_caret_rect,
139    const gfx::Rect& expected_composition_head) {
140  waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED;
141  while (expected_caret_rect != caret_rect_ ||
142         expected_composition_head != composition_head_)
143    content::RunMessageLoop();
144  waiting_type_ = NO_WAIT;
145}
146
147void TextInputTestHelper::WaitForSurroundingTextChanged(
148    const string16& expected_text,
149    const gfx::Range& expected_selection) {
150  waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED;
151  while (expected_text != surrounding_text_ ||
152         expected_selection != selection_range_)
153    content::RunMessageLoop();
154  waiting_type_ = NO_WAIT;
155}
156
157// static
158bool TextInputTestHelper::ConvertRectFromString(const std::string& str,
159                                                gfx::Rect* rect) {
160  DCHECK(rect);
161  std::vector<std::string> rect_piece;
162  if (Tokenize(str, ",", &rect_piece) != 4UL)
163    return false;
164  int x, y, width, height;
165  if (!base::StringToInt(rect_piece[0], &x))
166    return false;
167  if (!base::StringToInt(rect_piece[1], &y))
168    return false;
169  if (!base::StringToInt(rect_piece[2], &width))
170    return false;
171  if (!base::StringToInt(rect_piece[3], &height))
172    return false;
173  *rect = gfx::Rect(x, y, width, height);
174  return true;
175}
176
177// static
178bool TextInputTestHelper::ClickElement(const std::string& id,
179                                       content::WebContents* tab) {
180  std::string coordinate;
181  if (!content::ExecuteScriptAndExtractString(
182      tab,
183      "textinput_helper.retrieveElementCoordinate('" + id + "')",
184      &coordinate))
185    return false;
186  gfx::Rect rect;
187  if (!ConvertRectFromString(coordinate, &rect))
188    return false;
189
190  blink::WebMouseEvent mouse_event;
191  mouse_event.type = blink::WebInputEvent::MouseDown;
192  mouse_event.button = blink::WebMouseEvent::ButtonLeft;
193  mouse_event.x = rect.CenterPoint().x();
194  mouse_event.y = rect.CenterPoint().y();
195  mouse_event.clickCount = 1;
196  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
197
198  mouse_event.type = blink::WebInputEvent::MouseUp;
199  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
200  return true;
201}
202
203} // namespace chromeos
204