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 #include "remoting/client/plugin/normalizing_input_filter_mac.h" 6 7 #include "remoting/proto/event.pb.h" 8 #include "remoting/protocol/protocol_mock_objects.h" 9 #include "testing/gmock/include/gmock/gmock.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 using ::testing::InSequence; 13 using remoting::protocol::InputStub; 14 using remoting::protocol::KeyEvent; 15 using remoting::protocol::MockInputStub; 16 using remoting::protocol::MouseEvent; 17 18 namespace remoting { 19 20 namespace { 21 22 const unsigned int kUsbCapsLock = 0x070039; 23 const unsigned int kUsbLeftShift = 0x0700e1; 24 const unsigned int kUsbLeftOption = 0x0700e2; 25 const unsigned int kUsbLeftCmd = 0x0700e3; 26 const unsigned int kUsbRightCmd = 0x0700e7; 27 28 // A hardcoded value used to verify |lock_states| is preserved. 29 static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_NUMLOCK; 30 31 MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") { 32 return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && 33 arg.pressed() == pressed && 34 arg.lock_states() == kTestLockStates; 35 } 36 37 KeyEvent MakeKeyEvent(uint32 keycode, bool pressed) { 38 KeyEvent event; 39 event.set_usb_keycode(keycode); 40 event.set_pressed(pressed); 41 event.set_lock_states(kTestLockStates); 42 return event; 43 } 44 45 } // namespace 46 47 // Test CapsLock press/release. 48 TEST(NormalizingInputFilterMacTest, CapsLock) { 49 MockInputStub stub; 50 scoped_ptr<protocol::InputFilter> processor( 51 new NormalizingInputFilterMac(&stub)); 52 53 { 54 InSequence s; 55 56 // Verifies the generated CapsLock up/down events. 57 EXPECT_CALL(stub, InjectKeyEvent(EqualsUsbEvent(kUsbCapsLock, true))); 58 EXPECT_CALL(stub, InjectKeyEvent(EqualsUsbEvent(kUsbCapsLock, false))); 59 } 60 61 // Injecting a CapsLock down event with NumLock on. 62 processor->InjectKeyEvent(MakeKeyEvent(kUsbCapsLock, true)); 63 } 64 65 // Test without pressing command key. 66 TEST(NormalizingInputFilterMacTest, NoInjection) { 67 MockInputStub stub; 68 scoped_ptr<protocol::InputFilter> processor( 69 new NormalizingInputFilterMac(&stub)); 70 71 { 72 InSequence s; 73 74 EXPECT_CALL(stub, InjectKeyEvent( 75 EqualsUsbEvent('C', true))); 76 EXPECT_CALL(stub, InjectKeyEvent( 77 EqualsUsbEvent('C', false))); 78 } 79 80 // C Down and C Up. 81 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 82 processor->InjectKeyEvent(MakeKeyEvent('C', false)); 83 } 84 85 // Test pressing command key and other normal keys. 86 TEST(NormalizingInputFilterMacTest, CmdKey) { 87 MockInputStub stub; 88 scoped_ptr<protocol::InputFilter> processor( 89 new NormalizingInputFilterMac(&stub)); 90 91 { 92 InSequence s; 93 94 // Left command key. 95 EXPECT_CALL(stub, InjectKeyEvent( 96 EqualsUsbEvent(kUsbLeftCmd, true))); 97 EXPECT_CALL(stub, InjectKeyEvent( 98 EqualsUsbEvent('C', true))); 99 EXPECT_CALL(stub, InjectKeyEvent( 100 EqualsUsbEvent('C', false))); 101 EXPECT_CALL(stub, InjectKeyEvent( 102 EqualsUsbEvent(kUsbLeftCmd, false))); 103 104 // Right command key. 105 EXPECT_CALL(stub, InjectKeyEvent( 106 EqualsUsbEvent(kUsbRightCmd, true))); 107 EXPECT_CALL(stub, InjectKeyEvent( 108 EqualsUsbEvent('C', true))); 109 EXPECT_CALL(stub, InjectKeyEvent( 110 EqualsUsbEvent('C', false))); 111 EXPECT_CALL(stub, InjectKeyEvent( 112 EqualsUsbEvent(kUsbRightCmd, false))); 113 114 // More than one keys after CMD. 115 EXPECT_CALL(stub, InjectKeyEvent( 116 EqualsUsbEvent(kUsbRightCmd, true))); 117 EXPECT_CALL(stub, InjectKeyEvent( 118 EqualsUsbEvent('C', true))); 119 EXPECT_CALL(stub, InjectKeyEvent( 120 EqualsUsbEvent('V', true))); 121 EXPECT_CALL(stub, InjectKeyEvent( 122 EqualsUsbEvent('C', false))); 123 EXPECT_CALL(stub, InjectKeyEvent( 124 EqualsUsbEvent('V', false))); 125 EXPECT_CALL(stub, InjectKeyEvent( 126 EqualsUsbEvent(kUsbRightCmd, false))); 127 } 128 129 // Left command key. 130 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); 131 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 132 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); 133 134 // Right command key. 135 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); 136 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 137 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); 138 139 // More than one keys after CMD. 140 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); 141 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 142 processor->InjectKeyEvent(MakeKeyEvent('V', true)); 143 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); 144 } 145 146 // Test pressing command and special keys. 147 TEST(NormalizingInputFilterMacTest, SpecialKeys) { 148 MockInputStub stub; 149 scoped_ptr<protocol::InputFilter> processor( 150 new NormalizingInputFilterMac(&stub)); 151 152 { 153 InSequence s; 154 155 // Command + Shift. 156 EXPECT_CALL(stub, InjectKeyEvent( 157 EqualsUsbEvent(kUsbLeftCmd, true))); 158 EXPECT_CALL(stub, InjectKeyEvent( 159 EqualsUsbEvent(kUsbLeftShift, true))); 160 EXPECT_CALL(stub, InjectKeyEvent( 161 EqualsUsbEvent(kUsbLeftCmd, false))); 162 EXPECT_CALL(stub, InjectKeyEvent( 163 EqualsUsbEvent(kUsbLeftShift, false))); 164 165 // Command + Option. 166 EXPECT_CALL(stub, InjectKeyEvent( 167 EqualsUsbEvent(kUsbLeftCmd, true))); 168 EXPECT_CALL(stub, InjectKeyEvent( 169 EqualsUsbEvent(kUsbLeftOption, true))); 170 EXPECT_CALL(stub, InjectKeyEvent( 171 EqualsUsbEvent(kUsbLeftCmd, false))); 172 EXPECT_CALL(stub, InjectKeyEvent( 173 EqualsUsbEvent(kUsbLeftOption, false))); 174 } 175 176 // Command + Shift. 177 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); 178 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, true)); 179 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); 180 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, false)); 181 182 // Command + Option. 183 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); 184 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, true)); 185 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); 186 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, false)); 187 } 188 189 // Test pressing multiple command keys. 190 TEST(NormalizingInputFilterMacTest, MultipleCmdKeys) { 191 MockInputStub stub; 192 scoped_ptr<protocol::InputFilter> processor( 193 new NormalizingInputFilterMac(&stub)); 194 195 { 196 InSequence s; 197 198 EXPECT_CALL(stub, InjectKeyEvent( 199 EqualsUsbEvent(kUsbLeftCmd, true))); 200 EXPECT_CALL(stub, InjectKeyEvent( 201 EqualsUsbEvent('C', true))); 202 EXPECT_CALL(stub, InjectKeyEvent( 203 EqualsUsbEvent(kUsbRightCmd, true))); 204 EXPECT_CALL(stub, InjectKeyEvent( 205 EqualsUsbEvent('C', false))); 206 EXPECT_CALL(stub, InjectKeyEvent( 207 EqualsUsbEvent(kUsbLeftCmd, false))); 208 } 209 210 // Test multiple CMD keys at the same time. 211 // L CMD Down, C Down, R CMD Down, L CMD Up. 212 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); 213 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 214 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); 215 processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); 216 } 217 218 // Test press C key before command key. 219 TEST(NormalizingInputFilterMacTest, BeforeCmdKey) { 220 MockInputStub stub; 221 scoped_ptr<protocol::InputFilter> processor( 222 new NormalizingInputFilterMac(&stub)); 223 224 { 225 InSequence s; 226 227 EXPECT_CALL(stub, InjectKeyEvent( 228 EqualsUsbEvent('C', true))); 229 EXPECT_CALL(stub, InjectKeyEvent( 230 EqualsUsbEvent(kUsbRightCmd, true))); 231 EXPECT_CALL(stub, InjectKeyEvent( 232 EqualsUsbEvent('C', false))); 233 EXPECT_CALL(stub, InjectKeyEvent( 234 EqualsUsbEvent(kUsbRightCmd, false))); 235 EXPECT_CALL(stub, InjectKeyEvent( 236 EqualsUsbEvent('C', false))); 237 } 238 239 // Press C before command key. 240 processor->InjectKeyEvent(MakeKeyEvent('C', true)); 241 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); 242 processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); 243 processor->InjectKeyEvent(MakeKeyEvent('C', false)); 244 } 245 246 } // namespace remoting 247