| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 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. | 
 |    4  | 
 |    5 #include "content/browser/renderer_host/input/buffered_input_router.h" | 
 |    6  | 
 |    7 #include "base/auto_reset.h" | 
 |    8 #include "content/browser/renderer_host/input/browser_input_event.h" | 
 |    9 #include "content/browser/renderer_host/input/input_ack_handler.h" | 
 |   10 #include "content/browser/renderer_host/input/input_queue.h" | 
 |   11 #include "content/browser/renderer_host/render_widget_host_impl.h" | 
 |   12 #include "content/common/input_messages.h" | 
 |   13 #include "content/common/view_messages.h" | 
 |   14 #include "content/public/browser/native_web_keyboard_event.h" | 
 |   15 #include "content/public/browser/user_metrics.h" | 
 |   16  | 
 |   17 using WebKit::WebGestureEvent; | 
 |   18 using WebKit::WebInputEvent; | 
 |   19 using WebKit::WebKeyboardEvent; | 
 |   20 using WebKit::WebMouseEvent; | 
 |   21 using WebKit::WebMouseWheelEvent; | 
 |   22 using WebKit::WebTouchEvent; | 
 |   23  | 
 |   24 namespace content { | 
 |   25  | 
 |   26 BufferedInputRouter::BufferedInputRouter(IPC::Sender* sender, | 
 |   27                                          InputRouterClient* client, | 
 |   28                                          InputAckHandler* ack_handler, | 
 |   29                                          int routing_id) | 
 |   30     : client_(client), | 
 |   31       ack_handler_(ack_handler), | 
 |   32       sender_(sender), | 
 |   33       routing_id_(routing_id), | 
 |   34       queued_gesture_count_(0), | 
 |   35       has_touch_handler_(false), | 
 |   36       queued_touch_count_(0), | 
 |   37       input_queue_override_(NULL), | 
 |   38       next_input_id_(1), | 
 |   39       in_flight_packet_id_(0) { | 
 |   40   input_queue_.reset(new InputQueue(this)); | 
 |   41 } | 
 |   42  | 
 |   43 BufferedInputRouter::~BufferedInputRouter() {} | 
 |   44  | 
 |   45 void BufferedInputRouter::Flush() { | 
 |   46   TRACE_EVENT0("input", "BufferedInputRouter::Flush"); | 
 |   47   DCHECK_EQ(0, in_flight_packet_id_); | 
 |   48   input_queue_->BeginFlush(); | 
 |   49 } | 
 |   50  | 
 |   51 bool BufferedInputRouter::SendInput(scoped_ptr<IPC::Message> message) { | 
 |   52   DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); | 
 |   53   DCHECK(message->type() != InputMsg_HandleEventPacket::ID); | 
 |   54   DCHECK(message->type() != InputMsg_HandleInputEvent::ID); | 
 |   55   input_queue_->QueueEvent(BrowserInputEvent::Create( | 
 |   56       NextInputID(), IPCInputEventPayload::Create(message.Pass()), this)); | 
 |   57   return true; | 
 |   58 } | 
 |   59  | 
 |   60 void BufferedInputRouter::SendMouseEvent( | 
 |   61     const MouseEventWithLatencyInfo& mouse_event) { | 
 |   62   if (!client_->OnSendMouseEvent(mouse_event)) | 
 |   63     return; | 
 |   64   // TODO(jdduke): Coalescing, http://crbug.com/289520 | 
 |   65   QueueWebEvent(mouse_event.event, mouse_event.latency, false); | 
 |   66 } | 
 |   67  | 
 |   68 void BufferedInputRouter::SendWheelEvent( | 
 |   69     const MouseWheelEventWithLatencyInfo& wheel_event) { | 
 |   70   if (!client_->OnSendWheelEvent(wheel_event)) | 
 |   71     return; | 
 |   72   QueueWebEvent(wheel_event.event, wheel_event.latency, false); | 
 |   73 } | 
 |   74  | 
 |   75 void BufferedInputRouter::SendKeyboardEvent( | 
 |   76     const NativeWebKeyboardEvent& key_event, | 
 |   77     const ui::LatencyInfo& latency_info) { | 
 |   78   bool is_shortcut = false; | 
 |   79   if (!client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut)) | 
 |   80     return; | 
 |   81   int64 event_id = QueueWebEvent(key_event, latency_info, is_shortcut); | 
 |   82   if (event_id) { | 
 |   83     DCHECK(queued_key_map_.find(event_id) == queued_key_map_.end()); | 
 |   84     queued_key_map_[event_id] = key_event; | 
 |   85   } | 
 |   86 } | 
 |   87  | 
 |   88 void BufferedInputRouter::SendGestureEvent( | 
 |   89     const GestureEventWithLatencyInfo& gesture_event) { | 
 |   90   if (!client_->OnSendGestureEvent(gesture_event)) | 
 |   91     return; | 
 |   92   if (QueueWebEvent(gesture_event.event, gesture_event.latency, false)) | 
 |   93     ++queued_gesture_count_; | 
 |   94 } | 
 |   95  | 
 |   96 void BufferedInputRouter::SendTouchEvent( | 
 |   97     const TouchEventWithLatencyInfo& touch_event) { | 
 |   98   if (!client_->OnSendTouchEvent(touch_event)) | 
 |   99     return; | 
 |  100   if (QueueWebEvent(touch_event.event, touch_event.latency, false)) | 
 |  101     ++queued_touch_count_; | 
 |  102 } | 
 |  103  | 
 |  104 void BufferedInputRouter::SendMouseEventImmediately( | 
 |  105     const MouseEventWithLatencyInfo& mouse_event) { | 
 |  106   if (!client_->OnSendMouseEventImmediately(mouse_event)) | 
 |  107     return; | 
 |  108   QueueWebEvent(mouse_event.event, mouse_event.latency, false); | 
 |  109 } | 
 |  110  | 
 |  111 void BufferedInputRouter::SendTouchEventImmediately( | 
 |  112     const TouchEventWithLatencyInfo& touch_event) { | 
 |  113   if (!client_->OnSendTouchEventImmediately(touch_event)) | 
 |  114     return; | 
 |  115   QueueWebEvent(touch_event.event, touch_event.latency, false); | 
 |  116 } | 
 |  117  | 
 |  118 void BufferedInputRouter::SendGestureEventImmediately( | 
 |  119     const GestureEventWithLatencyInfo& gesture_event) { | 
 |  120   if (!client_->OnSendGestureEventImmediately(gesture_event)) | 
 |  121     return; | 
 |  122   QueueWebEvent(gesture_event.event, gesture_event.latency, false); | 
 |  123 } | 
 |  124  | 
 |  125 void BufferedInputRouter::Deliver(const EventPacket& packet) { | 
 |  126   TRACE_EVENT2("input", "BufferedInputRouter::DeliverPacket", | 
 |  127                "id", packet.id(), | 
 |  128                "events", packet.size()); | 
 |  129   DCHECK(packet.id()); | 
 |  130   DCHECK(!in_flight_packet_id_); | 
 |  131   if (!sender_->Send(new InputMsg_HandleEventPacket( | 
 |  132            routing_id_, packet, InputEventDispositions()))) { | 
 |  133     return; | 
 |  134   } | 
 |  135  | 
 |  136   in_flight_packet_id_ = packet.id(); | 
 |  137   client_->IncrementInFlightEventCount(); | 
 |  138 } | 
 |  139  | 
 |  140 void BufferedInputRouter::DidFinishFlush() { | 
 |  141   TRACE_EVENT0("input", "BufferedInputRouter::DidFinishFlush"); | 
 |  142   client_->DidFlush(); | 
 |  143 } | 
 |  144  | 
 |  145 void BufferedInputRouter::SetNeedsFlush() { | 
 |  146   TRACE_EVENT0("input", "BufferedInputRouter::SetNeedsFlush"); | 
 |  147   client_->SetNeedsFlush(); | 
 |  148 } | 
 |  149  | 
 |  150 void BufferedInputRouter::OnDispatched(const BrowserInputEvent& event, | 
 |  151                                        InputEventDisposition disposition) { | 
 |  152   // Only WebInputEvents currently have ack response. | 
 |  153   if (event.payload()->GetType() != InputEvent::Payload::WEB_INPUT_EVENT) | 
 |  154     return; | 
 |  155  | 
 |  156   const WebInputEventPayload* web_payload = | 
 |  157       WebInputEventPayload::Cast(event.payload()); | 
 |  158  | 
 |  159   OnWebInputEventAck(event.id(), | 
 |  160                      *web_payload->web_event(), | 
 |  161                      web_payload->latency_info(), | 
 |  162                      ToAckState(disposition), | 
 |  163                      true); | 
 |  164 } | 
 |  165  | 
 |  166 void BufferedInputRouter::OnDispatched( | 
 |  167     const BrowserInputEvent& event, | 
 |  168     InputEventDisposition disposition, | 
 |  169     ScopedVector<BrowserInputEvent>* followup) { | 
 |  170   DCHECK(followup); | 
 |  171   DCHECK_NE(INPUT_EVENT_ACK_STATE_CONSUMED, ToAckState(disposition)); | 
 |  172  | 
 |  173   // Events sent to the router within this scope will be added to |followup|. | 
 |  174   base::AutoReset<ScopedVector<BrowserInputEvent>*> input_queue_override( | 
 |  175       &input_queue_override_, followup); | 
 |  176  | 
 |  177   OnDispatched(event, disposition); | 
 |  178 } | 
 |  179  | 
 |  180 bool BufferedInputRouter::OnMessageReceived(const IPC::Message& message) { | 
 |  181   bool handled = true; | 
 |  182   bool message_is_ok = true; | 
 |  183   IPC_BEGIN_MESSAGE_MAP_EX(BufferedInputRouter, message, message_is_ok) | 
 |  184     IPC_MESSAGE_HANDLER(InputHostMsg_HandleEventPacket_ACK, OnEventPacketAck) | 
 |  185     IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, | 
 |  186                         OnHasTouchEventHandlers) | 
 |  187     IPC_MESSAGE_UNHANDLED(handled = false) | 
 |  188   IPC_END_MESSAGE_MAP() | 
 |  189  | 
 |  190   if (!message_is_ok) | 
 |  191     ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 
 |  192  | 
 |  193   return handled; | 
 |  194 } | 
 |  195  | 
 |  196 const NativeWebKeyboardEvent* | 
 |  197     BufferedInputRouter::GetLastKeyboardEvent() const { | 
 |  198   return queued_key_map_.empty() ? NULL : &queued_key_map_.begin()->second; | 
 |  199 } | 
 |  200  | 
 |  201 bool BufferedInputRouter::ShouldForwardTouchEvent() const { | 
 |  202   return has_touch_handler_ && queued_touch_count_ > 0; | 
 |  203 } | 
 |  204  | 
 |  205 bool BufferedInputRouter::ShouldForwardGestureEvent( | 
 |  206     const GestureEventWithLatencyInfo& touch_event) const { | 
 |  207   return true; | 
 |  208 } | 
 |  209  | 
 |  210 bool BufferedInputRouter::HasQueuedGestureEvents() const { | 
 |  211   return queued_gesture_count_ > 0; | 
 |  212 } | 
 |  213  | 
 |  214 void BufferedInputRouter::OnWebInputEventAck( | 
 |  215     int64 event_id, | 
 |  216     const WebKit::WebInputEvent& web_event, | 
 |  217     const ui::LatencyInfo& latency_info, | 
 |  218     InputEventAckState acked_result, | 
 |  219     bool ack_from_input_queue) { | 
 |  220   if (WebInputEvent::isKeyboardEventType(web_event.type)) { | 
 |  221     if (ack_from_input_queue) { | 
 |  222       KeyMap::iterator key_it = queued_key_map_.find(event_id); | 
 |  223       DCHECK(key_it != queued_key_map_.end()); | 
 |  224       NativeWebKeyboardEvent key_event = key_it->second; | 
 |  225       queued_key_map_.erase(key_it); | 
 |  226       ack_handler_->OnKeyboardEventAck(key_event, acked_result); | 
 |  227     } else { | 
 |  228       DCHECK_EQ(0, event_id); | 
 |  229       ack_handler_->OnKeyboardEventAck( | 
 |  230           static_cast<const NativeWebKeyboardEvent&>(web_event), acked_result); | 
 |  231     } | 
 |  232     // WARNING: This BufferedInputRouter can be deallocated at this point | 
 |  233     // (i.e.  in the case of Ctrl+W, where the call to | 
 |  234     // HandleKeyboardEvent destroys this BufferedInputRouter). | 
 |  235   } else if (web_event.type == WebInputEvent::MouseWheel) { | 
 |  236     ack_handler_->OnWheelEventAck( | 
 |  237         static_cast<const WebMouseWheelEvent&>(web_event), acked_result); | 
 |  238   } else if (WebInputEvent::isTouchEventType(web_event.type)) { | 
 |  239     if (ack_from_input_queue) { | 
 |  240       DCHECK_GT(queued_touch_count_, 0); | 
 |  241       --queued_touch_count_; | 
 |  242     } | 
 |  243     ack_handler_->OnTouchEventAck( | 
 |  244         TouchEventWithLatencyInfo(static_cast<const WebTouchEvent&>(web_event), | 
 |  245                                   latency_info), | 
 |  246         acked_result); | 
 |  247   } else if (WebInputEvent::isGestureEventType(web_event.type)) { | 
 |  248     if (ack_from_input_queue) { | 
 |  249       DCHECK_GT(queued_gesture_count_, 0); | 
 |  250       --queued_gesture_count_; | 
 |  251     } | 
 |  252     ack_handler_->OnGestureEventAck( | 
 |  253         static_cast<const WebGestureEvent&>(web_event), acked_result); | 
 |  254   } else | 
 |  255     NOTREACHED() << "Unexpected WebInputEvent in OnWebInputEventAck"; | 
 |  256 } | 
 |  257  | 
 |  258 void BufferedInputRouter::OnEventPacketAck( | 
 |  259     int64 packet_id, | 
 |  260     const InputEventDispositions& dispositions) { | 
 |  261   TRACE_EVENT2("input", "BufferedInputRouter::OnEventPacketAck", | 
 |  262                "id", packet_id, | 
 |  263                "dispositions", dispositions.size()); | 
 |  264   if (!in_flight_packet_id_ || packet_id != in_flight_packet_id_) { | 
 |  265     ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK); | 
 |  266     return; | 
 |  267   } | 
 |  268  | 
 |  269   in_flight_packet_id_ = 0; | 
 |  270   client_->DecrementInFlightEventCount(); | 
 |  271  | 
 |  272   InputQueue::AckResult ack_result = | 
 |  273       input_queue_->OnEventPacketAck(packet_id, dispositions); | 
 |  274   if (ack_result == InputQueue::ACK_UNEXPECTED) | 
 |  275     ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK); | 
 |  276   else if (ack_result == InputQueue::ACK_INVALID) | 
 |  277     ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 
 |  278 } | 
 |  279  | 
 |  280 void BufferedInputRouter::OnHasTouchEventHandlers(bool has_handlers) { | 
 |  281   if (has_touch_handler_ == has_handlers) | 
 |  282     return; | 
 |  283   has_touch_handler_ = has_handlers; | 
 |  284   client_->OnHasTouchEventHandlers(has_handlers); | 
 |  285 } | 
 |  286  | 
 |  287 int64 BufferedInputRouter::QueueWebEvent(const WebKit::WebInputEvent& web_event, | 
 |  288                                          const ui::LatencyInfo& latency_info, | 
 |  289                                          bool is_key_shortcut) { | 
 |  290   TRACE_EVENT0("input", "BufferedInputRouter::QueueWebEvent"); | 
 |  291  | 
 |  292   if (FilterWebEvent(web_event, latency_info)) { | 
 |  293     TRACE_EVENT_INSTANT0("input", | 
 |  294                          "BufferedInputRouter::QueueWebEvent::Filtered", | 
 |  295                          TRACE_EVENT_SCOPE_THREAD); | 
 |  296     return 0; | 
 |  297   } | 
 |  298  | 
 |  299   int64 event_id = NextInputID(); | 
 |  300   scoped_ptr<BrowserInputEvent> event = BrowserInputEvent::Create( | 
 |  301       event_id, | 
 |  302       WebInputEventPayload::Create(web_event, | 
 |  303                                    latency_info, | 
 |  304                                    is_key_shortcut), | 
 |  305       this); | 
 |  306  | 
 |  307   // The presence of |input_queue_override_| implies that we are in the | 
 |  308   // scope of |OnInputEventDispatched()| with an event can create followup. | 
 |  309   if (input_queue_override_) | 
 |  310     input_queue_override_->push_back(event.release()); | 
 |  311   else | 
 |  312     input_queue_->QueueEvent(event.Pass()); | 
 |  313  | 
 |  314   return event_id; | 
 |  315 } | 
 |  316  | 
 |  317 bool BufferedInputRouter::FilterWebEvent(const WebKit::WebInputEvent& web_event, | 
 |  318                                          const ui::LatencyInfo& latency_info) { | 
 |  319   // Perform optional, synchronous event handling, sending ACK messages for | 
 |  320   // processed events, or proceeding as usual. | 
 |  321   InputEventAckState filter_ack = | 
 |  322       client_->FilterInputEvent(web_event, latency_info); | 
 |  323   switch (filter_ack) { | 
 |  324     // Send the ACK and early exit. | 
 |  325     case INPUT_EVENT_ACK_STATE_CONSUMED: | 
 |  326     case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: | 
 |  327       OnWebInputEventAck(0, web_event, latency_info, filter_ack, false); | 
 |  328       // WARNING: |this| may be deleted at this point. | 
 |  329       return true; | 
 |  330  | 
 |  331     // Drop the event. | 
 |  332     case INPUT_EVENT_ACK_STATE_UNKNOWN: | 
 |  333       return true; | 
 |  334  | 
 |  335     // Proceed as normal. | 
 |  336     case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: | 
 |  337     default: | 
 |  338       break; | 
 |  339   }; | 
 |  340  | 
 |  341   return false; | 
 |  342 } | 
 |  343  | 
 |  344 int64 BufferedInputRouter::NextInputID() { return next_input_id_++; } | 
 |  345  | 
 |  346 }  // namespace content | 
| OLD | NEW |