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.
6 #error This test requires brlapi.
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/screen_locker.h"
15 #include "chrome/browser/chromeos/login/screen_locker_tester.h"
16 #include "chrome/browser/chromeos/login/user_manager.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h"
19 #include "chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h"
20 #include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
21 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
22 #include "chrome/browser/extensions/extension_apitest.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chromeos/chromeos_switches.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"
31 using chromeos::ProfileHelper;
32 using chromeos::ScreenLocker;
33 using chromeos::UserManager;
34 using chromeos::test::ScreenLockerTester;
35 using content::BrowserThread;
37 namespace extensions {
39 namespace braille_display_private {
43 const char kTestUserName[] = "owner@invalid.domain";
47 // Data maintained by the mock BrlapiConnection. This data lives throughout
48 // a test, while the api implementation takes ownership of the connection
50 struct MockBrlapiConnectionData {
54 std::vector<std::string> written_content;
55 // List of brlapi key codes. A negative number makes the connection mock
56 // return an error from ReadKey.
57 std::deque<brlapi_keyCode_t> pending_keys;
58 // Causes a new display to appear to appear on disconnect, that is the
59 // display size doubles and the controller gets notified of a brltty
61 bool reappear_on_disconnect;
64 class MockBrlapiConnection : public BrlapiConnection {
66 explicit MockBrlapiConnection(MockBrlapiConnectionData* data)
68 virtual ConnectResult Connect(const OnDataReadyCallback& on_data_ready)
70 data_->connected = true;
71 on_data_ready_ = on_data_ready;
72 if (!data_->pending_keys.empty()) {
73 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
74 base::Bind(&MockBrlapiConnection::NotifyDataReady,
75 base::Unretained(this)));
77 return CONNECT_SUCCESS;
80 virtual void Disconnect() OVERRIDE {
81 data_->connected = false;
82 if (data_->reappear_on_disconnect) {
83 data_->display_size *= 2;
84 BrowserThread::PostTask(
85 BrowserThread::IO, FROM_HERE,
86 base::Bind(&BrailleControllerImpl::PokeSocketDirForTesting,
87 base::Unretained(BrailleControllerImpl::GetInstance())));
91 virtual bool Connected() OVERRIDE {
92 return data_->connected;
95 virtual brlapi_error_t* BrlapiError() OVERRIDE {
99 virtual std::string BrlapiStrError() OVERRIDE {
100 return data_->error.brlerrno != BRLAPI_ERROR_SUCCESS ? "Error" : "Success";
103 virtual bool GetDisplaySize(size_t* size) OVERRIDE {
104 *size = data_->display_size;
108 virtual bool WriteDots(const unsigned char* cells) OVERRIDE {
109 std::string written(reinterpret_cast<const char*>(cells),
110 data_->display_size);
111 data_->written_content.push_back(written);
115 virtual int ReadKey(brlapi_keyCode_t* key_code) OVERRIDE {
116 if (!data_->pending_keys.empty()) {
117 int queued_key_code = data_->pending_keys.front();
118 data_->pending_keys.pop_front();
119 if (queued_key_code < 0) {
120 data_->error.brlerrno = BRLAPI_ERROR_EOF;
121 return -1; // Signal error.
123 *key_code = queued_key_code;
132 void NotifyDataReady() {
133 on_data_ready_.Run();
134 if (!data_->pending_keys.empty()) {
135 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
136 base::Bind(&MockBrlapiConnection::NotifyDataReady,
137 base::Unretained(this)));
141 MockBrlapiConnectionData* data_;
142 OnDataReadyCallback on_data_ready_;
145 class BrailleDisplayPrivateApiTest : public ExtensionApiTest {
147 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
148 ExtensionApiTest::SetUpInProcessBrowserTestFixture();
149 connection_data_.connected = false;
150 connection_data_.display_size = 0;
151 connection_data_.error.brlerrno = BRLAPI_ERROR_SUCCESS;
152 connection_data_.reappear_on_disconnect = false;
153 BrailleControllerImpl::GetInstance()->SetCreateBrlapiConnectionForTesting(
155 &BrailleDisplayPrivateApiTest::CreateBrlapiConnection,
156 base::Unretained(this)));
157 DisableAccessibilityManagerBraille();
161 MockBrlapiConnectionData connection_data_;
163 // By default, don't let the accessibility manager interfere and
164 // steal events. Some tests override this to keep the normal behaviour
165 // of the accessibility manager.
166 virtual void DisableAccessibilityManagerBraille() {
167 chromeos::AccessibilityManager::SetBrailleControllerForTest(
168 &stub_braille_controller_);
172 scoped_ptr<BrlapiConnection> CreateBrlapiConnection() {
173 return scoped_ptr<BrlapiConnection>(
174 new MockBrlapiConnection(&connection_data_));
177 StubBrailleController stub_braille_controller_;
180 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, WriteDots) {
181 connection_data_.display_size = 11;
182 ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/write_dots"))
184 ASSERT_EQ(3U, connection_data_.written_content.size());
185 const std::string expected_content(connection_data_.display_size, '\0');
186 for (size_t i = 0; i < connection_data_.written_content.size(); ++i) {
187 ASSERT_EQ(std::string(
188 connection_data_.display_size,
189 static_cast<char>(i)),
190 connection_data_.written_content[i])
191 << "String " << i << " doesn't match";
195 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
196 connection_data_.display_size = 11;
197 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
198 BRLAPI_KEY_CMD_LNUP);
199 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
200 BRLAPI_KEY_CMD_LNDN);
201 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
202 BRLAPI_KEY_CMD_FWINLT);
203 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
204 BRLAPI_KEY_CMD_FWINRT);
205 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
207 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
209 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
210 BRLAPI_KEY_CMD_ROUTE | 5);
211 // Space (0) and all combinations of dots.
212 for (int i = 0; i < 256; ++i) {
213 connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
214 BRLAPI_KEY_CMD_PASSDOTS | i);
216 ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/key_events"));
219 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, DisplayStateChanges) {
220 connection_data_.display_size = 11;
221 connection_data_.pending_keys.push_back(-1);
222 connection_data_.reappear_on_disconnect = true;
223 ASSERT_TRUE(RunComponentExtensionTest(
224 "braille_display_private/display_state_changes"));
227 class BrailleDisplayPrivateAPIUserTest : public BrailleDisplayPrivateApiTest {
229 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
230 command_line->AppendSwitch(chromeos::switches::kLoginManager);
231 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
232 TestingProfile::kTestUserProfileDir);
235 class MockEventDelegate : public BrailleDisplayPrivateAPI::EventDelegate {
237 MockEventDelegate() : event_count_(0) {}
239 int GetEventCount() { return event_count_; }
241 virtual void BroadcastEvent(scoped_ptr<Event> event) OVERRIDE {
244 virtual bool HasListener() OVERRIDE { return true; }
250 MockEventDelegate* SetMockEventDelegate(BrailleDisplayPrivateAPI* api) {
251 MockEventDelegate* delegate = new MockEventDelegate();
252 api->SetEventDelegateForTest(
253 scoped_ptr<BrailleDisplayPrivateAPI::EventDelegate>(delegate).Pass());
257 void LockScreen(ScreenLockerTester* tester) {
258 ScreenLocker::Show();
259 tester->EmulateWindowManagerReady();
260 content::WindowedNotificationObserver lock_state_observer(
261 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
262 content::NotificationService::AllSources());
263 if (!tester->IsLocked())
264 lock_state_observer.Wait();
265 ASSERT_TRUE(tester->IsLocked());
268 void DismissLockScreen(ScreenLockerTester* tester) {
269 ScreenLocker::Hide();
270 content::WindowedNotificationObserver lock_state_observer(
271 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
272 content::NotificationService::AllSources());
273 if (tester->IsLocked())
274 lock_state_observer.Wait();
275 ASSERT_FALSE(tester->IsLocked());
279 virtual void DisableAccessibilityManagerBraille() OVERRIDE {
280 // Let the accessibility manager behave as usual for these tests.
284 IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateAPIUserTest,
285 KeyEventOnLockScreen) {
286 scoped_ptr<ScreenLockerTester> tester(ScreenLocker::GetTester());
288 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
289 UserManager::Get()->SessionStarted();
290 Profile* profile = ProfileManager::GetActiveUserProfile();
292 ProfileHelper::GetSigninProfile()->IsSameProfile(profile))
293 << ProfileHelper::GetSigninProfile()->GetDebugName() << " vs. "
294 << profile->GetDebugName();
296 // Create API and event delegate for sign in profile.
297 BrailleDisplayPrivateAPI signin_api(ProfileHelper::GetSigninProfile());
298 MockEventDelegate* signin_delegate = SetMockEventDelegate(&signin_api);
299 EXPECT_EQ(0, signin_delegate->GetEventCount());
300 // Create api and delegate for the logged in user.
301 BrailleDisplayPrivateAPI user_api(profile);
302 MockEventDelegate* user_delegate = SetMockEventDelegate(&user_api);
304 // Send key event to both profiles.
306 key_event.command = KEY_COMMAND_LINE_UP;
307 signin_api.OnKeyEvent(key_event);
308 user_api.OnKeyEvent(key_event);
309 EXPECT_EQ(0, signin_delegate->GetEventCount());
310 EXPECT_EQ(1, user_delegate->GetEventCount());
312 // Lock screen, and make sure that the key event goes to the
314 LockScreen(tester.get());
315 signin_api.OnKeyEvent(key_event);
316 user_api.OnKeyEvent(key_event);
317 EXPECT_EQ(1, signin_delegate->GetEventCount());
318 EXPECT_EQ(1, user_delegate->GetEventCount());
320 // Unlock screen, making sur ekey events go to the user profile again.
321 DismissLockScreen(tester.get());
322 signin_api.OnKeyEvent(key_event);
323 user_api.OnKeyEvent(key_event);
324 EXPECT_EQ(1, signin_delegate->GetEventCount());
325 EXPECT_EQ(2, user_delegate->GetEventCount());
328 } // namespace braille_display_private
330 } // namespace extensions