Index: content/browser/renderer_host/input/input_router_impl.cc |
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc |
index 364f7ca5a9d884f7cb1d0809517fe7fdd5834fac..5edebe204a9df48c1e76d3e4999b505b17789dc3 100644 |
--- a/content/browser/renderer_host/input/input_router_impl.cc |
+++ b/content/browser/renderer_host/input/input_router_impl.cc |
@@ -18,6 +18,7 @@ |
#include "content/common/content_constants_internal.h" |
#include "content/common/edit_command.h" |
#include "content/common/input/input_event_ack_state.h" |
+#include "content/common/input/input_event_stream_validator.h" |
#include "content/common/input/touch_action.h" |
#include "content/common/input/web_touch_event_traits.h" |
#include "content/common/input_messages.h" |
@@ -56,7 +57,7 @@ const char* GetEventAckName(InputEventAckState ack_result) { |
} // namespace |
-InputRouterImpl::Config::Config() { |
+InputRouterImpl::Config::Config() : validate_event_stream(false) { |
} |
InputRouterImpl::InputRouterImpl(IPC::Sender* sender, |
@@ -75,23 +76,24 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender, |
current_view_flags_(0), |
current_ack_source_(ACK_SOURCE_NONE), |
flush_requested_(false), |
+ in_recycle_(false), |
touch_event_queue_(this, config.touch_config), |
gesture_event_queue_(this, this, config.gesture_config) { |
DCHECK(sender); |
DCHECK(client); |
DCHECK(ack_handler); |
UpdateTouchAckTimeoutEnabled(); |
+ if (config.validate_event_stream) { |
+ optional_input_stream_validator_.reset(new InputEventStreamValidator()); |
+ optional_output_stream_validator_.reset(new InputEventStreamValidator()); |
+ } |
} |
InputRouterImpl::~InputRouterImpl() {} |
-void InputRouterImpl::Flush() { |
- flush_requested_ = true; |
- SignalFlushedIfNecessary(); |
-} |
- |
bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { |
- DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); |
+ DCHECK(!in_recycle_); |
+ DCHECK_EQ(IPC_MESSAGE_ID_CLASS(message->type()), InputMsgStart); |
switch (message->type()) { |
// Check for types that require an ACK. |
case InputMsg_SelectRange::ID: |
@@ -108,6 +110,7 @@ bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { |
void InputRouterImpl::SendMouseEvent( |
const MouseEventWithLatencyInfo& mouse_event) { |
+ DCHECK(!in_recycle_); |
if (mouse_event.event.type == WebInputEvent::MouseDown && |
gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
ShouldDeferMouseDown(mouse_event)) |
@@ -122,10 +125,12 @@ void InputRouterImpl::SendMouseEvent( |
void InputRouterImpl::SendWheelEvent( |
const MouseWheelEventWithLatencyInfo& wheel_event) { |
+ DCHECK(!in_recycle_); |
SendWheelEvent(QueuedWheelEvent(wheel_event, false)); |
} |
void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { |
+ DCHECK(!in_recycle_); |
if (mouse_wheel_pending_) { |
// If there's already a mouse wheel event waiting to be sent to the |
// renderer, add the new deltas to that event. Not doing so (e.g., by |
@@ -160,6 +165,7 @@ void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { |
void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
const ui::LatencyInfo& latency_info, |
bool is_keyboard_shortcut) { |
+ DCHECK(!in_recycle_); |
// Put all WebKeyboardEvent objects in a queue since we can't trust the |
// renderer and we need to give something to the HandleKeyboardEvent |
// handler. |
@@ -174,7 +180,11 @@ void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
void InputRouterImpl::SendGestureEvent( |
const GestureEventWithLatencyInfo& original_gesture_event) { |
- input_stream_validator_.Validate(original_gesture_event.event); |
+ if (in_recycle_) |
+ return; |
+ |
+ if (optional_input_stream_validator_) |
+ optional_input_stream_validator_->Validate(original_gesture_event.event); |
GestureEventWithLatencyInfo gesture_event(original_gesture_event); |
@@ -192,10 +202,45 @@ void InputRouterImpl::SendGestureEvent( |
void InputRouterImpl::SendTouchEvent( |
const TouchEventWithLatencyInfo& touch_event) { |
- input_stream_validator_.Validate(touch_event.event); |
+ DCHECK(!in_recycle_); |
+ if (optional_input_stream_validator_) |
+ optional_input_stream_validator_->Validate(touch_event.event); |
touch_event_queue_.QueueEvent(touch_event); |
} |
+void InputRouterImpl::Recycle() { |
+ DCHECK(!in_recycle_); |
+ DCHECK_EQ(current_ack_source_, ACK_SOURCE_NONE); |
+ base::AutoReset<bool> auto_reset_in_recycle(&in_recycle_, true); |
+ |
+ key_queue_.clear(); |
+ coalesced_mouse_wheel_events_.clear(); |
+ next_mouse_move_.reset(); |
+ next_selection_range_.reset(); |
+ next_move_caret_.reset(); |
+ |
+ // It's *extremely* important that all touches currently queued be ack'ed to |
+ // the view. Though all (potentially) derived gestures will be ignored, the |
+ // touches must be ack'ed to the client, ensuring upstream gesture detection |
+ // is properly flushed. |
+ touch_event_queue_.Flush(INPUT_EVENT_ACK_STATE_CONSUMED); |
+ gesture_event_queue_.Recycle(); |
+ touch_action_filter_.ResetTouchAction(); |
+ |
+ if (optional_input_stream_validator_) |
+ optional_input_stream_validator_.reset(new InputEventStreamValidator()); |
+ if (optional_output_stream_validator_) |
+ optional_output_stream_validator_.reset(new InputEventStreamValidator()); |
+ |
+ DCHECK(!HasPendingEvents()); |
+ SignalFlushedIfNecessary(); |
+} |
+ |
+void InputRouterImpl::RequestFlushedNotification() { |
+ flush_requested_ = true; |
+ SignalFlushedIfNecessary(); |
+} |
+ |
// Forwards MouseEvent without passing it through |
// TouchpadTapSuppressionController. |
void InputRouterImpl::SendMouseEventImmediately( |
@@ -310,7 +355,7 @@ bool InputRouterImpl::SendSelectRange(scoped_ptr<IPC::Message> message) { |
} |
bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) { |
- DCHECK(message->type() == InputMsg_MoveCaret::ID); |
+ DCHECK_EQ(message->type(), InputMsg_MoveCaret::ID); |
if (move_caret_pending_) { |
next_move_caret_ = message.Pass(); |
return true; |
@@ -342,7 +387,9 @@ void InputRouterImpl::FilterAndSendWebInputEvent( |
void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, |
const ui::LatencyInfo& latency_info, |
bool is_keyboard_shortcut) { |
- output_stream_validator_.Validate(input_event); |
+ DCHECK(!in_recycle_); |
+ if (optional_output_stream_validator_) |
+ optional_output_stream_validator_->Validate(input_event); |
if (OfferToClient(input_event, latency_info)) |
return; |
@@ -507,7 +554,6 @@ void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { |
touch_action_filter_.ResetTouchAction(); |
touch_event_queue_.OnHasTouchEventHandlers(has_handlers); |
- client_->OnHasTouchEventHandlers(has_handlers); |
} |
void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) { |