Chromium Code Reviews| 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, |