OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/frame_host/render_frame_host_manager.h" | 5 #include "content/browser/frame_host/render_frame_host_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "content/browser/frame_host/navigation_request.h" | 23 #include "content/browser/frame_host/navigation_request.h" |
24 #include "content/browser/frame_host/navigator.h" | 24 #include "content/browser/frame_host/navigator.h" |
25 #include "content/browser/frame_host/render_frame_host_factory.h" | 25 #include "content/browser/frame_host/render_frame_host_factory.h" |
26 #include "content/browser/frame_host/render_frame_host_impl.h" | 26 #include "content/browser/frame_host/render_frame_host_impl.h" |
27 #include "content/browser/frame_host/render_frame_proxy_host.h" | 27 #include "content/browser/frame_host/render_frame_proxy_host.h" |
28 #include "content/browser/renderer_host/render_process_host_impl.h" | 28 #include "content/browser/renderer_host/render_process_host_impl.h" |
29 #include "content/browser/renderer_host/render_view_host_factory.h" | 29 #include "content/browser/renderer_host/render_view_host_factory.h" |
30 #include "content/browser/renderer_host/render_view_host_impl.h" | 30 #include "content/browser/renderer_host/render_view_host_impl.h" |
31 #include "content/browser/site_instance_impl.h" | 31 #include "content/browser/site_instance_impl.h" |
32 #include "content/browser/webui/web_ui_controller_factory_registry.h" | 32 #include "content/browser/webui/web_ui_controller_factory_registry.h" |
| 33 #include "content/browser/webui/web_ui_impl.h" |
33 #include "content/common/frame_messages.h" | 34 #include "content/common/frame_messages.h" |
34 #include "content/common/site_isolation_policy.h" | 35 #include "content/common/site_isolation_policy.h" |
35 #include "content/common/view_messages.h" | 36 #include "content/common/view_messages.h" |
36 #include "content/public/browser/content_browser_client.h" | 37 #include "content/public/browser/content_browser_client.h" |
37 #include "content/public/browser/render_process_host_observer.h" | 38 #include "content/public/browser/render_process_host_observer.h" |
38 #include "content/public/browser/render_widget_host_iterator.h" | 39 #include "content/public/browser/render_widget_host_iterator.h" |
39 #include "content/public/browser/render_widget_host_view.h" | 40 #include "content/public/browser/render_widget_host_view.h" |
40 #include "content/public/browser/user_metrics.h" | 41 #include "content/public/browser/user_metrics.h" |
| 42 #include "content/public/browser/web_ui_controller.h" |
41 #include "content/public/common/browser_plugin_guest_mode.h" | 43 #include "content/public/common/browser_plugin_guest_mode.h" |
42 #include "content/public/common/content_switches.h" | 44 #include "content/public/common/content_switches.h" |
43 #include "content/public/common/referrer.h" | 45 #include "content/public/common/referrer.h" |
44 #include "content/public/common/url_constants.h" | 46 #include "content/public/common/url_constants.h" |
45 | 47 |
46 namespace content { | 48 namespace content { |
47 | 49 |
48 namespace { | 50 namespace { |
49 | 51 |
50 // Helper function to add the FrameTree of the given node's opener to the list | 52 // Helper function to add the FrameTree of the given node's opener to the list |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 RenderViewHostDelegate* render_view_delegate, | 213 RenderViewHostDelegate* render_view_delegate, |
212 RenderWidgetHostDelegate* render_widget_delegate, | 214 RenderWidgetHostDelegate* render_widget_delegate, |
213 Delegate* delegate) | 215 Delegate* delegate) |
214 : frame_tree_node_(frame_tree_node), | 216 : frame_tree_node_(frame_tree_node), |
215 delegate_(delegate), | 217 delegate_(delegate), |
216 render_frame_delegate_(render_frame_delegate), | 218 render_frame_delegate_(render_frame_delegate), |
217 render_view_delegate_(render_view_delegate), | 219 render_view_delegate_(render_view_delegate), |
218 render_widget_delegate_(render_widget_delegate), | 220 render_widget_delegate_(render_widget_delegate), |
219 proxy_hosts_(new RenderFrameProxyHostMap(this)), | 221 proxy_hosts_(new RenderFrameProxyHostMap(this)), |
220 interstitial_page_(nullptr), | 222 interstitial_page_(nullptr), |
221 current_web_ui_is_navigating_(false), | 223 should_reuse_web_ui_(false), |
222 weak_factory_(this) { | 224 weak_factory_(this) { |
223 DCHECK(frame_tree_node_); | 225 DCHECK(frame_tree_node_); |
224 } | 226 } |
225 | 227 |
226 RenderFrameHostManager::~RenderFrameHostManager() { | 228 RenderFrameHostManager::~RenderFrameHostManager() { |
227 if (pending_render_frame_host_) { | 229 if (pending_render_frame_host_) { |
228 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost(); | 230 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost(); |
229 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); | 231 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); |
230 } | 232 } |
231 | 233 |
232 if (speculative_render_frame_host_) { | 234 if (speculative_render_frame_host_) { |
233 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost(); | 235 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost(); |
234 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); | 236 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); |
235 } | 237 } |
236 | 238 |
237 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get()); | 239 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get()); |
238 | 240 |
239 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts. | 241 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts. |
240 // It is important to delete those prior to deleting the current | 242 // It is important to delete those prior to deleting the current |
241 // RenderFrameHost, since the CrossProcessFrameConnector (owned by | 243 // RenderFrameHost, since the CrossProcessFrameConnector (owned by |
242 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with | 244 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with |
243 // the current RenderFrameHost and uses it during its destructor. | 245 // the current RenderFrameHost and uses it during its destructor. |
244 ResetProxyHosts(); | 246 ResetProxyHosts(); |
245 | 247 |
| 248 // Release the WebUI prior to resetting the current RenderFrameHost, as the |
| 249 // WebUI accesses the RenderFrameHost during cleanup. |
| 250 web_ui_.reset(); |
| 251 |
246 // We should always have a current RenderFrameHost except in some tests. | 252 // We should always have a current RenderFrameHost except in some tests. |
247 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); | 253 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); |
248 } | 254 } |
249 | 255 |
250 void RenderFrameHostManager::Init(SiteInstance* site_instance, | 256 void RenderFrameHostManager::Init(SiteInstance* site_instance, |
251 int32 view_routing_id, | 257 int32 view_routing_id, |
252 int32 frame_routing_id, | 258 int32 frame_routing_id, |
253 int32 widget_routing_id) { | 259 int32 widget_routing_id) { |
254 DCHECK(site_instance); | 260 DCHECK(site_instance); |
255 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must | 261 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must |
(...skipping 20 matching lines...) Expand all Loading... |
276 return nullptr; | 282 return nullptr; |
277 return render_frame_host_->render_view_host(); | 283 return render_frame_host_->render_view_host(); |
278 } | 284 } |
279 | 285 |
280 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { | 286 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { |
281 if (!pending_render_frame_host_) | 287 if (!pending_render_frame_host_) |
282 return nullptr; | 288 return nullptr; |
283 return pending_render_frame_host_->render_view_host(); | 289 return pending_render_frame_host_->render_view_host(); |
284 } | 290 } |
285 | 291 |
286 WebUIImpl* RenderFrameHostManager::GetNavigatingWebUI() const { | |
287 if (current_web_ui_is_navigating_) | |
288 return render_frame_host_->web_ui(); | |
289 | |
290 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
291 switches::kEnableBrowserSideNavigation)) { | |
292 if (speculative_render_frame_host_) | |
293 return speculative_render_frame_host_->web_ui(); | |
294 } else { | |
295 if (pending_render_frame_host_) | |
296 return pending_render_frame_host_->web_ui(); | |
297 } | |
298 return nullptr; | |
299 } | |
300 | |
301 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { | 292 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { |
302 if (interstitial_page_) | 293 if (interstitial_page_) |
303 return interstitial_page_->GetView(); | 294 return interstitial_page_->GetView(); |
304 if (render_frame_host_) | 295 if (render_frame_host_) |
305 return render_frame_host_->GetView(); | 296 return render_frame_host_->GetView(); |
306 return nullptr; | 297 return nullptr; |
307 } | 298 } |
308 | 299 |
309 bool RenderFrameHostManager::ForInnerDelegate() { | 300 bool RenderFrameHostManager::ForInnerDelegate() { |
310 return delegate_->GetOuterDelegateFrameTreeNodeID() != | 301 return delegate_->GetOuterDelegateFrameTreeNodeID() != |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 | 350 |
360 void RenderFrameHostManager::RemoveOuterDelegateFrame() { | 351 void RenderFrameHostManager::RemoveOuterDelegateFrame() { |
361 FrameTreeNode* outer_delegate_frame_tree_node = | 352 FrameTreeNode* outer_delegate_frame_tree_node = |
362 FrameTreeNode::GloballyFindByID( | 353 FrameTreeNode::GloballyFindByID( |
363 delegate_->GetOuterDelegateFrameTreeNodeID()); | 354 delegate_->GetOuterDelegateFrameTreeNodeID()); |
364 DCHECK(outer_delegate_frame_tree_node->parent()); | 355 DCHECK(outer_delegate_frame_tree_node->parent()); |
365 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( | 356 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( |
366 outer_delegate_frame_tree_node); | 357 outer_delegate_frame_tree_node); |
367 } | 358 } |
368 | 359 |
| 360 void RenderFrameHostManager::SetPendingWebUI(const GURL& url, int bindings) { |
| 361 pending_web_ui_ = CreateWebUI(url, bindings); |
| 362 pending_and_current_web_ui_.reset(); |
| 363 } |
| 364 |
| 365 scoped_ptr<WebUIImpl> RenderFrameHostManager::CreateWebUI(const GURL& url, |
| 366 int bindings) { |
| 367 scoped_ptr<WebUIImpl> new_web_ui(delegate_->CreateWebUIForRenderManager(url)); |
| 368 |
| 369 // If we have assigned (zero or more) bindings to this NavigationEntry in the |
| 370 // past, make sure we're not granting it different bindings than it had |
| 371 // before. If so, note it and don't give it any bindings, to avoid a |
| 372 // potential privilege escalation. |
| 373 if (new_web_ui && bindings != NavigationEntryImpl::kInvalidBindings && |
| 374 new_web_ui->GetBindings() != bindings) { |
| 375 RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM")); |
| 376 return nullptr; |
| 377 } |
| 378 return new_web_ui.Pass(); |
| 379 } |
| 380 |
369 RenderFrameHostImpl* RenderFrameHostManager::Navigate( | 381 RenderFrameHostImpl* RenderFrameHostManager::Navigate( |
370 const GURL& dest_url, | 382 const GURL& dest_url, |
371 const FrameNavigationEntry& frame_entry, | 383 const FrameNavigationEntry& frame_entry, |
372 const NavigationEntryImpl& entry) { | 384 const NavigationEntryImpl& entry) { |
373 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", | 385 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", |
374 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 386 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
375 // Create a pending RenderFrameHost to use for the navigation. | 387 // Create a pending RenderFrameHost to use for the navigation. |
376 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( | 388 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( |
377 dest_url, | 389 dest_url, |
378 // TODO(creis): Move source_site_instance to FNE. | 390 // TODO(creis): Move source_site_instance to FNE. |
(...skipping 28 matching lines...) Expand all Loading... |
407 // site that is handled via Mojo, then Mojo WebUI code in //chrome will | 419 // site that is handled via Mojo, then Mojo WebUI code in //chrome will |
408 // add a service to this RFH's ServiceRegistry). | 420 // add a service to this RFH's ServiceRegistry). |
409 dest_render_frame_host->SetUpMojoIfNeeded(); | 421 dest_render_frame_host->SetUpMojoIfNeeded(); |
410 | 422 |
411 // Recreate the opener chain. | 423 // Recreate the opener chain. |
412 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), | 424 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), |
413 frame_tree_node_); | 425 frame_tree_node_); |
414 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) | 426 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) |
415 return nullptr; | 427 return nullptr; |
416 | 428 |
417 if (GetNavigatingWebUI()) { | |
418 GetNavigatingWebUI()->RenderViewCreated( | |
419 dest_render_frame_host->render_view_host()); | |
420 } | |
421 | |
422 // Now that we've created a new renderer, be sure to hide it if it isn't | 429 // Now that we've created a new renderer, be sure to hide it if it isn't |
423 // our primary one. Otherwise, we might crash if we try to call Show() | 430 // our primary one. Otherwise, we might crash if we try to call Show() |
424 // on it later. | 431 // on it later. |
425 if (dest_render_frame_host != render_frame_host_) { | 432 if (dest_render_frame_host != render_frame_host_) { |
426 if (dest_render_frame_host->GetView()) | 433 if (dest_render_frame_host->GetView()) |
427 dest_render_frame_host->GetView()->Hide(); | 434 dest_render_frame_host->GetView()->Hide(); |
428 } else { | 435 } else { |
429 // After a renderer crash we'd have marked the host as invisible, so we | 436 // After a renderer crash we'd have marked the host as invisible, so we |
430 // need to set the visibility of the new View to the correct value here | 437 // need to set the visibility of the new View to the correct value here |
431 // after reload. | 438 // after reload. |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 | 669 |
663 // Make sure any dynamic changes to this frame's sandbox flags that were made | 670 // Make sure any dynamic changes to this frame's sandbox flags that were made |
664 // prior to navigation take effect. | 671 // prior to navigation take effect. |
665 CommitPendingSandboxFlags(); | 672 CommitPendingSandboxFlags(); |
666 } | 673 } |
667 | 674 |
668 void RenderFrameHostManager::CommitPendingIfNecessary( | 675 void RenderFrameHostManager::CommitPendingIfNecessary( |
669 RenderFrameHostImpl* render_frame_host, | 676 RenderFrameHostImpl* render_frame_host, |
670 bool was_caused_by_user_gesture) { | 677 bool was_caused_by_user_gesture) { |
671 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { | 678 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { |
672 DCHECK(!current_web_ui_is_navigating_ || render_frame_host_->web_ui()); | 679 DCHECK(!should_reuse_web_ui_ || web_ui_); |
673 | 680 |
674 // We should only hear this from our current renderer. | 681 // We should only hear this from our current renderer. |
675 DCHECK_EQ(render_frame_host_, render_frame_host); | 682 DCHECK_EQ(render_frame_host_, render_frame_host); |
676 | 683 |
677 // A commit is required if there is a navigating WebUI, even without a | 684 // Even when there is no pending RVH, there may be a pending Web UI. |
678 // pending or speculative RenderFrameHost. | 685 if (pending_web_ui() || speculative_web_ui_) |
679 if (GetNavigatingWebUI()) | |
680 CommitPending(); | 686 CommitPending(); |
681 return; | 687 return; |
682 } | 688 } |
683 | 689 |
684 if (render_frame_host == pending_render_frame_host_ || | 690 if (render_frame_host == pending_render_frame_host_ || |
685 render_frame_host == speculative_render_frame_host_) { | 691 render_frame_host == speculative_render_frame_host_) { |
686 // The pending cross-process navigation completed, so show the renderer. | 692 // The pending cross-process navigation completed, so show the renderer. |
687 CommitPending(); | 693 CommitPending(); |
688 } else if (render_frame_host == render_frame_host_) { | 694 } else if (render_frame_host == render_frame_host_) { |
689 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 695 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 // Subframe navigations will use the current renderer, unless | 1018 // Subframe navigations will use the current renderer, unless |
1013 // --site-per-process is enabled. | 1019 // --site-per-process is enabled. |
1014 // TODO(carlosk): Have renderer-initated main frame navigations swap processes | 1020 // TODO(carlosk): Have renderer-initated main frame navigations swap processes |
1015 // if needed when it no longer breaks OAuth popups (see | 1021 // if needed when it no longer breaks OAuth popups (see |
1016 // https://crbug.com/440266). | 1022 // https://crbug.com/440266). |
1017 bool is_main_frame = frame_tree_node_->IsMainFrame(); | 1023 bool is_main_frame = frame_tree_node_->IsMainFrame(); |
1018 if (current_site_instance == dest_site_instance.get() || | 1024 if (current_site_instance == dest_site_instance.get() || |
1019 (!request.browser_initiated() && is_main_frame) || | 1025 (!request.browser_initiated() && is_main_frame) || |
1020 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && | 1026 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && |
1021 !current_site_instance->RequiresDedicatedProcess())) { | 1027 !current_site_instance->RequiresDedicatedProcess())) { |
1022 // Reuse the current RenderFrameHost if its SiteInstance matches the the | 1028 // Reuse the current RFH if its SiteInstance matches the the navigation's |
1023 // navigation's or if this is a subframe navigation. We only swap RFHs for | 1029 // or if this is a subframe navigation. We only swap RFHs for subframes when |
1024 // subframes when --site-per-process is enabled. | 1030 // --site-per-process is enabled. |
1025 CleanUpNavigation(); | 1031 CleanUpNavigation(); |
1026 navigation_rfh = render_frame_host_.get(); | 1032 navigation_rfh = render_frame_host_.get(); |
1027 | 1033 |
1028 UpdateWebUIOnCurrentFrameHost( | 1034 // As SiteInstances are the same, check if the WebUI should be reused. |
1029 request.common_params().url, | 1035 const NavigationEntry* current_navigation_entry = |
1030 request.restore_type() != NavigationEntryImpl::RESTORE_NONE, | 1036 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
1031 request.bindings()); | 1037 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, |
1032 | 1038 request.common_params().url); |
1033 DCHECK(!speculative_render_frame_host_); | 1039 if (!should_reuse_web_ui_) { |
| 1040 speculative_web_ui_ = CreateWebUI(request.common_params().url, |
| 1041 request.bindings()); |
| 1042 // Make sure the current RenderViewHost has the right bindings. |
| 1043 if (speculative_web_ui() && |
| 1044 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { |
| 1045 render_frame_host_->render_view_host()->AllowBindings( |
| 1046 speculative_web_ui()->GetBindings()); |
| 1047 } |
| 1048 } |
1034 } else { | 1049 } else { |
1035 // If the current RenderFrameHost cannot be used a new speculative one is | 1050 // If the SiteInstance for the final URL doesn't match the one from the |
1036 // created with the SiteInstance for the current URL. | 1051 // speculatively created RenderFrameHost, create a new RenderFrameHost using |
1037 | 1052 // this new SiteInstance. |
1038 // Check if an existing speculative RenderFrameHost can be reused. | |
1039 if (!speculative_render_frame_host_ || | 1053 if (!speculative_render_frame_host_ || |
1040 speculative_render_frame_host_->GetSiteInstance() != | 1054 speculative_render_frame_host_->GetSiteInstance() != |
1041 dest_site_instance.get()) { | 1055 dest_site_instance.get()) { |
1042 // If a previous speculative RenderFrameHost didn't exist or if its | |
1043 // SiteInstace differs from the one for the current URL, a new one needs | |
1044 // to be created. | |
1045 CleanUpNavigation(); | 1056 CleanUpNavigation(); |
1046 bool success = CreateSpeculativeRenderFrameHost(current_site_instance, | 1057 bool success = CreateSpeculativeRenderFrameHost( |
1047 dest_site_instance.get()); | 1058 request.common_params().url, current_site_instance, |
| 1059 dest_site_instance.get(), request.bindings()); |
1048 DCHECK(success); | 1060 DCHECK(success); |
1049 } | 1061 } |
1050 | |
1051 bool changed_web_ui = speculative_render_frame_host_->UpdateWebUI( | |
1052 request.common_params().url, request.bindings()); | |
1053 if (changed_web_ui && speculative_render_frame_host_->web_ui()) { | |
1054 speculative_render_frame_host_->web_ui()->RenderViewCreated( | |
1055 speculative_render_frame_host_->render_view_host()); | |
1056 } | |
1057 DCHECK(speculative_render_frame_host_); | 1062 DCHECK(speculative_render_frame_host_); |
1058 DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui()); | |
1059 | |
1060 navigation_rfh = speculative_render_frame_host_.get(); | 1063 navigation_rfh = speculative_render_frame_host_.get(); |
1061 | 1064 |
1062 // Check if our current RFH is live. | 1065 // Check if our current RFH is live. |
1063 if (!render_frame_host_->IsRenderFrameLive()) { | 1066 if (!render_frame_host_->IsRenderFrameLive()) { |
1064 // The current RFH is not live. There's no reason to sit around with a | 1067 // The current RFH is not live. There's no reason to sit around with a |
1065 // sad tab or a newly created RFH while we wait for the navigation to | 1068 // sad tab or a newly created RFH while we wait for the navigation to |
1066 // complete. Just switch to the speculative RFH now and go back to normal. | 1069 // complete. Just switch to the speculative RFH now and go back to normal. |
1067 // (Note that we don't care about on{before}unload handlers if the current | 1070 // (Note that we don't care about on{before}unload handlers if the current |
1068 // RFH isn't live.) | 1071 // RFH isn't live.) |
1069 CommitPending(); | 1072 CommitPending(); |
1070 } | 1073 } |
1071 DCHECK(!current_web_ui_is_navigating_); | |
1072 } | 1074 } |
1073 DCHECK(navigation_rfh && | 1075 DCHECK(navigation_rfh && |
1074 (navigation_rfh == render_frame_host_.get() || | 1076 (navigation_rfh == render_frame_host_.get() || |
1075 navigation_rfh == speculative_render_frame_host_.get())); | 1077 navigation_rfh == speculative_render_frame_host_.get())); |
1076 | 1078 |
1077 // If the RenderFrame that needs to navigate is not live (its process was just | 1079 // If the RenderFrame that needs to navigate is not live (its process was just |
1078 // created or has crashed), initialize it. | 1080 // created or has crashed), initialize it. |
1079 if (!navigation_rfh->IsRenderFrameLive()) { | 1081 if (!navigation_rfh->IsRenderFrameLive()) { |
1080 // Recreate the opener chain. | 1082 // Recreate the opener chain. |
1081 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); | 1083 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); |
1082 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) | 1084 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) { |
1083 return nullptr; | 1085 return nullptr; |
1084 | |
1085 if (GetNavigatingWebUI()) { | |
1086 GetNavigatingWebUI()->RenderViewCreated( | |
1087 navigation_rfh->render_view_host()); | |
1088 } | 1086 } |
1089 | 1087 |
1090 if (navigation_rfh == render_frame_host_) { | 1088 if (navigation_rfh == render_frame_host_) { |
1091 // TODO(nasko): This is a very ugly hack. The Chrome extensions process | 1089 // TODO(nasko): This is a very ugly hack. The Chrome extensions process |
1092 // manager still uses NotificationService and expects to see a | 1090 // manager still uses NotificationService and expects to see a |
1093 // RenderViewHost changed notification after WebContents and | 1091 // RenderViewHost changed notification after WebContents and |
1094 // RenderFrameHostManager are completely initialized. This should be | 1092 // RenderFrameHostManager are completely initialized. This should be |
1095 // removed once the process manager moves away from NotificationService. | 1093 // removed once the process manager moves away from NotificationService. |
1096 // See https://crbug.com/462682. | 1094 // See https://crbug.com/462682. |
1097 delegate_->NotifyMainFrameSwappedFromRenderManager( | 1095 delegate_->NotifyMainFrameSwappedFromRenderManager( |
1098 nullptr, render_frame_host_->render_view_host()); | 1096 nullptr, render_frame_host_->render_view_host()); |
1099 } | 1097 } |
1100 } | 1098 } |
1101 | 1099 |
1102 return navigation_rfh; | 1100 return navigation_rfh; |
1103 } | 1101 } |
1104 | 1102 |
1105 // PlzNavigate | 1103 // PlzNavigate |
1106 void RenderFrameHostManager::CleanUpNavigation() { | 1104 void RenderFrameHostManager::CleanUpNavigation() { |
1107 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 1105 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
1108 switches::kEnableBrowserSideNavigation)); | 1106 switches::kEnableBrowserSideNavigation)); |
1109 // TODO(carlosk): the discarding of the current RFH WebUI and the cleanup of | 1107 speculative_web_ui_.reset(); |
1110 // the speculative RFH should not always happen together. | 1108 should_reuse_web_ui_ = false; |
1111 current_web_ui_is_navigating_ = false; | |
1112 if (speculative_render_frame_host_) | 1109 if (speculative_render_frame_host_) |
1113 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); | 1110 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); |
1114 } | 1111 } |
1115 | 1112 |
1116 // PlzNavigate | 1113 // PlzNavigate |
1117 scoped_ptr<RenderFrameHostImpl> | 1114 scoped_ptr<RenderFrameHostImpl> |
1118 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { | 1115 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { |
1119 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 1116 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
1120 switches::kEnableBrowserSideNavigation)); | 1117 switches::kEnableBrowserSideNavigation)); |
1121 speculative_render_frame_host_->GetProcess()->RemovePendingView(); | 1118 speculative_render_frame_host_->GetProcess()->RemovePendingView(); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 // We can't switch a RenderView between view source and non-view source mode | 1291 // We can't switch a RenderView between view source and non-view source mode |
1295 // without screwing up the session history sometimes (when navigating between | 1292 // without screwing up the session history sometimes (when navigating between |
1296 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat | 1293 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat |
1297 // it as a new navigation). So require a BrowsingInstance switch. | 1294 // it as a new navigation). So require a BrowsingInstance switch. |
1298 if (current_is_view_source_mode != new_is_view_source_mode) | 1295 if (current_is_view_source_mode != new_is_view_source_mode) |
1299 return true; | 1296 return true; |
1300 | 1297 |
1301 return false; | 1298 return false; |
1302 } | 1299 } |
1303 | 1300 |
| 1301 bool RenderFrameHostManager::ShouldReuseWebUI( |
| 1302 const NavigationEntry* current_entry, |
| 1303 const GURL& new_url) const { |
| 1304 NavigationControllerImpl& controller = |
| 1305 delegate_->GetControllerForRenderManager(); |
| 1306 return current_entry && web_ui_ && |
| 1307 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
| 1308 controller.GetBrowserContext(), current_entry->GetURL()) == |
| 1309 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
| 1310 controller.GetBrowserContext(), new_url)); |
| 1311 } |
| 1312 |
1304 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( | 1313 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( |
1305 const GURL& dest_url, | 1314 const GURL& dest_url, |
1306 SiteInstance* source_instance, | 1315 SiteInstance* source_instance, |
1307 SiteInstance* dest_instance, | 1316 SiteInstance* dest_instance, |
1308 SiteInstance* candidate_instance, | 1317 SiteInstance* candidate_instance, |
1309 ui::PageTransition transition, | 1318 ui::PageTransition transition, |
1310 bool dest_is_restore, | 1319 bool dest_is_restore, |
1311 bool dest_is_view_source_mode) { | 1320 bool dest_is_view_source_mode) { |
1312 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 1321 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
1313 | 1322 |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1626 // The process for the new SiteInstance may (if we're sharing a process with | 1635 // The process for the new SiteInstance may (if we're sharing a process with |
1627 // another host that already initialized it) or may not (we have our own | 1636 // another host that already initialized it) or may not (we have our own |
1628 // process or the existing process crashed) have been initialized. Calling | 1637 // process or the existing process crashed) have been initialized. Calling |
1629 // Init multiple times will be ignored, so this is safe. | 1638 // Init multiple times will be ignored, so this is safe. |
1630 if (!new_instance->GetProcess()->Init()) | 1639 if (!new_instance->GetProcess()->Init()) |
1631 return; | 1640 return; |
1632 | 1641 |
1633 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); | 1642 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); |
1634 | 1643 |
1635 // Create a non-swapped-out RFH with the given opener. | 1644 // Create a non-swapped-out RFH with the given opener. |
1636 pending_render_frame_host_ = | 1645 pending_render_frame_host_ = CreateRenderFrame( |
1637 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr); | 1646 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); |
1638 } | 1647 } |
1639 | 1648 |
1640 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( | 1649 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( |
1641 SiteInstance* old_instance, | 1650 SiteInstance* old_instance, |
1642 SiteInstance* new_instance) { | 1651 SiteInstance* new_instance) { |
1643 // Only create opener proxies if they are in the same BrowsingInstance. | 1652 // Only create opener proxies if they are in the same BrowsingInstance. |
1644 if (new_instance->IsRelatedSiteInstance(old_instance)) { | 1653 if (new_instance->IsRelatedSiteInstance(old_instance)) { |
1645 CreateOpenerProxies(new_instance, frame_tree_node_); | 1654 CreateOpenerProxies(new_instance, frame_tree_node_); |
1646 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { | 1655 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { |
1647 // Ensure that the frame tree has RenderFrameProxyHosts for the | 1656 // Ensure that the frame tree has RenderFrameProxyHosts for the |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1723 } | 1732 } |
1724 | 1733 |
1725 return RenderFrameHostFactory::Create( | 1734 return RenderFrameHostFactory::Create( |
1726 site_instance, render_view_host, render_frame_delegate_, | 1735 site_instance, render_view_host, render_frame_delegate_, |
1727 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, | 1736 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, |
1728 widget_routing_id, flags); | 1737 widget_routing_id, flags); |
1729 } | 1738 } |
1730 | 1739 |
1731 // PlzNavigate | 1740 // PlzNavigate |
1732 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( | 1741 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( |
| 1742 const GURL& url, |
1733 SiteInstance* old_instance, | 1743 SiteInstance* old_instance, |
1734 SiteInstance* new_instance) { | 1744 SiteInstance* new_instance, |
| 1745 int bindings) { |
1735 CHECK(new_instance); | 1746 CHECK(new_instance); |
1736 CHECK_NE(old_instance, new_instance); | 1747 CHECK_NE(old_instance, new_instance); |
1737 CHECK(!current_web_ui_is_navigating_); | 1748 CHECK(!should_reuse_web_ui_); |
| 1749 |
| 1750 // Note: |speculative_web_ui_| must be initialized before starting the |
| 1751 // |speculative_render_frame_host_| creation steps otherwise the WebUI |
| 1752 // won't be properly initialized. |
| 1753 speculative_web_ui_ = CreateWebUI(url, bindings); |
1738 | 1754 |
1739 // The process for the new SiteInstance may (if we're sharing a process with | 1755 // The process for the new SiteInstance may (if we're sharing a process with |
1740 // another host that already initialized it) or may not (we have our own | 1756 // another host that already initialized it) or may not (we have our own |
1741 // process or the existing process crashed) have been initialized. Calling | 1757 // process or the existing process crashed) have been initialized. Calling |
1742 // Init multiple times will be ignored, so this is safe. | 1758 // Init multiple times will be ignored, so this is safe. |
1743 if (!new_instance->GetProcess()->Init()) | 1759 if (!new_instance->GetProcess()->Init()) |
1744 return false; | 1760 return false; |
1745 | 1761 |
1746 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); | 1762 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); |
1747 | 1763 |
1748 int create_render_frame_flags = 0; | 1764 int create_render_frame_flags = 0; |
1749 if (delegate_->IsHidden()) | 1765 if (delegate_->IsHidden()) |
1750 create_render_frame_flags |= CREATE_RF_HIDDEN; | 1766 create_render_frame_flags |= CREATE_RF_HIDDEN; |
1751 speculative_render_frame_host_ = | 1767 speculative_render_frame_host_ = |
1752 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr); | 1768 CreateRenderFrame(new_instance, speculative_web_ui_.get(), |
| 1769 create_render_frame_flags, nullptr); |
1753 | 1770 |
1754 return !!speculative_render_frame_host_; | 1771 if (!speculative_render_frame_host_) { |
| 1772 speculative_web_ui_.reset(); |
| 1773 return false; |
| 1774 } |
| 1775 return true; |
1755 } | 1776 } |
1756 | 1777 |
1757 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( | 1778 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( |
1758 SiteInstance* instance, | 1779 SiteInstance* instance, |
| 1780 WebUIImpl* web_ui, |
1759 int flags, | 1781 int flags, |
1760 int* view_routing_id_ptr) { | 1782 int* view_routing_id_ptr) { |
1761 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); | 1783 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); |
1762 bool swapped_out_forbidden = | 1784 bool swapped_out_forbidden = |
1763 SiteIsolationPolicy::IsSwappedOutStateForbidden(); | 1785 SiteIsolationPolicy::IsSwappedOutStateForbidden(); |
1764 | 1786 |
1765 CHECK(instance); | 1787 CHECK(instance); |
1766 CHECK(!swapped_out_forbidden || !swapped_out); | 1788 CHECK(!swapped_out_forbidden || !swapped_out); |
1767 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || | 1789 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || |
1768 frame_tree_node_->IsMainFrame()); | 1790 frame_tree_node_->IsMainFrame()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1866 success = InitRenderFrame(new_render_frame_host.get()); | 1888 success = InitRenderFrame(new_render_frame_host.get()); |
1867 } | 1889 } |
1868 } | 1890 } |
1869 | 1891 |
1870 if (success) { | 1892 if (success) { |
1871 if (view_routing_id_ptr) | 1893 if (view_routing_id_ptr) |
1872 *view_routing_id_ptr = render_view_host->GetRoutingID(); | 1894 *view_routing_id_ptr = render_view_host->GetRoutingID(); |
1873 } | 1895 } |
1874 } | 1896 } |
1875 | 1897 |
| 1898 // When a new RenderView is created by the renderer process, the new |
| 1899 // WebContents gets a RenderViewHost in the SiteInstance of its opener |
| 1900 // WebContents. If not used in the first navigation, this RVH is swapped out |
| 1901 // and is not granted bindings, so we may need to grant them when swapping it |
| 1902 // in. |
| 1903 if (web_ui && !new_render_frame_host->GetProcess()->IsForGuestsOnly()) { |
| 1904 int required_bindings = web_ui->GetBindings(); |
| 1905 RenderViewHost* render_view_host = |
| 1906 new_render_frame_host->render_view_host(); |
| 1907 if ((render_view_host->GetEnabledBindings() & required_bindings) != |
| 1908 required_bindings) { |
| 1909 render_view_host->AllowBindings(required_bindings); |
| 1910 } |
| 1911 } |
| 1912 |
1876 // Returns the new RFH if it isn't swapped out. | 1913 // Returns the new RFH if it isn't swapped out. |
1877 if (success && !swapped_out) { | 1914 if (success && !swapped_out) { |
1878 DCHECK(new_render_frame_host->GetSiteInstance() == instance); | 1915 DCHECK(new_render_frame_host->GetSiteInstance() == instance); |
1879 return new_render_frame_host.Pass(); | 1916 return new_render_frame_host.Pass(); |
1880 } | 1917 } |
1881 return nullptr; | 1918 return nullptr; |
1882 } | 1919 } |
1883 | 1920 |
1884 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { | 1921 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { |
1885 // A RenderFrameProxyHost should never be created in the same SiteInstance as | 1922 // A RenderFrameProxyHost should never be created in the same SiteInstance as |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 RenderFrameProxyHost* proxy) { | 2021 RenderFrameProxyHost* proxy) { |
1985 // Ensure the renderer process is initialized before creating the | 2022 // Ensure the renderer process is initialized before creating the |
1986 // RenderView. | 2023 // RenderView. |
1987 if (!render_view_host->GetProcess()->Init()) | 2024 if (!render_view_host->GetProcess()->Init()) |
1988 return false; | 2025 return false; |
1989 | 2026 |
1990 // We may have initialized this RenderViewHost for another RenderFrameHost. | 2027 // We may have initialized this RenderViewHost for another RenderFrameHost. |
1991 if (render_view_host->IsRenderViewLive()) | 2028 if (render_view_host->IsRenderViewLive()) |
1992 return true; | 2029 return true; |
1993 | 2030 |
| 2031 // If |render_view_host| is not for a proxy and the navigation is to a WebUI, |
| 2032 // and if the RenderView is not in a guest process, tell |render_view_host| |
| 2033 // about any bindings it will need enabled. |
| 2034 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850. |
| 2035 WebUIImpl* dest_web_ui = nullptr; |
| 2036 if (!proxy) { |
| 2037 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2038 switches::kEnableBrowserSideNavigation)) { |
| 2039 dest_web_ui = |
| 2040 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get(); |
| 2041 } else { |
| 2042 dest_web_ui = pending_web_ui(); |
| 2043 } |
| 2044 } |
| 2045 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) { |
| 2046 render_view_host->AllowBindings(dest_web_ui->GetBindings()); |
| 2047 } else { |
| 2048 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled |
| 2049 // process unless it's swapped out. |
| 2050 if (render_view_host->is_active()) { |
| 2051 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| 2052 render_view_host->GetProcess()->GetID())); |
| 2053 } |
| 2054 } |
| 2055 |
1994 int opener_frame_routing_id = | 2056 int opener_frame_routing_id = |
1995 GetOpenerRoutingID(render_view_host->GetSiteInstance()); | 2057 GetOpenerRoutingID(render_view_host->GetSiteInstance()); |
1996 | 2058 |
1997 bool created = delegate_->CreateRenderViewForRenderManager( | 2059 bool created = delegate_->CreateRenderViewForRenderManager( |
1998 render_view_host, opener_frame_routing_id, | 2060 render_view_host, opener_frame_routing_id, |
1999 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, | 2061 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, |
2000 frame_tree_node_->current_replication_state()); | 2062 frame_tree_node_->current_replication_state()); |
2001 | 2063 |
2002 if (created && proxy) | 2064 if (created && proxy) |
2003 proxy->set_render_frame_proxy_created(true); | 2065 proxy->set_render_frame_proxy_created(true); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2075 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); | 2137 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); |
2076 if (proxy) | 2138 if (proxy) |
2077 return proxy->GetRoutingID(); | 2139 return proxy->GetRoutingID(); |
2078 | 2140 |
2079 return MSG_ROUTING_NONE; | 2141 return MSG_ROUTING_NONE; |
2080 } | 2142 } |
2081 | 2143 |
2082 void RenderFrameHostManager::CommitPending() { | 2144 void RenderFrameHostManager::CommitPending() { |
2083 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", | 2145 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", |
2084 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 2146 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
| 2147 bool browser_side_navigation = |
| 2148 base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2149 switches::kEnableBrowserSideNavigation); |
| 2150 |
2085 // First check whether we're going to want to focus the location bar after | 2151 // First check whether we're going to want to focus the location bar after |
2086 // this commit. We do this now because the navigation hasn't formally | 2152 // this commit. We do this now because the navigation hasn't formally |
2087 // committed yet, so if we've already cleared the pending WebUI the call chain | 2153 // committed yet, so if we've already cleared |pending_web_ui_| the call chain |
2088 // this triggers won't be able to figure out what's going on. | 2154 // this triggers won't be able to figure out what's going on. |
2089 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 2155 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
2090 | 2156 |
| 2157 // Next commit the Web UI, if any. Either replace |web_ui_| with |
| 2158 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or |
| 2159 // leave |web_ui_| as is if reusing it. |
| 2160 DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_)); |
| 2161 if (pending_web_ui_ || speculative_web_ui_) { |
| 2162 DCHECK(!should_reuse_web_ui_); |
| 2163 web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release() |
| 2164 : pending_web_ui_.release()); |
| 2165 } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) { |
| 2166 if (browser_side_navigation) { |
| 2167 DCHECK(web_ui_); |
| 2168 should_reuse_web_ui_ = false; |
| 2169 } else { |
| 2170 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); |
| 2171 pending_and_current_web_ui_.reset(); |
| 2172 } |
| 2173 } else { |
| 2174 web_ui_.reset(); |
| 2175 } |
| 2176 DCHECK(!speculative_web_ui_); |
| 2177 DCHECK(!should_reuse_web_ui_); |
| 2178 |
| 2179 // It's possible for the pending_render_frame_host_ to be nullptr when we |
| 2180 // aren't crossing process boundaries. If so, we just needed to handle the Web |
| 2181 // UI committing above and we're done. |
2091 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { | 2182 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { |
2092 DCHECK_EQ(current_web_ui_is_navigating_, !!render_frame_host_->web_ui()); | |
2093 current_web_ui_is_navigating_ = false; | |
2094 // If there's no pending/speculative RenderFrameHost then the current | |
2095 // RenderFrameHost is committing. | |
2096 if (will_focus_location_bar) | 2183 if (will_focus_location_bar) |
2097 delegate_->SetFocusToLocationBar(false); | 2184 delegate_->SetFocusToLocationBar(false); |
2098 return; | 2185 return; |
2099 } | 2186 } |
2100 | 2187 |
2101 // Remember if the page was focused so we can focus the new renderer in | 2188 // Remember if the page was focused so we can focus the new renderer in |
2102 // that case. | 2189 // that case. |
2103 bool focus_render_view = !will_focus_location_bar && | 2190 bool focus_render_view = !will_focus_location_bar && |
2104 render_frame_host_->GetView() && | 2191 render_frame_host_->GetView() && |
2105 render_frame_host_->GetView()->HasFocus(); | 2192 render_frame_host_->GetView()->HasFocus(); |
2106 | 2193 |
2107 bool is_main_frame = frame_tree_node_->IsMainFrame(); | 2194 bool is_main_frame = frame_tree_node_->IsMainFrame(); |
2108 | 2195 |
2109 // Swap in the pending or speculative frame and make it active. Also ensure | 2196 // Swap in the pending or speculative frame and make it active. Also ensure |
2110 // the FrameTree stays in sync. | 2197 // the FrameTree stays in sync. |
2111 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; | 2198 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; |
2112 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 2199 if (!browser_side_navigation) { |
2113 switches::kEnableBrowserSideNavigation)) { | |
2114 DCHECK(!speculative_render_frame_host_); | 2200 DCHECK(!speculative_render_frame_host_); |
2115 old_render_frame_host = | 2201 old_render_frame_host = |
2116 SetRenderFrameHost(pending_render_frame_host_.Pass()); | 2202 SetRenderFrameHost(pending_render_frame_host_.Pass()); |
2117 } else { | 2203 } else { |
2118 // PlzNavigate | 2204 // PlzNavigate |
2119 DCHECK(speculative_render_frame_host_); | 2205 DCHECK(speculative_render_frame_host_); |
2120 old_render_frame_host = | 2206 old_render_frame_host = |
2121 SetRenderFrameHost(speculative_render_frame_host_.Pass()); | 2207 SetRenderFrameHost(speculative_render_frame_host_.Pass()); |
2122 } | 2208 } |
2123 | 2209 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2273 // If we are currently navigating cross-process, we want to get back to normal | 2359 // If we are currently navigating cross-process, we want to get back to normal |
2274 // and then navigate as usual. | 2360 // and then navigate as usual. |
2275 if (pending_render_frame_host_) | 2361 if (pending_render_frame_host_) |
2276 CancelPending(); | 2362 CancelPending(); |
2277 | 2363 |
2278 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 2364 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
2279 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( | 2365 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( |
2280 dest_url, source_instance, dest_instance, nullptr, transition, | 2366 dest_url, source_instance, dest_instance, nullptr, transition, |
2281 dest_is_restore, dest_is_view_source_mode); | 2367 dest_is_restore, dest_is_view_source_mode); |
2282 | 2368 |
| 2369 const NavigationEntry* current_entry = |
| 2370 delegate_->GetLastCommittedNavigationEntryForRenderManager(); |
| 2371 |
2283 DCHECK(!pending_render_frame_host_); | 2372 DCHECK(!pending_render_frame_host_); |
2284 | 2373 |
2285 if (new_instance.get() != current_instance) { | 2374 if (new_instance.get() != current_instance) { |
2286 TRACE_EVENT_INSTANT2( | 2375 TRACE_EVENT_INSTANT2( |
2287 "navigation", | 2376 "navigation", |
2288 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", | 2377 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", |
2289 TRACE_EVENT_SCOPE_THREAD, | 2378 TRACE_EVENT_SCOPE_THREAD, |
2290 "current_instance id", current_instance->GetId(), | 2379 "current_instance id", current_instance->GetId(), |
2291 "new_instance id", new_instance->GetId()); | 2380 "new_instance id", new_instance->GetId()); |
2292 | 2381 |
2293 // New SiteInstance: create a pending RFH to navigate. | 2382 // New SiteInstance: create a pending RFH to navigate. |
2294 | 2383 |
2295 current_web_ui_is_navigating_ = false; | 2384 // This will possibly create (set to nullptr) a Web UI object for the |
| 2385 // pending page. We'll use this later to give the page special access. This |
| 2386 // must happen before the new renderer is created below so it will get |
| 2387 // bindings. It must also happen after the above conditional call to |
| 2388 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_ |
| 2389 // and the page will not have its bindings set appropriately. |
| 2390 SetPendingWebUI(dest_url, bindings); |
2296 CreatePendingRenderFrameHost(current_instance, new_instance.get()); | 2391 CreatePendingRenderFrameHost(current_instance, new_instance.get()); |
2297 DCHECK(pending_render_frame_host_); | |
2298 if (!pending_render_frame_host_) | 2392 if (!pending_render_frame_host_) |
2299 return nullptr; | 2393 return nullptr; |
2300 | 2394 |
2301 pending_render_frame_host_->UpdateWebUI(dest_url, bindings); | |
2302 if (pending_render_frame_host_->web_ui()) { | |
2303 pending_render_frame_host_->web_ui()->RenderViewCreated( | |
2304 pending_render_frame_host_->render_view_host()); | |
2305 } | |
2306 | |
2307 // We now have a pending RFH and possibly an associated pending WebUI. | |
2308 DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui()); | |
2309 | |
2310 // Check if our current RFH is live before we set up a transition. | 2395 // Check if our current RFH is live before we set up a transition. |
2311 if (!render_frame_host_->IsRenderFrameLive()) { | 2396 if (!render_frame_host_->IsRenderFrameLive()) { |
2312 // The current RFH is not live. There's no reason to sit around with a | 2397 // The current RFH is not live. There's no reason to sit around with a |
2313 // sad tab or a newly created RFH while we wait for the pending RFH to | 2398 // sad tab or a newly created RFH while we wait for the pending RFH to |
2314 // navigate. Just switch to the pending RFH now and go back to normal. | 2399 // navigate. Just switch to the pending RFH now and go back to normal. |
2315 // (Note that we don't care about on{before}unload handlers if the current | 2400 // (Note that we don't care about on{before}unload handlers if the current |
2316 // RFH isn't live.) | 2401 // RFH isn't live.) |
2317 CommitPending(); | 2402 CommitPending(); |
2318 return render_frame_host_.get(); | 2403 return render_frame_host_.get(); |
2319 } | 2404 } |
2320 // Otherwise, it's safe to treat this as a pending cross-process transition. | 2405 // Otherwise, it's safe to treat this as a pending cross-process transition. |
2321 | 2406 |
| 2407 // We now have a pending RFH. |
| 2408 DCHECK(pending_render_frame_host_); |
| 2409 |
2322 // We need to wait until the beforeunload handler has run, unless we are | 2410 // We need to wait until the beforeunload handler has run, unless we are |
2323 // transferring an existing request (in which case it has already run). | 2411 // transferring an existing request (in which case it has already run). |
2324 // Suspend the new render view (i.e., don't let it send the cross-process | 2412 // Suspend the new render view (i.e., don't let it send the cross-process |
2325 // Navigate message) until we hear back from the old renderer's | 2413 // Navigate message) until we hear back from the old renderer's |
2326 // beforeunload handler. If the handler returns false, we'll have to | 2414 // beforeunload handler. If the handler returns false, we'll have to |
2327 // cancel the request. | 2415 // cancel the request. |
| 2416 // |
2328 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); | 2417 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); |
2329 bool is_transfer = transferred_request_id != GlobalRequestID(); | 2418 bool is_transfer = transferred_request_id != GlobalRequestID(); |
2330 if (is_transfer) { | 2419 if (is_transfer) { |
2331 // We don't need to stop the old renderer or run beforeunload/unload | 2420 // We don't need to stop the old renderer or run beforeunload/unload |
2332 // handlers, because those have already been done. | 2421 // handlers, because those have already been done. |
2333 DCHECK(cross_site_transferring_request_->request_id() == | 2422 DCHECK(cross_site_transferring_request_->request_id() == |
2334 transferred_request_id); | 2423 transferred_request_id); |
2335 } else { | 2424 } else { |
2336 // Also make sure the old render view stops, in case a load is in | 2425 // Also make sure the old render view stops, in case a load is in |
2337 // progress. (We don't want to do this for transfers, since it will | 2426 // progress. (We don't want to do this for transfers, since it will |
(...skipping 14 matching lines...) Expand all Loading... |
2352 | 2441 |
2353 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. | 2442 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. |
2354 | 2443 |
2355 // It's possible to swap out the current RFH and then decide to navigate in it | 2444 // It's possible to swap out the current RFH and then decide to navigate in it |
2356 // anyway (e.g., a cross-process navigation that redirects back to the | 2445 // anyway (e.g., a cross-process navigation that redirects back to the |
2357 // original site). In that case, we have a proxy for the current RFH but | 2446 // original site). In that case, we have a proxy for the current RFH but |
2358 // haven't deleted it yet. The new navigation will swap it back in, so we can | 2447 // haven't deleted it yet. The new navigation will swap it back in, so we can |
2359 // delete the proxy. | 2448 // delete the proxy. |
2360 proxy_hosts_->Remove(new_instance.get()->GetId()); | 2449 proxy_hosts_->Remove(new_instance.get()->GetId()); |
2361 | 2450 |
2362 UpdateWebUIOnCurrentFrameHost(dest_url, dest_is_restore, bindings); | 2451 if (ShouldReuseWebUI(current_entry, dest_url)) { |
| 2452 pending_web_ui_.reset(); |
| 2453 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); |
| 2454 } else { |
| 2455 SetPendingWebUI(dest_url, bindings); |
| 2456 // Make sure the new RenderViewHost has the right bindings. |
| 2457 if (pending_web_ui() && |
| 2458 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { |
| 2459 render_frame_host_->render_view_host()->AllowBindings( |
| 2460 pending_web_ui()->GetBindings()); |
| 2461 } |
| 2462 } |
| 2463 |
| 2464 if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) { |
| 2465 pending_web_ui()->RenderViewReused(render_frame_host_->render_view_host(), |
| 2466 frame_tree_node_->IsMainFrame()); |
| 2467 } |
2363 | 2468 |
2364 // The renderer can exit view source mode when any error or cancellation | 2469 // The renderer can exit view source mode when any error or cancellation |
2365 // happen. We must overwrite to recover the mode. | 2470 // happen. We must overwrite to recover the mode. |
2366 if (dest_is_view_source_mode) { | 2471 if (dest_is_view_source_mode) { |
2367 render_frame_host_->render_view_host()->Send( | 2472 render_frame_host_->render_view_host()->Send( |
2368 new ViewMsg_EnableViewSourceMode( | 2473 new ViewMsg_EnableViewSourceMode( |
2369 render_frame_host_->render_view_host()->GetRoutingID())); | 2474 render_frame_host_->render_view_host()->GetRoutingID())); |
2370 } | 2475 } |
2371 | 2476 |
2372 return render_frame_host_.get(); | 2477 return render_frame_host_.get(); |
2373 } | 2478 } |
2374 | 2479 |
2375 void RenderFrameHostManager::UpdateWebUIOnCurrentFrameHost(const GURL& dest_url, | |
2376 bool dest_is_restore, | |
2377 int bindings) { | |
2378 WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type(); | |
2379 bool changed_web_ui = render_frame_host_->UpdateWebUI(dest_url, bindings); | |
2380 | |
2381 // If a change in WebUI happened, check this is an acceptable case. | |
2382 if (changed_web_ui) | |
2383 CheckWebUITransition(previous_web_ui_type, dest_url, dest_is_restore); | |
2384 | |
2385 // If there is a WebUI in the current RenderFrameHost, it will navigate. | |
2386 current_web_ui_is_navigating_ = !!render_frame_host_->web_ui(); | |
2387 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui()); | |
2388 | |
2389 // If the current RenderFrameHost has a WebUI and the associated RenderFrame | |
2390 // is alive, notify to the WebUI that the RenderView is being created or | |
2391 // reused depending on whether the WebUI was changed or not. | |
2392 if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) { | |
2393 if (changed_web_ui) { | |
2394 GetNavigatingWebUI()->RenderViewCreated( | |
2395 render_frame_host_->render_view_host()); | |
2396 } else { | |
2397 GetNavigatingWebUI()->RenderViewReused( | |
2398 render_frame_host_->render_view_host(), | |
2399 frame_tree_node_->IsMainFrame()); | |
2400 } | |
2401 } | |
2402 } | |
2403 | |
2404 void RenderFrameHostManager::CancelPending() { | 2480 void RenderFrameHostManager::CancelPending() { |
2405 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", | 2481 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", |
2406 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 2482 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
2407 current_web_ui_is_navigating_ = false; | |
2408 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); | 2483 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); |
2409 } | 2484 } |
2410 | 2485 |
2411 scoped_ptr<RenderFrameHostImpl> | 2486 scoped_ptr<RenderFrameHostImpl> |
2412 RenderFrameHostManager::UnsetPendingRenderFrameHost() { | 2487 RenderFrameHostManager::UnsetPendingRenderFrameHost() { |
2413 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = | 2488 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = |
2414 pending_render_frame_host_.Pass(); | 2489 pending_render_frame_host_.Pass(); |
2415 | 2490 |
2416 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( | 2491 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( |
2417 pending_render_frame_host.get(), | 2492 pending_render_frame_host.get(), |
2418 render_frame_host_.get()); | 2493 render_frame_host_.get()); |
2419 | 2494 |
2420 current_web_ui_is_navigating_ = false; | |
2421 | |
2422 // We no longer need to prevent the process from exiting. | 2495 // We no longer need to prevent the process from exiting. |
2423 pending_render_frame_host->GetProcess()->RemovePendingView(); | 2496 pending_render_frame_host->GetProcess()->RemovePendingView(); |
2424 | 2497 |
| 2498 pending_web_ui_.reset(); |
| 2499 pending_and_current_web_ui_.reset(); |
| 2500 |
2425 return pending_render_frame_host.Pass(); | 2501 return pending_render_frame_host.Pass(); |
2426 } | 2502 } |
2427 | 2503 |
2428 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( | 2504 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( |
2429 scoped_ptr<RenderFrameHostImpl> render_frame_host) { | 2505 scoped_ptr<RenderFrameHostImpl> render_frame_host) { |
2430 // Swap the two. | 2506 // Swap the two. |
2431 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = | 2507 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = |
2432 render_frame_host_.Pass(); | 2508 render_frame_host_.Pass(); |
2433 render_frame_host_ = render_frame_host.Pass(); | 2509 render_frame_host_ = render_frame_host.Pass(); |
2434 | 2510 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 if (rvh && !rvh->IsRenderViewLive()) { | 2665 if (rvh && !rvh->IsRenderViewLive()) { |
2590 EnsureRenderViewInitialized(rvh, instance); | 2666 EnsureRenderViewInitialized(rvh, instance); |
2591 } else { | 2667 } else { |
2592 // Create a swapped out RenderView in the given SiteInstance if none | 2668 // Create a swapped out RenderView in the given SiteInstance if none |
2593 // exists. Since an opener can point to a subframe, do this on the root | 2669 // exists. Since an opener can point to a subframe, do this on the root |
2594 // frame of the current opener's frame tree. | 2670 // frame of the current opener's frame tree. |
2595 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { | 2671 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { |
2596 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); | 2672 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); |
2597 } else { | 2673 } else { |
2598 frame_tree->root()->render_manager()->CreateRenderFrame( | 2674 frame_tree->root()->render_manager()->CreateRenderFrame( |
2599 instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr); | 2675 instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, |
| 2676 nullptr); |
2600 } | 2677 } |
2601 } | 2678 } |
2602 } | 2679 } |
2603 } | 2680 } |
2604 | 2681 |
2605 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { | 2682 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { |
2606 if (!frame_tree_node_->opener()) | 2683 if (!frame_tree_node_->opener()) |
2607 return MSG_ROUTING_NONE; | 2684 return MSG_ROUTING_NONE; |
2608 | 2685 |
2609 return frame_tree_node_->opener() | 2686 return frame_tree_node_->opener() |
2610 ->render_manager() | 2687 ->render_manager() |
2611 ->GetRoutingIdForSiteInstance(instance); | 2688 ->GetRoutingIdForSiteInstance(instance); |
2612 } | 2689 } |
2613 | 2690 |
2614 void RenderFrameHostManager::CheckWebUITransition( | |
2615 WebUI::TypeID previous_web_ui_type, | |
2616 const GURL& dest_url, | |
2617 bool dest_is_restore) { | |
2618 // There are a few navigation cases that allow for changes to the WebUI of | |
2619 // the current RenderFrameHost. | |
2620 BrowserContext* browser_context = | |
2621 delegate_->GetControllerForRenderManager().GetBrowserContext(); | |
2622 if (render_frame_host_->web_ui()) { | |
2623 // Switching WebUI from one type to another while keeping the | |
2624 // RenderFrameHost is never acceptable. | |
2625 CHECK(previous_web_ui_type == WebUI::kNoWebUI); | |
2626 | |
2627 // Going from not having to having a WebUI is acceptable for: | |
2628 // - The first navigation of this frame. | |
2629 const NavigationEntry* current_entry = | |
2630 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | |
2631 bool is_first_navigation_for_frame = !current_entry; | |
2632 | |
2633 // - A restore navigation to a WebUI URL. | |
2634 const GURL& current_effective_url = | |
2635 current_entry ? SiteInstanceImpl::GetEffectiveURL( | |
2636 browser_context, current_entry->GetURL()) | |
2637 : render_frame_host_->GetSiteInstance()->GetSiteURL(); | |
2638 bool is_webui_restore = | |
2639 dest_is_restore && | |
2640 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( | |
2641 browser_context, current_effective_url); | |
2642 | |
2643 // - Navigating back from a special renderer URL. | |
2644 bool is_back_from_renderer_url = | |
2645 current_entry && IsRendererDebugURL(current_entry->GetURL()); | |
2646 | |
2647 // - Navigating in webview tag guest. | |
2648 bool is_webview_tag_guest = | |
2649 render_frame_host_->GetSiteInstance()->GetSiteURL().SchemeIs( | |
2650 kGuestScheme); | |
2651 CHECK(is_first_navigation_for_frame || is_webui_restore || | |
2652 is_back_from_renderer_url || is_webview_tag_guest); | |
2653 } else { | |
2654 // Going from having to not having a WebUI is acceptable when Navigating to | |
2655 // a special renderer URL. | |
2656 CHECK(IsRendererDebugURL( | |
2657 SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url))); | |
2658 } | |
2659 } | |
2660 | |
2661 } // namespace content | 2691 } // namespace content |
OLD | NEW |