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