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.
5 // TODO: Need to deal with NPAPI's NPSavedData.
6 // I haven't seen plugins use it yet.
8 #ifndef CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
9 #define CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
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/geometry/point.h"
22 #include "ui/gfx/geometry/rect.h"
23 #include "ui/gfx/native_widget_types.h"
27 class SingleThreadTaskRunner
;
35 class PluginStreamUrl
;
37 class WebPluginResourceClient
;
39 #if defined(OS_MACOSX)
40 class ScopedCurrentPluginEvent
;
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
> {
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
);
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
58 // url: The instance URL.
59 // param_names: the list of names of attributes passed via the
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
66 // This also controls whether the plugin is instantiated as
67 // a full page plugin (NP_FULL) or embedded (NP_EMBED)
69 bool Start(const GURL
& url
,
70 char** const param_names
,
71 char** const param_values
,
75 // NPAPI's instance identifier for this instance
76 NPP
npp() { return npp_
; }
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
;
84 // Get/Set whether this instance is in Windowless mode.
86 bool windowless() { return windowless_
; }
87 void set_windowless(bool value
) { windowless_
= value
; }
89 // Get/Set whether this instance is transparent. This only applies to
90 // windowless plugins. Transparent plugins require that webkit paint the
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
; }
97 // Get/Set the WebPlugin associated with this instance
98 WebPlugin
* webplugin() { return webplugin_
; }
99 void set_web_plugin(WebPlugin
* webplugin
) {
100 webplugin_
= webplugin
;
103 // Get the mimeType for this plugin stream
104 const std::string
&mime_type() { return mime_type_
; }
106 PluginLib
* plugin_lib() { return plugin_
.get(); }
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
;
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
,
131 const std::string
& mime_type
,
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
);
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
);
145 // Closes all open streams on this instance.
148 // Returns the WebPluginResourceClient object for a stream that has become
150 WebPluginResourceClient
* GetRangeRequest(int id
);
152 // Have the plugin create its script object.
153 NPObject
* GetPluginScriptableObject();
155 // Returns the form value of this instance.
156 bool GetFormValue(base::string16
* value
);
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
);
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; }
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();
170 // Helper that implements NPN_PluginThreadAsyncCall semantics
171 void PluginThreadAsyncCall(void (*func
)(void *),
174 uint32
ScheduleTimer(uint32 interval
,
176 void (*func
)(NPP id
, uint32 timer_id
));
178 void UnscheduleTimer(uint32 timer_id
);
180 bool ConvertPoint(double source_x
, double source_y
,
181 NPCoordinateSpace source_space
,
182 double* dest_x
, double* dest_y
,
183 NPCoordinateSpace dest_space
);
185 NPError
PopUpContextMenu(NPMenu
* menu
);
188 // NPAPI methods for calling the Plugin Instance
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*);
202 bool NPP_Print(NPPrint
* platform_print
);
203 void NPP_URLRedirectNotify(const char* url
, int32_t status
,
206 void SendJavaScriptStream(const GURL
& url
,
207 const std::string
& result
,
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();
220 void PushPopupsEnabledState(bool enabled
);
221 void PopPopupsEnabledState();
223 bool popups_allowed() const {
224 return popups_enabled_stack_
.empty() ? false : popups_enabled_stack_
.top();
227 // Initiates byte range reads for plugins.
228 void RequestRead(NPStream
* stream
, NPByteRange
* range_list
);
230 // Handles GetURL/GetURLNotify/PostURL/PostURLNotify requests initiated
232 void RequestURL(const char* url
,
240 // Handles NPN_URLRedirectResponse calls issued by plugins in response to
241 // HTTP URL redirect notifications.
242 void URLRedirectResponse(bool allow
, void* notify_data
);
244 bool handles_url_redirects() const { return handles_url_redirects_
; }
247 friend class base::RefCountedThreadSafe
<PluginInstance
>;
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
;
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
);
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_
;
290 scoped_refptr
<PluginHost
> host_
;
291 NPPluginFuncs
* npp_functions_
;
292 std::vector
<scoped_refptr
<PluginStream
> > open_streams_
;
293 gfx::PluginWindowHandle window_handle_
;
296 WebPlugin
* webplugin_
;
297 std::string mime_type_
;
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
308 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
309 scoped_refptr
<PluginStreamUrl
> plugin_data_stream_
;
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.
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_
;
319 // True if in CloseStreams().
320 bool in_close_streams_
;
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_
;
326 // Next unusued timer id.
327 uint32 next_timer_id_
;
329 // Map of timer id to settings for timer.
334 typedef std::map
<uint32
, TimerInfo
> TimerMap
;
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_
;
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_
;
352 DISALLOW_COPY_AND_ASSIGN(PluginInstance
);
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
{
361 ScopedCurrentPluginEvent(PluginInstance
* instance
, NPCocoaEvent
* event
);
362 ~ScopedCurrentPluginEvent();
365 scoped_refptr
<PluginInstance
> instance_
;
366 DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent
);
370 } // namespace content
372 #endif // CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_