11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/frame_host/render_frame_host_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/devtools/render_view_devtools_agent_host.h" 1481d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch#include "content/browser/frame_host/debug_urls.h" 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/browser/frame_host/interstitial_page_impl.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/browser/frame_host/navigation_controller_impl.h" 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/browser/frame_host/navigation_entry_impl.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_factory.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/site_instance_impl.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/webui/web_ui_controller_factory_registry.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/webui/web_ui_impl.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/view_messages.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/port/browser/render_widget_host_view_port.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h" 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/render_widget_host_iterator.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui_controller.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams() 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : is_transfer(false), frame_id(-1), should_replace_current_entry(false) { 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GlobalRequestID& global_request_id, 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool is_transfer, 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::vector<GURL>& transfer_url_chain, 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Referrer referrer, 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PageTransition page_transition, 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 frame_id, 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool should_replace_current_entry) 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : global_request_id(global_request_id), 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_transfer(is_transfer), 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transfer_url_chain(transfer_url_chain), 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) referrer(referrer), 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) page_transition(page_transition), 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) frame_id(frame_id), 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) should_replace_current_entry(should_replace_current_entry) { 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {} 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderFrameHostManager::RenderFrameHostManager( 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RenderFrameHostDelegate* render_frame_delegate, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostDelegate* render_view_delegate, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHostDelegate* render_widget_delegate, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_(false), 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) render_frame_delegate_(render_frame_delegate), 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_delegate_(render_view_delegate), 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_widget_delegate_(render_widget_delegate), 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_(NULL), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_(NULL), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interstitial_page_(NULL) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderFrameHostManager::~RenderFrameHostManager() { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_render_view_host_) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPending(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should always have a main RenderViewHost except in some tests. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* render_view_host = render_view_host_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_ = NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_view_host) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host->Shutdown(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shut down any swapped out RenderViewHosts. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != swapped_out_hosts_.end(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->Shutdown(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::Init(BrowserContext* browser_context, 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstance* site_instance, 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int routing_id, 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int main_frame_routing_id) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a RenderViewHost, once we have an instance. It is important to 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // immediately give this SiteInstance to a RenderViewHost so that it is 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ref counted. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!site_instance) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) site_instance = SiteInstance::Create(browser_context); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_ = static_cast<RenderViewHostImpl*>( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostFactory::Create( 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) site_instance, render_view_delegate_, render_frame_delegate_, 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) render_widget_delegate_, routing_id, main_frame_routing_id, false, 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delegate_->IsHidden())); 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_host_->AttachToFrameTree(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Keep track of renderer processes as they start to shut down or are 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // crashed/killed. 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NotificationService::AllSources()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSING, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotificationService::AllSources()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderViewHostImpl* RenderFrameHostManager::current_host() const { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_view_host_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderViewHostImpl* RenderFrameHostManager::pending_render_view_host() const { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pending_render_view_host_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (interstitial_page_) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return interstitial_page_->GetView(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!render_view_host_) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_view_host_->GetView(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_web_ui_.reset( 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->CreateWebUIForRenderManager(entry.GetURL())); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_and_current_web_ui_.reset(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have assigned (zero or more) bindings to this NavigationEntry in the 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // past, make sure we're not granting it different bindings than it had 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // before. If so, note it and don't give it any bindings, to avoid a 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // potential privilege escalation. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pending_web_ui_.get() && 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry.bindings() != NavigationEntryImpl::kInvalidBindings && 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_web_ui_->GetBindings() != entry.bindings()) { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordAction(UserMetricsAction("ProcessSwapBindingsMismatch_RVHM")); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_web_ui_.reset(); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderViewHostImpl* RenderFrameHostManager::Navigate( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationEntryImpl& entry) { 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate"); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a pending RenderViewHost. It will give us the one we should use 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* dest_render_view_host = 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<RenderViewHostImpl*>(UpdateRendererStateForNavigate(entry)); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dest_render_view_host) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; // We weren't able to create a pending render view host. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the current render_view_host_ isn't live, we should create it so 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we don't show a sad tab while the dest_render_view_host fetches 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // its first page. (Bug 1145340) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_render_view_host != render_view_host_ && 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !render_view_host_->IsRenderViewLive()) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: we don't call InitRenderView here because we are navigating away 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // soon anyway, and we don't have the NavigationEntry for this host. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->CreateRenderViewForRenderManager(render_view_host_, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MSG_ROUTING_NONE); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the renderer crashed, then try to create a new one to satisfy this 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation request. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dest_render_view_host->IsRenderViewLive()) { 173fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch // Recreate the opener chain. 174fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager( 175fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch dest_render_view_host->GetSiteInstance()); 176fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch if (!InitRenderView(dest_render_view_host, opener_route_id)) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now that we've created a new renderer, be sure to hide it if it isn't 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our primary one. Otherwise, we might crash if we try to call Show() 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on it later. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_render_view_host != render_view_host_ && 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_render_view_host->GetView()) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest_render_view_host->GetView()->Hide(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is our primary renderer, notify here as we won't be calling 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CommitPending (which does the notify). 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delegate_->NotifySwappedFromRenderManager(NULL, render_view_host_); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dest_render_view_host; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::Stop() { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_->Stop(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are cross-navigating, we should stop the pending renderers. This 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will lead to a DidFailProvisionalLoad, which will properly destroy them. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cross_navigation_pending_) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_->Send( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ViewMsg_Stop(pending_render_view_host_->GetRoutingID())); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::SetIsLoading(bool is_loading) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_->SetIsLoading(is_loading); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_render_view_host_) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_->SetIsLoading(is_loading); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::ShouldCloseTabOnUnresponsiveRenderer() { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cross_navigation_pending_) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // We should always have a pending RVH when there's a cross-process navigation 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // in progress. Sanity check this for http://crbug.com/276333. 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CHECK(pending_render_view_host_); 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // If the tab becomes unresponsive during {before}unload while doing a 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cross-site navigation, proceed with the navigation. (This assumes that 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the pending RenderViewHost is still responsive.) 2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (render_view_host_->is_waiting_for_unload_ack()) { 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The request has been started and paused while we're waiting for the 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // unload handler to finish. We'll pretend that it did. The pending 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // renderer will then be swapped in as part of the usual DidNavigate logic. 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // (If the unload handler later finishes, this call will be ignored because 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // the pending_nav_params_ state will already be cleaned up.) 2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) current_host()->OnSwappedOut(true); 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else if (render_view_host_->is_waiting_for_beforeunload_ack()) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Haven't gotten around to starting the request, because we're still 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // waiting for the beforeunload handler to finish. We'll pretend that it 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // did finish, to let the navigation proceed. Note that there's a danger 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the beforeunload handler will later finish and possibly return 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // false (meaning the navigation should not proceed), but we'll ignore it 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in this case because it took too long. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_render_view_host_->are_navigations_suspended()) 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_render_view_host_->SetNavigationsSuspended( 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false, base::TimeTicks::Now()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::SwappedOut(RenderViewHost* render_view_host) { 2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Make sure this is from our current RVH, and that we have a pending 2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // navigation from OnCrossSiteResponse. (There may be no pending navigation 2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // for data URLs that don't make network requests, for example.) If not, 2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // just return early and ignore. 2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (render_view_host != render_view_host_ || !pending_nav_params_.get()) { 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_nav_params_.reset(); 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Now that the unload handler has run, we need to either initiate the 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // pending transfer (if there is one) or resume the paused response (if not). 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(creis): The blank swapped out page is visible during this time, but 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // we can shorten this by delivering the response directly, rather than 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // forcing an identical request to be made. 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (pending_nav_params_->is_transfer) { 2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Treat the last URL in the chain as the destination and the remainder as 2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the redirect chain. 2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CHECK(pending_nav_params_->transfer_url_chain.size()); 2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GURL transfer_url = pending_nav_params_->transfer_url_chain.back(); 2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_nav_params_->transfer_url_chain.pop_back(); 2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We don't know whether the original request had |user_action| set to true. 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // However, since we force the navigation to be in the current tab, it 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // doesn't matter. 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_host->GetDelegate()->RequestTransferURL( 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) transfer_url, 2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_nav_params_->transfer_url_chain, 2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_nav_params_->referrer, 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_nav_params_->page_transition, 2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CURRENT_TAB, 2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_nav_params_->frame_id, 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_nav_params_->global_request_id, 277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_nav_params_->should_replace_current_entry, 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) true); 2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (pending_render_view_host_) { 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RenderProcessHostImpl* pending_process = 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static_cast<RenderProcessHostImpl*>( 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_render_view_host_->GetProcess()); 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_process->ResumeDeferredNavigation( 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_nav_params_->global_request_id); 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_nav_params_.reset(); 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::DidNavigateMainFrame( 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHost* render_view_host) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cross_navigation_pending_) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pending_render_view_host_); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should only hear this from our current renderer. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(render_view_host == render_view_host_); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Even when there is no pending RVH, there may be a pending Web UI. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_web_ui()) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommitPending(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_view_host == pending_render_view_host_) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The pending cross-site navigation completed, so show the renderer. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it committed without sending network requests (e.g., data URLs), 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then we still need to swap out the old RVH first and run its unload 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handler. OK for that to happen in the background. 3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (pending_render_view_host_->HasPendingCrossSiteRequest()) 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SwapOutOldPage(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommitPending(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_ = false; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (render_view_host == render_view_host_) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A navigation in the original page has taken place. Cancel the pending 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPending(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_ = false; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No one else should be sending us DidNavigate in this state. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(false); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::DidDisownOpener(RenderViewHost* render_view_host) { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notify all swapped out hosts, including the pending RVH. 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != swapped_out_hosts_.end(); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++iter) { 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(iter->second->GetSiteInstance(), 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_host()->GetSiteInstance()); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter->second->DisownOpener(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::RendererAbortedProvisionalLoad( 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHost* render_view_host) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We used to cancel the pending renderer here for cross-site downloads. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, it's not safe to do that because the download logic repeatedly 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // looks for this WebContents based on a render view ID. Instead, we just 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // leave the pending renderer around until the next navigation event 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (Navigate, DidNavigate, etc), which will clean it up properly. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(creis): All of this will go away when we move the cross-site logic 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ResourceDispatcherHost, so that we intercept responses rather than 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation events. (That's necessary to support onunload anyway.) Once 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we've made that change, we won't create a pending renderer until we know 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the response is not a download. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::RendererProcessClosing( 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderProcessHost* render_process_host) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any swapped out RVHs from this process, so that we don't try to 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // swap them back in while the process is exiting. Start by finding them, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since there could be more than one. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::list<int> ids_to_remove; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != swapped_out_hosts_.end(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second->GetProcess() == render_process_host) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_to_remove.push_back(iter->first); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now delete them. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!ids_to_remove.empty()) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_[ids_to_remove.back()]->Shutdown(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_.erase(ids_to_remove.back()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids_to_remove.pop_back(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::ShouldClosePage( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool for_cross_site_transition, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool proceed, 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeTicks& proceed_time) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (for_cross_site_transition) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore if we're not in a cross-site navigation. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cross_navigation_pending_) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proceed) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ok to unload the current page, so proceed with the cross-site 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation. Note that if navigations are not currently suspended, it 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // might be because the renderer was deemed unresponsive and this call was 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is ok to do nothing here. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_render_view_host_ && 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_->are_navigations_suspended()) { 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_render_view_host_->SetNavigationsSuspended(false, proceed_time); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current page says to cancel. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPending(); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_ = false; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-cross site transition means closing the entire tab. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool proceed_to_fire_unload; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->BeforeUnloadFiredFromRenderManager(proceed, proceed_time, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &proceed_to_fire_unload); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proceed_to_fire_unload) { 4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If we're about to close the tab and there's a pending RVH, cancel it. 4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Otherwise, if the navigation in the pending RVH completes before the 4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // close in the current RVH, we'll lose the tab close. 4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (pending_render_view_host_) { 4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CancelPending(); 4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) cross_navigation_pending_ = false; 4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is not a cross-site navigation, the tab is being closed. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_->ClosePage(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::OnCrossSiteResponse( 4167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RenderViewHost* pending_render_view_host, 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GlobalRequestID& global_request_id, 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool is_transfer, 4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::vector<GURL>& transfer_url_chain, 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const Referrer& referrer, 4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PageTransition page_transition, 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int64 frame_id, 423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool should_replace_current_entry) { 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This should be called either when the pending RVH is ready to commit or 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // when we realize that the current RVH's request requires a transfer. 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK( 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_render_view_host == pending_render_view_host_ || 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_render_view_host == render_view_host_); 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(creis): Eventually we will want to check all navigation responses 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // here, but currently we pass information for a transfer if 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // ShouldSwapProcessesForRedirect returned true in the network stack. 4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // In that case, we should set up a transfer after the unload handler runs. 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If is_transfer is false, we will just run the unload handler and resume. 4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_nav_params_.reset(new PendingNavigationParams( 4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) global_request_id, is_transfer, transfer_url_chain, referrer, 437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) page_transition, frame_id, should_replace_current_entry)); 4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Run the unload handler of the current page. 4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SwapOutOldPage(); 4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::SwapOutOldPage() { 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Should only see this while we have a pending renderer or transfer. 4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(cross_navigation_pending_ || pending_nav_params_.get()); 4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Tell the renderer to suppress any further modal dialogs so that we can swap 448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // it out. This must be done before canceling any current dialog, in case 449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // there is a loop creating additional dialogs. 450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) render_view_host_->SuppressDialogsUntilSwapOut(); 451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Now close any modal dialogs that would prevent us from swapping out. This 453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is 454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // no longer on the stack when we send the SwapOut message. 4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delegate_->CancelModalDialogsForRenderManager(); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the old renderer it is being swapped out. This will fire the unload 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handler (without firing the beforeunload handler a second time). When the 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unload handler finishes and the navigation completes, we will send a 4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // message to the ResourceDispatcherHost, allowing the pending RVH's response 4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // to resume. 4627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) render_view_host_->SwapOut(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ResourceDispatcherHost has told us to run the onunload handler, which 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // means it is not a download or unsafe page, and we are going to perform the 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation. Thus, we no longer need to remember that the RenderViewHost 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is part of a pending cross-site request. 4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (pending_render_view_host_) 4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_render_view_host_->SetHasPendingCrossSiteRequest(false); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::Observe( 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NotificationSource& source, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NotificationDetails& details) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case NOTIFICATION_RENDERER_PROCESS_CLOSED: 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NOTIFICATION_RENDERER_PROCESS_CLOSING: 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RendererProcessClosing( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Source<RenderProcessHost>(source).ptr()); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::ShouldTransitionCrossSite() { 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // False in the single-process mode, as it makes RVHs to accumulate 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // in swapped_out_hosts_. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if we are using process-per-site-instance (default) or 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process-per-site (kProcessPerSite). 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation( 499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const NavigationEntry* current_entry, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationEntryImpl* new_entry) const { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(new_entry); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If new_entry already has a SiteInstance, assume it is correct and use it. 504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (new_entry->site_instance()) 505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for reasons to swap processes even if we are in a process model that 508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // doesn't usually swap (e.g., process-per-tab). Any time we return true, 509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the new_entry will be rendered in a new SiteInstance AND BrowsingInstance. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We use the effective URL here, since that's what is used in the 512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // SiteInstance's site and when we later call IsSameWebSite. If there is no 513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // current_entry, check the current SiteInstance's site, which might already 514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // be committed to a Web UI URL (such as the NTP). 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserContext* browser_context = 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->GetControllerForRenderManager().GetBrowserContext(); 517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const GURL& current_url = (current_entry) ? 518f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstanceImpl::GetEffectiveURL(browser_context, 519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) current_entry->GetURL()) : 520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) render_view_host_->GetSiteInstance()->GetSiteURL(); 521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context, 522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new_entry->GetURL()); 523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 52481d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch // Don't force a new BrowsingInstance for debug URLs that are handled in the 52581d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch // renderer process, like javascript: or chrome://crash. 52681d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch if (IsRendererDebugURL(new_url)) 52781d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch return false; 52881d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch 529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // For security, we should transition between processes when one is a Web UI 530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // page and one isn't. 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_context, current_url)) { 533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If so, force a swap if destination is not an acceptable URL for Web UI. 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Here, data URLs are never allowed. 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( 536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context, new_url, false)) { 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 540f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Force a swap if it's a Web UI URL. 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context, new_url)) { 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Check with the content client as well. Important to pass current_url here, 548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // which uses the SiteInstance's site if there is no current_entry. 549f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (GetContentClient()->browser()->ShouldSwapBrowsingInstancesForNavigation( 550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) render_view_host_->GetSiteInstance(), current_url, new_url)) { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't switch a RenderView between view source and non-view source mode 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without screwing up the session history sometimes (when navigating between 556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat 557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // it as a new navigation). So require a BrowsingInstance switch. 558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_entry && 559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode()) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::ShouldReuseWebUI( 566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const NavigationEntry* current_entry, 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationEntryImpl* new_entry) const { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationControllerImpl& controller = 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->GetControllerForRenderManager(); 570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_entry && web_ui_.get() && 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller.GetBrowserContext(), current_entry->GetURL()) == 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller.GetBrowserContext(), new_entry->GetURL())); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry( 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationEntryImpl& entry, 579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstance* current_instance, 580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool force_browsing_instance_swap) { 581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Determine which SiteInstance to use for navigating to |entry|. 582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const GURL& dest_url = entry.GetURL(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationControllerImpl& controller = 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->GetControllerForRenderManager(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserContext* browser_context = controller.GetBrowserContext(); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If a swap is required, we need to force the SiteInstance AND 588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // BrowsingInstance to be different ones, using CreateForURL. 589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (force_browsing_instance_swap) { 590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We shouldn't be forcing a swap if an entry already has a SiteInstance. 591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK(!entry.site_instance()); 592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SiteInstance::CreateForURL(browser_context, dest_url); 593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the entry has an instance already we should use it. 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry.site_instance()) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry.site_instance(); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (UGLY) HEURISTIC, process-per-site only: 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this navigation is generated, then it probably corresponds to a search 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // query. Given that search results typically lead to users navigating to 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other sites, we don't really want to use the search engine hostname to 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // determine the site instance for this navigation. 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This can be removed once we have a way to transition between 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RenderViews in response to a link click. 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) && 6107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PageTransitionCoreTypeIs(entry.GetTransitionType(), 6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PAGE_TRANSITION_GENERATED)) { 612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_instance; 6137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstanceImpl* current_site_instance = 616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static_cast<SiteInstanceImpl*>(current_instance); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for this entry. We won't commit the SiteInstance to this site until the 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation commits (in DidNavigate), unless the navigation entry was 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // restored or it's a Web UI as described below. 622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!current_site_instance->HasSite()) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we've already created a SiteInstance for our destination, we don't 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to use this unused SiteInstance; use the existing one. (We don't 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // do this check if the current_instance has a site, because for now, we 626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // want to compare against the current URL and not the SiteInstance's site. 627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // In this case, there is no current URL, so comparing against the site is 628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // ok. See additional comments below.) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also, if the URL should use process-per-site mode and there is an 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // existing process for the site, we should use it. We can call 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetRelatedSiteInstance() for this, which will eagerly set the site and 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thus use the correct process. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_process_per_site = 6357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RenderProcessHost::ShouldUseProcessPerSite(browser_context, dest_url) && 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url); 637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_site_instance->HasRelatedSiteInstance(dest_url) || 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_process_per_site) { 639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_site_instance->GetRelatedSiteInstance(dest_url); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For extensions, Web UI URLs (such as the new tab page), and apps we do 643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // not want to use the current_instance if it has no site, since it will 644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance for 645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this URL instead (with the correct process type). 646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_site_instance->HasWrongProcessForURL(dest_url)) 647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_site_instance->GetRelatedSiteInstance(dest_url); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // View-source URLs must use a new SiteInstance and BrowsingInstance. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(nasko): This is the same condition as later in the function. This 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be taken into account when refactoring this method as part of 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/123007. 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry.IsViewSourceMode()) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SiteInstance::CreateForURL(browser_context, dest_url); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are navigating from a blank SiteInstance to a WebUI, make sure we 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // create a new SiteInstance. 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_context, dest_url)) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SiteInstance::CreateForURL(browser_context, dest_url); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normally the "site" on the SiteInstance is set lazily when the load 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually commits. This is to support better process sharing in case 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the site redirects to some other site: we want to use the destination 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // site in the site instance. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the case of session restore, as it loads all the pages immediately 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we need to set the site first, otherwise after a restore none of the 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pages would share renderers in process-per-site. 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE) 672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) current_site_instance->SetSite(dest_url); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_site_instance; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Otherwise, only create a new SiteInstance for a cross-site navigation. 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(creis): Once we intercept links and script-based navigations, we 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be able to enforce that all entries in a SiteInstance actually have 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same site, and it will be safe to compare the URL against the 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SiteInstance's site, as follows: 683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // const GURL& current_url = current_instance->site(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, though, we're in a hybrid model where you only switch 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SiteInstances if you type in a cross-site URL. This means we have to 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compare the entry's URL to the last committed entry's URL. 687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NavigationEntry* current_entry = controller.GetLastCommittedEntry(); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (interstitial_page_) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The interstitial is currently the last committed entry, but we want to 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compare against the last non-interstitial entry. 691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) current_entry = controller.GetEntryAtOffset(-1); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 693f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If there is no last non-interstitial entry (and current_instance already 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has a site), then we must have been opened from another tab. We want 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to compare against the URL of the page that opened us, but we can't 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get to it directly. The best we can do is check against the site of 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the SiteInstance. This will be correct when we intercept links and 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // script-based navigations, but for now, it could place some pages in a 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new process unnecessarily. We should only hit this case if a page tries 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to open a new tab to an interstitial-inducing URL, and then navigates 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the page to a different same-site URL. (This seems very unlikely in 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // practice.) 703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const GURL& current_url = (current_entry) ? current_entry->GetURL() : 704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) current_instance->GetSiteURL(); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // View-source URLs must use a new SiteInstance and BrowsingInstance. 70781d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch // We don't need a swap when going from view-source to a debug URL like 70881d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch // chrome://crash, however. 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(creis): Refactor this method so this duplicated code isn't needed. 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://crbug.com/123007. 711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_entry && 71281d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch current_entry->IsViewSourceMode() != entry.IsViewSourceMode() && 71381d04fa4ca6b8e7c49e7a3401149aa77d5b4f381Ben Murdoch !IsRendererDebugURL(dest_url)) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SiteInstance::CreateForURL(browser_context, dest_url); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the current SiteInstance for same site navigations, as long as the 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process type is correct. (The URL may have been installed as an app since 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the last time we visited it.) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) && 721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !current_site_instance->HasWrongProcessForURL(dest_url)) { 722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_instance; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 724f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Start the new renderer in a new SiteInstance, but in the current 726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // BrowsingInstance. It is important to immediately give this new 727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // SiteInstance to a RenderViewHost (if it is different than our current 728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // SiteInstance), so that it is ref counted. This will happen in 729f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // CreateRenderView. 730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return current_instance->GetRelatedSiteInstance(dest_url); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int RenderFrameHostManager::CreateRenderView( 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SiteInstance* instance, 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int opener_route_id, 7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool swapped_out, 7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool hidden) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(instance); 7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden. 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We are creating a pending or swapped out RVH here. We should never create 742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // it in the same SiteInstance as our current RVH. 743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_NE(render_view_host_->GetSiteInstance(), instance); 744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we've already created an RVH for this SiteInstance. If so, try 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to re-use the existing one, which has already been initialized. We'll 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remove it from the list of swapped out hosts if it commits. 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* new_render_view_host = static_cast<RenderViewHostImpl*>( 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSwappedOutRenderViewHost(instance)); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_render_view_host) { 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent the process from exiting while we're trying to use it. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!swapped_out) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_render_view_host->GetProcess()->AddPendingView(); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new RenderViewHost if we don't find an existing one. 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_render_view_host = static_cast<RenderViewHostImpl*>( 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostFactory::Create(instance, 758a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch render_view_delegate_, 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) render_frame_delegate_, 760a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch render_widget_delegate_, 761a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch MSG_ROUTING_NONE, 762a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch MSG_ROUTING_NONE, 7633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) swapped_out, 7643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) hidden)); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the new RVH is swapped out already, store it. Otherwise prevent the 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process from exiting while we're trying to navigate in it. 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (swapped_out) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_[instance->GetId()] = new_render_view_host; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_render_view_host->GetProcess()->AddPendingView(); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = InitRenderView(new_render_view_host, opener_route_id); 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't show the view until we get a DidNavigate from it. 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_render_view_host->GetView()->Hide(); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!swapped_out) { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPending(); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use this as our new pending RVH if it isn't swapped out. 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!swapped_out) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_ = new_render_view_host; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_render_view_host->GetRoutingID(); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 790f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, 791f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int opener_route_id) { 79268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If the pending navigation is to a WebUI and the RenderView is not in a 79368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // guest process, tell the RenderView about any bindings it will need enabled. 794f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (pending_web_ui() && !render_view_host->GetProcess()->IsGuest()) { 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host->AllowBindings(pending_web_ui()->GetBindings()); 796f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 797f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled 798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // process unless it's swapped out. 799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RenderViewHostImpl* rvh_impl = 800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<RenderViewHostImpl*>(render_view_host); 801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!rvh_impl->is_swapped_out()) { 802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) render_view_host->GetProcess()->GetID())); 804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 805f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return delegate_->CreateRenderViewForRenderManager(render_view_host, 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opener_route_id); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 811f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::CommitPending() { 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check whether we're going to want to focus the location bar after 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this commit. We do this now because the navigation hasn't formally 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // committed yet, so if we've already cleared |pending_web_ui_| the call chain 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this triggers won't be able to figure out what's going on. 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We expect SwapOutOldPage to have canceled any modal dialogs and told the 819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // renderer to suppress any further dialogs until it is swapped out. However, 820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // crash reports indicate that it's still possible for modal dialogs to exist 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // at this point, which poses a risk if we delete their RenderViewHost below. 822a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Cancel them again to be safe. http://crbug.com/324320. 823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) delegate_->CancelModalDialogsForRenderManager(); 824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next commit the Web UI, if any. Either replace |web_ui_| with 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // leave |web_ui_| as is if reusing it. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); 82933bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch if (pending_web_ui_) { 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_ui_.reset(pending_web_ui_.release()); 83133bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch } else if (!pending_and_current_web_ui_.get()) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_ui_.reset(); 83333bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch } else { 83433bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); 83533bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch pending_and_current_web_ui_.reset(); 83633bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch } 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible for the pending_render_view_host_ to be NULL when we aren't 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // crossing process boundaries. If so, we just needed to handle the Web UI 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // committing above and we're done. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pending_render_view_host_) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (will_focus_location_bar) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetFocusToLocationBar(false); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remember if the page was focused so we can focus the new renderer in 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that case. 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool focus_render_view = !will_focus_location_bar && 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_->GetView() && render_view_host_->GetView()->HasFocus(); 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Swap in the pending view and make it active. Also ensure the FrameTree 8534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // stays in sync. 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* old_render_view_host = render_view_host_; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_ = pending_render_view_host_; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_ = NULL; 8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_host_->AttachToFrameTree(); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The process will no longer try to exit, so we can decrement the count. 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_->GetProcess()->RemovePendingView(); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If the view is gone, then this RenderViewHost died while it was hidden. 86368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // We ignored the RenderProcessGone call at the time, so we should send it now 86468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // to make sure the sad tab shows up, etc. 86568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!render_view_host_->GetView()) 86668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) delegate_->RenderProcessGoneFromRenderManager(render_view_host_); 86768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) else if (!delegate_->IsHidden()) 86868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) render_view_host_->GetView()->Show(); 86968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Hide the old view now that the new one is visible. 8714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (old_render_view_host->GetView()) { 8724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) old_render_view_host->GetView()->Hide(); 8734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) old_render_view_host->WasSwappedOut(); 8744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 8754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the size is up to date. (Fix for bug 1079768.) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->UpdateRenderViewSizeForRenderManager(); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (will_focus_location_bar) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetFocusToLocationBar(false); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (focus_render_view && render_view_host_->GetView()) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHostViewPort::FromRWHV(render_view_host_->GetView())->Focus(); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Notify that we've swapped RenderViewHosts. We do this 8854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // before shutting down the RVH so that we can clean up 8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // RendererResources related to the RVH first. 8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delegate_->NotifySwappedFromRenderManager(old_render_view_host, 8884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) render_view_host_); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the pending view was on the swapped out list, we can remove it. 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_.erase(render_view_host_->GetSiteInstance()->GetId()); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If there are no active RVHs in this SiteInstance, it means that 8947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // this RVH was the last active one in the SiteInstance. Now that we 8957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // know that all RVHs are swapped out, we can delete all the RVHs in 8967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // this SiteInstance. 8977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!static_cast<SiteInstanceImpl*>(old_render_view_host->GetSiteInstance())-> 8987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch active_view_count()) { 8997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ShutdownRenderViewHostsInSiteInstance( 9007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch old_render_view_host->GetSiteInstance()->GetId()); 9017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This is deleted while cleaning up the SitaInstance's views. 9027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch old_render_view_host = NULL; 9037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (old_render_view_host->IsRenderViewLive()) { 9047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the old RVH is live, we are swapping it out and should keep track of 9057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // it in case we navigate back to it. 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(old_render_view_host->is_swapped_out()); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temp fix for http://crbug.com/90867 until we do a better cleanup to make 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sure we don't get different rvh instances for the same site instance 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the same rvhmgr. 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(creis): Clean this up. 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 old_site_instance_id = 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_render_view_host->GetSiteInstance()->GetId(); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostMap::iterator iter = 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_.find(old_site_instance_id); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != swapped_out_hosts_.end() && 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second != old_render_view_host) { 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown the RVH that will be replaced in the map to avoid a leak. 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->Shutdown(); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_[old_site_instance_id] = old_render_view_host; 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_render_view_host->Shutdown(); 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_render_view_host = NULL; // Shutdown() deletes it. 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::ShutdownRenderViewHostsInSiteInstance( 9287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int32 site_instance_id) { 9297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // First remove any swapped out RVH for this SiteInstance from our 9307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // list. 9317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch swapped_out_hosts_.erase(site_instance_id); 9327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 93358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<RenderWidgetHostIterator> widgets( 93458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RenderWidgetHostImpl::GetAllRenderWidgetHosts()); 93558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) while (RenderWidgetHost* widget = widgets->GetNextHost()) { 93658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!widget->IsRenderView()) 9377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch continue; 9387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RenderViewHostImpl* rvh = 93958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) static_cast<RenderViewHostImpl*>(RenderViewHost::From(widget)); 94058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (site_instance_id == rvh->GetSiteInstance()->GetId()) 94158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) rvh->Shutdown(); 9427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderViewHostImpl* RenderFrameHostManager::UpdateRendererStateForNavigate( 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationEntryImpl& entry) { 947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If we are currently navigating cross-process, we want to get back to normal 948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // and then navigate as usual. 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cross_navigation_pending_) { 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_render_view_host_) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPending(); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_ = false; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // render_view_host_'s SiteInstance and new_instance will not be deleted 956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // before the end of this method, so we don't have to worry about their ref 957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // counts dropping to zero. 958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstance* current_instance = render_view_host_->GetSiteInstance(); 959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SiteInstance* new_instance = current_instance; 960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We do not currently swap processes for navigations in webview tag guests. 962f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme); 963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 964f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Determine if we need a new BrowsingInstance for this entry. If true, this 965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // implies that it will get a new SiteInstance (and likely process), and that 966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // other tabs in the current BrosingInstance will be unalbe to script it. 967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This is used for cases that require a process swap even in the 968f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // process-per-tab model, such as WebUI pages. 969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const NavigationEntry* current_entry = 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->GetLastCommittedNavigationEntryForRenderManager(); 971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool force_swap = !is_guest_scheme && 972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap)) 974f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 976f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If force_swap is true, we must use a different SiteInstance. If we didn't, 977f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // we would have two RenderViewHosts in the same SiteInstance and the same 978f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // tab, resulting in page_id conflicts for their NavigationEntries. 979f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (force_swap) 980f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK_NE(new_instance, current_instance); 981f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 982f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (new_instance != current_instance) { 983f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // New SiteInstance: create a pending RVH to navigate. 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!cross_navigation_pending_); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will possibly create (set to NULL) a Web UI object for the pending 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // page. We'll use this later to give the page special access. This must 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen before the new renderer is created below so it will get bindings. 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It must also happen after the above conditional call to CancelPending(), 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise CancelPending may clear the pending_web_ui_ and the page will 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not have its bindings set appropriately. 9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetPendingWebUI(entry); 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that we have created RVHs for the new RVH's opener chain if 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are staying in the same BrowsingInstance. This allows the pending RVH 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to send cross-process script calls to its opener(s). 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int opener_route_id = MSG_ROUTING_NONE; 998f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (new_instance->IsRelatedSiteInstance(current_instance)) { 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opener_route_id = 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->CreateOpenerRenderViewsForRenderManager(new_instance); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a non-swapped-out pending RVH with the given opener and navigate 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it. 10053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int route_id = CreateRenderView(new_instance, opener_route_id, false, 10063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delegate_->IsHidden()); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (route_id == MSG_ROUTING_NONE) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if our current RVH is live before we set up a transition. 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!render_view_host_->IsRenderViewLive()) { 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cross_navigation_pending_) { 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current RVH is not live. There's no reason to sit around with a 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sad tab or a newly created RVH while we wait for the pending RVH to 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigate. Just switch to the pending RVH now and go back to non 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cross-navigating (Note that we don't care about on{before}unload 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handlers if the current RVH isn't live.) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommitPending(); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_view_host_; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_view_host_; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, it's safe to treat this as a pending cross-site transition. 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We need to wait until the beforeunload handler has run, unless we are 1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transferring an existing request (in which case it has already run). 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Suspend the new render view (i.e., don't let it send the cross-site 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Navigate message) until we hear back from the old renderer's 1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // beforeunload handler. If the handler returns false, we'll have to 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cancel the request. 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pending_render_view_host_->are_navigations_suspended()); 1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool is_transfer = 1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry.transferred_global_request_id() != GlobalRequestID(); 10364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (is_transfer) { 10374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We don't need to stop the old renderer or run beforeunload/unload 10384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // handlers, because those have already been done. 10394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(pending_nav_params_->global_request_id == 10404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) entry.transferred_global_request_id()); 10414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Also make sure the old render view stops, in case a load is in 1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // progress. (We don't want to do this for transfers, since it will 1044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // interrupt the transfer with an unexpected DidStopLoading.) 1045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) render_view_host_->Send( 1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new ViewMsg_Stop(render_view_host_->GetRoutingID())); 1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pending_render_view_host_->SetNavigationsSuspended(true, 1049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeTicks()); 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Tell the CrossSiteRequestManager that this RVH has a pending cross-site 10524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // request, so that ResourceDispatcherHost will know to tell us to run the 10534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // old page's unload handler before it sends the response. 10544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pending_render_view_host_->SetHasPendingCrossSiteRequest(true); 10554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We now have a pending RVH. 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!cross_navigation_pending_); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cross_navigation_pending_ = true; 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1061c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Unless we are transferring an existing request, we should now 1062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // tell the old render view to run its beforeunload handler, since it 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doesn't otherwise know that the cross-site request is happening. This 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will trigger a call to ShouldClosePage with the reply. 1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_transfer) 1066c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) render_view_host_->FirePageBeforeUnload(true); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pending_render_view_host_; 1069f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1070f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1071f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Otherwise the same SiteInstance can be used. Navigate render_view_host_. 1072f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!cross_navigation_pending_); 1073f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (ShouldReuseWebUI(current_entry, &entry)) { 1074f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_web_ui_.reset(); 1075f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_and_current_web_ui_ = web_ui_->AsWeakPtr(); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1077f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SetPendingWebUI(entry); 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1079f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Make sure the new RenderViewHost has the right bindings. 1080f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (pending_web_ui() && !render_view_host_->GetProcess()->IsGuest()) 1081f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) render_view_host_->AllowBindings(pending_web_ui()->GetBindings()); 1082f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1084f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (pending_web_ui() && render_view_host_->IsRenderViewLive()) 1085f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_web_ui()->GetController()->RenderViewReused(render_view_host_); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1087f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The renderer can exit view source mode when any error or cancellation 1088f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // happen. We must overwrite to recover the mode. 1089f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (entry.IsViewSourceMode()) { 1090f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) render_view_host_->Send( 1091f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ViewMsg_EnableViewSourceMode(render_view_host_->GetRoutingID())); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_view_host_; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1097f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::CancelPending() { 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* pending_render_view_host = pending_render_view_host_; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_ = NULL; 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewDevToolsAgentHost::OnCancelPendingNavigation( 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host, 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host_); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We no longer need to prevent the process from exiting. 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host->GetProcess()->RemovePendingView(); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The pending RVH may already be on the swapped out list if we started to 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // swap it back in and then canceled. If so, make sure it gets swapped out 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // again. If it's not on the swapped out list (e.g., aborting a pending 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load), then it's safe to shut down. 1112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (IsOnSwappedOutList(pending_render_view_host)) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any currently suspended navigations are no longer needed. 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host->CancelSuspendedNavigations(); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pending_render_view_host->SwapOut(); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We won't be coming back, so shut this one down. 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host->Shutdown(); 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_web_ui_.reset(); 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_and_current_web_ui_.reset(); 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RenderFrameHostManager::RenderViewDeleted(RenderViewHost* rvh) { 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are doing this in order to work around and to track a crasher 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (http://crbug.com/23411) where it seems that pending_render_view_host_ is 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deleted (not sure from where) but not NULLed. 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rvh == pending_render_view_host_) { 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If you hit this NOTREACHED, please report it in the following bug 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/23411 Make sure to include what you were doing when it 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happened (navigating to a new page, closing a tab...) and if you can 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reproduce. 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_render_view_host_ = NULL; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure deleted RVHs are not kept in the swapped out list while we are 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // still alive. (If render_view_host_ is null, we're already being deleted.) 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!render_view_host_) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't look it up by SiteInstance ID, which may no longer be valid. 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RenderViewHostMap::iterator iter = swapped_out_hosts_.begin(); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != swapped_out_hosts_.end(); 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second == rvh) { 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swapped_out_hosts_.erase(iter); 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool RenderFrameHostManager::IsOnSwappedOutList(RenderViewHost* rvh) const { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rvh->GetSiteInstance()) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RenderViewHostMap::const_iterator iter = swapped_out_hosts_.find( 1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rvh->GetSiteInstance()->GetId()); 1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (iter == swapped_out_hosts_.end()) 1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return iter->second == rvh; 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RenderViewHostImpl* RenderFrameHostManager::GetSwappedOutRenderViewHost( 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SiteInstance* instance) { 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostMap::iterator iter = swapped_out_hosts_.find(instance->GetId()); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != swapped_out_hosts_.end()) 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return iter->second; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 1176