| 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/input_queue.h" | 
 |    6  | 
 |    7 #include "base/bind.h" | 
 |    8 #include "base/debug/trace_event.h" | 
 |    9 #include "content/browser/renderer_host/input/browser_input_event.h" | 
 |   10 #include "content/browser/renderer_host/input/input_queue_client.h" | 
 |   11 #include "content/common/input/event_packet.h" | 
 |   12 #include "content/common/input/input_event.h" | 
 |   13  | 
 |   14 namespace content { | 
 |   15  | 
 |   16 // A specialized EventPacket with utility methods for dispatched event handling. | 
 |   17 class InputQueue::BrowserEventPacket : public EventPacket { | 
 |   18  public: | 
 |   19   typedef ScopedVector<BrowserInputEvent> BrowserInputEvents; | 
 |   20  | 
 |   21   BrowserEventPacket() : weak_factory_(this) {} | 
 |   22   virtual ~BrowserEventPacket() {} | 
 |   23  | 
 |   24   // Validate the response and signal dispatch to the processed events. | 
 |   25   // Undelivered events will be re-enqueued, and any generated followup events | 
 |   26   // will be inserted at the same relative order as their generating event. | 
 |   27   AckResult ValidateAndDispatchAck(int64 packet_id, | 
 |   28                                    const InputEventDispositions& dispositions) { | 
 |   29     if (!Validate(packet_id, dispositions)) | 
 |   30       return ACK_INVALID; | 
 |   31  | 
 |   32     // Empty the packet; events will be re-enqueued as necessary. | 
 |   33     InputEvents dispatched_events; | 
 |   34     events_.swap(dispatched_events); | 
 |   35  | 
 |   36     // The packet could be deleted as a result of event dispatch; use a local | 
 |   37     // weak ref to ensure proper shutdown. | 
 |   38     base::WeakPtr<EventPacket> weak_ref_this = weak_factory_.GetWeakPtr(); | 
 |   39  | 
 |   40     BrowserInputEvents followup_events; | 
 |   41     for (size_t i = 0; i < dispatched_events.size(); ++i) { | 
 |   42       // Take ownership of the event. | 
 |   43       scoped_ptr<BrowserInputEvent> event( | 
 |   44           static_cast<BrowserInputEvent*>(dispatched_events[i])); | 
 |   45       dispatched_events[i] = NULL; | 
 |   46  | 
 |   47       // Re-enqueue undelivered events. | 
 |   48       InputEventDisposition disposition = dispositions[i]; | 
 |   49       if (disposition == INPUT_EVENT_COULD_NOT_DELIVER) { | 
 |   50         Add(event.PassAs<InputEvent>()); | 
 |   51         continue; | 
 |   52       } | 
 |   53  | 
 |   54       event->OnDispatched(disposition, &followup_events); | 
 |   55  | 
 |   56       // TODO(jdduke): http://crbug.com/274029 | 
 |   57       if (!weak_ref_this.get()) | 
 |   58         return ACK_SHUTDOWN; | 
 |   59  | 
 |   60       AddAll(&followup_events); | 
 |   61     } | 
 |   62     return ACK_OK; | 
 |   63   } | 
 |   64  | 
 |   65  protected: | 
 |   66   // Add and take ownership of events in |followup_events|. | 
 |   67   void AddAll(BrowserInputEvents* followup_events) { | 
 |   68     for (BrowserInputEvents::iterator iter = followup_events->begin(); | 
 |   69          iter != followup_events->end(); | 
 |   70          ++iter) { | 
 |   71       Add(scoped_ptr<InputEvent>(*iter)); | 
 |   72     } | 
 |   73     followup_events->weak_clear(); | 
 |   74   } | 
 |   75  | 
 |   76   // Perform a sanity check of the ack against the current packet. | 
 |   77   // |packet_id| should match that of this packet, and |dispositions| should | 
 |   78   // be of size equal to the number of events in this packet. | 
 |   79   bool Validate(int64 packet_id, | 
 |   80                 const InputEventDispositions& dispositions) const { | 
 |   81     if (packet_id != id()) | 
 |   82       return false; | 
 |   83  | 
 |   84     if (dispositions.size() != size()) | 
 |   85       return false; | 
 |   86  | 
 |   87     return true; | 
 |   88   } | 
 |   89  | 
 |   90  private: | 
 |   91   base::WeakPtrFactory<EventPacket> weak_factory_; | 
 |   92 }; | 
 |   93  | 
 |   94 InputQueue::InputQueue(InputQueueClient* client) | 
 |   95     : client_(client), | 
 |   96       next_packet_id_(1), | 
 |   97       flush_requested_(false), | 
 |   98       in_flush_packet_(new BrowserEventPacket()), | 
 |   99       pending_flush_packet_(new BrowserEventPacket()) { | 
 |  100   DCHECK(client_); | 
 |  101 } | 
 |  102  | 
 |  103 InputQueue::~InputQueue() {} | 
 |  104  | 
 |  105 void InputQueue::QueueEvent(scoped_ptr<BrowserInputEvent> event) { | 
 |  106   DCHECK(event); | 
 |  107   DCHECK(event->valid()); | 
 |  108   pending_flush_packet_->Add(event.PassAs<InputEvent>()); | 
 |  109   RequestFlushIfNecessary(); | 
 |  110 } | 
 |  111  | 
 |  112 void InputQueue::BeginFlush() { | 
 |  113   // Ignore repeated flush attempts. | 
 |  114   if (!flush_requested_) | 
 |  115     return; | 
 |  116  | 
 |  117   DCHECK(!FlushInProgress()); | 
 |  118   DCHECK(!pending_flush_packet_->empty()); | 
 |  119  | 
 |  120   flush_requested_ = false; | 
 |  121   in_flush_packet_.swap(pending_flush_packet_); | 
 |  122   DeliverInFlushPacket(); | 
 |  123 } | 
 |  124  | 
 |  125 InputQueue::AckResult InputQueue::OnEventPacketAck( | 
 |  126     int64 packet_id, | 
 |  127     const InputEventDispositions& dispositions) { | 
 |  128   if (!FlushInProgress()) | 
 |  129     return ACK_UNEXPECTED; | 
 |  130  | 
 |  131   TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "AckPacket", | 
 |  132                           "id", packet_id); | 
 |  133  | 
 |  134   AckResult ack_result = | 
 |  135       in_flush_packet_->ValidateAndDispatchAck(packet_id, dispositions); | 
 |  136  | 
 |  137   if (ack_result != ACK_OK) | 
 |  138     return ack_result; | 
 |  139  | 
 |  140   if (FlushInProgress()) { | 
 |  141     DeliverInFlushPacket(); | 
 |  142   } else { | 
 |  143     TRACE_EVENT_ASYNC_END0("input", "InputQueueFlush", this); | 
 |  144     client_->DidFinishFlush(); | 
 |  145     RequestFlushIfNecessary(); | 
 |  146   } | 
 |  147  | 
 |  148   return ACK_OK; | 
 |  149 } | 
 |  150  | 
 |  151 size_t InputQueue::QueuedEventCount() const { | 
 |  152   return in_flush_packet_->size() + pending_flush_packet_->size(); | 
 |  153 } | 
 |  154  | 
 |  155 void InputQueue::DeliverInFlushPacket() { | 
 |  156   DCHECK(FlushInProgress()); | 
 |  157   TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "DeliverPacket", | 
 |  158                           "id", next_packet_id_); | 
 |  159   in_flush_packet_->set_id(next_packet_id_++); | 
 |  160   client_->Deliver(*in_flush_packet_); | 
 |  161 } | 
 |  162  | 
 |  163 void InputQueue::RequestFlushIfNecessary() { | 
 |  164   if (flush_requested_) | 
 |  165     return; | 
 |  166  | 
 |  167   // Defer flush requests until the current flush has finished. | 
 |  168   if (FlushInProgress()) | 
 |  169     return; | 
 |  170  | 
 |  171   // No additional events to flush. | 
 |  172   if (pending_flush_packet_->empty()) | 
 |  173     return; | 
 |  174  | 
 |  175   TRACE_EVENT_ASYNC_BEGIN0("input", "InputQueueFlush", this); | 
 |  176   TRACE_EVENT_ASYNC_STEP0("input", "InputQueueFlush", this, "Request"); | 
 |  177   flush_requested_ = true; | 
 |  178   client_->SetNeedsFlush(); | 
 |  179 } | 
 |  180  | 
 |  181 bool InputQueue::FlushInProgress() const { return !in_flush_packet_->empty(); } | 
 |  182  | 
 |  183 } // namespace content | 
| OLD | NEW |