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// A BrowserPluginGuest is the browser side of a browser <--> embedder
6// renderer channel. A BrowserPlugin (a WebPlugin) is on the embedder
7// renderer side of browser <--> embedder renderer communication.
8//
9// BrowserPluginGuest lives on the UI thread of the browser process. Any
10// messages about the guest render process that the embedder might be interested
11// in receiving should be listened for here.
12//
13// BrowserPluginGuest is a WebContentsObserver for the guest WebContents.
14// BrowserPluginGuest operates under the assumption that the guest will be
15// accessible through only one RenderViewHost for the lifetime of
16// the guest WebContents. Thus, cross-process navigation is not supported.
17
18#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
19#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
20
21#include <map>
22#include <queue>
23
24#include "base/compiler_specific.h"
25#include "base/memory/linked_ptr.h"
26#include "base/memory/weak_ptr.h"
27#include "base/values.h"
28#include "content/common/edit_command.h"
29#include "content/common/input/input_event_ack_state.h"
30#include "content/public/browser/browser_plugin_guest_delegate.h"
31#include "content/public/browser/web_contents_observer.h"
32#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
33#include "third_party/WebKit/public/web/WebDragOperation.h"
34#include "third_party/WebKit/public/web/WebDragStatus.h"
35#include "third_party/WebKit/public/web/WebInputEvent.h"
36#include "ui/base/ime/text_input_mode.h"
37#include "ui/base/ime/text_input_type.h"
38#include "ui/gfx/rect.h"
39
40class SkBitmap;
41struct BrowserPluginHostMsg_Attach_Params;
42struct BrowserPluginHostMsg_ResizeGuest_Params;
43struct FrameHostMsg_CompositorFrameSwappedACK_Params;
44struct FrameHostMsg_ReclaimCompositorResources_Params;
45#if defined(OS_MACOSX)
46struct FrameHostMsg_ShowPopup_Params;
47#endif
48
49namespace blink {
50class WebInputEvent;
51}  // namespace blink
52
53namespace cc {
54class CompositorFrame;
55}  // namespace cc
56
57namespace gfx {
58class Range;
59}  // namespace gfx
60
61namespace content {
62
63class BrowserPluginGuestManager;
64class RenderViewHostImpl;
65class RenderWidgetHost;
66class RenderWidgetHostView;
67class SiteInstance;
68struct DropData;
69
70// A browser plugin guest provides functionality for WebContents to operate in
71// the guest role and implements guest-specific overrides for ViewHostMsg_*
72// messages.
73//
74// When a guest is initially created, it is in an unattached state. That is,
75// it is not visible anywhere and has no embedder WebContents assigned.
76// A BrowserPluginGuest is said to be "attached" if it has an embedder.
77// A BrowserPluginGuest can also create a new unattached guest via
78// CreateNewWindow. The newly created guest will live in the same partition,
79// which means it can share storage and can script this guest.
80class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
81 public:
82  virtual ~BrowserPluginGuest();
83
84  // The WebContents passed into the factory method here has not been
85  // initialized yet and so it does not yet hold a SiteInstance.
86  // BrowserPluginGuest must be constructed and installed into a WebContents
87  // prior to its initialization because WebContents needs to determine what
88  // type of WebContentsView to construct on initialization. The content
89  // embedder needs to be aware of |guest_site_instance| on the guest's
90  // construction and so we pass it in here.
91  static BrowserPluginGuest* Create(WebContentsImpl* web_contents,
92                                    BrowserPluginGuestDelegate* delegate);
93
94  // Returns whether the given WebContents is a BrowserPlugin guest.
95  static bool IsGuest(WebContentsImpl* web_contents);
96
97  // Returns whether the given RenderviewHost is a BrowserPlugin guest.
98  static bool IsGuest(RenderViewHostImpl* render_view_host);
99
100  // Returns a WeakPtr to this BrowserPluginGuest.
101  base::WeakPtr<BrowserPluginGuest> AsWeakPtr();
102
103  // Sets the focus state of the current RenderWidgetHostView.
104  void SetFocus(RenderWidgetHost* rwh, bool focused);
105
106  // Sets the lock state of the pointer. Returns true if |allowed| is true and
107  // the mouse has been successfully locked.
108  bool LockMouse(bool allowed);
109
110  // Return true if the mouse is locked.
111  bool mouse_locked() const { return mouse_locked_; }
112
113  // Called when the embedder WebContents changes visibility.
114  void EmbedderVisibilityChanged(bool visible);
115
116  // Destroys the guest WebContents and all its associated state, including
117  // this BrowserPluginGuest, and its new unattached windows.
118  void Destroy();
119
120  // Creates a new guest WebContentsImpl with the provided |params| with |this|
121  // as the |opener|.
122  WebContentsImpl* CreateNewGuestWindow(
123      const WebContents::CreateParams& params);
124
125  // Returns the identifier that uniquely identifies a browser plugin guest
126  // within an embedder.
127  int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
128
129  bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
130
131  WebContentsImpl* embedder_web_contents() const {
132    return embedder_web_contents_;
133  }
134
135  // Returns the embedder's RenderWidgetHostView if it is available.
136  // Returns NULL otherwise.
137  RenderWidgetHostView* GetEmbedderRenderWidgetHostView();
138
139  bool focused() const { return focused_; }
140  bool visible() const { return guest_visible_; }
141  bool is_in_destruction() { return is_in_destruction_; }
142
143  void UpdateVisibility();
144
145  void CopyFromCompositingSurface(
146      gfx::Rect src_subrect,
147      gfx::Size dst_size,
148      const base::Callback<void(bool, const SkBitmap&)>& callback);
149
150  BrowserPluginGuestManager* GetBrowserPluginGuestManager() const;
151
152  // WebContentsObserver implementation.
153  virtual void DidCommitProvisionalLoadForFrame(
154      RenderFrameHost* render_frame_host,
155      const GURL& url,
156      ui::PageTransition transition_type) OVERRIDE;
157
158  virtual void RenderViewReady() OVERRIDE;
159  virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
160  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
161  virtual bool OnMessageReceived(const IPC::Message& message,
162                                 RenderFrameHost* render_frame_host) OVERRIDE;
163
164  // Exposes the protected web_contents() from WebContentsObserver.
165  WebContentsImpl* GetWebContents() const;
166
167  gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const;
168
169  // Helper to send messages to embedder. This methods fills the message with
170  // the correct routing id.
171  void SendMessageToEmbedder(IPC::Message* msg);
172
173  // Returns whether the guest is attached to an embedder.
174  bool attached() const { return embedder_web_contents_ != NULL; }
175
176  // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
177  // and initializes the guest with the provided |params|. Attaching a guest
178  // to an embedder implies that this guest's lifetime is no longer managed
179  // by its opener, and it can begin loading resources.
180  void Attach(int browser_plugin_instance_id,
181              WebContentsImpl* embedder_web_contents,
182              const BrowserPluginHostMsg_Attach_Params& params);
183
184  // Returns whether BrowserPluginGuest is interested in receiving the given
185  // |message|.
186  static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
187
188  void DragSourceEndedAt(int client_x, int client_y, int screen_x,
189      int screen_y, blink::WebDragOperation operation);
190
191  // Called when the drag started by this guest ends at an OS-level.
192  void EndSystemDrag();
193
194  void RespondToPermissionRequest(int request_id,
195                                  bool should_allow,
196                                  const std::string& user_input);
197
198  void PointerLockPermissionResponse(bool allow);
199
200  void SwapCompositorFrame(uint32 output_surface_id,
201                           int host_process_id,
202                           int host_routing_id,
203                           scoped_ptr<cc::CompositorFrame> frame);
204
205  void SetContentsOpaque(bool opaque);
206
207 private:
208  class EmbedderWebContentsObserver;
209
210  // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
211  // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
212  BrowserPluginGuest(bool has_render_view,
213                     WebContentsImpl* web_contents,
214                     BrowserPluginGuestDelegate* delegate);
215
216  void WillDestroy();
217
218  void Initialize(int browser_plugin_instance_id,
219                  const BrowserPluginHostMsg_Attach_Params& params,
220                  WebContentsImpl* embedder_web_contents);
221
222  bool InAutoSizeBounds(const gfx::Size& size) const;
223
224  // Message handlers for messages from embedder.
225
226  void OnCompositorFrameSwappedACK(
227      int instance_id,
228      const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
229  void OnCopyFromCompositingSurfaceAck(int instance_id,
230                                       int request_id,
231                                       const SkBitmap& bitmap);
232  // Handles drag events from the embedder.
233  // When dragging, the drag events go to the embedder first, and if the drag
234  // happens on the browser plugin, then the plugin sends a corresponding
235  // drag-message to the guest. This routes the drag-message to the guest
236  // renderer.
237  void OnDragStatusUpdate(int instance_id,
238                          blink::WebDragStatus drag_status,
239                          const DropData& drop_data,
240                          blink::WebDragOperationsMask drag_mask,
241                          const gfx::Point& location);
242  // Instructs the guest to execute an edit command decoded in the embedder.
243  void OnExecuteEditCommand(int instance_id,
244                            const std::string& command);
245
246  // Returns compositor resources reclaimed in the embedder to the guest.
247  void OnReclaimCompositorResources(
248      int instance_id,
249      const FrameHostMsg_ReclaimCompositorResources_Params& params);
250
251  void OnLockMouse(bool user_gesture,
252                   bool last_unlocked_by_target,
253                   bool privileged);
254  void OnLockMouseAck(int instance_id, bool succeeded);
255  void OnPluginDestroyed(int instance_id);
256  // Resizes the guest's web contents.
257  void OnResizeGuest(
258      int instance_id, const BrowserPluginHostMsg_ResizeGuest_Params& params);
259  void OnSetFocus(int instance_id, bool focused);
260  // Sets the name of the guest so that other guests in the same partition can
261  // access it.
262  void OnSetName(int instance_id, const std::string& name);
263  // Updates the size state of the guest.
264  void OnSetEditCommandsForNextKeyEvent(
265      int instance_id,
266      const std::vector<EditCommand>& edit_commands);
267  // The guest WebContents is visible if both its embedder is visible and
268  // the browser plugin element is visible. If either one is not then the
269  // WebContents is marked as hidden. A hidden WebContents will consume
270  // fewer GPU and CPU resources.
271  //
272  // When every WebContents in a RenderProcessHost is hidden, it will lower
273  // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
274  //
275  // It will also send a message to the guest renderer process to cleanup
276  // resources such as dropping back buffers and adjusting memory limits (if in
277  // compositing mode, see CCLayerTreeHost::setVisible).
278  //
279  // Additionally, it will slow down Javascript execution and garbage
280  // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
281  // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
282  void OnSetVisibility(int instance_id, bool visible);
283  void OnUnlockMouse();
284  void OnUnlockMouseAck(int instance_id);
285  void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
286
287  void OnTextInputTypeChanged(ui::TextInputType type,
288                              ui::TextInputMode input_mode,
289                              bool can_compose_inline);
290  void OnImeSetComposition(
291      int instance_id,
292      const std::string& text,
293      const std::vector<blink::WebCompositionUnderline>& underlines,
294      int selection_start,
295      int selection_end);
296  void OnImeConfirmComposition(
297      int instance_id,
298      const std::string& text,
299      bool keep_selection);
300  void OnExtendSelectionAndDelete(int instance_id, int before, int after);
301  void OnImeCancelComposition();
302#if defined(OS_MACOSX) || defined(USE_AURA)
303  void OnImeCompositionRangeChanged(
304      const gfx::Range& range,
305      const std::vector<gfx::Rect>& character_bounds);
306#endif
307
308  // Message handlers for messages from guest.
309  void OnHandleInputEventAck(
310      blink::WebInputEvent::Type event_type,
311      InputEventAckState ack_result);
312  void OnHasTouchEventHandlers(bool accept);
313#if defined(OS_MACOSX)
314  // On MacOS X popups are painted by the browser process. We handle them here
315  // so that they are positioned correctly.
316  void OnShowPopup(RenderFrameHost* render_frame_host,
317                   const FrameHostMsg_ShowPopup_Params& params);
318#endif
319  void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
320  void OnTakeFocus(bool reverse);
321  void OnUpdateFrameName(int frame_id,
322                         bool is_top_level,
323                         const std::string& name);
324
325  // Forwards all messages from the |pending_messages_| queue to the embedder.
326  void SendQueuedMessages();
327
328  scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
329  WebContentsImpl* embedder_web_contents_;
330
331  // An identifier that uniquely identifies a browser plugin within an embedder.
332  int browser_plugin_instance_id_;
333  float guest_device_scale_factor_;
334  gfx::Rect guest_window_rect_;
335  bool focused_;
336  bool mouse_locked_;
337  bool pending_lock_request_;
338  bool guest_visible_;
339  bool embedder_visible_;
340
341  // Each copy-request is identified by a unique number. The unique number is
342  // used to keep track of the right callback.
343  int copy_request_id_;
344  typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
345  typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
346  CopyRequestMap copy_request_callbacks_;
347
348  // Indicates that this BrowserPluginGuest has associated renderer-side state.
349  // This is used to determine whether or not to create a new RenderView when
350  // this guest is attached. A BrowserPluginGuest would have renderer-side state
351  // prior to attachment if it is created via a call to window.open and
352  // maintains a JavaScript reference to its opener.
353  bool has_render_view_;
354
355  // Last seen size of guest contents (by SwapCompositorFrame).
356  gfx::Size last_seen_view_size_;
357  // Last seen size of BrowserPlugin (by OnResizeGuest).
358  gfx::Size last_seen_browser_plugin_size_;
359
360  bool is_in_destruction_;
361
362  // Text input type states.
363  ui::TextInputType last_text_input_type_;
364  ui::TextInputMode last_input_mode_;
365  bool last_can_compose_inline_;
366
367  // This is a queue of messages that are destined to be sent to the embedder
368  // once the guest is attached to a particular embedder.
369  std::deque<linked_ptr<IPC::Message> > pending_messages_;
370
371  BrowserPluginGuestDelegate* const delegate_;
372
373  // Weak pointer used to ask GeolocationPermissionContext about geolocation
374  // permission.
375  base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
376
377  DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
378};
379
380}  // namespace content
381
382#endif  // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
383