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_IMPL_H_ 6 #define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_ 7 8 #include <map> 9 #include <vector> 10 11 #include "base/callback.h" 12 #include "base/compiler_specific.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/strings/string16.h" 16 #include "base/time/time.h" 17 #include "content/browser/accessibility/browser_accessibility_manager.h" 18 #include "content/common/accessibility_mode_enums.h" 19 #include "content/common/content_export.h" 20 #include "content/common/mojo/service_registry_impl.h" 21 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/common/javascript_message_type.h" 23 #include "net/http/http_response_headers.h" 24 #include "third_party/WebKit/public/platform/WebNotificationPermission.h" 25 #include "third_party/WebKit/public/web/WebTextDirection.h" 26 #include "ui/accessibility/ax_node_data.h" 27 #include "ui/base/page_transition_types.h" 28 29 class GURL; 30 struct AccessibilityHostMsg_EventParams; 31 struct AccessibilityHostMsg_LocationChangeParams; 32 struct FrameHostMsg_DidFailProvisionalLoadWithError_Params; 33 struct FrameHostMsg_OpenURL_Params; 34 struct FrameHostMsg_BeginNavigation_Params; 35 struct FrameMsg_Navigate_Params; 36 #if defined(OS_MACOSX) || defined(OS_ANDROID) 37 struct FrameHostMsg_ShowPopup_Params; 38 #endif 39 40 namespace base { 41 class FilePath; 42 class ListValue; 43 } 44 45 namespace content { 46 47 class CrossProcessFrameConnector; 48 class CrossSiteTransferringRequest; 49 class FrameTree; 50 class FrameTreeNode; 51 class RenderFrameHostDelegate; 52 class RenderFrameProxyHost; 53 class RenderProcessHost; 54 class RenderViewHostImpl; 55 class RenderWidgetHostImpl; 56 struct ContextMenuParams; 57 struct GlobalRequestID; 58 struct Referrer; 59 struct ShowDesktopNotificationHostMsgParams; 60 struct TransitionLayerData; 61 62 class CONTENT_EXPORT RenderFrameHostImpl 63 : public RenderFrameHost, 64 public BrowserAccessibilityDelegate { 65 public: 66 // Keeps track of the state of the RenderFrameHostImpl, particularly with 67 // respect to swap out. 68 enum RenderFrameHostImplState { 69 // The standard state for a RFH handling the communication with an active 70 // RenderFrame. 71 STATE_DEFAULT = 0, 72 // The RFH has not received the SwapOutACK yet, but the new page has 73 // committed in a different RFH. Upon reception of the SwapOutACK, the RFH 74 // will either enter STATE_SWAPPED_OUT (if it is a main frame and there are 75 // other active frames in its SiteInstance) or it will be deleted. 76 STATE_PENDING_SWAP_OUT, 77 // The RFH is swapped out and stored inside a RenderFrameProxyHost, being 78 // used as a placeholder to allow cross-process communication. Only main 79 // frames can enter this state. 80 STATE_SWAPPED_OUT, 81 }; 82 // Helper function to determine whether the RFH state should contribute to the 83 // number of active frames of a SiteInstance or not. 84 static bool IsRFHStateActive(RenderFrameHostImplState rfh_state); 85 86 // An accessibility reset is only allowed to prevent very rare corner cases 87 // or race conditions where the browser and renderer get out of sync. If 88 // this happens more than this many times, kill the renderer. 89 static const int kMaxAccessibilityResets = 5; 90 91 static RenderFrameHostImpl* FromID(int process_id, int routing_id); 92 93 virtual ~RenderFrameHostImpl(); 94 95 // RenderFrameHost 96 virtual int GetRoutingID() OVERRIDE; 97 virtual SiteInstance* GetSiteInstance() OVERRIDE; 98 virtual RenderProcessHost* GetProcess() OVERRIDE; 99 virtual RenderFrameHost* GetParent() OVERRIDE; 100 virtual const std::string& GetFrameName() OVERRIDE; 101 virtual bool IsCrossProcessSubframe() OVERRIDE; 102 virtual GURL GetLastCommittedURL() OVERRIDE; 103 virtual gfx::NativeView GetNativeView() OVERRIDE; 104 virtual void ExecuteJavaScript( 105 const base::string16& javascript) OVERRIDE; 106 virtual void ExecuteJavaScript( 107 const base::string16& javascript, 108 const JavaScriptResultCallback& callback) OVERRIDE; 109 virtual void ExecuteJavaScriptForTests( 110 const base::string16& javascript) OVERRIDE; 111 virtual RenderViewHost* GetRenderViewHost() OVERRIDE; 112 virtual ServiceRegistry* GetServiceRegistry() OVERRIDE; 113 114 // IPC::Sender 115 virtual bool Send(IPC::Message* msg) OVERRIDE; 116 117 // IPC::Listener 118 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; 119 120 // BrowserAccessibilityDelegate 121 virtual void AccessibilitySetFocus(int acc_obj_id) OVERRIDE; 122 virtual void AccessibilityDoDefaultAction(int acc_obj_id) OVERRIDE; 123 virtual void AccessibilityShowMenu(const gfx::Point& global_point) OVERRIDE; 124 virtual void AccessibilityScrollToMakeVisible( 125 int acc_obj_id, const gfx::Rect& subfocus) OVERRIDE; 126 virtual void AccessibilityScrollToPoint( 127 int acc_obj_id, const gfx::Point& point) OVERRIDE; 128 virtual void AccessibilitySetTextSelection( 129 int acc_obj_id, int start_offset, int end_offset) OVERRIDE; 130 virtual bool AccessibilityViewHasFocus() const OVERRIDE; 131 virtual gfx::Rect AccessibilityGetViewBounds() const OVERRIDE; 132 virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) 133 const OVERRIDE; 134 virtual void AccessibilityHitTest(const gfx::Point& point) OVERRIDE; 135 virtual void AccessibilityFatalError() OVERRIDE; 136 virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() OVERRIDE; 137 virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() 138 OVERRIDE; 139 virtual BrowserAccessibilityManager* AccessibilityGetChildFrame( 140 int accessibility_node_id) OVERRIDE; 141 virtual BrowserAccessibility* AccessibilityGetParentFrame() OVERRIDE; 142 143 // Creates a RenderFrame in the renderer process. Only called for 144 // cross-process subframe navigations in --site-per-process. 145 bool CreateRenderFrame(int parent_routing_id); 146 147 // Returns whether the RenderFrame in the renderer process has been created 148 // and still has a connection. This is valid for all frames. 149 bool IsRenderFrameLive(); 150 151 // Tracks whether the RenderFrame for this RenderFrameHost has been created in 152 // the renderer process. This is currently only used for subframes. 153 // TODO(creis): Use this for main frames as well when RVH goes away. set_render_frame_created(bool created)154 void set_render_frame_created(bool created) { 155 render_frame_created_ = created; 156 } 157 158 // Called for renderer-created windows to resume requests from this frame, 159 // after they are blocked in RenderWidgetHelper::CreateNewWindow. 160 void Init(); 161 routing_id()162 int routing_id() const { return routing_id_; } 163 void OnCreateChildFrame(int new_routing_id, 164 const std::string& frame_name); 165 render_view_host()166 RenderViewHostImpl* render_view_host() { return render_view_host_; } delegate()167 RenderFrameHostDelegate* delegate() { return delegate_; } frame_tree_node()168 FrameTreeNode* frame_tree_node() { return frame_tree_node_; } 169 // TODO(nasko): The RenderWidgetHost will be owned by RenderFrameHost in 170 // the future, so update this accessor to return the right pointer. 171 RenderWidgetHostImpl* GetRenderWidgetHost(); 172 173 // This function is called when this is a swapped out RenderFrameHost that 174 // lives in the same process as the parent frame. The 175 // |cross_process_frame_connector| allows the non-swapped-out 176 // RenderFrameHost for a frame to communicate with the parent process 177 // so that it may composite drawing data. 178 // 179 // Ownership is not transfered. set_cross_process_frame_connector(CrossProcessFrameConnector * cross_process_frame_connector)180 void set_cross_process_frame_connector( 181 CrossProcessFrameConnector* cross_process_frame_connector) { 182 cross_process_frame_connector_ = cross_process_frame_connector; 183 } 184 set_render_frame_proxy_host(RenderFrameProxyHost * proxy)185 void set_render_frame_proxy_host(RenderFrameProxyHost* proxy) { 186 render_frame_proxy_host_ = proxy; 187 } 188 189 // Returns a bitwise OR of bindings types that have been enabled for this 190 // RenderFrameHostImpl's RenderView. See BindingsPolicy for details. 191 // TODO(creis): Make bindings frame-specific, to support cases like <webview>. 192 int GetEnabledBindings(); 193 194 // Called on the pending RenderFrameHost when the network response is ready to 195 // commit. We should ensure that the old RenderFrameHost runs its unload 196 // handler and determine whether a transfer to a different RenderFrameHost is 197 // needed. 198 void OnCrossSiteResponse( 199 const GlobalRequestID& global_request_id, 200 scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request, 201 const std::vector<GURL>& transfer_url_chain, 202 const Referrer& referrer, 203 ui::PageTransition page_transition, 204 bool should_replace_current_entry); 205 206 // Called on the current RenderFrameHost when the network response is first 207 // receieved. 208 void OnDeferredAfterResponseStarted( 209 const GlobalRequestID& global_request_id, 210 const TransitionLayerData& transition_data); 211 212 // Tells the renderer that this RenderFrame is being swapped out for one in a 213 // different renderer process. It should run its unload handler, move to 214 // a blank document and create a RenderFrameProxy to replace the RenderFrame. 215 // The renderer should preserve the Proxy object until it exits, in case we 216 // come back. The renderer can exit if it has no other active RenderFrames, 217 // but not until WasSwappedOut is called (when it is no longer visible). 218 void SwapOut(RenderFrameProxyHost* proxy); 219 220 void OnSwappedOut(bool timed_out); is_swapped_out()221 bool is_swapped_out() { return is_swapped_out_; } set_swapped_out(bool is_swapped_out)222 void set_swapped_out(bool is_swapped_out) { 223 is_swapped_out_ = is_swapped_out; 224 } 225 226 // Sets the RVH for |this| as pending shutdown. |on_swap_out| will be called 227 // when the SwapOutACK is received. 228 void SetPendingShutdown(const base::Closure& on_swap_out); 229 230 // Sends the given navigation message. Use this rather than sending it 231 // yourself since this does the internal bookkeeping described below. This 232 // function takes ownership of the provided message pointer. 233 // 234 // If a cross-site request is in progress, we may be suspended while waiting 235 // for the onbeforeunload handler, so this function might buffer the message 236 // rather than sending it. 237 void Navigate(const FrameMsg_Navigate_Params& params); 238 239 // Load the specified URL; this is a shortcut for Navigate(). 240 void NavigateToURL(const GURL& url); 241 242 // Stop the load in progress. 243 void Stop(); 244 245 // Returns whether navigation messages are currently suspended for this 246 // RenderFrameHost. Only true during a cross-site navigation, while waiting 247 // for the onbeforeunload handler. are_navigations_suspended()248 bool are_navigations_suspended() const { return navigations_suspended_; } 249 250 // Suspends (or unsuspends) any navigation messages from being sent from this 251 // RenderFrameHost. This is called when a pending RenderFrameHost is created 252 // for a cross-site navigation, because we must suspend any navigations until 253 // we hear back from the old renderer's onbeforeunload handler. Note that it 254 // is important that only one navigation event happen after calling this 255 // method with |suspend| equal to true. If |suspend| is false and there is a 256 // suspended_nav_message_, this will send the message. This function should 257 // only be called to toggle the state; callers should check 258 // are_navigations_suspended() first. If |suspend| is false, the time that the 259 // user decided the navigation should proceed should be passed as 260 // |proceed_time|. 261 void SetNavigationsSuspended(bool suspend, 262 const base::TimeTicks& proceed_time); 263 264 // Clears any suspended navigation state after a cross-site navigation is 265 // canceled or suspended. This is important if we later return to this 266 // RenderFrameHost. 267 void CancelSuspendedNavigations(); 268 269 // Runs the beforeunload handler for this frame. |for_cross_site_transition| 270 // indicates whether this call is for the current frame during a cross-process 271 // navigation. False means we're closing the entire tab. 272 void DispatchBeforeUnload(bool for_cross_site_transition); 273 274 // Set the frame's opener to null in the renderer process in response to an 275 // action in another renderer process. 276 void DisownOpener(); 277 278 // Deletes the current selection plus the specified number of characters 279 // before and after the selection or caret. 280 void ExtendSelectionAndDelete(size_t before, size_t after); 281 282 // Notifies the RenderFrame that the JavaScript message that was shown was 283 // closed by the user. 284 void JavaScriptDialogClosed(IPC::Message* reply_msg, 285 bool success, 286 const base::string16& user_input, 287 bool dialog_was_suppressed); 288 289 // Called when an HTML5 notification is closed. 290 void NotificationClosed(int notification_id); 291 292 // Clears any outstanding transition request. This is called when we hear the 293 // response or commit. 294 void ClearPendingTransitionRequestData(); 295 296 // Send a message to the renderer process to change the accessibility mode. 297 void SetAccessibilityMode(AccessibilityMode AccessibilityMode); 298 299 // Turn on accessibility testing. The given callback will be run 300 // every time an accessibility notification is received from the 301 // renderer process, and the accessibility tree it sent can be 302 // retrieved using GetAXTreeForTesting(). 303 void SetAccessibilityCallbackForTesting( 304 const base::Callback<void(ui::AXEvent, int)>& callback); 305 306 // Returns a snapshot of the accessibility tree received from the 307 // renderer as of the last time an accessibility notification was 308 // received. 309 const ui::AXTree* GetAXTreeForTesting(); 310 311 // Access the BrowserAccessibilityManager if it already exists. browser_accessibility_manager()312 BrowserAccessibilityManager* browser_accessibility_manager() const { 313 return browser_accessibility_manager_.get(); 314 } 315 316 // If accessibility is enabled, get the BrowserAccessibilityManager for 317 // this frame, or create one if it doesn't exist yet, otherwise return 318 // NULL. 319 BrowserAccessibilityManager* GetOrCreateBrowserAccessibilityManager(); 320 set_disallow_browser_accessibility_manager_for_testing(bool flag)321 void set_disallow_browser_accessibility_manager_for_testing(bool flag) { 322 disallow_browser_accessibility_manager_for_testing_ = flag; 323 } 324 325 #if defined(OS_WIN) 326 void SetParentNativeViewAccessible( 327 gfx::NativeViewAccessible accessible_parent); 328 gfx::NativeViewAccessible GetParentNativeViewAccessible() const; 329 #elif defined(OS_MACOSX) 330 // Select popup menu related methods (for external popup menus). 331 void DidSelectPopupMenuItem(int selected_index); 332 void DidCancelPopupMenu(); 333 #elif defined(OS_ANDROID) 334 void DidSelectPopupMenuItems(const std::vector<int>& selected_indices); 335 void DidCancelPopupMenu(); 336 #endif 337 338 protected: 339 friend class RenderFrameHostFactory; 340 341 // TODO(nasko): Remove dependency on RenderViewHost here. RenderProcessHost 342 // should be the abstraction needed here, but we need RenderViewHost to pass 343 // into WebContentsObserver::FrameDetached for now. 344 RenderFrameHostImpl(RenderViewHostImpl* render_view_host, 345 RenderFrameHostDelegate* delegate, 346 FrameTree* frame_tree, 347 FrameTreeNode* frame_tree_node, 348 int routing_id, 349 bool is_swapped_out); 350 351 private: 352 friend class TestRenderFrameHost; 353 friend class TestRenderViewHost; 354 355 FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe); 356 357 // IPC Message handlers. 358 void OnAddMessageToConsole(int32 level, 359 const base::string16& message, 360 int32 line_no, 361 const base::string16& source_id); 362 void OnDetach(); 363 void OnFrameFocused(); 364 void OnOpenURL(const FrameHostMsg_OpenURL_Params& params); 365 void OnDocumentOnLoadCompleted(); 366 void OnDidStartProvisionalLoadForFrame(const GURL& url, 367 bool is_transition_navigation); 368 void OnDidFailProvisionalLoadWithError( 369 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params); 370 void OnDidFailLoadWithError( 371 const GURL& url, 372 int error_code, 373 const base::string16& error_description); 374 void OnDidCommitProvisionalLoad(const IPC::Message& msg); 375 void OnBeforeUnloadACK( 376 bool proceed, 377 const base::TimeTicks& renderer_before_unload_start_time, 378 const base::TimeTicks& renderer_before_unload_end_time); 379 void OnSwapOutACK(); 380 void OnContextMenu(const ContextMenuParams& params); 381 void OnJavaScriptExecuteResponse(int id, const base::ListValue& result); 382 void OnRunJavaScriptMessage(const base::string16& message, 383 const base::string16& default_prompt, 384 const GURL& frame_url, 385 JavaScriptMessageType type, 386 IPC::Message* reply_msg); 387 void OnRunBeforeUnloadConfirm(const GURL& frame_url, 388 const base::string16& message, 389 bool is_reload, 390 IPC::Message* reply_msg); 391 void OnRequestPlatformNotificationPermission(const GURL& origin, 392 int request_id); 393 void OnShowDesktopNotification( 394 int notification_id, 395 const ShowDesktopNotificationHostMsgParams& params); 396 void OnCancelDesktopNotification(int notification_id); 397 void OnTextSurroundingSelectionResponse(const base::string16& content, 398 size_t start_offset, 399 size_t end_offset); 400 void OnDidAccessInitialDocument(); 401 void OnDidDisownOpener(); 402 void OnDidAssignPageId(int32 page_id); 403 void OnUpdateTitle(int32 page_id, 404 const base::string16& title, 405 blink::WebTextDirection title_direction); 406 void OnUpdateEncoding(const std::string& encoding); 407 void OnBeginNavigation( 408 const FrameHostMsg_BeginNavigation_Params& params); 409 void OnAccessibilityEvents( 410 const std::vector<AccessibilityHostMsg_EventParams>& params, 411 int reset_token); 412 void OnAccessibilityLocationChanges( 413 const std::vector<AccessibilityHostMsg_LocationChangeParams>& params); 414 415 #if defined(OS_MACOSX) || defined(OS_ANDROID) 416 void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params); 417 void OnHidePopup(); 418 #endif 419 420 // Returns whether the given URL is allowed to commit in the current process. 421 // This is a more conservative check than RenderProcessHost::FilterURL, since 422 // it will be used to kill processes that commit unauthorized URLs. 423 bool CanCommitURL(const GURL& url); 424 425 void PlatformNotificationPermissionRequestDone( 426 int request_id, blink::WebNotificationPermission permission); 427 428 // Update the the singleton FrameAccessibility instance with a map 429 // from accessibility node id to the frame routing id of a cross-process 430 // iframe. 431 void UpdateCrossProcessIframeAccessibility( 432 const std::map<int32, int> node_to_frame_routing_id_map); 433 434 // Update the the singleton FrameAccessibility instance with a map 435 // from accessibility node id to the browser plugin instance id of a 436 // guest WebContents. 437 void UpdateGuestFrameAccessibility( 438 const std::map<int32, int> node_to_browser_plugin_instance_id_map); 439 440 // For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a 441 // refcount that calls Shutdown when it reaches zero. This allows each 442 // RenderFrameHostManager to just care about RenderFrameHosts, while ensuring 443 // we have a RenderViewHost for each RenderFrameHost. 444 // TODO(creis): RenderViewHost will eventually go away and be replaced with 445 // some form of page context. 446 RenderViewHostImpl* render_view_host_; 447 448 RenderFrameHostDelegate* delegate_; 449 450 // |cross_process_frame_connector_| passes messages from an out-of-process 451 // child frame to the parent process for compositing. 452 // 453 // This is only non-NULL when this is the swapped out RenderFrameHost in 454 // the same site instance as this frame's parent. 455 // 456 // See the class comment above CrossProcessFrameConnector for more 457 // information. 458 // 459 // This will move to RenderFrameProxyHost when that class is created. 460 CrossProcessFrameConnector* cross_process_frame_connector_; 461 462 // The proxy created for this RenderFrameHost. It is used to send and receive 463 // IPC messages while in swapped out state. 464 // TODO(nasko): This can be removed once we don't have a swapped out state on 465 // RenderFrameHosts. See https://crbug.com/357747. 466 RenderFrameProxyHost* render_frame_proxy_host_; 467 468 // Reference to the whole frame tree that this RenderFrameHost belongs to. 469 // Allows this RenderFrameHost to add and remove nodes in response to 470 // messages from the renderer requesting DOM manipulation. 471 FrameTree* frame_tree_; 472 473 // The FrameTreeNode which this RenderFrameHostImpl is hosted in. 474 FrameTreeNode* frame_tree_node_; 475 476 // The mapping of pending JavaScript calls created by 477 // ExecuteJavaScript and their corresponding callbacks. 478 std::map<int, JavaScriptResultCallback> javascript_callbacks_; 479 480 // Map from notification_id to a callback to cancel them. 481 std::map<int, base::Closure> cancel_notification_callbacks_; 482 483 int routing_id_; 484 bool is_swapped_out_; 485 486 // Tracks whether the RenderFrame for this RenderFrameHost has been created in 487 // the renderer process. Currently only used for subframes. 488 // TODO(creis): Use this for main frames as well when RVH goes away. 489 bool render_frame_created_; 490 491 // Whether we should buffer outgoing Navigate messages rather than sending 492 // them. This will be true when a RenderFrameHost is created for a cross-site 493 // request, until we hear back from the onbeforeunload handler of the old 494 // RenderFrameHost. 495 bool navigations_suspended_; 496 497 // We only buffer the params for a suspended navigation while this RFH is the 498 // pending RenderFrameHost of a RenderFrameHostManager. There will only ever 499 // be one suspended navigation, because RenderFrameHostManager will destroy 500 // the pending RenderFrameHost and create a new one if a second navigation 501 // occurs. 502 scoped_ptr<FrameMsg_Navigate_Params> suspended_nav_params_; 503 504 // When the last BeforeUnload message was sent. 505 base::TimeTicks send_before_unload_start_time_; 506 507 ServiceRegistryImpl service_registry_; 508 509 // The object managing the accessibility tree for this frame. 510 scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_; 511 512 // This is nonzero if we sent an accessibility reset to the renderer and 513 // we're waiting for an IPC containing this reset token (sequentially 514 // assigned) and a complete replacement accessibility tree. 515 int accessibility_reset_token_; 516 517 // A count of the number of times we needed to reset accessibility, so 518 // we don't keep trying to reset forever. 519 int accessibility_reset_count_; 520 521 // Callback when an event is received, for testing. 522 base::Callback<void(ui::AXEvent, int)> accessibility_testing_callback_; 523 // The most recently received accessibility tree - for testing only. 524 scoped_ptr<ui::AXTree> ax_tree_for_testing_; 525 // Flag to not create a BrowserAccessibilityManager, for testing. 526 bool disallow_browser_accessibility_manager_for_testing_; 527 528 // NOTE: This must be the last member. 529 base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_; 530 531 DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImpl); 532 }; 533 534 } // namespace content 535 536 #endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_IMPL_H_ 537