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( | |
Charlie Reis
2014/07/29 17:46:56
// PlzNavigate
clamy
2014/07/30 13:10:25
Done.
| |
231 const NavigationEntryImpl& entry, | |
232 const FrameMsg_Navigate_Params& navigate_params) { | |
Charlie Reis
2014/07/29 17:46:56
I'd like to be very careful about preventing other
clamy
2014/07/30 13:10:25
Done.
| |
233 // TODO(clamy): replace RenderViewHost::IsRenderViewLive by | |
234 // RenderFrameHost::IsLive. | |
Charlie Reis
2014/07/29 17:46:56
I think Ken's adding IsRenderFrameLive in https://
clamy
2014/07/30 13:10:24
Ok. I will rebase if it lands before this CL.
| |
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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 // immediately. | 586 // immediately. |
576 NavigationRequestInfo info(params); | 587 NavigationRequestInfo info(params); |
577 | 588 |
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 |
596 // Create a speculative RFH for the navigation if necessary. | |
597 RenderFrameHostImpl* dest_render_frame_host = render_frame_host_.get(); | |
598 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | |
599 SiteInstance* new_instance = GetSiteInstanceForNavigation( | |
600 *NavigationEntryImpl::FromNavigationEntry( | |
601 frame_tree_node_->navigator()->GetController()->GetPendingEntry())); | |
602 if (current_instance != new_instance) { | |
603 dest_render_frame_host = CreateRenderFrameHostForNewSiteInstance( | |
604 current_instance, new_instance, true); | |
605 DCHECK(dest_render_frame_host); | |
606 } | |
607 InitRenderFrameHostsBeforeNavigation(dest_render_frame_host); | |
608 | |
585 navigation_request_.reset( | 609 navigation_request_.reset( |
586 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); | 610 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); |
587 navigation_request_->BeginNavigation(params.request_body); | 611 navigation_request_->BeginNavigation(params.request_body); |
588 // TODO(clamy): If we have no live RenderFrameHost to handle the request (eg | 612 } |
589 // cross-site navigation) spawn one speculatively here and keep track of it. | 613 |
614 void RenderFrameHostManager::CommitNavigation( | |
Charlie Reis
2014/07/29 17:46:56
// PlzNavigate
clamy
2014/07/30 13:10:25
Done.
| |
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 = CreateRenderFrameHostForNewSiteInstance( | |
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, we should ask it to run its | |
660 // unload handler, and possibly create a RenderFrameProxyHost for it. | |
661 // Otherwise we are leaking the current RFH here. | |
662 if (rfh_to_navigate != render_frame_host_.get()) | |
663 SetRenderFrameHost(speculative_render_frame_host_.Pass()); | |
664 DCHECK(!speculative_render_frame_host_.get()); | |
665 | |
666 navigation_request_.reset(); | |
590 } | 667 } |
591 | 668 |
592 void RenderFrameHostManager::Observe( | 669 void RenderFrameHostManager::Observe( |
593 int type, | 670 int type, |
594 const NotificationSource& source, | 671 const NotificationSource& source, |
595 const NotificationDetails& details) { | 672 const NotificationDetails& details) { |
596 switch (type) { | 673 switch (type) { |
597 case NOTIFICATION_RENDERER_PROCESS_CLOSED: | 674 case NOTIFICATION_RENDERER_PROCESS_CLOSED: |
598 case NOTIFICATION_RENDERER_PROCESS_CLOSING: | 675 case NOTIFICATION_RENDERER_PROCESS_CLOSING: |
599 RendererProcessClosing( | 676 RendererProcessClosing( |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
893 } | 970 } |
894 | 971 |
895 // Start the new renderer in a new SiteInstance, but in the current | 972 // Start the new renderer in a new SiteInstance, but in the current |
896 // BrowsingInstance. It is important to immediately give this new | 973 // BrowsingInstance. It is important to immediately give this new |
897 // SiteInstance to a RenderViewHost (if it is different than our current | 974 // SiteInstance to a RenderViewHost (if it is different than our current |
898 // SiteInstance), so that it is ref counted. This will happen in | 975 // SiteInstance), so that it is ref counted. This will happen in |
899 // CreateRenderView. | 976 // CreateRenderView. |
900 return current_instance->GetRelatedSiteInstance(dest_url); | 977 return current_instance->GetRelatedSiteInstance(dest_url); |
901 } | 978 } |
902 | 979 |
980 RenderFrameHostImpl* RenderFrameHostManager:: | |
981 CreateRenderFrameHostForNewSiteInstance( | |
982 SiteInstance* old_instance, | |
983 SiteInstance* new_instance, | |
984 bool is_speculative) { | |
985 // Ensure that we have created RFHs for the new RFH's opener chain if | |
986 // we are staying in the same BrowsingInstance. This allows the new RFH | |
987 // to send cross-process script calls to its opener(s). | |
988 int opener_route_id = MSG_ROUTING_NONE; | |
989 if (new_instance->IsRelatedSiteInstance(old_instance)) { | |
990 opener_route_id = | |
991 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); | |
992 } | |
993 | |
994 // Create a non-swapped-out RFH with the given opener. | |
995 int route_id = CreateRenderFrame(new_instance, opener_route_id, false, | |
996 delegate_->IsHidden(), is_speculative); | |
997 if (route_id == MSG_ROUTING_NONE) { | |
998 if (is_speculative) | |
999 speculative_render_frame_host_.reset(); | |
1000 else | |
1001 pending_render_frame_host_.reset(); | |
1002 return NULL; | |
1003 } | |
1004 if (is_speculative) | |
1005 return speculative_render_frame_host_.get(); | |
1006 return pending_render_frame_host_.get(); | |
1007 } | |
1008 | |
903 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( | 1009 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( |
904 SiteInstance* site_instance, | 1010 SiteInstance* site_instance, |
905 int view_routing_id, | 1011 int view_routing_id, |
906 int frame_routing_id, | 1012 int frame_routing_id, |
907 bool swapped_out, | 1013 bool swapped_out, |
908 bool hidden) { | 1014 bool hidden) { |
909 if (frame_routing_id == MSG_ROUTING_NONE) | 1015 if (frame_routing_id == MSG_ROUTING_NONE) |
910 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); | 1016 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); |
911 | 1017 |
912 // Create a RVH for main frames, or find the existing one for subframes. | 1018 // Create a RVH for main frames, or find the existing one for subframes. |
(...skipping 24 matching lines...) Expand all Loading... | |
937 frame_tree_node_, | 1043 frame_tree_node_, |
938 frame_routing_id, | 1044 frame_routing_id, |
939 swapped_out).release()); | 1045 swapped_out).release()); |
940 return render_frame_host.Pass(); | 1046 return render_frame_host.Pass(); |
941 } | 1047 } |
942 | 1048 |
943 int RenderFrameHostManager::CreateRenderFrame( | 1049 int RenderFrameHostManager::CreateRenderFrame( |
944 SiteInstance* instance, | 1050 SiteInstance* instance, |
945 int opener_route_id, | 1051 int opener_route_id, |
946 bool swapped_out, | 1052 bool swapped_out, |
947 bool hidden) { | 1053 bool hidden, |
1054 bool is_speculative) { | |
948 CHECK(instance); | 1055 CHECK(instance); |
949 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. | 1056 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. |
1057 DCHECK(!(swapped_out && is_speculative)); | |
950 | 1058 |
951 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; | 1059 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; |
952 RenderFrameHostImpl* frame_to_announce = NULL; | 1060 RenderFrameHostImpl* frame_to_announce = NULL; |
953 int routing_id = MSG_ROUTING_NONE; | 1061 int routing_id = MSG_ROUTING_NONE; |
954 | 1062 |
955 // We are creating a pending or swapped out RFH here. We should never create | 1063 // We are creating a pending or swapped out RFH here. We should never create |
956 // it in the same SiteInstance as our current RFH. | 1064 // it in the same SiteInstance as our current RFH. |
957 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); | 1065 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); |
958 | 1066 |
959 // Check if we've already created an RFH for this SiteInstance. If so, try | 1067 // 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. | 1121 // Don't show the main frame's view until we get a DidNavigate from it. |
1014 render_view_host->GetView()->Hide(); | 1122 render_view_host->GetView()->Hide(); |
1015 } else if (!swapped_out && pending_render_frame_host_) { | 1123 } else if (!swapped_out && pending_render_frame_host_) { |
1016 CancelPending(); | 1124 CancelPending(); |
1017 } | 1125 } |
1018 routing_id = render_view_host->GetRoutingID(); | 1126 routing_id = render_view_host->GetRoutingID(); |
1019 frame_to_announce = new_render_frame_host.get(); | 1127 frame_to_announce = new_render_frame_host.get(); |
1020 } | 1128 } |
1021 | 1129 |
1022 // Use this as our new pending RFH if it isn't swapped out. | 1130 // Use this as our new pending RFH if it isn't swapped out. |
1023 if (!swapped_out) | 1131 if (!swapped_out) { |
1024 pending_render_frame_host_ = new_render_frame_host.Pass(); | 1132 if (is_speculative) |
1133 speculative_render_frame_host_ = new_render_frame_host.Pass(); | |
1134 else | |
1135 pending_render_frame_host_ = new_render_frame_host.Pass(); | |
1136 } | |
1025 | 1137 |
1026 // If a brand new RFH was created, announce it to observers. | 1138 // If a brand new RFH was created, announce it to observers. |
1027 if (frame_to_announce) | 1139 if (frame_to_announce) |
1028 render_frame_delegate_->RenderFrameCreated(frame_to_announce); | 1140 render_frame_delegate_->RenderFrameCreated(frame_to_announce); |
1029 | 1141 |
1030 return routing_id; | 1142 return routing_id; |
1031 } | 1143 } |
1032 | 1144 |
1033 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, | 1145 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, |
1034 int opener_route_id, | 1146 int opener_route_id, |
(...skipping 16 matching lines...) Expand all Loading... | |
1051 if (!rvh_impl->IsSwappedOut()) { | 1163 if (!rvh_impl->IsSwappedOut()) { |
1052 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | 1164 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
1053 render_view_host->GetProcess()->GetID())); | 1165 render_view_host->GetProcess()->GetID())); |
1054 } | 1166 } |
1055 } | 1167 } |
1056 | 1168 |
1057 return delegate_->CreateRenderViewForRenderManager( | 1169 return delegate_->CreateRenderViewForRenderManager( |
1058 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); | 1170 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); |
1059 } | 1171 } |
1060 | 1172 |
1173 bool RenderFrameHostManager::InitRenderFrameHostsBeforeNavigation( | |
1174 RenderFrameHostImpl* dest_render_frame_host) { | |
1175 // If the current render_frame_host_ isn't live, we should create it so | |
1176 // that we don't show a sad tab while the dest_render_frame_host fetches | |
1177 // its first page. (crbug.com/1145340) | |
1178 if (dest_render_frame_host != render_frame_host_ && | |
1179 !render_frame_host_->render_view_host()->IsRenderViewLive()) { | |
1180 // Note: we don't call InitRenderView here because we are navigating away | |
1181 // soon anyway, and we don't have the NavigationEntry for this host. | |
1182 delegate_->CreateRenderViewForRenderManager( | |
1183 render_frame_host_->render_view_host(), MSG_ROUTING_NONE, | |
1184 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame()); | |
1185 } | |
1186 | |
1187 // If the renderer crashed, then try to create a new one to satisfy this | |
1188 // navigation request. | |
1189 if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) { | |
1190 // Recreate the opener chain. | |
1191 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( | |
1192 dest_render_frame_host->GetSiteInstance()); | |
1193 if (!InitRenderView(dest_render_frame_host->render_view_host(), | |
1194 opener_route_id, | |
1195 MSG_ROUTING_NONE, | |
1196 frame_tree_node_->IsMainFrame())) | |
1197 return false; | |
1198 | |
1199 // Now that we've created a new renderer, be sure to hide it if it isn't | |
1200 // our primary one. Otherwise, we might crash if we try to call Show() | |
1201 // on it later. | |
1202 if (dest_render_frame_host != render_frame_host_ && | |
1203 dest_render_frame_host->render_view_host()->GetView()) { | |
1204 dest_render_frame_host->render_view_host()->GetView()->Hide(); | |
1205 } else { | |
1206 // Notify here as we won't be calling CommitPending (which does the | |
1207 // notify). | |
1208 delegate_->NotifySwappedFromRenderManager( | |
1209 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame()); | |
1210 } | |
1211 } | |
1212 return true; | |
1213 } | |
1214 | |
1215 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( | |
1216 const NavigationEntryImpl& entry) { | |
1217 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | |
1218 SiteInstance* new_instance = current_instance; | |
1219 | |
1220 // We do not currently swap processes for navigations in webview tag guests. | |
1221 bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme); | |
1222 | |
1223 // Determine if we need a new BrowsingInstance for this entry. If true, this | |
1224 // implies that it will get a new SiteInstance (and likely process), and that | |
1225 // other tabs in the current BrowsingInstance will be unable to script it. | |
1226 // This is used for cases that require a process swap even in the | |
1227 // process-per-tab model, such as WebUI pages. | |
1228 const NavigationEntry* current_entry = | |
1229 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | |
1230 bool force_swap = !is_guest_scheme && | |
1231 ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); | |
1232 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) | |
1233 new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap); | |
1234 | |
1235 // If force_swap is true, we must use a different SiteInstance. If we didn't, | |
1236 // we would have two RenderFrameHosts in the same SiteInstance and the same | |
1237 // frame, resulting in page_id conflicts for their NavigationEntries. | |
1238 if (force_swap) | |
1239 CHECK_NE(new_instance, current_instance); | |
1240 | |
1241 return new_instance; | |
1242 } | |
1243 | |
1061 void RenderFrameHostManager::CommitPending() { | 1244 void RenderFrameHostManager::CommitPending() { |
1062 // First check whether we're going to want to focus the location bar after | 1245 // 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 | 1246 // 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 | 1247 // 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. | 1248 // this triggers won't be able to figure out what's going on. |
1066 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 1249 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
1067 | 1250 |
1068 // We expect SwapOutOldPage to have canceled any modal dialogs and told the | 1251 // 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, | 1252 // 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 | 1253 // 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_) { | 1442 if (cross_navigation_pending_) { |
1260 if (pending_render_frame_host_) | 1443 if (pending_render_frame_host_) |
1261 CancelPending(); | 1444 CancelPending(); |
1262 cross_navigation_pending_ = false; | 1445 cross_navigation_pending_ = false; |
1263 } | 1446 } |
1264 | 1447 |
1265 // render_frame_host_'s SiteInstance and new_instance will not be deleted | 1448 // 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 | 1449 // before the end of this method, so we don't have to worry about their ref |
1267 // counts dropping to zero. | 1450 // counts dropping to zero. |
1268 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 1451 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
1269 SiteInstance* new_instance = current_instance; | 1452 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 = | 1453 const NavigationEntry* current_entry = |
1280 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | 1454 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 | 1455 |
1292 if (new_instance != current_instance) { | 1456 if (new_instance != current_instance) { |
1293 // New SiteInstance: create a pending RFH to navigate. | 1457 // New SiteInstance: create a pending RFH to navigate. |
1294 DCHECK(!cross_navigation_pending_); | 1458 DCHECK(!cross_navigation_pending_); |
1295 | 1459 |
1296 // This will possibly create (set to NULL) a Web UI object for the pending | 1460 // 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 | 1461 // 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. | 1462 // 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(), | 1463 // It must also happen after the above conditional call to CancelPending(), |
1300 // otherwise CancelPending may clear the pending_web_ui_ and the page will | 1464 // otherwise CancelPending may clear the pending_web_ui_ and the page will |
1301 // not have its bindings set appropriately. | 1465 // not have its bindings set appropriately. |
1302 SetPendingWebUI(entry); | 1466 SetPendingWebUI(entry); |
1303 | 1467 |
1304 // Ensure that we have created RFHs for the new RFH's opener chain if | 1468 if (!CreateRenderFrameHostForNewSiteInstance( |
1305 // we are staying in the same BrowsingInstance. This allows the pending RFH | 1469 current_instance, new_instance, false)) { |
1306 // to send cross-process script calls to its opener(s). | 1470 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 } | 1471 } |
1312 | 1472 |
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. | 1473 // Check if our current RFH is live before we set up a transition. |
1321 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { | 1474 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { |
1322 if (!cross_navigation_pending_) { | 1475 if (!cross_navigation_pending_) { |
1323 // The current RFH is not live. There's no reason to sit around with a | 1476 // 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 | 1477 // 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 | 1478 // 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 | 1479 // cross-navigating (Note that we don't care about on{before}unload |
1327 // handlers if the current RFH isn't live.) | 1480 // handlers if the current RFH isn't live.) |
1328 CommitPending(); | 1481 CommitPending(); |
1329 return render_frame_host_.get(); | 1482 return render_frame_host_.get(); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1506 SiteInstance* instance) const { | 1659 SiteInstance* instance) const { |
1507 RenderFrameProxyHostMap::const_iterator iter = | 1660 RenderFrameProxyHostMap::const_iterator iter = |
1508 proxy_hosts_.find(instance->GetId()); | 1661 proxy_hosts_.find(instance->GetId()); |
1509 if (iter != proxy_hosts_.end()) | 1662 if (iter != proxy_hosts_.end()) |
1510 return iter->second; | 1663 return iter->second; |
1511 | 1664 |
1512 return NULL; | 1665 return NULL; |
1513 } | 1666 } |
1514 | 1667 |
1515 } // namespace content | 1668 } // namespace content |
OLD | NEW |