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. 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 
     40 class SkBitmap;
     41 struct BrowserPluginHostMsg_AutoSize_Params;
     42 struct BrowserPluginHostMsg_Attach_Params;
     43 struct BrowserPluginHostMsg_ResizeGuest_Params;
     44 struct FrameHostMsg_CompositorFrameSwappedACK_Params;
     45 struct FrameHostMsg_ReclaimCompositorResources_Params;
     46 #if defined(OS_MACOSX)
     47 struct ViewHostMsg_ShowPopup_Params;
     48 #endif
     49 struct ViewHostMsg_TextInputState_Params;
     50 struct ViewHostMsg_UpdateRect_Params;
     51 
     52 namespace blink {
     53 class WebInputEvent;
     54 }
     55 
     56 namespace gfx {
     57 class Range;
     58 }
     59 
     60 namespace content {
     61 
     62 class BrowserPluginGuestManager;
     63 class RenderViewHostImpl;
     64 class RenderWidgetHostView;
     65 class SiteInstance;
     66 class WebCursor;
     67 struct DropData;
     68 
     69 // A browser plugin guest provides functionality for WebContents to operate in
     70 // the guest role and implements guest-specific overrides for ViewHostMsg_*
     71 // messages.
     72 //
     73 // When a guest is initially created, it is in an unattached state. That is,
     74 // it is not visible anywhere and has no embedder WebContents assigned.
     75 // A BrowserPluginGuest is said to be "attached" if it has an embedder.
     76 // A BrowserPluginGuest can also create a new unattached guest via
     77 // CreateNewWindow. The newly created guest will live in the same partition,
     78 // which means it can share storage and can script this guest.
     79 class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
     80  public:
     81   virtual ~BrowserPluginGuest();
     82 
     83   // The WebContents passed into the factory method here has not been
     84   // initialized yet and so it does not yet hold a SiteInstance.
     85   // BrowserPluginGuest must be constructed and installed into a WebContents
     86   // prior to its initialization because WebContents needs to determine what
     87   // type of WebContentsView to construct on initialization. The content
     88   // embedder needs to be aware of |guest_site_instance| on the guest's
     89   // construction and so we pass it in here.
     90   static BrowserPluginGuest* Create(
     91       int instance_id,
     92       SiteInstance* guest_site_instance,
     93       WebContentsImpl* web_contents,
     94       scoped_ptr<base::DictionaryValue> extra_params,
     95       BrowserPluginGuest* opener);
     96 
     97   // Returns whether the given WebContents is a BrowserPlugin guest.
     98   static bool IsGuest(WebContentsImpl* web_contents);
     99 
    100   // Returns whether the given RenderviewHost is a BrowserPlugin guest.
    101   static bool IsGuest(RenderViewHostImpl* render_view_host);
    102 
    103   // Returns a WeakPtr to this BrowserPluginGuest.
    104   base::WeakPtr<BrowserPluginGuest> AsWeakPtr();
    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   // Called when the embedder WebContents changes visibility.
    111   void EmbedderVisibilityChanged(bool visible);
    112 
    113   // Destroys the guest WebContents and all its associated state, including
    114   // this BrowserPluginGuest, and its new unattached windows.
    115   void Destroy();
    116 
    117   // Returns the identifier that uniquely identifies a browser plugin guest
    118   // within an embedder.
    119   int instance_id() const { return instance_id_; }
    120 
    121   bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
    122 
    123   WebContentsImpl* embedder_web_contents() const {
    124     return embedder_web_contents_;
    125   }
    126 
    127   // Returns the embedder's RenderWidgetHostView if it is available.
    128   // Returns NULL otherwise.
    129   RenderWidgetHostView* GetEmbedderRenderWidgetHostView();
    130 
    131   bool focused() const { return focused_; }
    132   bool visible() const { return guest_visible_; }
    133   bool is_in_destruction() { return is_in_destruction_; }
    134 
    135   // Returns the BrowserPluginGuest that created this guest, if any.
    136   BrowserPluginGuest* GetOpener() const;
    137 
    138   void UpdateVisibility();
    139 
    140   void CopyFromCompositingSurface(
    141       gfx::Rect src_subrect,
    142       gfx::Size dst_size,
    143       const base::Callback<void(bool, const SkBitmap&)>& callback);
    144 
    145   BrowserPluginGuestManager* GetBrowserPluginGuestManager() const;
    146 
    147   // WebContentsObserver implementation.
    148   virtual void DidCommitProvisionalLoadForFrame(
    149       int64 frame_id,
    150       const base::string16& frame_unique_name,
    151       bool is_main_frame,
    152       const GURL& url,
    153       PageTransition transition_type,
    154       RenderViewHost* render_view_host) OVERRIDE;
    155 
    156   virtual void RenderViewReady() OVERRIDE;
    157   virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
    158   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
    159 
    160   // Exposes the protected web_contents() from WebContentsObserver.
    161   WebContentsImpl* GetWebContents() const;
    162 
    163   gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const;
    164 
    165   // Helper to send messages to embedder. This methods fills the message with
    166   // the correct routing id.
    167   void SendMessageToEmbedder(IPC::Message* msg);
    168 
    169   // Returns whether the guest is attached to an embedder.
    170   bool attached() const { return embedder_web_contents_ != NULL; }
    171 
    172   // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
    173   // and initializes the guest with the provided |params|. Attaching a guest
    174   // to an embedder implies that this guest's lifetime is no longer managed
    175   // by its opener, and it can begin loading resources. |extra_params| are
    176   // parameters passed into BrowserPlugin from JavaScript to be forwarded to
    177   // the content embedder.
    178   void Attach(WebContentsImpl* embedder_web_contents,
    179               const BrowserPluginHostMsg_Attach_Params& params,
    180               const base::DictionaryValue& extra_params);
    181 
    182   // Returns whether BrowserPluginGuest is interested in receiving the given
    183   // |message|.
    184   static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
    185   gfx::Rect ToGuestRect(const gfx::Rect& rect);
    186 
    187   void DragSourceEndedAt(int client_x, int client_y, int screen_x,
    188       int screen_y, blink::WebDragOperation operation);
    189 
    190   // Called when the drag started by this guest ends at an OS-level.
    191   void EndSystemDrag();
    192 
    193   void set_delegate(BrowserPluginGuestDelegate* delegate) {
    194     DCHECK(!delegate_);
    195     delegate_ = delegate;
    196   }
    197 
    198   void RespondToPermissionRequest(int request_id,
    199                                   bool should_allow,
    200                                   const std::string& user_input);
    201 
    202   void PointerLockPermissionResponse(bool allow);
    203 
    204  private:
    205   class EmbedderWebContentsObserver;
    206 
    207   // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
    208   // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
    209   BrowserPluginGuest(int instance_id,
    210                      bool has_render_view,
    211                      WebContentsImpl* web_contents);
    212 
    213   void WillDestroy();
    214 
    215   void Initialize(const BrowserPluginHostMsg_Attach_Params& params,
    216                   WebContentsImpl* embedder_web_contents,
    217                   const base::DictionaryValue& extra_params);
    218 
    219   bool InAutoSizeBounds(const gfx::Size& size) const;
    220 
    221   // Message handlers for messages from embedder.
    222 
    223   void OnCompositorFrameSwappedACK(
    224       int instance_id,
    225       const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
    226   void OnCopyFromCompositingSurfaceAck(int instance_id,
    227                                        int request_id,
    228                                        const SkBitmap& bitmap);
    229   // Handles drag events from the embedder.
    230   // When dragging, the drag events go to the embedder first, and if the drag
    231   // happens on the browser plugin, then the plugin sends a corresponding
    232   // drag-message to the guest. This routes the drag-message to the guest
    233   // renderer.
    234   void OnDragStatusUpdate(int instance_id,
    235                           blink::WebDragStatus drag_status,
    236                           const DropData& drop_data,
    237                           blink::WebDragOperationsMask drag_mask,
    238                           const gfx::Point& location);
    239   // Instructs the guest to execute an edit command decoded in the embedder.
    240   void OnExecuteEditCommand(int instance_id,
    241                             const std::string& command);
    242 
    243   // Returns compositor resources reclaimed in the embedder to the guest.
    244   void OnReclaimCompositorResources(
    245       int instance_id,
    246       const FrameHostMsg_ReclaimCompositorResources_Params& params);
    247 
    248   void OnHandleInputEvent(int instance_id,
    249                                   const gfx::Rect& guest_window_rect,
    250                                   const blink::WebInputEvent* event);
    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 OnSetAutoSize(
    265       int instance_id,
    266       const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
    267       const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
    268   void OnSetEditCommandsForNextKeyEvent(
    269       int instance_id,
    270       const std::vector<EditCommand>& edit_commands);
    271   void OnSetContentsOpaque(int instance_id, bool opaque);
    272   // The guest WebContents is visible if both its embedder is visible and
    273   // the browser plugin element is visible. If either one is not then the
    274   // WebContents is marked as hidden. A hidden WebContents will consume
    275   // fewer GPU and CPU resources.
    276   //
    277   // When every WebContents in a RenderProcessHost is hidden, it will lower
    278   // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
    279   //
    280   // It will also send a message to the guest renderer process to cleanup
    281   // resources such as dropping back buffers and adjusting memory limits (if in
    282   // compositing mode, see CCLayerTreeHost::setVisible).
    283   //
    284   // Additionally, it will slow down Javascript execution and garbage
    285   // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
    286   // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
    287   void OnSetVisibility(int instance_id, bool visible);
    288   void OnUnlockMouse();
    289   void OnUnlockMouseAck(int instance_id);
    290   void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
    291 
    292   void OnTextInputStateChanged(
    293       const ViewHostMsg_TextInputState_Params& params);
    294 
    295   void OnImeSetComposition(
    296       int instance_id,
    297       const std::string& text,
    298       const std::vector<blink::WebCompositionUnderline>& underlines,
    299       int selection_start,
    300       int selection_end);
    301   void OnImeConfirmComposition(
    302       int instance_id,
    303       const std::string& text,
    304       bool keep_selection);
    305   void OnExtendSelectionAndDelete(int instance_id, int before, int after);
    306   void OnImeCancelComposition();
    307 #if defined(OS_MACOSX) || defined(USE_AURA)
    308   void OnImeCompositionRangeChanged(
    309       const gfx::Range& range,
    310       const std::vector<gfx::Rect>& character_bounds);
    311 #endif
    312 
    313   // Message handlers for messages from guest.
    314 
    315   void OnDragStopped();
    316   void OnHandleInputEventAck(
    317       blink::WebInputEvent::Type event_type,
    318       InputEventAckState ack_result);
    319   void OnHasTouchEventHandlers(bool accept);
    320   void OnSetCursor(const WebCursor& cursor);
    321   // On MacOSX popups are painted by the browser process. We handle them here
    322   // so that they are positioned correctly.
    323 #if defined(OS_MACOSX)
    324   void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
    325 #endif
    326   void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
    327   void OnTakeFocus(bool reverse);
    328   void OnUpdateFrameName(int frame_id,
    329                          bool is_top_level,
    330                          const std::string& name);
    331   void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
    332 
    333   // Forwards all messages from the |pending_messages_| queue to the embedder.
    334   void SendQueuedMessages();
    335 
    336   scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
    337   WebContentsImpl* embedder_web_contents_;
    338 
    339   // An identifier that uniquely identifies a browser plugin guest within an
    340   // embedder.
    341   int instance_id_;
    342   float guest_device_scale_factor_;
    343   gfx::Rect guest_window_rect_;
    344   gfx::Rect guest_screen_rect_;
    345   bool focused_;
    346   bool mouse_locked_;
    347   bool pending_lock_request_;
    348   bool guest_visible_;
    349   bool guest_opaque_;
    350   bool embedder_visible_;
    351   std::string name_;
    352   bool auto_size_enabled_;
    353   gfx::Size max_auto_size_;
    354   gfx::Size min_auto_size_;
    355   gfx::Size full_size_;
    356 
    357   // Each copy-request is identified by a unique number. The unique number is
    358   // used to keep track of the right callback.
    359   int copy_request_id_;
    360   typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
    361   typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
    362   CopyRequestMap copy_request_callbacks_;
    363 
    364   // Indicates that this BrowserPluginGuest has associated renderer-side state.
    365   // This is used to determine whether or not to create a new RenderView when
    366   // this guest is attached. A BrowserPluginGuest would have renderer-side state
    367   // prior to attachment if it is created via a call to window.open and
    368   // maintains a JavaScript reference to its opener.
    369   bool has_render_view_;
    370 
    371   // Last seen size of guest contents (by OnUpdateRect).
    372   gfx::Size last_seen_view_size_;
    373   // Last seen autosize attribute state (by OnUpdateRect).
    374   bool last_seen_auto_size_enabled_;
    375 
    376   bool is_in_destruction_;
    377 
    378   // Text input type states.
    379   ui::TextInputType last_text_input_type_;
    380   ui::TextInputMode last_input_mode_;
    381   bool last_can_compose_inline_;
    382 
    383   // This is a queue of messages that are destined to be sent to the embedder
    384   // once the guest is attached to a particular embedder.
    385   std::deque<linked_ptr<IPC::Message> > pending_messages_;
    386 
    387   BrowserPluginGuestDelegate* delegate_;
    388 
    389   // Weak pointer used to ask GeolocationPermissionContext about geolocation
    390   // permission.
    391   base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
    392 
    393   DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
    394 };
    395 
    396 }  // namespace content
    397 
    398 #endif  // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
    399