Home | History | Annotate | Download | only in plugin
      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_cros.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 kUsbLeftOsKey      = 0x0700e3;
     23 const unsigned int kUsbRightOsKey     = 0x0700e7;
     24 const unsigned int kUsbLeftAltKey     = 0x0700e2;
     25 const unsigned int kUsbRightAltKey    = 0x0700e6;
     26 
     27 const unsigned int kUsbFunctionKey    = 0x07003a;  // F1
     28 const unsigned int kUsbExtendedKey    = 0x070049;  // Insert
     29 const unsigned int kUsbOtherKey       = 0x07002b;  // Tab
     30 
     31 // A hardcoded value used to verify |lock_states| is preserved.
     32 static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_NUMLOCK;
     33 
     34 MATCHER_P2(EqualsKeyEvent, usb_keycode, pressed, "") {
     35   return arg.usb_keycode() == static_cast<uint32>(usb_keycode) &&
     36          arg.pressed() == pressed &&
     37          arg.lock_states() == kTestLockStates;
     38 }
     39 
     40 KeyEvent MakeKeyEvent(uint32 keycode, bool pressed) {
     41   KeyEvent event;
     42   event.set_usb_keycode(keycode);
     43   event.set_pressed(pressed);
     44   event.set_lock_states(kTestLockStates);
     45   return event;
     46 }
     47 
     48 void PressAndReleaseKey(InputStub* input_stub, uint32 keycode) {
     49   input_stub->InjectKeyEvent(MakeKeyEvent(keycode, true));
     50   input_stub->InjectKeyEvent(MakeKeyEvent(keycode, false));
     51 }
     52 
     53 MATCHER_P2(EqualsMouseMoveEvent, x, y, "") {
     54   return arg.x() == x && arg.y() == y;
     55 }
     56 
     57 MATCHER_P2(EqualsMouseButtonEvent, button, button_down, "") {
     58   return arg.button() == button && arg.button_down() == button_down;
     59 }
     60 
     61 static MouseEvent MakeMouseMoveEvent(int x, int y) {
     62   MouseEvent event;
     63   event.set_x(x);
     64   event.set_y(y);
     65   return event;
     66 }
     67 
     68 static MouseEvent MakeMouseButtonEvent(MouseEvent::MouseButton button,
     69                                        bool button_down) {
     70   MouseEvent event;
     71   event.set_button(button);
     72   event.set_button_down(button_down);
     73   return event;
     74 }
     75 
     76 }  // namespace
     77 
     78 // Test OSKey press/release.
     79 TEST(NormalizingInputFilterCrosTest, PressReleaseOsKey) {
     80   MockInputStub stub;
     81   scoped_ptr<protocol::InputFilter> processor(
     82       new NormalizingInputFilterCros(&stub));
     83 
     84   {
     85     InSequence s;
     86 
     87     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
     88     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false)));
     89 
     90     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightOsKey, true)));
     91     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightOsKey, false)));
     92   }
     93 
     94   // Inject press & release events for left & right OSKeys.
     95   PressAndReleaseKey(processor.get(), kUsbLeftOsKey);
     96   PressAndReleaseKey(processor.get(), kUsbRightOsKey);
     97 }
     98 
     99 // Test OSKey key repeat switches it to "modifying" mode.
    100 TEST(NormalizingInputFilterCrosTest, OSKeyRepeats) {
    101   MockInputStub stub;
    102   scoped_ptr<protocol::InputFilter> processor(
    103       new NormalizingInputFilterCros(&stub));
    104 
    105   {
    106     InSequence s;
    107 
    108     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    109     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    110     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    111   }
    112 
    113   // Inject a press and repeats for the left OSKey, but don't release it, and
    114   // verify that the repeats result in press events.
    115   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    116   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    117   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    118 }
    119 
    120 // Test OSKey press followed by function key press and release results in
    121 // just the function key events.
    122 TEST(NormalizingInputFilterCrosTest, FunctionKey) {
    123   MockInputStub stub;
    124   scoped_ptr<protocol::InputFilter> processor(
    125       new NormalizingInputFilterCros(&stub));
    126 
    127   {
    128     InSequence s;
    129 
    130     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbFunctionKey, true)));
    131     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbFunctionKey, false)));
    132   }
    133 
    134   // Hold the left OSKey while pressing & releasing the function key.
    135   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    136   PressAndReleaseKey(processor.get(), kUsbFunctionKey);
    137   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false));
    138 }
    139 
    140 // Test OSKey press followed by extended key press and release results in
    141 // just the function key events.
    142 TEST(NormalizingInputFilterCrosTest, ExtendedKey) {
    143   MockInputStub stub;
    144   scoped_ptr<protocol::InputFilter> processor(
    145       new NormalizingInputFilterCros(&stub));
    146 
    147   {
    148     InSequence s;
    149 
    150     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, true)));
    151     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, false)));
    152   }
    153 
    154   // Hold the left OSKey while pressing & releasing the function key.
    155   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    156   PressAndReleaseKey(processor.get(), kUsbExtendedKey);
    157   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false));
    158 }
    159 
    160 // Test OSKey press followed by non-function, non-extended key press and release
    161 // results in normal-looking sequence.
    162 TEST(NormalizingInputFilterCrosTest, OtherKey) {
    163   MockInputStub stub;
    164   scoped_ptr<protocol::InputFilter> processor(
    165       new NormalizingInputFilterCros(&stub));
    166 
    167   {
    168     InSequence s;
    169 
    170     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    171     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, true)));
    172     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, false)));
    173     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false)));
    174   }
    175 
    176   // Hold the left OSKey while pressing & releasing the function key.
    177   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    178   PressAndReleaseKey(processor.get(), kUsbOtherKey);
    179   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false));
    180 }
    181 
    182 // Test OSKey press followed by extended key press, then normal key press
    183 // results in OSKey switching to modifying mode for the normal key.
    184 TEST(NormalizingInputFilterCrosTest, ExtendedThenOtherKey) {
    185   MockInputStub stub;
    186   scoped_ptr<protocol::InputFilter> processor(
    187       new NormalizingInputFilterCros(&stub));
    188 
    189   {
    190     InSequence s;
    191 
    192     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, true)));
    193     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, false)));
    194     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    195     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, true)));
    196     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, false)));
    197     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false)));
    198   }
    199 
    200   // Hold the left OSKey while pressing & releasing the function key.
    201   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    202   PressAndReleaseKey(processor.get(), kUsbExtendedKey);
    203   PressAndReleaseKey(processor.get(), kUsbOtherKey);
    204   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false));
    205 }
    206 
    207 // Test OSKey press followed by mouse event puts the OSKey into modifying mode.
    208 TEST(NormalizingInputFilterCrosTest, MouseEvent) {
    209   MockInputStub stub;
    210   scoped_ptr<protocol::InputFilter> processor(
    211       new NormalizingInputFilterCros(&stub));
    212 
    213   {
    214     InSequence s;
    215 
    216     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true)));
    217     EXPECT_CALL(stub, InjectMouseEvent(EqualsMouseMoveEvent(0, 0)));
    218     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false)));
    219   }
    220 
    221   // Hold the left OSKey while pressing & releasing the function key.
    222   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true));
    223   processor->InjectMouseEvent(MakeMouseMoveEvent(0, 0));
    224   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false));
    225 }
    226 
    227 // Test left alt + right click is remapped to left alt + left click.
    228 TEST(NormalizingInputFilterCrosTest, LeftAltClick) {
    229   MockInputStub stub;
    230   scoped_ptr<protocol::InputFilter> processor(
    231       new NormalizingInputFilterCros(&stub));
    232 
    233   {
    234     InSequence s;
    235 
    236     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftAltKey, true)));
    237     EXPECT_CALL(stub, InjectMouseEvent(
    238         EqualsMouseButtonEvent(MouseEvent::BUTTON_LEFT, true)));
    239     EXPECT_CALL(stub, InjectMouseEvent(
    240         EqualsMouseButtonEvent(MouseEvent::BUTTON_LEFT, false)));
    241     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftAltKey, false)));
    242   }
    243 
    244   // Hold the left alt key while left-clicking. ChromeOS will rewrite this as
    245   // Alt+RightClick
    246   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftAltKey, true));
    247   processor->InjectMouseEvent(
    248       MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, true));
    249   processor->InjectMouseEvent(
    250       MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, false));
    251   processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftAltKey, false));
    252 }
    253 
    254 // Test that right alt + right click is unchanged.
    255 TEST(NormalizingInputFilterCrosTest, RightAltClick) {
    256   MockInputStub stub;
    257   scoped_ptr<protocol::InputFilter> processor(
    258       new NormalizingInputFilterCros(&stub));
    259 
    260   {
    261     InSequence s;
    262 
    263     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightAltKey, true)));
    264     EXPECT_CALL(stub, InjectMouseEvent(
    265         EqualsMouseButtonEvent(MouseEvent::BUTTON_RIGHT, true)));
    266     EXPECT_CALL(stub, InjectMouseEvent(
    267         EqualsMouseButtonEvent(MouseEvent::BUTTON_RIGHT, false)));
    268     EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightAltKey, false)));
    269   }
    270 
    271   // Hold the right alt key while left-clicking. ChromeOS will rewrite this as
    272   // Alt+RightClick
    273   processor->InjectKeyEvent(MakeKeyEvent(kUsbRightAltKey, true));
    274   processor->InjectMouseEvent(
    275       MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, true));
    276   processor->InjectMouseEvent(
    277       MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, false));
    278   processor->InjectKeyEvent(MakeKeyEvent(kUsbRightAltKey, false));
    279 }
    280 
    281 }  // namespace remoting
    282