OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/plugins/pepper_plugin_object.h" | 5 #include "webkit/plugins/ppapi/plugin_object.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/ref_counted.h" | 8 #include "base/ref_counted.h" |
9 #include "base/scoped_ptr.h" | 9 #include "base/scoped_ptr.h" |
10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "third_party/npapi/bindings/npapi.h" | 12 #include "third_party/npapi/bindings/npapi.h" |
13 #include "third_party/npapi/bindings/npruntime.h" | 13 #include "third_party/npapi/bindings/npruntime.h" |
14 #include "ppapi/c/dev/ppb_var_deprecated.h" | 14 #include "ppapi/c/dev/ppb_var_deprecated.h" |
15 #include "ppapi/c/dev/ppp_class_deprecated.h" | 15 #include "ppapi/c/dev/ppp_class_deprecated.h" |
16 #include "ppapi/c/pp_resource.h" | 16 #include "ppapi/c/pp_resource.h" |
17 #include "ppapi/c/pp_var.h" | 17 #include "ppapi/c/pp_var.h" |
18 #include "ppapi/c/ppb_class.h" | 18 #include "ppapi/c/ppb_class.h" |
19 #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" | 19 #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" |
20 #include "webkit/glue/plugins/pepper_class.h" | 20 #include "webkit/plugins/ppapi/npapi_glue.h" |
21 #include "webkit/glue/plugins/pepper_plugin_module.h" | 21 #include "webkit/plugins/ppapi/plugin_module.h" |
22 #include "webkit/glue/plugins/pepper_resource.h" | 22 #include "webkit/plugins/ppapi/resource.h" |
23 #include "webkit/glue/plugins/pepper_string.h" | 23 #include "webkit/plugins/ppapi/string.h" |
24 #include "webkit/glue/plugins/pepper_var.h" | 24 #include "webkit/plugins/ppapi/var.h" |
| 25 #include "webkit/plugins/ppapi/var_object_class.h" |
25 | 26 |
26 using WebKit::WebBindings; | 27 using WebKit::WebBindings; |
27 | 28 |
28 namespace pepper { | 29 namespace webkit { |
| 30 namespace ppapi { |
29 | 31 |
30 namespace { | 32 namespace { |
31 | 33 |
32 const char kInvalidValueException[] = "Error: Invalid value"; | 34 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 | 35 |
318 // NPObject implementation in terms of PPP_Class_Deprecated -------------------- | 36 // NPObject implementation in terms of PPP_Class_Deprecated -------------------- |
319 | 37 |
320 NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) { | 38 NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) { |
321 return PluginObject::AllocateObjectWrapper(); | 39 return PluginObject::AllocateObjectWrapper(); |
322 } | 40 } |
323 | 41 |
324 void WrapperClass_Deallocate(NPObject* np_object) { | 42 void WrapperClass_Deallocate(NPObject* np_object) { |
325 PluginObject* plugin_object = PluginObject::FromNPObject(np_object); | 43 PluginObject* plugin_object = PluginObject::FromNPObject(np_object); |
326 if (!plugin_object) | 44 if (!plugin_object) |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 return static_cast<NPObjectWrapper*>(object)->obj; | 321 return static_cast<NPObjectWrapper*>(object)->obj; |
604 } | 322 } |
605 | 323 |
606 // static | 324 // static |
607 NPObject* PluginObject::AllocateObjectWrapper() { | 325 NPObject* PluginObject::AllocateObjectWrapper() { |
608 NPObjectWrapper* wrapper = new NPObjectWrapper; | 326 NPObjectWrapper* wrapper = new NPObjectWrapper; |
609 memset(wrapper, 0, sizeof(NPObjectWrapper)); | 327 memset(wrapper, 0, sizeof(NPObjectWrapper)); |
610 return wrapper; | 328 return wrapper; |
611 } | 329 } |
612 | 330 |
613 // VarObjectClass::InstanceData ----------------------------------------------- | 331 } // namespace ppapi |
| 332 } // namespace webkit |
614 | 333 |
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 } // namespace pepper | |
OLD | NEW |