Home | History | Annotate | Download | only in npapi
      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 // TODO: Need to deal with NPAPI's NPSavedData.
      6 //       I haven't seen plugins use it yet.
      7 
      8 #ifndef CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
      9 #define CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
     10 
     11 #include <map>
     12 #include <stack>
     13 #include <string>
     14 #include <vector>
     15 
     16 #include "base/basictypes.h"
     17 #include "base/files/file_path.h"
     18 #include "base/memory/ref_counted.h"
     19 #include "third_party/npapi/bindings/npapi.h"
     20 #include "third_party/npapi/bindings/nphostapi.h"
     21 #include "ui/gfx/native_widget_types.h"
     22 #include "ui/gfx/point.h"
     23 #include "ui/gfx/rect.h"
     24 #include "url/gurl.h"
     25 
     26 namespace base {
     27 class MessageLoop;
     28 }
     29 
     30 namespace content {
     31 
     32 class PluginLib;
     33 class PluginHost;
     34 class PluginStream;
     35 class PluginStreamUrl;
     36 class WebPlugin;
     37 class WebPluginResourceClient;
     38 
     39 #if defined(OS_MACOSX)
     40 class ScopedCurrentPluginEvent;
     41 #endif
     42 
     43 // A PluginInstance is an active, running instance of a Plugin.
     44 // A single plugin may have many PluginInstances.
     45 class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
     46  public:
     47   // Create a new instance of a plugin.  The PluginInstance
     48   // will hold a reference to the plugin.
     49   PluginInstance(PluginLib* plugin, const std::string &mime_type);
     50 
     51   // Activates the instance by calling NPP_New.
     52   // This should be called after our instance is all
     53   // setup from the host side and we are ready to receive
     54   // requests from the plugin.  We must not call any
     55   // functions on the plugin instance until start has
     56   // been called.
     57   //
     58   // url: The instance URL.
     59   // param_names: the list of names of attributes passed via the
     60   //       element.
     61   // param_values: the list of values corresponding to param_names
     62   // param_count: number of attributes
     63   // load_manually: if true indicates that the plugin data would be passed
     64   //                from webkit. if false indicates that the plugin should
     65   //                download the data.
     66   //                This also controls whether the plugin is instantiated as
     67   //                a full page plugin (NP_FULL) or embedded (NP_EMBED)
     68   //
     69   bool Start(const GURL& url,
     70              char** const param_names,
     71              char** const param_values,
     72              int param_count,
     73              bool load_manually);
     74 
     75   // NPAPI's instance identifier for this instance
     76   NPP npp() { return npp_; }
     77 
     78   // Get/Set for the instance's window handle.
     79   gfx::PluginWindowHandle window_handle() const { return window_handle_; }
     80   void set_window_handle(gfx::PluginWindowHandle value) {
     81     window_handle_ = value;
     82   }
     83 
     84   // Get/Set whether this instance is in Windowless mode.
     85   // Default is false.
     86   bool windowless() { return windowless_; }
     87   void set_windowless(bool value) { windowless_ = value; }
     88 
     89   // Get/Set whether this instance is transparent. This only applies to
     90   // windowless plugins.  Transparent plugins require that webkit paint the
     91   // background.
     92   // Default is true for all plugins other than Flash. For Flash, we default to
     93   // opaque since it always tells us if it's transparent during NPP_New.
     94   bool transparent() { return transparent_; }
     95   void set_transparent(bool value) { transparent_ = value; }
     96 
     97   // Get/Set the WebPlugin associated with this instance
     98   WebPlugin* webplugin() { return webplugin_; }
     99   void set_web_plugin(WebPlugin* webplugin) {
    100     webplugin_ = webplugin;
    101   }
    102 
    103   // Get the mimeType for this plugin stream
    104   const std::string &mime_type() { return mime_type_; }
    105 
    106   PluginLib* plugin_lib() { return plugin_.get(); }
    107 
    108 #if defined(OS_MACOSX)
    109   // Get/Set the Mac NPAPI drawing and event models
    110   NPDrawingModel drawing_model() { return drawing_model_; }
    111   void set_drawing_model(NPDrawingModel value) { drawing_model_ = value; }
    112   NPEventModel event_model() { return event_model_; }
    113   void set_event_model(NPEventModel value) { event_model_ = value; }
    114   // Updates the instance's tracking of the location of the plugin location
    115   // relative to the upper left of the screen.
    116   void set_plugin_origin(const gfx::Point& origin) { plugin_origin_ = origin; }
    117   // Updates the instance's tracking of the frame of the containing window
    118   // relative to the upper left of the screen.
    119   void set_window_frame(const gfx::Rect& frame) {
    120     containing_window_frame_ = frame;
    121   }
    122 #endif
    123 
    124   // Creates a stream for sending an URL.  If notify_id is non-zero, it will
    125   // send a notification to the plugin when the stream is complete; otherwise it
    126   // will not.  Set object_url to true if the load is for the object tag's url,
    127   // or false if it's for a url that the plugin fetched through
    128   // NPN_GetUrl[Notify].
    129   PluginStreamUrl* CreateStream(unsigned long resource_id,
    130                                 const GURL& url,
    131                                 const std::string& mime_type,
    132                                 int notify_id);
    133 
    134   // For each instance, we track all streams.  When the
    135   // instance closes, all remaining streams are also
    136   // closed.  All streams associated with this instance
    137   // should call AddStream so that they can be cleaned
    138   // up when the instance shuts down.
    139   void AddStream(PluginStream* stream);
    140 
    141   // This is called when a stream is closed. We remove the stream from the
    142   // list, which releases the reference maintained to the stream.
    143   void RemoveStream(PluginStream* stream);
    144 
    145   // Closes all open streams on this instance.
    146   void CloseStreams();
    147 
    148   // Returns the WebPluginResourceClient object for a stream that has become
    149   // seekable.
    150   WebPluginResourceClient* GetRangeRequest(int id);
    151 
    152   // Have the plugin create its script object.
    153   NPObject* GetPluginScriptableObject();
    154 
    155   // Returns the form value of this instance.
    156   bool GetFormValue(base::string16* value);
    157 
    158   // WebViewDelegate methods that we implement. This is for handling
    159   // callbacks during getURLNotify.
    160   void DidFinishLoadWithReason(const GURL& url, NPReason reason, int notify_id);
    161 
    162   // If true, send the Mozilla user agent instead of Chrome's to the plugin.
    163   bool use_mozilla_user_agent() { return use_mozilla_user_agent_; }
    164   void set_use_mozilla_user_agent() { use_mozilla_user_agent_ = true; }
    165 
    166   // If the plugin instance is backed by a texture, return its ID in the
    167   // compositor's namespace. Otherwise return 0. Returns 0 by default.
    168   unsigned GetBackingTextureId();
    169 
    170   // Helper that implements NPN_PluginThreadAsyncCall semantics
    171   void PluginThreadAsyncCall(void (*func)(void *),
    172                              void* userData);
    173 
    174   uint32 ScheduleTimer(uint32 interval,
    175                        NPBool repeat,
    176                        void (*func)(NPP id, uint32 timer_id));
    177 
    178   void UnscheduleTimer(uint32 timer_id);
    179 
    180   bool ConvertPoint(double source_x, double source_y,
    181                     NPCoordinateSpace source_space,
    182                     double* dest_x, double* dest_y,
    183                     NPCoordinateSpace dest_space);
    184 
    185   NPError PopUpContextMenu(NPMenu* menu);
    186 
    187   //
    188   // NPAPI methods for calling the Plugin Instance
    189   //
    190   NPError NPP_New(unsigned short, short, char *[], char *[]);
    191   NPError NPP_SetWindow(NPWindow*);
    192   NPError NPP_NewStream(NPMIMEType, NPStream*, NPBool, unsigned short*);
    193   NPError NPP_DestroyStream(NPStream*, NPReason);
    194   int NPP_WriteReady(NPStream*);
    195   int NPP_Write(NPStream*, int, int, void*);
    196   void NPP_StreamAsFile(NPStream*, const char*);
    197   void NPP_URLNotify(const char*, NPReason, void*);
    198   NPError NPP_GetValue(NPPVariable, void*);
    199   NPError NPP_SetValue(NPNVariable, void*);
    200   short NPP_HandleEvent(void*);
    201   void NPP_Destroy();
    202   bool NPP_Print(NPPrint* platform_print);
    203   void NPP_URLRedirectNotify(const char* url, int32_t status,
    204                              void* notify_data);
    205 
    206   void SendJavaScriptStream(const GURL& url,
    207                             const std::string& result,
    208                             bool success,
    209                             int notify_id);
    210 
    211   void DidReceiveManualResponse(const GURL& url,
    212                                 const std::string& mime_type,
    213                                 const std::string& headers,
    214                                 uint32 expected_length,
    215                                 uint32 last_modified);
    216   void DidReceiveManualData(const char* buffer, int length);
    217   void DidFinishManualLoading();
    218   void DidManualLoadFail();
    219 
    220   void PushPopupsEnabledState(bool enabled);
    221   void PopPopupsEnabledState();
    222 
    223   bool popups_allowed() const {
    224     return popups_enabled_stack_.empty() ? false : popups_enabled_stack_.top();
    225   }
    226 
    227   // Initiates byte range reads for plugins.
    228   void RequestRead(NPStream* stream, NPByteRange* range_list);
    229 
    230   // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated
    231   // by plugins.
    232   void RequestURL(const char* url,
    233                   const char* method,
    234                   const char* target,
    235                   const char* buf,
    236                   unsigned int len,
    237                   bool notify,
    238                   void* notify_data);
    239 
    240   // Handles NPN_URLRedirectResponse calls issued by plugins in response to
    241   // HTTP URL redirect notifications.
    242   void URLRedirectResponse(bool allow, void* notify_data);
    243 
    244   bool handles_url_redirects() const { return handles_url_redirects_; }
    245 
    246  private:
    247   friend class base::RefCountedThreadSafe<PluginInstance>;
    248 
    249 #if defined(OS_MACOSX)
    250   friend class ScopedCurrentPluginEvent;
    251   // Sets the event that the plugin is currently handling. The object is not
    252   // owned or copied, so the caller must call this again with NULL before the
    253   // event pointer becomes invalid. Clients use ScopedCurrentPluginEvent rather
    254   // than calling this directly.
    255   void set_currently_handled_event(NPCocoaEvent* event) {
    256     currently_handled_event_ = event;
    257   }
    258 #endif
    259 
    260   ~PluginInstance();
    261   void OnPluginThreadAsyncCall(void (*func)(void *), void* userData);
    262   void OnTimerCall(void (*func)(NPP id, uint32 timer_id),
    263                    NPP id, uint32 timer_id);
    264   bool IsValidStream(const NPStream* stream);
    265   void GetNotifyData(int notify_id, bool* notify, void** notify_data);
    266 
    267   // This is a hack to get the real player plugin to work with chrome
    268   // The real player plugin dll(nppl3260) when loaded by firefox is loaded via
    269   // the NS COM API which is analogous to win32 COM. So the NPAPI functions in
    270   // the plugin are invoked via an interface by firefox. The plugin instance
    271   // handle which is passed to every NPAPI method is owned by the real player
    272   // plugin, i.e. it expects the ndata member to point to a structure which
    273   // it knows about. Eventually it dereferences this structure and compares
    274   // a member variable at offset 0x24(Version 6.0.11.2888) /2D (Version
    275   // 6.0.11.3088) with 0 and on failing this check, takes  a different code
    276   // path which causes a crash. Safari and Opera work with version 6.0.11.2888
    277   // by chance as their ndata structure contains a 0 at the location which real
    278   // player checks:(. They crash with version 6.0.11.3088 as well. The
    279   // following member just adds a 96 byte padding to our PluginInstance class
    280   // which is passed in the ndata member. This magic number works correctly on
    281   // Vista with UAC on or off :(.
    282   // NOTE: Please dont change the ordering of the member variables
    283   // New members should be added after this padding array.
    284   // TODO(iyengar) : Disassemble the Realplayer ndata structure and look into
    285   // the possiblity of conforming to it (http://b/issue?id=936667). We
    286   // could also log a bug with Real, which would save the effort.
    287   uint8                                    zero_padding_[96];
    288   scoped_refptr<PluginLib>                 plugin_;
    289   NPP                                      npp_;
    290   scoped_refptr<PluginHost>                host_;
    291   NPPluginFuncs*                           npp_functions_;
    292   std::vector<scoped_refptr<PluginStream> > open_streams_;
    293   gfx::PluginWindowHandle                  window_handle_;
    294   bool                                     windowless_;
    295   bool                                     transparent_;
    296   WebPlugin*                               webplugin_;
    297   std::string                              mime_type_;
    298   GURL                                     get_url_;
    299   intptr_t                                 get_notify_data_;
    300   bool                                     use_mozilla_user_agent_;
    301 #if defined(OS_MACOSX)
    302   NPDrawingModel                           drawing_model_;
    303   NPEventModel                             event_model_;
    304   gfx::Point                               plugin_origin_;
    305   gfx::Rect                                containing_window_frame_;
    306   NPCocoaEvent*                            currently_handled_event_;  // weak
    307 #endif
    308   base::MessageLoop*                       message_loop_;
    309   scoped_refptr<PluginStreamUrl>           plugin_data_stream_;
    310 
    311   // This flag if true indicates that the plugin data would be passed from
    312   // webkit. if false indicates that the plugin should download the data.
    313   bool                                     load_manually_;
    314 
    315   // Stack indicating if popups are to be enabled for the outgoing
    316   // NPN_GetURL/NPN_GetURLNotify calls.
    317   std::stack<bool>                         popups_enabled_stack_;
    318 
    319   // True if in CloseStreams().
    320   bool in_close_streams_;
    321 
    322   // List of files created for the current plugin instance. File names are
    323   // added to the list every time the NPP_StreamAsFile function is called.
    324   std::vector<base::FilePath> files_created_;
    325 
    326   // Next unusued timer id.
    327   uint32 next_timer_id_;
    328 
    329   // Map of timer id to settings for timer.
    330   struct TimerInfo {
    331     uint32 interval;
    332     bool repeat;
    333   };
    334   typedef std::map<uint32, TimerInfo> TimerMap;
    335   TimerMap timers_;
    336 
    337   // Tracks pending GET/POST requests so that the plugin-given data doesn't
    338   // cross process boundaries to an untrusted process.
    339   typedef std::map<int, void*> PendingRequestMap;
    340   PendingRequestMap pending_requests_;
    341   int next_notify_id_;
    342 
    343   // Used to track pending range requests so that when WebPlugin replies to us
    344   // we can match the reply to the stream.
    345   typedef std::map<int, scoped_refptr<PluginStream> > PendingRangeRequestMap;
    346   PendingRangeRequestMap pending_range_requests_;
    347   int next_range_request_id_;
    348   // The plugin handles the NPAPI URL redirect notification API.
    349   // See here https://wiki.mozilla.org/NPAPI:HTTPRedirectHandling
    350   bool handles_url_redirects_;
    351 
    352   DISALLOW_COPY_AND_ASSIGN(PluginInstance);
    353 };
    354 
    355 #if defined(OS_MACOSX)
    356 // Helper to simplify correct usage of set_currently_handled_event.
    357 // Instantiating will set |instance|'s currently handled to |event| for the
    358 // lifetime of the object, then NULL when it goes out of scope.
    359 class ScopedCurrentPluginEvent {
    360  public:
    361   ScopedCurrentPluginEvent(PluginInstance* instance, NPCocoaEvent* event);
    362   ~ScopedCurrentPluginEvent();
    363 
    364  private:
    365   scoped_refptr<PluginInstance> instance_;
    366   DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent);
    367 };
    368 #endif
    369 
    370 }  // namespace content
    371 
    372 #endif  // CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
    373