| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/input_method/xkeyboard.h" | 5 #include "chrome/browser/chromeos/input_method/xkeyboard.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 } | 42 } |
| 43 | 43 |
| 44 InputMethodWhitelist whitelist_; | 44 InputMethodWhitelist whitelist_; |
| 45 InputMethodUtil util_; | 45 InputMethodUtil util_; |
| 46 scoped_ptr<XKeyboard> xkey_; | 46 scoped_ptr<XKeyboard> xkey_; |
| 47 | 47 |
| 48 MessageLoopForUI message_loop_; | 48 MessageLoopForUI message_loop_; |
| 49 content::TestBrowserThread ui_thread_; | 49 content::TestBrowserThread ui_thread_; |
| 50 }; | 50 }; |
| 51 | 51 |
| 52 // Returns a ModifierMap object that contains the following mapping: | |
| 53 // - kSearchKey is mapped to |search|. | |
| 54 // - kControl key is mapped to |control|. | |
| 55 // - kAlt key is mapped to |alt|. | |
| 56 ModifierMap GetMap(ModifierKey search, ModifierKey control, ModifierKey alt) { | |
| 57 ModifierMap modifier_key; | |
| 58 // Use the Search key as |search|. | |
| 59 modifier_key.push_back(ModifierKeyPair(kSearchKey, search)); | |
| 60 modifier_key.push_back(ModifierKeyPair(kControlKey, control)); | |
| 61 modifier_key.push_back(ModifierKeyPair(kAltKey, alt)); | |
| 62 return modifier_key; | |
| 63 } | |
| 64 | |
| 65 // Checks |modifier_map| and returns true if the following conditions are met: | |
| 66 // - kSearchKey is mapped to |search|. | |
| 67 // - kControl key is mapped to |control|. | |
| 68 // - kAlt key is mapped to |alt|. | |
| 69 bool CheckMap(const ModifierMap& modifier_map, | |
| 70 ModifierKey search, ModifierKey control, ModifierKey alt) { | |
| 71 ModifierMap::const_iterator begin = modifier_map.begin(); | |
| 72 ModifierMap::const_iterator end = modifier_map.end(); | |
| 73 if ((std::count(begin, end, ModifierKeyPair(kSearchKey, search)) == 1) && | |
| 74 (std::count(begin, end, | |
| 75 ModifierKeyPair(kControlKey, control)) == 1) && | |
| 76 (std::count(begin, end, ModifierKeyPair(kAltKey, alt)) == 1)) { | |
| 77 return true; | |
| 78 } | |
| 79 return false; | |
| 80 } | |
| 81 | |
| 82 // Returns true if X display is available. | 52 // Returns true if X display is available. |
| 83 bool DisplayAvailable() { | 53 bool DisplayAvailable() { |
| 84 return ui::GetXDisplay() ? true : false; | 54 return ui::GetXDisplay() ? true : false; |
| 85 } | 55 } |
| 86 | 56 |
| 87 } // namespace | 57 } // namespace |
| 88 | 58 |
| 89 // Tests CreateFullXkbLayoutName() function. | 59 // Tests CreateFullXkbLayoutName() function. |
| 90 TEST_F(XKeyboardTest, TestCreateFullXkbLayoutNameBasic) { | 60 TEST_F(XKeyboardTest, TestCreateFullXkbLayoutNameBasic) { |
| 91 // CreateFullXkbLayoutName should not accept an empty |layout_name|. | |
| 92 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName( | |
| 93 "", GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 94 | |
| 95 // CreateFullXkbLayoutName should not accept an empty ModifierMap. | |
| 96 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName( | |
| 97 "us", ModifierMap()).c_str()); | |
| 98 | |
| 99 // CreateFullXkbLayoutName should not accept an incomplete ModifierMap. | |
| 100 ModifierMap tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 101 tmp_map.pop_back(); | |
| 102 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 103 | |
| 104 // CreateFullXkbLayoutName should not accept redundant ModifierMaps. | |
| 105 tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 106 tmp_map.push_back(ModifierKeyPair(kSearchKey, kVoidKey)); // two search maps | |
| 107 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 108 tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 109 tmp_map.push_back(ModifierKeyPair(kControlKey, kVoidKey)); // two ctrls | |
| 110 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 111 tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 112 tmp_map.push_back(ModifierKeyPair(kAltKey, kVoidKey)); // two alts. | |
| 113 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 114 | |
| 115 // CreateFullXkbLayoutName should not accept invalid ModifierMaps. | |
| 116 tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 117 tmp_map.push_back(ModifierKeyPair(kVoidKey, kSearchKey)); // can't remap void | |
| 118 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 119 tmp_map = GetMap(kVoidKey, kVoidKey, kVoidKey); | |
| 120 tmp_map.push_back(ModifierKeyPair(kCapsLockKey, kSearchKey)); // ditto | |
| 121 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName("us", tmp_map).c_str()); | |
| 122 | |
| 123 // CreateFullXkbLayoutName can remap Search/Ctrl/Alt to CapsLock. | |
| 124 EXPECT_STREQ("us+chromeos(capslock_disabled_disabled)", | |
| 125 xkey_->CreateFullXkbLayoutName( | |
| 126 "us", | |
| 127 GetMap(kCapsLockKey, kVoidKey, kVoidKey)).c_str()); | |
| 128 EXPECT_STREQ("us+chromeos(disabled_capslock_disabled)", | |
| 129 xkey_->CreateFullXkbLayoutName( | |
| 130 "us", | |
| 131 GetMap(kVoidKey, kCapsLockKey, kVoidKey)).c_str()); | |
| 132 EXPECT_STREQ("us+chromeos(disabled_disabled_capslock)", | |
| 133 xkey_->CreateFullXkbLayoutName( | |
| 134 "us", | |
| 135 GetMap(kVoidKey, kVoidKey, kCapsLockKey)).c_str()); | |
| 136 | |
| 137 // CreateFullXkbLayoutName should not accept non-alphanumeric characters | 61 // CreateFullXkbLayoutName should not accept non-alphanumeric characters |
| 138 // except "()-_". | 62 // except "()-_". |
| 139 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName( | 63 EXPECT_EQ("", xkey_->CreateFullXkbLayoutName("us!")); |
| 140 "us!", GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | 64 EXPECT_EQ("", xkey_->CreateFullXkbLayoutName("us; /bin/sh")); |
| 141 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName( | 65 EXPECT_EQ("ab-c_12+chromeos(search_leftcontrol_leftalt_keepralt)", |
| 142 "us; /bin/sh", GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | 66 xkey_->CreateFullXkbLayoutName("ab-c_12")); |
| 143 EXPECT_STREQ("ab-c_12+chromeos(disabled_disabled_disabled)", | |
| 144 xkey_->CreateFullXkbLayoutName( | |
| 145 "ab-c_12", | |
| 146 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 147 | 67 |
| 148 // CreateFullXkbLayoutName should not accept upper-case ascii characters. | 68 // CreateFullXkbLayoutName should not accept upper-case ascii characters. |
| 149 EXPECT_STREQ("", xkey_->CreateFullXkbLayoutName( | 69 EXPECT_EQ("", xkey_->CreateFullXkbLayoutName("US")); |
| 150 "US", GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 151 | 70 |
| 152 // CreateFullXkbLayoutName should accept lower-case ascii characters. | 71 // CreateFullXkbLayoutName should accept lower-case ascii characters. |
| 153 for (int c = 'a'; c <= 'z'; ++c) { | 72 for (int c = 'a'; c <= 'z'; ++c) { |
| 154 EXPECT_STRNE("", xkey_->CreateFullXkbLayoutName( | 73 EXPECT_NE("", xkey_->CreateFullXkbLayoutName(std::string(3, c))); |
| 155 std::string(3, c), | |
| 156 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 157 } | 74 } |
| 158 | 75 |
| 159 // CreateFullXkbLayoutName should accept numbers. | 76 // CreateFullXkbLayoutName should accept numbers. |
| 160 for (int c = '0'; c <= '9'; ++c) { | 77 for (int c = '0'; c <= '9'; ++c) { |
| 161 EXPECT_STRNE("", xkey_->CreateFullXkbLayoutName( | 78 EXPECT_NE("", xkey_->CreateFullXkbLayoutName(std::string(3, c))); |
| 162 std::string(3, c), | |
| 163 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 164 } | 79 } |
| 165 | 80 |
| 166 // CreateFullXkbLayoutName should accept a layout with a variant name. | 81 // CreateFullXkbLayoutName should accept a layout with a variant name. |
| 167 EXPECT_STREQ("us(dvorak)+chromeos(disabled_disabled_disabled)", | 82 EXPECT_EQ("us(dvorak)+chromeos(search_leftcontrol_leftalt_keepralt)", |
| 168 xkey_->CreateFullXkbLayoutName( | 83 xkey_->CreateFullXkbLayoutName("us(dvorak)")); |
| 169 "us(dvorak)", | 84 EXPECT_EQ("jp+chromeos(search_leftcontrol_leftalt_keepralt)", |
| 170 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | 85 xkey_->CreateFullXkbLayoutName("jp")); |
| 171 EXPECT_STREQ("jp+chromeos(disabled_disabled_disabled)", | |
| 172 xkey_->CreateFullXkbLayoutName( | |
| 173 "jp", // does not use AltGr, therefore no _keepralt. | |
| 174 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 175 } | |
| 176 | |
| 177 TEST_F(XKeyboardTest, TestCreateFullXkbLayoutNameKeepCapsLock) { | |
| 178 EXPECT_STREQ("us(colemak)+chromeos(search_disabled_disabled)", | |
| 179 xkey_->CreateFullXkbLayoutName( | |
| 180 "us(colemak)", | |
| 181 // The 1st kVoidKey should be ignored. | |
| 182 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 183 EXPECT_STREQ("de(neo)+chromeos(search_leftcontrol_leftcontrol_keepralt)", | |
| 184 xkey_->CreateFullXkbLayoutName( | |
| 185 // The 1st kControlKey should be ignored. | |
| 186 "de(neo)", GetMap(kControlKey, | |
| 187 kControlKey, | |
| 188 kControlKey)).c_str()); | |
| 189 EXPECT_STREQ("gb(extd)+chromeos(disabled_disabled_disabled_keepralt)", | |
| 190 xkey_->CreateFullXkbLayoutName( | |
| 191 "gb(extd)", | |
| 192 GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 193 } | |
| 194 | |
| 195 TEST_F(XKeyboardTest, TestCreateFullXkbLayoutNameKeepAlt) { | |
| 196 EXPECT_STREQ("us(intl)+chromeos(disabled_disabled_disabled_keepralt)", | |
| 197 xkey_->CreateFullXkbLayoutName( | |
| 198 "us(intl)", GetMap(kVoidKey, kVoidKey, kVoidKey)).c_str()); | |
| 199 EXPECT_STREQ("kr(kr104)+" | |
| 200 "chromeos(leftcontrol_leftcontrol_leftcontrol_keepralt)", | |
| 201 xkey_->CreateFullXkbLayoutName( | |
| 202 "kr(kr104)", GetMap(kControlKey, | |
| 203 kControlKey, | |
| 204 kControlKey)).c_str()); | |
| 205 } | |
| 206 | |
| 207 // Tests if CreateFullXkbLayoutName and ExtractLayoutNameFromFullXkbLayoutName | |
| 208 // functions could handle all combinations of modifier remapping. | |
| 209 TEST_F(XKeyboardTest, TestCreateFullXkbLayoutNameModifierKeys) { | |
| 210 std::set<std::string> layouts; | |
| 211 for (int i = 0; i < static_cast<int>(kNumModifierKeys); ++i) { | |
| 212 for (int j = 0; j < static_cast<int>(kNumModifierKeys); ++j) { | |
| 213 for (int k = 0; k < static_cast<int>(kNumModifierKeys); ++k) { | |
| 214 const std::string layout = xkey_->CreateFullXkbLayoutName( | |
| 215 "us", GetMap(ModifierKey(i), ModifierKey(j), ModifierKey(k))); | |
| 216 // CreateFullXkbLayoutName should succeed (i.e. should not return "".) | |
| 217 EXPECT_STREQ("us+", layout.substr(0, 3).c_str()) | |
| 218 << "layout: " << layout; | |
| 219 // All 4*3*3 layouts should be different. | |
| 220 EXPECT_TRUE(layouts.insert(layout).second) << "layout: " << layout; | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 } | 86 } |
| 225 | 87 |
| 226 TEST_F(XKeyboardTest, TestSetCapsLockEnabled) { | 88 TEST_F(XKeyboardTest, TestSetCapsLockEnabled) { |
| 227 if (!DisplayAvailable()) { | 89 if (!DisplayAvailable()) { |
| 228 // Do not fail the test to allow developers to run unit_tests without an X | 90 // Do not fail the test to allow developers to run unit_tests without an X |
| 229 // server (e.g. via ssh). Note that both try bots and waterfall always have | 91 // server (e.g. via ssh). Note that both try bots and waterfall always have |
| 230 // an X server for running browser_tests. | 92 // an X server for running browser_tests. |
| 231 DVLOG(1) << "X server is not available. Skip the test."; | 93 DVLOG(1) << "X server is not available. Skip the test."; |
| 232 return; | 94 return; |
| 233 } | 95 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 | 177 |
| 316 // No-op SetLockedModifiers call. | 178 // No-op SetLockedModifiers call. |
| 317 xkey_->SetLockedModifiers(kDontChange, kDontChange); | 179 xkey_->SetLockedModifiers(kDontChange, kDontChange); |
| 318 EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled()); | 180 EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled()); |
| 319 EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled()); | 181 EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled()); |
| 320 | 182 |
| 321 // No-op GetLockedModifiers call. Confirm it does not crash. | 183 // No-op GetLockedModifiers call. Confirm it does not crash. |
| 322 xkey_->GetLockedModifiers(NULL, NULL); | 184 xkey_->GetLockedModifiers(NULL, NULL); |
| 323 } | 185 } |
| 324 | 186 |
| 325 TEST_F(XKeyboardTest, TestContainsModifierKeyAsReplacement) { | |
| 326 EXPECT_FALSE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 327 GetMap(kVoidKey, kVoidKey, kVoidKey), kCapsLockKey)); | |
| 328 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 329 GetMap(kCapsLockKey, kVoidKey, kVoidKey), kCapsLockKey)); | |
| 330 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 331 GetMap(kVoidKey, kCapsLockKey, kVoidKey), kCapsLockKey)); | |
| 332 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 333 GetMap(kVoidKey, kVoidKey, kCapsLockKey), kCapsLockKey)); | |
| 334 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 335 GetMap(kCapsLockKey, kCapsLockKey, kVoidKey), kCapsLockKey)); | |
| 336 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 337 GetMap(kCapsLockKey, kCapsLockKey, kCapsLockKey), kCapsLockKey)); | |
| 338 EXPECT_TRUE(XKeyboard::ContainsModifierKeyAsReplacement( | |
| 339 GetMap(kSearchKey, kVoidKey, kVoidKey), kSearchKey)); | |
| 340 } | |
| 341 | |
| 342 TEST_F(XKeyboardTest, TestSetAutoRepeatEnabled) { | 187 TEST_F(XKeyboardTest, TestSetAutoRepeatEnabled) { |
| 343 if (!DisplayAvailable()) { | 188 if (!DisplayAvailable()) { |
| 344 DVLOG(1) << "X server is not available. Skip the test."; | 189 DVLOG(1) << "X server is not available. Skip the test."; |
| 345 return; | 190 return; |
| 346 } | 191 } |
| 347 const bool state = XKeyboard::GetAutoRepeatEnabledForTesting(); | 192 const bool state = XKeyboard::GetAutoRepeatEnabledForTesting(); |
| 348 XKeyboard::SetAutoRepeatEnabled(!state); | 193 XKeyboard::SetAutoRepeatEnabled(!state); |
| 349 EXPECT_EQ(!state, XKeyboard::GetAutoRepeatEnabledForTesting()); | 194 EXPECT_EQ(!state, XKeyboard::GetAutoRepeatEnabledForTesting()); |
| 350 // Restore the initial state. | 195 // Restore the initial state. |
| 351 XKeyboard::SetAutoRepeatEnabled(state); | 196 XKeyboard::SetAutoRepeatEnabled(state); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 370 | 215 |
| 371 // Restore the initial state. | 216 // Restore the initial state. |
| 372 EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(rate)); | 217 EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(rate)); |
| 373 EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp)); | 218 EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp)); |
| 374 EXPECT_EQ(rate.initial_delay_in_ms, tmp.initial_delay_in_ms); | 219 EXPECT_EQ(rate.initial_delay_in_ms, tmp.initial_delay_in_ms); |
| 375 EXPECT_EQ(rate.repeat_interval_in_ms, tmp.repeat_interval_in_ms); | 220 EXPECT_EQ(rate.repeat_interval_in_ms, tmp.repeat_interval_in_ms); |
| 376 } | 221 } |
| 377 | 222 |
| 378 } // namespace input_method | 223 } // namespace input_method |
| 379 } // namespace chromeos | 224 } // namespace chromeos |
| OLD | NEW |