diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc index 51dac34cf28a4..c81c408d6b058 100644 --- a/content/browser/renderer_host/direct_manipulation_helper_win.cc +++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc @@ -164,10 +164,26 @@ void DirectManipulationHelper::UpdateEventHandler( RemoveAnimationObserver(); } + // IDirectManipulationViewport methods (Stop / RemoveEventHandler / + // AddEventHandler) and IDirectManipulationUpdateManager::Update are COM + // calls on the browser UI STA and may synchronously pump window messages + // (see the matching comment in LegacyRenderWidgetHostHWND::UpdateParent). + // Re-entrant dispatch can reach LegacyRenderWidgetHostHWND::Destroy() -> + // direct_manipulation_helper_.reset() -> ~DirectManipulationHelper(), or + // OnNCDestroy -> delete LegacyRenderWidgetHostHWND, either of which frees + // |this|. Guard against |this| being freed mid-method. + base::WeakPtr ref(weak_factory_.GetWeakPtr()); + if (event_handler_) { event_handler_.Reset(); viewport_->Stop(); + if (!ref) { + return; + } viewport_->RemoveEventHandler(view_port_handler_cookie_); + if (!ref) { + return; + } } window_tree_host_ = window_tree_host; @@ -186,6 +202,9 @@ void DirectManipulationHelper::UpdateEventHandler( // IDirectManipulationViewportEventHandler. HRESULT hr = viewport_->AddEventHandler(window_, event_handler_.Get(), &view_port_handler_cookie_); + if (!ref) { + return; + } if (!SUCCEEDED(hr)) { event_handler_.Reset(); return;