- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / browser_plugin / browser_plugin_guest.h
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 WebContentsDelegate and WebContentsObserver for the
14 // guest WebContents. BrowserPluginGuest operates under the assumption that the
15 // guest will be 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/id_map.h"
26 #include "base/memory/shared_memory.h"
27 #include "base/memory/weak_ptr.h"
28 #include "base/values.h"
29 #include "content/common/edit_command.h"
30 #include "content/port/common/input_event_ack_state.h"
31 #include "content/public/browser/browser_plugin_guest_delegate.h"
32 #include "content/public/browser/javascript_dialog_manager.h"
33 #include "content/public/browser/web_contents_delegate.h"
34 #include "content/public/browser/web_contents_observer.h"
35 #include "content/public/common/browser_plugin_permission_type.h"
36 #include "third_party/WebKit/public/web/WebDragOperation.h"
37 #include "third_party/WebKit/public/web/WebDragStatus.h"
38 #include "third_party/WebKit/public/web/WebInputEvent.h"
39 #include "ui/gfx/rect.h"
40 #include "ui/surface/transport_dib.h"
41
42 struct BrowserPluginHostMsg_AutoSize_Params;
43 struct BrowserPluginHostMsg_Attach_Params;
44 struct BrowserPluginHostMsg_ResizeGuest_Params;
45 struct ViewHostMsg_CreateWindow_Params;
46 #if defined(OS_MACOSX)
47 struct ViewHostMsg_ShowPopup_Params;
48 #endif
49 struct ViewHostMsg_UpdateRect_Params;
50 class WebCursor;
51
52 namespace cc {
53 class CompositorFrameAck;
54 }
55
56 namespace WebKit {
57 class WebInputEvent;
58 }
59
60 namespace content {
61
62 class BrowserPluginHostFactory;
63 class BrowserPluginEmbedder;
64 class BrowserPluginGuestManager;
65 class RenderProcessHost;
66 class RenderWidgetHostView;
67 class SiteInstance;
68 struct DropData;
69 struct MediaStreamRequest;
70
71 // A browser plugin guest provides functionality for WebContents to operate in
72 // the guest role and implements guest-specific overrides for ViewHostMsg_*
73 // messages.
74 //
75 // When a guest is initially created, it is in an unattached state. That is,
76 // it is not visible anywhere and has no embedder WebContents assigned.
77 // A BrowserPluginGuest is said to be "attached" if it has an embedder.
78 // A BrowserPluginGuest can also create a new unattached guest via
79 // CreateNewWindow. The newly created guest will live in the same partition,
80 // which means it can share storage and can script this guest.
81 class CONTENT_EXPORT BrowserPluginGuest
82     : public JavaScriptDialogManager,
83       public WebContentsDelegate,
84       public WebContentsObserver,
85       public base::SupportsWeakPtr<BrowserPluginGuest> {
86  public:
87   typedef base::Callback<void(bool)> GeolocationCallback;
88   virtual ~BrowserPluginGuest();
89
90   // The WebContents passed into the factory method here has not been
91   // initialized yet and so it does not yet hold a SiteInstance.
92   // BrowserPluginGuest must be constructed and installed into a WebContents
93   // prior to its initialization because WebContents needs to determine what
94   // type of WebContentsView to construct on initialization. The content
95   // embedder needs to be aware of |guest_site_instance| on the guest's
96   // construction and so we pass it in here.
97   static BrowserPluginGuest* Create(
98       int instance_id,
99       SiteInstance* guest_site_instance,
100       WebContentsImpl* web_contents,
101       scoped_ptr<base::DictionaryValue> extra_params);
102
103   static BrowserPluginGuest* CreateWithOpener(
104       int instance_id,
105       WebContentsImpl* web_contents,
106       BrowserPluginGuest* opener,
107       bool has_render_view);
108
109   // Called when the embedder WebContents is destroyed to give the
110   // BrowserPluginGuest an opportunity to clean up after itself.
111   void EmbedderDestroyed();
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   // Returns the identifier that uniquely identifies a browser plugin guest
121   // within an embedder.
122   int instance_id() const { return instance_id_; }
123
124   // Overrides factory for testing. Default (NULL) value indicates regular
125   // (non-test) environment.
126   static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
127     BrowserPluginGuest::factory_ = factory;
128   }
129
130   bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
131
132   void Initialize(WebContentsImpl* embedder_web_contents,
133                   const BrowserPluginHostMsg_Attach_Params& params);
134
135   void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) {
136     guest_hang_timeout_ = timeout;
137   }
138
139   WebContentsImpl* embedder_web_contents() const {
140     return embedder_web_contents_;
141   }
142
143   RenderWidgetHostView* GetEmbedderRenderWidgetHostView();
144
145   bool focused() const { return focused_; }
146   bool visible() const { return guest_visible_; }
147   void clear_damage_buffer() { damage_buffer_.reset(); }
148   bool is_in_destruction() { return is_in_destruction_; }
149
150   BrowserPluginGuest* opener() const { return opener_.get(); }
151
152   // Returns whether the mouse pointer was unlocked.
153   bool UnlockMouseIfNecessary(const NativeWebKeyboardEvent& event);
154
155   void UpdateVisibility();
156
157   // WebContentsObserver implementation.
158   virtual void DidCommitProvisionalLoadForFrame(
159       int64 frame_id,
160       const string16& frame_unique_name,
161       bool is_main_frame,
162       const GURL& url,
163       PageTransition transition_type,
164       RenderViewHost* render_view_host) OVERRIDE;
165   virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
166
167   virtual void RenderViewReady() OVERRIDE;
168   virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
169   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
170
171   // WebContentsDelegate implementation.
172   virtual bool AddMessageToConsole(WebContents* source,
173                                    int32 level,
174                                    const string16& message,
175                                    int32 line_no,
176                                    const string16& source_id) OVERRIDE;
177   // If a new window is created with target="_blank" and rel="noreferrer", then
178   // this method is called, indicating that the new WebContents is ready to be
179   // attached.
180   virtual void AddNewContents(WebContents* source,
181                               WebContents* new_contents,
182                               WindowOpenDisposition disposition,
183                               const gfx::Rect& initial_pos,
184                               bool user_gesture,
185                               bool* was_blocked) OVERRIDE;
186   virtual void CanDownload(RenderViewHost* render_view_host,
187                            int request_id,
188                            const std::string& request_method,
189                            const base::Callback<void(bool)>& callback) OVERRIDE;
190   virtual void LoadProgressChanged(WebContents* source,
191                                    double progress) OVERRIDE;
192   virtual void CloseContents(WebContents* source) OVERRIDE;
193   virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE;
194   virtual bool HandleContextMenu(const ContextMenuParams& params) OVERRIDE;
195   virtual void HandleKeyboardEvent(
196       WebContents* source,
197       const NativeWebKeyboardEvent& event) OVERRIDE;
198   virtual WebContents* OpenURLFromTab(WebContents* source,
199                                       const OpenURLParams& params) OVERRIDE;
200   virtual void WebContentsCreated(WebContents* source_contents,
201                                   int64 source_frame_id,
202                                   const string16& frame_name,
203                                   const GURL& target_url,
204                                   WebContents* new_contents) OVERRIDE;
205   virtual void RendererUnresponsive(WebContents* source) OVERRIDE;
206   virtual void RendererResponsive(WebContents* source) OVERRIDE;
207   virtual void RunFileChooser(WebContents* web_contents,
208                               const FileChooserParams& params) OVERRIDE;
209   virtual bool ShouldFocusPageAfterCrash() OVERRIDE;
210   virtual void RequestMediaAccessPermission(
211       WebContents* web_contents,
212       const MediaStreamRequest& request,
213       const MediaResponseCallback& callback) OVERRIDE;
214
215   // JavaScriptDialogManager implementation.
216   virtual void RunJavaScriptDialog(
217       WebContents* web_contents,
218       const GURL& origin_url,
219       const std::string& accept_lang,
220       JavaScriptMessageType javascript_message_type,
221       const string16& message_text,
222       const string16& default_prompt_text,
223       const DialogClosedCallback& callback,
224       bool* did_suppress_message) OVERRIDE;
225   virtual void RunBeforeUnloadDialog(
226       WebContents* web_contents,
227       const string16& message_text,
228       bool is_reload,
229       const DialogClosedCallback& callback) OVERRIDE;
230   virtual bool HandleJavaScriptDialog(WebContents* web_contents,
231                                       bool accept,
232                                       const string16* prompt_override) OVERRIDE;
233   virtual void CancelActiveAndPendingDialogs(
234       WebContents* web_contents) OVERRIDE;
235   virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
236
237   // Exposes the protected web_contents() from WebContentsObserver.
238   WebContentsImpl* GetWebContents();
239
240   // Overridden in tests.
241   virtual void SetDamageBuffer(
242       const BrowserPluginHostMsg_ResizeGuest_Params& params);
243
244   gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const;
245
246   // Helper to send messages to embedder. This methods fills the message with
247   // the correct routing id.
248   // Overridden in test implementation since we want to intercept certain
249   // messages for testing.
250   virtual void SendMessageToEmbedder(IPC::Message* msg);
251
252   // Returns whether the guest is attached to an embedder.
253   bool attached() const { return !!embedder_web_contents_; }
254
255   // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
256   // and initializes the guest with the provided |params|. Attaching a guest
257   // to an embedder implies that this guest's lifetime is no longer managed
258   // by its opener, and it can begin loading resources. |extra_params| are
259   // parameters passed into BrowserPlugin from JavaScript to be forwarded to
260   // the content embedder.
261   void Attach(WebContentsImpl* embedder_web_contents,
262               BrowserPluginHostMsg_Attach_Params params,
263               const base::DictionaryValue& extra_params);
264
265   // Requests geolocation permission through Embedder JavaScript API.
266   void AskEmbedderForGeolocationPermission(int bridge_id,
267                                            const GURL& requesting_frame,
268                                            const GeolocationCallback& callback);
269   // Cancels pending geolocation request.
270   void CancelGeolocationRequest(int bridge_id);
271
272   // Allow the embedder to call this for unhandled messages when
273   // BrowserPluginGuest is already destroyed.
274   static void AcknowledgeBufferPresent(int route_id,
275                                        int gpu_host_id,
276                                        const std::string& mailbox_name,
277                                        uint32 sync_point);
278
279   // Returns whether BrowserPluginGuest is interested in receiving the given
280   // |message|.
281   static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
282   gfx::Rect ToGuestRect(const gfx::Rect& rect);
283
284   void DragSourceEndedAt(int client_x, int client_y, int screen_x,
285       int screen_y, WebKit::WebDragOperation operation);
286
287   void DragSourceMovedTo(int client_x, int client_y,
288                          int screen_x, int screen_y);
289
290   // Called when the drag started by this guest ends at an OS-level.
291   void EndSystemDrag();
292
293   // |this| takes ownership of |delegate|.
294   void SetDelegate(BrowserPluginGuestDelegate* delegate);
295
296   void RespondToPermissionRequest(int request_id,
297                                   bool should_allow,
298                                   const std::string& user_input);
299
300  private:
301   class EmbedderWebContentsObserver;
302   friend class TestBrowserPluginGuest;
303
304   class DownloadRequest;
305   class GeolocationRequest;
306   class JavaScriptDialogRequest;
307   // MediaRequest because of naming conflicts with MediaStreamRequest.
308   class MediaRequest;
309   class NewWindowRequest;
310   class PermissionRequest;
311   class PointerLockRequest;
312
313   BrowserPluginGuest(int instance_id,
314                      WebContentsImpl* web_contents,
315                      BrowserPluginGuest* opener,
316                      bool has_render_view);
317
318   // Destroy unattached new windows that have been opened by this
319   // BrowserPluginGuest.
320   void DestroyUnattachedWindows();
321
322   void LoadURLWithParams(WebContents* web_contents,
323                          const GURL& url,
324                          const Referrer& referrer,
325                          PageTransition transition_type);
326
327   // Bridge IDs correspond to a geolocation request. This method will remove
328   // the bookkeeping for a particular geolocation request associated with the
329   // provided |bridge_id|. It returns the request ID of the geolocation request.
330   int RemoveBridgeID(int bridge_id);
331
332   // Returns the |request_id| generated for the |request| provided.
333   int RequestPermission(
334       BrowserPluginPermissionType permission_type,
335       scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
336       const base::DictionaryValue& request_info);
337
338   // Creates a new guest window, and BrowserPluginGuest that is owned by this
339   // BrowserPluginGuest.
340   BrowserPluginGuest* CreateNewGuestWindow(const OpenURLParams& params);
341
342   base::SharedMemory* damage_buffer() const { return damage_buffer_.get(); }
343   const gfx::Size& damage_view_size() const { return damage_view_size_; }
344   float damage_buffer_scale_factor() const {
345     return damage_buffer_scale_factor_;
346   }
347   // Returns the damage buffer corresponding to the handle in resize |params|.
348   base::SharedMemory* GetDamageBufferFromEmbedder(
349       const BrowserPluginHostMsg_ResizeGuest_Params& params);
350
351   bool InAutoSizeBounds(const gfx::Size& size) const;
352
353   void RequestNewWindowPermission(WebContentsImpl* new_contents,
354                                   WindowOpenDisposition disposition,
355                                   const gfx::Rect& initial_bounds,
356                                   bool user_gesture);
357
358   // Message handlers for messages from embedder.
359
360   void OnCompositorFrameACK(int instance_id,
361                             int route_id,
362                             uint32 output_surface_id,
363                             int renderer_host_id,
364                             const cc::CompositorFrameAck& ack);
365
366   // Handles drag events from the embedder.
367   // When dragging, the drag events go to the embedder first, and if the drag
368   // happens on the browser plugin, then the plugin sends a corresponding
369   // drag-message to the guest. This routes the drag-message to the guest
370   // renderer.
371   void OnDragStatusUpdate(int instance_id,
372                           WebKit::WebDragStatus drag_status,
373                           const DropData& drop_data,
374                           WebKit::WebDragOperationsMask drag_mask,
375                           const gfx::Point& location);
376   // Instructs the guest to execute an edit command decoded in the embedder.
377   void OnExecuteEditCommand(int instance_id,
378                             const std::string& command);
379   // Overriden in tests.
380   virtual void OnHandleInputEvent(int instance_id,
381                                   const gfx::Rect& guest_window_rect,
382                                   const WebKit::WebInputEvent* event);
383   void OnLockMouse(bool user_gesture,
384                    bool last_unlocked_by_target,
385                    bool privileged);
386   void OnLockMouseAck(int instance_id, bool succeeded);
387   void OnNavigateGuest(int instance_id, const std::string& src);
388   void OnPluginDestroyed(int instance_id);
389   // Grab the new damage buffer from the embedder, and resize the guest's
390   // web contents.
391   void OnResizeGuest(int instance_id,
392                      const BrowserPluginHostMsg_ResizeGuest_Params& params);
393   // Overriden in tests.
394   virtual void OnSetFocus(int instance_id, bool focused);
395   // Sets the name of the guest so that other guests in the same partition can
396   // access it.
397   void OnSetName(int instance_id, const std::string& name);
398   // Updates the size state of the guest.
399   void OnSetSize(
400       int instance_id,
401       const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
402       const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
403   void OnSetEditCommandsForNextKeyEvent(
404       int instance_id,
405       const std::vector<EditCommand>& edit_commands);
406   // The guest WebContents is visible if both its embedder is visible and
407   // the browser plugin element is visible. If either one is not then the
408   // WebContents is marked as hidden. A hidden WebContents will consume
409   // fewer GPU and CPU resources.
410   //
411   // When every WebContents in a RenderProcessHost is hidden, it will lower
412   // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
413   //
414   // It will also send a message to the guest renderer process to cleanup
415   // resources such as dropping back buffers and adjusting memory limits (if in
416   // compositing mode, see CCLayerTreeHost::setVisible).
417   //
418   // Additionally, it will slow down Javascript execution and garbage
419   // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
420   // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
421   void OnSetVisibility(int instance_id, bool visible);
422   // Message from embedder acknowledging last HW buffer.
423   void OnSwapBuffersACK(int instance_id,
424                         int route_id,
425                         int gpu_host_id,
426                         const std::string& mailbox_name,
427                         uint32 sync_point);
428   void OnUnlockMouse();
429   void OnUnlockMouseAck(int instance_id);
430   void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
431   void OnUpdateRectACK(
432       int instance_id,
433       bool needs_ack,
434       const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
435       const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
436
437
438   // Message handlers for messages from guest.
439
440   void OnDragStopped();
441   void OnHandleInputEventAck(
442       WebKit::WebInputEvent::Type event_type,
443       InputEventAckState ack_result);
444   void OnHasTouchEventHandlers(bool accept);
445   void OnSetCursor(const WebCursor& cursor);
446   // On MacOSX popups are painted by the browser process. We handle them here
447   // so that they are positioned correctly.
448 #if defined(OS_MACOSX)
449   void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
450 #endif
451   void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
452   // Overriden in tests.
453   virtual void OnTakeFocus(bool reverse);
454   void OnUpdateFrameName(int frame_id,
455                          bool is_top_level,
456                          const std::string& name);
457   void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
458
459   // Requests download permission through embedder JavaScript API after
460   // retrieving url information from IO thread.
461   void DidRetrieveDownloadURLFromRequestId(
462       const std::string& request_method,
463       const base::Callback<void(bool)>& callback,
464       const std::string& url);
465
466   // Embedder sets permission to allow or deny geolocation request.
467   void SetGeolocationPermission(
468       GeolocationCallback callback, int bridge_id, bool allowed);
469
470   // Forwards all messages from the |pending_messages_| queue to the embedder.
471   void SendQueuedMessages();
472
473   // Weak pointer used to ask GeolocationPermissionContext about geolocation
474   // permission.
475   base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
476
477   // Static factory instance (always NULL for non-test).
478   static BrowserPluginHostFactory* factory_;
479
480   scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
481   WebContentsImpl* embedder_web_contents_;
482
483   std::map<int, int> bridge_id_to_request_id_map_;
484
485   // An identifier that uniquely identifies a browser plugin guest within an
486   // embedder.
487   int instance_id_;
488   scoped_ptr<base::SharedMemory> damage_buffer_;
489   // An identifier that uniquely identifies a damage buffer.
490   uint32 damage_buffer_sequence_id_;
491   size_t damage_buffer_size_;
492   gfx::Size damage_view_size_;
493   float damage_buffer_scale_factor_;
494   float guest_device_scale_factor_;
495   gfx::Rect guest_window_rect_;
496   gfx::Rect guest_screen_rect_;
497   base::TimeDelta guest_hang_timeout_;
498   bool focused_;
499   bool mouse_locked_;
500   bool pending_lock_request_;
501   bool guest_visible_;
502   bool embedder_visible_;
503   std::string name_;
504   bool auto_size_enabled_;
505   gfx::Size max_auto_size_;
506   gfx::Size min_auto_size_;
507
508   // Tracks the name, and target URL of the new window and whether or not it has
509   // changed since the WebContents has been created and before the new window
510   // has been attached to a BrowserPlugin. Once the first navigation commits, we
511   // no longer track this information.
512   struct NewWindowInfo {
513     bool changed;
514     GURL url;
515     std::string name;
516     NewWindowInfo(const GURL& url, const std::string& name) :
517         changed(false),
518         url(url),
519         name(name) {}
520   };
521   typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap;
522   PendingWindowMap pending_new_windows_;
523   base::WeakPtr<BrowserPluginGuest> opener_;
524   // A counter to generate a unique request id for a permission request.
525   // We only need the ids to be unique for a given BrowserPluginGuest.
526   int next_permission_request_id_;
527
528   // A map to store relevant info for a request keyed by the request's id.
529   typedef std::map<int, scoped_refptr<PermissionRequest> > RequestMap;
530   RequestMap permission_request_map_;
531
532   // Indicates that this BrowserPluginGuest has associated renderer-side state.
533   // This is used to determine whether or not to create a new RenderView when
534   // this guest is attached.
535   bool has_render_view_;
536
537   // Last seen size of guest contents (by OnUpdateRect).
538   gfx::Size last_seen_view_size_;
539   // Last seen autosize attribute state (by OnUpdateRect).
540   bool last_seen_auto_size_enabled_;
541
542   bool is_in_destruction_;
543
544   // This is a queue of messages that are destined to be sent to the embedder
545   // once the guest is attached to a particular embedder.
546   std::queue<IPC::Message*> pending_messages_;
547
548   scoped_ptr<BrowserPluginGuestDelegate> delegate_;
549
550   // These are parameters passed from JavaScript on attachment to the content
551   // embedder.
552   scoped_ptr<base::DictionaryValue> extra_attach_params_;
553
554   DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
555 };
556
557 }  // namespace content
558
559 #endif  // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_