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/message_channel.h"
11 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
12 #include "content/renderer/pepper/pepper_try_catch.h"
13 #include "content/renderer/pepper/plugin_module.h"
14 #include "content/renderer/pepper/plugin_object.h"
15 #include "content/renderer/pepper/v8object_var.h"
16 #include "ppapi/c/dev/ppb_var_deprecated.h"
17 #include "ppapi/c/ppb_var.h"
18 #include "ppapi/shared_impl/ppb_var_shared.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebElement.h"
21 #include "third_party/WebKit/public/web/WebLocalFrame.h"
22 #include "third_party/WebKit/public/web/WebPluginContainer.h"
23 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
25 using ppapi::V8ObjectVar
;
26 using ppapi::PpapiGlobals
;
27 using ppapi::ScopedPPVar
;
28 using ppapi::ScopedPPVarArray
;
29 using ppapi::StringVar
;
36 const char kInvalidIdentifierException
[] = "Error: Invalid identifier.";
37 const char kInvalidObjectException
[] = "Error: Invalid object";
38 const char kUnableToCallMethodException
[] = "Error: Unable to call method";
40 class ObjectAccessor
{
42 ObjectAccessor(PP_Var var
)
43 : object_var_(V8ObjectVar::FromPPVar(var
).get()),
44 instance_(object_var_
? object_var_
->instance() : NULL
) {
46 converter_
.reset(new V8VarConverter(instance_
->pp_instance(),
47 V8VarConverter::kAllowObjectVars
));
51 // Check if the object is valid. If it isn't, set an exception and return
53 bool IsValid(PP_Var
* exception
) {
54 // If we already have an exception, then the call is invalid according to
56 if (exception
&& exception
->type
!= PP_VARTYPE_UNDEFINED
)
61 *exception
= ppapi::StringVar::StringToPPVar(kInvalidObjectException
);
64 // Lazily grab the object so that the handle is created in the current handle
66 v8::Handle
<v8::Object
> GetObject() { return object_var_
->GetHandle(); }
67 PepperPluginInstanceImpl
* instance() { return instance_
; }
68 V8VarConverter
* converter() { return converter_
.get(); }
71 V8ObjectVar
* object_var_
;
72 PepperPluginInstanceImpl
* instance_
;
73 scoped_ptr
<V8VarConverter
> converter_
;
76 bool IsValidIdentifer(PP_Var identifier
, PP_Var
* exception
) {
77 if (identifier
.type
== PP_VARTYPE_INT32
||
78 identifier
.type
== PP_VARTYPE_STRING
) {
82 *exception
= ppapi::StringVar::StringToPPVar(kInvalidIdentifierException
);
86 bool HasPropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
87 ObjectAccessor
accessor(var
);
88 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
91 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
93 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
94 if (try_catch
.HasException())
97 bool result
= accessor
.GetObject()->Has(v8_name
);
98 if (try_catch
.HasException())
103 bool HasMethodDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
104 ObjectAccessor
accessor(var
);
105 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
108 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
110 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
111 if (try_catch
.HasException())
114 bool result
= accessor
.GetObject()->Has(v8_name
) &&
115 accessor
.GetObject()->Get(v8_name
)->IsFunction();
116 if (try_catch
.HasException())
121 PP_Var
GetProperty(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
122 ObjectAccessor
accessor(var
);
123 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
124 return PP_MakeUndefined();
126 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
128 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
129 if (try_catch
.HasException())
130 return PP_MakeUndefined();
132 ScopedPPVar result_var
= try_catch
.FromV8(accessor
.GetObject()->Get(v8_name
));
133 if (try_catch
.HasException())
134 return PP_MakeUndefined();
136 return result_var
.Release();
139 void EnumerateProperties(PP_Var var
,
140 uint32_t* property_count
,
143 ObjectAccessor
accessor(var
);
144 if (!accessor
.IsValid(exception
))
147 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
153 v8::Local
<v8::Array
> identifiers
= accessor
.GetObject()->GetPropertyNames();
154 if (try_catch
.HasException())
156 ScopedPPVarArray
identifier_vars(identifiers
->Length());
157 for (uint32_t i
= 0; i
< identifiers
->Length(); ++i
) {
158 ScopedPPVar var
= try_catch
.FromV8(identifiers
->Get(i
));
159 if (try_catch
.HasException())
161 identifier_vars
.Set(i
, var
);
164 size_t size
= identifier_vars
.size();
165 *properties
= identifier_vars
.Release(
166 ScopedPPVarArray::PassPPBMemoryAllocatedArray());
167 *property_count
= size
;
170 void SetPropertyDeprecated(PP_Var var
,
174 ObjectAccessor
accessor(var
);
175 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
178 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
180 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
181 v8::Handle
<v8::Value
> v8_value
= try_catch
.ToV8(value
);
183 if (try_catch
.HasException())
186 accessor
.GetObject()->Set(v8_name
, v8_value
);
187 try_catch
.HasException(); // Ensure an exception gets set if one occured.
190 void DeletePropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
191 ObjectAccessor
accessor(var
);
192 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
195 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
197 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
199 if (try_catch
.HasException())
202 accessor
.GetObject()->Delete(v8_name
);
203 try_catch
.HasException(); // Ensure an exception gets set if one occured.
206 PP_Var
CallDeprecatedInternal(PP_Var var
,
211 ObjectAccessor
accessor(var
);
212 if (!accessor
.IsValid(exception
))
213 return PP_MakeUndefined();
215 // If the method name is undefined, set it to the empty string to trigger
216 // calling |var| as a function.
217 ScopedPPVar
scoped_name(method_name
);
218 if (method_name
.type
== PP_VARTYPE_UNDEFINED
) {
219 scoped_name
= ScopedPPVar(ScopedPPVar::PassRef(),
220 StringVar::StringToPPVar(""));
223 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
225 v8::Handle
<v8::Value
> v8_method_name
= try_catch
.ToV8(scoped_name
.get());
226 if (try_catch
.HasException())
227 return PP_MakeUndefined();
229 if (!v8_method_name
->IsString()) {
230 try_catch
.SetException(kUnableToCallMethodException
);
231 return PP_MakeUndefined();
234 v8::Handle
<v8::Object
> function
= accessor
.GetObject();
235 v8::Handle
<v8::Object
> recv
=
236 accessor
.instance()->GetMainWorldContext()->Global();
237 if (v8_method_name
.As
<v8::String
>()->Length() != 0) {
238 function
= function
->Get(v8_method_name
)
239 ->ToObject(accessor
.instance()->GetIsolate());
240 recv
= accessor
.GetObject();
243 if (try_catch
.HasException())
244 return PP_MakeUndefined();
246 if (!function
->IsFunction()) {
247 try_catch
.SetException(kUnableToCallMethodException
);
248 return PP_MakeUndefined();
251 scoped_ptr
<v8::Handle
<v8::Value
>[] > converted_args(
252 new v8::Handle
<v8::Value
>[argc
]);
253 for (uint32_t i
= 0; i
< argc
; ++i
) {
254 converted_args
[i
] = try_catch
.ToV8(argv
[i
]);
255 if (try_catch
.HasException())
256 return PP_MakeUndefined();
259 blink::WebPluginContainer
* container
= accessor
.instance()->container();
260 blink::WebLocalFrame
* frame
= NULL
;
262 frame
= container
->element().document().frame();
265 try_catch
.SetException("No frame to execute script in.");
266 return PP_MakeUndefined();
269 v8::Handle
<v8::Value
> result
= frame
->callFunctionEvenIfScriptDisabled(
270 function
.As
<v8::Function
>(), recv
, argc
, converted_args
.get());
271 ScopedPPVar result_var
= try_catch
.FromV8(result
);
273 if (try_catch
.HasException())
274 return PP_MakeUndefined();
276 return result_var
.Release();
279 PP_Var
CallDeprecated(PP_Var var
,
284 ObjectAccessor
accessor(var
);
285 if (accessor
.instance() && accessor
.instance()->IsProcessingUserGesture()) {
286 blink::WebScopedUserGesture
user_gesture(
287 accessor
.instance()->CurrentUserGestureToken());
288 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
290 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
293 PP_Var
Construct(PP_Var var
, uint32_t argc
, PP_Var
* argv
, PP_Var
* exception
) {
296 return PP_MakeUndefined();
299 bool IsInstanceOfDeprecated(PP_Var var
,
300 const PPP_Class_Deprecated
* ppp_class
,
301 void** ppp_class_data
) {
302 scoped_refptr
<V8ObjectVar
> object(V8ObjectVar::FromPPVar(var
));
304 return false; // Not an object at all.
306 v8::HandleScope
handle_scope(object
->instance()->GetIsolate());
307 v8::Handle
<v8::Context
> context
= object
->instance()->GetMainWorldContext();
308 if (context
.IsEmpty())
310 v8::Context::Scope
context_scope(context
);
311 PluginObject
* plugin_object
= PluginObject::FromV8Object(
312 object
->instance()->GetIsolate(), object
->GetHandle());
313 if (plugin_object
&& plugin_object
->ppp_class() == ppp_class
) {
315 *ppp_class_data
= plugin_object
->ppp_class_data();
322 PP_Var
CreateObjectDeprecated(PP_Instance pp_instance
,
323 const PPP_Class_Deprecated
* ppp_class
,
324 void* ppp_class_data
) {
325 PepperPluginInstanceImpl
* instance
=
326 HostGlobals::Get()->GetInstance(pp_instance
);
328 DLOG(ERROR
) << "Create object passed an invalid instance.";
329 return PP_MakeNull();
331 return PluginObject::Create(instance
, ppp_class
, ppp_class_data
);
334 PP_Var
CreateObjectWithModuleDeprecated(PP_Module pp_module
,
335 const PPP_Class_Deprecated
* ppp_class
,
336 void* ppp_class_data
) {
337 PluginModule
* module
= HostGlobals::Get()->GetModule(pp_module
);
339 return PP_MakeNull();
340 return PluginObject::Create(
341 module
->GetSomeInstance(), ppp_class
, ppp_class_data
);
347 const PPB_Var_Deprecated
* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
348 static const PPB_Var_Deprecated var_deprecated_interface
= {
349 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef
,
350 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release
,
351 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8
,
352 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8
,
353 &HasPropertyDeprecated
,
354 &HasMethodDeprecated
,
356 &EnumerateProperties
,
357 &SetPropertyDeprecated
,
358 &DeletePropertyDeprecated
,
361 &IsInstanceOfDeprecated
,
362 &CreateObjectDeprecated
,
363 &CreateObjectWithModuleDeprecated
, };
365 return &var_deprecated_interface
;
368 } // namespace content