OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/frame_host/render_frame_host_manager.h" | 5 #include "content/browser/frame_host/render_frame_host_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 // Instruct the destination render frame host to set up a Mojo connection | 411 // Instruct the destination render frame host to set up a Mojo connection |
412 // with the new render frame if necessary. Note that this call needs to | 412 // with the new render frame if necessary. Note that this call needs to |
413 // occur before initializing the RenderView; the flow of creating the | 413 // occur before initializing the RenderView; the flow of creating the |
414 // RenderView can cause browser-side code to execute that expects the this | 414 // RenderView can cause browser-side code to execute that expects the this |
415 // RFH's ServiceRegistry to be initialized (e.g., if the site is a WebUI | 415 // RFH's ServiceRegistry to be initialized (e.g., if the site is a WebUI |
416 // site that is handled via Mojo, then Mojo WebUI code in //chrome will | 416 // site that is handled via Mojo, then Mojo WebUI code in //chrome will |
417 // add a service to this RFH's ServiceRegistry). | 417 // add a service to this RFH's ServiceRegistry). |
418 dest_render_frame_host->SetUpMojoIfNeeded(); | 418 dest_render_frame_host->SetUpMojoIfNeeded(); |
419 | 419 |
420 // Recreate the opener chain. | 420 // Recreate the opener chain. |
421 CreateOpenerProxiesIfNeeded(dest_render_frame_host->GetSiteInstance()); | 421 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), |
| 422 frame_tree_node_); |
422 if (!InitRenderView(dest_render_frame_host->render_view_host(), | 423 if (!InitRenderView(dest_render_frame_host->render_view_host(), |
423 MSG_ROUTING_NONE, | 424 MSG_ROUTING_NONE, |
424 frame_tree_node_->IsMainFrame())) | 425 frame_tree_node_->IsMainFrame())) |
425 return nullptr; | 426 return nullptr; |
426 | 427 |
427 // Now that we've created a new renderer, be sure to hide it if it isn't | 428 // Now that we've created a new renderer, be sure to hide it if it isn't |
428 // our primary one. Otherwise, we might crash if we try to call Show() | 429 // our primary one. Otherwise, we might crash if we try to call Show() |
429 // on it later. | 430 // on it later. |
430 if (dest_render_frame_host != render_frame_host_) { | 431 if (dest_render_frame_host != render_frame_host_) { |
431 if (dest_render_frame_host->GetView()) | 432 if (dest_render_frame_host->GetView()) |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 } | 1037 } |
1037 } | 1038 } |
1038 DCHECK(navigation_rfh && | 1039 DCHECK(navigation_rfh && |
1039 (navigation_rfh == render_frame_host_.get() || | 1040 (navigation_rfh == render_frame_host_.get() || |
1040 navigation_rfh == speculative_render_frame_host_.get())); | 1041 navigation_rfh == speculative_render_frame_host_.get())); |
1041 | 1042 |
1042 // If the RenderFrame that needs to navigate is not live (its process was just | 1043 // If the RenderFrame that needs to navigate is not live (its process was just |
1043 // created or has crashed), initialize it. | 1044 // created or has crashed), initialize it. |
1044 if (!navigation_rfh->IsRenderFrameLive()) { | 1045 if (!navigation_rfh->IsRenderFrameLive()) { |
1045 // Recreate the opener chain. | 1046 // Recreate the opener chain. |
1046 CreateOpenerProxiesIfNeeded(navigation_rfh->GetSiteInstance()); | 1047 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); |
1047 if (!InitRenderView(navigation_rfh->render_view_host(), MSG_ROUTING_NONE, | 1048 if (!InitRenderView(navigation_rfh->render_view_host(), MSG_ROUTING_NONE, |
1048 frame_tree_node_->IsMainFrame())) { | 1049 frame_tree_node_->IsMainFrame())) { |
1049 return nullptr; | 1050 return nullptr; |
1050 } | 1051 } |
1051 | 1052 |
1052 if (navigation_rfh == render_frame_host_) { | 1053 if (navigation_rfh == render_frame_host_) { |
1053 // TODO(nasko): This is a very ugly hack. The Chrome extensions process | 1054 // TODO(nasko): This is a very ugly hack. The Chrome extensions process |
1054 // manager still uses NotificationService and expects to see a | 1055 // manager still uses NotificationService and expects to see a |
1055 // RenderViewHost changed notification after WebContents and | 1056 // RenderViewHost changed notification after WebContents and |
1056 // RenderFrameHostManager are completely initialized. This should be | 1057 // RenderFrameHostManager are completely initialized. This should be |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1571 | 1572 |
1572 // Create a non-swapped-out RFH with the given opener. | 1573 // Create a non-swapped-out RFH with the given opener. |
1573 pending_render_frame_host_ = CreateRenderFrame( | 1574 pending_render_frame_host_ = CreateRenderFrame( |
1574 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); | 1575 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); |
1575 } | 1576 } |
1576 | 1577 |
1577 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( | 1578 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( |
1578 SiteInstance* old_instance, | 1579 SiteInstance* old_instance, |
1579 SiteInstance* new_instance) { | 1580 SiteInstance* new_instance) { |
1580 // Only create opener proxies if they are in the same BrowsingInstance. | 1581 // Only create opener proxies if they are in the same BrowsingInstance. |
1581 if (new_instance->IsRelatedSiteInstance(old_instance)) | 1582 if (new_instance->IsRelatedSiteInstance(old_instance)) { |
1582 CreateOpenerProxiesIfNeeded(new_instance); | 1583 CreateOpenerProxies(new_instance, frame_tree_node_); |
1583 if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { | 1584 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { |
1584 // Ensure that the frame tree has RenderFrameProxyHosts for the new | 1585 // Ensure that the frame tree has RenderFrameProxyHosts for the |
1585 // SiteInstance in all nodes except the current one. We do this for all | 1586 // new SiteInstance in all nodes except the current one. We do this for |
1586 // frames in the tree, whether they are in the same BrowsingInstance or not. | 1587 // all frames in the tree, whether they are in the same BrowsingInstance or |
1587 // We will still check whether two frames are in the same BrowsingInstance | 1588 // not. If |new_instance| is in the same BrowsingInstance as |
1588 // before we allow them to interact (e.g., postMessage). | 1589 // |old_instance|, this will be done as part of CreateOpenerProxies above; |
| 1590 // otherwise, we do this here. We will still check whether two frames are |
| 1591 // in the same BrowsingInstance before we allow them to interact (e.g., |
| 1592 // postMessage). |
1589 frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance( | 1593 frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance( |
1590 frame_tree_node_, new_instance); | 1594 frame_tree_node_, new_instance); |
1591 } | 1595 } |
1592 } | 1596 } |
1593 | 1597 |
1594 void RenderFrameHostManager::CreateProxiesForNewNamedFrame() { | 1598 void RenderFrameHostManager::CreateProxiesForNewNamedFrame() { |
1595 if (!SiteIsolationPolicy::AreCrossProcessFramesPossible()) | 1599 if (!SiteIsolationPolicy::AreCrossProcessFramesPossible()) |
1596 return; | 1600 return; |
1597 | 1601 |
1598 DCHECK(!frame_tree_node_->frame_name().empty()); | 1602 DCHECK(!frame_tree_node_->frame_name().empty()); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1876 } | 1880 } |
1877 | 1881 |
1878 void RenderFrameHostManager::EnsureRenderViewInitialized( | 1882 void RenderFrameHostManager::EnsureRenderViewInitialized( |
1879 RenderViewHostImpl* render_view_host, | 1883 RenderViewHostImpl* render_view_host, |
1880 SiteInstance* instance) { | 1884 SiteInstance* instance) { |
1881 DCHECK(frame_tree_node_->IsMainFrame()); | 1885 DCHECK(frame_tree_node_->IsMainFrame()); |
1882 | 1886 |
1883 if (render_view_host->IsRenderViewLive()) | 1887 if (render_view_host->IsRenderViewLive()) |
1884 return; | 1888 return; |
1885 | 1889 |
1886 // Recreate the opener chain. | |
1887 CreateOpenerProxiesIfNeeded(instance); | |
1888 | |
1889 // If the proxy in |instance| doesn't exist, this RenderView is not swapped | 1890 // If the proxy in |instance| doesn't exist, this RenderView is not swapped |
1890 // out and shouldn't be reinitialized here. | 1891 // out and shouldn't be reinitialized here. |
1891 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); | 1892 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); |
1892 if (!proxy) | 1893 if (!proxy) |
1893 return; | 1894 return; |
1894 | 1895 |
1895 InitRenderView(render_view_host, proxy->GetRoutingID(), false); | 1896 InitRenderView(render_view_host, proxy->GetRoutingID(), false); |
1896 proxy->set_render_frame_proxy_created(true); | 1897 proxy->set_render_frame_proxy_created(true); |
1897 } | 1898 } |
1898 | 1899 |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2453 return proxy_hosts_->Get(instance->GetId()); | 2454 return proxy_hosts_->Get(instance->GetId()); |
2454 } | 2455 } |
2455 | 2456 |
2456 std::map<int, RenderFrameProxyHost*> | 2457 std::map<int, RenderFrameProxyHost*> |
2457 RenderFrameHostManager::GetAllProxyHostsForTesting() { | 2458 RenderFrameHostManager::GetAllProxyHostsForTesting() { |
2458 std::map<int, RenderFrameProxyHost*> result; | 2459 std::map<int, RenderFrameProxyHost*> result; |
2459 result.insert(proxy_hosts_->begin(), proxy_hosts_->end()); | 2460 result.insert(proxy_hosts_->begin(), proxy_hosts_->end()); |
2460 return result; | 2461 return result; |
2461 } | 2462 } |
2462 | 2463 |
2463 void RenderFrameHostManager::CreateOpenerProxiesIfNeeded( | |
2464 SiteInstance* instance) { | |
2465 FrameTreeNode* opener = frame_tree_node_->opener(); | |
2466 if (!opener) | |
2467 return; | |
2468 | |
2469 // TODO(alexmos): This should process all openers in the current frame tree, | |
2470 // not just current node's opener. | |
2471 | |
2472 // Create proxies for the opener chain. | |
2473 opener->render_manager()->CreateOpenerProxies(instance); | |
2474 } | |
2475 | |
2476 void RenderFrameHostManager::CollectOpenerFrameTrees( | 2464 void RenderFrameHostManager::CollectOpenerFrameTrees( |
2477 std::vector<FrameTree*>* opener_frame_trees, | 2465 std::vector<FrameTree*>* opener_frame_trees, |
2478 base::hash_set<FrameTreeNode*>* nodes_with_back_links) { | 2466 base::hash_set<FrameTreeNode*>* nodes_with_back_links) { |
2479 CHECK(opener_frame_trees); | 2467 CHECK(opener_frame_trees); |
2480 opener_frame_trees->push_back(frame_tree_node_->frame_tree()); | 2468 opener_frame_trees->push_back(frame_tree_node_->frame_tree()); |
2481 | 2469 |
2482 size_t visited_index = 0; | 2470 size_t visited_index = 0; |
2483 while (visited_index < opener_frame_trees->size()) { | 2471 while (visited_index < opener_frame_trees->size()) { |
2484 FrameTree* frame_tree = (*opener_frame_trees)[visited_index]; | 2472 FrameTree* frame_tree = (*opener_frame_trees)[visited_index]; |
2485 visited_index++; | 2473 visited_index++; |
2486 frame_tree->ForEach(base::Bind(&OpenerForFrameTreeNode, visited_index, | 2474 frame_tree->ForEach(base::Bind(&OpenerForFrameTreeNode, visited_index, |
2487 opener_frame_trees, nodes_with_back_links)); | 2475 opener_frame_trees, nodes_with_back_links)); |
2488 } | 2476 } |
2489 } | 2477 } |
2490 | 2478 |
2491 void RenderFrameHostManager::CreateOpenerProxies(SiteInstance* instance) { | 2479 void RenderFrameHostManager::CreateOpenerProxies( |
| 2480 SiteInstance* instance, |
| 2481 FrameTreeNode* skip_this_node) { |
2492 std::vector<FrameTree*> opener_frame_trees; | 2482 std::vector<FrameTree*> opener_frame_trees; |
2493 base::hash_set<FrameTreeNode*> nodes_with_back_links; | 2483 base::hash_set<FrameTreeNode*> nodes_with_back_links; |
2494 | 2484 |
2495 CollectOpenerFrameTrees(&opener_frame_trees, &nodes_with_back_links); | 2485 CollectOpenerFrameTrees(&opener_frame_trees, &nodes_with_back_links); |
2496 | 2486 |
2497 // Create opener proxies for frame trees, processing furthest openers from | 2487 // Create opener proxies for frame trees, processing furthest openers from |
2498 // this node first and this node last. In the common case without cycles, | 2488 // this node first and this node last. In the common case without cycles, |
2499 // this will ensure that each tree's openers are created before the tree's | 2489 // this will ensure that each tree's openers are created before the tree's |
2500 // nodes need to reference them. | 2490 // nodes need to reference them. |
2501 for (int i = opener_frame_trees.size() - 1; i >= 0; i--) { | 2491 for (int i = opener_frame_trees.size() - 1; i >= 0; i--) { |
2502 opener_frame_trees[i] | 2492 opener_frame_trees[i] |
2503 ->root() | 2493 ->root() |
2504 ->render_manager() | 2494 ->render_manager() |
2505 ->CreateOpenerProxiesForFrameTree(instance); | 2495 ->CreateOpenerProxiesForFrameTree(instance, skip_this_node); |
2506 } | 2496 } |
2507 | 2497 |
2508 // Set openers for nodes in |nodes_with_back_links| in a second pass. | 2498 // Set openers for nodes in |nodes_with_back_links| in a second pass. |
2509 // The proxies created at these FrameTreeNodes in | 2499 // The proxies created at these FrameTreeNodes in |
2510 // CreateOpenerProxiesForFrameTree won't have their opener routing ID | 2500 // CreateOpenerProxiesForFrameTree won't have their opener routing ID |
2511 // available when created due to cycles or back links in the opener chain. | 2501 // available when created due to cycles or back links in the opener chain. |
2512 // They must have their openers updated as a separate step after proxy | 2502 // They must have their openers updated as a separate step after proxy |
2513 // creation. | 2503 // creation. |
2514 for (const auto& node : nodes_with_back_links) { | 2504 for (const auto& node : nodes_with_back_links) { |
2515 RenderFrameProxyHost* proxy = | 2505 RenderFrameProxyHost* proxy = |
2516 node->render_manager()->GetRenderFrameProxyHost(instance); | 2506 node->render_manager()->GetRenderFrameProxyHost(instance); |
2517 // If there is no proxy, the cycle may involve nodes in the same process, | 2507 // If there is no proxy, the cycle may involve nodes in the same process, |
2518 // or, if this is a subframe, --site-per-process may be off. Either way, | 2508 // or, if this is a subframe, --site-per-process may be off. Either way, |
2519 // there's nothing more to do. | 2509 // there's nothing more to do. |
2520 if (!proxy) | 2510 if (!proxy) |
2521 continue; | 2511 continue; |
2522 | 2512 |
2523 int opener_routing_id = | 2513 int opener_routing_id = |
2524 node->render_manager()->GetOpenerRoutingID(instance); | 2514 node->render_manager()->GetOpenerRoutingID(instance); |
2525 DCHECK_NE(opener_routing_id, MSG_ROUTING_NONE); | 2515 DCHECK_NE(opener_routing_id, MSG_ROUTING_NONE); |
2526 proxy->Send(new FrameMsg_UpdateOpener(proxy->GetRoutingID(), | 2516 proxy->Send(new FrameMsg_UpdateOpener(proxy->GetRoutingID(), |
2527 opener_routing_id)); | 2517 opener_routing_id)); |
2528 } | 2518 } |
2529 } | 2519 } |
2530 | 2520 |
2531 void RenderFrameHostManager::CreateOpenerProxiesForFrameTree( | 2521 void RenderFrameHostManager::CreateOpenerProxiesForFrameTree( |
2532 SiteInstance* instance) { | 2522 SiteInstance* instance, |
2533 // If any of the RenderViewHosts (current, pending, or swapped out) for this | 2523 FrameTreeNode* skip_this_node) { |
2534 // FrameTree has the same SiteInstance, then we can return early, since | 2524 // Currently, this function is only called on main frames. It should |
2535 // proxies for other nodes in the tree should also exist (when in | 2525 // actually work correctly for subframes as well, so if that need ever |
2536 // site-per-process mode). An exception is if we are in | 2526 // arises, it should be sufficient to remove this DCHECK. |
2537 // IsSwappedOutStateForbidden mode and find a pending RenderViewHost: in this | 2527 DCHECK(frame_tree_node_->IsMainFrame()); |
2538 // case, we should still create a proxy, which will allow communicating with | 2528 |
2539 // the opener until the pending RenderView commits, or if the pending | 2529 if (frame_tree_node_ == skip_this_node) |
2540 // navigation is canceled. | |
2541 FrameTree* frame_tree = frame_tree_node_->frame_tree(); | |
2542 RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance); | |
2543 bool need_proxy_for_pending_rvh = | |
2544 SiteIsolationPolicy::IsSwappedOutStateForbidden() && | |
2545 (rvh == pending_render_view_host()); | |
2546 if (rvh && rvh->IsRenderViewLive() && !need_proxy_for_pending_rvh) | |
2547 return; | 2530 return; |
2548 | 2531 |
2549 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { | 2532 FrameTree* frame_tree = frame_tree_node_->frame_tree(); |
2550 // Ensure that all the nodes in the opener's frame tree have | 2533 if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { |
2551 // RenderFrameProxyHosts for the new SiteInstance. | 2534 // Ensure that all the nodes in the opener's FrameTree have |
2552 frame_tree->CreateProxiesForSiteInstance(nullptr, instance); | 2535 // RenderFrameProxyHosts for the new SiteInstance. Only pass the node to |
2553 } else if (rvh && !rvh->IsRenderViewLive()) { | 2536 // be skipped if it's in the same FrameTree. |
2554 EnsureRenderViewInitialized(rvh, instance); | 2537 if (skip_this_node && skip_this_node->frame_tree() != frame_tree) |
| 2538 skip_this_node = nullptr; |
| 2539 frame_tree->CreateProxiesForSiteInstance(skip_this_node, instance); |
2555 } else { | 2540 } else { |
2556 // Create a swapped out RenderView in the given SiteInstance if none exists, | 2541 // If any of the RenderViewHosts (current, pending, or swapped out) for this |
2557 // setting its opener to the given route_id. Since the opener can point to | 2542 // FrameTree has the same SiteInstance, then we can return early and reuse |
2558 // a subframe, do this on the root frame of the opener's frame tree. | 2543 // them. An exception is if we are in IsSwappedOutStateForbidden mode and |
2559 // Return the new view's route_id. | 2544 // find a pending RenderViewHost: in this case, we should still create a |
2560 frame_tree->root()->render_manager()-> | 2545 // proxy, which will allow communicating with the opener until the pending |
2561 CreateRenderFrame(instance, nullptr, | 2546 // RenderView commits, or if the pending navigation is canceled. |
2562 CREATE_RF_FOR_MAIN_FRAME_NAVIGATION | | 2547 RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance); |
2563 CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, | 2548 bool need_proxy_for_pending_rvh = |
2564 nullptr); | 2549 SiteIsolationPolicy::IsSwappedOutStateForbidden() && |
| 2550 (rvh == pending_render_view_host()); |
| 2551 if (rvh && rvh->IsRenderViewLive() && !need_proxy_for_pending_rvh) |
| 2552 return; |
| 2553 |
| 2554 if (rvh && !rvh->IsRenderViewLive()) { |
| 2555 EnsureRenderViewInitialized(rvh, instance); |
| 2556 } else { |
| 2557 // Create a swapped out RenderView in the given SiteInstance if none |
| 2558 // exists. Since an opener can point to a subframe, do this on the root |
| 2559 // frame of the current opener's frame tree. |
| 2560 frame_tree->root()->render_manager()-> |
| 2561 CreateRenderFrame(instance, nullptr, |
| 2562 CREATE_RF_FOR_MAIN_FRAME_NAVIGATION | |
| 2563 CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, |
| 2564 nullptr); |
| 2565 } |
2565 } | 2566 } |
2566 } | 2567 } |
2567 | 2568 |
2568 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { | 2569 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { |
2569 if (!frame_tree_node_->opener()) | 2570 if (!frame_tree_node_->opener()) |
2570 return MSG_ROUTING_NONE; | 2571 return MSG_ROUTING_NONE; |
2571 | 2572 |
2572 return frame_tree_node_->opener() | 2573 return frame_tree_node_->opener() |
2573 ->render_manager() | 2574 ->render_manager() |
2574 ->GetRoutingIdForSiteInstance(instance); | 2575 ->GetRoutingIdForSiteInstance(instance); |
2575 } | 2576 } |
2576 | 2577 |
2577 } // namespace content | 2578 } // namespace content |
OLD | NEW |