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 b1653692c42112e5fb0c051641545d6f62903c23..205fe7b6f4880e3f3d4d0b9c277347347c294921 100644 |
--- a/content/browser/web_contents/web_contents_impl.cc |
+++ b/content/browser/web_contents/web_contents_impl.cc |
@@ -257,6 +257,13 @@ class AXTreeSnapshotCombiner : public base::RefCounted<AXTreeSnapshotCombiner> { |
AXTreeSnapshotCallback callback_; |
}; |
+// Helper for GetWebContentsAndAllInner(). |
+bool GetWebContentsHelper(std::vector<WebContentsImpl*>* all_guest_contents, |
+ WebContents* guest_contents) { |
+ all_guest_contents->push_back(static_cast<WebContentsImpl*>(guest_contents)); |
+ return false; |
+} |
+ |
} // namespace |
WebContents* WebContents::Create(const WebContents::CreateParams& params) { |
@@ -381,6 +388,9 @@ WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode( |
WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { |
if (OuterContentsFrameTreeNode()) |
OuterContentsFrameTreeNode()->RemoveObserver(this); |
+ |
+ if (outer_web_contents_) |
+ outer_web_contents_->node_.DetachInnerWebContents(current_web_contents_); |
} |
void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( |
@@ -391,9 +401,25 @@ void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( |
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_contents_frame->frame_tree_node()->AddObserver(this); |
} |
+void WebContentsImpl::WebContentsTreeNode::AttachInnerWebContents( |
+ WebContentsImpl* inner_web_contents) { |
+ inner_web_contents_.push_back(inner_web_contents); |
+} |
+ |
+void WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents( |
+ WebContentsImpl* inner_web_contents) { |
+ DCHECK(std::find(inner_web_contents_.begin(), inner_web_contents_.end(), |
+ inner_web_contents) != inner_web_contents_.end()); |
+ inner_web_contents_.erase( |
+ std::remove(inner_web_contents_.begin(), inner_web_contents_.end(), |
+ inner_web_contents), |
+ inner_web_contents_.end()); |
+} |
+ |
FrameTreeNode* |
WebContentsImpl::WebContentsTreeNode::OuterContentsFrameTreeNode() const { |
return FrameTreeNode::GloballyFindByID(outer_contents_frame_tree_node_id_); |
@@ -414,6 +440,23 @@ void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents( |
focused_web_contents_ = web_contents; |
} |
+WebContentsImpl* |
+WebContentsImpl::WebContentsTreeNode::GetInnerWebContentsInFrame( |
+ const FrameTreeNode* frame) { |
+ for (auto* contents : inner_web_contents_) |
+ if (contents->node_.OuterContentsFrameTreeNode() == frame) |
ncarter (slow)
2017/03/27 23:21:37
Might be faster to do this?
auto ftn_id = frame->
paulmeyer
2017/03/31 18:31:16
Agreed. Done.
|
+ return contents; |
+ return nullptr; |
+} |
+ |
+void WebContentsImpl::WebContentsTreeNode::GetAllInnerWebContents( |
+ std::vector<WebContentsImpl*>* all_contents) { |
+ for (auto* contents : inner_web_contents_) { |
+ all_contents->push_back(contents); |
+ contents->node_.GetAllInnerWebContents(all_contents); |
+ } |
+} |
+ |
// WebContentsImpl ------------------------------------------------------------- |
WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) |
@@ -661,7 +704,7 @@ std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() { |
// static |
WebContentsImpl* WebContentsImpl::FromFrameTreeNode( |
- FrameTreeNode* frame_tree_node) { |
+ const FrameTreeNode* frame_tree_node) { |
return static_cast<WebContentsImpl*>( |
WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host())); |
} |
@@ -678,6 +721,13 @@ WebContents* WebContentsImpl::FromRenderFrameHostID(int render_process_host_id, |
return WebContents::FromRenderFrameHost(render_frame_host); |
} |
+// static |
+WebContentsImpl* WebContentsImpl::FromOuterFrameTreeNode( |
+ const FrameTreeNode* frame_tree_node) { |
+ return WebContentsImpl::FromFrameTreeNode(frame_tree_node)-> |
+ node_.GetInnerWebContentsInFrame(frame_tree_node); |
+} |
+ |
RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() { |
return GetRenderManager(); |
} |
@@ -1033,6 +1083,19 @@ WebContentsBindingSet* WebContentsImpl::GetBindingSet( |
return it->second; |
} |
+std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() { |
+ std::vector<WebContentsImpl*> all_contents(1, this); |
+ |
+ if (browser_plugin_embedder_) { |
+ GetBrowserContext()->GetGuestManager()->ForEachGuest( |
+ this, base::Bind(&GetWebContentsHelper, &all_contents)); |
+ } else { |
+ node_.GetAllInnerWebContents(&all_contents); |
+ } |
+ |
+ return all_contents; |
+} |
+ |
void WebContentsImpl::UpdateDeviceScaleFactor(double device_scale_factor) { |
SendPageMessage( |
new PageMsg_SetDeviceScaleFactor(MSG_ROUTING_NONE, device_scale_factor)); |
@@ -1843,8 +1906,16 @@ RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost( |
if (receiving_widget != GetMainFrame()->GetRenderWidgetHost()) |
return receiving_widget; |
- FrameTreeNode* focused_frame = |
- GetFocusedWebContents()->frame_tree_.GetFocusedFrame(); |
+ // If the focused WebContents is a guest WebContents, then get the focused |
+ // frame in the embedder WebContents instead. |
+ FrameTreeNode* focused_frame = nullptr; |
+ WebContentsImpl* focused_contents = GetFocusedWebContents(); |
+ if (focused_contents->browser_plugin_guest_ && |
+ !GuestMode::IsCrossProcessFrameGuest(focused_contents)) { |
+ focused_frame = frame_tree_.GetFocusedFrame(); |
+ } else { |
+ focused_frame = GetFocusedWebContents()->frame_tree_.GetFocusedFrame(); |
+ } |
ncarter (slow)
2017/03/27 23:21:37
Is this an orthogonal bugfix? What implications do
paulmeyer
2017/03/31 18:31:16
Actually, I don't think this is even necessary any
|
if (!focused_frame) |
return receiving_widget; |
@@ -3261,25 +3332,12 @@ void WebContentsImpl::Find(int request_id, |
return; |
} |
- // See if a top level browser plugin handles the find request first. |
- // TODO(paulmeyer): Remove this after find-in-page works across GuestViews. |
- if (browser_plugin_embedder_ && |
- browser_plugin_embedder_->Find(request_id, search_text, options)) { |
- return; |
- } |
- |
GetOrCreateFindRequestManager()->Find(request_id, search_text, options); |
} |
void WebContentsImpl::StopFinding(StopFindAction action) { |
- // See if a top level browser plugin handles the stop finding request first. |
- // TODO(paulmeyer): Remove this after find-in-page works across GuestViews. |
- if (browser_plugin_embedder_ && |
- browser_plugin_embedder_->StopFinding(action)) { |
- return; |
- } |
- |
- GetOrCreateFindRequestManager()->StopFinding(action); |
+ if (FindRequestManager* manager = GetFindRequestManager()) |
+ manager->StopFinding(action); |
} |
bool WebContentsImpl::WasRecentlyAudible() { |
@@ -4749,6 +4807,8 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node, |
// input redirection mechanism. It must not become focused direcly. |
if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) { |
frame_tree_.SetFocusedFrame(node, source); |
+ if (GetFocusedWebContents() != this) |
+ GetOutermostWebContents()->node_.SetFocusedWebContents(this); |
return; |
} |
@@ -5201,12 +5261,34 @@ std::unique_ptr<WebUIImpl> WebContentsImpl::CreateWebUI( |
return nullptr; |
} |
+FindRequestManager* WebContentsImpl::GetFindRequestManager() { |
+ for (WebContentsImpl* contents = this; contents; |
+ contents = contents->GetOuterWebContents()) { |
+ if (contents->find_request_manager_) |
+ return contents->find_request_manager_.get(); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
FindRequestManager* WebContentsImpl::GetOrCreateFindRequestManager() { |
- // TODO(paulmeyer): This method will need to access (or potentially create) |
- // the FindRequestManager in the outermost WebContents once find-in-page |
- // across GuestViews is implemented. |
- if (!find_request_manager_) |
- find_request_manager_.reset(new FindRequestManager(this)); |
+ if (FindRequestManager* manager = GetFindRequestManager()) |
+ return manager; |
+ |
+ // No existing FindRequestManager found, so one must be created. |
+ find_request_manager_.reset(new FindRequestManager(this)); |
+ |
+ // Concurrent find sessions must not overlap, so destroy any existing |
+ // FindRequestManagers in any inner WebContentses. |
+ for (WebContentsImpl* contents : GetWebContentsAndAllInner()) { |
+ if (contents == this) |
+ continue; |
+ if (contents->find_request_manager_) { |
+ contents->find_request_manager_->StopFinding( |
+ content::STOP_FIND_ACTION_CLEAR_SELECTION); |
+ contents->find_request_manager_.release(); |
+ } |
+ } |
return find_request_manager_.get(); |
} |
@@ -5258,6 +5340,12 @@ void WebContentsImpl::SetHasPersistentVideo(bool has_persistent_video) { |
media_web_contents_observer()->RequestPersistentVideo(has_persistent_video); |
} |
+void WebContentsImpl::BrowserPluginGuestWillDestroy() { |
+ WebContentsImpl* outermost = GetOutermostWebContents(); |
+ if (this != outermost && ContainsOrIsFocusedWebContents()) |
+ outermost->SetAsFocusedWebContentsIfNecessary(); |
+} |
+ |
#if defined(OS_ANDROID) |
void WebContentsImpl::NotifyFindMatchRectsReply( |
int version, |