Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / renderer / pepper / ppb_var_deprecated_impl.cc
blob23472fac26cc431bfaab7ad7738166f593385e6d
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/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;
26 using ppapi::Var;
27 using WebKit::WebBindings;
29 namespace content {
31 namespace {
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 // ---------------------------------------------------------------------------
46 // Utilities
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) {
55 switch (var.type) {
56 case PP_VARTYPE_UNDEFINED:
57 VOID_TO_NPVARIANT(*result);
58 break;
59 case PP_VARTYPE_NULL:
60 NULL_TO_NPVARIANT(*result);
61 break;
62 case PP_VARTYPE_BOOL:
63 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
64 break;
65 case PP_VARTYPE_INT32:
66 INT32_TO_NPVARIANT(var.value.as_int, *result);
67 break;
68 case PP_VARTYPE_DOUBLE:
69 DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
70 break;
71 case PP_VARTYPE_STRING: {
72 StringVar* string = StringVar::FromPPVar(var);
73 if (!string) {
74 VOID_TO_NPVARIANT(*result);
75 return false;
77 const std::string& value = string->value();
78 STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
79 break;
81 case PP_VARTYPE_OBJECT: {
82 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
83 if (!object.get()) {
84 VOID_TO_NPVARIANT(*result);
85 return false;
87 OBJECT_TO_NPVARIANT(object->np_object(), *result);
88 break;
90 default:
91 VOID_TO_NPVARIANT(*result);
92 return false;
94 return true;
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
108 // use.
109 class ObjectAccessorTryCatch : public TryCatch {
110 public:
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());
125 protected:
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 {
144 public:
145 ObjectAccessorWithIdentifierTryCatch(PP_Var object,
146 PP_Var identifier,
147 PP_Var* exception)
148 : ObjectAccessorTryCatch(object, exception),
149 identifier_(0) {
150 if (!has_exception()) {
151 identifier_ = PPVarToNPIdentifier(identifier);
152 if (!identifier_)
153 SetException(kInvalidPropertyException);
157 NPIdentifier identifier() const { return identifier_; }
159 private:
160 NPIdentifier identifier_;
162 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
165 PP_Bool HasProperty(PP_Var var,
166 PP_Var name,
167 PP_Var* exception) {
168 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
169 if (accessor.has_exception())
170 return PP_FALSE;
171 return BoolToPPBool(WebBindings::hasProperty(NULL,
172 accessor.object()->np_object(),
173 accessor.identifier()));
176 bool HasPropertyDeprecated(PP_Var var,
177 PP_Var name,
178 PP_Var* exception) {
179 return PPBoolToBool(HasProperty(var, name, exception));
182 bool HasMethodDeprecated(PP_Var var,
183 PP_Var name,
184 PP_Var* exception) {
185 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
186 if (accessor.has_exception())
187 return false;
188 return WebBindings::hasMethod(NULL, accessor.object()->np_object(),
189 accessor.identifier());
192 PP_Var GetProperty(PP_Var var,
193 PP_Var name,
194 PP_Var* exception) {
195 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
196 if (accessor.has_exception())
197 return PP_MakeUndefined();
199 NPVariant result;
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);
209 return ret;
212 void EnumerateProperties(PP_Var var,
213 uint32_t* property_count,
214 PP_Var** properties,
215 PP_Var* exception) {
216 *properties = NULL;
217 *property_count = 0;
219 ObjectAccessorTryCatch accessor(var, exception);
220 if (accessor.has_exception())
221 return;
223 NPIdentifier* identifiers = NULL;
224 uint32_t count = 0;
225 if (!WebBindings::enumerate(NULL, accessor.object()->np_object(),
226 &identifiers, &count)) {
227 accessor.SetException(kUnableToGetAllPropertiesException);
228 return;
231 if (count == 0)
232 return;
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]);
239 free(identifiers);
242 void SetPropertyDeprecated(PP_Var var,
243 PP_Var name,
244 PP_Var value,
245 PP_Var* exception) {
246 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
247 if (accessor.has_exception())
248 return;
250 NPVariant variant;
251 if (!PPVarToNPVariantNoCopy(value, &variant)) {
252 accessor.SetException(kInvalidValueException);
253 return;
255 if (!WebBindings::setProperty(NULL, accessor.object()->np_object(),
256 accessor.identifier(), &variant))
257 accessor.SetException(kUnableToSetPropertyException);
260 void DeletePropertyDeprecated(PP_Var var,
261 PP_Var name,
262 PP_Var* exception) {
263 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
264 if (accessor.has_exception())
265 return;
267 if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(),
268 accessor.identifier()))
269 accessor.SetException(kUnableToRemovePropertyException);
272 PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor,
273 PP_Var method_name,
274 uint32_t argc,
275 PP_Var* argv,
276 PP_Var* exception) {
277 NPIdentifier identifier;
278 if (method_name.type == PP_VARTYPE_UNDEFINED) {
279 identifier = NULL;
280 } else if (method_name.type == PP_VARTYPE_STRING) {
281 // Specifically allow only string functions to be called.
282 identifier = PPVarToNPIdentifier(method_name);
283 if (!identifier) {
284 accessor->SetException(kInvalidPropertyException);
285 return PP_MakeUndefined();
287 } else {
288 accessor->SetException(kInvalidPropertyException);
289 return PP_MakeUndefined();
292 scoped_ptr<NPVariant[]> args;
293 if (argc) {
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();
304 bool ok;
306 NPVariant result;
307 if (identifier) {
308 ok = WebBindings::invoke(NULL, accessor->object()->np_object(),
309 identifier, args.get(), argc, &result);
310 } else {
311 ok = WebBindings::invokeDefault(NULL, accessor->object()->np_object(),
312 args.get(), argc, &result);
315 if (!ok) {
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);
323 return ret;
326 PP_Var CallDeprecated(PP_Var var,
327 PP_Var method_name,
328 uint32_t argc,
329 PP_Var* argv,
330 PP_Var* exception) {
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,
339 exception);
341 return InternalCallDeprecated(&accessor, method_name, argc, argv, exception);
344 PP_Var Construct(PP_Var var,
345 uint32_t argc,
346 PP_Var* argv,
347 PP_Var* exception) {
348 ObjectAccessorTryCatch accessor(var, exception);
349 if (accessor.has_exception())
350 return PP_MakeUndefined();
352 scoped_ptr<NPVariant[]> args;
353 if (argc) {
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();
364 NPVariant result;
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);
374 return ret;
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));
381 if (!object.get())
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);
393 if (!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);
404 if (!module)
405 return PP_MakeNull();
406 return PluginObject::Create(module->GetSomeInstance(),
407 ppp_class, ppp_class_data);
410 } // namespace
412 // static
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,
421 &GetProperty,
422 &EnumerateProperties,
423 &SetPropertyDeprecated,
424 &DeletePropertyDeprecated,
425 &CallDeprecated,
426 &Construct,
427 &IsInstanceOfDeprecated,
428 &CreateObjectDeprecated,
429 &CreateObjectWithModuleDeprecated,
432 return &var_deprecated_interface;
435 } // namespace content