Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: src/trusted/plugin/scriptable_handle.cc

Issue 7799028: Remove src/trusted/plugin (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: fix gyp file for necessary -I Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/plugin/scriptable_handle.h ('k') | src/trusted/plugin/service_runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2011 (c) The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7
8 // Scriptable handle implementation.
9
10 #include "native_client/src/trusted/plugin/scriptable_handle.h"
11
12 #include <stdio.h>
13 #include <string.h>
14
15 #include <assert.h>
16 #include <set>
17 #include <sstream>
18 #include <string>
19 #include <vector>
20
21
22 #include "native_client/src/include/checked_cast.h"
23 #include "native_client/src/include/nacl_macros.h"
24 #include "native_client/src/include/nacl_string.h"
25 #include "native_client/src/include/portability.h"
26 #include "native_client/src/shared/platform/nacl_check.h"
27 #include "native_client/src/shared/srpc/nacl_srpc.h"
28 #include "native_client/src/trusted/plugin/array_ppapi.h"
29 #include "native_client/src/trusted/plugin/browser_interface.h"
30 #include "native_client/src/trusted/plugin/desc_based_handle.h"
31 #include "native_client/src/trusted/plugin/method_map.h"
32 #include "native_client/src/trusted/plugin/plugin.h"
33 #include "native_client/src/trusted/plugin/utility.h"
34 #include "native_client/src/trusted/plugin/var_utils.h"
35
36
37 namespace plugin {
38
39 namespace {
40
41 // For security we keep track of the set of scriptable handles that were
42 // created.
43
44 std::set<const plugin::ScriptableHandle*>* g_ValidHandles = 0;
45
46 void RememberValidHandle(const ScriptableHandle* handle) {
47 // Initialize the set.
48 // BUG: this is not thread safe. We may leak sets, or worse, may not
49 // correctly insert valid handles into the set.
50 // TODO(sehr): use pthread_once or similar initialization.
51 if (NULL == g_ValidHandles) {
52 g_ValidHandles = new(std::nothrow) std::set<const ScriptableHandle*>;
53 if (NULL == g_ValidHandles) {
54 return;
55 }
56 }
57 // Remember the handle.
58 g_ValidHandles->insert(handle);
59 }
60
61 pp::Var Error(nacl::string call_name, const char* caller,
62 const char* error, pp::Var* exception) {
63 nacl::stringstream error_stream;
64 error_stream << call_name << ": " << error;
65 if (!exception->is_undefined()) {
66 error_stream << " - " + exception->AsString();
67 }
68 // Get the error string in 2 steps; otherwise, the temporary string returned
69 // by the stream is destructed, causing a dangling pointer.
70 std::string str = error_stream.str();
71 const char* e = str.c_str();
72 PLUGIN_PRINTF(("ScriptableHandle::%s (%s)\n", caller, e));
73 *exception = pp::Var(e);
74 return pp::Var();
75 }
76
77 // Helper functionality common to HasProperty and HasMethod.
78 bool HasCallType(Plugin* plugin,
79 CallType call_type,
80 nacl::string call_name,
81 const char* caller) {
82 uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name);
83 PLUGIN_PRINTF(("ScriptableHandle::%s (id=%"NACL_PRIxPTR")\n",
84 caller, id));
85 return plugin->HasMethod(id, call_type);
86 }
87
88 // Helper functionality common to GetProperty, SetProperty and Call.
89 // If |call_type| is PROPERTY_GET, ignores args and expects 1 return var.
90 // If |call_type| is PROPERTY_SET, expects 1 arg and returns void var.
91 // Sets |exception| on failure.
92 pp::Var Invoke(Plugin* plugin,
93 CallType call_type,
94 nacl::string call_name,
95 const char* caller,
96 const std::vector<pp::Var>& args,
97 pp::Var* exception) {
98 uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name);
99
100 // Initialize input/output parameters.
101 SrpcParams params;
102 NaClSrpcArg** inputs = params.ins();
103 NaClSrpcArg** outputs = params.outs();
104 if (!plugin->InitParams(id, call_type, &params)) {
105 return Error(call_name, caller,
106 "srpc parameter initialization failed", exception);
107 }
108 uint32_t input_length = params.InputLength();
109 int32_t output_length = params.OutputLength();
110 PLUGIN_PRINTF(("ScriptableHandle::%s (initialized %"NACL_PRIu32" ins, %"
111 NACL_PRIu32" outs)\n", caller, input_length, output_length));
112
113 // Verify input/output parameter list length.
114 if (args.size() != params.SignatureLength()) {
115 return Error(call_name, caller,
116 "incompatible srpc parameter list", exception);
117 }
118 PLUGIN_PRINTF(("ScriptableHandle::%s (verified signature)\n", caller));
119
120 // Marshall input parameters.
121 if (input_length > 0) {
122 assert(call_type != PROPERTY_GET); // expect no inputs for "get"
123 for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (inputs[i] != NULL); ++i) {
124 if (!PPVarToNaClSrpcArg(args[i], inputs[i], exception)) {
125 return Error(call_name, caller,
126 "srpc input marshalling failed", exception);
127 }
128 }
129 }
130 if (call_type == PROPERTY_SET) assert(input_length == 1);
131 PLUGIN_PRINTF(("ScriptableHandle::%s (marshalled inputs)\n", caller));
132
133 // Allocate array-typed output parameters.
134 if (args.size() > input_length) {
135 for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (outputs[i] != NULL); ++i) {
136 if (!PPVarToAllocateNaClSrpcArg(args[input_length + i],
137 outputs[i], exception)) {
138 return Error(call_name, caller, "srpc output array allocation failed",
139 exception);
140 }
141 }
142 }
143 PLUGIN_PRINTF(("ScriptableHandle::%s (output array allocation done)\n",
144 caller));
145
146 // Invoke.
147 if (!plugin->Invoke(id, call_type, &params)) {
148 nacl::string err = nacl::string(caller) + "('" + call_name + "') failed\n";
149 if (params.exception_string() != NULL) {
150 err = params.exception_string();
151 }
152 *exception = pp::Var(err.c_str());
153 return Error(call_name, caller, "invocation failed", exception);
154 }
155 PLUGIN_PRINTF(("ScriptableHandle::%s (invocation done)\n", caller));
156
157 // Marshall output parameters.
158 pp::Var retvar;
159 if (output_length > 0) {
160 assert(call_type != PROPERTY_SET); // expect no outputs for "set"
161 retvar = NaClSrpcArgToPPVar(outputs[0], plugin, exception);
162 if (output_length > 1) {
163 ArrayPpapi* array = new(std::nothrow) ArrayPpapi(plugin);
164 if (array == NULL) {
165 *exception = pp::Var("failed to allocate output array");
166 } else {
167 array->SetProperty(pp::Var(0), retvar, exception);
168 for (int32_t i = 1; i < output_length; ++i) {
169 pp::Var v = NaClSrpcArgToPPVar(outputs[i], plugin, exception);
170 array->SetProperty(pp::Var(i), v, exception);
171 }
172 }
173
174 retvar = pp::VarPrivate(plugin, array);
175 }
176 if (!exception->is_undefined()) {
177 return Error(call_name, caller, "srpc output marshalling failed",
178 exception);
179 }
180 }
181 if (call_type == PROPERTY_GET) assert(output_length == 1);
182 return retvar;
183 }
184
185 } // namespace
186
187 ScriptableHandle::ScriptableHandle(Plugin* plugin)
188 : var_(NULL), num_unref_calls_(0), plugin_(plugin), desc_handle_(NULL) {
189 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p, plugin=%p)\n",
190 static_cast<void*>(this),
191 static_cast<void*>(plugin)));
192 RememberValidHandle(this);
193 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n",
194 static_cast<void*>(this)));
195 }
196
197 ScriptableHandle::ScriptableHandle(DescBasedHandle* desc_handle)
198 : var_(NULL), num_unref_calls_(0), plugin_(NULL), desc_handle_(desc_handle) {
199 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p,"
200 " desc_handle=%p)\n",
201 static_cast<void*>(this),
202 static_cast<void*>(desc_handle)));
203 RememberValidHandle(this);
204 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n",
205 static_cast<void*>(this)));
206 }
207
208 ScriptableHandle::~ScriptableHandle() {
209 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p)\n",
210 static_cast<void*>(this)));
211 // If the set was empty, just return.
212 if (NULL == g_ValidHandles) {
213 return;
214 }
215 // Remove the scriptable handle from the set of valid handles.
216 g_ValidHandles->erase(this);
217 // If handle is a plugin, the browser is deleting it (and might have
218 // already done so). Otherwise, delete here.
219 if (desc_handle_ != NULL) {
220 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle "
221 "(this=%p, delete desc_handle=%p)\n",
222 static_cast<void*>(this), static_cast<void*>(desc_handle_)));
223 delete desc_handle_;
224 desc_handle_ = NULL;
225 }
226 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p, return)\n",
227 static_cast<void*>(this)));
228 }
229
230 // Check that an object is a validly created ScriptableHandle.
231 bool ScriptableHandle::is_valid(const ScriptableHandle* handle) {
232 PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p)\n",
233 static_cast<void*>(const_cast<ScriptableHandle*>(handle))));
234 if (NULL == g_ValidHandles) {
235 PLUGIN_PRINTF(("ScriptableHandle::is_valid (return 0)\n"));
236 return false;
237 }
238 size_t count =
239 g_ValidHandles->count(static_cast<const ScriptableHandle*>(handle));
240 PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p, count=%"
241 NACL_PRIuS")\n",
242 static_cast<void*>(const_cast<ScriptableHandle*>(handle)),
243 count));
244 return 0 != count;
245 }
246
247 void ScriptableHandle::Unref(ScriptableHandle** handle) {
248 if (*handle != NULL) {
249 (*handle)->Unref();
250 *handle = NULL;
251 }
252 }
253
254 ScriptableHandle* ScriptableHandle::NewPlugin(Plugin* plugin) {
255 PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (plugin=%p)\n",
256 static_cast<void*>(plugin)));
257 if (plugin == NULL) {
258 return NULL;
259 }
260 ScriptableHandle* scriptable_handle =
261 new(std::nothrow) ScriptableHandle(plugin);
262 if (scriptable_handle == NULL) {
263 return NULL;
264 }
265 PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (return %p)\n",
266 static_cast<void*>(scriptable_handle)));
267 return scriptable_handle;
268 }
269
270
271 ScriptableHandle* ScriptableHandle::NewDescHandle(
272 DescBasedHandle* desc_handle) {
273 PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (desc_handle=%p)\n",
274 static_cast<void*>(desc_handle)));
275 if (desc_handle == NULL) {
276 return NULL;
277 }
278 ScriptableHandle* scriptable_handle =
279 new(std::nothrow) ScriptableHandle(desc_handle);
280 if (scriptable_handle == NULL) {
281 return NULL;
282 }
283 PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (return %p)\n",
284 static_cast<void*>(scriptable_handle)));
285 return scriptable_handle;
286 }
287
288
289 bool ScriptableHandle::HasProperty(const pp::Var& name, pp::Var* exception) {
290 UNREFERENCED_PARAMETER(exception);
291 PLUGIN_PRINTF(("ScriptableHandle::HasProperty (this=%p, name=%s)\n",
292 static_cast<void*>(this), name.DebugString().c_str()));
293 if (plugin_ == NULL) {
294 return false;
295 }
296 if (!name.is_string() && !name.is_int())
297 return false;
298 bool has_property = HasCallType(plugin_,
299 PROPERTY_GET,
300 name.AsString(),
301 "HasProperty");
302 PLUGIN_PRINTF(("ScriptableHandle::HasProperty (has_property=%d)\n",
303 has_property));
304 return has_property;
305 }
306
307
308 bool ScriptableHandle::HasMethod(const pp::Var& name, pp::Var* exception) {
309 UNREFERENCED_PARAMETER(exception);
310 PLUGIN_PRINTF(("ScriptableHandle::HasMethod (this=%p, name='%s')\n",
311 static_cast<void*>(this), name.DebugString().c_str()));
312 if (plugin_ == NULL) {
313 return false;
314 }
315 if (!name.is_string())
316 return false;
317 bool has_method = HasCallType(plugin_,
318 METHOD_CALL,
319 name.AsString(),
320 "HasMethod");
321 PLUGIN_PRINTF(("ScriptableHandle::HasMethod (has_method=%d)\n",
322 has_method));
323 return has_method;
324 }
325
326
327 pp::Var ScriptableHandle::GetProperty(const pp::Var& name,
328 pp::Var* exception) {
329 PLUGIN_PRINTF(("ScriptableHandle::GetProperty (name=%s)\n",
330 name.DebugString().c_str()));
331 if (plugin_ == NULL) {
332 return pp::Var();
333 }
334 pp::Var property = Invoke(plugin_,
335 PROPERTY_GET,
336 NameAsString(name),
337 "GetProperty",
338 std::vector<pp::Var>(), exception);
339 PLUGIN_PRINTF(("ScriptableHandle::GetProperty (property=%s)\n",
340 property.DebugString().c_str()));
341 return property;
342 }
343
344
345 void ScriptableHandle::SetProperty(const pp::Var& name,
346 const pp::Var& value,
347 pp::Var* exception) {
348 PLUGIN_PRINTF(("ScriptableHandle::SetProperty (name=%s, value=%s)\n",
349 name.DebugString().c_str(), value.DebugString().c_str()));
350 if (plugin_ == NULL) {
351 return;
352 }
353 std::vector<pp::Var> args;
354 args.push_back(pp::Var(pp::Var::DontManage(), value.pp_var()));
355 Invoke(plugin_,
356 PROPERTY_SET,
357 NameAsString(name),
358 "SetProperty",
359 args,
360 exception);
361 std::string exception_string("NULL");
362 if (exception != NULL) {
363 exception_string = exception->DebugString();
364 }
365 PLUGIN_PRINTF(("ScriptableHandle::SetProperty (exception=%s)\n",
366 exception_string.c_str()));
367 }
368
369
370 void ScriptableHandle::RemoveProperty(const pp::Var& name,
371 pp::Var* exception) {
372 PLUGIN_PRINTF(("ScriptableHandle::RemoveProperty (name=%s)\n",
373 name.DebugString().c_str()));
374 Error(NameAsString(name), "RemoveProperty",
375 "property removal is not supported", exception);
376 }
377
378 // TODO(polina): should methods also be added?
379 // This is currently never called and the exact semantics is not clear.
380 // http://code.google.com/p/chromium/issues/detail?id=51089
381 void ScriptableHandle::GetAllPropertyNames(std::vector<pp::Var>* properties,
382 pp::Var* exception) {
383 UNREFERENCED_PARAMETER(exception);
384 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames ()\n"));
385 if (plugin_ == NULL) {
386 return;
387 }
388 std::vector<uintptr_t>* ids = plugin_->GetPropertyIdentifiers();
389 if (ids == NULL) {
390 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
391 "(ids=%p)\n", reinterpret_cast<void*>(ids)));
392 return;
393 }
394 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
395 "(ids->size()=%"NACL_PRIuS")\n", ids->size()));
396 for (size_t i = 0; i < ids->size(); ++i) {
397 nacl::string name =
398 plugin_->browser_interface()->IdentifierToString(ids->at(i));
399 properties->push_back(pp::Var(name));
400 }
401 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
402 "(properties=%"NACL_PRIuS")\n", properties->size()));
403 }
404
405
406 pp::Var ScriptableHandle::Call(const pp::Var& name,
407 const std::vector<pp::Var>& args,
408 pp::Var* exception) {
409 PLUGIN_PRINTF(("ScriptableHandle::Call (name=%s, %"NACL_PRIuS
410 " args)\n", name.DebugString().c_str(), args.size()));
411 if (plugin_ == NULL) {
412 pp::Var();
413 }
414 if (name.is_undefined()) // invoke default
415 return pp::Var();
416 assert(name.is_string());
417 pp::Var return_var = Invoke(plugin_,
418 METHOD_CALL,
419 name.AsString(),
420 "Call",
421 args,
422 exception);
423 PLUGIN_PRINTF(("ScriptableHandle::Call (return=%s)\n",
424 return_var.DebugString().c_str()));
425 return return_var;
426 }
427
428
429 pp::Var ScriptableHandle::Construct(const std::vector<pp::Var>& args,
430 pp::Var* exception) {
431 PLUGIN_PRINTF(("ScriptableHandle::Construct (%"NACL_PRIuS
432 " args)\n", args.size()));
433 return Error("constructor", "Construct", "constructor is not supported",
434 exception);
435 }
436
437
438 ScriptableHandle* ScriptableHandle::AddRef() {
439 // This is called when we are about to share this object with the browser,
440 // and we need to make sure we have an internal plugin reference, so this
441 // object doesn't get deallocated when the browser discards its references.
442 if (var_ == NULL) {
443 var_ = new(std::nothrow) pp::VarPrivate(plugin_, this);
444 CHECK(var_ != NULL);
445 }
446 PLUGIN_PRINTF(("ScriptableHandle::AddRef (this=%p, var=%p)\n",
447 static_cast<void*>(this), static_cast<void*>(var_)));
448 return this;
449 }
450
451
452 void ScriptableHandle::Unref() {
453 // We should have no more than one internal owner of this object, so this
454 // should be called no more than once.
455 CHECK(++num_unref_calls_ == 1);
456 PLUGIN_PRINTF(("ScriptableHandle::Unref (this=%p, var=%p)\n",
457 static_cast<void*>(this), static_cast<void*>(var_)));
458 if (var_ != NULL) {
459 // We have shared this with the browser while keeping our own var
460 // reference, but we no longer need ours. If the browser has copies,
461 // it will clean things up later, otherwise this object will get
462 // deallocated right away.
463 PLUGIN_PRINTF(("ScriptableHandle::Unref (delete var)\n"));
464 pp::Var* var = var_;
465 var_ = NULL;
466 delete var;
467 } else {
468 // Neither the browser nor plugin ever var referenced this object,
469 // so it can safely discarded.
470 PLUGIN_PRINTF(("ScriptableHandle::Unref (delete this)\n"));
471 CHECK(var_ == NULL);
472 delete this;
473 }
474 }
475
476
477 } // namespace plugin
OLDNEW
« no previous file with comments | « src/trusted/plugin/scriptable_handle.h ('k') | src/trusted/plugin/service_runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698