Home | History | Annotate | Download | only in input_method
      1 // Copyright 2014 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 "base/logging.h"
      6 #include "base/metrics/histogram.h"
      7 #include "base/metrics/histogram_samples.h"
      8 #include "base/metrics/statistics_recorder.h"
      9 #include "base/test/histogram_tester.h"
     10 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
     11 #include "chrome/browser/chromeos/input_method/input_method_engine.h"
     12 #include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
     13 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
     14 #include "chromeos/ime/extension_ime_util.h"
     15 #include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "ui/base/ime/chromeos/mock_ime_input_context_handler.h"
     18 
     19 namespace chromeos {
     20 
     21 namespace input_method {
     22 namespace {
     23 
     24 const char kTestExtensionId[] = "mppnpdlheglhdfmldimlhpnegondlapf";
     25 const char kTestExtensionId2[] = "dmpipdbjkoajgdeppkffbjhngfckdloi";
     26 const char kTestImeComponentId[] = "test_engine_id";
     27 
     28 enum CallsBitmap {
     29   NONE = 0U,
     30   ACTIVATE = 1U,
     31   DEACTIVATED = 2U,
     32   ONFOCUS = 4U,
     33   ONBLUR = 8U
     34 };
     35 
     36 void InitInputMethod() {
     37   ComponentExtensionIMEManager* comp_ime_manager =
     38       new ComponentExtensionIMEManager;
     39   MockComponentExtIMEManagerDelegate* delegate =
     40       new MockComponentExtIMEManagerDelegate;
     41 
     42   ComponentExtensionIME ext1;
     43   ext1.id = kTestExtensionId;
     44 
     45   ComponentExtensionEngine ext1_engine1;
     46   ext1_engine1.engine_id = kTestImeComponentId;
     47   ext1_engine1.language_codes.push_back("en-US");
     48   ext1_engine1.layouts.push_back("us");
     49   ext1.engines.push_back(ext1_engine1);
     50 
     51   std::vector<ComponentExtensionIME> ime_list;
     52   ime_list.push_back(ext1);
     53   delegate->set_ime_list(ime_list);
     54   comp_ime_manager->Initialize(
     55       scoped_ptr<ComponentExtensionIMEManagerDelegate>(delegate).Pass());
     56 
     57   MockInputMethodManager* manager = new MockInputMethodManager;
     58   manager->SetComponentExtensionIMEManager(
     59       scoped_ptr<ComponentExtensionIMEManager>(comp_ime_manager).Pass());
     60   InitializeForTesting(manager);
     61 }
     62 
     63 class TestObserver : public InputMethodEngineInterface::Observer {
     64  public:
     65   TestObserver() : calls_bitmap_(NONE) {}
     66   virtual ~TestObserver() {}
     67 
     68   virtual void OnActivate(const std::string& engine_id) OVERRIDE {
     69     calls_bitmap_ |= ACTIVATE;
     70   }
     71   virtual void OnDeactivated(const std::string& engine_id) OVERRIDE {
     72     calls_bitmap_ |= DEACTIVATED;
     73   }
     74   virtual void OnFocus(
     75       const InputMethodEngineInterface::InputContext& context) OVERRIDE {
     76     calls_bitmap_ |= ONFOCUS;
     77   }
     78   virtual void OnBlur(int context_id) OVERRIDE {
     79     calls_bitmap_ |= ONBLUR;
     80   }
     81   virtual void OnKeyEvent(
     82       const std::string& engine_id,
     83       const InputMethodEngineInterface::KeyboardEvent& event,
     84       input_method::KeyEventHandle* key_data) OVERRIDE {}
     85   virtual void OnInputContextUpdate(
     86       const InputMethodEngineInterface::InputContext& context) OVERRIDE {}
     87   virtual void OnCandidateClicked(
     88       const std::string& engine_id,
     89       int candidate_id,
     90       InputMethodEngineInterface::MouseButtonEvent button) OVERRIDE {}
     91   virtual void OnMenuItemActivated(
     92       const std::string& engine_id,
     93       const std::string& menu_id) OVERRIDE {}
     94   virtual void OnSurroundingTextChanged(
     95       const std::string& engine_id,
     96       const std::string& text,
     97       int cursor_pos,
     98       int anchor_pos) OVERRIDE {}
     99   virtual void OnReset(const std::string& engine_id) OVERRIDE {}
    100 
    101   unsigned char GetCallsBitmapAndReset() {
    102     unsigned char ret = calls_bitmap_;
    103     calls_bitmap_ = NONE;
    104     return ret;
    105   }
    106 
    107  private:
    108   unsigned char calls_bitmap_;
    109 
    110   DISALLOW_COPY_AND_ASSIGN(TestObserver);
    111 };
    112 
    113 class InputMethodEngineTest :  public testing::Test {
    114  public:
    115   InputMethodEngineTest() : observer_(NULL), input_view_("inputview.html") {
    116     languages_.push_back("en-US");
    117     layouts_.push_back("us");
    118     InitInputMethod();
    119     IMEBridge::Initialize();
    120     mock_ime_input_context_handler_.reset(new MockIMEInputContextHandler());
    121     IMEBridge::Get()->SetInputContextHandler(
    122         mock_ime_input_context_handler_.get());
    123   }
    124   virtual ~InputMethodEngineTest() {
    125     IMEBridge::Get()->SetInputContextHandler(NULL);
    126     engine_.reset();
    127     Shutdown();
    128   }
    129 
    130  protected:
    131   void CreateEngine(bool whitelisted) {
    132     engine_.reset(new InputMethodEngine());
    133     observer_ = new TestObserver();
    134     scoped_ptr<InputMethodEngineInterface::Observer> observer_ptr(observer_);
    135     engine_->Initialize(observer_ptr.Pass(),
    136                         whitelisted ? kTestExtensionId : kTestExtensionId2);
    137   }
    138 
    139   void FocusIn(ui::TextInputType input_type) {
    140     IMEEngineHandlerInterface::InputContext input_context(
    141         input_type, ui::TEXT_INPUT_MODE_DEFAULT);
    142     engine_->FocusIn(input_context);
    143     IMEBridge::Get()->SetCurrentTextInputType(input_type);
    144   }
    145 
    146   scoped_ptr<InputMethodEngine> engine_;
    147 
    148   TestObserver* observer_;
    149   std::vector<std::string> languages_;
    150   std::vector<std::string> layouts_;
    151   GURL options_page_;
    152   GURL input_view_;
    153 
    154   scoped_ptr<MockIMEInputContextHandler> mock_ime_input_context_handler_;
    155 
    156  private:
    157   DISALLOW_COPY_AND_ASSIGN(InputMethodEngineTest);
    158 };
    159 
    160 }  // namespace
    161 
    162 TEST_F(InputMethodEngineTest, TestSwitching) {
    163   CreateEngine(false);
    164   // Enable/disable with focus.
    165   FocusIn(ui::TEXT_INPUT_TYPE_URL);
    166   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    167   engine_->Enable(kTestImeComponentId);
    168   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    169   engine_->Disable();
    170   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    171   // Enable/disable without focus.
    172   engine_->FocusOut();
    173   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    174   engine_->Enable(kTestImeComponentId);
    175   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    176   engine_->Disable();
    177   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    178   // Focus change when enabled.
    179   engine_->Enable(kTestImeComponentId);
    180   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    181   engine_->FocusOut();
    182   EXPECT_EQ(ONBLUR, observer_->GetCallsBitmapAndReset());
    183   // Focus change when disabled.
    184   engine_->Disable();
    185   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    186   FocusIn(ui::TEXT_INPUT_TYPE_TEXT);
    187   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    188   engine_->FocusOut();
    189   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    190 }
    191 
    192 TEST_F(InputMethodEngineTest, TestSwitching_Password_3rd_Party) {
    193   CreateEngine(false);
    194   // Enable/disable with focus.
    195   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
    196   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    197   engine_->Enable(kTestImeComponentId);
    198   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    199   engine_->Disable();
    200   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    201   // Focus change when enabled.
    202   engine_->Enable(kTestImeComponentId);
    203   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    204   engine_->FocusOut();
    205   EXPECT_EQ(ONBLUR, observer_->GetCallsBitmapAndReset());
    206   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
    207   EXPECT_EQ(ONFOCUS, observer_->GetCallsBitmapAndReset());
    208   engine_->Disable();
    209   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    210 }
    211 
    212 TEST_F(InputMethodEngineTest, TestSwitching_Password_Whitelisted) {
    213   CreateEngine(true);
    214   // Enable/disable with focus.
    215   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
    216   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
    217   engine_->Enable(kTestImeComponentId);
    218   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    219   engine_->Disable();
    220   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    221   // Focus change when enabled.
    222   engine_->Enable(kTestImeComponentId);
    223   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
    224   engine_->FocusOut();
    225   EXPECT_EQ(ONBLUR, observer_->GetCallsBitmapAndReset());
    226   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
    227   EXPECT_EQ(ONFOCUS, observer_->GetCallsBitmapAndReset());
    228   engine_->Disable();
    229   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
    230 }
    231 
    232 TEST_F(InputMethodEngineTest, TestHistograms) {
    233   CreateEngine(true);
    234   FocusIn(ui::TEXT_INPUT_TYPE_TEXT);
    235   engine_->Enable(kTestImeComponentId);
    236   std::vector<InputMethodEngineInterface::SegmentInfo> segments;
    237   engine_->SetComposition(
    238       engine_->GetCotextIdForTesting(), "test", 0, 0, 0, segments, NULL);
    239   std::string error;
    240   base::HistogramTester histograms;
    241   engine_->CommitText(1, "input", &error);
    242   engine_->CommitText(1,
    243                       "\xE5\x85\xA5\xE5\x8A\x9B",  // 2 UTF-8 characters
    244                       &error);
    245   engine_->CommitText(1, "input\xE5\x85\xA5\xE5\x8A\x9B", &error);
    246   histograms.ExpectTotalCount("InputMethod.CommitLength", 3);
    247   histograms.ExpectBucketCount("InputMethod.CommitLength", 5, 1);
    248   histograms.ExpectBucketCount("InputMethod.CommitLength", 2, 1);
    249   histograms.ExpectBucketCount("InputMethod.CommitLength", 7, 1);
    250 }
    251 
    252 }  // namespace input_method
    253 }  // namespace chromeos
    254