Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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 "content/browser/pointer_lock_browsertest.h" | |
| 6 | |
| 7 #include "content/browser/frame_host/frame_tree.h" | |
| 8 #include "content/browser/renderer_host/render_widget_host_impl.h" | |
| 9 #include "content/browser/renderer_host/render_widget_host_input_event_router.h" | |
| 10 #include "content/browser/web_contents/web_contents_impl.h" | |
| 11 #include "content/public/browser/web_contents_delegate.h" | |
| 12 #include "content/public/test/browser_test_utils.h" | |
| 13 #include "content/public/test/content_browser_test.h" | |
| 14 #include "content/public/test/content_browser_test_utils.h" | |
| 15 #include "content/public/test/test_utils.h" | |
| 16 #include "content/shell/browser/shell.h" | |
| 17 #include "content/test/content_browser_test_utils_internal.h" | |
| 18 #include "net/dns/mock_host_resolver.h" | |
| 19 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 20 | |
| 21 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) | |
|
Charlie Reis
2017/02/15 21:38:49
Any reason not to use USE_AURA? Might simplify th
lfg
2017/02/15 22:02:48
Done.
| |
| 22 #include "content/browser/renderer_host/render_widget_host_view_aura.h" | |
| 23 #include "content/browser/web_contents/web_contents_view_aura.h" | |
| 24 #endif | |
| 25 | |
| 26 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \ | |
| 27 defined(OS_MACOSX) | |
|
Charlie Reis
2017/02/15 21:38:49
Is there an easier way to do this in the build fil
lfg
2017/02/15 22:02:47
Done.
| |
| 28 | |
| 29 namespace content { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) | |
| 34 class MockRenderWidgetHostView : public RenderWidgetHostViewAura { | |
| 35 public: | |
| 36 MockRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack) | |
| 37 : RenderWidgetHostViewAura(host, is_guest_view_hack), | |
| 38 host_(RenderWidgetHostImpl::From(host)) {} | |
| 39 ~MockRenderWidgetHostView() override { | |
| 40 if (mouse_locked_) | |
| 41 UnlockMouse(); | |
| 42 } | |
| 43 | |
| 44 bool LockMouse() override { | |
| 45 mouse_locked_ = true; | |
| 46 | |
|
Charlie Reis
2017/02/15 21:38:49
nit: No need for blank line here.
lfg
2017/02/15 22:02:47
Done.
| |
| 47 return true; | |
| 48 } | |
| 49 | |
| 50 void UnlockMouse() override { | |
| 51 host_->LostMouseLock(); | |
| 52 mouse_locked_ = false; | |
| 53 } | |
| 54 | |
| 55 bool IsMouseLocked() override { return mouse_locked_; } | |
| 56 | |
| 57 bool HasFocus() const override { return true; } | |
| 58 | |
| 59 void OnWindowFocused(aura::Window* gained_focus, | |
| 60 aura::Window* lost_focus) override { | |
| 61 // Ignore window focus events. | |
| 62 } | |
| 63 | |
| 64 RenderWidgetHostImpl* host_; | |
| 65 }; | |
| 66 #endif | |
| 67 | |
| 68 } // namespace | |
| 69 | |
| 70 class MockPointerLockWebContentsDelegate : public WebContentsDelegate { | |
| 71 public: | |
| 72 MockPointerLockWebContentsDelegate() {} | |
| 73 ~MockPointerLockWebContentsDelegate() override {} | |
| 74 | |
| 75 void RequestToLockMouse(WebContents* web_contents, | |
| 76 bool user_gesture, | |
| 77 bool last_unlocked_by_target) override { | |
| 78 web_contents->GotResponseToLockMouseRequest(true); | |
| 79 } | |
| 80 | |
| 81 void LostMouseLock() override {} | |
| 82 }; | |
| 83 | |
| 84 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) | |
| 85 void InstallCreateHooksForPointerLockBrowserTests() { | |
| 86 WebContentsViewAura::InstallCreateHookForTests( | |
| 87 [](RenderWidgetHost* host, | |
| 88 bool is_guest_view_hack) -> RenderWidgetHostViewAura* { | |
| 89 return new MockRenderWidgetHostView(host, is_guest_view_hack); | |
| 90 }); | |
| 91 } | |
| 92 #endif | |
| 93 | |
| 94 class PointerLockBrowserTest : public ContentBrowserTest { | |
| 95 public: | |
| 96 PointerLockBrowserTest() {} | |
| 97 | |
| 98 protected: | |
| 99 void SetUpCommandLine(base::CommandLine* command_line) override { | |
| 100 IsolateAllSitesForTesting(command_line); | |
| 101 } | |
| 102 | |
| 103 void SetUp() override { | |
| 104 InstallCreateHooksForPointerLockBrowserTests(); | |
| 105 ContentBrowserTest::SetUp(); | |
| 106 } | |
| 107 | |
| 108 void SetUpOnMainThread() override { | |
| 109 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 110 SetupCrossSiteRedirector(embedded_test_server()); | |
| 111 ASSERT_TRUE(embedded_test_server()->Start()); | |
| 112 | |
| 113 web_contents()->SetDelegate(&web_contents_delegate_); | |
| 114 } | |
| 115 | |
| 116 WebContentsImpl* web_contents() const { | |
| 117 return static_cast<WebContentsImpl*>(shell()->web_contents()); | |
| 118 } | |
| 119 | |
| 120 private: | |
| 121 MockPointerLockWebContentsDelegate web_contents_delegate_; | |
| 122 }; | |
| 123 | |
| 124 IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLock) { | |
| 125 GURL main_url(embedded_test_server()->GetURL( | |
| 126 "a.com", "/cross_site_iframe_factory.html?a(b)")); | |
| 127 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | |
| 128 | |
| 129 FrameTreeNode* root = web_contents()->GetFrameTree()->root(); | |
| 130 FrameTreeNode* child = root->child_at(0); | |
| 131 | |
| 132 // Request a pointer lock on the root frame's body. | |
| 133 EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()")); | |
| 134 | |
| 135 // Root frame should have been granted pointer lock. | |
| 136 bool locked = false; | |
| 137 EXPECT_TRUE(ExecuteScriptAndExtractBool(root, | |
| 138 "window.domAutomationController.send(" | |
| 139 "document.pointerLockElement == " | |
| 140 "document.body);", | |
| 141 &locked)); | |
| 142 EXPECT_TRUE(locked); | |
| 143 | |
| 144 // Request a pointer lock on the child frame's body. | |
| 145 EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()")); | |
| 146 | |
| 147 // Child frame should not be granted pointer lock since the root frame has it. | |
| 148 EXPECT_TRUE(ExecuteScriptAndExtractBool(child, | |
| 149 "window.domAutomationController.send(" | |
| 150 "document.pointerLockElement == " | |
| 151 "document.body);", | |
| 152 &locked)); | |
| 153 EXPECT_FALSE(locked); | |
| 154 | |
| 155 // Release pointer lock on root frame. | |
| 156 EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()")); | |
| 157 | |
| 158 // Request a pointer lock on the child frame's body. | |
| 159 EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()")); | |
| 160 | |
| 161 // Child frame should have been granted pointer lock. | |
| 162 EXPECT_TRUE(ExecuteScriptAndExtractBool(child, | |
| 163 "window.domAutomationController.send(" | |
| 164 "document.pointerLockElement == " | |
| 165 "document.body);", | |
| 166 &locked)); | |
| 167 EXPECT_TRUE(locked); | |
| 168 } | |
| 169 | |
| 170 IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) { | |
| 171 GURL main_url(embedded_test_server()->GetURL( | |
| 172 "a.com", "/cross_site_iframe_factory.html?a(b)")); | |
| 173 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | |
| 174 | |
| 175 FrameTreeNode* root = web_contents()->GetFrameTree()->root(); | |
| 176 FrameTreeNode* child = root->child_at(0); | |
| 177 RenderWidgetHostInputEventRouter* router = | |
| 178 web_contents()->GetInputEventRouter(); | |
| 179 RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>( | |
| 180 root->current_frame_host()->GetView()); | |
| 181 RenderWidgetHostViewBase* child_view = static_cast<RenderWidgetHostViewBase*>( | |
| 182 child->current_frame_host()->GetView()); | |
| 183 | |
| 184 // Request a pointer lock on the root frame's body. | |
| 185 EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()")); | |
| 186 | |
| 187 // Root frame should have been granted pointer lock. | |
| 188 bool locked = false; | |
| 189 EXPECT_TRUE(ExecuteScriptAndExtractBool(root, | |
| 190 "window.domAutomationController.send(" | |
| 191 "document.pointerLockElement == " | |
| 192 "document.body);", | |
| 193 &locked)); | |
| 194 EXPECT_TRUE(locked); | |
| 195 | |
| 196 // Add a mouse move event listener to the root frame. | |
| 197 EXPECT_TRUE(ExecuteScript( | |
| 198 root, | |
| 199 "var x; var y; var mX; var mY; document.addEventListener('mousemove', " | |
| 200 "function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});")); | |
| 201 | |
| 202 blink::WebMouseEvent mouse_event(blink::WebInputEvent::MouseMove, | |
| 203 blink::WebInputEvent::NoModifiers, | |
| 204 blink::WebInputEvent::TimeStampForTesting); | |
| 205 mouse_event.x = 10; | |
| 206 mouse_event.y = 10; | |
| 207 mouse_event.movementX = 10; | |
| 208 mouse_event.movementY = 10; | |
|
Charlie Reis
2017/02/15 21:38:49
nit: Maybe set these to different values (e.g., 10
lfg
2017/02/15 22:02:47
Done.
| |
| 209 router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo()); | |
| 210 | |
| 211 // Make sure that the renderer handled the input event. | |
| 212 MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost()); | |
| 213 root_observer.Wait(); | |
| 214 | |
| 215 int x, y, movementX, movementY; | |
| 216 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 217 root, "window.domAutomationController.send(x);", &x)); | |
| 218 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 219 root, "window.domAutomationController.send(y);", &y)); | |
| 220 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 221 root, "window.domAutomationController.send(mX);", &movementX)); | |
| 222 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 223 root, "window.domAutomationController.send(mY);", &movementY)); | |
| 224 EXPECT_EQ(10, x); | |
| 225 EXPECT_EQ(10, y); | |
| 226 EXPECT_EQ(10, movementX); | |
| 227 EXPECT_EQ(10, movementY); | |
| 228 | |
| 229 // Release pointer lock on root frame. | |
| 230 EXPECT_TRUE(ExecuteScript(root, "document.exitPointerLock()")); | |
| 231 | |
| 232 // Request a pointer lock on the child frame's body. | |
| 233 EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()")); | |
| 234 | |
| 235 // Child frame should have been granted pointer lock. | |
| 236 EXPECT_TRUE(ExecuteScriptAndExtractBool(child, | |
| 237 "window.domAutomationController.send(" | |
| 238 "document.pointerLockElement == " | |
| 239 "document.body);", | |
| 240 &locked)); | |
| 241 EXPECT_TRUE(locked); | |
| 242 | |
| 243 // Add a mouse move event listener to the child frame. | |
| 244 EXPECT_TRUE(ExecuteScript( | |
| 245 child, | |
| 246 "var x; var y; var mX; var mY; document.addEventListener('mousemove', " | |
| 247 "function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});")); | |
| 248 | |
| 249 gfx::Point transformed_point; | |
| 250 root_view->TransformPointToCoordSpaceForView(gfx::Point(0, 0), child_view, | |
| 251 &transformed_point); | |
| 252 | |
| 253 mouse_event.x = -transformed_point.x() + 11; | |
| 254 mouse_event.y = -transformed_point.y() + 11; | |
| 255 mouse_event.movementX = 11; | |
| 256 mouse_event.movementY = 11; | |
| 257 // We use root_view intentionally as the RenderWidgetHostInputEventRouter is | |
| 258 // responsible for correctly routing the event to the child frame. | |
| 259 router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo()); | |
| 260 | |
| 261 // Make sure that the renderer handled the input event. | |
| 262 MainThreadFrameObserver child_observer(child_view->GetRenderWidgetHost()); | |
| 263 child_observer.Wait(); | |
| 264 | |
| 265 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 266 child, "window.domAutomationController.send(x);", &x)); | |
| 267 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 268 child, "window.domAutomationController.send(y);", &y)); | |
| 269 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 270 child, "window.domAutomationController.send(mX);", &movementX)); | |
| 271 EXPECT_TRUE(ExecuteScriptAndExtractInt( | |
| 272 child, "window.domAutomationController.send(mY);", &movementY)); | |
| 273 EXPECT_EQ(11, x); | |
| 274 EXPECT_EQ(11, y); | |
| 275 EXPECT_EQ(11, movementX); | |
| 276 EXPECT_EQ(11, movementY); | |
| 277 } | |
| 278 | |
| 279 } // namespace content | |
| 280 | |
| 281 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) || | |
| 282 // defined(OS_MACOSX) | |
| OLD | NEW |