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

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

Issue 1352813006: Move WebUI ownership from the RenderFrameHostManager to the RenderFrameHost. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor changes to adress latest CR comments. Created 5 years, 1 month 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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 RenderViewHostDelegate* render_view_delegate, 211 RenderViewHostDelegate* render_view_delegate,
214 RenderWidgetHostDelegate* render_widget_delegate, 212 RenderWidgetHostDelegate* render_widget_delegate,
215 Delegate* delegate) 213 Delegate* delegate)
216 : frame_tree_node_(frame_tree_node), 214 : frame_tree_node_(frame_tree_node),
217 delegate_(delegate), 215 delegate_(delegate),
218 render_frame_delegate_(render_frame_delegate), 216 render_frame_delegate_(render_frame_delegate),
219 render_view_delegate_(render_view_delegate), 217 render_view_delegate_(render_view_delegate),
220 render_widget_delegate_(render_widget_delegate), 218 render_widget_delegate_(render_widget_delegate),
221 proxy_hosts_(new RenderFrameProxyHostMap(this)), 219 proxy_hosts_(new RenderFrameProxyHostMap(this)),
222 interstitial_page_(nullptr), 220 interstitial_page_(nullptr),
223 should_reuse_web_ui_(false), 221 current_web_ui_is_navigating_(false),
224 weak_factory_(this) { 222 weak_factory_(this) {
225 DCHECK(frame_tree_node_); 223 DCHECK(frame_tree_node_);
226 } 224 }
227 225
228 RenderFrameHostManager::~RenderFrameHostManager() { 226 RenderFrameHostManager::~RenderFrameHostManager() {
229 if (pending_render_frame_host_) { 227 if (pending_render_frame_host_) {
230 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost(); 228 scoped_ptr<RenderFrameHostImpl> relic = UnsetPendingRenderFrameHost();
231 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); 229 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get());
232 } 230 }
233 231
234 if (speculative_render_frame_host_) { 232 if (speculative_render_frame_host_) {
235 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost(); 233 scoped_ptr<RenderFrameHostImpl> relic = UnsetSpeculativeRenderFrameHost();
236 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get()); 234 ShutdownProxiesIfLastActiveFrameInSiteInstance(relic.get());
237 } 235 }
238 236
239 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get()); 237 ShutdownProxiesIfLastActiveFrameInSiteInstance(render_frame_host_.get());
240 238
241 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts. 239 // Delete any RenderFrameProxyHosts and swapped out RenderFrameHosts.
242 // It is important to delete those prior to deleting the current 240 // It is important to delete those prior to deleting the current
243 // RenderFrameHost, since the CrossProcessFrameConnector (owned by 241 // RenderFrameHost, since the CrossProcessFrameConnector (owned by
244 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with 242 // RenderFrameProxyHost) points to the RenderWidgetHostView associated with
245 // the current RenderFrameHost and uses it during its destructor. 243 // the current RenderFrameHost and uses it during its destructor.
246 ResetProxyHosts(); 244 ResetProxyHosts();
247 245
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. 246 // We should always have a current RenderFrameHost except in some tests.
253 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>()); 247 SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
254 } 248 }
255 249
256 void RenderFrameHostManager::Init(SiteInstance* site_instance, 250 void RenderFrameHostManager::Init(SiteInstance* site_instance,
257 int32 view_routing_id, 251 int32 view_routing_id,
258 int32 frame_routing_id, 252 int32 frame_routing_id,
259 int32 widget_routing_id) { 253 int32 widget_routing_id) {
260 DCHECK(site_instance); 254 DCHECK(site_instance);
261 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must 255 // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must
(...skipping 20 matching lines...) Expand all
282 return nullptr; 276 return nullptr;
283 return render_frame_host_->render_view_host(); 277 return render_frame_host_->render_view_host();
284 } 278 }
285 279
286 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { 280 RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const {
287 if (!pending_render_frame_host_) 281 if (!pending_render_frame_host_)
288 return nullptr; 282 return nullptr;
289 return pending_render_frame_host_->render_view_host(); 283 return pending_render_frame_host_->render_view_host();
290 } 284 }
291 285
286 WebUIImpl* RenderFrameHostManager::GetNavigatingWebUI() const {
287 if (current_web_ui_is_navigating_)
288 return render_frame_host_->web_ui();
289
290 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
291 switches::kEnableBrowserSideNavigation)) {
292 if (speculative_render_frame_host_)
293 return speculative_render_frame_host_->web_ui();
294 } else {
295 if (pending_render_frame_host_)
296 return pending_render_frame_host_->web_ui();
297 }
298 return nullptr;
299 }
300
292 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { 301 RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
293 if (interstitial_page_) 302 if (interstitial_page_)
294 return interstitial_page_->GetView(); 303 return interstitial_page_->GetView();
295 if (render_frame_host_) 304 if (render_frame_host_)
296 return render_frame_host_->GetView(); 305 return render_frame_host_->GetView();
297 return nullptr; 306 return nullptr;
298 } 307 }
299 308
300 bool RenderFrameHostManager::ForInnerDelegate() { 309 bool RenderFrameHostManager::ForInnerDelegate() {
301 return delegate_->GetOuterDelegateFrameTreeNodeID() != 310 return delegate_->GetOuterDelegateFrameTreeNodeID() !=
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 359
351 void RenderFrameHostManager::RemoveOuterDelegateFrame() { 360 void RenderFrameHostManager::RemoveOuterDelegateFrame() {
352 FrameTreeNode* outer_delegate_frame_tree_node = 361 FrameTreeNode* outer_delegate_frame_tree_node =
353 FrameTreeNode::GloballyFindByID( 362 FrameTreeNode::GloballyFindByID(
354 delegate_->GetOuterDelegateFrameTreeNodeID()); 363 delegate_->GetOuterDelegateFrameTreeNodeID());
355 DCHECK(outer_delegate_frame_tree_node->parent()); 364 DCHECK(outer_delegate_frame_tree_node->parent());
356 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( 365 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame(
357 outer_delegate_frame_tree_node); 366 outer_delegate_frame_tree_node);
358 } 367 }
359 368
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( 369 RenderFrameHostImpl* RenderFrameHostManager::Navigate(
382 const GURL& dest_url, 370 const GURL& dest_url,
383 const FrameNavigationEntry& frame_entry, 371 const FrameNavigationEntry& frame_entry,
384 const NavigationEntryImpl& entry) { 372 const NavigationEntryImpl& entry) {
385 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", 373 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate",
386 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 374 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
387 // Create a pending RenderFrameHost to use for the navigation. 375 // Create a pending RenderFrameHost to use for the navigation.
388 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( 376 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(
389 dest_url, 377 dest_url,
390 // TODO(creis): Move source_site_instance to FNE. 378 // 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 407 // site that is handled via Mojo, then Mojo WebUI code in //chrome will
420 // add a service to this RFH's ServiceRegistry). 408 // add a service to this RFH's ServiceRegistry).
421 dest_render_frame_host->SetUpMojoIfNeeded(); 409 dest_render_frame_host->SetUpMojoIfNeeded();
422 410
423 // Recreate the opener chain. 411 // Recreate the opener chain.
424 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), 412 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(),
425 frame_tree_node_); 413 frame_tree_node_);
426 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) 414 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr))
427 return nullptr; 415 return nullptr;
428 416
417 if (GetNavigatingWebUI()) {
418 GetNavigatingWebUI()->RenderViewCreated(
419 dest_render_frame_host->render_view_host());
420 }
421
429 // Now that we've created a new renderer, be sure to hide it if it isn't 422 // 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() 423 // our primary one. Otherwise, we might crash if we try to call Show()
431 // on it later. 424 // on it later.
432 if (dest_render_frame_host != render_frame_host_) { 425 if (dest_render_frame_host != render_frame_host_) {
433 if (dest_render_frame_host->GetView()) 426 if (dest_render_frame_host->GetView())
434 dest_render_frame_host->GetView()->Hide(); 427 dest_render_frame_host->GetView()->Hide();
435 } else { 428 } else {
436 // After a renderer crash we'd have marked the host as invisible, so we 429 // 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 430 // need to set the visibility of the new View to the correct value here
438 // after reload. 431 // after reload.
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 662
670 // Make sure any dynamic changes to this frame's sandbox flags that were made 663 // Make sure any dynamic changes to this frame's sandbox flags that were made
671 // prior to navigation take effect. 664 // prior to navigation take effect.
672 CommitPendingSandboxFlags(); 665 CommitPendingSandboxFlags();
673 } 666 }
674 667
675 void RenderFrameHostManager::CommitPendingIfNecessary( 668 void RenderFrameHostManager::CommitPendingIfNecessary(
676 RenderFrameHostImpl* render_frame_host, 669 RenderFrameHostImpl* render_frame_host,
677 bool was_caused_by_user_gesture) { 670 bool was_caused_by_user_gesture) {
678 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { 671 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
679 DCHECK(!should_reuse_web_ui_ || web_ui_); 672 DCHECK(!current_web_ui_is_navigating_ || render_frame_host_->web_ui());
680 673
681 // We should only hear this from our current renderer. 674 // We should only hear this from our current renderer.
682 DCHECK_EQ(render_frame_host_, render_frame_host); 675 DCHECK_EQ(render_frame_host_, render_frame_host);
683 676
684 // Even when there is no pending RVH, there may be a pending Web UI. 677 // A commit is required if there is a navigating WebUI, even without a
685 if (pending_web_ui() || speculative_web_ui_) 678 // pending or speculative RenderFrameHost.
679 if (GetNavigatingWebUI())
686 CommitPending(); 680 CommitPending();
687 return; 681 return;
688 } 682 }
689 683
690 if (render_frame_host == pending_render_frame_host_ || 684 if (render_frame_host == pending_render_frame_host_ ||
691 render_frame_host == speculative_render_frame_host_) { 685 render_frame_host == speculative_render_frame_host_) {
692 // The pending cross-process navigation completed, so show the renderer. 686 // The pending cross-process navigation completed, so show the renderer.
693 CommitPending(); 687 CommitPending();
694 } else if (render_frame_host == render_frame_host_) { 688 } else if (render_frame_host == render_frame_host_) {
695 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 689 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 // Subframe navigations will use the current renderer, unless 1012 // Subframe navigations will use the current renderer, unless
1019 // --site-per-process is enabled. 1013 // --site-per-process is enabled.
1020 // TODO(carlosk): Have renderer-initated main frame navigations swap processes 1014 // TODO(carlosk): Have renderer-initated main frame navigations swap processes
1021 // if needed when it no longer breaks OAuth popups (see 1015 // if needed when it no longer breaks OAuth popups (see
1022 // https://crbug.com/440266). 1016 // https://crbug.com/440266).
1023 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1017 bool is_main_frame = frame_tree_node_->IsMainFrame();
1024 if (current_site_instance == dest_site_instance.get() || 1018 if (current_site_instance == dest_site_instance.get() ||
1025 (!request.browser_initiated() && is_main_frame) || 1019 (!request.browser_initiated() && is_main_frame) ||
1026 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && 1020 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() &&
1027 !current_site_instance->RequiresDedicatedProcess())) { 1021 !current_site_instance->RequiresDedicatedProcess())) {
1028 // Reuse the current RFH if its SiteInstance matches the the navigation's 1022 // Reuse the current RenderFrameHost if its SiteInstance matches the the
1029 // or if this is a subframe navigation. We only swap RFHs for subframes when 1023 // navigation's or if this is a subframe navigation. We only swap RFHs for
1030 // --site-per-process is enabled. 1024 // subframes when --site-per-process is enabled.
1031 CleanUpNavigation(); 1025 CleanUpNavigation();
1032 navigation_rfh = render_frame_host_.get(); 1026 navigation_rfh = render_frame_host_.get();
1033 1027
1034 // As SiteInstances are the same, check if the WebUI should be reused. 1028 WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type();
1035 const NavigationEntry* current_navigation_entry = 1029 bool changed_web_ui = render_frame_host_->UpdateWebUI(
1036 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 1030 request.common_params().url, request.bindings());
1037 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, 1031
1038 request.common_params().url); 1032 // If a change in WebUI happened, check this is an acceptable case.
1039 if (!should_reuse_web_ui_) { 1033 CHECK(!changed_web_ui ||
1040 speculative_web_ui_ = CreateWebUI(request.common_params().url, 1034 (IsAcceptableWebUITransition(
1041 request.bindings()); 1035 previous_web_ui_type, request.common_params().url,
1042 // Make sure the current RenderViewHost has the right bindings. 1036 request.restore_type() != NavigationEntryImpl::RESTORE_NONE)));
1043 if (speculative_web_ui() && 1037
1044 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { 1038 // If there is a WebUI in the current RenderFrameHost, it will navigate.
1045 render_frame_host_->render_view_host()->AllowBindings( 1039 current_web_ui_is_navigating_ = !!render_frame_host_->web_ui();
1046 speculative_web_ui()->GetBindings()); 1040 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui());
1041
1042 // If the current RenderFrameHost has a WebUI and the associated RenderFrame
1043 // is alive, notify to the WebUI that the RenderView is being created or
1044 // reused depending on whether the WebUI was changed or not.
1045 if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) {
1046 if (changed_web_ui) {
1047 GetNavigatingWebUI()->RenderViewCreated(
1048 render_frame_host_->render_view_host());
1049 } else {
1050 GetNavigatingWebUI()->RenderViewReused(
1051 render_frame_host_->render_view_host(),
1052 frame_tree_node_->IsMainFrame());
1047 } 1053 }
1048 } 1054 }
1055
1056 DCHECK(!speculative_render_frame_host_);
1049 } else { 1057 } else {
1050 // If the SiteInstance for the final URL doesn't match the one from the 1058 // If the SiteInstance for the final URL doesn't match the one from the
1051 // speculatively created RenderFrameHost, create a new RenderFrameHost using 1059 // speculatively created RenderFrameHost, create a new RenderFrameHost using
1052 // this new SiteInstance. 1060 // this new SiteInstance.
1053 if (!speculative_render_frame_host_ || 1061 if (!speculative_render_frame_host_ ||
1054 speculative_render_frame_host_->GetSiteInstance() != 1062 speculative_render_frame_host_->GetSiteInstance() !=
1055 dest_site_instance.get()) { 1063 dest_site_instance.get()) {
1064 // Creates a new speculative RenderFrameHost if the previous one didn't
1065 // exist or if its SiteInstace differs from the current one.
1056 CleanUpNavigation(); 1066 CleanUpNavigation();
1057 bool success = CreateSpeculativeRenderFrameHost( 1067 bool success = CreateSpeculativeRenderFrameHost(current_site_instance,
1058 request.common_params().url, current_site_instance, 1068 dest_site_instance.get());
1059 dest_site_instance.get(), request.bindings());
1060 DCHECK(success); 1069 DCHECK(success);
1070
1071 speculative_render_frame_host_->UpdateWebUI(request.common_params().url,
1072 request.bindings());
1073 if (speculative_render_frame_host_->web_ui()) {
1074 speculative_render_frame_host_->web_ui()->RenderViewCreated(
1075 speculative_render_frame_host_->render_view_host());
1076 }
1077 } else {
1078 // Reuses the previous speculative RenderFrameHost.
1079 bool changed_web_ui = speculative_render_frame_host_->UpdateWebUI(
1080 request.common_params().url, request.bindings());
1081 if (changed_web_ui && speculative_render_frame_host_->web_ui()) {
1082 speculative_render_frame_host_->web_ui()->RenderViewCreated(
nasko 2015/11/04 17:16:10 The comment above says reuser, yet the call is to
carlosk 2015/11/04 21:43:59 We reuse the speculative RFH but if a new WebUI is
nasko 2015/11/05 00:36:38 Awesome!
1083 speculative_render_frame_host_->render_view_host());
1084 }
1061 } 1085 }
1062 DCHECK(speculative_render_frame_host_); 1086 DCHECK(speculative_render_frame_host_);
1087 DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui());
1088
1063 navigation_rfh = speculative_render_frame_host_.get(); 1089 navigation_rfh = speculative_render_frame_host_.get();
1064 1090
1065 // Check if our current RFH is live. 1091 // Check if our current RFH is live.
1066 if (!render_frame_host_->IsRenderFrameLive()) { 1092 if (!render_frame_host_->IsRenderFrameLive()) {
1067 // The current RFH is not live. There's no reason to sit around with a 1093 // The current RFH is not live. There's no reason to sit around with a
1068 // sad tab or a newly created RFH while we wait for the navigation to 1094 // sad tab or a newly created RFH while we wait for the navigation to
1069 // complete. Just switch to the speculative RFH now and go back to normal. 1095 // complete. Just switch to the speculative RFH now and go back to normal.
1070 // (Note that we don't care about on{before}unload handlers if the current 1096 // (Note that we don't care about on{before}unload handlers if the current
1071 // RFH isn't live.) 1097 // RFH isn't live.)
1072 CommitPending(); 1098 CommitPending();
1073 } 1099 }
1100 DCHECK(!current_web_ui_is_navigating_);
1074 } 1101 }
1075 DCHECK(navigation_rfh && 1102 DCHECK(navigation_rfh &&
1076 (navigation_rfh == render_frame_host_.get() || 1103 (navigation_rfh == render_frame_host_.get() ||
1077 navigation_rfh == speculative_render_frame_host_.get())); 1104 navigation_rfh == speculative_render_frame_host_.get()));
1078 1105
1079 // If the RenderFrame that needs to navigate is not live (its process was just 1106 // If the RenderFrame that needs to navigate is not live (its process was just
1080 // created or has crashed), initialize it. 1107 // created or has crashed), initialize it.
1081 if (!navigation_rfh->IsRenderFrameLive()) { 1108 if (!navigation_rfh->IsRenderFrameLive()) {
1082 // Recreate the opener chain. 1109 // Recreate the opener chain.
1083 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); 1110 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_);
1084 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) { 1111 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr))
1085 return nullptr; 1112 return nullptr;
1113
1114 if (GetNavigatingWebUI()) {
1115 GetNavigatingWebUI()->RenderViewCreated(
1116 navigation_rfh->render_view_host());
1086 } 1117 }
1087 1118
1088 if (navigation_rfh == render_frame_host_) { 1119 if (navigation_rfh == render_frame_host_) {
1089 // 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
1090 // manager still uses NotificationService and expects to see a 1121 // manager still uses NotificationService and expects to see a
1091 // RenderViewHost changed notification after WebContents and 1122 // RenderViewHost changed notification after WebContents and
1092 // RenderFrameHostManager are completely initialized. This should be 1123 // RenderFrameHostManager are completely initialized. This should be
1093 // removed once the process manager moves away from NotificationService. 1124 // removed once the process manager moves away from NotificationService.
1094 // See https://crbug.com/462682. 1125 // See https://crbug.com/462682.
1095 delegate_->NotifyMainFrameSwappedFromRenderManager( 1126 delegate_->NotifyMainFrameSwappedFromRenderManager(
1096 nullptr, render_frame_host_->render_view_host()); 1127 nullptr, render_frame_host_->render_view_host());
1097 } 1128 }
1098 } 1129 }
1099 1130
1100 return navigation_rfh; 1131 return navigation_rfh;
1101 } 1132 }
1102 1133
1103 // PlzNavigate 1134 // PlzNavigate
1104 void RenderFrameHostManager::CleanUpNavigation() { 1135 void RenderFrameHostManager::CleanUpNavigation() {
1105 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1136 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1106 switches::kEnableBrowserSideNavigation)); 1137 switches::kEnableBrowserSideNavigation));
1107 speculative_web_ui_.reset(); 1138 // TODO(carlosk): the discarding of the current RFH WebUI and the cleanup of
1108 should_reuse_web_ui_ = false; 1139 // the speculative RFH should not always happen together.
1140 current_web_ui_is_navigating_ = false;
1109 if (speculative_render_frame_host_) 1141 if (speculative_render_frame_host_)
1110 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); 1142 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
1111 } 1143 }
1112 1144
1113 // PlzNavigate 1145 // PlzNavigate
1114 scoped_ptr<RenderFrameHostImpl> 1146 scoped_ptr<RenderFrameHostImpl>
1115 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { 1147 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
1116 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1148 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1117 switches::kEnableBrowserSideNavigation)); 1149 switches::kEnableBrowserSideNavigation));
1118 speculative_render_frame_host_->GetProcess()->RemovePendingView(); 1150 speculative_render_frame_host_->GetProcess()->RemovePendingView();
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 // We can't switch a RenderView between view source and non-view source mode 1323 // We can't switch a RenderView between view source and non-view source mode
1292 // without screwing up the session history sometimes (when navigating between 1324 // without screwing up the session history sometimes (when navigating between
1293 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat 1325 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
1294 // it as a new navigation). So require a BrowsingInstance switch. 1326 // it as a new navigation). So require a BrowsingInstance switch.
1295 if (current_is_view_source_mode != new_is_view_source_mode) 1327 if (current_is_view_source_mode != new_is_view_source_mode)
1296 return true; 1328 return true;
1297 1329
1298 return false; 1330 return false;
1299 } 1331 }
1300 1332
1301 bool RenderFrameHostManager::ShouldReuseWebUI(
1302 const NavigationEntry* current_entry,
1303 const GURL& new_url) const {
1304 NavigationControllerImpl& controller =
1305 delegate_->GetControllerForRenderManager();
1306 return current_entry && web_ui_ &&
1307 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
1308 controller.GetBrowserContext(), current_entry->GetURL()) ==
1309 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
1310 controller.GetBrowserContext(), new_url));
1311 }
1312
1313 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( 1333 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
1314 const GURL& dest_url, 1334 const GURL& dest_url,
1315 SiteInstance* source_instance, 1335 SiteInstance* source_instance,
1316 SiteInstance* dest_instance, 1336 SiteInstance* dest_instance,
1317 SiteInstance* candidate_instance, 1337 SiteInstance* candidate_instance,
1318 ui::PageTransition transition, 1338 ui::PageTransition transition,
1319 bool dest_is_restore, 1339 bool dest_is_restore,
1320 bool dest_is_view_source_mode) { 1340 bool dest_is_view_source_mode) {
1321 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1341 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1322 1342
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 // The process for the new SiteInstance may (if we're sharing a process with 1655 // The process for the new SiteInstance may (if we're sharing a process with
1636 // another host that already initialized it) or may not (we have our own 1656 // another host that already initialized it) or may not (we have our own
1637 // process or the existing process crashed) have been initialized. Calling 1657 // process or the existing process crashed) have been initialized. Calling
1638 // Init multiple times will be ignored, so this is safe. 1658 // Init multiple times will be ignored, so this is safe.
1639 if (!new_instance->GetProcess()->Init()) 1659 if (!new_instance->GetProcess()->Init())
1640 return; 1660 return;
1641 1661
1642 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1662 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1643 1663
1644 // Create a non-swapped-out RFH with the given opener. 1664 // Create a non-swapped-out RFH with the given opener.
1645 pending_render_frame_host_ = CreateRenderFrame( 1665 pending_render_frame_host_ =
1646 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); 1666 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1647 } 1667 }
1648 1668
1649 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( 1669 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
1650 SiteInstance* old_instance, 1670 SiteInstance* old_instance,
1651 SiteInstance* new_instance) { 1671 SiteInstance* new_instance) {
1652 // Only create opener proxies if they are in the same BrowsingInstance. 1672 // Only create opener proxies if they are in the same BrowsingInstance.
1653 if (new_instance->IsRelatedSiteInstance(old_instance)) { 1673 if (new_instance->IsRelatedSiteInstance(old_instance)) {
1654 CreateOpenerProxies(new_instance, frame_tree_node_); 1674 CreateOpenerProxies(new_instance, frame_tree_node_);
1655 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { 1675 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
1656 // Ensure that the frame tree has RenderFrameProxyHosts for the 1676 // Ensure that the frame tree has RenderFrameProxyHosts for the
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 } 1752 }
1733 1753
1734 return RenderFrameHostFactory::Create( 1754 return RenderFrameHostFactory::Create(
1735 site_instance, render_view_host, render_frame_delegate_, 1755 site_instance, render_view_host, render_frame_delegate_,
1736 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, 1756 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
1737 widget_routing_id, flags); 1757 widget_routing_id, flags);
1738 } 1758 }
1739 1759
1740 // PlzNavigate 1760 // PlzNavigate
1741 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( 1761 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
1742 const GURL& url,
1743 SiteInstance* old_instance, 1762 SiteInstance* old_instance,
1744 SiteInstance* new_instance, 1763 SiteInstance* new_instance) {
1745 int bindings) {
1746 CHECK(new_instance); 1764 CHECK(new_instance);
1747 CHECK_NE(old_instance, new_instance); 1765 CHECK_NE(old_instance, new_instance);
1748 CHECK(!should_reuse_web_ui_); 1766 CHECK(!current_web_ui_is_navigating_);
1749
1750 // Note: |speculative_web_ui_| must be initialized before starting the
1751 // |speculative_render_frame_host_| creation steps otherwise the WebUI
1752 // won't be properly initialized.
1753 speculative_web_ui_ = CreateWebUI(url, bindings);
1754 1767
1755 // The process for the new SiteInstance may (if we're sharing a process with 1768 // The process for the new SiteInstance may (if we're sharing a process with
1756 // another host that already initialized it) or may not (we have our own 1769 // another host that already initialized it) or may not (we have our own
1757 // process or the existing process crashed) have been initialized. Calling 1770 // process or the existing process crashed) have been initialized. Calling
1758 // Init multiple times will be ignored, so this is safe. 1771 // Init multiple times will be ignored, so this is safe.
1759 if (!new_instance->GetProcess()->Init()) 1772 if (!new_instance->GetProcess()->Init())
1760 return false; 1773 return false;
1761 1774
1762 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1775 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1763 1776
1764 int create_render_frame_flags = 0; 1777 int create_render_frame_flags = 0;
1765 if (delegate_->IsHidden()) 1778 if (delegate_->IsHidden())
1766 create_render_frame_flags |= CREATE_RF_HIDDEN; 1779 create_render_frame_flags |= CREATE_RF_HIDDEN;
1767 speculative_render_frame_host_ = 1780 speculative_render_frame_host_ =
1768 CreateRenderFrame(new_instance, speculative_web_ui_.get(), 1781 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1769 create_render_frame_flags, nullptr);
1770 1782
1771 if (!speculative_render_frame_host_) { 1783 return !!speculative_render_frame_host_;
1772 speculative_web_ui_.reset();
1773 return false;
1774 }
1775 return true;
1776 } 1784 }
1777 1785
1778 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( 1786 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
1779 SiteInstance* instance, 1787 SiteInstance* instance,
1780 WebUIImpl* web_ui,
1781 int flags, 1788 int flags,
1782 int* view_routing_id_ptr) { 1789 int* view_routing_id_ptr) {
1783 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1790 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1784 bool swapped_out_forbidden = 1791 bool swapped_out_forbidden =
1785 SiteIsolationPolicy::IsSwappedOutStateForbidden(); 1792 SiteIsolationPolicy::IsSwappedOutStateForbidden();
1786 1793
1787 CHECK(instance); 1794 CHECK(instance);
1788 CHECK(!swapped_out_forbidden || !swapped_out); 1795 CHECK(!swapped_out_forbidden || !swapped_out);
1789 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || 1796 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
1790 frame_tree_node_->IsMainFrame()); 1797 frame_tree_node_->IsMainFrame());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 success = InitRenderFrame(new_render_frame_host.get()); 1895 success = InitRenderFrame(new_render_frame_host.get());
1889 } 1896 }
1890 } 1897 }
1891 1898
1892 if (success) { 1899 if (success) {
1893 if (view_routing_id_ptr) 1900 if (view_routing_id_ptr)
1894 *view_routing_id_ptr = render_view_host->GetRoutingID(); 1901 *view_routing_id_ptr = render_view_host->GetRoutingID();
1895 } 1902 }
1896 } 1903 }
1897 1904
1898 // When a new RenderView is created by the renderer process, the new
1899 // WebContents gets a RenderViewHost in the SiteInstance of its opener
1900 // WebContents. If not used in the first navigation, this RVH is swapped out
1901 // and is not granted bindings, so we may need to grant them when swapping it
1902 // in.
1903 if (web_ui && !new_render_frame_host->GetProcess()->IsForGuestsOnly()) {
1904 int required_bindings = web_ui->GetBindings();
1905 RenderViewHost* render_view_host =
1906 new_render_frame_host->render_view_host();
1907 if ((render_view_host->GetEnabledBindings() & required_bindings) !=
1908 required_bindings) {
1909 render_view_host->AllowBindings(required_bindings);
1910 }
1911 }
1912
1913 // Returns the new RFH if it isn't swapped out. 1905 // Returns the new RFH if it isn't swapped out.
1914 if (success && !swapped_out) { 1906 if (success && !swapped_out) {
1915 DCHECK(new_render_frame_host->GetSiteInstance() == instance); 1907 DCHECK(new_render_frame_host->GetSiteInstance() == instance);
1916 return new_render_frame_host.Pass(); 1908 return new_render_frame_host.Pass();
1917 } 1909 }
1918 return nullptr; 1910 return nullptr;
1919 } 1911 }
1920 1912
1921 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { 1913 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
1922 // A RenderFrameProxyHost should never be created in the same SiteInstance as 1914 // A RenderFrameProxyHost should never be created in the same SiteInstance as
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 RenderFrameProxyHost* proxy) { 2013 RenderFrameProxyHost* proxy) {
2022 // Ensure the renderer process is initialized before creating the 2014 // Ensure the renderer process is initialized before creating the
2023 // RenderView. 2015 // RenderView.
2024 if (!render_view_host->GetProcess()->Init()) 2016 if (!render_view_host->GetProcess()->Init())
2025 return false; 2017 return false;
2026 2018
2027 // We may have initialized this RenderViewHost for another RenderFrameHost. 2019 // We may have initialized this RenderViewHost for another RenderFrameHost.
2028 if (render_view_host->IsRenderViewLive()) 2020 if (render_view_host->IsRenderViewLive())
2029 return true; 2021 return true;
2030 2022
2031 // If |render_view_host| is not for a proxy and the navigation is to a WebUI,
2032 // and if the RenderView is not in a guest process, tell |render_view_host|
2033 // about any bindings it will need enabled.
2034 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850.
2035 WebUIImpl* dest_web_ui = nullptr;
2036 if (!proxy) {
2037 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2038 switches::kEnableBrowserSideNavigation)) {
2039 dest_web_ui =
2040 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
2041 } else {
2042 dest_web_ui = pending_web_ui();
2043 }
2044 }
2045 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) {
2046 render_view_host->AllowBindings(dest_web_ui->GetBindings());
2047 } else {
2048 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
2049 // process unless it's swapped out.
2050 if (render_view_host->is_active()) {
2051 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
2052 render_view_host->GetProcess()->GetID()));
2053 }
2054 }
2055
2056 int opener_frame_routing_id = 2023 int opener_frame_routing_id =
2057 GetOpenerRoutingID(render_view_host->GetSiteInstance()); 2024 GetOpenerRoutingID(render_view_host->GetSiteInstance());
2058 2025
2059 bool created = delegate_->CreateRenderViewForRenderManager( 2026 bool created = delegate_->CreateRenderViewForRenderManager(
2060 render_view_host, opener_frame_routing_id, 2027 render_view_host, opener_frame_routing_id,
2061 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, 2028 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE,
2062 frame_tree_node_->current_replication_state()); 2029 frame_tree_node_->current_replication_state());
2063 2030
2064 if (created && proxy) 2031 if (created && proxy)
2065 proxy->set_render_frame_proxy_created(true); 2032 proxy->set_render_frame_proxy_created(true);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2137 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); 2104 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
2138 if (proxy) 2105 if (proxy)
2139 return proxy->GetRoutingID(); 2106 return proxy->GetRoutingID();
2140 2107
2141 return MSG_ROUTING_NONE; 2108 return MSG_ROUTING_NONE;
2142 } 2109 }
2143 2110
2144 void RenderFrameHostManager::CommitPending() { 2111 void RenderFrameHostManager::CommitPending() {
2145 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 2112 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
2146 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2113 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2147 bool browser_side_navigation =
2148 base::CommandLine::ForCurrentProcess()->HasSwitch(
2149 switches::kEnableBrowserSideNavigation);
2150
2151 // First check whether we're going to want to focus the location bar after 2114 // First check whether we're going to want to focus the location bar after
2152 // this commit. We do this now because the navigation hasn't formally 2115 // this commit. We do this now because the navigation hasn't formally
2153 // committed yet, so if we've already cleared |pending_web_ui_| the call chain 2116 // committed yet, so if we've already cleared the pending WebUI the call chain
2154 // this triggers won't be able to figure out what's going on. 2117 // this triggers won't be able to figure out what's going on.
2155 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 2118 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
2156 2119
2157 // Next commit the Web UI, if any. Either replace |web_ui_| with
2158 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
2159 // leave |web_ui_| as is if reusing it.
2160 DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_));
2161 if (pending_web_ui_ || speculative_web_ui_) {
2162 DCHECK(!should_reuse_web_ui_);
2163 web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release()
2164 : pending_web_ui_.release());
2165 } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) {
2166 if (browser_side_navigation) {
2167 DCHECK(web_ui_);
2168 should_reuse_web_ui_ = false;
2169 } else {
2170 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
2171 pending_and_current_web_ui_.reset();
2172 }
2173 } else {
2174 web_ui_.reset();
2175 }
2176 DCHECK(!speculative_web_ui_);
2177 DCHECK(!should_reuse_web_ui_);
2178
2179 // It's possible for the pending_render_frame_host_ to be nullptr when we
2180 // aren't crossing process boundaries. If so, we just needed to handle the Web
2181 // UI committing above and we're done.
2182 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { 2120 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
2121 DCHECK_EQ(current_web_ui_is_navigating_, !!render_frame_host_->web_ui());
2122 current_web_ui_is_navigating_ = false;
2123 // If there's no pending/speculative RenderFrameHost then the current
2124 // RenderFrameHost is committing.
2183 if (will_focus_location_bar) 2125 if (will_focus_location_bar)
2184 delegate_->SetFocusToLocationBar(false); 2126 delegate_->SetFocusToLocationBar(false);
2185 return; 2127 return;
2186 } 2128 }
2187 2129
2188 // Remember if the page was focused so we can focus the new renderer in 2130 // Remember if the page was focused so we can focus the new renderer in
2189 // that case. 2131 // that case.
2190 bool focus_render_view = !will_focus_location_bar && 2132 bool focus_render_view = !will_focus_location_bar &&
2191 render_frame_host_->GetView() && 2133 render_frame_host_->GetView() &&
2192 render_frame_host_->GetView()->HasFocus(); 2134 render_frame_host_->GetView()->HasFocus();
2193 2135
2194 bool is_main_frame = frame_tree_node_->IsMainFrame(); 2136 bool is_main_frame = frame_tree_node_->IsMainFrame();
2195 2137
2196 // Swap in the pending or speculative frame and make it active. Also ensure 2138 // Swap in the pending or speculative frame and make it active. Also ensure
2197 // the FrameTree stays in sync. 2139 // the FrameTree stays in sync.
2198 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; 2140 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
2199 if (!browser_side_navigation) { 2141 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
2142 switches::kEnableBrowserSideNavigation)) {
2200 DCHECK(!speculative_render_frame_host_); 2143 DCHECK(!speculative_render_frame_host_);
2201 old_render_frame_host = 2144 old_render_frame_host =
2202 SetRenderFrameHost(pending_render_frame_host_.Pass()); 2145 SetRenderFrameHost(pending_render_frame_host_.Pass());
2203 } else { 2146 } else {
2204 // PlzNavigate 2147 // PlzNavigate
2205 DCHECK(speculative_render_frame_host_); 2148 DCHECK(speculative_render_frame_host_);
2206 old_render_frame_host = 2149 old_render_frame_host =
2207 SetRenderFrameHost(speculative_render_frame_host_.Pass()); 2150 SetRenderFrameHost(speculative_render_frame_host_.Pass());
2208 } 2151 }
2209 2152
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 // If we are currently navigating cross-process, we want to get back to normal 2302 // If we are currently navigating cross-process, we want to get back to normal
2360 // and then navigate as usual. 2303 // and then navigate as usual.
2361 if (pending_render_frame_host_) 2304 if (pending_render_frame_host_)
2362 CancelPending(); 2305 CancelPending();
2363 2306
2364 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 2307 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
2365 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( 2308 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
2366 dest_url, source_instance, dest_instance, nullptr, transition, 2309 dest_url, source_instance, dest_instance, nullptr, transition,
2367 dest_is_restore, dest_is_view_source_mode); 2310 dest_is_restore, dest_is_view_source_mode);
2368 2311
2369 const NavigationEntry* current_entry =
2370 delegate_->GetLastCommittedNavigationEntryForRenderManager();
2371
2372 DCHECK(!pending_render_frame_host_); 2312 DCHECK(!pending_render_frame_host_);
2373 2313
2374 if (new_instance.get() != current_instance) { 2314 if (new_instance.get() != current_instance) {
2375 TRACE_EVENT_INSTANT2( 2315 TRACE_EVENT_INSTANT2(
2376 "navigation", 2316 "navigation",
2377 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 2317 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
2378 TRACE_EVENT_SCOPE_THREAD, 2318 TRACE_EVENT_SCOPE_THREAD,
2379 "current_instance id", current_instance->GetId(), 2319 "current_instance id", current_instance->GetId(),
2380 "new_instance id", new_instance->GetId()); 2320 "new_instance id", new_instance->GetId());
2381 2321
2382 // New SiteInstance: create a pending RFH to navigate. 2322 // New SiteInstance: create a pending RFH to navigate.
2383 2323
2384 // This will possibly create (set to nullptr) a Web UI object for the 2324 current_web_ui_is_navigating_ = false;
2385 // pending page. We'll use this later to give the page special access. This
2386 // must happen before the new renderer is created below so it will get
2387 // bindings. It must also happen after the above conditional call to
2388 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
2389 // and the page will not have its bindings set appropriately.
2390 SetPendingWebUI(dest_url, bindings);
2391 CreatePendingRenderFrameHost(current_instance, new_instance.get()); 2325 CreatePendingRenderFrameHost(current_instance, new_instance.get());
2326 DCHECK(pending_render_frame_host_);
2392 if (!pending_render_frame_host_) 2327 if (!pending_render_frame_host_)
2393 return nullptr; 2328 return nullptr;
2394 2329
2330 pending_render_frame_host_->UpdateWebUI(dest_url, bindings);
2331 if (pending_render_frame_host_->web_ui()) {
2332 pending_render_frame_host_->web_ui()->RenderViewCreated(
2333 pending_render_frame_host_->render_view_host());
2334 }
2335
2336 // We now have a pending RFH and possibly an associated pending WebUI.
2337 DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui());
2338
2395 // Check if our current RFH is live before we set up a transition. 2339 // Check if our current RFH is live before we set up a transition.
2396 if (!render_frame_host_->IsRenderFrameLive()) { 2340 if (!render_frame_host_->IsRenderFrameLive()) {
2397 // The current RFH is not live. There's no reason to sit around with a 2341 // The current RFH is not live. There's no reason to sit around with a
2398 // sad tab or a newly created RFH while we wait for the pending RFH to 2342 // sad tab or a newly created RFH while we wait for the pending RFH to
2399 // navigate. Just switch to the pending RFH now and go back to normal. 2343 // navigate. Just switch to the pending RFH now and go back to normal.
2400 // (Note that we don't care about on{before}unload handlers if the current 2344 // (Note that we don't care about on{before}unload handlers if the current
2401 // RFH isn't live.) 2345 // RFH isn't live.)
2402 CommitPending(); 2346 CommitPending();
2403 return render_frame_host_.get(); 2347 return render_frame_host_.get();
2404 } 2348 }
2405 // Otherwise, it's safe to treat this as a pending cross-process transition. 2349 // Otherwise, it's safe to treat this as a pending cross-process transition.
2406 2350
2407 // We now have a pending RFH.
2408 DCHECK(pending_render_frame_host_);
2409
2410 // We need to wait until the beforeunload handler has run, unless we are 2351 // We need to wait until the beforeunload handler has run, unless we are
2411 // transferring an existing request (in which case it has already run). 2352 // transferring an existing request (in which case it has already run).
2412 // Suspend the new render view (i.e., don't let it send the cross-process 2353 // Suspend the new render view (i.e., don't let it send the cross-process
2413 // Navigate message) until we hear back from the old renderer's 2354 // Navigate message) until we hear back from the old renderer's
2414 // beforeunload handler. If the handler returns false, we'll have to 2355 // beforeunload handler. If the handler returns false, we'll have to
2415 // cancel the request. 2356 // cancel the request.
2416 //
2417 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 2357 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
2418 bool is_transfer = transferred_request_id != GlobalRequestID(); 2358 bool is_transfer = transferred_request_id != GlobalRequestID();
2419 if (is_transfer) { 2359 if (is_transfer) {
2420 // We don't need to stop the old renderer or run beforeunload/unload 2360 // We don't need to stop the old renderer or run beforeunload/unload
2421 // handlers, because those have already been done. 2361 // handlers, because those have already been done.
2422 DCHECK(cross_site_transferring_request_->request_id() == 2362 DCHECK(cross_site_transferring_request_->request_id() ==
2423 transferred_request_id); 2363 transferred_request_id);
2424 } else { 2364 } else {
2425 // Also make sure the old render view stops, in case a load is in 2365 // Also make sure the old render view stops, in case a load is in
2426 // progress. (We don't want to do this for transfers, since it will 2366 // progress. (We don't want to do this for transfers, since it will
(...skipping 14 matching lines...) Expand all
2441 2381
2442 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. 2382 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_.
2443 2383
2444 // It's possible to swap out the current RFH and then decide to navigate in it 2384 // It's possible to swap out the current RFH and then decide to navigate in it
2445 // anyway (e.g., a cross-process navigation that redirects back to the 2385 // anyway (e.g., a cross-process navigation that redirects back to the
2446 // original site). In that case, we have a proxy for the current RFH but 2386 // original site). In that case, we have a proxy for the current RFH but
2447 // haven't deleted it yet. The new navigation will swap it back in, so we can 2387 // haven't deleted it yet. The new navigation will swap it back in, so we can
2448 // delete the proxy. 2388 // delete the proxy.
2449 proxy_hosts_->Remove(new_instance.get()->GetId()); 2389 proxy_hosts_->Remove(new_instance.get()->GetId());
2450 2390
2451 if (ShouldReuseWebUI(current_entry, dest_url)) { 2391 WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type();
2452 pending_web_ui_.reset(); 2392 bool changed_web_ui = render_frame_host_->UpdateWebUI(dest_url, bindings);
2453 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); 2393
2454 } else { 2394 // If a change in WebUI happened, check this is an acceptable case.
2455 SetPendingWebUI(dest_url, bindings); 2395 CHECK(!changed_web_ui ||
2456 // Make sure the new RenderViewHost has the right bindings. 2396 IsAcceptableWebUITransition(previous_web_ui_type, dest_url,
2457 if (pending_web_ui() && 2397 dest_is_restore));
2458 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { 2398
2459 render_frame_host_->render_view_host()->AllowBindings( 2399 // If there is a WebUI in the current RenderFrameHost, it will navigate.
2460 pending_web_ui()->GetBindings()); 2400 current_web_ui_is_navigating_ = !!render_frame_host_->web_ui();
2401 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui());
2402
2403 // If the current RenderFrameHost has a WebUI and the associated RenderFrame
2404 // is alive, notify to the WebUI that the RenderView is being created or
2405 // reused depending on whether the WebUI was changed or not.
2406 if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) {
2407 if (changed_web_ui) {
2408 GetNavigatingWebUI()->RenderViewCreated(
2409 render_frame_host_->render_view_host());
2410 } else {
2411 GetNavigatingWebUI()->RenderViewReused(
2412 render_frame_host_->render_view_host(),
2413 frame_tree_node_->IsMainFrame());
nasko 2015/11/04 17:16:10 All of the new code here is very similar to the co
carlosk 2015/11/04 21:43:59 My first look at consolidating this made me choose
nasko 2015/11/05 00:36:38 Acknowledged.
2461 } 2414 }
2462 } 2415 }
2463 2416
2464 if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) {
2465 pending_web_ui()->RenderViewReused(render_frame_host_->render_view_host(),
2466 frame_tree_node_->IsMainFrame());
2467 }
2468
2469 // The renderer can exit view source mode when any error or cancellation 2417 // The renderer can exit view source mode when any error or cancellation
2470 // happen. We must overwrite to recover the mode. 2418 // happen. We must overwrite to recover the mode.
2471 if (dest_is_view_source_mode) { 2419 if (dest_is_view_source_mode) {
2472 render_frame_host_->render_view_host()->Send( 2420 render_frame_host_->render_view_host()->Send(
2473 new ViewMsg_EnableViewSourceMode( 2421 new ViewMsg_EnableViewSourceMode(
2474 render_frame_host_->render_view_host()->GetRoutingID())); 2422 render_frame_host_->render_view_host()->GetRoutingID()));
2475 } 2423 }
2476 2424
2477 return render_frame_host_.get(); 2425 return render_frame_host_.get();
2478 } 2426 }
2479 2427
2480 void RenderFrameHostManager::CancelPending() { 2428 void RenderFrameHostManager::CancelPending() {
2481 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", 2429 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
2482 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2430 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2431 current_web_ui_is_navigating_ = false;
2483 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); 2432 DiscardUnusedFrame(UnsetPendingRenderFrameHost());
2484 } 2433 }
2485 2434
2486 scoped_ptr<RenderFrameHostImpl> 2435 scoped_ptr<RenderFrameHostImpl>
2487 RenderFrameHostManager::UnsetPendingRenderFrameHost() { 2436 RenderFrameHostManager::UnsetPendingRenderFrameHost() {
2488 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = 2437 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host =
2489 pending_render_frame_host_.Pass(); 2438 pending_render_frame_host_.Pass();
2490 2439
2491 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( 2440 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
2492 pending_render_frame_host.get(), 2441 pending_render_frame_host.get(),
2493 render_frame_host_.get()); 2442 render_frame_host_.get());
2494 2443
2444 current_web_ui_is_navigating_ = false;
2445
2495 // We no longer need to prevent the process from exiting. 2446 // We no longer need to prevent the process from exiting.
2496 pending_render_frame_host->GetProcess()->RemovePendingView(); 2447 pending_render_frame_host->GetProcess()->RemovePendingView();
2497 2448
2498 pending_web_ui_.reset();
2499 pending_and_current_web_ui_.reset();
2500
2501 return pending_render_frame_host.Pass(); 2449 return pending_render_frame_host.Pass();
2502 } 2450 }
2503 2451
2504 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( 2452 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
2505 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 2453 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
2506 // Swap the two. 2454 // Swap the two.
2507 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 2455 scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
2508 render_frame_host_.Pass(); 2456 render_frame_host_.Pass();
2509 render_frame_host_ = render_frame_host.Pass(); 2457 render_frame_host_ = render_frame_host.Pass();
2510 2458
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2665 if (rvh && !rvh->IsRenderViewLive()) { 2613 if (rvh && !rvh->IsRenderViewLive()) {
2666 EnsureRenderViewInitialized(rvh, instance); 2614 EnsureRenderViewInitialized(rvh, instance);
2667 } else { 2615 } else {
2668 // Create a swapped out RenderView in the given SiteInstance if none 2616 // Create a swapped out RenderView in the given SiteInstance if none
2669 // exists. Since an opener can point to a subframe, do this on the root 2617 // exists. Since an opener can point to a subframe, do this on the root
2670 // frame of the current opener's frame tree. 2618 // frame of the current opener's frame tree.
2671 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { 2619 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
2672 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); 2620 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
2673 } else { 2621 } else {
2674 frame_tree->root()->render_manager()->CreateRenderFrame( 2622 frame_tree->root()->render_manager()->CreateRenderFrame(
2675 instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, 2623 instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
2676 nullptr);
2677 } 2624 }
2678 } 2625 }
2679 } 2626 }
2680 } 2627 }
2681 2628
2682 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { 2629 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
2683 if (!frame_tree_node_->opener()) 2630 if (!frame_tree_node_->opener())
2684 return MSG_ROUTING_NONE; 2631 return MSG_ROUTING_NONE;
2685 2632
2686 return frame_tree_node_->opener() 2633 return frame_tree_node_->opener()
2687 ->render_manager() 2634 ->render_manager()
2688 ->GetRoutingIdForSiteInstance(instance); 2635 ->GetRoutingIdForSiteInstance(instance);
2689 } 2636 }
2690 2637
2638 bool RenderFrameHostManager::IsAcceptableWebUITransition(
2639 WebUI::TypeID previous_web_ui_type,
2640 const GURL& dest_url,
2641 bool dest_is_restore) {
2642 // There are a few navigation cases that allow for changes to the WebUI of
2643 // the current RenderFrameHost.
2644 BrowserContext* browser_context =
2645 delegate_->GetControllerForRenderManager().GetBrowserContext();
2646 if (render_frame_host_->web_ui()) {
2647 // Switching WebUI from one type to another is never acceptable.
nasko 2015/11/04 17:16:10 It is acceptable, as long as we change RFHs, right
carlosk 2015/11/04 21:43:59 This method only cares about WebUI transitions on
nasko 2015/11/05 00:36:38 Let's clarify it in the comment then. Appending "
carlosk 2015/11/05 13:19:06 Done.
2648 DCHECK(previous_web_ui_type == WebUI::kNoWebUI);
2649
2650 // Going from not having to having a WebUI is acceptable for:
2651 // - The first navigation of this frame.
2652 const NavigationEntry* current_entry =
2653 delegate_->GetLastCommittedNavigationEntryForRenderManager();
2654 bool is_first_navigation_for_frame = !current_entry;
2655 // - A restore navigation to a WebUI URL.
nasko 2015/11/04 17:16:10 Let's leave an empty line between the different ca
carlosk 2015/11/04 21:43:59 Done.
2656 const GURL& current_effective_url =
2657 current_entry ? SiteInstanceImpl::GetEffectiveURL(
2658 browser_context, current_entry->GetURL())
2659 : render_frame_host_->GetSiteInstance()->GetSiteURL();
2660 bool is_webui_restore =
2661 dest_is_restore &&
2662 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
2663 browser_context, current_effective_url);
2664 // - Navigating back from a special renderer controlled URL.
nasko 2015/11/04 17:16:10 Let's drop the "controlled" word and just have it
carlosk 2015/11/04 21:43:59 Done.
2665 bool is_back_from_renderer_url =
2666 current_entry && IsRendererDebugURL(current_entry->GetURL());
2667 // - Navigating in webview tag guest.
2668 bool is_webview_tag_guest =
2669 render_frame_host_->GetSiteInstance()->GetSiteURL().SchemeIs(
2670 kGuestScheme);
2671 DCHECK(is_first_navigation_for_frame || is_webui_restore ||
2672 is_back_from_renderer_url || is_webview_tag_guest);
2673 } else {
2674 // Going from having to not having a WebUI is acceptable for:
2675 // - Navigating to a special, renderer controlled URL.
nasko 2015/11/04 17:16:10 Same comment as above.
carlosk 2015/11/04 21:43:59 Done.
2676 DCHECK(IsRendererDebugURL(
2677 SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url)));
2678 }
2679 return true;
nasko 2015/11/04 17:16:10 So this method always returns true? Why is it then
carlosk 2015/11/04 21:43:59 This made sense then these were called from inside
nasko 2015/11/05 00:36:38 Cool!
2680 }
2681
2691 } // namespace content 2682 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698