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

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: Blink ASSERT was missing.. 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* web_contents)
333 : web_contents_(web_contents),
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& child : inner_web_contents_tree_nodes_)
352 child->outer_web_contents_ = nullptr; 354 child.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::FindInnerWebContentsAtFrame(
375 const FrameTreeNode* node) const {
376 auto iter = inner_web_contents_tree_nodes_.find(node->frame_tree_node_id());
377 if (iter != inner_web_contents_tree_nodes_.end()) {
378 return iter->second->web_contents_;
379 }
380 return nullptr;
366 } 381 }
367 382
368 // WebContentsImpl ------------------------------------------------------------- 383 // WebContentsImpl -------------------------------------------------------------
369 384
370 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) 385 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
371 : delegate_(NULL), 386 : delegate_(NULL),
372 controller_(this, browser_context), 387 controller_(this, browser_context),
373 render_view_host_delegate_view_(NULL), 388 render_view_host_delegate_view_(NULL),
374 created_with_opener_(false), 389 created_with_opener_(false),
375 frame_tree_(new NavigatorImpl(&controller_, this), 390 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 1401 // created. This is needed because the usual initialization happens during
1387 // the first navigation, but when attaching a new window we don't navigate 1402 // 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 1403 // before attaching. If the browser side is already initialized, the calls
1389 // below will just early return. 1404 // below will just early return.
1390 render_manager->InitRenderView(GetRenderViewHost(), nullptr); 1405 render_manager->InitRenderView(GetRenderViewHost(), nullptr);
1391 GetMainFrame()->Init(); 1406 GetMainFrame()->Init();
1392 if (!render_manager->GetRenderWidgetHostView()) 1407 if (!render_manager->GetRenderWidgetHostView())
1393 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost()); 1408 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost());
1394 1409
1395 // Create a link to our outer WebContents. 1410 // Create a link to our outer WebContents.
1396 node_.reset(new WebContentsTreeNode()); 1411 node_.reset(new WebContentsTreeNode(this));
1397 node_->ConnectToOuterWebContents( 1412 node_->ConnectToOuterWebContents(
1398 static_cast<WebContentsImpl*>(outer_web_contents), 1413 static_cast<WebContentsImpl*>(outer_web_contents),
1399 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); 1414 static_cast<RenderFrameHostImpl*>(outer_contents_frame));
1400 1415
1401 DCHECK(outer_contents_frame); 1416 DCHECK(outer_contents_frame);
1402 1417
1403 // Create a proxy in top-level RenderFrameHostManager, pointing to the 1418 // Create a proxy in top-level RenderFrameHostManager, pointing to the
1404 // SiteInstance of the outer WebContents. The proxy will be used to send 1419 // SiteInstance of the outer WebContents. The proxy will be used to send
1405 // postMessage to the inner WebContents. 1420 // postMessage to the inner WebContents.
1406 render_manager->CreateOuterDelegateProxy( 1421 render_manager->CreateOuterDelegateProxy(
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 1801
1787 // Events for widgets other than the main frame (e.g., popup menus) should be 1802 // Events for widgets other than the main frame (e.g., popup menus) should be
1788 // forwarded directly to the widget they arrived on. 1803 // forwarded directly to the widget they arrived on.
1789 if (receiving_widget != GetMainFrame()->GetRenderWidgetHost()) 1804 if (receiving_widget != GetMainFrame()->GetRenderWidgetHost())
1790 return receiving_widget; 1805 return receiving_widget;
1791 1806
1792 FrameTreeNode* focused_frame = frame_tree_.GetFocusedFrame(); 1807 FrameTreeNode* focused_frame = frame_tree_.GetFocusedFrame();
1793 if (!focused_frame) 1808 if (!focused_frame)
1794 return receiving_widget; 1809 return receiving_widget;
1795 1810
1811 // If there is an inner web contents (<webview>, <guestview>, ...) with focus,
1812 // return its RenderWidgetHost. This will recurse to an arbitrary number of
1813 // WebContents to the deepest focused one.
1814 WebContentsImpl* inner_contents =
1815 (node_) ? node_->FindInnerWebContentsAtFrame(focused_frame) : 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 RenderWidgetHostImpl* rwh = node->current_frame_host()->GetRenderWidgetHost();
4517 if (rwh)
4518 rwh->Focus();
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.
4531
4532 FrameTreeNode* old_focused_node = frame_tree_.GetFocusedFrame();
4533
4534 if (old_focused_node != nullptr && node_) {
4535 if (!node || old_focused_node != node) {
4536 WebContentsImpl* inner_contents =
4537 node_->FindInnerWebContentsAtFrame(old_focused_node);
4538 if (inner_contents)
4539 inner_contents->SetFocusedFrameInternal(nullptr, source, false);
4540 }
4541 }
4542
4543 // focus in parent.
4544 WebContentsImpl* 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 FrameTreeNode* 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(
4555 outer_contents->frame_tree_.root(), source, true);
4556 } else {
4557 // Notify outer about our focus change.
4558 SiteInstance* outer_node_site_instance =
4559 outer_node->parent()->current_frame_host()->GetSiteInstance();
alexmos 2016/05/19 00:08:09 I don't think you need parent() here -- seems like
avallee 2016/05/24 20:07:08 lfg suggested the change as the outer_node does no
4560 RenderFrameProxyHost* outer_proxy =
4561 frame_tree_.root()->render_manager()->GetRenderFrameProxyHost(
4562 outer_node_site_instance);
4563 if (outer_proxy)
4564 outer_proxy->SetFocusedFrame();
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