DanglingPtr: fix dangling ptr in FrameTree
|root_| raw_ptr is first deleted and then cleared, which caused a
dangling ptr. The issue is that while running |root_| destructor chain,
we would re-access |root_| pointer value, which prevents us from using
mechanisms such as `ClearAndDelete` or a unique_ptr.
By making this a composition, we ensure the aforementioned pattern still
works, while making object lifetime management easier.
Bug: 1291138,1298696
Change-Id: I4fb214888aec67a8b01e1a10d83bfecf6d698846
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3934736
Commit-Queue: Paul Semel <[email protected]>
Reviewed-by: Arthur Sonzogni <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1057418}
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index cab0dae..1b0aba4 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -20,7 +20,6 @@
#include "base/trace_event/optional_trace_event.h"
#include "base/trace_event/typed_macros.h"
#include "base/unguessable_token.h"
-#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
@@ -204,31 +203,29 @@
navigator_delegate,
navigation_controller_delegate),
type_(type),
- root_(new FrameTreeNode(this,
- nullptr,
- // The top-level frame must always be in a
- // document scope.
- blink::mojom::TreeScopeType::kDocument,
- false,
- devtools_frame_token,
- blink::mojom::FrameOwnerProperties(),
- blink::FrameOwnerElementType::kNone,
- blink::FramePolicy())),
focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
load_progress_(0.0),
fenced_frames_impl_(
blink::features::IsFencedFramesEnabled()
? absl::optional<blink::features::FencedFramesImplementationType>(
blink::features::kFencedFramesImplementationTypeParam.Get())
- : absl::nullopt) {}
+ : absl::nullopt),
+ root_(this,
+ nullptr,
+ // The top-level frame must always be in a
+ // document scope.
+ blink::mojom::TreeScopeType::kDocument,
+ false,
+ devtools_frame_token,
+ blink::mojom::FrameOwnerProperties(),
+ blink::FrameOwnerElementType::kNone,
+ blink::FramePolicy()) {}
FrameTree::~FrameTree() {
is_being_destroyed_ = true;
#if DCHECK_IS_ON()
DCHECK(was_shut_down_);
#endif
- delete root_;
- root_ = nullptr;
}
FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
@@ -261,7 +258,7 @@
FrameTreeNode* FrameTree::FindByName(const std::string& name) {
if (name.empty())
- return root_;
+ return &root_;
for (FrameTreeNode* node : Nodes()) {
if (node->frame_name() == name)
@@ -282,7 +279,7 @@
}
FrameTree::NodeRange FrameTree::NodesIncludingInnerTreeNodes() {
- return NodeRange({root_}, nullptr,
+ return NodeRange({&root_}, nullptr,
/*should_descend_into_inner_trees=*/true,
/*include_delegate_nodes_for_inner_frame_trees=*/false);
}
@@ -293,7 +290,7 @@
std::vector<FrameTreeNode*> nodes;
DCHECK(node_iter != node_range.end());
- FrameTree* root_loading_tree = root_->frame_tree()->LoadingTree();
+ FrameTree* root_loading_tree = root_.frame_tree()->LoadingTree();
while (node_iter != node_range.end()) {
// Skip over frame trees and children which belong to inner web contents
// i.e., when nodes doesn't point to the same loading frame tree.
@@ -333,7 +330,7 @@
}
FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
- return NodeRange({root_}, node, /*should_descend_into_inner_trees=*/false,
+ return NodeRange({&root_}, node, /*should_descend_into_inner_trees=*/false,
/*include_delegate_nodes_for_inner_frame_trees=*/false);
}
@@ -559,7 +556,7 @@
}
RenderFrameHostImpl* FrameTree::GetMainFrame() const {
- return root_->current_frame_host();
+ return root_.current_frame_host();
}
FrameTreeNode* FrameTree::GetFocusedFrame() {
@@ -690,10 +687,10 @@
}
double FrameTree::GetLoadProgress() {
- if (root_->HasNavigation())
+ if (root_.HasNavigation())
return blink::kInitialLoadProgress;
- return root_->current_frame_host()->GetPage().load_progress();
+ return root_.current_frame_host()->GetPage().load_progress();
}
bool FrameTree::IsLoadingIncludingInnerFrameTrees() const {
@@ -728,7 +725,7 @@
}
void FrameTree::SetPageFocus(SiteInstanceGroup* group, bool is_focused) {
- RenderFrameHostManager* root_manager = root_->render_manager();
+ RenderFrameHostManager* root_manager = root_.render_manager();
// Portal frame tree should not get page focus.
DCHECK(!IsPortal() || !is_focused);
@@ -797,10 +794,10 @@
// blink::FrameTree::SetName always keeps |unique_name| empty in case of a
// main frame - let's do the same thing here.
std::string unique_name;
- root_->render_manager()->InitRoot(main_frame_site_instance,
- renderer_initiated_creation, frame_policy,
- main_frame_name);
- root_->SetFencedFramePropertiesIfNeeded();
+ root_.render_manager()->InitRoot(main_frame_site_instance,
+ renderer_initiated_creation, frame_policy,
+ main_frame_name);
+ root_.SetFencedFramePropertiesIfNeeded();
// The initial empty document should inherit the origin of its opener (the
// origin may change after the first commit), except when they are in
@@ -812,7 +809,7 @@
// Checking sandbox flags of the new frame should be safe at this point,
// because the flags should be already inherited when creating the root node.
DCHECK(!renderer_initiated_creation || opener_for_origin);
- root_->current_frame_host()->SetOriginDependentStateOfNewFrame(
+ root_.current_frame_host()->SetOriginDependentStateOfNewFrame(
renderer_initiated_creation ? opener_for_origin->GetLastCommittedOrigin()
: url::Origin());
@@ -861,7 +858,7 @@
was_shut_down_ = true;
#endif
- RenderFrameHostManager* root_manager = root_->render_manager();
+ RenderFrameHostManager* root_manager = root_.render_manager();
if (!root_manager->current_frame_host()) {
// The page has been transferred out during an activation. There is little
@@ -870,9 +867,9 @@
// need to be moved along during activation replace this line with a DCHECK
// that there are no pending delete instances.
root_manager->ClearRFHsPendingShutdown();
- DCHECK(!root_->navigation_request());
+ DCHECK(!root_.navigation_request());
DCHECK(!root_manager->speculative_frame_host());
- manager_delegate_->OnFrameTreeNodeDestroyed(root_);
+ manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
return;
}
@@ -901,7 +898,7 @@
// Do not update state as the FrameTree::Delegate (possibly a WebContents) is
// being destroyed.
- root_->ResetNavigationRequestButKeepState();
+ root_.ResetNavigationRequestButKeepState();
if (root_manager->speculative_frame_host()) {
root_manager->DiscardSpeculativeRenderFrameHostForShutdown();
}
@@ -911,7 +908,7 @@
// navigation request is reset.
controller().GetBackForwardCache().Shutdown();
- manager_delegate_->OnFrameTreeNodeDestroyed(root_);
+ manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
render_view_delegate_->RenderViewDeleted(
root_manager->current_frame_host()->render_view_host());
}