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 |