blob: 7426ca4db90134cc5497c5673055ab4c06b3b4b9 [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
avi1023d012015-12-25 02:39:147#include <stddef.h>
8#include <stdint.h>
9
[email protected]aaa72e72011-07-28 16:12:0410#include <limits>
11
[email protected]20790a222013-07-25 02:23:0512#include "content/renderer/pepper/host_globals.h"
raymes2515b7d2014-09-04 23:01:2913#include "content/renderer/pepper/message_channel.h"
[email protected]adab2332013-07-25 18:04:3214#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
raymes2515b7d2014-09-04 23:01:2915#include "content/renderer/pepper/pepper_try_catch.h"
[email protected]20790a222013-07-25 02:23:0516#include "content/renderer/pepper/plugin_module.h"
17#include "content/renderer/pepper/plugin_object.h"
raymes2515b7d2014-09-04 23:01:2918#include "content/renderer/pepper/v8object_var.h"
[email protected]aaa72e72011-07-28 16:12:0419#include "ppapi/c/dev/ppb_var_deprecated.h"
20#include "ppapi/c/ppb_var.h"
[email protected]d989cce2011-12-08 04:51:1421#include "ppapi/shared_impl/ppb_var_shared.h"
raymes2515b7d2014-09-04 23:01:2922#include "third_party/WebKit/public/web/WebDocument.h"
23#include "third_party/WebKit/public/web/WebElement.h"
24#include "third_party/WebKit/public/web/WebLocalFrame.h"
25#include "third_party/WebKit/public/web/WebPluginContainer.h"
dcheng16be73c2015-06-11 22:02:4126#include "third_party/WebKit/public/web/WebPluginScriptForbiddenScope.h"
[email protected]2255a9332013-06-17 05:12:3127#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
[email protected]aaa72e72011-07-28 16:12:0428
raymes2515b7d2014-09-04 23:01:2929using ppapi::V8ObjectVar;
[email protected]794d83cd2011-10-20 19:09:2030using ppapi::PpapiGlobals;
raymes2515b7d2014-09-04 23:01:2931using ppapi::ScopedPPVar;
32using ppapi::ScopedPPVarArray;
[email protected]ce701cd2011-08-01 21:47:0433using ppapi::StringVar;
34using ppapi::Var;
[email protected]aaa72e72011-07-28 16:12:0435
[email protected]adab2332013-07-25 18:04:3236namespace content {
[email protected]aaa72e72011-07-28 16:12:0437
38namespace {
39
raymes2515b7d2014-09-04 23:01:2940const char kInvalidIdentifierException[] = "Error: Invalid identifier.";
[email protected]aaa72e72011-07-28 16:12:0441const char kInvalidObjectException[] = "Error: Invalid object";
[email protected]aaa72e72011-07-28 16:12:0442const char kUnableToCallMethodException[] = "Error: Unable to call method";
[email protected]aaa72e72011-07-28 16:12:0443
raymes2515b7d2014-09-04 23:01:2944class ObjectAccessor {
45 public:
46 ObjectAccessor(PP_Var var)
Daniel Cheng99adf742014-09-05 06:26:5047 : object_var_(V8ObjectVar::FromPPVar(var).get()),
raymes2515b7d2014-09-04 23:01:2948 instance_(object_var_ ? object_var_->instance() : NULL) {
dmichaele17054722014-10-10 20:03:1949 if (instance_) {
50 converter_.reset(new V8VarConverter(instance_->pp_instance(),
51 V8VarConverter::kAllowObjectVars));
52 }
raymes2515b7d2014-09-04 23:01:2953 }
[email protected]aaa72e72011-07-28 16:12:0454
raymes2515b7d2014-09-04 23:01:2955 // Check if the object is valid. If it isn't, set an exception and return
56 // false.
57 bool IsValid(PP_Var* exception) {
58 // If we already have an exception, then the call is invalid according to
59 // the unittests.
60 if (exception && exception->type != PP_VARTYPE_UNDEFINED)
[email protected]aaa72e72011-07-28 16:12:0461 return false;
raymes2515b7d2014-09-04 23:01:2962 if (instance_)
dcheng16be73c2015-06-11 22:02:4163 return !instance_->is_deleted() ||
64 !blink::WebPluginScriptForbiddenScope::isForbidden();
raymes2515b7d2014-09-04 23:01:2965 if (exception)
66 *exception = ppapi::StringVar::StringToPPVar(kInvalidObjectException);
67 return false;
[email protected]aaa72e72011-07-28 16:12:0468 }
raymes2515b7d2014-09-04 23:01:2969 // Lazily grab the object so that the handle is created in the current handle
70 // scope.
deepak.s750d68f2015-04-30 07:32:4171 v8::Local<v8::Object> GetObject() { return object_var_->GetHandle(); }
raymes2515b7d2014-09-04 23:01:2972 PepperPluginInstanceImpl* instance() { return instance_; }
dmichaele17054722014-10-10 20:03:1973 V8VarConverter* converter() { return converter_.get(); }
raymesdc463a92014-09-03 05:51:0474
75 private:
raymes2515b7d2014-09-04 23:01:2976 V8ObjectVar* object_var_;
77 PepperPluginInstanceImpl* instance_;
dmichaele17054722014-10-10 20:03:1978 scoped_ptr<V8VarConverter> converter_;
raymesdc463a92014-09-03 05:51:0479};
80
raymes2515b7d2014-09-04 23:01:2981bool IsValidIdentifer(PP_Var identifier, PP_Var* exception) {
82 if (identifier.type == PP_VARTYPE_INT32 ||
83 identifier.type == PP_VARTYPE_STRING) {
84 return true;
85 }
86 if (exception)
87 *exception = ppapi::StringVar::StringToPPVar(kInvalidIdentifierException);
88 return false;
[email protected]aaa72e72011-07-28 16:12:0489}
90
[email protected]ad63b5c2014-04-11 21:12:3691bool HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:2992 ObjectAccessor accessor(var);
93 if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
94 return false;
95
dmichaele17054722014-10-10 20:03:1996 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
97 exception);
deepak.s750d68f2015-04-30 07:32:4198 v8::Local<v8::Value> v8_name = try_catch.ToV8(name);
raymes2515b7d2014-09-04 23:01:2999 if (try_catch.HasException())
100 return false;
101
102 bool result = accessor.GetObject()->Has(v8_name);
103 if (try_catch.HasException())
104 return false;
105 return result;
[email protected]aaa72e72011-07-28 16:12:04106}
107
[email protected]ad63b5c2014-04-11 21:12:36108bool HasMethodDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29109 ObjectAccessor accessor(var);
110 if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
[email protected]aaa72e72011-07-28 16:12:04111 return false;
raymes2515b7d2014-09-04 23:01:29112
dmichaele17054722014-10-10 20:03:19113 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
114 exception);
deepak.s750d68f2015-04-30 07:32:41115 v8::Local<v8::Value> v8_name = try_catch.ToV8(name);
raymes2515b7d2014-09-04 23:01:29116 if (try_catch.HasException())
117 return false;
118
119 bool result = accessor.GetObject()->Has(v8_name) &&
120 accessor.GetObject()->Get(v8_name)->IsFunction();
121 if (try_catch.HasException())
122 return false;
123 return result;
[email protected]aaa72e72011-07-28 16:12:04124}
125
[email protected]ad63b5c2014-04-11 21:12:36126PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29127 ObjectAccessor accessor(var);
128 if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
[email protected]aaa72e72011-07-28 16:12:04129 return PP_MakeUndefined();
130
dmichaele17054722014-10-10 20:03:19131 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
132 exception);
deepak.s750d68f2015-04-30 07:32:41133 v8::Local<v8::Value> v8_name = try_catch.ToV8(name);
raymes2515b7d2014-09-04 23:01:29134 if (try_catch.HasException())
[email protected]aaa72e72011-07-28 16:12:04135 return PP_MakeUndefined();
[email protected]aaa72e72011-07-28 16:12:04136
raymes2515b7d2014-09-04 23:01:29137 ScopedPPVar result_var = try_catch.FromV8(accessor.GetObject()->Get(v8_name));
138 if (try_catch.HasException())
139 return PP_MakeUndefined();
140
141 return result_var.Release();
[email protected]aaa72e72011-07-28 16:12:04142}
143
144void EnumerateProperties(PP_Var var,
145 uint32_t* property_count,
146 PP_Var** properties,
147 PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29148 ObjectAccessor accessor(var);
149 if (!accessor.IsValid(exception))
150 return;
151
dmichaele17054722014-10-10 20:03:19152 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
153 exception);
raymes2515b7d2014-09-04 23:01:29154
[email protected]aaa72e72011-07-28 16:12:04155 *properties = NULL;
156 *property_count = 0;
157
raymes2515b7d2014-09-04 23:01:29158 v8::Local<v8::Array> identifiers = accessor.GetObject()->GetPropertyNames();
159 if (try_catch.HasException())
[email protected]aaa72e72011-07-28 16:12:04160 return;
raymes2515b7d2014-09-04 23:01:29161 ScopedPPVarArray identifier_vars(identifiers->Length());
162 for (uint32_t i = 0; i < identifiers->Length(); ++i) {
163 ScopedPPVar var = try_catch.FromV8(identifiers->Get(i));
164 if (try_catch.HasException())
165 return;
166 identifier_vars.Set(i, var);
[email protected]aaa72e72011-07-28 16:12:04167 }
168
raymes2515b7d2014-09-04 23:01:29169 size_t size = identifier_vars.size();
170 *properties = identifier_vars.Release(
171 ScopedPPVarArray::PassPPBMemoryAllocatedArray());
172 *property_count = size;
[email protected]aaa72e72011-07-28 16:12:04173}
174
175void SetPropertyDeprecated(PP_Var var,
176 PP_Var name,
177 PP_Var value,
178 PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29179 ObjectAccessor accessor(var);
180 if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
[email protected]aaa72e72011-07-28 16:12:04181 return;
182
dmichaele17054722014-10-10 20:03:19183 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
184 exception);
deepak.s750d68f2015-04-30 07:32:41185 v8::Local<v8::Value> v8_name = try_catch.ToV8(name);
186 v8::Local<v8::Value> v8_value = try_catch.ToV8(value);
raymes2515b7d2014-09-04 23:01:29187
188 if (try_catch.HasException())
[email protected]aaa72e72011-07-28 16:12:04189 return;
raymes2515b7d2014-09-04 23:01:29190
191 accessor.GetObject()->Set(v8_name, v8_value);
192 try_catch.HasException(); // Ensure an exception gets set if one occured.
[email protected]aaa72e72011-07-28 16:12:04193}
194
[email protected]ad63b5c2014-04-11 21:12:36195void DeletePropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29196 ObjectAccessor accessor(var);
197 if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
[email protected]aaa72e72011-07-28 16:12:04198 return;
199
dmichaele17054722014-10-10 20:03:19200 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
201 exception);
deepak.s750d68f2015-04-30 07:32:41202 v8::Local<v8::Value> v8_name = try_catch.ToV8(name);
raymes2515b7d2014-09-04 23:01:29203
204 if (try_catch.HasException())
205 return;
206
207 accessor.GetObject()->Delete(v8_name);
208 try_catch.HasException(); // Ensure an exception gets set if one occured.
[email protected]aaa72e72011-07-28 16:12:04209}
210
raymes2515b7d2014-09-04 23:01:29211PP_Var CallDeprecatedInternal(PP_Var var,
[email protected]99800f2a2012-07-10 23:41:40212 PP_Var method_name,
213 uint32_t argc,
214 PP_Var* argv,
215 PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29216 ObjectAccessor accessor(var);
217 if (!accessor.IsValid(exception))
218 return PP_MakeUndefined();
219
220 // If the method name is undefined, set it to the empty string to trigger
221 // calling |var| as a function.
222 ScopedPPVar scoped_name(method_name);
[email protected]aaa72e72011-07-28 16:12:04223 if (method_name.type == PP_VARTYPE_UNDEFINED) {
raymes2515b7d2014-09-04 23:01:29224 scoped_name = ScopedPPVar(ScopedPPVar::PassRef(),
225 StringVar::StringToPPVar(""));
226 }
227
dmichaele17054722014-10-10 20:03:19228 PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
229 exception);
deepak.s750d68f2015-04-30 07:32:41230 v8::Local<v8::Value> v8_method_name = try_catch.ToV8(scoped_name.get());
raymes2515b7d2014-09-04 23:01:29231 if (try_catch.HasException())
232 return PP_MakeUndefined();
233
234 if (!v8_method_name->IsString()) {
235 try_catch.SetException(kUnableToCallMethodException);
236 return PP_MakeUndefined();
237 }
238
deepak.s750d68f2015-04-30 07:32:41239 v8::Local<v8::Object> function = accessor.GetObject();
240 v8::Local<v8::Object> recv =
raymes816f98b2014-09-29 04:14:38241 accessor.instance()->GetMainWorldContext()->Global();
raymes2515b7d2014-09-04 23:01:29242 if (v8_method_name.As<v8::String>()->Length() != 0) {
dcarney04cd9642014-11-21 13:58:11243 function = function->Get(v8_method_name)
244 ->ToObject(accessor.instance()->GetIsolate());
raymes2515b7d2014-09-04 23:01:29245 recv = accessor.GetObject();
246 }
247
248 if (try_catch.HasException())
249 return PP_MakeUndefined();
250
251 if (!function->IsFunction()) {
252 try_catch.SetException(kUnableToCallMethodException);
253 return PP_MakeUndefined();
254 }
255
deepak.s750d68f2015-04-30 07:32:41256 scoped_ptr<v8::Local<v8::Value>[] > converted_args(
257 new v8::Local<v8::Value>[argc]);
raymes2515b7d2014-09-04 23:01:29258 for (uint32_t i = 0; i < argc; ++i) {
259 converted_args[i] = try_catch.ToV8(argv[i]);
260 if (try_catch.HasException())
[email protected]aaa72e72011-07-28 16:12:04261 return PP_MakeUndefined();
raymes2515b7d2014-09-04 23:01:29262 }
263
264 blink::WebPluginContainer* container = accessor.instance()->container();
265 blink::WebLocalFrame* frame = NULL;
266 if (container)
267 frame = container->element().document().frame();
268
269 if (!frame) {
270 try_catch.SetException("No frame to execute script in.");
[email protected]aaa72e72011-07-28 16:12:04271 return PP_MakeUndefined();
272 }
273
deepak.s750d68f2015-04-30 07:32:41274 v8::Local<v8::Value> result = frame->callFunctionEvenIfScriptDisabled(
raymes2515b7d2014-09-04 23:01:29275 function.As<v8::Function>(), recv, argc, converted_args.get());
276 ScopedPPVar result_var = try_catch.FromV8(result);
[email protected]aaa72e72011-07-28 16:12:04277
raymes2515b7d2014-09-04 23:01:29278 if (try_catch.HasException())
[email protected]aaa72e72011-07-28 16:12:04279 return PP_MakeUndefined();
[email protected]aaa72e72011-07-28 16:12:04280
raymes2515b7d2014-09-04 23:01:29281 return result_var.Release();
[email protected]aaa72e72011-07-28 16:12:04282}
283
[email protected]99800f2a2012-07-10 23:41:40284PP_Var CallDeprecated(PP_Var var,
285 PP_Var method_name,
286 uint32_t argc,
287 PP_Var* argv,
288 PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29289 ObjectAccessor accessor(var);
290 if (accessor.instance() && accessor.instance()->IsProcessingUserGesture()) {
291 blink::WebScopedUserGesture user_gesture(
292 accessor.instance()->CurrentUserGestureToken());
293 return CallDeprecatedInternal(var, method_name, argc, argv, exception);
[email protected]99800f2a2012-07-10 23:41:40294 }
raymes2515b7d2014-09-04 23:01:29295 return CallDeprecatedInternal(var, method_name, argc, argv, exception);
[email protected]99800f2a2012-07-10 23:41:40296}
297
[email protected]ad63b5c2014-04-11 21:12:36298PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) {
raymes2515b7d2014-09-04 23:01:29299 // Deprecated.
300 NOTREACHED();
301 return PP_MakeUndefined();
[email protected]aaa72e72011-07-28 16:12:04302}
303
304bool IsInstanceOfDeprecated(PP_Var var,
305 const PPP_Class_Deprecated* ppp_class,
306 void** ppp_class_data) {
raymes2515b7d2014-09-04 23:01:29307 scoped_refptr<V8ObjectVar> object(V8ObjectVar::FromPPVar(var));
[email protected]ff875be52013-06-02 23:47:38308 if (!object.get())
[email protected]aaa72e72011-07-28 16:12:04309 return false; // Not an object at all.
310
raymes2515b7d2014-09-04 23:01:29311 v8::HandleScope handle_scope(object->instance()->GetIsolate());
deepak.s750d68f2015-04-30 07:32:41312 v8::Local<v8::Context> context = object->instance()->GetMainWorldContext();
raymes9db73d22014-10-20 23:45:31313 if (context.IsEmpty())
314 return false;
315 v8::Context::Scope context_scope(context);
raymes2515b7d2014-09-04 23:01:29316 PluginObject* plugin_object = PluginObject::FromV8Object(
317 object->instance()->GetIsolate(), object->GetHandle());
318 if (plugin_object && plugin_object->ppp_class() == ppp_class) {
319 if (ppp_class_data)
320 *ppp_class_data = plugin_object->ppp_class_data();
321 return true;
322 }
323
324 return false;
[email protected]aaa72e72011-07-28 16:12:04325}
326
[email protected]794d83cd2011-10-20 19:09:20327PP_Var CreateObjectDeprecated(PP_Instance pp_instance,
[email protected]aaa72e72011-07-28 16:12:04328 const PPP_Class_Deprecated* ppp_class,
329 void* ppp_class_data) {
[email protected]adab2332013-07-25 18:04:32330 PepperPluginInstanceImpl* instance =
331 HostGlobals::Get()->GetInstance(pp_instance);
[email protected]aaa72e72011-07-28 16:12:04332 if (!instance) {
333 DLOG(ERROR) << "Create object passed an invalid instance.";
334 return PP_MakeNull();
335 }
336 return PluginObject::Create(instance, ppp_class, ppp_class_data);
337}
338
[email protected]794d83cd2011-10-20 19:09:20339PP_Var CreateObjectWithModuleDeprecated(PP_Module pp_module,
[email protected]aaa72e72011-07-28 16:12:04340 const PPP_Class_Deprecated* ppp_class,
341 void* ppp_class_data) {
[email protected]2f59e382011-10-20 22:51:01342 PluginModule* module = HostGlobals::Get()->GetModule(pp_module);
[email protected]aaa72e72011-07-28 16:12:04343 if (!module)
344 return PP_MakeNull();
[email protected]ad63b5c2014-04-11 21:12:36345 return PluginObject::Create(
346 module->GetSomeInstance(), ppp_class, ppp_class_data);
[email protected]aaa72e72011-07-28 16:12:04347}
348
[email protected]aaa72e72011-07-28 16:12:04349} // namespace
350
351// static
[email protected]872caf562011-12-07 22:50:43352const PPB_Var_Deprecated* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
353 static const PPB_Var_Deprecated var_deprecated_interface = {
[email protected]ad63b5c2014-04-11 21:12:36354 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
355 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
356 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
357 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
358 &HasPropertyDeprecated,
359 &HasMethodDeprecated,
360 &GetProperty,
361 &EnumerateProperties,
362 &SetPropertyDeprecated,
363 &DeletePropertyDeprecated,
364 &CallDeprecated,
365 &Construct,
366 &IsInstanceOfDeprecated,
367 &CreateObjectDeprecated,
368 &CreateObjectWithModuleDeprecated, };
[email protected]aaa72e72011-07-28 16:12:04369
[email protected]aaa72e72011-07-28 16:12:04370 return &var_deprecated_interface;
371}
372
[email protected]adab2332013-07-25 18:04:32373} // namespace content