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