Index: content/browser/web_contents/web_contents_impl.cc |
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc |
index 2daf76a0a060f226895085cd7feedadfe38e5cd6..d0d5340746a1383e4058f4a429b9a8009503e3db 100644 |
--- a/content/browser/web_contents/web_contents_impl.cc |
+++ b/content/browser/web_contents/web_contents_impl.cc |
@@ -380,9 +380,10 @@ WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode() |
WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { |
// Remove child pointer from our parent. |
if (outer_web_contents_) { |
- ChildrenSet& child_ptrs_in_parent = |
+ ChildrenMap& child_ptrs_in_parent = |
outer_web_contents_->node_->inner_web_contents_tree_nodes_; |
- ChildrenSet::iterator iter = child_ptrs_in_parent.find(this); |
+ ChildrenMap::iterator iter = |
+ child_ptrs_in_parent.find(outer_contents_frame_tree_node_id_); |
DCHECK(iter != child_ptrs_in_parent.end()); |
child_ptrs_in_parent.erase(iter); |
} |
@@ -391,11 +392,12 @@ WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { |
// TODO(lazyboy): We should destroy the children WebContentses too. If the |
// children do not manage their own lifetime, then we would leak their |
// WebContentses. |
- for (WebContentsTreeNode* child : inner_web_contents_tree_nodes_) |
- child->outer_web_contents_ = nullptr; |
+ for (auto child : inner_web_contents_tree_nodes_) |
+ child.second->node_->outer_web_contents_ = nullptr; |
} |
void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( |
+ WebContentsImpl* web_contents, |
WebContentsImpl* outer_web_contents, |
RenderFrameHostImpl* outer_contents_frame) { |
DCHECK(!focused_web_contents_) << "Should not attach a root node."; |
@@ -410,7 +412,9 @@ void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( |
outer_web_contents_->node_->SetFocusedWebContents(outer_web_contents_); |
} |
- outer_web_contents_->node_->inner_web_contents_tree_nodes_.insert(this); |
+ outer_web_contents_->node_ |
+ ->inner_web_contents_tree_nodes_[outer_contents_frame_tree_node_id_] = |
+ web_contents; |
} |
void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents( |
@@ -420,6 +424,14 @@ void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents( |
focused_web_contents_ = web_contents; |
} |
+WebContentsImpl* WebContentsImpl::WebContentsTreeNode::find_contents_at_node( |
alexmos
2017/02/23 20:07:04
Name this FindContentsAtNode, since it's not a sim
avallee
2017/02/28 20:13:00
Done.
|
+ int frame_tree_node_id) { |
+ auto iter = inner_web_contents_tree_nodes_.find(frame_tree_node_id); |
+ if (iter == inner_web_contents_tree_nodes_.end()) |
+ return nullptr; |
+ return iter->second; |
+} |
+ |
// WebContentsImpl ------------------------------------------------------------- |
WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) |
@@ -1440,7 +1452,7 @@ void WebContentsImpl::AttachToOuterWebContentsFrame( |
// Create a link to our outer WebContents. |
node_.reset(new WebContentsTreeNode()); |
node_->ConnectToOuterWebContents( |
- static_cast<WebContentsImpl*>(outer_web_contents), |
+ this, static_cast<WebContentsImpl*>(outer_web_contents), |
alexmos
2017/02/23 20:07:04
Maybe it would help if WebContentsTreeNode just kn
avallee
2017/02/28 20:13:01
My original iteration of the downward link did jus
|
static_cast<RenderFrameHostImpl*>(outer_contents_frame)); |
DCHECK(outer_contents_frame); |
@@ -1459,6 +1471,12 @@ void WebContentsImpl::AttachToOuterWebContentsFrame( |
render_manager->GetRenderWidgetHostView()) |
->RegisterFrameSinkId(); |
+ // Set up the the guest's AX tree to point back at the embedder's AX tree. |
+ auto* parent_frame = outer_contents_frame->GetParent(); |
+ GetMainFrame()->set_browser_plugin_embedder_ax_tree_id( |
+ parent_frame->GetAXTreeID()); |
+ GetMainFrame()->UpdateAXTreeData(); |
+ |
// At this point, we should destroy the TextInputManager which will notify all |
// the RWHV in this WebContents. The RWHV in this WebContents should use the |
// TextInputManager owned by the outer WebContents. |
@@ -4329,6 +4347,20 @@ WebContentsImpl* WebContentsImpl::GetOutermostWebContents() { |
return root; |
} |
+void WebContentsImpl::FocusOuterAttachmentFrameChain() { |
+ WebContentsImpl* outer_contents = GetOuterWebContents(); |
+ if (!outer_contents) |
+ return; |
+ |
+ FrameTreeNode* outer_node = |
+ FrameTreeNode::GloballyFindByID(GetOuterDelegateFrameTreeNodeId()); |
+ outer_contents->frame_tree_.SetFocusedFrame(outer_node, nullptr); |
alexmos
2017/02/23 20:07:04
Can you please explain why this is now necessary?
avallee
2017/02/28 20:13:01
Maybe the site instance still needs to be passed a
alexmos
2017/03/03 20:07:57
Acknowledged.
Thinking about the source SiteIns
|
+ if (GetRenderManager()->GetProxyToOuterDelegate()) |
+ GetRenderManager()->GetProxyToOuterDelegate()->SetFocusedFrame(); |
+ |
+ outer_contents->FocusOuterAttachmentFrameChain(); |
+} |
+ |
void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { |
// Don't send notifications if we are just creating a swapped-out RVH for |
// the opener chain. These won't be used for view-source or WebUI, so it's |
@@ -4733,8 +4765,7 @@ void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() { |
// Make sure the outer web contents knows our frame is focused. Otherwise, the |
// outer renderer could have the element before or after the frame element |
// focused which would return early without actually advancing focus. |
- if (GetRenderManager()->GetProxyToOuterDelegate()) |
- GetRenderManager()->GetProxyToOuterDelegate()->SetFocusedFrame(); |
+ FocusOuterAttachmentFrameChain(); |
GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(true); |
GetOutermostWebContents()->node_->SetFocusedWebContents(this); |
@@ -4749,9 +4780,40 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node, |
return; |
} |
- SetAsFocusedWebContentsIfNecessary(); |
- |
frame_tree_.SetFocusedFrame(node, source); |
+ |
+ WebContentsImpl* inner_contents = nullptr; |
+ if (node_) |
+ inner_contents = node_->find_contents_at_node(node->frame_tree_node_id()); |
+ |
+ WebContentsImpl* contents_to_focus = inner_contents ? inner_contents : this; |
alexmos
2017/02/23 20:07:04
I'm a bit confused about this change also. See my
avallee
2017/02/28 20:13:00
If you clicked the webview before routing the inpu
alexmos
2017/03/03 20:07:57
Ack. I was confused that FocusOuterAttachmentFram
|
+ contents_to_focus->SetAsFocusedWebContentsIfNecessary(); |
+} |
+ |
+RenderFrameHost* WebContentsImpl::GetFocusedFrameIncludingInnerWebContents() { |
+ if (!node_) |
+ return GetFocusedFrame(); |
+ |
+ auto* contents = this; |
+ auto* focused_node = contents->frame_tree_.GetFocusedFrame(); |
alexmos
2017/02/23 20:07:04
nit: at least for me, an explicit type here instea
avallee
2017/02/28 20:13:00
Done.
|
+ |
+ // If there is no focused frame in the outer WebContents, we need to return |
+ // null. |
+ if (!focused_node) |
+ return nullptr; |
+ |
+ // We cannot return the frame where an inner WebContents is attached, if the |
+ // inner WebContents does not have a focused frame, return its main frame. |
+ while (true) { |
+ contents = contents->node_->find_contents_at_node( |
+ focused_node->frame_tree_node_id()); |
alexmos
2017/02/23 20:07:04
Why not just pass in the FTN* and retrieve the FTN
avallee
2017/02/28 20:13:01
Done.
|
+ if (!contents) |
+ return focused_node->current_frame_host(); |
+ |
+ focused_node = contents->frame_tree_.GetFocusedFrame(); |
+ if (!focused_node) |
+ return contents->GetMainFrame(); |
alexmos
2017/02/23 20:07:04
What makes this necessary? How can we get here in
avallee
2017/02/28 20:13:00
On attach or after reaching the end of content, th
alexmos
2017/03/03 20:07:57
Not quite sure what you meant by "after reaching t
avallee
2017/06/21 02:25:35
I think this will get called on attach, but as a r
|
+ } |
} |
void WebContentsImpl::OnFocusedElementChangedInFrame( |