Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: webkit/glue/plugins/pepper_plugin_object.cc

Issue 5828003: Move the Pepper implementation from webkit/glue/plugins/pepper_* to... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/pepper_plugin_object.h ('k') | webkit/glue/plugins/pepper_private.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #include "webkit/glue/plugins/pepper_plugin_object.h"
6
7 #include "base/logging.h"
8 #include "base/ref_counted.h"
9 #include "base/scoped_ptr.h"
10 #include "base/string_number_conversions.h"
11 #include "base/string_util.h"
12 #include "third_party/npapi/bindings/npapi.h"
13 #include "third_party/npapi/bindings/npruntime.h"
14 #include "ppapi/c/dev/ppb_var_deprecated.h"
15 #include "ppapi/c/dev/ppp_class_deprecated.h"
16 #include "ppapi/c/pp_resource.h"
17 #include "ppapi/c/pp_var.h"
18 #include "ppapi/c/ppb_class.h"
19 #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
20 #include "webkit/glue/plugins/pepper_class.h"
21 #include "webkit/glue/plugins/pepper_plugin_module.h"
22 #include "webkit/glue/plugins/pepper_resource.h"
23 #include "webkit/glue/plugins/pepper_string.h"
24 #include "webkit/glue/plugins/pepper_var.h"
25
26 using WebKit::WebBindings;
27
28 namespace pepper {
29
30 namespace {
31
32 const char kInvalidValueException[] = "Error: Invalid value";
33 const char kInvalidPluginValue[] = "Error: Plugin returned invalid value.";
34
35 // -----------------------------------------------------------------------------
36 // Utilities
37
38 // Converts the given PP_Var to an NPVariant, returning true on success.
39 // False means that the given variant is invalid. In this case, the result
40 // NPVariant will be set to a void one.
41 //
42 // The contents of the PP_Var will be copied unless the PP_Var corresponds to
43 // an object.
44 bool PPVarToNPVariant(PP_Var var, NPVariant* result) {
45 switch (var.type) {
46 case PP_VARTYPE_UNDEFINED:
47 VOID_TO_NPVARIANT(*result);
48 break;
49 case PP_VARTYPE_NULL:
50 NULL_TO_NPVARIANT(*result);
51 break;
52 case PP_VARTYPE_BOOL:
53 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
54 break;
55 case PP_VARTYPE_INT32:
56 INT32_TO_NPVARIANT(var.value.as_int, *result);
57 break;
58 case PP_VARTYPE_DOUBLE:
59 DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
60 break;
61 case PP_VARTYPE_STRING: {
62 scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
63 if (!string) {
64 VOID_TO_NPVARIANT(*result);
65 return false;
66 }
67 const std::string& value = string->value();
68 STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), *result);
69 break;
70 }
71 case PP_VARTYPE_OBJECT: {
72 scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var));
73 if (!object) {
74 VOID_TO_NPVARIANT(*result);
75 return false;
76 }
77 OBJECT_TO_NPVARIANT(WebBindings::retainObject(object->np_object()),
78 *result);
79 break;
80 }
81 }
82 return true;
83 }
84
85 // PPVarArrayFromNPVariantArray ------------------------------------------------
86
87 // Converts an array of NPVariants to an array of PP_Var, and scopes the
88 // ownership of the PP_Var. This is used when converting argument lists from
89 // WebKit to the plugin.
90 class PPVarArrayFromNPVariantArray {
91 public:
92 PPVarArrayFromNPVariantArray(PluginModule* module,
93 size_t size,
94 const NPVariant* variants)
95 : size_(size) {
96 if (size_ > 0) {
97 array_.reset(new PP_Var[size_]);
98 for (size_t i = 0; i < size_; i++)
99 array_[i] = Var::NPVariantToPPVar(module, &variants[i]);
100 }
101 }
102
103 ~PPVarArrayFromNPVariantArray() {
104 for (size_t i = 0; i < size_; i++)
105 Var::PluginReleasePPVar(array_[i]);
106 }
107
108 PP_Var* array() { return array_.get(); }
109
110 private:
111 size_t size_;
112 scoped_array<PP_Var> array_;
113
114 DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray);
115 };
116
117 // PPVarFromNPObject -----------------------------------------------------------
118
119 // Converts an NPObject tp PP_Var, and scopes the ownership of the PP_Var. This
120 // is used when converting 'this' pointer from WebKit to the plugin.
121 class PPVarFromNPObject {
122 public:
123 PPVarFromNPObject(PluginModule* module, NPObject* object)
124 : var_(ObjectVar::NPObjectToPPVar(module, object)) {
125 }
126 ~PPVarFromNPObject() {
127 Var::PluginReleasePPVar(var_);
128 }
129 PP_Var var() const { return var_; }
130 private:
131 const PP_Var var_;
132
133 DISALLOW_COPY_AND_ASSIGN(PPVarFromNPObject);
134 };
135
136 // PPResultAndExceptionToNPResult ----------------------------------------------
137
138 // Convenience object for converting a PPAPI call that can throw an exception
139 // and optionally return a value, back to the NPAPI layer which expects a
140 // NPVariant as a result.
141 //
142 // Normal usage is that you will pass the result of exception() to the
143 // PPAPI function as the exception output parameter. Then you will either
144 // call SetResult with the result of the PPAPI call, or
145 // CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var.
146 //
147 // Both SetResult and CheckExceptionForNoResult will throw an exception to
148 // the JavaScript library if the plugin reported an exception. SetResult
149 // will additionally convert the result to an NPVariant and write it to the
150 // output parameter given in the constructor.
151 class PPResultAndExceptionToNPResult {
152 public:
153 // The object_var parameter is the object to associate any exception with.
154 // It may not be NULL.
155 //
156 // The np_result parameter is the NPAPI result output parameter. This may be
157 // NULL if there is no NPVariant result (like for HasProperty). If this is
158 // specified, you must call SetResult() to set it. If it is not, you must
159 // call CheckExceptionForNoResult to do the exception checking with no result
160 // conversion.
161 PPResultAndExceptionToNPResult(NPObject* object_var,
162 NPVariant* np_result)
163 : object_var_(object_var),
164 np_result_(np_result),
165 exception_(PP_MakeUndefined()),
166 success_(false),
167 checked_exception_(false) {
168 }
169
170 ~PPResultAndExceptionToNPResult() {
171 // The user should have called SetResult or CheckExceptionForNoResult
172 // before letting this class go out of scope, or the exception will have
173 // been lost.
174 DCHECK(checked_exception_);
175
176 ObjectVar::PluginReleasePPVar(exception_);
177 }
178
179 // Returns true if an exception has been set.
180 bool has_exception() const { return exception_.type != PP_VARTYPE_UNDEFINED; }
181
182 // Returns a pointer to the exception. You would pass this to the PPAPI
183 // function as the exception parameter. If it is set to non-void, this object
184 // will take ownership of destroying it.
185 PP_Var* exception() { return &exception_; }
186
187 // Returns true if everything succeeded with no exception. This is valid only
188 // after calling SetResult/CheckExceptionForNoResult.
189 bool success() const {
190 DCHECK(checked_exception_);
191 return success_;
192 }
193
194 // Call this with the return value of the PPAPI function. It will convert
195 // the result to the NPVariant output parameter and pass any exception on to
196 // the JS engine. It will update the success flag and return it.
197 bool SetResult(PP_Var result) {
198 DCHECK(!checked_exception_); // Don't call more than once.
199 DCHECK(np_result_); // Should be expecting a result.
200
201 checked_exception_ = true;
202
203 if (has_exception()) {
204 ThrowException();
205 success_ = false;
206 } else if (!PPVarToNPVariant(result, np_result_)) {
207 WebBindings::setException(object_var_, kInvalidPluginValue);
208 success_ = false;
209 } else {
210 success_ = true;
211 }
212
213 // No matter what happened, we need to release the reference to the
214 // value passed in. On success, a reference to this value will be in
215 // the np_result_.
216 Var::PluginReleasePPVar(result);
217 return success_;
218 }
219
220 // Call this after calling a PPAPI function that could have set the
221 // exception. It will pass the exception on to the JS engine and update
222 // the success flag.
223 //
224 // The success flag will be returned.
225 bool CheckExceptionForNoResult() {
226 DCHECK(!checked_exception_); // Don't call more than once.
227 DCHECK(!np_result_); // Can't have a result when doing this.
228
229 checked_exception_ = true;
230
231 if (has_exception()) {
232 ThrowException();
233 success_ = false;
234 return false;
235 }
236 success_ = true;
237 return true;
238 }
239
240 // Call this to ignore any exception. This prevents the DCHECK from failing
241 // in the destructor.
242 void IgnoreException() {
243 checked_exception_ = true;
244 }
245
246 private:
247 // Throws the current exception to JS. The exception must be set.
248 void ThrowException() {
249 scoped_refptr<StringVar> string(StringVar::FromPPVar(exception_));
250 if (string) {
251 WebBindings::setException(object_var_, string->value().c_str());
252 }
253 }
254
255 NPObject* object_var_; // Non-owning ref (see constructor).
256 NPVariant* np_result_; // Output value, possibly NULL (see constructor).
257 PP_Var exception_; // Exception set by the PPAPI call. We own a ref to it.
258 bool success_; // See the success() function above.
259 bool checked_exception_; // SetResult/CheckExceptionForNoResult was called.
260
261 DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult);
262 };
263
264 // NPObjectAccessorWithIdentifier ----------------------------------------------
265
266 // Helper class for our NPObject wrapper. This converts a call from WebKit
267 // where it gives us an NPObject and an NPIdentifier to an easily-accessible
268 // ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the
269 // NPIdentifier).
270 //
271 // If the NPObject or identifier is invalid, we'll set is_valid() to false.
272 // The caller should check is_valid() before doing anything with the class.
273 //
274 // JS can't have integer functions, so when dealing with these, we don't want
275 // to allow integer identifiers. The calling code can decode if it wants to
276 // allow integer identifiers (like for property access) or prohibit them
277 // (like for method calling) by setting |allow_integer_identifier|. If this
278 // is false and the identifier is an integer, we'll set is_valid() to false.
279 //
280 // Getting an integer identifier in this case should be impossible. V8
281 // shouldn't be allowing this, and the Pepper Var calls from the plugin are
282 // supposed to error out before calling into V8 (which will then call us back).
283 // Aside from an egregious error, the only time this could happen is an NPAPI
284 // plugin calling us.
285 class NPObjectAccessorWithIdentifier {
286 public:
287 NPObjectAccessorWithIdentifier(NPObject* object,
288 NPIdentifier identifier,
289 bool allow_integer_identifier)
290 : object_(PluginObject::FromNPObject(object)),
291 identifier_(PP_MakeUndefined()) {
292 if (object_) {
293 identifier_ = Var::NPIdentifierToPPVar(object_->module(), identifier);
294 if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier)
295 identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid.
296 }
297 }
298
299 ~NPObjectAccessorWithIdentifier() {
300 Var::PluginReleasePPVar(identifier_);
301 }
302
303 // Returns true if both the object and identifier are valid.
304 bool is_valid() const {
305 return object_ && identifier_.type != PP_VARTYPE_UNDEFINED;
306 }
307
308 PluginObject* object() { return object_; }
309 PP_Var identifier() const { return identifier_; }
310
311 private:
312 PluginObject* object_;
313 PP_Var identifier_;
314
315 DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier);
316 };
317
318 // NPObject implementation in terms of PPP_Class_Deprecated --------------------
319
320 NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) {
321 return PluginObject::AllocateObjectWrapper();
322 }
323
324 void WrapperClass_Deallocate(NPObject* np_object) {
325 PluginObject* plugin_object = PluginObject::FromNPObject(np_object);
326 if (!plugin_object)
327 return;
328 plugin_object->ppp_class()->Deallocate(plugin_object->ppp_class_data());
329 delete plugin_object;
330 }
331
332 void WrapperClass_Invalidate(NPObject* object) {
333 }
334
335 bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) {
336 NPObjectAccessorWithIdentifier accessor(object, method_name, false);
337 if (!accessor.is_valid())
338 return false;
339
340 PPResultAndExceptionToNPResult result_converter(
341 accessor.object()->GetNPObject(), NULL);
342 bool rv = accessor.object()->ppp_class()->HasMethod(
343 accessor.object()->ppp_class_data(), accessor.identifier(),
344 result_converter.exception());
345 result_converter.CheckExceptionForNoResult();
346 return rv;
347 }
348
349 bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name,
350 const NPVariant* argv, uint32_t argc,
351 NPVariant* result) {
352 NPObjectAccessorWithIdentifier accessor(object, method_name, false);
353 if (!accessor.is_valid())
354 return false;
355
356 PPResultAndExceptionToNPResult result_converter(
357 accessor.object()->GetNPObject(), result);
358 PPVarArrayFromNPVariantArray args(accessor.object()->module(), argc, argv);
359
360 return result_converter.SetResult(accessor.object()->ppp_class()->Call(
361 accessor.object()->ppp_class_data(), accessor.identifier(),
362 argc, args.array(), result_converter.exception()));
363 }
364
365 bool WrapperClass_InvokeDefault(NPObject* np_object, const NPVariant* argv,
366 uint32_t argc, NPVariant* result) {
367 PluginObject* obj = PluginObject::FromNPObject(np_object);
368 if (!obj)
369 return false;
370
371 PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
372 PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
373
374 result_converter.SetResult(obj->ppp_class()->Call(
375 obj->ppp_class_data(), PP_MakeUndefined(), argc, args.array(),
376 result_converter.exception()));
377 return result_converter.success();
378 }
379
380 bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) {
381 NPObjectAccessorWithIdentifier accessor(object, property_name, true);
382 if (!accessor.is_valid())
383 return false;
384
385 PPResultAndExceptionToNPResult result_converter(
386 accessor.object()->GetNPObject(), NULL);
387 bool rv = accessor.object()->ppp_class()->HasProperty(
388 accessor.object()->ppp_class_data(), accessor.identifier(),
389 result_converter.exception());
390 result_converter.CheckExceptionForNoResult();
391 return rv;
392 }
393
394 bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name,
395 NPVariant* result) {
396 NPObjectAccessorWithIdentifier accessor(object, property_name, true);
397 if (!accessor.is_valid())
398 return false;
399
400 PPResultAndExceptionToNPResult result_converter(
401 accessor.object()->GetNPObject(), result);
402 return result_converter.SetResult(accessor.object()->ppp_class()->GetProperty(
403 accessor.object()->ppp_class_data(), accessor.identifier(),
404 result_converter.exception()));
405 }
406
407 bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name,
408 const NPVariant* value) {
409 NPObjectAccessorWithIdentifier accessor(object, property_name, true);
410 if (!accessor.is_valid())
411 return false;
412
413 PPResultAndExceptionToNPResult result_converter(
414 accessor.object()->GetNPObject(), NULL);
415 PP_Var value_var = Var::NPVariantToPPVar(accessor.object()->module(), value);
416 accessor.object()->ppp_class()->SetProperty(
417 accessor.object()->ppp_class_data(), accessor.identifier(), value_var,
418 result_converter.exception());
419 Var::PluginReleasePPVar(value_var);
420 return result_converter.CheckExceptionForNoResult();
421 }
422
423 bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) {
424 NPObjectAccessorWithIdentifier accessor(object, property_name, true);
425 if (!accessor.is_valid())
426 return false;
427
428 PPResultAndExceptionToNPResult result_converter(
429 accessor.object()->GetNPObject(), NULL);
430 accessor.object()->ppp_class()->RemoveProperty(
431 accessor.object()->ppp_class_data(), accessor.identifier(),
432 result_converter.exception());
433 return result_converter.CheckExceptionForNoResult();
434 }
435
436 bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values,
437 uint32_t* count) {
438 *values = NULL;
439 *count = 0;
440 PluginObject* obj = PluginObject::FromNPObject(object);
441 if (!obj)
442 return false;
443
444 uint32_t property_count = 0;
445 PP_Var* properties = NULL; // Must be freed!
446 PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), NULL);
447 obj->ppp_class()->GetAllPropertyNames(obj->ppp_class_data(),
448 &property_count, &properties,
449 result_converter.exception());
450
451 // Convert the array of PP_Var to an array of NPIdentifiers. If any
452 // conversions fail, we will set the exception.
453 if (!result_converter.has_exception()) {
454 if (property_count > 0) {
455 *values = static_cast<NPIdentifier*>(
456 malloc(sizeof(NPIdentifier) * property_count));
457 *count = 0; // Will be the number of items successfully converted.
458 for (uint32_t i = 0; i < property_count; ++i) {
459 if (!((*values)[i] = Var::PPVarToNPIdentifier(properties[i]))) {
460 // Throw an exception for the failed convertion.
461 *result_converter.exception() = StringVar::StringToPPVar(
462 obj->module(), kInvalidValueException);
463 break;
464 }
465 (*count)++;
466 }
467
468 if (result_converter.has_exception()) {
469 // We don't actually have to free the identifiers we converted since
470 // all identifiers leak anyway :( .
471 free(*values);
472 *values = NULL;
473 *count = 0;
474 }
475 }
476 }
477
478 // This will actually throw the exception, either from GetAllPropertyNames,
479 // or if anything was set during the conversion process.
480 result_converter.CheckExceptionForNoResult();
481
482 // Release the PP_Var that the plugin allocated. On success, they will all
483 // be converted to NPVariants, and on failure, we want them to just go away.
484 for (uint32_t i = 0; i < property_count; ++i)
485 Var::PluginReleasePPVar(properties[i]);
486 free(properties);
487 return result_converter.success();
488 }
489
490 bool WrapperClass_Construct(NPObject* object, const NPVariant* argv,
491 uint32_t argc, NPVariant* result) {
492 PluginObject* obj = PluginObject::FromNPObject(object);
493 if (!obj)
494 return false;
495
496 PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
497 PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
498 return result_converter.SetResult(obj->ppp_class()->Construct(
499 obj->ppp_class_data(), argc, args.array(),
500 result_converter.exception()));
501 }
502
503 const NPClass wrapper_class = {
504 NP_CLASS_STRUCT_VERSION,
505 WrapperClass_Allocate,
506 WrapperClass_Deallocate,
507 WrapperClass_Invalidate,
508 WrapperClass_HasMethod,
509 WrapperClass_Invoke,
510 WrapperClass_InvokeDefault,
511 WrapperClass_HasProperty,
512 WrapperClass_GetProperty,
513 WrapperClass_SetProperty,
514 WrapperClass_RemoveProperty,
515 WrapperClass_Enumerate,
516 WrapperClass_Construct
517 };
518
519 } // namespace
520
521 // PluginObject ----------------------------------------------------------------
522
523 struct PluginObject::NPObjectWrapper : public NPObject {
524 // Points to the var object that owns this wrapper. This value may be NULL
525 // if there is no var owning this wrapper. This can happen if the plugin
526 // releases all references to the var, but a reference to the underlying
527 // NPObject is still held by script on the page.
528 PluginObject* obj;
529 };
530
531 PluginObject::PluginObject(PluginModule* module,
532 NPObjectWrapper* object_wrapper,
533 const PPP_Class_Deprecated* ppp_class,
534 void* ppp_class_data)
535 : module_(module),
536 object_wrapper_(object_wrapper),
537 ppp_class_(ppp_class),
538 ppp_class_data_(ppp_class_data) {
539 // Make the object wrapper refer back to this class so our NPObject
540 // implementation can call back into the Pepper layer.
541 object_wrapper_->obj = this;
542 module_->AddPluginObject(this);
543 }
544
545 PluginObject::~PluginObject() {
546 // The wrapper we made for this NPObject may still have a reference to it
547 // from JavaScript, so we clear out its ObjectVar back pointer which will
548 // cause all calls "up" to the plugin to become NOPs. Our ObjectVar base
549 // class will release our reference to the object, which may or may not
550 // delete the NPObject.
551 DCHECK(object_wrapper_->obj == this);
552 object_wrapper_->obj = NULL;
553 module_->RemovePluginObject(this);
554 }
555
556 PP_Var PluginObject::Create(PluginModule* module,
557 const PPP_Class_Deprecated* ppp_class,
558 void* ppp_class_data) {
559 // This will internally end up calling our AllocateObjectWrapper via the
560 // WrapperClass_Allocated function which will have created an object wrapper
561 // appropriate for this class (derived from NPObject).
562 NPObjectWrapper* wrapper = static_cast<NPObjectWrapper*>(
563 WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class)));
564
565 // This object will register itself both with the NPObject and with the
566 // PluginModule. The NPObject will normally handle its lifetime, and it
567 // will get deleted in the destroy method. It may also get deleted when the
568 // plugin module is deallocated.
569 new PluginObject(module, wrapper, ppp_class, ppp_class_data);
570
571 // We can just use a normal ObjectVar to refer to this object from the
572 // plugin. It will hold a ref to the underlying NPObject which will in turn
573 // hold our pluginObject.
574 return ObjectVar::NPObjectToPPVar(module, wrapper);
575 }
576
577 NPObject* PluginObject::GetNPObject() const {
578 return object_wrapper_;
579 }
580
581 // static
582 bool PluginObject::IsInstanceOf(NPObject* np_object,
583 const PPP_Class_Deprecated* ppp_class,
584 void** ppp_class_data) {
585 // Validate that this object is implemented by our wrapper class before
586 // trying to get the PluginObject.
587 if (np_object->_class != &wrapper_class)
588 return false;
589
590 PluginObject* plugin_object = FromNPObject(np_object);
591 if (!plugin_object)
592 return false; // Object is no longer alive.
593
594 if (plugin_object->ppp_class() != ppp_class)
595 return false;
596 if (ppp_class_data)
597 *ppp_class_data = plugin_object->ppp_class_data();
598 return true;
599 }
600
601 // static
602 PluginObject* PluginObject::FromNPObject(NPObject* object) {
603 return static_cast<NPObjectWrapper*>(object)->obj;
604 }
605
606 // static
607 NPObject* PluginObject::AllocateObjectWrapper() {
608 NPObjectWrapper* wrapper = new NPObjectWrapper;
609 memset(wrapper, 0, sizeof(NPObjectWrapper));
610 return wrapper;
611 }
612
613 // VarObjectClass::InstanceData -----------------------------------------------
614
615 struct VarObjectClass::InstanceData : public NPObject {
616 InstanceData() : native_data(NULL) {}
617
618 scoped_refptr<VarObjectClass> object_class;
619 void* native_data;
620 };
621
622 // VarObjectClass::Property ---------------------------------------------------
623
624 VarObjectClass::Property::Property(const PP_ClassProperty& prop)
625 : method(prop.method),
626 getter(prop.getter),
627 setter(prop.setter),
628 writable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)),
629 enumerable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) {
630 }
631
632
633 // VarObjectAccessorWithIdentifier ---------------------------------------------
634
635 // Helper class for the new (PPB_Class) NPObject wrapper. This converts a call
636 // from WebKit where it gives us an NPObject and an NPIdentifier to an
637 // easily-accessible InstanceData (corresponding to the NPObject) and
638 // std::string and Property (corresponding to the NPIdentifier).
639 class VarObjectAccessorWithIdentifier {
640 public:
641 VarObjectAccessorWithIdentifier(NPObject* object, NPIdentifier identifier)
642 : exists_(false),
643 instance_(static_cast<VarObjectClass::InstanceData*>(object)),
644 property_(NULL) {
645 if (instance_) {
646 const NPUTF8* string_value = NULL;
647 int32_t int_value = 0;
648 bool is_string = false;
649 WebBindings::extractIdentifierData(identifier, string_value, int_value,
650 is_string);
651 if (is_string) {
652 property_name_ = string_value;
653
654 const VarObjectClass::PropertyMap& properties =
655 instance_->object_class->properties();
656 VarObjectClass::PropertyMap::const_iterator it =
657 properties.find(property_name_);
658 if (it != properties.end()) {
659 property_ = &it->second;
660 exists_ = true;
661 }
662 }
663 }
664 }
665
666 // Return true if the object is valid, the identifier is valid, and the
667 // property with said name exists.
668 bool exists() const { return exists_; }
669 bool is_method() const { return exists() && property_->method; }
670 bool is_readable() const { return exists() && property_->getter; }
671 bool is_writable() const {
672 return exists() && property_->setter && property_->writable;
673 }
674 const VarObjectClass::InstanceData* instance() const { return instance_; }
675 const VarObjectClass::Property* property() const { return property_; }
676 PluginModule* module() const {
677 return instance_ ? instance_->object_class->module() : NULL;
678 }
679
680 private:
681 bool exists_;
682 const VarObjectClass::InstanceData* instance_;
683 std::string property_name_;
684 const VarObjectClass::Property* property_;
685
686 DISALLOW_COPY_AND_ASSIGN(VarObjectAccessorWithIdentifier);
687 };
688
689 // NPObject implementation in terms of PPB_Class -------------------------------
690
691 namespace {
692
693 NPObject* VarObjectClassAllocate(NPP npp, NPClass* the_class) {
694 return new VarObjectClass::InstanceData;
695 }
696
697 void VarObjectClassDeallocate(NPObject* object) {
698 VarObjectClass::InstanceData* instance =
699 static_cast<VarObjectClass::InstanceData*>(object);
700 if (instance->object_class->instance_native_destructor())
701 instance->object_class->instance_native_destructor()(instance->native_data);
702 delete instance;
703 }
704
705 bool VarObjectClassHasMethod(NPObject* np_obj, NPIdentifier name) {
706 VarObjectAccessorWithIdentifier accessor(np_obj, name);
707 return accessor.is_method();
708 }
709
710 bool VarObjectClassInvoke(NPObject* np_obj, NPIdentifier name,
711 const NPVariant* args, uint32 arg_count,
712 NPVariant* result) {
713 VarObjectAccessorWithIdentifier accessor(np_obj, name);
714 if (!accessor.is_method())
715 return false;
716
717 PPResultAndExceptionToNPResult result_converter(np_obj, result);
718 PPVarArrayFromNPVariantArray arguments(accessor.module(), arg_count, args);
719 PPVarFromNPObject self(accessor.module(), np_obj);
720
721 return result_converter.SetResult(accessor.property()->method(
722 accessor.instance()->native_data, self.var(), arguments.array(), arg_count,
723 result_converter.exception()));
724 }
725
726 bool VarObjectClassInvokeDefault(NPObject* np_obj,
727 const NPVariant* args,
728 uint32 arg_count,
729 NPVariant* result) {
730 VarObjectClass::InstanceData* instance =
731 static_cast<VarObjectClass::InstanceData*>(np_obj);
732 if (!instance || !instance->object_class->instance_invoke())
733 return false;
734
735 PPResultAndExceptionToNPResult result_converter(np_obj, result);
736 PPVarArrayFromNPVariantArray arguments(instance->object_class->module(),
737 arg_count, args);
738 PPVarFromNPObject self(instance->object_class->module(), np_obj);
739
740 return result_converter.SetResult(instance->object_class->instance_invoke()(
741 instance->native_data, self.var(), arguments.array(), arg_count,
742 result_converter.exception()));
743 }
744
745 bool VarObjectClassHasProperty(NPObject* np_obj, NPIdentifier name) {
746 VarObjectAccessorWithIdentifier accessor(np_obj, name);
747 return accessor.is_readable();
748 }
749
750 bool VarObjectClassGetProperty(NPObject* np_obj, NPIdentifier name,
751 NPVariant* result) {
752 VarObjectAccessorWithIdentifier accessor(np_obj, name);
753 if (!accessor.is_readable()) {
754 return false;
755 }
756
757 PPResultAndExceptionToNPResult result_converter(np_obj, result);
758 PPVarFromNPObject self(accessor.module(), np_obj);
759
760 return result_converter.SetResult(accessor.property()->getter(
761 accessor.instance()->native_data, self.var(), 0, 0,
762 result_converter.exception()));
763 }
764
765 bool VarObjectClassSetProperty(NPObject* np_obj, NPIdentifier name,
766 const NPVariant* variant) {
767 VarObjectAccessorWithIdentifier accessor(np_obj, name);
768 if (!accessor.is_writable()) {
769 return false;
770 }
771
772 PPResultAndExceptionToNPResult result_converter(np_obj, NULL);
773 PPVarArrayFromNPVariantArray arguments(accessor.module(), 1, variant);
774 PPVarFromNPObject self(accessor.module(), np_obj);
775
776 // Ignore return value.
777 Var::PluginReleasePPVar(accessor.property()->setter(
778 accessor.instance()->native_data, self.var(), arguments.array(), 1,
779 result_converter.exception()));
780
781 return result_converter.CheckExceptionForNoResult();
782 }
783
784 bool VarObjectClassEnumerate(NPObject *np_obj, NPIdentifier **value,
785 uint32_t *count) {
786 VarObjectClass::InstanceData* instance =
787 static_cast<VarObjectClass::InstanceData*>(np_obj);
788 *count = 0;
789 *value = NULL;
790 if (!instance)
791 return false;
792
793 const VarObjectClass::PropertyMap& properties =
794 instance->object_class->properties();
795
796 // Don't bother calculating the size of enumerable properties, just allocate
797 // enough for all and then fill it partially.
798 *value = static_cast<NPIdentifier*>(
799 malloc(sizeof(NPIdentifier) * properties.size()));
800
801 NPIdentifier* inserter = *value;
802 for (VarObjectClass::PropertyMap::const_iterator i = properties.begin();
803 i != properties.end(); ++i)
804 if (i->second.enumerable)
805 *inserter++ = WebBindings::getStringIdentifier(i->first.c_str());
806
807 *count = inserter - *value;
808 return true;
809 }
810
811 NPClass objectclassvar_class = {
812 NP_CLASS_STRUCT_VERSION,
813 &VarObjectClassAllocate,
814 &VarObjectClassDeallocate,
815 NULL,
816 &VarObjectClassHasMethod,
817 &VarObjectClassInvoke,
818 &VarObjectClassInvokeDefault,
819 &VarObjectClassHasProperty,
820 &VarObjectClassGetProperty,
821 &VarObjectClassSetProperty,
822 NULL,
823 &VarObjectClassEnumerate,
824 };
825
826 // PPB_Class interface ---------------------------------------------------------
827
828 PP_Resource Create(PP_Module module, PP_ClassDestructor destruct,
829 PP_ClassFunction invoke, PP_ClassProperty* properties) {
830 PluginModule* plugin_module = ResourceTracker::Get()->GetModule(module);
831 if (!properties || !plugin_module)
832 return 0;
833 scoped_refptr<VarObjectClass> cls = new VarObjectClass(plugin_module,
834 destruct,
835 invoke,
836 properties);
837 if (!cls)
838 return 0;
839 return cls->GetReference();
840 }
841
842 PP_Var Instantiate(PP_Resource class_object, void* native_data,
843 PP_Var* exception) {
844 scoped_refptr<VarObjectClass> object_class =
845 Resource::GetAs<VarObjectClass>(class_object);
846 if (!object_class)
847 return PP_MakeUndefined();
848 NPObject* obj = WebBindings::createObject(NULL, &objectclassvar_class);
849 VarObjectClass::InstanceData* instance_data =
850 static_cast<VarObjectClass::InstanceData*>(obj);
851 instance_data->object_class = object_class;
852 instance_data->native_data = native_data;
853 return ObjectVar::NPObjectToPPVar(object_class->module(), obj);
854 }
855
856 } // namespace
857
858 // VarObjectClass --------------------------------------------------------------
859
860 VarObjectClass::VarObjectClass(PluginModule* module,
861 PP_ClassDestructor destruct,
862 PP_ClassFunction invoke,
863 PP_ClassProperty* properties)
864 : Resource(module),
865 instance_native_destructor_(destruct),
866 instance_invoke_(invoke) {
867 PP_ClassProperty* prop = properties;
868 while (prop->name) {
869 properties_.insert(std::make_pair(std::string(prop->name),
870 Property(*prop)));
871 ++prop;
872 }
873 }
874
875 // static
876 const PPB_Class* VarObjectClass::GetInterface() {
877 static PPB_Class interface = {
878 &Create,
879 &Instantiate
880 };
881 return &interface;
882 }
883
884 // virtual
885 VarObjectClass::~VarObjectClass() { }
886
887 VarObjectClass* VarObjectClass::AsVarObjectClass() {
888 return this;
889 }
890
891 } // namespace pepper
OLDNEW
« no previous file with comments | « webkit/glue/plugins/pepper_plugin_object.h ('k') | webkit/glue/plugins/pepper_private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698