1// Copyright (c) 2012 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_RENDERER_HOST_RENDER_VIEW_HOST_IMPL_H_
6#define CONTENT_BROWSER_RENDERER_HOST_RENDER_VIEW_HOST_IMPL_H_
7
8#include <map>
9#include <string>
10#include <vector>
11
12#include "base/callback.h"
13#include "base/compiler_specific.h"
14#include "base/logging.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/process/kill.h"
17#include "content/browser/renderer_host/render_widget_host_impl.h"
18#include "content/browser/site_instance_impl.h"
19#include "content/common/drag_event_source_info.h"
20#include "content/public/browser/notification_observer.h"
21#include "content/public/browser/render_view_host.h"
22#include "content/public/common/window_container_type.h"
23#include "net/base/load_states.h"
24#include "third_party/WebKit/public/web/WebAXEnums.h"
25#include "third_party/WebKit/public/web/WebConsoleMessage.h"
26#include "third_party/WebKit/public/web/WebPopupType.h"
27#include "third_party/skia/include/core/SkColor.h"
28#include "ui/base/window_open_disposition.h"
29
30class SkBitmap;
31class FrameMsg_Navigate;
32struct FrameMsg_Navigate_Params;
33struct MediaPlayerAction;
34struct ViewHostMsg_CreateWindow_Params;
35struct ViewMsg_PostMessage_Params;
36
37namespace base {
38class ListValue;
39}
40
41namespace gfx {
42class Range;
43}
44
45namespace ui {
46class AXTree;
47struct SelectedFileInfo;
48}
49
50namespace content {
51
52class MediaWebContentsObserver;
53class ChildProcessSecurityPolicyImpl;
54class PageState;
55class RenderWidgetHostDelegate;
56class SessionStorageNamespace;
57class SessionStorageNamespaceImpl;
58class TestRenderViewHost;
59class TimeoutMonitor;
60struct FileChooserParams;
61
62#if defined(COMPILER_MSVC)
63// RenderViewHostImpl is the bottom of a diamond-shaped hierarchy,
64// with RenderWidgetHost at the root. VS warns when methods from the
65// root are overridden in only one of the base classes and not both
66// (in this case, RenderWidgetHostImpl provides implementations of
67// many of the methods).  This is a silly warning when dealing with
68// pure virtual methods that only have a single implementation in the
69// hierarchy above this class, and is safe to ignore in this case.
70#pragma warning(push)
71#pragma warning(disable: 4250)
72#endif
73
74// This implements the RenderViewHost interface that is exposed to
75// embedders of content, and adds things only visible to content.
76//
77// The exact API of this object needs to be more thoroughly designed. Right
78// now it mimics what WebContentsImpl exposed, which is a fairly large API and
79// may contain things that are not relevant to a common subset of views. See
80// also the comment in render_view_host_delegate.h about the size and scope of
81// the delegate API.
82//
83// Right now, the concept of page navigation (both top level and frame) exists
84// in the WebContentsImpl still, so if you instantiate one of these elsewhere,
85// you will not be able to traverse pages back and forward. We need to determine
86// if we want to bring that and other functionality down into this object so it
87// can be shared by others.
88class CONTENT_EXPORT RenderViewHostImpl
89    : public RenderViewHost,
90      public RenderWidgetHostImpl {
91 public:
92  // Keeps track of the state of the RenderViewHostImpl, particularly with
93  // respect to swap out.
94  enum RenderViewHostImplState {
95    // The standard state for a RVH handling the communication with a
96    // RenderView.
97    STATE_DEFAULT = 0,
98    // The RVH is waiting for the CloseACK from the RenderView.
99    STATE_WAITING_FOR_CLOSE,
100    // The RVH has not received the SwapOutACK yet, but the new page has
101    // committed in a different RVH. The number of active views of the RVH
102    // SiteInstanceImpl is not zero. Upon reception of the SwapOutACK, the RVH
103    // will be swapped out.
104    STATE_PENDING_SWAP_OUT,
105    // The RVH has not received the SwapOutACK yet, but the new page has
106    // committed in a different RVH. The number of active views of the RVH
107    // SiteInstanceImpl is zero. Upon reception of the SwapOutACK, the RVH will
108    // be shutdown.
109    STATE_PENDING_SHUTDOWN,
110    // The RVH is swapped out, and it is being used as a placeholder to allow
111    // for cross-process communication.
112    STATE_SWAPPED_OUT,
113  };
114  // Helper function to determine whether the RVH state should contribute to the
115  // number of active views of a SiteInstance or not.
116  static bool IsRVHStateActive(RenderViewHostImplState rvh_state);
117
118  // Convenience function, just like RenderViewHost::FromID.
119  static RenderViewHostImpl* FromID(int render_process_id, int render_view_id);
120
121  // |routing_id| could be a valid route id, or it could be MSG_ROUTING_NONE, in
122  // which case RenderWidgetHost will create a new one.  |swapped_out| indicates
123  // whether the view should initially be swapped out (e.g., for an opener
124  // frame being rendered by another process). |hidden| indicates whether the
125  // view is initially hidden or visible.
126  //
127  // The |session_storage_namespace| parameter allows multiple render views and
128  // WebContentses to share the same session storage (part of the WebStorage
129  // spec) space. This is useful when restoring contentses, but most callers
130  // should pass in NULL which will cause a new SessionStorageNamespace to be
131  // created.
132  RenderViewHostImpl(
133      SiteInstance* instance,
134      RenderViewHostDelegate* delegate,
135      RenderWidgetHostDelegate* widget_delegate,
136      int routing_id,
137      int main_frame_routing_id,
138      bool swapped_out,
139      bool hidden);
140  virtual ~RenderViewHostImpl();
141
142  // RenderViewHost implementation.
143  virtual RenderFrameHost* GetMainFrame() OVERRIDE;
144  virtual void AllowBindings(int binding_flags) OVERRIDE;
145  virtual void ClearFocusedElement() OVERRIDE;
146  virtual bool IsFocusedElementEditable() OVERRIDE;
147  virtual void ClosePage() OVERRIDE;
148  virtual void CopyImageAt(int x, int y) OVERRIDE;
149  virtual void SaveImageAt(int x, int y) OVERRIDE;
150  virtual void DirectoryEnumerationFinished(
151      int request_id,
152      const std::vector<base::FilePath>& files) OVERRIDE;
153  virtual void DisableScrollbarsForThreshold(const gfx::Size& size) OVERRIDE;
154  virtual void DragSourceEndedAt(
155      int client_x, int client_y, int screen_x, int screen_y,
156      blink::WebDragOperation operation) OVERRIDE;
157  virtual void DragSourceSystemDragEnded() OVERRIDE;
158  virtual void DragTargetDragEnter(
159      const DropData& drop_data,
160      const gfx::Point& client_pt,
161      const gfx::Point& screen_pt,
162      blink::WebDragOperationsMask operations_allowed,
163      int key_modifiers) OVERRIDE;
164  virtual void DragTargetDragOver(
165      const gfx::Point& client_pt,
166      const gfx::Point& screen_pt,
167      blink::WebDragOperationsMask operations_allowed,
168      int key_modifiers) OVERRIDE;
169  virtual void DragTargetDragLeave() OVERRIDE;
170  virtual void DragTargetDrop(const gfx::Point& client_pt,
171                              const gfx::Point& screen_pt,
172                              int key_modifiers) OVERRIDE;
173  virtual void EnableAutoResize(const gfx::Size& min_size,
174                                const gfx::Size& max_size) OVERRIDE;
175  virtual void DisableAutoResize(const gfx::Size& new_size) OVERRIDE;
176  virtual void EnablePreferredSizeMode() OVERRIDE;
177  virtual void ExecuteMediaPlayerActionAtLocation(
178      const gfx::Point& location,
179      const blink::WebMediaPlayerAction& action) OVERRIDE;
180  virtual void ExecutePluginActionAtLocation(
181      const gfx::Point& location,
182      const blink::WebPluginAction& action) OVERRIDE;
183  virtual void ExitFullscreen() OVERRIDE;
184  virtual void FilesSelectedInChooser(
185      const std::vector<ui::SelectedFileInfo>& files,
186      FileChooserParams::Mode permissions) OVERRIDE;
187  virtual RenderViewHostDelegate* GetDelegate() const OVERRIDE;
188  virtual int GetEnabledBindings() const OVERRIDE;
189  virtual SiteInstance* GetSiteInstance() const OVERRIDE;
190  virtual bool IsRenderViewLive() const OVERRIDE;
191  virtual void NotifyMoveOrResizeStarted() OVERRIDE;
192  virtual void SetWebUIProperty(const std::string& name,
193                                const std::string& value) OVERRIDE;
194  virtual void Zoom(PageZoom zoom) OVERRIDE;
195  virtual void SyncRendererPrefs() OVERRIDE;
196  virtual WebPreferences GetWebkitPreferences() OVERRIDE;
197  virtual void UpdateWebkitPreferences(
198      const WebPreferences& prefs) OVERRIDE;
199  virtual void OnWebkitPreferencesChanged() OVERRIDE;
200  virtual void GetAudioOutputControllers(
201      const GetAudioOutputControllersCallback& callback) const OVERRIDE;
202  virtual void SelectWordAroundCaret() OVERRIDE;
203
204#if defined(OS_ANDROID)
205  virtual void ActivateNearestFindResult(int request_id,
206                                         float x,
207                                         float y) OVERRIDE;
208  virtual void RequestFindMatchRects(int current_version) OVERRIDE;
209#endif
210
211  void set_delegate(RenderViewHostDelegate* d) {
212    CHECK(d);  // http://crbug.com/82827
213    delegate_ = d;
214  }
215
216  // Set up the RenderView child process. Virtual because it is overridden by
217  // TestRenderViewHost. If the |frame_name| parameter is non-empty, it is used
218  // as the name of the new top-level frame.
219  // The |opener_route_id| parameter indicates which RenderView created this
220  // (MSG_ROUTING_NONE if none). If |max_page_id| is larger than -1, the
221  // RenderView is told to start issuing page IDs at |max_page_id| + 1.
222  // |window_was_created_with_opener| is true if this top-level frame was
223  // created with an opener. (The opener may have been closed since.)
224  // The |proxy_route_id| is only used when creating a RenderView in swapped out
225  // state.
226  virtual bool CreateRenderView(const base::string16& frame_name,
227                                int opener_route_id,
228                                int proxy_route_id,
229                                int32 max_page_id,
230                                bool window_was_created_with_opener);
231
232  base::TerminationStatus render_view_termination_status() const {
233    return render_view_termination_status_;
234  }
235
236  // Returns the content specific prefs for this RenderViewHost.
237  WebPreferences ComputeWebkitPrefs(const GURL& url);
238
239  // Whether this RenderViewHost has been swapped out to be displayed by a
240  // different process.
241  bool IsSwappedOut() const { return rvh_state_ == STATE_SWAPPED_OUT; }
242
243  // The current state of this RVH.
244  RenderViewHostImplState rvh_state() const { return rvh_state_; }
245
246  // Tells the renderer that this RenderView will soon be swapped out, and thus
247  // not to create any new modal dialogs until it happens.  This must be done
248  // separately so that the PageGroupLoadDeferrers of any current dialogs are no
249  // longer on the stack when we attempt to swap it out.
250  void SuppressDialogsUntilSwapOut();
251
252  // Called when either the SwapOut request has been acknowledged or has timed
253  // out.
254  void OnSwappedOut(bool timed_out);
255
256  // Set |this| as pending shutdown. |on_swap_out| will be called
257  // when the SwapOutACK is received, or when the unload timer times out.
258  void SetPendingShutdown(const base::Closure& on_swap_out);
259
260  // Close the page ignoring whether it has unload events registers.
261  // This is called after the beforeunload and unload events have fired
262  // and the user has agreed to continue with closing the page.
263  void ClosePageIgnoringUnloadEvents();
264
265  // Tells the renderer view to focus the first (last if reverse is true) node.
266  void SetInitialFocus(bool reverse);
267
268  // Get html data by serializing all frames of current page with lists
269  // which contain all resource links that have local copy.
270  // The parameter links contain original URLs of all saved links.
271  // The parameter local_paths contain corresponding local file paths of
272  // all saved links, which matched with vector:links one by one.
273  // The parameter local_directory_name is relative path of directory which
274  // contain all saved auxiliary files included all sub frames and resouces.
275  void GetSerializedHtmlDataForCurrentPageWithLocalLinks(
276      const std::vector<GURL>& links,
277      const std::vector<base::FilePath>& local_paths,
278      const base::FilePath& local_directory_name);
279
280  // Notifies the RenderViewHost that its load state changed.
281  void LoadStateChanged(const GURL& url,
282                        const net::LoadStateWithParam& load_state,
283                        uint64 upload_position,
284                        uint64 upload_size);
285
286  bool SuddenTerminationAllowed() const;
287  void set_sudden_termination_allowed(bool enabled) {
288    sudden_termination_allowed_ = enabled;
289  }
290
291  // RenderWidgetHost public overrides.
292  virtual void Init() OVERRIDE;
293  virtual void Shutdown() OVERRIDE;
294  virtual void WasHidden() OVERRIDE;
295  virtual void WasShown(const ui::LatencyInfo& latency_info) OVERRIDE;
296  virtual bool IsRenderView() const OVERRIDE;
297  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
298  virtual void GotFocus() OVERRIDE;
299  virtual void LostCapture() OVERRIDE;
300  virtual void LostMouseLock() OVERRIDE;
301  virtual void SetIsLoading(bool is_loading) OVERRIDE;
302  virtual void ForwardMouseEvent(
303      const blink::WebMouseEvent& mouse_event) OVERRIDE;
304  virtual void OnPointerEventActivate() OVERRIDE;
305  virtual void ForwardKeyboardEvent(
306      const NativeWebKeyboardEvent& key_event) OVERRIDE;
307  virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
308
309  // Creates a new RenderView with the given route id.
310  void CreateNewWindow(
311      int route_id,
312      int main_frame_route_id,
313      const ViewHostMsg_CreateWindow_Params& params,
314      SessionStorageNamespace* session_storage_namespace);
315
316  // Creates a new RenderWidget with the given route id.  |popup_type| indicates
317  // if this widget is a popup and what kind of popup it is (select, autofill).
318  void CreateNewWidget(int route_id, blink::WebPopupType popup_type);
319
320  // Creates a full screen RenderWidget.
321  void CreateNewFullscreenWidget(int route_id);
322
323#if defined(ENABLE_BROWSER_CDMS)
324  MediaWebContentsObserver* media_web_contents_observer() {
325    return media_web_contents_observer_.get();
326  }
327#endif
328
329  int main_frame_routing_id() const {
330    return main_frame_routing_id_;
331  }
332
333  bool is_waiting_for_beforeunload_ack() {
334    return is_waiting_for_beforeunload_ack_;
335  }
336
337  // Whether the RVH is waiting for the unload ack from the renderer.
338  bool IsWaitingForUnloadACK() const;
339
340  void OnTextSurroundingSelectionResponse(const base::string16& content,
341                                          size_t start_offset,
342                                          size_t end_offset);
343
344  // Update the FrameTree to use this RenderViewHost's main frame
345  // RenderFrameHost. Called when the RenderViewHost is committed.
346  //
347  // TODO(ajwong): Remove once RenderViewHost no longer owns the main frame
348  // RenderFrameHost.
349  void AttachToFrameTree();
350
351  // Increases the refcounting on this RVH. This is done by the FrameTree on
352  // creation of a RenderFrameHost.
353  void increment_ref_count() { ++frames_ref_count_; }
354
355  // Decreases the refcounting on this RVH. This is done by the FrameTree on
356  // destruction of a RenderFrameHost.
357  void decrement_ref_count() { --frames_ref_count_; }
358
359  // Returns the refcount on this RVH, that is the number of RenderFrameHosts
360  // currently using it.
361  int ref_count() { return frames_ref_count_; }
362
363  // NOTE: Do not add functions that just send an IPC message that are called in
364  // one or two places. Have the caller send the IPC message directly (unless
365  // the caller places are in different platforms, in which case it's better
366  // to keep them consistent).
367
368 protected:
369  // RenderWidgetHost protected overrides.
370  virtual void OnUserGesture() OVERRIDE;
371  virtual void NotifyRendererUnresponsive() OVERRIDE;
372  virtual void NotifyRendererResponsive() OVERRIDE;
373  virtual void OnRenderAutoResized(const gfx::Size& size) OVERRIDE;
374  virtual void RequestToLockMouse(bool user_gesture,
375                                  bool last_unlocked_by_target) OVERRIDE;
376  virtual bool IsFullscreen() const OVERRIDE;
377  virtual void OnFocus() OVERRIDE;
378  virtual void OnBlur() OVERRIDE;
379
380  // IPC message handlers.
381  void OnShowView(int route_id,
382                  WindowOpenDisposition disposition,
383                  const gfx::Rect& initial_pos,
384                  bool user_gesture);
385  void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
386  void OnShowFullscreenWidget(int route_id);
387  void OnRunModal(int opener_id, IPC::Message* reply_msg);
388  void OnRenderViewReady();
389  void OnRenderProcessGone(int status, int error_code);
390  void OnUpdateState(int32 page_id, const PageState& state);
391  void OnUpdateTargetURL(const GURL& url);
392  void OnClose();
393  void OnRequestMove(const gfx::Rect& pos);
394  void OnDocumentAvailableInMainFrame(bool uses_temporary_zoom_level);
395  void OnToggleFullscreen(bool enter_fullscreen);
396  void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
397  void OnPasteFromSelectionClipboard();
398  void OnRouteCloseEvent();
399  void OnRouteMessageEvent(const ViewMsg_PostMessage_Params& params);
400  void OnStartDragging(const DropData& drop_data,
401                       blink::WebDragOperationsMask operations_allowed,
402                       const SkBitmap& bitmap,
403                       const gfx::Vector2d& bitmap_offset_in_dip,
404                       const DragEventSourceInfo& event_info);
405  void OnUpdateDragCursor(blink::WebDragOperation drag_operation);
406  void OnTargetDropACK();
407  void OnTakeFocus(bool reverse);
408  void OnFocusedNodeChanged(bool is_editable_node);
409  void OnClosePageACK();
410  void OnDidZoomURL(double zoom_level, const GURL& url);
411  void OnRunFileChooser(const FileChooserParams& params);
412  void OnFocusedNodeTouched(bool editable);
413
414 private:
415  // TODO(nasko): Temporarily friend RenderFrameHostImpl, so we don't duplicate
416  // utility functions and state needed in both classes, while we move frame
417  // specific code away from this class.
418  friend class RenderFrameHostImpl;
419  friend class TestRenderViewHost;
420  FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, BasicRenderFrameHost);
421  FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, RoutingIdSane);
422
423  // TODO(creis): Move to a private namespace on RenderFrameHostImpl.
424  // Delay to wait on closing the WebContents for a beforeunload/unload handler
425  // to fire.
426  static const int kUnloadTimeoutMS;
427
428  // Updates the state of this RenderViewHost and clears any waiting state
429  // that is no longer relevant.
430  void SetState(RenderViewHostImplState rvh_state);
431
432  bool CanAccessFilesOfPageState(const PageState& state) const;
433
434  // The number of RenderFrameHosts which have a reference to this RVH.
435  int frames_ref_count_;
436
437  // Our delegate, which wants to know about changes in the RenderView.
438  RenderViewHostDelegate* delegate_;
439
440  // The SiteInstance associated with this RenderViewHost.  All pages drawn
441  // in this RenderViewHost are part of this SiteInstance.  Should not change
442  // over time.
443  scoped_refptr<SiteInstanceImpl> instance_;
444
445  // true if we are currently waiting for a response for drag context
446  // information.
447  bool waiting_for_drag_context_response_;
448
449  // A bitwise OR of bindings types that have been enabled for this RenderView.
450  // See BindingsPolicy for details.
451  int enabled_bindings_;
452
453  // The most recent page ID we've heard from the renderer process.  This is
454  // used as context when other session history related IPCs arrive.
455  // TODO(creis): Allocate this in WebContents/NavigationController instead.
456  int32 page_id_;
457
458  // The current state of this RVH.
459  // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
460  RenderViewHostImplState rvh_state_;
461
462  // Routing ID for the main frame's RenderFrameHost.
463  int main_frame_routing_id_;
464
465  // If we were asked to RunModal, then this will hold the reply_msg that we
466  // must return to the renderer to unblock it.
467  IPC::Message* run_modal_reply_msg_;
468  // This will hold the routing id of the RenderView that opened us.
469  int run_modal_opener_id_;
470
471  // Set to true when there is a pending ViewMsg_ShouldClose message.  This
472  // ensures we don't spam the renderer with multiple beforeunload requests.
473  // When either this value or IsWaitingForUnloadACK is true, the value of
474  // unload_ack_is_for_cross_site_transition_ indicates whether this is for a
475  // cross-site transition or a tab close attempt.
476  // TODO(clamy): Remove this boolean and add one more state to the state
477  // machine.
478  // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
479  bool is_waiting_for_beforeunload_ack_;
480
481  // Valid only when is_waiting_for_beforeunload_ack_ or
482  // IsWaitingForUnloadACK is true.  This tells us if the unload request
483  // is for closing the entire tab ( = false), or only this RenderViewHost in
484  // the case of a cross-site transition ( = true).
485  // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
486  bool unload_ack_is_for_cross_site_transition_;
487
488  // True if the render view can be shut down suddenly.
489  bool sudden_termination_allowed_;
490
491  // The termination status of the last render view that terminated.
492  base::TerminationStatus render_view_termination_status_;
493
494  // Set to true if we requested the on screen keyboard to be displayed.
495  bool virtual_keyboard_requested_;
496
497#if defined(ENABLE_BROWSER_CDMS)
498  // Manages all the media player and CDM managers and forwards IPCs to them.
499  scoped_ptr<MediaWebContentsObserver> media_web_contents_observer_;
500#endif
501
502  // Used to swap out or shutdown this RVH when the unload event is taking too
503  // long to execute, depending on the number of active views in the
504  // SiteInstance.
505  // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
506  scoped_ptr<TimeoutMonitor> unload_event_monitor_timeout_;
507
508  // Called after receiving the SwapOutACK when the RVH is in state pending
509  // shutdown. Also called if the unload timer times out.
510  // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
511  base::Closure pending_shutdown_on_swap_out_;
512
513  // True if the current focused element is editable.
514  bool is_focused_element_editable_;
515
516  // This is updated every time UpdateWebkitPreferences is called. That method
517  // is in turn called when any of the settings change that the WebPreferences
518  // values depend on.
519  scoped_ptr<WebPreferences> web_preferences_;
520
521  bool updating_web_preferences_;
522
523  base::WeakPtrFactory<RenderViewHostImpl> weak_factory_;
524
525  DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
526};
527
528#if defined(COMPILER_MSVC)
529#pragma warning(pop)
530#endif
531
532}  // namespace content
533
534#endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_VIEW_HOST_IMPL_H_
535