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

Unified Diff: native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc

Issue 914983003: [NaCl SDK] Switch ppapi_simple to C library (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix tty output bug Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
deleted file mode 100644
index 63b85305cef79c0a0f2e44a74a7ae99b1643b8cf..0000000000000000000000000000000000000000
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
+++ /dev/null
@@ -1,612 +0,0 @@
-// 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.
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <termios.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <cstring>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "nacl_io/ioctl.h"
-#include "nacl_io/kernel_wrap.h"
-#include "nacl_io/log.h"
-#include "nacl_io/nacl_io.h"
-
-#include "ppapi/c/ppb_var.h"
-
-#include "ppapi/cpp/input_event.h"
-#include "ppapi/cpp/message_loop.h"
-#include "ppapi/cpp/module.h"
-#include "ppapi/cpp/rect.h"
-#include "ppapi/cpp/size.h"
-#include "ppapi/cpp/touch_point.h"
-#include "ppapi/cpp/var.h"
-#include "ppapi/cpp/var_array.h"
-#include "ppapi/cpp/var_dictionary.h"
-
-#include "ppapi_simple/ps_event.h"
-#include "ppapi_simple/ps_instance.h"
-#include "ppapi_simple/ps_interface.h"
-#include "ppapi_simple/ps_main.h"
-
-#if defined(WIN32)
-#define open _open
-#define dup2 _dup2
-#endif
-
-static PSInstance* s_InstanceObject = NULL;
-
-PSInstance* PSInstance::GetInstance() {
- return s_InstanceObject;
-}
-
-struct StartInfo {
- PSInstance* inst_;
- uint32_t argc_;
- char** argv_;
-};
-
-
-// The starting point for 'main'. We create this thread to hide the real
-// main pepper thread which must never be blocked.
-void* PSInstance::MainThreadThunk(void *info) {
- s_InstanceObject->Trace("Got MainThreadThunk.\n");
- StartInfo* si = static_cast<StartInfo*>(info);
- PSInstance* instance = si->inst_;
- instance->main_loop_ = new pp::MessageLoop(si->inst_);
- instance->main_loop_->AttachToCurrentThread();
-
- int ret = instance->MainThread(si->argc_, si->argv_);
-
- // Clean up StartInfo.
- for (uint32_t i = 0; i < si->argc_; i++) {
- delete[] si->argv_[i];
- }
- delete[] si->argv_;
- delete si;
-
- // Exit the entire process once the 'main' thread returns.
- // The error code will be available to javascript via
- // the exitcode parameter of the crash event.
-#ifdef __native_client__
- exit(ret);
-#else
- instance->ExitHandshake(ret);
-#endif
- return NULL;
-}
-
-void PSInstance::ExitHandshake(int status) {
- if (exit_message_ == NULL)
- return;
-
- RegisterMessageHandler(exit_message_, MessageHandlerExitStatic, this);
-
- // Send the exit message to JavaScript. Then wait
- // for the reply/confirmation.
- std::stringstream ss;
- ss << exit_message_ << ":" << status;
-
- pthread_mutex_lock(&exit_lock_);
- PostMessage(ss.str());
- pthread_cond_wait(&exit_cond_, &exit_lock_);
- pthread_mutex_unlock(&exit_lock_);
-}
-
-// The default implementation supports running a 'C' main.
-int PSInstance::MainThread(int argc, char* argv[]) {
- if (!main_cb_) {
- Error("No main defined.\n");
- return 0;
- }
-
- Trace("Starting MAIN.\n");
- int ret = main_cb_(argc, argv);
- Log("Main thread returned with %d.\n", ret);
-
- return ret;
-}
-
-PSInstance::PSInstance(PP_Instance instance)
- : pp::Instance(instance),
- pp::MouseLock(this),
- pp::Graphics3DClient(this),
- main_loop_(NULL),
- events_enabled_(PSE_NONE),
- verbosity_(PSV_WARN),
- tty_fd_(-1),
- tty_prefix_(NULL),
- exit_message_(NULL) {
-
- pthread_mutex_init(&exit_lock_, NULL);
- pthread_cond_init(&exit_cond_, NULL);
-
- // Set the single Instance object
- s_InstanceObject = this;
-
-#ifdef NACL_SDK_DEBUG
- SetVerbosity(PSV_LOG);
-#endif
-
- RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
- PP_INPUTEVENT_CLASS_KEYBOARD |
- PP_INPUTEVENT_CLASS_WHEEL |
- PP_INPUTEVENT_CLASS_TOUCH);
-}
-
-PSInstance::~PSInstance() {
- s_InstanceObject = NULL;
-}
-
-void PSInstance::SetMain(PSMainFunc_t main) {
- main_cb_ = main;
-}
-
-bool PSInstance::Init(uint32_t arg,
- const char* argn[],
- const char* argv[]) {
- StartInfo* si = new StartInfo;
-
- si->inst_ = this;
- si->argc_ = 0;
- si->argv_ = new char *[arg+1];
- si->argv_[0] = NULL;
-
- // Process embed attributes into the environment.
- // Converted the attribute names to uppercase as environment variables are
- // case sensitive but are almost universally uppercase in practice.
- for (uint32_t i = 0; i < arg; i++) {
- std::string key = argn[i];
- std::transform(key.begin(), key.end(), key.begin(), toupper);
- setenv(key.c_str(), argv[i], 1);
- }
-
- // Set a default value for SRC.
- setenv("SRC", "NMF?", 0);
- // Use the src tag name if ARG0 is not explicitly specified.
- setenv("ARG0", getenv("SRC"), 0);
-
- // Walk ARG0..ARGn populating argv until an argument is missing.
- for (;;) {
- std::ostringstream arg_stream;
- arg_stream << "ARG" << si->argc_;
- std::string arg_name = arg_stream.str();
- const char* next_arg = getenv(arg_name.c_str());
- if (NULL == next_arg)
- break;
-
- char* value = new char[strlen(next_arg) + 1];
- strcpy(value, next_arg);
- si->argv_[si->argc_++] = value;
- }
-
- PSInterfaceInit();
- bool props_processed = ProcessProperties();
-
- // Log arg values only once ProcessProperties has been
- // called so that the ps_verbosity attribute will be in
- // effect.
- for (uint32_t i = 0; i < arg; i++) {
- if (argv[i]) {
- Trace("attribs[%d] '%s=%s'\n", i, argn[i], argv[i]);
- } else {
- Trace("attribs[%d] '%s'\n", i, argn[i]);
- }
- }
-
- for (uint32_t i = 0; i < si->argc_; i++) {
- Trace("argv[%d] '%s'\n", i, si->argv_[i]);
- }
-
- if (!props_processed) {
- Warn("Skipping create thread.\n");
- return false;
- }
-
- pthread_t main_thread;
- int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si);
- Trace("Created thread: %d.\n", ret);
- return ret == 0;
-}
-
-// Processes the properties set at compile time via the
-// initialization macro, or via dynamically set embed attributes
-// through instance DidCreate.
-bool PSInstance::ProcessProperties() {
- // Reset verbosity if passed in
- const char* verbosity = getenv("PS_VERBOSITY");
- if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));
-
- // Enable NaCl IO to map STDIN, STDOUT, and STDERR
- nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
-
- tty_prefix_ = getenv("PS_TTY_PREFIX");
- if (tty_prefix_) {
- tty_fd_ = open("/dev/tty", O_WRONLY);
- if (tty_fd_ >= 0) {
- RegisterMessageHandler(tty_prefix_, MessageHandlerInputStatic, this);
- const char* tty_resize = getenv("PS_TTY_RESIZE");
- if (tty_resize)
- RegisterMessageHandler(tty_resize, MessageHandlerResizeStatic, this);
-
- char* tty_rows = getenv("PS_TTY_ROWS");
- char* tty_cols = getenv("PS_TTY_COLS");
- if (tty_rows && tty_cols) {
- char* end = tty_rows;
- int rows = strtol(tty_rows, &end, 10);
- if (*end != '\0' || rows < 0) {
- Error("Invalid value for PS_TTY_ROWS: %s\n", tty_rows);
- } else {
- end = tty_cols;
- int cols = strtol(tty_cols, &end, 10);
- if (*end != '\0' || cols < 0)
- Error("Invalid value for PS_TTY_COLS: %s\n", tty_cols);
- else
- HandleResize(cols, rows);
- }
- }
- else if (tty_rows || tty_cols) {
- Error("PS_TTY_ROWS and PS_TTY_COLS must be set together\n");
- }
-
- tioc_nacl_output handler;
- handler.handler = TtyOutputHandlerStatic;
- handler.user_data = this;
- ioctl(tty_fd_, TIOCNACLOUTPUT, &handler);
- } else {
- Error("Failed to open /dev/tty.\n");
- }
- }
-
- // Set default values
- setenv("PS_STDIN", "/dev/stdin", 0);
- setenv("PS_STDOUT", "/dev/stdout", 0);
- setenv("PS_STDERR", "/dev/console3", 0);
-
- int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
- dup2(fd0, 0);
-
- int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
- dup2(fd1, 1);
-
- int fd2 = open(getenv("PS_STDERR"), O_WRONLY);
- dup2(fd2, 2);
-
- RegisterMessageHandler("jspipe1", MessageHandlerInputStatic, this);
- RegisterMessageHandler("jspipe2", MessageHandlerInputStatic, this);
- RegisterMessageHandler("jspipe3", MessageHandlerInputStatic, this);
-
- exit_message_ = getenv("PS_EXIT_MESSAGE");
-
- // If PS_EXIT_MESSAGE is set in the environment then we perform a handshake
- // with JavaScript when program exits.
- if (exit_message_ != NULL)
- nacl_io_set_exit_callback(HandleExitStatic, this);
-
- // Set line buffering on stdout and stderr
-#if !defined(WIN32)
- setvbuf(stderr, NULL, _IOLBF, 0);
- setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
- return true;
-}
-
-void PSInstance::SetVerbosity(Verbosity verbosity) {
- verbosity_ = verbosity;
-}
-
-void PSInstance::VALog(Verbosity verbosity, const char *fmt, va_list args) {
- if (verbosity <= verbosity_) {
- fprintf(stderr, "ps: ");
- vfprintf(stderr, fmt, args);
- }
-}
-
-void PSInstance::Trace(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- VALog(PSV_TRACE, fmt, ap);
- va_end(ap);
-}
-
-void PSInstance::Log(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- VALog(PSV_LOG, fmt, ap);
- va_end(ap);
-}
-
-void PSInstance::Warn(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- VALog(PSV_WARN, fmt, ap);
- va_end(ap);
-}
-
-void PSInstance::Error(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- VALog(PSV_ERROR, fmt, ap);
- va_end(ap);
-}
-
-void PSInstance::SetEnabledEvents(uint32_t mask) {
- events_enabled_ = mask;
- if (mask == 0) {
- static bool warn_once = true;
- if (warn_once) {
- Warn("PSInstance::SetEnabledEvents(mask) where mask == 0 will block\n");
- Warn("all events. This can come from PSEventSetFilter(PSE_NONE);\n");
- warn_once = false;
- }
- }
-}
-
-void PSInstance::PostEvent(PSEventType type) {
- assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST == type ||
- PSE_MOUSELOCK_MOUSELOCKLOST == type);
-
- PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
- memset(env, 0, sizeof(*env));
- env->type = type;
- event_queue_.Enqueue(env);
-}
-
-void PSInstance::PostEvent(PSEventType type, PP_Bool bool_value) {
- assert(PSE_INSTANCE_DIDCHANGEFOCUS == type);
-
- PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
- memset(env, 0, sizeof(*env));
- env->type = type;
- env->as_bool = bool_value;
- event_queue_.Enqueue(env);
-}
-
-void PSInstance::PostEvent(PSEventType type, PP_Resource resource) {
- assert(PSE_INSTANCE_HANDLEINPUT == type ||
- PSE_INSTANCE_DIDCHANGEVIEW == type);
-
- if (resource) {
- PSInterfaceCore()->AddRefResource(resource);
- }
- PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
- memset(env, 0, sizeof(*env));
- env->type = type;
- env->as_resource = resource;
- event_queue_.Enqueue(env);
-}
-
-ssize_t PSInstance::TtyOutputHandler(const char* buf, size_t count) {
- // We prepend the prefix_ to the data in buf, then package it up
- // and post it as a message to javascript.
- const char* data = static_cast<const char*>(buf);
- std::string message = tty_prefix_;
- message.append(data, count);
- PostMessage(pp::Var(message));
- return count;
-}
-
-void PSInstance::MessageHandlerExit(const pp::Var& message) {
- assert(message.is_string());
- pthread_mutex_lock(&exit_lock_);
- pthread_cond_signal(&exit_cond_);
- pthread_mutex_unlock(&exit_lock_);
-}
-
-void PSInstance::MessageHandlerInput(const pp::Var& key,
- const pp::Var& message) {
- std::string key_string = key.AsString();
-
- const char* filename = NULL;
- if (key_string == tty_prefix_) {
- filename = "/dev/tty";
- } else if (key_string == "jspipe1") {
- filename = "/dev/jspipe1";
- } else if (key_string == "jspipe2") {
- filename = "/dev/jspipe2";
- } else if (key_string == "jspipe3") {
- filename = "/dev/jspipe3";
- } else {
- Error("unexpected input key: %s", key_string.c_str());
- return;
- }
-
- int fd = open(filename, O_RDONLY);
- if (fd < 0) {
- Error("error opening file: %s (%s)", filename, strerror(errno));
- return;
- }
-
- int ret = ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message.pp_var());
- if (ret != 0) {
- Error("ioctl on %s failed: %d.\n", filename, ret);
- close(fd);
- return;
- }
-
- close(fd);
-}
-
-void PSInstance::HandleExitStatic(int status, void* user_data) {
- PSInstance* instance = static_cast<PSInstance*>(user_data);
- instance->ExitHandshake(status);
-}
-
-void PSInstance::HandleResize(int width, int height) {
- struct winsize size;
- memset(&size, 0, sizeof(size));
- size.ws_col = width;
- size.ws_row = height;
- ioctl(tty_fd_, TIOCSWINSZ, &size);
-}
-
-void PSInstance::MessageHandlerResize(const pp::Var& message) {
- assert(message.is_array());
- pp::VarArray array(message);
- assert(array.GetLength() == 2);
-
- int width = array.Get(0).AsInt();
- int height = array.Get(1).AsInt();
- HandleResize(width, height);
-}
-
-ssize_t PSInstance::TtyOutputHandlerStatic(const char* buf,
- size_t count,
- void* user_data) {
- PSInstance* instance = static_cast<PSInstance*>(user_data);
- return instance->TtyOutputHandler(buf, count);
-}
-
-void PSInstance::MessageHandlerExitStatic(const pp::Var& key,
- const pp::Var& value,
- void* user_data) {
- PSInstance* instance = static_cast<PSInstance*>(user_data);
- instance->MessageHandlerExit(value);
-}
-
-void PSInstance::MessageHandlerInputStatic(const pp::Var& key,
- const pp::Var& value,
- void* user_data) {
- PSInstance* instance = static_cast<PSInstance*>(user_data);
- instance->MessageHandlerInput(key, value);
-}
-
-void PSInstance::MessageHandlerResizeStatic(const pp::Var& key,
- const pp::Var& value,
- void* user_data) {
- PSInstance* instance = static_cast<PSInstance*>(user_data);
- instance->MessageHandlerResize(value);
-}
-
-void PSInstance::RegisterMessageHandler(std::string message_name,
- MessageHandler_t handler,
- void* user_data) {
- Trace("registering msg handler: %s\n", message_name.c_str());
- if (handler == NULL) {
- message_handlers_.erase(message_name);
- return;
- }
-
- MessageHandler message_handler = { handler, user_data };
- message_handlers_[message_name] = message_handler;
-}
-
-void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
- assert(PSE_INSTANCE_HANDLEMESSAGE == type);
-
- pp::Var event(var);
-
- // If the message is a dictionary then see if it matches one
- // of the specific handlers, then call that handler rather than
- // queuing an event.
- if (event.is_dictionary()) {
- pp::VarDictionary dictionary(var);
- pp::VarArray keys = dictionary.GetKeys();
- if (keys.GetLength() == 1) {
- pp::Var key = keys.Get(0);
- Trace("calling handler for: %s\n", key.AsString().c_str());
- MessageHandlerMap::iterator iter = message_handlers_.find(key.AsString());
- if (iter != message_handlers_.end()) {
- MessageHandler_t handler = iter->second.handler;
- void* user_data = iter->second.user_data;
- handler(key, dictionary.Get(key), user_data);
- return;
- }
- }
- }
-
- PSInterfaceVar()->AddRef(var);
- PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
- memset(env, 0, sizeof(*env));
- env->type = type;
- env->as_var = var;
- event_queue_.Enqueue(env);
-}
-
-PSEvent* PSInstance::TryAcquireEvent() {
- PSEvent* event;
- while(true) {
- event = event_queue_.Dequeue(false);
- if (NULL == event)
- break;
- if (events_enabled_ & event->type)
- break;
- // Release filtered events & continue to acquire.
- ReleaseEvent(event);
- }
- return event;
-}
-
-PSEvent* PSInstance::WaitAcquireEvent() {
- PSEvent* event;
- while(true) {
- event = event_queue_.Dequeue(true);
- if (events_enabled_ & event->type)
- break;
- // Release filtered events & continue to acquire.
- ReleaseEvent(event);
- }
- return event;
-}
-
-void PSInstance::ReleaseEvent(PSEvent* event) {
- if (event) {
- switch(event->type) {
- case PSE_INSTANCE_HANDLEMESSAGE:
- PSInterfaceVar()->Release(event->as_var);
- break;
- case PSE_INSTANCE_HANDLEINPUT:
- case PSE_INSTANCE_DIDCHANGEVIEW:
- if (event->as_resource) {
- PSInterfaceCore()->ReleaseResource(event->as_resource);
- }
- break;
- default:
- break;
- }
- free(event);
- }
-}
-
-void PSInstance::HandleMessage(const pp::Var& message) {
- Trace("Got Message\n");
- PostEvent(PSE_INSTANCE_HANDLEMESSAGE, message.pp_var());
-}
-
-bool PSInstance::HandleInputEvent(const pp::InputEvent& event) {
- PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource());
- return true;
-}
-
-void PSInstance::DidChangeView(const pp::View& view) {
- pp::Size new_size = view.GetRect().size();
- Log("Got View change: %d,%d\n", new_size.width(), new_size.height());
- PostEvent(PSE_INSTANCE_DIDCHANGEVIEW, view.pp_resource());
-}
-
-void PSInstance::DidChangeFocus(bool focus) {
- Log("Got Focus change: %s\n", focus ? "FOCUS ON" : "FOCUS OFF");
- PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE);
-}
-
-void PSInstance::Graphics3DContextLost() {
- Log("Graphics3DContextLost\n");
- PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
-}
-
-void PSInstance::MouseLockLost() {
- Log("MouseLockLost\n");
- PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
-}

Powered by Google App Engine
This is Rietveld 408576698