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

Side by Side Diff: content/browser/web_contents/web_contents_impl.cc

Issue 1934703002: Fix keyboard focus for OOPIF-<webview>. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments. Fix tab focus change. Created 4 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/web_contents/web_contents_impl.h" 5 #include "content/browser/web_contents/web_contents_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <cmath> 9 #include <cmath>
10 #include <utility> 10 #include <utility>
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 : render_process_id(render_process_id), 321 : render_process_id(render_process_id),
322 render_frame_id(render_frame_id), 322 render_frame_id(render_frame_id),
323 chooser(chooser), 323 chooser(chooser),
324 identifier(identifier) { 324 identifier(identifier) {
325 } 325 }
326 326
327 WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() { 327 WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
328 } 328 }
329 329
330 // WebContentsImpl::WebContentsTreeNode ---------------------------------------- 330 // WebContentsImpl::WebContentsTreeNode ----------------------------------------
331 WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode() 331 WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode(
332 : outer_web_contents_(nullptr), 332 WebContentsImpl* inner)
333 : inner_web_contents_(inner),
334 outer_web_contents_(nullptr),
333 outer_contents_frame_tree_node_id_( 335 outer_contents_frame_tree_node_id_(
334 FrameTreeNode::kFrameTreeNodeInvalidId) { 336 FrameTreeNode::kFrameTreeNodeInvalidId) {}
335 }
336 337
337 WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { 338 WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() {
338 // Remove child pointer from our parent. 339 // Remove child pointer from our parent.
339 if (outer_web_contents_) { 340 if (outer_web_contents_) {
340 ChildrenSet& child_ptrs_in_parent = 341 ChildrenMap& child_ptrs_in_parent =
341 outer_web_contents_->node_->inner_web_contents_tree_nodes_; 342 outer_web_contents_->node_->inner_web_contents_tree_nodes_;
342 ChildrenSet::iterator iter = child_ptrs_in_parent.find(this); 343 ChildrenMap::iterator iter =
344 child_ptrs_in_parent.find(outer_contents_frame_tree_node_id_);
343 DCHECK(iter != child_ptrs_in_parent.end()); 345 DCHECK(iter != child_ptrs_in_parent.end());
344 child_ptrs_in_parent.erase(this); 346 child_ptrs_in_parent.erase(iter);
345 } 347 }
346 348
347 // Remove parent pointers from our children. 349 // Remove parent pointers from our children.
348 // TODO(lazyboy): We should destroy the children WebContentses too. If the 350 // TODO(lazyboy): We should destroy the children WebContentses too. If the
349 // children do not manage their own lifetime, then we would leak their 351 // children do not manage their own lifetime, then we would leak their
350 // WebContentses. 352 // WebContentses.
351 for (WebContentsTreeNode* child : inner_web_contents_tree_nodes_) 353 for (auto& children : inner_web_contents_tree_nodes_)
alexmos 2016/05/12 20:28:41 nit: s/children/child/ (it's still referring to j
avallee 2016/05/16 20:26:43 Done.
352 child->outer_web_contents_ = nullptr; 354 children.second->outer_web_contents_ = nullptr;
353 } 355 }
354 356
355 void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( 357 void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents(
356 WebContentsImpl* outer_web_contents, 358 WebContentsImpl* outer_web_contents,
357 RenderFrameHostImpl* outer_contents_frame) { 359 RenderFrameHostImpl* outer_contents_frame) {
358 outer_web_contents_ = outer_web_contents; 360 outer_web_contents_ = outer_web_contents;
359 outer_contents_frame_tree_node_id_ = 361 outer_contents_frame_tree_node_id_ =
360 outer_contents_frame->frame_tree_node()->frame_tree_node_id(); 362 outer_contents_frame->frame_tree_node()->frame_tree_node_id();
361 363
362 if (!outer_web_contents_->node_) 364 if (!outer_web_contents_->node_)
363 outer_web_contents_->node_.reset(new WebContentsTreeNode()); 365 outer_web_contents_->node_.reset(
366 new WebContentsTreeNode(outer_web_contents_));
364 367
365 outer_web_contents_->node_->inner_web_contents_tree_nodes_.insert(this); 368 outer_web_contents_->node_
369 ->inner_web_contents_tree_nodes_[outer_contents_frame_tree_node_id_] =
370 this;
371 }
372
373 const WebContentsImpl*
374 WebContentsImpl::WebContentsTreeNode::FindContentsForFrame(int frame_id) const {
375 auto iter = inner_web_contents_tree_nodes_.find(frame_id);
376 if (iter != inner_web_contents_tree_nodes_.end()) {
377 return iter->second->inner_web_contents_;
378 }
379 return nullptr;
366 } 380 }
367 381
368 // WebContentsImpl ------------------------------------------------------------- 382 // WebContentsImpl -------------------------------------------------------------
369 383
370 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) 384 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
371 : delegate_(NULL), 385 : delegate_(NULL),
372 controller_(this, browser_context), 386 controller_(this, browser_context),
373 render_view_host_delegate_view_(NULL), 387 render_view_host_delegate_view_(NULL),
374 created_with_opener_(false), 388 created_with_opener_(false),
375 frame_tree_(new NavigatorImpl(&controller_, this), 389 frame_tree_(new NavigatorImpl(&controller_, this),
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after
1386 // created. This is needed because the usual initialization happens during 1400 // created. This is needed because the usual initialization happens during
1387 // the first navigation, but when attaching a new window we don't navigate 1401 // the first navigation, but when attaching a new window we don't navigate
1388 // before attaching. If the browser side is already initialized, the calls 1402 // before attaching. If the browser side is already initialized, the calls
1389 // below will just early return. 1403 // below will just early return.
1390 render_manager->InitRenderView(GetRenderViewHost(), nullptr); 1404 render_manager->InitRenderView(GetRenderViewHost(), nullptr);
1391 GetMainFrame()->Init(); 1405 GetMainFrame()->Init();
1392 if (!render_manager->GetRenderWidgetHostView()) 1406 if (!render_manager->GetRenderWidgetHostView())
1393 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost()); 1407 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost());
1394 1408
1395 // Create a link to our outer WebContents. 1409 // Create a link to our outer WebContents.
1396 node_.reset(new WebContentsTreeNode()); 1410 node_.reset(new WebContentsTreeNode(this));
1397 node_->ConnectToOuterWebContents( 1411 node_->ConnectToOuterWebContents(
1398 static_cast<WebContentsImpl*>(outer_web_contents), 1412 static_cast<WebContentsImpl*>(outer_web_contents),
1399 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); 1413 static_cast<RenderFrameHostImpl*>(outer_contents_frame));
1400 1414
1401 DCHECK(outer_contents_frame); 1415 DCHECK(outer_contents_frame);
1402 1416
1403 // Create a proxy in top-level RenderFrameHostManager, pointing to the 1417 // Create a proxy in top-level RenderFrameHostManager, pointing to the
1404 // SiteInstance of the outer WebContents. The proxy will be used to send 1418 // SiteInstance of the outer WebContents. The proxy will be used to send
1405 // postMessage to the inner WebContents. 1419 // postMessage to the inner WebContents.
1406 render_manager->CreateOuterDelegateProxy( 1420 render_manager->CreateOuterDelegateProxy(
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 1800
1787 // Events for widgets other than the main frame (e.g., popup menus) should be 1801 // Events for widgets other than the main frame (e.g., popup menus) should be
1788 // forwarded directly to the widget they arrived on. 1802 // forwarded directly to the widget they arrived on.
1789 if (receiving_widget != GetMainFrame()->GetRenderWidgetHost()) 1803 if (receiving_widget != GetMainFrame()->GetRenderWidgetHost())
1790 return receiving_widget; 1804 return receiving_widget;
1791 1805
1792 FrameTreeNode* focused_frame = frame_tree_.GetFocusedFrame(); 1806 FrameTreeNode* focused_frame = frame_tree_.GetFocusedFrame();
1793 if (!focused_frame) 1807 if (!focused_frame)
1794 return receiving_widget; 1808 return receiving_widget;
1795 1809
1810 // If there is an inner web contents (<webview>, <guestview>, ...) with focus,
1811 // return its RenderWidgetHost.
alexmos 2016/05/12 20:28:40 This will recurse down if there are multiple level
avallee 2016/05/16 20:26:43 Done.
1812 WebContentsImpl* inner_contents =
1813 (node_.get())
alexmos 2016/05/12 20:28:42 nit: .get() shouldn't be necessary
avallee 2016/05/16 20:26:44 Done.
1814 ? node_->FindContentsForFrame(focused_frame->frame_tree_node_id())
1815 : nullptr;
1816 if (inner_contents) {
1817 return inner_contents->GetFocusedRenderWidgetHost(
1818 inner_contents->GetMainFrame()->GetRenderWidgetHost());
1819 }
1796 // The view may be null if a subframe's renderer process has crashed while 1820 // The view may be null if a subframe's renderer process has crashed while
1797 // the subframe has focus. Drop the event in that case. Do not give 1821 // the subframe has focus. Drop the event in that case. Do not give
1798 // it to the main frame, so that the user doesn't unexpectedly type into the 1822 // it to the main frame, so that the user doesn't unexpectedly type into the
1799 // wrong frame if a focused subframe renderer crashes while they type. 1823 // wrong frame if a focused subframe renderer crashes while they type.
1800 RenderWidgetHostView* view = focused_frame->current_frame_host()->GetView(); 1824 RenderWidgetHostView* view = focused_frame->current_frame_host()->GetView();
1801 if (!view) 1825 if (!view)
1802 return nullptr; 1826 return nullptr;
1803 1827
1804 return RenderWidgetHostImpl::From(view->GetRenderWidgetHost()); 1828 return RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
1805 } 1829 }
(...skipping 2672 matching lines...) Expand 10 before | Expand all | Expand 10 after
4478 GetSiteInstance()); 4502 GetSiteInstance());
4479 } else { 4503 } else {
4480 RenderFrameHostImpl* source_rfhi = 4504 RenderFrameHostImpl* source_rfhi =
4481 static_cast<RenderFrameHostImpl*>(source_rfh); 4505 static_cast<RenderFrameHostImpl*>(source_rfh);
4482 source_rfhi->frame_tree_node()->render_manager()->CreateOpenerProxies( 4506 source_rfhi->frame_tree_node()->render_manager()->CreateOpenerProxies(
4483 GetSiteInstance(), nullptr); 4507 GetSiteInstance(), nullptr);
4484 } 4508 }
4485 } 4509 }
4486 } 4510 }
4487 4511
4512 void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
4513 SiteInstance* source) {
4514 SetFocusedFrameInternal(node, source, true /* can visit outer contents */);
4515
4516 auto rwh = node->current_frame_host()->GetRenderWidgetHost();
alexmos 2016/05/12 20:28:40 nit: RenderWidgetHostImpl* instead of auto might b
avallee 2016/05/16 20:26:43 Done.
4517 if (rwh)
4518 rwh->Focus();
alexmos 2016/05/12 20:28:40 Why is this necessary? Page focus and frame focus
avallee 2016/05/16 20:26:43 Without this call, the renderer for the webview do
alexmos 2016/05/19 00:08:09 Yup, that very likely indicates a problem with pag
avallee 2016/05/24 20:07:07 Added note in code. Will fix in follow-up cl. My f
4519 }
4520
4521 void WebContentsImpl::SetFocusedFrameInternal(FrameTreeNode* node,
4522 SiteInstance* source,
4523 bool can_visit_outer_contents) {
4524 // Approach: Recursively unfocus any inner web contents. Then set
4525 // representation of this web contents in the outer contents to be focused,
4526 // finally focus the node in current frame tree.
4527 //
4528 // Usually only one of unfocusing children and focusing self in parent would
4529 // happen. If unfocusing a child, then we're already focused in our parent, if
4530 // we have one.
alexmos 2016/05/12 20:28:40 I had trouble following this comment when I first
avallee 2016/05/16 20:26:43 Here's an enhanced version of your example https:/
alexmos 2016/05/19 00:08:09 Thanks for the detailed examples, this makes sense
avallee 2016/05/24 20:07:07 Your approach I think would work nicely. It's simp
4531
4532 auto old_focus_node = frame_tree_.GetFocusedFrame();
alexmos 2016/05/12 20:28:40 nit: s/old_focus_node/old_focused_node/
avallee 2016/05/16 20:26:43 Done.
4533
4534 if (old_focus_node != nullptr && node_.get()) {
alexmos 2016/05/12 20:28:42 nit: .get() not necessary
avallee 2016/05/16 20:26:44 Done.
4535 if (!node || old_focus_node != node) {
4536 WebContentsImpl* inner_contents =
4537 node_->FindContentsForFrame(old_focus_node->frame_tree_node_id());
4538 if (inner_contents)
4539 inner_contents->SetFocusedFrameInternal(nullptr, source, false);
alexmos 2016/05/12 20:28:41 I think this whole function could be simplified to
avallee 2016/05/16 20:26:43 I agree that the split could work. 1. Find the com
alexmos 2016/05/19 00:08:09 This makes sense, though I'm not sure if the code
4540 }
4541 }
4542
4543 // focus in parent.
4544 auto outer_contents = GetOuterWebContents();
4545 // If we're coming from parent, we don't want to recurse back into the parent.
4546 if (outer_contents && can_visit_outer_contents) {
4547 auto outer_node =
4548 outer_contents->frame_tree_.FindByID(GetOuterDelegateFrameTreeNodeId());
4549 if (outer_node == nullptr) {
4550 // With browser plugin, we will have an outer contents but no node in the
4551 // outer contents' frame tree.
4552 // HACK: We are assuming that the guest contents can only be embedded
4553 // within the embedder's main frame.
4554 outer_contents->SetFocusedFrameInternal(
alexmos 2016/05/12 20:28:40 Please follow up on this hack with BrowserPlugin e
avallee 2016/05/16 20:26:44 We tested it and it seems we can only embed in the
alexmos 2016/05/19 00:08:09 Acknowledged. Can you remove the "HACK" from the
avallee 2016/05/24 20:07:07 Deleted this whole function.
4555 outer_contents->frame_tree_.root(), source, true);
4556 } else {
4557 // Notify outer about our focus change.
4558 auto outer_node_site_instance =
4559 outer_node->parent()->current_frame_host()->GetSiteInstance();
4560 auto outer_proxy =
4561 frame_tree_.root()->render_manager()->GetRenderFrameProxyHost(
4562 outer_node_site_instance);
4563 if (outer_proxy)
alexmos 2016/05/12 20:28:40 Why would outer_proxy be null? After talking thro
avallee 2016/05/16 20:26:44 Agreed, it should exist.
alexmos 2016/05/19 00:08:09 So then, can you remove this if?
avallee 2016/05/24 20:07:07 Deleted
4564 outer_proxy->SetFocusedFrame();
alexmos 2016/05/12 20:28:42 Won't you notify the embedder's SiteInstance as pa
avallee 2016/05/16 20:26:43 For the webview specific case, the rfp that we wan
alexmos 2016/05/19 00:08:09 Sorry, I'm confused about this. Consider the samp
avallee 2016/05/24 20:07:07 I think that this is no longer necessary with the
4565 outer_contents->SetFocusedFrameInternal(outer_node, source, true);
4566 }
4567 }
4568 // Set focus for myself.
4569 frame_tree_.SetFocusedFrame(node, source);
4570 }
4571
4488 bool WebContentsImpl::AddMessageToConsole(int32_t level, 4572 bool WebContentsImpl::AddMessageToConsole(int32_t level,
4489 const base::string16& message, 4573 const base::string16& message,
4490 int32_t line_no, 4574 int32_t line_no,
4491 const base::string16& source_id) { 4575 const base::string16& source_id) {
4492 if (!delegate_) 4576 if (!delegate_)
4493 return false; 4577 return false;
4494 return delegate_->AddMessageToConsole(this, level, message, line_no, 4578 return delegate_->AddMessageToConsole(this, level, message, line_no,
4495 source_id); 4579 source_id);
4496 } 4580 }
4497 4581
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
5015 for (RenderViewHost* render_view_host : render_view_host_set) 5099 for (RenderViewHost* render_view_host : render_view_host_set)
5016 render_view_host->OnWebkitPreferencesChanged(); 5100 render_view_host->OnWebkitPreferencesChanged();
5017 } 5101 }
5018 5102
5019 void WebContentsImpl::SetJavaScriptDialogManagerForTesting( 5103 void WebContentsImpl::SetJavaScriptDialogManagerForTesting(
5020 JavaScriptDialogManager* dialog_manager) { 5104 JavaScriptDialogManager* dialog_manager) {
5021 dialog_manager_ = dialog_manager; 5105 dialog_manager_ = dialog_manager;
5022 } 5106 }
5023 5107
5024 } // namespace content 5108 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698