1 // Copyright (c) 2011 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/plugin_object.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14 #include "content/renderer/pepper/pepper_try_catch.h"
15 #include "content/renderer/pepper/plugin_module.h"
16 #include "content/renderer/pepper/v8_var_converter.h"
17 #include "gin/arguments.h"
18 #include "gin/converter.h"
19 #include "gin/function_template.h"
20 #include "gin/handle.h"
21 #include "gin/interceptor.h"
22 #include "gin/object_template_builder.h"
23 #include "gin/public/gin_embedders.h"
24 #include "ppapi/c/dev/ppb_var_deprecated.h"
25 #include "ppapi/c/dev/ppp_class_deprecated.h"
26 #include "ppapi/c/pp_resource.h"
27 #include "ppapi/c/pp_var.h"
28 #include "ppapi/shared_impl/ppapi_globals.h"
29 #include "ppapi/shared_impl/resource_tracker.h"
30 #include "ppapi/shared_impl/var.h"
31 #include "ppapi/shared_impl/var_tracker.h"
33 using ppapi::PpapiGlobals
;
34 using ppapi::ScopedPPVar
;
35 using ppapi::ScopedPPVarArray
;
36 using ppapi::StringVar
;
43 const char kInvalidValueException
[] = "Error: Invalid value";
47 // PluginObject ----------------------------------------------------------------
49 PluginObject::~PluginObject() {
51 ppp_class_
->Deallocate(ppp_class_data_
);
52 instance_
->RemovePluginObject(this);
57 gin::WrapperInfo
PluginObject::kWrapperInfo
= {gin::kEmbedderNativeGin
};
60 PluginObject
* PluginObject::FromV8Object(v8::Isolate
* isolate
,
61 v8::Local
<v8::Object
> v8_object
) {
62 PluginObject
* plugin_object
;
63 if (!v8_object
.IsEmpty() &&
64 gin::ConvertFromV8(isolate
, v8_object
, &plugin_object
)) {
71 PP_Var
PluginObject::Create(PepperPluginInstanceImpl
* instance
,
72 const PPP_Class_Deprecated
* ppp_class
,
73 void* ppp_class_data
) {
74 V8VarConverter
var_converter(instance
->pp_instance(),
75 V8VarConverter::kAllowObjectVars
);
76 PepperTryCatchVar
try_catch(instance
, &var_converter
, NULL
);
77 gin::Handle
<PluginObject
> object
=
78 gin::CreateHandle(instance
->GetIsolate(),
79 new PluginObject(instance
, ppp_class
, ppp_class_data
));
80 ScopedPPVar result
= try_catch
.FromV8(object
.ToV8());
81 DCHECK(!try_catch
.HasException());
82 return result
.Release();
85 v8::Local
<v8::Value
> PluginObject::GetNamedProperty(
87 const std::string
& identifier
) {
88 ScopedPPVar
identifier_var(ScopedPPVar::PassRef(),
89 StringVar::StringToPPVar(identifier
));
90 return GetPropertyOrMethod(instance_
->GetIsolate(), identifier_var
.get());
93 bool PluginObject::SetNamedProperty(v8::Isolate
* isolate
,
94 const std::string
& identifier
,
95 v8::Local
<v8::Value
> value
) {
98 ScopedPPVar
identifier_var(ScopedPPVar::PassRef(),
99 StringVar::StringToPPVar(identifier
));
100 V8VarConverter
var_converter(instance_
->pp_instance(),
101 V8VarConverter::kAllowObjectVars
);
102 PepperTryCatchV8
try_catch(instance_
, &var_converter
, isolate
);
105 ppp_class_
->HasProperty(ppp_class_data_
, identifier_var
.get(),
106 try_catch
.exception());
107 if (try_catch
.ThrowException())
113 ScopedPPVar var
= try_catch
.FromV8(value
);
114 if (try_catch
.ThrowException())
117 ppp_class_
->SetProperty(ppp_class_data_
, identifier_var
.get(), var
.get(),
118 try_catch
.exception());
120 // If the plugin threw an exception, then throw a V8 version of it to
121 // JavaScript. Either way, return true, because we successfully dispatched
122 // the call to the plugin.
123 try_catch
.ThrowException();
127 std::vector
<std::string
> PluginObject::EnumerateNamedProperties(
128 v8::Isolate
* isolate
) {
129 std::vector
<std::string
> result
;
133 V8VarConverter
var_converter(instance_
->pp_instance(),
134 V8VarConverter::kAllowObjectVars
);
135 PepperTryCatchV8
try_catch(instance_
, &var_converter
, isolate
);
139 ppp_class_
->GetAllPropertyNames(ppp_class_data_
, &count
, &name_vars
,
140 try_catch
.exception());
141 ScopedPPVarArray
scoped_name_vars(
142 ScopedPPVarArray::PassPPBMemoryAllocatedArray(), name_vars
, count
);
144 if (try_catch
.ThrowException())
147 for (uint32_t i
= 0; i
< count
; ++i
) {
148 StringVar
* string_var
= StringVar::FromPPVar(name_vars
[i
]);
150 result
.push_back(string_var
->value());
152 try_catch
.ThrowException(kInvalidValueException
);
161 void PluginObject::InstanceDeleted() {
165 PluginObject::PluginObject(PepperPluginInstanceImpl
* instance
,
166 const PPP_Class_Deprecated
* ppp_class
,
167 void* ppp_class_data
)
168 : gin::NamedPropertyInterceptor(instance
->GetIsolate(), this),
170 ppp_class_(ppp_class
),
171 ppp_class_data_(ppp_class_data
),
172 template_cache_(instance
->GetIsolate()),
173 weak_factory_(this) {
174 instance_
->AddPluginObject(this);
177 gin::ObjectTemplateBuilder
PluginObject::GetObjectTemplateBuilder(
178 v8::Isolate
* isolate
) {
179 return Wrappable
<PluginObject
>::GetObjectTemplateBuilder(isolate
)
180 .AddNamedPropertyInterceptor();
183 v8::Local
<v8::Value
> PluginObject::GetPropertyOrMethod(v8::Isolate
* isolate
,
184 PP_Var identifier_var
) {
186 return v8::Local
<v8::Value
>();
188 V8VarConverter
var_converter(instance_
->pp_instance(),
189 V8VarConverter::kAllowObjectVars
);
190 PepperTryCatchV8
try_catch(instance_
, &var_converter
, isolate
);
192 ppp_class_
->HasProperty(ppp_class_data_
, identifier_var
,
193 try_catch
.exception());
194 if (try_catch
.ThrowException())
195 return v8::Local
<v8::Value
>();
198 ScopedPPVar
result_var(ScopedPPVar::PassRef(),
199 ppp_class_
->GetProperty(ppp_class_data_
, identifier_var
,
200 try_catch
.exception()));
201 if (try_catch
.ThrowException())
202 return v8::Local
<v8::Value
>();
204 v8::Local
<v8::Value
> result
= try_catch
.ToV8(result_var
.get());
205 if (try_catch
.ThrowException())
206 return v8::Local
<v8::Value
>();
211 bool has_method
= identifier_var
.type
== PP_VARTYPE_STRING
&&
212 ppp_class_
->HasMethod(ppp_class_data_
, identifier_var
,
213 try_catch
.exception());
214 if (try_catch
.ThrowException())
215 return v8::Local
<v8::Value
>();
218 const std::string
& identifier
=
219 StringVar::FromPPVar(identifier_var
)->value();
220 return GetFunctionTemplate(isolate
, identifier
)->GetFunction();
223 return v8::Local
<v8::Value
>();
226 void PluginObject::Call(const std::string
& identifier
,
227 gin::Arguments
* args
) {
231 V8VarConverter
var_converter(instance_
->pp_instance(),
232 V8VarConverter::kAllowObjectVars
);
233 PepperTryCatchV8
try_catch(instance_
, &var_converter
, args
->isolate());
234 ScopedPPVar
identifier_var(ScopedPPVar::PassRef(),
235 StringVar::StringToPPVar(identifier
));
236 ScopedPPVarArray
argument_vars(args
->Length());
238 for (uint32_t i
= 0; i
< argument_vars
.size(); ++i
) {
239 v8::Local
<v8::Value
> arg
;
240 if (!args
->GetNext(&arg
)) {
244 argument_vars
.Set(i
, try_catch
.FromV8(arg
));
245 if (try_catch
.ThrowException())
249 // For the OOP plugin case we need to grab a reference on the plugin module
250 // object to ensure that it is not destroyed courtesy an incoming
251 // ExecuteScript call which destroys the plugin module and in turn the
253 scoped_refptr
<PluginModule
> ref(instance_
->module());
255 ScopedPPVar
result_var(ScopedPPVar::PassRef(),
256 ppp_class_
->Call(ppp_class_data_
, identifier_var
.get(),
257 argument_vars
.size(), argument_vars
.get(),
258 try_catch
.exception()));
259 if (try_catch
.ThrowException())
262 v8::Local
<v8::Value
> result
= try_catch
.ToV8(result_var
.get());
263 if (try_catch
.ThrowException())
266 args
->Return(result
);
269 v8::Local
<v8::FunctionTemplate
> PluginObject::GetFunctionTemplate(
270 v8::Isolate
* isolate
,
271 const std::string
& name
) {
272 v8::Local
<v8::FunctionTemplate
> function_template
= template_cache_
.Get(name
);
273 if (!function_template
.IsEmpty())
274 return function_template
;
276 gin::CreateFunctionTemplate(
277 isolate
, base::Bind(&PluginObject::Call
, weak_factory_
.GetWeakPtr(),
279 template_cache_
.Set(name
, function_template
);
280 return function_template
;
283 } // namespace content