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/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_(static_cast<VarObjectClass::InstanceData*>(object)), |
| 30 property_(NULL) { |
| 31 if (instance_) { |
| 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_->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() const { return instance_; } |
| 61 const VarObjectClass::Property* property() const { return property_; } |
| 62 PluginModule* module() const { |
| 63 return instance_ ? instance_->object_class->module() : NULL; |
| 64 } |
| 65 |
| 66 private: |
| 67 bool exists_; |
| 68 const VarObjectClass::InstanceData* instance_; |
| 69 std::string property_name_; |
| 70 const VarObjectClass::Property* property_; |
| 71 |
| 72 DISALLOW_COPY_AND_ASSIGN(VarObjectAccessorWithIdentifier); |
| 73 }; |
| 74 |
| 75 NPObject* VarObjectClassAllocate(NPP npp, NPClass* the_class) { |
| 76 return new VarObjectClass::InstanceData; |
| 77 } |
| 78 |
| 79 void VarObjectClassDeallocate(NPObject* object) { |
| 80 VarObjectClass::InstanceData* instance = |
| 81 static_cast<VarObjectClass::InstanceData*>(object); |
| 82 if (instance->object_class->instance_native_destructor()) |
| 83 instance->object_class->instance_native_destructor()(instance->native_data); |
| 84 delete instance; |
| 85 } |
| 86 |
| 87 bool VarObjectClassHasMethod(NPObject* np_obj, NPIdentifier name) { |
| 88 VarObjectAccessorWithIdentifier accessor(np_obj, name); |
| 89 return accessor.is_method(); |
| 90 } |
| 91 |
| 92 bool VarObjectClassInvoke(NPObject* np_obj, NPIdentifier name, |
| 93 const NPVariant* args, uint32 arg_count, |
| 94 NPVariant* result) { |
| 95 VarObjectAccessorWithIdentifier accessor(np_obj, name); |
| 96 if (!accessor.is_method()) |
| 97 return false; |
| 98 |
| 99 PPResultAndExceptionToNPResult result_converter(np_obj, result); |
| 100 PPVarArrayFromNPVariantArray arguments(accessor.module(), arg_count, args); |
| 101 PPVarFromNPObject self(accessor.module(), np_obj); |
| 102 |
| 103 return result_converter.SetResult(accessor.property()->method( |
| 104 accessor.instance()->native_data, self.var(), arguments.array(), arg_count, |
| 105 result_converter.exception())); |
| 106 } |
| 107 |
| 108 bool VarObjectClassInvokeDefault(NPObject* np_obj, |
| 109 const NPVariant* args, |
| 110 uint32 arg_count, |
| 111 NPVariant* result) { |
| 112 VarObjectClass::InstanceData* instance = |
| 113 static_cast<VarObjectClass::InstanceData*>(np_obj); |
| 114 if (!instance || !instance->object_class->instance_invoke()) |
| 115 return false; |
| 116 |
| 117 PPResultAndExceptionToNPResult result_converter(np_obj, result); |
| 118 PPVarArrayFromNPVariantArray arguments(instance->object_class->module(), |
| 119 arg_count, args); |
| 120 PPVarFromNPObject self(instance->object_class->module(), np_obj); |
| 121 |
| 122 return result_converter.SetResult(instance->object_class->instance_invoke()( |
| 123 instance->native_data, self.var(), arguments.array(), arg_count, |
| 124 result_converter.exception())); |
| 125 } |
| 126 |
| 127 bool VarObjectClassHasProperty(NPObject* np_obj, NPIdentifier name) { |
| 128 VarObjectAccessorWithIdentifier accessor(np_obj, name); |
| 129 return accessor.is_readable(); |
| 130 } |
| 131 |
| 132 bool VarObjectClassGetProperty(NPObject* np_obj, NPIdentifier name, |
| 133 NPVariant* result) { |
| 134 VarObjectAccessorWithIdentifier accessor(np_obj, name); |
| 135 if (!accessor.is_readable()) { |
| 136 return false; |
| 137 } |
| 138 |
| 139 PPResultAndExceptionToNPResult result_converter(np_obj, result); |
| 140 PPVarFromNPObject self(accessor.module(), np_obj); |
| 141 |
| 142 return result_converter.SetResult(accessor.property()->getter( |
| 143 accessor.instance()->native_data, self.var(), 0, 0, |
| 144 result_converter.exception())); |
| 145 } |
| 146 |
| 147 bool VarObjectClassSetProperty(NPObject* np_obj, NPIdentifier name, |
| 148 const NPVariant* variant) { |
| 149 VarObjectAccessorWithIdentifier accessor(np_obj, name); |
| 150 if (!accessor.is_writable()) { |
| 151 return false; |
| 152 } |
| 153 |
| 154 PPResultAndExceptionToNPResult result_converter(np_obj, NULL); |
| 155 PPVarArrayFromNPVariantArray arguments(accessor.module(), 1, variant); |
| 156 PPVarFromNPObject self(accessor.module(), np_obj); |
| 157 |
| 158 // Ignore return value. |
| 159 Var::PluginReleasePPVar(accessor.property()->setter( |
| 160 accessor.instance()->native_data, self.var(), arguments.array(), 1, |
| 161 result_converter.exception())); |
| 162 |
| 163 return result_converter.CheckExceptionForNoResult(); |
| 164 } |
| 165 |
| 166 bool VarObjectClassEnumerate(NPObject *np_obj, NPIdentifier **value, |
| 167 uint32_t *count) { |
| 168 VarObjectClass::InstanceData* instance = |
| 169 static_cast<VarObjectClass::InstanceData*>(np_obj); |
| 170 *count = 0; |
| 171 *value = NULL; |
| 172 if (!instance) |
| 173 return false; |
| 174 |
| 175 const VarObjectClass::PropertyMap& properties = |
| 176 instance->object_class->properties(); |
| 177 |
| 178 // Don't bother calculating the size of enumerable properties, just allocate |
| 179 // enough for all and then fill it partially. |
| 180 *value = static_cast<NPIdentifier*>( |
| 181 malloc(sizeof(NPIdentifier) * properties.size())); |
| 182 |
| 183 NPIdentifier* inserter = *value; |
| 184 for (VarObjectClass::PropertyMap::const_iterator i = properties.begin(); |
| 185 i != properties.end(); ++i) |
| 186 if (i->second.enumerable) |
| 187 *inserter++ = WebBindings::getStringIdentifier(i->first.c_str()); |
| 188 |
| 189 *count = inserter - *value; |
| 190 return true; |
| 191 } |
| 192 |
| 193 NPClass objectclassvar_class = { |
| 194 NP_CLASS_STRUCT_VERSION, |
| 195 &VarObjectClassAllocate, |
| 196 &VarObjectClassDeallocate, |
| 197 NULL, |
| 198 &VarObjectClassHasMethod, |
| 199 &VarObjectClassInvoke, |
| 200 &VarObjectClassInvokeDefault, |
| 201 &VarObjectClassHasProperty, |
| 202 &VarObjectClassGetProperty, |
| 203 &VarObjectClassSetProperty, |
| 204 NULL, |
| 205 &VarObjectClassEnumerate, |
| 206 }; |
| 207 |
| 208 // PPB_Class ------------------------------------------------------------------- |
| 209 |
| 210 PP_Resource Create(PP_Module module, PP_ClassDestructor destruct, |
| 211 PP_ClassFunction invoke, PP_ClassProperty* properties) { |
| 212 PluginModule* plugin_module = ResourceTracker::Get()->GetModule(module); |
| 213 if (!properties || !plugin_module) |
| 214 return 0; |
| 215 scoped_refptr<VarObjectClass> cls = new VarObjectClass(plugin_module, |
| 216 destruct, |
| 217 invoke, |
| 218 properties); |
| 219 if (!cls) |
| 220 return 0; |
| 221 return cls->GetReference(); |
| 222 } |
| 223 |
| 224 PP_Var Instantiate(PP_Resource class_object, void* native_data, |
| 225 PP_Var* exception) { |
| 226 scoped_refptr<VarObjectClass> object_class = |
| 227 Resource::GetAs<VarObjectClass>(class_object); |
| 228 if (!object_class) |
| 229 return PP_MakeUndefined(); |
| 230 NPObject* obj = WebBindings::createObject(NULL, &objectclassvar_class); |
| 231 VarObjectClass::InstanceData* instance_data = |
| 232 static_cast<VarObjectClass::InstanceData*>(obj); |
| 233 instance_data->object_class = object_class; |
| 234 instance_data->native_data = native_data; |
| 235 return ObjectVar::NPObjectToPPVar(object_class->module(), obj); |
| 236 } |
| 237 |
| 238 } // namespace |
| 239 |
| 240 // VarObjectClass -------------------------------------------------------------- |
| 241 |
| 242 VarObjectClass::Property::Property(const PP_ClassProperty& prop) |
| 243 : method(prop.method), |
| 244 getter(prop.getter), |
| 245 setter(prop.setter), |
| 246 writable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)), |
| 247 enumerable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) { |
| 248 } |
| 249 |
| 250 VarObjectClass::InstanceData::InstanceData() : native_data(NULL) { |
| 251 } |
| 252 |
| 253 VarObjectClass::VarObjectClass(PluginModule* module, |
| 254 PP_ClassDestructor destruct, |
| 255 PP_ClassFunction invoke, |
| 256 PP_ClassProperty* properties) |
| 257 : Resource(module), |
| 258 instance_native_destructor_(destruct), |
| 259 instance_invoke_(invoke) { |
| 260 PP_ClassProperty* prop = properties; |
| 261 while (prop->name) { |
| 262 properties_.insert(std::make_pair(std::string(prop->name), |
| 263 Property(*prop))); |
| 264 ++prop; |
| 265 } |
| 266 } |
| 267 |
| 268 // virtual |
| 269 VarObjectClass::~VarObjectClass() { |
| 270 } |
| 271 |
| 272 VarObjectClass* VarObjectClass::AsVarObjectClass() { |
| 273 return this; |
| 274 } |
| 275 |
| 276 // static |
| 277 const PPB_Class* VarObjectClass::GetInterface() { |
| 278 static PPB_Class interface = { |
| 279 &Create, |
| 280 &Instantiate |
| 281 }; |
| 282 return &interface; |
| 283 } |
| 284 |
| 285 } // namespace ppapi |
| 286 } // namespace webkit |
OLD | NEW |