OLD | NEW |
| (Empty) |
1 // Copyright 2016 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/renderer/mus/compositor_mus_connection.h" | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/macros.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/test/test_simple_task_runner.h" | |
12 #include "base/time/time.h" | |
13 #include "content/common/input/input_event_ack.h" | |
14 #include "content/common/input/input_event_ack_state.h" | |
15 #include "content/public/test/mock_render_thread.h" | |
16 #include "content/renderer/input/input_handler_manager.h" | |
17 #include "content/renderer/input/input_handler_manager_client.h" | |
18 #include "content/renderer/input/render_widget_input_handler.h" | |
19 #include "content/renderer/mus/render_widget_mus_connection.h" | |
20 #include "content/renderer/render_widget.h" | |
21 #include "content/test/fake_compositor_dependencies.h" | |
22 #include "mojo/public/cpp/bindings/interface_request.h" | |
23 #include "services/ui/public/cpp/tests/test_window.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | |
25 #include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_schedu
ler.h" | |
26 #include "ui/events/blink/did_overscroll_params.h" | |
27 #include "ui/events/event_utils.h" | |
28 #include "ui/events/mojo/event.mojom.h" | |
29 #include "ui/events/mojo/event_constants.mojom.h" | |
30 #include "ui/events/mojo/keyboard_codes.mojom.h" | |
31 | |
32 using ui::mojom::EventResult; | |
33 | |
34 namespace content { | |
35 | |
36 namespace { | |
37 | |
38 // Wrapper for the callback provided to | |
39 // CompositorMusConnection:OnWindowInputEvent. This tracks whether the it was | |
40 // called, along with the result. | |
41 class TestCallback : public base::RefCounted<TestCallback> { | |
42 public: | |
43 TestCallback() : called_(false), result_(EventResult::UNHANDLED) {} | |
44 | |
45 bool called() { return called_; } | |
46 EventResult result() { return result_; } | |
47 | |
48 void ResultCallback(EventResult result) { | |
49 called_ = true; | |
50 result_ = result; | |
51 } | |
52 | |
53 private: | |
54 friend class base::RefCounted<TestCallback>; | |
55 | |
56 ~TestCallback() {} | |
57 | |
58 bool called_; | |
59 EventResult result_; | |
60 | |
61 DISALLOW_COPY_AND_ASSIGN(TestCallback); | |
62 }; | |
63 | |
64 // Allows for overriding the behaviour of HandleInputEvent, to simulate input | |
65 // handlers which consume events before they are sent to the renderer. | |
66 class TestInputHandlerManager : public InputHandlerManager { | |
67 public: | |
68 TestInputHandlerManager( | |
69 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | |
70 InputHandlerManagerClient* client, | |
71 blink::scheduler::RendererScheduler* renderer_scheduler) | |
72 : InputHandlerManager(task_runner, client, nullptr, renderer_scheduler), | |
73 override_result_(false), | |
74 result_(InputEventAckState::INPUT_EVENT_ACK_STATE_UNKNOWN) {} | |
75 ~TestInputHandlerManager() override {} | |
76 | |
77 // Stops overriding the behaviour of HandleInputEvent | |
78 void ClearHandleInputEventOverride(); | |
79 | |
80 // Overrides the behaviour of HandleInputEvent, returing |result|. | |
81 void SetHandleInputEventResult(InputEventAckState result); | |
82 | |
83 // InputHandlerManager: | |
84 void HandleInputEvent(int routing_id, | |
85 blink::WebScopedInputEvent input_event, | |
86 const ui::LatencyInfo& latency_info, | |
87 const InputEventAckStateCallback& callback) override; | |
88 | |
89 private: | |
90 // If true InputHandlerManager::HandleInputEvent is not called. | |
91 bool override_result_; | |
92 | |
93 // The result to return in HandleInputEvent if |override_result_|. | |
94 InputEventAckState result_; | |
95 | |
96 DISALLOW_COPY_AND_ASSIGN(TestInputHandlerManager); | |
97 }; | |
98 | |
99 void TestInputHandlerManager::ClearHandleInputEventOverride() { | |
100 override_result_ = false; | |
101 } | |
102 | |
103 void TestInputHandlerManager::SetHandleInputEventResult( | |
104 InputEventAckState result) { | |
105 override_result_ = true; | |
106 result_ = result; | |
107 } | |
108 | |
109 void TestInputHandlerManager::HandleInputEvent( | |
110 int routing_id, | |
111 blink::WebScopedInputEvent input_event, | |
112 const ui::LatencyInfo& latency_info, | |
113 const InputEventAckStateCallback& callback) { | |
114 if (override_result_) { | |
115 callback.Run(result_, std::move(input_event), latency_info, nullptr); | |
116 return; | |
117 } | |
118 InputHandlerManager::HandleInputEvent(routing_id, std::move(input_event), | |
119 latency_info, callback); | |
120 } | |
121 | |
122 // Empty implementation of InputHandlerManagerClient. | |
123 class TestInputHandlerManagerClient : public InputHandlerManagerClient { | |
124 public: | |
125 TestInputHandlerManagerClient() {} | |
126 ~TestInputHandlerManagerClient() override{}; | |
127 | |
128 // InputHandlerManagerClient: | |
129 void SetInputHandlerManager( | |
130 InputHandlerManager* input_handler_manager) override {} | |
131 void RegisterRoutingID(int routing_id) override {} | |
132 void UnregisterRoutingID(int routing_id) override {} | |
133 void DidOverscroll(int routing_id, | |
134 const ui::DidOverscrollParams& params) override {} | |
135 void DidStopFlinging(int routing_id) override {} | |
136 void DispatchNonBlockingEventToMainThread( | |
137 int routing_id, | |
138 blink::WebScopedInputEvent event, | |
139 const ui::LatencyInfo& latency_info) override {} | |
140 | |
141 void NotifyInputEventHandled(int routing_id, | |
142 blink::WebInputEvent::Type type, | |
143 InputEventAckState ack_result) override {} | |
144 void ProcessRafAlignedInput(int routing_id) override {} | |
145 | |
146 private: | |
147 DISALLOW_COPY_AND_ASSIGN(TestInputHandlerManagerClient); | |
148 }; | |
149 | |
150 // Implementation of RenderWidget for testing, performs no initialization. | |
151 class TestRenderWidget : public RenderWidget { | |
152 public: | |
153 explicit TestRenderWidget(CompositorDependencies* compositor_deps) | |
154 : RenderWidget(1, | |
155 compositor_deps, | |
156 blink::WebPopupTypeNone, | |
157 ScreenInfo(), | |
158 true, | |
159 false, | |
160 false) {} | |
161 | |
162 protected: | |
163 ~TestRenderWidget() override {} | |
164 | |
165 private: | |
166 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget); | |
167 }; | |
168 | |
169 // Test override of RenderWidgetInputHandler to allow the control of | |
170 // HandleInputEvent. This will perform no actions on input until a | |
171 // RenderWidgetInputHandlerDelegate is set. Once set this will always ack | |
172 // received events. | |
173 class TestRenderWidgetInputHandler : public RenderWidgetInputHandler { | |
174 public: | |
175 TestRenderWidgetInputHandler(RenderWidget* render_widget); | |
176 ~TestRenderWidgetInputHandler() override {} | |
177 | |
178 void set_delegate(RenderWidgetInputHandlerDelegate* delegate) { | |
179 delegate_ = delegate; | |
180 } | |
181 void set_state(InputEventAckState state) { state_ = state; } | |
182 | |
183 // RenderWidgetInputHandler: | |
184 void HandleInputEvent(const blink::WebInputEvent& input_event, | |
185 const ui::LatencyInfo& latency_info, | |
186 InputEventDispatchType dispatch_type) override; | |
187 | |
188 private: | |
189 // The input delegate which receives event acks. | |
190 RenderWidgetInputHandlerDelegate* delegate_; | |
191 | |
192 // The result of input handling to send to |delegate_| during the ack. | |
193 InputEventAckState state_; | |
194 | |
195 DISALLOW_COPY_AND_ASSIGN(TestRenderWidgetInputHandler); | |
196 }; | |
197 | |
198 TestRenderWidgetInputHandler::TestRenderWidgetInputHandler( | |
199 RenderWidget* render_widget) | |
200 : RenderWidgetInputHandler(render_widget, render_widget), | |
201 delegate_(nullptr), | |
202 state_(InputEventAckState::INPUT_EVENT_ACK_STATE_UNKNOWN) {} | |
203 | |
204 void TestRenderWidgetInputHandler::HandleInputEvent( | |
205 const blink::WebInputEvent& input_event, | |
206 const ui::LatencyInfo& latency_info, | |
207 InputEventDispatchType dispatch_type) { | |
208 if (delegate_) { | |
209 std::unique_ptr<InputEventAck> ack(new InputEventAck( | |
210 InputEventAckSource::COMPOSITOR_THREAD, input_event.type(), state_)); | |
211 delegate_->OnInputEventAck(std::move(ack)); | |
212 } | |
213 } | |
214 | |
215 } // namespace | |
216 | |
217 // Test suite for CompositorMusConnection, this does not setup a full renderer | |
218 // environment. This does not establish a connection to a mus server, nor does | |
219 // it initialize one. | |
220 class CompositorMusConnectionTest : public testing::Test { | |
221 public: | |
222 CompositorMusConnectionTest() {} | |
223 ~CompositorMusConnectionTest() override {} | |
224 | |
225 // Returns a valid key event, so that it can be converted to a web event by | |
226 // CompositorMusConnection. | |
227 std::unique_ptr<ui::Event> GenerateKeyEvent(); | |
228 | |
229 // Calls CompositorMusConnection::OnWindowInputEvent. | |
230 void OnWindowInputEvent( | |
231 ui::Window* window, | |
232 const ui::Event& event, | |
233 std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback); | |
234 | |
235 // Confirms the state of pending tasks enqueued on each task runner, and runs | |
236 // until idle. | |
237 void VerifyAndRunQueues(bool main_task_runner_enqueued, | |
238 bool compositor_task_runner_enqueued); | |
239 | |
240 CompositorMusConnection* compositor_connection() { | |
241 return compositor_connection_.get(); | |
242 } | |
243 RenderWidgetMusConnection* connection() { return connection_; } | |
244 TestInputHandlerManager* input_handler_manager() { | |
245 return input_handler_manager_.get(); | |
246 } | |
247 TestRenderWidgetInputHandler* render_widget_input_handler() { | |
248 return render_widget_input_handler_.get(); | |
249 } | |
250 | |
251 // testing::Test: | |
252 void SetUp() override; | |
253 void TearDown() override; | |
254 | |
255 private: | |
256 // Mocks/Fakes of the testing environment. | |
257 TestInputHandlerManagerClient input_handler_manager_client_; | |
258 FakeCompositorDependencies compositor_dependencies_; | |
259 blink::scheduler::FakeRendererScheduler renderer_scheduler_; | |
260 MockRenderThread render_thread_; | |
261 scoped_refptr<TestRenderWidget> render_widget_; | |
262 mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request_; | |
263 | |
264 // Not owned, RenderWidgetMusConnection tracks in static state. Cleared during | |
265 // TearDown. | |
266 RenderWidgetMusConnection* connection_; | |
267 | |
268 // Test versions of task runners, see VerifyAndRunQueues to use in testing. | |
269 scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_; | |
270 scoped_refptr<base::TestSimpleTaskRunner> compositor_task_runner_; | |
271 | |
272 // Actual CompositorMusConnection for testing. | |
273 scoped_refptr<CompositorMusConnection> compositor_connection_; | |
274 | |
275 // Test implementations, to control input given to |compositor_connection_|. | |
276 std::unique_ptr<TestInputHandlerManager> input_handler_manager_; | |
277 std::unique_ptr<TestRenderWidgetInputHandler> render_widget_input_handler_; | |
278 | |
279 DISALLOW_COPY_AND_ASSIGN(CompositorMusConnectionTest); | |
280 }; | |
281 | |
282 std::unique_ptr<ui::Event> CompositorMusConnectionTest::GenerateKeyEvent() { | |
283 return std::unique_ptr<ui::Event>(new ui::KeyEvent( | |
284 ui::ET_KEY_PRESSED, ui::KeyboardCode::VKEY_A, ui::EF_NONE)); | |
285 } | |
286 | |
287 void CompositorMusConnectionTest::OnWindowInputEvent( | |
288 ui::Window* window, | |
289 const ui::Event& event, | |
290 std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback) { | |
291 compositor_connection_->OnWindowInputEvent(window, event, ack_callback); | |
292 } | |
293 | |
294 void CompositorMusConnectionTest::VerifyAndRunQueues( | |
295 bool main_task_runner_enqueued, | |
296 bool compositor_task_runner_enqueued) { | |
297 // Run through the enqueued actions. | |
298 EXPECT_EQ(main_task_runner_enqueued, main_task_runner_->HasPendingTask()); | |
299 main_task_runner_->RunUntilIdle(); | |
300 | |
301 EXPECT_EQ(compositor_task_runner_enqueued, | |
302 compositor_task_runner_->HasPendingTask()); | |
303 compositor_task_runner_->RunUntilIdle(); | |
304 } | |
305 | |
306 void CompositorMusConnectionTest::SetUp() { | |
307 testing::Test::SetUp(); | |
308 | |
309 main_task_runner_ = new base::TestSimpleTaskRunner(); | |
310 compositor_task_runner_ = new base::TestSimpleTaskRunner(); | |
311 | |
312 input_handler_manager_.reset(new TestInputHandlerManager( | |
313 compositor_task_runner_, &input_handler_manager_client_, | |
314 &renderer_scheduler_)); | |
315 | |
316 const int routing_id = 42; | |
317 compositor_connection_ = new CompositorMusConnection( | |
318 routing_id, main_task_runner_, compositor_task_runner_, | |
319 std::move(request_), input_handler_manager_.get()); | |
320 | |
321 // CompositorMusConnection attempts to create connection to the non-existant | |
322 // server. Clear that. | |
323 compositor_task_runner_->ClearPendingTasks(); | |
324 | |
325 render_widget_ = new TestRenderWidget(&compositor_dependencies_); | |
326 render_widget_input_handler_.reset( | |
327 new TestRenderWidgetInputHandler(render_widget_.get())); | |
328 connection_ = RenderWidgetMusConnection::GetOrCreate(routing_id); | |
329 connection_->SetInputHandler(render_widget_input_handler_.get()); | |
330 } | |
331 | |
332 void CompositorMusConnectionTest::TearDown() { | |
333 // Clear static state. | |
334 connection_->OnConnectionLost(); | |
335 testing::Test::TearDown(); | |
336 } | |
337 | |
338 // Tests that for events which the renderer will ack, yet not consume, that | |
339 // CompositorMusConnection consumes the ack during OnWindowInputEvent, and calls | |
340 // it with the correct state once processed. | |
341 TEST_F(CompositorMusConnectionTest, NotConsumed) { | |
342 TestRenderWidgetInputHandler* input_handler = render_widget_input_handler(); | |
343 input_handler->set_delegate(connection()); | |
344 input_handler->set_state( | |
345 InputEventAckState::INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | |
346 | |
347 ui::TestWindow test_window; | |
348 std::unique_ptr<ui::Event> event(GenerateKeyEvent()); | |
349 scoped_refptr<TestCallback> test_callback(new TestCallback); | |
350 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback( | |
351 new base::Callback<void(EventResult)>( | |
352 base::Bind(&TestCallback::ResultCallback, test_callback))); | |
353 | |
354 OnWindowInputEvent(&test_window, *event.get(), &ack_callback); | |
355 // OnWindowInputEvent is expected to clear the callback if it plans on | |
356 // handling the ack. | |
357 EXPECT_FALSE(ack_callback.get()); | |
358 | |
359 VerifyAndRunQueues(true, true); | |
360 | |
361 // The ack callback should have been called | |
362 EXPECT_TRUE(test_callback->called()); | |
363 EXPECT_EQ(EventResult::UNHANDLED, test_callback->result()); | |
364 } | |
365 | |
366 // Tests that for events which the renderer will ack, and consume, that | |
367 // CompositorMusConnection consumes the ack during OnWindowInputEvent, and calls | |
368 // it with the correct state once processed. | |
369 TEST_F(CompositorMusConnectionTest, Consumed) { | |
370 TestRenderWidgetInputHandler* input_handler = render_widget_input_handler(); | |
371 input_handler->set_delegate(connection()); | |
372 input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED); | |
373 | |
374 ui::TestWindow test_window; | |
375 std::unique_ptr<ui::Event> event(GenerateKeyEvent()); | |
376 scoped_refptr<TestCallback> test_callback(new TestCallback); | |
377 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback( | |
378 new base::Callback<void(EventResult)>( | |
379 base::Bind(&TestCallback::ResultCallback, test_callback))); | |
380 | |
381 OnWindowInputEvent(&test_window, *event.get(), &ack_callback); | |
382 // OnWindowInputEvent is expected to clear the callback if it plans on | |
383 // handling the ack. | |
384 EXPECT_FALSE(ack_callback.get()); | |
385 | |
386 VerifyAndRunQueues(true, true); | |
387 | |
388 // The ack callback should have been called | |
389 EXPECT_TRUE(test_callback->called()); | |
390 EXPECT_EQ(EventResult::HANDLED, test_callback->result()); | |
391 } | |
392 | |
393 // Tests that when the RenderWidgetInputHandler does not ack before a new event | |
394 // arrives, that only the most recent ack is fired. | |
395 TEST_F(CompositorMusConnectionTest, LostAck) { | |
396 ui::TestWindow test_window; | |
397 std::unique_ptr<ui::Event> event1(GenerateKeyEvent()); | |
398 scoped_refptr<TestCallback> test_callback1(new TestCallback); | |
399 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback1( | |
400 new base::Callback<void(EventResult)>( | |
401 base::Bind(&TestCallback::ResultCallback, test_callback1))); | |
402 | |
403 OnWindowInputEvent(&test_window, *event1.get(), &ack_callback1); | |
404 EXPECT_FALSE(ack_callback1.get()); | |
405 // When simulating the timeout the ack is never enqueued | |
406 VerifyAndRunQueues(true, false); | |
407 | |
408 // Setting a delegate will lead to the next event being acked. Having a | |
409 // cleared queue simulates the input handler timing out on an event. | |
410 TestRenderWidgetInputHandler* input_handler = render_widget_input_handler(); | |
411 input_handler->set_delegate(connection()); | |
412 input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED); | |
413 | |
414 std::unique_ptr<ui::Event> event2(GenerateKeyEvent()); | |
415 scoped_refptr<TestCallback> test_callback2(new TestCallback); | |
416 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback2( | |
417 new base::Callback<void(EventResult)>( | |
418 base::Bind(&TestCallback::ResultCallback, test_callback2))); | |
419 OnWindowInputEvent(&test_window, *event2.get(), &ack_callback2); | |
420 EXPECT_FALSE(ack_callback2.get()); | |
421 | |
422 VerifyAndRunQueues(true, true); | |
423 | |
424 // Only the most recent ack was called. | |
425 EXPECT_FALSE(test_callback1->called()); | |
426 EXPECT_TRUE(test_callback2->called()); | |
427 EXPECT_EQ(EventResult::HANDLED, test_callback2->result()); | |
428 } | |
429 | |
430 // Tests that when an input handler consumes the event, that | |
431 // CompositorMusConnection will consume the ack, but call as UNHANDLED. | |
432 TEST_F(CompositorMusConnectionTest, InputHandlerConsumes) { | |
433 input_handler_manager()->SetHandleInputEventResult( | |
434 InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED); | |
435 ui::TestWindow test_window; | |
436 std::unique_ptr<ui::Event> event(GenerateKeyEvent()); | |
437 scoped_refptr<TestCallback> test_callback(new TestCallback); | |
438 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback( | |
439 new base::Callback<void(EventResult)>( | |
440 base::Bind(&TestCallback::ResultCallback, test_callback))); | |
441 | |
442 OnWindowInputEvent(&test_window, *event.get(), &ack_callback); | |
443 | |
444 EXPECT_FALSE(ack_callback.get()); | |
445 VerifyAndRunQueues(false, false); | |
446 EXPECT_TRUE(test_callback->called()); | |
447 EXPECT_EQ(EventResult::UNHANDLED, test_callback->result()); | |
448 } | |
449 | |
450 // Tests that when the renderer will not ack an event, that | |
451 // CompositorMusConnection will consume the ack, but call as UNHANDLED. | |
452 TEST_F(CompositorMusConnectionTest, RendererWillNotSendAck) { | |
453 ui::TestWindow test_window; | |
454 ui::PointerEvent event( | |
455 ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_NONE, 0, 0, | |
456 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE), | |
457 ui::EventTimeForNow()); | |
458 | |
459 scoped_refptr<TestCallback> test_callback(new TestCallback); | |
460 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback( | |
461 new base::Callback<void(EventResult)>( | |
462 base::Bind(&TestCallback::ResultCallback, test_callback))); | |
463 | |
464 OnWindowInputEvent(&test_window, event, &ack_callback); | |
465 EXPECT_FALSE(ack_callback.get()); | |
466 | |
467 VerifyAndRunQueues(true, false); | |
468 EXPECT_TRUE(test_callback->called()); | |
469 EXPECT_EQ(EventResult::UNHANDLED, test_callback->result()); | |
470 } | |
471 | |
472 // Tests that when a touch event id provided, that CompositorMusConnection | |
473 // consumes the ack. | |
474 TEST_F(CompositorMusConnectionTest, TouchEventConsumed) { | |
475 TestRenderWidgetInputHandler* input_handler = render_widget_input_handler(); | |
476 input_handler->set_delegate(connection()); | |
477 input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED); | |
478 | |
479 ui::TestWindow test_window; | |
480 ui::PointerEvent event( | |
481 ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_NONE, 0, 0, | |
482 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH), | |
483 ui::EventTimeForNow()); | |
484 | |
485 scoped_refptr<TestCallback> test_callback(new TestCallback); | |
486 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback( | |
487 new base::Callback<void(EventResult)>( | |
488 base::Bind(&TestCallback::ResultCallback, test_callback))); | |
489 | |
490 OnWindowInputEvent(&test_window, event, &ack_callback); | |
491 // OnWindowInputEvent is expected to clear the callback if it plans on | |
492 // handling the ack. | |
493 EXPECT_FALSE(ack_callback.get()); | |
494 | |
495 VerifyAndRunQueues(true, true); | |
496 | |
497 // The ack callback should have been called | |
498 EXPECT_TRUE(test_callback->called()); | |
499 EXPECT_EQ(EventResult::HANDLED, test_callback->result()); | |
500 } | |
501 | |
502 } // namespace content | |
OLD | NEW |