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
29class GURL;
30struct AccessibilityHostMsg_EventParams;
31struct AccessibilityHostMsg_LocationChangeParams;
32struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
33struct FrameHostMsg_OpenURL_Params;
34struct FrameHostMsg_BeginNavigation_Params;
35struct FrameMsg_Navigate_Params;
36#if defined(OS_MACOSX) || defined(OS_ANDROID)
37struct FrameHostMsg_ShowPopup_Params;
38#endif
39
40namespace base {
41class FilePath;
42class ListValue;
43}
44
45namespace content {
46
47class CrossProcessFrameConnector;
48class CrossSiteTransferringRequest;
49class FrameTree;
50class FrameTreeNode;
51class RenderFrameHostDelegate;
52class RenderFrameProxyHost;
53class RenderProcessHost;
54class RenderViewHostImpl;
55class RenderWidgetHostImpl;
56struct ContextMenuParams;
57struct GlobalRequestID;
58struct Referrer;
59struct ShowDesktopNotificationHostMsgParams;
60struct TransitionLayerData;
61
62class 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.
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
162  int routing_id() const { return routing_id_; }
163  void OnCreateChildFrame(int new_routing_id,
164                          const std::string& frame_name);
165
166  RenderViewHostImpl* render_view_host() { return render_view_host_; }
167  RenderFrameHostDelegate* delegate() { return delegate_; }
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.
180  void set_cross_process_frame_connector(
181      CrossProcessFrameConnector* cross_process_frame_connector) {
182    cross_process_frame_connector_ = cross_process_frame_connector;
183  }
184
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);
221  bool is_swapped_out() { return 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.
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.
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
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