Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / plugin_object.cc
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.
4
5 #include "content/renderer/pepper/plugin_object.h"
6
7 #include "base/bind.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"
32
33 using ppapi::PpapiGlobals;
34 using ppapi::ScopedPPVar;
35 using ppapi::ScopedPPVarArray;
36 using ppapi::StringVar;
37 using ppapi::Var;
38
39 namespace content {
40
41 namespace {
42
43 const char kInvalidValueException[] = "Error: Invalid value";
44
45 }  // namespace
46
47 // PluginObject ----------------------------------------------------------------
48
49 PluginObject::~PluginObject() {
50   if (instance_) {
51     ppp_class_->Deallocate(ppp_class_data_);
52     instance_->RemovePluginObject(this);
53   }
54 }
55
56 // static
57 gin::WrapperInfo PluginObject::kWrapperInfo = {gin::kEmbedderNativeGin};
58
59 // static
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)) {
65     return plugin_object;
66   }
67   return NULL;
68 }
69
70 // static
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();
83 }
84
85 v8::Local<v8::Value> PluginObject::GetNamedProperty(
86     v8::Isolate* isolate,
87     const std::string& identifier) {
88   ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
89                              StringVar::StringToPPVar(identifier));
90   return GetPropertyOrMethod(instance_->GetIsolate(), identifier_var.get());
91 }
92
93 bool PluginObject::SetNamedProperty(v8::Isolate* isolate,
94                                     const std::string& identifier,
95                                     v8::Local<v8::Value> value) {
96   if (!instance_)
97     return false;
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);
103
104   bool has_property =
105       ppp_class_->HasProperty(ppp_class_data_, identifier_var.get(),
106                               try_catch.exception());
107   if (try_catch.ThrowException())
108     return false;
109
110   if (!has_property)
111     return false;
112
113   ScopedPPVar var = try_catch.FromV8(value);
114   if (try_catch.ThrowException())
115     return false;
116
117   ppp_class_->SetProperty(ppp_class_data_, identifier_var.get(), var.get(),
118                           try_catch.exception());
119
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();
124   return true;
125 }
126
127 std::vector<std::string> PluginObject::EnumerateNamedProperties(
128     v8::Isolate* isolate) {
129   std::vector<std::string> result;
130   if (!instance_)
131     return result;
132
133   V8VarConverter var_converter(instance_->pp_instance(),
134                                V8VarConverter::kAllowObjectVars);
135   PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
136
137   PP_Var* name_vars;
138   uint32_t count = 0;
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);
143
144   if (try_catch.ThrowException())
145     return result;
146
147   for (uint32_t i = 0; i < count; ++i) {
148     StringVar* string_var = StringVar::FromPPVar(name_vars[i]);
149     if (string_var) {
150       result.push_back(string_var->value());
151     } else {
152       try_catch.ThrowException(kInvalidValueException);
153       result.clear();
154       return result;
155     }
156   }
157
158   return result;
159 }
160
161 void PluginObject::InstanceDeleted() {
162   instance_ = NULL;
163 }
164
165 PluginObject::PluginObject(PepperPluginInstanceImpl* instance,
166                            const PPP_Class_Deprecated* ppp_class,
167                            void* ppp_class_data)
168     : gin::NamedPropertyInterceptor(instance->GetIsolate(), this),
169       instance_(instance),
170       ppp_class_(ppp_class),
171       ppp_class_data_(ppp_class_data),
172       weak_factory_(this) {
173   instance_->AddPluginObject(this);
174 }
175
176 gin::ObjectTemplateBuilder PluginObject::GetObjectTemplateBuilder(
177     v8::Isolate* isolate) {
178   return Wrappable<PluginObject>::GetObjectTemplateBuilder(isolate)
179       .AddNamedPropertyInterceptor();
180 }
181
182 v8::Local<v8::Value> PluginObject::GetPropertyOrMethod(v8::Isolate* isolate,
183                                                        PP_Var identifier_var) {
184   if (!instance_)
185     return v8::Local<v8::Value>();
186
187   V8VarConverter var_converter(instance_->pp_instance(),
188                                V8VarConverter::kAllowObjectVars);
189   PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
190   bool has_property =
191       ppp_class_->HasProperty(ppp_class_data_, identifier_var,
192                               try_catch.exception());
193   if (try_catch.ThrowException())
194     return v8::Local<v8::Value>();
195
196   if (has_property) {
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>();
202
203     v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
204     if (try_catch.ThrowException())
205       return v8::Local<v8::Value>();
206
207     return result;
208   }
209
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>();
215
216   if (has_method) {
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();
223   }
224
225   return v8::Local<v8::Value>();
226 }
227
228 void PluginObject::Call(const std::string& identifier,
229                         gin::Arguments* args) {
230   if (!instance_)
231     return;
232
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());
239
240   for (uint32_t i = 0; i < argument_vars.size(); ++i) {
241     v8::Handle<v8::Value> arg;
242     if (!args->GetNext(&arg)) {
243       NOTREACHED();
244     }
245
246     argument_vars.Set(i, try_catch.FromV8(arg));
247     if (try_catch.ThrowException())
248       return;
249   }
250
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
254   // dispatcher.
255   scoped_refptr<PluginModule> ref(instance_->module());
256
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())
262     return;
263
264   v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
265   if (try_catch.ThrowException())
266     return;
267
268   args->Return(result);
269 }
270
271 }  // namespace content