textinput_test_helper.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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::OnUntranslatedIMEMessage(
98  const base::NativeEvent& event) {
99}
100
101void TextInputTestHelper::OnCaretBoundsChanged(
102    const ui::TextInputClient* client) {
103  gfx::Range text_range;
104  if (!GetTextInputClient()->GetTextRange(&text_range) ||
105      !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text_) ||
106      !GetTextInputClient()->GetSelectionRange(&selection_range_))
107      return;
108  if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
109    base::MessageLoop::current()->Quit();
110}
111
112void TextInputTestHelper::OnInputLocaleChanged() {
113}
114
115void TextInputTestHelper::OnTextInputStateChanged(
116    const ui::TextInputClient* client) {
117}
118
119void 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
128void 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
136void 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
144void 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
154void TextInputTestHelper::WaitForSurroundingTextChanged(
155    const 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
165bool 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
185bool 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  WebKit::WebMouseEvent mouse_event;
198  mouse_event.type = WebKit::WebInputEvent::MouseDown;
199  mouse_event.button = WebKit::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 = WebKit::WebInputEvent::MouseUp;
206  tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
207  return true;
208}
209
210} // namespace chromeos
211