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