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"
9 #include "content/renderer/pepper/common.h"
10 #include "content/renderer/pepper/host_globals.h"
11 #include "content/renderer/pepper/npapi_glue.h"
12 #include "content/renderer/pepper/npobject_var.h"
13 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14 #include "content/renderer/pepper/plugin_module.h"
15 #include "content/renderer/pepper/plugin_object.h"
16 #include "ppapi/c/dev/ppb_var_deprecated.h"
17 #include "ppapi/c/ppb_var.h"
18 #include "ppapi/c/pp_var.h"
19 #include "ppapi/shared_impl/ppb_var_shared.h"
20 #include "third_party/WebKit/public/web/WebBindings.h"
21 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
23 using ppapi::NPObjectVar
;
24 using ppapi::PpapiGlobals
;
25 using ppapi::StringVar
;
27 using WebKit::WebBindings
;
33 const char kInvalidObjectException
[] = "Error: Invalid object";
34 const char kInvalidPropertyException
[] = "Error: Invalid property";
35 const char kInvalidValueException
[] = "Error: Invalid value";
36 const char kUnableToGetPropertyException
[] = "Error: Unable to get property";
37 const char kUnableToSetPropertyException
[] = "Error: Unable to set property";
38 const char kUnableToRemovePropertyException
[] =
39 "Error: Unable to remove property";
40 const char kUnableToGetAllPropertiesException
[] =
41 "Error: Unable to get all properties";
42 const char kUnableToCallMethodException
[] = "Error: Unable to call method";
43 const char kUnableToConstructException
[] = "Error: Unable to construct";
45 // ---------------------------------------------------------------------------
48 // Converts the given PP_Var to an NPVariant, returning true on success.
49 // False means that the given variant is invalid. In this case, the result
50 // NPVariant will be set to a void one.
52 // The contents of the PP_Var will NOT be copied, so you need to ensure that
53 // the PP_Var remains valid while the resultant NPVariant is in use.
54 bool PPVarToNPVariantNoCopy(PP_Var var
, NPVariant
* result
) {
56 case PP_VARTYPE_UNDEFINED
:
57 VOID_TO_NPVARIANT(*result
);
60 NULL_TO_NPVARIANT(*result
);
63 BOOLEAN_TO_NPVARIANT(var
.value
.as_bool
, *result
);
65 case PP_VARTYPE_INT32
:
66 INT32_TO_NPVARIANT(var
.value
.as_int
, *result
);
68 case PP_VARTYPE_DOUBLE
:
69 DOUBLE_TO_NPVARIANT(var
.value
.as_double
, *result
);
71 case PP_VARTYPE_STRING
: {
72 StringVar
* string
= StringVar::FromPPVar(var
);
74 VOID_TO_NPVARIANT(*result
);
77 const std::string
& value
= string
->value();
78 STRINGN_TO_NPVARIANT(value
.c_str(), value
.size(), *result
);
81 case PP_VARTYPE_OBJECT
: {
82 scoped_refptr
<NPObjectVar
> object(NPObjectVar::FromPPVar(var
));
84 VOID_TO_NPVARIANT(*result
);
87 OBJECT_TO_NPVARIANT(object
->np_object(), *result
);
91 VOID_TO_NPVARIANT(*result
);
97 // ObjectAccessorTryCatch ------------------------------------------------------
99 // Automatically sets up a TryCatch for accessing the object identified by the
100 // given PP_Var. The module from the object will be used for the exception
101 // strings generated by the TryCatch.
103 // This will automatically retrieve the ObjectVar from the object and throw
104 // an exception if it's invalid. At the end of construction, if there is no
105 // exception, you know that there is no previously set exception, that the
106 // object passed in is valid and ready to use (via the object() getter), and
107 // that the TryCatch's pp_module() getter is also set up properly and ready to
109 class ObjectAccessorTryCatch
: public TryCatch
{
111 ObjectAccessorTryCatch(PP_Var object
, PP_Var
* exception
)
112 : TryCatch(exception
),
113 object_(NPObjectVar::FromPPVar(object
)) {
114 if (!object_
.get()) {
115 SetException(kInvalidObjectException
);
119 NPObjectVar
* object() { return object_
.get(); }
121 PepperPluginInstanceImpl
* GetPluginInstance() {
122 return HostGlobals::Get()->GetInstance(object()->pp_instance());
126 scoped_refptr
<NPObjectVar
> object_
;
128 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch
);
131 // ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
133 // Automatically sets up a TryCatch for accessing the identifier on the given
134 // object. This just extends ObjectAccessorTryCatch to additionally convert
135 // the given identifier to an NPIdentifier and validate it, throwing an
136 // exception if it's invalid.
138 // At the end of construction, if there is no exception, you know that there is
139 // no previously set exception, that the object passed in is valid and ready to
140 // use (via the object() getter), that the identifier is valid and ready to
141 // use (via the identifier() getter), and that the TryCatch's pp_module() getter
142 // is also set up properly and ready to use.
143 class ObjectAccessorWithIdentifierTryCatch
: public ObjectAccessorTryCatch
{
145 ObjectAccessorWithIdentifierTryCatch(PP_Var object
,
148 : ObjectAccessorTryCatch(object
, exception
),
150 if (!has_exception()) {
151 identifier_
= PPVarToNPIdentifier(identifier
);
153 SetException(kInvalidPropertyException
);
157 NPIdentifier
identifier() const { return identifier_
; }
160 NPIdentifier identifier_
;
162 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch
);
165 PP_Bool
HasProperty(PP_Var var
,
168 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
169 if (accessor
.has_exception())
171 return BoolToPPBool(WebBindings::hasProperty(NULL
,
172 accessor
.object()->np_object(),
173 accessor
.identifier()));
176 bool HasPropertyDeprecated(PP_Var var
,
179 return PPBoolToBool(HasProperty(var
, name
, exception
));
182 bool HasMethodDeprecated(PP_Var var
,
185 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
186 if (accessor
.has_exception())
188 return WebBindings::hasMethod(NULL
, accessor
.object()->np_object(),
189 accessor
.identifier());
192 PP_Var
GetProperty(PP_Var var
,
195 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
196 if (accessor
.has_exception())
197 return PP_MakeUndefined();
200 if (!WebBindings::getProperty(NULL
, accessor
.object()->np_object(),
201 accessor
.identifier(), &result
)) {
202 // An exception may have been raised.
203 accessor
.SetException(kUnableToGetPropertyException
);
204 return PP_MakeUndefined();
207 PP_Var ret
= NPVariantToPPVar(accessor
.GetPluginInstance(), &result
);
208 WebBindings::releaseVariantValue(&result
);
212 void EnumerateProperties(PP_Var var
,
213 uint32_t* property_count
,
219 ObjectAccessorTryCatch
accessor(var
, exception
);
220 if (accessor
.has_exception())
223 NPIdentifier
* identifiers
= NULL
;
225 if (!WebBindings::enumerate(NULL
, accessor
.object()->np_object(),
226 &identifiers
, &count
)) {
227 accessor
.SetException(kUnableToGetAllPropertiesException
);
234 *property_count
= count
;
235 *properties
= static_cast<PP_Var
*>(malloc(sizeof(PP_Var
) * count
));
236 for (uint32_t i
= 0; i
< count
; ++i
) {
237 (*properties
)[i
] = NPIdentifierToPPVar(identifiers
[i
]);
242 void SetPropertyDeprecated(PP_Var var
,
246 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
247 if (accessor
.has_exception())
251 if (!PPVarToNPVariantNoCopy(value
, &variant
)) {
252 accessor
.SetException(kInvalidValueException
);
255 if (!WebBindings::setProperty(NULL
, accessor
.object()->np_object(),
256 accessor
.identifier(), &variant
))
257 accessor
.SetException(kUnableToSetPropertyException
);
260 void DeletePropertyDeprecated(PP_Var var
,
263 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
264 if (accessor
.has_exception())
267 if (!WebBindings::removeProperty(NULL
, accessor
.object()->np_object(),
268 accessor
.identifier()))
269 accessor
.SetException(kUnableToRemovePropertyException
);
272 PP_Var
InternalCallDeprecated(ObjectAccessorTryCatch
* accessor
,
277 NPIdentifier identifier
;
278 if (method_name
.type
== PP_VARTYPE_UNDEFINED
) {
280 } else if (method_name
.type
== PP_VARTYPE_STRING
) {
281 // Specifically allow only string functions to be called.
282 identifier
= PPVarToNPIdentifier(method_name
);
284 accessor
->SetException(kInvalidPropertyException
);
285 return PP_MakeUndefined();
288 accessor
->SetException(kInvalidPropertyException
);
289 return PP_MakeUndefined();
292 scoped_ptr
<NPVariant
[]> args
;
294 args
.reset(new NPVariant
[argc
]);
295 for (uint32_t i
= 0; i
< argc
; ++i
) {
296 if (!PPVarToNPVariantNoCopy(argv
[i
], &args
[i
])) {
297 // This argument was invalid, throw an exception & give up.
298 accessor
->SetException(kInvalidValueException
);
299 return PP_MakeUndefined();
308 ok
= WebBindings::invoke(NULL
, accessor
->object()->np_object(),
309 identifier
, args
.get(), argc
, &result
);
311 ok
= WebBindings::invokeDefault(NULL
, accessor
->object()->np_object(),
312 args
.get(), argc
, &result
);
316 // An exception may have been raised.
317 accessor
->SetException(kUnableToCallMethodException
);
318 return PP_MakeUndefined();
321 PP_Var ret
= NPVariantToPPVar(accessor
->GetPluginInstance(), &result
);
322 WebBindings::releaseVariantValue(&result
);
326 PP_Var
CallDeprecated(PP_Var var
,
331 ObjectAccessorTryCatch
accessor(var
, exception
);
332 if (accessor
.has_exception())
333 return PP_MakeUndefined();
334 PepperPluginInstanceImpl
* plugin
= accessor
.GetPluginInstance();
335 if (plugin
&& plugin
->IsProcessingUserGesture()) {
336 WebKit::WebScopedUserGesture
user_gesture(
337 plugin
->CurrentUserGestureToken());
338 return InternalCallDeprecated(&accessor
, method_name
, argc
, argv
,
341 return InternalCallDeprecated(&accessor
, method_name
, argc
, argv
, exception
);
344 PP_Var
Construct(PP_Var var
,
348 ObjectAccessorTryCatch
accessor(var
, exception
);
349 if (accessor
.has_exception())
350 return PP_MakeUndefined();
352 scoped_ptr
<NPVariant
[]> args
;
354 args
.reset(new NPVariant
[argc
]);
355 for (uint32_t i
= 0; i
< argc
; ++i
) {
356 if (!PPVarToNPVariantNoCopy(argv
[i
], &args
[i
])) {
357 // This argument was invalid, throw an exception & give up.
358 accessor
.SetException(kInvalidValueException
);
359 return PP_MakeUndefined();
365 if (!WebBindings::construct(NULL
, accessor
.object()->np_object(),
366 args
.get(), argc
, &result
)) {
367 // An exception may have been raised.
368 accessor
.SetException(kUnableToConstructException
);
369 return PP_MakeUndefined();
372 PP_Var ret
= NPVariantToPPVar(accessor
.GetPluginInstance(), &result
);
373 WebBindings::releaseVariantValue(&result
);
377 bool IsInstanceOfDeprecated(PP_Var var
,
378 const PPP_Class_Deprecated
* ppp_class
,
379 void** ppp_class_data
) {
380 scoped_refptr
<NPObjectVar
> object(NPObjectVar::FromPPVar(var
));
382 return false; // Not an object at all.
384 return PluginObject::IsInstanceOf(object
->np_object(),
385 ppp_class
, ppp_class_data
);
388 PP_Var
CreateObjectDeprecated(PP_Instance pp_instance
,
389 const PPP_Class_Deprecated
* ppp_class
,
390 void* ppp_class_data
) {
391 PepperPluginInstanceImpl
* instance
=
392 HostGlobals::Get()->GetInstance(pp_instance
);
394 DLOG(ERROR
) << "Create object passed an invalid instance.";
395 return PP_MakeNull();
397 return PluginObject::Create(instance
, ppp_class
, ppp_class_data
);
400 PP_Var
CreateObjectWithModuleDeprecated(PP_Module pp_module
,
401 const PPP_Class_Deprecated
* ppp_class
,
402 void* ppp_class_data
) {
403 PluginModule
* module
= HostGlobals::Get()->GetModule(pp_module
);
405 return PP_MakeNull();
406 return PluginObject::Create(module
->GetSomeInstance(),
407 ppp_class
, ppp_class_data
);
413 const PPB_Var_Deprecated
* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
414 static const PPB_Var_Deprecated var_deprecated_interface
= {
415 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef
,
416 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release
,
417 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8
,
418 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8
,
419 &HasPropertyDeprecated
,
420 &HasMethodDeprecated
,
422 &EnumerateProperties
,
423 &SetPropertyDeprecated
,
424 &DeletePropertyDeprecated
,
427 &IsInstanceOfDeprecated
,
428 &CreateObjectDeprecated
,
429 &CreateObjectWithModuleDeprecated
,
432 return &var_deprecated_interface
;
435 } // namespace content