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

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: Ready for review: Fix works with oopif webview but does not fix crbug.com/609903 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_)
lfg 2016/05/06 21:23:33 Use auto&, so you don't make a copy of the pair to
avallee 2016/05/11 18:26:11 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 WebContentsImpl* WebContentsImpl::WebContentsTreeNode::find_contents_for_frame(
374 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.
1812 WebContentsImpl* inner_contents =
1813 (node_.get())
1814 ? node_->find_contents_for_frame(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();
4517 if (rwh) {
lfg 2016/05/06 21:23:33 nit: {}
avallee 2016/05/11 18:26:11 Done.
4518 rwh->Focus();
4519 }
4520 }
4521
4522 void WebContentsImpl::SetFocusedFrameInternal(FrameTreeNode* node,
4523 SiteInstance* source,
4524 bool can_visit_outer_contents) {
4525 // Approach: Recursively unfocus any inner web contents. Then set
4526 // representation of this web contents in the outer contents to be focused,
4527 // finally focus the node in current frame tree.
4528 //
4529 // Usually only one of unfocusing children and focusing self in parent would
4530 // happen. If unfocusing a child, then we're already focused in our parent, if
4531 // we have one.
4532
4533 auto old_focus_node = frame_tree_.GetFocusedFrame();
4534
4535 if (old_focus_node != nullptr && node_.get()) {
4536 if (!node || old_focus_node != node) {
4537 WebContentsImpl* inner_contents =
4538 node_->find_contents_for_frame(old_focus_node->frame_tree_node_id());
4539 if (inner_contents) {
lfg 2016/05/06 21:23:33 nit: {}
avallee 2016/05/11 18:26:11 Done.
4540 inner_contents->SetFocusedFrameInternal(nullptr, source, false);
4541 }
4542 }
4543 }
4544
4545 // focus in parent.
4546 auto outer_contents = GetOuterWebContents();
4547 // If we're coming from parent, we don't want to recurse back into the parent.
4548 if (outer_contents && can_visit_outer_contents) {
4549 auto outer_node =
4550 outer_contents->frame_tree_.FindByID(GetOuterDelegateFrameTreeNodeId());
4551 if (outer_node == nullptr) {
4552 // With browser plugin, we will have an outer contents but no node in the
4553 // outer contents' frame tree.
4554 // maybe focus outer main frame.
lfg 2016/05/06 21:23:33 Not sure I follow this. Why are we focusing the ro
avallee 2016/05/11 18:26:11 Comment should answer this. It's not ideal, but it
4555 outer_contents->SetFocusedFrameInternal(
4556 outer_contents->frame_tree_.root(), source, true);
4557 } else {
4558 // Notify outer about our focus change.
4559 auto outer_node_site_instance =
4560 outer_node->current_frame_host()->GetSiteInstance();
lfg 2016/05/06 21:23:33 I think this should be outer_node->parent()->curre
avallee 2016/05/11 18:26:11 Done.
4561 auto outer_proxy =
4562 frame_tree_.root()->render_manager()->GetRenderFrameProxyHost(
4563 outer_node_site_instance);
4564 if (outer_proxy) {
lfg 2016/05/06 21:23:33 nit: {}
avallee 2016/05/11 18:26:11 Done.
4565 outer_proxy->SetFocusedFrame();
4566 }
4567 outer_contents->SetFocusedFrameInternal(outer_node, source, true);
4568 }
4569 }
4570 // Set focus for myself.
4571 frame_tree_.SetFocusedFrame(node, source);
4572 }
4573
4488 bool WebContentsImpl::AddMessageToConsole(int32_t level, 4574 bool WebContentsImpl::AddMessageToConsole(int32_t level,
4489 const base::string16& message, 4575 const base::string16& message,
4490 int32_t line_no, 4576 int32_t line_no,
4491 const base::string16& source_id) { 4577 const base::string16& source_id) {
4492 if (!delegate_) 4578 if (!delegate_)
4493 return false; 4579 return false;
4494 return delegate_->AddMessageToConsole(this, level, message, line_no, 4580 return delegate_->AddMessageToConsole(this, level, message, line_no,
4495 source_id); 4581 source_id);
4496 } 4582 }
4497 4583
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
5015 for (RenderViewHost* render_view_host : render_view_host_set) 5101 for (RenderViewHost* render_view_host : render_view_host_set)
5016 render_view_host->OnWebkitPreferencesChanged(); 5102 render_view_host->OnWebkitPreferencesChanged();
5017 } 5103 }
5018 5104
5019 void WebContentsImpl::SetJavaScriptDialogManagerForTesting( 5105 void WebContentsImpl::SetJavaScriptDialogManagerForTesting(
5020 JavaScriptDialogManager* dialog_manager) { 5106 JavaScriptDialogManager* dialog_manager) {
5021 dialog_manager_ = dialog_manager; 5107 dialog_manager_ = dialog_manager;
5022 } 5108 }
5023 5109
5024 } // namespace content 5110 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698