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/global_request_id.h" 16 #include "content/public/browser/notification_observer.h" 17 #include "content/public/browser/notification_registrar.h" 18 #include "content/public/common/referrer.h" 19 #include "ui/base/page_transition_types.h" 20 21 struct FrameHostMsg_BeginNavigation_Params; 22 struct FrameMsg_Navigate_Params; 23 24 namespace content { 25 class BrowserContext; 26 class CrossProcessFrameConnector; 27 class CrossSiteTransferringRequest; 28 class InterstitialPageImpl; 29 class FrameTreeNode; 30 class NavigationControllerImpl; 31 class NavigationEntry; 32 class NavigationEntryImpl; 33 class NavigationRequest; 34 class RenderFrameHost; 35 class RenderFrameHostDelegate; 36 class RenderFrameHost; 37 class RenderFrameHostImpl; 38 class RenderFrameHostManagerTest; 39 class RenderFrameProxyHost; 40 class RenderViewHost; 41 class RenderViewHostImpl; 42 class RenderWidgetHostDelegate; 43 class RenderWidgetHostView; 44 class TestWebContents; 45 class WebUIImpl; 46 struct NavigationBeforeCommitInfo; 47 48 // Manages RenderFrameHosts for a FrameTreeNode. This class acts as a state 49 // machine to make cross-process navigations in a frame possible. 50 class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver { 51 public: 52 // Functions implemented by our owner that we need. 53 // 54 // TODO(brettw) Clean this up! These are all the functions in WebContentsImpl 55 // that are required to run this class. The design should probably be better 56 // such that these are more clear. 57 // 58 // There is additional complexity that some of the functions we need in 59 // WebContentsImpl are inherited and non-virtual. These are named with 60 // "RenderManager" so that the duplicate implementation of them will be clear. 61 // 62 // Functions and parameters whose description are prefixed by PlzNavigate are 63 // part of a navigation refactoring project, currently behind the 64 // enable-browser-side-navigation flag. The idea is to move the logic behind 65 // driving navigations from the renderer to the browser. 66 class CONTENT_EXPORT Delegate { 67 public: 68 // Initializes the given renderer if necessary and creates the view ID 69 // corresponding to this view host. If this method is not called and the 70 // process is not shared, then the WebContentsImpl will act as though the 71 // renderer is not running (i.e., it will render "sad tab"). This method is 72 // automatically called from LoadURL. |for_main_frame_navigation| indicates 73 // whether this RenderViewHost is used to render a top-level frame, so the 74 // appropriate RenderWidgetHostView type is used. 75 virtual bool CreateRenderViewForRenderManager( 76 RenderViewHost* render_view_host, 77 int opener_route_id, 78 int proxy_routing_id, 79 bool for_main_frame_navigation) = 0; 80 virtual bool CreateRenderFrameForRenderManager( 81 RenderFrameHost* render_frame_host, 82 int parent_routing_id) = 0; 83 virtual void BeforeUnloadFiredFromRenderManager( 84 bool proceed, const base::TimeTicks& proceed_time, 85 bool* proceed_to_fire_unload) = 0; 86 virtual void RenderProcessGoneFromRenderManager( 87 RenderViewHost* render_view_host) = 0; 88 virtual void UpdateRenderViewSizeForRenderManager() = 0; 89 virtual void CancelModalDialogsForRenderManager() = 0; 90 virtual void NotifySwappedFromRenderManager(RenderFrameHost* old_host, 91 RenderFrameHost* new_host, 92 bool is_main_frame) = 0; 93 virtual NavigationControllerImpl& 94 GetControllerForRenderManager() = 0; 95 96 // Create swapped out RenderViews in the given SiteInstance for each tab in 97 // the opener chain of this tab, if any. This allows the current tab to 98 // make cross-process script calls to its opener(s). Returns the route ID 99 // of the immediate opener, if one exists (otherwise MSG_ROUTING_NONE). 100 virtual int CreateOpenerRenderViewsForRenderManager( 101 SiteInstance* instance) = 0; 102 103 // Creates a WebUI object for the given URL if one applies. Ownership of the 104 // returned pointer will be passed to the caller. If no WebUI applies, 105 // returns NULL. 106 virtual WebUIImpl* CreateWebUIForRenderManager(const GURL& url) = 0; 107 108 // Returns the navigation entry of the current navigation, or NULL if there 109 // is none. 110 virtual NavigationEntry* 111 GetLastCommittedNavigationEntryForRenderManager() = 0; 112 113 // Returns true if the location bar should be focused by default rather than 114 // the page contents. The view calls this function when the tab is focused 115 // to see what it should do. 116 virtual bool FocusLocationBarByDefault() = 0; 117 118 // Focuses the location bar. 119 virtual void SetFocusToLocationBar(bool select_all) = 0; 120 121 // Creates a view and sets the size for the specified RVH. 122 virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) = 0; 123 124 // Returns true if views created for this delegate should be created in a 125 // hidden state. 126 virtual bool IsHidden() = 0; 127 128 protected: ~Delegate()129 virtual ~Delegate() {} 130 }; 131 132 // Used with FrameTree::ForEach to delete RenderFrameHosts pending shutdown 133 // from a FrameTreeNode's RenderFrameHostManager. Used during destruction of 134 // WebContentsImpl. 135 static bool ClearRFHsPendingShutdown(FrameTreeNode* node); 136 137 // All three delegate pointers must be non-NULL and are not owned by this 138 // class. They must outlive this class. The RenderViewHostDelegate and 139 // RenderWidgetHostDelegate are what will be installed into all 140 // RenderViewHosts that are created. 141 // 142 // You must call Init() before using this class. 143 RenderFrameHostManager( 144 FrameTreeNode* frame_tree_node, 145 RenderFrameHostDelegate* render_frame_delegate, 146 RenderViewHostDelegate* render_view_delegate, 147 RenderWidgetHostDelegate* render_widget_delegate, 148 Delegate* delegate); 149 virtual ~RenderFrameHostManager(); 150 151 // For arguments, see WebContentsImpl constructor. 152 void Init(BrowserContext* browser_context, 153 SiteInstance* site_instance, 154 int view_routing_id, 155 int frame_routing_id); 156 157 // Returns the currently active RenderFrameHost. 158 // 159 // This will be non-NULL between Init() and Shutdown(). You may want to NULL 160 // check it in many cases, however. Windows can send us messages during the 161 // destruction process after it has been shut down. current_frame_host()162 RenderFrameHostImpl* current_frame_host() const { 163 return render_frame_host_.get(); 164 } 165 166 // TODO(creis): Remove this when we no longer use RVH for navigation. 167 RenderViewHostImpl* current_host() const; 168 169 // Returns the view associated with the current RenderViewHost, or NULL if 170 // there is no current one. 171 RenderWidgetHostView* GetRenderWidgetHostView() const; 172 173 RenderFrameProxyHost* GetProxyToParent(); 174 175 // Returns the pending RenderFrameHost, or NULL if there is no pending one. pending_frame_host()176 RenderFrameHostImpl* pending_frame_host() const { 177 return pending_render_frame_host_.get(); 178 } 179 180 // TODO(creis): Remove this when we no longer use RVH for navigation. 181 RenderViewHostImpl* pending_render_view_host() const; 182 183 // Returns the current committed Web UI or NULL if none applies. web_ui()184 WebUIImpl* web_ui() const { return web_ui_.get(); } 185 186 // Returns the Web UI for the pending navigation, or NULL of none applies. pending_web_ui()187 WebUIImpl* pending_web_ui() const { 188 return pending_web_ui_.get() ? pending_web_ui_.get() : 189 pending_and_current_web_ui_.get(); 190 } 191 192 // Sets the pending Web UI for the pending navigation, ensuring that the 193 // bindings are appropriate for the given NavigationEntry. 194 void SetPendingWebUI(const NavigationEntryImpl& entry); 195 196 // Called when we want to instruct the renderer to navigate to the given 197 // navigation entry. It may create a new RenderFrameHost or re-use an existing 198 // one. The RenderFrameHost to navigate will be returned. Returns NULL if one 199 // could not be created. 200 RenderFrameHostImpl* Navigate(const NavigationEntryImpl& entry); 201 202 // Instructs the various live views to stop. Called when the user directed the 203 // page to stop loading. 204 void Stop(); 205 206 // Notifies the regular and pending RenderViewHosts that a load is or is not 207 // happening. Even though the message is only for one of them, we don't know 208 // which one so we tell both. 209 void SetIsLoading(bool is_loading); 210 211 // Whether to close the tab or not when there is a hang during an unload 212 // handler. If we are mid-crosssite navigation, then we should proceed 213 // with the navigation instead of closing the tab. 214 bool ShouldCloseTabOnUnresponsiveRenderer(); 215 216 // Confirms whether we should close the page or navigate away. This is called 217 // before a cross-site request or before a tab/window is closed (as indicated 218 // by the first parameter) to allow the appropriate renderer to approve or 219 // deny the request. |proceed| indicates whether the user chose to proceed. 220 // |proceed_time| is the time when the request was allowed to proceed. 221 void OnBeforeUnloadACK(bool for_cross_site_transition, 222 bool proceed, 223 const base::TimeTicks& proceed_time); 224 225 // The |pending_render_frame_host| is ready to commit a page. We should 226 // ensure that the old RenderFrameHost runs its unload handler first and 227 // determine whether a RenderFrameHost transfer is needed. 228 // |cross_site_transferring_request| is NULL if a request is not being 229 // transferred between renderers. 230 void OnCrossSiteResponse( 231 RenderFrameHostImpl* pending_render_frame_host, 232 const GlobalRequestID& global_request_id, 233 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, 234 const std::vector<GURL>& transfer_url_chain, 235 const Referrer& referrer, 236 ui::PageTransition page_transition, 237 bool should_replace_current_entry); 238 239 // Received a response from CrossSiteResourceHandler. If the navigation 240 // specifies a transition, this is called and the navigation will not resume 241 // until ResumeResponseDeferredAtStart. 242 void OnDeferredAfterResponseStarted( 243 const GlobalRequestID& global_request_id, 244 RenderFrameHostImpl* pending_render_frame_host); 245 246 // Resume navigation paused after receiving response headers. 247 void ResumeResponseDeferredAtStart(); 248 249 // Called when a renderer's frame navigates. 250 void DidNavigateFrame(RenderFrameHostImpl* render_frame_host); 251 252 // Called when a renderer sets its opener to null. 253 void DidDisownOpener(RenderFrameHost* render_frame_host); 254 255 // Helper method to create and initialize a RenderFrameHost. If |swapped_out| 256 // is true, it will be initially placed on the swapped out hosts list. 257 // Returns the routing id of the *view* associated with the frame. 258 int CreateRenderFrame(SiteInstance* instance, 259 int opener_route_id, 260 bool swapped_out, 261 bool for_main_frame_navigation, 262 bool hidden); 263 264 // Helper method to create and initialize a RenderFrameProxyHost and return 265 // its routing id. 266 int CreateRenderFrameProxy(SiteInstance* instance); 267 268 // Sets the passed passed interstitial as the currently showing interstitial. 269 // |interstitial_page| should be non NULL (use the remove_interstitial_page 270 // method to unset the interstitial) and no interstitial page should be set 271 // when there is already a non NULL interstitial page set. set_interstitial_page(InterstitialPageImpl * interstitial_page)272 void set_interstitial_page(InterstitialPageImpl* interstitial_page) { 273 DCHECK(!interstitial_page_ && interstitial_page); 274 interstitial_page_ = interstitial_page; 275 } 276 277 // Unsets the currently showing interstitial. remove_interstitial_page()278 void remove_interstitial_page() { 279 DCHECK(interstitial_page_); 280 interstitial_page_ = NULL; 281 } 282 283 // Returns the currently showing interstitial, NULL if no interstitial is 284 // showing. interstitial_page()285 InterstitialPageImpl* interstitial_page() const { return interstitial_page_; } 286 287 // NotificationObserver implementation. 288 virtual void Observe(int type, 289 const NotificationSource& source, 290 const NotificationDetails& details) OVERRIDE; 291 292 // Returns whether the given RenderFrameHost (or its associated 293 // RenderViewHost) is on the list of swapped out RenderFrameHosts. 294 bool IsRVHOnSwappedOutList(RenderViewHostImpl* rvh) const; 295 bool IsOnSwappedOutList(RenderFrameHostImpl* rfh) const; 296 297 // Returns the swapped out RenderViewHost or RenderFrameHost for the given 298 // SiteInstance, if any. This method is *deprecated* and 299 // GetRenderFrameProxyHost should be used. 300 RenderViewHostImpl* GetSwappedOutRenderViewHost(SiteInstance* instance) const; 301 RenderFrameProxyHost* GetRenderFrameProxyHost( 302 SiteInstance* instance) const; 303 304 // Deletes a RenderFrameHost that was pending shutdown. 305 void ClearPendingShutdownRFHForSiteInstance(int32 site_instance_id, 306 RenderFrameHostImpl* rfh); 307 308 // Deletes any proxy hosts associated with this node. Used during destruction 309 // of WebContentsImpl. 310 void ResetProxyHosts(); 311 312 // Returns the routing id for a RenderFrameHost or RenderFrameHostProxy 313 // that has the given SiteInstance and is associated with this 314 // RenderFrameHostManager. Returns MSG_ROUTING_NONE if none is found. 315 int GetRoutingIdForSiteInstance(SiteInstance* site_instance); 316 317 // PlzNavigate: sends a RequestNavigation IPC to the renderer to ask it to 318 // navigate. If no live renderer is present, then the navigation request will 319 // be sent directly to the ResourceDispatcherHost. 320 bool RequestNavigation(const NavigationEntryImpl& entry, 321 const FrameMsg_Navigate_Params& navigate_params); 322 323 // PlzNavigate: Used to start a navigation. OnBeginNavigation is called 324 // directly by RequestNavigation when there is no live renderer. Otherwise, it 325 // is called following a BeginNavigation IPC from the renderer (which in 326 // browser-initiated navigation also happens after RequestNavigation has been 327 // called). 328 void OnBeginNavigation(const FrameHostMsg_BeginNavigation_Params& params); 329 330 // PlzNavigate: Called when a navigation request has received a response, to 331 // select a renderer to use for the navigation. 332 void CommitNavigation(const NavigationBeforeCommitInfo& info); 333 334 private: 335 friend class RenderFrameHostManagerTest; 336 friend class TestWebContents; 337 338 FRIEND_TEST_ALL_PREFIXES(CrossProcessFrameTreeBrowserTest, 339 CreateCrossProcessSubframeProxies); 340 341 // Returns the current navigation request (used in the PlzNavigate navigation 342 // logic refactoring project). navigation_request_for_testing()343 NavigationRequest* navigation_request_for_testing() const { 344 return navigation_request_.get(); } 345 346 // Used with FrameTree::ForEach to erase RenderFrameProxyHosts from a 347 // FrameTreeNode's RenderFrameHostManager. 348 static bool ClearProxiesInSiteInstance(int32 site_instance_id, 349 FrameTreeNode* node); 350 351 // Returns whether this tab should transition to a new renderer for 352 // cross-site URLs. Enabled unless we see the --process-per-tab command line 353 // switch. Can be overridden in unit tests. 354 bool ShouldTransitionCrossSite(); 355 356 // Returns true if for the navigation from |current_effective_url| to 357 // |new_effective_url|, a new SiteInstance and BrowsingInstance should be 358 // created (even if we are in a process model that doesn't usually swap). 359 // This forces a process swap and severs script connections with existing 360 // tabs. Cases where this can happen include transitions between WebUI and 361 // regular web pages. |new_site_instance| may be null. 362 // If there is no current NavigationEntry, then |current_is_view_source_mode| 363 // should be the same as |new_is_view_source_mode|. 364 // 365 // We use the effective URL here, since that's what is used in the 366 // SiteInstance's site and when we later call IsSameWebSite. If there is no 367 // current NavigationEntry, check the current SiteInstance's site, which might 368 // already be committed to a Web UI URL (such as the NTP). 369 bool ShouldSwapBrowsingInstancesForNavigation( 370 const GURL& current_effective_url, 371 bool current_is_view_source_mode, 372 SiteInstance* new_site_instance, 373 const GURL& new_effective_url, 374 bool new_is_view_source_mode) const; 375 376 // Returns true if it is safe to reuse the current WebUI when navigating from 377 // |current_entry| to |new_entry|. 378 bool ShouldReuseWebUI( 379 const NavigationEntry* current_entry, 380 const NavigationEntryImpl* new_entry) const; 381 382 // Returns the SiteInstance to use for the navigation. 383 SiteInstance* GetSiteInstanceForNavigation( 384 const GURL& dest_url, 385 SiteInstance* dest_instance, 386 ui::PageTransition dest_transition, 387 bool dest_is_restore, 388 bool dest_is_view_source_mode); 389 390 // Returns an appropriate SiteInstance object for the given |dest_url|, 391 // possibly reusing the current SiteInstance. If --process-per-tab is used, 392 // this is only called when ShouldSwapBrowsingInstancesForNavigation returns 393 // true. |dest_instance| will be used if it is not null. 394 // This is a helper function for GetSiteInstanceForNavigation. 395 SiteInstance* GetSiteInstanceForURL( 396 const GURL& dest_url, 397 SiteInstance* dest_instance, 398 ui::PageTransition dest_transition, 399 bool dest_is_restore, 400 bool dest_is_view_source_mode, 401 SiteInstance* current_instance, 402 bool force_browsing_instance_swap); 403 404 // Creates a new RenderFrameHostImpl for the |new_instance| while respecting 405 // the opener route if needed and stores it in pending_render_frame_host_. 406 void CreateRenderFrameHostForNewSiteInstance( 407 SiteInstance* old_instance, 408 SiteInstance* new_instance, 409 bool is_main_frame); 410 411 // Creates a RenderFrameHost and corresponding RenderViewHost if necessary. 412 scoped_ptr<RenderFrameHostImpl> CreateRenderFrameHost(SiteInstance* instance, 413 int view_routing_id, 414 int frame_routing_id, 415 bool swapped_out, 416 bool hidden); 417 418 // Sets up the necessary state for a new RenderViewHost with the given opener, 419 // if necessary. It creates a RenderFrameProxy in the target renderer process 420 // with the given |proxy_routing_id|, which is used to route IPC messages when 421 // in swapped out state. Returns early if the RenderViewHost has already been 422 // initialized for another RenderFrameHost. 423 // TODO(creis): opener_route_id is currently for the RenderViewHost but should 424 // be for the RenderFrame, since frames can have openers. 425 bool InitRenderView(RenderViewHostImpl* render_view_host, 426 int opener_route_id, 427 int proxy_routing_id, 428 bool for_main_frame_navigation); 429 430 // Initialization for RenderFrameHost uses the same sequence as InitRenderView 431 // above. 432 bool InitRenderFrame(RenderFrameHostImpl* render_frame_host); 433 434 // Sets the pending RenderFrameHost/WebUI to be the active one. Note that this 435 // doesn't require the pending render_frame_host_ pointer to be non-NULL, 436 // since there could be Web UI switching as well. Call this for every commit. 437 void CommitPending(); 438 439 // Runs the unload handler in the current page, after the new page has 440 // committed. 441 void SwapOutOldPage(RenderFrameHostImpl* old_render_frame_host); 442 443 // Shutdown all RenderFrameProxyHosts in a SiteInstance. This is called to 444 // shutdown frames when all the frames in a SiteInstance are confirmed to be 445 // swapped out. 446 void ShutdownRenderFrameProxyHostsInSiteInstance(int32 site_instance_id); 447 448 // Helper method to terminate the pending RenderViewHost. 449 void CancelPending(); 450 451 // Helper method to set the active RenderFrameHost. Returns the old 452 // RenderFrameHost and updates counts. 453 scoped_ptr<RenderFrameHostImpl> SetRenderFrameHost( 454 scoped_ptr<RenderFrameHostImpl> render_frame_host); 455 456 RenderFrameHostImpl* UpdateStateForNavigate( 457 const NavigationEntryImpl& entry); 458 459 // Called when a renderer process is starting to close. We should not 460 // schedule new navigations in its swapped out RenderFrameHosts after this. 461 void RendererProcessClosing(RenderProcessHost* render_process_host); 462 463 // Helper method to delete a RenderFrameProxyHost from the list, if one exists 464 // for the given |instance|. 465 void DeleteRenderFrameProxyHost(SiteInstance* instance); 466 467 // For use in creating RenderFrameHosts. 468 FrameTreeNode* frame_tree_node_; 469 470 // Our delegate, not owned by us. Guaranteed non-NULL. 471 Delegate* delegate_; 472 473 // Whether a navigation requiring different RenderFrameHosts is pending. This 474 // is either for cross-site requests or when required for the process type 475 // (like WebUI). 476 bool cross_navigation_pending_; 477 478 // Implemented by the owner of this class. These delegates are installed into 479 // all the RenderFrameHosts that we create. 480 RenderFrameHostDelegate* render_frame_delegate_; 481 RenderViewHostDelegate* render_view_delegate_; 482 RenderWidgetHostDelegate* render_widget_delegate_; 483 484 // Our RenderFrameHost and its associated Web UI (if any, will be NULL for 485 // non-WebUI pages). This object is responsible for all communication with 486 // a child RenderFrame instance. 487 // For now, RenderFrameHost keeps a RenderViewHost in its SiteInstance alive. 488 // Eventually, RenderViewHost will be replaced with a page context. 489 scoped_ptr<RenderFrameHostImpl> render_frame_host_; 490 scoped_ptr<WebUIImpl> web_ui_; 491 492 // A RenderFrameHost used to load a cross-site page. This remains hidden 493 // while a cross-site request is pending until it calls DidNavigate. It may 494 // have an associated Web UI, in which case the Web UI pointer will be non- 495 // NULL. 496 // 497 // The |pending_web_ui_| may be non-NULL even when the 498 // |pending_render_frame_host_| is NULL. This will happen when we're 499 // transitioning between two Web UI pages: the RFH won't be swapped, so the 500 // pending pointer will be unused, but there will be a pending Web UI 501 // associated with the navigation. 502 scoped_ptr<RenderFrameHostImpl> pending_render_frame_host_; 503 504 // If a pending request needs to be transferred to another process, this 505 // owns the request until it's transferred to the new process, so it will be 506 // cleaned up if the navigation is cancelled. Otherwise, this is NULL. 507 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request_; 508 509 // Tracks information about any navigation paused after receiving response 510 // headers. 511 scoped_ptr<GlobalRequestID> response_started_id_; 512 513 // If either of these is non-NULL, the pending navigation is to a chrome: 514 // page. The scoped_ptr is used if pending_web_ui_ != web_ui_, the WeakPtr is 515 // used for when they reference the same object. If either is non-NULL, the 516 // other should be NULL. 517 scoped_ptr<WebUIImpl> pending_web_ui_; 518 base::WeakPtr<WebUIImpl> pending_and_current_web_ui_; 519 520 // A map of site instance ID to RenderFrameProxyHosts. 521 typedef base::hash_map<int32, RenderFrameProxyHost*> RenderFrameProxyHostMap; 522 RenderFrameProxyHostMap proxy_hosts_; 523 524 // A map of RenderFrameHosts pending shutdown. 525 typedef base::hash_map<int32, linked_ptr<RenderFrameHostImpl> > 526 RFHPendingDeleteMap; 527 RFHPendingDeleteMap pending_delete_hosts_; 528 529 // The intersitial page currently shown if any, not own by this class 530 // (the InterstitialPage is self-owned, it deletes itself when hidden). 531 InterstitialPageImpl* interstitial_page_; 532 533 NotificationRegistrar registrar_; 534 535 // PlzNavigate: Owns a navigation request that originated in that frame until 536 // it commits. 537 scoped_ptr<NavigationRequest> navigation_request_; 538 539 base::WeakPtrFactory<RenderFrameHostManager> weak_factory_; 540 541 DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManager); 542 }; 543 544 } // namespace content 545 546 #endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ 547