diff --git a/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc b/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc index 71570ab35ad30..4960651093073 100644 --- a/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc +++ b/third_party/blink/renderer/platform/widget/input/widget_base_input_handler.cc @@ -269,6 +269,16 @@ WebInputEventResult WidgetBaseInputHandler::HandleTouchEvent( WebCoalescedInputEvent(pointer_event, coalesced_event.latency_info())); } + // The synchronous JS dispatch inside HandleInputEvent below can run a + // nested event loop (alert/print/debugger). The Delete IPC arrives on + // kInternalNavigationAssociated which is not pausable, so it can run + // inside that nested loop and destroy the WidgetBase that owns |this| + // as an inline member. Guard with a WeakPtr exactly as the caller does + // at line 423; that check is too late because we make up to 16 calls + // here before returning. See crbug.com/1031028 for the non-touch case. + base::WeakPtr weak_self = + weak_ptr_factory_.GetWeakPtr(); + const WebTouchEvent touch_event = static_cast(input_event); for (unsigned i = 0; i < touch_event.touches_length; ++i) { @@ -283,6 +293,10 @@ WebInputEventResult WidgetBaseInputHandler::HandleTouchEvent( coalesced_event.GetPredictedEventsPointers(), coalesced_event.latency_info()); widget_->client()->HandleInputEvent(coalesced_pointer_event); + // |this| may have been freed inside the dispatch above. + if (!weak_self) { + return WebInputEventResult::kNotHandled; + } } } return widget_->client()->DispatchBufferedTouchEvents();