Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 // WebContentsImpl::WebContentsTreeNode ---------------------------------------- | 373 // WebContentsImpl::WebContentsTreeNode ---------------------------------------- |
| 374 WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode() | 374 WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode() |
| 375 : outer_web_contents_(nullptr), | 375 : outer_web_contents_(nullptr), |
| 376 outer_contents_frame_tree_node_id_( | 376 outer_contents_frame_tree_node_id_( |
| 377 FrameTreeNode::kFrameTreeNodeInvalidId), | 377 FrameTreeNode::kFrameTreeNodeInvalidId), |
| 378 focused_web_contents_(nullptr) {} | 378 focused_web_contents_(nullptr) {} |
| 379 | 379 |
| 380 WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { | 380 WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() { |
| 381 // Remove child pointer from our parent. | 381 // Remove child pointer from our parent. |
| 382 if (outer_web_contents_) { | 382 if (outer_web_contents_) { |
| 383 ChildrenSet& child_ptrs_in_parent = | 383 ChildrenMap& child_ptrs_in_parent = |
| 384 outer_web_contents_->node_->inner_web_contents_tree_nodes_; | 384 outer_web_contents_->node_->inner_web_contents_tree_nodes_; |
| 385 ChildrenSet::iterator iter = child_ptrs_in_parent.find(this); | 385 ChildrenMap::iterator iter = |
| 386 child_ptrs_in_parent.find(outer_contents_frame_tree_node_id_); | |
| 386 DCHECK(iter != child_ptrs_in_parent.end()); | 387 DCHECK(iter != child_ptrs_in_parent.end()); |
| 387 child_ptrs_in_parent.erase(iter); | 388 child_ptrs_in_parent.erase(iter); |
| 388 } | 389 } |
| 389 | 390 |
| 390 // Remove parent pointers from our children. | 391 // Remove parent pointers from our children. |
| 391 // TODO(lazyboy): We should destroy the children WebContentses too. If the | 392 // TODO(lazyboy): We should destroy the children WebContentses too. If the |
| 392 // children do not manage their own lifetime, then we would leak their | 393 // children do not manage their own lifetime, then we would leak their |
| 393 // WebContentses. | 394 // WebContentses. |
| 394 for (WebContentsTreeNode* child : inner_web_contents_tree_nodes_) | 395 for (auto child : inner_web_contents_tree_nodes_) |
| 395 child->outer_web_contents_ = nullptr; | 396 child.second->node_->outer_web_contents_ = nullptr; |
| 396 } | 397 } |
| 397 | 398 |
| 398 void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( | 399 void WebContentsImpl::WebContentsTreeNode::ConnectToOuterWebContents( |
| 400 WebContentsImpl* web_contents, | |
| 399 WebContentsImpl* outer_web_contents, | 401 WebContentsImpl* outer_web_contents, |
| 400 RenderFrameHostImpl* outer_contents_frame) { | 402 RenderFrameHostImpl* outer_contents_frame) { |
| 401 DCHECK(!focused_web_contents_) << "Should not attach a root node."; | 403 DCHECK(!focused_web_contents_) << "Should not attach a root node."; |
| 402 outer_web_contents_ = outer_web_contents; | 404 outer_web_contents_ = outer_web_contents; |
| 403 outer_contents_frame_tree_node_id_ = | 405 outer_contents_frame_tree_node_id_ = |
| 404 outer_contents_frame->frame_tree_node()->frame_tree_node_id(); | 406 outer_contents_frame->frame_tree_node()->frame_tree_node_id(); |
| 405 | 407 |
| 406 if (!outer_web_contents_->node_) { | 408 if (!outer_web_contents_->node_) { |
| 407 // This will only be reached when creating a new WebContents tree. | 409 // This will only be reached when creating a new WebContents tree. |
| 408 // Initialize the root of this tree and set it as focused. | 410 // Initialize the root of this tree and set it as focused. |
| 409 outer_web_contents_->node_.reset(new WebContentsTreeNode()); | 411 outer_web_contents_->node_.reset(new WebContentsTreeNode()); |
| 410 outer_web_contents_->node_->SetFocusedWebContents(outer_web_contents_); | 412 outer_web_contents_->node_->SetFocusedWebContents(outer_web_contents_); |
| 411 } | 413 } |
| 412 | 414 |
| 413 outer_web_contents_->node_->inner_web_contents_tree_nodes_.insert(this); | 415 outer_web_contents_->node_ |
| 416 ->inner_web_contents_tree_nodes_[outer_contents_frame_tree_node_id_] = | |
| 417 web_contents; | |
| 414 } | 418 } |
| 415 | 419 |
| 416 void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents( | 420 void WebContentsImpl::WebContentsTreeNode::SetFocusedWebContents( |
| 417 WebContentsImpl* web_contents) { | 421 WebContentsImpl* web_contents) { |
| 418 DCHECK(!outer_web_contents()) | 422 DCHECK(!outer_web_contents()) |
| 419 << "Only the outermost WebContents tracks focus."; | 423 << "Only the outermost WebContents tracks focus."; |
| 420 focused_web_contents_ = web_contents; | 424 focused_web_contents_ = web_contents; |
| 421 } | 425 } |
| 422 | 426 |
| 427 WebContentsImpl* | |
| 428 WebContentsImpl::WebContentsTreeNode::FindInnerWebContentsAtNode( | |
| 429 FrameTreeNode* node) { | |
| 430 int frame_tree_node_id = node->frame_tree_node_id(); | |
| 431 auto iter = inner_web_contents_tree_nodes_.find(frame_tree_node_id); | |
|
alexmos
2017/03/03 20:07:57
nit: might as well just use "node->frame_tree_node
avallee
2017/06/21 02:25:35
This is gone after rebase.
| |
| 432 if (iter == inner_web_contents_tree_nodes_.end()) | |
| 433 return nullptr; | |
| 434 return iter->second; | |
| 435 } | |
| 436 | |
| 423 // WebContentsImpl ------------------------------------------------------------- | 437 // WebContentsImpl ------------------------------------------------------------- |
| 424 | 438 |
| 425 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) | 439 WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) |
| 426 : delegate_(NULL), | 440 : delegate_(NULL), |
| 427 controller_(this, browser_context), | 441 controller_(this, browser_context), |
| 428 render_view_host_delegate_view_(NULL), | 442 render_view_host_delegate_view_(NULL), |
| 429 created_with_opener_(false), | 443 created_with_opener_(false), |
| 430 frame_tree_(new NavigatorImpl(&controller_, this), | 444 frame_tree_(new NavigatorImpl(&controller_, this), |
| 431 this, | 445 this, |
| 432 this, | 446 this, |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1433 // before attaching. If the browser side is already initialized, the calls | 1447 // before attaching. If the browser side is already initialized, the calls |
| 1434 // below will just early return. | 1448 // below will just early return. |
| 1435 render_manager->InitRenderView(GetRenderViewHost(), nullptr); | 1449 render_manager->InitRenderView(GetRenderViewHost(), nullptr); |
| 1436 GetMainFrame()->Init(); | 1450 GetMainFrame()->Init(); |
| 1437 if (!render_manager->GetRenderWidgetHostView()) | 1451 if (!render_manager->GetRenderWidgetHostView()) |
| 1438 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost()); | 1452 CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost()); |
| 1439 | 1453 |
| 1440 // Create a link to our outer WebContents. | 1454 // Create a link to our outer WebContents. |
| 1441 node_.reset(new WebContentsTreeNode()); | 1455 node_.reset(new WebContentsTreeNode()); |
| 1442 node_->ConnectToOuterWebContents( | 1456 node_->ConnectToOuterWebContents( |
| 1443 static_cast<WebContentsImpl*>(outer_web_contents), | 1457 this, static_cast<WebContentsImpl*>(outer_web_contents), |
| 1444 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); | 1458 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); |
| 1445 | 1459 |
| 1446 DCHECK(outer_contents_frame); | 1460 DCHECK(outer_contents_frame); |
| 1447 | 1461 |
| 1448 // Create a proxy in top-level RenderFrameHostManager, pointing to the | 1462 // Create a proxy in top-level RenderFrameHostManager, pointing to the |
| 1449 // SiteInstance of the outer WebContents. The proxy will be used to send | 1463 // SiteInstance of the outer WebContents. The proxy will be used to send |
| 1450 // postMessage to the inner WebContents. | 1464 // postMessage to the inner WebContents. |
| 1451 render_manager->CreateOuterDelegateProxy( | 1465 render_manager->CreateOuterDelegateProxy( |
| 1452 outer_contents_frame->GetSiteInstance(), | 1466 outer_contents_frame->GetSiteInstance(), |
| 1453 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); | 1467 static_cast<RenderFrameHostImpl*>(outer_contents_frame)); |
| 1454 | 1468 |
| 1455 render_manager->SetRWHViewForInnerContents( | 1469 render_manager->SetRWHViewForInnerContents( |
| 1456 render_manager->GetRenderWidgetHostView()); | 1470 render_manager->GetRenderWidgetHostView()); |
| 1457 | 1471 |
| 1458 static_cast<RenderWidgetHostViewChildFrame*>( | 1472 static_cast<RenderWidgetHostViewChildFrame*>( |
| 1459 render_manager->GetRenderWidgetHostView()) | 1473 render_manager->GetRenderWidgetHostView()) |
| 1460 ->RegisterFrameSinkId(); | 1474 ->RegisterFrameSinkId(); |
| 1461 | 1475 |
| 1476 // Set up the the guest's AX tree to point back at the embedder's AX tree. | |
| 1477 auto* parent_frame = outer_contents_frame->GetParent(); | |
| 1478 GetMainFrame()->set_browser_plugin_embedder_ax_tree_id( | |
| 1479 parent_frame->GetAXTreeID()); | |
| 1480 GetMainFrame()->UpdateAXTreeData(); | |
| 1481 | |
| 1462 // At this point, we should destroy the TextInputManager which will notify all | 1482 // At this point, we should destroy the TextInputManager which will notify all |
| 1463 // the RWHV in this WebContents. The RWHV in this WebContents should use the | 1483 // the RWHV in this WebContents. The RWHV in this WebContents should use the |
| 1464 // TextInputManager owned by the outer WebContents. | 1484 // TextInputManager owned by the outer WebContents. |
| 1465 // TODO(ekaramad): Is it possible to have TextInputState before attaching to | 1485 // TODO(ekaramad): Is it possible to have TextInputState before attaching to |
| 1466 // outer WebContents? In such a case, is this still the right way to hand off | 1486 // outer WebContents? In such a case, is this still the right way to hand off |
| 1467 // state tracking from inner WebContents's TextInputManager to that of the | 1487 // state tracking from inner WebContents's TextInputManager to that of the |
| 1468 // outer WebContent (crbug.com/609846)? | 1488 // outer WebContent (crbug.com/609846)? |
| 1469 text_input_manager_.reset(nullptr); | 1489 text_input_manager_.reset(nullptr); |
| 1470 } | 1490 } |
| 1471 | 1491 |
| (...skipping 2849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4321 return false; | 4341 return false; |
| 4322 } | 4342 } |
| 4323 | 4343 |
| 4324 WebContentsImpl* WebContentsImpl::GetOutermostWebContents() { | 4344 WebContentsImpl* WebContentsImpl::GetOutermostWebContents() { |
| 4325 WebContentsImpl* root = this; | 4345 WebContentsImpl* root = this; |
| 4326 while (root->GetOuterWebContents()) | 4346 while (root->GetOuterWebContents()) |
| 4327 root = root->GetOuterWebContents(); | 4347 root = root->GetOuterWebContents(); |
| 4328 return root; | 4348 return root; |
| 4329 } | 4349 } |
| 4330 | 4350 |
| 4351 void WebContentsImpl::FocusOuterAttachmentFrameChain() { | |
| 4352 WebContentsImpl* outer_contents = GetOuterWebContents(); | |
| 4353 if (!outer_contents) | |
| 4354 return; | |
| 4355 | |
| 4356 FrameTreeNode* outer_node = | |
| 4357 FrameTreeNode::GloballyFindByID(GetOuterDelegateFrameTreeNodeId()); | |
| 4358 outer_contents->frame_tree_.SetFocusedFrame(outer_node, nullptr); | |
| 4359 | |
| 4360 // For browser initiated focus change, let embedding renderer know of the | |
| 4361 // change. In tab navigation can become trapped in the inner contents without | |
|
alexmos
2017/03/03 20:07:57
By "In tab navigation" do you just mean "Tab navig
avallee
2017/06/21 02:25:35
Clarified comment.
| |
| 4362 // this. | |
| 4363 if (GetRenderManager()->GetProxyToOuterDelegate()) | |
| 4364 GetRenderManager()->GetProxyToOuterDelegate()->SetFocusedFrame(); | |
| 4365 | |
| 4366 outer_contents->FocusOuterAttachmentFrameChain(); | |
| 4367 } | |
| 4368 | |
| 4331 void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { | 4369 void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { |
| 4332 // Don't send notifications if we are just creating a swapped-out RVH for | 4370 // Don't send notifications if we are just creating a swapped-out RVH for |
| 4333 // the opener chain. These won't be used for view-source or WebUI, so it's | 4371 // the opener chain. These won't be used for view-source or WebUI, so it's |
| 4334 // ok to return early. | 4372 // ok to return early. |
| 4335 if (!static_cast<RenderViewHostImpl*>(render_view_host)->is_active()) | 4373 if (!static_cast<RenderViewHostImpl*>(render_view_host)->is_active()) |
| 4336 return; | 4374 return; |
| 4337 | 4375 |
| 4338 if (delegate_) | 4376 if (delegate_) |
| 4339 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); | 4377 view_->SetOverscrollControllerEnabled(CanOverscrollContent()); |
| 4340 | 4378 |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4725 return; | 4763 return; |
| 4726 | 4764 |
| 4727 // Send a page level blur to the old contents so that it displays inactive UI | 4765 // Send a page level blur to the old contents so that it displays inactive UI |
| 4728 // and focus this contents to activate it. | 4766 // and focus this contents to activate it. |
| 4729 if (old_contents) | 4767 if (old_contents) |
| 4730 old_contents->GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(false); | 4768 old_contents->GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(false); |
| 4731 | 4769 |
| 4732 // Make sure the outer web contents knows our frame is focused. Otherwise, the | 4770 // Make sure the outer web contents knows our frame is focused. Otherwise, the |
| 4733 // outer renderer could have the element before or after the frame element | 4771 // outer renderer could have the element before or after the frame element |
| 4734 // focused which would return early without actually advancing focus. | 4772 // focused which would return early without actually advancing focus. |
| 4735 if (GetRenderManager()->GetProxyToOuterDelegate()) | 4773 FocusOuterAttachmentFrameChain(); |
| 4736 GetRenderManager()->GetProxyToOuterDelegate()->SetFocusedFrame(); | |
| 4737 | 4774 |
| 4738 GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(true); | 4775 GetMainFrame()->GetRenderWidgetHost()->SetPageFocus(true); |
| 4739 GetOutermostWebContents()->node_->SetFocusedWebContents(this); | 4776 GetOutermostWebContents()->node_->SetFocusedWebContents(this); |
| 4740 } | 4777 } |
| 4741 | 4778 |
| 4742 void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node, | 4779 void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node, |
| 4743 SiteInstance* source) { | 4780 SiteInstance* source) { |
| 4744 // The PDF plugin still runs as a BrowserPlugin and must go through the | 4781 // The PDF plugin still runs as a BrowserPlugin and must go through the |
| 4745 // input redirection mechanism. It must not become focused direcly. | 4782 // input redirection mechanism. It must not become focused direcly. |
| 4746 if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) { | 4783 if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) { |
| 4747 frame_tree_.SetFocusedFrame(node, source); | 4784 frame_tree_.SetFocusedFrame(node, source); |
| 4748 return; | 4785 return; |
| 4749 } | 4786 } |
| 4750 | 4787 |
| 4751 SetAsFocusedWebContentsIfNecessary(); | 4788 frame_tree_.SetFocusedFrame(node, source); |
| 4752 | 4789 |
| 4753 frame_tree_.SetFocusedFrame(node, source); | 4790 WebContentsImpl* inner_contents = nullptr; |
| 4791 if (node_) | |
| 4792 inner_contents = node_->FindInnerWebContentsAtNode(node); | |
| 4793 | |
| 4794 WebContentsImpl* contents_to_focus = inner_contents ? inner_contents : this; | |
| 4795 contents_to_focus->SetAsFocusedWebContentsIfNecessary(); | |
| 4796 } | |
| 4797 | |
| 4798 RenderFrameHost* WebContentsImpl::GetFocusedFrameIncludingInnerWebContents() { | |
| 4799 if (!node_) | |
| 4800 return GetFocusedFrame(); | |
| 4801 | |
| 4802 WebContentsImpl* contents = this; | |
| 4803 FrameTreeNode* focused_node = contents->frame_tree_.GetFocusedFrame(); | |
| 4804 | |
| 4805 // If there is no focused frame in the outer WebContents, we need to return | |
| 4806 // null. | |
| 4807 if (!focused_node) | |
| 4808 return nullptr; | |
| 4809 | |
| 4810 // We cannot return the frame where an inner WebContents is attached, if the | |
|
alexmos
2017/03/03 20:07:57
I think this is talking about two different things
avallee
2017/06/21 02:25:35
rephrased.
| |
| 4811 // inner WebContents does not have a focused frame, return its main frame. | |
| 4812 while (true) { | |
| 4813 contents = contents->node_->FindInnerWebContentsAtNode(focused_node); | |
| 4814 if (!contents) | |
| 4815 return focused_node->current_frame_host(); | |
| 4816 | |
| 4817 focused_node = contents->frame_tree_.GetFocusedFrame(); | |
| 4818 if (!focused_node) | |
| 4819 return contents->GetMainFrame(); | |
| 4820 } | |
| 4754 } | 4821 } |
| 4755 | 4822 |
| 4756 void WebContentsImpl::OnFocusedElementChangedInFrame( | 4823 void WebContentsImpl::OnFocusedElementChangedInFrame( |
| 4757 RenderFrameHostImpl* frame, | 4824 RenderFrameHostImpl* frame, |
| 4758 const gfx::Rect& bounds_in_root_view) { | 4825 const gfx::Rect& bounds_in_root_view) { |
| 4759 RenderWidgetHostViewBase* root_view = | 4826 RenderWidgetHostViewBase* root_view = |
| 4760 static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView()); | 4827 static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView()); |
| 4761 if (!root_view || !frame->GetView()) | 4828 if (!root_view || !frame->GetView()) |
| 4762 return; | 4829 return; |
| 4763 | 4830 |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5428 RenderViewHost* render_view_host = RenderViewHost::From(render_widget_host); | 5495 RenderViewHost* render_view_host = RenderViewHost::From(render_widget_host); |
| 5429 if (!render_view_host) | 5496 if (!render_view_host) |
| 5430 continue; | 5497 continue; |
| 5431 render_view_host_set.insert(render_view_host); | 5498 render_view_host_set.insert(render_view_host); |
| 5432 } | 5499 } |
| 5433 for (RenderViewHost* render_view_host : render_view_host_set) | 5500 for (RenderViewHost* render_view_host : render_view_host_set) |
| 5434 render_view_host->OnWebkitPreferencesChanged(); | 5501 render_view_host->OnWebkitPreferencesChanged(); |
| 5435 } | 5502 } |
| 5436 | 5503 |
| 5437 } // namespace content | 5504 } // namespace content |
| OLD | NEW |