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 // Scriptable plugin implementation.
7 #include "ppapi/native_client/src/trusted/plugin/scriptable_plugin.h"
15 #include "native_client/src/include/nacl_macros.h"
16 #include "native_client/src/include/nacl_string.h"
17 #include "native_client/src/include/portability.h"
18 #include "native_client/src/shared/platform/nacl_check.h"
19 #include "native_client/src/shared/srpc/nacl_srpc.h"
20 #include "ppapi/native_client/src/trusted/plugin/plugin.h"
21 #include "ppapi/native_client/src/trusted/plugin/utility.h"
28 pp::Var
Error(const nacl::string
& call_name
, const char* caller
,
29 const char* error
, pp::Var
* exception
) {
30 nacl::stringstream error_stream
;
31 error_stream
<< call_name
<< ": " << error
;
32 if (!exception
->is_undefined()) {
33 error_stream
<< " - " + exception
->AsString();
35 // Get the error string in 2 steps; otherwise, the temporary string returned
36 // by the stream is destructed, causing a dangling pointer.
37 std::string str
= error_stream
.str();
38 const char* e
= str
.c_str();
39 PLUGIN_PRINTF(("ScriptablePlugin::%s (%s)\n", caller
, e
));
40 *exception
= pp::Var(e
);
44 // In JavaScript, foo[1] is equivalent to foo["1"], so map both indexed and
45 // string names to a string.
46 nacl::string
NameAsString(const pp::Var
& name
) {
48 return name
.AsString();
50 nacl::stringstream namestream
;
51 namestream
<< name
.AsInt();
52 return namestream
.str();
55 // Returns a pp::Var corresponding to |arg| or void. Sets |exception| on error.
56 pp::Var
NaClSrpcArgToPPVar(const NaClSrpcArg
* arg
, pp::Var
* exception
) {
57 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (arg->tag='%c')\n", arg
->tag
));
60 case NACL_SRPC_ARG_TYPE_BOOL
:
61 var
= pp::Var(arg
->u
.bval
!= 0);
63 case NACL_SRPC_ARG_TYPE_DOUBLE
:
64 var
= pp::Var(arg
->u
.dval
);
66 case NACL_SRPC_ARG_TYPE_INT
:
67 var
= pp::Var(arg
->u
.ival
);
69 case NACL_SRPC_ARG_TYPE_LONG
:
70 // PPAPI does not have a 64-bit integral type. Downcast.
71 var
= pp::Var(static_cast<int32_t>(arg
->u
.lval
));
73 case NACL_SRPC_ARG_TYPE_STRING
:
74 var
= pp::Var(arg
->arrays
.str
);
76 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY
:
77 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY
:
78 case NACL_SRPC_ARG_TYPE_INT_ARRAY
:
79 case NACL_SRPC_ARG_TYPE_LONG_ARRAY
:
80 case NACL_SRPC_ARG_TYPE_OBJECT
:
81 case NACL_SRPC_ARG_TYPE_HANDLE
:
82 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY
:
83 case NACL_SRPC_ARG_TYPE_INVALID
:
85 *exception
= "variant array and invalid argument types are not supported";
87 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (return var=%s, exception=%s)\n",
88 var
.DebugString().c_str(), exception
->DebugString().c_str()));
94 ScriptablePlugin::ScriptablePlugin(Plugin
* plugin
)
95 : var_(NULL
), num_unref_calls_(0), plugin_(plugin
) {
96 PLUGIN_PRINTF(("ScriptablePlugin::ScriptablePlugin (this=%p, plugin=%p)\n",
97 static_cast<void*>(this),
98 static_cast<void*>(plugin
)));
101 ScriptablePlugin::~ScriptablePlugin() {
102 PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p)\n",
103 static_cast<void*>(this)));
104 PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p, return)\n",
105 static_cast<void*>(this)));
108 void ScriptablePlugin::Unref(ScriptablePlugin
** handle
) {
109 if (*handle
!= NULL
) {
115 ScriptablePlugin
* ScriptablePlugin::NewPlugin(Plugin
* plugin
) {
116 PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (plugin=%p)\n",
117 static_cast<void*>(plugin
)));
118 if (plugin
== NULL
) {
121 ScriptablePlugin
* scriptable_plugin
= new ScriptablePlugin(plugin
);
122 if (scriptable_plugin
== NULL
) {
125 PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (return %p)\n",
126 static_cast<void*>(scriptable_plugin
)));
127 return scriptable_plugin
;
130 bool ScriptablePlugin::HasProperty(const pp::Var
& name
, pp::Var
* exception
) {
131 UNREFERENCED_PARAMETER(exception
);
132 PLUGIN_PRINTF(("ScriptablePlugin::HasProperty (this=%p, name=%s)\n",
133 static_cast<void*>(this), name
.DebugString().c_str()));
134 if (plugin_
== NULL
) {
137 if (!name
.is_string() && !name
.is_int())
139 bool has_property
= plugin_
->HasProperty(name
.AsString());
140 PLUGIN_PRINTF(("ScriptablePlugin::HasProperty (has_property=%d)\n",
146 bool ScriptablePlugin::HasMethod(const pp::Var
& name
, pp::Var
* exception
) {
147 UNREFERENCED_PARAMETER(exception
);
148 PLUGIN_PRINTF(("ScriptablePlugin::HasMethod (this=%p, name='%s')\n",
149 static_cast<void*>(this), name
.DebugString().c_str()));
154 pp::Var
ScriptablePlugin::GetProperty(const pp::Var
& name
,
155 pp::Var
* exception
) {
156 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (name=%s)\n",
157 name
.DebugString().c_str()));
158 if (plugin_
== NULL
) {
162 NaClSrpcArg prop_value
;
163 nacl::string prop_name
= NameAsString(name
);
164 if (!plugin_
->GetProperty(prop_name
, &prop_value
)) {
165 return Error(prop_name
, "GetProperty", "invocation failed", exception
);
167 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (invocation done)\n"));
168 // Marshall output parameter.
169 pp::Var property
= NaClSrpcArgToPPVar(&prop_value
, exception
);
170 if (!exception
->is_undefined()) {
171 return Error(prop_name
, "GetProperty", "output marshalling failed",
174 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (property=%s)\n",
175 property
.DebugString().c_str()));
180 void ScriptablePlugin::SetProperty(const pp::Var
& name
,
181 const pp::Var
& value
,
182 pp::Var
* exception
) {
183 PLUGIN_PRINTF(("ScriptablePlugin::SetProperty (name=%s, value=%s)\n",
184 name
.DebugString().c_str(), value
.DebugString().c_str()));
185 Error("SetProperty", name
.DebugString().c_str(),
186 "property setting is not supported", exception
);
190 void ScriptablePlugin::RemoveProperty(const pp::Var
& name
,
191 pp::Var
* exception
) {
192 PLUGIN_PRINTF(("ScriptablePlugin::RemoveProperty (name=%s)\n",
193 name
.DebugString().c_str()));
194 Error(NameAsString(name
), "RemoveProperty",
195 "property removal is not supported", exception
);
198 void ScriptablePlugin::GetAllPropertyNames(std::vector
<pp::Var
>* properties
,
199 pp::Var
* exception
) {
200 PLUGIN_PRINTF(("ScriptablePlugin::GetAllPropertyNames ()\n"));
201 UNREFERENCED_PARAMETER(properties
);
202 UNREFERENCED_PARAMETER(exception
);
203 Error("GetAllPropertyNames", "", "GetAllPropertyNames is not supported",
208 pp::Var
ScriptablePlugin::Call(const pp::Var
& name
,
209 const std::vector
<pp::Var
>& args
,
210 pp::Var
* exception
) {
211 PLUGIN_PRINTF(("ScriptablePlugin::Call (name=%s, %" NACL_PRIuS
212 " args)\n", name
.DebugString().c_str(), args
.size()));
213 return Error("Call", name
.DebugString().c_str(),
214 "method invocation is not supported", exception
);
218 pp::Var
ScriptablePlugin::Construct(const std::vector
<pp::Var
>& args
,
219 pp::Var
* exception
) {
220 PLUGIN_PRINTF(("ScriptablePlugin::Construct (%" NACL_PRIuS
221 " args)\n", args
.size()));
222 return Error("constructor", "Construct", "constructor is not supported",
227 ScriptablePlugin
* ScriptablePlugin::AddRef() {
228 // This is called when we are about to share this object with the browser,
229 // and we need to make sure we have an internal plugin reference, so this
230 // object doesn't get deallocated when the browser discards its references.
232 var_
= new pp::VarPrivate(plugin_
, this);
235 PLUGIN_PRINTF(("ScriptablePlugin::AddRef (this=%p, var=%p)\n",
236 static_cast<void*>(this), static_cast<void*>(var_
)));
241 void ScriptablePlugin::Unref() {
242 // We should have no more than one internal owner of this object, so this
243 // should be called no more than once.
244 CHECK(++num_unref_calls_
== 1);
245 PLUGIN_PRINTF(("ScriptablePlugin::Unref (this=%p, var=%p)\n",
246 static_cast<void*>(this), static_cast<void*>(var_
)));
248 // We have shared this with the browser while keeping our own var
249 // reference, but we no longer need ours. If the browser has copies,
250 // it will clean things up later, otherwise this object will get
251 // deallocated right away.
252 PLUGIN_PRINTF(("ScriptablePlugin::Unref (delete var)\n"));
257 // Neither the browser nor plugin ever var referenced this object,
258 // so it can safely discarded.
259 PLUGIN_PRINTF(("ScriptablePlugin::Unref (delete this)\n"));
266 } // namespace plugin