diff options
author | noelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-15 02:35:26 +0000 |
---|---|---|
committer | noelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-15 02:35:26 +0000 |
commit | f9a7a34abb8e2d069a44e07e70a22b9bc79efb72 (patch) | |
tree | f4d8c54a823e88d6622a70ced9dd71a22451e920 /native_client_sdk | |
parent | 2a2cdf0699150d7eb1c6f078733d6e6083d5f6e7 (diff) | |
download | chromium_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')
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 + |