Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / input_method / input_method_engine_unittest.cc
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 "chrome/browser/chromeos/input_method/input_method_configuration.h"
10 #include "chrome/browser/chromeos/input_method/input_method_engine.h"
11 #include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
12 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
13 #include "chromeos/ime/extension_ime_util.h"
14 #include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/base/ime/chromeos/mock_ime_input_context_handler.h"
17
18 namespace chromeos {
19
20 namespace input_method {
21 namespace {
22
23 const char kTestExtensionId[] = "mppnpdlheglhdfmldimlhpnegondlapf";
24 const char kTestExtensionId2[] = "dmpipdbjkoajgdeppkffbjhngfckdloi";
25 const char kTestImeEngineId[] = "test_engine_id";
26
27 const char* kHistogramNames[] = {
28     "InputMethod.Enable.test_engine_id", "InputMethod.Commit.test_engine_id",
29     "InputMethod.CommitCharacter.test_engine_id",
30 };
31
32 scoped_ptr<base::HistogramSamples> GetHistogramSamples(
33     const char* histogram_name) {
34   base::HistogramBase* histogram =
35       base::StatisticsRecorder::FindHistogram(histogram_name);
36   EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram);
37   return histogram->SnapshotSamples().Pass();
38 }
39
40 enum CallsBitmap {
41   NONE = 0U,
42   ACTIVATE = 1U,
43   DEACTIVATED = 2U,
44   ONFOCUS = 4U,
45   ONBLUR = 8U
46 };
47
48 void InitInputMethod() {
49   ComponentExtensionIMEManager* comp_ime_manager =
50       new ComponentExtensionIMEManager;
51   MockComponentExtIMEManagerDelegate* delegate =
52       new MockComponentExtIMEManagerDelegate;
53
54   ComponentExtensionIME ext1;
55   ext1.id = kTestExtensionId;
56
57   ComponentExtensionEngine ext1_engine1;
58   ext1_engine1.engine_id = kTestImeEngineId;
59   ext1_engine1.language_codes.push_back("en-US");
60   ext1_engine1.layouts.push_back("us");
61   ext1.engines.push_back(ext1_engine1);
62
63   std::vector<ComponentExtensionIME> ime_list;
64   ime_list.push_back(ext1);
65   delegate->set_ime_list(ime_list);
66   comp_ime_manager->Initialize(
67       scoped_ptr<ComponentExtensionIMEManagerDelegate>(delegate).Pass());
68
69   MockInputMethodManager* manager = new MockInputMethodManager;
70   manager->SetComponentExtensionIMEManager(
71       scoped_ptr<ComponentExtensionIMEManager>(comp_ime_manager).Pass());
72   InitializeForTesting(manager);
73 }
74
75 class TestObserver : public InputMethodEngineInterface::Observer {
76  public:
77   TestObserver() : calls_bitmap_(NONE) {}
78   virtual ~TestObserver() {}
79
80   virtual void OnActivate(const std::string& engine_id) OVERRIDE {
81     calls_bitmap_ |= ACTIVATE;
82   }
83   virtual void OnDeactivated(const std::string& engine_id) OVERRIDE {
84     calls_bitmap_ |= DEACTIVATED;
85   }
86   virtual void OnFocus(
87       const InputMethodEngineInterface::InputContext& context) OVERRIDE {
88     calls_bitmap_ |= ONFOCUS;
89   }
90   virtual void OnBlur(int context_id) OVERRIDE {
91     calls_bitmap_ |= ONBLUR;
92   }
93   virtual void OnKeyEvent(
94       const std::string& engine_id,
95       const InputMethodEngineInterface::KeyboardEvent& event,
96       input_method::KeyEventHandle* key_data) OVERRIDE {}
97   virtual void OnInputContextUpdate(
98       const InputMethodEngineInterface::InputContext& context) OVERRIDE {}
99   virtual void OnCandidateClicked(
100       const std::string& engine_id,
101       int candidate_id,
102       InputMethodEngineInterface::MouseButtonEvent button) OVERRIDE {}
103   virtual void OnMenuItemActivated(
104       const std::string& engine_id,
105       const std::string& menu_id) OVERRIDE {}
106   virtual void OnSurroundingTextChanged(
107       const std::string& engine_id,
108       const std::string& text,
109       int cursor_pos,
110       int anchor_pos) OVERRIDE {}
111   virtual void OnReset(const std::string& engine_id) OVERRIDE {}
112
113   unsigned char GetCallsBitmapAndReset() {
114     unsigned char ret = calls_bitmap_;
115     calls_bitmap_ = NONE;
116     return ret;
117   }
118
119  private:
120   unsigned char calls_bitmap_;
121
122   DISALLOW_COPY_AND_ASSIGN(TestObserver);
123 };
124
125 class InputMethodEngineTest :  public testing::Test {
126  public:
127   InputMethodEngineTest() : observer_(NULL), input_view_("inputview.html") {
128     languages_.push_back("en-US");
129     layouts_.push_back("us");
130     InitInputMethod();
131     IMEBridge::Initialize();
132     mock_ime_input_context_handler_.reset(new MockIMEInputContextHandler());
133     IMEBridge::Get()->SetInputContextHandler(
134         mock_ime_input_context_handler_.get());
135
136     base::StatisticsRecorder::Initialize();
137
138     for (size_t i = 0; i < arraysize(kHistogramNames); i++) {
139       base::Histogram::FactoryGet(
140           kHistogramNames[i], 0, 1000000, 50, base::HistogramBase::kNoFlags)
141           ->Add(0);
142       initial_histogram_samples_[i] =
143           GetHistogramSamples(kHistogramNames[i]).Pass();
144       initial_histogram_samples_map_[kHistogramNames[i]] =
145           initial_histogram_samples_[i].get();
146     }
147   }
148   virtual ~InputMethodEngineTest() {
149     IMEBridge::Get()->SetInputContextHandler(NULL);
150     engine_.reset();
151     Shutdown();
152   }
153
154  protected:
155   scoped_ptr<base::HistogramSamples> GetHistogramSamplesDelta(
156       const char* histogram_name) {
157     scoped_ptr<base::HistogramSamples> delta_samples(
158         GetHistogramSamples(histogram_name));
159     delta_samples->Subtract(*initial_histogram_samples_map_[histogram_name]);
160
161     return delta_samples.Pass();
162   }
163
164   void ExpectNewSample(const char* histogram_name,
165                        base::HistogramBase::Sample sample,
166                        int total_count,
167                        int sample_count) {
168     scoped_ptr<base::HistogramSamples> delta_samples(
169         GetHistogramSamplesDelta(histogram_name));
170     EXPECT_EQ(total_count, delta_samples->TotalCount());
171     EXPECT_EQ(sample_count, delta_samples->GetCount(sample));
172   }
173
174   void CreateEngine(bool whitelisted) {
175     engine_.reset(new InputMethodEngine());
176     observer_ = new TestObserver();
177     scoped_ptr<InputMethodEngineInterface::Observer> observer_ptr(observer_);
178     engine_->Initialize(observer_ptr.Pass(),
179                         "",
180                         whitelisted ? kTestExtensionId : kTestExtensionId2,
181                         kTestImeEngineId,
182                         languages_,
183                         layouts_,
184                         options_page_,
185                         input_view_);
186   }
187
188   void FocusIn(ui::TextInputType input_type) {
189     IMEEngineHandlerInterface::InputContext input_context(
190         input_type, ui::TEXT_INPUT_MODE_DEFAULT);
191     engine_->FocusIn(input_context);
192     IMEBridge::Get()->SetCurrentTextInputType(input_type);
193   }
194
195   scoped_ptr<InputMethodEngine> engine_;
196
197   TestObserver* observer_;
198   std::vector<std::string> languages_;
199   std::vector<std::string> layouts_;
200   GURL options_page_;
201   GURL input_view_;
202
203   scoped_ptr<base::HistogramSamples>
204       initial_histogram_samples_[arraysize(kHistogramNames)];
205   std::map<std::string, base::HistogramSamples*> initial_histogram_samples_map_;
206
207   scoped_ptr<MockIMEInputContextHandler> mock_ime_input_context_handler_;
208
209  private:
210   DISALLOW_COPY_AND_ASSIGN(InputMethodEngineTest);
211 };
212
213 }  // namespace
214
215 TEST_F(InputMethodEngineTest, TestSwitching) {
216   CreateEngine(false);
217   // Enable/disable with focus.
218   FocusIn(ui::TEXT_INPUT_TYPE_URL);
219   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
220   engine_->Enable();
221   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
222   engine_->Disable();
223   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
224   // Enable/disable without focus.
225   engine_->FocusOut();
226   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
227   engine_->Enable();
228   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
229   engine_->Disable();
230   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
231   // Focus change when enabled.
232   engine_->Enable();
233   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
234   engine_->FocusOut();
235   EXPECT_EQ(ONBLUR, observer_->GetCallsBitmapAndReset());
236   // Focus change when disabled.
237   engine_->Disable();
238   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
239   FocusIn(ui::TEXT_INPUT_TYPE_TEXT);
240   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
241   engine_->FocusOut();
242   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
243 }
244
245 TEST_F(InputMethodEngineTest, TestSwitching_Password_3rd_Party) {
246   CreateEngine(false);
247   // Enable/disable with focus.
248   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
249   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
250   engine_->Enable();
251   EXPECT_EQ(ACTIVATE, observer_->GetCallsBitmapAndReset());
252   engine_->Disable();
253   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
254   // Focus change when enabled.
255   engine_->Enable();
256   EXPECT_EQ(ACTIVATE, observer_->GetCallsBitmapAndReset());
257   engine_->FocusOut();
258   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
259   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
260   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
261   engine_->Disable();
262   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
263 }
264
265 TEST_F(InputMethodEngineTest, TestSwitching_Password_Whitelisted) {
266   CreateEngine(true);
267   // Enable/disable with focus.
268   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
269   EXPECT_EQ(NONE, observer_->GetCallsBitmapAndReset());
270   engine_->Enable();
271   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
272   engine_->Disable();
273   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
274   // Focus change when enabled.
275   engine_->Enable();
276   EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset());
277   engine_->FocusOut();
278   EXPECT_EQ(ONBLUR, observer_->GetCallsBitmapAndReset());
279   FocusIn(ui::TEXT_INPUT_TYPE_PASSWORD);
280   EXPECT_EQ(ONFOCUS, observer_->GetCallsBitmapAndReset());
281   engine_->Disable();
282   EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
283 }
284
285 TEST_F(InputMethodEngineTest, TestHistograms) {
286   CreateEngine(true);
287   FocusIn(ui::TEXT_INPUT_TYPE_TEXT);
288   engine_->Enable();
289   std::string error;
290   ExpectNewSample("InputMethod.Enable.test_engine_id", 1, 1, 1);
291   engine_->CommitText(1, "input", &error);
292   engine_->CommitText(1, "入力", &error);
293   engine_->CommitText(1, "input入力", &error);
294   ExpectNewSample("InputMethod.Commit.test_engine_id", 1, 3, 3);
295   ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 5, 3, 1);
296   ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 2, 3, 1);
297   ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 7, 3, 1);
298 }
299
300 }  // namespace input_method
301 }  // namespace chromeos