Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: content/browser/frame_host/render_frame_host_manager.cc

Issue 379143002: PlzNavigate: implement RequestNavigation in the no live renderer case (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Charlie's comments Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_before_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(
Charlie Reis 2014/07/30 23:37:32 // PlzNavigate
clamy 2014/08/05 11:52:44 Done.
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
Charlie Reis 2014/07/30 23:37:32 Is this modeled after some existing code? I worry
clamy 2014/08/05 11:52:44 There is currently no unified code to do this on t
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
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 // PlzNavigate
231 bool RenderFrameHostManager::RequestNavigation(
232 const NavigationEntryImpl& entry,
233 const FrameMsg_Navigate_Params& navigate_params) {
234 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
235 switches::kEnableBrowserSideNavigation));
236 // TODO(clamy): replace RenderViewHost::IsRenderViewLive by
237 // RenderFrameHost::IsLive.
238 if (render_frame_host_->render_view_host()->IsRenderViewLive())
239 // TODO(clamy): send a RequestNavigation IPC.
240 return true;
241
242 // The navigation request is sent directly to the IO thread.
243 OnBeginNavigation(BeginNavigationFromNavigate(navigate_params));
244 return true;
245 }
246
233 void RenderFrameHostManager::Stop() { 247 void RenderFrameHostManager::Stop() {
234 render_frame_host_->render_view_host()->Stop(); 248 render_frame_host_->render_view_host()->Stop();
235 249
236 // If we are cross-navigating, we should stop the pending renderers. This 250 // If we are cross-navigating, we should stop the pending renderers. This
237 // will lead to a DidFailProvisionalLoad, which will properly destroy them. 251 // will lead to a DidFailProvisionalLoad, which will properly destroy them.
238 if (cross_navigation_pending_) { 252 if (cross_navigation_pending_) {
239 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( 253 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop(
240 pending_render_frame_host_->render_view_host()->GetRoutingID())); 254 pending_render_frame_host_->render_view_host()->GetRoutingID()));
241 } 255 }
242 } 256 }
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 RFHPendingDeleteMap::iterator iter = 576 RFHPendingDeleteMap::iterator iter =
563 pending_delete_hosts_.find(site_instance_id); 577 pending_delete_hosts_.find(site_instance_id);
564 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) 578 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh)
565 pending_delete_hosts_.erase(site_instance_id); 579 pending_delete_hosts_.erase(site_instance_id);
566 } 580 }
567 581
568 void RenderFrameHostManager::ResetProxyHosts() { 582 void RenderFrameHostManager::ResetProxyHosts() {
569 STLDeleteValues(&proxy_hosts_); 583 STLDeleteValues(&proxy_hosts_);
570 } 584 }
571 585
586 // PlzNavigate
572 void RenderFrameHostManager::OnBeginNavigation( 587 void RenderFrameHostManager::OnBeginNavigation(
573 const FrameHostMsg_BeginNavigation_Params& params) { 588 const FrameHostMsg_BeginNavigation_Params& params) {
589 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
590 switches::kEnableBrowserSideNavigation));
574 // TODO(clamy): Check if navigations are blocked and if so, return 591 // TODO(clamy): Check if navigations are blocked and if so, return
575 // immediately. 592 // immediately.
576 NavigationRequestInfo info(params); 593 NavigationRequestInfo info(params);
577 594
578 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ? 595 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ?
579 params.url : frame_tree_node_->frame_tree()->root()->current_url(); 596 params.url : frame_tree_node_->frame_tree()->root()->current_url();
580 info.is_main_frame = frame_tree_node_->IsMainFrame(); 597 info.is_main_frame = frame_tree_node_->IsMainFrame();
581 info.parent_is_main_frame = !frame_tree_node_->parent() ? 598 info.parent_is_main_frame = !frame_tree_node_->parent() ?
582 false : frame_tree_node_->parent()->IsMainFrame(); 599 false : frame_tree_node_->parent()->IsMainFrame();
583 info.is_showing = GetRenderWidgetHostView()->IsShowing(); 600 info.is_showing = GetRenderWidgetHostView()->IsShowing();
584 601
602 // Create a speculative RFH for the navigation if necessary.
603 RenderFrameHostImpl* dest_render_frame_host = render_frame_host_.get();
604 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
605 SiteInstance* new_instance = GetSiteInstanceForNavigation(
606 *NavigationEntryImpl::FromNavigationEntry(
607 frame_tree_node_->navigator()->GetController()->GetPendingEntry()));
Charlie Reis 2014/07/30 23:37:33 We didn't have a dependency on GetPendingEntry bef
clamy 2014/08/05 11:52:44 We can pass it in the case where we call it from N
Charlie Reis 2014/08/05 23:59:51 I don't follow this part. Today, we already recei
608 if (current_instance != new_instance) {
609 dest_render_frame_host = CreateRenderFrameHostForNewSiteInstance(
610 current_instance, new_instance, true);
611 DCHECK(dest_render_frame_host);
612 }
613 InitRenderFrameHostsBeforeNavigation(dest_render_frame_host);
614
585 navigation_request_.reset( 615 navigation_request_.reset(
586 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); 616 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id()));
587 navigation_request_->BeginNavigation(params.request_body); 617 navigation_request_->BeginNavigation(params.request_body);
588 // TODO(clamy): If we have no live RenderFrameHost to handle the request (eg 618 }
589 // cross-site navigation) spawn one speculatively here and keep track of it. 619
620 // PlzNavigate
621 void RenderFrameHostManager::CommitNavigation(
622 const NavigationBeforeCommitInfo& info) {
623 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
624 switches::kEnableBrowserSideNavigation));
625 // Update the pending NavigationEntry for commit.
626 // TODO(clamy): Check if some more state should be updated at that point.
627 NavigationEntry* entry =
628 frame_tree_node_->navigator()->GetController()->GetPendingEntry();
Charlie Reis 2014/07/30 23:37:32 Again, we didn't depend on GetPendingEntry() being
clamy 2014/08/05 11:52:44 In the current design, in-page navigations should
Charlie Reis 2014/08/05 23:59:51 (Tangent: We should be able to determine if a navi
629 entry->SetURL(info.navigation_url);
630
631 // Pick the right RenderFrameHost to commit the navigation. If the current RFH
632 // is not suitable, a RFH may have been spawned speculatively to handle the
633 // navigation. If there is none, or if it is not suitable, a new RFH needs to
634 // be created.
635 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
636 SiteInstance* speculative_instance = speculative_render_frame_host_.get() ?
637 speculative_render_frame_host_->GetSiteInstance() : NULL;
638 DCHECK(current_instance != speculative_instance);
639
640 SiteInstance* new_instance = GetSiteInstanceForNavigation(
641 *NavigationEntryImpl::FromNavigationEntry(entry));
642 RenderFrameHostImpl* rfh_to_navigate = NULL;
643 DCHECK(!pending_render_frame_host_.get());
644
645 if (current_instance == new_instance)
646 rfh_to_navigate = render_frame_host_.get();
647
648 if (speculative_instance) {
649 if (speculative_instance == new_instance) {
650 rfh_to_navigate = speculative_render_frame_host_.get();
651 } else {
652 speculative_render_frame_host_.reset();
653 }
654 }
655
656 if (!rfh_to_navigate) {
657 rfh_to_navigate = CreateRenderFrameHostForNewSiteInstance(
658 current_instance, new_instance, true);
659 DCHECK(rfh_to_navigate);
660 }
661
662 // A WebUI renderer should never display a non WebUI url.
663 frame_tree_node_->navigator()->CheckWebUIRendererDoesNotDisplayNormalURL(
664 rfh_to_navigate, info.navigation_url);
665
666 // TODO(clamy): the rfh_to_navigate should now send a commit IPC to the
Charlie Reis 2014/07/30 23:37:32 I'm having trouble following the planned IPC timel
clamy 2014/08/05 11:52:44 Yes at https://docs.google.com/document/d/1cSW8fpJ
667 // renderer.
668 // TODO(clamy): If the current RFH is not reused, we should ask it to run its
669 // unload handler, and possibly create a RenderFrameProxyHost for it.
670 // Otherwise we are leaking the current RFH here.
671 if (rfh_to_navigate != render_frame_host_.get())
672 SetRenderFrameHost(speculative_render_frame_host_.Pass());
673 DCHECK(!speculative_render_frame_host_.get());
674
675 navigation_request_.reset();
590 } 676 }
591 677
592 void RenderFrameHostManager::Observe( 678 void RenderFrameHostManager::Observe(
593 int type, 679 int type,
594 const NotificationSource& source, 680 const NotificationSource& source,
595 const NotificationDetails& details) { 681 const NotificationDetails& details) {
596 switch (type) { 682 switch (type) {
597 case NOTIFICATION_RENDERER_PROCESS_CLOSED: 683 case NOTIFICATION_RENDERER_PROCESS_CLOSED:
598 case NOTIFICATION_RENDERER_PROCESS_CLOSING: 684 case NOTIFICATION_RENDERER_PROCESS_CLOSING:
599 RendererProcessClosing( 685 RendererProcessClosing(
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 } 979 }
894 980
895 // Start the new renderer in a new SiteInstance, but in the current 981 // Start the new renderer in a new SiteInstance, but in the current
896 // BrowsingInstance. It is important to immediately give this new 982 // BrowsingInstance. It is important to immediately give this new
897 // SiteInstance to a RenderViewHost (if it is different than our current 983 // SiteInstance to a RenderViewHost (if it is different than our current
898 // SiteInstance), so that it is ref counted. This will happen in 984 // SiteInstance), so that it is ref counted. This will happen in
899 // CreateRenderView. 985 // CreateRenderView.
900 return current_instance->GetRelatedSiteInstance(dest_url); 986 return current_instance->GetRelatedSiteInstance(dest_url);
901 } 987 }
902 988
989 RenderFrameHostImpl* RenderFrameHostManager::
990 CreateRenderFrameHostForNewSiteInstance(
991 SiteInstance* old_instance,
992 SiteInstance* new_instance,
993 bool is_speculative) {
994 // Ensure that we have created RFHs for the new RFH's opener chain if
995 // we are staying in the same BrowsingInstance. This allows the new RFH
996 // to send cross-process script calls to its opener(s).
997 int opener_route_id = MSG_ROUTING_NONE;
998 if (new_instance->IsRelatedSiteInstance(old_instance)) {
999 opener_route_id =
1000 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
1001 }
1002
1003 // Create a non-swapped-out RFH with the given opener.
1004 int route_id = CreateRenderFrame(new_instance, opener_route_id, false,
1005 delegate_->IsHidden(), is_speculative);
1006 if (route_id == MSG_ROUTING_NONE) {
1007 if (is_speculative)
1008 speculative_render_frame_host_.reset();
1009 else
1010 pending_render_frame_host_.reset();
1011 return NULL;
1012 }
1013 if (is_speculative)
1014 return speculative_render_frame_host_.get();
1015 return pending_render_frame_host_.get();
1016 }
1017
903 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( 1018 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
904 SiteInstance* site_instance, 1019 SiteInstance* site_instance,
905 int view_routing_id, 1020 int view_routing_id,
906 int frame_routing_id, 1021 int frame_routing_id,
907 bool swapped_out, 1022 bool swapped_out,
908 bool hidden) { 1023 bool hidden) {
909 if (frame_routing_id == MSG_ROUTING_NONE) 1024 if (frame_routing_id == MSG_ROUTING_NONE)
910 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); 1025 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
911 1026
912 // Create a RVH for main frames, or find the existing one for subframes. 1027 // Create a RVH for main frames, or find the existing one for subframes.
(...skipping 24 matching lines...) Expand all
937 frame_tree_node_, 1052 frame_tree_node_,
938 frame_routing_id, 1053 frame_routing_id,
939 swapped_out).release()); 1054 swapped_out).release());
940 return render_frame_host.Pass(); 1055 return render_frame_host.Pass();
941 } 1056 }
942 1057
943 int RenderFrameHostManager::CreateRenderFrame( 1058 int RenderFrameHostManager::CreateRenderFrame(
944 SiteInstance* instance, 1059 SiteInstance* instance,
945 int opener_route_id, 1060 int opener_route_id,
946 bool swapped_out, 1061 bool swapped_out,
947 bool hidden) { 1062 bool hidden,
1063 bool is_speculative) {
948 CHECK(instance); 1064 CHECK(instance);
949 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. 1065 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
1066 DCHECK(!(swapped_out && is_speculative));
950 1067
951 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; 1068 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
952 RenderFrameHostImpl* frame_to_announce = NULL; 1069 RenderFrameHostImpl* frame_to_announce = NULL;
953 int routing_id = MSG_ROUTING_NONE; 1070 int routing_id = MSG_ROUTING_NONE;
954 1071
955 // We are creating a pending or swapped out RFH here. We should never create 1072 // We are creating a pending or swapped out RFH here. We should never create
956 // it in the same SiteInstance as our current RFH. 1073 // it in the same SiteInstance as our current RFH.
957 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); 1074 CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
958 1075
959 // Check if we've already created an RFH for this SiteInstance. If so, try 1076 // 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
1013 // Don't show the main frame's view until we get a DidNavigate from it. 1130 // Don't show the main frame's view until we get a DidNavigate from it.
1014 render_view_host->GetView()->Hide(); 1131 render_view_host->GetView()->Hide();
1015 } else if (!swapped_out && pending_render_frame_host_) { 1132 } else if (!swapped_out && pending_render_frame_host_) {
1016 CancelPending(); 1133 CancelPending();
1017 } 1134 }
1018 routing_id = render_view_host->GetRoutingID(); 1135 routing_id = render_view_host->GetRoutingID();
1019 frame_to_announce = new_render_frame_host.get(); 1136 frame_to_announce = new_render_frame_host.get();
1020 } 1137 }
1021 1138
1022 // Use this as our new pending RFH if it isn't swapped out. 1139 // Use this as our new pending RFH if it isn't swapped out.
1023 if (!swapped_out) 1140 if (!swapped_out) {
1024 pending_render_frame_host_ = new_render_frame_host.Pass(); 1141 if (is_speculative)
1142 speculative_render_frame_host_ = new_render_frame_host.Pass();
1143 else
1144 pending_render_frame_host_ = new_render_frame_host.Pass();
1145 }
1025 1146
1026 // If a brand new RFH was created, announce it to observers. 1147 // If a brand new RFH was created, announce it to observers.
1027 if (frame_to_announce) 1148 if (frame_to_announce)
1028 render_frame_delegate_->RenderFrameCreated(frame_to_announce); 1149 render_frame_delegate_->RenderFrameCreated(frame_to_announce);
1029 1150
1030 return routing_id; 1151 return routing_id;
1031 } 1152 }
1032 1153
1033 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, 1154 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host,
1034 int opener_route_id, 1155 int opener_route_id,
(...skipping 16 matching lines...) Expand all
1051 if (!rvh_impl->IsSwappedOut()) { 1172 if (!rvh_impl->IsSwappedOut()) {
1052 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1173 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1053 render_view_host->GetProcess()->GetID())); 1174 render_view_host->GetProcess()->GetID()));
1054 } 1175 }
1055 } 1176 }
1056 1177
1057 return delegate_->CreateRenderViewForRenderManager( 1178 return delegate_->CreateRenderViewForRenderManager(
1058 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); 1179 render_view_host, opener_route_id, proxy_routing_id, for_main_frame);
1059 } 1180 }
1060 1181
1182 bool RenderFrameHostManager::InitRenderFrameHostsBeforeNavigation(
1183 RenderFrameHostImpl* dest_render_frame_host) {
1184 // If the current render_frame_host_ isn't live, we should create it so
1185 // that we don't show a sad tab while the dest_render_frame_host fetches
1186 // its first page. (crbug.com/1145340)
1187 if (dest_render_frame_host != render_frame_host_ &&
1188 !render_frame_host_->render_view_host()->IsRenderViewLive()) {
1189 // Note: we don't call InitRenderView here because we are navigating away
1190 // soon anyway, and we don't have the NavigationEntry for this host.
1191 delegate_->CreateRenderViewForRenderManager(
1192 render_frame_host_->render_view_host(), MSG_ROUTING_NONE,
1193 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame());
1194 }
1195
1196 // If the renderer crashed, then try to create a new one to satisfy this
1197 // navigation request.
1198 if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) {
1199 // Recreate the opener chain.
1200 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
1201 dest_render_frame_host->GetSiteInstance());
1202 if (!InitRenderView(dest_render_frame_host->render_view_host(),
1203 opener_route_id,
1204 MSG_ROUTING_NONE,
1205 frame_tree_node_->IsMainFrame()))
1206 return false;
1207
1208 // Now that we've created a new renderer, be sure to hide it if it isn't
1209 // our primary one. Otherwise, we might crash if we try to call Show()
1210 // on it later.
1211 if (dest_render_frame_host != render_frame_host_ &&
1212 dest_render_frame_host->render_view_host()->GetView()) {
1213 dest_render_frame_host->render_view_host()->GetView()->Hide();
1214 } else {
1215 // Notify here as we won't be calling CommitPending (which does the
1216 // notify).
1217 delegate_->NotifySwappedFromRenderManager(
1218 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame());
1219 }
1220 }
1221 return true;
1222 }
1223
1224 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
1225 const NavigationEntryImpl& entry) {
1226 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1227 SiteInstance* new_instance = current_instance;
1228
1229 // We do not currently swap processes for navigations in webview tag guests.
1230 bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
1231
1232 // Determine if we need a new BrowsingInstance for this entry. If true, this
1233 // implies that it will get a new SiteInstance (and likely process), and that
1234 // other tabs in the current BrowsingInstance will be unable to script it.
1235 // This is used for cases that require a process swap even in the
1236 // process-per-tab model, such as WebUI pages.
1237 const NavigationEntry* current_entry =
1238 delegate_->GetLastCommittedNavigationEntryForRenderManager();
1239 bool force_swap = !is_guest_scheme &&
1240 ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry);
1241 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
1242 new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap);
1243
1244 // If force_swap is true, we must use a different SiteInstance. If we didn't,
1245 // we would have two RenderFrameHosts in the same SiteInstance and the same
1246 // frame, resulting in page_id conflicts for their NavigationEntries.
1247 if (force_swap)
1248 CHECK_NE(new_instance, current_instance);
1249
1250 return new_instance;
1251 }
1252
1061 void RenderFrameHostManager::CommitPending() { 1253 void RenderFrameHostManager::CommitPending() {
1062 // First check whether we're going to want to focus the location bar after 1254 // 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 1255 // 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 1256 // 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. 1257 // this triggers won't be able to figure out what's going on.
1066 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1258 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1067 1259
1068 // We expect SwapOutOldPage to have canceled any modal dialogs and told the 1260 // 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, 1261 // 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 1262 // 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
1259 if (cross_navigation_pending_) { 1451 if (cross_navigation_pending_) {
1260 if (pending_render_frame_host_) 1452 if (pending_render_frame_host_)
1261 CancelPending(); 1453 CancelPending();
1262 cross_navigation_pending_ = false; 1454 cross_navigation_pending_ = false;
1263 } 1455 }
1264 1456
1265 // render_frame_host_'s SiteInstance and new_instance will not be deleted 1457 // 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 1458 // before the end of this method, so we don't have to worry about their ref
1267 // counts dropping to zero. 1459 // counts dropping to zero.
1268 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1460 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1269 SiteInstance* new_instance = current_instance; 1461 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 = 1462 const NavigationEntry* current_entry =
1280 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 1463 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 1464
1292 if (new_instance != current_instance) { 1465 if (new_instance != current_instance) {
1293 // New SiteInstance: create a pending RFH to navigate. 1466 // New SiteInstance: create a pending RFH to navigate.
1294 DCHECK(!cross_navigation_pending_); 1467 DCHECK(!cross_navigation_pending_);
1295 1468
1296 // This will possibly create (set to NULL) a Web UI object for the pending 1469 // 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 1470 // 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. 1471 // 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(), 1472 // It must also happen after the above conditional call to CancelPending(),
1300 // otherwise CancelPending may clear the pending_web_ui_ and the page will 1473 // otherwise CancelPending may clear the pending_web_ui_ and the page will
1301 // not have its bindings set appropriately. 1474 // not have its bindings set appropriately.
1302 SetPendingWebUI(entry); 1475 SetPendingWebUI(entry);
1303 1476
1304 // Ensure that we have created RFHs for the new RFH's opener chain if 1477 if (!CreateRenderFrameHostForNewSiteInstance(
1305 // we are staying in the same BrowsingInstance. This allows the pending RFH 1478 current_instance, new_instance, false)) {
1306 // to send cross-process script calls to its opener(s). 1479 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 } 1480 }
1312 1481
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. 1482 // Check if our current RFH is live before we set up a transition.
1321 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { 1483 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
1322 if (!cross_navigation_pending_) { 1484 if (!cross_navigation_pending_) {
1323 // The current RFH is not live. There's no reason to sit around with a 1485 // 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 1486 // 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 1487 // 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 1488 // cross-navigating (Note that we don't care about on{before}unload
1327 // handlers if the current RFH isn't live.) 1489 // handlers if the current RFH isn't live.)
1328 CommitPending(); 1490 CommitPending();
1329 return render_frame_host_.get(); 1491 return render_frame_host_.get();
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 SiteInstance* instance) const { 1668 SiteInstance* instance) const {
1507 RenderFrameProxyHostMap::const_iterator iter = 1669 RenderFrameProxyHostMap::const_iterator iter =
1508 proxy_hosts_.find(instance->GetId()); 1670 proxy_hosts_.find(instance->GetId());
1509 if (iter != proxy_hosts_.end()) 1671 if (iter != proxy_hosts_.end())
1510 return iter->second; 1672 return iter->second;
1511 1673
1512 return NULL; 1674 return NULL;
1513 } 1675 }
1514 1676
1515 } // namespace content 1677 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698