summaryrefslogtreecommitdiffstats
path: root/webkit/glue/plugins/pepper_var.h
blob: 8929448ca84d66d59c5f8c8739b9b2efaab7cb6d (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
// 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.

#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_VAR_H_
#define WEBKIT_GLUE_PLUGINS_PEPPER_VAR_H_

#include <string>

#include "webkit/glue/plugins/pepper_resource.h"

struct PP_Var;
struct PPB_Var;
struct PPB_Var_Deprecated;
typedef struct NPObject NPObject;
typedef struct _NPVariant NPVariant;
typedef void* NPIdentifier;

namespace pepper {

// Var -------------------------------------------------------------------------

// Represents a non-POD var. This is derived from a resource even though it
// isn't a resource from the plugin's perspective. This allows us to re-use
// the refcounting and the association with the module from the resource code.
class Var : public Resource {
 public:
  virtual ~Var();

  // Resource overrides.
  virtual Var* AsVar() { return this; }

  // Returns a PP_Var that corresponds to the given NPVariant. The contents of
  // the NPVariant will be copied unless the NPVariant corresponds to an
  // object. This will handle all Variant types including POD, strings, and
  // objects.
  //
  // The returned PP_Var will have a refcount of 1, this passing ownership of
  // the reference to the caller. This is suitable for returning to a plugin.
  static PP_Var NPVariantToPPVar(PluginModule* module,
                                 const NPVariant* variant);

  // Returns a NPIdentifier that corresponds to the given PP_Var. The contents
  // of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a
  // string or integer type.
  static NPIdentifier PPVarToNPIdentifier(PP_Var var);

  // Returns a PP_Var corresponding to the given identifier. In the case of
  // a string identifier, the string will be allocated associated with the
  // given module. A returned string will have a reference count of 1.
  static PP_Var NPIdentifierToPPVar(PluginModule* module, NPIdentifier id);

  // Provides access to the manual refcounting of a PP_Var from the plugin's
  // perspective. This is different than the AddRef/Release on this scoped
  // object. This uses the ResourceTracker, which keeps a separate "plugin
  // refcount" that prevents the plugin from messing up our refcounting or
  // freeing something out from under us.
  //
  // You should not generally need to use these functions. However, if you
  // call a plugin function that returns a var, it will transfer a ref to us
  // (the caller) which in the case of a string or object var will need to
  // be released.
  //
  // Example, assuming we're expecting the plugin to return a string:
  //   PP_Var rv = some_ppp_interface->DoSomething(a, b, c);
  //
  //   // Get the string value. This will take a reference to the object which
  //   // will prevent it from being deleted out from under us when we call
  //   // PluginReleasePPVar().
  //   scoped_refptr<StringVar> string(StringVar::FromPPVar(rv));
  //
  //   // Release the reference the plugin gave us when returning the value.
  //   // This is legal to do for all types of vars.
  //   Var::PluginReleasePPVar(rv);
  //
  //   // Use the string.
  //   if (!string)
  //     return false;  // It didn't return a proper string.
  //   UseTheString(string->value());
  static void PluginAddRefPPVar(PP_Var var);
  static void PluginReleasePPVar(PP_Var var);

  // Returns the PPB_Var_Deprecated interface for the plugin to use.
  static const PPB_Var_Deprecated* GetDeprecatedInterface();

  // Returns the PPB_Var interface for the plugin to use.
  static const PPB_Var* GetInterface();

 protected:
  // This can only be constructed as a StringVar or an ObjectVar.
  explicit Var(PluginModule* module);

 private:
  DISALLOW_COPY_AND_ASSIGN(Var);
};

// StringVar -------------------------------------------------------------------

// Represents a string-based Var.
//
// Returning a given string as a PP_Var:
//   return StringVar::StringToPPVar(module, my_string);
//
// Converting a PP_Var to a string:
//   scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
//   if (!string)
//     return false;  // Not a string or an invalid var.
//   DoSomethingWithTheString(string->value());
class StringVar : public Var {
 public:
  StringVar(PluginModule* module, const char* str, uint32 len);
  virtual ~StringVar();

  const std::string& value() const { return value_; }

  // Resource overrides.
  virtual StringVar* AsStringVar() { return this; }

  // Helper function to create a PP_Var of type string that contains a copy of
  // the given string. The input data must be valid UTF-8 encoded text, if it
  // is not valid UTF-8, a NULL var will be returned.
  //
  // The return value will have a reference count of 1. Internally, this will
  // create a StringVar, associate it with a module, and return the reference
  // to it in the var.
  static PP_Var StringToPPVar(PluginModule* module, const std::string& str);
  static PP_Var StringToPPVar(PluginModule* module,
                              const char* str, uint32 len);

  // Helper function that converts a PP_Var to a string. This will return NULL
  // if the PP_Var is not of string type or the string is invalid.
  static scoped_refptr<StringVar> FromPPVar(PP_Var var);

 private:
  std::string value_;

  DISALLOW_COPY_AND_ASSIGN(StringVar);
};

// ObjectVar -------------------------------------------------------------------

// Represents a JavaScript object Var. By itself, this represents random
// NPObjects that a given plugin (identified by the resource's module) wants to
// reference. If two different modules reference the same NPObject (like the
// "window" object), then there will be different ObjectVar's (and hence PP_Var
// IDs) for each module. This allows us to track all references owned by a
// given module and free them when the plugin exits independently of other
// plugins that may be running at the same time.
//
// See StringVar for examples, except obviously using NPObjects instead of
// strings.
class ObjectVar : public Var {
 public:
  virtual ~ObjectVar();

  // Resource overrides.
  virtual ObjectVar* AsObjectVar() { return this; }

  // Returns the underlying NPObject corresponding to this ObjectVar.
  // Guaranteed non-NULL.
  NPObject* np_object() const { return np_object_; }

  // Helper function to create a PP_Var of type object that contains the given
  // NPObject for use byt he given module. Calling this function multiple times
  // given the same module + NPObject results in the same PP_Var, assuming that
  // there is still a PP_Var with a reference open to it from the previous
  // call.
  //
  // The module is necessary because we can have different modules pointing to
  // the same NPObject, and we want to keep their refs separate.
  //
  // If no ObjectVar currently exists corresponding to the NPObject, one is
  // created associated with the given module.
  static PP_Var NPObjectToPPVar(PluginModule* module, NPObject* object);

  // Helper function that converts a PP_Var to an object. This will return NULL
  // if the PP_Var is not of object type or the object is invalid.
  static scoped_refptr<ObjectVar> FromPPVar(PP_Var var);

 protected:
  // You should always use FromNPObject to create an ObjectVar. This function
  // guarantees that we maintain the 1:1 mapping between NPObject and
  // ObjectVar.
  ObjectVar(PluginModule* module, NPObject* np_object);

 private:
  // Guaranteed non-NULL, this is the underlying object used by WebKit. We
  // hold a reference to this object.
  NPObject* np_object_;

  DISALLOW_COPY_AND_ASSIGN(ObjectVar);
};

// TryCatch --------------------------------------------------------------------

// Instantiate this object on the stack to catch V8 exceptions and pass them
// to an optional out parameter supplied by the plugin.
class TryCatch {
 public:
  // The given exception may be NULL if the consumer isn't interested in
  // catching exceptions. If non-NULL, the given var will be updated if any
  // exception is thrown (so it must outlive the TryCatch object).
  //
  // The module associated with the exception is passed so we know which module
  // to associate any exception string with. It may be NULL if you don't know
  // the module at construction time, in which case you should set it later
  // by calling set_module().
  //
  // If an exception is thrown when the module is NULL, setting *any* exception
  // will result in using the InvalidObjectException.
  TryCatch(PluginModule* module, PP_Var* exception);
  ~TryCatch();

  // Get and set the module. This may be NULL (see the constructor).
  PluginModule* module() { return module_; }
  void set_module(PluginModule* module) { module_ = module; }

  // Returns true is an exception has been thrown. This can be true immediately
  // after construction if the var passed to the constructor is non-void.
  bool has_exception() const { return has_exception_; }

  // Sets the given exception. If no module has been set yet, the message will
  // be ignored (since we have no module to associate the string with) and the
  // SetInvalidObjectException() will be used instead.
  //
  // If an exception has been previously set, this function will do nothing
  // (normally you want only the first exception).
  void SetException(const char* message);

  // Sets the exception to be a generic message contained in a magic string
  // not associated with any module.
  void SetInvalidObjectException();

 private:
  static void Catch(void* self, const char* message);

  PluginModule* module_;

  // True if an exception has been thrown. Since the exception itself may be
  // NULL if the plugin isn't interested in getting the exception, this will
  // always indicate if SetException has been called, regardless of whether
  // the exception itself has been stored.
  bool has_exception_;

  // May be null if the consumer isn't interesting in catching exceptions.
  PP_Var* exception_;
};

}  // namespace pepper

#endif  // WEBKIT_GLUE_PLUGINS_PEPPER_VAR_H_