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());
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index e3eb4c5..ac4e414 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -358,7 +358,7 @@
bool NeedToFireBeforeUnload() override;
void DispatchBeforeUnload(bool auto_cancel) override;
void AttachToOuterWebContentsFrame(
- WebContents* outer_web_contents,
+ std::unique_ptr<WebContents> current_web_contents,
RenderFrameHost* outer_contents_frame) override;
WebContentsImpl* GetOuterWebContents() override;
WebContentsImpl* GetOutermostWebContents() override;
@@ -1093,8 +1093,11 @@
explicit WebContentsTreeNode(WebContentsImpl* current_web_contents);
~WebContentsTreeNode() final;
- void ConnectToOuterWebContents(WebContentsImpl* outer_web_contents,
- RenderFrameHostImpl* outer_contents_frame);
+ // Connects |current_web_contents| to the outer WebContents that owns
+ // |outer_contents_frame|.
+ void ConnectToOuterWebContents(
+ std::unique_ptr<WebContents> current_web_contents,
+ RenderFrameHostImpl* outer_contents_frame);
WebContentsImpl* outer_web_contents() const { return outer_web_contents_; }
int outer_contents_frame_tree_node_id() const {
@@ -1109,11 +1112,13 @@
// otherwise.
WebContentsImpl* GetInnerWebContentsInFrame(const FrameTreeNode* frame);
- const std::vector<WebContentsImpl*>& inner_web_contents() const;
+ std::vector<WebContentsImpl*> GetInnerWebContents() const;
private:
- void AttachInnerWebContents(WebContentsImpl* inner_web_contents);
- void DetachInnerWebContents(WebContentsImpl* inner_web_contents);
+ void AttachInnerWebContents(
+ std::unique_ptr<WebContents> inner_web_contents);
+ std::unique_ptr<WebContents> DetachInnerWebContents(
+ WebContentsImpl* inner_web_contents);
// FrameTreeNode::Observer implementation.
void OnFrameTreeNodeDestroyed(FrameTreeNode* node) final;
@@ -1129,8 +1134,9 @@
// |current_web_contents_| as an inner WebContents.
int outer_contents_frame_tree_node_id_;
- // List of inner WebContents that we host.
- std::vector<WebContentsImpl*> inner_web_contents_;
+ // List of inner WebContents that we host. The outer WebContents owns the
+ // inner WebContents.
+ std::vector<std::unique_ptr<WebContents>> inner_web_contents_;
// Only the root node should have this set. This indicates the WebContents
// whose frame tree has the focused frame. The WebContents tree could be