summaryrefslogtreecommitdiffstats
path: root/webkit/plugins/npapi/plugin_instance.h
blob: 84283bbc9914af9fb5eb91323ccca5bce958419d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
// 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/files/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"

namespace base {
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 for all plugins other than Flash. For Flash, we default to
  // opaque since it always tells us if it's transparent during NPP_New.
  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_.get(); }

#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(base::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
  base::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<base::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_