| Index: src/trusted/plugin/scriptable_handle.cc
|
| diff --git a/src/trusted/plugin/scriptable_handle.cc b/src/trusted/plugin/scriptable_handle.cc
|
| deleted file mode 100644
|
| index 2e173ea8c11cb3331664e82432eb7f7e495bc466..0000000000000000000000000000000000000000
|
| --- a/src/trusted/plugin/scriptable_handle.cc
|
| +++ /dev/null
|
| @@ -1,477 +0,0 @@
|
| -/*
|
| - * Copyright 2011 (c) The Native Client Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -
|
| -// Scriptable handle implementation.
|
| -
|
| -#include "native_client/src/trusted/plugin/scriptable_handle.h"
|
| -
|
| -#include <stdio.h>
|
| -#include <string.h>
|
| -
|
| -#include <assert.h>
|
| -#include <set>
|
| -#include <sstream>
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -
|
| -#include "native_client/src/include/checked_cast.h"
|
| -#include "native_client/src/include/nacl_macros.h"
|
| -#include "native_client/src/include/nacl_string.h"
|
| -#include "native_client/src/include/portability.h"
|
| -#include "native_client/src/shared/platform/nacl_check.h"
|
| -#include "native_client/src/shared/srpc/nacl_srpc.h"
|
| -#include "native_client/src/trusted/plugin/array_ppapi.h"
|
| -#include "native_client/src/trusted/plugin/browser_interface.h"
|
| -#include "native_client/src/trusted/plugin/desc_based_handle.h"
|
| -#include "native_client/src/trusted/plugin/method_map.h"
|
| -#include "native_client/src/trusted/plugin/plugin.h"
|
| -#include "native_client/src/trusted/plugin/utility.h"
|
| -#include "native_client/src/trusted/plugin/var_utils.h"
|
| -
|
| -
|
| -namespace plugin {
|
| -
|
| -namespace {
|
| -
|
| -// For security we keep track of the set of scriptable handles that were
|
| -// created.
|
| -
|
| -std::set<const plugin::ScriptableHandle*>* g_ValidHandles = 0;
|
| -
|
| -void RememberValidHandle(const ScriptableHandle* handle) {
|
| - // Initialize the set.
|
| - // BUG: this is not thread safe. We may leak sets, or worse, may not
|
| - // correctly insert valid handles into the set.
|
| - // TODO(sehr): use pthread_once or similar initialization.
|
| - if (NULL == g_ValidHandles) {
|
| - g_ValidHandles = new(std::nothrow) std::set<const ScriptableHandle*>;
|
| - if (NULL == g_ValidHandles) {
|
| - return;
|
| - }
|
| - }
|
| - // Remember the handle.
|
| - g_ValidHandles->insert(handle);
|
| -}
|
| -
|
| -pp::Var Error(nacl::string call_name, const char* caller,
|
| - const char* error, pp::Var* exception) {
|
| - nacl::stringstream error_stream;
|
| - error_stream << call_name << ": " << error;
|
| - if (!exception->is_undefined()) {
|
| - error_stream << " - " + exception->AsString();
|
| - }
|
| - // Get the error string in 2 steps; otherwise, the temporary string returned
|
| - // by the stream is destructed, causing a dangling pointer.
|
| - std::string str = error_stream.str();
|
| - const char* e = str.c_str();
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (%s)\n", caller, e));
|
| - *exception = pp::Var(e);
|
| - return pp::Var();
|
| -}
|
| -
|
| -// Helper functionality common to HasProperty and HasMethod.
|
| -bool HasCallType(Plugin* plugin,
|
| - CallType call_type,
|
| - nacl::string call_name,
|
| - const char* caller) {
|
| - uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name);
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (id=%"NACL_PRIxPTR")\n",
|
| - caller, id));
|
| - return plugin->HasMethod(id, call_type);
|
| -}
|
| -
|
| -// Helper functionality common to GetProperty, SetProperty and Call.
|
| -// If |call_type| is PROPERTY_GET, ignores args and expects 1 return var.
|
| -// If |call_type| is PROPERTY_SET, expects 1 arg and returns void var.
|
| -// Sets |exception| on failure.
|
| -pp::Var Invoke(Plugin* plugin,
|
| - CallType call_type,
|
| - nacl::string call_name,
|
| - const char* caller,
|
| - const std::vector<pp::Var>& args,
|
| - pp::Var* exception) {
|
| - uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name);
|
| -
|
| - // Initialize input/output parameters.
|
| - SrpcParams params;
|
| - NaClSrpcArg** inputs = params.ins();
|
| - NaClSrpcArg** outputs = params.outs();
|
| - if (!plugin->InitParams(id, call_type, ¶ms)) {
|
| - return Error(call_name, caller,
|
| - "srpc parameter initialization failed", exception);
|
| - }
|
| - uint32_t input_length = params.InputLength();
|
| - int32_t output_length = params.OutputLength();
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (initialized %"NACL_PRIu32" ins, %"
|
| - NACL_PRIu32" outs)\n", caller, input_length, output_length));
|
| -
|
| - // Verify input/output parameter list length.
|
| - if (args.size() != params.SignatureLength()) {
|
| - return Error(call_name, caller,
|
| - "incompatible srpc parameter list", exception);
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (verified signature)\n", caller));
|
| -
|
| - // Marshall input parameters.
|
| - if (input_length > 0) {
|
| - assert(call_type != PROPERTY_GET); // expect no inputs for "get"
|
| - for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (inputs[i] != NULL); ++i) {
|
| - if (!PPVarToNaClSrpcArg(args[i], inputs[i], exception)) {
|
| - return Error(call_name, caller,
|
| - "srpc input marshalling failed", exception);
|
| - }
|
| - }
|
| - }
|
| - if (call_type == PROPERTY_SET) assert(input_length == 1);
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (marshalled inputs)\n", caller));
|
| -
|
| - // Allocate array-typed output parameters.
|
| - if (args.size() > input_length) {
|
| - for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (outputs[i] != NULL); ++i) {
|
| - if (!PPVarToAllocateNaClSrpcArg(args[input_length + i],
|
| - outputs[i], exception)) {
|
| - return Error(call_name, caller, "srpc output array allocation failed",
|
| - exception);
|
| - }
|
| - }
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (output array allocation done)\n",
|
| - caller));
|
| -
|
| - // Invoke.
|
| - if (!plugin->Invoke(id, call_type, ¶ms)) {
|
| - nacl::string err = nacl::string(caller) + "('" + call_name + "') failed\n";
|
| - if (params.exception_string() != NULL) {
|
| - err = params.exception_string();
|
| - }
|
| - *exception = pp::Var(err.c_str());
|
| - return Error(call_name, caller, "invocation failed", exception);
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::%s (invocation done)\n", caller));
|
| -
|
| - // Marshall output parameters.
|
| - pp::Var retvar;
|
| - if (output_length > 0) {
|
| - assert(call_type != PROPERTY_SET); // expect no outputs for "set"
|
| - retvar = NaClSrpcArgToPPVar(outputs[0], plugin, exception);
|
| - if (output_length > 1) {
|
| - ArrayPpapi* array = new(std::nothrow) ArrayPpapi(plugin);
|
| - if (array == NULL) {
|
| - *exception = pp::Var("failed to allocate output array");
|
| - } else {
|
| - array->SetProperty(pp::Var(0), retvar, exception);
|
| - for (int32_t i = 1; i < output_length; ++i) {
|
| - pp::Var v = NaClSrpcArgToPPVar(outputs[i], plugin, exception);
|
| - array->SetProperty(pp::Var(i), v, exception);
|
| - }
|
| - }
|
| -
|
| - retvar = pp::VarPrivate(plugin, array);
|
| - }
|
| - if (!exception->is_undefined()) {
|
| - return Error(call_name, caller, "srpc output marshalling failed",
|
| - exception);
|
| - }
|
| - }
|
| - if (call_type == PROPERTY_GET) assert(output_length == 1);
|
| - return retvar;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -ScriptableHandle::ScriptableHandle(Plugin* plugin)
|
| - : var_(NULL), num_unref_calls_(0), plugin_(plugin), desc_handle_(NULL) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p, plugin=%p)\n",
|
| - static_cast<void*>(this),
|
| - static_cast<void*>(plugin)));
|
| - RememberValidHandle(this);
|
| - PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -ScriptableHandle::ScriptableHandle(DescBasedHandle* desc_handle)
|
| - : var_(NULL), num_unref_calls_(0), plugin_(NULL), desc_handle_(desc_handle) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p,"
|
| - " desc_handle=%p)\n",
|
| - static_cast<void*>(this),
|
| - static_cast<void*>(desc_handle)));
|
| - RememberValidHandle(this);
|
| - PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -ScriptableHandle::~ScriptableHandle() {
|
| - PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p)\n",
|
| - static_cast<void*>(this)));
|
| - // If the set was empty, just return.
|
| - if (NULL == g_ValidHandles) {
|
| - return;
|
| - }
|
| - // Remove the scriptable handle from the set of valid handles.
|
| - g_ValidHandles->erase(this);
|
| - // If handle is a plugin, the browser is deleting it (and might have
|
| - // already done so). Otherwise, delete here.
|
| - if (desc_handle_ != NULL) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle "
|
| - "(this=%p, delete desc_handle=%p)\n",
|
| - static_cast<void*>(this), static_cast<void*>(desc_handle_)));
|
| - delete desc_handle_;
|
| - desc_handle_ = NULL;
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p, return)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -// Check that an object is a validly created ScriptableHandle.
|
| -bool ScriptableHandle::is_valid(const ScriptableHandle* handle) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p)\n",
|
| - static_cast<void*>(const_cast<ScriptableHandle*>(handle))));
|
| - if (NULL == g_ValidHandles) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::is_valid (return 0)\n"));
|
| - return false;
|
| - }
|
| - size_t count =
|
| - g_ValidHandles->count(static_cast<const ScriptableHandle*>(handle));
|
| - PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p, count=%"
|
| - NACL_PRIuS")\n",
|
| - static_cast<void*>(const_cast<ScriptableHandle*>(handle)),
|
| - count));
|
| - return 0 != count;
|
| -}
|
| -
|
| -void ScriptableHandle::Unref(ScriptableHandle** handle) {
|
| - if (*handle != NULL) {
|
| - (*handle)->Unref();
|
| - *handle = NULL;
|
| - }
|
| -}
|
| -
|
| -ScriptableHandle* ScriptableHandle::NewPlugin(Plugin* plugin) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (plugin=%p)\n",
|
| - static_cast<void*>(plugin)));
|
| - if (plugin == NULL) {
|
| - return NULL;
|
| - }
|
| - ScriptableHandle* scriptable_handle =
|
| - new(std::nothrow) ScriptableHandle(plugin);
|
| - if (scriptable_handle == NULL) {
|
| - return NULL;
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (return %p)\n",
|
| - static_cast<void*>(scriptable_handle)));
|
| - return scriptable_handle;
|
| -}
|
| -
|
| -
|
| -ScriptableHandle* ScriptableHandle::NewDescHandle(
|
| - DescBasedHandle* desc_handle) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (desc_handle=%p)\n",
|
| - static_cast<void*>(desc_handle)));
|
| - if (desc_handle == NULL) {
|
| - return NULL;
|
| - }
|
| - ScriptableHandle* scriptable_handle =
|
| - new(std::nothrow) ScriptableHandle(desc_handle);
|
| - if (scriptable_handle == NULL) {
|
| - return NULL;
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (return %p)\n",
|
| - static_cast<void*>(scriptable_handle)));
|
| - return scriptable_handle;
|
| -}
|
| -
|
| -
|
| -bool ScriptableHandle::HasProperty(const pp::Var& name, pp::Var* exception) {
|
| - UNREFERENCED_PARAMETER(exception);
|
| - PLUGIN_PRINTF(("ScriptableHandle::HasProperty (this=%p, name=%s)\n",
|
| - static_cast<void*>(this), name.DebugString().c_str()));
|
| - if (plugin_ == NULL) {
|
| - return false;
|
| - }
|
| - if (!name.is_string() && !name.is_int())
|
| - return false;
|
| - bool has_property = HasCallType(plugin_,
|
| - PROPERTY_GET,
|
| - name.AsString(),
|
| - "HasProperty");
|
| - PLUGIN_PRINTF(("ScriptableHandle::HasProperty (has_property=%d)\n",
|
| - has_property));
|
| - return has_property;
|
| -}
|
| -
|
| -
|
| -bool ScriptableHandle::HasMethod(const pp::Var& name, pp::Var* exception) {
|
| - UNREFERENCED_PARAMETER(exception);
|
| - PLUGIN_PRINTF(("ScriptableHandle::HasMethod (this=%p, name='%s')\n",
|
| - static_cast<void*>(this), name.DebugString().c_str()));
|
| - if (plugin_ == NULL) {
|
| - return false;
|
| - }
|
| - if (!name.is_string())
|
| - return false;
|
| - bool has_method = HasCallType(plugin_,
|
| - METHOD_CALL,
|
| - name.AsString(),
|
| - "HasMethod");
|
| - PLUGIN_PRINTF(("ScriptableHandle::HasMethod (has_method=%d)\n",
|
| - has_method));
|
| - return has_method;
|
| -}
|
| -
|
| -
|
| -pp::Var ScriptableHandle::GetProperty(const pp::Var& name,
|
| - pp::Var* exception) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetProperty (name=%s)\n",
|
| - name.DebugString().c_str()));
|
| - if (plugin_ == NULL) {
|
| - return pp::Var();
|
| - }
|
| - pp::Var property = Invoke(plugin_,
|
| - PROPERTY_GET,
|
| - NameAsString(name),
|
| - "GetProperty",
|
| - std::vector<pp::Var>(), exception);
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetProperty (property=%s)\n",
|
| - property.DebugString().c_str()));
|
| - return property;
|
| -}
|
| -
|
| -
|
| -void ScriptableHandle::SetProperty(const pp::Var& name,
|
| - const pp::Var& value,
|
| - pp::Var* exception) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::SetProperty (name=%s, value=%s)\n",
|
| - name.DebugString().c_str(), value.DebugString().c_str()));
|
| - if (plugin_ == NULL) {
|
| - return;
|
| - }
|
| - std::vector<pp::Var> args;
|
| - args.push_back(pp::Var(pp::Var::DontManage(), value.pp_var()));
|
| - Invoke(plugin_,
|
| - PROPERTY_SET,
|
| - NameAsString(name),
|
| - "SetProperty",
|
| - args,
|
| - exception);
|
| - std::string exception_string("NULL");
|
| - if (exception != NULL) {
|
| - exception_string = exception->DebugString();
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::SetProperty (exception=%s)\n",
|
| - exception_string.c_str()));
|
| -}
|
| -
|
| -
|
| -void ScriptableHandle::RemoveProperty(const pp::Var& name,
|
| - pp::Var* exception) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::RemoveProperty (name=%s)\n",
|
| - name.DebugString().c_str()));
|
| - Error(NameAsString(name), "RemoveProperty",
|
| - "property removal is not supported", exception);
|
| -}
|
| -
|
| -// TODO(polina): should methods also be added?
|
| -// This is currently never called and the exact semantics is not clear.
|
| -// http://code.google.com/p/chromium/issues/detail?id=51089
|
| -void ScriptableHandle::GetAllPropertyNames(std::vector<pp::Var>* properties,
|
| - pp::Var* exception) {
|
| - UNREFERENCED_PARAMETER(exception);
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames ()\n"));
|
| - if (plugin_ == NULL) {
|
| - return;
|
| - }
|
| - std::vector<uintptr_t>* ids = plugin_->GetPropertyIdentifiers();
|
| - if (ids == NULL) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
|
| - "(ids=%p)\n", reinterpret_cast<void*>(ids)));
|
| - return;
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
|
| - "(ids->size()=%"NACL_PRIuS")\n", ids->size()));
|
| - for (size_t i = 0; i < ids->size(); ++i) {
|
| - nacl::string name =
|
| - plugin_->browser_interface()->IdentifierToString(ids->at(i));
|
| - properties->push_back(pp::Var(name));
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames "
|
| - "(properties=%"NACL_PRIuS")\n", properties->size()));
|
| -}
|
| -
|
| -
|
| -pp::Var ScriptableHandle::Call(const pp::Var& name,
|
| - const std::vector<pp::Var>& args,
|
| - pp::Var* exception) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::Call (name=%s, %"NACL_PRIuS
|
| - " args)\n", name.DebugString().c_str(), args.size()));
|
| - if (plugin_ == NULL) {
|
| - pp::Var();
|
| - }
|
| - if (name.is_undefined()) // invoke default
|
| - return pp::Var();
|
| - assert(name.is_string());
|
| - pp::Var return_var = Invoke(plugin_,
|
| - METHOD_CALL,
|
| - name.AsString(),
|
| - "Call",
|
| - args,
|
| - exception);
|
| - PLUGIN_PRINTF(("ScriptableHandle::Call (return=%s)\n",
|
| - return_var.DebugString().c_str()));
|
| - return return_var;
|
| -}
|
| -
|
| -
|
| -pp::Var ScriptableHandle::Construct(const std::vector<pp::Var>& args,
|
| - pp::Var* exception) {
|
| - PLUGIN_PRINTF(("ScriptableHandle::Construct (%"NACL_PRIuS
|
| - " args)\n", args.size()));
|
| - return Error("constructor", "Construct", "constructor is not supported",
|
| - exception);
|
| -}
|
| -
|
| -
|
| -ScriptableHandle* ScriptableHandle::AddRef() {
|
| - // This is called when we are about to share this object with the browser,
|
| - // and we need to make sure we have an internal plugin reference, so this
|
| - // object doesn't get deallocated when the browser discards its references.
|
| - if (var_ == NULL) {
|
| - var_ = new(std::nothrow) pp::VarPrivate(plugin_, this);
|
| - CHECK(var_ != NULL);
|
| - }
|
| - PLUGIN_PRINTF(("ScriptableHandle::AddRef (this=%p, var=%p)\n",
|
| - static_cast<void*>(this), static_cast<void*>(var_)));
|
| - return this;
|
| -}
|
| -
|
| -
|
| -void ScriptableHandle::Unref() {
|
| - // We should have no more than one internal owner of this object, so this
|
| - // should be called no more than once.
|
| - CHECK(++num_unref_calls_ == 1);
|
| - PLUGIN_PRINTF(("ScriptableHandle::Unref (this=%p, var=%p)\n",
|
| - static_cast<void*>(this), static_cast<void*>(var_)));
|
| - if (var_ != NULL) {
|
| - // We have shared this with the browser while keeping our own var
|
| - // reference, but we no longer need ours. If the browser has copies,
|
| - // it will clean things up later, otherwise this object will get
|
| - // deallocated right away.
|
| - PLUGIN_PRINTF(("ScriptableHandle::Unref (delete var)\n"));
|
| - pp::Var* var = var_;
|
| - var_ = NULL;
|
| - delete var;
|
| - } else {
|
| - // Neither the browser nor plugin ever var referenced this object,
|
| - // so it can safely discarded.
|
| - PLUGIN_PRINTF(("ScriptableHandle::Unref (delete this)\n"));
|
| - CHECK(var_ == NULL);
|
| - delete this;
|
| - }
|
| -}
|
| -
|
| -
|
| -} // namespace plugin
|
|
|