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 #ifdef WEB_FRAME_USES_V8_LOCAL
252 scoped_ptr
<v8::Local
<v8::Value
>[]> converted_args(
253 new v8::Local
<v8::Value
>[argc
]);
255 scoped_ptr
<v8::Handle
<v8::Value
>[] > converted_args(
256 new v8::Handle
<v8::Value
>[argc
]);
259 for (uint32_t i
= 0; i
< argc
; ++i
) {
260 converted_args
[i
] = try_catch
.ToV8(argv
[i
]);
261 if (try_catch
.HasException())
262 return PP_MakeUndefined();
265 blink::WebPluginContainer
* container
= accessor
.instance()->container();
266 blink::WebLocalFrame
* frame
= NULL
;
268 frame
= container
->element().document().frame();
271 try_catch
.SetException("No frame to execute script in.");
272 return PP_MakeUndefined();
275 v8::Handle
<v8::Value
> result
= frame
->callFunctionEvenIfScriptDisabled(
276 function
.As
<v8::Function
>(), recv
, argc
, converted_args
.get());
277 ScopedPPVar result_var
= try_catch
.FromV8(result
);
279 if (try_catch
.HasException())
280 return PP_MakeUndefined();
282 return result_var
.Release();
285 PP_Var
CallDeprecated(PP_Var var
,
290 ObjectAccessor
accessor(var
);
291 if (accessor
.instance() && accessor
.instance()->IsProcessingUserGesture()) {
292 blink::WebScopedUserGesture
user_gesture(
293 accessor
.instance()->CurrentUserGestureToken());
294 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
296 return CallDeprecatedInternal(var
, method_name
, argc
, argv
, exception
);
299 PP_Var
Construct(PP_Var var
, uint32_t argc
, PP_Var
* argv
, PP_Var
* exception
) {
302 return PP_MakeUndefined();
305 bool IsInstanceOfDeprecated(PP_Var var
,
306 const PPP_Class_Deprecated
* ppp_class
,
307 void** ppp_class_data
) {
308 scoped_refptr
<V8ObjectVar
> object(V8ObjectVar::FromPPVar(var
));
310 return false; // Not an object at all.
312 v8::HandleScope
handle_scope(object
->instance()->GetIsolate());
313 v8::Handle
<v8::Context
> context
= object
->instance()->GetMainWorldContext();
314 if (context
.IsEmpty())
316 v8::Context::Scope
context_scope(context
);
317 PluginObject
* plugin_object
= PluginObject::FromV8Object(
318 object
->instance()->GetIsolate(), object
->GetHandle());
319 if (plugin_object
&& plugin_object
->ppp_class() == ppp_class
) {
321 *ppp_class_data
= plugin_object
->ppp_class_data();
328 PP_Var
CreateObjectDeprecated(PP_Instance pp_instance
,
329 const PPP_Class_Deprecated
* ppp_class
,
330 void* ppp_class_data
) {
331 PepperPluginInstanceImpl
* instance
=
332 HostGlobals::Get()->GetInstance(pp_instance
);
334 DLOG(ERROR
) << "Create object passed an invalid instance.";
335 return PP_MakeNull();
337 return PluginObject::Create(instance
, ppp_class
, ppp_class_data
);
340 PP_Var
CreateObjectWithModuleDeprecated(PP_Module pp_module
,
341 const PPP_Class_Deprecated
* ppp_class
,
342 void* ppp_class_data
) {
343 PluginModule
* module
= HostGlobals::Get()->GetModule(pp_module
);
345 return PP_MakeNull();
346 return PluginObject::Create(
347 module
->GetSomeInstance(), ppp_class
, ppp_class_data
);
353 const PPB_Var_Deprecated
* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
354 static const PPB_Var_Deprecated var_deprecated_interface
= {
355 ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef
,
356 ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release
,
357 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8
,
358 ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8
,
359 &HasPropertyDeprecated
,
360 &HasMethodDeprecated
,
362 &EnumerateProperties
,
363 &SetPropertyDeprecated
,
364 &DeletePropertyDeprecated
,
367 &IsInstanceOfDeprecated
,
368 &CreateObjectDeprecated
,
369 &CreateObjectWithModuleDeprecated
, };
371 return &var_deprecated_interface
;
374 } // namespace content