| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/chromeos/input_method/textinput_test_helper.h" | 
 |  | 
 | #include "base/run_loop.h" | 
 | #include "base/strings/string_number_conversions.h" | 
 | #include "base/strings/string_split.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/strings/utf_string_conversions.h" | 
 | #include "base/threading/platform_thread.h" | 
 | #include "chrome/browser/ui/browser.h" | 
 | #include "chrome/browser/ui/browser_window.h" | 
 | #include "chrome/test/base/interactive_test_utils.h" | 
 | #include "content/public/browser/render_view_host.h" | 
 | #include "content/public/browser/render_widget_host.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/test/browser_test_utils.h" | 
 | #include "content/public/test/test_utils.h" | 
 | #include "ui/aura/window_event_dispatcher.h" | 
 | #include "ui/aura/window_tree_host.h" | 
 | #include "ui/base/ime/init/input_method_factory.h" | 
 |  | 
 | namespace chromeos { | 
 |  | 
 | void TextInputTestBase::SetUpInProcessBrowserTestFixture() { | 
 |   ui::SetUpInputMethodFactoryForTesting(); | 
 | } | 
 |  | 
 | ui::InputMethod* TextInputTestBase::GetInputMethod() const { | 
 |   return browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod(); | 
 | } | 
 |  | 
 | TextInputTestHelper::TextInputTestHelper(ui::InputMethod* input_method) | 
 |     : waiting_type_(NO_WAIT), | 
 |       selection_range_(gfx::Range::InvalidRange()), | 
 |       focus_state_(false), | 
 |       latest_text_input_type_(ui::TEXT_INPUT_TYPE_NONE), | 
 |       input_method_(input_method) { | 
 |   input_method_->AddObserver(this); | 
 | } | 
 |  | 
 | TextInputTestHelper::~TextInputTestHelper() { | 
 |   input_method_->RemoveObserver(this); | 
 | } | 
 |  | 
 | base::string16 TextInputTestHelper::GetSurroundingText() const { | 
 |   return surrounding_text_; | 
 | } | 
 |  | 
 | gfx::Rect TextInputTestHelper::GetCaretRect() const { | 
 |   return caret_rect_; | 
 | } | 
 |  | 
 | gfx::Rect TextInputTestHelper::GetCompositionHead() const { | 
 |   return composition_head_; | 
 | } | 
 |  | 
 | gfx::Range TextInputTestHelper::GetSelectionRange() const { | 
 |   return selection_range_; | 
 | } | 
 |  | 
 | bool TextInputTestHelper::GetFocusState() const { | 
 |   return focus_state_; | 
 | } | 
 |  | 
 | ui::TextInputType TextInputTestHelper::GetTextInputType() const { | 
 |   return latest_text_input_type_; | 
 | } | 
 |  | 
 | ui::TextInputClient* TextInputTestHelper::GetTextInputClient() const { | 
 |   return input_method_->GetTextInputClient(); | 
 | } | 
 |  | 
 | void TextInputTestHelper::OnShowVirtualKeyboardIfEnabled() {} | 
 |  | 
 | void TextInputTestHelper::OnInputMethodDestroyed( | 
 |     const ui::InputMethod* input_method) { | 
 | } | 
 |  | 
 | void TextInputTestHelper::OnFocus() { | 
 |   focus_state_ = true; | 
 |   if (waiting_type_ == WAIT_ON_FOCUS) | 
 |     base::RunLoop::QuitCurrentWhenIdleDeprecated(); | 
 | } | 
 |  | 
 | void TextInputTestHelper::OnBlur() { | 
 |   focus_state_ = false; | 
 |   if (waiting_type_ == WAIT_ON_BLUR) | 
 |     base::RunLoop::QuitCurrentWhenIdleDeprecated(); | 
 | } | 
 |  | 
 | void TextInputTestHelper::OnCaretBoundsChanged( | 
 |     const ui::TextInputClient* client) { | 
 |   gfx::Range text_range; | 
 |   if (GetTextInputClient()) { | 
 |     if (!GetTextInputClient()->GetTextRange(&text_range) || | 
 |         !GetTextInputClient()->GetTextFromRange(text_range, | 
 |                                                 &surrounding_text_) || | 
 |         !GetTextInputClient()->GetEditableSelectionRange(&selection_range_)) | 
 |       return; | 
 |   } | 
 |   if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED) | 
 |     base::RunLoop::QuitCurrentWhenIdleDeprecated(); | 
 | } | 
 |  | 
 | void TextInputTestHelper::OnTextInputStateChanged( | 
 |     const ui::TextInputClient* client) { | 
 |   latest_text_input_type_ = | 
 |       client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; | 
 |   if (waiting_type_ == WAIT_ON_TEXT_INPUT_TYPE_CHANGED) | 
 |     base::RunLoop::QuitCurrentWhenIdleDeprecated(); | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForTextInputStateChanged( | 
 |     ui::TextInputType expected_type) { | 
 |   CHECK_EQ(NO_WAIT, waiting_type_); | 
 |   waiting_type_ = WAIT_ON_TEXT_INPUT_TYPE_CHANGED; | 
 |   while (latest_text_input_type_ != expected_type) | 
 |     content::RunMessageLoop(); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForFocus() { | 
 |   CHECK_EQ(NO_WAIT, waiting_type_); | 
 |   waiting_type_ = WAIT_ON_FOCUS; | 
 |   while (focus_state_) | 
 |     content::RunMessageLoop(); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForBlur() { | 
 |   CHECK_EQ(NO_WAIT, waiting_type_); | 
 |   waiting_type_ = WAIT_ON_BLUR; | 
 |   while (!focus_state_) | 
 |     content::RunMessageLoop(); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForCaretBoundsChanged( | 
 |     const gfx::Rect& expected_caret_rect, | 
 |     const gfx::Rect& expected_composition_head) { | 
 |   waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED; | 
 |   while (expected_caret_rect != caret_rect_ || | 
 |          expected_composition_head != composition_head_) | 
 |     content::RunMessageLoop(); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForSurroundingTextChanged( | 
 |     const base::string16& expected_text, | 
 |     const gfx::Range& expected_selection) { | 
 |   waiting_type_ = WAIT_ON_CARET_BOUNDS_CHANGED; | 
 |   while (expected_text != surrounding_text_ || | 
 |          expected_selection != selection_range_) | 
 |     content::RunMessageLoop(); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | void TextInputTestHelper::WaitForPassageOfTimeMillis(const int milliseconds) { | 
 |   CHECK_EQ(NO_WAIT, waiting_type_); | 
 |   waiting_type_ = WAIT_ON_PASSAGE_OF_TIME; | 
 |   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(milliseconds)); | 
 |   waiting_type_ = NO_WAIT; | 
 | } | 
 |  | 
 | // static | 
 | bool TextInputTestHelper::ConvertRectFromString(const std::string& str, | 
 |                                                 gfx::Rect* rect) { | 
 |   DCHECK(rect); | 
 |   std::vector<base::StringPiece> rect_piece = base::SplitStringPiece( | 
 |       str, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | 
 |   if (rect_piece.size() != 4UL) | 
 |     return false; | 
 |   int x, y, width, height; | 
 |   if (!base::StringToInt(rect_piece[0], &x)) | 
 |     return false; | 
 |   if (!base::StringToInt(rect_piece[1], &y)) | 
 |     return false; | 
 |   if (!base::StringToInt(rect_piece[2], &width)) | 
 |     return false; | 
 |   if (!base::StringToInt(rect_piece[3], &height)) | 
 |     return false; | 
 |   *rect = gfx::Rect(x, y, width, height); | 
 |   return true; | 
 | } | 
 |  | 
 | // static | 
 | bool TextInputTestHelper::ClickElement(const std::string& id, | 
 |                                        content::WebContents* tab) { | 
 |   std::string coordinate; | 
 |   if (!content::ExecuteScriptAndExtractString( | 
 |       tab, | 
 |       "textinput_helper.retrieveElementCoordinate('" + id + "')", | 
 |       &coordinate)) | 
 |     return false; | 
 |   gfx::Rect rect; | 
 |   if (!ConvertRectFromString(coordinate, &rect)) | 
 |     return false; | 
 |  | 
 |   blink::WebMouseEvent mouse_event( | 
 |       blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers, | 
 |       blink::WebInputEvent::GetStaticTimeStampForTests()); | 
 |   mouse_event.button = blink::WebMouseEvent::Button::kLeft; | 
 |   mouse_event.SetPositionInWidget(rect.CenterPoint().x(), | 
 |                                   rect.CenterPoint().y()); | 
 |   mouse_event.click_count = 1; | 
 |   tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event); | 
 |  | 
 |   mouse_event.SetType(blink::WebInputEvent::kMouseUp); | 
 |   tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event); | 
 |   return true; | 
 | } | 
 |  | 
 | } // namespace chromeos |