// Copyright (c) 2012 The Chromium 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 plugin implementation. #include "ppapi/native_client/src/trusted/plugin/scriptable_plugin.h" #include #include #include #include #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 "ppapi/native_client/src/trusted/plugin/plugin.h" #include "ppapi/native_client/src/trusted/plugin/utility.h" namespace plugin { namespace { pp::Var Error(const 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(("ScriptablePlugin::%s (%s)\n", caller, e)); *exception = pp::Var(e); return pp::Var(); } } // namespace ScriptablePlugin::ScriptablePlugin(Plugin* plugin) : var_(NULL), num_unref_calls_(0), plugin_(plugin) { PLUGIN_PRINTF(("ScriptablePlugin::ScriptablePlugin (this=%p, plugin=%p)\n", static_cast(this), static_cast(plugin))); } ScriptablePlugin::~ScriptablePlugin() { PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p)\n", static_cast(this))); PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p, return)\n", static_cast(this))); } void ScriptablePlugin::Unref(ScriptablePlugin** handle) { if (*handle != NULL) { (*handle)->Unref(); *handle = NULL; } } ScriptablePlugin* ScriptablePlugin::NewPlugin(Plugin* plugin) { PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (plugin=%p)\n", static_cast(plugin))); if (plugin == NULL) { return NULL; } ScriptablePlugin* scriptable_plugin = new ScriptablePlugin(plugin); if (scriptable_plugin == NULL) { return NULL; } PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (return %p)\n", static_cast(scriptable_plugin))); return scriptable_plugin; } bool ScriptablePlugin::HasProperty(const pp::Var& name, pp::Var* exception) { UNREFERENCED_PARAMETER(exception); PLUGIN_PRINTF(("ScriptablePlugin::HasProperty (this=%p, name=%s)\n", static_cast(this), name.DebugString().c_str())); return false; } bool ScriptablePlugin::HasMethod(const pp::Var& name, pp::Var* exception) { UNREFERENCED_PARAMETER(exception); PLUGIN_PRINTF(("ScriptablePlugin::HasMethod (this=%p, name='%s')\n", static_cast(this), name.DebugString().c_str())); return false; } pp::Var ScriptablePlugin::GetProperty(const pp::Var& name, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (name=%s)\n", name.DebugString().c_str())); Error("GetProperty", name.DebugString().c_str(), "property getting is not supported", exception); return pp::Var(); } void ScriptablePlugin::SetProperty(const pp::Var& name, const pp::Var& value, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::SetProperty (name=%s, value=%s)\n", name.DebugString().c_str(), value.DebugString().c_str())); Error("SetProperty", name.DebugString().c_str(), "property setting is not supported", exception); } void ScriptablePlugin::RemoveProperty(const pp::Var& name, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::RemoveProperty (name=%s)\n", name.DebugString().c_str())); Error("RemoveProperty", name.DebugString().c_str(), "property removal is not supported", exception); } void ScriptablePlugin::GetAllPropertyNames(std::vector* properties, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::GetAllPropertyNames ()\n")); UNREFERENCED_PARAMETER(properties); UNREFERENCED_PARAMETER(exception); Error("GetAllPropertyNames", "", "GetAllPropertyNames is not supported", exception); } pp::Var ScriptablePlugin::Call(const pp::Var& name, const std::vector& args, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::Call (name=%s, %" NACL_PRIuS " args)\n", name.DebugString().c_str(), args.size())); return Error("Call", name.DebugString().c_str(), "method invocation is not supported", exception); } pp::Var ScriptablePlugin::Construct(const std::vector& args, pp::Var* exception) { PLUGIN_PRINTF(("ScriptablePlugin::Construct (%" NACL_PRIuS " args)\n", args.size())); return Error("constructor", "Construct", "constructor is not supported", exception); } ScriptablePlugin* ScriptablePlugin::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 pp::VarPrivate(plugin_, this); CHECK(var_ != NULL); } PLUGIN_PRINTF(("ScriptablePlugin::AddRef (this=%p, var=%p)\n", static_cast(this), static_cast(var_))); return this; } void ScriptablePlugin::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(("ScriptablePlugin::Unref (this=%p, var=%p)\n", static_cast(this), static_cast(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(("ScriptablePlugin::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(("ScriptablePlugin::Unref (delete this)\n")); CHECK(var_ == NULL); delete this; } } } // namespace plugin