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 19 namespace chromeos { 20 namespace { 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 30 void TextInputTestBase::SetUpInProcessBrowserTestFixture() { 31 ui::SetUpInputMethodFactoryForTesting(); 32 } 33 34 TextInputTestHelper::TextInputTestHelper() 35 : waiting_type_(NO_WAIT), 36 selection_range_(ui::Range::InvalidRange()), 37 focus_state_(false), 38 latest_text_input_type_(ui::TEXT_INPUT_TYPE_NONE) { 39 GetInputMethod()->AddObserver(this); 40 } 41 42 TextInputTestHelper::~TextInputTestHelper() { 43 GetInputMethod()->RemoveObserver(this); 44 } 45 46 string16 TextInputTestHelper::GetSurroundingText() const { 47 return surrounding_text_; 48 } 49 50 gfx::Rect TextInputTestHelper::GetCaretRect() const { 51 return caret_rect_; 52 } 53 54 gfx::Rect TextInputTestHelper::GetCompositionHead() const { 55 return composition_head_; 56 } 57 58 ui::Range TextInputTestHelper::GetSelectionRange() const { 59 return selection_range_; 60 } 61 62 bool TextInputTestHelper::GetFocusState() const { 63 return focus_state_; 64 } 65 66 ui::TextInputType TextInputTestHelper::GetTextInputType() const { 67 return latest_text_input_type_; 68 } 69 70 ui::TextInputClient* TextInputTestHelper::GetTextInputClient() const { 71 return GetInputMethod()->GetTextInputClient(); 72 } 73 74 void 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 81 void TextInputTestHelper::OnInputMethodDestroyed( 82 const ui::InputMethod* input_method) { 83 } 84 85 void TextInputTestHelper::OnFocus() { 86 focus_state_ = true; 87 if (waiting_type_ == WAIT_ON_FOCUS) 88 base::MessageLoop::current()->Quit(); 89 } 90 91 void TextInputTestHelper::OnBlur() { 92 focus_state_ = false; 93 if (waiting_type_ == WAIT_ON_BLUR) 94 base::MessageLoop::current()->Quit(); 95 } 96 97 void TextInputTestHelper::OnUntranslatedIMEMessage( 98 const base::NativeEvent& event) { 99 } 100 101 void TextInputTestHelper::OnCaretBoundsChanged( 102 const ui::TextInputClient* client) { 103 ui::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 112 void TextInputTestHelper::OnInputLocaleChanged() { 113 } 114 115 void TextInputTestHelper::OnTextInputStateChanged( 116 const ui::TextInputClient* client) { 117 } 118 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 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 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 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 154 void TextInputTestHelper::WaitForSurroundingTextChanged( 155 const string16& expected_text, 156 const ui::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 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 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 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