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/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
;
26 using blink::WebBindings
;
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 // ---------------------------------------------------------------------------
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
) {
55 case PP_VARTYPE_UNDEFINED
:
56 VOID_TO_NPVARIANT(*result
);
59 NULL_TO_NPVARIANT(*result
);
62 BOOLEAN_TO_NPVARIANT(var
.value
.as_bool
, *result
);
64 case PP_VARTYPE_INT32
:
65 INT32_TO_NPVARIANT(var
.value
.as_int
, *result
);
67 case PP_VARTYPE_DOUBLE
:
68 DOUBLE_TO_NPVARIANT(var
.value
.as_double
, *result
);
70 case PP_VARTYPE_STRING
: {
71 StringVar
* string
= StringVar::FromPPVar(var
);
73 VOID_TO_NPVARIANT(*result
);
76 const std::string
& value
= string
->value();
77 STRINGN_TO_NPVARIANT(value
.c_str(), value
.size(), *result
);
80 case PP_VARTYPE_OBJECT
: {
81 scoped_refptr
<NPObjectVar
> object(NPObjectVar::FromPPVar(var
));
83 VOID_TO_NPVARIANT(*result
);
86 OBJECT_TO_NPVARIANT(object
->np_object(), *result
);
90 VOID_TO_NPVARIANT(*result
);
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
108 class ObjectAccessorTryCatch
: public TryCatch
{
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());
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
{
143 ObjectAccessorWithIdentifierTryCatch(PP_Var object
,
146 : ObjectAccessorTryCatch(object
, exception
), identifier_(0) {
147 if (!has_exception()) {
148 identifier_
= PPVarToNPIdentifier(identifier
);
150 SetException(kInvalidPropertyException
);
154 NPIdentifier
identifier() const { return identifier_
; }
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())
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())
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();
188 if (!WebBindings::getProperty(NULL
,
189 accessor
.object()->np_object(),
190 accessor
.identifier(),
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
);
202 void EnumerateProperties(PP_Var var
,
203 uint32_t* property_count
,
209 ObjectAccessorTryCatch
accessor(var
, exception
);
210 if (accessor
.has_exception())
213 NPIdentifier
* identifiers
= NULL
;
215 if (!WebBindings::enumerate(
216 NULL
, accessor
.object()->np_object(), &identifiers
, &count
)) {
217 accessor
.SetException(kUnableToGetAllPropertiesException
);
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
]);
232 void SetPropertyDeprecated(PP_Var var
,
236 ObjectAccessorWithIdentifierTryCatch
accessor(var
, name
, exception
);
237 if (accessor
.has_exception())
241 if (!PPVarToNPVariantNoCopy(value
, &variant
)) {
242 accessor
.SetException(kInvalidValueException
);
245 if (!WebBindings::setProperty(NULL
,
246 accessor
.object()->np_object(),
247 accessor
.identifier(),
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())
257 if (!WebBindings::removeProperty(
258 NULL
, accessor
.object()->np_object(), accessor
.identifier()))
259 accessor
.SetException(kUnableToRemovePropertyException
);
262 PP_Var
InternalCallDeprecated(ObjectAccessorTryCatch
* accessor
,
267 NPIdentifier identifier
;
268 if (method_name
.type
== PP_VARTYPE_UNDEFINED
) {
270 } else if (method_name
.type
== PP_VARTYPE_STRING
) {
271 // Specifically allow only string functions to be called.
272 identifier
= PPVarToNPIdentifier(method_name
);
274 accessor
->SetException(kInvalidPropertyException
);
275 return PP_MakeUndefined();
278 accessor
->SetException(kInvalidPropertyException
);
279 return PP_MakeUndefined();
282 scoped_ptr
<NPVariant
[]> args
;
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();
298 ok
= WebBindings::invoke(NULL
,
299 accessor
->object()->np_object(),
305 ok
= WebBindings::invokeDefault(
306 NULL
, accessor
->object()->np_object(), args
.get(), argc
, &result
);
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
);
320 PP_Var
CallDeprecated(PP_Var var
,
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
;
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();
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
);
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
));
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
);
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
);
395 return PP_MakeNull();
396 return PluginObject::Create(
397 module
->GetSomeInstance(), ppp_class
, ppp_class_data
);
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
,
412 &EnumerateProperties
,
413 &SetPropertyDeprecated
,
414 &DeletePropertyDeprecated
,
417 &IsInstanceOfDeprecated
,
418 &CreateObjectDeprecated
,
419 &CreateObjectWithModuleDeprecated
, };
421 return &var_deprecated_interface
;
424 } // namespace content