summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authornoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-15 02:35:26 +0000
committernoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-15 02:35:26 +0000
commitf9a7a34abb8e2d069a44e07e70a22b9bc79efb72 (patch)
treef4d8c54a823e88d6622a70ced9dd71a22451e920 /native_client_sdk
parent2a2cdf0699150d7eb1c6f078733d6e6083d5f6e7 (diff)
downloadchromium_src-f9a7a34abb8e2d069a44e07e70a22b9bc79efb72.zip
chromium_src-f9a7a34abb8e2d069a44e07e70a22b9bc79efb72.tar.gz
chromium_src-f9a7a34abb8e2d069a44e07e70a22b9bc79efb72.tar.bz2
Support a simple "main" view of PPAPI
Add ppapi_main and hello_world_stdio Automatically call 'main' after initialization Mount /dev/console /dev/tty to support STDIN,STDOUT,STDERR R=binji@chromium.org BUG=165626 Review URL: https://codereview.chromium.org/11519028 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173260 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rwxr-xr-xnative_client_sdk/src/build_tools/build_sdk.py5
-rw-r--r--native_client_sdk/src/build_tools/generate_index.py12
-rwxr-xr-xnative_client_sdk/src/build_tools/generate_make.py6
-rw-r--r--native_client_sdk/src/examples/hello_world/example.js24
-rw-r--r--native_client_sdk/src/examples/hello_world/hello_world.c29
-rw-r--r--native_client_sdk/src/examples/hello_world/index.html15
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/Makefile61
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/example.dsc35
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/example.js24
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/hello_world.c78
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/index.html37
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/library.dsc27
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc169
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h50
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc58
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_main.h53
-rw-r--r--native_client_sdk/src/tools/common.mk242
17 files changed, 916 insertions, 9 deletions
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 283396930..a577475 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -602,6 +602,7 @@ EXAMPLE_LIST = [
'gamepad',
'geturl',
'hello_nacl_mounts',
+ 'hello_world_stdio',
'hello_world',
'hello_world_gles',
'hello_world_interactive',
@@ -619,6 +620,7 @@ LIBRARY_LIST = [
'ppapi',
'ppapi_cpp',
'ppapi_gles2',
+ 'ppapi_main',
'pthread',
'zlib',
]
@@ -666,7 +668,8 @@ def BuildStepCopyExamples(pepperdir, toolchains, build_experimental, clobber):
# Copy individual files
files = ['favicon.ico', 'httpd.cmd']
for filename in files:
- oshelpers.Copy(['-v', os.path.join(SDK_EXAMPLE_DIR, filename), exampledir])
+ oshelpers.Copy(['-v', os.path.join(SDK_EXAMPLE_DIR, filename),
+ exampledir])
args = ['--dstroot=%s' % pepperdir, '--master']
for toolchain in toolchains:
diff --git a/native_client_sdk/src/build_tools/generate_index.py b/native_client_sdk/src/build_tools/generate_index.py
index d733162..5bfe23a 100644
--- a/native_client_sdk/src/build_tools/generate_index.py
+++ b/native_client_sdk/src/build_tools/generate_index.py
@@ -57,10 +57,14 @@ mulithreading...</p></dd>
""",
'Tools': """
<h3>Using the Tools</h3>
-<dd><p>The following "hello_world" examples, show the basic outline of a Native
-Client application. The make files in each of the examples below show a
-simple way to build a NaCl application using
-<a href="http://www.gnu.org/software/make/manual/make.html">GNU Make</a>.
+<dd><p>The following "hello_world" examples, show the basic outline of a
+several types of Native Client applications. The simplest, "Hello World Stdio"
+uses several provided libraries to simplify startup and provides a
+simplified make showing a single build configuration. The other examples in
+this SDK however, are designed to build and run with multiple toolsets, build
+configurations, etc...
+making the build much more complex. In all cases we are using <a
+href="http://www.gnu.org/software/make/manual/make.html">GNU Make</a>.
See the link for further information.
</p></dd>
""",
diff --git a/native_client_sdk/src/build_tools/generate_make.py b/native_client_sdk/src/build_tools/generate_make.py
index 786a1e7..af3f839 100755
--- a/native_client_sdk/src/build_tools/generate_make.py
+++ b/native_client_sdk/src/build_tools/generate_make.py
@@ -217,7 +217,8 @@ DSC_FORMAT = {
'DEFINES': (list, '', False),
'LDFLAGS': (list, '', False),
'INCLUDES': (list, '', False),
- 'LIBS' : (list, '', False)
+ 'LIBS' : (list, '', False),
+ 'DEPS' : (list, '', False)
}, True),
'HEADERS': (list, {
'FILES': (list, '', True),
@@ -500,7 +501,8 @@ def ProcessProject(srcroot, dstroot, desc, toolchains):
# Add Makefile and make.bat
repdict = GenerateReplacements(desc, tools)
- WriteReplaced(template, make_path, repdict)
+ if not 'Makefile' in desc.get('DATA', []):
+ WriteReplaced(template, make_path, repdict)
outdir = os.path.dirname(os.path.abspath(make_path))
pepperdir = os.path.dirname(os.path.dirname(outdir))
diff --git a/native_client_sdk/src/examples/hello_world/example.js b/native_client_sdk/src/examples/hello_world/example.js
new file mode 100644
index 0000000..13a9997
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world/example.js
@@ -0,0 +1,24 @@
+// 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.
+
+var kMaxArraySize = 20;
+var messageArray = new Array();
+
+// Once we load, hide the plugin
+function moduleDidLoad() {
+ common.hideModule();
+}
+
+// Called by the common.js module.
+function handleMessage(message) {
+ // Show last |kMaxArraySize| events in html.
+ messageArray.push(message.data);
+ if (messageArray.length > kMaxArraySize) {
+ messageArray.shift();
+ }
+ var newData = messageArray.join('<BR>');
+ document.getElementById('outputString').innerHTML = newData;
+ // Print event to console.
+ console.log(message.data);
+}
diff --git a/native_client_sdk/src/examples/hello_world/hello_world.c b/native_client_sdk/src/examples/hello_world/hello_world.c
index bbd0693..2d1666e 100644
--- a/native_client_sdk/src/examples/hello_world/hello_world.c
+++ b/native_client_sdk/src/examples/hello_world/hello_world.c
@@ -15,6 +15,7 @@
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb.h"
+#include "ppapi/c/ppb_console.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_var.h"
@@ -34,6 +35,7 @@
#define TCNAME "host"
#endif
+static PPB_Console* ppb_console_interface = NULL;
static PPB_Messaging* ppb_messaging_interface = NULL;
static PPB_Var* ppb_var_interface = NULL;
@@ -54,6 +56,23 @@ static struct PP_Var CStrToVar(const char* str) {
/**
+ * Post a message back to our JavaScript
+ */
+static void SendMessage(PP_Instance instance, const char *str) {
+ if (ppb_messaging_interface)
+ ppb_messaging_interface->PostMessage(instance, CStrToVar(str));
+}
+
+/**
+ * Send a message to the JavaScript Console
+ */
+static void LogMessage(PP_Instance instance, const char *str) {
+ if (ppb_console_interface)
+ ppb_console_interface->Log(instance, PP_LOGLEVEL_ERROR,
+ CStrToVar(str));
+}
+
+/**
* Called when the NaCl module is instantiated on the web page. The identifier
* of the new instance will be passed in as the first argument (this value is
* generated by the browser and is an opaque handle). This is called for each
@@ -80,8 +99,12 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
const char* argn[],
const char* argv[]) {
- const char* message = "alert:Hello World (" TCNAME ")!";
- ppb_messaging_interface->PostMessage(instance, CStrToVar(message));
+ const char* post_msg = "Hello World (" TCNAME ")!";
+ const char* console_msg = "Hello World (JavsScript Console)!";
+
+ SendMessage(instance, post_msg);
+ LogMessage(instance, console_msg);
+
return PP_TRUE;
}
@@ -160,6 +183,8 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
*/
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
PPB_GetInterface get_browser) {
+ ppb_console_interface =
+ (PPB_Console*)(get_browser(PPB_CONSOLE_INTERFACE));
ppb_messaging_interface =
(PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
diff --git a/native_client_sdk/src/examples/hello_world/index.html b/native_client_sdk/src/examples/hello_world/index.html
index 5b20825..3fc523d 100644
--- a/native_client_sdk/src/examples/hello_world/index.html
+++ b/native_client_sdk/src/examples/hello_world/index.html
@@ -10,12 +10,27 @@ found in the LICENSE file.
<meta http-equiv="Expires" content="-1">
<title><TITLE></title>
<script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
</head>
<body data-name="<NAME>" data-tc="<tc>" data-path="<path>">
<h1><TITLE></h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>This example demonstrates a complete NaCl PPAPI application. In
+source file hello_world.c contains the three required PPAPI functions
+ PPP_InitializeModule, PPP_GetInterface, PPP_ShutdownModule which initialize
+the application, provide a string name to callback interface mapping, and
+cleanup on shutdown respectively.</p>
+ <p>The example will query for the Console, PostMessage and Var interfaces to
+send a message to JavaScript which will be added to the output box. In
+addition, it will send another message to the JavaScript Console to simulate
+logging for development.</p>
+
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
+ <h1>OUTPUT</h1>
+ <pre>
+ <p><b id='outputString'></b></p>
+ </pre>
</body>
</html>
diff --git a/native_client_sdk/src/examples/hello_world_stdio/Makefile b/native_client_sdk/src/examples/hello_world_stdio/Makefile
new file mode 100644
index 0000000..d3b34a6
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_stdio/Makefile
@@ -0,0 +1,61 @@
+# 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.
+
+#
+# GNU Make based build file. For details on GNU Make see:
+# http://www.gnu.org/software/make/manual/make.html
+#
+#
+
+
+#
+# Default configuration
+#
+# By default we will build a Debug configuration using the GCC newlib toolcahin
+# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
+# the make command-line or in this file prior to including common.mk
+#
+include common.mk
+
+
+#
+# Target Name
+#
+# The base name of the final NEXE, also the name of the NMF file containing
+# the mapping between architecture and actual NEXE.
+#
+TARGET=hello_world_stdio
+
+#
+# List of sources to compile
+#
+SOURCES=hello_world.c
+
+
+#
+# List of libraries to link against. Unlike some tools, the GCC and LLVM
+# based tools require libraries to be specified in the correct order. The
+# order should be symbol reference followed by symbol definition, with direct
+# sources to the link (object files) are left most. In this case:
+# hello_world -> ppapi_main -> ppapi_cpp -> ppapi -> pthread -> libc
+# Notice that pthread and libc are implied and come last through standard
+# compiler/link switches, for example -pthread.
+#
+LIBS=ppapi_main ppapi_cpp ppapi
+
+
+#
+# Use the compile macro for each source.
+#
+$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src))))
+
+#
+# Use the link macro for this target on the list of sources.
+#
+$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS)))
+
+#
+# Specify the NMF to be created with no additional arugments.
+#
+$(eval $(call NMF_RULE,$(TARGET),))
diff --git a/native_client_sdk/src/examples/hello_world_stdio/example.dsc b/native_client_sdk/src/examples/hello_world_stdio/example.dsc
new file mode 100644
index 0000000..e80021c
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_stdio/example.dsc
@@ -0,0 +1,35 @@
+{
+ 'TOOLS': ['newlib'],
+ 'SEARCH': [
+ '.',
+ '..',
+ '../../tools',
+ ],
+ 'TARGETS': [
+ {
+ 'NAME' : 'hello_world_stdio',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['hello_world.c'],
+ 'LIBS': ['ppapi_main', 'nacl_mounts', 'ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'Makefile',
+ 'common.mk',
+ 'example.js',
+ ],
+ 'DEST': 'examples',
+ 'NAME': 'hello_world_stdio',
+ 'TITLE': 'Hello World STDIO.',
+ 'DESC': """
+
+ The Hello World Stdio example is the simplest one in the SDK. It uses the
+ppapi_main library which creates an Module and Instance, using default values
+to simplify setup and communication with the PPAPI system. In addition, it
+uses the nacl_mounts library to remap IO to the Pepper API. This
+simplifies IO by providing a standard blocking API and allowing STDERR to go to
+the JavaScript console by default.""",
+ 'FOCUS': 'Basic HTML, JavaScript, Minimal App.',
+ 'GROUP': 'Tools'
+}
+
diff --git a/native_client_sdk/src/examples/hello_world_stdio/example.js b/native_client_sdk/src/examples/hello_world_stdio/example.js
new file mode 100644
index 0000000..13a9997
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_stdio/example.js
@@ -0,0 +1,24 @@
+// 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.
+
+var kMaxArraySize = 20;
+var messageArray = new Array();
+
+// Once we load, hide the plugin
+function moduleDidLoad() {
+ common.hideModule();
+}
+
+// Called by the common.js module.
+function handleMessage(message) {
+ // Show last |kMaxArraySize| events in html.
+ messageArray.push(message.data);
+ if (messageArray.length > kMaxArraySize) {
+ messageArray.shift();
+ }
+ var newData = messageArray.join('<BR>');
+ document.getElementById('outputString').innerHTML = newData;
+ // Print event to console.
+ console.log(message.data);
+}
diff --git a/native_client_sdk/src/examples/hello_world_stdio/hello_world.c b/native_client_sdk/src/examples/hello_world_stdio/hello_world.c
new file mode 100644
index 0000000..2771be0
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_stdio/hello_world.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <string.h>
+
+
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppb_messaging.h"
+#include "ppapi/c/ppb_console.h"
+
+#include "ppapi_main/ppapi_main.h"
+
+
+// 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_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
+// from the developer, making it safe to use blocking calls.
+// The arguments are provided as:
+// argv[0] = "NEXE"
+// argv[1] = "--<KEY>"
+// argv[2] = "<VALUE>"
+// 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);
+
+ SendMessage("Hello World STDIO.\n");
+ LogMessage("Hello World STDERR.\n");
+
+ return 0;
+}
diff --git a/native_client_sdk/src/examples/hello_world_stdio/index.html b/native_client_sdk/src/examples/hello_world_stdio/index.html
new file mode 100644
index 0000000..2beaf10
--- /dev/null
+++ b/native_client_sdk/src/examples/hello_world_stdio/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<!--
+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.
+-->
+<head>
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Expires" content="-1">
+ <title><TITLE></title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
+</head>
+<body data-name="<NAME>" data-tc="<tc>" data-path="<path>">
+ <h1><TITLE></h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+
+ <p>This example demonstrates using nacl_mounts ppapi_main to simplify the
+ creation of a PPAPI application. The ppapi_main library handles the creation
+ and initialization of a pp::Instance object. The nacl_mounts library
+ intercepts standard file IO, allowing the remapping of STDOUT, and
+ STDERR.</p>
+ <p>In main, we write to both STDOUT and STDERR, printing a hello world
+ message.</p>
+
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+ <div id="listener"></div>
+ <h1>OUTPUT</h1>
+ <pre>
+ <p><b id='outputString'></b></p>
+ </pre>
+</body>
+</html> \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/ppapi_main/library.dsc b/native_client_sdk/src/libraries/ppapi_main/library.dsc
new file mode 100644
index 0000000..a2bd0a1
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/library.dsc
@@ -0,0 +1,27 @@
+{
+ 'TOOLS': ['newlib', 'glibc'],
+ 'SEARCH': [
+ '.',
+ ],
+ 'TARGETS': [
+ {
+ 'NAME' : 'ppapi_main',
+ 'TYPE' : 'lib',
+ 'SOURCES' : [
+ "ppapi_instance.cc",
+ "ppapi_main.cc",
+ ],
+ }
+ ],
+ 'HEADERS': [
+ {
+ 'FILES': [
+ "ppapi_instance.h",
+ "ppapi_main.h",
+ ],
+ 'DEST': 'include/ppapi_main',
+ },
+ ],
+ 'DEST': 'src',
+ 'NAME': 'ppapi_main',
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
new file mode 100644
index 0000000..8bc51dd
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
@@ -0,0 +1,169 @@
+// 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 <pthread.h>
+#include <stdio.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+
+#include "ppapi_main/ppapi_instance.h"
+#include "ppapi_main/ppapi_main.h"
+
+struct StartInfo {
+ uint32_t argc_;
+ const char** argv_;
+};
+
+static void* StartMain(void *info) {
+ StartInfo* si = static_cast<StartInfo*>(info);
+
+ if (NULL != info) {
+ ppapi_main(si->argc_, si->argv_);
+
+ for (uint32_t i = 0; i < si->argc_; i++) {
+ delete[] si->argv_[i];
+ }
+ delete[] si->argv_;
+ delete si;
+ }
+ else {
+ const char *argv[] = { "NEXE", NULL };
+ ppapi_main(1, argv);
+ }
+ return NULL;
+}
+
+PPAPIInstance::PPAPIInstance(PP_Instance instance, const char *args[])
+ : pp::Instance(instance),
+ has_focus_(false) {
+
+ while (*args) {
+ std::string key = *args++;
+ std::string val = *args++;
+ properties_[key] = val;
+ }
+
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+ RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
+}
+
+PPAPIInstance::~PPAPIInstance() {
+}
+
+bool PPAPIInstance::Init(uint32_t arg,
+ const char* argn[],
+ const char* argv[]) {
+ StartInfo* si = new StartInfo;
+
+ si->argc_ = 1;
+ si->argv_ = new const char *[arg*2+1];
+
+ char *name = new char[5];
+ strcpy(name, "NEXE");
+ si->argv_[0] = name;
+
+ for (uint32_t i=0; i < arg; i++) {
+ // If we start with PM prefix set the instance argument map
+ if (0 == strncmp(argn[i], "PM_", 3)) {
+ std::string key = argn[i];
+ std::string val = argv[i];
+ properties_[key] = val;
+ }
+ // Otherwise turn it into arguments
+ else {
+ char *key = new char[strlen(argn[i]) + 3];
+ key[0] = '-';
+ key[1] = '-';
+ strcpy(&key[2], argn[i]);
+
+ si->argv_[si->argc_++] = key;
+ if (argv[i] && argv[i][0]) {
+ char *val = new char[strlen(argv[i]) + 1];
+ strcpy(val, argv[i]);
+ si->argv_[si->argc_++] = val;
+ }
+ }
+ }
+
+// ki_init();
+
+ if (ProcessProperties()) {
+ pthread_t main_thread;
+ int ret = pthread_create(&main_thread, NULL, StartMain,
+ static_cast<void*>(si));
+ return ret == 0;
+ }
+
+ return false;
+}
+
+const char* PPAPIInstance::GetProperty(const char* key, const char* def) {
+ PropteryMap_t::iterator it = properties_.find(key);
+ if (it != properties_.end()) {
+ return it->second.c_str();
+ }
+ return 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* stderr_path = GetProperty("PM_STDERR", "/dev/console3");
+#endif
+}
+
+void PPAPIInstance::HandleMessage(const pp::Var& message) {
+}
+
+
+bool PPAPIInstance::HandleInputEvent(const pp::InputEvent& event) {
+ switch (event.GetType()) {
+ case PP_INPUTEVENT_TYPE_UNDEFINED:
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ // If we do not yet have focus, return true. In return Chrome will give
+ // focus to the NaCl embed.
+ return !has_focus_;
+ break;
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEUP:
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE:
+ case PP_INPUTEVENT_TYPE_MOUSEENTER:
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE:
+ case PP_INPUTEVENT_TYPE_WHEEL:
+ case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYUP:
+ case PP_INPUTEVENT_TYPE_CHAR:
+ case PP_INPUTEVENT_TYPE_CONTEXTMENU:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
+ case PP_INPUTEVENT_TYPE_IME_TEXT:
+ case PP_INPUTEVENT_TYPE_TOUCHSTART:
+ case PP_INPUTEVENT_TYPE_TOUCHMOVE:
+ case PP_INPUTEVENT_TYPE_TOUCHEND:
+ case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
+ default:
+ return false;
+ }
+ return false;
+}
+
+void PPAPIInstance::DidChangeView(const pp::View&) {
+}
+
+void PPAPIInstance::DidChangeFocus(bool focus) {
+ has_focus_ = focus;
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
new file mode 100644
index 0000000..279388e
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
@@ -0,0 +1,50 @@
+// 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.
+
+#ifndef PPAPI_MAIN_PPAPI_INSTANCE_H_
+#define PPAPI_MAIN_PPAPI_INSTANCE_H_
+
+#include <map>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/cpp/fullscreen.h"
+#include "ppapi/cpp/instance.h"
+
+typedef std::map<std::string, std::string> PropteryMap_t;
+
+class PPAPIInstance : public pp::Instance {
+ public:
+ PPAPIInstance(PP_Instance instance, const char *args[]);
+ virtual ~PPAPIInstance();
+
+ // Called by the browser when the NaCl module is loaded and all ready to go.
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
+
+ // Called whenever the in-browser window changes size.
+ virtual void DidChangeView(const pp::View& view);
+
+ // Called by the browser when the NaCl canvas gets or loses focus.
+ virtual void DidChangeFocus(bool has_focus);
+
+ // Called by the browser to handle the postMessage() call in Javascript.
+ virtual void HandleMessage(const pp::Var& message);
+
+ // Called by the browser to handle incoming input events.
+ virtual bool HandleInputEvent(const pp::InputEvent& event);
+
+ protected:
+ // Called by Init to processes default and embed tag arguments prior to
+ // launching the 'ppapi_main' thread.
+ virtual bool ProcessProperties();
+
+ // Returns value based on KEY or default
+ const char* GetProperty(const char* key, const char* def = NULL);
+
+ private:
+ PropteryMap_t properties_;
+ bool has_focus_;
+};
+
+
+#endif // PPAPI_MAIN_PPAPI_INSTANCE_H_
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc
new file mode 100644
index 0000000..c3c7392
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.cc
@@ -0,0 +1,58 @@
+/* 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 "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+
+#include "ppapi_main/ppapi_instance.h"
+#include "ppapi_main/ppapi_main.h"
+
+
+static pp::Instance* s_Instance = NULL;
+
+
+// Helpers to access PPAPI interfaces
+PP_Instance PPAPI_GetInstanceId() {
+ return s_Instance->pp_instance();
+}
+
+const void* PPAPI_GetInterface(const char *name) {
+ return pp::Module::Get()->GetBrowserInterface(name);
+}
+
+
+void* PPAPI_CreateInstance(PP_Instance inst, const char *args[]) {
+ return static_cast<void*>(new PPAPIInstance(inst, args));
+}
+
+/// The Module class. The browser calls the CreateInstance() method to create
+/// an instance of your NaCl module on the web page. The browser creates a new
+/// instance for each <embed> tag with type="application/x-nacl".
+class PPAPIMainModule : public pp::Module {
+ public:
+ PPAPIMainModule() : pp::Module() {}
+ virtual ~PPAPIMainModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ s_Instance = static_cast<pp::Instance*>(UserCreateInstance(instance));
+ return s_Instance;
+ }
+};
+
+namespace pp {
+/// Factory function called by the browser when the module is first loaded.
+/// The browser keeps a singleton of this module. It calls the
+/// CreateInstance() method on the object you return to make instances. There
+/// is one instance per <embed> tag on the page. This is the main binding
+/// point for your NaCl module with the browser.
+Module* CreateModule() {
+ return new PPAPIMainModule();
+}
+
+} // namespace pp
+
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
new file mode 100644
index 0000000..78be506
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef PPAPI_MAIN_PPAPI_MAIN_H_
+#define PPAPI_MAIN_PPAPI_MAIN_H_
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_module.h"
+#include "utils/macros.h"
+
+EXTERN_C_BEGIN
+
+// Prototype for 'main' which will get called on startup
+int ppapi_main(int argc, const char *argv[]);
+
+// Provided by "main" module, use one of the macros below
+void* UserCreateInstance(PP_Instance inst);
+
+// Helpers to access PPAPI interfaces
+PP_Instance PPAPI_GetInstanceId();
+const void* PPAPI_GetInterface(const char *name);
+
+// Provided by library for basic instance types
+void* PPAPI_CreateInstance(PP_Instance inst, const char *args[]);
+void* PPAPI_CreateInstance2D(PP_Instance inst, const char *args[]);
+void* PPAPI_CreateInstance3D(PP_Instance inst, const char *args[]);
+
+EXTERN_C_END
+
+#define PPAPI_MAIN_DEFAULT_ARGS \
+ { \
+ "PM_STDIN", "/dev/tty", \
+ "PM_STDIO", "/dev/console0", \
+ "PM_STDERR", "/dev/console3", \
+ NULL, NULL \
+ }
+
+
+#define PPAPI_MAIN_USE(factory, args) \
+void* UserCreateInstance(PP_Instance inst) { \
+ static const char *params[] = args; \
+ return factory(inst, params); \
+}
+
+#define PPAPI_MAIN_WITH_DEFAULT_ARGS \
+ PPAPI_MAIN_USE(PPAPI_CreateInstance, PPAPI_MAIN_DEFAULT_ARGS)
+
+#define PPAPI_MAIN_WITH_ARGS(args) \
+ PPAPI_MAIN_USE(PPAPI_CreateInstance, args)
+
+
+#endif // PPAPI_MAIN_PPAPI_MAIN_H_
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
new file mode 100644
index 0000000..45917dc
--- /dev/null
+++ b/native_client_sdk/src/tools/common.mk
@@ -0,0 +1,242 @@
+# 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.
+
+#
+# GNU Make based build file. For details on GNU Make see:
+# http://www.gnu.org/software/make/manual/make.html
+#
+#
+
+#
+# Toolchain
+#
+# This makefile is designed to work with the NEWLIB toolchain which is
+# currently supported by x86 and ARM. To switch to glibc, you would need
+# to drop support for ARM.
+#
+TOOLCHAIN?=newlib
+
+#
+# Build Configuration
+#
+# The SDK provides two sets of libraries, Debug and Release. Debug libraries
+# are compiled without optimizations to make debugging easier. By default
+# this will build a Debug configuration.
+#
+CONFIG?=Debug
+
+
+# Note for Windows:
+# Both GCC and LLVM bases tools (include the version of Make.exe that comes
+# with the SDK) both expect and are capable of dealing with the '/' seperator.
+# For that reason, the tools in the SDK, including build, compilers, scripts
+# all have a preference for POSIX style command-line arguments.
+#
+# Keep in mind however that the shell is responsible for command-line escaping,
+# globbing, and variable expansion, so those may change based on which shell
+# is used. For Cygwin shells this can include automatic and incorrect expansion
+# of response files (files starting with '@').
+#
+
+# Disable DOS PATH warning when using Cygwin based NaCl tools on Windows.
+#
+CYGWIN?=nodosfilewarning
+export CYGWIN
+
+
+#
+# Get pepper directory for toolchain and includes.
+#
+# If NACL_SDK_ROOT is not set, then assume it can be found a two directories up,
+# from the default example directory location.
+#
+THIS_MAKEFILE:=$(abspath $(lastword $(MAKEFILE_LIST)))
+THIS_DIR:=$(abspath $(dir $(THIS_MAKEFILE)))
+NACL_SDK_ROOT?=$(abspath $(dir $(THIS_MAKEFILE))../..)
+
+
+#
+# Defaults build flags
+#
+# Convert warnings to errors, and build with no optimization.
+#
+NACL_WARNINGS:=-Wno-long-long -Werror
+OPT_FLAGS:=-g -O0
+CXX_FLAGS:=-pthread -I$(NACL_SDK_ROOT)/include
+LD_FLAGS:=-pthread
+
+
+#
+# Library Paths
+#
+# Libraries are stored in different directories for each achitecture as well
+# as different subdirectories for Debug vs Release configurations. This make
+# only supports the Debug configuration for simplicity.
+#
+# By default for x86 32 bit this expands to:
+# $(NACL_SDK_ROOT)/lib/newlib_x86_32/Debug
+#
+LD_X86_32:=-L$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_32/$(CONFIG)
+LD_X86_64:=-L$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_64/$(CONFIG)
+LD_ARM:=-L$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_arm/$(CONFIG)
+
+
+#
+# Compute path to requested NaCl Toolchain
+#
+OSNAME:=$(shell python $(NACL_SDK_ROOT)/tools/getos.py)
+TC_PATH:=$(abspath $(NACL_SDK_ROOT)/toolchain)
+
+
+#
+# Alias for standard POSIX file system commands
+#
+CP:=python $(NACL_SDK_ROOT)/tools/oshelpers.py cp
+MKDIR:=python $(NACL_SDK_ROOT)/tools/oshelpers.py mkdir
+MV:=python $(NACL_SDK_ROOT)/tools/oshelpers.py mv
+RM:=python $(NACL_SDK_ROOT)/tools/oshelpers.py rm
+
+
+#
+# The default target
+#
+# If no targets are specified on the command-line, the first target listed in
+# the makefile becomes the default target. By convention this is usually called
+# the 'all' target. Here we leave it blank to be first, but define it later
+#
+all:
+
+
+#
+# Target to remove temporary files
+#
+.PHONY: clean
+clean:
+ $(RM) $(TARGET).nmf
+ $(RM) -fr $(TOOLCHAIN)
+
+#
+# Macros for TOOLS
+#
+# We use the C++ compiler for everything and then use the -Wl,-as-needed flag
+# in the linker to drop libc++ unless it's actually needed.
+#
+X86_CXX?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-g++
+X86_LINK?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-g++ -Wl,-as-needed
+
+ARM_CXX?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-g++
+ARM_LINK?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-g++ -Wl,-as-needed
+
+
+#
+# Rules for output directories.
+#
+# Output will be places in a directory name based on Toolchain and configuration
+# be default this will be "newlib/Debug". We use a python wrapped MKDIR to
+# proivde a cross platform solution. The use of '|' checks for existance instead
+# of timestamp, since the directory can update when files change.
+#
+$(TOOLCHAIN):
+ $(MKDIR) $(TOOLCHAIN)
+
+$(TOOLCHAIN)/$(CONFIG): | $(TOOLCHAIN)
+ $(MKDIR) $(TOOLCHAIN)/$(CONFIG)
+
+OUTDIR:=$(TOOLCHAIN)/$(CONFIG)
+
+
+#
+# Compile Macro
+#
+# $1 = Source Name
+#
+# By default, if $(1) = source.c, this rule expands to:
+# newlib/Debug/source_x86_32.o : souce.c Makefile | newlib/Debug
+#
+# Which means if 'source.c' or Makefile are newer than the object
+# newlib/Debug/source_x86_32.o, then run the step:
+# $(X86_CC) -o newlib/Debug/source_x86_32.o -c source.c ....
+#
+# We repeat this expansion for 64 bit X86 and conditionally for ARM if
+# TOOLCHAIN=newlib
+#
+define COMPILE_RULE
+$(OUTDIR)/$(basename $(1))_x86_32.o : $(1) $(THIS_MAKE) | $(OUTDIR)
+ $(X86_CXX) -o $$@ -c $$< -m32 $(OPT_FLAGS) $(CXX_FLAGS) $(NACL_WARNINGS)
+
+$(OUTDIR)/$(basename $(1))_x86_64.o : $(1) $(THIS_MAKE) | $(OUTDIR)
+ $(X86_CXX) -o $$@ -c $$< -m64 $(OPT_FLAGS) $(CXX_FLAGS) $(NACL_WARNINGS)
+
+$(OUTDIR)/$(basename $(1))_arm.o : $(1) $(THIS_MAKE) | $(OUTDIR)
+ $(ARM_CXX) -o $$@ -c $$< $(OPT_FLAGS) $(CXX_FLAGS) $(NACL_WARNINGS)
+endef
+
+
+#
+# Link Macro
+#
+# $1 = Target Name
+# $2 = List of Sources
+#
+# By default, if $(1) = foo $(2) = A.c B.cc, this rule expands to:
+# newlib/Debug/foo_x86_32.nexe : newlib/Debug/A_x86_32.o ...
+#
+# Which means if A_x86_32.o or sourceB_32.o is newer than the nexe then
+# run the build step:
+# $(X86_LINK) -o newlib/Debug/foo_x86_32.nexe newlib/Debug/A_x86_32.o ...
+#
+# Note:
+# We expand each library as '-l<name>' which will look for lib<name> in the
+# directory specified by $(LD_X86_32)
+#
+# We repeat this expansion for 64 bit X86 and conditionally for ARM if
+# TOOLCHAIN=newlib
+#
+define LINK_RULE
+NMF_TARGETS+=$(OUTDIR)/$(1)_x86_32.nexe
+$(OUTDIR)/$(1)_x86_32.nexe : $(foreach src,$(2),$(OUTDIR)/$(basename $(src))_x86_32.o)
+ $(X86_LINK) -o $$@ $$^ -m32 $(LD_X86_32) $(LD_FLAGS) $(foreach lib,$(LIBS),-l$(lib))
+
+NMF_TARGETS+=$(OUTDIR)/$(1)_x86_64.nexe
+$(OUTDIR)/$(1)_x86_64.nexe : $(foreach src,$(2),$(OUTDIR)/$(basename $(src))_x86_64.o)
+ $(X86_LINK) -o $$@ $$^ -m64 $(LD_X86_64) $(LD_FLAGS) $(foreach lib,$(LIBS),-l$(lib))
+
+NMF_TARGETS+=$(OUTDIR)/$(1)_arm.nexe
+$(OUTDIR)/$(1)_arm.nexe : $(foreach src,$(2),$(OUTDIR)/$(basename $(src))_arm.o)
+ $(ARM_LINK) -o $$@ $$^ $(LD_ARM) $(LD_FLAGS) $(foreach lib,$(LIBS),-l$(lib))
+endef
+
+
+#
+# Generate NMF_TARGETS
+#
+ARCHES=x86_32 x86_64
+ifeq "newlib" "$(TOOLCHAIN)"
+ARCHES+=arm
+endif
+
+
+#
+# NMF Manifiest generation
+#
+# Use the python script create_nmf to scan the binaries for dependencies using
+# objdump. Pass in the (-L) paths to the default library toolchains so that we
+# can find those libraries and have it automatically copy the files (-s) to
+# the target directory for us.
+#
+# $1 = Target Name (the basename of the nmf
+# $2 = Additional create_nmf.py arguments
+#
+NMF:=python $(NACL_SDK_ROOT)/tools/create_nmf.py
+GLIBC_DUMP:=$(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/bin/objdump
+GLIBC_PATHS:=-L $(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/lib32
+GLIBC_PATHS+=-L $(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/lib
+
+define NMF_RULE
+$(OUTDIR)/$(1).nmf : $(foreach arch,$(ARCHES),$(OUTDIR)/$(1)_$(arch).nexe)
+ $(NMF) -o $$@ $$^ -D $(GLIBC_DUMP) $(GLIBC_PATHS) $(2)
+
+all : $(OUTDIR)/$(1).nmf
+endef
+