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

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 // PlzNavigate
50 FrameHostMsg_BeginNavigation_Params BeginNavigationFromNavigate(
51 const FrameMsg_Navigate_Params& navigate_params) {
52 FrameHostMsg_BeginNavigation_Params begin_navigation_params;
53 begin_navigation_params.method = navigate_params.is_post ?
54 "POST" : "GET";
55 begin_navigation_params.url = navigate_params.url;
56 begin_navigation_params.referrer = navigate_params.referrer.url;
57 begin_navigation_params.referrer_policy = navigate_params.referrer.policy;
58
59 // TODO(clamy): This should be modified to take into account caching policy
60 // requirements (eg for POST reloads).
61 begin_navigation_params.load_flags =
62 net::LOAD_NORMAL | net::LOAD_ENABLE_LOAD_TIMING;
63
64 // TODO(clamy): Post data from the browser should be put in the request body.
65
66 begin_navigation_params.has_user_gesture = false;
67 begin_navigation_params.transition_type = navigate_params.transition;
68 begin_navigation_params.should_replace_current_entry =
69 navigate_params.should_replace_current_entry;
70 begin_navigation_params.allow_download =
71 navigate_params.allow_download;
72 return begin_navigation_params;
73 }
74
75 } // namespace
76
45 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( 77 RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams(
46 const GlobalRequestID& global_request_id, 78 const GlobalRequestID& global_request_id,
47 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, 79 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
48 const std::vector<GURL>& transfer_url_chain, 80 const std::vector<GURL>& transfer_url_chain,
49 Referrer referrer, 81 Referrer referrer,
50 PageTransition page_transition, 82 PageTransition page_transition,
51 int render_frame_id, 83 int render_frame_id,
52 bool should_replace_current_entry) 84 bool should_replace_current_entry)
53 : global_request_id(global_request_id), 85 : global_request_id(global_request_id),
54 cross_site_transferring_request(cross_site_transferring_request.Pass()), 86 cross_site_transferring_request(cross_site_transferring_request.Pass()),
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 205 }
174 206
175 RenderFrameHostImpl* RenderFrameHostManager::Navigate( 207 RenderFrameHostImpl* RenderFrameHostManager::Navigate(
176 const NavigationEntryImpl& entry) { 208 const NavigationEntryImpl& entry) {
177 TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate"); 209 TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate");
178 // Create a pending RenderFrameHost to use for the navigation. 210 // Create a pending RenderFrameHost to use for the navigation.
179 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(entry); 211 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(entry);
180 if (!dest_render_frame_host) 212 if (!dest_render_frame_host)
181 return NULL; // We weren't able to create a pending render frame host. 213 return NULL; // We weren't able to create a pending render frame host.
182 214
183 // If the current render_frame_host_ isn't live, we should create it so 215 // 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 216 if (!InitRenderFrameHostsBeforeNavigation(dest_render_frame_host))
185 // its first page. (Bug 1145340) 217 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 218
221 // If entry includes the request ID of a request that is being transferred, 219 // 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 220 // the destination render frame will take ownership, so release ownership of
223 // the request. 221 // the request.
224 if (pending_nav_params_ && 222 if (pending_nav_params_ &&
225 pending_nav_params_->global_request_id == 223 pending_nav_params_->global_request_id ==
226 entry.transferred_global_request_id()) { 224 entry.transferred_global_request_id()) {
227 pending_nav_params_->cross_site_transferring_request->ReleaseRequest(); 225 pending_nav_params_->cross_site_transferring_request->ReleaseRequest();
228 } 226 }
229 227
230 return dest_render_frame_host; 228 return dest_render_frame_host;
231 } 229 }
232 230
231 // PlzNavigate
232 bool RenderFrameHostManager::RequestNavigation(
233 const NavigationEntryImpl& entry,
234 const FrameMsg_Navigate_Params& navigate_params) {
235 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
236 switches::kEnableBrowserSideNavigation));
237 // TODO(clamy): replace RenderViewHost::IsRenderViewLive by
238 // RenderFrameHost::IsLive.
239 if (render_frame_host_->render_view_host()->IsRenderViewLive())
240 // TODO(clamy): send a RequestNavigation IPC.
241 return true;
242
243 // The navigation request is sent directly to the IO thread.
244 OnBeginNavigation(BeginNavigationFromNavigate(navigate_params));
245 return true;
246 }
247
233 void RenderFrameHostManager::Stop() { 248 void RenderFrameHostManager::Stop() {
234 render_frame_host_->render_view_host()->Stop(); 249 render_frame_host_->render_view_host()->Stop();
235 250
236 // If we are cross-navigating, we should stop the pending renderers. This 251 // If we are cross-navigating, we should stop the pending renderers. This
237 // will lead to a DidFailProvisionalLoad, which will properly destroy them. 252 // will lead to a DidFailProvisionalLoad, which will properly destroy them.
238 if (cross_navigation_pending_) { 253 if (cross_navigation_pending_) {
239 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop( 254 pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop(
240 pending_render_frame_host_->render_view_host()->GetRoutingID())); 255 pending_render_frame_host_->render_view_host()->GetRoutingID()));
241 } 256 }
242 } 257 }
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 RFHPendingDeleteMap::iterator iter = 577 RFHPendingDeleteMap::iterator iter =
563 pending_delete_hosts_.find(site_instance_id); 578 pending_delete_hosts_.find(site_instance_id);
564 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh) 579 if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh)
565 pending_delete_hosts_.erase(site_instance_id); 580 pending_delete_hosts_.erase(site_instance_id);
566 } 581 }
567 582
568 void RenderFrameHostManager::ResetProxyHosts() { 583 void RenderFrameHostManager::ResetProxyHosts() {
569 STLDeleteValues(&proxy_hosts_); 584 STLDeleteValues(&proxy_hosts_);
570 } 585 }
571 586
587 // PlzNavigate
572 void RenderFrameHostManager::OnBeginNavigation( 588 void RenderFrameHostManager::OnBeginNavigation(
573 const FrameHostMsg_BeginNavigation_Params& params) { 589 const FrameHostMsg_BeginNavigation_Params& params) {
590 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
591 switches::kEnableBrowserSideNavigation));
574 // TODO(clamy): Check if navigations are blocked and if so, return 592 // TODO(clamy): Check if navigations are blocked and if so, return
575 // immediately. 593 // immediately.
576 NavigationRequestInfo info(params); 594 NavigationRequestInfo info(params);
577 595
578 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ? 596 info.first_party_for_cookies = frame_tree_node_->IsMainFrame() ?
579 params.url : frame_tree_node_->frame_tree()->root()->current_url(); 597 params.url : frame_tree_node_->frame_tree()->root()->current_url();
580 info.is_main_frame = frame_tree_node_->IsMainFrame(); 598 info.is_main_frame = frame_tree_node_->IsMainFrame();
581 info.parent_is_main_frame = !frame_tree_node_->parent() ? 599 info.parent_is_main_frame = !frame_tree_node_->parent() ?
582 false : frame_tree_node_->parent()->IsMainFrame(); 600 false : frame_tree_node_->parent()->IsMainFrame();
583 info.is_showing = GetRenderWidgetHostView()->IsShowing(); 601 info.is_showing = GetRenderWidgetHostView()->IsShowing();
584 602
603 // Create a speculative RFH for the navigation if necessary.
Charlie Reis 2014/08/05 23:59:51 "if necessary" is confusing, since it's never nece
604 RenderFrameHostImpl* dest_render_frame_host = render_frame_host_.get();
605 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
Charlie Reis 2014/08/05 23:59:51 These SiteInstance* pointers get very subtle, as w
606 SiteInstance* new_instance = GetSiteInstanceForNavigation(
607 *NavigationEntryImpl::FromNavigationEntry(
608 frame_tree_node_->navigator()->GetController()->GetPendingEntry()));
609 if (current_instance != new_instance) {
610 dest_render_frame_host = CreateRenderFrameHostForNewSiteInstance(
611 current_instance, new_instance, true);
612 DCHECK(dest_render_frame_host);
613 }
614 InitRenderFrameHostsBeforeNavigation(dest_render_frame_host);
615
585 navigation_request_.reset( 616 navigation_request_.reset(
586 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id())); 617 new NavigationRequest(info, frame_tree_node_->frame_tree_node_id()));
587 navigation_request_->BeginNavigation(params.request_body); 618 navigation_request_->BeginNavigation(params.request_body);
588 // TODO(clamy): If we have no live RenderFrameHost to handle the request (eg 619 }
589 // cross-site navigation) spawn one speculatively here and keep track of it. 620
621 // PlzNavigate
622 void RenderFrameHostManager::CommitNavigation(
623 const NavigationBeforeCommitInfo& info) {
624 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
625 switches::kEnableBrowserSideNavigation));
626 // Update the pending NavigationEntry for commit.
627 // TODO(clamy): Check if some more state should be updated at that point.
628 NavigationEntry* entry =
629 frame_tree_node_->navigator()->GetController()->GetPendingEntry();
630 entry->SetURL(info.navigation_url);
631
632 // Pick the right RenderFrameHost to commit the navigation. If the current RFH
633 // is not suitable, a RFH may have been spawned speculatively to handle the
634 // navigation. If there is none, or if it is not suitable, a new RFH needs to
635 // be created.
636 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
637 SiteInstance* speculative_instance = speculative_render_frame_host_.get() ?
638 speculative_render_frame_host_->GetSiteInstance() : NULL;
639 DCHECK(current_instance != speculative_instance);
640
641 SiteInstance* new_instance = GetSiteInstanceForNavigation(
642 *NavigationEntryImpl::FromNavigationEntry(entry));
643 RenderFrameHostImpl* rfh_to_navigate = NULL;
644 DCHECK(!pending_render_frame_host_.get());
645
646 if (current_instance == new_instance)
647 rfh_to_navigate = render_frame_host_.get();
648
649 if (speculative_instance) {
650 if (speculative_instance == new_instance) {
651 rfh_to_navigate = speculative_render_frame_host_.get();
652 } else {
653 speculative_render_frame_host_.reset();
654 }
655 }
656
657 if (!rfh_to_navigate) {
658 rfh_to_navigate = CreateRenderFrameHostForNewSiteInstance(
659 current_instance, new_instance, true);
660 DCHECK(rfh_to_navigate);
661 }
662
663 // A WebUI renderer should never display a non WebUI url.
664 frame_tree_node_->navigator()->CheckWebUIRendererDoesNotDisplayNormalURL(
Charlie Reis 2014/08/05 23:59:51 This feels awkward to me. I don't think we should
665 rfh_to_navigate, info.navigation_url);
666
667 // TODO(clamy): the rfh_to_navigate should now send a commit IPC to the
668 // renderer.
669 // TODO(clamy): If the current RFH is not reused, we should ask it to run its
670 // unload handler, and possibly create a RenderFrameProxyHost for it.
671 // Otherwise we are leaking the current RFH here.
672 if (rfh_to_navigate != render_frame_host_.get())
673 SetRenderFrameHost(speculative_render_frame_host_.Pass());
674 DCHECK(!speculative_render_frame_host_.get());
675
676 navigation_request_.reset();
590 } 677 }
591 678
592 void RenderFrameHostManager::Observe( 679 void RenderFrameHostManager::Observe(
593 int type, 680 int type,
594 const NotificationSource& source, 681 const NotificationSource& source,
595 const NotificationDetails& details) { 682 const NotificationDetails& details) {
596 switch (type) { 683 switch (type) {
597 case NOTIFICATION_RENDERER_PROCESS_CLOSED: 684 case NOTIFICATION_RENDERER_PROCESS_CLOSED:
598 case NOTIFICATION_RENDERER_PROCESS_CLOSING: 685 case NOTIFICATION_RENDERER_PROCESS_CLOSING:
599 RendererProcessClosing( 686 RendererProcessClosing(
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 const NavigationEntryImpl* new_entry) const { 813 const NavigationEntryImpl* new_entry) const {
727 NavigationControllerImpl& controller = 814 NavigationControllerImpl& controller =
728 delegate_->GetControllerForRenderManager(); 815 delegate_->GetControllerForRenderManager();
729 return current_entry && web_ui_.get() && 816 return current_entry && web_ui_.get() &&
730 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 817 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
731 controller.GetBrowserContext(), current_entry->GetURL()) == 818 controller.GetBrowserContext(), current_entry->GetURL()) ==
732 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 819 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
733 controller.GetBrowserContext(), new_entry->GetURL())); 820 controller.GetBrowserContext(), new_entry->GetURL()));
734 } 821 }
735 822
823 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
824 const NavigationEntryImpl& entry) {
825 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
826 SiteInstance* new_instance = current_instance;
827
828 // We do not currently swap processes for navigations in webview tag guests.
829 bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
830
831 // Determine if we need a new BrowsingInstance for this entry. If true, this
832 // implies that it will get a new SiteInstance (and likely process), and that
833 // other tabs in the current BrowsingInstance will be unable to script it.
834 // This is used for cases that require a process swap even in the
835 // process-per-tab model, such as WebUI pages.
836 const NavigationEntry* current_entry =
837 delegate_->GetLastCommittedNavigationEntryForRenderManager();
838 bool force_swap = !is_guest_scheme &&
839 ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry);
840 if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
841 new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap);
842
843 // If force_swap is true, we must use a different SiteInstance. If we didn't,
844 // we would have two RenderFrameHosts in the same SiteInstance and the same
845 // frame, resulting in page_id conflicts for their NavigationEntries.
846 if (force_swap)
847 CHECK_NE(new_instance, current_instance);
848
849 return new_instance;
850 }
851
736 SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry( 852 SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
737 const NavigationEntryImpl& entry, 853 const NavigationEntryImpl& entry,
738 SiteInstance* current_instance, 854 SiteInstance* current_instance,
739 bool force_browsing_instance_swap) { 855 bool force_browsing_instance_swap) {
740 // Determine which SiteInstance to use for navigating to |entry|. 856 // Determine which SiteInstance to use for navigating to |entry|.
741 const GURL& dest_url = entry.GetURL(); 857 const GURL& dest_url = entry.GetURL();
742 NavigationControllerImpl& controller = 858 NavigationControllerImpl& controller =
743 delegate_->GetControllerForRenderManager(); 859 delegate_->GetControllerForRenderManager();
744 BrowserContext* browser_context = controller.GetBrowserContext(); 860 BrowserContext* browser_context = controller.GetBrowserContext();
745 861
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 } 1009 }
894 1010
895 // Start the new renderer in a new SiteInstance, but in the current 1011 // Start the new renderer in a new SiteInstance, but in the current
896 // BrowsingInstance. It is important to immediately give this new 1012 // BrowsingInstance. It is important to immediately give this new
897 // SiteInstance to a RenderViewHost (if it is different than our current 1013 // SiteInstance to a RenderViewHost (if it is different than our current
898 // SiteInstance), so that it is ref counted. This will happen in 1014 // SiteInstance), so that it is ref counted. This will happen in
899 // CreateRenderView. 1015 // CreateRenderView.
900 return current_instance->GetRelatedSiteInstance(dest_url); 1016 return current_instance->GetRelatedSiteInstance(dest_url);
901 } 1017 }
902 1018
1019 RenderFrameHostImpl* RenderFrameHostManager::
1020 CreateRenderFrameHostForNewSiteInstance(
1021 SiteInstance* old_instance,
1022 SiteInstance* new_instance,
1023 bool is_speculative) {
1024 // Ensure that we have created RFHs for the new RFH's opener chain if
1025 // we are staying in the same BrowsingInstance. This allows the new RFH
1026 // to send cross-process script calls to its opener(s).
1027 int opener_route_id = MSG_ROUTING_NONE;
1028 if (new_instance->IsRelatedSiteInstance(old_instance)) {
1029 opener_route_id =
1030 delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
1031 }
1032
1033 // Create a non-swapped-out RFH with the given opener.
1034 int route_id = CreateRenderFrame(new_instance, opener_route_id, false,
1035 delegate_->IsHidden(), is_speculative);
1036 if (route_id == MSG_ROUTING_NONE) {
1037 if (is_speculative)
1038 speculative_render_frame_host_.reset();
1039 else
1040 pending_render_frame_host_.reset();
1041 return NULL;
1042 }
1043 if (is_speculative)
1044 return speculative_render_frame_host_.get();
1045 return pending_render_frame_host_.get();
1046 }
1047
903 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost( 1048 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
904 SiteInstance* site_instance, 1049 SiteInstance* site_instance,
905 int view_routing_id, 1050 int view_routing_id,
906 int frame_routing_id, 1051 int frame_routing_id,
907 bool swapped_out, 1052 bool swapped_out,
908 bool hidden) { 1053 bool hidden) {
909 if (frame_routing_id == MSG_ROUTING_NONE) 1054 if (frame_routing_id == MSG_ROUTING_NONE)
910 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID(); 1055 frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
911 1056
912 // Create a RVH for main frames, or find the existing one for subframes. 1057 // Create a RVH for main frames, or find the existing one for subframes.
(...skipping 24 matching lines...) Expand all
937 frame_tree_node_, 1082 frame_tree_node_,
938 frame_routing_id, 1083 frame_routing_id,
939 swapped_out).release()); 1084 swapped_out).release());
940 return render_frame_host.Pass(); 1085 return render_frame_host.Pass();
941 } 1086 }
942 1087
943 int RenderFrameHostManager::CreateRenderFrame( 1088 int RenderFrameHostManager::CreateRenderFrame(
944 SiteInstance* instance, 1089 SiteInstance* instance,
945 int opener_route_id, 1090 int opener_route_id,
946 bool swapped_out, 1091 bool swapped_out,
947 bool hidden) { 1092 bool hidden,
1093 bool is_speculative) {
948 CHECK(instance); 1094 CHECK(instance);
949 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. 1095 DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
1096 DCHECK(!(swapped_out && is_speculative));
950 1097
951 scoped_ptr<RenderFrameHostImpl> new_render_frame_host; 1098 scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
952 RenderFrameHostImpl* frame_to_announce = NULL; 1099 RenderFrameHostImpl* frame_to_announce = NULL;
953 int routing_id = MSG_ROUTING_NONE; 1100 int routing_id = MSG_ROUTING_NONE;
954 1101
955 // We are creating a pending or swapped out RFH here. We should never create 1102 // We are creating a pending or swapped out RFH here. We should never create
956 // it in the same SiteInstance as our current RFH. 1103 // it in the same SiteInstance as our current RFH.
957 CHECK_NE(render_frame_host_->GetSiteInstance(), instance); 1104 CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
958 1105
959 // Check if we've already created an RFH for this SiteInstance. If so, try 1106 // 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. 1160 // Don't show the main frame's view until we get a DidNavigate from it.
1014 render_view_host->GetView()->Hide(); 1161 render_view_host->GetView()->Hide();
1015 } else if (!swapped_out && pending_render_frame_host_) { 1162 } else if (!swapped_out && pending_render_frame_host_) {
1016 CancelPending(); 1163 CancelPending();
1017 } 1164 }
1018 routing_id = render_view_host->GetRoutingID(); 1165 routing_id = render_view_host->GetRoutingID();
1019 frame_to_announce = new_render_frame_host.get(); 1166 frame_to_announce = new_render_frame_host.get();
1020 } 1167 }
1021 1168
1022 // Use this as our new pending RFH if it isn't swapped out. 1169 // Use this as our new pending RFH if it isn't swapped out.
1023 if (!swapped_out) 1170 if (!swapped_out) {
1024 pending_render_frame_host_ = new_render_frame_host.Pass(); 1171 if (is_speculative)
1172 speculative_render_frame_host_ = new_render_frame_host.Pass();
1173 else
1174 pending_render_frame_host_ = new_render_frame_host.Pass();
1175 }
1025 1176
1026 // If a brand new RFH was created, announce it to observers. 1177 // If a brand new RFH was created, announce it to observers.
1027 if (frame_to_announce) 1178 if (frame_to_announce)
1028 render_frame_delegate_->RenderFrameCreated(frame_to_announce); 1179 render_frame_delegate_->RenderFrameCreated(frame_to_announce);
1029 1180
1030 return routing_id; 1181 return routing_id;
1031 } 1182 }
1032 1183
1033 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, 1184 bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host,
1034 int opener_route_id, 1185 int opener_route_id,
(...skipping 16 matching lines...) Expand all
1051 if (!rvh_impl->IsSwappedOut()) { 1202 if (!rvh_impl->IsSwappedOut()) {
1052 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1203 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
1053 render_view_host->GetProcess()->GetID())); 1204 render_view_host->GetProcess()->GetID()));
1054 } 1205 }
1055 } 1206 }
1056 1207
1057 return delegate_->CreateRenderViewForRenderManager( 1208 return delegate_->CreateRenderViewForRenderManager(
1058 render_view_host, opener_route_id, proxy_routing_id, for_main_frame); 1209 render_view_host, opener_route_id, proxy_routing_id, for_main_frame);
1059 } 1210 }
1060 1211
1212 bool RenderFrameHostManager::InitRenderFrameHostsBeforeNavigation(
1213 RenderFrameHostImpl* dest_render_frame_host) {
1214 // If the current render_frame_host_ isn't live, we should create it so
1215 // that we don't show a sad tab while the dest_render_frame_host fetches
1216 // its first page. (crbug.com/1145340)
1217 if (dest_render_frame_host != render_frame_host_ &&
1218 !render_frame_host_->render_view_host()->IsRenderViewLive()) {
1219 // Note: we don't call InitRenderView here because we are navigating away
1220 // soon anyway, and we don't have the NavigationEntry for this host.
1221 delegate_->CreateRenderViewForRenderManager(
1222 render_frame_host_->render_view_host(), MSG_ROUTING_NONE,
1223 MSG_ROUTING_NONE, frame_tree_node_->IsMainFrame());
1224 }
1225
1226 // If the renderer crashed, then try to create a new one to satisfy this
1227 // navigation request.
1228 if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) {
1229 // Recreate the opener chain.
1230 int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
1231 dest_render_frame_host->GetSiteInstance());
1232 if (!InitRenderView(dest_render_frame_host->render_view_host(),
1233 opener_route_id,
1234 MSG_ROUTING_NONE,
1235 frame_tree_node_->IsMainFrame()))
1236 return false;
1237
1238 // Now that we've created a new renderer, be sure to hide it if it isn't
1239 // our primary one. Otherwise, we might crash if we try to call Show()
1240 // on it later.
1241 if (dest_render_frame_host != render_frame_host_ &&
1242 dest_render_frame_host->render_view_host()->GetView()) {
1243 dest_render_frame_host->render_view_host()->GetView()->Hide();
1244 } else {
1245 // Notify here as we won't be calling CommitPending (which does the
1246 // notify).
1247 delegate_->NotifySwappedFromRenderManager(
1248 NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame());
1249 }
1250 }
1251 return true;
1252 }
1253
1061 void RenderFrameHostManager::CommitPending() { 1254 void RenderFrameHostManager::CommitPending() {
1062 // First check whether we're going to want to focus the location bar after 1255 // 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 1256 // 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 1257 // 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. 1258 // this triggers won't be able to figure out what's going on.
1066 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 1259 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
1067 1260
1068 // We expect SwapOutOldPage to have canceled any modal dialogs and told the 1261 // 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, 1262 // 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 1263 // 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_) { 1452 if (cross_navigation_pending_) {
1260 if (pending_render_frame_host_) 1453 if (pending_render_frame_host_)
1261 CancelPending(); 1454 CancelPending();
1262 cross_navigation_pending_ = false; 1455 cross_navigation_pending_ = false;
1263 } 1456 }
1264 1457
1265 // render_frame_host_'s SiteInstance and new_instance will not be deleted 1458 // 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 1459 // before the end of this method, so we don't have to worry about their ref
1267 // counts dropping to zero. 1460 // counts dropping to zero.
1268 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1461 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1269 SiteInstance* new_instance = current_instance; 1462 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 = 1463 const NavigationEntry* current_entry =
1280 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 1464 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 1465
1292 if (new_instance != current_instance) { 1466 if (new_instance != current_instance) {
1293 // New SiteInstance: create a pending RFH to navigate. 1467 // New SiteInstance: create a pending RFH to navigate.
1294 DCHECK(!cross_navigation_pending_); 1468 DCHECK(!cross_navigation_pending_);
1295 1469
1296 // This will possibly create (set to NULL) a Web UI object for the pending 1470 // 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 1471 // 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. 1472 // 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(), 1473 // It must also happen after the above conditional call to CancelPending(),
1300 // otherwise CancelPending may clear the pending_web_ui_ and the page will 1474 // otherwise CancelPending may clear the pending_web_ui_ and the page will
1301 // not have its bindings set appropriately. 1475 // not have its bindings set appropriately.
1302 SetPendingWebUI(entry); 1476 SetPendingWebUI(entry);
1303 1477
1304 // Ensure that we have created RFHs for the new RFH's opener chain if 1478 if (!CreateRenderFrameHostForNewSiteInstance(
1305 // we are staying in the same BrowsingInstance. This allows the pending RFH 1479 current_instance, new_instance, false)) {
1306 // to send cross-process script calls to its opener(s). 1480 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 } 1481 }
1312 1482
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. 1483 // Check if our current RFH is live before we set up a transition.
1321 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) { 1484 if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
1322 if (!cross_navigation_pending_) { 1485 if (!cross_navigation_pending_) {
1323 // The current RFH is not live. There's no reason to sit around with a 1486 // 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 1487 // 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 1488 // 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 1489 // cross-navigating (Note that we don't care about on{before}unload
1327 // handlers if the current RFH isn't live.) 1490 // handlers if the current RFH isn't live.)
1328 CommitPending(); 1491 CommitPending();
1329 return render_frame_host_.get(); 1492 return render_frame_host_.get();
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 SiteInstance* instance) const { 1669 SiteInstance* instance) const {
1507 RenderFrameProxyHostMap::const_iterator iter = 1670 RenderFrameProxyHostMap::const_iterator iter =
1508 proxy_hosts_.find(instance->GetId()); 1671 proxy_hosts_.find(instance->GetId());
1509 if (iter != proxy_hosts_.end()) 1672 if (iter != proxy_hosts_.end())
1510 return iter->second; 1673 return iter->second;
1511 1674
1512 return NULL; 1675 return NULL;
1513 } 1676 }
1514 1677
1515 } // namespace content 1678 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698