| OLD | NEW |
| (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/plugins/ppapi/var_object_class.h" | |
| 6 | |
| 7 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | |
| 8 #include "webkit/plugins/ppapi/npapi_glue.h" | |
| 9 #include "webkit/plugins/ppapi/resource_tracker.h" | |
| 10 #include "webkit/plugins/ppapi/var.h" | |
| 11 | |
| 12 using WebKit::WebBindings; | |
| 13 | |
| 14 namespace webkit { | |
| 15 namespace ppapi { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // VarObjectAccessorWithIdentifier --------------------------------------------- | |
| 20 | |
| 21 // Helper class for the new (PPB_Class) NPObject wrapper. This converts a call | |
| 22 // from WebKit where it gives us an NPObject and an NPIdentifier to an | |
| 23 // easily-accessible InstanceData (corresponding to the NPObject) and | |
| 24 // std::string and Property (corresponding to the NPIdentifier). | |
| 25 class VarObjectAccessorWithIdentifier { | |
| 26 public: | |
| 27 VarObjectAccessorWithIdentifier(NPObject* object, NPIdentifier identifier) | |
| 28 : exists_(false), | |
| 29 instance_data_(static_cast<VarObjectClass::InstanceData*>(object)), | |
| 30 property_(NULL) { | |
| 31 if (instance_data_) { | |
| 32 const NPUTF8* string_value = NULL; | |
| 33 int32_t int_value = 0; | |
| 34 bool is_string = false; | |
| 35 WebBindings::extractIdentifierData(identifier, string_value, int_value, | |
| 36 is_string); | |
| 37 if (is_string) { | |
| 38 property_name_ = string_value; | |
| 39 | |
| 40 const VarObjectClass::PropertyMap& properties = | |
| 41 instance_data_->object_class->properties(); | |
| 42 VarObjectClass::PropertyMap::const_iterator it = | |
| 43 properties.find(property_name_); | |
| 44 if (it != properties.end()) { | |
| 45 property_ = &it->second; | |
| 46 exists_ = true; | |
| 47 } | |
| 48 } | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 // Return true if the object is valid, the identifier is valid, and the | |
| 53 // property with said name exists. | |
| 54 bool exists() const { return exists_; } | |
| 55 bool is_method() const { return exists() && property_->method; } | |
| 56 bool is_readable() const { return exists() && property_->getter; } | |
| 57 bool is_writable() const { | |
| 58 return exists() && property_->setter && property_->writable; | |
| 59 } | |
| 60 const VarObjectClass::InstanceData* instance_data() const { | |
| 61 return instance_data_; | |
| 62 } | |
| 63 const VarObjectClass::Property* property() const { return property_; } | |
| 64 PluginInstance* instance() const { | |
| 65 return instance_data_ ? instance_data_->object_class->instance() : NULL; | |
| 66 } | |
| 67 | |
| 68 private: | |
| 69 bool exists_; | |
| 70 const VarObjectClass::InstanceData* instance_data_; | |
| 71 std::string property_name_; | |
| 72 const VarObjectClass::Property* property_; | |
| 73 | |
| 74 DISALLOW_COPY_AND_ASSIGN(VarObjectAccessorWithIdentifier); | |
| 75 }; | |
| 76 | |
| 77 NPObject* VarObjectClassAllocate(NPP npp, NPClass* the_class) { | |
| 78 return new VarObjectClass::InstanceData; | |
| 79 } | |
| 80 | |
| 81 void VarObjectClassDeallocate(NPObject* object) { | |
| 82 VarObjectClass::InstanceData* instance = | |
| 83 static_cast<VarObjectClass::InstanceData*>(object); | |
| 84 if (instance->object_class->instance_native_destructor()) | |
| 85 instance->object_class->instance_native_destructor()(instance->native_data); | |
| 86 delete instance; | |
| 87 } | |
| 88 | |
| 89 bool VarObjectClassHasMethod(NPObject* np_obj, NPIdentifier name) { | |
| 90 VarObjectAccessorWithIdentifier accessor(np_obj, name); | |
| 91 return accessor.is_method(); | |
| 92 } | |
| 93 | |
| 94 bool VarObjectClassInvoke(NPObject* np_obj, NPIdentifier name, | |
| 95 const NPVariant* args, uint32 arg_count, | |
| 96 NPVariant* result) { | |
| 97 VarObjectAccessorWithIdentifier accessor(np_obj, name); | |
| 98 if (!accessor.is_method()) | |
| 99 return false; | |
| 100 | |
| 101 PPResultAndExceptionToNPResult result_converter(np_obj, result); | |
| 102 PPVarArrayFromNPVariantArray arguments(accessor.instance(), arg_count, args); | |
| 103 PPVarFromNPObject self(accessor.instance(), np_obj); | |
| 104 | |
| 105 return result_converter.SetResult(accessor.property()->method( | |
| 106 accessor.instance_data()->native_data, self.var(), arguments.array(), | |
| 107 arg_count, result_converter.exception())); | |
| 108 } | |
| 109 | |
| 110 bool VarObjectClassInvokeDefault(NPObject* np_obj, | |
| 111 const NPVariant* args, | |
| 112 uint32 arg_count, | |
| 113 NPVariant* result) { | |
| 114 VarObjectClass::InstanceData* instance = | |
| 115 static_cast<VarObjectClass::InstanceData*>(np_obj); | |
| 116 if (!instance || !instance->object_class->instance_invoke()) | |
| 117 return false; | |
| 118 | |
| 119 PPResultAndExceptionToNPResult result_converter(np_obj, result); | |
| 120 PPVarArrayFromNPVariantArray arguments(instance->object_class->instance(), | |
| 121 arg_count, args); | |
| 122 PPVarFromNPObject self(instance->object_class->instance(), np_obj); | |
| 123 | |
| 124 return result_converter.SetResult(instance->object_class->instance_invoke()( | |
| 125 instance->native_data, self.var(), arguments.array(), arg_count, | |
| 126 result_converter.exception())); | |
| 127 } | |
| 128 | |
| 129 bool VarObjectClassHasProperty(NPObject* np_obj, NPIdentifier name) { | |
| 130 VarObjectAccessorWithIdentifier accessor(np_obj, name); | |
| 131 return accessor.is_readable(); | |
| 132 } | |
| 133 | |
| 134 bool VarObjectClassGetProperty(NPObject* np_obj, NPIdentifier name, | |
| 135 NPVariant* result) { | |
| 136 VarObjectAccessorWithIdentifier accessor(np_obj, name); | |
| 137 if (!accessor.is_readable()) { | |
| 138 return false; | |
| 139 } | |
| 140 | |
| 141 PPResultAndExceptionToNPResult result_converter(np_obj, result); | |
| 142 PPVarFromNPObject self(accessor.instance(), np_obj); | |
| 143 | |
| 144 return result_converter.SetResult(accessor.property()->getter( | |
| 145 accessor.instance_data()->native_data, self.var(), 0, 0, | |
| 146 result_converter.exception())); | |
| 147 } | |
| 148 | |
| 149 bool VarObjectClassSetProperty(NPObject* np_obj, NPIdentifier name, | |
| 150 const NPVariant* variant) { | |
| 151 VarObjectAccessorWithIdentifier accessor(np_obj, name); | |
| 152 if (!accessor.is_writable()) { | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 PPResultAndExceptionToNPResult result_converter(np_obj, NULL); | |
| 157 PPVarArrayFromNPVariantArray arguments(accessor.instance(), 1, variant); | |
| 158 PPVarFromNPObject self(accessor.instance(), np_obj); | |
| 159 | |
| 160 // Ignore return value. | |
| 161 Var::PluginReleasePPVar(accessor.property()->setter( | |
| 162 accessor.instance_data()->native_data, self.var(), arguments.array(), 1, | |
| 163 result_converter.exception())); | |
| 164 | |
| 165 return result_converter.CheckExceptionForNoResult(); | |
| 166 } | |
| 167 | |
| 168 bool VarObjectClassEnumerate(NPObject *np_obj, NPIdentifier **value, | |
| 169 uint32_t *count) { | |
| 170 VarObjectClass::InstanceData* instance = | |
| 171 static_cast<VarObjectClass::InstanceData*>(np_obj); | |
| 172 *count = 0; | |
| 173 *value = NULL; | |
| 174 if (!instance) | |
| 175 return false; | |
| 176 | |
| 177 const VarObjectClass::PropertyMap& properties = | |
| 178 instance->object_class->properties(); | |
| 179 | |
| 180 // Don't bother calculating the size of enumerable properties, just allocate | |
| 181 // enough for all and then fill it partially. | |
| 182 *value = static_cast<NPIdentifier*>( | |
| 183 malloc(sizeof(NPIdentifier) * properties.size())); | |
| 184 | |
| 185 NPIdentifier* inserter = *value; | |
| 186 for (VarObjectClass::PropertyMap::const_iterator i = properties.begin(); | |
| 187 i != properties.end(); ++i) | |
| 188 if (i->second.enumerable) | |
| 189 *inserter++ = WebBindings::getStringIdentifier(i->first.c_str()); | |
| 190 | |
| 191 *count = inserter - *value; | |
| 192 return true; | |
| 193 } | |
| 194 | |
| 195 NPClass objectclassvar_class = { | |
| 196 NP_CLASS_STRUCT_VERSION, | |
| 197 &VarObjectClassAllocate, | |
| 198 &VarObjectClassDeallocate, | |
| 199 NULL, | |
| 200 &VarObjectClassHasMethod, | |
| 201 &VarObjectClassInvoke, | |
| 202 &VarObjectClassInvokeDefault, | |
| 203 &VarObjectClassHasProperty, | |
| 204 &VarObjectClassGetProperty, | |
| 205 &VarObjectClassSetProperty, | |
| 206 NULL, | |
| 207 &VarObjectClassEnumerate, | |
| 208 }; | |
| 209 | |
| 210 // PPB_Class ------------------------------------------------------------------- | |
| 211 | |
| 212 PP_Resource Create(PP_Instance instance_id, PP_ClassDestructor destruct, | |
| 213 PP_ClassFunction invoke, PP_ClassProperty* properties) { | |
| 214 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); | |
| 215 if (!properties || !instance) | |
| 216 return 0; | |
| 217 scoped_refptr<VarObjectClass> cls = new VarObjectClass(instance, | |
| 218 destruct, | |
| 219 invoke, | |
| 220 properties); | |
| 221 if (!cls) | |
| 222 return 0; | |
| 223 return cls->GetReference(); | |
| 224 } | |
| 225 | |
| 226 PP_Var Instantiate(PP_Resource class_object, void* native_data, | |
| 227 PP_Var* exception) { | |
| 228 scoped_refptr<VarObjectClass> object_class = | |
| 229 Resource::GetAs<VarObjectClass>(class_object); | |
| 230 if (!object_class) | |
| 231 return PP_MakeUndefined(); | |
| 232 NPObject* obj = WebBindings::createObject(NULL, &objectclassvar_class); | |
| 233 VarObjectClass::InstanceData* instance_data = | |
| 234 static_cast<VarObjectClass::InstanceData*>(obj); | |
| 235 instance_data->object_class = object_class; | |
| 236 instance_data->native_data = native_data; | |
| 237 return ObjectVar::NPObjectToPPVar(object_class->instance(), obj); | |
| 238 } | |
| 239 | |
| 240 } // namespace | |
| 241 | |
| 242 // VarObjectClass -------------------------------------------------------------- | |
| 243 | |
| 244 VarObjectClass::Property::Property(const PP_ClassProperty& prop) | |
| 245 : method(prop.method), | |
| 246 getter(prop.getter), | |
| 247 setter(prop.setter), | |
| 248 writable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)), | |
| 249 enumerable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) { | |
| 250 } | |
| 251 | |
| 252 VarObjectClass::InstanceData::InstanceData() : native_data(NULL) { | |
| 253 } | |
| 254 | |
| 255 VarObjectClass::InstanceData::~InstanceData() {} | |
| 256 | |
| 257 VarObjectClass::VarObjectClass(PluginInstance* instance, | |
| 258 PP_ClassDestructor destruct, | |
| 259 PP_ClassFunction invoke, | |
| 260 PP_ClassProperty* properties) | |
| 261 : Resource(instance), | |
| 262 instance_native_destructor_(destruct), | |
| 263 instance_invoke_(invoke) { | |
| 264 PP_ClassProperty* prop = properties; | |
| 265 while (prop->name) { | |
| 266 properties_.insert(std::make_pair(std::string(prop->name), | |
| 267 Property(*prop))); | |
| 268 ++prop; | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 // virtual | |
| 273 VarObjectClass::~VarObjectClass() { | |
| 274 } | |
| 275 | |
| 276 VarObjectClass* VarObjectClass::AsVarObjectClass() { | |
| 277 return this; | |
| 278 } | |
| 279 | |
| 280 // static | |
| 281 const PPB_Class* VarObjectClass::GetInterface() { | |
| 282 static PPB_Class interface = { | |
| 283 &Create, | |
| 284 &Instantiate | |
| 285 }; | |
| 286 return &interface; | |
| 287 } | |
| 288 | |
| 289 } // namespace ppapi | |
| 290 } // namespace webkit | |
| OLD | NEW |