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/WebPluginScriptForbiddenScope.h"
24 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
26 using ppapi::V8ObjectVar
;
27 using ppapi::PpapiGlobals
;
28 using ppapi::ScopedPPVar
;
29 using ppapi::ScopedPPVarArray
;
30 using ppapi::StringVar
;
37 const char kInvalidIdentifierException
[] = "Error: Invalid identifier.";
38 const char kInvalidObjectException
[] = "Error: Invalid object";
39 const char kUnableToCallMethodException
[] = "Error: Unable to call method";
41 class ObjectAccessor
{
43 ObjectAccessor(PP_Var var
)
44 : object_var_(V8ObjectVar::FromPPVar(var
).get()),
45 instance_(object_var_
? object_var_
->instance() : NULL
) {
47 converter_
.reset(new V8VarConverter(instance_
->pp_instance(),
48 V8VarConverter::kAllowObjectVars
));
52 // Check if the object is valid. If it isn't, set an exception and return
54 bool IsValid(PP_Var
* exception
) {
55 // If we already have an exception, then the call is invalid according to
57 if (exception
&& exception
->type
!= PP_VARTYPE_UNDEFINED
)
60 return !instance_
->is_deleted() ||
61 !blink::WebPluginScriptForbiddenScope::isForbidden();
63 *exception
= ppapi::StringVar::StringToPPVar(kInvalidObjectException
);
66 // Lazily grab the object so that the handle is created in the current handle
68 v8::Local
<v8::Object
> GetObject() { return object_var_
->GetHandle(); }
69 PepperPluginInstanceImpl
* instance() { return instance_
; }
70 V8VarConverter
* converter() { return converter_
.get(); }
73 V8ObjectVar
* object_var_
;
74 PepperPluginInstanceImpl
* instance_
;
75 scoped_ptr
<V8VarConverter
> converter_
;
78 bool IsValidIdentifer(PP_Var identifier
, PP_Var
* exception
) {
79 if (identifier
.type
== PP_VARTYPE_INT32
||
80 identifier
.type
== PP_VARTYPE_STRING
) {
84 *exception
= ppapi::StringVar::StringToPPVar(kInvalidIdentifierException
);
88 bool HasPropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
89 ObjectAccessor
accessor(var
);
90 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
93 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
95 v8::Local
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
96 if (try_catch
.HasException())
99 bool result
= accessor
.GetObject()->Has(v8_name
);
100 if (try_catch
.HasException())
105 bool HasMethodDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
106 ObjectAccessor
accessor(var
);
107 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
110 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
112 v8::Local
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
113 if (try_catch
.HasException())
116 bool result
= accessor
.GetObject()->Has(v8_name
) &&
117 accessor
.GetObject()->Get(v8_name
)->IsFunction();
118 if (try_catch
.HasException())
123 PP_Var
GetProperty(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
124 ObjectAccessor
accessor(var
);
125 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
126 return PP_MakeUndefined();
128 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
130 v8::Local
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
131 if (try_catch
.HasException())
132 return PP_MakeUndefined();
134 ScopedPPVar result_var
= try_catch
.FromV8(accessor
.GetObject()->Get(v8_name
));
135 if (try_catch
.HasException())
136 return PP_MakeUndefined();
138 return result_var
.Release();
141 void EnumerateProperties(PP_Var var
,
142 uint32_t* property_count
,
145 ObjectAccessor
accessor(var
);
146 if (!accessor
.IsValid(exception
))
149 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
155 v8::Local
<v8::Array
> identifiers
= accessor
.GetObject()->GetPropertyNames();
156 if (try_catch
.HasException())
158 ScopedPPVarArray
identifier_vars(identifiers
->Length());
159 for (uint32_t i
= 0; i
< identifiers
->Length(); ++i
) {
160 ScopedPPVar var
= try_catch
.FromV8(identifiers
->Get(i
));
161 if (try_catch
.HasException())
163 identifier_vars
.Set(i
, var
);
166 size_t size
= identifier_vars
.size();
167 *properties
= identifier_vars
.Release(
168 ScopedPPVarArray::PassPPBMemoryAllocatedArray());
169 *property_count
= size
;
172 void SetPropertyDeprecated(PP_Var var
,
176 ObjectAccessor
accessor(var
);
177 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
180 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
182 v8::Local
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
183 v8::Local
<v8::Value
> v8_value
= try_catch
.ToV8(value
);
185 if (try_catch
.HasException())
188 accessor
.GetObject()->Set(v8_name
, v8_value
);
189 try_catch
.HasException(); // Ensure an exception gets set if one occured.
192 void DeletePropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
193 ObjectAccessor
accessor(var
);
194 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
197 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
199 v8::Local
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
201 if (try_catch
.HasException())
204 accessor
.GetObject()->Delete(v8_name
);
205 try_catch
.HasException(); // Ensure an exception gets set if one occured.
208 PP_Var
CallDeprecatedInternal(PP_Var var
,
213 ObjectAccessor
accessor(var
);
214 if (!accessor
.IsValid(exception
))
215 return PP_MakeUndefined();
217 // If the method name is undefined, set it to the empty string to trigger
218 // calling |var| as a function.
219 ScopedPPVar
scoped_name(method_name
);
220 if (method_name
.type
== PP_VARTYPE_UNDEFINED
) {
221 scoped_name
= ScopedPPVar(ScopedPPVar::PassRef(),
222 StringVar::StringToPPVar(""));
225 PepperTryCatchVar
try_catch(accessor
.instance(), accessor
.converter(),
227 v8::Local
<v8::Value
> v8_method_name
= try_catch
.ToV8(scoped_name
.get());
228 if (try_catch
.HasException())
229 return PP_MakeUndefined();
231 if (!v8_method_name
->IsString()) {
232 try_catch
.SetException(kUnableToCallMethodException
);
233 return PP_MakeUndefined();
236 v8::Local
<v8::Object
> function
= accessor
.GetObject();
237 v8::Local
<v8::Object
> recv
=
238 accessor
.instance()->GetMainWorldContext()->Global();
239 if (v8_method_name
.As
<v8::String
>()->Length() != 0) {
240 function
= function
->Get(v8_method_name
)
241 ->ToObject(accessor
.instance()->GetIsolate());
242 recv
= accessor
.GetObject();
245 if (try_catch
.HasException())
246 return PP_MakeUndefined();
248 if (!function
->IsFunction()) {
249 try_catch
.SetException(kUnableToCallMethodException
);
250 return PP_MakeUndefined();
253 scoped_ptr
<v8::Local
<v8::Value
>[] > converted_args(
254 new v8::Local
<v8::Value
>[argc
]);
255 for (uint32_t i
= 0; i
< argc
; ++i
) {
256 converted_args
[i
] = try_catch
.ToV8(argv
[i
]);
257 if (try_catch
.HasException())
258 return PP_MakeUndefined();
261 blink::WebPluginContainer
* container
= accessor
.instance()->container();
262 blink::WebLocalFrame
* frame
= NULL
;
264 frame
= container
->element().document().frame();
267 try_catch
.SetException("No frame to execute script in.");
268 return PP_MakeUndefined();
271 v8::Local
<v8::Value
> result
= frame
->callFunctionEvenIfScriptDisabled(
272 function
.As
<v8::Function
>(), recv
, argc
, converted_args
.get());
273 ScopedPPVar result_var
= try_catch
.FromV8(result
);
275 if (try_catch
.HasException())
276 return PP_MakeUndefined();
278 return result_var
.Release();
281 PP_Var
CallDeprecated(PP_Var var
,
286 ObjectAccessor
accessor(var
);
287 if (accessor
.instance() && accessor
.instance()->IsProcessingUserGesture()) {
288 blink::WebScopedUserGesture
user_gesture(
289 accessor
.instance()->CurrentUserGestureToken());
290 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
292 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
295 PP_Var
Construct(PP_Var var
, uint32_t argc
, PP_Var
* argv
, PP_Var
* exception
) {
298 return PP_MakeUndefined();
301 bool IsInstanceOfDeprecated(PP_Var var
,
302 const PPP_Class_Deprecated
* ppp_class
,
303 void** ppp_class_data
) {
304 scoped_refptr
<V8ObjectVar
> object(V8ObjectVar::FromPPVar(var
));
306 return false; // Not an object at all.
308 v8::HandleScope
handle_scope(object
->instance()->GetIsolate());
309 v8::Local
<v8::Context
> context
= object
->instance()->GetMainWorldContext();
310 if (context
.IsEmpty())
312 v8::Context::Scope
context_scope(context
);
313 PluginObject
* plugin_object
= PluginObject::FromV8Object(
314 object
->instance()->GetIsolate(), object
->GetHandle());
315 if (plugin_object
&& plugin_object
->ppp_class() == ppp_class
) {
317 *ppp_class_data
= plugin_object
->ppp_class_data();
324 PP_Var
CreateObjectDeprecated(PP_Instance pp_instance
,
325 const PPP_Class_Deprecated
* ppp_class
,
326 void* ppp_class_data
) {
327 PepperPluginInstanceImpl
* instance
=
328 HostGlobals::Get()->GetInstance(pp_instance
);
330 DLOG(ERROR
) << "Create object passed an invalid instance.";
331 return PP_MakeNull();
333 return PluginObject::Create(instance
, ppp_class
, ppp_class_data
);
336 PP_Var
CreateObjectWithModuleDeprecated(PP_Module pp_module
,
337 const PPP_Class_Deprecated
* ppp_class
,
338 void* ppp_class_data
) {
339 PluginModule
* module
= HostGlobals::Get()->GetModule(pp_module
);
341 return PP_MakeNull();
342 return PluginObject::Create(
343 module
->GetSomeInstance(), ppp_class
, ppp_class_data
);
349 const PPB_Var_Deprecated
* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
350 static const PPB_Var_Deprecated var_deprecated_interface
= {
351 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef
,
352 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release
,
353 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8
,
354 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8
,
355 &HasPropertyDeprecated
,
356 &HasMethodDeprecated
,
358 &EnumerateProperties
,
359 &SetPropertyDeprecated
,
360 &DeletePropertyDeprecated
,
363 &IsInstanceOfDeprecated
,
364 &CreateObjectDeprecated
,
365 &CreateObjectWithModuleDeprecated
, };
367 return &var_deprecated_interface
;
370 } // namespace content