Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / braille_display_private / braille_display_private_apitest.cc
1 // Copyright 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 #ifndef USE_BRLAPI
6 #error This test requires brlapi.
7 #endif
8
9 #include <deque>
10
11 #include "base/bind.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
14 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
15 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h"
18 #include "chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h"
19 #include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
20 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
21 #include "chrome/browser/extensions/extension_apitest.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "components/user_manager/user_manager.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_service.h"
28 #include "content/public/test/test_utils.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using chromeos::ProfileHelper;
32 using chromeos::ScreenLocker;
33 using user_manager::UserManager;
34 using chromeos::test::ScreenLockerTester;
35 using content::BrowserThread;
36
37 namespace extensions {
38 namespace api {
39 namespace braille_display_private {
40
41 namespace {
42
43 const char kTestUserName[] = "owner@invalid.domain";
44
45 // Used to make ReadKeys return an error.
46 brlapi_keyCode_t kErrorKeyCode = BRLAPI_KEY_MAX;
47
48 }  // namespace
49
50 // Data maintained by the mock BrlapiConnection.  This data lives throughout
51 // a test, while the api implementation takes ownership of the connection
52 // itself.
53 struct MockBrlapiConnectionData {
54   bool connected;
55   size_t display_size;
56   brlapi_error_t error;
57   std::vector<std::string> written_content;
58   // List of brlapi key codes.  A negative number makes the connection mock
59   // return an error from ReadKey.
60   std::deque<brlapi_keyCode_t> pending_keys;
61   // Causes a new display to appear to appear on disconnect, that is the
62   // display size doubles and the controller gets notified of a brltty
63   // restart.
64   bool reappear_on_disconnect;
65 };
66
67 class MockBrlapiConnection : public BrlapiConnection {
68  public:
69   explicit MockBrlapiConnection(MockBrlapiConnectionData* data)
70       : data_(data) {}
71   virtual ConnectResult Connect(const OnDataReadyCallback& on_data_ready)
72       override {
73     data_->connected = true;
74     on_data_ready_ = on_data_ready;
75     if (!data_->pending_keys.empty()) {
76       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
77                               base::Bind(&MockBrlapiConnection::NotifyDataReady,
78                                         base::Unretained(this)));
79     }
80     return CONNECT_SUCCESS;
81   }
82
83   virtual void Disconnect() override {
84     data_->connected = false;
85     if (data_->reappear_on_disconnect) {
86       data_->display_size *= 2;
87       BrowserThread::PostTask(
88           BrowserThread::IO, FROM_HERE,
89           base::Bind(&BrailleControllerImpl::PokeSocketDirForTesting,
90                      base::Unretained(BrailleControllerImpl::GetInstance())));
91     }
92   }
93
94   virtual bool Connected() override {
95     return data_->connected;
96   }
97
98   virtual brlapi_error_t* BrlapiError() override {
99     return &data_->error;
100   }
101
102   virtual std::string BrlapiStrError() override {
103     return data_->error.brlerrno != BRLAPI_ERROR_SUCCESS ? "Error" : "Success";
104   }
105
106   virtual bool GetDisplaySize(size_t* size) override {
107     *size = data_->display_size;
108     return true;
109   }
110
111   virtual bool WriteDots(const unsigned char* cells) override {
112     std::string written(reinterpret_cast<const char*>(cells),
113                         data_->display_size);
114     data_->written_content.push_back(written);
115     return true;
116   }
117
118   virtual int ReadKey(brlapi_keyCode_t* key_code) override {
119     if (!data_->pending_keys.empty()) {
120       brlapi_keyCode_t queued_key_code = data_->pending_keys.front();
121       data_->pending_keys.pop_front();
122       if (queued_key_code == kErrorKeyCode) {
123         data_->error.brlerrno = BRLAPI_ERROR_EOF;
124         return -1;  // Signal error.
125       }
126       *key_code = queued_key_code;
127       return 1;
128     } else {
129       return 0;
130     }
131   }
132
133  private:
134
135   void NotifyDataReady() {
136     on_data_ready_.Run();
137     if (!data_->pending_keys.empty()) {
138       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
139                               base::Bind(&MockBrlapiConnection::NotifyDataReady,
140                                         base::Unretained(this)));
141     }
142   }
143
144   MockBrlapiConnectionData* data_;
145   OnDataReadyCallback on_data_ready_;
146 };
147
148 class BrailleDisplayPrivateApiTest : public ExtensionApiTest {
149  public:
150   virtual void SetUpInProcessBrowserTestFixture() override {
151     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
152     connection_data_.connected = false;
153     connection_data_.display_size = 0;
154     connection_data_.error.brlerrno = BRLAPI_ERROR_SUCCESS;
155     connection_data_.reappear_on_disconnect = false;
156     BrailleControllerImpl::GetInstance()->SetCreateBrlapiConnectionForTesting(
157         base::Bind(
158             &BrailleDisplayPrivateApiTest::CreateBrlapiConnection,
159             base::Unretained(this)));
160     DisableAccessibilityManagerBraille();
161   }
162
163  protected:
164   MockBrlapiConnectionData connection_data_;
165
166   // By default, don't let the accessibility manager interfere and
167   // steal events.  Some tests override this to keep the normal behaviour
168   // of the accessibility manager.
169   virtual void DisableAccessibilityManagerBraille() {
170     chromeos::AccessibilityManager::SetBrailleControllerForTest(
171         &stub_braille_controller_);
172   }
173
174  private:
175   scoped_ptr<BrlapiConnection> CreateBrlapiConnection() {
176     return scoped_ptr<BrlapiConnection>(
177         new MockBrlapiConnection(&connection_data_));
178   }
179
180   StubBrailleController stub_braille_controller_;
181 };
182
183 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, WriteDots) {
184   connection_data_.display_size = 11;
185   ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/write_dots"))
186       << message_;
187   ASSERT_EQ(3U, connection_data_.written_content.size());
188   const std::string expected_content(connection_data_.display_size, '\0');
189   for (size_t i = 0; i < connection_data_.written_content.size(); ++i) {
190     ASSERT_EQ(std::string(
191         connection_data_.display_size,
192         static_cast<char>(i)),
193                  connection_data_.written_content[i])
194         << "String " << i << " doesn't match";
195   }
196 }
197
198 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
199   connection_data_.display_size = 11;
200
201   // Braille navigation commands.
202   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
203                                           BRLAPI_KEY_CMD_LNUP);
204   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
205                                           BRLAPI_KEY_CMD_LNDN);
206   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
207                                           BRLAPI_KEY_CMD_FWINLT);
208   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
209                                           BRLAPI_KEY_CMD_FWINRT);
210   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
211                                           BRLAPI_KEY_CMD_TOP);
212   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
213                                           BRLAPI_KEY_CMD_BOT);
214   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
215                                           BRLAPI_KEY_CMD_ROUTE | 5);
216
217   // Braille display standard keyboard emulation.
218
219   // An ascii character.
220   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_SYM | 'A');
221   // A non-ascii 'latin1' character.  Small letter a with ring above.
222   connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_SYM | 0xE5);
223   // A non-latin1 Unicode character.  LATIN SMALL LETTER A WITH MACRON.
224   connection_data_.pending_keys.push_back(
225       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x100);
226   // A Unicode character outside the BMP.  CAT FACE WITH TEARS OF JOY.
227   // With anticipation for the first emoji-enabled braille display.
228   connection_data_.pending_keys.push_back(
229       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x1F639);
230   // Invalid Unicode character.
231   connection_data_.pending_keys.push_back(
232       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_UNICODE | 0x110000);
233
234   // Non-alphanumeric function keys.
235
236   // Backspace.
237   connection_data_.pending_keys.push_back(
238       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_SYM_BACKSPACE);
239   // Shift+Tab.
240   connection_data_.pending_keys.push_back(
241       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_FLG_SHIFT | BRLAPI_KEY_SYM_TAB);
242   // Alt+F3. (0-based).
243   connection_data_.pending_keys.push_back(
244       BRLAPI_KEY_TYPE_SYM | BRLAPI_KEY_FLG_META |
245       (BRLAPI_KEY_SYM_FUNCTION + 2));
246
247   // ctrl+dot1+dot2.
248   connection_data_.pending_keys.push_back(
249       BRLAPI_KEY_TYPE_CMD | BRLAPI_KEY_FLG_CONTROL | BRLAPI_KEY_CMD_PASSDOTS |
250       BRLAPI_DOT1 | BRLAPI_DOT2);
251
252   // Braille dot keys, all combinations including space (0).
253   for (int i = 0; i < 256; ++i) {
254     connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
255                                             BRLAPI_KEY_CMD_PASSDOTS | i);
256   }
257
258   ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/key_events"));
259 }
260
261 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, DisplayStateChanges) {
262   connection_data_.display_size = 11;
263   connection_data_.pending_keys.push_back(kErrorKeyCode);
264   connection_data_.reappear_on_disconnect = true;
265   ASSERT_TRUE(RunComponentExtensionTest(
266       "braille_display_private/display_state_changes"));
267 }
268
269 class BrailleDisplayPrivateAPIUserTest : public BrailleDisplayPrivateApiTest {
270  public:
271   virtual void SetUpCommandLine(CommandLine* command_line) override {
272     command_line->AppendSwitch(chromeos::switches::kLoginManager);
273     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
274                                     TestingProfile::kTestUserProfileDir);
275   }
276
277   class MockEventDelegate : public BrailleDisplayPrivateAPI::EventDelegate {
278    public:
279     MockEventDelegate() : event_count_(0) {}
280
281     int GetEventCount() { return event_count_; }
282
283     virtual void BroadcastEvent(scoped_ptr<Event> event) override {
284       ++event_count_;
285     }
286     virtual bool HasListener() override { return true; }
287
288    private:
289     int event_count_;
290   };
291
292   MockEventDelegate* SetMockEventDelegate(BrailleDisplayPrivateAPI* api) {
293     MockEventDelegate* delegate = new MockEventDelegate();
294     api->SetEventDelegateForTest(
295         scoped_ptr<BrailleDisplayPrivateAPI::EventDelegate>(delegate).Pass());
296     return delegate;
297   }
298
299   void LockScreen(ScreenLockerTester* tester) {
300     ScreenLocker::Show();
301     tester->EmulateWindowManagerReady();
302     content::WindowedNotificationObserver lock_state_observer(
303         chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
304         content::NotificationService::AllSources());
305     if (!tester->IsLocked())
306       lock_state_observer.Wait();
307     ASSERT_TRUE(tester->IsLocked());
308   }
309
310   void DismissLockScreen(ScreenLockerTester* tester) {
311     ScreenLocker::Hide();
312     content::WindowedNotificationObserver lock_state_observer(
313         chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
314         content::NotificationService::AllSources());
315     if (tester->IsLocked())
316       lock_state_observer.Wait();
317     ASSERT_FALSE(tester->IsLocked());
318   }
319
320  protected:
321   virtual void DisableAccessibilityManagerBraille() override {
322     // Let the accessibility manager behave as usual for these tests.
323   }
324 };
325
326 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateAPIUserTest,
327                        KeyEventOnLockScreen) {
328   scoped_ptr<ScreenLockerTester> tester(ScreenLocker::GetTester());
329   // Log in.
330   user_manager::UserManager::Get()->UserLoggedIn(
331       kTestUserName, kTestUserName, true);
332   user_manager::UserManager::Get()->SessionStarted();
333   Profile* profile = ProfileManager::GetActiveUserProfile();
334   ASSERT_FALSE(
335       ProfileHelper::GetSigninProfile()->IsSameProfile(profile))
336       << ProfileHelper::GetSigninProfile()->GetDebugName() << " vs. "
337       << profile->GetDebugName();
338
339   // Create API and event delegate for sign in profile.
340   BrailleDisplayPrivateAPI signin_api(ProfileHelper::GetSigninProfile());
341   MockEventDelegate* signin_delegate = SetMockEventDelegate(&signin_api);
342   EXPECT_EQ(0, signin_delegate->GetEventCount());
343   // Create api and delegate for the logged in user.
344   BrailleDisplayPrivateAPI user_api(profile);
345   MockEventDelegate* user_delegate = SetMockEventDelegate(&user_api);
346
347   // Send key event to both profiles.
348   KeyEvent key_event;
349   key_event.command = KEY_COMMAND_LINE_UP;
350   signin_api.OnBrailleKeyEvent(key_event);
351   user_api.OnBrailleKeyEvent(key_event);
352   EXPECT_EQ(0, signin_delegate->GetEventCount());
353   EXPECT_EQ(1, user_delegate->GetEventCount());
354
355   // Lock screen, and make sure that the key event goes to the
356   // signin profile.
357   LockScreen(tester.get());
358   signin_api.OnBrailleKeyEvent(key_event);
359   user_api.OnBrailleKeyEvent(key_event);
360   EXPECT_EQ(1, signin_delegate->GetEventCount());
361   EXPECT_EQ(1, user_delegate->GetEventCount());
362
363   // Unlock screen, making sur ekey events go to the user profile again.
364   DismissLockScreen(tester.get());
365   signin_api.OnBrailleKeyEvent(key_event);
366   user_api.OnBrailleKeyEvent(key_event);
367   EXPECT_EQ(1, signin_delegate->GetEventCount());
368   EXPECT_EQ(2, user_delegate->GetEventCount());
369 }
370
371 }  // namespace braille_display_private
372 }  // namespace api
373 }  // namespace extensions