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
) {
47 // Check if the object is valid. If it isn't, set an exception and return
49 bool IsValid(PP_Var
* exception
) {
50 // If we already have an exception, then the call is invalid according to
52 if (exception
&& exception
->type
!= PP_VARTYPE_UNDEFINED
)
57 *exception
= ppapi::StringVar::StringToPPVar(kInvalidObjectException
);
60 // Lazily grab the object so that the handle is created in the current handle
62 v8::Handle
<v8::Object
> GetObject() { return object_var_
->GetHandle(); }
63 PepperPluginInstanceImpl
* instance() { return instance_
; }
66 V8ObjectVar
* object_var_
;
67 PepperPluginInstanceImpl
* instance_
;
70 bool IsValidIdentifer(PP_Var identifier
, PP_Var
* exception
) {
71 if (identifier
.type
== PP_VARTYPE_INT32
||
72 identifier
.type
== PP_VARTYPE_STRING
) {
76 *exception
= ppapi::StringVar::StringToPPVar(kInvalidIdentifierException
);
80 bool HasPropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
81 ObjectAccessor
accessor(var
);
82 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
85 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
86 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
87 if (try_catch
.HasException())
90 bool result
= accessor
.GetObject()->Has(v8_name
);
91 if (try_catch
.HasException())
96 bool HasMethodDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
97 ObjectAccessor
accessor(var
);
98 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
101 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
102 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
103 if (try_catch
.HasException())
106 bool result
= accessor
.GetObject()->Has(v8_name
) &&
107 accessor
.GetObject()->Get(v8_name
)->IsFunction();
108 if (try_catch
.HasException())
113 PP_Var
GetProperty(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
114 ObjectAccessor
accessor(var
);
115 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
116 return PP_MakeUndefined();
118 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
119 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
120 if (try_catch
.HasException())
121 return PP_MakeUndefined();
123 ScopedPPVar result_var
= try_catch
.FromV8(accessor
.GetObject()->Get(v8_name
));
124 if (try_catch
.HasException())
125 return PP_MakeUndefined();
127 return result_var
.Release();
130 void EnumerateProperties(PP_Var var
,
131 uint32_t* property_count
,
134 ObjectAccessor
accessor(var
);
135 if (!accessor
.IsValid(exception
))
138 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
143 v8::Local
<v8::Array
> identifiers
= accessor
.GetObject()->GetPropertyNames();
144 if (try_catch
.HasException())
146 ScopedPPVarArray
identifier_vars(identifiers
->Length());
147 for (uint32_t i
= 0; i
< identifiers
->Length(); ++i
) {
148 ScopedPPVar var
= try_catch
.FromV8(identifiers
->Get(i
));
149 if (try_catch
.HasException())
151 identifier_vars
.Set(i
, var
);
154 size_t size
= identifier_vars
.size();
155 *properties
= identifier_vars
.Release(
156 ScopedPPVarArray::PassPPBMemoryAllocatedArray());
157 *property_count
= size
;
160 void SetPropertyDeprecated(PP_Var var
,
164 ObjectAccessor
accessor(var
);
165 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
168 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
169 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
170 v8::Handle
<v8::Value
> v8_value
= try_catch
.ToV8(value
);
172 if (try_catch
.HasException())
175 accessor
.GetObject()->Set(v8_name
, v8_value
);
176 try_catch
.HasException(); // Ensure an exception gets set if one occured.
179 void DeletePropertyDeprecated(PP_Var var
, PP_Var name
, PP_Var
* exception
) {
180 ObjectAccessor
accessor(var
);
181 if (!accessor
.IsValid(exception
) || !IsValidIdentifer(name
, exception
))
184 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
185 v8::Handle
<v8::Value
> v8_name
= try_catch
.ToV8(name
);
187 if (try_catch
.HasException())
190 accessor
.GetObject()->Delete(v8_name
);
191 try_catch
.HasException(); // Ensure an exception gets set if one occured.
194 PP_Var
CallDeprecatedInternal(PP_Var var
,
199 ObjectAccessor
accessor(var
);
200 if (!accessor
.IsValid(exception
))
201 return PP_MakeUndefined();
203 // If the method name is undefined, set it to the empty string to trigger
204 // calling |var| as a function.
205 ScopedPPVar
scoped_name(method_name
);
206 if (method_name
.type
== PP_VARTYPE_UNDEFINED
) {
207 scoped_name
= ScopedPPVar(ScopedPPVar::PassRef(),
208 StringVar::StringToPPVar(""));
211 PepperTryCatchVar
try_catch(accessor
.instance(), exception
);
212 v8::Handle
<v8::Value
> v8_method_name
= try_catch
.ToV8(scoped_name
.get());
213 if (try_catch
.HasException())
214 return PP_MakeUndefined();
216 if (!v8_method_name
->IsString()) {
217 try_catch
.SetException(kUnableToCallMethodException
);
218 return PP_MakeUndefined();
221 v8::Handle
<v8::Object
> function
= accessor
.GetObject();
222 v8::Handle
<v8::Object
> recv
=
223 accessor
.instance()->GetContext()->Global();
224 if (v8_method_name
.As
<v8::String
>()->Length() != 0) {
225 function
= function
->Get(v8_method_name
)->ToObject();
226 recv
= accessor
.GetObject();
229 if (try_catch
.HasException())
230 return PP_MakeUndefined();
232 if (!function
->IsFunction()) {
233 try_catch
.SetException(kUnableToCallMethodException
);
234 return PP_MakeUndefined();
237 scoped_ptr
<v8::Handle
<v8::Value
>[] > converted_args(
238 new v8::Handle
<v8::Value
>[argc
]);
239 for (uint32_t i
= 0; i
< argc
; ++i
) {
240 converted_args
[i
] = try_catch
.ToV8(argv
[i
]);
241 if (try_catch
.HasException())
242 return PP_MakeUndefined();
245 blink::WebPluginContainer
* container
= accessor
.instance()->container();
246 blink::WebLocalFrame
* frame
= NULL
;
248 frame
= container
->element().document().frame();
251 try_catch
.SetException("No frame to execute script in.");
252 return PP_MakeUndefined();
255 v8::Handle
<v8::Value
> result
= frame
->callFunctionEvenIfScriptDisabled(
256 function
.As
<v8::Function
>(), recv
, argc
, converted_args
.get());
257 ScopedPPVar result_var
= try_catch
.FromV8(result
);
259 if (try_catch
.HasException())
260 return PP_MakeUndefined();
262 return result_var
.Release();
265 PP_Var
CallDeprecated(PP_Var var
,
270 ObjectAccessor
accessor(var
);
271 if (accessor
.instance() && accessor
.instance()->IsProcessingUserGesture()) {
272 blink::WebScopedUserGesture
user_gesture(
273 accessor
.instance()->CurrentUserGestureToken());
274 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
276 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
279 PP_Var
Construct(PP_Var var
, uint32_t argc
, PP_Var
* argv
, PP_Var
* exception
) {
282 return PP_MakeUndefined();
285 bool IsInstanceOfDeprecated(PP_Var var
,
286 const PPP_Class_Deprecated
* ppp_class
,
287 void** ppp_class_data
) {
288 scoped_refptr
<V8ObjectVar
> object(V8ObjectVar::FromPPVar(var
));
290 return false; // Not an object at all.
292 v8::HandleScope
handle_scope(object
->instance()->GetIsolate());
293 v8::Context::Scope
context_scope(object
->instance()->GetContext());
294 PluginObject
* plugin_object
= PluginObject::FromV8Object(
295 object
->instance()->GetIsolate(), object
->GetHandle());
296 if (plugin_object
&& plugin_object
->ppp_class() == ppp_class
) {
298 *ppp_class_data
= plugin_object
->ppp_class_data();
305 PP_Var
CreateObjectDeprecated(PP_Instance pp_instance
,
306 const PPP_Class_Deprecated
* ppp_class
,
307 void* ppp_class_data
) {
308 PepperPluginInstanceImpl
* instance
=
309 HostGlobals::Get()->GetInstance(pp_instance
);
311 DLOG(ERROR
) << "Create object passed an invalid instance.";
312 return PP_MakeNull();
314 return PluginObject::Create(instance
, ppp_class
, ppp_class_data
);
317 PP_Var
CreateObjectWithModuleDeprecated(PP_Module pp_module
,
318 const PPP_Class_Deprecated
* ppp_class
,
319 void* ppp_class_data
) {
320 PluginModule
* module
= HostGlobals::Get()->GetModule(pp_module
);
322 return PP_MakeNull();
323 return PluginObject::Create(
324 module
->GetSomeInstance(), ppp_class
, ppp_class_data
);
330 const PPB_Var_Deprecated
* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
331 static const PPB_Var_Deprecated var_deprecated_interface
= {
332 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef
,
333 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release
,
334 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8
,
335 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8
,
336 &HasPropertyDeprecated
,
337 &HasMethodDeprecated
,
339 &EnumerateProperties
,
340 &SetPropertyDeprecated
,
341 &DeletePropertyDeprecated
,
344 &IsInstanceOfDeprecated
,
345 &CreateObjectDeprecated
,
346 &CreateObjectWithModuleDeprecated
, };
348 return &var_deprecated_interface
;
351 } // namespace content