| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "content/browser/child_process_security_policy_impl.h" | 13 #include "content/browser/child_process_security_policy_impl.h" |
| 14 #include "content/browser/devtools/render_view_devtools_agent_host.h" | 14 #include "content/browser/devtools/render_view_devtools_agent_host.h" |
| 15 #include "content/browser/frame_host/cross_site_transferring_request.h" | 15 #include "content/browser/frame_host/cross_site_transferring_request.h" |
| 16 #include "content/browser/frame_host/debug_urls.h" | 16 #include "content/browser/frame_host/debug_urls.h" |
| 17 #include "content/browser/frame_host/interstitial_page_impl.h" | 17 #include "content/browser/frame_host/interstitial_page_impl.h" |
| 18 #include "content/browser/frame_host/navigation_commit_info.h" |
| 18 #include "content/browser/frame_host/navigation_controller_impl.h" | 19 #include "content/browser/frame_host/navigation_controller_impl.h" |
| 19 #include "content/browser/frame_host/navigation_entry_impl.h" | 20 #include "content/browser/frame_host/navigation_entry_impl.h" |
| 20 #include "content/browser/frame_host/navigation_request.h" | 21 #include "content/browser/frame_host/navigation_request.h" |
| 21 #include "content/browser/frame_host/navigation_request_info.h" | 22 #include "content/browser/frame_host/navigation_request_info.h" |
| 22 #include "content/browser/frame_host/navigator.h" | 23 #include "content/browser/frame_host/navigator.h" |
| 23 #include "content/browser/frame_host/render_frame_host_factory.h" | 24 #include "content/browser/frame_host/render_frame_host_factory.h" |
| 24 #include "content/browser/frame_host/render_frame_host_impl.h" | 25 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 25 #include "content/browser/frame_host/render_frame_proxy_host.h" | 26 #include "content/browser/frame_host/render_frame_proxy_host.h" |
| 26 #include "content/browser/renderer_host/render_process_host_impl.h" | 27 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 27 #include "content/browser/renderer_host/render_view_host_factory.h" | 28 #include "content/browser/renderer_host/render_view_host_factory.h" |
| 28 #include "content/browser/renderer_host/render_view_host_impl.h" | 29 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 29 #include "content/browser/site_instance_impl.h" | 30 #include "content/browser/site_instance_impl.h" |
| 30 #include "content/browser/webui/web_ui_controller_factory_registry.h" | 31 #include "content/browser/webui/web_ui_controller_factory_registry.h" |
| 31 #include "content/browser/webui/web_ui_impl.h" | 32 #include "content/browser/webui/web_ui_impl.h" |
| 32 #include "content/common/view_messages.h" | 33 #include "content/common/view_messages.h" |
| 33 #include "content/public/browser/content_browser_client.h" | 34 #include "content/public/browser/content_browser_client.h" |
| 34 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_service.h" |
| 35 #include "content/public/browser/notification_types.h" | 36 #include "content/public/browser/notification_types.h" |
| 36 #include "content/public/browser/render_widget_host_iterator.h" | 37 #include "content/public/browser/render_widget_host_iterator.h" |
| 37 #include "content/public/browser/render_widget_host_view.h" | 38 #include "content/public/browser/render_widget_host_view.h" |
| 38 #include "content/public/browser/user_metrics.h" | 39 #include "content/public/browser/user_metrics.h" |
| 39 #include "content/public/browser/web_ui_controller.h" | 40 #include "content/public/browser/web_ui_controller.h" |
| 40 #include "content/public/common/content_switches.h" | 41 #include "content/public/common/content_switches.h" |
| 41 #include "content/public/common/url_constants.h" | 42 #include "content/public/common/url_constants.h" |
| 43 #include "net/base/load_flags.h" |
| 42 | 44 |
| 43 namespace content { | 45 namespace content { |
| 44 | 46 |
| 47 namespace { |
| 48 |
| 49 FrameHostMsg_BeginNavigation_Params BeginNavigationFromNavigate( |
| 50 const FrameMsg_Navigate_Params& navigate_params) { |
| 51 FrameHostMsg_BeginNavigation_Params begin_navigation_params; |
| 52 begin_navigation_params.method = navigate_params.is_post ? |
| 53 "POST" : "GET"; |
| 54 begin_navigation_params.url = navigate_params.url; |
| 55 begin_navigation_params.referrer = navigate_params.referrer.url; |
| 56 begin_navigation_params.referrer_policy = navigate_params.referrer.policy; |
| 57 |
| 58 // TODO(clamy): This should be modified to take into account caching policy |
| 59 // requirements (eg for POST reloads). |
| 60 begin_navigation_params.load_flags = |
| 61 net::LOAD_NORMAL | net::LOAD_ENABLE_LOAD_TIMING; |
| 62 |
| 63 // TODO(clamy): Post data from the browser should be put in the request body. |
| 64 |
| 65 begin_navigation_params.has_user_gesture = false; |
| 66 begin_navigation_params.transition_type = navigate_params.transition; |
| 67 begin_navigation_params.should_replace_current_entry = |
| 68 navigate_params.should_replace_current_entry; |
| 69 begin_navigation_params.allow_download = |
| 70 navigate_params.allow_download; |
| 71 return begin_navigation_params; |
| 72 } |
| 73 |
| 74 } // namespace |
| 75 |
| 45 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( | 76 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( |
| 46 const GlobalRequestID& global_request_id, | 77 const GlobalRequestID& global_request_id, |
| 47 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, | 78 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, |
| 48 const std::vector<GURL>& transfer_url_chain, | 79 const std::vector<GURL>& transfer_url_chain, |
| 49 Referrer referrer, | 80 Referrer referrer, |
| 50 PageTransition page_transition, | 81 PageTransition page_transition, |
| 51 int render_frame_id, | 82 int render_frame_id, |
| 52 bool should_replace_current_entry) | 83 bool should_replace_current_entry) |
| 53 : global_request_id(global_request_id), | 84 : global_request_id(global_request_id), |
| 54 cross_site_transferring_request(cross_site_transferring_request.Pass()), | 85 cross_site_transferring_request(cross_site_transferring_request.Pass()), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 } | 204 } |
| 174 | 205 |
| 175 RenderFrameHostImpl* RenderFrameHostManager::Navigate( | 206 RenderFrameHostImpl* RenderFrameHostManager::Navigate( |
| 176 const NavigationEntryImpl& entry) { | 207 const NavigationEntryImpl& entry) { |
| 177 TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate"); | 208 TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate"); |
| 178 // Create a pending RenderFrameHost to use for the navigation. | 209 // Create a pending RenderFrameHost to use for the navigation. |
| 179 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(entry); | 210 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(entry); |
| 180 if (!dest_render_frame_host) | 211 if (!dest_render_frame_host) |
| 181 return NULL; // We weren't able to create a pending render frame host. | 212 return NULL; // We weren't able to create a pending render frame host. |
| 182 | 213 |
| 183 // If the current render_frame_host_ isn't live, we should create it so | 214 // Initialize the destination RFH and the current RFH if they are not live. |
| 184 // that we don't show a sad tab while the dest_render_frame_host fetches | 215 if (!InitRenderFrameHostsBeforeNavigation(dest_render_frame_host)) |
| 185 // its first page. (Bug 1145340) | 216 return NULL; |
| 186 if (dest_render_frame_host != render_frame_host_ && | |
| 187 !render_frame_host_->render_view_host()->IsRenderViewLive()) { | |
| 188 // Note: we don't call InitRenderView here because we are navigating away | |
| 189 // soon anyway, and we don't have the NavigationEntry for this host. | |
| 190 delegate_->CreateRenderViewForRenderManager( | |
| 191 render_frame_host_->render_view_host(), MSG_ROUTING_NONE, | |
| 192 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame()); | |
| 193 } | |
| 194 | |
| 195 // If the renderer crashed, then try to create a new one to satisfy this | |
| 196 // navigation request. | |
| 197 if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) { | |
| 198 // Recreate the opener chain. | |
| 199 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( | |
| 200 dest_render_frame_host->GetSiteInstance()); | |
| 201 if (!InitRenderView(dest_render_frame_host->render_view_host(), | |
| 202 opener_route_id, | |
| 203 MSG_ROUTING_NONE, | |
| 204 frame_tree_node_->IsMainFrame())) | |
| 205 return NULL; | |
| 206 | |
| 207 // Now that we've created a new renderer, be sure to hide it if it isn't | |
| 208 // our primary one. Otherwise, we might crash if we try to call Show() | |
| 209 // on it later. | |
| 210 if (dest_render_frame_host != render_frame_host_ && | |
| 211 dest_render_frame_host->render_view_host()->GetView()) { | |
| 212 dest_render_frame_host->render_view_host()->GetView()->Hide(); | |
| 213 } else { | |
| 214 // Notify here as we won't be calling CommitPending (which does the | |
| 215 // notify). | |
| 216 delegate_->NotifySwappedFromRenderManager( | |
| 217 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); | |
| 218 } | |
| 219 } | |
| 220 | 217 |
| 221 // If entry includes the request ID of a request that is being transferred, | 218 // If entry includes the request ID of a request that is being transferred, |
| 222 // the destination render frame will take ownership, so release ownership of | 219 // the destination render frame will take ownership, so release ownership of |
| 223 // the request. | 220 // the request. |
| 224 if (pending_nav_params_ && | 221 if (pending_nav_params_ && |
| 225 pending_nav_params_->global_request_id == | 222 pending_nav_params_->global_request_id == |
| 226 entry.transferred_global_request_id()) { | 223 entry.transferred_global_request_id()) { |
| 227 pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); | 224 pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); |
| 228 } | 225 } |
| 229 | 226 |
| 230 return dest_render_frame_host; | 227 return dest_render_frame_host; |
| 231 } | 228 } |
| 232 | 229 |
| 230 bool RenderFrameHostManager::RequestNavigation( |
| 231 const NavigationEntryImpl& entry, |
| 232 const FrameMsg_Navigate_Params& navigate_params) { |
| 233 // TODO(clamy): replace RenderViewHost::IsRenderViewLive by |
| 234 // RenderFrameHost::IsLive. |
| 235 if (render_frame_host_->render_view_host()->IsRenderViewLive()) |
| 236 // TODO(clamy): send a RequestNavigation IPC. |
| 237 return true; |
| 238 |
| 239 // The navigation request is sent directly to the IO thread. |
| 240 OnBeginNavigation(BeginNavigationFromNavigate(navigate_params)); |
| 241 return true; |
| 242 } |
| 243 |
| 233 void RenderFrameHostManager::Stop() { | 244 void RenderFrameHostManager::Stop() { |
| 234 render_frame_host_->render_view_host()->Stop(); | 245 render_frame_host_->render_view_host()->Stop(); |
| 235 | 246 |
| 236 // If we are cross-navigating, we should stop the pending renderers. This | 247 // If we are cross-navigating, we should stop the pending renderers. This |
| 237 // will lead to a DidFailProvisionalLoad, which will properly destroy them. | 248 // will lead to a DidFailProvisionalLoad, which will properly destroy them. |
| 238 if (cross_navigation_pending_) { | 249 if (cross_navigation_pending_) { |
| 239 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( | 250 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( |
| 240 pending_render_frame_host_->render_view_host()->GetRoutingID())); | 251 pending_render_frame_host_->render_view_host()->GetRoutingID())); |
| 241 } | 252 } |
| 242 } | 253 } |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ? | 589 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ? |
| 579 params.url : frame_tree_node_->frame_tree()->root()->current_url(); | 590 params.url : frame_tree_node_->frame_tree()->root()->current_url(); |
| 580 info.is_main_frame = frame_tree_node_->IsMainFrame(); | 591 info.is_main_frame = frame_tree_node_->IsMainFrame(); |
| 581 info.parent_is_main_frame = !frame_tree_node_->parent() ? | 592 info.parent_is_main_frame = !frame_tree_node_->parent() ? |
| 582 false : frame_tree_node_->parent()->IsMainFrame(); | 593 false : frame_tree_node_->parent()->IsMainFrame(); |
| 583 info.is_showing = GetRenderWidgetHostView()->IsShowing(); | 594 info.is_showing = GetRenderWidgetHostView()->IsShowing(); |
| 584 | 595 |
| 585 navigation_request_.reset( | 596 navigation_request_.reset( |
| 586 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); | 597 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); |
| 587 navigation_request_->BeginNavigation(params.request_body); | 598 navigation_request_->BeginNavigation(params.request_body); |
| 588 // TODO(clamy): If we have no live RenderFrameHost to handle the request (eg | 599 |
| 589 // cross-site navigation) spawn one speculatively here and keep track of it. | 600 // Create a new RFH for the navigation if necessary. |
| 601 RenderFrameHostImpl* dest_render_frame_host = render_frame_host_.get(); |
| 602 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
| 603 SiteInstance* new_instance = GetSiteInstanceForNavigation( |
| 604 *NavigationEntryImpl::FromNavigationEntry( |
| 605 frame_tree_node_->navigator()->GetController()->GetPendingEntry())); |
| 606 if (current_instance != new_instance) { |
| 607 dest_render_frame_host = CreateRenderFrameHostForCrossSite( |
| 608 current_instance, new_instance, true); |
| 609 DCHECK(dest_render_frame_host); |
| 610 } |
| 611 InitRenderFrameHostsBeforeNavigation(dest_render_frame_host); |
| 612 } |
| 613 |
| 614 void RenderFrameHostManager::CommitNavigation( |
| 615 const NavigationCommitInfo& info) { |
| 616 // Update the pending NavigationEntry for commit. |
| 617 // TODO(clamy): Check if some more state should be updated at that point. |
| 618 NavigationEntry* entry = |
| 619 frame_tree_node_->navigator()->GetController()->GetPendingEntry(); |
| 620 entry->SetURL(info.navigation_url); |
| 621 |
| 622 // Pick the right RenderFrameHost to commit the navigation. If the current RFH |
| 623 // is not suitable, a RFH may have been spawned speculatively to handle the |
| 624 // navigation. If there is none, or if it is not suitable, a new RFH needs to |
| 625 // be created. |
| 626 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
| 627 SiteInstance* speculative_instance = speculative_render_frame_host_.get() ? |
| 628 speculative_render_frame_host_->GetSiteInstance() : NULL; |
| 629 DCHECK(current_instance != speculative_instance); |
| 630 |
| 631 SiteInstance* new_instance = GetSiteInstanceForNavigation( |
| 632 *NavigationEntryImpl::FromNavigationEntry(entry)); |
| 633 RenderFrameHostImpl* rfh_to_navigate = NULL; |
| 634 DCHECK(!pending_render_frame_host_.get()); |
| 635 |
| 636 if (current_instance == new_instance) |
| 637 rfh_to_navigate = render_frame_host_.get(); |
| 638 |
| 639 if (speculative_instance) { |
| 640 if (speculative_instance == new_instance) { |
| 641 rfh_to_navigate = speculative_render_frame_host_.get(); |
| 642 } else { |
| 643 speculative_render_frame_host_.reset(); |
| 644 } |
| 645 } |
| 646 |
| 647 if (!rfh_to_navigate) { |
| 648 rfh_to_navigate = CreateRenderFrameHostForCrossSite( |
| 649 current_instance, new_instance, true); |
| 650 DCHECK(rfh_to_navigate); |
| 651 } |
| 652 |
| 653 // A WebUI renderer should never display a non WebUI url. |
| 654 frame_tree_node_->navigator()->CheckWebUIRendererDoesNotDisplayNormalURL( |
| 655 rfh_to_navigate, info.navigation_url); |
| 656 |
| 657 // TODO(clamy): the rfh_to_navigate should now send a commit IPC to the |
| 658 // renderer. |
| 659 // TODO(clamy): If the current RFH is not reused, then it should be swapped |
| 660 // out, and asked to run its unload handler. |
| 661 if (rfh_to_navigate != render_frame_host_.get()) |
| 662 SetRenderFrameHost(speculative_render_frame_host_.Pass()); |
| 663 DCHECK(!speculative_render_frame_host_.get()); |
| 664 |
| 665 navigation_request_.reset(); |
| 590 } | 666 } |
| 591 | 667 |
| 592 void RenderFrameHostManager::Observe( | 668 void RenderFrameHostManager::Observe( |
| 593 int type, | 669 int type, |
| 594 const NotificationSource& source, | 670 const NotificationSource& source, |
| 595 const NotificationDetails& details) { | 671 const NotificationDetails& details) { |
| 596 switch (type) { | 672 switch (type) { |
| 597 case NOTIFICATION_RENDERER_PROCESS_CLOSED: | 673 case NOTIFICATION_RENDERER_PROCESS_CLOSED: |
| 598 case NOTIFICATION_RENDERER_PROCESS_CLOSING: | 674 case NOTIFICATION_RENDERER_PROCESS_CLOSING: |
| 599 RendererProcessClosing( | 675 RendererProcessClosing( |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 } | 969 } |
| 894 | 970 |
| 895 // Start the new renderer in a new SiteInstance, but in the current | 971 // Start the new renderer in a new SiteInstance, but in the current |
| 896 // BrowsingInstance. It is important to immediately give this new | 972 // BrowsingInstance. It is important to immediately give this new |
| 897 // SiteInstance to a RenderViewHost (if it is different than our current | 973 // SiteInstance to a RenderViewHost (if it is different than our current |
| 898 // SiteInstance), so that it is ref counted. This will happen in | 974 // SiteInstance), so that it is ref counted. This will happen in |
| 899 // CreateRenderView. | 975 // CreateRenderView. |
| 900 return current_instance->GetRelatedSiteInstance(dest_url); | 976 return current_instance->GetRelatedSiteInstance(dest_url); |
| 901 } | 977 } |
| 902 | 978 |
| 979 RenderFrameHostImpl* RenderFrameHostManager::CreateRenderFrameHostForCrossSite( |
| 980 SiteInstance* old_instance, |
| 981 SiteInstance* new_instance, |
| 982 bool is_speculative) { |
| 983 // Ensure that we have created RFHs for the new RFH's opener chain if |
| 984 // we are staying in the same BrowsingInstance. This allows the pending RFH |
| 985 // to send cross-process script calls to its opener(s). |
| 986 int opener_route_id = MSG_ROUTING_NONE; |
| 987 if (new_instance->IsRelatedSiteInstance(old_instance)) { |
| 988 opener_route_id = |
| 989 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); |
| 990 } |
| 991 |
| 992 // Create a non-swapped-out speculative RFH with the given opener. |
| 993 int route_id = CreateRenderFrame(new_instance, opener_route_id, false, |
| 994 delegate_->IsHidden(), is_speculative); |
| 995 if (route_id == MSG_ROUTING_NONE) { |
| 996 if (is_speculative) |
| 997 speculative_render_frame_host_.reset(); |
| 998 else |
| 999 pending_render_frame_host_.reset(); |
| 1000 return NULL; |
| 1001 } |
| 1002 if (is_speculative) |
| 1003 return speculative_render_frame_host_.get(); |
| 1004 return pending_render_frame_host_.get(); |
| 1005 } |
| 1006 |
| 903 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( | 1007 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( |
| 904 SiteInstance* site_instance, | 1008 SiteInstance* site_instance, |
| 905 int view_routing_id, | 1009 int view_routing_id, |
| 906 int frame_routing_id, | 1010 int frame_routing_id, |
| 907 bool swapped_out, | 1011 bool swapped_out, |
| 908 bool hidden) { | 1012 bool hidden) { |
| 909 if (frame_routing_id == MSG_ROUTING_NONE) | 1013 if (frame_routing_id == MSG_ROUTING_NONE) |
| 910 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); | 1014 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); |
| 911 | 1015 |
| 912 // Create a RVH for main frames, or find the existing one for subframes. | 1016 // Create a RVH for main frames, or find the existing one for subframes. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 937 frame_tree_node_, | 1041 frame_tree_node_, |
| 938 frame_routing_id, | 1042 frame_routing_id, |
| 939 swapped_out).release()); | 1043 swapped_out).release()); |
| 940 return render_frame_host.Pass(); | 1044 return render_frame_host.Pass(); |
| 941 } | 1045 } |
| 942 | 1046 |
| 943 int RenderFrameHostManager::CreateRenderFrame( | 1047 int RenderFrameHostManager::CreateRenderFrame( |
| 944 SiteInstance* instance, | 1048 SiteInstance* instance, |
| 945 int opener_route_id, | 1049 int opener_route_id, |
| 946 bool swapped_out, | 1050 bool swapped_out, |
| 947 bool hidden) { | 1051 bool hidden, |
| 1052 bool is_speculative) { |
| 948 CHECK(instance); | 1053 CHECK(instance); |
| 949 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. | 1054 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. |
| 1055 DCHECK(!(swapped_out && is_speculative)); |
| 950 | 1056 |
| 951 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; | 1057 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; |
| 952 RenderFrameHostImpl* frame_to_announce = NULL; | 1058 RenderFrameHostImpl* frame_to_announce = NULL; |
| 953 int routing_id = MSG_ROUTING_NONE; | 1059 int routing_id = MSG_ROUTING_NONE; |
| 954 | 1060 |
| 955 // We are creating a pending or swapped out RFH here. We should never create | 1061 // We are creating a pending or swapped out RFH here. We should never create |
| 956 // it in the same SiteInstance as our current RFH. | 1062 // it in the same SiteInstance as our current RFH. |
| 957 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); | 1063 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); |
| 958 | 1064 |
| 959 // Check if we've already created an RFH for this SiteInstance. If so, try | 1065 // Check if we've already created an RFH for this SiteInstance. If so, try |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 // Don't show the main frame's view until we get a DidNavigate from it. | 1119 // Don't show the main frame's view until we get a DidNavigate from it. |
| 1014 render_view_host->GetView()->Hide(); | 1120 render_view_host->GetView()->Hide(); |
| 1015 } else if (!swapped_out && pending_render_frame_host_) { | 1121 } else if (!swapped_out && pending_render_frame_host_) { |
| 1016 CancelPending(); | 1122 CancelPending(); |
| 1017 } | 1123 } |
| 1018 routing_id = render_view_host->GetRoutingID(); | 1124 routing_id = render_view_host->GetRoutingID(); |
| 1019 frame_to_announce = new_render_frame_host.get(); | 1125 frame_to_announce = new_render_frame_host.get(); |
| 1020 } | 1126 } |
| 1021 | 1127 |
| 1022 // Use this as our new pending RFH if it isn't swapped out. | 1128 // Use this as our new pending RFH if it isn't swapped out. |
| 1023 if (!swapped_out) | 1129 if (!swapped_out) { |
| 1024 pending_render_frame_host_ = new_render_frame_host.Pass(); | 1130 if (is_speculative) |
| 1131 speculative_render_frame_host_ = new_render_frame_host.Pass(); |
| 1132 else |
| 1133 pending_render_frame_host_ = new_render_frame_host.Pass(); |
| 1134 } |
| 1025 | 1135 |
| 1026 // If a brand new RFH was created, announce it to observers. | 1136 // If a brand new RFH was created, announce it to observers. |
| 1027 if (frame_to_announce) | 1137 if (frame_to_announce) |
| 1028 render_frame_delegate_->RenderFrameCreated(frame_to_announce); | 1138 render_frame_delegate_->RenderFrameCreated(frame_to_announce); |
| 1029 | 1139 |
| 1030 return routing_id; | 1140 return routing_id; |
| 1031 } | 1141 } |
| 1032 | 1142 |
| 1033 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, | 1143 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, |
| 1034 int opener_route_id, | 1144 int opener_route_id, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1051 if (!rvh_impl->IsSwappedOut()) { | 1161 if (!rvh_impl->IsSwappedOut()) { |
| 1052 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | 1162 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| 1053 render_view_host->GetProcess()->GetID())); | 1163 render_view_host->GetProcess()->GetID())); |
| 1054 } | 1164 } |
| 1055 } | 1165 } |
| 1056 | 1166 |
| 1057 return delegate_->CreateRenderViewForRenderManager( | 1167 return delegate_->CreateRenderViewForRenderManager( |
| 1058 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); | 1168 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); |
| 1059 } | 1169 } |
| 1060 | 1170 |
| 1171 bool RenderFrameHostManager::InitRenderFrameHostsBeforeNavigation( |
| 1172 RenderFrameHostImpl* dest_render_frame_host) { |
| 1173 // If the current render_frame_host_ isn't live, we should create it so |
| 1174 // that we don't show a sad tab while the dest_render_frame_host fetches |
| 1175 // its first page. (crbug.com/1145340) |
| 1176 if (dest_render_frame_host != render_frame_host_ && |
| 1177 !render_frame_host_->render_view_host()->IsRenderViewLive()) { |
| 1178 // Note: we don't call InitRenderView here because we are navigating away |
| 1179 // soon anyway, and we don't have the NavigationEntry for this host. |
| 1180 delegate_->CreateRenderViewForRenderManager( |
| 1181 render_frame_host_->render_view_host(), MSG_ROUTING_NONE, |
| 1182 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame()); |
| 1183 } |
| 1184 |
| 1185 // If the renderer crashed, then try to create a new one to satisfy this |
| 1186 // navigation request. |
| 1187 if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) { |
| 1188 // Recreate the opener chain. |
| 1189 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( |
| 1190 dest_render_frame_host->GetSiteInstance()); |
| 1191 if (!InitRenderView(dest_render_frame_host->render_view_host(), |
| 1192 opener_route_id, |
| 1193 MSG_ROUTING_NONE, |
| 1194 frame_tree_node_->IsMainFrame())) |
| 1195 return false; |
| 1196 |
| 1197 // Now that we've created a new renderer, be sure to hide it if it isn't |
| 1198 // our primary one. Otherwise, we might crash if we try to call Show() |
| 1199 // on it later. |
| 1200 if (dest_render_frame_host != render_frame_host_ && |
| 1201 dest_render_frame_host->render_view_host()->GetView()) { |
| 1202 dest_render_frame_host->render_view_host()->GetView()->Hide(); |
| 1203 } else { |
| 1204 // Notify here as we won't be calling CommitPending (which does the |
| 1205 // notify). |
| 1206 delegate_->NotifySwappedFromRenderManager( |
| 1207 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); |
| 1208 } |
| 1209 } |
| 1210 return true; |
| 1211 } |
| 1212 |
| 1213 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( |
| 1214 const NavigationEntryImpl& entry) { |
| 1215 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
| 1216 SiteInstance* new_instance = current_instance; |
| 1217 |
| 1218 // We do not currently swap processes for navigations in webview tag guests. |
| 1219 bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme); |
| 1220 |
| 1221 // Determine if we need a new BrowsingInstance for this entry. If true, this |
| 1222 // implies that it will get a new SiteInstance (and likely process), and that |
| 1223 // other tabs in the current BrowsingInstance will be unable to script it. |
| 1224 // This is used for cases that require a process swap even in the |
| 1225 // process-per-tab model, such as WebUI pages. |
| 1226 const NavigationEntry* current_entry = |
| 1227 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
| 1228 bool force_swap = !is_guest_scheme && |
| 1229 ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); |
| 1230 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) |
| 1231 new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap); |
| 1232 |
| 1233 // If force_swap is true, we must use a different SiteInstance. If we didn't, |
| 1234 // we would have two RenderFrameHosts in the same SiteInstance and the same |
| 1235 // frame, resulting in page_id conflicts for their NavigationEntries. |
| 1236 if (force_swap) |
| 1237 CHECK_NE(new_instance, current_instance); |
| 1238 |
| 1239 return new_instance; |
| 1240 } |
| 1241 |
| 1061 void RenderFrameHostManager::CommitPending() { | 1242 void RenderFrameHostManager::CommitPending() { |
| 1062 // First check whether we're going to want to focus the location bar after | 1243 // First check whether we're going to want to focus the location bar after |
| 1063 // this commit. We do this now because the navigation hasn't formally | 1244 // this commit. We do this now because the navigation hasn't formally |
| 1064 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 1245 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
| 1065 // this triggers won't be able to figure out what's going on. | 1246 // this triggers won't be able to figure out what's going on. |
| 1066 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 1247 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
| 1067 | 1248 |
| 1068 // We expect SwapOutOldPage to have canceled any modal dialogs and told the | 1249 // We expect SwapOutOldPage to have canceled any modal dialogs and told the |
| 1069 // renderer to suppress any further dialogs until it is swapped out. However, | 1250 // renderer to suppress any further dialogs until it is swapped out. However, |
| 1070 // crash reports indicate that it's still possible for modal dialogs to exist | 1251 // crash reports indicate that it's still possible for modal dialogs to exist |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 if (cross_navigation_pending_) { | 1440 if (cross_navigation_pending_) { |
| 1260 if (pending_render_frame_host_) | 1441 if (pending_render_frame_host_) |
| 1261 CancelPending(); | 1442 CancelPending(); |
| 1262 cross_navigation_pending_ = false; | 1443 cross_navigation_pending_ = false; |
| 1263 } | 1444 } |
| 1264 | 1445 |
| 1265 // render_frame_host_'s SiteInstance and new_instance will not be deleted | 1446 // render_frame_host_'s SiteInstance and new_instance will not be deleted |
| 1266 // before the end of this method, so we don't have to worry about their ref | 1447 // before the end of this method, so we don't have to worry about their ref |
| 1267 // counts dropping to zero. | 1448 // counts dropping to zero. |
| 1268 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 1449 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
| 1269 SiteInstance* new_instance = current_instance; | 1450 SiteInstance* new_instance = GetSiteInstanceForNavigation(entry); |
| 1270 | |
| 1271 // We do not currently swap processes for navigations in webview tag guests. | |
| 1272 bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme); | |
| 1273 | |
| 1274 // Determine if we need a new BrowsingInstance for this entry. If true, this | |
| 1275 // implies that it will get a new SiteInstance (and likely process), and that | |
| 1276 // other tabs in the current BrowsingInstance will be unable to script it. | |
| 1277 // This is used for cases that require a process swap even in the | |
| 1278 // process-per-tab model, such as WebUI pages. | |
| 1279 const NavigationEntry* current_entry = | 1451 const NavigationEntry* current_entry = |
| 1280 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | 1452 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
| 1281 bool force_swap = !is_guest_scheme && | |
| 1282 ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); | |
| 1283 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) | |
| 1284 new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap); | |
| 1285 | |
| 1286 // If force_swap is true, we must use a different SiteInstance. If we didn't, | |
| 1287 // we would have two RenderFrameHosts in the same SiteInstance and the same | |
| 1288 // frame, resulting in page_id conflicts for their NavigationEntries. | |
| 1289 if (force_swap) | |
| 1290 CHECK_NE(new_instance, current_instance); | |
| 1291 | 1453 |
| 1292 if (new_instance != current_instance) { | 1454 if (new_instance != current_instance) { |
| 1293 // New SiteInstance: create a pending RFH to navigate. | 1455 // New SiteInstance: create a pending RFH to navigate. |
| 1294 DCHECK(!cross_navigation_pending_); | 1456 DCHECK(!cross_navigation_pending_); |
| 1295 | 1457 |
| 1296 // This will possibly create (set to NULL) a Web UI object for the pending | 1458 // This will possibly create (set to NULL) a Web UI object for the pending |
| 1297 // page. We'll use this later to give the page special access. This must | 1459 // page. We'll use this later to give the page special access. This must |
| 1298 // happen before the new renderer is created below so it will get bindings. | 1460 // happen before the new renderer is created below so it will get bindings. |
| 1299 // It must also happen after the above conditional call to CancelPending(), | 1461 // It must also happen after the above conditional call to CancelPending(), |
| 1300 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 1462 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
| 1301 // not have its bindings set appropriately. | 1463 // not have its bindings set appropriately. |
| 1302 SetPendingWebUI(entry); | 1464 SetPendingWebUI(entry); |
| 1303 | 1465 |
| 1304 // Ensure that we have created RFHs for the new RFH's opener chain if | 1466 if (!CreateRenderFrameHostForCrossSite( |
| 1305 // we are staying in the same BrowsingInstance. This allows the pending RFH | 1467 current_instance, new_instance, false)) { |
| 1306 // to send cross-process script calls to its opener(s). | 1468 return NULL; |
| 1307 int opener_route_id = MSG_ROUTING_NONE; | |
| 1308 if (new_instance->IsRelatedSiteInstance(current_instance)) { | |
| 1309 opener_route_id = | |
| 1310 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); | |
| 1311 } | 1469 } |
| 1312 | 1470 |
| 1313 // Create a non-swapped-out pending RFH with the given opener and navigate | |
| 1314 // it. | |
| 1315 int route_id = CreateRenderFrame(new_instance, opener_route_id, false, | |
| 1316 delegate_->IsHidden()); | |
| 1317 if (route_id == MSG_ROUTING_NONE) | |
| 1318 return NULL; | |
| 1319 | |
| 1320 // Check if our current RFH is live before we set up a transition. | 1471 // Check if our current RFH is live before we set up a transition. |
| 1321 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { | 1472 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { |
| 1322 if (!cross_navigation_pending_) { | 1473 if (!cross_navigation_pending_) { |
| 1323 // The current RFH is not live. There's no reason to sit around with a | 1474 // The current RFH is not live. There's no reason to sit around with a |
| 1324 // sad tab or a newly created RFH while we wait for the pending RFH to | 1475 // sad tab or a newly created RFH while we wait for the pending RFH to |
| 1325 // navigate. Just switch to the pending RFH now and go back to non | 1476 // navigate. Just switch to the pending RFH now and go back to non |
| 1326 // cross-navigating (Note that we don't care about on{before}unload | 1477 // cross-navigating (Note that we don't care about on{before}unload |
| 1327 // handlers if the current RFH isn't live.) | 1478 // handlers if the current RFH isn't live.) |
| 1328 CommitPending(); | 1479 CommitPending(); |
| 1329 return render_frame_host_.get(); | 1480 return render_frame_host_.get(); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 SiteInstance* instance) const { | 1657 SiteInstance* instance) const { |
| 1507 RenderFrameProxyHostMap::const_iterator iter = | 1658 RenderFrameProxyHostMap::const_iterator iter = |
| 1508 proxy_hosts_.find(instance->GetId()); | 1659 proxy_hosts_.find(instance->GetId()); |
| 1509 if (iter != proxy_hosts_.end()) | 1660 if (iter != proxy_hosts_.end()) |
| 1510 return iter->second; | 1661 return iter->second; |
| 1511 | 1662 |
| 1512 return NULL; | 1663 return NULL; |
| 1513 } | 1664 } |
| 1514 | 1665 |
| 1515 } // namespace content | 1666 } // namespace content |
| OLD | NEW |