| Index: src/trusted/plugin/srpc/plugin.cc
|
| ===================================================================
|
| --- src/trusted/plugin/srpc/plugin.cc (revision 2716)
|
| +++ src/trusted/plugin/srpc/plugin.cc (working copy)
|
| @@ -1,636 +0,0 @@
|
| -/*
|
| - * Copyright 2008 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.
|
| - */
|
| -
|
| -#include "native_client/src/trusted/plugin/srpc/plugin.h"
|
| -
|
| -#include <assert.h>
|
| -#include <fcntl.h>
|
| -#include <stdarg.h>
|
| -#include <stdio.h>
|
| -#include <stdlib.h>
|
| -#include <string.h>
|
| -
|
| -#include <sys/types.h>
|
| -#include <sys/stat.h>
|
| -
|
| -#include "native_client/src/include/nacl_string.h"
|
| -#include "native_client/src/include/portability_string.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_base.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
|
| -#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
|
| -#include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
|
| -#include "native_client/src/trusted/plugin/npapi/video.h"
|
| -#include "native_client/src/trusted/plugin/origin.h"
|
| -#include "native_client/src/trusted/plugin/srpc/browser_interface.h"
|
| -#include "native_client/src/trusted/plugin/srpc/connected_socket.h"
|
| -#include "native_client/src/trusted/plugin/srpc/nexe_arch.h"
|
| -#include "native_client/src/trusted/plugin/srpc/scriptable_handle.h"
|
| -#include "native_client/src/trusted/plugin/srpc/service_runtime.h"
|
| -#include "native_client/src/trusted/plugin/srpc/shared_memory.h"
|
| -#include "native_client/src/trusted/plugin/srpc/socket_address.h"
|
| -#include "native_client/src/trusted/plugin/srpc/stream_shm_buffer.h"
|
| -#include "native_client/src/trusted/plugin/srpc/string_encoding.h"
|
| -#include "native_client/src/trusted/plugin/srpc/utility.h"
|
| -
|
| -namespace {
|
| -
|
| -static int32_t stringToInt32(char* src) {
|
| - return strtol(src, // NOLINT(runtime/deprecated_fn)
|
| - static_cast<char**>(NULL), 0);
|
| -}
|
| -
|
| -// TODO(sehr): using a static jmpbuf here has several problems. Notably we
|
| -// cannot reliably handle errors when there are multiple plugins in the same
|
| -// process. Issue 605.
|
| -PLUGIN_JMPBUF g_LoaderEnv;
|
| -
|
| -bool ShmFactory(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| -
|
| - plugin::SharedMemory* portable_shared_memory =
|
| - plugin::SharedMemory::New(plugin, params->ins()[0]->u.ival);
|
| - plugin::ScriptableHandle* shared_memory =
|
| - plugin->browser_interface()->NewScriptableHandle(portable_shared_memory);
|
| - if (NULL == shared_memory) {
|
| - params->set_exception_string("out of memory");
|
| - portable_shared_memory->Delete();
|
| - return false;
|
| - }
|
| -
|
| - params->outs()[0]->tag = NACL_SRPC_ARG_TYPE_OBJECT;
|
| - params->outs()[0]->u.oval = shared_memory;
|
| - return true;
|
| -}
|
| -
|
| -bool DefaultSocketAddress(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - if (NULL == plugin->socket_address()) {
|
| - params->set_exception_string("no socket address");
|
| - return false;
|
| - }
|
| - plugin->socket_address()->AddRef();
|
| - // Plug the scriptable object into the return values.
|
| - params->outs()[0]->tag = NACL_SRPC_ARG_TYPE_OBJECT;
|
| - params->outs()[0]->u.oval = plugin->socket_address();
|
| - return true;
|
| -}
|
| -
|
| -// A method to test the cost of invoking a method in a plugin without
|
| -// making an RPC to the service runtime. Used for performance evaluation.
|
| -bool NullPluginMethod(void* obj, plugin::SrpcParams* params) {
|
| - UNREFERENCED_PARAMETER(obj);
|
| - params->outs()[0]->tag = NACL_SRPC_ARG_TYPE_INT;
|
| - params->outs()[0]->u.ival = 0;
|
| - return true;
|
| -}
|
| -
|
| -bool GetModuleReadyProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - if (plugin->socket()) {
|
| - params->outs()[0]->u.ival = 1;
|
| - } else {
|
| - params->outs()[0]->u.ival = 0;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool SetModuleReadyProperty(void* obj, plugin::SrpcParams* params) {
|
| - UNREFERENCED_PARAMETER(obj);
|
| - params->set_exception_string("__moduleReady is a read-only property");
|
| - return false;
|
| -}
|
| -
|
| -bool GetNexesProperty(void* obj, plugin::SrpcParams* params) {
|
| - UNREFERENCED_PARAMETER(obj);
|
| - UNREFERENCED_PARAMETER(params);
|
| - // Note, "get" must be present in the method map for "set" to work.
|
| - PLUGIN_PRINTF(("GetNexesProperty not yet implemented.\n"));
|
| - return false;
|
| -}
|
| -
|
| -// Update "nexes", a write-only property that computes a value to
|
| -// assign to the "src" property based on the supported sandbox.
|
| -bool SetNexesProperty(void* obj, plugin::SrpcParams* params) {
|
| - return reinterpret_cast<plugin::Plugin*>(obj)->
|
| - SetNexesPropertyImpl(params->ins()[0]->u.sval);
|
| -}
|
| -
|
| -bool GetSrcProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - if (plugin->logical_url() != NULL) {
|
| - params->outs()[0]->u.sval = strdup(plugin->logical_url());
|
| - PLUGIN_PRINTF(("GetSrcProperty 'src' = %s\n", plugin->logical_url()));
|
| - return true;
|
| - } else {
|
| - // (NULL is not an acceptable SRPC result.)
|
| - PLUGIN_PRINTF(("GetSrcProperty 'src' failed\n"));
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool SetSrcProperty(void* obj, plugin::SrpcParams* params) {
|
| - PLUGIN_PRINTF(("SetSrcProperty\n"));
|
| - return reinterpret_cast<plugin::Plugin*>(obj)->
|
| - SetSrcPropertyImpl(params->ins()[0]->u.sval);
|
| -}
|
| -
|
| -bool GetHeightProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - params->outs()[0]->u.ival = plugin->height();
|
| - return true;
|
| -}
|
| -
|
| -bool SetHeightProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - plugin->set_height(params->ins()[0]->u.ival);
|
| - return true;
|
| -}
|
| -
|
| -bool GetWidthProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - params->outs()[0]->u.ival = plugin->width();
|
| - return true;
|
| -}
|
| -
|
| -bool SetWidthProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - plugin->set_width(params->ins()[0]->u.ival);
|
| - return true;
|
| -}
|
| -
|
| -bool GetVideoUpdateModeProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - params->outs()[0]->u.ival = plugin->video_update_mode();
|
| - return true;
|
| -}
|
| -
|
| -bool SetVideoUpdateModeProperty(void* obj, plugin::SrpcParams* params) {
|
| - plugin::Plugin* plugin = reinterpret_cast<plugin::Plugin*>(obj);
|
| - plugin->set_video_update_mode(params->ins()[0]->u.ival);
|
| - return true;
|
| -}
|
| -
|
| -void SignalHandler(int value) {
|
| - PLUGIN_PRINTF(("Plugin::SignalHandler()\n"));
|
| - PLUGIN_LONGJMP(g_LoaderEnv, value);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace plugin {
|
| -
|
| -// TODO(mseaborn): Although this will usually not block, it will
|
| -// block if the socket's buffer fills up.
|
| -bool Plugin::SendAsyncMessage(void* obj, SrpcParams* params,
|
| - nacl::DescWrapper** fds, int fds_count) {
|
| - Plugin* plugin = reinterpret_cast<Plugin*>(obj);
|
| - if (plugin->service_runtime_ == NULL) {
|
| - params->set_exception_string("No subprocess running");
|
| - return false;
|
| - }
|
| -
|
| - // TODO(mseaborn): Handle strings containing NULLs. This might
|
| - // involve using a different SRPC type.
|
| - char* utf8string = params->ins()[0]->u.sval;
|
| - char* data;
|
| - size_t data_size;
|
| - if (!ByteStringFromUTF8(utf8string, strlen(utf8string), &data, &data_size)) {
|
| - params->set_exception_string("Invalid string");
|
| - return false;
|
| - }
|
| - nacl::DescWrapper::MsgIoVec iov;
|
| - nacl::DescWrapper::MsgHeader message;
|
| - iov.base = data;
|
| - iov.length = static_cast<nacl_abi_size_t>(data_size);
|
| - message.iov = &iov;
|
| - message.iov_length = 1;
|
| - message.ndescv = fds;
|
| - message.ndescv_length = fds_count;
|
| - message.flags = 0;
|
| - nacl::DescWrapper* socket = plugin->service_runtime_->async_send_desc;
|
| - ssize_t sent = socket->SendMsg(&message, 0);
|
| - free(data);
|
| - if (sent < 0) {
|
| - params->set_exception_string("Error sending message");
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -// TODO(mseaborn): Combine __sendAsyncMessage0 and __sendAsyncMessage1
|
| -// into a single method that takes an array of FDs. SRPC does not
|
| -// provide a handle array type so there is not a simple way to do
|
| -// this.
|
| -bool Plugin::SendAsyncMessage0(void* obj, SrpcParams* params) {
|
| - return SendAsyncMessage(obj, params, NULL, 0);
|
| -}
|
| -
|
| -bool Plugin::SendAsyncMessage1(void* obj, SrpcParams* params) {
|
| - Plugin* plugin = reinterpret_cast<Plugin*>(obj);
|
| - nacl::DescWrapper* fd_to_send =
|
| - plugin->wrapper_factory()->MakeGeneric(params->ins()[1]->u.hval);
|
| - return SendAsyncMessage(obj, params, &fd_to_send, 1);
|
| -}
|
| -
|
| -static int const kAbiHeaderBuffer = 256; // must be at least EI_ABIVERSION + 1
|
| -
|
| -void Plugin::LoadMethods() {
|
| - // Methods supported by Plugin.
|
| - AddMethodCall(ShmFactory, "__shmFactory", "i", "h");
|
| - AddMethodCall(DefaultSocketAddress, "__defaultSocketAddress", "", "h");
|
| - AddMethodCall(NullPluginMethod, "__nullPluginMethod", "s", "i");
|
| - AddMethodCall(SendAsyncMessage0, "__sendAsyncMessage0", "s", "");
|
| - AddMethodCall(SendAsyncMessage1, "__sendAsyncMessage1", "sh", "");
|
| - // Properties implemented by Plugin.
|
| - AddPropertyGet(GetHeightProperty, "height", "i");
|
| - AddPropertySet(SetHeightProperty, "height", "i");
|
| - AddPropertyGet(GetModuleReadyProperty, "__moduleReady", "i");
|
| - AddPropertySet(SetModuleReadyProperty, "__moduleReady", "i");
|
| - AddPropertyGet(GetNexesProperty, "nexes", "s");
|
| - AddPropertySet(SetNexesProperty, "nexes", "s");
|
| - AddPropertyGet(GetSrcProperty, "src", "s");
|
| - AddPropertySet(SetSrcProperty, "src", "s");
|
| - AddPropertyGet(GetVideoUpdateModeProperty, "videoUpdateMode", "i");
|
| - AddPropertySet(SetVideoUpdateModeProperty, "videoUpdateMode", "i");
|
| - AddPropertyGet(GetWidthProperty, "width", "i");
|
| - AddPropertySet(SetWidthProperty, "width", "i");
|
| -}
|
| -
|
| -bool Plugin::HasMethodEx(uintptr_t method_id, CallType call_type) {
|
| - if (NULL == socket_) {
|
| - return false;
|
| - }
|
| - return socket_->handle()->HasMethod(method_id, call_type);
|
| -}
|
| -
|
| -bool Plugin::InvokeEx(uintptr_t method_id,
|
| - CallType call_type,
|
| - SrpcParams* params) {
|
| - if (NULL == socket_) {
|
| - return false;
|
| - }
|
| - return socket_->handle()->Invoke(method_id, call_type, params);
|
| -}
|
| -
|
| -bool Plugin::InitParamsEx(uintptr_t method_id,
|
| - CallType call_type,
|
| - SrpcParams* params) {
|
| - if (NULL == socket_) {
|
| - return false;
|
| - }
|
| - return socket_->handle()->InitParams(method_id, call_type, params);
|
| -}
|
| -
|
| -
|
| -bool Plugin::SetNexesPropertyImpl(const char* nexes_attr) {
|
| - PLUGIN_PRINTF(("Plugin::SetNexesPropertyImpl: %s\n", nexes_attr));
|
| - nacl::string result;
|
| - if (!GetNexeURL(nexes_attr, &result)) {
|
| - // TODO(adonovan): Ideally we would print to the browser's
|
| - // JavaScript console: alert popups are annoying, and no-one can
|
| - // be expected to read stderr.
|
| - PLUGIN_PRINTF(("%s\n", result.c_str()));
|
| - browser_interface()->Alert(instance_id(), result);
|
| - return false;
|
| - } else {
|
| - return SetSrcPropertyImpl(result);
|
| - }
|
| -}
|
| -
|
| -bool Plugin::SetSrcPropertyImpl(const nacl::string& url) {
|
| - if (NULL != service_runtime_) {
|
| - PLUGIN_PRINTF(("Plugin::SetProperty: unloading previous\n"));
|
| - // Plugin owns socket_address_ and socket_, so when we change to a new
|
| - // socket we need to give up ownership of the old one.
|
| - socket_address_->Unref();
|
| - socket_address_ = NULL;
|
| - socket_->Unref();
|
| - socket_ = NULL;
|
| - service_runtime_->Shutdown();
|
| - delete service_runtime_;
|
| - service_runtime_ = NULL;
|
| - ShutDownReceiveThread();
|
| - }
|
| - return RequestNaClModule(url);
|
| -}
|
| -
|
| -bool Plugin::Init(BrowserInterface* browser_interface,
|
| - InstanceIdentifier instance_id,
|
| - int argc,
|
| - char* argn[],
|
| - char* argv[]) {
|
| - PLUGIN_PRINTF(("Plugin::Init: instance_id=%p\n",
|
| - reinterpret_cast<void*>(instance_id)));
|
| -
|
| - browser_interface_ = browser_interface;
|
| - instance_id_ = instance_id;
|
| - // Remember the embed/object argn/argv pairs.
|
| - argn_ = new(std::nothrow) char*[argc];
|
| - argv_ = new(std::nothrow) char*[argc];
|
| - argc_ = 0;
|
| - // Set up the height and width attributes if passed (for Opera)
|
| - for (int i = 0; i < argc; ++i) {
|
| - if (!strncmp(argn[i], "height", 7)) {
|
| - set_height(stringToInt32(argv[i]));
|
| - } else if (!strncmp(argn[i], "width", 6)) {
|
| - set_width(stringToInt32(argv[i]));
|
| - } else if (!strncmp(argn[i], "update", 7)) {
|
| - set_video_update_mode(stringToInt32(argv[i]));
|
| - } else {
|
| - if (NULL != argn_ && NULL != argv_) {
|
| - argn_[argc_] = strdup(argn[i]);
|
| - argv_[argc_] = strdup(argv[i]);
|
| - if (NULL == argn_[argc_] ||
|
| - NULL == argv_[argc_]) {
|
| - // Give up on passing arguments.
|
| - free(argn_[argc_]);
|
| - free(argv_[argc_]);
|
| - continue;
|
| - }
|
| - ++argc_;
|
| - }
|
| - }
|
| - }
|
| - // TODO(sehr): this leaks strings if there is a subsequent failure.
|
| -
|
| - // Set up the factory used to produce DescWrappers.
|
| - wrapper_factory_ = new nacl::DescWrapperFactory();
|
| - if (NULL == wrapper_factory_) {
|
| - return false;
|
| - }
|
| - PLUGIN_PRINTF(("Plugin::Init: wrapper_factory=%p\n",
|
| - reinterpret_cast<void*>(wrapper_factory_)));
|
| -
|
| - // Check that the origin is allowed.
|
| - nacl::string href = "";
|
| - if (browser_interface_->GetOrigin(instance_id_, &href)) {
|
| - origin_ = nacl::UrlToOrigin(href);
|
| - PLUGIN_PRINTF(("Plugin::Init: origin=%s\n", origin_.c_str()));
|
| - // Check that origin is in the list of permitted origins.
|
| - origin_valid_ = nacl::OriginIsInWhitelist(origin_);
|
| - // This implementation of same-origin policy does not take
|
| - // document.domain element into account.
|
| - }
|
| -
|
| - // Set up the scriptable methods for the plugin.
|
| - LoadMethods();
|
| -
|
| - // If the <embed src='...'> attr was defined, the browser would have
|
| - // implicitly called GET on it, which calls Load() and set_logical_url().
|
| - // In the absence of this attr, we use the "nexes" attribute if present.
|
| - if (logical_url() == NULL) {
|
| - const char* nexes_attr = LookupArgument("nexes");
|
| - if (nexes_attr != NULL) {
|
| - SetNexesPropertyImpl(nexes_attr);
|
| - }
|
| - }
|
| -
|
| - PLUGIN_PRINTF(("Plugin::Init: done\n"));
|
| - // Return success.
|
| - return true;
|
| -}
|
| -
|
| -Plugin::Plugin()
|
| - : service_runtime_(NULL),
|
| - receive_thread_running_(false),
|
| - argc_(-1),
|
| - argn_(NULL),
|
| - argv_(NULL),
|
| - socket_address_(NULL),
|
| - socket_(NULL),
|
| - local_url_(NULL),
|
| - logical_url_(NULL),
|
| - origin_valid_(false),
|
| - height_(0),
|
| - width_(0),
|
| - video_update_mode_(kVideoUpdatePluginPaint),
|
| - wrapper_factory_(NULL) {
|
| - PLUGIN_PRINTF(("Plugin::Plugin(%p)\n", static_cast<void*>(this)));
|
| -}
|
| -
|
| -void Plugin::Invalidate() {
|
| - socket_address_ = NULL;
|
| - socket_ = NULL;
|
| -}
|
| -
|
| -void Plugin::ShutDownReceiveThread() {
|
| - if (receive_thread_running_) {
|
| - NaClThreadJoin(&receive_thread_);
|
| - receive_thread_running_ = false;
|
| - }
|
| -}
|
| -
|
| -Plugin::~Plugin() {
|
| - PLUGIN_PRINTF(("Plugin::~Plugin(%p)\n", static_cast<void*>(this)));
|
| -
|
| - // After invalidation, the browser does not respect reference counting,
|
| - // so we shut down here what we can and prevent attempts to shut down
|
| - // other linked structures in Deallocate.
|
| -
|
| - // Free the socket address for this plugin, if any.
|
| - if (NULL != socket_address_) {
|
| - PLUGIN_PRINTF(("Plugin::~Plugin: unloading\n"));
|
| - // Deallocating a plugin releases ownership of the socket address.
|
| - socket_address_->Unref();
|
| - }
|
| - // Free the connected socket for this plugin, if any.
|
| - if (NULL != socket_) {
|
| - PLUGIN_PRINTF(("Plugin::~Plugin: unloading\n"));
|
| - // Deallocating a plugin releases ownership of the socket.
|
| - socket_->Unref();
|
| - }
|
| - // Clear the pointers to the connected socket and service runtime interface.
|
| - socket_address_ = NULL;
|
| - socket_ = NULL;
|
| - delete service_runtime_;
|
| - service_runtime_ = NULL;
|
| - ShutDownReceiveThread();
|
| - PLUGIN_PRINTF(("Plugin::~Plugin(%p)\n", static_cast<void*>(this)));
|
| - free(local_url_);
|
| - free(logical_url_);
|
| -}
|
| -
|
| -void Plugin::set_local_url(const char* url) {
|
| - PLUGIN_PRINTF(("Plugin::set_local_url(%s)\n", url));
|
| - if (local_url_ != NULL) free(local_url_);
|
| - local_url_ = strdup(url);
|
| -}
|
| -
|
| -void Plugin::set_logical_url(const char* url) {
|
| - PLUGIN_PRINTF(("Plugin::set_logical_url(%s)\n", url));
|
| - if (logical_url_ != NULL) free(logical_url_);
|
| - logical_url_ = strdup(url);
|
| -}
|
| -
|
| -// Create a new service node from a downloaded service.
|
| -bool Plugin::Load(nacl::string logical_url, const char* local_url) {
|
| - return Load(logical_url, local_url, static_cast<StreamShmBuffer*>(NULL));
|
| -}
|
| -
|
| -bool Plugin::Load(nacl::string logical_url,
|
| - const char* local_url,
|
| - StreamShmBuffer* shmbufp) {
|
| - BrowserInterface* browser_interface = this->browser_interface();
|
| -
|
| - if (NULL == shmbufp) {
|
| - PLUGIN_PRINTF(("Plugin::Load(%s)\n", local_url));
|
| - } else {
|
| - PLUGIN_PRINTF(("Plugin::Load(%p)\n", reinterpret_cast<void*>(shmbufp)));
|
| - }
|
| -
|
| - // Save the origin and local_url.
|
| - set_nacl_module_origin(nacl::UrlToOrigin(logical_url));
|
| - set_logical_url(logical_url.c_str());
|
| - set_local_url(local_url);
|
| - // If the page origin where the EMBED/OBJECT tag occurs is not in
|
| - // the whitelist, refuse to load. If the NaCl module's origin is
|
| - // not in the whitelist, also refuse to load.
|
| - // TODO(adonovan): JavaScript permits cross-origin loading, and so
|
| - // does Chrome ; why don't we?
|
| - if (!origin_valid_ || !nacl::OriginIsInWhitelist(nacl_module_origin())) {
|
| - nacl::string message = nacl::string("Load failed: NaCl module ") +
|
| - logical_url + " does not come ""from a whitelisted source. "
|
| - "See native_client/src/trusted/plugin/origin.cc for the list.";
|
| - browser_interface->Alert(instance_id(), message.c_str());
|
| - return false;
|
| - }
|
| - // Catch any bad accesses, etc., while loading.
|
| - ScopedCatchSignals sigcatcher(
|
| - (ScopedCatchSignals::SigHandlerType) SignalHandler);
|
| - if (PLUGIN_SETJMP(g_LoaderEnv, 1)) {
|
| - return false;
|
| - }
|
| -
|
| - PLUGIN_PRINTF(("Load: NaCl module from '%s'\n", local_url_));
|
| -
|
| - // Check ELF magic and ABI version compatibility.
|
| - bool success = false;
|
| - nacl::string error_string;
|
| - if (NULL == shmbufp) {
|
| - success = browser_interface->MightBeElfExecutable(local_url_,
|
| - &error_string);
|
| - } else {
|
| - // Read out first chunk for MightBeElfExecutable; this suffices for
|
| - // ELF headers etc.
|
| - char elf_hdr_buf[kAbiHeaderBuffer];
|
| - ssize_t result;
|
| - result = shmbufp->read(0, sizeof elf_hdr_buf, elf_hdr_buf);
|
| - if (sizeof elf_hdr_buf == result) { // (const char*)(elf_hdr_buf)
|
| - success = browser_interface->MightBeElfExecutable(elf_hdr_buf,
|
| - sizeof elf_hdr_buf,
|
| - &error_string);
|
| - }
|
| - }
|
| - if (!success) {
|
| - browser_interface->Alert(instance_id(), error_string);
|
| - return false;
|
| - }
|
| - // Load a file via a forked sel_ldr process.
|
| - service_runtime_ = new(std::nothrow) ServiceRuntime(browser_interface, this);
|
| - if (NULL == service_runtime_) {
|
| - PLUGIN_PRINTF((" ServiceRuntime Ctor failed\n"));
|
| - browser_interface->Alert(instance_id(),
|
| - "ServiceRuntime Ctor failed");
|
| - return false;
|
| - }
|
| - bool service_runtime_started = false;
|
| - if (NULL == shmbufp) {
|
| - service_runtime_started = service_runtime_->Start(local_url_);
|
| - } else {
|
| - int32_t size;
|
| - NaClDesc* raw_desc = shmbufp->shm(&size);
|
| - if (NULL == raw_desc) {
|
| - PLUGIN_PRINTF((" extracting shm failed\n"));
|
| - return false;
|
| - }
|
| - nacl::DescWrapper* wrapped_shm =
|
| - wrapper_factory_->MakeGeneric(NaClDescRef(raw_desc));
|
| - service_runtime_started = service_runtime_->Start(local_url_, wrapped_shm);
|
| - // Start consumes the wrapped_shm.
|
| - }
|
| - if (!service_runtime_started) {
|
| - PLUGIN_PRINTF((" Load: FAILED to start service runtime"));
|
| - browser_interface->Alert(instance_id(),
|
| - "Load: FAILED to start service runtime");
|
| - return false;
|
| - }
|
| -
|
| - PLUGIN_PRINTF((" Load: started sel_ldr\n"));
|
| - socket_address_ = service_runtime_->default_socket_address();
|
| - PLUGIN_PRINTF((" Load: established socket address %p\n",
|
| - static_cast<void*>(socket_address_)));
|
| - socket_ = service_runtime_->default_socket();
|
| - PLUGIN_PRINTF((" Load: established socket %p\n",
|
| - static_cast<void*>(socket_)));
|
| - // Plugin takes ownership of socket_ from service_runtime_,
|
| - // so we do not need to call NPN_RetainObject.
|
| - // Invoke the onload handler, if any.
|
| - RunOnloadHandler();
|
| - return true;
|
| -}
|
| -
|
| -bool Plugin::LogAtServiceRuntime(int severity, nacl::string msg) {
|
| - return service_runtime_->Log(severity, msg);
|
| -}
|
| -
|
| -char* Plugin::LookupArgument(const char* key) {
|
| - char** keys = argn();
|
| - for (int ii = 0, len = argc(); ii < len; ++ii) {
|
| - if (!strcmp(keys[ii], key)) {
|
| - return argv()[ii];
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -bool Plugin::RunOnloadHandler() {
|
| - BrowserInterface* browser = browser_interface();
|
| - const char* onload_handler = LookupArgument("onload");
|
| - if (onload_handler == NULL) {
|
| - return true;
|
| - }
|
| - return browser->EvalString(instance_id(), onload_handler);
|
| -}
|
| -
|
| -bool Plugin::RunOnfailHandler() {
|
| - BrowserInterface* browser = browser_interface();
|
| - const char* onfail_handler = LookupArgument("onfail");
|
| - if (onfail_handler == NULL) {
|
| - return true;
|
| - }
|
| - return browser->EvalString(instance_id(), onfail_handler);
|
| -}
|
| -
|
| -// The NaCl audio/video interface uses a global mutex to protect observed
|
| -// timing-sensitive accesses to the plugin's window when starting up and
|
| -// shutting down. Because there is a relatively complex relationship between
|
| -// ConnectedSocket and Plugin to synchronize accesses, this code is built in
|
| -// both the NPAPI and PPAPI plugins. This is unfortunate, because only
|
| -// the NPAPI plugin (when not used as part of the Chrome integration) actually
|
| -// needs the locking.
|
| -// TODO(sehr): move this code to somewhere in the npapi directory.
|
| -class GlobalVideoMutex {
|
| - public:
|
| - GlobalVideoMutex() { NaClMutexCtor(&mutex_); }
|
| - ~GlobalVideoMutex() { NaClMutexDtor(&mutex_); }
|
| - void Lock() { NaClMutexLock(&mutex_); }
|
| - void Unlock() { NaClMutexUnlock(&mutex_); }
|
| -
|
| - private:
|
| - NaClMutex mutex_;
|
| -};
|
| -
|
| -static GlobalVideoMutex g_VideoMutex;
|
| -
|
| -void VideoGlobalLock() {
|
| - g_VideoMutex.Lock();
|
| -}
|
| -
|
| -void VideoGlobalUnlock() {
|
| - g_VideoMutex.Unlock();
|
| -}
|
| -
|
| -} // namespace plugin
|
|
|