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" | |
34 #include "content/common/frame_messages.h" | 33 #include "content/common/frame_messages.h" |
35 #include "content/common/site_isolation_policy.h" | 34 #include "content/common/site_isolation_policy.h" |
36 #include "content/common/view_messages.h" | 35 #include "content/common/view_messages.h" |
37 #include "content/public/browser/content_browser_client.h" | 36 #include "content/public/browser/content_browser_client.h" |
38 #include "content/public/browser/render_process_host_observer.h" | 37 #include "content/public/browser/render_process_host_observer.h" |
39 #include "content/public/browser/render_widget_host_iterator.h" | 38 #include "content/public/browser/render_widget_host_iterator.h" |
40 #include "content/public/browser/render_widget_host_view.h" | 39 #include "content/public/browser/render_widget_host_view.h" |
41 #include "content/public/browser/user_metrics.h" | 40 #include "content/public/browser/user_metrics.h" |
42 #include "content/public/browser/web_ui_controller.h" | |
43 #include "content/public/common/browser_plugin_guest_mode.h" | 41 #include "content/public/common/browser_plugin_guest_mode.h" |
44 #include "content/public/common/content_switches.h" | 42 #include "content/public/common/content_switches.h" |
45 #include "content/public/common/referrer.h" | 43 #include "content/public/common/referrer.h" |
46 #include "content/public/common/url_constants.h" | 44 #include "content/public/common/url_constants.h" |
47 | 45 |
48 namespace content { | 46 namespace content { |
49 | 47 |
50 namespace { | 48 namespace { |
51 | 49 |
52 // Helper function to add the FrameTree of the given node's opener to the list | 50 // Helper function to add the FrameTree of the given node's opener to the list |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 int exit_code) { | 198 int exit_code) { |
201 manager_->RendererProcessClosing(host); | 199 manager_->RendererProcessClosing(host); |
202 } | 200 } |
203 | 201 |
204 // static | 202 // static |
205 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { | 203 bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) { |
206 node->render_manager()->pending_delete_hosts_.clear(); | 204 node->render_manager()->pending_delete_hosts_.clear(); |
207 return true; | 205 return true; |
208 } | 206 } |
209 | 207 |
| 208 // static |
| 209 bool RenderFrameHostManager::ClearWebUIInstances(FrameTreeNode* node) { |
| 210 node->current_frame_host()->ClearAllWebUI(); |
| 211 if (node->render_manager()->pending_render_frame_host_) |
| 212 node->render_manager()->pending_render_frame_host_->ClearAllWebUI(); |
| 213 // PlzNavigate |
| 214 if (node->render_manager()->speculative_render_frame_host_) |
| 215 node->render_manager()->speculative_render_frame_host_->ClearAllWebUI(); |
| 216 return true; |
| 217 } |
| 218 |
210 RenderFrameHostManager::RenderFrameHostManager( | 219 RenderFrameHostManager::RenderFrameHostManager( |
211 FrameTreeNode* frame_tree_node, | 220 FrameTreeNode* frame_tree_node, |
212 RenderFrameHostDelegate* render_frame_delegate, | 221 RenderFrameHostDelegate* render_frame_delegate, |
213 RenderViewHostDelegate* render_view_delegate, | 222 RenderViewHostDelegate* render_view_delegate, |
214 RenderWidgetHostDelegate* render_widget_delegate, | 223 RenderWidgetHostDelegate* render_widget_delegate, |
215 Delegate* delegate) | 224 Delegate* delegate) |
216 : frame_tree_node_(frame_tree_node), | 225 : frame_tree_node_(frame_tree_node), |
217 delegate_(delegate), | 226 delegate_(delegate), |
218 render_frame_delegate_(render_frame_delegate), | 227 render_frame_delegate_(render_frame_delegate), |
219 render_view_delegate_(render_view_delegate), | 228 render_view_delegate_(render_view_delegate), |
220 render_widget_delegate_(render_widget_delegate), | 229 render_widget_delegate_(render_widget_delegate), |
221 proxy_hosts_(new RenderFrameProxyHostMap(this)), | 230 proxy_hosts_(new RenderFrameProxyHostMap(this)), |
222 interstitial_page_(nullptr), | 231 interstitial_page_(nullptr), |
223 should_reuse_web_ui_(false), | |
224 weak_factory_(this) { | 232 weak_factory_(this) { |
225 DCHECK(frame_tree_node_); | 233 DCHECK(frame_tree_node_); |
226 } | 234 } |
227 | 235 |
228 RenderFrameHostManager::~RenderFrameHostManager() { | 236 RenderFrameHostManager::~RenderFrameHostManager() { |
229 if (pending_render_frame_host_) { | 237 if (pending_render_frame_host_) { |
230 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost(); | 238 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost(); |
231 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); | 239 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); |
232 } | 240 } |
233 | 241 |
234 if (speculative_render_frame_host_) { | 242 if (speculative_render_frame_host_) { |
235 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost(); | 243 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost(); |
236 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); | 244 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); |
237 } | 245 } |
238 | 246 |
239 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get()); | 247 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get()); |
240 | 248 |
241 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts. | 249 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts. |
242 // It is important to delete those prior to deleting the current | 250 // It is important to delete those prior to deleting the current |
243 // RenderFrameHost, since the CrossProcessFrameConnector (owned by | 251 // RenderFrameHost, since the CrossProcessFrameConnector (owned by |
244 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with | 252 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with |
245 // the current RenderFrameHost and uses it during its destructor. | 253 // the current RenderFrameHost and uses it during its destructor. |
246 ResetProxyHosts(); | 254 ResetProxyHosts(); |
247 | 255 |
248 // Release the WebUI prior to resetting the current RenderFrameHost, as the | |
249 // WebUI accesses the RenderFrameHost during cleanup. | |
250 web_ui_.reset(); | |
251 | |
252 // We should always have a current RenderFrameHost except in some tests. | 256 // We should always have a current RenderFrameHost except in some tests. |
253 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); | 257 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); |
254 } | 258 } |
255 | 259 |
256 void RenderFrameHostManager::Init(SiteInstance* site_instance, | 260 void RenderFrameHostManager::Init(SiteInstance* site_instance, |
257 int32 view_routing_id, | 261 int32 view_routing_id, |
258 int32 frame_routing_id, | 262 int32 frame_routing_id, |
259 int32 widget_routing_id) { | 263 int32 widget_routing_id) { |
260 DCHECK(site_instance); | 264 DCHECK(site_instance); |
261 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must | 265 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must |
(...skipping 20 matching lines...) Expand all Loading... |
282 return nullptr; | 286 return nullptr; |
283 return render_frame_host_->render_view_host(); | 287 return render_frame_host_->render_view_host(); |
284 } | 288 } |
285 | 289 |
286 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { | 290 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { |
287 if (!pending_render_frame_host_) | 291 if (!pending_render_frame_host_) |
288 return nullptr; | 292 return nullptr; |
289 return pending_render_frame_host_->render_view_host(); | 293 return pending_render_frame_host_->render_view_host(); |
290 } | 294 } |
291 | 295 |
| 296 WebUIImpl* RenderFrameHostManager::GetNavigatingWebUI() const { |
| 297 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 298 switches::kEnableBrowserSideNavigation)) { |
| 299 if (speculative_render_frame_host_) |
| 300 return speculative_render_frame_host_->web_ui(); |
| 301 } else { |
| 302 if (pending_render_frame_host_) |
| 303 return pending_render_frame_host_->web_ui(); |
| 304 } |
| 305 return render_frame_host_->pending_web_ui(); |
| 306 } |
| 307 |
292 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { | 308 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { |
293 if (interstitial_page_) | 309 if (interstitial_page_) |
294 return interstitial_page_->GetView(); | 310 return interstitial_page_->GetView(); |
295 if (render_frame_host_) | 311 if (render_frame_host_) |
296 return render_frame_host_->GetView(); | 312 return render_frame_host_->GetView(); |
297 return nullptr; | 313 return nullptr; |
298 } | 314 } |
299 | 315 |
300 bool RenderFrameHostManager::ForInnerDelegate() { | 316 bool RenderFrameHostManager::ForInnerDelegate() { |
301 return delegate_->GetOuterDelegateFrameTreeNodeID() != | 317 return delegate_->GetOuterDelegateFrameTreeNodeID() != |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 366 |
351 void RenderFrameHostManager::RemoveOuterDelegateFrame() { | 367 void RenderFrameHostManager::RemoveOuterDelegateFrame() { |
352 FrameTreeNode* outer_delegate_frame_tree_node = | 368 FrameTreeNode* outer_delegate_frame_tree_node = |
353 FrameTreeNode::GloballyFindByID( | 369 FrameTreeNode::GloballyFindByID( |
354 delegate_->GetOuterDelegateFrameTreeNodeID()); | 370 delegate_->GetOuterDelegateFrameTreeNodeID()); |
355 DCHECK(outer_delegate_frame_tree_node->parent()); | 371 DCHECK(outer_delegate_frame_tree_node->parent()); |
356 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( | 372 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( |
357 outer_delegate_frame_tree_node); | 373 outer_delegate_frame_tree_node); |
358 } | 374 } |
359 | 375 |
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 | |
381 RenderFrameHostImpl* RenderFrameHostManager::Navigate( | 376 RenderFrameHostImpl* RenderFrameHostManager::Navigate( |
382 const GURL& dest_url, | 377 const GURL& dest_url, |
383 const FrameNavigationEntry& frame_entry, | 378 const FrameNavigationEntry& frame_entry, |
384 const NavigationEntryImpl& entry) { | 379 const NavigationEntryImpl& entry) { |
385 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", | 380 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", |
386 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 381 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
387 // Create a pending RenderFrameHost to use for the navigation. | 382 // Create a pending RenderFrameHost to use for the navigation. |
388 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( | 383 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( |
389 dest_url, | 384 dest_url, |
390 // TODO(creis): Move source_site_instance to FNE. | 385 // TODO(creis): Move source_site_instance to FNE. |
(...skipping 28 matching lines...) Expand all Loading... |
419 // site that is handled via Mojo, then Mojo WebUI code in //chrome will | 414 // site that is handled via Mojo, then Mojo WebUI code in //chrome will |
420 // add a service to this RFH's ServiceRegistry). | 415 // add a service to this RFH's ServiceRegistry). |
421 dest_render_frame_host->SetUpMojoIfNeeded(); | 416 dest_render_frame_host->SetUpMojoIfNeeded(); |
422 | 417 |
423 // Recreate the opener chain. | 418 // Recreate the opener chain. |
424 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), | 419 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), |
425 frame_tree_node_); | 420 frame_tree_node_); |
426 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) | 421 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) |
427 return nullptr; | 422 return nullptr; |
428 | 423 |
| 424 if (GetNavigatingWebUI()) { |
| 425 // A new RenderView was created and there is a navigating WebUI which |
| 426 // never interacted with it. So notify the WebUI using RenderViewCreated. |
| 427 GetNavigatingWebUI()->RenderViewCreated( |
| 428 dest_render_frame_host->render_view_host()); |
| 429 } |
| 430 |
429 // Now that we've created a new renderer, be sure to hide it if it isn't | 431 // Now that we've created a new renderer, be sure to hide it if it isn't |
430 // our primary one. Otherwise, we might crash if we try to call Show() | 432 // our primary one. Otherwise, we might crash if we try to call Show() |
431 // on it later. | 433 // on it later. |
432 if (dest_render_frame_host != render_frame_host_.get()) { | 434 if (dest_render_frame_host != render_frame_host_.get()) { |
433 if (dest_render_frame_host->GetView()) | 435 if (dest_render_frame_host->GetView()) |
434 dest_render_frame_host->GetView()->Hide(); | 436 dest_render_frame_host->GetView()->Hide(); |
435 } else { | 437 } else { |
436 // After a renderer crash we'd have marked the host as invisible, so we | 438 // After a renderer crash we'd have marked the host as invisible, so we |
437 // need to set the visibility of the new View to the correct value here | 439 // need to set the visibility of the new View to the correct value here |
438 // after reload. | 440 // after reload. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 | 673 |
672 // Make sure any dynamic changes to this frame's sandbox flags that were made | 674 // Make sure any dynamic changes to this frame's sandbox flags that were made |
673 // prior to navigation take effect. | 675 // prior to navigation take effect. |
674 CommitPendingSandboxFlags(); | 676 CommitPendingSandboxFlags(); |
675 } | 677 } |
676 | 678 |
677 void RenderFrameHostManager::CommitPendingIfNecessary( | 679 void RenderFrameHostManager::CommitPendingIfNecessary( |
678 RenderFrameHostImpl* render_frame_host, | 680 RenderFrameHostImpl* render_frame_host, |
679 bool was_caused_by_user_gesture) { | 681 bool was_caused_by_user_gesture) { |
680 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { | 682 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { |
681 DCHECK(!should_reuse_web_ui_ || web_ui_); | |
682 | 683 |
683 // We should only hear this from our current renderer. | 684 // We should only hear this from our current renderer. |
684 DCHECK_EQ(render_frame_host_.get(), render_frame_host); | 685 DCHECK_EQ(render_frame_host_.get(), render_frame_host); |
685 | 686 |
686 // Even when there is no pending RVH, there may be a pending Web UI. | 687 // If the current RenderFrameHost has a pending WebUI it must be committed. |
687 if (pending_web_ui() || speculative_web_ui_) | 688 // Note: When one tries to move same-site commit logic into RenderFrameHost |
| 689 // itself, mind that the focus setting logic inside CommitPending also needs |
| 690 // to be moved there. |
| 691 if (render_frame_host_->pending_web_ui()) |
688 CommitPending(); | 692 CommitPending(); |
689 return; | 693 return; |
690 } | 694 } |
691 | 695 |
692 if (render_frame_host == pending_render_frame_host_.get() || | 696 if (render_frame_host == pending_render_frame_host_.get() || |
693 render_frame_host == speculative_render_frame_host_.get()) { | 697 render_frame_host == speculative_render_frame_host_.get()) { |
694 // The pending cross-process navigation completed, so show the renderer. | 698 // The pending cross-process navigation completed, so show the renderer. |
695 CommitPending(); | 699 CommitPending(); |
696 } else if (render_frame_host == render_frame_host_.get()) { | 700 } else if (render_frame_host == render_frame_host_.get()) { |
697 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 701 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 // as browser-initiated navigations. NavigationRequests marked as | 1020 // as browser-initiated navigations. NavigationRequests marked as |
1017 // renderer-initiated are created by receiving a BeginNavigation IPC, and will | 1021 // renderer-initiated are created by receiving a BeginNavigation IPC, and will |
1018 // then proceed in the same renderer that sent the IPC due to the condition | 1022 // then proceed in the same renderer that sent the IPC due to the condition |
1019 // below. | 1023 // below. |
1020 // Subframe navigations will use the current renderer, unless | 1024 // Subframe navigations will use the current renderer, unless |
1021 // --site-per-process is enabled. | 1025 // --site-per-process is enabled. |
1022 // TODO(carlosk): Have renderer-initated main frame navigations swap processes | 1026 // TODO(carlosk): Have renderer-initated main frame navigations swap processes |
1023 // if needed when it no longer breaks OAuth popups (see | 1027 // if needed when it no longer breaks OAuth popups (see |
1024 // https://crbug.com/440266). | 1028 // https://crbug.com/440266). |
1025 bool is_main_frame = frame_tree_node_->IsMainFrame(); | 1029 bool is_main_frame = frame_tree_node_->IsMainFrame(); |
| 1030 bool notify_webui_of_rv_creation = false; |
1026 if (current_site_instance == dest_site_instance.get() || | 1031 if (current_site_instance == dest_site_instance.get() || |
1027 (!request.browser_initiated() && is_main_frame) || | 1032 (!request.browser_initiated() && is_main_frame) || |
1028 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && | 1033 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && |
1029 !current_site_instance->RequiresDedicatedProcess())) { | 1034 !current_site_instance->RequiresDedicatedProcess())) { |
1030 // Reuse the current RFH if its SiteInstance matches the the navigation's | 1035 // Reuse the current RenderFrameHost if its SiteInstance matches the |
1031 // or if this is a subframe navigation. We only swap RFHs for subframes when | 1036 // navigation's or if this is a subframe navigation. We only swap |
1032 // --site-per-process is enabled. | 1037 // RenderFrameHosts for subframes when --site-per-process is enabled. |
1033 CleanUpNavigation(); | 1038 |
| 1039 // There might be a pending WebUI in the current RenderFrameHost from a |
| 1040 // previous call of this function for the same navigation and it should be |
| 1041 // maintained for the next call to RenderFrameHostImpl::UpdatePendingWebUI. |
| 1042 // So instead of calling CleanUpNavigation, discard the speculative |
| 1043 // RenderFrameHost. |
| 1044 if (speculative_render_frame_host_) |
| 1045 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); |
| 1046 |
| 1047 UpdatePendingWebUIOnCurrentFrameHost(request.common_params().url, |
| 1048 request.bindings()); |
| 1049 |
1034 navigation_rfh = render_frame_host_.get(); | 1050 navigation_rfh = render_frame_host_.get(); |
1035 | 1051 |
1036 // As SiteInstances are the same, check if the WebUI should be reused. | 1052 DCHECK(!speculative_render_frame_host_); |
1037 const NavigationEntry* current_navigation_entry = | |
1038 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | |
1039 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, | |
1040 request.common_params().url); | |
1041 if (!should_reuse_web_ui_) { | |
1042 speculative_web_ui_ = CreateWebUI(request.common_params().url, | |
1043 request.bindings()); | |
1044 // Make sure the current RenderViewHost has the right bindings. | |
1045 if (speculative_web_ui() && | |
1046 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { | |
1047 render_frame_host_->render_view_host()->AllowBindings( | |
1048 speculative_web_ui()->GetBindings()); | |
1049 } | |
1050 } | |
1051 } else { | 1053 } else { |
1052 // If the SiteInstance for the final URL doesn't match the one from the | 1054 // If the current RenderFrameHost cannot be used a new speculative one is |
1053 // speculatively created RenderFrameHost, create a new RenderFrameHost using | 1055 // created with the SiteInstance for the current URL. |
1054 // this new SiteInstance. | 1056 |
| 1057 // Check if an existing speculative RenderFrameHost can be reused. |
1055 if (!speculative_render_frame_host_ || | 1058 if (!speculative_render_frame_host_ || |
1056 speculative_render_frame_host_->GetSiteInstance() != | 1059 speculative_render_frame_host_->GetSiteInstance() != |
1057 dest_site_instance.get()) { | 1060 dest_site_instance.get()) { |
| 1061 // If a previous speculative RenderFrameHost didn't exist or if its |
| 1062 // SiteInstance differs from the one for the current URL, a new one needs |
| 1063 // to be created. |
1058 CleanUpNavigation(); | 1064 CleanUpNavigation(); |
1059 bool success = CreateSpeculativeRenderFrameHost( | 1065 bool success = CreateSpeculativeRenderFrameHost(current_site_instance, |
1060 request.common_params().url, current_site_instance, | 1066 dest_site_instance.get()); |
1061 dest_site_instance.get(), request.bindings()); | |
1062 DCHECK(success); | 1067 DCHECK(success); |
1063 } | 1068 } |
1064 DCHECK(speculative_render_frame_host_); | 1069 DCHECK(speculative_render_frame_host_); |
| 1070 |
| 1071 bool changed_web_ui = speculative_render_frame_host_->UpdatePendingWebUI( |
| 1072 request.common_params().url, request.bindings()); |
| 1073 speculative_render_frame_host_->CommitPendingWebUI(); |
| 1074 DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui()); |
| 1075 notify_webui_of_rv_creation = |
| 1076 changed_web_ui && speculative_render_frame_host_->web_ui(); |
| 1077 |
1065 navigation_rfh = speculative_render_frame_host_.get(); | 1078 navigation_rfh = speculative_render_frame_host_.get(); |
1066 | 1079 |
1067 // Check if our current RFH is live. | 1080 // Check if our current RFH is live. |
1068 if (!render_frame_host_->IsRenderFrameLive()) { | 1081 if (!render_frame_host_->IsRenderFrameLive()) { |
1069 // The current RFH is not live. There's no reason to sit around with a | 1082 // The current RFH is not live. There's no reason to sit around with a |
1070 // sad tab or a newly created RFH while we wait for the navigation to | 1083 // sad tab or a newly created RFH while we wait for the navigation to |
1071 // complete. Just switch to the speculative RFH now and go back to normal. | 1084 // complete. Just switch to the speculative RFH now and go back to normal. |
1072 // (Note that we don't care about on{before}unload handlers if the current | 1085 // (Note that we don't care about on{before}unload handlers if the current |
1073 // RFH isn't live.) | 1086 // RFH isn't live.) |
1074 CommitPending(); | 1087 CommitPending(); |
1075 } | 1088 } |
1076 } | 1089 } |
1077 DCHECK(navigation_rfh && | 1090 DCHECK(navigation_rfh && |
1078 (navigation_rfh == render_frame_host_.get() || | 1091 (navigation_rfh == render_frame_host_.get() || |
1079 navigation_rfh == speculative_render_frame_host_.get())); | 1092 navigation_rfh == speculative_render_frame_host_.get())); |
1080 | 1093 |
1081 // If the RenderFrame that needs to navigate is not live (its process was just | 1094 // If the RenderFrame that needs to navigate is not live (its process was just |
1082 // created or has crashed), initialize it. | 1095 // created or has crashed), initialize it. |
1083 if (!navigation_rfh->IsRenderFrameLive()) { | 1096 if (!navigation_rfh->IsRenderFrameLive()) { |
1084 // Recreate the opener chain. | 1097 // Recreate the opener chain. |
1085 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); | 1098 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); |
1086 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) { | 1099 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) |
1087 return nullptr; | 1100 return nullptr; |
1088 } | 1101 notify_webui_of_rv_creation = true; |
1089 | 1102 |
1090 if (navigation_rfh == render_frame_host_.get()) { | 1103 if (navigation_rfh == render_frame_host_.get()) { |
1091 // TODO(nasko): This is a very ugly hack. The Chrome extensions process | 1104 // TODO(nasko): This is a very ugly hack. The Chrome extensions process |
1092 // manager still uses NotificationService and expects to see a | 1105 // manager still uses NotificationService and expects to see a |
1093 // RenderViewHost changed notification after WebContents and | 1106 // RenderViewHost changed notification after WebContents and |
1094 // RenderFrameHostManager are completely initialized. This should be | 1107 // RenderFrameHostManager are completely initialized. This should be |
1095 // removed once the process manager moves away from NotificationService. | 1108 // removed once the process manager moves away from NotificationService. |
1096 // See https://crbug.com/462682. | 1109 // See https://crbug.com/462682. |
1097 delegate_->NotifyMainFrameSwappedFromRenderManager( | 1110 delegate_->NotifyMainFrameSwappedFromRenderManager( |
1098 nullptr, render_frame_host_->render_view_host()); | 1111 nullptr, render_frame_host_->render_view_host()); |
1099 } | 1112 } |
| 1113 DCHECK(navigation_rfh->IsRenderFrameLive()); |
1100 } | 1114 } |
1101 | 1115 |
| 1116 // If a WebUI was created in a speculative RenderFrameHost or a new RenderView |
| 1117 // was created then the WebUI never interacted with the RenderView. Notify |
| 1118 // using RenderViewCreated. |
| 1119 if (notify_webui_of_rv_creation && GetNavigatingWebUI()) |
| 1120 GetNavigatingWebUI()->RenderViewCreated(navigation_rfh->render_view_host()); |
| 1121 |
1102 return navigation_rfh; | 1122 return navigation_rfh; |
1103 } | 1123 } |
1104 | 1124 |
1105 // PlzNavigate | 1125 // PlzNavigate |
1106 void RenderFrameHostManager::CleanUpNavigation() { | 1126 void RenderFrameHostManager::CleanUpNavigation() { |
1107 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 1127 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
1108 switches::kEnableBrowserSideNavigation)); | 1128 switches::kEnableBrowserSideNavigation)); |
1109 speculative_web_ui_.reset(); | 1129 render_frame_host_->ClearPendingWebUI(); |
1110 should_reuse_web_ui_ = false; | |
1111 if (speculative_render_frame_host_) | 1130 if (speculative_render_frame_host_) |
1112 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); | 1131 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); |
1113 } | 1132 } |
1114 | 1133 |
1115 // PlzNavigate | 1134 // PlzNavigate |
1116 scoped_ptr<RenderFrameHostImpl> | 1135 scoped_ptr<RenderFrameHostImpl> |
1117 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { | 1136 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { |
1118 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | 1137 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
1119 switches::kEnableBrowserSideNavigation)); | 1138 switches::kEnableBrowserSideNavigation)); |
1120 speculative_render_frame_host_->GetProcess()->RemovePendingView(); | 1139 speculative_render_frame_host_->GetProcess()->RemovePendingView(); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 // We can't switch a RenderView between view source and non-view source mode | 1312 // We can't switch a RenderView between view source and non-view source mode |
1294 // without screwing up the session history sometimes (when navigating between | 1313 // without screwing up the session history sometimes (when navigating between |
1295 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat | 1314 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat |
1296 // it as a new navigation). So require a BrowsingInstance switch. | 1315 // it as a new navigation). So require a BrowsingInstance switch. |
1297 if (current_is_view_source_mode != new_is_view_source_mode) | 1316 if (current_is_view_source_mode != new_is_view_source_mode) |
1298 return true; | 1317 return true; |
1299 | 1318 |
1300 return false; | 1319 return false; |
1301 } | 1320 } |
1302 | 1321 |
1303 bool RenderFrameHostManager::ShouldReuseWebUI( | |
1304 const NavigationEntry* current_entry, | |
1305 const GURL& new_url) const { | |
1306 NavigationControllerImpl& controller = | |
1307 delegate_->GetControllerForRenderManager(); | |
1308 return current_entry && web_ui_ && | |
1309 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( | |
1310 controller.GetBrowserContext(), current_entry->GetURL()) == | |
1311 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( | |
1312 controller.GetBrowserContext(), new_url)); | |
1313 } | |
1314 | |
1315 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( | 1322 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( |
1316 const GURL& dest_url, | 1323 const GURL& dest_url, |
1317 SiteInstance* source_instance, | 1324 SiteInstance* source_instance, |
1318 SiteInstance* dest_instance, | 1325 SiteInstance* dest_instance, |
1319 SiteInstance* candidate_instance, | 1326 SiteInstance* candidate_instance, |
1320 ui::PageTransition transition, | 1327 ui::PageTransition transition, |
1321 bool dest_is_restore, | 1328 bool dest_is_restore, |
1322 bool dest_is_view_source_mode) { | 1329 bool dest_is_view_source_mode) { |
1323 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 1330 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
1324 | 1331 |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1637 // The process for the new SiteInstance may (if we're sharing a process with | 1644 // The process for the new SiteInstance may (if we're sharing a process with |
1638 // another host that already initialized it) or may not (we have our own | 1645 // another host that already initialized it) or may not (we have our own |
1639 // process or the existing process crashed) have been initialized. Calling | 1646 // process or the existing process crashed) have been initialized. Calling |
1640 // Init multiple times will be ignored, so this is safe. | 1647 // Init multiple times will be ignored, so this is safe. |
1641 if (!new_instance->GetProcess()->Init()) | 1648 if (!new_instance->GetProcess()->Init()) |
1642 return; | 1649 return; |
1643 | 1650 |
1644 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); | 1651 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); |
1645 | 1652 |
1646 // Create a non-swapped-out RFH with the given opener. | 1653 // Create a non-swapped-out RFH with the given opener. |
1647 pending_render_frame_host_ = CreateRenderFrame( | 1654 pending_render_frame_host_ = |
1648 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); | 1655 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr); |
1649 } | 1656 } |
1650 | 1657 |
1651 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( | 1658 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( |
1652 SiteInstance* old_instance, | 1659 SiteInstance* old_instance, |
1653 SiteInstance* new_instance) { | 1660 SiteInstance* new_instance) { |
1654 // Only create opener proxies if they are in the same BrowsingInstance. | 1661 // Only create opener proxies if they are in the same BrowsingInstance. |
1655 if (new_instance->IsRelatedSiteInstance(old_instance)) { | 1662 if (new_instance->IsRelatedSiteInstance(old_instance)) { |
1656 CreateOpenerProxies(new_instance, frame_tree_node_); | 1663 CreateOpenerProxies(new_instance, frame_tree_node_); |
1657 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { | 1664 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { |
1658 // Ensure that the frame tree has RenderFrameProxyHosts for the | 1665 // Ensure that the frame tree has RenderFrameProxyHosts for the |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1734 } | 1741 } |
1735 | 1742 |
1736 return RenderFrameHostFactory::Create( | 1743 return RenderFrameHostFactory::Create( |
1737 site_instance, render_view_host, render_frame_delegate_, | 1744 site_instance, render_view_host, render_frame_delegate_, |
1738 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, | 1745 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, |
1739 widget_routing_id, flags); | 1746 widget_routing_id, flags); |
1740 } | 1747 } |
1741 | 1748 |
1742 // PlzNavigate | 1749 // PlzNavigate |
1743 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( | 1750 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( |
1744 const GURL& url, | |
1745 SiteInstance* old_instance, | 1751 SiteInstance* old_instance, |
1746 SiteInstance* new_instance, | 1752 SiteInstance* new_instance) { |
1747 int bindings) { | |
1748 CHECK(new_instance); | 1753 CHECK(new_instance); |
1749 CHECK_NE(old_instance, new_instance); | 1754 CHECK_NE(old_instance, new_instance); |
1750 CHECK(!should_reuse_web_ui_); | |
1751 | |
1752 // Note: |speculative_web_ui_| must be initialized before starting the | |
1753 // |speculative_render_frame_host_| creation steps otherwise the WebUI | |
1754 // won't be properly initialized. | |
1755 speculative_web_ui_ = CreateWebUI(url, bindings); | |
1756 | 1755 |
1757 // The process for the new SiteInstance may (if we're sharing a process with | 1756 // The process for the new SiteInstance may (if we're sharing a process with |
1758 // another host that already initialized it) or may not (we have our own | 1757 // another host that already initialized it) or may not (we have our own |
1759 // process or the existing process crashed) have been initialized. Calling | 1758 // process or the existing process crashed) have been initialized. Calling |
1760 // Init multiple times will be ignored, so this is safe. | 1759 // Init multiple times will be ignored, so this is safe. |
1761 if (!new_instance->GetProcess()->Init()) | 1760 if (!new_instance->GetProcess()->Init()) |
1762 return false; | 1761 return false; |
1763 | 1762 |
1764 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); | 1763 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); |
1765 | 1764 |
1766 int create_render_frame_flags = 0; | 1765 int create_render_frame_flags = 0; |
1767 if (delegate_->IsHidden()) | 1766 if (delegate_->IsHidden()) |
1768 create_render_frame_flags |= CREATE_RF_HIDDEN; | 1767 create_render_frame_flags |= CREATE_RF_HIDDEN; |
1769 speculative_render_frame_host_ = | 1768 speculative_render_frame_host_ = |
1770 CreateRenderFrame(new_instance, speculative_web_ui_.get(), | 1769 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr); |
1771 create_render_frame_flags, nullptr); | |
1772 | 1770 |
1773 if (!speculative_render_frame_host_) { | 1771 return !!speculative_render_frame_host_; |
1774 speculative_web_ui_.reset(); | |
1775 return false; | |
1776 } | |
1777 return true; | |
1778 } | 1772 } |
1779 | 1773 |
1780 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( | 1774 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( |
1781 SiteInstance* instance, | 1775 SiteInstance* instance, |
1782 WebUIImpl* web_ui, | |
1783 int flags, | 1776 int flags, |
1784 int* view_routing_id_ptr) { | 1777 int* view_routing_id_ptr) { |
1785 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); | 1778 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); |
1786 bool swapped_out_forbidden = | 1779 bool swapped_out_forbidden = |
1787 SiteIsolationPolicy::IsSwappedOutStateForbidden(); | 1780 SiteIsolationPolicy::IsSwappedOutStateForbidden(); |
1788 | 1781 |
1789 CHECK(instance); | 1782 CHECK(instance); |
1790 CHECK(!swapped_out_forbidden || !swapped_out); | 1783 CHECK(!swapped_out_forbidden || !swapped_out); |
1791 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || | 1784 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || |
1792 frame_tree_node_->IsMainFrame()); | 1785 frame_tree_node_->IsMainFrame()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1890 success = InitRenderFrame(new_render_frame_host.get()); | 1883 success = InitRenderFrame(new_render_frame_host.get()); |
1891 } | 1884 } |
1892 } | 1885 } |
1893 | 1886 |
1894 if (success) { | 1887 if (success) { |
1895 if (view_routing_id_ptr) | 1888 if (view_routing_id_ptr) |
1896 *view_routing_id_ptr = render_view_host->GetRoutingID(); | 1889 *view_routing_id_ptr = render_view_host->GetRoutingID(); |
1897 } | 1890 } |
1898 } | 1891 } |
1899 | 1892 |
1900 // When a new RenderView is created by the renderer process, the new | |
1901 // WebContents gets a RenderViewHost in the SiteInstance of its opener | |
1902 // WebContents. If not used in the first navigation, this RVH is swapped out | |
1903 // and is not granted bindings, so we may need to grant them when swapping it | |
1904 // in. | |
1905 if (web_ui && !new_render_frame_host->GetProcess()->IsForGuestsOnly()) { | |
1906 int required_bindings = web_ui->GetBindings(); | |
1907 RenderViewHost* render_view_host = | |
1908 new_render_frame_host->render_view_host(); | |
1909 if ((render_view_host->GetEnabledBindings() & required_bindings) != | |
1910 required_bindings) { | |
1911 render_view_host->AllowBindings(required_bindings); | |
1912 } | |
1913 } | |
1914 | |
1915 // Returns the new RFH if it isn't swapped out. | 1893 // Returns the new RFH if it isn't swapped out. |
1916 if (success && !swapped_out) { | 1894 if (success && !swapped_out) { |
1917 DCHECK(new_render_frame_host->GetSiteInstance() == instance); | 1895 DCHECK(new_render_frame_host->GetSiteInstance() == instance); |
1918 return new_render_frame_host.Pass(); | 1896 return new_render_frame_host.Pass(); |
1919 } | 1897 } |
1920 return nullptr; | 1898 return nullptr; |
1921 } | 1899 } |
1922 | 1900 |
1923 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { | 1901 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { |
1924 // A RenderFrameProxyHost should never be created in the same SiteInstance as | 1902 // A RenderFrameProxyHost should never be created in the same SiteInstance as |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2023 RenderFrameProxyHost* proxy) { | 2001 RenderFrameProxyHost* proxy) { |
2024 // Ensure the renderer process is initialized before creating the | 2002 // Ensure the renderer process is initialized before creating the |
2025 // RenderView. | 2003 // RenderView. |
2026 if (!render_view_host->GetProcess()->Init()) | 2004 if (!render_view_host->GetProcess()->Init()) |
2027 return false; | 2005 return false; |
2028 | 2006 |
2029 // We may have initialized this RenderViewHost for another RenderFrameHost. | 2007 // We may have initialized this RenderViewHost for another RenderFrameHost. |
2030 if (render_view_host->IsRenderViewLive()) | 2008 if (render_view_host->IsRenderViewLive()) |
2031 return true; | 2009 return true; |
2032 | 2010 |
2033 // If |render_view_host| is not for a proxy and the navigation is to a WebUI, | |
2034 // and if the RenderView is not in a guest process, tell |render_view_host| | |
2035 // about any bindings it will need enabled. | |
2036 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850. | |
2037 WebUIImpl* dest_web_ui = nullptr; | |
2038 if (!proxy) { | |
2039 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
2040 switches::kEnableBrowserSideNavigation)) { | |
2041 dest_web_ui = | |
2042 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get(); | |
2043 } else { | |
2044 dest_web_ui = pending_web_ui(); | |
2045 } | |
2046 } | |
2047 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) { | |
2048 render_view_host->AllowBindings(dest_web_ui->GetBindings()); | |
2049 } else { | |
2050 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled | |
2051 // process unless it's swapped out. | |
2052 if (render_view_host->is_active()) { | |
2053 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | |
2054 render_view_host->GetProcess()->GetID())); | |
2055 } | |
2056 } | |
2057 | |
2058 int opener_frame_routing_id = | 2011 int opener_frame_routing_id = |
2059 GetOpenerRoutingID(render_view_host->GetSiteInstance()); | 2012 GetOpenerRoutingID(render_view_host->GetSiteInstance()); |
2060 | 2013 |
2061 bool created = delegate_->CreateRenderViewForRenderManager( | 2014 bool created = delegate_->CreateRenderViewForRenderManager( |
2062 render_view_host, opener_frame_routing_id, | 2015 render_view_host, opener_frame_routing_id, |
2063 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, | 2016 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, |
2064 frame_tree_node_->current_replication_state()); | 2017 frame_tree_node_->current_replication_state()); |
2065 | 2018 |
2066 if (created && proxy) | 2019 if (created && proxy) |
2067 proxy->set_render_frame_proxy_created(true); | 2020 proxy->set_render_frame_proxy_created(true); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2139 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); | 2092 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); |
2140 if (proxy) | 2093 if (proxy) |
2141 return proxy->GetRoutingID(); | 2094 return proxy->GetRoutingID(); |
2142 | 2095 |
2143 return MSG_ROUTING_NONE; | 2096 return MSG_ROUTING_NONE; |
2144 } | 2097 } |
2145 | 2098 |
2146 void RenderFrameHostManager::CommitPending() { | 2099 void RenderFrameHostManager::CommitPending() { |
2147 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", | 2100 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", |
2148 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 2101 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
2149 bool browser_side_navigation = | |
2150 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
2151 switches::kEnableBrowserSideNavigation); | |
2152 | |
2153 // First check whether we're going to want to focus the location bar after | 2102 // First check whether we're going to want to focus the location bar after |
2154 // this commit. We do this now because the navigation hasn't formally | 2103 // this commit. We do this now because the navigation hasn't formally |
2155 // committed yet, so if we've already cleared |pending_web_ui_| the call chain | 2104 // committed yet, so if we've already cleared the pending WebUI the call chain |
2156 // this triggers won't be able to figure out what's going on. | 2105 // this triggers won't be able to figure out what's going on. |
2157 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); | 2106 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); |
2158 | 2107 |
2159 // Next commit the Web UI, if any. Either replace |web_ui_| with | 2108 // If the current RenderFrameHost has a pending WebUI then just commit it and |
2160 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or | 2109 // return (there should be nothing else to commit). |
2161 // leave |web_ui_| as is if reusing it. | 2110 if (render_frame_host_->pending_web_ui()) { |
2162 DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_)); | 2111 DCHECK(!pending_render_frame_host_ && !speculative_render_frame_host_); |
2163 if (pending_web_ui_ || speculative_web_ui_) { | 2112 render_frame_host_->CommitPendingWebUI(); |
2164 DCHECK(!should_reuse_web_ui_); | |
2165 web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release() | |
2166 : pending_web_ui_.release()); | |
2167 } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) { | |
2168 if (browser_side_navigation) { | |
2169 DCHECK(web_ui_); | |
2170 should_reuse_web_ui_ = false; | |
2171 } else { | |
2172 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); | |
2173 pending_and_current_web_ui_.reset(); | |
2174 } | |
2175 } else { | |
2176 web_ui_.reset(); | |
2177 } | |
2178 DCHECK(!speculative_web_ui_); | |
2179 DCHECK(!should_reuse_web_ui_); | |
2180 | |
2181 // It's possible for the pending_render_frame_host_ to be nullptr when we | |
2182 // aren't crossing process boundaries. If so, we just needed to handle the Web | |
2183 // UI committing above and we're done. | |
2184 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { | |
2185 if (will_focus_location_bar) | 2113 if (will_focus_location_bar) |
2186 delegate_->SetFocusToLocationBar(false); | 2114 delegate_->SetFocusToLocationBar(false); |
2187 return; | 2115 return; |
2188 } | 2116 } |
2189 | 2117 |
2190 // Remember if the page was focused so we can focus the new renderer in | 2118 // Remember if the page was focused so we can focus the new renderer in |
2191 // that case. | 2119 // that case. |
2192 bool focus_render_view = !will_focus_location_bar && | 2120 bool focus_render_view = !will_focus_location_bar && |
2193 render_frame_host_->GetView() && | 2121 render_frame_host_->GetView() && |
2194 render_frame_host_->GetView()->HasFocus(); | 2122 render_frame_host_->GetView()->HasFocus(); |
2195 | 2123 |
2196 bool is_main_frame = frame_tree_node_->IsMainFrame(); | 2124 bool is_main_frame = frame_tree_node_->IsMainFrame(); |
2197 | 2125 |
2198 // Swap in the pending or speculative frame and make it active. Also ensure | 2126 // Swap in the pending or speculative frame and make it active. Also ensure |
2199 // the FrameTree stays in sync. | 2127 // the FrameTree stays in sync. |
2200 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; | 2128 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; |
2201 if (!browser_side_navigation) { | 2129 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2130 switches::kEnableBrowserSideNavigation)) { |
2202 DCHECK(!speculative_render_frame_host_); | 2131 DCHECK(!speculative_render_frame_host_); |
2203 old_render_frame_host = | 2132 old_render_frame_host = |
2204 SetRenderFrameHost(pending_render_frame_host_.Pass()); | 2133 SetRenderFrameHost(pending_render_frame_host_.Pass()); |
2205 } else { | 2134 } else { |
2206 // PlzNavigate | 2135 // PlzNavigate |
2207 DCHECK(speculative_render_frame_host_); | 2136 DCHECK(speculative_render_frame_host_); |
2208 old_render_frame_host = | 2137 old_render_frame_host = |
2209 SetRenderFrameHost(speculative_render_frame_host_.Pass()); | 2138 SetRenderFrameHost(speculative_render_frame_host_.Pass()); |
2210 } | 2139 } |
2211 | 2140 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 // If we are currently navigating cross-process, we want to get back to normal | 2290 // If we are currently navigating cross-process, we want to get back to normal |
2362 // and then navigate as usual. | 2291 // and then navigate as usual. |
2363 if (pending_render_frame_host_) | 2292 if (pending_render_frame_host_) |
2364 CancelPending(); | 2293 CancelPending(); |
2365 | 2294 |
2366 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); | 2295 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); |
2367 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( | 2296 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( |
2368 dest_url, source_instance, dest_instance, nullptr, transition, | 2297 dest_url, source_instance, dest_instance, nullptr, transition, |
2369 dest_is_restore, dest_is_view_source_mode); | 2298 dest_is_restore, dest_is_view_source_mode); |
2370 | 2299 |
2371 const NavigationEntry* current_entry = | |
2372 delegate_->GetLastCommittedNavigationEntryForRenderManager(); | |
2373 | |
2374 DCHECK(!pending_render_frame_host_); | 2300 DCHECK(!pending_render_frame_host_); |
2375 | 2301 |
2376 if (new_instance.get() != current_instance) { | 2302 if (new_instance.get() != current_instance) { |
2377 TRACE_EVENT_INSTANT2( | 2303 TRACE_EVENT_INSTANT2( |
2378 "navigation", | 2304 "navigation", |
2379 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", | 2305 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", |
2380 TRACE_EVENT_SCOPE_THREAD, | 2306 TRACE_EVENT_SCOPE_THREAD, |
2381 "current_instance id", current_instance->GetId(), | 2307 "current_instance id", current_instance->GetId(), |
2382 "new_instance id", new_instance->GetId()); | 2308 "new_instance id", new_instance->GetId()); |
2383 | 2309 |
2384 // New SiteInstance: create a pending RFH to navigate. | 2310 // New SiteInstance: create a pending RFH to navigate. |
2385 | 2311 |
2386 // This will possibly create (set to nullptr) a Web UI object for the | |
2387 // pending page. We'll use this later to give the page special access. This | |
2388 // must happen before the new renderer is created below so it will get | |
2389 // bindings. It must also happen after the above conditional call to | |
2390 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_ | |
2391 // and the page will not have its bindings set appropriately. | |
2392 SetPendingWebUI(dest_url, bindings); | |
2393 CreatePendingRenderFrameHost(current_instance, new_instance.get()); | 2312 CreatePendingRenderFrameHost(current_instance, new_instance.get()); |
| 2313 DCHECK(pending_render_frame_host_); |
2394 if (!pending_render_frame_host_) | 2314 if (!pending_render_frame_host_) |
2395 return nullptr; | 2315 return nullptr; |
2396 | 2316 |
| 2317 pending_render_frame_host_->UpdatePendingWebUI(dest_url, bindings); |
| 2318 pending_render_frame_host_->CommitPendingWebUI(); |
| 2319 DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui()); |
| 2320 |
| 2321 // If a WebUI exists in the pending RenderFrameHost it was just created, as |
| 2322 // well as the RenderView, and they never interacted. So notify it using |
| 2323 // RenderViewCreated. |
| 2324 if (pending_render_frame_host_->web_ui()) { |
| 2325 pending_render_frame_host_->web_ui()->RenderViewCreated( |
| 2326 pending_render_frame_host_->render_view_host()); |
| 2327 } |
| 2328 |
2397 // Check if our current RFH is live before we set up a transition. | 2329 // Check if our current RFH is live before we set up a transition. |
2398 if (!render_frame_host_->IsRenderFrameLive()) { | 2330 if (!render_frame_host_->IsRenderFrameLive()) { |
2399 // The current RFH is not live. There's no reason to sit around with a | 2331 // The current RFH is not live. There's no reason to sit around with a |
2400 // sad tab or a newly created RFH while we wait for the pending RFH to | 2332 // sad tab or a newly created RFH while we wait for the pending RFH to |
2401 // navigate. Just switch to the pending RFH now and go back to normal. | 2333 // navigate. Just switch to the pending RFH now and go back to normal. |
2402 // (Note that we don't care about on{before}unload handlers if the current | 2334 // (Note that we don't care about on{before}unload handlers if the current |
2403 // RFH isn't live.) | 2335 // RFH isn't live.) |
2404 CommitPending(); | 2336 CommitPending(); |
2405 return render_frame_host_.get(); | 2337 return render_frame_host_.get(); |
2406 } | 2338 } |
2407 // Otherwise, it's safe to treat this as a pending cross-process transition. | 2339 // Otherwise, it's safe to treat this as a pending cross-process transition. |
2408 | 2340 |
2409 // We now have a pending RFH. | |
2410 DCHECK(pending_render_frame_host_); | |
2411 | |
2412 // We need to wait until the beforeunload handler has run, unless we are | 2341 // We need to wait until the beforeunload handler has run, unless we are |
2413 // transferring an existing request (in which case it has already run). | 2342 // transferring an existing request (in which case it has already run). |
2414 // Suspend the new render view (i.e., don't let it send the cross-process | 2343 // Suspend the new render view (i.e., don't let it send the cross-process |
2415 // Navigate message) until we hear back from the old renderer's | 2344 // Navigate message) until we hear back from the old renderer's |
2416 // beforeunload handler. If the handler returns false, we'll have to | 2345 // beforeunload handler. If the handler returns false, we'll have to |
2417 // cancel the request. | 2346 // cancel the request. |
2418 // | |
2419 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); | 2347 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); |
2420 bool is_transfer = transferred_request_id != GlobalRequestID(); | 2348 bool is_transfer = transferred_request_id != GlobalRequestID(); |
2421 if (is_transfer) { | 2349 if (is_transfer) { |
2422 // We don't need to stop the old renderer or run beforeunload/unload | 2350 // We don't need to stop the old renderer or run beforeunload/unload |
2423 // handlers, because those have already been done. | 2351 // handlers, because those have already been done. |
2424 DCHECK(cross_site_transferring_request_->request_id() == | 2352 DCHECK(cross_site_transferring_request_->request_id() == |
2425 transferred_request_id); | 2353 transferred_request_id); |
2426 } else { | 2354 } else { |
2427 // Also make sure the old render view stops, in case a load is in | 2355 // Also make sure the old render view stops, in case a load is in |
2428 // progress. (We don't want to do this for transfers, since it will | 2356 // progress. (We don't want to do this for transfers, since it will |
2429 // interrupt the transfer with an unexpected DidStopLoading.) | 2357 // interrupt the transfer with an unexpected DidStopLoading.) |
2430 render_frame_host_->Send(new FrameMsg_Stop( | 2358 render_frame_host_->Send(new FrameMsg_Stop( |
2431 render_frame_host_->GetRoutingID())); | 2359 render_frame_host_->GetRoutingID())); |
2432 pending_render_frame_host_->SetNavigationsSuspended(true, | 2360 pending_render_frame_host_->SetNavigationsSuspended(true, |
2433 base::TimeTicks()); | 2361 base::TimeTicks()); |
2434 // Unless we are transferring an existing request, we should now tell the | 2362 // Unless we are transferring an existing request, we should now tell the |
2435 // old render view to run its beforeunload handler, since it doesn't | 2363 // old render view to run its beforeunload handler, since it doesn't |
2436 // otherwise know that the cross-site request is happening. This will | 2364 // otherwise know that the cross-site request is happening. This will |
2437 // trigger a call to OnBeforeUnloadACK with the reply. | 2365 // trigger a call to OnBeforeUnloadACK with the reply. |
2438 render_frame_host_->DispatchBeforeUnload(true); | 2366 render_frame_host_->DispatchBeforeUnload(true); |
2439 } | 2367 } |
2440 | 2368 |
| 2369 DCHECK(!render_frame_host_->pending_web_ui()); |
2441 return pending_render_frame_host_.get(); | 2370 return pending_render_frame_host_.get(); |
2442 } | 2371 } |
2443 | 2372 |
2444 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. | 2373 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. |
2445 | 2374 |
2446 // It's possible to swap out the current RFH and then decide to navigate in it | 2375 // It's possible to swap out the current RFH and then decide to navigate in it |
2447 // anyway (e.g., a cross-process navigation that redirects back to the | 2376 // anyway (e.g., a cross-process navigation that redirects back to the |
2448 // original site). In that case, we have a proxy for the current RFH but | 2377 // original site). In that case, we have a proxy for the current RFH but |
2449 // haven't deleted it yet. The new navigation will swap it back in, so we can | 2378 // haven't deleted it yet. The new navigation will swap it back in, so we can |
2450 // delete the proxy. | 2379 // delete the proxy. |
2451 proxy_hosts_->Remove(new_instance.get()->GetId()); | 2380 proxy_hosts_->Remove(new_instance.get()->GetId()); |
2452 | 2381 |
2453 if (ShouldReuseWebUI(current_entry, dest_url)) { | 2382 UpdatePendingWebUIOnCurrentFrameHost(dest_url, bindings); |
2454 pending_web_ui_.reset(); | |
2455 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); | |
2456 } else { | |
2457 SetPendingWebUI(dest_url, bindings); | |
2458 // Make sure the new RenderViewHost has the right bindings. | |
2459 if (pending_web_ui() && | |
2460 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { | |
2461 render_frame_host_->render_view_host()->AllowBindings( | |
2462 pending_web_ui()->GetBindings()); | |
2463 } | |
2464 } | |
2465 | |
2466 if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) { | |
2467 pending_web_ui()->RenderViewReused(render_frame_host_->render_view_host(), | |
2468 frame_tree_node_->IsMainFrame()); | |
2469 } | |
2470 | 2383 |
2471 // The renderer can exit view source mode when any error or cancellation | 2384 // The renderer can exit view source mode when any error or cancellation |
2472 // happen. We must overwrite to recover the mode. | 2385 // happen. We must overwrite to recover the mode. |
2473 if (dest_is_view_source_mode) { | 2386 if (dest_is_view_source_mode) { |
2474 render_frame_host_->render_view_host()->Send( | 2387 render_frame_host_->render_view_host()->Send( |
2475 new ViewMsg_EnableViewSourceMode( | 2388 new ViewMsg_EnableViewSourceMode( |
2476 render_frame_host_->render_view_host()->GetRoutingID())); | 2389 render_frame_host_->render_view_host()->GetRoutingID())); |
2477 } | 2390 } |
2478 | 2391 |
2479 return render_frame_host_.get(); | 2392 return render_frame_host_.get(); |
2480 } | 2393 } |
2481 | 2394 |
| 2395 void RenderFrameHostManager::UpdatePendingWebUIOnCurrentFrameHost( |
| 2396 const GURL& dest_url, |
| 2397 int entry_bindings) { |
| 2398 bool pending_webui_changed = |
| 2399 render_frame_host_->UpdatePendingWebUI(dest_url, entry_bindings); |
| 2400 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->pending_web_ui()); |
| 2401 |
| 2402 if (render_frame_host_->pending_web_ui() && pending_webui_changed && |
| 2403 render_frame_host_->IsRenderFrameLive()) { |
| 2404 // If a pending WebUI exists in the current RenderFrameHost and it has been |
| 2405 // updated and the associated RenderFrame is alive, notify the WebUI about |
| 2406 // the RenderView. |
| 2407 // Note: If the RenderFrame is not alive at this point the notification will |
| 2408 // happen later, when the RenderView is created. |
| 2409 if (render_frame_host_->pending_web_ui() == render_frame_host_->web_ui()) { |
| 2410 // If the active WebUI is being reused it has already interacting with |
| 2411 // this RenderView in the past, so call RenderViewReused. |
| 2412 render_frame_host_->pending_web_ui()->RenderViewReused( |
| 2413 render_frame_host_->render_view_host(), |
| 2414 frame_tree_node_->IsMainFrame()); |
| 2415 } else { |
| 2416 // If this is a new WebUI it has never interacted with the existing |
| 2417 // RenderView so call RenderViewCreated. |
| 2418 render_frame_host_->pending_web_ui()->RenderViewCreated( |
| 2419 render_frame_host_->render_view_host()); |
| 2420 } |
| 2421 } |
| 2422 } |
| 2423 |
2482 void RenderFrameHostManager::CancelPending() { | 2424 void RenderFrameHostManager::CancelPending() { |
2483 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", | 2425 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", |
2484 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); | 2426 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); |
| 2427 render_frame_host_->ClearPendingWebUI(); |
2485 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); | 2428 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); |
2486 } | 2429 } |
2487 | 2430 |
2488 scoped_ptr<RenderFrameHostImpl> | 2431 scoped_ptr<RenderFrameHostImpl> |
2489 RenderFrameHostManager::UnsetPendingRenderFrameHost() { | 2432 RenderFrameHostManager::UnsetPendingRenderFrameHost() { |
2490 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = | 2433 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = |
2491 pending_render_frame_host_.Pass(); | 2434 pending_render_frame_host_.Pass(); |
2492 | 2435 |
2493 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( | 2436 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( |
2494 pending_render_frame_host.get(), | 2437 pending_render_frame_host.get(), |
2495 render_frame_host_.get()); | 2438 render_frame_host_.get()); |
2496 | 2439 |
2497 // We no longer need to prevent the process from exiting. | 2440 // We no longer need to prevent the process from exiting. |
2498 pending_render_frame_host->GetProcess()->RemovePendingView(); | 2441 pending_render_frame_host->GetProcess()->RemovePendingView(); |
2499 | 2442 |
2500 pending_web_ui_.reset(); | |
2501 pending_and_current_web_ui_.reset(); | |
2502 | |
2503 return pending_render_frame_host.Pass(); | 2443 return pending_render_frame_host.Pass(); |
2504 } | 2444 } |
2505 | 2445 |
2506 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( | 2446 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( |
2507 scoped_ptr<RenderFrameHostImpl> render_frame_host) { | 2447 scoped_ptr<RenderFrameHostImpl> render_frame_host) { |
2508 // Swap the two. | 2448 // Swap the two. |
2509 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = | 2449 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = |
2510 render_frame_host_.Pass(); | 2450 render_frame_host_.Pass(); |
2511 render_frame_host_ = render_frame_host.Pass(); | 2451 render_frame_host_ = render_frame_host.Pass(); |
2512 | 2452 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2667 if (rvh && !rvh->IsRenderViewLive()) { | 2607 if (rvh && !rvh->IsRenderViewLive()) { |
2668 EnsureRenderViewInitialized(rvh, instance); | 2608 EnsureRenderViewInitialized(rvh, instance); |
2669 } else { | 2609 } else { |
2670 // Create a swapped out RenderView in the given SiteInstance if none | 2610 // Create a swapped out RenderView in the given SiteInstance if none |
2671 // exists. Since an opener can point to a subframe, do this on the root | 2611 // exists. Since an opener can point to a subframe, do this on the root |
2672 // frame of the current opener's frame tree. | 2612 // frame of the current opener's frame tree. |
2673 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { | 2613 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { |
2674 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); | 2614 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); |
2675 } else { | 2615 } else { |
2676 frame_tree->root()->render_manager()->CreateRenderFrame( | 2616 frame_tree->root()->render_manager()->CreateRenderFrame( |
2677 instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, | 2617 instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr); |
2678 nullptr); | |
2679 } | 2618 } |
2680 } | 2619 } |
2681 } | 2620 } |
2682 } | 2621 } |
2683 | 2622 |
2684 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { | 2623 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { |
2685 if (!frame_tree_node_->opener()) | 2624 if (!frame_tree_node_->opener()) |
2686 return MSG_ROUTING_NONE; | 2625 return MSG_ROUTING_NONE; |
2687 | 2626 |
2688 return frame_tree_node_->opener() | 2627 return frame_tree_node_->opener() |
2689 ->render_manager() | 2628 ->render_manager() |
2690 ->GetRoutingIdForSiteInstance(instance); | 2629 ->GetRoutingIdForSiteInstance(instance); |
2691 } | 2630 } |
2692 | 2631 |
2693 } // namespace content | 2632 } // namespace content |
OLD | NEW |