render_frame_host_manager.h revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ 6#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ 7 8#include "base/basictypes.h" 9#include "base/logging.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/memory/weak_ptr.h" 12#include "content/browser/renderer_host/render_view_host_delegate.h" 13#include "content/browser/site_instance_impl.h" 14#include "content/common/content_export.h" 15#include "content/public/browser/notification_observer.h" 16#include "content/public/browser/notification_registrar.h" 17#include "content/public/common/referrer.h" 18 19 20namespace content { 21class BrowserContext; 22class InterstitialPageImpl; 23class NavigationControllerImpl; 24class NavigationEntry; 25class NavigationEntryImpl; 26class RenderFrameHostDelegate; 27class RenderFrameHostManagerTest; 28class RenderViewHost; 29class RenderViewHostImpl; 30class RenderWidgetHostDelegate; 31class RenderWidgetHostView; 32class TestWebContents; 33class WebUIImpl; 34 35// Manages RenderFrameHosts for a FrameTreeNode. This class acts as a state 36// machine to make cross-process navigations in a frame possible. 37class CONTENT_EXPORT RenderFrameHostManager 38 : public RenderViewHostDelegate::RendererManagement, 39 public NotificationObserver { 40 public: 41 // Functions implemented by our owner that we need. 42 // 43 // TODO(brettw) Clean this up! These are all the functions in WebContentsImpl 44 // that are required to run this class. The design should probably be better 45 // such that these are more clear. 46 // 47 // There is additional complexity that some of the functions we need in 48 // WebContentsImpl are inherited and non-virtual. These are named with 49 // "RenderManager" so that the duplicate implementation of them will be clear. 50 class CONTENT_EXPORT Delegate { 51 public: 52 // Initializes the given renderer if necessary and creates the view ID 53 // corresponding to this view host. If this method is not called and the 54 // process is not shared, then the WebContentsImpl will act as though the 55 // renderer is not running (i.e., it will render "sad tab"). This method is 56 // automatically called from LoadURL. 57 // 58 // If you are attaching to an already-existing RenderView, you should call 59 // InitWithExistingID. 60 virtual bool CreateRenderViewForRenderManager( 61 RenderViewHost* render_view_host, int opener_route_id) = 0; 62 virtual void BeforeUnloadFiredFromRenderManager( 63 bool proceed, const base::TimeTicks& proceed_time, 64 bool* proceed_to_fire_unload) = 0; 65 virtual void RenderProcessGoneFromRenderManager( 66 RenderViewHost* render_view_host) = 0; 67 virtual void UpdateRenderViewSizeForRenderManager() = 0; 68 virtual void CancelModalDialogsForRenderManager() = 0; 69 virtual void NotifySwappedFromRenderManager( 70 RenderViewHost* old_host, RenderViewHost* new_host) = 0; 71 virtual NavigationControllerImpl& 72 GetControllerForRenderManager() = 0; 73 74 // Create swapped out RenderViews in the given SiteInstance for each tab in 75 // the opener chain of this tab, if any. This allows the current tab to 76 // make cross-process script calls to its opener(s). Returns the route ID 77 // of the immediate opener, if one exists (otherwise MSG_ROUTING_NONE). 78 virtual int CreateOpenerRenderViewsForRenderManager( 79 SiteInstance* instance) = 0; 80 81 // Creates a WebUI object for the given URL if one applies. Ownership of the 82 // returned pointer will be passed to the caller. If no WebUI applies, 83 // returns NULL. 84 virtual WebUIImpl* CreateWebUIForRenderManager(const GURL& url) = 0; 85 86 // Returns the navigation entry of the current navigation, or NULL if there 87 // is none. 88 virtual NavigationEntry* 89 GetLastCommittedNavigationEntryForRenderManager() = 0; 90 91 // Returns true if the location bar should be focused by default rather than 92 // the page contents. The view calls this function when the tab is focused 93 // to see what it should do. 94 virtual bool FocusLocationBarByDefault() = 0; 95 96 // Focuses the location bar. 97 virtual void SetFocusToLocationBar(bool select_all) = 0; 98 99 // Creates a view and sets the size for the specified RVH. 100 virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) = 0; 101 102 // Returns true if views created for this delegate should be created in a 103 // hidden state. 104 virtual bool IsHidden() = 0; 105 106 protected: 107 virtual ~Delegate() {} 108 }; 109 110 // All three delegate pointers must be non-NULL and are not owned by this 111 // class. They must outlive this class. The RenderViewHostDelegate and 112 // RenderWidgetHostDelegate are what will be installed into all 113 // RenderViewHosts that are created. 114 // 115 // You must call Init() before using this class. 116 RenderFrameHostManager( 117 RenderFrameHostDelegate* render_frame_delegate, 118 RenderViewHostDelegate* render_view_delegate, 119 RenderWidgetHostDelegate* render_widget_delegate, 120 Delegate* delegate); 121 virtual ~RenderFrameHostManager(); 122 123 // For arguments, see WebContentsImpl constructor. 124 void Init(BrowserContext* browser_context, 125 SiteInstance* site_instance, 126 int routing_id, 127 int main_frame_routing_id); 128 129 // Returns the currently active RenderViewHost. 130 // 131 // This will be non-NULL between Init() and Shutdown(). You may want to NULL 132 // check it in many cases, however. Windows can send us messages during the 133 // destruction process after it has been shut down. 134 RenderViewHostImpl* current_host() const; 135 136 // Returns the view associated with the current RenderViewHost, or NULL if 137 // there is no current one. 138 RenderWidgetHostView* GetRenderWidgetHostView() const; 139 140 // Returns the pending render view host, or NULL if there is no pending one. 141 RenderViewHostImpl* pending_render_view_host() const; 142 143 // Returns the current committed Web UI or NULL if none applies. 144 WebUIImpl* web_ui() const { return web_ui_.get(); } 145 146 // Returns the Web UI for the pending navigation, or NULL of none applies. 147 WebUIImpl* pending_web_ui() const { 148 return pending_web_ui_.get() ? pending_web_ui_.get() : 149 pending_and_current_web_ui_.get(); 150 } 151 152 // Sets the pending Web UI for the pending navigation, ensuring that the 153 // bindings are appropriate for the given NavigationEntry. 154 void SetPendingWebUI(const NavigationEntryImpl& entry); 155 156 // Called when we want to instruct the renderer to navigate to the given 157 // navigation entry. It may create a new RenderViewHost or re-use an existing 158 // one. The RenderViewHost to navigate will be returned. Returns NULL if one 159 // could not be created. 160 RenderViewHostImpl* Navigate(const NavigationEntryImpl& entry); 161 162 // Instructs the various live views to stop. Called when the user directed the 163 // page to stop loading. 164 void Stop(); 165 166 // Notifies the regular and pending RenderViewHosts that a load is or is not 167 // happening. Even though the message is only for one of them, we don't know 168 // which one so we tell both. 169 void SetIsLoading(bool is_loading); 170 171 // Whether to close the tab or not when there is a hang during an unload 172 // handler. If we are mid-crosssite navigation, then we should proceed 173 // with the navigation instead of closing the tab. 174 bool ShouldCloseTabOnUnresponsiveRenderer(); 175 176 // The RenderViewHost has been swapped out, so we should resume the pending 177 // network response and allow the pending RenderViewHost to commit. 178 void SwappedOut(RenderViewHost* render_view_host); 179 180 // Called when a renderer's main frame navigates. 181 void DidNavigateMainFrame(RenderViewHost* render_view_host); 182 183 // Called when a renderer sets its opener to null. 184 void DidDisownOpener(RenderViewHost* render_view_host); 185 186 // Helper method to create a RenderViewHost. If |swapped_out| is true, it 187 // will be initially placed on the swapped out hosts list. Otherwise, it 188 // will be used for a pending cross-site navigation. 189 int CreateRenderView(SiteInstance* instance, 190 int opener_route_id, 191 bool swapped_out, 192 bool hidden); 193 194 // Called when a provisional load on the given renderer is aborted. 195 void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host); 196 197 // Sets the passed passed interstitial as the currently showing interstitial. 198 // |interstitial_page| should be non NULL (use the remove_interstitial_page 199 // method to unset the interstitial) and no interstitial page should be set 200 // when there is already a non NULL interstitial page set. 201 void set_interstitial_page(InterstitialPageImpl* interstitial_page) { 202 DCHECK(!interstitial_page_ && interstitial_page); 203 interstitial_page_ = interstitial_page; 204 } 205 206 // Unsets the currently showing interstitial. 207 void remove_interstitial_page() { 208 DCHECK(interstitial_page_); 209 interstitial_page_ = NULL; 210 } 211 212 // Returns the currently showing interstitial, NULL if no interstitial is 213 // showing. 214 InterstitialPageImpl* interstitial_page() const { return interstitial_page_; } 215 216 // RenderViewHostDelegate::RendererManagement implementation. 217 virtual void ShouldClosePage( 218 bool for_cross_site_transition, 219 bool proceed, 220 const base::TimeTicks& proceed_time) OVERRIDE; 221 virtual void OnCrossSiteResponse( 222 RenderViewHost* pending_render_view_host, 223 const GlobalRequestID& global_request_id, 224 bool is_transfer, 225 const std::vector<GURL>& transfer_url_chain, 226 const Referrer& referrer, 227 PageTransition page_transition, 228 int64 frame_id, 229 bool should_replace_current_entry) OVERRIDE; 230 231 // NotificationObserver implementation. 232 virtual void Observe(int type, 233 const NotificationSource& source, 234 const NotificationDetails& details) OVERRIDE; 235 236 // Called when a RenderViewHost is about to be deleted. 237 void RenderViewDeleted(RenderViewHost* rvh); 238 239 // Returns whether the given RenderViewHost is on the list of swapped out 240 // RenderViewHosts. 241 bool IsOnSwappedOutList(RenderViewHost* rvh) const; 242 243 // Returns the swapped out RenderViewHost for the given SiteInstance, if any. 244 RenderViewHostImpl* GetSwappedOutRenderViewHost(SiteInstance* instance); 245 246 // Runs the unload handler in the current page, when we know that a pending 247 // cross-process navigation is going to commit. We may initiate a transfer 248 // to a new process after this completes or times out. 249 void SwapOutOldPage(); 250 251 private: 252 friend class RenderFrameHostManagerTest; 253 friend class TestWebContents; 254 255 // Tracks information about a navigation while a cross-process transition is 256 // in progress, in case we need to transfer it to a new RenderViewHost. 257 struct PendingNavigationParams { 258 PendingNavigationParams(); 259 PendingNavigationParams(const GlobalRequestID& global_request_id, 260 bool is_transfer, 261 const std::vector<GURL>& transfer_url, 262 Referrer referrer, 263 PageTransition page_transition, 264 int64 frame_id, 265 bool should_replace_current_entry); 266 ~PendingNavigationParams(); 267 268 // The child ID and request ID for the pending navigation. Present whether 269 // |is_transfer| is true or false. 270 GlobalRequestID global_request_id; 271 272 // Whether this pending navigation needs to be transferred to another 273 // process than the one it was going to commit in. If so, the 274 // |transfer_url|, |referrer|, and |frame_id| parameters will be set. 275 bool is_transfer; 276 277 // If |is_transfer|, this is the URL chain of the request. The first entry 278 // is the original request URL, and the last entry is the destination URL to 279 // request in the new process. 280 std::vector<GURL> transfer_url_chain; 281 282 // If |is_transfer|, this is the referrer to use for the request in the new 283 // process. 284 Referrer referrer; 285 286 // If |is_transfer|, this is the transition type for the original 287 // navigation. 288 PageTransition page_transition; 289 290 // If |is_transfer|, this is the frame ID to use in RequestTransferURL. 291 int64 frame_id; 292 293 // If |is_transfer|, this is whether the navigation should replace the 294 // current history entry. 295 bool should_replace_current_entry; 296 }; 297 298 // Returns whether this tab should transition to a new renderer for 299 // cross-site URLs. Enabled unless we see the --process-per-tab command line 300 // switch. Can be overridden in unit tests. 301 bool ShouldTransitionCrossSite(); 302 303 // Returns true if for the navigation from |current_entry| to |new_entry|, 304 // a new SiteInstance and BrowsingInstance should be created (even if we are 305 // in a process model that doesn't usually swap). This forces a process swap 306 // and severs script connections with existing tabs. Cases where this can 307 // happen include transitions between WebUI and regular web pages. 308 // Either of the entries may be NULL. 309 bool ShouldSwapBrowsingInstancesForNavigation( 310 const NavigationEntry* current_entry, 311 const NavigationEntryImpl* new_entry) const; 312 313 // Returns true if it is safe to reuse the current WebUI when navigating from 314 // |current_entry| to |new_entry|. 315 bool ShouldReuseWebUI( 316 const NavigationEntry* current_entry, 317 const NavigationEntryImpl* new_entry) const; 318 319 // Returns an appropriate SiteInstance object for the given NavigationEntry, 320 // possibly reusing the current SiteInstance. If --process-per-tab is used, 321 // this is only called when ShouldSwapBrowsingInstancesForNavigation returns 322 // true. 323 SiteInstance* GetSiteInstanceForEntry( 324 const NavigationEntryImpl& entry, 325 SiteInstance* current_instance, 326 bool force_browsing_instance_swap); 327 328 // Sets up the necessary state for a new RenderViewHost with the given opener. 329 bool InitRenderView(RenderViewHost* render_view_host, int opener_route_id); 330 331 // Sets the pending RenderViewHost/WebUI to be the active one. Note that this 332 // doesn't require the pending render_view_host_ pointer to be non-NULL, since 333 // there could be Web UI switching as well. Call this for every commit. 334 void CommitPending(); 335 336 // Shutdown all RenderViewHosts in a SiteInstance. This is called 337 // to shutdown views when all the views in a SiteInstance are 338 // confirmed to be swapped out. 339 void ShutdownRenderViewHostsInSiteInstance(int32 site_instance_id); 340 341 // Helper method to terminate the pending RenderViewHost. 342 void CancelPending(); 343 344 RenderViewHostImpl* UpdateRendererStateForNavigate( 345 const NavigationEntryImpl& entry); 346 347 // Called when a renderer process is starting to close. We should not 348 // schedule new navigations in its swapped out RenderViewHosts after this. 349 void RendererProcessClosing(RenderProcessHost* render_process_host); 350 351 // Our delegate, not owned by us. Guaranteed non-NULL. 352 Delegate* delegate_; 353 354 // Whether a navigation requiring different RenderView's is pending. This is 355 // either cross-site request is (in the new process model), or when required 356 // for the view type (like view source versus not). 357 bool cross_navigation_pending_; 358 359 // Implemented by the owner of this class, these delegates are installed into 360 // all the RenderViewHosts that we create. 361 RenderFrameHostDelegate* render_frame_delegate_; 362 RenderViewHostDelegate* render_view_delegate_; 363 RenderWidgetHostDelegate* render_widget_delegate_; 364 365 // Our RenderView host and its associated Web UI (if any, will be NULL for 366 // non-DOM-UI pages). This object is responsible for all communication with 367 // a child RenderView instance. 368 RenderViewHostImpl* render_view_host_; 369 scoped_ptr<WebUIImpl> web_ui_; 370 371 // A RenderViewHost used to load a cross-site page. This remains hidden 372 // while a cross-site request is pending until it calls DidNavigate. It may 373 // have an associated Web UI, in which case the Web UI pointer will be non- 374 // NULL. 375 // 376 // The |pending_web_ui_| may be non-NULL even when the 377 // |pending_render_view_host_| is NULL. This will happen when we're 378 // transitioning between two Web UI pages: the RVH won't be swapped, so the 379 // pending pointer will be unused, but there will be a pending Web UI 380 // associated with the navigation. 381 RenderViewHostImpl* pending_render_view_host_; 382 383 // Tracks information about any current pending cross-process navigation. 384 scoped_ptr<PendingNavigationParams> pending_nav_params_; 385 386 // If either of these is non-NULL, the pending navigation is to a chrome: 387 // page. The scoped_ptr is used if pending_web_ui_ != web_ui_, the WeakPtr is 388 // used for when they reference the same object. If either is non-NULL, the 389 // other should be NULL. 390 scoped_ptr<WebUIImpl> pending_web_ui_; 391 base::WeakPtr<WebUIImpl> pending_and_current_web_ui_; 392 393 // A map of site instance ID to swapped out RenderViewHosts. This may include 394 // pending_render_view_host_ for navigations to existing entries. 395 typedef base::hash_map<int32, RenderViewHostImpl*> RenderViewHostMap; 396 RenderViewHostMap swapped_out_hosts_; 397 398 // The intersitial page currently shown if any, not own by this class 399 // (the InterstitialPage is self-owned, it deletes itself when hidden). 400 InterstitialPageImpl* interstitial_page_; 401 402 NotificationRegistrar registrar_; 403 404 DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManager); 405}; 406 407} // namespace content 408 409#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ 410