diff options
Diffstat (limited to 'webkit/glue/plugins/plugin_instance.h')
-rw-r--r-- | webkit/glue/plugins/plugin_instance.h | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h new file mode 100644 index 0000000..36bf601 --- /dev/null +++ b/webkit/glue/plugins/plugin_instance.h @@ -0,0 +1,360 @@ +// Copyright (c) 2010 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_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ + +#include <map> +#include <set> +#include <stack> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "gfx/native_widget_types.h" +#include "gfx/point.h" +#include "gfx/rect.h" +#include "googleurl/src/gurl.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +class MessageLoop; + +namespace webkit_glue { +class WebPlugin; +class WebPluginResourceClient; +} + +namespace NPAPI +{ +class PluginLib; +class PluginHost; +class PluginStream; +class PluginStreamUrl; +class PluginDataStream; +#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 + webkit_glue::WebPlugin* webplugin() { return webplugin_; } + void set_web_plugin(webkit_glue::WebPlugin* webplugin) { + webplugin_ = webplugin; + } + + // Get the mimeType for this plugin stream + const std::string &mime_type() { return mime_type_; } + + NPAPI::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. + webkit_glue::WebPluginResourceClient* GetRangeRequest(int id); + + // Have the plugin create it's script object. + NPObject *GetPluginScriptableObject(); + + // 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; } + + // 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 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); + + 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<NPAPI::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_; + webkit_glue::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_; + + 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) + : instance_(instance) { + instance_->set_currently_handled_event(event); + } + ~ScopedCurrentPluginEvent() { + instance_->set_currently_handled_event(NULL); + } + private: + scoped_refptr<PluginInstance> instance_; + DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent); +}; +#endif + +} // namespace NPAPI + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_INSTANCE_H__ |