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