summaryrefslogtreecommitdiff
path: root/native_client_sdk
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-09-19 22:36:51 +0100
committerTorne (Richard Coles) <torne@google.com>2013-09-19 22:36:51 +0100
commitd0247b1b59f9c528cb6df88b4f2b9afaf80d181e (patch)
tree5c397fadc190cc71bffe2ffad1efc27a5b95309d /native_client_sdk
parentf7571f5f07547e2f3e0addf48d1f2a7ec3632957 (diff)
downloadchromium_org-d0247b1b59f9c528cb6df88b4f2b9afaf80d181e.tar.gz
Merge from Chromium at DEPS revision 224184
This commit was generated by merge_to_master.py. Change-Id: Ia3424df5abed9bea642c522b9e2358dceabd8423
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/build_tools/generate_make.py9
-rwxr-xr-xnative_client_sdk/src/build_tools/parse_dsc.py4
-rw-r--r--native_client_sdk/src/build_tools/sdk_files.list1
-rwxr-xr-xnative_client_sdk/src/build_tools/test_sdk.py8
-rw-r--r--native_client_sdk/src/doc/_sphinxext/devsite_builder.py16
-rw-r--r--native_client_sdk/src/doc/community/middleware.rst4
-rw-r--r--native_client_sdk/src/doc/devguide/coding/application-structure.rst266
-rw-r--r--native_client_sdk/src/doc/devguide/coding/message-system.rst384
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/building.rst4
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst606
-rw-r--r--native_client_sdk/src/doc/devguide/tutorial.rst2
-rw-r--r--native_client_sdk/src/doc/images/postmessage.pngbin100536 -> 0 bytes
-rw-r--r--native_client_sdk/src/doc/images/postmessage2.pngbin52716 -> 0 bytes
-rw-r--r--native_client_sdk/src/doc/index.rst2
-rw-r--r--native_client_sdk/src/doc/nacl-and-pnacl.rst100
-rw-r--r--native_client_sdk/src/doc/rest-devsite-examples.rst21
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/example.dsc2
-rw-r--r--native_client_sdk/src/getting_started/part1/hello_tutorial.cc17
-rw-r--r--native_client_sdk/src/getting_started/part1/index.html65
-rw-r--r--native_client_sdk/src/getting_started/part2/README23
-rw-r--r--native_client_sdk/src/getting_started/part2/example.dsc20
-rw-r--r--native_client_sdk/src/getting_started/part2/example.js24
-rw-r--r--native_client_sdk/src/getting_started/part2/hello_tutorial.cc56
-rw-r--r--native_client_sdk/src/getting_started/part2/index.html42
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc15
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tty.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/syscalls/remove.c8
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc3
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc2
-rwxr-xr-xnative_client_sdk/src/tools/run.py2
30 files changed, 1626 insertions, 81 deletions
diff --git a/native_client_sdk/src/build_tools/generate_make.py b/native_client_sdk/src/build_tools/generate_make.py
index 2b402d5699..2140642679 100644
--- a/native_client_sdk/src/build_tools/generate_make.py
+++ b/native_client_sdk/src/build_tools/generate_make.py
@@ -21,7 +21,7 @@ Trace.verbose = False
def IsExample(desc):
dest = desc['DEST']
- return dest.startswith('examples') or dest.startswith('tests')
+ return dest.startswith(('examples', 'tests', 'getting_started'))
def GenerateSourceCopyList(desc):
@@ -39,7 +39,9 @@ def GenerateSourceCopyList(desc):
sources.extend(desc.get('DATA', []))
if IsExample(desc):
- sources.extend(['common.js', 'icon128.png', 'background.js'])
+ sources.append('common.js')
+ if not desc.get('NO_PACKAGE_FILES'):
+ sources.extend(['icon128.png', 'background.js'])
return sources
@@ -235,7 +237,8 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
if IsExample(desc):
ProcessHTML(srcroot, dstroot, desc, toolchains, configs,
first_toolchain)
- GenerateManifest(srcroot, dstroot, desc)
+ if not desc.get('NO_PACKAGE_FILES'):
+ GenerateManifest(srcroot, dstroot, desc)
return (name, desc['DEST'])
diff --git a/native_client_sdk/src/build_tools/parse_dsc.py b/native_client_sdk/src/build_tools/parse_dsc.py
index 848e74d973..bf18d5710f 100755
--- a/native_client_sdk/src/build_tools/parse_dsc.py
+++ b/native_client_sdk/src/build_tools/parse_dsc.py
@@ -15,7 +15,11 @@ VALID_TOOLCHAINS = ['newlib', 'glibc', 'pnacl', 'win', 'linux', 'mac']
DSC_FORMAT = {
'DISABLE': (bool, [True, False], False),
'SEL_LDR': (bool, [True, False], False),
+ # Disable this project from being included in the NaCl packaged app.
'DISABLE_PACKAGE': (bool, [True, False], False),
+ # Don't generate the additional files to allow this project to run as a
+ # packaged app (i.e. manifest.json, background.js, etc.).
+ 'NO_PACKAGE_FILES': (bool, [True, False], False),
'TOOLS' : (list, VALID_TOOLCHAINS, True),
'CONFIGS' : (list, ['Debug', 'Release'], False),
'PREREQ' : (list, '', False),
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index 91bddbb93d..b42123d9b0 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -41,6 +41,7 @@ examples/tutorial/using_ppapi_simple/*
[win]getting_started/make.bat
getting_started/Makefile
getting_started/part1/*
+getting_started/part2/*
include/error_handling/*
include/GLES2/*
include/gmock/*
diff --git a/native_client_sdk/src/build_tools/test_sdk.py b/native_client_sdk/src/build_tools/test_sdk.py
index 6adce2fcef..cf5db614b5 100755
--- a/native_client_sdk/src/build_tools/test_sdk.py
+++ b/native_client_sdk/src/build_tools/test_sdk.py
@@ -30,11 +30,11 @@ sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import getos
def StepBuildExamples(pepperdir):
- build_sdk.BuildStepMakeAll(pepperdir, 'getting_started',
- 'Build Getting Started',
- deps=False, config='Release')
-
for config in ('Debug', 'Release'):
+ build_sdk.BuildStepMakeAll(pepperdir, 'getting_started',
+ 'Build Getting Started (%s)' % config,
+ deps=False, config=config)
+
build_sdk.BuildStepMakeAll(pepperdir, 'examples',
'Build Examples (%s)' % config,
deps=False, config=config)
diff --git a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
index dc881bceb3..461c606554 100644
--- a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
+++ b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
@@ -61,6 +61,11 @@ class DevsiteHTMLTranslator(HTMLTranslator):
Hooked into the HTML builder by setting the html_translator_class
option in conf.py
+
+ HTMLTranslator is provided by Sphinx. It's a subclass of the
+ HTMLTranslator provided by docutils, with Sphinx-specific features added.
+ Here we provide devsite-specific behavior by overriding some of the
+ visiting methods.
"""
def __init__(self, builder, *args, **kwds):
# HTMLTranslator is an old-style Python class, so 'super' doesn't work: use
@@ -85,6 +90,17 @@ class DevsiteHTMLTranslator(HTMLTranslator):
# Override to not pop anything from context
self.body.append('</ul>\n')
+ def visit_literal(self, node):
+ # Sphinx emits <tt></tt> for literals (``like this``), with <span> per word
+ # to protect against wrapping, etc. We're required to emit plain <code>
+ # tags for them.
+ # Emit a simple <code> tag without enabling "protect_literal_text" mode,
+ # so Sphinx's visit_Text doesn't mess with the contents.
+ self.body.append(self.starttag(node, 'code', suffix=''))
+
+ def depart_literal(self, node):
+ self.body.append('</code>')
+
def visit_literal_block(self, node):
# We don't use Sphinx's buildin pygments integration for code highlighting,
# because the devsite requires special <pre> tags for that and handles the
diff --git a/native_client_sdk/src/doc/community/middleware.rst b/native_client_sdk/src/doc/community/middleware.rst
new file mode 100644
index 0000000000..9a02f13fc9
--- /dev/null
+++ b/native_client_sdk/src/doc/community/middleware.rst
@@ -0,0 +1,4 @@
+###############################
+Middleware and Software Support
+###############################
+
diff --git a/native_client_sdk/src/doc/devguide/coding/application-structure.rst b/native_client_sdk/src/doc/devguide/coding/application-structure.rst
index c79185085e..fd5a06d662 100644
--- a/native_client_sdk/src/doc/devguide/coding/application-structure.rst
+++ b/native_client_sdk/src/doc/devguide/coding/application-structure.rst
@@ -4,5 +4,269 @@
Application Structure
#####################
-foo
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+This chapter of the Developer's Guide describes the general structure of a
+Native Client application. The chapter assumes you are familiar with the
+material presented in the :doc:`Technical Overview <../../overview>`.
+
+
+.. Note::
+ :class: note
+
+ The "Hello, World" example is used here to illustrate basic
+ Native Client programming techniques. You can find this code in the
+ */examples/hello_world* directory in the Native Client SDK download.
+
+Glossary
+========
+
+instance
+ A rectangle on a web page that is managed by a Native Client module (the
+ rectangle can have width=0 and height=0, which means that nothing is drawn on
+ the page).
+
+manifest file
+ A file containing metadata or information about accompanying files.
+
+module
+ Short for "Native Client module," which is an executable file that is
+ generated by compiling C or C++ code with the Native Client toolchain. The
+ file extension for a module is .nexe.
+
+
+Application components
+======================
+
+A Native Client application typically contains the following components:
+
+* an HTML file;
+* JavaScript code, which can be included in the HTML file or contained in one or
+ more separate .js files;
+* CSS styles, which can be included in the HTML file or contained in one or more
+ separate .css files;
+* a Native Client manifest file (with a .nmf extension) that specifies how to
+ load a Native Client module for different processors; and
+* a Native Client module, written in C or C++, and compiled into one or more
+ executable files (with a .nexe extension) for different processors.
+
+
+Applications that are published in the `Chrome Web Store
+<https://chrome.google.com/webstore/search?q=%22Native+Client%22+OR+NativeClient+OR+NaCl>`_
+also include a Chrome
+Web Store manifest file ``(manifest.json)`` and one or more icon files.
+
+
+HTML file and the <embed> element
+=================================
+
+The ``<embed>`` element in an HTML file triggers the loading of a Native Client module and specifies the rectangle on the web page that is managed by the module. Here is the <embed> element from the "Hello, World" application:
+
+.. naclcode::
+
+ <embed name="nacl_module"
+ id="hello_world"
+ width=200 height=200
+ src="hello_world.nmf"
+ type="application/x-nacl" />
+
+In the ``<embed>`` element:
+
+name
+ is the DOM name attribute for the Native Client module
+ ("nacl_module" is often used as a convention)
+id
+ specifies the DOM ID for the Native Client module
+width, height
+ specify the size in pixels of the rectangle on the web page that is
+ managed by the Native Client module (if the module does not have a
+ visible area, these values can be 0)
+src
+ refers to the Native Client manifest file that is used to determine
+ which version of a module to load based on the architecture of the
+ user's computer (see the following section for more information)
+type
+ specifies the MIME type of the embedded content; for Native Client
+ modules the type must be "application/x-nacl"
+
+
+.. _manifest_file:
+
+Manifest Files
+==============
+
+Native Client applications have two types of manifest files: a Chrome Web Store
+manifest file and a Native Client manifest file.
+
+A **Chrome Web Store manifest file** is a file with information about a web
+application that is published in the Chrome Web Store. This file, named
+``manifest.json``, is required for applications that are published in the Chrome
+Web Store. For more information about this file see :doc:`Distributing Your
+Application <../distributing>`. and the `Chrome Web Store manifest file format
+<http://code.google.com/chrome/extensions/manifest.html>`_.
+
+A **Native Client manifest file** is a file that specifies which Native Client
+module (executable) to load for each of the supported end-user computer
+architectures (for example, x86-32, x86-64, or ARM). This file is required for
+all Native Client applications. The extension for this file is .nmf.
+
+The browser uses the Native Client manifest file to determine which compiled
+Native Client module to load for a given end-user computer architecture. In most
+cases, you can simply use the Python script provided with the SDK,
+``create_nmf.py``, to create a manifest file for your application as part of the
+compilation step (see the Makefile in any of the SDK examples for an
+illustration of how to do so).
+
+Here's a sample manifest file for an application that uses the
+:ref:`newlib<c_libraries>` C library:
+
+.. naclcode::
+
+ {
+ "program": {
+ "x86-32": {
+ "url": "hello_world_x86_32.nexe"
+ },
+ "x86-64": {
+ "url": "hello_world_x86_64.nexe"
+ },
+ "arm": {
+ "url": "hello_world_arm.nexe"
+ }
+ }
+ }
+
+For applications that use the newlib library, a typical manifest file contains a
+`JSON <http://www.json.org/>`_ dictionary with a single top-level key/value
+pair: the "program" key and a value consisting of a nested dictionary. The
+nested dictionary contains keys corresponding to the names of the supported
+computer architectures, and values referencing the file to load for a given
+architecture—specifically, the URL of the .nexe file, given by the ``"url"``
+key. URLs are specified relative to the location of the manifest file.
+
+For applications that use the :ref:`glibc<c_libraries>`
+library, the manifest file must also contain a "files" key that specifies the
+shared libraries that the applications use. This is discussed in detail in
+:doc:`Dynamic Linking and Loading with glibc<../devcycle/dynamic-loading>`. To
+see some example manifest files, build some of the example applications in the
+SDK (run ``make`` in the example subdirectories) and look at the generated
+manifest files.
+
+
+Modules and instances
+=====================
+
+A Native Client **module** is C or C++ code compiled into an executable .nexe file.
+
+An **instance** is a rectangle on a web page that is managed by a module. An
+instance may have a dimension of width=0 and height=0, meaning that the instance
+does not have any visible component on the web page. An instance is created by
+including an ``<embed>`` element in a web page. The ``<embed>`` element
+references a Native Client manifest file that loads a version of the module
+compiled for the end-user's computer architecture. A module may be included in a
+web page multiple times by using multiple ``<embed>`` elements that refer to the
+module; in this case the Native Client runtime system loads the module once and
+creates multiple instances that are managed by the module.
+
+The "Hello, World" example has one instance of the ``hello_world`` module, i.e.,
+one ``<embed>`` element in ``hello_world.html``. The actual module that is
+loaded (``hello_world_x86_32.nexe`` or ``hello_world_x86_64.nexe``) depends on
+the end-user computer architecture.
+
+
+Native Client modules: A closer look
+====================================
+
+A Native Client module must include three components:
+
+* a factory function called ``CreateModule()``
+* a Module class (derived from the ``pp::Module`` class)
+* an Instance class (derived from the ``pp:Instance`` class)
+
+In the "Hello, World" example, these three components are specified in the file
+``hello_world.cc``. Here is the factory function:
+
+.. naclcode::
+
+ Module* CreateModule() {
+ return new hello_world::HelloWorldModule();
+ }
+
+Native Client modules do not have a ``main()`` function. The ``CreateModule()``
+factory function is the main binding point between a module and the browser, and
+serves as the entry point into the module. The browser calls ``CreateModule()``
+when a module is first loaded; this function returns a Module object derived
+from the ``pp::Module`` class. The browser keeps a singleton of the Module
+object.
+
+Below is the Module class from the "Hello, World" example:
+
+.. naclcode::
+
+ class HelloWorldModule : public pp::Module {
+ public:
+ HelloWorldModule() : pp::Module() {}
+ virtual ~HelloWorldModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new HelloWorldInstance(instance);
+ }
+ };
+
+
+The Module class must include a ``CreateInstance()`` function. The browser calls
+the ``CreateInstance()`` function of the Module object returned by
+``CreateModule()`` every time it encounters an ``<embed>`` element on a web page
+that references the same module. The ``CreateInstance()`` function creates and
+returns an Instance object derived from the ``pp::Instance`` class.
+
+Below is the Instance class from the "Hello, World" example:
+
+.. naclcode::
+
+ class HelloWorldInstance : public pp::Instance {
+ public:
+ explicit HelloWorldInstance(PP_Instance instance) : pp::Instance(instance) {}
+ virtual ~HelloWorldInstance() {}
+
+ virtual void HandleMessage(const pp::Var& var_message);
+ };
+
+As in the example above, the Instance class for your module will likely include
+an implementation of the ``HandleMessage()`` funtion. The browser calls an
+instance's ``HandleMessage()`` function every time the JavaScript code in an
+application calls ``postMessage()`` to send a message to the instance. See the
+:doc:`Native Client messaging system<message-system>` for more information about
+how to send messages between JavaScript code and Native Client modules.
+
+The module in the "Hello, World" example is created from two files:
+``hello_world.cc`` and ``helper_functions.cc``. The first file,
+``hello_world.cc``, contains the ``CreateModule()`` factory function and the
+Module and Instance classes described above. The second file,
+``helper_functions.cc``, contains plain C++ functions that do not use the Pepper
+API. This is a typical design pattern in Native Client, where plain C++
+non-Pepper functions (functions that use standard types like ``string``) are
+specified in a separate file from Pepper functions (functions that use ``Var``,
+for example). This design pattern allows the plain C++ functions to be
+unit-tested with a command-line test (e.g., ``test_helper_functions.cc``); this
+is easier than running tests inside Chrome.
+
+While the ``CreateModule()`` factory function, the ``Module`` class, and the
+``Instance`` class are required for a Native Client application, the code
+samples shown above don't actually do anything. Subsequent chapters in the
+Developer's Guide build on these code samples and add more interesting
+functionality.
+
+
+Threading
+=========
+
+.. FIXME: link to pp:Core page for CallOnMainThread. But this is no longer
+ true anyway...
+
+Currently, calls to a Native Client module always execute on the main thread of
+the module. Similarly, all calls to the Pepper API (with the exception of
+pp::Core::CallOnMainThread()) must be made on the main thread of the module.
diff --git a/native_client_sdk/src/doc/devguide/coding/message-system.rst b/native_client_sdk/src/doc/devguide/coding/message-system.rst
index 6120254b41..14d52fc05d 100644
--- a/native_client_sdk/src/doc/devguide/coding/message-system.rst
+++ b/native_client_sdk/src/doc/devguide/coding/message-system.rst
@@ -1,5 +1,381 @@
-##############
-Message System
-##############
+.. _messaging_system:
-foo
+################
+Messaging System
+################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+This chapter describes the messaging system used to communicate between the
+JavaScript code and the Native Client module's C or C++ code in a
+Native Client application. It introduces the concept of asynchronous
+programming and the basic steps required to set up a Native Client module
+that sends messages to and receive messages from JavaScript. This chapter
+assumes you are familiar with the material presented in the
+:doc:`Application Structure <application-structure>` chapter.
+
+.. Note::
+ :class: note
+
+ The "Hello, World" example for getting started with NaCl is used here to
+ illustrate basic programming techniques. You can find this code in
+ the ``/getting_started/part2`` directory in the Native Client SDK download.
+
+Reference information
+=====================
+
+For reference information related to the Pepper messaging API, see the
+following documentation:
+
+* `pp::Instance class <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance>`_ HandleMessage(), PostMessage())
+* `pp::Module class <https://developers.google.com/native-client/peppercpp/classpp_1_1_module>`_
+* `pp::Var class <https://developers.google.com/native-client/peppercpp/classpp_1_1_var>`_
+
+
+Glossary
+========
+
+asynchronous programming
+ In the asynchronous programming model, function calls are executed and
+ return immediately without waiting for a response. Using this model,
+ functions are nonblocking; the web browser continues processing JavaScript
+ and C/C++ functions.
+Var
+ An object in a Native Client module that corresponds to a JavaScript
+ variable.
+web workers
+ `Web workers <http://en.wikipedia.org/wiki/Web_Workers>`_ provide a
+ mechanism for running heavy-weight JavaScript code on background threads
+ so that the main web page can continue to respond to user interaction.
+ Web pages interact with web workers by using ``postMessage()`` to send
+ messages. The way a web page interacts with a Native Client module
+ is analogous to the way it interacts with web workers.
+
+
+Introduction to the messaging system
+====================================
+
+Native Client modules and JavaScript communicate by sending messages
+to each other. The most basic form of a message is a string. Messages
+support many JavaScript types, including ints, arrays, array buffers,
+and dictionaries (see `pp::Var
+<https://developers.google.com/native-client/peppercpp/classpp_1_1_var>`_,
+`pp:VarArrayBuffer
+<https://developers.google.com/native-client/peppercpp/classpp_1_1_var_array_buffer>`_,
+and the general `messaging system documentation
+<https://developers.google.com/native-client/pepperc/struct_p_p_b___messaging__1__0>`_).
+It's up to you to decide on the type of message and define how to
+process the messages on both the JavaScript and Native Client
+side. For the "Hello, World" example, we will work with string-typed
+messages only.
+
+When JavaScript posts a message to the Native Client module, the
+Pepper ``HandleMessage()`` function is invoked on the module
+side. Similarly, the Native Client module can post a message to
+JavaScript, and this message triggers a JavaScript event listener for
+``message`` events in the DOM. (See the W3C specification on
+`Document Object Model Events
+<http://www.w3.org/TR/DOM-Level-2-Events/events.html>`_ for more
+information.) In the "Hello, World" example, the JavaScript functions for
+posting and handling messages are named ``postMessage()`` and
+``handleMessage()`` (but any names could be used). On the Native Client
+C++ side, the Pepper Library functions for posting and handling
+messages are:
+
+* ``void pp::Instance::PostMessage(const Var &message)``
+* ``virtual void pp::Instance::HandleMessage(const Var &message)``
+
+If you want to receive messages from JavaScript, you need to implement the
+``pp::Instance::HandleMessage()`` function in your Native Client module.
+
+Design of the messaging system
+------------------------------
+
+The Native Client messaging system is analogous to the system used by
+the browser to allow web workers to communicate (see the `W3 web
+worker specification <http://www.w3.org/TR/workers>`_). The Native
+Client messaging system is designed to keep the web page responsive while the
+Native Client module is performing potentially heavy processing in the
+background. When JavaScript sends a message to the Native Client
+module, the ``postMessage()`` call returns as soon as it sends its message
+to the Native Client module. The JavaScript does not wait for a reply
+from Native Client, thus avoiding bogging down the main JavaScript
+thread. On the JavaScript side, you set up an event listener to
+respond to the message sent by the Native Client module when it has
+finished the requested processing and returns a message.
+
+This asynchronous processing model keeps the main thread free while
+avoiding the following problems:
+
+* The JavaScript engine hangs while waiting for a synchronous call to return.
+* The browser pops up a dialog when a JavaScript entry point takes longer
+ than a few moments.
+* The application hangs while waiting for an unresponsive Native Client module.
+
+Communication tasks in the "Hello, World" example
+=================================================
+
+The following sections describe how the "Hello, World" example posts
+and handles messages on both the JavaScript side and the Native Client
+side of the application.
+
+JavaScript code
+---------------
+
+The JavaScript code and HTML in the "Hello, World" example can be
+found in the ``example.js``, ``common.js``, and ``index.html`` files.
+The important steps are:
+
+#. Sets up an event listener to listen for ``message`` events from the
+ Native Client module.
+#. Implements an event handler that the event listener invokes to handle
+ incoming ``message`` events.
+#. Calls ``postMessage()`` to communicate with the NaCl module,
+ after the page loads.
+
+Step 1: From common.js
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ function attachDefaultListeners() {
+ // The NaCl module embed is created within the listenerDiv
+ var listenerDiv = document.getElementById('listener');
+ // ...
+
+ // register the handleMessage function as the message event handler.
+ listenerDiv.addEventListener('message', handleMessage, true);
+ // ...
+ }
+
+
+Step 2: From example.js
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ // This function is called by common.js when a message is received from the
+ // NaCl module.
+ function handleMessage(message) {
+ // In the example, we simply log the data that's received in the message.
+ var logEl = document.getElementById('log');
+ logEl.textContent += message.data;
+ }
+
+ // In the index.html we have set up the appropriate divs:
+ <body {{attrs}}>
+ <!-- ... -->
+ <div id="listener"></div>
+ <div id="log"></div>
+ </body>
+
+
+Step 3: From example.js
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ // From example.js, Step 3:
+ function moduleDidLoad() {
+ // After the NaCl module has loaded, common.naclModule is a reference to the
+ // NaCl module's <embed> element.
+ //
+ // postMessage sends a message to it.
+ common.naclModule.postMessage('hello');
+ }
+
+
+Native Client module
+--------------------
+
+The C++ code in the Native Client module of the "Hello, World" example:
+
+#. Implements ``pp::Instance::HandleMessage()`` to handle messages sent
+ by the JavaScript.
+#. Processes incoming messages. This example simply checks that JavaScript
+ has sent a "hello" message and not some other message.
+#. Calls ``PostMessage()`` to send an acknowledgement back to the
+ JavaScript code. The acknowledgement is a string in the form of a ``Var``
+ that the JavaScript code can process. In general, a ``pp::Var`` can be
+ several JavaScript types, see the
+ `messaging system documentation
+ <https://developers.google.com/native-client/pepperc/struct_p_p_b___messaging__1__0>`_.
+
+
+.. naclcode::
+
+ class HelloTutorialInstance : public pp::Instance {
+ public:
+ // ...
+
+ // === Step 1: Implement the HandleMessage function. ===
+ virtual void HandleMessage(const pp::Var& var_message) {
+
+ // === Step 2: Process the incoming message. ===
+ // Ignore the message if it is not a string.
+ if (!var_message.is_string())
+ return;
+
+ // Get the string message and compare it to "hello".
+ std::string message = var_message.AsString();
+ if (message == kHelloString) {
+ // === Step 3: Send the reply. ===
+ // If it matches, send our response back to JavaScript.
+ pp::Var var_reply(kReplyString);
+ PostMessage(var_reply);
+ }
+ }
+ };
+
+
+Messaging in JavaScript code: More details.
+===========================================
+
+This section describes in more detail the messaging system code in the
+JavaScript portion of the "Hello, World" example.
+
+Setting up an event listener and handler
+----------------------------------------
+
+The following JavaScript code sets up an event listener for messages
+posted by the Native Client module. It then defines a message handler
+that simply logs the content of messages received from the module.
+
+Setting up the 'message' handler on load
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ // From common.js
+
+ // Listen for the DOM content to be loaded. This event is fired when
+ // parsing of the page's document has finished.
+ document.addEventListener('DOMContentLoaded', function() {
+ var body = document.body;
+ // ...
+ var loadFunction = common.domContentLoaded;
+ // ... set up parameters ...
+ loadFunction(...);
+ }
+
+ // This function is exported as common.domContentLoaded.
+ function domContentLoaded(...) {
+ // ...
+ if (common.naclModule == null) {
+ // ...
+ attachDefaultListeners();
+ // initialize common.naclModule ...
+ } else {
+ // ...
+ }
+ }
+
+ function attachDefaultListeners() {
+ var listenerDiv = document.getElementById('listener');
+ // ...
+ listenerDiv.addEventListener('message', handleMessage, true);
+ // ...
+ }
+
+
+Implementing the handler
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ // From example.js
+ function handleMessage(message) {
+ var logEl = document.getElementById('log');
+ logEl.textContent += message.data;
+ }
+
+
+Note that the ``handleMessage()`` function is handed a message_event
+containing ``data`` that you can display or manipulate in JavaScript. The
+"Hello, World" application simply logs this data to the ``log`` div.
+
+
+Messaging in the Native Client module: More details.
+====================================================
+
+This section describes in more detail the messaging system code in
+the Native Client module portion of the "Hello, World" example.
+
+Implementing HandleMessage()
+----------------------------
+
+If you want the Native Client module to receive and handle messages
+from JavaScript, you need to implement a ``HandleMessage()`` function
+for your module's ``pp::Instance`` class. The
+``HelloWorldInstance::HandleMessage()`` function examines the message
+posted from JavaScript. First it examines that the type of the
+``pp::Var`` is indeed a string (not a double, etc.). It then
+interprets the data as a string with ``var_message.AsString()``, and
+checks that the string matches ``kHelloString``. After examining the
+message received from JavaScript, the code calls ``PostMessage()`` to
+send a reply message back to the JavaScript side.
+
+.. naclcode::
+
+ namespace {
+
+ // The expected string sent by the JavaScript.
+ const char* const kHelloString = "hello";
+ // The string sent back to the JavaScript code upon receipt of a message
+ // containing "hello".
+ const char* const kReplyString = "hello from NaCl";
+
+ } // namespace
+
+ class HelloTutorialInstance : public pp::Instance {
+ public:
+ // ...
+ virtual void HandleMessage(const pp::Var& var_message) {
+ // Ignore the message if it is not a string.
+ if (!var_message.is_string())
+ return;
+
+ // Get the string message and compare it to "hello".
+ std::string message = var_message.AsString();
+ if (message == kHelloString) {
+ // If it matches, send our response back to JavaScript.
+ pp::Var var_reply(kReplyString);
+ PostMessage(var_reply);
+ }
+ }
+ };
+
+
+Implementing application-specific functions
+-------------------------------------------
+
+While the "Hello, World" example is very simple, your Native Client
+module will likely include application-specific functions to perform
+custom tasks in response to messages. For example the application
+could be a compression and decompression service (two functions
+exported). The application could set up an application-specific
+convention that messages coming from JavaScript are colon-separated
+pairs of the form ``<command>:<data>``. The Native Client module
+message handler can then split the incoming string along the ``:``
+character to determine which command to execute. If the command is
+"compress", then data to process is an uncompressed string. If the
+command is "uncompress", then data to process is an already-compressed
+string. After processing the data asynchronously, the application then
+returns the result to JavaScript.
+
+
+Sending messages back to the JavaScript code
+--------------------------------------------
+
+The Native Client module sends messages back to the JavaScript code
+using ``PostMessage()``. The Native Client module always returns
+its values in the form of a ``pp::Var`` that can be processed by the
+browser's JavaScript. In this example, the message is posted at the
+end of the Native Client module's ``HandleMessage()`` function:
+
+.. naclcode::
+
+ PostMessage(var_reply);
diff --git a/native_client_sdk/src/doc/devguide/devcycle/building.rst b/native_client_sdk/src/doc/devguide/devcycle/building.rst
index 413d6b0d81..48cca76693 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/building.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/building.rst
@@ -19,6 +19,8 @@ If you haven't read the Native Client :doc:`Technical Overview
<../../overview>` and :doc:`Tutorial <../tutorial>`, we recommend starting
with those.
+.. _target_architectures:
+
Target architectures
--------------------
@@ -195,6 +197,8 @@ targets the x86-64 architecture, i.e., ``x86_64-nacl-gcc``.
You should name executable modules with a ``.nexe`` filename extension,
regardless of what platform you're using.
+.. _compile_flags:
+
Compile flags for different development scenarios
=================================================
diff --git a/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst b/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
index a5f7e5ec11..c19fa8244a 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
@@ -1,3 +1,609 @@
######################################
Dynamic Linking and Loading with glibc
######################################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Introduction
+============
+
+This document describes how to create and deploy dynamically linked and loaded
+applications with the glibc library in the Native Client SDK. Before reading
+this document, we recommend reading :doc:`Building Native Client Modules
+<building>`
+
+.. _c_libraries:
+
+C standard libraries: glibc and newlib
+--------------------------------------
+
+The Native Client SDK comes with two C standard libraries --- glibc and
+newlib. These libraries are described in the table below.
+
++--------+----------+-------------+--------------------------------------------+
+| Library| Linking | License | Description |
++========+==========+=============+============================================+
+| glibc | dynamic | GNU Lesser | glibc is the GNU implementation of the |
+| | or static| General | POSIX_ standard runtime library for the C |
+| | | Public | programming language. Designed for |
+| | | License | portability and performance, glibc is one |
+| | | (LGPL) | of the most popular implementations of the |
+| | | | C library. It is comprised of a set of |
+| | | | interdependent libraries including libc, |
+| | | | libpthreads, libdl, and others. For |
+| | | | documentation, FAQs, and additional |
+| | | | information about glibc, see GLIBC_ |
++--------+----------+-------------+--------------------------------------------+
+| newlib | static | Berkeley | newlib is a C library intended for use in |
+| | | Software | embedded systems. Like glibc, newlib is a |
+| | | Distribution| conglomeration of several library parts. |
+| | | (BSD) type | It is available for use under BSD-type free|
+| | | free | software licenses, which generally makes it|
+| | | software | more suitable to link statically in |
+| | | licenses | commercial, closed-source applications. For|
+| | | | documentation, FAQs, and additional |
+| | | | information about newlib, see the `newlib |
+| | | | documentation`__. |
++--------+----------+-------------+--------------------------------------------+
+
+.. _GLIBC: http://www.gnu.org/software/libc/index.html
+.. _POSIX: http://en.wikipedia.org/wiki/POSIX
+__ http://sourceware.org/newlib
+
+For proprietary (closed-source) applications, your options are to either
+statically link to newlib, or dynamically link to glibc. We recommend
+dynamically linking to glibc, for a couple of reasons:
+
+* The glibc library is widely distributed (it's included in Linux
+ distributions), and as such it's mature, hardened, and feature-rich. Your
+ code is more likely to compile out-of-the-box with glibc.
+
+* Dynamic loading can provide a big performance benefit for your application if
+ you can structure the application to defer loading of code that's not needed
+ for initial interaction with the user. It takes some work to put such code in
+ shared libraries and to load the libraries at runtime, but the payoff is
+ usually worth it. In future releases, Chrome may also support caching of
+ common dynamically linked libraries such as libc.so between applications.
+ This could significantly reduce download size and provide a further potential
+ performance benefit (for example, the hello_world example would only require
+ downloading a .nexe file that's on the order of 30KB, rather than a .nexe
+ file and several libraries, which are on the order of 1.5MB).
+
+Native Client support for dynamic linking and loading is based on glibc. Thus,
+**if your Native Client application must dynamically link and load code (e.g.,
+due to licensing considerations), we recommend that you use the glibc
+library.**
+
+.. Note::
+ :class: note
+
+ **Notes:**
+
+ * **None of the above constitutes legal advice, or a description of the legal
+ obligations you need to fulfill in order to be compliant with the LGPL or
+ newlib licenses. The above description is only a technical explanation of
+ the differences between newlib and glibc, and the choice you must make
+ between the two libraries.**
+
+ * Static linking with glibc is rarely used. Use this feature with caution.
+
+ * The standard C++ runtime in Native Client is provided by libstdc++; this
+ library is independent from and layered on top of glibc. Because of
+ licensing restrictions, libstdc++ must be statically linked for commercial
+ uses, even if the rest of an application is dynamically linked.
+
+SDK toolchains
+--------------
+
+The Native Client SDK contains multiple toolchains, which are differentiated by
+:ref:`target architecture <target_architectures>` and C library:
+
+=================== ========= ===============================
+Target architecture C library Toolchain directory
+=================== ========= ===============================
+x86 newlib toolchain/<platform>_x86_newlib
+x86 glibc toolchain/<platform>_x86_glibc
+ARM newlib toolchain/<platform>_arm_newlib
+PNaCl newlib toolchain/<platform>_pnacl
+=================== ========= ===============================
+
+In the directories listed above, <platform> is the platform of your development
+machine (i.e., win, mac, or linux). For example, in the Windows SDK, the x86
+toolchain that uses glibc is in ``toolchain/win_x86_glibc``.
+
+.. Note::
+ :class: note
+
+ **Note:** The ARM and PNaCl toolchains are currently restricted to newlib.
+
+To use the glibc library and dynamic linking in your application, you **must**
+use a glibc toolchain. (Currently the only glibc toolchain is
+``<platform>_x86_glibc``.) Note that you must build all code in your application
+with one toolchain. Code from multiple toolchains cannot be mixed.
+
+Specifying and delivering shared libraries
+------------------------------------------
+
+One significant difference between newlib and glibc applications is that glibc
+applications must explicitly list and deploy the shared libraries that they
+use.
+
+In a desktop environment, when the user launches a dynamically linked
+application, the operating system's program loader determines the set of
+libraries the application requires by reading explicit inter-module
+dependencies from executable file headers, and loads the required libraries
+into the address space of the application process. Typically the required
+libraries will have been installed on the system as a part of the application's
+installation process. Often the desktop application developer doesn't know or
+think about the libraries that are required by an application, as those details
+are taken care of by the user's operating system.
+
+In the Native Client sandbox, dynamic linking can't rely in the same way on the
+operating system or the local file system. Instead, the application developer
+must identify the set of libraries that are required by an application, list
+those libraries in a Native Client :ref:`manifest file <manifest_file>`, and
+deploy the libraries along with the application. Instructions for how to build
+a dynamically linked Native Client application, generate a Native Client
+manifest (.nmf) file, and deploy an application are provided below.
+
+Building a dynamically linked application
+=========================================
+
+A dynamically linked application typically includes one Native Client module
+and one or more shared libraries. (How to allocate code between Native Client
+modules and shared libraries is a question of application design that is beyond
+the scope of this document.) Each Native Client module and shared library must
+be compiled for at least the x86 32-bit and 64-bit architectures.
+
+The dlopen example in the SDK
+-----------------------------
+
+The Native Client SDK includes an example that demonstrates how to build a
+shared library, and how to use the ``dlopen()`` interface to load that library
+at runtime (after the application is already running). Many applications load
+and link shared libraries at launch rather than at runtime, and hence do not
+use the ``dlopen()`` interface. The SDK example is nevertheless instructive, as
+it demonstrates how to build Native Client modules (.nexe files) and shared
+libraries (.so files) with the x86 glibc toolchain, and how to generate a
+Native Client manifest file for glibc applications.
+
+The SDK example, located in the directory examples/dlopen, includes two C++
+files:
+
+eightball.cc
+ This file implements the function ``Magic8Ball()``, which is used to provide
+ whimsical answers to user questions. The file is compiled into a shared
+ library, ``libeightball.so``.
+
+dlopen.cc
+ This file implements the Native Client module, which loads
+ ``libeightball.so``, receives messages from JavaScript (sent in response to
+ user input), calls ``Magic8Ball()`` to generate answers, and sends messages
+ back to JavaScript with the generated answers. The file is compiled into a
+ .nexe file.
+
+.. TODO(sbc): also mention reverse.{cc,h} files
+
+Run ``make`` in the dlopen directory to see the commands the Makefile executes
+to build x86 32-bit and 64-bit .nexe and .so files, and to generate a .nmf
+file. These commands are described below.
+
+.. Note::
+ :class: note
+
+ **Note:** The Makefiles for most of the examples in the SDK build the
+ examples using multiple toolchains (x86 newlib, x86 glibc, ARM, and PNaCl).
+ With a few exceptions (listed in the :ref:`Release Notes
+ <sdk-release-notes>`), running "make" in each example's directory builds
+ multiple versions of the example using the SDK toolchains. The dlopen example
+ is one of those exceptions – it is only built with the x86 glibc toolchain,
+ as that is currently the only toolchain that supports glibc and thus dynamic
+ linking and loading. Take a look at the example Makefiles and the generated
+ .nmf files for details on how to build dynamically linked applications.
+
+
+Building a Native Client module (.nexe file)
+--------------------------------------------
+
+.. TODO(sbc): there is a lot of redundant detail here. Also the Makefile
+ structure has changed significantly.
+
+The Makefile in the dlopen example builds ``dlopen.cc`` into a .nexe file using
+the two commands shown below. (For simplicity, the full path to the
+compiler/linker is not shown; the tool is located in the bin directory in the
+x86 glibc toolchain, e.g. toolchain/win_x86_glibc/bin.)
+
+To compile dlopen.cc into dlopen_x86_32.o::
+
+ i686-nacl-g++ -o dlopen_x86_32.o -c dlopen.cc -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall
+
+To link dlopen_x86_32.o into dlopen_x86_32.nexe::
+
+ i686-nacl-g++ -o dlopen_x86_32.nexe dlopen_x86_32.o -m32 -g -ldl -lppapi_cpp -lppapi
+
+A few of the flags in these commands are described below:
+
+``-o`` *file*
+ put the output in *file*
+
+``-c``
+ compile the source file, but do not link it
+
+``-m32``
+ produce 32-bit code (i.e., code for the x86-32 target architecture)
+
+``-g``
+ produce debugging information
+
+``-O0``
+ use a base optimization level that minimizes compile time
+
+``-pthread``
+ support multithreading with the pthread library
+
+``-W`` *warning*
+ request or supress the specified warning
+
+``-l`` *library*
+ use the specified *library* when linking (per C library naming conventions,
+ the linker uses the file lib*library*.so, or if that file is not available,
+ lib*library*.a; e.g., -ldl corresponds to libdl.so or libdl.a)
+
+Many of these flags are optional; you need not use all of them to compile and
+link your application. For example, you only need to use -ldl if your
+application uses the dlopen() interface to open a library at runtime. The
+toolchains in the Native Client SDK are based on the gcc compiler; see `gcc
+command options <http://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html>`_ for a
+full description of the gcc flags. For flags that are recommended with Native
+Client, see :ref:`compile flags for different development scenarios
+<compile_flags>`.
+
+Note that you can combine the compile and link steps to build a .nexe file
+using one command. Simply run i686-nacl-g++ once and use the appropriate
+combination of flags (omit the -c flag and include the -l flag with the
+required libraries)::
+
+ i686-nacl-g++ -o dlopen_x86_32.nexe dlopen.cc ^ -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall -ldl -lppapi_cpp -lppapi
+
+(The carat ``^`` allows the command to span multiple lines on Windows; to do
+the same on Mac and Linux use a backslash instead. Or you can simply type the
+command and all its arguments on one line.)
+
+The commands above build a 32-bit .nexe. To build a 64-bit .nexe, run the same
+commands but with the **-m64** flag instead of -m32, and of course specify
+different output file names. Check the Makefile in the dlopen example to see
+the set of commands that is used to generate 32-bit and 64-bit .nexes.
+
+Building a shared library (.so file)
+------------------------------------
+
+The Makefile in the dlopen example builds eightball.cc into a .so file using
+the two commands shown below.
+
+To compile eightball.cc into eightball_x86_32.o::
+
+ i686-nacl-g++ -o eightball_x86_32.o -c eightball.cc -m32 -g -O0 -pthread -std=gnu++98 -Wno-long-long -Wall -fPIC
+
+To link eightball_x86_32.o into eightball_x86_32.so::
+
+ i686-nacl-g++ -o libeightball.so eightball_x86_32.o -m32 -g -ldl -lppapi_cpp -lppapi -shared
+
+A couple of the important flags in these commands are described below:
+
+``-fPIC``
+ generate position-independent code (PIC) suitable for use in a shared library
+ (this flag is required for all x86 64-bit modules and for 32-bit shared
+ libraries)
+``-shared``
+ produce a shared object that can be linked with other objects to form an
+ executable (this flag is required for .so files)
+ As when building a .nexe, you can combine compiling and linking into one step
+ by running i686-nacl-g++ once with the appropriate combination of flags.
+
+As with .nexes, you need to generate both 32-bit and 64-bit versions of a
+shared object -- see the dlopen example for an illustration. In the dlopen
+example, the shared objects are put into the subdirectories ``lib32`` and
+``lib64``. These directories are used to collect all the shared libraries
+needed by the application, as discussed below.
+
+Generating a Native Client manifest file for a dynamically linked application
+=============================================================================
+
+The Native Client manifest file must specify the full list of executable files
+needed by an application, including the recursive closure of shared library
+dependencies. Take a look at the manifest file in the dlopen example to see how
+a glibc-style manifest file is structured. (Run make in the dlopen directory to
+generate the manifest file if you haven't done so already.) Here is an excerpt
+from ``dlopen.nmf``::
+
+ {
+ "files": {
+ "libeightball.so": {
+ "x86-64": {
+ "url": "lib64/libeightball.so"
+ },
+ "x86-32": {
+ "url": "lib32/libeightball.so"
+ }
+ },
+ "libstdc++.so.6": {
+ "x86-64": {
+ "url": "lib64/libstdc++.so.6"
+ },
+ "x86-32": {
+ "url": "lib32/libstdc++.so.6"
+ }
+ },
+ "libppapi_cpp.so": {
+ "x86-64": {
+ "url": "lib64/libppapi_cpp.so"
+ },
+ "x86-32": {
+ "url": "lib32/libppapi_cpp.so"
+ }
+ },
+ ... etc.
+
+In most cases, you can use the ``create_nmf.py`` script in the SDK to generate
+a manifest file for your application. The script is located in the tools
+directory (e.g., pepper_28/tools).
+
+.. TODO(sbc): running create_nmf.py is much simpler now.
+
+The Makefile in the dlopen example generates the manifest file ``dlopen.nmf``
+by running the following command::
+
+ python <NACL_SDK_ROOT>/tools/create_nmf.py ^
+ -D <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/bin/objdump ^
+ -o dlopen.nmf ^
+ -s . ^
+ dlopen_x86_32.nexe dlopen_x86_64.nexe lib32/libeightball.so lib64/libeightball.so ^
+ -L <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/lib32 ^
+ -L <NACL_SDK_ROOT>/toolchain/win_x86_glibc/x86_64-nacl/lib64
+
+(The carat ``^`` allows the command to span multiple lines on Windows; to do the
+same on Mac and Linux use a backslash instead, or you can simply type the
+command and all its arguments on one line. *<NACL_SDK_ROOT>* represents the path
+to the top-level directory of the bundle you are using, e.g.,
+*<location-where-you-installed-the-SDK>*/pepper_28.)
+
+
+Run python ``create_nmf.py --help`` to see a description of the command-line
+flags. A few of the important flags are described below.
+
+.. TODO(sbc): remove -D option which is now deprecated.
+
+``-D`` *tool*
+ use *tool* to read information about a file and determine shared library
+ dependencies (the tool must be a version of the `objdump
+ <http://en.wikipedia.org/wiki/Objdump>`_ utility)
+
+``-s`` *directory*
+ use *directory* to stage libraries (libraries are added to ``lib32`` and
+ ``lib64`` subfolders)
+
+``-L`` *directory*
+ add *directory* to the library search path
+
+.. Note::
+ :class: note
+
+ **Caution:** The ``create_nmf.py`` script only recognizes explicit shared
+ library dependencies (for example, dependencies specified with the -l flag
+ for the compiler/linker). The manifest file generated by create_nmf.py will
+ be incorrect in the following situations:
+
+ * You run ``create_nmf.py`` without listing as arguments all the libraries
+ that your application opens with ``dlopen()``.
+
+ * After you run ``create_nmf.py``, you subsequently add a library dependency
+ that is not mentioned in the manifest file.
+
+ * After you run ``create_nmf.py``, you subsequently change the directory
+ structure on your server or in your Chrome Web Store manifest file, such
+ that the needed libraries are no longer in the location specified in the
+ .nmf file
+
+ To handle the above situations correctly, you must re-run ``create_nmf.py``
+ (for example, if you added a new library dependency in your application or
+ changed the application directory structure), and make sure to list all the
+ libraries that your application opens at runtime with ``dlopen()`` (e.g.,
+ libeighball.so in the dlopen example).
+
+.. TODO(sbc): We probably don't want/need this next section in the docs at all.
+
+As an alternative to using ``create_nmf.py``, you can also chase down the full
+list of shared library dependencies manually and add those to your .nmf file.
+To do so, start by running the Native Client version of the objdump utility on
+your .nexe file, as shown below. (The objdump utility is located in the same
+directory as the glibc toolchain, e.g., toolchain/win_x86_glibc/bin.)
+
+::
+
+ i686-nacl-objdump -p dlopen_x86_32.nexe
+
+A .nexe file contains compiled machine code, as well as headers that describe
+the contents of the file and information about how to use the file. The objdump
+utility lets you examine the file's headers, including the "Dynamic Section,"
+which specifies shared library dependencies, as in this example output from the
+dlopen example::
+
+ Dynamic Section:
+ NEEDED libdl.so.32d9fc17
+ NEEDED libppapi_cpp.so
+ NEEDED libpthread.so.32d9fc17
+ NEEDED libstdc++.so.6
+ NEEDED libm.so.32d9fc17
+ NEEDED libgcc_s.so.1
+ NEEDED libc.so.32d9fc17
+ INIT 0x01000140
+ FINI 0x01002560
+ HASH 0x110025fc
+ ...
+
+
+All the files that are identified as NEEDED in the "Dynamic Section" portion of
+the objdump output are files that you need to list in your Native Client
+manifest file and distribute with your application. (The numbers listed at the
+end of the file names are version numbers, and you must list and distribute
+those exact versions.) Once you've identified the shared libraries that are
+needed by your .nexe file, you must repeat the process recursively: Run objdump
+on each of the NEEDED files, and add the newly-identified NEEDED files to your
+manifest file and to your distribution directories. To get the full list of
+libraries for an application, repeat the process until you've identified the
+recursive closure of dependencies.
+
+Deploying a dynamically linked application
+==========================================
+
+As described above, an application's manifest file must explicitly list all the
+executable code modules that the application requires, including modules from
+the application itself (.nexe and .so files), modules from the Native Client
+SDK (e.g., libppapi_cpp.so), and perhaps also modules from `naclports
+<http://code.google.com/p/naclports>`_ or from :doc:`middleware systems
+<../../community/middleware>` that the application uses. You must provide all of
+those modules as part of the application deployment process.
+
+As explained in :doc:`Distributing Your Application
+<../distributing>`, there are two basic ways to deploy an application:
+
+* **hosted application:** all modules are hosted together on a web server of
+ your choice
+
+* **packaged application:** all modules are packaged into one file, hosted in
+ the Chrome Web Store, and downloaded to the user's machine
+
+You must deploy all the modules listed in your application's manifest file for
+either the hosted application or the packaged application case. For hosted
+applications, you must upload the modules to your web server. For packaged
+applications, you must include the modules in the application's Chrome Web
+Store .crx file. Modules should use URLs/names that are consistent with those
+in the Native Client manifest file, and be named relative to the location of
+the manifest file. Remember that some of the libraries named in the manifest
+file may be located in directories you specified with the -L option to
+``create_nmf.py``. You are free to rename/rearrange files and directories
+referenced by the Native Client manifest file, so long as the modules are
+available in the locations indicated by the manifest file. If you move or
+rename modules, it may be easier to re-run create_nmf.py to generate a new
+manifest file rather than edit the original manifest file. For hosted
+applications, you can check for name mismatches during testing by watching the
+request log of the web server hosting your test deployment.
+
+Opening a shared library at runtime
+===================================
+
+Native Client supports a version of the POSIX standard ``dlopen()`` interface
+for opening libraries explicitly, after an application is already running.
+Calling ``dlopen()`` may cause a library download to occur, and automatically
+loads all libraries that are required by the named library.
+
+.. Note::
+ :class: note
+
+ **Caution:** Since ``dlopen()`` can potentially block, you must initially
+ call ``dlopen()`` off your application's main thread. Initial calls to
+ ``dlopen()`` from the main thread will always fail in the current
+ implementation of Native Client.
+
+The best practice for opening libraries with ``dlopen()`` is to use a worker
+thread to pre-load libraries asynchronously during initialization of your
+application, so that the libraries are available when they're needed. You can
+call ``dlopen()`` a second time when you need to use a library -- per the
+specification, subsequent calls to ``dlopen()`` return a handle to the
+previously loaded library. Note that you should only call dlclose() to close a
+library when you no longer need the library; otherwise, subsequent calls to
+``dlopen()`` could cause the library to be fetched again.
+
+The dlopen example in the SDK demonstrates how to open a shared library,
+magiceightball.so, at runtime. To reiterate, the example includes two C++
+files:
+
+.. TODO(sbc): mention the third .cc file which is now part of this example.
+
+* eightball.cc: this is the shared library that implements the function
+ ``Magic8Ball()`` (this file is compiled into libeightball.so)
+* dlopen.cc: this is the Native Client module that loads ``libeightball.so``
+ and calls ``Magic8Ball()`` to generate answers (this file is compiled into
+ dlopen_x86_{32,64}.nexe)
+
+When the Native Client module starts, it kicks off a worker thread that calls
+``dlopen()`` to load magiceightball.so. When the download of
+``libeightball.so`` completes, the worker thread schedules a callback function
+on the main thread. The callback function calls ``dlopen()`` for
+``magiceightball.so`` a second time; this second call obtains a proper handle
+to the library. Once the module has a handle to the library, it grabs the entry
+point in libeightball.so for the ``Magic8Ball()`` function. When a user types
+in a query and clicks the 'ASK!' button, the module calls ``Magic8Ball()`` to
+generate an answer, and returns the result to the user.
+
+The sequence of calls in the dlopen module is illustrated by the pseudo-code in
+the table below:
+
++------------------------------------------------+------------------------------------------+
+| Worker Thread | Main Thread |
++================================================+==========================================+
+| :: | :: |
+| | |
+| pthread_create(.., LoadLibrariesOnWorker, ..)| - |
+| - | LoadLibrariesOnWorker() |
+| - | LoadLibrary() |
+| - | dlopen("libeightball.so",...) |
+| - | CallOnMainThread(.., LoadDone, ..) |
+| LoadDone() | - |
+| UseLibrary() | - |
+| dlopen("libeightball.so", ...) | - |
+| offset = dlsym(..., "Magic8Ball") | - |
+| HandleMessage() | - |
+| _eightball = (TYPE_eightball) offset; | - |
+| PostMessage() | - |
++------------------------------------------------+------------------------------------------+
+
+Troubleshooting
+===============
+
+If your .nexe isn't loading, the best place to look for information that can
+help you troubleshoot the problem is stdout and nacllog. See the Debugging page
+for instructions about how to access those streams.
+
+Here are a few common error messages and explanations of what they mean:
+
+**/main.nexe: error while loading shared libraries: /main.nexe: failed to allocate code and data space for executable**
+ The .nexe may not have been compiled correctly (e.g., the .nexe may be
+ statically linked). Try cleaning and recompiling with the glibc toolchain.
+
+**/main.nexe: error while loading shared libraries: libpthread.so.xxxx: cannot open shared object file: Permission denied**
+ (xxxx is a version number, for example, 5055067a.) This error can result from
+ having the wrong path in the .nmf file. Double-check that the path in the
+ .nmf file is correct.
+
+**/main.nexe: error while loading shared libraries: /main.nexe: cannot open shared object file: No such file or directory**
+ If there are no obvious problems with your main.nexe entry in the .nmf file,
+ check where main.nexe is being requested from. Use Chrome's Developer Tools:
+ Click the menu icon |menu-icon|, select Tools > Developer Tools, click the
+ Network tab, and look at the path in the Name column.
+
+**NaCl module load failed: ELF executable text/rodata segment has wrong starting address**
+ This error happens when using a newlib-style .nmf file instead of a
+ glibc-style .nmf file. Make sure you build your application with the glic
+ toolchain, and use the create_nmf.py script to generate your .nmf file.
+
+**NativeClient: NaCl module load failed: Nexe crashed during startup**
+ This error message indicates that a module crashed while being loaded. You
+ can determine which module crashed by looking at the Network tab in Chrome's
+ Developer Tools (see above). The module that crashed will be the last one
+ that was loaded.
+
+**/lib/main.nexe: error while loading shared libraries: /lib/main.nexe: only ET_DYN and ET_EXEC can be loaded**
+ This error message indicates that there is an error with the .so files listed
+ in the .nmf file -- either the files are the wrong type or kind, or an
+ expected library is missing.
+
+**undefined reference to 'dlopen' collect2: ld returned 1 exit status**
+ This is a linker ordering problem that usually results from improper ordering
+ of command line flags when linking. Reconfigure your command line string to
+ list libraries after the -o flag.
+
+.. |menu-icon| image:: /images/menu-icon.png
diff --git a/native_client_sdk/src/doc/devguide/tutorial.rst b/native_client_sdk/src/doc/devguide/tutorial.rst
index d9976afd90..c636941b4b 100644
--- a/native_client_sdk/src/doc/devguide/tutorial.rst
+++ b/native_client_sdk/src/doc/devguide/tutorial.rst
@@ -369,7 +369,7 @@ Look for the JavaScript function ``moduleDidLoad()``, and add the new code below
(indicated by boldface type) to send a 'hello' message to the Native Client
module:
-..naclcode::
+.. naclcode::
function moduleDidLoad() {
HelloTutorialModule = document.getElementById('hello_tutorial');
diff --git a/native_client_sdk/src/doc/images/postmessage.png b/native_client_sdk/src/doc/images/postmessage.png
deleted file mode 100644
index e32876773c..0000000000
--- a/native_client_sdk/src/doc/images/postmessage.png
+++ /dev/null
Binary files differ
diff --git a/native_client_sdk/src/doc/images/postmessage2.png b/native_client_sdk/src/doc/images/postmessage2.png
deleted file mode 100644
index e26ec91667..0000000000
--- a/native_client_sdk/src/doc/images/postmessage2.png
+++ /dev/null
Binary files differ
diff --git a/native_client_sdk/src/doc/index.rst b/native_client_sdk/src/doc/index.rst
index 43fea41e76..84e78bf936 100644
--- a/native_client_sdk/src/doc/index.rst
+++ b/native_client_sdk/src/doc/index.rst
@@ -9,6 +9,7 @@ Contents:
rest-devsite-examples.rst
overview.rst
quick-start.rst
+ nacl-and-pnacl.rst
sdk/download.rst
sdk/examples.rst
sdk/index.rst
@@ -28,4 +29,5 @@ Contents:
devguide/coding/progress-events.rst
devguide/distributing.rst
community/application-gallery.rst
+ community/middleware.rst
peppercpp/index.rst
diff --git a/native_client_sdk/src/doc/nacl-and-pnacl.rst b/native_client_sdk/src/doc/nacl-and-pnacl.rst
new file mode 100644
index 0000000000..3881297675
--- /dev/null
+++ b/native_client_sdk/src/doc/nacl-and-pnacl.rst
@@ -0,0 +1,100 @@
+.. _nacl-and-pnacl:
+
+##############
+NaCl and PNaCl
+##############
+
+Introduction and historical background
+======================================
+
+Since its initial launch in 2011, Native Client enables executing native code
+securely inside a web application through the use of advanced Software Fault
+Isolation (SFI) techniques. TODO: link to paper?. Native Client provides
+developers with the ability to harness the client machine's computational power
+to a much fuller extent than traditional web technologies, by running compiled C
+and C++ code at near-native speeds and taking advantage of multiple cores with
+shared memory.
+
+While Native Client provides OS independence, it still requires developers to
+generate architecture-specific executable modules (**nexe**) for each hardware
+platform. In addition to being inconvenient for the developer,
+architecture-specific machine code is non-portable and not well suited to the
+open web. The traditional method of application distribution on the web is a
+self-contained bundle of HTML, CSS, JavaScript and resources (images, etc.) that
+can be hosted on a server and run inside a web browser. This means that a
+website created today should still work, on all platforms, years later.
+Architecture-specific executables are clearly not a good fit for this
+requirement.
+
+Therefore, today Native Client can only be used in applications and browser
+extensions that are installed through the Chrome Web Store. Exposing Native
+Client to the open web was deemed unacceptable as long as the technology is not
+fully portable.
+
+PNaCl
+=====
+
+PNaCl addresses the portability concern by splitting the compilation process
+into two parts: compiling the source code to a portable bitcode format, and
+translating this format to a host-specific executable. PNaCl enables developers
+to distribute *portable executables* (**pexe**-s) that the hosting environment
+(e.g. the Chrome browser) can translate to native code before executing. This
+aligns Native Client with existing open web technologies like JavaScript. The
+developer can simply distribute a **pexe** as part of an application along with
+HTML, CSS and JavaScript, and the user's machine will be able to run it. In
+other words, PNaCl combines the portability of existing web technologies with
+the performance and security benefits of Native Client.
+
+With PNaCl, the developer generates a single **pexe** from his source code,
+instead of a platform-specific **nexe** per architecture. The **pexe** provides
+both architecture- and OS-independence. Since the **pexe** contains an abstract,
+architecture-independent format, it does not have the portability problem
+described in the previous section. Future versions of the hosting environment
+should have no problem executing the **pexe**, even on new architectures.
+Moreover, if an existing architecture is enhanced in the future, the developer's
+code doesn't even have to be recompiled---in some cases the client-side
+translation will be able to take advantage of the new capabilities
+automatically.
+
+With the advent of PNaCl, the distribution limitations of Native Client can be
+lifted. Specifically, a **pexe** can simply be part of a web application---it
+does not have to be distributed through the Chrome Web Store.
+
+PNaCl is a new technology, so it still has a number of minor limitations when
+compared to existing, non-portable Native Client; the next sections describe the
+differences in detail.
+
+When to use PNaCl?
+==================
+
+PNaCl is the preferred toolchain for Native Client and the only way to deploy
+Native Client modules on the open web. Unless your project is considerably
+limited by one of the factors described in the next section, use PNaCl.
+
+Beginning with version 31, the Chrome web browser supports translation of
+**pexe** modules and their usage in web applications, without requiring the user
+to install the application explicitly or install any browser plugins. Native
+Client and PNaCl are open-source technologies, and our hope is that they will be
+added to other hosting platforms in the future.
+
+When to use non-portable NaCl
+=============================
+
+If controlled distribution through the web store is an important part of your
+product plan, the benefits of PNaCl are less important. However, note that it's
+still possible to use the PNaCl toolchain for distributing applications through
+the web store, and enjoy conveniences such as not needing to explicitly compile
+the application for all supported architectures.
+
+In addition, the following limitations apply to the initial release of PNaCl. If
+any of these are critical for your application, use non-portable Native Client:
+
+* By its nature, PNaCl does not support architecture-specific instructions in
+ the application (*inline assembly*). Future editions of PNaCl will attempt to
+ mitigate this problem by introducing portable intrinsics for vector
+ operations.
+* PNaCl only supports static linking with the ``newlib`` C standard library at
+ this time (a PNaCl port is provided by the NaCl SDK). Dynamic linking and
+ ``glibc`` are not supported. Work is under way to enable dynamic linking in
+ future versions of PNaCl.
+* In the initial release, PNaCl does not support C++ exception handling.
diff --git a/native_client_sdk/src/doc/rest-devsite-examples.rst b/native_client_sdk/src/doc/rest-devsite-examples.rst
index 304f972cdb..325993c7b1 100644
--- a/native_client_sdk/src/doc/rest-devsite-examples.rst
+++ b/native_client_sdk/src/doc/rest-devsite-examples.rst
@@ -78,6 +78,24 @@ To external locations
Plain links can be placed like this: http://google.com and also `like this
<http://google.com>`_.
+Definition lists
+================
+
+Can be used to define a group of related terms. Internal formatting is supported
+within the definition. No special formatting needs to be done for the definition
+name/title - it's handled by the devsite.
+
+Apple
+ The apple is the pomaceous fruit of the apple tree, species Malus domestica in
+ the rose family (**Rosaceae**).
+Fig
+ The common fig (**Ficus carica**) is a species of flowering plant in the genus
+ Ficus, from the family Moraceae, known as the common fig (or just the fig),
+ anjeer (Iran, Pakistan), and dumur (Bengali).
+Pear
+ The pear is any of several tree and shrub species of genus Pyrus /ˈpaɪrəs/, in
+ the family Rosaceae.
+
Notes and Admonitions
=====================
@@ -126,6 +144,9 @@ For some code (like shell samples), we want to disable pretty-printing:
By default ``:prettyprint:`` is ``1``.
+For short inline code, use fixed-formatting like ``int x = 2;``. Note that this
+won't get syntax-highlighted and may be line-wrapped, so keep it very short.
+
.. _link_for_section_heading:
Section heading
diff --git a/native_client_sdk/src/examples/demo/nacl_io/example.dsc b/native_client_sdk/src/examples/demo/nacl_io/example.dsc
index 4d1cf02770..65bb304366 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/example.dsc
+++ b/native_client_sdk/src/examples/demo/nacl_io/example.dsc
@@ -21,7 +21,7 @@
],
'DEST': 'examples/demo',
'NAME': 'nacl_io',
- 'TITLE': 'Nacl IO Demo',
+ 'TITLE': 'NaCl IO Demo',
'GROUP': 'Demo',
'PERMISSIONS': [
'unlimitedStorage'
diff --git a/native_client_sdk/src/getting_started/part1/hello_tutorial.cc b/native_client_sdk/src/getting_started/part1/hello_tutorial.cc
index ed69d51543..6f72e0c0eb 100644
--- a/native_client_sdk/src/getting_started/part1/hello_tutorial.cc
+++ b/native_client_sdk/src/getting_started/part1/hello_tutorial.cc
@@ -9,7 +9,7 @@
/// CreateModule() once to load the module code. After the code is loaded,
/// CreateModule() is not called again.
///
-/// Once the code is loaded, the browser than calls the CreateInstance()
+/// Once the code is loaded, the browser calls the CreateInstance()
/// method on the object returned by CreateModule(). It calls CreateInstance()
/// each time it encounters an <embed> tag that references your NaCl module.
///
@@ -32,8 +32,8 @@
/// module on the web page. The browser will ask the Module object to create
/// a new Instance for each occurrence of the <embed> tag that has these
/// attributes:
-/// type="application/x-pnacl"
/// src="hello_tutorial.nmf"
+/// type="application/x-pnacl"
/// To communicate with the browser, you must override HandleMessage() to
/// receive messages from the browser, and use PostMessage() to send messages
/// back to the browser. Note that this interface is asynchronous.
@@ -46,15 +46,8 @@ class HelloTutorialInstance : public pp::Instance {
virtual ~HelloTutorialInstance() {}
/// Handler for messages coming in from the browser via postMessage(). The
- /// @a var_message can contain anything: a JSON string; a string that encodes
- /// method names and arguments; etc. For example, you could use
- /// JSON.stringify in the browser to create a message that contains a method
- /// name and some parameters, something like this:
- /// var json_message = JSON.stringify({ "myMethod" : "3.14159" });
- /// nacl_module.postMessage(json_message);
- /// On receipt of this message in @a var_message, you could parse the JSON to
- /// retrieve the method name, match it to a function call, and then call it
- /// with the parameter.
+ /// @a var_message can contain be any pp:Var type; for example int, string
+ /// Array or Dictinary. Please see the pp:Var documentation for more details.
/// @param[in] var_message The message posted by the browser.
virtual void HandleMessage(const pp::Var& var_message) {
// TODO(sdk_user): 1. Make this function handle the incoming message.
@@ -63,7 +56,7 @@ class HelloTutorialInstance : public pp::Instance {
/// 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".
+/// instance for each <embed> tag with type="application/x-pnacl".
class HelloTutorialModule : public pp::Module {
public:
HelloTutorialModule() : pp::Module() {}
diff --git a/native_client_sdk/src/getting_started/part1/index.html b/native_client_sdk/src/getting_started/part1/index.html
index c3c76cf7cd..d4af2bbece 100644
--- a/native_client_sdk/src/getting_started/part1/index.html
+++ b/native_client_sdk/src/getting_started/part1/index.html
@@ -2,7 +2,7 @@
<html>
<!--
- Copyright (c) 2012 The Native Client Authors. All rights reserved.
+ Copyright (c) 2013 The Native Client Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
@@ -52,7 +52,7 @@
function updateStatus(opt_message) {
if (opt_message)
statusText = opt_message;
- var statusField = document.getElementById('status_field');
+ var statusField = document.getElementById('statusField');
if (statusField) {
statusField.innerHTML = statusText;
}
@@ -61,42 +61,35 @@
</head>
<body onload="pageDidLoad()">
-<h1>Native Client Module HelloTutorial</h1>
-<p>
- <!-- TODO(eliben): PNaCl-ize:
- Load the published .nexe. This includes the 'nacl' attribute which
- shows how to load multi-architecture modules. Each entry in the "nexes"
- object in the .nmf manifest file is a key-value pair: the key is the
- instruction set architecture ('x86-32', 'x86-64', etc.); the value is a URL
- for the desired NaCl module.
+ <h1>NaCl C++ Tutorial: Getting Started</h1>
+ <p>
+ <!--
+ Load the published pexe.
+ Note: Since this module does not use any real-estate in the browser, its
+ width and height are set to 0.
- Note: Since this NaCl module does not use any real-estate in the browser,
- it's width and height are set to 0.
+ Note: The <embed> element is wrapped inside a <div>, which has both a 'load'
+ and a 'message' event listener attached. This wrapping method is used
+ instead of attaching the event listeners directly to the <embed> element to
+ ensure that the listeners are active before the NaCl module 'load' event
+ fires. This also allows you to use PPB_Messaging.PostMessage() (in C) or
+ pp::Instance.PostMessage() (in C++) from within the initialization code in
+ your module.
+ -->
+ <div id="listener">
+ <script type="text/javascript">
+ var listener = document.getElementById('listener');
+ listener.addEventListener('load', moduleDidLoad, true);
+ listener.addEventListener('message', handleMessage, true);
+ </script>
- Note: The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
- and a 'message' event listener attached. This wrapping method is used
- instead of attaching the event listeners directly to the <EMBED> element to
- ensure that the listeners are active before the NaCl module 'load' event
- fires. This also allows you to use PPB_Messaging.PostMessage() (in C) or
- pp::Instance.PostMessage() (in C++) from within the initialization code in
- your NaCl module.
- -->
- <div id="listener">
- <script type="text/javascript">
- var listener = document.getElementById('listener');
- listener.addEventListener('load', moduleDidLoad, true);
- listener.addEventListener('message', handleMessage, true);
- </script>
-
- <embed
- id="hello_tutorial"
- width=0 height=0
- src="hello_tutorial.nmf"
- type="application/x-pnacl" />
- </div>
-</p>
+ <embed id="hello_tutorial"
+ width=0 height=0
+ src="hello_tutorial.nmf"
+ type="application/x-pnacl" />
+ </div>
+ </p>
-<h2>Status</h2>
-<div id="status_field">NO-STATUS</div>
+ <h2>Status <code id="statusField">NO-STATUS</code></h2>
</body>
</html>
diff --git a/native_client_sdk/src/getting_started/part2/README b/native_client_sdk/src/getting_started/part2/README
new file mode 100644
index 0000000000..96c97716f9
--- /dev/null
+++ b/native_client_sdk/src/getting_started/part2/README
@@ -0,0 +1,23 @@
+======================================
+C++ Tutorial: Getting Started (Part 2)
+======================================
+
+Please see the online documentation here:
+
+ https://developers.google.com/native-client/devguide/tutorial
+
+
+Part 2 of the tutorial is the same as part 1, except:
+
+* The SDK build system is now used. This simplifies supporting multiple NaCl
+ toolchains (e.g. PNaCl, newlib, GLibC). See $NACL_SDK_ROOT/README.Makefiles
+ for more information about the SDK Build system.
+
+* The example loads common.js, a JavaScript file that has common code used in
+ all of the SDK examples.
+
+* index.html has been simplified, and all JavaScript code has been moved to
+ separate .js files. This makes the example Content Security Policy
+ (CSP)-compliant. See
+ http://developer.chrome.com/apps/contentSecurityPolicy.html for more details.
+ CSP-compliance is required for Chrome Packaged apps.
diff --git a/native_client_sdk/src/getting_started/part2/example.dsc b/native_client_sdk/src/getting_started/part2/example.dsc
new file mode 100644
index 0000000000..9e10783cd6
--- /dev/null
+++ b/native_client_sdk/src/getting_started/part2/example.dsc
@@ -0,0 +1,20 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ # Don't copy the packaged app files: manifest.json, etc.
+ 'NO_PACKAGE_FILES': True,
+ 'TARGETS': [
+ {
+ 'NAME': 'part2',
+ 'TYPE': 'main',
+ 'SOURCES': ['hello_tutorial.cc'],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread'],
+ }
+ ],
+ 'DATA': [
+ 'example.js'
+ ],
+ 'DEST': 'getting_started',
+ 'NAME': 'part2',
+ 'TITLE': 'Getting Started: Part 2',
+ 'GROUP': 'Getting Started',
+}
diff --git a/native_client_sdk/src/getting_started/part2/example.js b/native_client_sdk/src/getting_started/part2/example.js
new file mode 100644
index 0000000000..7a392a2c62
--- /dev/null
+++ b/native_client_sdk/src/getting_started/part2/example.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2013 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.
+
+// This function is called by common.js when the NaCl module is
+// loaded.
+function moduleDidLoad() {
+ // Once we load, hide the plugin. In this example, we don't display anything
+ // in the plugin, so it is fine to hide it.
+ common.hideModule();
+
+ // After the NaCl module has loaded, common.naclModule is a reference to the
+ // NaCl module's <embed> element.
+ //
+ // postMessage sends a message to it.
+ common.naclModule.postMessage('hello');
+}
+
+// This function is called by common.js when a message is received from the
+// NaCl module.
+function handleMessage(message) {
+ var logEl = document.getElementById('log');
+ logEl.textContent += message.data;
+}
diff --git a/native_client_sdk/src/getting_started/part2/hello_tutorial.cc b/native_client_sdk/src/getting_started/part2/hello_tutorial.cc
new file mode 100644
index 0000000000..5261a06e46
--- /dev/null
+++ b/native_client_sdk/src/getting_started/part2/hello_tutorial.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 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/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+
+namespace {
+
+// The expected string sent by the browser.
+const char* const kHelloString = "hello";
+// The string sent back to the browser upon receipt of a message
+// containing "hello".
+const char* const kReplyString = "hello from NaCl";
+
+} // namespace
+
+class HelloTutorialInstance : public pp::Instance {
+ public:
+ explicit HelloTutorialInstance(PP_Instance instance)
+ : pp::Instance(instance) {}
+ virtual ~HelloTutorialInstance() {}
+
+ virtual void HandleMessage(const pp::Var& var_message) {
+ // Ignore the message if it is not a string.
+ if (!var_message.is_string())
+ return;
+
+ // Get the string message and compare it to "hello".
+ std::string message = var_message.AsString();
+ if (message == kHelloString) {
+ // If it matches, send our response back to JavaScript.
+ pp::Var var_reply(kReplyString);
+ PostMessage(var_reply);
+ }
+ }
+};
+
+class HelloTutorialModule : public pp::Module {
+ public:
+ HelloTutorialModule() : pp::Module() {}
+ virtual ~HelloTutorialModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new HelloTutorialInstance(instance);
+ }
+};
+
+namespace pp {
+
+Module* CreateModule() {
+ return new HelloTutorialModule();
+}
+
+} // namespace pp
diff --git a/native_client_sdk/src/getting_started/part2/index.html b/native_client_sdk/src/getting_started/part2/index.html
new file mode 100644
index 0000000000..2dd2f500a8
--- /dev/null
+++ b/native_client_sdk/src/getting_started/part2/index.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2013 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>
+<!--
+For the SDK examples, we support several toolchains (e.g. PNaCl, newlib,
+GLibC). In your own code, you'll likely just choose one toolchain (probably
+PNaCl), and load that directly.
+
+Rather than have each example repeat the same module loading code for each
+toolchain it supports, we set custom data attributes on the body. Those
+attributes are read by common.js to determine which toolchains are supported
+for the example.
+-->
+<body {{attrs}}>
+ <h1>{{title}}</h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <!--
+ Just as in part1, the <embed> element will be wrapped inside the <div>
+ element with the id "listener". In part1, the embed was specified in HTML,
+ here the common.js module creates a new <embed> element and adds it to the
+ <div> for us.
+ -->
+ <div id="listener"></div>
+
+ <!--
+ This element will be populated with the messages that come from the NaCl
+ module. See example.js.
+ -->
+ <div id="log"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
index 534e53a28d..5a2fc7a974 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
@@ -34,7 +34,6 @@ namespace nacl_io {
MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount),
is_readable_(false),
- did_resize_(false),
rows_(DEFAULT_TTY_ROWS),
cols_(DEFAULT_TTY_COLS) {
output_handler_.handler = NULL;
@@ -100,15 +99,8 @@ Error MountNodeTty::Write(size_t offs,
Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
AUTO_LOCK(node_lock_);
- did_resize_ = false;
while (!is_readable_) {
pthread_cond_wait(&is_readable_cond_, node_lock_.mutex());
- if (!is_readable_ && did_resize_) {
- // If an async resize event occured then return the failure and
- // set EINTR.
- *out_bytes = 0;
- return EINTR;
- }
}
size_t bytes_to_copy = std::min(count, input_buffer_.size());
@@ -259,13 +251,6 @@ Error MountNodeTty::Ioctl(int request, char* arg) {
cols_ = size->ws_col;
}
kill(getpid(), SIGWINCH);
-
- // Wake up any thread waiting on Read
- {
- AUTO_LOCK(node_lock_);
- did_resize_ = true;
- pthread_cond_broadcast(&is_readable_cond_);
- }
return 0;
}
case TIOCGWINSZ: {
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
index 8bf5b17304..c8070b9d5f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
@@ -53,7 +53,6 @@ class MountNodeTty : public MountNodeCharDevice {
std::deque<char> input_buffer_;
bool is_readable_;
- bool did_resize_;
pthread_cond_t is_readable_cond_;
struct termios termios_;
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/remove.c b/native_client_sdk/src/libraries/nacl_io/syscalls/remove.c
index a816abbd89..a3a7bfb438 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/remove.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/remove.c
@@ -5,6 +5,14 @@
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_wrap.h"
+#ifdef __GLIBC__
+// Glibc's remove(3) and unlink(2) entry points are not yet hooked up
+// to the lower level IRT interfaces. Therefore the only way to intercept
+// these calls is to override them here..
+// TODO(sbc): remove this once glibc plumbing is in place for remove/unlink
+
int remove(const char* path) {
return ki_remove(path);
}
+
+#endif
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
index 3dbb8eb61f..e2e416da76 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc
@@ -74,7 +74,6 @@ class KernelProxyTest : public ::testing::Test {
TEST_F(KernelProxyTest, FileLeak) {
const size_t buffer_size = 1024;
char filename[128];
- int file_num;
int garbage[buffer_size];
MountMem* mount = (MountMem*)kp_.RootMount();
@@ -83,7 +82,7 @@ TEST_F(KernelProxyTest, FileLeak) {
EXPECT_EQ(0, mount->Open(Path("/"), O_RDONLY, &root));
EXPECT_EQ(0, root->ChildCount());
- for (file_num = 0; file_num < 4096; file_num++) {
+ for (int file_num = 0; file_num < 4096; file_num++) {
sprintf(filename, "/foo%i.tmp", file_num++);
FILE* f = fopen(filename, "w");
EXPECT_NE((FILE*)0, f);
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
index 4472d8c592..8f9957c7d7 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc
@@ -257,10 +257,12 @@ TEST_F(KernelWrapTest, read) {
read(4567, NULL, 5678);
}
+#ifdef __GLIBC__
TEST_F(KernelWrapTest, remove) {
EXPECT_CALL(mock, remove(StrEq("remove"))).Times(1);
remove("remove");
}
+#endif
TEST_F(KernelWrapTest, rmdir) {
EXPECT_CALL(mock, rmdir(StrEq("rmdir"))).Times(1);
diff --git a/native_client_sdk/src/tools/run.py b/native_client_sdk/src/tools/run.py
index a8b3ebc925..e2af359581 100755
--- a/native_client_sdk/src/tools/run.py
+++ b/native_client_sdk/src/tools/run.py
@@ -46,7 +46,7 @@ def main(args):
dest='test_mode', action='store_true')
parser.add_option('-p', '--port',
help='Port to run server on. Default is 5103, ephemeral is 0.',
- default=5103)
+ type='int', default=5103)
options, args = parser.parse_args(args)
if not args:
parser.error('No executable given.')