Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Side by Side Diff: content/browser/pointer_lock_browsertest.cc

Issue 2592243002: Perform direct routing of mouse events when the pointer is locked. (Closed)
Patch Set: transform event, add tests Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698