Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / pepper / ppb_var_deprecated_impl.cc
blobbafbada0ddd44d9ba23ee561e9bd9cb390bcee08
1 // Copyright (c) 2012 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.
5 #include "content/renderer/pepper/ppb_var_deprecated_impl.h"
7 #include <limits>
9 #include "content/renderer/pepper/host_globals.h"
10 #include "content/renderer/pepper/npapi_glue.h"
11 #include "content/renderer/pepper/npobject_var.h"
12 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
13 #include "content/renderer/pepper/plugin_module.h"
14 #include "content/renderer/pepper/plugin_object.h"
15 #include "ppapi/c/dev/ppb_var_deprecated.h"
16 #include "ppapi/c/ppb_var.h"
17 #include "ppapi/c/pp_var.h"
18 #include "ppapi/shared_impl/ppb_var_shared.h"
19 #include "third_party/WebKit/public/web/WebBindings.h"
20 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
22 using ppapi::NPObjectVar;
23 using ppapi::PpapiGlobals;
24 using ppapi::StringVar;
25 using ppapi::Var;
26 using blink::WebBindings;
28 namespace content {
30 namespace {
32 const char kInvalidObjectException[] = "Error: Invalid object";
33 const char kInvalidPropertyException[] = "Error: Invalid property";
34 const char kInvalidValueException[] = "Error: Invalid value";
35 const char kUnableToGetPropertyException[] = "Error: Unable to get property";
36 const char kUnableToSetPropertyException[] = "Error: Unable to set property";
37 const char kUnableToRemovePropertyException[] =
38 "Error: Unable to remove property";
39 const char kUnableToGetAllPropertiesException[] =
40 "Error: Unable to get all properties";
41 const char kUnableToCallMethodException[] = "Error: Unable to call method";
42 const char kUnableToConstructException[] = "Error: Unable to construct";
44 // ---------------------------------------------------------------------------
45 // Utilities
47 // Converts the given PP_Var to an NPVariant, returning true on success.
48 // False means that the given variant is invalid. In this case, the result
49 // NPVariant will be set to a void one.
51 // The contents of the PP_Var will NOT be copied, so you need to ensure that
52 // the PP_Var remains valid while the resultant NPVariant is in use.
53 bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) {
54 switch (var.type) {
55 case PP_VARTYPE_UNDEFINED:
56 VOID_TO_NPVARIANT(*result);
57 break;
58 case PP_VARTYPE_NULL:
59 NULL_TO_NPVARIANT(*result);
60 break;
61 case PP_VARTYPE_BOOL:
62 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
63 break;
64 case PP_VARTYPE_INT32:
65 INT32_TO_NPVARIANT(var.value.as_int, *result);
66 break;
67 case PP_VARTYPE_DOUBLE:
68 DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
69 break;
70 case PP_VARTYPE_STRING: {
71 StringVar* string = StringVar::FromPPVar(var);
72 if (!string) {
73 VOID_TO_NPVARIANT(*result);
74 return false;
76 const std::string& value = string->value();
77 STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
78 break;
80 case PP_VARTYPE_OBJECT: {
81 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
82 if (!object.get()) {
83 VOID_TO_NPVARIANT(*result);
84 return false;
86 OBJECT_TO_NPVARIANT(object->np_object(), *result);
87 break;
89 default:
90 VOID_TO_NPVARIANT(*result);
91 return false;
93 return true;
96 // ObjectAccessorTryCatch ------------------------------------------------------
98 // Automatically sets up a TryCatch for accessing the object identified by the
99 // given PP_Var. The module from the object will be used for the exception
100 // strings generated by the TryCatch.
102 // This will automatically retrieve the ObjectVar from the object and throw
103 // an exception if it's invalid. At the end of construction, if there is no
104 // exception, you know that there is no previously set exception, that the
105 // object passed in is valid and ready to use (via the object() getter), and
106 // that the TryCatch's pp_module() getter is also set up properly and ready to
107 // use.
108 class ObjectAccessorTryCatch : public TryCatch {
109 public:
110 ObjectAccessorTryCatch(PP_Var object, PP_Var* exception)
111 : TryCatch(exception), object_(NPObjectVar::FromPPVar(object)) {
112 if (!object_.get()) {
113 SetException(kInvalidObjectException);
117 NPObjectVar* object() { return object_.get(); }
119 PepperPluginInstanceImpl* GetPluginInstance() {
120 return HostGlobals::Get()->GetInstance(object()->pp_instance());
123 protected:
124 scoped_refptr<NPObjectVar> object_;
126 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch);
129 // ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
131 // Automatically sets up a TryCatch for accessing the identifier on the given
132 // object. This just extends ObjectAccessorTryCatch to additionally convert
133 // the given identifier to an NPIdentifier and validate it, throwing an
134 // exception if it's invalid.
136 // At the end of construction, if there is no exception, you know that there is
137 // no previously set exception, that the object passed in is valid and ready to
138 // use (via the object() getter), that the identifier is valid and ready to
139 // use (via the identifier() getter), and that the TryCatch's pp_module() getter
140 // is also set up properly and ready to use.
141 class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch {
142 public:
143 ObjectAccessorWithIdentifierTryCatch(PP_Var object,
144 PP_Var identifier,
145 PP_Var* exception)
146 : ObjectAccessorTryCatch(object, exception), identifier_(0) {
147 if (!has_exception()) {
148 identifier_ = PPVarToNPIdentifier(identifier);
149 if (!identifier_)
150 SetException(kInvalidPropertyException);
154 NPIdentifier identifier() const { return identifier_; }
156 private:
157 NPIdentifier identifier_;
159 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
162 PP_Bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) {
163 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
164 if (accessor.has_exception())
165 return PP_FALSE;
166 return PP_FromBool(WebBindings::hasProperty(
167 NULL, accessor.object()->np_object(), accessor.identifier()));
170 bool HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
171 return PP_ToBool(HasProperty(var, name, exception));
174 bool HasMethodDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
175 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
176 if (accessor.has_exception())
177 return false;
178 return WebBindings::hasMethod(
179 NULL, accessor.object()->np_object(), accessor.identifier());
182 PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) {
183 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
184 if (accessor.has_exception())
185 return PP_MakeUndefined();
187 NPVariant result;
188 if (!WebBindings::getProperty(NULL,
189 accessor.object()->np_object(),
190 accessor.identifier(),
191 &result)) {
192 // An exception may have been raised.
193 accessor.SetException(kUnableToGetPropertyException);
194 return PP_MakeUndefined();
197 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
198 WebBindings::releaseVariantValue(&result);
199 return ret;
202 void EnumerateProperties(PP_Var var,
203 uint32_t* property_count,
204 PP_Var** properties,
205 PP_Var* exception) {
206 *properties = NULL;
207 *property_count = 0;
209 ObjectAccessorTryCatch accessor(var, exception);
210 if (accessor.has_exception())
211 return;
213 NPIdentifier* identifiers = NULL;
214 uint32_t count = 0;
215 if (!WebBindings::enumerate(
216 NULL, accessor.object()->np_object(), &identifiers, &count)) {
217 accessor.SetException(kUnableToGetAllPropertiesException);
218 return;
221 if (count == 0)
222 return;
224 *property_count = count;
225 *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count));
226 for (uint32_t i = 0; i < count; ++i) {
227 (*properties)[i] = NPIdentifierToPPVar(identifiers[i]);
229 free(identifiers);
232 void SetPropertyDeprecated(PP_Var var,
233 PP_Var name,
234 PP_Var value,
235 PP_Var* exception) {
236 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
237 if (accessor.has_exception())
238 return;
240 NPVariant variant;
241 if (!PPVarToNPVariantNoCopy(value, &variant)) {
242 accessor.SetException(kInvalidValueException);
243 return;
245 if (!WebBindings::setProperty(NULL,
246 accessor.object()->np_object(),
247 accessor.identifier(),
248 &variant))
249 accessor.SetException(kUnableToSetPropertyException);
252 void DeletePropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
253 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
254 if (accessor.has_exception())
255 return;
257 if (!WebBindings::removeProperty(
258 NULL, accessor.object()->np_object(), accessor.identifier()))
259 accessor.SetException(kUnableToRemovePropertyException);
262 PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor,
263 PP_Var method_name,
264 uint32_t argc,
265 PP_Var* argv,
266 PP_Var* exception) {
267 NPIdentifier identifier;
268 if (method_name.type == PP_VARTYPE_UNDEFINED) {
269 identifier = NULL;
270 } else if (method_name.type == PP_VARTYPE_STRING) {
271 // Specifically allow only string functions to be called.
272 identifier = PPVarToNPIdentifier(method_name);
273 if (!identifier) {
274 accessor->SetException(kInvalidPropertyException);
275 return PP_MakeUndefined();
277 } else {
278 accessor->SetException(kInvalidPropertyException);
279 return PP_MakeUndefined();
282 scoped_ptr<NPVariant[]> args;
283 if (argc) {
284 args.reset(new NPVariant[argc]);
285 for (uint32_t i = 0; i < argc; ++i) {
286 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
287 // This argument was invalid, throw an exception & give up.
288 accessor->SetException(kInvalidValueException);
289 return PP_MakeUndefined();
294 bool ok;
296 NPVariant result;
297 if (identifier) {
298 ok = WebBindings::invoke(NULL,
299 accessor->object()->np_object(),
300 identifier,
301 args.get(),
302 argc,
303 &result);
304 } else {
305 ok = WebBindings::invokeDefault(
306 NULL, accessor->object()->np_object(), args.get(), argc, &result);
309 if (!ok) {
310 // An exception may have been raised.
311 accessor->SetException(kUnableToCallMethodException);
312 return PP_MakeUndefined();
315 PP_Var ret = NPVariantToPPVar(accessor->GetPluginInstance(), &result);
316 WebBindings::releaseVariantValue(&result);
317 return ret;
320 PP_Var CallDeprecated(PP_Var var,
321 PP_Var method_name,
322 uint32_t argc,
323 PP_Var* argv,
324 PP_Var* exception) {
325 ObjectAccessorTryCatch accessor(var, exception);
326 if (accessor.has_exception())
327 return PP_MakeUndefined();
328 PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance();
329 if (plugin && plugin->IsProcessingUserGesture()) {
330 blink::WebScopedUserGesture user_gesture(plugin->CurrentUserGestureToken());
331 return InternalCallDeprecated(
332 &accessor, method_name, argc, argv, exception);
334 return InternalCallDeprecated(&accessor, method_name, argc, argv, exception);
337 PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) {
338 ObjectAccessorTryCatch accessor(var, exception);
339 if (accessor.has_exception())
340 return PP_MakeUndefined();
342 scoped_ptr<NPVariant[]> args;
343 if (argc) {
344 args.reset(new NPVariant[argc]);
345 for (uint32_t i = 0; i < argc; ++i) {
346 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
347 // This argument was invalid, throw an exception & give up.
348 accessor.SetException(kInvalidValueException);
349 return PP_MakeUndefined();
354 NPVariant result;
355 if (!WebBindings::construct(
356 NULL, accessor.object()->np_object(), args.get(), argc, &result)) {
357 // An exception may have been raised.
358 accessor.SetException(kUnableToConstructException);
359 return PP_MakeUndefined();
362 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
363 WebBindings::releaseVariantValue(&result);
364 return ret;
367 bool IsInstanceOfDeprecated(PP_Var var,
368 const PPP_Class_Deprecated* ppp_class,
369 void** ppp_class_data) {
370 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
371 if (!object.get())
372 return false; // Not an object at all.
374 return PluginObject::IsInstanceOf(
375 object->np_object(), ppp_class, ppp_class_data);
378 PP_Var CreateObjectDeprecated(PP_Instance pp_instance,
379 const PPP_Class_Deprecated* ppp_class,
380 void* ppp_class_data) {
381 PepperPluginInstanceImpl* instance =
382 HostGlobals::Get()->GetInstance(pp_instance);
383 if (!instance) {
384 DLOG(ERROR) << "Create object passed an invalid instance.";
385 return PP_MakeNull();
387 return PluginObject::Create(instance, ppp_class, ppp_class_data);
390 PP_Var CreateObjectWithModuleDeprecated(PP_Module pp_module,
391 const PPP_Class_Deprecated* ppp_class,
392 void* ppp_class_data) {
393 PluginModule* module = HostGlobals::Get()->GetModule(pp_module);
394 if (!module)
395 return PP_MakeNull();
396 return PluginObject::Create(
397 module->GetSomeInstance(), ppp_class, ppp_class_data);
400 } // namespace
402 // static
403 const PPB_Var_Deprecated* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
404 static const PPB_Var_Deprecated var_deprecated_interface = {
405 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
406 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
407 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
408 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
409 &HasPropertyDeprecated,
410 &HasMethodDeprecated,
411 &GetProperty,
412 &EnumerateProperties,
413 &SetPropertyDeprecated,
414 &DeletePropertyDeprecated,
415 &CallDeprecated,
416 &Construct,
417 &IsInstanceOfDeprecated,
418 &CreateObjectDeprecated,
419 &CreateObjectWithModuleDeprecated, };
421 return &var_deprecated_interface;
424 } // namespace content