Fix crash on app list start page contents not existing.
[chromium-blink-merge.git] / content / renderer / input / input_handler_manager.cc
blobf266cb85342b12a1e2b6e3466bc558fd49fb8541
1 // Copyright 2013 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.
5 #include "content/renderer/input/input_handler_manager.h"
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/input/input_handler.h"
11 #include "content/renderer/input/input_event_filter.h"
12 #include "content/renderer/input/input_handler_manager_client.h"
13 #include "content/renderer/input/input_handler_wrapper.h"
14 #include "content/renderer/input/input_scroll_elasticity_controller.h"
15 #include "content/renderer/scheduler/renderer_scheduler.h"
17 using blink::WebInputEvent;
19 namespace content {
21 namespace {
23 InputEventAckState InputEventDispositionToAck(
24 InputHandlerProxy::EventDisposition disposition) {
25 switch (disposition) {
26 case InputHandlerProxy::DID_HANDLE:
27 return INPUT_EVENT_ACK_STATE_CONSUMED;
28 case InputHandlerProxy::DID_NOT_HANDLE:
29 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
30 case InputHandlerProxy::DROP_EVENT:
31 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
33 NOTREACHED();
34 return INPUT_EVENT_ACK_STATE_UNKNOWN;
37 } // namespace
39 InputHandlerManager::InputHandlerManager(
40 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
41 InputHandlerManagerClient* client,
42 RendererScheduler* renderer_scheduler)
43 : message_loop_proxy_(message_loop_proxy),
44 client_(client),
45 renderer_scheduler_(renderer_scheduler) {
46 DCHECK(client_);
47 client_->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent,
48 base::Unretained(this)));
51 InputHandlerManager::~InputHandlerManager() {
52 client_->SetBoundHandler(InputHandlerManagerClient::Handler());
55 void InputHandlerManager::AddInputHandler(
56 int routing_id,
57 const base::WeakPtr<cc::InputHandler>& input_handler,
58 const base::WeakPtr<RenderViewImpl>& render_view_impl) {
59 if (message_loop_proxy_->BelongsToCurrentThread()) {
60 AddInputHandlerOnCompositorThread(routing_id,
61 base::MessageLoopProxy::current(),
62 input_handler,
63 render_view_impl);
64 } else {
65 message_loop_proxy_->PostTask(
66 FROM_HERE,
67 base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread,
68 base::Unretained(this),
69 routing_id,
70 base::MessageLoopProxy::current(),
71 input_handler,
72 render_view_impl));
76 void InputHandlerManager::AddInputHandlerOnCompositorThread(
77 int routing_id,
78 const scoped_refptr<base::MessageLoopProxy>& main_loop,
79 const base::WeakPtr<cc::InputHandler>& input_handler,
80 const base::WeakPtr<RenderViewImpl>& render_view_impl) {
81 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
83 // The handler could be gone by this point if the compositor has shut down.
84 if (!input_handler)
85 return;
87 // The same handler may be registered for a route multiple times.
88 if (input_handlers_.count(routing_id) != 0)
89 return;
91 TRACE_EVENT1("input",
92 "InputHandlerManager::AddInputHandlerOnCompositorThread",
93 "result", "AddingRoute");
94 client_->DidAddInputHandler(routing_id, input_handler.get());
95 input_handlers_.add(routing_id,
96 make_scoped_ptr(new InputHandlerWrapper(this,
97 routing_id, main_loop, input_handler, render_view_impl)));
100 void InputHandlerManager::RemoveInputHandler(int routing_id) {
101 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
102 DCHECK(input_handlers_.contains(routing_id));
104 TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
106 client_->DidRemoveInputHandler(routing_id);
107 input_handlers_.erase(routing_id);
110 void InputHandlerManager::ObserveWheelEventAndResultOnMainThread(
111 int routing_id,
112 const blink::WebMouseWheelEvent& wheel_event,
113 const cc::InputHandlerScrollResult& scroll_result) {
114 message_loop_proxy_->PostTask(
115 FROM_HERE,
116 base::Bind(
117 &InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread,
118 base::Unretained(this), routing_id, wheel_event, scroll_result));
121 void InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread(
122 int routing_id,
123 const blink::WebMouseWheelEvent& wheel_event,
124 const cc::InputHandlerScrollResult& scroll_result) {
125 auto it = input_handlers_.find(routing_id);
126 if (it == input_handlers_.end())
127 return;
129 InputHandlerProxy* proxy = it->second->input_handler_proxy();
130 DCHECK(proxy->scroll_elasticity_controller());
131 proxy->scroll_elasticity_controller()->ObserveWheelEventAndResult(
132 wheel_event, scroll_result);
135 InputEventAckState InputHandlerManager::HandleInputEvent(
136 int routing_id,
137 const WebInputEvent* input_event,
138 ui::LatencyInfo* latency_info) {
139 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
141 auto it = input_handlers_.find(routing_id);
142 if (it == input_handlers_.end()) {
143 TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent",
144 "result", "NoInputHandlerFound");
145 // Oops, we no longer have an interested input handler..
146 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
149 InputHandlerProxy* proxy = it->second->input_handler_proxy();
150 return InputEventDispositionToAck(
151 proxy->HandleInputEventWithLatencyInfo(*input_event, latency_info));
154 void InputHandlerManager::DidOverscroll(int routing_id,
155 const DidOverscrollParams& params) {
156 client_->DidOverscroll(routing_id, params);
159 void InputHandlerManager::DidStopFlinging(int routing_id) {
160 client_->DidStopFlinging(routing_id);
163 void InputHandlerManager::DidReceiveInputEvent(
164 const blink::WebInputEvent& web_input_event) {
165 renderer_scheduler_->DidReceiveInputEventOnCompositorThread(web_input_event);
168 void InputHandlerManager::DidAnimateForInput() {
169 renderer_scheduler_->DidAnimateForInputOnCompositorThread();
172 } // namespace content