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/window_event_dispatcher.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_ =
     77       client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
     78   if (waiting_type_ == WAIT_ON_TEXT_INPUT_TYPE_CHANGED)
     79     base::MessageLoop::current()->Quit();
     80 }
     81 
     82 void TextInputTestHelper::OnShowImeIfNeeded() {
     83 }
     84 
     85 void TextInputTestHelper::OnInputMethodDestroyed(
     86     const ui::InputMethod* input_method) {
     87 }
     88 
     89 void TextInputTestHelper::OnFocus() {
     90   focus_state_ = true;
     91   if (waiting_type_ == WAIT_ON_FOCUS)
     92     base::MessageLoop::current()->Quit();
     93 }
     94 
     95 void TextInputTestHelper::OnBlur() {
     96   focus_state_ = false;
     97   if (waiting_type_ == WAIT_ON_BLUR)
     98     base::MessageLoop::current()->Quit();
     99 }
    100 
    101 void TextInputTestHelper::OnCaretBoundsChanged(
    102     const ui::TextInputClient* client) {
    103   gfx::Range text_range;
    104   if (GetTextInputClient()) {
    105     if (!GetTextInputClient()->GetTextRange(&text_range) ||
    106         !GetTextInputClient()->GetTextFromRange(text_range,
    107                                                 &surrounding_text_) ||
    108         !GetTextInputClient()->GetSelectionRange(&selection_range_))
    109       return;
    110   }
    111   if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
    112     base::MessageLoop::current()->Quit();
    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 base::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
    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   blink::WebMouseEvent mouse_event;
    198   mouse_event.type = blink::WebInputEvent::MouseDown;
    199   mouse_event.button = blink::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 = blink::WebInputEvent::MouseUp;
    206   tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
    207   return true;
    208 }
    209 
    210 } // namespace chromeos
    211