0

Add support for simple run of "main"

Converts calls to PostMessage and LogMesssage to prints to
stderr and stdout.

TBR=binji@chromium.org
BUG=165626
NOTRY=true

Review URL: https://codereview.chromium.org/11592003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173399 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
noelallen@google.com
2012-12-16 22:17:49 +00:00
parent 924e9f9e90
commit 393b16e198
11 changed files with 251 additions and 65 deletions

@ -42,7 +42,7 @@ SOURCES=hello_world.c
# Notice that pthread and libc are implied and come last through standard
# compiler/link switches, for example -pthread.
#
LIBS=ppapi_main ppapi_cpp ppapi
LIBS=ppapi_main nacl_mounts ppapi_cpp ppapi
#

@ -1,7 +1,11 @@
/* 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 <stdio.h>
#include <string.h>
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_console.h"
@ -10,49 +14,12 @@
// Have the Module object provided by ppapi_main create a basic
// PPAPI instance with default arguments to setting up
// stdio file handles, processing keyboard, etc...
// PPAPI Instance with default arguments.
// PPAPI instance with default arguments which mounts the dev
// file system providing /dev/null, /dev/tty, and /devl/console3
// for null STDIN, STDOUT directed to PostMessage and STDERR
// directed to the JavaScript Console with LogLevel 'ERROR'
PPAPI_MAIN_WITH_DEFAULT_ARGS
static PPB_Messaging* ppb_messaging_interface = NULL;
static PPB_Var* ppb_var_interface = NULL;
static PPB_Console* ppb_console_interface = NULL;
/**
* Creates new string PP_Var from C string. The resulting object will be a
* refcounted string object. It will be AddRef()ed for the caller. When the
* caller is done with it, it should be Release()d.
* @param[in] str C string to be converted to PP_Var
* @return PP_Var containing string.
*/
static struct PP_Var CStrToVar(const char* str) {
if (ppb_var_interface != NULL) {
return ppb_var_interface->VarFromUtf8(str, strlen(str));
}
return PP_MakeUndefined();
}
//
// Post a message back to JavaScript
//
static void SendMessage(const char *str) {
PP_Instance instance = PPAPI_GetInstanceId();
if (ppb_messaging_interface)
ppb_messaging_interface->PostMessage(instance, CStrToVar(str));
}
//
// Send a message to the JavaScript Console
//
static void LogMessage(const char *str) {
PP_Instance instance = PPAPI_GetInstanceId();
if (ppb_console_interface)
ppb_console_interface->Log(instance, PP_LOGLEVEL_LOG,
CStrToVar(str));
}
//
// The "main" entry point called by PPAPIInstance once initialization
// takes place. This is called off the main thread, which is hidden
@ -64,15 +31,20 @@ static void LogMessage(const char *str) {
// Where the embed tag for this module uses KEY=VALUE
//
int ppapi_main(int argc, const char *argv[]) {
ppb_messaging_interface =
(PPB_Messaging*) PPAPI_GetInterface(PPB_MESSAGING_INTERFACE);
ppb_var_interface =
(PPB_Var*) PPAPI_GetInterface(PPB_VAR_INTERFACE);
ppb_console_interface =
(PPB_Console*) PPAPI_GetInterface(PPB_CONSOLE_INTERFACE);
int index = 1;
SendMessage("Hello World STDIO.\n");
LogMessage("Hello World STDERR.\n");
// Use PostMessage to send "Hello World" to JavaScript.
printf("Hello World STDIO.\n");
// Use PPAPI Console interface to send "Hello World" to the
// JavaScript Console.
fprintf(stderr, "Hello World STDERR.\n");
// Print the arguments we received from the web page
printf("NAME: %s\n", argv[0]);
while (index + 2 < argc) {
printf(" ARGS: %s=%s\n", argv[index+0], argv[index+1]);
index += 2;
}
return 0;
}

@ -50,6 +50,7 @@ void KernelProxy::Init(PepperInterface* ppapi) {
// Create memory mount at root
StringMap_t smap;
mounts_["/"] = MountMem::Create<MountMem>(dev_++, smap, ppapi_);
mounts_["/dev"] = MountDev::Create<MountDev>(dev_++, smap, ppapi_);
}
int KernelProxy::open(const char *path, int oflags) {

@ -6,12 +6,13 @@
#define _CRT_RAND_S
#endif
#include "nacl_mounts/mount_dev.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include "nacl_mounts/mount_dev.h"
#include "nacl_mounts/mount_node.h"
#include "nacl_mounts/mount_node_dir.h"
#include "nacl_mounts/pepper_interface.h"
#include "utils/auto_lock.h"
#if defined(__native_client__)
@ -36,6 +37,25 @@ class NullNode : public MountNode {
virtual int Write(size_t offs, const void* buf, size_t count);
};
class ConsoleNode : public NullNode {
public:
ConsoleNode(Mount* mount, int ino, int dev, PP_LogLevel level);
virtual int Write(size_t offs, const void* buf, size_t count);
private:
PP_LogLevel level_;
};
class TtyNode : public NullNode {
public:
TtyNode(Mount* mount, int ino, int dev);
virtual int Write(size_t offs, const void* buf, size_t count);
};
class ZeroNode : public MountNode {
public:
ZeroNode(Mount* mount, int ino, int dev);
@ -70,6 +90,45 @@ int NullNode::Write(size_t offs, const void* buf, size_t count) {
return count;
}
ConsoleNode::ConsoleNode(Mount* mount, int ino, int dev, PP_LogLevel level)
: NullNode(mount, ino, dev),
level_(level) {
}
int ConsoleNode::Write(size_t offs, const void* buf, size_t count) {
ConsoleInterface* con_intr = mount_->ppapi()->GetConsoleInterface();
VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
if (var_intr && con_intr) {
const char* data = static_cast<const char *>(buf);
uint32_t len = static_cast<uint32_t>(count);
struct PP_Var val = var_intr->VarFromUtf8(data, len);
con_intr->Log(mount_->ppapi()->GetInstance(), level_, val);
return count;
}
return 0;
}
TtyNode::TtyNode(Mount* mount, int ino, int dev)
: NullNode(mount, ino, dev) {
}
int TtyNode::Write(size_t offs, const void* buf, size_t count) {
MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface();
VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
if (var_intr && msg_intr) {
const char* data = static_cast<const char *>(buf);
uint32_t len = static_cast<uint32_t>(count);
struct PP_Var val = var_intr->VarFromUtf8(data, len);
msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
return count;
}
return 0;
}
ZeroNode::ZeroNode(Mount* mount, int ino, int dev)
: MountNode(mount, ino, dev) {
}
@ -132,6 +191,8 @@ int UrandomNode::Write(size_t offs, const void* buf, size_t count) {
return count;
}
} // namespace
MountNode *MountDev::Open(const Path& path, int mode) {
@ -177,7 +238,12 @@ int MountDev::Remove(const Path& path) {
MountDev::MountDev()
: null_node_(NULL),
zero_node_(NULL),
random_node_(NULL) {
random_node_(NULL),
console0_node_(NULL),
console1_node_(NULL),
console2_node_(NULL),
console3_node_(NULL),
tty_node_(NULL) {
}
bool MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
@ -191,10 +257,27 @@ bool MountDev::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
root_->AddChild("/zero", zero_node_);
random_node_ = new UrandomNode(this, 4, dev_);
root_->AddChild("/urandom", random_node_);
console0_node_ = new ConsoleNode(this, 5, dev_, PP_LOGLEVEL_TIP);
root_->AddChild("/console0", console0_node_);
console1_node_ = new ConsoleNode(this, 6, dev_, PP_LOGLEVEL_LOG);
root_->AddChild("/console1", console1_node_);
console2_node_ = new ConsoleNode(this, 7, dev_, PP_LOGLEVEL_WARNING);
root_->AddChild("/console2", console2_node_);
console3_node_ = new ConsoleNode(this, 8, dev_, PP_LOGLEVEL_ERROR);
root_->AddChild("/console3", console3_node_);
tty_node_ = new TtyNode(this, 9, dev_);
root_->AddChild("/tty", tty_node_);
return true;
}
void MountDev::Destroy() {
ReleaseAndNullNode(&tty_node_);
ReleaseAndNullNode(&console3_node_);
ReleaseAndNullNode(&console2_node_);
ReleaseAndNullNode(&console1_node_);
ReleaseAndNullNode(&console0_node_);
ReleaseAndNullNode(&random_node_);
ReleaseAndNullNode(&zero_node_);
ReleaseAndNullNode(&null_node_);

@ -32,6 +32,11 @@ class MountDev : public Mount {
MountNode* null_node_;
MountNode* zero_node_;
MountNode* random_node_;
MountNode* console0_node_;
MountNode* console1_node_;
MountNode* console2_node_;
MountNode* console3_node_;
MountNode* tty_node_;
friend class Mount;
};

@ -10,12 +10,17 @@
#include <ppapi/c/pp_instance.h>
#include <ppapi/c/pp_resource.h>
#include <ppapi/c/pp_var.h>
#include <ppapi/c/ppb_console.h>
#include <ppapi/c/ppb_messaging.h>
#include <utils/macros.h>
class ConsoleInterface;
class DirectoryReaderInterface;
class FileIoInterface;
class FileRefInterface;
class FileSystemInterface;
class MessagingInterface;
class VarInterface;
class PepperInterface {
@ -24,13 +29,21 @@ class PepperInterface {
virtual PP_Instance GetInstance() = 0;
virtual void AddRefResource(PP_Resource) = 0;
virtual void ReleaseResource(PP_Resource) = 0;
virtual ConsoleInterface* GetConsoleInterface() = 0;
virtual FileSystemInterface* GetFileSystemInterface() = 0;
virtual FileRefInterface* GetFileRefInterface() = 0;
virtual FileIoInterface* GetFileIoInterface() = 0;
virtual DirectoryReaderInterface* GetDirectoryReaderInterface() = 0;
virtual MessagingInterface* GetMessagingInterface() = 0;
virtual VarInterface* GetVarInterface() = 0;
};
class ConsoleInterface {
public:
virtual ~ConsoleInterface() {}
virtual void Log(PP_Instance, PP_LogLevel, struct PP_Var) = 0;
};
class FileSystemInterface {
public:
virtual ~FileSystemInterface() {}
@ -74,9 +87,16 @@ class DirectoryReaderInterface {
PP_CompletionCallback) = 0;
};
class MessagingInterface {
public:
virtual ~MessagingInterface() {}
virtual void PostMessage(PP_Instance, struct PP_Var ) = 0;
};
class VarInterface {
public:
virtual ~VarInterface() {}
virtual struct PP_Var VarFromUtf8(const char*, uint32_t) = 0;
virtual const char* VarToUtf8(PP_Var, uint32_t*) = 0;
};

@ -5,12 +5,15 @@
#include "nacl_mounts/real_pepper_interface.h"
#include <assert.h>
#include <stdio.h>
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/ppb_console.h>
#include <ppapi/c/ppb_file_io.h>
#include <ppapi/c/ppb_file_ref.h>
#include <ppapi/c/ppb_file_system.h>
#include <ppapi/c/ppb_messaging.h>
#include <ppapi/c/ppb_var.h>
#include <stdio.h>
#define DEFINE_CONSTRUCTOR(Class, Interface) \
Class::Class(const Interface* interface) : interface_(interface) {}
@ -45,6 +48,35 @@
}
#define DEFINE_VMETHOD1(Class, MethodName, Type0) \
void Class::MethodName(Type0 arg0) { \
interface_->MethodName(arg0); \
}
#define DEFINE_VMETHOD2(Class, MethodName, Type0, Type1) \
void Class::MethodName(Type0 arg0, Type1 arg1) { \
interface_->MethodName(arg0, arg1); \
}
#define DEFINE_VMETHOD3(Class, MethodName, Type0, Type1, Type2) \
void Class::MethodName(Type0 arg0, Type1 arg1, Type2 arg2) { \
interface_->MethodName(arg0, arg1, arg2); \
}
#define DEFINE_VMETHOD4(Class, MethodName, Type0, Type1, Type2, Type3) \
void Class::MethodName(Type0 arg0, Type1 arg1, Type2 arg2, \
Type3 arg3) { \
interface_->MethodName(arg0, arg1, arg2, arg3); \
}
#define DEFINE_VMETHOD5(Class, MethodName, Type0, Type1, Type2, Type3, Type4) \
void Class::MethodName(Type0 arg0, Type1 arg1, Type2 arg2, \
Type3 arg3, Type4 arg4) { \
interface_->MethodName(arg0, arg1, arg2, arg3, arg4); \
}
class RealFileSystemInterface : public FileSystemInterface {
public:
explicit RealFileSystemInterface(const PPB_FileSystem* filesystem_interface);
@ -61,6 +93,18 @@ DEFINE_METHOD3(RealFileSystemInterface, int32_t, Open, PP_Resource, int64_t,
PP_CompletionCallback)
class RealConsoleInterface : public ConsoleInterface {
public:
explicit RealConsoleInterface(const PPB_Console* console_interface);
virtual void Log(PP_Instance, PP_LogLevel, struct PP_Var);
private:
const PPB_Console* interface_;
};
DEFINE_CONSTRUCTOR(RealConsoleInterface, PPB_Console)
DEFINE_VMETHOD3(RealConsoleInterface, Log, PP_Instance, PP_LogLevel,
struct PP_Var);
class RealFileRefInterface : public FileRefInterface {
public:
explicit RealFileRefInterface(const PPB_FileRef* fileref_interface);
@ -141,14 +185,30 @@ class RealVarInterface : public VarInterface {
public:
explicit RealVarInterface(const PPB_Var* var_interface);
virtual struct PP_Var VarFromUtf8(const char *, uint32_t);
virtual const char* VarToUtf8(PP_Var, uint32_t*);
private:
const PPB_Var* interface_;
};
DEFINE_CONSTRUCTOR(RealVarInterface, PPB_Var)
DEFINE_METHOD2(RealVarInterface, struct PP_Var, VarFromUtf8, const char *,
uint32_t)
DEFINE_METHOD2(RealVarInterface, const char*, VarToUtf8, PP_Var, uint32_t*)
class RealMessagingInterface : public MessagingInterface {
public:
explicit RealMessagingInterface(const PPB_Messaging* messaging_interface);
virtual void PostMessage(PP_Instance, struct PP_Var);
private:
const PPB_Messaging* interface_;
};
DEFINE_CONSTRUCTOR(RealMessagingInterface, PPB_Messaging);
DEFINE_VMETHOD2(RealMessagingInterface, PostMessage, PP_Instance, struct
PP_Var);
RealPepperInterface::RealPepperInterface(PP_Instance instance,
PPB_GetInterface get_browser_interface)
@ -162,6 +222,9 @@ RealPepperInterface::RealPepperInterface(PP_Instance instance,
assert(core_interface_);
assert(message_loop_interface_);
console_interface_ = new RealConsoleInterface(
static_cast<const PPB_Console*>(get_browser_interface(
PPB_CONSOLE_INTERFACE)));
directory_reader_interface_ = new RealDirectoryReaderInterface(
static_cast<const PPB_DirectoryReader_Dev*>(get_browser_interface(
PPB_DIRECTORYREADER_DEV_INTERFACE)));
@ -172,6 +235,9 @@ RealPepperInterface::RealPepperInterface(PP_Instance instance,
filesystem_interface_ = new RealFileSystemInterface(
static_cast<const PPB_FileSystem*>(get_browser_interface(
PPB_FILESYSTEM_INTERFACE)));
messaging_interface_ = new RealMessagingInterface(
static_cast<const PPB_Messaging*>(get_browser_interface(
PPB_MESSAGING_INTERFACE)));
var_interface_= new RealVarInterface(
static_cast<const PPB_Var*>(get_browser_interface(
PPB_VAR_INTERFACE)));
@ -191,6 +257,10 @@ void RealPepperInterface::ReleaseResource(PP_Resource resource) {
core_interface_->ReleaseResource(resource);
}
ConsoleInterface* RealPepperInterface::GetConsoleInterface() {
return console_interface_;
}
FileSystemInterface* RealPepperInterface::GetFileSystemInterface() {
return filesystem_interface_;
}
@ -207,6 +277,10 @@ DirectoryReaderInterface* RealPepperInterface::GetDirectoryReaderInterface() {
return directory_reader_interface_;
}
MessagingInterface* RealPepperInterface::GetMessagingInterface() {
return messaging_interface_;
}
VarInterface* RealPepperInterface::GetVarInterface() {
return var_interface_;
}

@ -7,13 +7,18 @@
#include <ppapi/c/ppb.h>
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/ppb_console.h>
#include <ppapi/c/ppb_message_loop.h>
#include <ppapi/c/ppb_messaging.h>
#include <ppapi/c/ppb_var.h>
#include "pepper_interface.h"
class RealConsoleInterface;
class RealDirectoryReaderInterface;
class RealFileIoInterface;
class RealFileRefInterface;
class RealFileSystemInterface;
class RealMessagingInterface;
class RealVarInterface;
class RealPepperInterface : public PepperInterface {
@ -24,10 +29,12 @@ class RealPepperInterface : public PepperInterface {
virtual PP_Instance GetInstance();
virtual void AddRefResource(PP_Resource);
virtual void ReleaseResource(PP_Resource);
virtual ConsoleInterface* GetConsoleInterface();
virtual FileSystemInterface* GetFileSystemInterface();
virtual FileRefInterface* GetFileRefInterface();
virtual FileIoInterface* GetFileIoInterface();
virtual DirectoryReaderInterface* GetDirectoryReaderInterface();
virtual MessagingInterface* GetMessagingInterface();
virtual VarInterface* GetVarInterface();
int32_t InitializeMessageLoop();
@ -36,10 +43,12 @@ class RealPepperInterface : public PepperInterface {
PP_Instance instance_;
const PPB_Core* core_interface_;
const PPB_MessageLoop* message_loop_interface_;
RealConsoleInterface* console_interface_;
RealDirectoryReaderInterface* directory_reader_interface_;
RealFileIoInterface* fileio_interface_;
RealFileRefInterface* fileref_interface_;
RealFileSystemInterface* filesystem_interface_;
RealMessagingInterface* messaging_interface_;
RealVarInterface* var_interface_;
};

@ -76,6 +76,7 @@ class DirectoryReaderInterfaceMock : public DirectoryReaderInterface {
class VarInterfaceMock : public VarInterface {
public:
MOCK_METHOD2(VarFromUtf8, PP_Var(const char*, uint32_t));
MOCK_METHOD2(VarToUtf8, const char*(PP_Var, uint32_t*));
};

@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdlib>
#include <cstring>
@ -11,6 +14,8 @@
#include <string>
#include <vector>
#include "nacl_mounts/kernel_intercept.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
@ -19,6 +24,7 @@
#include "ppapi_main/ppapi_instance.h"
#include "ppapi_main/ppapi_main.h"
struct StartInfo {
uint32_t argc_;
const char** argv_;
@ -67,10 +73,7 @@ bool PPAPIInstance::Init(uint32_t arg,
si->argc_ = 1;
si->argv_ = new const char *[arg*2+1];
char *name = new char[5];
strcpy(name, "NEXE");
si->argv_[0] = name;
si->argv_[0] = NULL;
for (uint32_t i=0; i < arg; i++) {
// If we start with PM prefix set the instance argument map
@ -78,9 +81,17 @@ bool PPAPIInstance::Init(uint32_t arg,
std::string key = argn[i];
std::string val = argv[i];
properties_[key] = val;
continue;
}
// If this is the 'src' tag, then get the NMF name.
if (!strcmp("src", argn[i])) {
char *name = new char[strlen(argv[i]) + 1];
strcpy(name, argv[i]);
si->argv_[0] = name;
}
// Otherwise turn it into arguments
else {
// Otherwise turn it into arguments
char *key = new char[strlen(argn[i]) + 3];
key[0] = '-';
key[1] = '-';
@ -95,7 +106,12 @@ bool PPAPIInstance::Init(uint32_t arg,
}
}
// ki_init();
// If src was not found, set the first arg to something
if (NULL == si->argv_[0]) {
char *name = new char[5];
strcpy(name, "NMF?");
si->argv_[0] = name;
}
if (ProcessProperties()) {
pthread_t main_thread;
@ -116,11 +132,16 @@ const char* PPAPIInstance::GetProperty(const char* key, const char* def) {
}
bool PPAPIInstance::ProcessProperties() {
#if 0
const char* stdin_path = GetProperty("PM_STDIO", "/dev/tty");
const char* stdout_path = GetProperty("PM_STDOUT", "/dev/console0");
const char* stdin_path = GetProperty("PM_STDIO", "/dev/null");
const char* stdout_path = GetProperty("PM_STDOUT", "/dev/tty");
const char* stderr_path = GetProperty("PM_STDERR", "/dev/console3");
#endif
ki_init_ppapi(NULL, PPAPI_GetInstanceId(), PPAPI_GetInterface);
int f1 = open(stdin_path, O_RDONLY);
int f2 = open(stdout_path, O_WRONLY);
int f3 = open(stderr_path, O_WRONLY);
return true;
}
void PPAPIInstance::HandleMessage(const pp::Var& message) {

@ -30,7 +30,7 @@ EXTERN_C_END
#define PPAPI_MAIN_DEFAULT_ARGS \
{ \
"PM_STDIN", "/dev/tty", \
"PM_STDIN", "/dev/null", \
"PM_STDIO", "/dev/console0", \
"PM_STDERR", "/dev/console3", \
NULL, NULL \