fix: cross-origin navigation disposing WebFrameMain instances (#30076)

This commit is contained in:
Samuel Maddock 2021-08-18 14:23:41 -04:00 committed by GitHub
parent 90b5ba3bed
commit dd16d68e96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 96 deletions

View file

@ -1384,7 +1384,9 @@ void WebContents::HandleNewRenderFrame(
if (rwh_impl)
rwh_impl->disable_hidden_ = !background_throttling_;
WebFrameMain::RenderFrameCreated(render_frame_host);
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
if (web_frame)
web_frame->Connect();
}
void WebContents::RenderFrameCreated(
@ -1392,6 +1394,46 @@ void WebContents::RenderFrameCreated(
HandleNewRenderFrame(render_frame_host);
}
void WebContents::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
// A RenderFrameHost can be deleted when:
// - A WebContents is removed and its containing frames are disposed.
// - An <iframe> is removed from the DOM.
// - Cross-origin navigation creates a new RFH in a separate process which
// is swapped by content::RenderFrameHostManager.
//
// WebFrameMain::FromRenderFrameHost(rfh) will use the RFH's FrameTreeNode ID
// to find an existing instance of WebFrameMain. During a cross-origin
// navigation, the deleted RFH will be the old host which was swapped out. In
// this special case, we need to also ensure that WebFrameMain's internal RFH
// matches before marking it as disposed.
auto* web_frame = WebFrameMain::FromRenderFrameHost(render_frame_host);
if (web_frame && web_frame->render_frame_host() == render_frame_host)
web_frame->MarkRenderFrameDisposed();
}
void WebContents::RenderFrameHostChanged(content::RenderFrameHost* old_host,
content::RenderFrameHost* new_host) {
// During cross-origin navigation, a FrameTreeNode will swap out its RFH.
// If an instance of WebFrameMain exists, it will need to have its RFH
// swapped as well.
//
// |old_host| can be a nullptr in so we use |new_host| for looking up the
// WebFrameMain instance.
auto* web_frame =
WebFrameMain::FromFrameTreeNodeId(new_host->GetFrameTreeNodeId());
if (web_frame) {
CHECK_EQ(web_frame->render_frame_host(), old_host);
web_frame->UpdateRenderFrameHost(new_host);
}
}
void WebContents::FrameDeleted(int frame_tree_node_id) {
auto* web_frame = WebFrameMain::FromFrameTreeNodeId(frame_tree_node_id);
if (web_frame)
web_frame->Destroyed();
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
// This event is necessary for tracking any states with respect to
// intermediate render view hosts aka speculative render view hosts. Currently
@ -1631,13 +1673,6 @@ void WebContents::UpdateDraggableRegions(
observer.OnDraggableRegionsUpdated(regions);
}
void WebContents::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
// A WebFrameMain can outlive its RenderFrameHost so we need to mark it as
// disposed to prevent access to it.
WebFrameMain::RenderFrameDeleted(render_frame_host);
}
void WebContents::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
EmitNavigationEvent("did-start-navigation", navigation_handle);