Home | History | Annotate | Download | only in renderer
      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 <string>
      6 
      7 #include "content/common/view_messages.h"
      8 #include "content/public/test/render_view_test.h"
      9 #include "content/renderer/mouse_lock_dispatcher.h"
     10 #include "content/renderer/render_view_impl.h"
     11 #include "testing/gmock/include/gmock/gmock.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 using ::testing::_;
     15 
     16 namespace content {
     17 namespace {
     18 
     19 class MockLockTarget : public MouseLockDispatcher::LockTarget {
     20  public:
     21    MOCK_METHOD1(OnLockMouseACK, void(bool));
     22    MOCK_METHOD0(OnMouseLockLost, void());
     23    MOCK_METHOD1(HandleMouseLockedInputEvent,
     24                 bool(const blink::WebMouseEvent&));
     25 };
     26 
     27 // MouseLockDispatcher is a RenderViewObserver, and we test it by creating a
     28 // fixture containing a RenderViewImpl view() and interacting to that interface.
     29 class MouseLockDispatcherTest : public RenderViewTest {
     30  public:
     31   virtual void SetUp() {
     32     RenderViewTest::SetUp();
     33     route_id_ = view()->GetRoutingID();
     34     target_ = new MockLockTarget();
     35     alternate_target_ = new MockLockTarget();
     36   }
     37 
     38   virtual void TearDown() {
     39     RenderViewTest::TearDown();
     40     delete target_;
     41     delete alternate_target_;
     42   }
     43 
     44  protected:
     45   RenderViewImpl* view() { return static_cast<RenderViewImpl*>(view_); }
     46   MouseLockDispatcher* dispatcher() { return view()->mouse_lock_dispatcher(); }
     47   int route_id_;
     48   MockLockTarget* target_;
     49   MockLockTarget* alternate_target_;
     50 };
     51 
     52 }  // namespace
     53 
     54 // Test simple use of RenderViewImpl interface to WebKit for pointer lock.
     55 TEST_F(MouseLockDispatcherTest, BasicWebWidget) {
     56   // Start unlocked.
     57   EXPECT_FALSE(view()->isPointerLocked());
     58 
     59   // Lock.
     60   EXPECT_TRUE(view()->requestPointerLock());
     61   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
     62   EXPECT_TRUE(view()->isPointerLocked());
     63 
     64   // Unlock.
     65   view()->requestPointerUnlock();
     66   view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
     67   EXPECT_FALSE(view()->isPointerLocked());
     68 
     69   // Attempt a lock, and have it fail.
     70   EXPECT_TRUE(view()->requestPointerLock());
     71   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
     72   EXPECT_FALSE(view()->isPointerLocked());
     73 }
     74 
     75 // Test simple use of MouseLockDispatcher with a mock LockTarget.
     76 TEST_F(MouseLockDispatcherTest, BasicMockLockTarget) {
     77   ::testing::InSequence expect_calls_in_sequence;
     78   EXPECT_CALL(*target_, OnLockMouseACK(true));
     79   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_));
     80   EXPECT_CALL(*target_, OnMouseLockLost());
     81   EXPECT_CALL(*target_, OnLockMouseACK(false));
     82 
     83   // Start unlocked.
     84   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(NULL));
     85   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
     86 
     87   // Lock.
     88   EXPECT_TRUE(dispatcher()->LockMouse(target_));
     89   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
     90   EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
     91 
     92   // Receive mouse event.
     93   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
     94 
     95   // Unlock.
     96   dispatcher()->UnlockMouse(target_);
     97   view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
     98   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
     99 
    100   // Attempt a lock, and have it fail.
    101   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    102   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
    103   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
    104 }
    105 
    106 // Test deleting a target while it is in use by MouseLockDispatcher.
    107 TEST_F(MouseLockDispatcherTest, DeleteAndUnlock) {
    108   ::testing::InSequence expect_calls_in_sequence;
    109   EXPECT_CALL(*target_, OnLockMouseACK(true));
    110   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_)).Times(0);
    111   EXPECT_CALL(*target_, OnMouseLockLost()).Times(0);
    112 
    113   // Lock.
    114   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    115   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
    116   EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
    117 
    118   // Unlock, with a deleted target.
    119   // Don't receive mouse events or lock lost.
    120   dispatcher()->OnLockTargetDestroyed(target_);
    121   delete target_;
    122   target_ = NULL;
    123   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
    124   view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
    125   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
    126 }
    127 
    128 // Test deleting a target that is pending a lock request response.
    129 TEST_F(MouseLockDispatcherTest, DeleteWithPendingLockSuccess) {
    130   ::testing::InSequence expect_calls_in_sequence;
    131   EXPECT_CALL(*target_, OnLockMouseACK(true)).Times(0);
    132   EXPECT_CALL(*target_, OnMouseLockLost()).Times(0);
    133 
    134   // Lock request.
    135   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    136 
    137   // Before receiving response delete the target.
    138   dispatcher()->OnLockTargetDestroyed(target_);
    139   delete target_;
    140   target_ = NULL;
    141 
    142   // Lock response.
    143   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
    144 }
    145 
    146 // Test deleting a target that is pending a lock request failure response.
    147 TEST_F(MouseLockDispatcherTest, DeleteWithPendingLockFail) {
    148   ::testing::InSequence expect_calls_in_sequence;
    149   EXPECT_CALL(*target_, OnLockMouseACK(true)).Times(0);
    150   EXPECT_CALL(*target_, OnMouseLockLost()).Times(0);
    151 
    152   // Lock request.
    153   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    154 
    155   // Before receiving response delete the target.
    156   dispatcher()->OnLockTargetDestroyed(target_);
    157   delete target_;
    158   target_ = NULL;
    159 
    160   // Lock response.
    161   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, false));
    162 }
    163 
    164 // Test not receiving mouse events when a target is not locked.
    165 TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) {
    166   ::testing::InSequence expect_calls_in_sequence;
    167   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_)).Times(0);
    168   EXPECT_CALL(*target_, OnLockMouseACK(true));
    169   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_));
    170   EXPECT_CALL(*target_, OnMouseLockLost());
    171   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_)).Times(0);
    172 
    173   // (Don't) receive mouse event.
    174   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
    175 
    176   // Lock.
    177   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    178   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
    179   EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
    180 
    181   // Receive mouse event.
    182   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
    183 
    184   // Unlock.
    185   dispatcher()->UnlockMouse(target_);
    186   view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
    187   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
    188 
    189   // (Don't) receive mouse event.
    190   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
    191 }
    192 
    193 // Test multiple targets
    194 TEST_F(MouseLockDispatcherTest, MultipleTargets) {
    195   ::testing::InSequence expect_calls_in_sequence;
    196   EXPECT_CALL(*target_, OnLockMouseACK(true));
    197   EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_));
    198   EXPECT_CALL(*alternate_target_, HandleMouseLockedInputEvent(_)).Times(0);
    199   EXPECT_CALL(*target_, OnMouseLockLost()).Times(0);
    200   EXPECT_CALL(*alternate_target_, OnMouseLockLost()).Times(0);
    201   EXPECT_CALL(*target_, OnMouseLockLost());
    202 
    203   // Lock request for target.
    204   EXPECT_TRUE(dispatcher()->LockMouse(target_));
    205 
    206   // Fail attempt to lock alternate.
    207   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(alternate_target_));
    208   EXPECT_FALSE(dispatcher()->LockMouse(alternate_target_));
    209 
    210   // Lock completion for target.
    211   view()->OnMessageReceived(ViewMsg_LockMouse_ACK(route_id_, true));
    212   EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
    213 
    214   // Fail attempt to lock alternate.
    215   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(alternate_target_));
    216   EXPECT_FALSE(dispatcher()->LockMouse(alternate_target_));
    217 
    218   // Receive mouse event to only one target.
    219   dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent());
    220 
    221   // Unlock alternate target has no effect.
    222   dispatcher()->UnlockMouse(alternate_target_);
    223   EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_));
    224   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(alternate_target_));
    225 
    226   // Though the call to UnlockMouse should not unlock any target, we will
    227   // cause an unlock (as if e.g. user escaped mouse lock) and verify the
    228   // correct target is unlocked.
    229   view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_));
    230   EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_));
    231 }
    232 
    233 }  // namespace content
    234