Use strong ownership for attached inner WebContents.
Bug: 832879
Change-Id: Ib39e8caade4114b396337fa2efc04f4a54f69ed3
Reviewed-on: https://chromium-review.googlesource.com/c/1301843
Reviewed-by: Avi Drissman <[email protected]>
Commit-Queue: Lucas Gadani <[email protected]>
Cr-Commit-Position: refs/heads/master@{#603190}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 68b0df9..c5ae682b 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -479,38 +479,45 @@
FrameTreeNode::kFrameTreeNodeInvalidId),
focused_web_contents_(current_web_contents) {}
-WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() {
- if (OuterContentsFrameTreeNode())
- OuterContentsFrameTreeNode()->RemoveObserver(this);
-
- if (outer_web_contents_)
- outer_web_contents_->node_.DetachInnerWebContents(current_web_contents_);
-}
+WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() {}
void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents(
- WebContentsImpl* outer_web_contents,
+ std::unique_ptr<WebContents> current_web_contents,
RenderFrameHostImpl* outer_contents_frame) {
+ DCHECK_EQ(current_web_contents.get(), current_web_contents_);
+ auto* outer_web_contents =
+ static_cast<WebContentsImpl*>(FromRenderFrameHost(outer_contents_frame));
+
focused_web_contents_ = nullptr;
outer_web_contents_ = outer_web_contents;
outer_contents_frame_tree_node_id_ =
outer_contents_frame->frame_tree_node()->frame_tree_node_id();
- outer_web_contents_->node_.AttachInnerWebContents(current_web_contents_);
+ outer_web_contents_->node_.AttachInnerWebContents(
+ std::move(current_web_contents));
outer_contents_frame->frame_tree_node()->AddObserver(this);
}
void WebContentsImpl::WebContentsTreeNode::AttachInnerWebContents(
- WebContentsImpl* inner_web_contents) {
- inner_web_contents_.push_back(inner_web_contents);
+ std::unique_ptr<WebContents> inner_web_contents) {
+ inner_web_contents_.push_back(std::move(inner_web_contents));
}
-void WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents(
+std::unique_ptr<WebContents>
+WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents(
WebContentsImpl* inner_web_contents) {
- DCHECK(base::ContainsValue(inner_web_contents_, inner_web_contents));
- inner_web_contents_.erase(
- std::remove(inner_web_contents_.begin(), inner_web_contents_.end(),
- inner_web_contents),
- inner_web_contents_.end());
+ std::unique_ptr<WebContents> detached_contents;
+ for (std::unique_ptr<WebContents>& web_contents : inner_web_contents_) {
+ if (web_contents.get() == inner_web_contents) {
+ detached_contents = std::move(web_contents);
+ std::swap(web_contents, inner_web_contents_.back());
+ inner_web_contents_.pop_back();
+ return detached_contents;
+ }
+ }
+
+ NOTREACHED();
+ return nullptr;
}
FrameTreeNode*
@@ -523,7 +530,9 @@
DCHECK_EQ(outer_contents_frame_tree_node_id_, node->frame_tree_node_id())
<< "WebContentsTreeNode should only receive notifications for the "
"FrameTreeNode in its outer WebContents that hosts it.";
- delete current_web_contents_; // deletes |this| too.
+
+ // Deletes |this| too.
+ outer_web_contents_->node_.DetachInnerWebContents(current_web_contents_);
}
void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents(
@@ -537,17 +546,22 @@
WebContentsImpl::WebContentsTreeNode::GetInnerWebContentsInFrame(
const FrameTreeNode* frame) {
auto ftn_id = frame->frame_tree_node_id();
- for (WebContentsImpl* contents : inner_web_contents_) {
- if (contents->node_.outer_contents_frame_tree_node_id() == ftn_id) {
- return contents;
+ for (auto& contents : inner_web_contents_) {
+ WebContentsImpl* impl = static_cast<WebContentsImpl*>(contents.get());
+ if (impl->node_.outer_contents_frame_tree_node_id() == ftn_id) {
+ return impl;
}
}
return nullptr;
}
-const std::vector<WebContentsImpl*>&
-WebContentsImpl::WebContentsTreeNode::inner_web_contents() const {
- return inner_web_contents_;
+std::vector<WebContentsImpl*>
+WebContentsImpl::WebContentsTreeNode::GetInnerWebContents() const {
+ std::vector<WebContentsImpl*> inner_web_contents;
+ for (auto& contents : inner_web_contents_)
+ inner_web_contents.push_back(static_cast<WebContentsImpl*>(contents.get()));
+
+ return inner_web_contents;
}
// WebContentsImpl -------------------------------------------------------------
@@ -1248,7 +1262,7 @@
return inner_contents;
}
- return node_.inner_web_contents();
+ return node_.GetInnerWebContents();
}
std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() {
@@ -1779,9 +1793,10 @@
}
void WebContentsImpl::AttachToOuterWebContentsFrame(
- WebContents* outer_web_contents,
+ std::unique_ptr<WebContents> current_web_contents,
RenderFrameHost* outer_contents_frame) {
DCHECK(!node_.outer_web_contents());
+ DCHECK_EQ(current_web_contents.get(), this);
RenderFrameHostManager* render_manager = GetRenderManager();
@@ -1802,16 +1817,12 @@
if (!render_manager->GetRenderWidgetHostView())
CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost());
- auto* outer_web_contents_impl =
- static_cast<WebContentsImpl*>(outer_web_contents);
auto* outer_contents_frame_impl =
static_cast<RenderFrameHostImpl*>(outer_contents_frame);
// Create a link to our outer WebContents.
- node_.ConnectToOuterWebContents(outer_web_contents_impl,
+ node_.ConnectToOuterWebContents(std::move(current_web_contents),
outer_contents_frame_impl);
- DCHECK(outer_contents_frame);
-
// Create a proxy in top-level RenderFrameHostManager, pointing to the
// SiteInstance of the outer WebContents. The proxy will be used to send
// postMessage to the inner WebContents.
@@ -1820,7 +1831,7 @@
ReattachToOuterWebContentsFrame();
- if (outer_web_contents_impl->frame_tree_.GetFocusedFrame() ==
+ if (node_.outer_web_contents()->frame_tree_.GetFocusedFrame() ==
outer_contents_frame_impl->frame_tree_node()) {
SetFocusedFrame(frame_tree_.root(),
outer_contents_frame->GetSiteInstance());