Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1294)

Unified Diff: content/browser/web_contents/web_contents_impl.cc

Issue 2700613003: Enable find-in-page across GuestViews. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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,

Powered by Google App Engine
This is Rietveld 408576698