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

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: Fixed header 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 353
345 void RenderFrameHostManager::RemoveOuterDelegateFrame() { 354 void RenderFrameHostManager::RemoveOuterDelegateFrame() {
346 FrameTreeNode* outer_delegate_frame_tree_node = 355 FrameTreeNode* outer_delegate_frame_tree_node =
347 FrameTreeNode::GloballyFindByID( 356 FrameTreeNode::GloballyFindByID(
348 delegate_->GetOuterDelegateFrameTreeNodeID()); 357 delegate_->GetOuterDelegateFrameTreeNodeID());
349 DCHECK(outer_delegate_frame_tree_node->parent()); 358 DCHECK(outer_delegate_frame_tree_node->parent());
350 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame( 359 outer_delegate_frame_tree_node->frame_tree()->RemoveFrame(
351 outer_delegate_frame_tree_node); 360 outer_delegate_frame_tree_node);
352 } 361 }
353 362
354 void RenderFrameHostManager::SetPendingWebUI(const GURL& url, int bindings) {
355 pending_web_ui_ = CreateWebUI(url, bindings);
356 pending_and_current_web_ui_.reset();
357 }
358
359 scoped_ptr<WebUIImpl> RenderFrameHostManager::CreateWebUI(const GURL& url,
360 int bindings) {
361 scoped_ptr<WebUIImpl> new_web_ui(delegate_->CreateWebUIForRenderManager(url));
362
363 // If we have assigned (zero or more) bindings to this NavigationEntry in the
364 // past, make sure we're not granting it different bindings than it had
365 // before. If so, note it and don't give it any bindings, to avoid a
366 // potential privilege escalation.
367 if (new_web_ui && bindings != NavigationEntryImpl::kInvalidBindings &&
368 new_web_ui->GetBindings() != bindings) {
369 RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
370 return nullptr;
371 }
372 return new_web_ui.Pass();
373 }
374
375 RenderFrameHostImpl* RenderFrameHostManager::Navigate( 363 RenderFrameHostImpl* RenderFrameHostManager::Navigate(
376 const GURL& dest_url, 364 const GURL& dest_url,
377 const FrameNavigationEntry& frame_entry, 365 const FrameNavigationEntry& frame_entry,
378 const NavigationEntryImpl& entry) { 366 const NavigationEntryImpl& entry) {
379 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate", 367 TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate",
380 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 368 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
381 // Create a pending RenderFrameHost to use for the navigation. 369 // Create a pending RenderFrameHost to use for the navigation.
382 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate( 370 RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(
383 dest_url, 371 dest_url,
384 // TODO(creis): Move source_site_instance to FNE. 372 // TODO(creis): Move source_site_instance to FNE.
(...skipping 28 matching lines...) Expand all
413 // site that is handled via Mojo, then Mojo WebUI code in //chrome will 401 // site that is handled via Mojo, then Mojo WebUI code in //chrome will
414 // add a service to this RFH's ServiceRegistry). 402 // add a service to this RFH's ServiceRegistry).
415 dest_render_frame_host->SetUpMojoIfNeeded(); 403 dest_render_frame_host->SetUpMojoIfNeeded();
416 404
417 // Recreate the opener chain. 405 // Recreate the opener chain.
418 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(), 406 CreateOpenerProxies(dest_render_frame_host->GetSiteInstance(),
419 frame_tree_node_); 407 frame_tree_node_);
420 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr)) 408 if (!InitRenderView(dest_render_frame_host->render_view_host(), nullptr))
421 return nullptr; 409 return nullptr;
422 410
411 if (GetNavigatingWebUI()) {
412 GetNavigatingWebUI()->RenderViewCreated(
413 dest_render_frame_host->render_view_host());
414 }
415
423 // Now that we've created a new renderer, be sure to hide it if it isn't 416 // Now that we've created a new renderer, be sure to hide it if it isn't
424 // our primary one. Otherwise, we might crash if we try to call Show() 417 // our primary one. Otherwise, we might crash if we try to call Show()
425 // on it later. 418 // on it later.
426 if (dest_render_frame_host != render_frame_host_) { 419 if (dest_render_frame_host != render_frame_host_) {
427 if (dest_render_frame_host->GetView()) 420 if (dest_render_frame_host->GetView())
428 dest_render_frame_host->GetView()->Hide(); 421 dest_render_frame_host->GetView()->Hide();
429 } else { 422 } else {
430 // After a renderer crash we'd have marked the host as invisible, so we 423 // After a renderer crash we'd have marked the host as invisible, so we
431 // need to set the visibility of the new View to the correct value here 424 // need to set the visibility of the new View to the correct value here
432 // after reload. 425 // after reload.
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 656
664 // Make sure any dynamic changes to this frame's sandbox flags that were made 657 // Make sure any dynamic changes to this frame's sandbox flags that were made
665 // prior to navigation take effect. 658 // prior to navigation take effect.
666 CommitPendingSandboxFlags(); 659 CommitPendingSandboxFlags();
667 } 660 }
668 661
669 void RenderFrameHostManager::CommitPendingIfNecessary( 662 void RenderFrameHostManager::CommitPendingIfNecessary(
670 RenderFrameHostImpl* render_frame_host, 663 RenderFrameHostImpl* render_frame_host,
671 bool was_caused_by_user_gesture) { 664 bool was_caused_by_user_gesture) {
672 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { 665 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
673 DCHECK(!should_reuse_web_ui_ || web_ui_); 666 DCHECK(!current_web_ui_is_navigating_ || render_frame_host_->web_ui());
674 667
675 // We should only hear this from our current renderer. 668 // We should only hear this from our current renderer.
676 DCHECK_EQ(render_frame_host_, render_frame_host); 669 DCHECK_EQ(render_frame_host_, render_frame_host);
677 670
678 // Even when there is no pending RVH, there may be a pending Web UI. 671 // Even when there is no pending RVH, there may be a pending Web UI.
nasko 2015/11/02 17:00:36 This comment doesn't make as much sense with your
carlosk 2015/11/03 09:50:30 Done.
679 if (pending_web_ui() || speculative_web_ui_) 672 if (GetNavigatingWebUI())
680 CommitPending(); 673 CommitPending();
681 return; 674 return;
682 } 675 }
683 676
684 if (render_frame_host == pending_render_frame_host_ || 677 if (render_frame_host == pending_render_frame_host_ ||
685 render_frame_host == speculative_render_frame_host_) { 678 render_frame_host == speculative_render_frame_host_) {
686 // The pending cross-process navigation completed, so show the renderer. 679 // The pending cross-process navigation completed, so show the renderer.
687 CommitPending(); 680 CommitPending();
688 } else if (render_frame_host == render_frame_host_) { 681 } else if (render_frame_host == render_frame_host_) {
689 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 682 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 // Subframe navigations will use the current renderer, unless 1005 // Subframe navigations will use the current renderer, unless
1013 // --site-per-process is enabled. 1006 // --site-per-process is enabled.
1014 // TODO(carlosk): Have renderer-initated main frame navigations swap processes 1007 // TODO(carlosk): Have renderer-initated main frame navigations swap processes
1015 // if needed when it no longer breaks OAuth popups (see 1008 // if needed when it no longer breaks OAuth popups (see
1016 // https://crbug.com/440266). 1009 // https://crbug.com/440266).
1017 bool is_main_frame = frame_tree_node_->IsMainFrame(); 1010 bool is_main_frame = frame_tree_node_->IsMainFrame();
1018 if (current_site_instance == dest_site_instance.get() || 1011 if (current_site_instance == dest_site_instance.get() ||
1019 (!request.browser_initiated() && is_main_frame) || 1012 (!request.browser_initiated() && is_main_frame) ||
1020 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() && 1013 (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() &&
1021 !current_site_instance->RequiresDedicatedProcess())) { 1014 !current_site_instance->RequiresDedicatedProcess())) {
1022 // Reuse the current RFH if its SiteInstance matches the the navigation's 1015 // Reuse the current RenderFrameHost if its SiteInstance matches the the
1023 // or if this is a subframe navigation. We only swap RFHs for subframes when 1016 // navigation's or if this is a subframe navigation. We only swap RFHs for
1024 // --site-per-process is enabled. 1017 // subframes when --site-per-process is enabled.
1025 CleanUpNavigation(); 1018 CleanUpNavigation();
1026 navigation_rfh = render_frame_host_.get(); 1019 navigation_rfh = render_frame_host_.get();
1027 1020
1028 // As SiteInstances are the same, check if the WebUI should be reused. 1021 WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type();
1029 const NavigationEntry* current_navigation_entry = 1022 bool changed_web_ui = render_frame_host_->UpdateWebUI(
1030 delegate_->GetLastCommittedNavigationEntryForRenderManager(); 1023 request.common_params().url, request.bindings());
1031 should_reuse_web_ui_ = ShouldReuseWebUI(current_navigation_entry, 1024
1032 request.common_params().url); 1025 // If a change in WebUI happened, check this is an acceptable case.
1033 if (!should_reuse_web_ui_) { 1026 DCHECK(!changed_web_ui ||
1034 speculative_web_ui_ = CreateWebUI(request.common_params().url, 1027 (IsAcceptableWebUITransition(
1035 request.bindings()); 1028 previous_web_ui_type, request.common_params().url,
1036 // Make sure the current RenderViewHost has the right bindings. 1029 request.restore_type() != NavigationEntryImpl::RESTORE_NONE)));
1037 if (speculative_web_ui() && 1030
1038 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { 1031 // If there is a WebUI in the current RenderFrameHost, it will navigate.
1039 render_frame_host_->render_view_host()->AllowBindings( 1032 current_web_ui_is_navigating_ = !!render_frame_host_->web_ui();
1040 speculative_web_ui()->GetBindings()); 1033 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui());
1034
1035 // If the current RenderFrameHost has a WebUI and the associated RenderFrame
1036 // is alive, notify to the WebUI that the RenderView is being created or
1037 // reused depending on whether the WebUI was changed or not.
1038 if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) {
1039 if (changed_web_ui) {
1040 GetNavigatingWebUI()->RenderViewCreated(
1041 render_frame_host_->render_view_host());
1042 } else {
1043 GetNavigatingWebUI()->RenderViewReused(
1044 render_frame_host_->render_view_host(),
1045 frame_tree_node_->IsMainFrame());
1041 } 1046 }
1042 } 1047 }
1048
1049 DCHECK(!speculative_render_frame_host_);
1043 } else { 1050 } else {
1044 // If the SiteInstance for the final URL doesn't match the one from the 1051 // If the SiteInstance for the final URL doesn't match the one from the
1045 // speculatively created RenderFrameHost, create a new RenderFrameHost using 1052 // speculatively created RenderFrameHost, create a new RenderFrameHost using
1046 // this new SiteInstance. 1053 // this new SiteInstance.
1047 if (!speculative_render_frame_host_ || 1054 if (!speculative_render_frame_host_ ||
1048 speculative_render_frame_host_->GetSiteInstance() != 1055 speculative_render_frame_host_->GetSiteInstance() !=
1049 dest_site_instance.get()) { 1056 dest_site_instance.get()) {
1057 // Creates a new speculative RenderFrameHost if the previous one didn't
1058 // exist or if its SiteInstace differs from the current one.
1050 CleanUpNavigation(); 1059 CleanUpNavigation();
1051 bool success = CreateSpeculativeRenderFrameHost( 1060 bool success = CreateSpeculativeRenderFrameHost(current_site_instance,
1052 request.common_params().url, current_site_instance, 1061 dest_site_instance.get());
1053 dest_site_instance.get(), request.bindings());
1054 DCHECK(success); 1062 DCHECK(success);
1063
1064 speculative_render_frame_host_->UpdateWebUI(request.common_params().url,
1065 request.bindings());
1066 if (speculative_render_frame_host_->web_ui()) {
1067 speculative_render_frame_host_->web_ui()->RenderViewCreated(
1068 speculative_render_frame_host_->render_view_host());
1069 }
1070 } else {
1071 // Reuses the previous speculative RenderFrameHost.
1072 bool changed_web_ui = speculative_render_frame_host_->UpdateWebUI(
1073 request.common_params().url, request.bindings());
1074 if (changed_web_ui && speculative_render_frame_host_->web_ui()) {
1075 speculative_render_frame_host_->web_ui()->RenderViewCreated(
1076 speculative_render_frame_host_->render_view_host());
1077 }
1055 } 1078 }
1056 DCHECK(speculative_render_frame_host_); 1079 DCHECK(speculative_render_frame_host_);
1080 DCHECK_EQ(GetNavigatingWebUI(), speculative_render_frame_host_->web_ui());
1081
1057 navigation_rfh = speculative_render_frame_host_.get(); 1082 navigation_rfh = speculative_render_frame_host_.get();
1058 1083
1059 // Check if our current RFH is live. 1084 // Check if our current RFH is live.
1060 if (!render_frame_host_->IsRenderFrameLive()) { 1085 if (!render_frame_host_->IsRenderFrameLive()) {
1061 // The current RFH is not live. There's no reason to sit around with a 1086 // The current RFH is not live. There's no reason to sit around with a
1062 // sad tab or a newly created RFH while we wait for the navigation to 1087 // sad tab or a newly created RFH while we wait for the navigation to
1063 // complete. Just switch to the speculative RFH now and go back to normal. 1088 // complete. Just switch to the speculative RFH now and go back to normal.
1064 // (Note that we don't care about on{before}unload handlers if the current 1089 // (Note that we don't care about on{before}unload handlers if the current
1065 // RFH isn't live.) 1090 // RFH isn't live.)
1066 CommitPending(); 1091 CommitPending();
1067 } 1092 }
1093 DCHECK(!current_web_ui_is_navigating_);
1068 } 1094 }
1069 DCHECK(navigation_rfh && 1095 DCHECK(navigation_rfh &&
1070 (navigation_rfh == render_frame_host_.get() || 1096 (navigation_rfh == render_frame_host_.get() ||
1071 navigation_rfh == speculative_render_frame_host_.get())); 1097 navigation_rfh == speculative_render_frame_host_.get()));
1072 1098
1073 // If the RenderFrame that needs to navigate is not live (its process was just 1099 // If the RenderFrame that needs to navigate is not live (its process was just
1074 // created or has crashed), initialize it. 1100 // created or has crashed), initialize it.
1075 if (!navigation_rfh->IsRenderFrameLive()) { 1101 if (!navigation_rfh->IsRenderFrameLive()) {
1076 // Recreate the opener chain. 1102 // Recreate the opener chain.
1077 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_); 1103 CreateOpenerProxies(navigation_rfh->GetSiteInstance(), frame_tree_node_);
1078 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr)) { 1104 if (!InitRenderView(navigation_rfh->render_view_host(), nullptr))
1079 return nullptr; 1105 return nullptr;
1106
1107 if (GetNavigatingWebUI()) {
1108 GetNavigatingWebUI()->RenderViewCreated(
1109 navigation_rfh->render_view_host());
1080 } 1110 }
1081 1111
1082 if (navigation_rfh == render_frame_host_) { 1112 if (navigation_rfh == render_frame_host_) {
1083 // TODO(nasko): This is a very ugly hack. The Chrome extensions process 1113 // TODO(nasko): This is a very ugly hack. The Chrome extensions process
1084 // manager still uses NotificationService and expects to see a 1114 // manager still uses NotificationService and expects to see a
1085 // RenderViewHost changed notification after WebContents and 1115 // RenderViewHost changed notification after WebContents and
1086 // RenderFrameHostManager are completely initialized. This should be 1116 // RenderFrameHostManager are completely initialized. This should be
1087 // removed once the process manager moves away from NotificationService. 1117 // removed once the process manager moves away from NotificationService.
1088 // See https://crbug.com/462682. 1118 // See https://crbug.com/462682.
1089 delegate_->NotifyMainFrameSwappedFromRenderManager( 1119 delegate_->NotifyMainFrameSwappedFromRenderManager(
1090 nullptr, render_frame_host_->render_view_host()); 1120 nullptr, render_frame_host_->render_view_host());
1091 } 1121 }
1092 } 1122 }
1093 1123
1094 return navigation_rfh; 1124 return navigation_rfh;
1095 } 1125 }
1096 1126
1097 // PlzNavigate 1127 // PlzNavigate
1098 void RenderFrameHostManager::CleanUpNavigation() { 1128 void RenderFrameHostManager::CleanUpNavigation() {
1099 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1129 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1100 switches::kEnableBrowserSideNavigation)); 1130 switches::kEnableBrowserSideNavigation));
1101 speculative_web_ui_.reset(); 1131 // TODO(carlosk): the discarding of the current RFH WebUI and the cleanup of
1102 should_reuse_web_ui_ = false; 1132 // the speculative RFH should not always happen together.
1133 current_web_ui_is_navigating_ = false;
1103 if (speculative_render_frame_host_) 1134 if (speculative_render_frame_host_)
1104 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost()); 1135 DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
1105 } 1136 }
1106 1137
1107 // PlzNavigate 1138 // PlzNavigate
1108 scoped_ptr<RenderFrameHostImpl> 1139 scoped_ptr<RenderFrameHostImpl>
1109 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() { 1140 RenderFrameHostManager::UnsetSpeculativeRenderFrameHost() {
1110 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 1141 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
1111 switches::kEnableBrowserSideNavigation)); 1142 switches::kEnableBrowserSideNavigation));
1112 speculative_render_frame_host_->GetProcess()->RemovePendingView(); 1143 speculative_render_frame_host_->GetProcess()->RemovePendingView();
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 // We can't switch a RenderView between view source and non-view source mode 1316 // We can't switch a RenderView between view source and non-view source mode
1286 // without screwing up the session history sometimes (when navigating between 1317 // without screwing up the session history sometimes (when navigating between
1287 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat 1318 // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
1288 // it as a new navigation). So require a BrowsingInstance switch. 1319 // it as a new navigation). So require a BrowsingInstance switch.
1289 if (current_is_view_source_mode != new_is_view_source_mode) 1320 if (current_is_view_source_mode != new_is_view_source_mode)
1290 return true; 1321 return true;
1291 1322
1292 return false; 1323 return false;
1293 } 1324 }
1294 1325
1295 bool RenderFrameHostManager::ShouldReuseWebUI(
1296 const NavigationEntry* current_entry,
1297 const GURL& new_url) const {
1298 NavigationControllerImpl& controller =
1299 delegate_->GetControllerForRenderManager();
1300 return current_entry && web_ui_ &&
1301 (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
1302 controller.GetBrowserContext(), current_entry->GetURL()) ==
1303 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
1304 controller.GetBrowserContext(), new_url));
1305 }
1306
1307 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation( 1326 SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
1308 const GURL& dest_url, 1327 const GURL& dest_url,
1309 SiteInstance* source_instance, 1328 SiteInstance* source_instance,
1310 SiteInstance* dest_instance, 1329 SiteInstance* dest_instance,
1311 SiteInstance* candidate_instance, 1330 SiteInstance* candidate_instance,
1312 ui::PageTransition transition, 1331 ui::PageTransition transition,
1313 bool dest_is_restore, 1332 bool dest_is_restore,
1314 bool dest_is_view_source_mode) { 1333 bool dest_is_view_source_mode) {
1315 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 1334 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
1316 1335
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 // The process for the new SiteInstance may (if we're sharing a process with 1648 // The process for the new SiteInstance may (if we're sharing a process with
1630 // another host that already initialized it) or may not (we have our own 1649 // another host that already initialized it) or may not (we have our own
1631 // process or the existing process crashed) have been initialized. Calling 1650 // process or the existing process crashed) have been initialized. Calling
1632 // Init multiple times will be ignored, so this is safe. 1651 // Init multiple times will be ignored, so this is safe.
1633 if (!new_instance->GetProcess()->Init()) 1652 if (!new_instance->GetProcess()->Init())
1634 return; 1653 return;
1635 1654
1636 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1655 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1637 1656
1638 // Create a non-swapped-out RFH with the given opener. 1657 // Create a non-swapped-out RFH with the given opener.
1639 pending_render_frame_host_ = CreateRenderFrame( 1658 pending_render_frame_host_ =
1640 new_instance, pending_web_ui(), create_render_frame_flags, nullptr); 1659 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1641 } 1660 }
1642 1661
1643 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost( 1662 void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
1644 SiteInstance* old_instance, 1663 SiteInstance* old_instance,
1645 SiteInstance* new_instance) { 1664 SiteInstance* new_instance) {
1646 // Only create opener proxies if they are in the same BrowsingInstance. 1665 // Only create opener proxies if they are in the same BrowsingInstance.
1647 if (new_instance->IsRelatedSiteInstance(old_instance)) { 1666 if (new_instance->IsRelatedSiteInstance(old_instance)) {
1648 CreateOpenerProxies(new_instance, frame_tree_node_); 1667 CreateOpenerProxies(new_instance, frame_tree_node_);
1649 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { 1668 } else if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
1650 // Ensure that the frame tree has RenderFrameProxyHosts for the 1669 // Ensure that the frame tree has RenderFrameProxyHosts for the
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 } 1745 }
1727 1746
1728 return RenderFrameHostFactory::Create( 1747 return RenderFrameHostFactory::Create(
1729 site_instance, render_view_host, render_frame_delegate_, 1748 site_instance, render_view_host, render_frame_delegate_,
1730 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id, 1749 render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
1731 widget_routing_id, flags); 1750 widget_routing_id, flags);
1732 } 1751 }
1733 1752
1734 // PlzNavigate 1753 // PlzNavigate
1735 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost( 1754 bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
1736 const GURL& url,
1737 SiteInstance* old_instance, 1755 SiteInstance* old_instance,
1738 SiteInstance* new_instance, 1756 SiteInstance* new_instance) {
1739 int bindings) {
1740 CHECK(new_instance); 1757 CHECK(new_instance);
1741 CHECK_NE(old_instance, new_instance); 1758 CHECK_NE(old_instance, new_instance);
1742 CHECK(!should_reuse_web_ui_); 1759 CHECK(!current_web_ui_is_navigating_);
1743
1744 // Note: |speculative_web_ui_| must be initialized before starting the
1745 // |speculative_render_frame_host_| creation steps otherwise the WebUI
1746 // won't be properly initialized.
1747 speculative_web_ui_ = CreateWebUI(url, bindings);
1748 1760
1749 // The process for the new SiteInstance may (if we're sharing a process with 1761 // The process for the new SiteInstance may (if we're sharing a process with
1750 // another host that already initialized it) or may not (we have our own 1762 // another host that already initialized it) or may not (we have our own
1751 // process or the existing process crashed) have been initialized. Calling 1763 // process or the existing process crashed) have been initialized. Calling
1752 // Init multiple times will be ignored, so this is safe. 1764 // Init multiple times will be ignored, so this is safe.
1753 if (!new_instance->GetProcess()->Init()) 1765 if (!new_instance->GetProcess()->Init())
1754 return false; 1766 return false;
1755 1767
1756 CreateProxiesForNewRenderFrameHost(old_instance, new_instance); 1768 CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
1757 1769
1758 int create_render_frame_flags = 0; 1770 int create_render_frame_flags = 0;
1759 if (delegate_->IsHidden()) 1771 if (delegate_->IsHidden())
1760 create_render_frame_flags |= CREATE_RF_HIDDEN; 1772 create_render_frame_flags |= CREATE_RF_HIDDEN;
1761 speculative_render_frame_host_ = 1773 speculative_render_frame_host_ =
1762 CreateRenderFrame(new_instance, speculative_web_ui_.get(), 1774 CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
1763 create_render_frame_flags, nullptr);
1764 1775
1765 if (!speculative_render_frame_host_) { 1776 return !!speculative_render_frame_host_;
1766 speculative_web_ui_.reset();
1767 return false;
1768 }
1769 return true;
1770 } 1777 }
1771 1778
1772 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( 1779 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
1773 SiteInstance* instance, 1780 SiteInstance* instance,
1774 WebUIImpl* web_ui,
1775 int flags, 1781 int flags,
1776 int* view_routing_id_ptr) { 1782 int* view_routing_id_ptr) {
1777 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); 1783 bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
1778 bool swapped_out_forbidden = 1784 bool swapped_out_forbidden =
1779 SiteIsolationPolicy::IsSwappedOutStateForbidden(); 1785 SiteIsolationPolicy::IsSwappedOutStateForbidden();
1780 1786
1781 CHECK(instance); 1787 CHECK(instance);
1782 CHECK(!swapped_out_forbidden || !swapped_out); 1788 CHECK(!swapped_out_forbidden || !swapped_out);
1783 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() || 1789 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
1784 frame_tree_node_->IsMainFrame()); 1790 frame_tree_node_->IsMainFrame());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 success = InitRenderFrame(new_render_frame_host.get()); 1888 success = InitRenderFrame(new_render_frame_host.get());
1883 } 1889 }
1884 } 1890 }
1885 1891
1886 if (success) { 1892 if (success) {
1887 if (view_routing_id_ptr) 1893 if (view_routing_id_ptr)
1888 *view_routing_id_ptr = render_view_host->GetRoutingID(); 1894 *view_routing_id_ptr = render_view_host->GetRoutingID();
1889 } 1895 }
1890 } 1896 }
1891 1897
1892 // When a new RenderView is created by the renderer process, the new
1893 // WebContents gets a RenderViewHost in the SiteInstance of its opener
1894 // WebContents. If not used in the first navigation, this RVH is swapped out
1895 // and is not granted bindings, so we may need to grant them when swapping it
1896 // in.
1897 if (web_ui && !new_render_frame_host->GetProcess()->IsForGuestsOnly()) {
1898 int required_bindings = web_ui->GetBindings();
1899 RenderViewHost* render_view_host =
1900 new_render_frame_host->render_view_host();
1901 if ((render_view_host->GetEnabledBindings() & required_bindings) !=
1902 required_bindings) {
1903 render_view_host->AllowBindings(required_bindings);
1904 }
1905 }
1906
1907 // Returns the new RFH if it isn't swapped out. 1898 // Returns the new RFH if it isn't swapped out.
1908 if (success && !swapped_out) { 1899 if (success && !swapped_out) {
1909 DCHECK(new_render_frame_host->GetSiteInstance() == instance); 1900 DCHECK(new_render_frame_host->GetSiteInstance() == instance);
1910 return new_render_frame_host.Pass(); 1901 return new_render_frame_host.Pass();
1911 } 1902 }
1912 return nullptr; 1903 return nullptr;
1913 } 1904 }
1914 1905
1915 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) { 1906 int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
1916 // A RenderFrameProxyHost should never be created in the same SiteInstance as 1907 // A RenderFrameProxyHost should never be created in the same SiteInstance as
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2015 RenderFrameProxyHost* proxy) { 2006 RenderFrameProxyHost* proxy) {
2016 // Ensure the renderer process is initialized before creating the 2007 // Ensure the renderer process is initialized before creating the
2017 // RenderView. 2008 // RenderView.
2018 if (!render_view_host->GetProcess()->Init()) 2009 if (!render_view_host->GetProcess()->Init())
2019 return false; 2010 return false;
2020 2011
2021 // We may have initialized this RenderViewHost for another RenderFrameHost. 2012 // We may have initialized this RenderViewHost for another RenderFrameHost.
2022 if (render_view_host->IsRenderViewLive()) 2013 if (render_view_host->IsRenderViewLive())
2023 return true; 2014 return true;
2024 2015
2025 // If |render_view_host| is not for a proxy and the navigation is to a WebUI,
2026 // and if the RenderView is not in a guest process, tell |render_view_host|
2027 // about any bindings it will need enabled.
2028 // TODO(carlosk): Move WebUI to RenderFrameHost in https://crbug.com/508850.
2029 WebUIImpl* dest_web_ui = nullptr;
2030 if (!proxy) {
2031 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2032 switches::kEnableBrowserSideNavigation)) {
2033 dest_web_ui =
2034 should_reuse_web_ui_ ? web_ui_.get() : speculative_web_ui_.get();
2035 } else {
2036 dest_web_ui = pending_web_ui();
2037 }
2038 }
2039 if (dest_web_ui && !render_view_host->GetProcess()->IsForGuestsOnly()) {
2040 render_view_host->AllowBindings(dest_web_ui->GetBindings());
2041 } else {
2042 // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
2043 // process unless it's swapped out.
2044 if (render_view_host->is_active()) {
2045 CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
2046 render_view_host->GetProcess()->GetID()));
2047 }
2048 }
2049
2050 int opener_frame_routing_id = 2016 int opener_frame_routing_id =
2051 GetOpenerRoutingID(render_view_host->GetSiteInstance()); 2017 GetOpenerRoutingID(render_view_host->GetSiteInstance());
2052 2018
2053 bool created = delegate_->CreateRenderViewForRenderManager( 2019 bool created = delegate_->CreateRenderViewForRenderManager(
2054 render_view_host, opener_frame_routing_id, 2020 render_view_host, opener_frame_routing_id,
2055 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE, 2021 proxy ? proxy->GetRoutingID() : MSG_ROUTING_NONE,
2056 frame_tree_node_->current_replication_state()); 2022 frame_tree_node_->current_replication_state());
2057 2023
2058 if (created && proxy) 2024 if (created && proxy)
2059 proxy->set_render_frame_proxy_created(true); 2025 proxy->set_render_frame_proxy_created(true);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance); 2097 RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
2132 if (proxy) 2098 if (proxy)
2133 return proxy->GetRoutingID(); 2099 return proxy->GetRoutingID();
2134 2100
2135 return MSG_ROUTING_NONE; 2101 return MSG_ROUTING_NONE;
2136 } 2102 }
2137 2103
2138 void RenderFrameHostManager::CommitPending() { 2104 void RenderFrameHostManager::CommitPending() {
2139 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending", 2105 TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
2140 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2106 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2141 bool browser_side_navigation =
2142 base::CommandLine::ForCurrentProcess()->HasSwitch(
2143 switches::kEnableBrowserSideNavigation);
2144
2145 // First check whether we're going to want to focus the location bar after 2107 // First check whether we're going to want to focus the location bar after
2146 // this commit. We do this now because the navigation hasn't formally 2108 // this commit. We do this now because the navigation hasn't formally
2147 // committed yet, so if we've already cleared |pending_web_ui_| the call chain 2109 // committed yet, so if we've already cleared the pending WebUI the call chain
2148 // this triggers won't be able to figure out what's going on. 2110 // this triggers won't be able to figure out what's going on.
2149 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 2111 bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
2150 2112
2151 // Next commit the Web UI, if any. Either replace |web_ui_| with
2152 // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
2153 // leave |web_ui_| as is if reusing it.
2154 DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_));
2155 if (pending_web_ui_ || speculative_web_ui_) {
2156 DCHECK(!should_reuse_web_ui_);
2157 web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release()
2158 : pending_web_ui_.release());
2159 } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) {
2160 if (browser_side_navigation) {
2161 DCHECK(web_ui_);
2162 should_reuse_web_ui_ = false;
2163 } else {
2164 DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get());
2165 pending_and_current_web_ui_.reset();
2166 }
2167 } else {
2168 web_ui_.reset();
2169 }
2170 DCHECK(!speculative_web_ui_);
2171 DCHECK(!should_reuse_web_ui_);
2172
2173 // It's possible for the pending_render_frame_host_ to be nullptr when we
2174 // aren't crossing process boundaries. If so, we just needed to handle the Web
2175 // UI committing above and we're done.
2176 if (!pending_render_frame_host_ && !speculative_render_frame_host_) { 2113 if (!pending_render_frame_host_ && !speculative_render_frame_host_) {
2114 DCHECK_EQ(current_web_ui_is_navigating_, !!render_frame_host_->web_ui());
2115 current_web_ui_is_navigating_ = false;
2116 // If there's no pending/speculative RenderFrameHost then the current
2117 // RenderFrameHost is committing.
2177 if (will_focus_location_bar) 2118 if (will_focus_location_bar)
2178 delegate_->SetFocusToLocationBar(false); 2119 delegate_->SetFocusToLocationBar(false);
2179 return; 2120 return;
2180 } 2121 }
2181 2122
2182 // Remember if the page was focused so we can focus the new renderer in 2123 // Remember if the page was focused so we can focus the new renderer in
2183 // that case. 2124 // that case.
2184 bool focus_render_view = !will_focus_location_bar && 2125 bool focus_render_view = !will_focus_location_bar &&
2185 render_frame_host_->GetView() && 2126 render_frame_host_->GetView() &&
2186 render_frame_host_->GetView()->HasFocus(); 2127 render_frame_host_->GetView()->HasFocus();
2187 2128
2188 bool is_main_frame = frame_tree_node_->IsMainFrame(); 2129 bool is_main_frame = frame_tree_node_->IsMainFrame();
2189 2130
2190 // Swap in the pending or speculative frame and make it active. Also ensure 2131 // Swap in the pending or speculative frame and make it active. Also ensure
2191 // the FrameTree stays in sync. 2132 // the FrameTree stays in sync.
2192 scoped_ptr<RenderFrameHostImpl> old_render_frame_host; 2133 scoped_ptr<RenderFrameHostImpl> old_render_frame_host;
2193 if (!browser_side_navigation) { 2134 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
2135 switches::kEnableBrowserSideNavigation)) {
2194 DCHECK(!speculative_render_frame_host_); 2136 DCHECK(!speculative_render_frame_host_);
2195 old_render_frame_host = 2137 old_render_frame_host =
2196 SetRenderFrameHost(pending_render_frame_host_.Pass()); 2138 SetRenderFrameHost(pending_render_frame_host_.Pass());
2197 } else { 2139 } else {
2198 // PlzNavigate 2140 // PlzNavigate
2199 DCHECK(speculative_render_frame_host_); 2141 DCHECK(speculative_render_frame_host_);
2200 old_render_frame_host = 2142 old_render_frame_host =
2201 SetRenderFrameHost(speculative_render_frame_host_.Pass()); 2143 SetRenderFrameHost(speculative_render_frame_host_.Pass());
2202 } 2144 }
2203 2145
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 // If we are currently navigating cross-process, we want to get back to normal 2295 // If we are currently navigating cross-process, we want to get back to normal
2354 // and then navigate as usual. 2296 // and then navigate as usual.
2355 if (pending_render_frame_host_) 2297 if (pending_render_frame_host_)
2356 CancelPending(); 2298 CancelPending();
2357 2299
2358 SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); 2300 SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
2359 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation( 2301 scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
2360 dest_url, source_instance, dest_instance, nullptr, transition, 2302 dest_url, source_instance, dest_instance, nullptr, transition,
2361 dest_is_restore, dest_is_view_source_mode); 2303 dest_is_restore, dest_is_view_source_mode);
2362 2304
2363 const NavigationEntry* current_entry =
2364 delegate_->GetLastCommittedNavigationEntryForRenderManager();
2365
2366 DCHECK(!pending_render_frame_host_); 2305 DCHECK(!pending_render_frame_host_);
2367 2306
2368 if (new_instance.get() != current_instance) { 2307 if (new_instance.get() != current_instance) {
2369 TRACE_EVENT_INSTANT2( 2308 TRACE_EVENT_INSTANT2(
2370 "navigation", 2309 "navigation",
2371 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance", 2310 "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
2372 TRACE_EVENT_SCOPE_THREAD, 2311 TRACE_EVENT_SCOPE_THREAD,
2373 "current_instance id", current_instance->GetId(), 2312 "current_instance id", current_instance->GetId(),
2374 "new_instance id", new_instance->GetId()); 2313 "new_instance id", new_instance->GetId());
2375 2314
2376 // New SiteInstance: create a pending RFH to navigate. 2315 // New SiteInstance: create a pending RFH to navigate.
2377 2316
2378 // This will possibly create (set to nullptr) a Web UI object for the 2317 current_web_ui_is_navigating_ = false;
2379 // pending page. We'll use this later to give the page special access. This
2380 // must happen before the new renderer is created below so it will get
2381 // bindings. It must also happen after the above conditional call to
2382 // CancelPending(), otherwise CancelPending may clear the pending_web_ui_
2383 // and the page will not have its bindings set appropriately.
2384 SetPendingWebUI(dest_url, bindings);
2385 CreatePendingRenderFrameHost(current_instance, new_instance.get()); 2318 CreatePendingRenderFrameHost(current_instance, new_instance.get());
2386 if (!pending_render_frame_host_) 2319 if (!pending_render_frame_host_)
2387 return nullptr; 2320 return nullptr;
2388 2321
2322 pending_render_frame_host_->UpdateWebUI(dest_url, bindings);
2323 if (pending_render_frame_host_->web_ui()) {
2324 pending_render_frame_host_->web_ui()->RenderViewCreated(
2325 pending_render_frame_host_->render_view_host());
2326 }
2327
2328 // We now have a pending RFH and possibly an associated pending WebUI.
2329 DCHECK(pending_render_frame_host_);
nasko 2015/11/02 17:00:36 This DCHECK is redundant. The call to UpdateWebUI
carlosk 2015/11/03 09:50:30 I moved this up where it matters.
2330 DCHECK_EQ(GetNavigatingWebUI(), pending_render_frame_host_->web_ui());
2331
2389 // Check if our current RFH is live before we set up a transition. 2332 // Check if our current RFH is live before we set up a transition.
2390 if (!render_frame_host_->IsRenderFrameLive()) { 2333 if (!render_frame_host_->IsRenderFrameLive()) {
2391 // The current RFH is not live. There's no reason to sit around with a 2334 // The current RFH is not live. There's no reason to sit around with a
2392 // sad tab or a newly created RFH while we wait for the pending RFH to 2335 // sad tab or a newly created RFH while we wait for the pending RFH to
2393 // navigate. Just switch to the pending RFH now and go back to normal. 2336 // navigate. Just switch to the pending RFH now and go back to normal.
2394 // (Note that we don't care about on{before}unload handlers if the current 2337 // (Note that we don't care about on{before}unload handlers if the current
2395 // RFH isn't live.) 2338 // RFH isn't live.)
2396 CommitPending(); 2339 CommitPending();
2397 return render_frame_host_.get(); 2340 return render_frame_host_.get();
2398 } 2341 }
2399 // Otherwise, it's safe to treat this as a pending cross-process transition. 2342 // Otherwise, it's safe to treat this as a pending cross-process transition.
2400 2343
2401 // We now have a pending RFH.
2402 DCHECK(pending_render_frame_host_);
2403
2404 // We need to wait until the beforeunload handler has run, unless we are 2344 // We need to wait until the beforeunload handler has run, unless we are
2405 // transferring an existing request (in which case it has already run). 2345 // transferring an existing request (in which case it has already run).
2406 // Suspend the new render view (i.e., don't let it send the cross-process 2346 // Suspend the new render view (i.e., don't let it send the cross-process
2407 // Navigate message) until we hear back from the old renderer's 2347 // Navigate message) until we hear back from the old renderer's
2408 // beforeunload handler. If the handler returns false, we'll have to 2348 // beforeunload handler. If the handler returns false, we'll have to
2409 // cancel the request. 2349 // cancel the request.
2410 //
2411 DCHECK(!pending_render_frame_host_->are_navigations_suspended()); 2350 DCHECK(!pending_render_frame_host_->are_navigations_suspended());
2412 bool is_transfer = transferred_request_id != GlobalRequestID(); 2351 bool is_transfer = transferred_request_id != GlobalRequestID();
2413 if (is_transfer) { 2352 if (is_transfer) {
2414 // We don't need to stop the old renderer or run beforeunload/unload 2353 // We don't need to stop the old renderer or run beforeunload/unload
2415 // handlers, because those have already been done. 2354 // handlers, because those have already been done.
2416 DCHECK(cross_site_transferring_request_->request_id() == 2355 DCHECK(cross_site_transferring_request_->request_id() ==
2417 transferred_request_id); 2356 transferred_request_id);
2418 } else { 2357 } else {
2419 // Also make sure the old render view stops, in case a load is in 2358 // Also make sure the old render view stops, in case a load is in
2420 // progress. (We don't want to do this for transfers, since it will 2359 // progress. (We don't want to do this for transfers, since it will
(...skipping 14 matching lines...) Expand all
2435 2374
2436 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_. 2375 // Otherwise the same SiteInstance can be used. Navigate render_frame_host_.
2437 2376
2438 // It's possible to swap out the current RFH and then decide to navigate in it 2377 // It's possible to swap out the current RFH and then decide to navigate in it
2439 // anyway (e.g., a cross-process navigation that redirects back to the 2378 // anyway (e.g., a cross-process navigation that redirects back to the
2440 // original site). In that case, we have a proxy for the current RFH but 2379 // original site). In that case, we have a proxy for the current RFH but
2441 // haven't deleted it yet. The new navigation will swap it back in, so we can 2380 // haven't deleted it yet. The new navigation will swap it back in, so we can
2442 // delete the proxy. 2381 // delete the proxy.
2443 proxy_hosts_->Remove(new_instance.get()->GetId()); 2382 proxy_hosts_->Remove(new_instance.get()->GetId());
2444 2383
2445 if (ShouldReuseWebUI(current_entry, dest_url)) { 2384 WebUI::TypeID previous_web_ui_type = render_frame_host_->web_ui_type();
2446 pending_web_ui_.reset(); 2385 bool changed_web_ui = render_frame_host_->UpdateWebUI(dest_url, bindings);
2447 pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); 2386
2448 } else { 2387 // If a change in WebUI happened, check this is an acceptable case.
2449 SetPendingWebUI(dest_url, bindings); 2388 DCHECK(!changed_web_ui ||
2450 // Make sure the new RenderViewHost has the right bindings. 2389 IsAcceptableWebUITransition(previous_web_ui_type, dest_url,
2451 if (pending_web_ui() && 2390 dest_is_restore));
2452 !render_frame_host_->GetProcess()->IsForGuestsOnly()) { 2391
2453 render_frame_host_->render_view_host()->AllowBindings( 2392 // If there is a WebUI in the current RenderFrameHost, it will navigate.
2454 pending_web_ui()->GetBindings()); 2393 current_web_ui_is_navigating_ = !!render_frame_host_->web_ui();
2394 DCHECK_EQ(GetNavigatingWebUI(), render_frame_host_->web_ui());
2395
2396 // If the current RenderFrameHost has a WebUI and the associated RenderFrame
2397 // is alive, notify to the WebUI that the RenderView is being created or
2398 // reused depending on whether the WebUI was changed or not.
2399 if (GetNavigatingWebUI() && render_frame_host_->IsRenderFrameLive()) {
2400 if (changed_web_ui) {
2401 GetNavigatingWebUI()->RenderViewCreated(
2402 render_frame_host_->render_view_host());
2403 } else {
2404 GetNavigatingWebUI()->RenderViewReused(
2405 render_frame_host_->render_view_host(),
2406 frame_tree_node_->IsMainFrame());
2455 } 2407 }
2456 } 2408 }
2457 2409
2458 if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) {
2459 pending_web_ui()->RenderViewReused(render_frame_host_->render_view_host(),
2460 frame_tree_node_->IsMainFrame());
2461 }
2462
2463 // The renderer can exit view source mode when any error or cancellation 2410 // The renderer can exit view source mode when any error or cancellation
2464 // happen. We must overwrite to recover the mode. 2411 // happen. We must overwrite to recover the mode.
2465 if (dest_is_view_source_mode) { 2412 if (dest_is_view_source_mode) {
2466 render_frame_host_->render_view_host()->Send( 2413 render_frame_host_->render_view_host()->Send(
2467 new ViewMsg_EnableViewSourceMode( 2414 new ViewMsg_EnableViewSourceMode(
2468 render_frame_host_->render_view_host()->GetRoutingID())); 2415 render_frame_host_->render_view_host()->GetRoutingID()));
2469 } 2416 }
2470 2417
2471 return render_frame_host_.get(); 2418 return render_frame_host_.get();
2472 } 2419 }
2473 2420
2474 void RenderFrameHostManager::CancelPending() { 2421 void RenderFrameHostManager::CancelPending() {
2475 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending", 2422 TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
2476 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id()); 2423 "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
2424 current_web_ui_is_navigating_ = false;
2477 DiscardUnusedFrame(UnsetPendingRenderFrameHost()); 2425 DiscardUnusedFrame(UnsetPendingRenderFrameHost());
2478 } 2426 }
2479 2427
2480 scoped_ptr<RenderFrameHostImpl> 2428 scoped_ptr<RenderFrameHostImpl>
2481 RenderFrameHostManager::UnsetPendingRenderFrameHost() { 2429 RenderFrameHostManager::UnsetPendingRenderFrameHost() {
2482 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host = 2430 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host =
2483 pending_render_frame_host_.Pass(); 2431 pending_render_frame_host_.Pass();
2484 2432
2485 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation( 2433 RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
2486 pending_render_frame_host.get(), 2434 pending_render_frame_host.get(),
2487 render_frame_host_.get()); 2435 render_frame_host_.get());
2488 2436
2437 current_web_ui_is_navigating_ = false;
2438
2489 // We no longer need to prevent the process from exiting. 2439 // We no longer need to prevent the process from exiting.
2490 pending_render_frame_host->GetProcess()->RemovePendingView(); 2440 pending_render_frame_host->GetProcess()->RemovePendingView();
2491 2441
2492 pending_web_ui_.reset();
2493 pending_and_current_web_ui_.reset();
2494
2495 return pending_render_frame_host.Pass(); 2442 return pending_render_frame_host.Pass();
2496 } 2443 }
2497 2444
2498 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost( 2445 scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
2499 scoped_ptr<RenderFrameHostImpl> render_frame_host) { 2446 scoped_ptr<RenderFrameHostImpl> render_frame_host) {
2500 // Swap the two. 2447 // Swap the two.
2501 scoped_ptr<RenderFrameHostImpl> old_render_frame_host = 2448 scoped_ptr<RenderFrameHostImpl> old_render_frame_host =
2502 render_frame_host_.Pass(); 2449 render_frame_host_.Pass();
2503 render_frame_host_ = render_frame_host.Pass(); 2450 render_frame_host_ = render_frame_host.Pass();
2504 2451
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2659 if (rvh && !rvh->IsRenderViewLive()) { 2606 if (rvh && !rvh->IsRenderViewLive()) {
2660 EnsureRenderViewInitialized(rvh, instance); 2607 EnsureRenderViewInitialized(rvh, instance);
2661 } else { 2608 } else {
2662 // Create a swapped out RenderView in the given SiteInstance if none 2609 // Create a swapped out RenderView in the given SiteInstance if none
2663 // exists. Since an opener can point to a subframe, do this on the root 2610 // exists. Since an opener can point to a subframe, do this on the root
2664 // frame of the current opener's frame tree. 2611 // frame of the current opener's frame tree.
2665 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) { 2612 if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
2666 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance); 2613 frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
2667 } else { 2614 } else {
2668 frame_tree->root()->render_manager()->CreateRenderFrame( 2615 frame_tree->root()->render_manager()->CreateRenderFrame(
2669 instance, nullptr, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, 2616 instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
2670 nullptr);
2671 } 2617 }
2672 } 2618 }
2673 } 2619 }
2674 } 2620 }
2675 2621
2676 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) { 2622 int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
2677 if (!frame_tree_node_->opener()) 2623 if (!frame_tree_node_->opener())
2678 return MSG_ROUTING_NONE; 2624 return MSG_ROUTING_NONE;
2679 2625
2680 return frame_tree_node_->opener() 2626 return frame_tree_node_->opener()
2681 ->render_manager() 2627 ->render_manager()
2682 ->GetRoutingIdForSiteInstance(instance); 2628 ->GetRoutingIdForSiteInstance(instance);
2683 } 2629 }
2684 2630
2631 bool RenderFrameHostManager::IsAcceptableWebUITransition(
2632 WebUI::TypeID previous_web_ui_type,
2633 const GURL& dest_url,
2634 bool dest_is_restore) {
2635 // There are a few navigation cases that allow for changes to the WebUI of
2636 // the current RenderFrameHost.
2637 BrowserContext* browser_context =
2638 delegate_->GetControllerForRenderManager().GetBrowserContext();
2639 if (render_frame_host_->web_ui()) {
2640 // Switching WebUI from one type to another is never acceptable.
2641 DCHECK(previous_web_ui_type == WebUI::kNoWebUI);
2642
2643 // Going from not having to having a WebUI is acceptable for:
2644 // - The first navigation of this frame.
2645 const NavigationEntry* current_entry =
2646 delegate_->GetLastCommittedNavigationEntryForRenderManager();
2647 bool is_first_navigation_for_frame = !current_entry;
2648 // - A restore navigation to a WebUI URL.
2649 const GURL& current_effective_url =
2650 current_entry ? SiteInstanceImpl::GetEffectiveURL(
2651 browser_context, current_entry->GetURL())
2652 : render_frame_host_->GetSiteInstance()->GetSiteURL();
2653 bool is_webui_restore =
2654 dest_is_restore &&
2655 WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
2656 browser_context, current_effective_url);
2657 // - Navigating back from a special renderer controlled URL.
2658 bool is_back_from_renderer_url =
2659 current_entry && IsRendererDebugURL(current_entry->GetURL());
2660 // - Navigating in webview tag guest.
2661 bool is_webview_tag_guest =
2662 render_frame_host_->GetSiteInstance()->GetSiteURL().SchemeIs(
2663 kGuestScheme);
2664 DCHECK(is_first_navigation_for_frame || is_webui_restore ||
2665 is_back_from_renderer_url || is_webview_tag_guest);
2666 } else {
2667 // Going from having to not having a WebUI is acceptable for:
2668 // - Navigating to a special, renderer controlled URL.
2669 DCHECK(IsRendererDebugURL(
2670 SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url)));
2671 }
2672 return true;
2673 }
2674
2685 } // namespace content 2675 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698