Chromium Code Reviews| 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 int exit_code) { | 162 int exit_code) { | 
| 163 manager_->RendererProcessClosing(host); | 163 manager_->RendererProcessClosing(host); | 
| 164 } | 164 } | 
| 165 | 165 | 
| 166 // static | 166 // static | 
| 167 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { | 167 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { | 
| 168 node->render_manager()->pending_delete_hosts_.clear(); | 168 node->render_manager()->pending_delete_hosts_.clear(); | 
| 169 return true; | 169 return true; | 
| 170 } | 170 } | 
| 171 | 171 | 
| 172 namespace { | |
| 
 
Charlie Reis
2015/08/05 23:59:09
Nit: This should go above the RFHM:: stuff above.
 
alexmos
2015/08/06 17:05:39
Done.
 
 | |
| 173 | |
| 174 // Helper function to add the FrameTree of the current node's opener | |
| 
 
Charlie Reis
2015/08/05 23:59:09
s/current/given/
 
alexmos
2015/08/06 17:05:39
Done.
 
 | |
| 175 // to the list of |opener_trees|, if it doesn't exist there already. | |
| 176 // |visited_index| indicates which FrameTrees in |opener_trees| have already | |
| 177 // been visited (those at indexes less than |visited_index|). | |
| 
 
Charlie Reis
2015/08/05 23:59:09
nit: (i.e., those at indices...
 
alexmos
2015/08/06 17:05:39
Done.
 
 | |
| 178 // |nodes_with_back_links|, if not null, collects FrameTreeNodes with openers | |
| 
 
Charlie Reis
2015/08/05 23:59:09
Why would it be null?  I don't see a case where th
 
alexmos
2015/08/06 17:05:39
Removed from description and the if statement belo
 
 | |
| 179 // that point to FrameTrees that have already been visited (such as those with | |
| 
 
Charlie Reis
2015/08/05 23:59:09
nit: with openers in FrameTrees that...
 
alexmos
2015/08/06 17:05:39
Done.
 
 | |
| 180 // cycles). | |
| 181 bool OpenerForFrameTreeNode( | |
| 
 
Charlie Reis
2015/08/05 23:59:09
Does this need to return a bool?  Looks like it al
 
alexmos
2015/08/06 17:05:39
Done.  Yes, it's returning true just so it visits
 
 | |
| 182 size_t visited_index, | |
| 183 std::vector<FrameTree*>* opener_trees, | |
| 184 base::hash_set<FrameTreeNode*>* nodes_with_back_links, | |
| 185 FrameTreeNode* node) { | |
| 
 
Charlie Reis
2015/08/05 23:59:09
nit: Let's list |node| first, since it's the main
 
alexmos
2015/08/06 17:05:39
Hmm, I can't do that given how FrameTree::ForEach
 
Charlie Reis
2015/08/06 17:35:06
Acknowledged.
 
 | |
| 186 if (!node->opener()) | |
| 187 return true; | |
| 188 | |
| 189 FrameTree* opener_tree = node->opener()->frame_tree(); | |
| 190 | |
| 191 const auto& existing_tree_it = | |
| 192 std::find(opener_trees->begin(), opener_trees->end(), opener_tree); | |
| 193 if (existing_tree_it == opener_trees->end()) { | |
| 194 // This is a new opener tree that we will need to process. | |
| 195 opener_trees->push_back(opener_tree); | |
| 196 } else if (nodes_with_back_links) { | |
| 197 // If this tree is already on our processing list *and* we have visited it, | |
| 198 // then this node's opener is a back link. This means the node will need | |
| 199 // special treatment to process its opener. | |
| 200 size_t position = std::distance(opener_trees->begin(), existing_tree_it); | |
| 201 if (position < visited_index) | |
| 202 nodes_with_back_links->insert(node); | |
| 203 } | |
| 204 return true; | |
| 205 } | |
| 206 | |
| 207 } // namespace | |
| 208 | |
| 172 RenderFrameHostManager::RenderFrameHostManager( | 209 RenderFrameHostManager::RenderFrameHostManager( | 
| 173 FrameTreeNode* frame_tree_node, | 210 FrameTreeNode* frame_tree_node, | 
| 174 RenderFrameHostDelegate* render_frame_delegate, | 211 RenderFrameHostDelegate* render_frame_delegate, | 
| 175 RenderViewHostDelegate* render_view_delegate, | 212 RenderViewHostDelegate* render_view_delegate, | 
| 176 RenderWidgetHostDelegate* render_widget_delegate, | 213 RenderWidgetHostDelegate* render_widget_delegate, | 
| 177 Delegate* delegate) | 214 Delegate* delegate) | 
| 178 : frame_tree_node_(frame_tree_node), | 215 : frame_tree_node_(frame_tree_node), | 
| 179 delegate_(delegate), | 216 delegate_(delegate), | 
| 180 render_frame_delegate_(render_frame_delegate), | 217 render_frame_delegate_(render_frame_delegate), | 
| 181 render_view_delegate_(render_view_delegate), | 218 render_view_delegate_(render_view_delegate), | 
| (...skipping 2209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2391 result.insert(proxy_hosts_->begin(), proxy_hosts_->end()); | 2428 result.insert(proxy_hosts_->begin(), proxy_hosts_->end()); | 
| 2392 return result; | 2429 return result; | 
| 2393 } | 2430 } | 
| 2394 | 2431 | 
| 2395 void RenderFrameHostManager::CreateOpenerProxiesIfNeeded( | 2432 void RenderFrameHostManager::CreateOpenerProxiesIfNeeded( | 
| 2396 SiteInstance* instance) { | 2433 SiteInstance* instance) { | 
| 2397 FrameTreeNode* opener = frame_tree_node_->opener(); | 2434 FrameTreeNode* opener = frame_tree_node_->opener(); | 
| 2398 if (!opener) | 2435 if (!opener) | 
| 2399 return; | 2436 return; | 
| 2400 | 2437 | 
| 2438 // TODO(alexmos): This should process all openers in the current frame tree, | |
| 2439 // not just current node's opener. | |
| 
 
alexmos
2015/08/05 17:45:05
I noticed that this actually has a bug today: if A
 
Charlie Reis
2015/08/05 23:59:09
Nice catch.  Yes, a separate CL is fine, either be
 
alexmos
2015/08/06 17:05:39
OK, will do in a later CL.
 
 | |
| 2440 | |
| 2401 // Create proxies for the opener chain. | 2441 // Create proxies for the opener chain. | 
| 2402 opener->render_manager()->CreateOpenerProxies(instance); | 2442 opener->render_manager()->CreateOpenerProxies(instance); | 
| 2403 } | 2443 } | 
| 2404 | 2444 | 
| 2445 void RenderFrameHostManager::CollectOpenerFrameTrees( | |
| 2446 std::vector<FrameTree*>* opener_frame_trees, | |
| 2447 base::hash_set<FrameTreeNode*>* nodes_with_back_links) { | |
| 2448 CHECK(opener_frame_trees); | |
| 2449 opener_frame_trees->push_back(frame_tree_node_->frame_tree()); | |
| 2450 | |
| 2451 size_t visited_index = 0; | |
| 2452 while (visited_index < opener_frame_trees->size()) { | |
| 2453 FrameTree* frame_tree = (*opener_frame_trees)[visited_index]; | |
| 2454 visited_index++; | |
| 2455 frame_tree->ForEach(base::Bind(&OpenerForFrameTreeNode, visited_index, | |
| 2456 opener_frame_trees, nodes_with_back_links)); | |
| 2457 } | |
| 2458 } | |
| 2459 | |
| 2405 void RenderFrameHostManager::CreateOpenerProxies(SiteInstance* instance) { | 2460 void RenderFrameHostManager::CreateOpenerProxies(SiteInstance* instance) { | 
| 2406 // If this tab has an opener, recursively create proxies for the nodes on its | 2461 std::vector<FrameTree*> opener_frame_trees; | 
| 2407 // frame tree. | 2462 base::hash_set<FrameTreeNode*> nodes_with_back_links; | 
| 2408 // TODO(alexmos): Once we allow frame openers to be updated (which can happen | |
| 2409 // via window.open(url, "target_frame")), this will need to be resilient to | |
| 2410 // cycles. It will also need to handle tabs that have multiple openers (e.g., | |
| 2411 // main frame and subframe could have different openers, each of which must | |
| 2412 // be traversed). | |
| 2413 FrameTreeNode* opener = frame_tree_node_->opener(); | |
| 2414 if (opener) | |
| 2415 opener->render_manager()->CreateOpenerProxies(instance); | |
| 2416 | 2463 | 
| 2464 CollectOpenerFrameTrees(&opener_frame_trees, &nodes_with_back_links); | |
| 2465 | |
| 2466 // Create opener proxies for frame trees, processing furthest openers from | |
| 2467 // this node first and this node last. In the common case without cycles, | |
| 2468 // this will ensure that each tree's openers are created before the tree's | |
| 2469 // nodes need to reference them. | |
| 2470 for (int i = opener_frame_trees.size() - 1; i >= 0; i--) { | |
| 2471 opener_frame_trees[i] | |
| 2472 ->root() | |
| 2473 ->render_manager() | |
| 2474 ->CreateOpenerProxiesForFrameTree(instance); | |
| 2475 } | |
| 2476 | |
| 2477 // TODO(alexmos): Set openers for nodes in |nodes_with_back_links| in a | |
| 2478 // second pass. The proxies created at these FrameTreeNodes in | |
| 2479 // CreateOpenerProxiesForFrameTree won't have their opener routing ID | |
| 2480 // available when created due to cycles or back links in the opener chain. | |
| 2481 // They must have their openers updated as a separate step after proxy | |
| 2482 // creation. | |
| 2483 } | |
| 2484 | |
| 2485 void RenderFrameHostManager::CreateOpenerProxiesForFrameTree( | |
| 2486 SiteInstance* instance) { | |
| 2417 // If any of the RenderViewHosts (current, pending, or swapped out) for this | 2487 // If any of the RenderViewHosts (current, pending, or swapped out) for this | 
| 2418 // FrameTree has the same SiteInstance, then we can return early, since | 2488 // FrameTree has the same SiteInstance, then we can return early, since | 
| 2419 // proxies for other nodes in the tree should also exist (when in | 2489 // proxies for other nodes in the tree should also exist (when in | 
| 2420 // site-per-process mode). An exception is if we are in | 2490 // site-per-process mode). An exception is if we are in | 
| 2421 // IsSwappedOutStateForbidden mode and find a pending RenderViewHost: in this | 2491 // IsSwappedOutStateForbidden mode and find a pending RenderViewHost: in this | 
| 2422 // case, we should still create a proxy, which will allow communicating with | 2492 // case, we should still create a proxy, which will allow communicating with | 
| 2423 // the opener until the pending RenderView commits, or if the pending | 2493 // the opener until the pending RenderView commits, or if the pending | 
| 2424 // navigation is canceled. | 2494 // navigation is canceled. | 
| 2425 FrameTree* frame_tree = frame_tree_node_->frame_tree(); | 2495 FrameTree* frame_tree = frame_tree_node_->frame_tree(); | 
| 2426 RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance); | 2496 RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance); | 
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2452 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { | 2522 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { | 
| 2453 if (!frame_tree_node_->opener()) | 2523 if (!frame_tree_node_->opener()) | 
| 2454 return MSG_ROUTING_NONE; | 2524 return MSG_ROUTING_NONE; | 
| 2455 | 2525 | 
| 2456 return frame_tree_node_->opener() | 2526 return frame_tree_node_->opener() | 
| 2457 ->render_manager() | 2527 ->render_manager() | 
| 2458 ->GetRoutingIdForSiteInstance(instance); | 2528 ->GetRoutingIdForSiteInstance(instance); | 
| 2459 } | 2529 } | 
| 2460 | 2530 | 
| 2461 } // namespace content | 2531 } // namespace content | 
| OLD | NEW |