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

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

Issue 1472703004: Reland #2 of: Move WebUI ownership from the RenderFrameHostManager to the RenderFrameHost. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test shared code now uses lambda functions. More comments. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/frame_host/render_frame_host_manager.h" 5 #include "content/browser/frame_host/render_frame_host_manager.h"
6 6
7 #include <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
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
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
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
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
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
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_); 683 // There's no pending/speculative RenderFrameHost so it must be that the
684 // current renderer process completed a navigation.
682 685
683 // We should only hear this from our current renderer. 686 // We should only hear this from our current renderer.
684 DCHECK_EQ(render_frame_host_.get(), render_frame_host); 687 DCHECK_EQ(render_frame_host_.get(), render_frame_host);
685 688
686 // Even when there is no pending RVH, there may be a pending Web UI. 689 // If the current RenderFrameHost has a pending WebUI it must be committed.
687 if (pending_web_ui() || speculative_web_ui_) 690 // Note: When one tries to move same-site commit logic into RenderFrameHost
688 CommitPending(); 691 // itself, mind that the focus setting logic inside CommitPending also needs
692 // to be moved there.
693 if (render_frame_host_->pending_web_ui())
694 CommitPendingWebUI();
689 return; 695 return;
690 } 696 }
691 697
692 if (render_frame_host == pending_render_frame_host_.get() || 698 if (render_frame_host == pending_render_frame_host_.get() ||
693 render_frame_host == speculative_render_frame_host_.get()) { 699 render_frame_host == speculative_render_frame_host_.get()) {
694 // The pending cross-process navigation completed, so show the renderer. 700 // A cross-process navigation completed, so show the new renderer. If a
701 // same-process navigation is also ongoing, it will be canceled when the
702 // pending/speculative RenderFrameHost replaces the current one in the
703 // commit call below.
695 CommitPending(); 704 CommitPending();
696 } else if (render_frame_host == render_frame_host_.get()) { 705 } else if (render_frame_host == render_frame_host_.get()) {
706 // A same-process navigation committed while a simultaneous cross-process
707 // navigation is still ongoing.
708
709 // If the current RenderFrameHost has a pending WebUI it must be committed.
710 if (render_frame_host_->pending_web_ui())
711 CommitPendingWebUI();
712
713 // Decide on canceling the ongoing cross-process navigation.
697 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 714 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
698 switches::kEnableBrowserSideNavigation)) { 715 switches::kEnableBrowserSideNavigation)) {
699 CleanUpNavigation(); 716 CleanUpNavigation();
700 } else { 717 } else {
701 if (was_caused_by_user_gesture) { 718 if (was_caused_by_user_gesture) {
702 // A navigation in the original page has taken place. Cancel the 719 // A navigation in the original page has taken place. Cancel the
703 // pending one. Only do it for user gesture originated navigations to 720 // pending one. Only do it for user gesture originated navigations to
704 // prevent page doing any shenanigans to prevent user from navigating. 721 // prevent page doing any shenanigans to prevent user from navigating.
705 // See https://code.google.com/p/chromium/issues/detail?id=75195 722 // See https://code.google.com/p/chromium/issues/detail?id=75195
706 CancelPending(); 723 CancelPending();
707 } 724 }
708 } 725 }
709 } else { 726 } else {
710 // No one else should be sending us DidNavigate in this state. 727 // No one else should be sending us DidNavigate in this state.
711 DCHECK(false); 728 NOTREACHED();
712 } 729 }
713 } 730 }
714 731
715 void RenderFrameHostManager::DidChangeOpener( 732 void RenderFrameHostManager::DidChangeOpener(
716 int opener_routing_id, 733 int opener_routing_id,
717 SiteInstance* source_site_instance) { 734 SiteInstance* source_site_instance) {
718 FrameTreeNode* opener = nullptr; 735 FrameTreeNode* opener = nullptr;
719 if (opener_routing_id != MSG_ROUTING_NONE) { 736 if (opener_routing_id != MSG_ROUTING_NONE) {
720 RenderFrameHostImpl* opener_rfhi = RenderFrameHostImpl::FromID( 737 RenderFrameHostImpl* opener_rfhi = RenderFrameHostImpl::FromID(
721 source_site_instance->GetProcess()->GetID(), opener_routing_id); 738 source_site_instance->GetProcess()->GetID(), opener_routing_id);
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 // as browser-initiated navigations. NavigationRequests marked as 1033 // as browser-initiated navigations. NavigationRequests marked as
1017 // renderer-initiated are created by receiving a BeginNavigation IPC, and will 1034 // 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 1035 // then proceed in the same renderer that sent the IPC due to the condition
1019 // below. 1036 // below.
1020 // Subframe navigations will use the current renderer, unless 1037 // Subframe navigations will use the current renderer, unless
1021 // --site-per-process is enabled. 1038 // --site-per-process is enabled.
1022 // TODO(carlosk): Have renderer-initated main frame navigations swap processes 1039 // TODO(carlosk): Have renderer-initated main frame navigations swap processes
1023 // if needed when it no longer breaks OAuth popups (see 1040 // if needed when it no longer breaks OAuth popups (see
1024 // https://crbug.com/440266). 1041 // https://crbug.com/440266).
1025 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1042 bool is_main_frame = frame_tree_node_->IsMainFrame();
1043 bool notify_webui_of_rv_creation = false;
1026 if (current_site_instance == dest_site_instance.get() || 1044 if (current_site_instance == dest_site_instance.get() ||
1027 (!request.browser_initiated() && is_main_frame) || 1045 (!request.browser_initiated() && is_main_frame) ||
1028 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && 1046 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() &&
1029 !current_site_instance->RequiresDedicatedProcess())) { 1047 !current_site_instance->RequiresDedicatedProcess())) {
1030 // Reuse the current RFH if its SiteInstance matches the the navigation's 1048 // Reuse the current RenderFrameHost if its SiteInstance matches the
1031 // or if this is a subframe navigation. We only swap RFHs for subframes when 1049 // navigation's or if this is a subframe navigation. We only swap
1032 // --site-per-process is enabled. 1050 // RenderFrameHosts for subframes when --site-per-process is enabled.
1033 CleanUpNavigation(); 1051
1052 // GetFrameHostForNavigation will be called more than once during a
1053 // navigation (currently twice, on request and when it's about to commit in
1054 // the renderer). In the follow up calls an existing pending WebUI should
1055 // not be recreated if the URL didn't change. So instead of calling
1056 // CleanUpNavigation just discard the speculative RenderFrameHost if one
1057 // exists.
1058 if (speculative_render_frame_host_)
1059 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
1060
1061 UpdatePendingWebUIOnCurrentFrameHost(request.common_params().url,
1062 request.bindings());
1063
1034 navigation_rfh = render_frame_host_.get(); 1064 navigation_rfh = render_frame_host_.get();
1035 1065
1036 // As SiteInstances are the same, check if the WebUI should be reused. 1066 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 { 1067 } else {
1052 // If the SiteInstance for the final URL doesn't match the one from the 1068 // If the current RenderFrameHost cannot be used a speculative one is
1053 // speculatively created RenderFrameHost, create a new RenderFrameHost using 1069 // created with the SiteInstance for the current URL. If a speculative
1054 // this new SiteInstance. 1070 // RenderFrameHost already exists we try as much as possible to reuse it and
1071 // its associated WebUI.
1072
1073 // Check if an existing speculative RenderFrameHost can be reused.
1055 if (!speculative_render_frame_host_ || 1074 if (!speculative_render_frame_host_ ||
1056 speculative_render_frame_host_->GetSiteInstance() != 1075 speculative_render_frame_host_->GetSiteInstance() !=
1057 dest_site_instance.get()) { 1076 dest_site_instance.get()) {
1077 // If a previous speculative RenderFrameHost didn't exist or if its
1078 // SiteInstance differs from the one for the current URL, a new one needs
1079 // to be created.
1058 CleanUpNavigation(); 1080 CleanUpNavigation();
1059 bool success = CreateSpeculativeRenderFrameHost( 1081 bool success = CreateSpeculativeRenderFrameHost(current_site_instance,
1060 request.common_params().url, current_site_instance, 1082 dest_site_instance.get());
1061 dest_site_instance.get(), request.bindings());
1062 DCHECK(success); 1083 DCHECK(success);
1063 } 1084 }
1064 DCHECK(speculative_render_frame_host_); 1085 DCHECK(speculative_render_frame_host_);
1086
1087 bool changed_web_ui = speculative_render_frame_host_->UpdatePendingWebUI(
1088 request.common_params().url, request.bindings());
1089 speculative_render_frame_host_->CommitPendingWebUI();
1090 DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui());
1091 notify_webui_of_rv_creation =
1092 changed_web_ui && speculative_render_frame_host_->web_ui();
1093
1065 navigation_rfh = speculative_render_frame_host_.get(); 1094 navigation_rfh = speculative_render_frame_host_.get();
1066 1095
1067 // Check if our current RFH is live. 1096 // Check if our current RFH is live.
1068 if (!render_frame_host_->IsRenderFrameLive()) { 1097 if (!render_frame_host_->IsRenderFrameLive()) {
1069 // The current RFH is not live. There's no reason to sit around with a 1098 // 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 1099 // 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. 1100 // 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 1101 // (Note that we don't care about on{before}unload handlers if the current
1073 // RFH isn't live.) 1102 // RFH isn't live.)
1074 CommitPending(); 1103 CommitPending();
1075 } 1104 }
1076 } 1105 }
1077 DCHECK(navigation_rfh && 1106 DCHECK(navigation_rfh &&
1078 (navigation_rfh == render_frame_host_.get() || 1107 (navigation_rfh == render_frame_host_.get() ||
1079 navigation_rfh == speculative_render_frame_host_.get())); 1108 navigation_rfh == speculative_render_frame_host_.get()));
1080 1109
1081 // If the RenderFrame that needs to navigate is not live (its process was just 1110 // If the RenderFrame that needs to navigate is not live (its process was just
1082 // created or has crashed), initialize it. 1111 // created or has crashed), initialize it.
1083 if (!navigation_rfh->IsRenderFrameLive()) { 1112 if (!navigation_rfh->IsRenderFrameLive()) {
1084 // Recreate the opener chain. 1113 // Recreate the opener chain.
1085 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); 1114 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_);
1086 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) { 1115 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr))
1087 return nullptr; 1116 return nullptr;
1088 } 1117 notify_webui_of_rv_creation = true;
1089 1118
1090 if (navigation_rfh == render_frame_host_.get()) { 1119 if (navigation_rfh == render_frame_host_.get()) {
1091 // TODO(nasko): This is a very ugly hack. The Chrome extensions process 1120 // TODO(nasko): This is a very ugly hack. The Chrome extensions process
1092 // manager still uses NotificationService and expects to see a 1121 // manager still uses NotificationService and expects to see a
1093 // RenderViewHost changed notification after WebContents and 1122 // RenderViewHost changed notification after WebContents and
1094 // RenderFrameHostManager are completely initialized. This should be 1123 // RenderFrameHostManager are completely initialized. This should be
1095 // removed once the process manager moves away from NotificationService. 1124 // removed once the process manager moves away from NotificationService.
1096 // See https://crbug.com/462682. 1125 // See https://crbug.com/462682.
1097 delegate_->NotifyMainFrameSwappedFromRenderManager( 1126 delegate_->NotifyMainFrameSwappedFromRenderManager(
1098 nullptr, render_frame_host_->render_view_host()); 1127 nullptr, render_frame_host_->render_view_host());
1099 } 1128 }
1129 DCHECK(navigation_rfh->IsRenderFrameLive());
1100 } 1130 }
1101 1131
1132 // If a WebUI was created in a speculative RenderFrameHost or a new RenderView
1133 // was created then the WebUI never interacted with the RenderView. Notify
1134 // using RenderViewCreated.
1135 if (notify_webui_of_rv_creation && GetNavigatingWebUI())
1136 GetNavigatingWebUI()->RenderViewCreated(navigation_rfh->render_view_host());
1137
1102 return navigation_rfh; 1138 return navigation_rfh;
1103 } 1139 }
1104 1140
1105 // PlzNavigate 1141 // PlzNavigate
1106 void RenderFrameHostManager::CleanUpNavigation() { 1142 void RenderFrameHostManager::CleanUpNavigation() {
1107 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1143 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1108 switches::kEnableBrowserSideNavigation)); 1144 switches::kEnableBrowserSideNavigation));
1109 speculative_web_ui_.reset(); 1145 render_frame_host_->ClearPendingWebUI();
1110 should_reuse_web_ui_ = false;
1111 if (speculative_render_frame_host_) 1146 if (speculative_render_frame_host_)
1112 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); 1147 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
1113 } 1148 }
1114 1149
1115 // PlzNavigate 1150 // PlzNavigate
1116 scoped_ptr<RenderFrameHostImpl> 1151 scoped_ptr<RenderFrameHostImpl>
1117 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { 1152 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
1118 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1153 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1119 switches::kEnableBrowserSideNavigation)); 1154 switches::kEnableBrowserSideNavigation));
1120 speculative_render_frame_host_->GetProcess()->RemovePendingView(); 1155 speculative_render_frame_host_->GetProcess()->RemovePendingView();
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 // We can't switch a RenderView between view source and non-view source mode 1328 // 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 1329 // without screwing up the session history sometimes (when navigating between
1295 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat 1330 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
1296 // it as a new navigation). So require a BrowsingInstance switch. 1331 // it as a new navigation). So require a BrowsingInstance switch.
1297 if (current_is_view_source_mode != new_is_view_source_mode) 1332 if (current_is_view_source_mode != new_is_view_source_mode)
1298 return true; 1333 return true;
1299 1334
1300 return false; 1335 return false;
1301 } 1336 }
1302 1337
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( 1338 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
1316 const GURL& dest_url, 1339 const GURL& dest_url,
1317 SiteInstance* source_instance, 1340 SiteInstance* source_instance,
1318 SiteInstance* dest_instance, 1341 SiteInstance* dest_instance,
1319 SiteInstance* candidate_instance, 1342 SiteInstance* candidate_instance,
1320 ui::PageTransition transition, 1343 ui::PageTransition transition,
1321 bool dest_is_restore, 1344 bool dest_is_restore,
1322 bool dest_is_view_source_mode) { 1345 bool dest_is_view_source_mode) {
1323 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1346 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1324 1347
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1637 // The process for the new SiteInstance may (if we're sharing a process with 1660 // 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 1661 // another host that already initialized it) or may not (we have our own
1639 // process or the existing process crashed) have been initialized. Calling 1662 // process or the existing process crashed) have been initialized. Calling
1640 // Init multiple times will be ignored, so this is safe. 1663 // Init multiple times will be ignored, so this is safe.
1641 if (!new_instance->GetProcess()->Init()) 1664 if (!new_instance->GetProcess()->Init())
1642 return; 1665 return;
1643 1666
1644 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1667 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1645 1668
1646 // Create a non-swapped-out RFH with the given opener. 1669 // Create a non-swapped-out RFH with the given opener.
1647 pending_render_frame_host_ = CreateRenderFrame( 1670 pending_render_frame_host_ =
1648 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); 1671 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1649 } 1672 }
1650 1673
1651 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( 1674 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
1652 SiteInstance* old_instance, 1675 SiteInstance* old_instance,
1653 SiteInstance* new_instance) { 1676 SiteInstance* new_instance) {
1654 // Only create opener proxies if they are in the same BrowsingInstance. 1677 // Only create opener proxies if they are in the same BrowsingInstance.
1655 if (new_instance->IsRelatedSiteInstance(old_instance)) { 1678 if (new_instance->IsRelatedSiteInstance(old_instance)) {
1656 CreateOpenerProxies(new_instance, frame_tree_node_); 1679 CreateOpenerProxies(new_instance, frame_tree_node_);
1657 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { 1680 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
1658 // Ensure that the frame tree has RenderFrameProxyHosts for the 1681 // Ensure that the frame tree has RenderFrameProxyHosts for the
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1734 } 1757 }
1735 1758
1736 return RenderFrameHostFactory::Create( 1759 return RenderFrameHostFactory::Create(
1737 site_instance, render_view_host, render_frame_delegate_, 1760 site_instance, render_view_host, render_frame_delegate_,
1738 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, 1761 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
1739 widget_routing_id, flags); 1762 widget_routing_id, flags);
1740 } 1763 }
1741 1764
1742 // PlzNavigate 1765 // PlzNavigate
1743 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( 1766 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
1744 const GURL& url,
1745 SiteInstance* old_instance, 1767 SiteInstance* old_instance,
1746 SiteInstance* new_instance, 1768 SiteInstance* new_instance) {
1747 int bindings) {
1748 CHECK(new_instance); 1769 CHECK(new_instance);
1749 CHECK_NE(old_instance, new_instance); 1770 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 1771
1757 // The process for the new SiteInstance may (if we're sharing a process with 1772 // 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 1773 // another host that already initialized it) or may not (we have our own
1759 // process or the existing process crashed) have been initialized. Calling 1774 // process or the existing process crashed) have been initialized. Calling
1760 // Init multiple times will be ignored, so this is safe. 1775 // Init multiple times will be ignored, so this is safe.
1761 if (!new_instance->GetProcess()->Init()) 1776 if (!new_instance->GetProcess()->Init())
1762 return false; 1777 return false;
1763 1778
1764 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1779 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1765 1780
1766 int create_render_frame_flags = 0; 1781 int create_render_frame_flags = 0;
1767 if (delegate_->IsHidden()) 1782 if (delegate_->IsHidden())
1768 create_render_frame_flags |= CREATE_RF_HIDDEN; 1783 create_render_frame_flags |= CREATE_RF_HIDDEN;
1769 speculative_render_frame_host_ = 1784 speculative_render_frame_host_ =
1770 CreateRenderFrame(new_instance, speculative_web_ui_.get(), 1785 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1771 create_render_frame_flags, nullptr);
1772 1786
1773 if (!speculative_render_frame_host_) { 1787 return !!speculative_render_frame_host_;
1774 speculative_web_ui_.reset();
1775 return false;
1776 }
1777 return true;
1778 } 1788 }
1779 1789
1780 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( 1790 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
1781 SiteInstance* instance, 1791 SiteInstance* instance,
1782 WebUIImpl* web_ui,
1783 int flags, 1792 int flags,
1784 int* view_routing_id_ptr) { 1793 int* view_routing_id_ptr) {
1785 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1794 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1786 bool swapped_out_forbidden = 1795 bool swapped_out_forbidden =
1787 SiteIsolationPolicy::IsSwappedOutStateForbidden(); 1796 SiteIsolationPolicy::IsSwappedOutStateForbidden();
1788 1797
1789 CHECK(instance); 1798 CHECK(instance);
1790 CHECK(!swapped_out_forbidden || !swapped_out); 1799 CHECK(!swapped_out_forbidden || !swapped_out);
1791 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || 1800 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
1792 frame_tree_node_->IsMainFrame()); 1801 frame_tree_node_->IsMainFrame());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 success = InitRenderFrame(new_render_frame_host.get()); 1899 success = InitRenderFrame(new_render_frame_host.get());
1891 } 1900 }
1892 } 1901 }
1893 1902
1894 if (success) { 1903 if (success) {
1895 if (view_routing_id_ptr) 1904 if (view_routing_id_ptr)
1896 *view_routing_id_ptr = render_view_host->GetRoutingID(); 1905 *view_routing_id_ptr = render_view_host->GetRoutingID();
1897 } 1906 }
1898 } 1907 }
1899 1908
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. 1909 // Returns the new RFH if it isn't swapped out.
1916 if (success && !swapped_out) { 1910 if (success && !swapped_out) {
1917 DCHECK(new_render_frame_host->GetSiteInstance() == instance); 1911 DCHECK(new_render_frame_host->GetSiteInstance() == instance);
1918 return new_render_frame_host.Pass(); 1912 return new_render_frame_host.Pass();
1919 } 1913 }
1920 return nullptr; 1914 return nullptr;
1921 } 1915 }
1922 1916
1923 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { 1917 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
1924 // A RenderFrameProxyHost should never be created in the same SiteInstance as 1918 // A RenderFrameProxyHost should never be created in the same SiteInstance as
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2023 RenderFrameProxyHost* proxy) { 2017 RenderFrameProxyHost* proxy) {
2024 // Ensure the renderer process is initialized before creating the 2018 // Ensure the renderer process is initialized before creating the
2025 // RenderView. 2019 // RenderView.
2026 if (!render_view_host->GetProcess()->Init()) 2020 if (!render_view_host->GetProcess()->Init())
2027 return false; 2021 return false;
2028 2022
2029 // We may have initialized this RenderViewHost for another RenderFrameHost. 2023 // We may have initialized this RenderViewHost for another RenderFrameHost.
2030 if (render_view_host->IsRenderViewLive()) 2024 if (render_view_host->IsRenderViewLive())
2031 return true; 2025 return true;
2032 2026
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 = 2027 int opener_frame_routing_id =
2059 GetOpenerRoutingID(render_view_host->GetSiteInstance()); 2028 GetOpenerRoutingID(render_view_host->GetSiteInstance());
2060 2029
2061 bool created = delegate_->CreateRenderViewForRenderManager( 2030 bool created = delegate_->CreateRenderViewForRenderManager(
2062 render_view_host, opener_frame_routing_id, 2031 render_view_host, opener_frame_routing_id,
2063 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, 2032 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE,
2064 frame_tree_node_->current_replication_state()); 2033 frame_tree_node_->current_replication_state());
2065 2034
2066 if (created && proxy) 2035 if (created && proxy)
2067 proxy->set_render_frame_proxy_created(true); 2036 proxy->set_render_frame_proxy_created(true);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2136 !SiteIsolationPolicy::IsSwappedOutStateForbidden()) 2105 !SiteIsolationPolicy::IsSwappedOutStateForbidden())
2137 return pending_render_frame_host_->GetRoutingID(); 2106 return pending_render_frame_host_->GetRoutingID();
2138 2107
2139 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); 2108 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
2140 if (proxy) 2109 if (proxy)
2141 return proxy->GetRoutingID(); 2110 return proxy->GetRoutingID();
2142 2111
2143 return MSG_ROUTING_NONE; 2112 return MSG_ROUTING_NONE;
2144 } 2113 }
2145 2114
2115 void RenderFrameHostManager::CommitPendingWebUI() {
2116 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPendingWebUI",
2117 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2118 DCHECK(render_frame_host_->pending_web_ui());
2119
2120 // First check whether we're going to want to focus the location bar after
2121 // this commit. We do this now because the navigation hasn't formally
2122 // committed yet, so if we've already cleared the pending WebUI the call chain
2123 // this triggers won't be able to figure out what's going on.
2124 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
2125
2126 render_frame_host_->CommitPendingWebUI();
2127
2128 if (will_focus_location_bar)
2129 delegate_->SetFocusToLocationBar(false);
2130 }
2131
2146 void RenderFrameHostManager::CommitPending() { 2132 void RenderFrameHostManager::CommitPending() {
2147 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 2133 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
2148 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2134 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2149 bool browser_side_navigation = 2135 DCHECK(pending_render_frame_host_ || speculative_render_frame_host_);
2150 base::CommandLine::ForCurrentProcess()->HasSwitch(
2151 switches::kEnableBrowserSideNavigation);
2152 2136
2153 // First check whether we're going to want to focus the location bar after 2137 // 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 2138 // 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 2139 // 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. 2140 // this triggers won't be able to figure out what's going on.
2157 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 2141 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
2158 2142
2159 // Next commit the Web UI, if any. Either replace |web_ui_| with
2160 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
2161 // leave |web_ui_| as is if reusing it.
2162 DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_));
2163 if (pending_web_ui_ || speculative_web_ui_) {
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)
2186 delegate_->SetFocusToLocationBar(false);
2187 return;
2188 }
2189
2190 // Remember if the page was focused so we can focus the new renderer in 2143 // Remember if the page was focused so we can focus the new renderer in
2191 // that case. 2144 // that case.
2192 bool focus_render_view = !will_focus_location_bar && 2145 bool focus_render_view = !will_focus_location_bar &&
2193 render_frame_host_->GetView() && 2146 render_frame_host_->GetView() &&
2194 render_frame_host_->GetView()->HasFocus(); 2147 render_frame_host_->GetView()->HasFocus();
2195 2148
2196 bool is_main_frame = frame_tree_node_->IsMainFrame(); 2149 bool is_main_frame = frame_tree_node_->IsMainFrame();
2197 2150
2198 // Swap in the pending or speculative frame and make it active. Also ensure 2151 // Swap in the pending or speculative frame and make it active. Also ensure
2199 // the FrameTree stays in sync. 2152 // the FrameTree stays in sync.
2200 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; 2153 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
2201 if (!browser_side_navigation) { 2154 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
2155 switches::kEnableBrowserSideNavigation)) {
2202 DCHECK(!speculative_render_frame_host_); 2156 DCHECK(!speculative_render_frame_host_);
2203 old_render_frame_host = 2157 old_render_frame_host =
2204 SetRenderFrameHost(pending_render_frame_host_.Pass()); 2158 SetRenderFrameHost(pending_render_frame_host_.Pass());
2205 } else { 2159 } else {
2206 // PlzNavigate 2160 // PlzNavigate
2207 DCHECK(speculative_render_frame_host_); 2161 DCHECK(speculative_render_frame_host_);
2208 old_render_frame_host = 2162 old_render_frame_host =
2209 SetRenderFrameHost(speculative_render_frame_host_.Pass()); 2163 SetRenderFrameHost(speculative_render_frame_host_.Pass());
2210 } 2164 }
2211 2165
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2361 // If we are currently navigating cross-process, we want to get back to normal 2315 // If we are currently navigating cross-process, we want to get back to normal
2362 // and then navigate as usual. 2316 // and then navigate as usual.
2363 if (pending_render_frame_host_) 2317 if (pending_render_frame_host_)
2364 CancelPending(); 2318 CancelPending();
2365 2319
2366 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 2320 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
2367 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( 2321 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
2368 dest_url, source_instance, dest_instance, nullptr, transition, 2322 dest_url, source_instance, dest_instance, nullptr, transition,
2369 dest_is_restore, dest_is_view_source_mode); 2323 dest_is_restore, dest_is_view_source_mode);
2370 2324
2371 const NavigationEntry* current_entry =
2372 delegate_->GetLastCommittedNavigationEntryForRenderManager();
2373
2374 DCHECK(!pending_render_frame_host_); 2325 DCHECK(!pending_render_frame_host_);
2375 2326
2376 if (new_instance.get() != current_instance) { 2327 if (new_instance.get() != current_instance) {
2377 TRACE_EVENT_INSTANT2( 2328 TRACE_EVENT_INSTANT2(
2378 "navigation", 2329 "navigation",
2379 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 2330 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
2380 TRACE_EVENT_SCOPE_THREAD, 2331 TRACE_EVENT_SCOPE_THREAD,
2381 "current_instance id", current_instance->GetId(), 2332 "current_instance id", current_instance->GetId(),
2382 "new_instance id", new_instance->GetId()); 2333 "new_instance id", new_instance->GetId());
2383 2334
2384 // New SiteInstance: create a pending RFH to navigate. 2335 // New SiteInstance: create a pending RFH to navigate.
2385 2336
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()); 2337 CreatePendingRenderFrameHost(current_instance, new_instance.get());
2338 DCHECK(pending_render_frame_host_);
2394 if (!pending_render_frame_host_) 2339 if (!pending_render_frame_host_)
2395 return nullptr; 2340 return nullptr;
2396 2341
2342 pending_render_frame_host_->UpdatePendingWebUI(dest_url, bindings);
2343 pending_render_frame_host_->CommitPendingWebUI();
2344 DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui());
2345
2346 // If a WebUI exists in the pending RenderFrameHost it was just created, as
2347 // well as the RenderView, and they never interacted. So notify it using
2348 // RenderViewCreated.
2349 if (pending_render_frame_host_->web_ui()) {
2350 pending_render_frame_host_->web_ui()->RenderViewCreated(
2351 pending_render_frame_host_->render_view_host());
2352 }
2353
2397 // Check if our current RFH is live before we set up a transition. 2354 // Check if our current RFH is live before we set up a transition.
2398 if (!render_frame_host_->IsRenderFrameLive()) { 2355 if (!render_frame_host_->IsRenderFrameLive()) {
2399 // The current RFH is not live. There's no reason to sit around with a 2356 // 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 2357 // 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. 2358 // 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 2359 // (Note that we don't care about on{before}unload handlers if the current
2403 // RFH isn't live.) 2360 // RFH isn't live.)
2404 CommitPending(); 2361 CommitPending();
2405 return render_frame_host_.get(); 2362 return render_frame_host_.get();
2406 } 2363 }
2407 // Otherwise, it's safe to treat this as a pending cross-process transition. 2364 // Otherwise, it's safe to treat this as a pending cross-process transition.
2408 2365
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 2366 // 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). 2367 // 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 2368 // 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 2369 // Navigate message) until we hear back from the old renderer's
2416 // beforeunload handler. If the handler returns false, we'll have to 2370 // beforeunload handler. If the handler returns false, we'll have to
2417 // cancel the request. 2371 // cancel the request.
2418 //
2419 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 2372 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
2420 bool is_transfer = transferred_request_id != GlobalRequestID(); 2373 bool is_transfer = transferred_request_id != GlobalRequestID();
2421 if (is_transfer) { 2374 if (is_transfer) {
2422 // We don't need to stop the old renderer or run beforeunload/unload 2375 // We don't need to stop the old renderer or run beforeunload/unload
2423 // handlers, because those have already been done. 2376 // handlers, because those have already been done.
2424 DCHECK(cross_site_transferring_request_->request_id() == 2377 DCHECK(cross_site_transferring_request_->request_id() ==
2425 transferred_request_id); 2378 transferred_request_id);
2426 } else { 2379 } else {
2427 // Also make sure the old render view stops, in case a load is in 2380 // 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 2381 // progress. (We don't want to do this for transfers, since it will
(...skipping 14 matching lines...) Expand all
2443 2396
2444 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. 2397 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_.
2445 2398
2446 // It's possible to swap out the current RFH and then decide to navigate in it 2399 // 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 2400 // 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 2401 // 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 2402 // haven't deleted it yet. The new navigation will swap it back in, so we can
2450 // delete the proxy. 2403 // delete the proxy.
2451 proxy_hosts_->Remove(new_instance.get()->GetId()); 2404 proxy_hosts_->Remove(new_instance.get()->GetId());
2452 2405
2453 if (ShouldReuseWebUI(current_entry, dest_url)) { 2406 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 2407
2471 // The renderer can exit view source mode when any error or cancellation 2408 // The renderer can exit view source mode when any error or cancellation
2472 // happen. We must overwrite to recover the mode. 2409 // happen. We must overwrite to recover the mode.
2473 if (dest_is_view_source_mode) { 2410 if (dest_is_view_source_mode) {
2474 render_frame_host_->render_view_host()->Send( 2411 render_frame_host_->render_view_host()->Send(
2475 new ViewMsg_EnableViewSourceMode( 2412 new ViewMsg_EnableViewSourceMode(
2476 render_frame_host_->render_view_host()->GetRoutingID())); 2413 render_frame_host_->render_view_host()->GetRoutingID()));
2477 } 2414 }
2478 2415
2479 return render_frame_host_.get(); 2416 return render_frame_host_.get();
2480 } 2417 }
2481 2418
2419 void RenderFrameHostManager::UpdatePendingWebUIOnCurrentFrameHost(
2420 const GURL& dest_url,
2421 int entry_bindings) {
2422 bool pending_webui_changed =
2423 render_frame_host_->UpdatePendingWebUI(dest_url, entry_bindings);
2424 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->pending_web_ui());
2425
2426 if (render_frame_host_->pending_web_ui() && pending_webui_changed &&
2427 render_frame_host_->IsRenderFrameLive()) {
2428 // If a pending WebUI exists in the current RenderFrameHost and it has been
2429 // updated and the associated RenderFrame is alive, notify the WebUI about
2430 // the RenderView.
2431 // Note: If the RenderFrame is not alive at this point the notification will
2432 // happen later, when the RenderView is created.
2433 if (render_frame_host_->pending_web_ui() == render_frame_host_->web_ui()) {
2434 // If the active WebUI is being reused it has already interacting with
2435 // this RenderView in the past, so call RenderViewReused.
2436 render_frame_host_->pending_web_ui()->RenderViewReused(
2437 render_frame_host_->render_view_host(),
2438 frame_tree_node_->IsMainFrame());
2439 } else {
2440 // If this is a new WebUI it has never interacted with the existing
2441 // RenderView so call RenderViewCreated.
2442 render_frame_host_->pending_web_ui()->RenderViewCreated(
2443 render_frame_host_->render_view_host());
2444 }
2445 }
2446 }
2447
2482 void RenderFrameHostManager::CancelPending() { 2448 void RenderFrameHostManager::CancelPending() {
2483 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", 2449 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
2484 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2450 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2451 render_frame_host_->ClearPendingWebUI();
2485 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); 2452 DiscardUnusedFrame(UnsetPendingRenderFrameHost());
2486 } 2453 }
2487 2454
2488 scoped_ptr<RenderFrameHostImpl> 2455 scoped_ptr<RenderFrameHostImpl>
2489 RenderFrameHostManager::UnsetPendingRenderFrameHost() { 2456 RenderFrameHostManager::UnsetPendingRenderFrameHost() {
2490 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = 2457 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host =
2491 pending_render_frame_host_.Pass(); 2458 pending_render_frame_host_.Pass();
2492 2459
2493 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( 2460 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
2494 pending_render_frame_host.get(), 2461 pending_render_frame_host.get(),
2495 render_frame_host_.get()); 2462 render_frame_host_.get());
2496 2463
2497 // We no longer need to prevent the process from exiting. 2464 // We no longer need to prevent the process from exiting.
2498 pending_render_frame_host->GetProcess()->RemovePendingView(); 2465 pending_render_frame_host->GetProcess()->RemovePendingView();
2499 2466
2500 pending_web_ui_.reset();
2501 pending_and_current_web_ui_.reset();
2502
2503 return pending_render_frame_host.Pass(); 2467 return pending_render_frame_host.Pass();
2504 } 2468 }
2505 2469
2506 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( 2470 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
2507 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 2471 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
2508 // Swap the two. 2472 // Swap the two.
2509 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 2473 scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
2510 render_frame_host_.Pass(); 2474 render_frame_host_.Pass();
2511 render_frame_host_ = render_frame_host.Pass(); 2475 render_frame_host_ = render_frame_host.Pass();
2512 2476
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2667 if (rvh && !rvh->IsRenderViewLive()) { 2631 if (rvh && !rvh->IsRenderViewLive()) {
2668 EnsureRenderViewInitialized(rvh, instance); 2632 EnsureRenderViewInitialized(rvh, instance);
2669 } else { 2633 } else {
2670 // Create a swapped out RenderView in the given SiteInstance if none 2634 // 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 2635 // exists. Since an opener can point to a subframe, do this on the root
2672 // frame of the current opener's frame tree. 2636 // frame of the current opener's frame tree.
2673 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { 2637 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
2674 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); 2638 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
2675 } else { 2639 } else {
2676 frame_tree->root()->render_manager()->CreateRenderFrame( 2640 frame_tree->root()->render_manager()->CreateRenderFrame(
2677 instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, 2641 instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
2678 nullptr);
2679 } 2642 }
2680 } 2643 }
2681 } 2644 }
2682 } 2645 }
2683 2646
2684 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { 2647 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
2685 if (!frame_tree_node_->opener()) 2648 if (!frame_tree_node_->opener())
2686 return MSG_ROUTING_NONE; 2649 return MSG_ROUTING_NONE;
2687 2650
2688 return frame_tree_node_->opener() 2651 return frame_tree_node_->opener()
2689 ->render_manager() 2652 ->render_manager()
2690 ->GetRoutingIdForSiteInstance(instance); 2653 ->GetRoutingIdForSiteInstance(instance);
2691 } 2654 }
2692 2655
2693 } // namespace content 2656 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698