| 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 e0d64d07eab267edf2e559e905078c3dfda9145c..a2cded7f09f970a2b72c2a43bb4b156337457b11 100644
 | 
| --- a/content/browser/web_contents/web_contents_impl.cc
 | 
| +++ b/content/browser/web_contents/web_contents_impl.cc
 | 
| @@ -257,6 +257,14 @@ class AXTreeSnapshotCombiner : public base::RefCounted<AXTreeSnapshotCombiner> {
 | 
|    AXTreeSnapshotCallback callback_;
 | 
|  };
 | 
|  
 | 
| +// Helper for GetInnerWebContents().
 | 
| +bool GetInnerWebContentsHelper(
 | 
| +    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 +389,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 +402,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 +441,23 @@ void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents(
 | 
|    focused_web_contents_ = web_contents;
 | 
|  }
 | 
|  
 | 
| +WebContentsImpl*
 | 
| +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;
 | 
| +    }
 | 
| +  }
 | 
| +  return nullptr;
 | 
| +}
 | 
| +
 | 
| +const std::vector<WebContentsImpl*>&
 | 
| +WebContentsImpl::WebContentsTreeNode::inner_web_contents() const {
 | 
| +  return inner_web_contents_;
 | 
| +}
 | 
| +
 | 
|  // WebContentsImpl -------------------------------------------------------------
 | 
|  
 | 
|  WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
 | 
| @@ -664,7 +708,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()));
 | 
|  }
 | 
| @@ -681,6 +725,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();
 | 
|  }
 | 
| @@ -1038,6 +1089,29 @@ WebContentsBindingSet* WebContentsImpl::GetBindingSet(
 | 
|    return it->second;
 | 
|  }
 | 
|  
 | 
| +std::vector<WebContentsImpl*> WebContentsImpl::GetInnerWebContents() {
 | 
| +  if (browser_plugin_embedder_) {
 | 
| +    std::vector<WebContentsImpl*> inner_contents;
 | 
| +    GetBrowserContext()->GetGuestManager()->ForEachGuest(
 | 
| +        this, base::Bind(&GetInnerWebContentsHelper, &inner_contents));
 | 
| +    return inner_contents;
 | 
| +  }
 | 
| +
 | 
| +  return node_.inner_web_contents();
 | 
| +}
 | 
| +
 | 
| +std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() {
 | 
| +  std::vector<WebContentsImpl*> all_contents(1, this);
 | 
| +
 | 
| +  for (size_t i = 0; i != all_contents.size(); ++i) {
 | 
| +    for (auto* inner_contents : all_contents[i]->GetInnerWebContents()) {
 | 
| +      all_contents.push_back(inner_contents);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  return all_contents;
 | 
| +}
 | 
| +
 | 
|  void WebContentsImpl::UpdateDeviceScaleFactor(double device_scale_factor) {
 | 
|    SendPageMessage(
 | 
|        new PageMsg_SetDeviceScaleFactor(MSG_ROUTING_NONE, device_scale_factor));
 | 
| @@ -1859,8 +1933,15 @@ RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost(
 | 
|          ->GetRenderWidgetHost();
 | 
|    }
 | 
|  
 | 
| -  FrameTreeNode* focused_frame =
 | 
| -      focused_contents->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;
 | 
| +  if (focused_contents->browser_plugin_guest_ &&
 | 
| +      !GuestMode::IsCrossProcessFrameGuest(focused_contents)) {
 | 
| +    focused_frame = frame_tree_.GetFocusedFrame();
 | 
| +  } else {
 | 
| +    focused_frame = GetFocusedWebContents()->frame_tree_.GetFocusedFrame();
 | 
| +  }
 | 
|  
 | 
|    if (!focused_frame)
 | 
|      return receiving_widget;
 | 
| @@ -3323,25 +3404,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() {
 | 
| @@ -3796,6 +3864,9 @@ void WebContentsImpl::OnFindReply(RenderFrameHostImpl* source,
 | 
|                                    const gfx::Rect& selection_rect,
 | 
|                                    int active_match_ordinal,
 | 
|                                    bool final_update) {
 | 
| +  if (active_match_ordinal > 0)
 | 
| +    SetFocusedFrame(source->frame_tree_node(), source->GetSiteInstance());
 | 
| +
 | 
|    // Forward the find reply to the FindRequestManager, along with the
 | 
|    // RenderFrameHost associated with the frame that the reply came from.
 | 
|    GetOrCreateFindRequestManager()->OnFindReply(
 | 
| @@ -4800,6 +4871,11 @@ void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
 | 
|    if (old_contents == this)
 | 
|      return;
 | 
|  
 | 
| +  GetOutermostWebContents()->node_.SetFocusedWebContents(this);
 | 
| +
 | 
| +  if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_)
 | 
| +    return;
 | 
| +
 | 
|    // Send a page level blur to the old contents so that it displays inactive UI
 | 
|    // and focus this contents to activate it.
 | 
|    if (old_contents)
 | 
| @@ -4819,20 +4895,11 @@ void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
 | 
|    } else {
 | 
|      GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(true);
 | 
|    }
 | 
| -  GetOutermostWebContents()->node_.SetFocusedWebContents(this);
 | 
|  }
 | 
|  
 | 
|  void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
 | 
|                                        SiteInstance* source) {
 | 
| -  // The PDF plugin still runs as a BrowserPlugin and must go through the
 | 
| -  // input redirection mechanism. It must not become focused direcly.
 | 
| -  if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) {
 | 
| -    frame_tree_.SetFocusedFrame(node, source);
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
|    SetAsFocusedWebContentsIfNecessary();
 | 
| -
 | 
|    frame_tree_.SetFocusedFrame(node, source);
 | 
|  }
 | 
|  
 | 
| @@ -5275,12 +5342,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();
 | 
|  }
 | 
| @@ -5332,6 +5421,12 @@ void WebContentsImpl::SetHasPersistentVideo(bool has_persistent_video) {
 | 
|    media_web_contents_observer()->RequestPersistentVideo(has_persistent_video);
 | 
|  }
 | 
|  
 | 
| +void WebContentsImpl::BrowserPluginGuestWillDetach() {
 | 
| +  WebContentsImpl* outermost = GetOutermostWebContents();
 | 
| +  if (this != outermost && ContainsOrIsFocusedWebContents())
 | 
| +    outermost->SetAsFocusedWebContentsIfNecessary();
 | 
| +}
 | 
| +
 | 
|  #if defined(OS_ANDROID)
 | 
|  void WebContentsImpl::NotifyFindMatchRectsReply(
 | 
|      int version,
 | 
| 
 |