diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index 2e412026f5e74..e19424740e022 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc @@ -876,22 +876,33 @@ void ProcessManager::CloseLazyBackgroundPageNow(const ExtensionId& extension_id, return; } - // Close remaining views. - std::vector frames_to_close; + // Close remaining views. WebContents::ClosePage() can synchronously + // destroy the tab (and every RenderFrameHost in it) when the tab's main + // frame is already ready to be closed -- e.g. while a JavaScript dialog + // is showing -- so collect frame IDs rather than bare pointers and re- + // resolve on each iteration to avoid dereferencing a freed RFH. + std::vector frames_to_close; for (const auto& key_value : all_extension_frames_) { if (key_value.second.CanKeepalive() && GetExtensionID(key_value.first) == extension_id) { DCHECK(!key_value.second.has_keepalive); - frames_to_close.push_back(key_value.first); + frames_to_close.push_back(key_value.first->GetGlobalId()); } } - for (content::RenderFrameHost* frame : frames_to_close) { + for (const content::GlobalRenderFrameHostId& frame_id : frames_to_close) { + content::RenderFrameHost* frame = + content::RenderFrameHost::FromID(frame_id); + if (!frame) { + continue; + } content::WebContents::FromRenderFrameHost(frame)->ClosePage(); // WebContents::ClosePage() may result in calling // UnregisterRenderFrameHost() asynchronously and may cause race // conditions when the background page is reloaded. // To avoid this, unregister the view now. - UnregisterRenderFrameHost(frame); + if (content::RenderFrameHost::FromID(frame_id)) { + UnregisterRenderFrameHost(frame); + } } host = GetBackgroundHostForExtension(extension_id);