blob: cbfc6f9cae0c2bb13971b459bd9aa391ee04984a [file] [log] [blame]
[email protected]99800f2a2012-07-10 23:41:401// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]aaa72e72011-07-28 16:12:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]20790a222013-07-25 02:23:055#include "content/renderer/pepper/ppb_var_deprecated_impl.h"
[email protected]aaa72e72011-07-28 16:12:046
7#include <limits>
8
[email protected]20790a222013-07-25 02:23:059#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/plugin_module.h"
14#include "content/renderer/pepper/plugin_object.h"
15#include "content/renderer/pepper/ppapi_plugin_instance_impl.h"
[email protected]aaa72e72011-07-28 16:12:0416#include "ppapi/c/dev/ppb_var_deprecated.h"
17#include "ppapi/c/ppb_var.h"
18#include "ppapi/c/pp_var.h"
[email protected]d989cce2011-12-08 04:51:1419#include "ppapi/shared_impl/ppb_var_shared.h"
[email protected]2255a9332013-06-17 05:12:3120#include "third_party/WebKit/public/web/WebBindings.h"
21#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
[email protected]aaa72e72011-07-28 16:12:0422
[email protected]ce701cd2011-08-01 21:47:0423using ppapi::NPObjectVar;
[email protected]794d83cd2011-10-20 19:09:2024using ppapi::PpapiGlobals;
[email protected]ce701cd2011-08-01 21:47:0425using ppapi::StringVar;
26using ppapi::Var;
[email protected]aaa72e72011-07-28 16:12:0427using WebKit::WebBindings;
28
29namespace webkit {
30namespace ppapi {
31
32namespace {
33
34const char kInvalidObjectException[] = "Error: Invalid object";
35const char kInvalidPropertyException[] = "Error: Invalid property";
36const char kInvalidValueException[] = "Error: Invalid value";
37const char kUnableToGetPropertyException[] = "Error: Unable to get property";
38const char kUnableToSetPropertyException[] = "Error: Unable to set property";
39const char kUnableToRemovePropertyException[] =
40 "Error: Unable to remove property";
41const char kUnableToGetAllPropertiesException[] =
42 "Error: Unable to get all properties";
43const char kUnableToCallMethodException[] = "Error: Unable to call method";
44const char kUnableToConstructException[] = "Error: Unable to construct";
45
46// ---------------------------------------------------------------------------
47// Utilities
48
49// Converts the given PP_Var to an NPVariant, returning true on success.
50// False means that the given variant is invalid. In this case, the result
51// NPVariant will be set to a void one.
52//
53// The contents of the PP_Var will NOT be copied, so you need to ensure that
54// the PP_Var remains valid while the resultant NPVariant is in use.
55bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) {
56 switch (var.type) {
57 case PP_VARTYPE_UNDEFINED:
58 VOID_TO_NPVARIANT(*result);
59 break;
60 case PP_VARTYPE_NULL:
61 NULL_TO_NPVARIANT(*result);
62 break;
63 case PP_VARTYPE_BOOL:
64 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
65 break;
66 case PP_VARTYPE_INT32:
67 INT32_TO_NPVARIANT(var.value.as_int, *result);
68 break;
69 case PP_VARTYPE_DOUBLE:
70 DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
71 break;
72 case PP_VARTYPE_STRING: {
[email protected]28cfaed02011-08-22 22:15:5873 StringVar* string = StringVar::FromPPVar(var);
[email protected]aaa72e72011-07-28 16:12:0474 if (!string) {
75 VOID_TO_NPVARIANT(*result);
76 return false;
77 }
78 const std::string& value = string->value();
79 STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
80 break;
81 }
82 case PP_VARTYPE_OBJECT: {
[email protected]ce701cd2011-08-01 21:47:0483 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
[email protected]ff875be52013-06-02 23:47:3884 if (!object.get()) {
[email protected]aaa72e72011-07-28 16:12:0485 VOID_TO_NPVARIANT(*result);
86 return false;
87 }
88 OBJECT_TO_NPVARIANT(object->np_object(), *result);
89 break;
90 }
91 default:
92 VOID_TO_NPVARIANT(*result);
93 return false;
94 }
95 return true;
96}
97
98// ObjectAccessorTryCatch ------------------------------------------------------
99
100// Automatically sets up a TryCatch for accessing the object identified by the
101// given PP_Var. The module from the object will be used for the exception
102// strings generated by the TryCatch.
103//
104// This will automatically retrieve the ObjectVar from the object and throw
105// an exception if it's invalid. At the end of construction, if there is no
106// exception, you know that there is no previously set exception, that the
107// object passed in is valid and ready to use (via the object() getter), and
108// that the TryCatch's pp_module() getter is also set up properly and ready to
109// use.
110class ObjectAccessorTryCatch : public TryCatch {
111 public:
112 ObjectAccessorTryCatch(PP_Var object, PP_Var* exception)
[email protected]872caf562011-12-07 22:50:43113 : TryCatch(exception),
[email protected]ce701cd2011-08-01 21:47:04114 object_(NPObjectVar::FromPPVar(object)) {
[email protected]ff875be52013-06-02 23:47:38115 if (!object_.get()) {
[email protected]872caf562011-12-07 22:50:43116 SetException(kInvalidObjectException);
[email protected]aaa72e72011-07-28 16:12:04117 }
118 }
119
[email protected]ce701cd2011-08-01 21:47:04120 NPObjectVar* object() { return object_.get(); }
[email protected]aaa72e72011-07-28 16:12:04121
[email protected]ef6958672013-07-24 19:19:24122 PluginInstanceImpl* GetPluginInstance() {
[email protected]2f59e382011-10-20 22:51:01123 return HostGlobals::Get()->GetInstance(object()->pp_instance());
[email protected]aaa72e72011-07-28 16:12:04124 }
125
126 protected:
[email protected]ce701cd2011-08-01 21:47:04127 scoped_refptr<NPObjectVar> object_;
[email protected]aaa72e72011-07-28 16:12:04128
129 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch);
130};
131
132// ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
133
134// Automatically sets up a TryCatch for accessing the identifier on the given
135// object. This just extends ObjectAccessorTryCatch to additionally convert
136// the given identifier to an NPIdentifier and validate it, throwing an
137// exception if it's invalid.
138//
139// At the end of construction, if there is no exception, you know that there is
140// no previously set exception, that the object passed in is valid and ready to
141// use (via the object() getter), that the identifier is valid and ready to
142// use (via the identifier() getter), and that the TryCatch's pp_module() getter
143// is also set up properly and ready to use.
144class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch {
145 public:
146 ObjectAccessorWithIdentifierTryCatch(PP_Var object,
147 PP_Var identifier,
148 PP_Var* exception)
149 : ObjectAccessorTryCatch(object, exception),
150 identifier_(0) {
151 if (!has_exception()) {
152 identifier_ = PPVarToNPIdentifier(identifier);
153 if (!identifier_)
154 SetException(kInvalidPropertyException);
155 }
156 }
157
158 NPIdentifier identifier() const { return identifier_; }
159
160 private:
161 NPIdentifier identifier_;
162
163 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
164};
165
[email protected]aaa72e72011-07-28 16:12:04166PP_Bool HasProperty(PP_Var var,
167 PP_Var name,
168 PP_Var* exception) {
169 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
170 if (accessor.has_exception())
171 return PP_FALSE;
172 return BoolToPPBool(WebBindings::hasProperty(NULL,
173 accessor.object()->np_object(),
174 accessor.identifier()));
175}
176
177bool HasPropertyDeprecated(PP_Var var,
178 PP_Var name,
179 PP_Var* exception) {
180 return PPBoolToBool(HasProperty(var, name, exception));
181}
182
183bool HasMethodDeprecated(PP_Var var,
184 PP_Var name,
185 PP_Var* exception) {
186 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
187 if (accessor.has_exception())
188 return false;
189 return WebBindings::hasMethod(NULL, accessor.object()->np_object(),
190 accessor.identifier());
191}
192
193PP_Var GetProperty(PP_Var var,
194 PP_Var name,
195 PP_Var* exception) {
196 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
197 if (accessor.has_exception())
198 return PP_MakeUndefined();
199
200 NPVariant result;
201 if (!WebBindings::getProperty(NULL, accessor.object()->np_object(),
202 accessor.identifier(), &result)) {
203 // An exception may have been raised.
204 accessor.SetException(kUnableToGetPropertyException);
205 return PP_MakeUndefined();
206 }
207
208 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
209 WebBindings::releaseVariantValue(&result);
210 return ret;
211}
212
213void EnumerateProperties(PP_Var var,
214 uint32_t* property_count,
215 PP_Var** properties,
216 PP_Var* exception) {
217 *properties = NULL;
218 *property_count = 0;
219
220 ObjectAccessorTryCatch accessor(var, exception);
221 if (accessor.has_exception())
222 return;
223
224 NPIdentifier* identifiers = NULL;
225 uint32_t count = 0;
226 if (!WebBindings::enumerate(NULL, accessor.object()->np_object(),
227 &identifiers, &count)) {
228 accessor.SetException(kUnableToGetAllPropertiesException);
229 return;
230 }
231
232 if (count == 0)
233 return;
234
235 *property_count = count;
236 *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count));
237 for (uint32_t i = 0; i < count; ++i) {
[email protected]872caf562011-12-07 22:50:43238 (*properties)[i] = NPIdentifierToPPVar(identifiers[i]);
[email protected]aaa72e72011-07-28 16:12:04239 }
240 free(identifiers);
241}
242
243void SetPropertyDeprecated(PP_Var var,
244 PP_Var name,
245 PP_Var value,
246 PP_Var* exception) {
247 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
248 if (accessor.has_exception())
249 return;
250
251 NPVariant variant;
252 if (!PPVarToNPVariantNoCopy(value, &variant)) {
253 accessor.SetException(kInvalidValueException);
254 return;
255 }
256 if (!WebBindings::setProperty(NULL, accessor.object()->np_object(),
257 accessor.identifier(), &variant))
258 accessor.SetException(kUnableToSetPropertyException);
259}
260
261void DeletePropertyDeprecated(PP_Var var,
262 PP_Var name,
263 PP_Var* exception) {
264 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
265 if (accessor.has_exception())
266 return;
267
268 if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(),
269 accessor.identifier()))
270 accessor.SetException(kUnableToRemovePropertyException);
271}
272
[email protected]99800f2a2012-07-10 23:41:40273PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor,
274 PP_Var method_name,
275 uint32_t argc,
276 PP_Var* argv,
277 PP_Var* exception) {
[email protected]aaa72e72011-07-28 16:12:04278 NPIdentifier identifier;
279 if (method_name.type == PP_VARTYPE_UNDEFINED) {
280 identifier = NULL;
281 } else if (method_name.type == PP_VARTYPE_STRING) {
282 // Specifically allow only string functions to be called.
283 identifier = PPVarToNPIdentifier(method_name);
284 if (!identifier) {
[email protected]99800f2a2012-07-10 23:41:40285 accessor->SetException(kInvalidPropertyException);
[email protected]aaa72e72011-07-28 16:12:04286 return PP_MakeUndefined();
287 }
288 } else {
[email protected]99800f2a2012-07-10 23:41:40289 accessor->SetException(kInvalidPropertyException);
[email protected]aaa72e72011-07-28 16:12:04290 return PP_MakeUndefined();
291 }
292
[email protected]9ec0f9c2013-04-07 16:10:47293 scoped_ptr<NPVariant[]> args;
[email protected]aaa72e72011-07-28 16:12:04294 if (argc) {
295 args.reset(new NPVariant[argc]);
296 for (uint32_t i = 0; i < argc; ++i) {
297 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
298 // This argument was invalid, throw an exception & give up.
[email protected]99800f2a2012-07-10 23:41:40299 accessor->SetException(kInvalidValueException);
[email protected]aaa72e72011-07-28 16:12:04300 return PP_MakeUndefined();
301 }
302 }
303 }
304
305 bool ok;
306
307 NPVariant result;
308 if (identifier) {
[email protected]99800f2a2012-07-10 23:41:40309 ok = WebBindings::invoke(NULL, accessor->object()->np_object(),
[email protected]aaa72e72011-07-28 16:12:04310 identifier, args.get(), argc, &result);
311 } else {
[email protected]99800f2a2012-07-10 23:41:40312 ok = WebBindings::invokeDefault(NULL, accessor->object()->np_object(),
[email protected]aaa72e72011-07-28 16:12:04313 args.get(), argc, &result);
314 }
315
316 if (!ok) {
317 // An exception may have been raised.
[email protected]99800f2a2012-07-10 23:41:40318 accessor->SetException(kUnableToCallMethodException);
[email protected]aaa72e72011-07-28 16:12:04319 return PP_MakeUndefined();
320 }
321
[email protected]99800f2a2012-07-10 23:41:40322 PP_Var ret = NPVariantToPPVar(accessor->GetPluginInstance(), &result);
[email protected]aaa72e72011-07-28 16:12:04323 WebBindings::releaseVariantValue(&result);
324 return ret;
325}
326
[email protected]99800f2a2012-07-10 23:41:40327PP_Var CallDeprecated(PP_Var var,
328 PP_Var method_name,
329 uint32_t argc,
330 PP_Var* argv,
331 PP_Var* exception) {
332 ObjectAccessorTryCatch accessor(var, exception);
333 if (accessor.has_exception())
334 return PP_MakeUndefined();
[email protected]ef6958672013-07-24 19:19:24335 PluginInstanceImpl* plugin = accessor.GetPluginInstance();
[email protected]99800f2a2012-07-10 23:41:40336 if (plugin && plugin->IsProcessingUserGesture()) {
[email protected]75987872013-03-18 15:29:53337 WebKit::WebScopedUserGesture user_gesture(
338 plugin->CurrentUserGestureToken());
[email protected]99800f2a2012-07-10 23:41:40339 return InternalCallDeprecated(&accessor, method_name, argc, argv,
340 exception);
341 }
342 return InternalCallDeprecated(&accessor, method_name, argc, argv, exception);
343}
344
[email protected]aaa72e72011-07-28 16:12:04345PP_Var Construct(PP_Var var,
346 uint32_t argc,
347 PP_Var* argv,
348 PP_Var* exception) {
349 ObjectAccessorTryCatch accessor(var, exception);
350 if (accessor.has_exception())
351 return PP_MakeUndefined();
352
[email protected]9ec0f9c2013-04-07 16:10:47353 scoped_ptr<NPVariant[]> args;
[email protected]aaa72e72011-07-28 16:12:04354 if (argc) {
355 args.reset(new NPVariant[argc]);
356 for (uint32_t i = 0; i < argc; ++i) {
357 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
358 // This argument was invalid, throw an exception & give up.
359 accessor.SetException(kInvalidValueException);
360 return PP_MakeUndefined();
361 }
362 }
363 }
364
365 NPVariant result;
366 if (!WebBindings::construct(NULL, accessor.object()->np_object(),
367 args.get(), argc, &result)) {
368 // An exception may have been raised.
369 accessor.SetException(kUnableToConstructException);
370 return PP_MakeUndefined();
371 }
372
373 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
374 WebBindings::releaseVariantValue(&result);
375 return ret;
376}
377
378bool IsInstanceOfDeprecated(PP_Var var,
379 const PPP_Class_Deprecated* ppp_class,
380 void** ppp_class_data) {
[email protected]ce701cd2011-08-01 21:47:04381 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
[email protected]ff875be52013-06-02 23:47:38382 if (!object.get())
[email protected]aaa72e72011-07-28 16:12:04383 return false; // Not an object at all.
384
385 return PluginObject::IsInstanceOf(object->np_object(),
386 ppp_class, ppp_class_data);
387}
388
[email protected]794d83cd2011-10-20 19:09:20389PP_Var CreateObjectDeprecated(PP_Instance pp_instance,
[email protected]aaa72e72011-07-28 16:12:04390 const PPP_Class_Deprecated* ppp_class,
391 void* ppp_class_data) {
[email protected]ef6958672013-07-24 19:19:24392 PluginInstanceImpl* instance = HostGlobals::Get()->GetInstance(pp_instance);
[email protected]aaa72e72011-07-28 16:12:04393 if (!instance) {
394 DLOG(ERROR) << "Create object passed an invalid instance.";
395 return PP_MakeNull();
396 }
397 return PluginObject::Create(instance, ppp_class, ppp_class_data);
398}
399
[email protected]794d83cd2011-10-20 19:09:20400PP_Var CreateObjectWithModuleDeprecated(PP_Module pp_module,
[email protected]aaa72e72011-07-28 16:12:04401 const PPP_Class_Deprecated* ppp_class,
402 void* ppp_class_data) {
[email protected]2f59e382011-10-20 22:51:01403 PluginModule* module = HostGlobals::Get()->GetModule(pp_module);
[email protected]aaa72e72011-07-28 16:12:04404 if (!module)
405 return PP_MakeNull();
406 return PluginObject::Create(module->GetSomeInstance(),
407 ppp_class, ppp_class_data);
408}
409
[email protected]aaa72e72011-07-28 16:12:04410} // namespace
411
412// static
[email protected]872caf562011-12-07 22:50:43413const PPB_Var_Deprecated* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
414 static const PPB_Var_Deprecated var_deprecated_interface = {
[email protected]d989cce2011-12-08 04:51:14415 ::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,
[email protected]872caf562011-12-07 22:50:43419 &HasPropertyDeprecated,
420 &HasMethodDeprecated,
421 &GetProperty,
422 &EnumerateProperties,
423 &SetPropertyDeprecated,
424 &DeletePropertyDeprecated,
425 &CallDeprecated,
426 &Construct,
427 &IsInstanceOfDeprecated,
428 &CreateObjectDeprecated,
429 &CreateObjectWithModuleDeprecated,
430 };
[email protected]aaa72e72011-07-28 16:12:04431
[email protected]aaa72e72011-07-28 16:12:04432 return &var_deprecated_interface;
433}
434
435} // namespace ppapi
436} // namespace webkit
437