Home | History | Annotate | Download | only in input_method
      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_(gfx::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 base::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 gfx::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::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 
    108 void TextInputTestHelper::OnTextInputStateChanged(
    109     const ui::TextInputClient* client) {
    110 }
    111 
    112 void 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 
    121 void 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 
    129 void 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 
    137 void 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 
    147 void TextInputTestHelper::WaitForSurroundingTextChanged(
    148     const base::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
    158 bool 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
    178 bool 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