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::Handle<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 weak_factory_(this) {
173 instance_->AddPluginObject(this);
176 gin::ObjectTemplateBuilder PluginObject::GetObjectTemplateBuilder(
177 v8::Isolate* isolate) {
178 return Wrappable<PluginObject>::GetObjectTemplateBuilder(isolate)
179 .AddNamedPropertyInterceptor();
182 v8::Local<v8::Value> PluginObject::GetPropertyOrMethod(v8::Isolate* isolate,
183 PP_Var identifier_var) {
185 return v8::Local<v8::Value>();
187 V8VarConverter var_converter(instance_->pp_instance(),
188 V8VarConverter::kAllowObjectVars);
189 PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
191 ppp_class_->HasProperty(ppp_class_data_, identifier_var,
192 try_catch.exception());
193 if (try_catch.ThrowException())
194 return v8::Local<v8::Value>();
197 ScopedPPVar result_var(ScopedPPVar::PassRef(),
198 ppp_class_->GetProperty(ppp_class_data_, identifier_var,
199 try_catch.exception()));
200 if (try_catch.ThrowException())
201 return v8::Local<v8::Value>();
203 v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
204 if (try_catch.ThrowException())
205 return v8::Local<v8::Value>();
210 bool has_method = identifier_var.type == PP_VARTYPE_STRING &&
211 ppp_class_->HasMethod(ppp_class_data_, identifier_var,
212 try_catch.exception());
213 if (try_catch.ThrowException())
214 return v8::Local<v8::Value>();
217 const std::string& identifier =
218 StringVar::FromPPVar(identifier_var)->value();
219 return gin::CreateFunctionTemplate(isolate,
220 base::Bind(&PluginObject::Call,
221 weak_factory_.GetWeakPtr(),
222 identifier))->GetFunction();
225 return v8::Local<v8::Value>();
228 void PluginObject::Call(const std::string& identifier,
229 gin::Arguments* args) {
233 V8VarConverter var_converter(instance_->pp_instance(),
234 V8VarConverter::kAllowObjectVars);
235 PepperTryCatchV8 try_catch(instance_, &var_converter, args->isolate());
236 ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
237 StringVar::StringToPPVar(identifier));
238 ScopedPPVarArray argument_vars(args->Length());
240 for (uint32_t i = 0; i < argument_vars.size(); ++i) {
241 v8::Handle<v8::Value> arg;
242 if (!args->GetNext(&arg)) {
246 argument_vars.Set(i, try_catch.FromV8(arg));
247 if (try_catch.ThrowException())
251 // For the OOP plugin case we need to grab a reference on the plugin module
252 // object to ensure that it is not destroyed courtesy an incoming
253 // ExecuteScript call which destroys the plugin module and in turn the
255 scoped_refptr<PluginModule> ref(instance_->module());
257 ScopedPPVar result_var(ScopedPPVar::PassRef(),
258 ppp_class_->Call(ppp_class_data_, identifier_var.get(),
259 argument_vars.size(), argument_vars.get(),
260 try_catch.exception()));
261 if (try_catch.ThrowException())
264 v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
265 if (try_catch.ThrowException())
268 args->Return(result);
271 } // namespace content