| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // TODO: Need to deal with NPAPI's NPSavedData. | 
 | //       I haven't seen plugins use it yet. | 
 |  | 
 | #ifndef WEBKIT_PLUGINS_NPAPI_PLUGIN_INSTANCE_H_ | 
 | #define WEBKIT_PLUGINS_NPAPI_PLUGIN_INSTANCE_H_ | 
 |  | 
 | #include <map> | 
 | #include <stack> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "base/basictypes.h" | 
 | #include "base/file_path.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "googleurl/src/gurl.h" | 
 | #include "third_party/npapi/bindings/npapi.h" | 
 | #include "third_party/npapi/bindings/nphostapi.h" | 
 | #include "ui/gfx/native_widget_types.h" | 
 | #include "ui/gfx/point.h" | 
 | #include "ui/gfx/rect.h" | 
 |  | 
 | class MessageLoop; | 
 |  | 
 | namespace webkit { | 
 | namespace npapi { | 
 |  | 
 | class PluginLib; | 
 | class PluginHost; | 
 | class PluginStream; | 
 | class PluginStreamUrl; | 
 | class WebPlugin; | 
 | class WebPluginResourceClient; | 
 |  | 
 | #if defined(OS_MACOSX) | 
 | class ScopedCurrentPluginEvent; | 
 | #endif | 
 |  | 
 | // A PluginInstance is an active, running instance of a Plugin. | 
 | // A single plugin may have many PluginInstances. | 
 | class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { | 
 |  public: | 
 |   // Create a new instance of a plugin.  The PluginInstance | 
 |   // will hold a reference to the plugin. | 
 |   PluginInstance(PluginLib* plugin, const std::string &mime_type); | 
 |  | 
 |   // Activates the instance by calling NPP_New. | 
 |   // This should be called after our instance is all | 
 |   // setup from the host side and we are ready to receive | 
 |   // requests from the plugin.  We must not call any | 
 |   // functions on the plugin instance until start has | 
 |   // been called. | 
 |   // | 
 |   // url: The instance URL. | 
 |   // param_names: the list of names of attributes passed via the | 
 |   //       element. | 
 |   // param_values: the list of values corresponding to param_names | 
 |   // param_count: number of attributes | 
 |   // load_manually: if true indicates that the plugin data would be passed | 
 |   //                from webkit. if false indicates that the plugin should | 
 |   //                download the data. | 
 |   //                This also controls whether the plugin is instantiated as | 
 |   //                a full page plugin (NP_FULL) or embedded (NP_EMBED) | 
 |   // | 
 |   bool Start(const GURL& url, | 
 |              char** const param_names, | 
 |              char** const param_values, | 
 |              int param_count, | 
 |              bool load_manually); | 
 |  | 
 |   // NPAPI's instance identifier for this instance | 
 |   NPP npp() { return npp_; } | 
 |  | 
 |   // Get/Set for the instance's window handle. | 
 |   gfx::PluginWindowHandle window_handle() const { return window_handle_; } | 
 |   void set_window_handle(gfx::PluginWindowHandle value) { | 
 |     window_handle_ = value; | 
 |   } | 
 |  | 
 |   // Get/Set whether this instance is in Windowless mode. | 
 |   // Default is false. | 
 |   bool windowless() { return windowless_; } | 
 |   void set_windowless(bool value) { windowless_ = value; } | 
 |  | 
 |   // Get/Set whether this instance is transparent. | 
 |   // This only applies to windowless plugins.  Transparent | 
 |   // plugins require that webkit paint the background. | 
 |   // Default is true. | 
 |   bool transparent() { return transparent_; } | 
 |   void set_transparent(bool value) { transparent_ = value; } | 
 |  | 
 |   // Get/Set the WebPlugin associated with this instance | 
 |   WebPlugin* webplugin() { return webplugin_; } | 
 |   void set_web_plugin(WebPlugin* webplugin) { | 
 |     webplugin_ = webplugin; | 
 |   } | 
 |  | 
 |   // Get the mimeType for this plugin stream | 
 |   const std::string &mime_type() { return mime_type_; } | 
 |  | 
 |   PluginLib* plugin_lib() { return plugin_; } | 
 |  | 
 | #if defined(OS_MACOSX) | 
 |   // Get/Set the Mac NPAPI drawing and event models | 
 |   NPDrawingModel drawing_model() { return drawing_model_; } | 
 |   void set_drawing_model(NPDrawingModel value) { drawing_model_ = value; } | 
 |   NPEventModel event_model() { return event_model_; } | 
 |   void set_event_model(NPEventModel value) { event_model_ = value; } | 
 |   // Updates the instance's tracking of the location of the plugin location | 
 |   // relative to the upper left of the screen. | 
 |   void set_plugin_origin(const gfx::Point& origin) { plugin_origin_ = origin; } | 
 |   // Updates the instance's tracking of the frame of the containing window | 
 |   // relative to the upper left of the screen. | 
 |   void set_window_frame(const gfx::Rect& frame) { | 
 |     containing_window_frame_ = frame; | 
 |   } | 
 | #endif | 
 |  | 
 |   // Creates a stream for sending an URL.  If notify_id is non-zero, it will | 
 |   // send a notification to the plugin when the stream is complete; otherwise it | 
 |   // will not.  Set object_url to true if the load is for the object tag's url, | 
 |   // or false if it's for a url that the plugin fetched through | 
 |   // NPN_GetUrl[Notify]. | 
 |   PluginStreamUrl* CreateStream(unsigned long resource_id, | 
 |                                 const GURL& url, | 
 |                                 const std::string& mime_type, | 
 |                                 int notify_id); | 
 |  | 
 |   // For each instance, we track all streams.  When the | 
 |   // instance closes, all remaining streams are also | 
 |   // closed.  All streams associated with this instance | 
 |   // should call AddStream so that they can be cleaned | 
 |   // up when the instance shuts down. | 
 |   void AddStream(PluginStream* stream); | 
 |  | 
 |   // This is called when a stream is closed. We remove the stream from the | 
 |   // list, which releases the reference maintained to the stream. | 
 |   void RemoveStream(PluginStream* stream); | 
 |  | 
 |   // Closes all open streams on this instance. | 
 |   void CloseStreams(); | 
 |  | 
 |   // Returns the WebPluginResourceClient object for a stream that has become | 
 |   // seekable. | 
 |   WebPluginResourceClient* GetRangeRequest(int id); | 
 |  | 
 |   // Have the plugin create its script object. | 
 |   NPObject* GetPluginScriptableObject(); | 
 |  | 
 |   // Returns the form value of this instance. | 
 |   bool GetFormValue(string16* value); | 
 |  | 
 |   // WebViewDelegate methods that we implement. This is for handling | 
 |   // callbacks during getURLNotify. | 
 |   void DidFinishLoadWithReason(const GURL& url, NPReason reason, int notify_id); | 
 |  | 
 |   // If true, send the Mozilla user agent instead of Chrome's to the plugin. | 
 |   bool use_mozilla_user_agent() { return use_mozilla_user_agent_; } | 
 |   void set_use_mozilla_user_agent() { use_mozilla_user_agent_ = true; } | 
 |  | 
 |   // If the plugin instance is backed by a texture, return its ID in the | 
 |   // compositor's namespace. Otherwise return 0. Returns 0 by default. | 
 |   unsigned GetBackingTextureId(); | 
 |  | 
 |   // Helper that implements NPN_PluginThreadAsyncCall semantics | 
 |   void PluginThreadAsyncCall(void (*func)(void *), | 
 |                              void* userData); | 
 |  | 
 |   uint32 ScheduleTimer(uint32 interval, | 
 |                        NPBool repeat, | 
 |                        void (*func)(NPP id, uint32 timer_id)); | 
 |  | 
 |   void UnscheduleTimer(uint32 timer_id); | 
 |  | 
 |   bool ConvertPoint(double source_x, double source_y, | 
 |                     NPCoordinateSpace source_space, | 
 |                     double* dest_x, double* dest_y, | 
 |                     NPCoordinateSpace dest_space); | 
 |  | 
 |   NPError PopUpContextMenu(NPMenu* menu); | 
 |  | 
 |   // | 
 |   // NPAPI methods for calling the Plugin Instance | 
 |   // | 
 |   NPError NPP_New(unsigned short, short, char *[], char *[]); | 
 |   NPError NPP_SetWindow(NPWindow*); | 
 |   NPError NPP_NewStream(NPMIMEType, NPStream*, NPBool, unsigned short*); | 
 |   NPError NPP_DestroyStream(NPStream*, NPReason); | 
 |   int NPP_WriteReady(NPStream*); | 
 |   int NPP_Write(NPStream*, int, int, void*); | 
 |   void NPP_StreamAsFile(NPStream*, const char*); | 
 |   void NPP_URLNotify(const char*, NPReason, void*); | 
 |   NPError NPP_GetValue(NPPVariable, void*); | 
 |   NPError NPP_SetValue(NPNVariable, void*); | 
 |   short NPP_HandleEvent(void*); | 
 |   void NPP_Destroy(); | 
 |   bool NPP_Print(NPPrint* platform_print); | 
 |   void NPP_URLRedirectNotify(const char* url, int32_t status, | 
 |                              void* notify_data); | 
 |  | 
 |   void SendJavaScriptStream(const GURL& url, | 
 |                             const std::string& result, | 
 |                             bool success, | 
 |                             int notify_id); | 
 |  | 
 |   void DidReceiveManualResponse(const GURL& url, | 
 |                                 const std::string& mime_type, | 
 |                                 const std::string& headers, | 
 |                                 uint32 expected_length, | 
 |                                 uint32 last_modified); | 
 |   void DidReceiveManualData(const char* buffer, int length); | 
 |   void DidFinishManualLoading(); | 
 |   void DidManualLoadFail(); | 
 |  | 
 |   void PushPopupsEnabledState(bool enabled); | 
 |   void PopPopupsEnabledState(); | 
 |  | 
 |   bool popups_allowed() const { | 
 |     return popups_enabled_stack_.empty() ? false : popups_enabled_stack_.top(); | 
 |   } | 
 |  | 
 |   // Initiates byte range reads for plugins. | 
 |   void RequestRead(NPStream* stream, NPByteRange* range_list); | 
 |  | 
 |   // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated | 
 |   // by plugins. | 
 |   void RequestURL(const char* url, | 
 |                   const char* method, | 
 |                   const char* target, | 
 |                   const char* buf, | 
 |                   unsigned int len, | 
 |                   bool notify, | 
 |                   void* notify_data); | 
 |  | 
 |   // Handles NPN_URLRedirectResponse calls issued by plugins in response to | 
 |   // HTTP URL redirect notifications. | 
 |   void URLRedirectResponse(bool allow, void* notify_data); | 
 |  | 
 |   bool handles_url_redirects() const { return handles_url_redirects_; } | 
 |  | 
 |  private: | 
 |   friend class base::RefCountedThreadSafe<PluginInstance>; | 
 |  | 
 | #if defined(OS_MACOSX) | 
 |   friend class ScopedCurrentPluginEvent; | 
 |   // Sets the event that the plugin is currently handling. The object is not | 
 |   // owned or copied, so the caller must call this again with NULL before the | 
 |   // event pointer becomes invalid. Clients use ScopedCurrentPluginEvent rather | 
 |   // than calling this directly. | 
 |   void set_currently_handled_event(NPCocoaEvent* event) { | 
 |     currently_handled_event_ = event; | 
 |   } | 
 | #endif | 
 |  | 
 |   ~PluginInstance(); | 
 |   void OnPluginThreadAsyncCall(void (*func)(void *), void* userData); | 
 |   void OnTimerCall(void (*func)(NPP id, uint32 timer_id), | 
 |                    NPP id, uint32 timer_id); | 
 |   bool IsValidStream(const NPStream* stream); | 
 |   void GetNotifyData(int notify_id, bool* notify, void** notify_data); | 
 |  | 
 |   // This is a hack to get the real player plugin to work with chrome | 
 |   // The real player plugin dll(nppl3260) when loaded by firefox is loaded via | 
 |   // the NS COM API which is analogous to win32 COM. So the NPAPI functions in | 
 |   // the plugin are invoked via an interface by firefox. The plugin instance | 
 |   // handle which is passed to every NPAPI method is owned by the real player | 
 |   // plugin, i.e. it expects the ndata member to point to a structure which | 
 |   // it knows about. Eventually it dereferences this structure and compares | 
 |   // a member variable at offset 0x24(Version 6.0.11.2888) /2D (Version | 
 |   // 6.0.11.3088) with 0 and on failing this check, takes  a different code | 
 |   // path which causes a crash. Safari and Opera work with version 6.0.11.2888 | 
 |   // by chance as their ndata structure contains a 0 at the location which real | 
 |   // player checks:(. They crash with version 6.0.11.3088 as well. The | 
 |   // following member just adds a 96 byte padding to our PluginInstance class | 
 |   // which is passed in the ndata member. This magic number works correctly on | 
 |   // Vista with UAC on or off :(. | 
 |   // NOTE: Please dont change the ordering of the member variables | 
 |   // New members should be added after this padding array. | 
 |   // TODO(iyengar) : Disassemble the Realplayer ndata structure and look into | 
 |   // the possiblity of conforming to it (http://b/issue?id=936667). We | 
 |   // could also log a bug with Real, which would save the effort. | 
 |   uint8                                    zero_padding_[96]; | 
 |   scoped_refptr<PluginLib>                 plugin_; | 
 |   NPP                                      npp_; | 
 |   scoped_refptr<PluginHost>                host_; | 
 |   NPPluginFuncs*                           npp_functions_; | 
 |   std::vector<scoped_refptr<PluginStream> > open_streams_; | 
 |   gfx::PluginWindowHandle                  window_handle_; | 
 |   bool                                     windowless_; | 
 |   bool                                     transparent_; | 
 |   WebPlugin*                               webplugin_; | 
 |   std::string                              mime_type_; | 
 |   GURL                                     get_url_; | 
 |   intptr_t                                 get_notify_data_; | 
 |   bool                                     use_mozilla_user_agent_; | 
 | #if defined(OS_MACOSX) | 
 |   NPDrawingModel                           drawing_model_; | 
 |   NPEventModel                             event_model_; | 
 |   gfx::Point                               plugin_origin_; | 
 |   gfx::Rect                                containing_window_frame_; | 
 |   NPCocoaEvent*                            currently_handled_event_;  // weak | 
 | #endif | 
 |   MessageLoop*                             message_loop_; | 
 |   scoped_refptr<PluginStreamUrl>           plugin_data_stream_; | 
 |  | 
 |   // This flag if true indicates that the plugin data would be passed from | 
 |   // webkit. if false indicates that the plugin should download the data. | 
 |   bool                                     load_manually_; | 
 |  | 
 |   // Stack indicating if popups are to be enabled for the outgoing | 
 |   // NPN_GetURL/NPN_GetURLNotify calls. | 
 |   std::stack<bool>                         popups_enabled_stack_; | 
 |  | 
 |   // True if in CloseStreams(). | 
 |   bool in_close_streams_; | 
 |  | 
 |   // List of files created for the current plugin instance. File names are | 
 |   // added to the list every time the NPP_StreamAsFile function is called. | 
 |   std::vector<FilePath> files_created_; | 
 |  | 
 |   // Next unusued timer id. | 
 |   uint32 next_timer_id_; | 
 |  | 
 |   // Map of timer id to settings for timer. | 
 |   struct TimerInfo { | 
 |     uint32 interval; | 
 |     bool repeat; | 
 |   }; | 
 |   typedef std::map<uint32, TimerInfo> TimerMap; | 
 |   TimerMap timers_; | 
 |  | 
 |   // Tracks pending GET/POST requests so that the plugin-given data doesn't | 
 |   // cross process boundaries to an untrusted process. | 
 |   typedef std::map<int, void*> PendingRequestMap; | 
 |   PendingRequestMap pending_requests_; | 
 |   int next_notify_id_; | 
 |  | 
 |   // Used to track pending range requests so that when WebPlugin replies to us | 
 |   // we can match the reply to the stream. | 
 |   typedef std::map<int, scoped_refptr<PluginStream> > PendingRangeRequestMap; | 
 |   PendingRangeRequestMap pending_range_requests_; | 
 |   int next_range_request_id_; | 
 |   // The plugin handles the NPAPI URL redirect notification API. | 
 |   // See here https://wiki.mozilla.org/NPAPI:HTTPRedirectHandling | 
 |   bool handles_url_redirects_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(PluginInstance); | 
 | }; | 
 |  | 
 | #if defined(OS_MACOSX) | 
 | // Helper to simplify correct usage of set_currently_handled_event. | 
 | // Instantiating will set |instance|'s currently handled to |event| for the | 
 | // lifetime of the object, then NULL when it goes out of scope. | 
 | class ScopedCurrentPluginEvent { | 
 |  public: | 
 |   ScopedCurrentPluginEvent(PluginInstance* instance, NPCocoaEvent* event); | 
 |   ~ScopedCurrentPluginEvent(); | 
 |  | 
 |  private: | 
 |   scoped_refptr<PluginInstance> instance_; | 
 |   DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent); | 
 | }; | 
 | #endif | 
 |  | 
 | }  // namespace npapi | 
 | }  // namespace webkit | 
 |  | 
 | #endif  // WEBKIT_PLUGINS_NPAPI_PLUGIN_INSTANCE_H_ |