Chromium Code Reviews| 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/render_process_host_impl.h" | |
| 9 #include "content/browser/renderer_host/render_widget_host_impl.h" | |
| 10 #include "content/common/input/input_event_utils.h" | |
| 11 #include "content/common/input_messages.h" | |
| 12 #include "content/common/view_messages.h" | |
| 13 #include "content/public/browser/native_web_keyboard_event.h" | |
| 14 #include "content/public/browser/user_metrics.h" | |
| 15 | |
| 16 using base::Time; | |
| 17 using base::TimeDelta; | |
| 18 using WebKit::WebGestureEvent; | |
| 19 using WebKit::WebInputEvent; | |
| 20 using WebKit::WebKeyboardEvent; | |
| 21 using WebKit::WebMouseEvent; | |
| 22 using WebKit::WebMouseWheelEvent; | |
| 23 using WebKit::WebTouchEvent; | |
| 24 | |
| 25 namespace content { | |
| 26 | |
| 27 namespace { | |
| 28 | |
| 29 InputEventAckState FromState(InputEventState state) { | |
| 30 switch (state) { | |
| 31 case INPUT_EVENT_UNHANDLED: | |
| 32 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; | |
| 33 case INPUT_EVENT_IMPL_THREAD_ABSORBED: | |
| 34 return INPUT_EVENT_ACK_STATE_CONSUMED; | |
| 35 case INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS: | |
| 36 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; | |
| 37 case INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN: | |
| 38 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; | |
| 39 case INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER: | |
| 40 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; | |
| 41 case INPUT_EVENT_MAIN_THREAD_ABSORBED: | |
| 42 return INPUT_EVENT_ACK_STATE_CONSUMED; | |
| 43 case INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED: | |
| 44 return INPUT_EVENT_ACK_STATE_CONSUMED; | |
| 45 case INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED: | |
| 46 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; | |
| 47 case INPUT_EVENT_MAIN_THREAD_NO_HANDLER_EXISTS: | |
| 48 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; | |
| 49 case INPUT_EVENT_MAIN_THREAD_COULD_NOT_DELIVER: | |
| 50 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; | |
| 51 } | |
| 52 | |
| 53 NOTREACHED(); | |
| 54 return INPUT_EVENT_ACK_STATE_UNKNOWN; | |
| 55 } | |
| 56 | |
| 57 } // namespace | |
| 58 | |
| 59 BufferedInputRouter::BufferedInputRouter(RenderProcessHost* process, | |
| 60 InputRouterClient* client, | |
| 61 int routing_id) | |
| 62 : client_(client), | |
| 63 process_(process), | |
| 64 routing_id_(routing_id), | |
| 65 input_queue_(new InputQueue(this)), | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Passing partially constructed "this" pointer here
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 66 queued_gesture_count_(0), | |
| 67 has_touch_handler_(false), | |
| 68 queued_touch_count_(0), | |
| 69 input_queue_override_(NULL), | |
| 70 last_input_id_(0), | |
| 71 in_flight_packet_id_(0), | |
| 72 // TODO(jdduke): Determine a sensible value... | |
| 73 delayed_packet_timeout_ms_(10) {} | |
| 74 | |
| 75 BufferedInputRouter::~BufferedInputRouter() {} | |
| 76 | |
| 77 void BufferedInputRouter::Flush() { | |
| 78 TRACE_EVENT0("input", "BufferedInputRouter::Flush"); | |
| 79 DCHECK(in_flight_packet_id_ == 0); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
DCHECK_EQ(0, in_flight_packet_id_);
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 80 | |
| 81 in_flight_packet_id_ = 0; | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Delete this line, you already DCHECKed it above.
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 82 input_queue_->FlushEventsInCurrentFrame(); | |
| 83 if (in_flight_packet_id_) { | |
| 84 StartDelayedPacketMonitorTimeout( | |
| 85 TimeDelta::FromMilliseconds(delayed_packet_timeout_ms_)); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 bool BufferedInputRouter::SendInput(IPC::Message* message) { | |
| 90 scoped_ptr<IPC::Message> scoped_message(message); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Why take ownership?  Why not let the client manage
 
jdduke (slow)
2013/08/13 15:29:48
This was originally an OVERRIDE of IPC::Sender::Se
 
 | |
| 91 if (IPC_MESSAGE_ID_CLASS(message->type()) != InputMsgStart) { | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
These look like they should be DCHECK_EQ/DCHECK_NE
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 92 NOTREACHED() << "BufferedInputRouter only handles input-related messages."; | |
| 93 return false; | |
| 94 } | |
| 95 if (message->type() == InputMsg_HandleEventPacket::ID) { | |
| 96 NOTREACHED() << "WebInputEvents should never be sent via SendInput."; | |
| 97 return false; | |
| 98 } | |
| 99 | |
| 100 input_queue_->QueueEvent(InputEvent(NewInputID(), | |
| 101 INPUT_EVENT_ONE_WAY, | |
| 102 *scoped_message), NULL); | |
| 103 return true; | |
| 104 } | |
| 105 | |
| 106 void BufferedInputRouter::SendMouseEvent( | |
| 107 const MouseEventWithLatencyInfo& mouse_event) { | |
| 108 if (!client_->OnSendMouseEvent(mouse_event)) | |
| 109 return; | |
| 110 QueueWebEvent(mouse_event.event, mouse_event.latency, false, false); | |
| 111 } | |
| 112 | |
| 113 void BufferedInputRouter::SendWheelEvent( | |
| 114 const MouseWheelEventWithLatencyInfo& wheel_event) { | |
| 115 if (!client_->OnSendWheelEvent(wheel_event)) | |
| 116 return; | |
| 117 QueueWebEvent(wheel_event.event, wheel_event.latency, false, false); | |
| 118 } | |
| 119 | |
| 120 void BufferedInputRouter::SendKeyboardEvent( | |
| 121 const NativeWebKeyboardEvent& key_event, | |
| 122 const ui::LatencyInfo& latency_info) { | |
| 123 bool is_shortcut = false; | |
| 124 if (!client_->OnSendKeyboardEvent(key_event, latency_info, &is_shortcut)) | |
| 125 return; | |
| 126 int64 event_id = QueueWebEvent(key_event, latency_info, is_shortcut, false); | |
| 127 if (event_id) { | |
| 128 DCHECK(queued_key_map_.find(event_id) == queued_key_map_.end()); | |
| 129 queued_key_map_[event_id] = key_event; | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 void BufferedInputRouter::SendGestureEvent( | |
| 134 const GestureEventWithLatencyInfo& gesture_event) { | |
| 135 if (!client_->OnSendGestureEvent(gesture_event)) | |
| 136 return; | |
| 137 if (QueueWebEvent(gesture_event.event, gesture_event.latency, false, false)) | |
| 138 ++queued_gesture_count_; | |
| 139 } | |
| 140 | |
| 141 void BufferedInputRouter::SendTouchEvent( | |
| 142 const TouchEventWithLatencyInfo& touch_event) { | |
| 143 if (!client_->OnSendTouchEvent(touch_event)) | |
| 144 return; | |
| 145 if (QueueWebEvent(touch_event.event, touch_event.latency, false, true)) | |
| 146 ++queued_touch_count_; | |
| 147 } | |
| 148 | |
| 149 void BufferedInputRouter::SendMouseEventImmediately( | |
| 150 const MouseEventWithLatencyInfo& mouse_event) { | |
| 151 if (!client_->OnSendMouseEventImmediately(mouse_event)) | |
| 152 return; | |
| 153 QueueWebEvent(mouse_event.event, mouse_event.latency, false, false); | |
| 154 } | |
| 155 | |
| 156 void BufferedInputRouter::SendTouchEventImmediately( | |
| 157 const TouchEventWithLatencyInfo& touch_event) { | |
| 158 if (!client_->OnSendTouchEventImmediately(touch_event)) | |
| 159 return; | |
| 160 QueueWebEvent(touch_event.event, touch_event.latency, false, false); | |
| 161 } | |
| 162 | |
| 163 void BufferedInputRouter::SendGestureEventImmediately( | |
| 164 const GestureEventWithLatencyInfo& gesture_event) { | |
| 165 if (!client_->OnSendGestureEventImmediately(gesture_event)) | |
| 166 return; | |
| 167 QueueWebEvent(gesture_event.event, gesture_event.latency, false, false); | |
| 168 } | |
| 169 | |
| 170 void BufferedInputRouter::Deliver(const EventPacket& packet) { | |
| 171 TRACE_EVENT2("input", "BufferedInputRouter::DeliverPacket", | |
| 172 "id", packet.id, | |
| 173 "events", packet.events.size()); | |
| 174 // TODO(jdduke): How should we handle this case? Clear the existing queue? | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
I think you should mandate that the process has a
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 175 if (!process_->HasConnection()) | |
| 176 return; | |
| 177 | |
| 178 DCHECK(packet.id && !in_flight_packet_id_); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Split this into two separate DCHECKs (the output w
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 179 in_flight_packet_id_ = packet.id; | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Can you put these two lines after the Send() and j
 
jdduke (slow)
2013/08/13 15:29:48
Yeah, I was thinking of a the case where an ack re
 
 | |
| 180 client_->IncrementInFlightEventCount(); | |
| 181 if (!process_->Send(new InputMsg_HandleEventPacket(routing_id_, packet))) { | |
| 182 in_flight_packet_id_ = 0; | |
| 183 client_->DecrementInFlightEventCount(); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 void BufferedInputRouter::DidFlush() { | |
| 188 TRACE_EVENT0("input", "BufferedInputRouter::DidFlush"); | |
| 189 StopDelayedPacketMonitorTimeout(); | |
| 190 client_->DidFlush(); | |
| 191 } | |
| 192 | |
| 193 void BufferedInputRouter::SetNeedsFlush() { | |
| 194 TRACE_EVENT0("input", "BufferedInputRouter::SetNeedsFlush"); | |
| 195 client_->SetNeedsFlush(); | |
| 196 } | |
| 197 | |
| 198 void BufferedInputRouter::OnInputEventAck(const InputEvent& acked_event) { | |
| 199 if (!IsWebInputEventMessage(acked_event.message)) | |
| 200 return; | |
| 201 | |
| 202 const WebKit::WebInputEvent* web_event = NULL; | |
| 203 ui::LatencyInfo latency_info; | |
| 204 if (!CrackWebInputEventMessage(acked_event.message, | |
| 205 &web_event, | |
| 206 &latency_info, | |
| 207 NULL)) { | |
| 208 client_->OnUnexpectedEventAck(true); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
I'm not sure what the client is supposed to do wit
 
jdduke (slow)
2013/08/13 15:29:48
Why should the router know how to handle a bad mes
 
 | |
| 209 return; | |
| 210 } | |
| 211 | |
| 212 InputEventAckState ack_state = FromState(acked_event.state); | |
| 213 OnInputEventAck(acked_event.id, *web_event, latency_info, ack_state, true); | |
| 214 } | |
| 215 | |
| 216 void BufferedInputRouter::OnInputEventAck(const InputEvent& acked_event, | |
| 217 EventInjector* injector) { | |
| 218 // Temporarily override the input queue with |injector|. | |
| 219 base::AutoReset<EventAckHandler::EventInjector*> | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
I don't think this AutoReset trick is a good idea.
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 220 input_queue_override(&input_queue_override_, injector); | |
| 221 OnInputEventAck(acked_event); | |
| 222 } | |
| 223 | |
| 224 bool BufferedInputRouter::OnMessageReceived(const IPC::Message& message) { | |
| 225 bool handled = true; | |
| 226 bool message_is_ok = true; | |
| 227 IPC_BEGIN_MESSAGE_MAP_EX(BufferedInputRouter, message, message_is_ok) | |
| 228 IPC_MESSAGE_HANDLER(InputHostMsg_HandleEventPacket_ACK, OnEventPacketAck) | |
| 229 IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, | |
| 230 OnHasTouchEventHandlers) | |
| 231 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 232 IPC_END_MESSAGE_MAP() | |
| 233 | |
| 234 if (!message_is_ok) | |
| 235 client_->OnUnexpectedEventAck(true); | |
| 236 | |
| 237 return handled; | |
| 238 } | |
| 239 | |
| 240 const NativeWebKeyboardEvent* | |
| 241 BufferedInputRouter::GetLastKeyboardEvent() const { | |
| 242 return queued_key_map_.empty() ? NULL : &queued_key_map_.begin()->second; | |
| 243 } | |
| 244 | |
| 245 bool BufferedInputRouter::ShouldForwardTouchEvent() const { | |
| 246 return has_touch_handler_ && queued_touch_count_ > 0; | |
| 247 } | |
| 248 | |
| 249 bool BufferedInputRouter::ShouldForwardGestureEvent( | |
| 250 const GestureEventWithLatencyInfo& touch_event) const { | |
| 251 return true; | |
| 252 } | |
| 253 | |
| 254 bool BufferedInputRouter::HasQueuedGestureEvents() const { | |
| 255 return queued_gesture_count_ > 0; | |
| 256 } | |
| 257 | |
| 258 void BufferedInputRouter::OnInputEventAck( | |
| 259 int64 event_id, | |
| 260 const WebKit::WebInputEvent& web_event, | |
| 261 const ui::LatencyInfo& latency_info, | |
| 262 InputEventAckState acked_result, | |
| 263 bool ack_from_input_queue) { | |
| 264 if (WebInputEvent::isKeyboardEventType(web_event.type)) { | |
| 265 if (ack_from_input_queue) { | |
| 266 KeyMap::iterator key_it = queued_key_map_.find(event_id); | |
| 267 DCHECK(key_it != queued_key_map_.end()); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
DCHECK_NE(key_it, queued_key_map_.end());
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 268 if (key_it != queued_key_map_.end()) { | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Delete this if().
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 269 NativeWebKeyboardEvent key_event = key_it->second; | |
| 270 queued_key_map_.erase(key_it); | |
| 271 client_->OnKeyboardEventAck(key_event, acked_result); | |
| 272 } | |
| 273 } else { | |
| 274 DCHECK(event_id == 0); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
DCHECK_EQ(0, event_id);
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 275 client_->OnKeyboardEventAck( | |
| 276 static_cast<const NativeWebKeyboardEvent&>(web_event), acked_result); | |
| 277 } | |
| 278 // WARNING: This BufferedInputRouter can be deallocated at this point | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Should Ctrl-W's consequence be made async so that
 
jdduke (slow)
2013/08/13 15:29:48
That would be nice; I'm not sure what that would e
 
 | |
| 279 // (i.e. in the case of Ctrl+W, where the call to | |
| 280 // HandleKeyboardEvent destroys this BufferedInputRouter). | |
| 281 } else if (web_event.type == WebInputEvent::MouseWheel) { | |
| 282 client_->OnWheelEventAck( | |
| 283 static_cast<const WebMouseWheelEvent&>(web_event), acked_result); | |
| 284 } else if (WebInputEvent::isTouchEventType(web_event.type)) { | |
| 285 if (ack_from_input_queue) { | |
| 286 DCHECK(queued_touch_count_ > 0); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
DCHECK_GT(queued_touch_count_, 0);
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 287 --queued_touch_count_; | |
| 288 } | |
| 289 client_->OnTouchEventAck( | |
| 290 TouchEventWithLatencyInfo(static_cast<const WebTouchEvent&>(web_event), | |
| 291 latency_info), acked_result); | |
| 292 } else if (WebInputEvent::isGestureEventType(web_event.type)) { | |
| 293 if (ack_from_input_queue) { | |
| 294 DCHECK(queued_gesture_count_ > 0); | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
DCHECK_GT(queued_touch_count_, 0);
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 295 --queued_gesture_count_; | |
| 296 } | |
| 297 client_->OnGestureEventAck( | |
| 298 static_cast<const WebGestureEvent&>(web_event), acked_result); | |
| 299 } else { | |
| 300 NOTREACHED() << "Unexpected WebInputEvent in OnInputEventAck"; | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 void BufferedInputRouter::OnEventPacketAck(const EventPacket& packet) { | |
| 305 TRACE_EVENT1("input", "BufferedInputRouter::OnEventPacketAck", | |
| 306 "id", packet.id); | |
| 307 if (!in_flight_packet_id_ || packet.id != in_flight_packet_id_) { | |
| 308 client_->OnUnexpectedEventAck(false); | |
| 309 return; | |
| 310 } | |
| 311 | |
| 312 in_flight_packet_id_ = 0; | |
| 313 client_->DecrementInFlightEventCount(); | |
| 314 | |
| 315 InputQueue::AckResult ack_result = input_queue_->OnEventPacketAck(packet); | |
| 316 if (ack_result == InputQueue::ACK_UNEXPECTED) | |
| 317 client_->OnUnexpectedEventAck(false); | |
| 318 else if (ack_result == InputQueue::ACK_INVALID) | |
| 319 client_->OnUnexpectedEventAck(true); | |
| 320 } | |
| 321 | |
| 322 void BufferedInputRouter::OnHasTouchEventHandlers(bool has_handlers) { | |
| 323 if (has_touch_handler_ == has_handlers) | |
| 324 return; | |
| 325 has_touch_handler_ = has_handlers; | |
| 326 client_->OnHasTouchEventHandlers(has_handlers); | |
| 327 } | |
| 328 | |
| 329 int64 BufferedInputRouter::QueueWebEvent(const WebKit::WebInputEvent& web_event, | |
| 330 const ui::LatencyInfo& latency_info, | |
| 331 bool is_keyboard_shortcut, | |
| 332 bool has_followup) { | |
| 333 TRACE_EVENT0("input", "BufferedInputRouter::QueueWebEvent"); | |
| 334 | |
| 335 DCHECK(!process_->IgnoreInputEvents()); | |
| 336 if (FilterWebEvent(web_event, latency_info)) { | |
| 337 TRACE_EVENT_INSTANT0("input", | |
| 338 "BufferedInputRouter::QueueWebEvent::Filtered", | |
| 339 TRACE_EVENT_SCOPE_THREAD); | |
| 340 return 0; | |
| 341 } | |
| 342 | |
| 343 InputEventType type = has_followup ? INPUT_EVENT_NEEDS_ACK_AND_HAS_FOLLOWUP | |
| 344 : INPUT_EVENT_NEEDS_ACK; | |
| 345 InputEvent event(NewInputID(), | |
| 346 type, | |
| 347 InputMsg_HandleInputEvent(routing_id_, | |
| 348 &web_event, | |
| 349 latency_info, | |
| 350 is_keyboard_shortcut)); | |
| 351 | |
| 352 // The presence of |input_queue_override_| implies that we are in the | |
| 353 // scope of OnInputEventAck with a valid injector. | |
| 354 if (input_queue_override_) | |
| 355 input_queue_override_->InjectEvent(event, this); | |
| 356 else | |
| 357 input_queue_->QueueEvent(event, this); | |
| 358 | |
| 359 return event.id; | |
| 360 } | |
| 361 | |
| 362 bool BufferedInputRouter::FilterWebEvent(const WebKit::WebInputEvent& web_event, | |
| 363 const ui::LatencyInfo& latency_info) { | |
| 364 // Perform optional, synchronous event handling, sending ACK messages for | |
| 365 // processed events, or proceeding as usual. | |
| 366 InputEventAckState filter_ack = client_->FilterInputEvent(web_event, | |
| 367 latency_info); | |
| 368 switch (filter_ack) { | |
| 369 // Send the ACK and early exit. | |
| 370 case INPUT_EVENT_ACK_STATE_CONSUMED: | |
| 371 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: | |
| 372 OnInputEventAck(0, web_event, latency_info, filter_ack, false); | |
| 373 // WARNING: |this| may be deleted at this point. | |
| 374 return true; | |
| 375 | |
| 376 // Drop the event. | |
| 377 case INPUT_EVENT_ACK_STATE_UNKNOWN: | |
| 378 return true; | |
| 379 | |
| 380 // Proceed as normal. | |
| 381 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: | |
| 382 default: | |
| 383 break; | |
| 384 }; | |
| 385 | |
| 386 return false; | |
| 387 } | |
| 388 | |
| 389 void BufferedInputRouter::StartDelayedPacketMonitorTimeout(TimeDelta delay) { | |
| 390 Time target_delayed_time = Time::Now() + delay; | |
| 
 
aelias_OOO_until_Jul13
2013/08/13 06:11:51
Use TimeTicks::Now() instead.
 
jdduke (slow)
2013/08/13 15:29:48
Done.
 
 | |
| 391 if (time_when_signal_delayed_packet_.is_null() || | |
| 392 time_when_signal_delayed_packet_ > target_delayed_time) { | |
| 393 // This will effectively clear an existing timeout. | |
| 394 time_when_signal_delayed_packet_ = target_delayed_time; | |
| 395 } | |
| 396 | |
| 397 // If we already have a timer with the same or shorter duration, then we can | |
| 398 // wait for it to finish. | |
| 399 if (delayed_packet_timer_.IsRunning() && | |
| 400 delayed_packet_timer_.GetCurrentDelay() <= delay) { | |
| 401 return; | |
| 402 } | |
| 403 | |
| 404 time_when_signal_delayed_packet_ = target_delayed_time; | |
| 405 delayed_packet_timer_.Stop(); | |
| 406 delayed_packet_timer_.Start(FROM_HERE, delay, this, | |
| 407 &BufferedInputRouter::CheckShouldSignalDelayedPacket); | |
| 408 } | |
| 409 | |
| 410 void BufferedInputRouter::StopDelayedPacketMonitorTimeout() { | |
| 411 time_when_signal_delayed_packet_ = Time(); | |
| 412 delayed_packet_timer_.Stop(); | |
| 413 } | |
| 414 | |
| 415 void BufferedInputRouter::CheckShouldSignalDelayedPacket() { | |
| 416 if (time_when_signal_delayed_packet_.is_null()) | |
| 417 return; | |
| 418 | |
| 419 Time now = Time::Now(); | |
| 420 if (now < time_when_signal_delayed_packet_) { | |
| 421 StartDelayedPacketMonitorTimeout(time_when_signal_delayed_packet_ - now); | |
| 422 return; | |
| 423 } | |
| 424 | |
| 425 TRACE_EVENT1("input", "BufferedInputRouter::EventPacketDelayed", | |
| 426 "id", in_flight_packet_id_); | |
| 427 input_queue_->OnEventPacketAckDelayed(); | |
| 428 } | |
| 429 | |
| 430 int64 BufferedInputRouter::NewInputID() { | |
| 431 return ++last_input_id_; | |
| 432 } | |
| 433 | |
| 434 } // namespace content | |
| OLD | NEW |