summaryrefslogtreecommitdiff
path: root/native_client_sdk
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-10-18 15:46:22 +0100
committerTorne (Richard Coles) <torne@google.com>2013-10-18 15:46:22 +0100
commit4e180b6a0b4720a9b8e9e959a882386f690f08ff (patch)
tree788435d09362885908ba5ba9ef868b852ca82c0b /native_client_sdk
parent1179b92b08db0c652a0cf003ab4d89b31ce3610f (diff)
downloadchromium_org-4e180b6a0b4720a9b8e9e959a882386f690f08ff.tar.gz
Merge from Chromium at DEPS revision 228962
This commit was generated by merge_to_master.py. Change-Id: I23bd7d7766f213fd52f28ae5e1ecc6ae9df905ea
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/PRESUBMIT.py9
-rwxr-xr-xnative_client_sdk/src/build_tools/build_sdk.py14
-rw-r--r--native_client_sdk/src/build_tools/buildbot_common.py14
-rwxr-xr-xnative_client_sdk/src/build_tools/buildbot_run.py14
-rw-r--r--native_client_sdk/src/build_tools/generate_make.py1
-rw-r--r--native_client_sdk/src/build_tools/json/naclsdk_manifest0.json10
-rw-r--r--native_client_sdk/src/build_tools/json/naclsdk_manifest2.json40
-rw-r--r--native_client_sdk/src/build_tools/sdk_files.list10
-rwxr-xr-xnative_client_sdk/src/build_tools/tests/verify_ppapi_test.py1
-rwxr-xr-xnative_client_sdk/src/build_tools/update_sdktools.py2
-rw-r--r--native_client_sdk/src/doc/Makefile9
-rw-r--r--native_client_sdk/src/doc/README55
-rw-r--r--native_client_sdk/src/doc/_book.yaml17
-rw-r--r--native_client_sdk/src/doc/_project.yaml4
-rw-r--r--native_client_sdk/src/doc/_reference_toc.yaml494
-rw-r--r--native_client_sdk/src/doc/_sphinxext/devsite_builder.py102
-rw-r--r--native_client_sdk/src/doc/community/_toc.yaml14
-rw-r--r--native_client_sdk/src/doc/community/security-contest/contest-announcement.rst92
-rw-r--r--native_client_sdk/src/doc/community/security-contest/contest-faq.rst433
-rw-r--r--native_client_sdk/src/doc/community/security-contest/contest-terms.rst986
-rw-r--r--native_client_sdk/src/doc/community/security-contest/contest-warning.txt10
-rw-r--r--native_client_sdk/src/doc/community/security-contest/index.rst222
-rw-r--r--native_client_sdk/src/doc/conf.py15
-rw-r--r--native_client_sdk/src/doc/devguide/_toc.yaml10
-rw-r--r--native_client_sdk/src/doc/devguide/coding/FileIO.rst1
-rw-r--r--native_client_sdk/src/doc/devguide/coding/_toc.yaml24
-rw-r--r--native_client_sdk/src/doc/devguide/coding/application-structure.rst163
-rw-r--r--native_client_sdk/src/doc/devguide/coding/message-system.rst2
-rw-r--r--native_client_sdk/src/doc/devguide/coding/native-client-modules.rst69
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/_toc.yaml14
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/building.rst704
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/debugging.rst448
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst8
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/running.rst428
-rw-r--r--native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst8
-rw-r--r--native_client_sdk/src/doc/faq.rst528
-rw-r--r--native_client_sdk/src/doc/images/calendar-32.gifbin0 -> 805 bytes
-rw-r--r--native_client_sdk/src/doc/images/code-32.gifbin0 -> 597 bytes
-rw-r--r--native_client_sdk/src/doc/images/gift-32.gifbin0 -> 1092 bytes
-rw-r--r--native_client_sdk/src/doc/index.rst12
-rw-r--r--native_client_sdk/src/doc/nacl-and-pnacl.rst173
-rw-r--r--native_client_sdk/src/doc/overview.rst222
-rw-r--r--native_client_sdk/src/doc/publications-and-presentations.rst200
-rw-r--r--native_client_sdk/src/doc/reference/index.rst14
-rw-r--r--native_client_sdk/src/doc/reference/nacl-manifest-format.rst265
-rw-r--r--native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst536
-rw-r--r--native_client_sdk/src/doc/rest-devsite-examples.rst12
-rw-r--r--native_client_sdk/src/doc/sdk/_toc.yaml10
-rw-r--r--native_client_sdk/src/doc/sdk/download.rst274
-rw-r--r--native_client_sdk/src/doc/sdk/examples.rst199
-rw-r--r--native_client_sdk/src/doc/sdk/release-notes.rst521
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc2
-rw-r--r--native_client_sdk/src/examples/api/socket/echo_server.cc171
-rw-r--r--native_client_sdk/src/examples/api/socket/echo_server.h46
-rw-r--r--native_client_sdk/src/examples/api/socket/example.dsc3
-rw-r--r--native_client_sdk/src/examples/api/socket/example.js117
-rw-r--r--native_client_sdk/src/examples/api/socket/index.html12
-rw-r--r--native_client_sdk/src/examples/api/socket/socket.cc47
-rw-r--r--native_client_sdk/src/examples/api/url_loader/example.js16
-rw-r--r--native_client_sdk/src/examples/api/url_loader/index.html2
-rw-r--r--native_client_sdk/src/examples/api/url_loader/test.js32
-rw-r--r--native_client_sdk/src/examples/demo/earth/earth.cc45
-rw-r--r--native_client_sdk/src/examples/demo/life/life.c43
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/example.js77
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/handlers.c354
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/handlers.h13
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/index.html91
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c46
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h3
-rw-r--r--native_client_sdk/src/examples/demo/voronoi/index.html4
-rw-r--r--native_client_sdk/src/examples/demo/voronoi/voronoi.cc17
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/debugging.c149
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/example.dsc7
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/example.js81
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/index.html13
-rw-r--r--native_client_sdk/src/getting_started/part2/example.dsc3
-rw-r--r--native_client_sdk/src/gonacl_appengine/README13
-rw-r--r--native_client_sdk/src/gonacl_appengine/app.yaml12
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/bullet/.gitignore3
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/bullet/Makefile38
-rwxr-xr-xnative_client_sdk/src/gonacl_appengine/src/bullet/build.sh76
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/earth/Makefile (renamed from native_client_sdk/src/gonacl_appengine/src/Makefile)0
-rw-r--r--native_client_sdk/src/gonacl_appengine/src/earth/earth.cc (renamed from native_client_sdk/src/gonacl_appengine/src/earth.cc)37
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/common.css97
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAM.js224
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAMBullet.js48
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/box.json238
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/index.html88
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/main.js82
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js292
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scenes.js232
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/world.js140
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/example.js (renamed from native_client_sdk/src/gonacl_appengine/static/pnacl-demo/example.js)0
-rw-r--r--native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/index.html (renamed from native_client_sdk/src/gonacl_appengine/static/pnacl-demo/index.html)98
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h3
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc9
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc17
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h13
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h3
-rw-r--r--native_client_sdk/src/libraries/nacl_io/event_listener.cc16
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_handle.cc142
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_handle.h47
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc14
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_intercept.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc161
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.h6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc5
-rw-r--r--native_client_sdk/src/libraries/nacl_io/library.dsc2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount.h6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_dev.cc70
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_dev.h4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_http.cc10
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_mem.cc18
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node.cc27
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node.h17
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_dir.h5
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc53
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h9
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_http.cc9
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_http.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc22
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_mem.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc9
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h5
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc131
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_socket.h52
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_stream.h5
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc284
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h20
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc29
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_tty.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc10
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_udp.h6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc14
-rw-r--r--native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h13
-rw-r--r--native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc17
-rw-r--r--native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c10
-rw-r--r--native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c5
-rw-r--r--native_client_sdk/src/libraries/ppapi/library.dsc1
-rw-r--r--native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc6
-rw-r--r--native_client_sdk/src/resources/Makefile.example.template4
-rw-r--r--native_client_sdk/src/resources/common.js13
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/echo_server.cc179
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/echo_server.h65
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/example.dsc3
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/example.js40
-rw-r--r--native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc344
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/event_test.cc29
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_proxy_mock.h8
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc483
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_html5fs_test.cc38
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc34
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_node_mock.h8
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_node_test.cc72
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_node_tty_test.cc45
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mount_test.cc25
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/socket_test.cc11
-rw-r--r--native_client_sdk/src/tools/common.mk11
-rw-r--r--native_client_sdk/src/tools/host_gcc.mk1
-rwxr-xr-xnative_client_sdk/src/tools/httpd.py11
-rw-r--r--native_client_sdk/src/tools/nacl_gcc.mk4
-rw-r--r--native_client_sdk/src/tools/nacl_llvm.mk3
169 files changed, 10996 insertions, 2326 deletions
diff --git a/native_client_sdk/PRESUBMIT.py b/native_client_sdk/PRESUBMIT.py
index d28f05e608..93e7ad710e 100644
--- a/native_client_sdk/PRESUBMIT.py
+++ b/native_client_sdk/PRESUBMIT.py
@@ -38,4 +38,11 @@ def CheckChangeOnCommit(input_api, output_api):
def GetPreferredTrySlaves(project, change):
- return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
+ return [
+ 'linux_nacl_sdk',
+ 'linux_nacl_sdk_build',
+ 'win_nacl_sdk',
+ 'win_nacl_sdk_build',
+ 'mac_nacl_sdk',
+ 'mac_nacl_sdk_build'
+ ]
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 38bcde5c13..4762339c68 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -168,6 +168,7 @@ TEXT_FILES = [
'COPYING',
'LICENSE',
'README.Makefiles',
+ 'getting_started/README',
]
def BuildStepCopyTextFiles(pepperdir, pepper_ver, chrome_revision,
@@ -282,11 +283,11 @@ NACL_HEADER_MAP = {
('src/include/nacl/nacl_exception.h', 'nacl/'),
('src/include/nacl/nacl_minidump.h', 'nacl/'),
('src/untrusted/irt/irt.h', ''),
+ ('src/untrusted/irt/irt_dev.h', ''),
('src/untrusted/irt/irt_ppapi.h', ''),
('src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
('src/untrusted/nacl/nacl_startup.h', 'nacl/'),
('src/untrusted/nacl/nacl_thread.h', 'nacl/'),
- ('src/untrusted/nacl/pnacl.h', ''),
('src/untrusted/pthread/pthread.h', ''),
('src/untrusted/pthread/semaphore.h', ''),
('src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
@@ -295,11 +296,11 @@ NACL_HEADER_MAP = {
('src/include/nacl/nacl_exception.h', 'nacl/'),
('src/include/nacl/nacl_minidump.h', 'nacl/'),
('src/untrusted/irt/irt.h', ''),
+ ('src/untrusted/irt/irt_dev.h', ''),
('src/untrusted/irt/irt_ppapi.h', ''),
('src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
('src/untrusted/nacl/nacl_startup.h', 'nacl/'),
('src/untrusted/nacl/nacl_thread.h', 'nacl/'),
- ('src/untrusted/nacl/pnacl.h', ''),
('src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
],
'host': []
@@ -682,6 +683,10 @@ def BuildStepBuildLibraries(pepperdir, directory):
BuildStepMakeAll(pepperdir, directory, 'Build Libraries Release',
clean=True, config='Release')
+ # Cleanup .pyc file generated while building libraries. Without
+ # this we would end up shipping the pyc in the SDK tarball.
+ buildbot_common.RemoveFile(os.path.join(pepperdir, 'tools', '*.pyc'))
+
def GenerateNotice(fileroot, output_filename='NOTICE', extra_files=None):
# Look for LICENSE files
@@ -730,7 +735,6 @@ to test.""" % (e, file_list_rel, verify_filelist_py, file_list_rel,
buildbot_common.ErrorExit(msg)
-
def BuildStepTarBundle(pepper_ver, tarfile):
buildbot_common.BuildStep('Tar Pepper Bundle')
buildbot_common.MakeDir(os.path.dirname(tarfile))
@@ -738,7 +742,6 @@ def BuildStepTarBundle(pepper_ver, tarfile):
'pepper_' + pepper_ver], cwd=NACL_DIR)
-
def GetManifestBundle(pepper_ver, chrome_revision, nacl_revision, tarfile,
archive_url):
with open(tarfile, 'rb') as tarfile_stream:
@@ -919,13 +922,14 @@ def main(args):
BuildStepDownloadToolchains()
BuildStepUntarToolchains(pepperdir, toolchains)
- BuildStepCopyTextFiles(pepperdir, pepper_ver, chrome_revision, nacl_revision)
BuildStepBuildToolchains(pepperdir, toolchains)
BuildStepUpdateHelpers(pepperdir, True)
BuildStepUpdateUserProjects(pepperdir, toolchains,
options.build_experimental, True)
+ BuildStepCopyTextFiles(pepperdir, pepper_ver, chrome_revision, nacl_revision)
+
# Ship with libraries prebuilt, so run that first.
BuildStepBuildLibraries(pepperdir, 'src')
GenerateNotice(pepperdir)
diff --git a/native_client_sdk/src/build_tools/buildbot_common.py b/native_client_sdk/src/build_tools/buildbot_common.py
index 157cd0b856..f41eea186a 100644
--- a/native_client_sdk/src/build_tools/buildbot_common.py
+++ b/native_client_sdk/src/build_tools/buildbot_common.py
@@ -24,11 +24,25 @@ def IsSDKBuilder():
Trybot names:
(win|mac|linux)_nacl_sdk
+ Build-only Trybot names:
+ (win|mac|linux)_nacl_sdk_build
+
Builder names:
(windows|mac|linux)-sdk-multi(rel)?"""
return '-sdk-multi' in os.getenv('BUILDBOT_BUILDERNAME', '')
+def IsBuildOnlyBot():
+ """Returns True if this script is running on a build-only bot.
+
+ Build only bots are designed to be fast and non-flaky. Currently
+ this means they don't build chrome, and don't run any browser-based
+ tests. Currently the only build-only bots are trybots.
+
+ See IsSDKBuilder above for trybot/buildbot names."""
+ return os.getenv('BUILDBOT_BUILDERNAME', '').endswith('build')
+
+
def IsSDKTrybot():
"""Returns True if this script is running on an SDK trybot.
diff --git a/native_client_sdk/src/build_tools/buildbot_run.py b/native_client_sdk/src/build_tools/buildbot_run.py
index b58df097d8..902078056b 100755
--- a/native_client_sdk/src/build_tools/buildbot_run.py
+++ b/native_client_sdk/src/build_tools/buildbot_run.py
@@ -35,7 +35,7 @@ def StepRunUnittests():
Run([sys.executable, 'test_all.py'], env=env, cwd=SDK_SRC_DIR)
-def StepBuildSDK(args):
+def StepBuildSDK():
is_win = getos.GetPlatform() == 'win'
# Windows has a path length limit of 255 characters, after joining cwd with a
@@ -51,7 +51,7 @@ def StepBuildSDK(args):
new_script_dir = SCRIPT_DIR
try:
- Run([sys.executable, 'build_sdk.py'] + args, cwd=new_script_dir)
+ Run([sys.executable, 'build_sdk.py'], cwd=new_script_dir)
finally:
if is_win:
subprocess.check_call(['subst', '/D', subst_drive])
@@ -68,15 +68,17 @@ def StepTestSDK():
Run(cmd, cwd=SCRIPT_DIR)
-def main(args):
+def main():
StepRunUnittests()
- StepBuildSDK(args)
- StepTestSDK()
+ StepBuildSDK()
+ # Skip the testing phase if we are running on a build-only bots.
+ if not buildbot_common.IsBuildOnlyBot():
+ StepTestSDK()
return 0
if __name__ == '__main__':
try:
- sys.exit(main(sys.argv[1:]))
+ sys.exit(main())
except KeyboardInterrupt:
buildbot_common.ErrorExit('buildbot_run: interrupted')
diff --git a/native_client_sdk/src/build_tools/generate_make.py b/native_client_sdk/src/build_tools/generate_make.py
index 2140642679..2963d0bf03 100644
--- a/native_client_sdk/src/build_tools/generate_make.py
+++ b/native_client_sdk/src/build_tools/generate_make.py
@@ -226,6 +226,7 @@ def ProcessProject(pepperdir, srcroot, dstroot, desc, toolchains, configs=None,
target['CXXFLAGS'].insert(0, '-Wall')
template_dict = {
+ 'desc': desc,
'rel_sdk': '/'.join(['..'] * (len(desc['DEST'].split('/')) + 1)),
'pre': desc.get('PRE', ''),
'post': desc.get('POST', ''),
diff --git a/native_client_sdk/src/build_tools/json/naclsdk_manifest0.json b/native_client_sdk/src/build_tools/json/naclsdk_manifest0.json
index b09348aa96..a92c6442d7 100644
--- a/native_client_sdk/src/build_tools/json/naclsdk_manifest0.json
+++ b/native_client_sdk/src/build_tools/json/naclsdk_manifest0.json
@@ -4,17 +4,17 @@
"archives": [
{
"checksum": {
- "sha1": "9c9af9e050cce3d490c7c1dd612910bed3f32b59"
+ "sha1": "61bc0ab13c4ff1d3222446fb616f207b1617441f"
},
"host_os": "all",
- "size": 29354,
- "url": "https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/trunk.201132/sdk_tools.tgz"
+ "size": 29619,
+ "url": "https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/trunk.228691/sdk_tools.tgz"
}
],
- "description": "Native Client SDK Tools, revision 201132",
+ "description": "Native Client SDK Tools, revision 228691",
"name": "sdk_tools",
"recommended": "yes",
- "revision": 201132,
+ "revision": 228691,
"stability": "stable",
"version": 1
}
diff --git a/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json b/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
index c002b98cc5..21bd8e2d49 100644
--- a/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
+++ b/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
@@ -4,17 +4,17 @@
"archives": [
{
"checksum": {
- "sha1": "9c9af9e050cce3d490c7c1dd612910bed3f32b59"
+ "sha1": "61bc0ab13c4ff1d3222446fb616f207b1617441f"
},
"host_os": "all",
- "size": 29354,
- "url": "https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/trunk.201132/sdk_tools.tgz"
+ "size": 29619,
+ "url": "https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/trunk.228691/sdk_tools.tgz"
}
],
- "description": "Native Client SDK Tools, revision 201132",
+ "description": "Native Client SDK Tools, revision 228691",
"name": "sdk_tools",
"recommended": "yes",
- "revision": 201132,
+ "revision": 228691,
"stability": "stable",
"version": 1
},
@@ -35,16 +35,6 @@
},
{
"archives": [],
- "description": "Chrome 25 bundle, revision xxxxx",
- "name": "pepper_25",
- "recommended": "no",
- "repath": "pepper_25",
- "revision": 0,
- "stability": "post_stable",
- "version": 25
- },
- {
- "archives": [],
"description": "Chrome 26 bundle, revision xxxxx",
"name": "pepper_26",
"recommended": "no",
@@ -67,20 +57,20 @@
"archives": [],
"description": "Chrome 28 bundle, revision xxxxx",
"name": "pepper_28",
- "recommended": "yes",
+ "recommended": "no",
"repath": "pepper_28",
"revision": 0,
- "stability": "stable",
+ "stability": "post_stable",
"version": 28
},
{
"archives": [],
"description": "Chrome 29 bundle, revision xxxxx",
"name": "pepper_29",
- "recommended": "no",
+ "recommended": "yes",
"repath": "pepper_29",
"revision": 0,
- "stability": "beta",
+ "stability": "stable",
"version": 29
},
{
@@ -90,11 +80,21 @@
"recommended": "no",
"repath": "pepper_30",
"revision": 0,
- "stability": "dev",
+ "stability": "beta",
"version": 30
},
{
"archives": [],
+ "description": "Chrome 31 bundle, revision xxxxx",
+ "name": "pepper_31",
+ "recommended": "no",
+ "repath": "pepper_31",
+ "revision": 0,
+ "stability": "dev",
+ "version": 31
+ },
+ {
+ "archives": [],
"description": "Chrome Canary",
"name": "pepper_canary",
"recommended": "no",
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index b42123d9b0..9bcd608f84 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -42,6 +42,7 @@ examples/tutorial/using_ppapi_simple/*
getting_started/Makefile
getting_started/part1/*
getting_started/part2/*
+getting_started/README
include/error_handling/*
include/GLES2/*
include/gmock/*
@@ -286,6 +287,7 @@ src/ppapi_simple/*
src/sdk_util/*
toolchain/${PLATFORM}_arm_newlib/*
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/irt.h
+toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/irt_dev.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/irt_ppapi.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/nacl_dyncode.h
@@ -293,7 +295,6 @@ toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/nacl/nacl_thread.h
-toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/pnacl.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/pthread.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/include/semaphore.h
toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/crti.o
@@ -309,6 +310,7 @@ toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libppapi_stub.a
toolchain/${PLATFORM}_arm_newlib/arm-nacl/lib/libpthread.a
toolchain/${PLATFORM}_pnacl/*
toolchain/${PLATFORM}_pnacl/sdk/include/irt.h
+toolchain/${PLATFORM}_pnacl/sdk/include/irt_dev.h
toolchain/${PLATFORM}_pnacl/sdk/include/irt_ppapi.h
toolchain/${PLATFORM}_pnacl/sdk/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_pnacl/sdk/include/nacl/nacl_dyncode.h
@@ -316,7 +318,6 @@ toolchain/${PLATFORM}_pnacl/sdk/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_pnacl/sdk/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_pnacl/sdk/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_pnacl/sdk/include/nacl/nacl_thread.h
-toolchain/${PLATFORM}_pnacl/sdk/include/pnacl.h
toolchain/${PLATFORM}_pnacl/sdk/include/pthread.h
toolchain/${PLATFORM}_pnacl/sdk/include/semaphore.h
toolchain/${PLATFORM}_pnacl/sdk/lib/libminidump_generator.a
@@ -330,6 +331,7 @@ toolchain/${PLATFORM}_pnacl/sdk/lib/libppapi_stub.a
toolchain/${PLATFORM}_pnacl/sdk/lib/libpthread.a
toolchain/${PLATFORM}_x86_glibc/*
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt.h
+toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt_dev.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/irt_ppapi.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/nacl_dyncode.h
@@ -337,7 +339,6 @@ toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/nacl/nacl_thread.h
-toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/include/pnacl.h
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/lib/libminidump_generator.a
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/lib/libminidump_generator.so
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/lib/libnacl.a
@@ -364,6 +365,7 @@ toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/lib32/libppapi.so
toolchain/${PLATFORM}_x86_glibc/x86_64-nacl/lib32/libppapi_stub.a
toolchain/${PLATFORM}_x86_newlib/*
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/irt.h
+toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/irt_dev.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/irt_ppapi.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/dynamic_annotations.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/nacl_dyncode.h
@@ -371,7 +373,6 @@ toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/nacl_exception.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/nacl_minidump.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/nacl_startup.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/nacl/nacl_thread.h
-toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/pnacl.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/pthread.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/include/semaphore.h
toolchain/${PLATFORM}_x86_newlib/x86_64-nacl/lib/crti.o
@@ -419,7 +420,6 @@ tools/nacl_gcc.mk
tools/nacl_llvm.mk
tools/ncval${EXE_EXT}
tools/oshelpers.py
-tools/oshelpers.pyc
tools/quote.py
tools/run.py
tools/sel_ldr.py
diff --git a/native_client_sdk/src/build_tools/tests/verify_ppapi_test.py b/native_client_sdk/src/build_tools/tests/verify_ppapi_test.py
index d770182bc2..e63d10a956 100755
--- a/native_client_sdk/src/build_tools/tests/verify_ppapi_test.py
+++ b/native_client_sdk/src/build_tools/tests/verify_ppapi_test.py
@@ -47,7 +47,6 @@ class TestPartition(unittest.TestCase):
def testIgnoreTrusted(self):
filenames = [
os.path.join('ppapi', 'c', 'trusted', 'ppb_broker_trusted.h'),
- os.path.join('ppapi', 'c', 'trusted', 'ppb_file_io_trusted.h'),
os.path.join('ppapi', 'cpp', 'trusted', 'file_chooser_trusted.cc'),
]
result = verify_ppapi.PartitionFiles(filenames)
diff --git a/native_client_sdk/src/build_tools/update_sdktools.py b/native_client_sdk/src/build_tools/update_sdktools.py
index f74ec0d5f7..6007ae9513 100755
--- a/native_client_sdk/src/build_tools/update_sdktools.py
+++ b/native_client_sdk/src/build_tools/update_sdktools.py
@@ -107,7 +107,7 @@ def UpdateManifestFileToRevision(filename, revision):
def main(args):
- parser = optparse.OptionParser()
+ parser = optparse.OptionParser(description=__doc__)
parser.add_option('-r', '--revision',
help='set revision manually, rather than using the latest version')
options, args = parser.parse_args(args[1:])
diff --git a/native_client_sdk/src/doc/Makefile b/native_client_sdk/src/doc/Makefile
index 2fc4e0fe27..d9faadf1d4 100644
--- a/native_client_sdk/src/doc/Makefile
+++ b/native_client_sdk/src/doc/Makefile
@@ -183,9 +183,18 @@ pseudoxml:
devsite-prod:
$(SPHINXBUILD) -b devsite -D devsite_production_mode=1 $(ALLSPHINXOPTS) $(BUILDDIR)/devsite-prod
+ rm -rf $(BUILDDIR)/devsite-staging/images
+ cp -r $(BUILDDIR)/devsite-prod/_images $(BUILDDIR)/devsite-prod/images
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/devsite-prod."
+devsite-staging:
+ $(SPHINXBUILD) -b devsite -D devsite_foldername=$(USER) -D devsite_production_mode=1 $(ALLSPHINXOPTS) $(BUILDDIR)/devsite-staging
+ rm -rf $(BUILDDIR)/devsite-staging/images
+ cp -r $(BUILDDIR)/devsite-staging/_images $(BUILDDIR)/devsite-staging/images
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/devsite-staging."
+
devsite:
$(SPHINXBUILD) -b devsite -D devsite_production_mode=0 $(ALLSPHINXOPTS) $(BUILDDIR)/devsite
@echo
diff --git a/native_client_sdk/src/doc/README b/native_client_sdk/src/doc/README
index 14edf8a233..2d9bf86dc9 100644
--- a/native_client_sdk/src/doc/README
+++ b/native_client_sdk/src/doc/README
@@ -21,44 +21,59 @@ How to build
------------
To build the docs you will needs sphinx installed (and sphinx-build in your
-path), and simply run:
+path). On debian/ubuntu this command is part of the ``python-sphinx`` package.
- make
+There are many different output formats that can be generated using the targets
+in the included Makefile. The three most commonly used ones are ``devsite``,
+``devsite-prod`` and ``devsite-staging``.
-To rebuild all the pages always, add 'SPHINXOPTS=-a', e.g.:
+The ``devsite`` configuration is for generating docs for local viewing and is
+also the default make target. To build this config simply run::
- make SPHINXOPTS=-a
+ make
-To emit local-testing mode, instead of production mode, add:
- SPHINXOPTS='-D devsite_production_mode=0'
-e.g.:
+To rebuild all the pages always, add ``SPHINXOPTS=-a``, e.g.::
- make SPHINXOPTS='-D devsite_production_mode=0'
+ make SPHINXOPTS=-a
+
+To emit docs suitable for pushing to production use::
+
+ make devsite-prod
Production mode contains devsite-specific templating and non-HTML constructs.
+The ``devsite-staging`` target is exactly the same except that the html pages
+are all rooted under a folder called $USER, which allows each user to stage his
+own copy of the docs.
-The builder prints out the value of this setting - make sure it's what you
-expect it to be. For example:
+When building in production mode you can specify the name of the subfolder in
+which the docs are rooted by specifying ``SPHINXOPTS=-Ddevsite_foldername=``.
+For example::
- $ make
- sphinx-build -b devsite -d _build/doctrees . _build/devsite
- Running Sphinx v1.2b1
- loading pickled environment... done
- ----> Devsite builder with production mode = 1
+ make devsite-prod SPHINXOPTS=-Ddevsite_foldername=pepper_32
Local HTTP server to view the docs
----------------------------------
-To view the HTML locally, build the docs with production mode turned off, and
-run:
+To view the HTML locally, build the docs with production mode turned off, and
+run::
- make serve
+ make serve
This will start a webserver on the local machine, and allows the pages
-to be viewed by in a browser by navigating to:
+to be viewed by in a browser by navigating to::
- http://localhost:8009/
+ http://localhost:8009/
Serving through a server and not just file:/// because this way the <link>
relative paths to CSS actually work.
+Checking outgoing links for integrity
+-------------------------------------
+
+We use the Sphinx-provided link checker (configured in conf.py and with some
+monkey-patching in the extension) to check the outgoing links from the
+documentation. To run the link checker::
+
+ make linkcheck
+
+And look for "broken" in the output file.
diff --git a/native_client_sdk/src/doc/_book.yaml b/native_client_sdk/src/doc/_book.yaml
new file mode 100644
index 0000000000..32dd6aaccf
--- /dev/null
+++ b/native_client_sdk/src/doc/_book.yaml
@@ -0,0 +1,17 @@
+toc:
+- title: "Version ${version} (${folder})"
+ path: /native-client/${folder}/version
+- title: "News & Announcements"
+ path: /native-client/${folder}/announcements
+- title: "Technical Overview"
+ path: /native-client/${folder}/overview
+- title: "Quick-start"
+ path: /native-client/${folder}/quick-start
+- include: /native-client/${folder}/sdk/_toc.yaml
+- include: /native-client/${folder}/devguide/_toc.yaml
+- include: /native-client/${folder}/_reference_toc.yaml
+- include: /native-client/${folder}/community/_toc.yaml
+- title: "FAQ"
+ path: /native-client/${folder}/faq
+- title: "Get Help with NaCl"
+ path: /native-client/${folder}/help
diff --git a/native_client_sdk/src/doc/_project.yaml b/native_client_sdk/src/doc/_project.yaml
new file mode 100644
index 0000000000..eaac5c65f1
--- /dev/null
+++ b/native_client_sdk/src/doc/_project.yaml
@@ -0,0 +1,4 @@
+name: "Native Client"
+description: "Native Client documentation for Pepper ${version}"
+home_url: /native-client/${folder}/
+content_license: cc3-apache2
diff --git a/native_client_sdk/src/doc/_reference_toc.yaml b/native_client_sdk/src/doc/_reference_toc.yaml
new file mode 100644
index 0000000000..71a17d51af
--- /dev/null
+++ b/native_client_sdk/src/doc/_reference_toc.yaml
@@ -0,0 +1,494 @@
+toc:
+- title: "Pepper C API"
+ path: /native-client/${folder}/pepperc/
+ section:
+ - title: "Interfaces"
+ path: /native-client/${folder}/pepperc/group___interfaces
+ section:
+ - title: "PPB_Audio"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___audio__1__0
+ - title: "PPB_AudioConfig"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___audio_config__1__1
+ - title: "PPB_Console"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___console__1__0
+ - title: "PPB_Core"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___core__1__0
+ - title: "PPB_FileIO"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___file_i_o__1__1
+ - title: "PPB_FileRef"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___file_ref__1__1
+ - title: "PPB_FileSystem"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___file_system__1__0
+ - title: "PPB_Fullscreen"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___fullscreen__1__0
+ - title: "PPB_Gamepad"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___gamepad__1__0
+ - title: "PPB_Graphics2D"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___graphics2_d__1__1
+ - title: "PPB_Graphics3D"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___graphics3_d__1__0
+ - title: "PPB_HostResolver"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___host_resolver__1__0
+ - title: "PPB_IMEInputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___i_m_e_input_event__1__0
+ - title: "PPB_ImageData"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___image_data__1__0
+ - title: "PPB_InputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___input_event__1__0
+ - title: "PPB_Instance"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___instance__1__0
+ - title: "PPB_KeyboardInputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___keyboard_input_event__1__0
+ - title: "PPB_MessageLoop"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___message_loop__1__0
+ - title: "PPB_Messaging"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___messaging__1__0
+ - title: "PPB_MouseCursor"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___mouse_cursor__1__0
+ - title: "PPB_MouseInputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___mouse_input_event__1__1
+ - title: "PPB_MouseLock"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___mouse_lock__1__0
+ - title: "PPB_NetAddress"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___net_address__1__0
+ - title: "PPB_NetworkProxy"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___network_proxy__1__0
+ - title: "PPB_OpenGLES2"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2
+ - title: "PPB_OpenGLES2ChromiumEnableFeature"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_chromium_enable_feature
+ - title: "PPB_OpenGLES2ChromiumMapSub"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_chromium_map_sub
+ - title: "PPB_OpenGLES2FramebufferBlit"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_framebuffer_blit
+ - title: "PPB_OpenGLES2FramebufferMultisample"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_framebuffer_multisample
+ - title: "PPB_OpenGLES2InstancedArrays"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_instanced_arrays
+ - title: "PPB_OpenGLES2Query"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___open_g_l_e_s2_query
+ - title: "PPB_TCPSocket"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___t_c_p_socket__1__0
+ - title: "PPB_TextInputController"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___text_input_controller__1__0
+ - title: "PPB_TouchInputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___touch_input_event__1__0
+ - title: "PPB_UDPSocket"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___u_d_p_socket__1__0
+ - title: "PPB_URLLoader"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___u_r_l_loader__1__0
+ - title: "PPB_URLRequestInfo"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___u_r_l_request_info__1__0
+ - title: "PPB_URLResponseInfo"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___u_r_l_response_info__1__0
+ - title: "PPB_Var"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___var__1__1
+ - title: "PPB_VarArray"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___var_array__1__0
+ - title: "PPB_VarArrayBuffer"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___var_array_buffer__1__0
+ - title: "PPB_VarDictionary"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___var_dictionary__1__0
+ - title: "PPB_View"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___view__1__1
+ - title: "PPB_WebSocket"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___web_socket__1__0
+ - title: "PPB_WheelInputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_b___wheel_input_event__1__0
+ - title: "PPP_Graphics3D"
+ path: /native-client/${folder}/pepperc/struct_p_p_p___graphics3_d__1__0
+ - title: "PPP_InputEvent"
+ path: /native-client/${folder}/pepperc/struct_p_p_p___input_event__0__1
+ - title: "PPP_Instance"
+ path: /native-client/${folder}/pepperc/struct_p_p_p___instance__1__1
+ - title: "PPP_Messaging"
+ path: /native-client/${folder}/pepperc/struct_p_p_p___messaging__1__0
+ - title: "PPP_MouseLock"
+ path: /native-client/${folder}/pepperc/struct_p_p_p___mouse_lock__1__0
+ - title: "Structures"
+ path: /native-client/${folder}/pepperc/group___structs
+ section:
+ - title: "PP_ArrayOutput"
+ path: /native-client/${folder}/pepperc/struct_p_p___array_output
+ - title: "PP_CompletionCallback"
+ path: /native-client/${folder}/pepperc/struct_p_p___completion_callback
+ - title: "PP_DirectoryEntry"
+ path: /native-client/${folder}/pepperc/struct_p_p___directory_entry
+ - title: "PP_FileInfo"
+ path: /native-client/${folder}/pepperc/struct_p_p___file_info
+ - title: "PP_FloatPoint"
+ path: /native-client/${folder}/pepperc/struct_p_p___float_point
+ - title: "PP_GamepadSampleData"
+ path: /native-client/${folder}/pepperc/struct_p_p___gamepad_sample_data
+ - title: "PP_GamepadsSampleData"
+ path: /native-client/${folder}/pepperc/struct_p_p___gamepads_sample_data
+ - title: "PP_HostResolverHint"
+ path: /native-client/${folder}/pepperc/struct_p_p___host_resolver___hint
+ - title: "PP_ImageDataDesc"
+ path: /native-client/${folder}/pepperc/struct_p_p___image_data_desc
+ - title: "PP_InputEventCharacter"
+ path: /native-client/${folder}/pepperc/struct_p_p___input_event___character
+ - title: "PP_InputEventKey"
+ path: /native-client/${folder}/pepperc/struct_p_p___input_event___key
+ - title: "PP_InputEventMouse"
+ path: /native-client/${folder}/pepperc/struct_p_p___input_event___mouse
+ - title: "PP_InputEventWheel"
+ path: /native-client/${folder}/pepperc/struct_p_p___input_event___wheel
+ - title: "PP_NetAddressIPv4"
+ path: /native-client/${folder}/pepperc/struct_p_p___net_address___i_pv4
+ - title: "PP_NetAddressIPv6"
+ path: /native-client/${folder}/pepperc/struct_p_p___net_address___i_pv6
+ - title: "PP_Point"
+ path: /native-client/${folder}/pepperc/struct_p_p___point
+ - title: "PP_Rect"
+ path: /native-client/${folder}/pepperc/struct_p_p___rect
+ - title: "PP_Size"
+ path: /native-client/${folder}/pepperc/struct_p_p___size
+ - title: "PP_TouchPoint"
+ path: /native-client/${folder}/pepperc/struct_p_p___touch_point
+ - title: "PP_Var"
+ path: /native-client/${folder}/pepperc/struct_p_p___var
+ - title: "PP_VarValue"
+ path: /native-client/${folder}/pepperc/union_p_p___var_value
+ - title: "Functions"
+ path: /native-client/${folder}/pepperc/group___functions
+ - title: "Enums"
+ path: /native-client/${folder}/pepperc/group___enums
+ - title: "Typedefs"
+ path: /native-client/${folder}/pepperc/group___typedefs
+ - title: "Macros"
+ path: /native-client/${folder}/pepperc/globals_defs
+ - title: "Files"
+ path: /native-client/${folder}/pepperc/files
+ section:
+ - title: "pp_array_output.h"
+ path: /native-client/${folder}/pepperc/pp__array__output_8h
+ - title: "pp_bool.h"
+ path: /native-client/${folder}/pepperc/pp__bool_8h
+ - title: "pp_completion_callback.h"
+ path: /native-client/${folder}/pepperc/pp__completion__callback_8h
+ - title: "pp_directory_entry.h"
+ path: /native-client/${folder}/pepperc/pp__directory__entry_8h
+ - title: "pp_errors.h"
+ path: /native-client/${folder}/pepperc/pp__errors_8h
+ - title: "pp_file_info.h"
+ path: /native-client/${folder}/pepperc/pp__file__info_8h
+ - title: "pp_graphics_3d.h"
+ path: /native-client/${folder}/pepperc/pp__graphics__3d_8h
+ - title: "pp_input_event.h"
+ path: /native-client/${folder}/pepperc/pp__input__event_8h
+ - title: "pp_instance.h"
+ path: /native-client/${folder}/pepperc/pp__instance_8h
+ - title: "pp_module.h"
+ path: /native-client/${folder}/pepperc/pp__module_8h
+ - title: "pp_point.h"
+ path: /native-client/${folder}/pepperc/pp__point_8h
+ - title: "pp_rect.h"
+ path: /native-client/${folder}/pepperc/pp__rect_8h
+ - title: "pp_resource.h"
+ path: /native-client/${folder}/pepperc/pp__resource_8h
+ - title: "pp_size.h"
+ path: /native-client/${folder}/pepperc/pp__size_8h
+ - title: "pp_stdint.h"
+ path: /native-client/${folder}/pepperc/pp__stdint_8h
+ - title: "pp_time.h"
+ path: /native-client/${folder}/pepperc/pp__time_8h
+ - title: "pp_touch_point.h"
+ path: /native-client/${folder}/pepperc/pp__touch__point_8h
+ - title: "pp_var.h"
+ path: /native-client/${folder}/pepperc/pp__var_8h
+ - title: "ppb.h"
+ path: /native-client/${folder}/pepperc/ppb_8h
+ - title: "ppb_audio.h"
+ path: /native-client/${folder}/pepperc/ppb__audio_8h
+ - title: "ppb_audio_config.h"
+ path: /native-client/${folder}/pepperc/ppb__audio__config_8h
+ - title: "ppb_console.h"
+ path: /native-client/${folder}/pepperc/ppb__console_8h
+ - title: "ppb_core.h"
+ path: /native-client/${folder}/pepperc/ppb__core_8h
+ - title: "ppb_file_io.h"
+ path: /native-client/${folder}/pepperc/ppb__file__io_8h
+ - title: "ppb_file_ref.h"
+ path: /native-client/${folder}/pepperc/ppb__file__ref_8h
+ - title: "ppb_file_system.h"
+ path: /native-client/${folder}/pepperc/ppb__file__system_8h
+ - title: "ppb_fullscreen.h"
+ path: /native-client/${folder}/pepperc/ppb__fullscreen_8h
+ - title: "ppb_gamepad.h"
+ path: /native-client/${folder}/pepperc/ppb__gamepad_8h
+ - title: "ppb_graphics_2d.h"
+ path: /native-client/${folder}/pepperc/ppb__graphics__2d_8h
+ - title: "ppb_graphics_3d.h"
+ path: /native-client/${folder}/pepperc/ppb__graphics__3d_8h
+ - title: "ppb_host_resolver.h"
+ path: /native-client/${folder}/pepperc/ppb__host__resolver_8h
+ - title: "ppb_image_data.h"
+ path: /native-client/${folder}/pepperc/ppb__image__data_8h
+ - title: "ppb_input_event.h"
+ path: /native-client/${folder}/pepperc/ppb__input__event_8h
+ - title: "ppb_instance.h"
+ path: /native-client/${folder}/pepperc/ppb__instance_8h
+ - title: "ppb_message_loop.h"
+ path: /native-client/${folder}/pepperc/ppb__message__loop_8h
+ - title: "ppb_messaging.h"
+ path: /native-client/${folder}/pepperc/ppb__messaging_8h
+ - title: "ppb_mouse_cursor.h"
+ path: /native-client/${folder}/pepperc/ppb__mouse__cursor_8h
+ - title: "ppb_mouse_lock.h"
+ path: /native-client/${folder}/pepperc/ppb__mouse__lock_8h
+ - title: "ppb_net_address.h"
+ path: /native-client/${folder}/pepperc/ppb__net__address_8h
+ - title: "ppb_network_proxy.h"
+ path: /native-client/${folder}/pepperc/ppb__network__proxy_8h
+ - title: "ppb_opengles2.h"
+ path: /native-client/${folder}/pepperc/ppb__opengles2_8h
+ - title: "ppb_tcp_socket.h"
+ path: /native-client/${folder}/pepperc/ppb__tcp__socket_8h
+ - title: "ppb_text_input_controller.h"
+ path: /native-client/${folder}/pepperc/ppb__text__input__controller_8h
+ - title: "ppb_udp_socket.h"
+ path: /native-client/${folder}/pepperc/ppb__udp__socket_8h
+ - title: "ppb_url_loader.h"
+ path: /native-client/${folder}/pepperc/ppb__url__loader_8h
+ - title: "ppb_url_request_info.h"
+ path: /native-client/${folder}/pepperc/ppb__url__request__info_8h
+ - title: "ppb_url_response_info.h"
+ path: /native-client/${folder}/pepperc/ppb__url__response__info_8h
+ - title: "ppb_var.h"
+ path: /native-client/${folder}/pepperc/ppb__var_8h
+ - title: "ppb_var_array.h"
+ path: /native-client/${folder}/pepperc/ppb__var__array_8h
+ - title: "ppb_var_array_buffer.h"
+ path: /native-client/${folder}/pepperc/ppb__var__array__buffer_8h
+ - title: "ppb_var_dictionary.h"
+ path: /native-client/${folder}/pepperc/ppb__var__dictionary_8h
+ - title: "ppb_view.h"
+ path: /native-client/${folder}/pepperc/ppb__view_8h
+ - title: "ppb_websocket.h"
+ path: /native-client/${folder}/pepperc/ppb__websocket_8h
+ - title: "ppp.h"
+ path: /native-client/${folder}/pepperc/ppp_8h
+ - title: "ppp_graphics_3d.h"
+ path: /native-client/${folder}/pepperc/ppp__graphics__3d_8h
+ - title: "ppp_input_event.h"
+ path: /native-client/${folder}/pepperc/ppp__input__event_8h
+ - title: "ppp_instance.h"
+ path: /native-client/${folder}/pepperc/ppp__instance_8h
+ - title: "ppp_messaging.h"
+ path: /native-client/${folder}/pepperc/ppp__messaging_8h
+ - title: "ppp_mouse_lock.h"
+ path: /native-client/${folder}/pepperc/ppp__mouse__lock_8h
+- title: "Pepper C++ API"
+ path: /native-client/${folder}/peppercpp/
+ section:
+ - title: "Classes"
+ path: /native-client/${folder}/peppercpp/inherits
+ section:
+ - title: "Audio"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_audio
+ - title: "AudioConfig"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_audio_config
+ - title: "CompletionCallback"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_completion_callback
+ - title: "CompletionCallbackFactory"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_completion_callback_factory
+ - title: "CompletionCallbackWithOutput"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_completion_callback_with_output
+ - title: "Core"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_core
+ - title: "DirectoryEntry"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_directory_entry
+ - title: "FileIO"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_file_i_o
+ - title: "FileRef"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_file_ref
+ - title: "FileSystem"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_file_system
+ - title: "FloatPoint"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_float_point
+ - title: "Fullscreen"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_fullscreen
+ - title: "Graphics2D"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_graphics2_d
+ - title: "Graphics3D"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_graphics3_d
+ - title: "Graphics3DClient"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_graphics3_d_client
+ - title: "HostResolver"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_host_resolver
+ - title: "IMEInputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_i_m_e_input_event
+ - title: "ImageData"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_image_data
+ - title: "InputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_input_event
+ - title: "Instance"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_instance
+ - title: "InstanceHandle"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_instance_handle
+ - title: "KeyboardInputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_keyboard_input_event
+ - title: "MessageLoop"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_message_loop
+ - title: "Module"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_module
+ - title: "MouseCursor"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_mouse_cursor
+ - title: "MouseInputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_mouse_input_event
+ - title: "MouseLock"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_mouse_lock
+ - title: "NetAddress"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_net_address
+ - title: "NetworkProxy"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_network_proxy
+ - title: "PaintAggregator"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_paint_aggregator
+ - title: "PaintManager"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_paint_manager
+ - title: "PaintManager::Client"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_paint_manager_1_1_client
+ - title: "Point"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_point
+ - title: "Rect"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_rect
+ - title: "Resource"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_resource
+ - title: "Size"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_size
+ - title: "TCPSocket"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_t_c_p_socket
+ - title: "TextInputController"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_text_input_controller
+ - title: "TouchInputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_touch_input_event
+ - title: "TouchPoint"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_touch_point
+ - title: "UDPSocket"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_u_d_p_socket
+ - title: "URLLoader"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_u_r_l_loader
+ - title: "URLRequestInfo"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_u_r_l_request_info
+ - title: "URLResponseInfo"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_u_r_l_response_info
+ - title: "Var"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_var
+ - title: "Var::OutException"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_var_1_1_out_exception
+ - title: "VarArray"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_var_array
+ - title: "VarArrayBuffer"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_var_array_buffer
+ - title: "VarDictionary"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_var_dictionary
+ - title: "View"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_view
+ - title: "WebSocket"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_web_socket
+ - title: "WheelInputEvent"
+ path: /native-client/${folder}/peppercpp/classpp_1_1_wheel_input_event
+ - title: "Ext::ExtCompletionCallbackWithOutput"
+ path: /native-client/${folder}/peppercpp/classpp_1_1ext_1_1_ext_completion_callback_with_output
+ - title: "Internal::CompletionCallbackWithOutputBase"
+ path: /native-client/${folder}/peppercpp/classpp_1_1internal_1_1_completion_callback_with_output_base
+ - title: "Internal::DirectoryEntryArrayOutputAdapterWithStorage"
+ path: /native-client/${folder}/peppercpp/classpp_1_1internal_1_1_directory_entry_array_output_adapter_with_storage
+ - title: "Files"
+ path: /native-client/${folder}/peppercpp/files
+ section:
+ - title: "audio.h"
+ path: /native-client/${folder}/peppercpp/audio_8h
+ - title: "audio_config.h"
+ path: /native-client/${folder}/peppercpp/audio__config_8h
+ - title: "completion_callback.h"
+ path: /native-client/${folder}/peppercpp/completion__callback_8h
+ - title: "completion_callback_factory.h"
+ path: /native-client/${folder}/peppercpp/completion__callback__factory_8h
+ - title: "core.h"
+ path: /native-client/${folder}/peppercpp/core_8h
+ - title: "directory_entry.h"
+ path: /native-client/${folder}/peppercpp/directory__entry_8h
+ - title: "file_io.h"
+ path: /native-client/${folder}/peppercpp/file__io_8h
+ - title: "file_ref.h"
+ path: /native-client/${folder}/peppercpp/file__ref_8h
+ - title: "file_system.h"
+ path: /native-client/${folder}/peppercpp/file__system_8h
+ - title: "fullscreen.h"
+ path: /native-client/${folder}/peppercpp/fullscreen_8h
+ - title: "graphics_2d.h"
+ path: /native-client/${folder}/peppercpp/graphics__2d_8h
+ - title: "graphics_3d.h"
+ path: /native-client/${folder}/peppercpp/graphics__3d_8h
+ - title: "graphics_3d_client.h"
+ path: /native-client/${folder}/peppercpp/graphics__3d__client_8h
+ - title: "host_resolver.h"
+ path: /native-client/${folder}/peppercpp/host__resolver_8h
+ - title: "image_data.h"
+ path: /native-client/${folder}/peppercpp/image__data_8h
+ - title: "input_event.h"
+ path: /native-client/${folder}/peppercpp/input__event_8h
+ - title: "instance.h"
+ path: /native-client/${folder}/peppercpp/instance_8h
+ - title: "instance_handle.h"
+ path: /native-client/${folder}/peppercpp/instance__handle_8h
+ - title: "logging.h"
+ path: /native-client/${folder}/peppercpp/logging_8h
+ - title: "message_loop.h"
+ path: /native-client/${folder}/peppercpp/message__loop_8h
+ - title: "module.h"
+ path: /native-client/${folder}/peppercpp/module_8h
+ - title: "module_embedder.h"
+ path: /native-client/${folder}/peppercpp/module__embedder_8h
+ - title: "module_impl.h"
+ path: /native-client/${folder}/peppercpp/module__impl_8h
+ - title: "mouse_cursor.h"
+ path: /native-client/${folder}/peppercpp/mouse__cursor_8h
+ - title: "mouse_lock.h"
+ path: /native-client/${folder}/peppercpp/mouse__lock_8h
+ - title: "net_address.h"
+ path: /native-client/${folder}/peppercpp/net__address_8h
+ - title: "network_proxy.h"
+ path: /native-client/${folder}/peppercpp/network__proxy_8h
+ - title: "paint_aggregator.h"
+ path: /native-client/${folder}/peppercpp/paint__aggregator_8h
+ - title: "paint_manager.h"
+ path: /native-client/${folder}/peppercpp/paint__manager_8h
+ - title: "pass_ref.h"
+ path: /native-client/${folder}/peppercpp/pass__ref_8h
+ - title: "point.h"
+ path: /native-client/${folder}/peppercpp/point_8h
+ - title: "rect.h"
+ path: /native-client/${folder}/peppercpp/rect_8h
+ - title: "resource.h"
+ path: /native-client/${folder}/peppercpp/resource_8h
+ - title: "size.h"
+ path: /native-client/${folder}/peppercpp/size_8h
+ - title: "tcp_socket.h"
+ path: /native-client/${folder}/peppercpp/tcp__socket_8h
+ - title: "text_input_controller.h"
+ path: /native-client/${folder}/peppercpp/text__input__controller_8h
+ - title: "touch_point.h"
+ path: /native-client/${folder}/peppercpp/touch__point_8h
+ - title: "udp_socket.h"
+ path: /native-client/${folder}/peppercpp/udp__socket_8h
+ - title: "url_loader.h"
+ path: /native-client/${folder}/peppercpp/url__loader_8h
+ - title: "url_request_info.h"
+ path: /native-client/${folder}/peppercpp/url__request__info_8h
+ - title: "url_response_info.h"
+ path: /native-client/${folder}/peppercpp/url__response__info_8h
+ - title: "var.h"
+ path: /native-client/${folder}/peppercpp/var_8h
+ - title: "var_array.h"
+ path: /native-client/${folder}/peppercpp/var__array_8h
+ - title: "var_array_buffer.h"
+ path: /native-client/${folder}/peppercpp/var__array__buffer_8h
+ - title: "var_dictionary.h"
+ path: /native-client/${folder}/peppercpp/var__dictionary_8h
+ - title: "view.h"
+ path: /native-client/${folder}/peppercpp/view_8h
+ - title: "websocket.h"
+ path: /native-client/${folder}/peppercpp/websocket_8h
diff --git a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
index fd4c074cc4..dbb288cd4c 100644
--- a/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
+++ b/native_client_sdk/src/doc/_sphinxext/devsite_builder.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013 The Native Client Authors. All rights reserved.
+# 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.
@@ -15,7 +15,9 @@ from sphinx.util.osutil import ensuredir
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.writers.html import HTMLWriter
from sphinx.writers.html import SmartyPantsHTMLTranslator as HTMLTranslator
+from sphinx.util.console import bold
+PEPPER_VERSION = "31"
# TODO(eliben): it may be interesting to use an actual Sphinx template here at
# some point.
@@ -23,9 +25,10 @@ PAGE_TEMPLATE = string.Template(r'''
${devsite_prefix}
<html devsite>
<head>
+ ${nonprod_meta_head}
<title>${doc_title}</title>
- <meta name="project_path" value="/native-client/_project.yaml" />
- <meta name="book_path" value="/native-client/_book.yaml" />
+ <meta name="project_path" value="/native-client${folder}/_project.yaml" />
+ <meta name="book_path" value="/native-client${folder}/_book.yaml" />
<link href="/native-client/css/local_extensions.css" rel="stylesheet" type="text/css"/>
${nonprod_css}
<style type="text/css">
@@ -43,9 +46,8 @@ ${doc_body}
'''.lstrip())
DEVSITE_PREFIX = r'''
-{% setvar pepperversion %}pepper28{% endsetvar %}
-{% include "native-client/_local_variables.html" %}
-'''.lstrip()
+{% setvar pepperversion %}pepper''' + PEPPER_VERSION + ''' {% endsetvar %}
+{% include "native-client/_local_variables.html" %}'''
DEVSITE_BUTTERBAR = '{{butterbar}}'
@@ -54,6 +56,7 @@ DEVSITE_BUTTERBAR = '{{butterbar}}'
# testing purposes only.
NONPROD_CSS = '<link href="/_static/css/local_extensions.css"'\
'rel="stylesheet" type="text/css"/>'
+NONPROD_META_HEAD = '<meta charset="utf-8" />'
class DevsiteHTMLTranslator(HTMLTranslator):
@@ -140,9 +143,23 @@ class DevsiteHTMLTranslator(HTMLTranslator):
# Paths to images in .rst sources should be absolute. This visitor does the
# required transformation for the path to be correct in the final HTML.
if self.builder.devsite_production_mode:
- node['uri'] = '/native-client/' + node['uri']
+ node['uri'] = self.builder.get_production_url(node['uri'])
HTMLTranslator.visit_image(self, node)
+ def visit_reference(self, node):
+ # In "kill_internal_links" mode, we don't emit the actual links for internal
+ # nodes.
+ if self.builder.kill_internal_links and node.get('internal'):
+ pass
+ else:
+ HTMLTranslator.visit_reference(self, node)
+
+ def depart_reference(self, node):
+ if self.builder.kill_internal_links and node.get('internal'):
+ pass
+ else:
+ HTMLTranslator.depart_reference(self, node)
+
def visit_title(self, node):
# Why this?
#
@@ -219,6 +236,7 @@ class DevsiteBuilder(StandaloneHTMLBuilder):
def init(self):
self.devsite_production_mode = int(self.config.devsite_production_mode) == 1
+ self.kill_internal_links = int(self.config.kill_internal_links) == 1
print "----> Devsite builder with production mode = %d" % (
self.devsite_production_mode,)
self.config_hash = ''
@@ -228,11 +246,56 @@ class DevsiteBuilder(StandaloneHTMLBuilder):
self.init_translator_class()
self.init_highlighter()
+ def finish(self):
+ super(DevsiteBuilder, self).finish()
+
+ if self.devsite_production_mode:
+ self.info(bold('generating yaml files... '), nonl=True)
+
+ substitutions = {
+ 'version': PEPPER_VERSION,
+ 'folder': self.config.devsite_foldername
+ }
+
+ olddir = os.getcwd()
+ try:
+ os.chdir(self.env.srcdir)
+ for root, dirs, files in os.walk('.'):
+ root = os.path.normpath(root)
+ if root.startswith("_"):
+ continue
+ for filename in files:
+ if os.path.splitext(filename)[1] != ".yaml":
+ continue
+ filename = os.path.join(root, filename)
+ outfile = os.path.join(self.outdir, filename)
+ with open(filename) as f:
+ template = string.Template(f.read())
+
+ with open(outfile, 'w') as f:
+ f.write(template.substitute(substitutions))
+ finally:
+ os.chdir(olddir)
+
+ self.info()
+
+ def dump_inventory(self):
+ # We don't want an inventory file when building for devsite
+ if not self.devsite_production_mode:
+ super(DevsiteBuilder, self).dump_inventory()
+
+ def get_production_url(self, url):
+ if not self.devsite_production_mode:
+ return url
+
+ if self.config.devsite_foldername:
+ return '/native-client/%s/%s' % (self.config.devsite_foldername, url)
+
+ return '/native-client/%s' % url
+
def get_target_uri(self, docname, typ=None):
if self.devsite_production_mode:
- # TODO(eliben): testrst here will have to be replaced with
- # {{pepperversion}}
- return '/native-client/testrst/%s' % docname
+ return self.get_production_url(docname)
else:
return docname + self.link_suffix
@@ -262,13 +325,20 @@ class DevsiteBuilder(StandaloneHTMLBuilder):
"""
if not 'body' in context:
return
+
+ folder = ''
+ if self.devsite_production_mode and self.config.devsite_foldername:
+ folder = "/" + self.config.devsite_foldername
+
# codecs.open is the fast Python 2.x way of emulating the encoding= argument
# in Python 3's builtin open.
with codecs.open(filename, 'w', encoding='utf-8') as f:
f.write(PAGE_TEMPLATE.substitute(
doc_title=context.get('title', ''),
doc_body=context.get('body'),
+ folder=folder,
nonprod_css=self._conditional_nonprod(NONPROD_CSS),
+ nonprod_meta_head=self._conditional_nonprod(NONPROD_META_HEAD),
devsite_prefix=self._conditional_devsite(DEVSITE_PREFIX),
devsite_butterbar=self._conditional_devsite(DEVSITE_BUTTERBAR)))
@@ -300,10 +370,18 @@ class NaclCodeDirective(Directive):
def setup(app):
""" Extension registration hook.
"""
+ # linkcheck issues HEAD requests to save time, but some Google properties
+ # reject them and we get spurious 405 responses. Monkey-patch sphinx to
+ # just use normal GET requests.
+ # See: https://bitbucket.org/birkenfeld/sphinx/issue/1292/
+ from sphinx.builders import linkcheck
+ import urllib2
+ linkcheck.HeadRequest = urllib2.Request
+
app.add_directive('naclcode', NaclCodeDirective)
app.add_builder(DevsiteBuilder)
# "Production mode" for local testing vs. on-server documentation.
app.add_config_value('devsite_production_mode', default='1', rebuild='html')
-
-
+ app.add_config_value('kill_internal_links', default='0', rebuild='html')
+ app.add_config_value('devsite_foldername', default=None, rebuild='html')
diff --git a/native_client_sdk/src/doc/community/_toc.yaml b/native_client_sdk/src/doc/community/_toc.yaml
new file mode 100644
index 0000000000..ba8a936f0c
--- /dev/null
+++ b/native_client_sdk/src/doc/community/_toc.yaml
@@ -0,0 +1,14 @@
+toc:
+- title: "Community"
+ path: /native-client/${folder}/community
+ section:
+ - title: "Middleware & Software Support"
+ path: /native-client/${folder}/community/middleware
+ - title: "Application Gallery"
+ path: /native-client/${folder}/community/application-gallery
+ - title: "Developers Speak: Porting to Native Client"
+ path: /native-client/${folder}/community/developers
+ - title: "Talks, Demos, and Publications"
+ path: /native-client/${folder}/community/talks
+ - title: "Security Contest Archive"
+ path: /native-client/${folder}/community/security-contest/
diff --git a/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst b/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst
new file mode 100644
index 0000000000..9c7443a339
--- /dev/null
+++ b/native_client_sdk/src/doc/community/security-contest/contest-announcement.rst
@@ -0,0 +1,92 @@
+.. _contest_announcement:
+
+##############################
+Native Client Security Contest
+##############################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+.. include:: contest-warning.txt
+
+Do you think it is impossible to safely run untrusted x86 code on the
+web? Do you want a chance to impress a panel of some of the :ref:`top
+security experts<contest_judges>` in the world? Then submit an
+exploit to the Native Client Security contest and you could also win
+:ref:`cash prizes<contest_faq_prizes>`, not to mention bragging
+rights.
+
+.. |WHAT| image:: /images/code-32.gif
+.. |WHEN| image:: /images/calendar-32.gif
+.. |PRIZES| image:: /images/gift-32.gif
+
+What it is
+==========
+
+|WHAT| This is a contest with the goal to test the security of Native Client.
+
+To participate, you will need to:
+
+* `Register <http://nativeclientsecuritycontest.appspot.com/register>`_
+ yourself (or your team)
+* `Download <http://code.google.com/p/nativeclient/wiki/Downloads?tm=2>`_
+ our latest build
+* `Join <http://groups.google.com/group/native-client-discuss>`_
+ the Native Client discussion group
+* `Report <http://code.google.com/p/nativeclient/issues/list>`_
+ the exploits you find to our team
+
+When
+====
+
+|WHEN| You can register for the contest on Wednesday, February
+25th 2009. The contest will end on Tuesday, May 5th 2009 at 11:59:59
+Pacific time. Sign up early to start reporting exploits as soon as
+possible.
+
+What's in it for you
+====================
+
+|PRIZES| Participating in the contest means that you will engage with
+early stage research technology. In addition, your work will be
+reviewed by a :ref:`panel of security experts <contest_judges>` from
+some of the world's most renowned universities, chaired by Edward
+Felten of Princeton University. Finally, by submitting high impact
+bug(s), you will also have the chance to compete to win one of our
+five cash prizes, as well as the recognition of your peers.
+
+.. sidebar:: More about Native Client
+
+ * `Learn more about the Native Client open-source project
+ <http://code.google.com/p/nativeclient>`_
+
+ * `Download Native Client
+ <http://code.google.com/p/nativeclient/wiki/Downloads?tm=2>`_
+
+ * `Read the research paper
+ <http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/pubs/archive/34913.pdf>`_
+ (PDF)
+
+.. sidebar:: Featured Video
+
+ Watch a talk about Native Client at Stanford University.
+
+ .. raw:: html
+
+ <iframe width="640" height="360" src="//www.youtube.com/embed/L8m9U7p_Ntk?feature=player_embedded" frameborder="0" allowfullscreen></iframe>
+
+Forum: native-client-announce
+=============================
+
+.. raw:: html
+
+ <iframe src="https://groups.google.com/forum/embed/?place=forum/native-client-announce&amp;showsearch=false&amp;showtabs=false&amp;theme=default&amp;hideforumtitle=true&amp;hidesubject=false&amp;showpopout=true&amp;parenturl=https%3A%2F%2Fdevelopers.google.com%2Fnative-client%2Fcommunity%2Fsecurity-contest%2Fcontest-announcement" scrolling="no" frameborder="1" width="768" height="512"></iframe>
+
+Forum: native-client-discuss
+============================
+
+.. raw:: html
+
+ <iframe src="https://groups.google.com/forum/embed/?place=forum/native-client-discuss&amp;showsearch=false&amp;showtabs=false&amp;theme=default&amp;hideforumtitle=true&amp;hidesubject=false&amp;showpopout=true&amp;parenturl=https%3A%2F%2Fdevelopers.google.com%2Fnative-client%2Fcommunity%2Fsecurity-contest%2Fcontest-announcement" scrolling="no" frameborder="1" width="768" height="512"></iframe>
diff --git a/native_client_sdk/src/doc/community/security-contest/contest-faq.rst b/native_client_sdk/src/doc/community/security-contest/contest-faq.rst
new file mode 100644
index 0000000000..22728f1f17
--- /dev/null
+++ b/native_client_sdk/src/doc/community/security-contest/contest-faq.rst
@@ -0,0 +1,433 @@
+.. _contest_faq:
+
+####################
+Security Contest FAQ
+####################
+
+.. include:: contest-warning.txt
+
+This FAQ is provided for reference only. For the complete official
+contest rules, see the Terms and Conditions.
+
+.. contents::
+ :local:
+ :backlinks: none
+
+What is this contest about?
+===========================
+
+We launched this contest in order to help make Native Client more
+secure. We invite participants to discover security bugs in our
+technology in order to compete to win cash prizes.
+
+Where can I get more information on Native Client?
+==================================================
+
+You can read our `research paper
+<http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/pubs/archive/34913.pdf>`_
+(PDF) or visit the site for the `Native Client open-source project
+<http://code.google.com/p/nativeclient>`_.
+
+What people are you looking for?
+================================
+
+We are not looking for any particular participant profile. Everyone
+who is eligible to participate based on the :doc:`Terms and Conditions
+<contest-terms>` of the contest can sign up.
+
+How do I sign up?
+=================
+
+The first thing you need to do is to register. Then you and your team
+members (if any) will receive an email from our team asking you to
+review and accept the :doc:`Terms and Conditions
+<contest-terms>`:doc:` of the contest <contest-terms>`. Once everyone
+from your team has accepted the :doc:`Terms and Conditions
+<contest-terms>` you can start submitting bugs through the Native
+Client issue tracker. You should not submit any bugs as part of your
+contest entries until everyone on your team has accepted the
+:doc:`Terms and Conditions <contest-terms>`, as those bugs will not be
+eligible for consideration in the contest.
+
+What is the process of participating?
+=====================================
+
+After you register yourself or your team and every member of your team
+has accepted the :doc:`Terms and Conditions <contest-terms>`, download
+the latest build of Native Client, attack it, and identify security
+exploits. Submit these bugs through our Native Client Issue Tracker as
+quickly as you can, as you will only get credit for exploits that are
+first reported by yourself or your team. Before the end of the
+contest, you will need to submit a summary with the top 10 exploits
+you identified. Our judges will review submitted summaries and will
+select the top 5 contestants.
+
+.. _contest_faq_prizes:
+
+How many prizes are there? What are the prizes?
+===============================================
+
+There are five cash prizes: The first prize is $8,192, the second
+prize $4,096, the third prize is $2,048, the fourth prize is $1,024
+and the fifth prize is $1,024. All amounts are in USD.
+
+Can I sign up as a team? How many people can be a member of my team?
+====================================================================
+
+You can sign up as a team. There is no limit to how many people can
+participate in your team. However we recommend that you keep the size
+of your team small so as to be able to better coordinate during the
+contest.
+
+What will I need to do to win?
+==============================
+
+To participate, you will need to test the Native Client builds,
+identify security exploits which affect the current Native Client
+build at the time of submission and report them to our team. Our
+judges will review your entry. If you are one of the top five
+participants selected by the judges and satisfy the requirements for
+eligibility, then you will win a cash prize. For more information on
+how to participate and how your entry will be evaluated please review
+our detailed :doc:`Terms and Conditions <contest-terms>`.
+
+Who is going to judge these entries? Who are these people?
+==========================================================
+
+Google has recruited a group of distinguished security experts to
+serve as judges for this contest:
+
+* Edward Felten — jury chair (Princeton)
+* Alex Halderman (Michigan)
+* Brad Karp (University College London)
+* Greg Morrisett (Harvard)
+* Niels Provos (Google)
+* Stefan Savage (UCSD)
+* Dan Wallach (Rice)
+* Bennet Yee (Google)
+* Nickolai Zeldovich (MIT)
+
+Check out the :ref:`Judges info <contest_judges>` to learn more about
+their careers and contributions to the security community.
+
+When can I start submitting issues?
+===================================
+
+You can start submitting issues after you and your team members (if
+any) have completed the registration process and accepted the
+:doc:`Terms and Conditions <contest-terms>`.
+
+Registration does not work for me---what can I do?
+==================================================
+
+We recommend that you post this problem at the Google Group. Once you
+do so, a member from our team will reach out to you to try to diagnose
+the issue. We will try to help you out; keep in mind though that we
+can not be responsible for the inability of a participant to register.
+
+I registered as a team but I want to change the team composition by adding or removing members. What should I do?
+=================================================================================================================
+
+Please reply to one of the registration email messages you received
+(it should be sent to nacl-security-contest@google.com) and indicate
+the changes you'd like to make. Please note that neither the team name
+nor team membership can be changed once all members have accepted the
+:doc:`Terms and Conditions <contest-terms>`.
+
+I have a previous engagement and I cannot sign up until after the competition starts. Is this ok?
+=================================================================================================
+
+You can sign up until the last day of the contest May
+5th, 2009. However, keep in mind that while you can submit bugs
+through the Native Client Issue Tracker, none of these will be taken
+into account unless you (and all your team members) have completed the
+registration process prior to submitting any bugs.
+
+My team has accepted the Terms and Conditions except for one person who is unavailable / whose email was misspelled / etc. What can I do?
+=========================================================================================================================================
+
+To make edits to your team's composition, or to update the contact
+information of a team member, you will need to reply to one of the
+registration emails you received (it should be sent to
+nacl-security-contest@google.com) and indicate the changes you'd like
+to make. Please note that this will mean that your team members will
+receive an email notifying them of the changes in the team's
+composition and asking them to re-accept the :doc:`Terms and
+Conditions <contest-terms>`. All team members will need to re-accept
+the :doc:`Terms and Conditions <contest-terms>` for the team to be
+considered as active.
+
+Can I enter multiple times?
+===========================
+
+No, you cannot enter multiple times. If you register as an individual
+you can not also register on a team and if you are on a team you can
+not also be on another team.
+
+Why do you need a prize recipient?
+==================================
+
+Google will not be responsible for the division of any prize money
+between members of a potential winning team. Instead Google will
+deliver the prize to one member indicated by the team. The team is
+solely responsible for managing the logistics of distributing the
+prize among team members. This is why Google asks all participating
+teams to identify a prize recipient.
+
+We want to change the prize recipient. What can we do?
+======================================================
+
+To make edits to the prize recipient before all team members have
+accepted the :doc:`Terms and Conditions <contest-terms>`, you will
+need to reply to one of the registration emails you received (it
+should be sent to nacl-security-contest@google.com) and indicate the
+changes you'd like to make. Please note that this will mean that your
+team members will receive an email notifying them of the change and
+asking them to re-accept the :doc:`Terms and Conditions
+<contest-terms>`. All team members will need to re-accept the
+:doc:`Terms and Conditions <contest-terms>` for the team to be
+considered registered. After all team members have accepted the
+:doc:`Terms and Conditions <contest-terms>`, there can be no changes
+to the prize recipient.
+
+I want to remain anonymous during the contest. Is this possible?
+================================================================
+
+Yes. However, you will still need to provide us with your email
+address to register. After the contest ends and if you are one of the
+top 5 participants, to claim your prize, you and all of your team
+members (if any) will need to submit to Google all necessary tax and
+legal information that Google will need to comply with US and
+international legal and tax regulations.
+
+One of my professors / friends is a judge. Can I participate?
+=============================================================
+
+Yes, you can participate.
+
+Can my company be registered as an entrant?
+===========================================
+
+No, this is not possible under our :doc:`Terms and Conditions
+<contest-terms>`.
+
+I never signed up for this contest, but I got an email from you. What is this about?
+====================================================================================
+
+You have probably received an e-mail identifying you as a member of
+team that another person has created. In our email, we identified the
+email address of a person who registered you as a teammate in the
+Native Client Security Contest. If you want to participate in this
+person's team, then accept the :doc:`Terms and Conditions
+<contest-terms>` by clicking on the link included in the email. If you
+do not wish to participate in the contest or you want to do so as a
+member of a different team, then you can remove yourself from the list
+of team members of that particular team.
+
+I tried to sign up and it seems someone who wants to be a member of my team has already registered with another team. What can we do?
+=====================================================================================================================================
+
+If everyone in your potential teammate's original team (including
+himself/herself) has accepted the :doc:`Terms and Conditions
+<contest-terms>` of the contest, then unfortunately you will have to
+look for other potential partners. Otherwise, your potential teammate
+can remove himself from the other team. All he/she will need to do is
+to reply to one of the registration emails he/she received (it should
+be sent to nacl-security-contest@google.com) and indicate the changes
+to be made. Please note that this will mean that his/her team members
+will receive an email notifying them of the changes in the team's
+composition and asking them to re-accept the :doc:`Terms and
+Conditions <contest-terms>`. All team members of that team will need
+to re-accept the :doc:`Terms and Conditions <contest-terms>` for that
+team to be considered as active.
+
+I lost or never got the email asking me to confirm the Terms and Conditions. What can I do?
+===========================================================================================
+
+Don't worry, just send us an email at nacl-security-contest@google.com
+and we will send you the link you need.
+
+One of our team members rejected the Terms and Conditions. What can we do?
+==========================================================================
+
+Your team is now considered to be invalid. If this rejection happened
+by accident, please restart the registration process. If it was
+deliberate then create a new team with teammates who are willing to
+accept the :doc:`Terms and Conditions <contest-terms>`. No one can
+participate in the contest unless they have accepted the :doc:`Terms
+and Conditions <contest-terms>` and no team can participate unless all
+team members have accepted the :doc:`Terms and Conditions
+<contest-terms>`.
+
+How are you going to evaluate the submissions?
+==============================================
+
+The judges will evaluate each Summary based on the following
+criteria: a) Quality (Severity, Scope, Reliability and Style) and b)
+Quantity. Please review the judging criteria in the contest
+:doc:`Terms and Conditions <contest-terms>` for more information.
+
+Can I include issues I submitted before the contest?
+====================================================
+
+No, you can not.
+
+What is the difference between exploit, issue and summary?
+==========================================================
+
+An exploit becomes an issue once you submit it through the Native
+Client issue tracker. A summary can include multiple issues but not
+more than 10.
+
+What issues should I include in the summary?
+============================================
+
+You should include a maximum of 10 issues that you and your team
+members (if any) submitted to the Native Client Issue tracker. We
+recommend that you carefully review the judging criteria in the
+:doc:`Terms and Conditions <contest-terms>` to identify which bugs are
+more likely to be perceived as high impact from our judges and could
+help you win one of the five cash prizes. Do not include issues that
+have been marked as duplicates or unverifiable, as these will not be
+taken into account by our judges.
+
+Why are you asking for the top 10 issues only?
+==============================================
+
+We want to make sure that we use our judges' time wisely. Rather than
+having them review hundreds of similar or small scale bugs, sometimes
+identified with the same automatic process, we are limiting the number
+of issues that each participant can submit in his/her/their summary.
+
+My English is not great---will this count against me in the judging process?
+============================================================================
+
+Entries in languages other than in English or entries that are deemed
+incomprehensible by the judges will not be reviewed. We do not plan to
+penalize summaries for spelling or grammar mistakes, but please make
+your descriptions as clear as possible.
+
+What information do I need to include in the issue submission?
+==============================================================
+
+Please review the "Minimum requirements for issues" section of
+contest's :doc:`Terms and Conditions <contest-terms>`. You will find a
+list of all the information you will need to include in every
+submitted issue. Failure to provide this information might make the
+submitted issue invalid for the purposes of this contest.
+
+How do I contest a decision that a bug is a duplicate?
+======================================================
+
+Please highlight this in our Google Group and a member of our team
+will get in touch with you.
+
+Why is the Native Client team updating the source code during the contest?
+==========================================================================
+
+We are updating Native Client's source code to fix bugs reported by
+contest participants or exploits identified by our team. Our goal is
+to protect contestants and other users of the Native Client software
+from exploits that could damage their system. In addition, by updating
+our builds, we will be providing you with more opportunities to find
+new security bugs. Finally, we believe this will make the contest more
+interesting by continuously raising the bar of bug finding.
+
+I forgot to include something in the summary---what can I do?
+=============================================================
+
+If the contest has not ended, you may submit an updated summary. You
+may not submit an updated summary once the contest has ended.
+
+Someone from our team submitted a summary on behalf of our team without consulting with everyone else. How can we ensure that the judges will use the previous summary and not the last one?
+============================================================================================================================================================================================
+
+If your team member submitted his / her version of the team's summary
+before the end date of the contest, and if this is the last summary
+that was submitted from your team, then the Judges will disregard all
+previous versions of your summary and will only review this last
+one. If the contest has not ended, you may resubmit a previous summary
+to override the first.
+
+Will you be evaluating each exploit separately for every one of the criteria?
+=============================================================================
+
+We will use our criteria to evaluate submitted summaries, not
+individual exploits.
+
+I only found one exploit but I think it is very good. Can I still win?
+======================================================================
+
+Yes. Quantity is only one of the criteria we use to evaluate submitted
+summaries.
+
+How are you going to pick the winners?
+======================================
+
+After the contest ends, all submitted Summaries will be judged by a
+panel of at least three judges. The judges will evaluate each Summary
+based on the following criteria: a) Quality (Severity, Scope,
+Reliability and Style) and b) Quantity. Each panel will evaluate a
+number of the submitted summaries and will select the highest ranking
+Summaries to move to the next level of judging. Those top Summaries
+will then be evaluated by all Judges using the same Criteria, and the
+top five Summaries will be selected as potential winners. For more
+information on the judging criteria and the judging process please
+review the relevant section of the :doc:`Terms and Conditions
+<contest-terms>`.
+
+When and how are we going to find out the results of the contest?
+=================================================================
+
+We will contact all prospective winners at the email address provided
+to us at the registration process. You may request a list of winners
+after December 7th, 2009 by writing to: Native Client Security Contest
+Google Inc. 1600 Amphitheater Parkway Mountain View, CA 94043 USA
+
+What will Google do with my data?
+=================================
+
+The personal data you provided to Google during the Contest will be
+stored and processed in the US within the context of the Contest. We
+will maintain your data in the way described at the Google Privacy
+Policy found at http://www.google.com/privacypolicy.html. Google may
+use your data to verify your identity, postal address and telephone
+number in the event you qualify for a prize. You have a right to
+access and withdraw your personal data. To exercise this right, you
+may write to: Native Client Security Contest, Google Inc., 1600
+Amphitheater Parkway, Mountain View, CA 94043, USA.
+
+I have more questions---where can I get a response?
+===================================================
+
+We recommend to ask any additional questions you might have in the
+Google Group. Members from our team will be monitoring the group and
+will respond to your question there, to benefit other contest
+participants.
+
+I like this project. Are you hiring people to work on it full time?
+===================================================================
+
+At Google we are always looking for great people. Please review our
+current openings at www.google.com/jobs.
+
+How can I get involved in this project besides the contest?
+===========================================================
+
+Thank you for your interest in Native Client. You can help us by:
+
+* Identifying bugs
+* Porting OS libraries
+* Writing apps
+
+We would also like to see you participate in our discussion group.
+
+Why is my country/province excluded from the contest?
+=====================================================
+
+While we seek to make this contest open worldwide, we cannot open it
+to residents of Cuba, Iran, Syria, North Korea, Sudan, or Myanmar
+(Burma) because of U.S. laws. In addition, the contest is not open to
+residents of Brazil, Italy, or Quebec because of local
+restrictions. For more information on eligibility, see the :doc:`Terms
+and Conditions <contest-terms>`.
diff --git a/native_client_sdk/src/doc/community/security-contest/contest-terms.rst b/native_client_sdk/src/doc/community/security-contest/contest-terms.rst
new file mode 100644
index 0000000000..cc50381116
--- /dev/null
+++ b/native_client_sdk/src/doc/community/security-contest/contest-terms.rst
@@ -0,0 +1,986 @@
+.. _contest_terms:
+
+#####################################
+Security Contest Terms and Conditions
+#####################################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+.. include:: contest-warning.txt
+
+.. Note::
+ :class: warning
+
+ This has been reformatted from the original, and the enumeration
+ list numbering style differs from the original document.
+
+NO PURCHASE NECESSARY TO ENTER OR WIN. VOID WHERE PROHIBITED. CONTEST
+IS OPEN TO RESIDENTS OF THE 50 UNITED STATES, THE DISTRICT OF COLUMBIA
+AND WORLDWIDE, EXCEPT FOR ITALY, BRAZIL, QUEBEC, CUBA, IRAN, SYRIA,
+NORTH KOREA, SUDAN AND MYANMAR.
+
+ENTRY IN THIS CONTEST CONSTITUTES YOUR ACCEPTANCE OF THESE TERMS AND
+CONDITIONS.
+
+I. Binding Agreement
+
+ In order to enter the Native Client Security Contest ("Contest"),
+ you must agree to these Terms and Conditions ("Terms"). Therefore,
+ please read these Terms prior to entry to ensure you understand and
+ agree. You agree that submission of an entry in the Contest
+ constitutes your agreement to these Terms. After reading the Terms
+ and in order to participate, each Participant (as defined below)
+ must complete the registration form, clicking the "I understand and
+ agree" box (or the equivalent), on the Contest entry webpage. Once
+ the Participant clicks the "I understand and agree" box (or the
+ equivalent), the Terms form a binding legal agreement between each
+ Participant and Google with respect to the Contest.
+
+ Participants may not submit an Exploit, Issue or Summary to the
+ Contest and are not eligible to receive the prizes described in
+ these Terms unless they agree to these Terms. If a Participant is
+ part of a team, each member of the team must read and agree to
+ these Terms and click on the "I understand and agree" box (or the
+ equivalent) described herein. Failure of any member of a team to
+ agree to these Terms and click on the "I understand and agree" box
+ (or the equivalent) described herein will disqualify the entire
+ team.
+
+ By entering, Participant warrants that Participant has not violated
+ any employment agreement or other restriction imposed by his or her
+ employer by participating in this Contest.
+
+#. Description
+
+ The Contest is organized by Google and is designed to motivate the
+ developer community to identify and report security Exploits (as
+ defined below) on Google’s Native Client software and reward those
+ developers who identify one or more security Exploits that are
+ evaluated as a winning exploit by the Judges.
+
+ Once a Participant has registered for the Contest, the Participant
+ will be asked to identify security Exploits in Google’s Native
+ Client Software and enter those Exploits on Google’s `Native Client
+ Issue Tracker <http://code.google.com/p/nativeclient/issues/list>`_
+ web site using the "Security Contest Template." At this point, the
+ Exploit will become an Issue and will no longer be able to be
+ identified by another Participant. Google will then verify that the
+ Issue is reproducible. If so, that Issue will become a Verified
+ Issue. Finally, the Participant will submit a Summary of up to his
+ or her top ten best Issues that were submitted on the `Native
+ Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_. Since it is
+ possible that an Issue may not be verified until after the Contest
+ End Date, if a Participant includes such an Issue in their Summary
+ and such Issue is not ultimately verified, then that Issue will not
+ be considered to be part of the Summary.
+
+ Prizes will be awarded to those Participants who submit the best
+ Summaries as determined in the sole discretion of the Judges when
+ considering the Judging Criteria described herein.
+
+#. Sponsor
+
+ The Contest is sponsored by Google Inc. ("Google" or "Sponsor"), a
+ Delaware corporation with its principal place of business at 1600
+ Amphitheater Parkway, Mountain View, CA, 94043, USA.
+
+#. Term
+
+ The Contest begins at 9:00:00 A.M. Pacific Time (PT) Zone in the
+ United States on Februrary 25th, 2009 ("Contest Start Date") and
+ ends at 11:59:59 P.M. PT on May 5th, 2009 ("Contest End
+ Date"). Participants must register by May 5th, 2009 at 11:59:59
+ Pacific Time to be eligible to participate. ENTRANTS ARE
+ RESPONSIBLE FOR DETERMINING THE CORRESPONDING TIME ZONE IN THEIR
+ RESPECTIVE JURISDICTIONS.
+
+#. Definitions
+
+ Throughout these Terms, Google will use the following defined terms
+ and words. Please review them carefully to ensure you understand.
+
+ 1. Covert Channel Attack: A "Covert Channel Attack" means an
+ attempt to manipulate certain properties of a communications
+ medium in an unexpected, unconventional, or unforeseen way in
+ order to transmit information through the medium without
+ detection by anyone other than the entities operating the covert
+ channel. Exploits that are Covert Channel Attacks are excluded
+ from the Contest.
+
+ #. Exploit: An "Exploit" means a sequence of steps that require and
+ use Native Client to produce or have the potential to produce
+ behavior prohibited by Native Client's security policies and
+ design which can be found at
+ http://src.chromium.org/viewvc/native_client/trunk/src/native_client/README.html.
+ Google reserves the right to modify the security policies and
+ design at any time. An example of an Exploit would be producing
+ file system or network access outside of the scope of
+ permissible use via JavaScript in a browser. An Exploit that
+ defeats one but not all Native Client security measures is still
+ considered to produce behavior prohibited by Native Client's
+ security policies for the purposes of this Contest and would be
+ entitled to be identified as an Exploit in the Contest.
+
+ #. Inner Sandbox: The "Inner Sandbox" means the Native Client
+ security system that a) inspects executables before running them
+ to try to detect the potential for an executable to produce
+ prohibited behavior, and b) prevents from running any
+ executables that are detected to have the potential to produce
+ prohibited behavior.
+
+ #. Issue: An "Issue" means an entry of a single Exploit by a
+ Participant into the `Native Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_ using a
+ properly filled out Security Contest Template. Once the Exploit
+ has been properly entered it becomes an Issue.
+
+ #. Native Client Issue Tracker: The "Native Client Issue Tracker"
+ is located at
+ http://code.google.com/p/nativeclient/issues/list. It is a web
+ application that manages and maintains a list of Issues,
+ including Issues that are not eligible for contest entry.
+
+ #. Native Client Version Number: The "Native Client Version Number"
+ is defined as the number between the platform name (separated by
+ an '_') and the file extension (separated by a '.') in the
+ Native Client download. For example, if the the filename of the
+ download on the Native Client download page is
+ "nacl_linux_0.1_32_2009_01_16.tgz" or
+ "nacl_windows_0.1_32_2009_01_16.zip", the Version Number is
+ "0.1_32_2009_01_16".
+
+ #. Outer Sandbox: The "Outer Sandbox" means the Native Client
+ security system that 1) observes executables while they are
+ running to detect the attempts at prohibited behavior and 2)
+ terminates misbehaving executables if it observes any attempts
+ to produce prohibited behavior.
+
+ #. Participant: A "Participant" means any individual or team of
+ individuals that has agreed to these Terms, meets the
+ eligibility criteria described below, and is participating in
+ the Contest.
+
+ #. Side Channel Attack: A "Side Channel Attack" means any attack
+ based on information gained as a side-effect of the
+ implementation of a cryptosystem, rather than brute force or
+ theoretical weaknesses in the algorithms. For example, attacks
+ that use timing information, power consumption variation,
+ electromagnetic leaks or sound to obtain information illicitly
+ are side channel attacks. Exploits that are Side Channel Attacks
+ are excluded from the Contest.
+
+ #. Summary: A "Summary" means the final electronic document
+ complying with the requirements of Section X that each
+ Participant must submit in order to participate in the
+ Contest. A Summary may contain up to 10 Issues. If Issues do not
+ ultimately become Verified Issues, they will not be considered
+ as part of the Summary and Participant understands and accepts
+ the risk that if the Participant identified an Issue on a
+ Summary that had not yet been verified, that Issue will not be
+ considered as part of the Summary if not subsequently verified.
+
+ #. Verified Issue: A "Verified Issue" means an Exploit that has
+ been a) submitted to the `Native Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_ in
+ accordance with these Terms, and b) confirmed by the Native
+ Client team at Google to exhibit the behavior described in the
+ Issue report.
+
+#. Eligibility
+
+ The Contest is open to Participants who (1) have agreed to these
+ Terms; (2) who are of or above the legal age of majority, at the
+ time of entry, to form valid contracts in their respective country,
+ province or state of legal residence (and at least the age of 20 in
+ Taiwan); (3) are not residents of Italy, Brazil, Quebec, Cuba,
+ Iran, Syria, North Korea, Sudan, or Myanmar; and (4) who have
+ software development experience. Sponsor reserves the right to
+ verify eligibility and to adjudicate on any dispute at any
+ time. The Contest is void in, and not open to residents of, Italy,
+ Brazil, Quebec, Cuba, Iran, Syria, North Korea, Sudan, Myanmar, or
+ to individuals and entities restricted by U.S. export controls and
+ sanctions, and is void in any other nation, state, or province
+ where prohibited or restricted by U.S. or local law.
+
+ Employees and contractors of Google, affiliates and subsidiaries of
+ Google, the Judges and members of their immediate families (defined
+ as parents, children, siblings and spouse, regardless of where they
+ reside and/or those living in the same household of each) are not
+ eligible to participate in the Contest. Judges may not help any
+ Participant with their submissions and Judges must recuse
+ themselves in cases where they have a conflict of interest that
+ becomes known to the Judge.
+
+#. Registration & Entry Process
+
+ 1. All Participants must register at
+ code.google.com/contests/nativeclient-security/ by May 5th, 2009
+ at 11:59:59 Pacific Time. All individuals participating in the
+ Contest (either as an individual Participant or as a member of a
+ team) must provide the following registration information:
+
+ (a) Email Address(es) of the Participant. The first member of a
+ team to register must list the email addresses of all
+ members of the Participant team, and all members must
+ ultimately agree to the Terms as described more fully below.
+
+ (#) Nationality and primary place of residence of the Participant.
+
+ (#) If the Participant is a team, the email address of the team
+ member who is selected to be the recipient of the prize. The
+ first member of the team to register will designate this
+ information in the initial team registration.
+
+ (#) Participant name, which is the team name in the case of a
+ team or the user name chosen by an individual in the case of
+ an individual Participant.
+
+ Failure to fully, completely and accurately provide this
+ information will disqualify the Entry.
+
+ #. Any potential prize recipient may be required to show proof of
+ being the authorized account holder for an email address. The
+ "Authorized Account Holder" is the natural person assigned to an
+ email address by the relevant provider of email services.
+
+ #. Participants that are teams must provide the above registration
+ information for every individual who is a member of the
+ team. Every individual who is part of the team must agree to the
+ Terms in order for the team to be eligible to participate by
+ clicking the "I understand and agree" box (or the equivalent) on
+ the Contest entry webpage. Members of a team will be able to
+ edit the information relating to the team only until the last
+ member of the team has accepted these Terms by clicking the "I
+ understand and agree" box (or the equivalent) on the Contest
+ entry webpage. Issues submitted by members of a team prior to
+ the time that all individual members of the team have clicked
+ the "I understand and agree" box (or the equivalent) will not be
+ valid Issue submissions and will not be eligible entries in the
+ Contest. Google will send an email to all members of the team
+ when the final team member has accepted the terms, however
+ Google will have no liability for failure to send such an email
+ or for the failure of any team member to receive the email.
+
+ #. Issues submitted by Participants who are individuals prior to
+ the time that the individual has clicked the "I understand and
+ agree" box (or the equivalent) will not be valid Issue
+ submissions and will not be eligible entries in the
+ Contest. Google will send an email to the individual when the
+ individual has accepted the terms, however Google will have no
+ liability for failure to send such an email or for the failure
+ of any team member to receive the email.
+
+ #. All entries become the property of Sponsor and will not be
+ acknowledged or returned. Entries are void if they are in whole
+ or part illegible, incomplete, damaged, altered, counterfeit,
+ obtained through fraud, or late.
+
+ #. LIMIT ONE ENTRY PER PERSON. Individuals may only enter one time,
+ whether as an individual Participant or as a team
+ Participant. Google, in its sole discretion, may disqualify any
+ Participant (including team Participants) that it believes has
+ violated this provision.
+
+#. Submission Process
+
+ 1. Each Participant must submit:
+
+ (a) At least one Issue in the `Native Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_ that
+ describes an Exploit and includes the information detailed
+ in the "Issues" section below. Any team member can submit an
+ Issue on behalf of the team. All entries will be deemed made
+ by the Authorized Account Holder of the email address
+ submitted at the time of entry.
+
+ (#) One Summary per Participant that includes the information
+ detailed in the "Summary" section below. Participant will be
+ entitled to amend its Summary until the Contest End Date and
+ only the last version will be considered by the Judges.
+
+ #. Each Issue must be written in the English language. Google or
+ the Judges may refuse to review submissions that they deem
+ incomprehensible, include Issues that are not repeatable as
+ determined by Google, or that otherwise do not meet the
+ requirements of these Terms.
+
+ #. To enter an Issue in the `Native Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_, each
+ Participant must use the "Security Contest Template" and provide
+ completely and accurately all information requested by the
+ template. Any Issues that are not entered with the "Security
+ Contest Template" may not be considered by the Judges. Each
+ Issue must contain the items described in the "Issues" section
+ of these Terms.
+
+#. Issues
+
+ 1. Minimum requirements for Issues: Participant must identify an
+ Exploit and enter the Exploit into the `Native Client Issue
+ Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_. Once the
+ Exploit is submitted it becomes an Issue. Each submitted Issue
+ must include (i) the following information and (ii) all
+ additional information requested on the "Security Contest
+ Template":
+
+ (a) The user name (in the case of Individual Participants) or
+ the team name (in the case of team Participants) of the
+ Participant submitting the Issue, which must be identical to
+ the user name or team name submitted during the registration
+ process.
+
+ (#) A gzipped tar archive (with paths relative to
+ nacl/googleclient/native_client/tests/) that contains any
+ instructions and files necessary to reproduce the Exploit,
+ which must include:
+
+ (1) A README.txt file that describes:
+
+ * The version number of current version of Native Client
+ at the time of submission. Issues submitted with a
+ version number listed other than the current version
+ at the time of submission will be invalid;
+
+ * The steps required to reproduce the Exploit;
+
+ * The effect of the Exploit; and
+
+ * Platform requirements for the Exploit, including but
+ not necessarily limited to:
+
+ * browser version;
+
+ * operating system name(s) and version(s); and/or
+
+ * any other platform requirements relevant to the Exploit.
+
+ (#) If the Exploit requires a binary executable, both the
+ source code and binary executable must be provided upon
+ creation of the Issue. Any subsequent updates to the
+ source code or binary executable after the creation of
+ the Issue will not be considered for the purposes of
+ this Contest. The binary executable must build cleanly
+ by executing the command "make" in the exploit directory
+ (e.g. nacl/googleclient/native_client/tests/exploit1).
+
+ #. Verified Issues: In order for an Issue to become a Verified
+ Issue, Google will first examine the submitted Issue to
+ determine whether it complies with the following:
+
+ (a) The Exploit must not contain or depend upon access or use of
+ any third party software or code that Google does not have
+ readily available to it or that would require complying with
+ third party license agreement that Google in its sole
+ discretion deems onerous or burdensome.
+
+ (#) Google must be able to replicate the Exploit in its sole
+ discretion.
+
+ (#) The Exploit must affect at least one "opt-" platform from a
+ standard build of the most recent released version of Native
+ Client as of the time of submission of the Issue for the
+ Exploit.
+
+ #. Timeliness
+
+ (a) If the vulnerability exposed by the submitted Exploit was
+ disclosed in a previously reported Issue (whether or not
+ submitted by a Participant) or in the previously published
+ Native Client release notes, the submission will be invalid
+ for the purposes of this Contest. Two Exploits are
+ considered to expose the same vulnerability if the
+ theoretical patch required to fix one vulnerability also
+ fixes the second vulnerability.
+
+ (#) Google will update the Native Client source code base at
+ most twice per week. These updates, if they occur, will
+ appear Mondays and Thursdays between 3 p.m. and 8
+ p.m. Pacific Time.
+
+ (#) Issues will not be valid if they have been entered before
+ the later of (i) the Contest Start Date or (ii) the time at
+ which all members of a team Participant or the individual
+ Participant, as the case may be, have accepted these Terms.
+
+ #. Excluded Exploits. The following types of Exploits are invalid
+ for the purposes of this Contest:
+
+ * Covert Channel Attacks;
+
+ * Sidechannel Attacks;
+
+ * Exploits requiring a virtualized CPU;
+
+ * Exploits that rely on features, misfeatures or defects of
+ virtual machines (i.e. VMWare, Xen, Parallels etc.);
+
+ * Exploits that require the machine to be previously compromised
+ by malicious software (including but not limited to viruses or
+ malware); and
+
+ * Exploits that rely on hardware failures, other than Exploits
+ which, in Google’s sole judgment, depend on CPU errata but
+ which can be reproduced reliably with a common system
+ configuration and under normal operating conditions, or
+ statistically improbable hardware behaviors. Examples include
+ but are not limited to Exploits that rely on memory errors
+ induced by cosmic radiation, and Exploits that require
+ abnormal heating, cooling or other abnormal physical
+ conditions.
+
+ #. Completeness. Issues submitted that lack any of the above
+ materials or fail to meet any of the above criteria, may not be
+ considered in the judging process at Google's sole
+ discretion. Issues that are not included in a Participant
+ Summary (see section below) will not be considered.
+
+#. Summary
+
+ 1. Every Participant must submit a Summary at the `Native Client
+ Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_ complying
+ with the requirements of this section. The Participant must
+ select no more than 10 of the Verified Issues submitted by the
+ Participant for inclusion on the Summary. Each Summary must be
+ in English and must contain the following information:
+
+ * The Issues must be listed in descending order of severity, as
+ determined by the Participant in accordance with the Judging
+ Criteria.
+
+ * Each Issue listed in the Summary must be identified by ID
+ number of the Issue. The ID number is the identifying number
+ created for each Issue as listed on the `Native Client Issue
+ Tracker <http://code.google.com/p/nativeclient/issues/list>`_.
+
+ * A description of the effect of each Exploit.
+
+ * The platform requirements of each Exploit.
+
+ * The version number(s) of Native Client software affected by
+ each Exploit (which must be the version number of the Native
+ Client software current at the time the Issue was submitted to
+ the `Native Client Issue Tracker
+ <http://code.google.com/p/nativeclient/issues/list>`_).
+
+ * Any other details about the Exploit and the submission that
+ are relevant to the judging criteria, such as, for example,
+ the approach used in finding the exploits, innovative or
+ scalable techniques used to discover exploits, or
+ architectural analysis.
+
+ * The team name or user name of the Participant. Google may, in
+ its sole discretion, eliminate or disqualify any Summary that
+ lists user names or team names that are not identical to the
+ user name or team name of the Participant listed on the
+ Contest entry form.
+
+ #. Each Summary must be a maximum of 8 pages long, in PDF format
+ viewable with Adobe Reader version 9. The Summary must be
+ formatted for 8.5 inches x11 inches or A4 paper, with a minimum
+ font size of 10 pt. Any submission that does not meet these
+ formatting criteria may be disqualified at the sole discretion
+ of Google.
+
+ #. All Issues listed in the Summary will be verified by Google
+ before submission of the Summary to the Judges after the Contest
+ Closing Date. Participants may submit or resubmit their Summary
+ at any time during the duration of the Contest, however, the
+ Judges will consider only the last Summary from each Participant
+ prior to the Contest Closing Date and ignore all other Summaries
+ previously submitted by the Participant.
+
+#. Judging
+
+ 1. After the Contest End Date and on or about May 15th, 2009, all
+ submitted Summaries will be judged by one of at least three
+ panels with a minimum of three experts in the field of online
+ security ("Judges") on each panel. Judges will evaluate each
+ Summary in accordance with the Judging Criteria described
+ below. Each panel will evaluate a number of the submitted
+ Summaries using the Judging Criteria described below and will
+ select the highest ranking Summaries to move to the next level
+ of judging. During the first round of judging, each panel will
+ select no more than ten Summaries to move forward to the second
+ round of judging unless there is a tie between or among any
+ Participants. During the second round of judging, those
+ Summaries selected during the first round of judging will then
+ be evaluated by all Judges using the below Judging Criteria and
+ the top five Summaries will be selected as potential
+ winners. All decisions of the Judges are final and binding.
+
+ #. Judging Criteria. The Judges will consider each Summary under
+ following judging criteria ("Judging Criteria"):
+
+ (a) Quality of Exploit. Quality will be decided by the Judges in
+ their sole discretion and will be based on (in order of
+ importance to the Judges) Severity, Scope, Reliability and
+ Style.
+
+ (i) Severity: the more disruptive the effects of the
+ Exploit, the higher its quality. Here is a
+ non-exhaustive ranking of the most common Exploits
+ starting from 'minor' to 'severe':
+
+ * Browser crash;
+
+ * Denial of service or machine crash;
+
+ * Compromise of the Outer Sandbox;
+
+ * Information leak (such as of a cookie or password);
+
+ * Compromise of both the Inner and Outer Sandbox; and/or
+
+ * Prohibited side effect (such as reading or writing
+ files to the client machine), escalation of privilege
+ (such as executing other programs outside of Native
+ Client).
+
+ Any Exploit that does not address the above elements
+ will be evaluated on a case-by-case basis and the
+ severity of such Exploits will be determined solely at
+ the Judge’s discretion.
+
+ (#) Scope: the more computers that an Exploit would
+ potentially affect, the bigger its scope and therefore
+ higher the quality of the Exploit. Consider the
+ following:
+
+ * Exploits that affect all platforms supported by Native
+ Client (where platform is defined as a browser,
+ operating system and hardware combination) have higher
+ quality than an Exploit specific to a particular
+ platform.
+
+ * Exploits that require non-current or beta versions
+ (historic or future) of hardware or software are lower
+ quality.
+
+ * Exploits that rely on concurrent usage of other
+ installed software or web content must make a
+ compelling case about the likelihood of the
+ prerequisite software or content being present, or
+ they will be considered of lower quality.
+
+ (#) Reliability: The more frequent or probable the
+ occurrence identified by the Exploit, the more
+ "reliable" it may be. Consider the following:
+
+ * Exploits that require uncommon software to be
+ installed on the machine in order to function will be
+ deemed to have lower quality.
+
+ * Entries that include Exploits that cannot be
+ reproduced 100% of the time, but which can be
+ reproduced a significant percentage of the time, will
+ be deemed to have a lower quality to account for a
+ lowered probability that the attack will succeed.
+
+ (#) Style: Submissions that demonstrate exceptional style
+ will receive a higher ranking. Factors that contribute
+ to style include:
+
+ * Ingenuity in mechanism used to bypass security;
+
+ * Uniqueness of the Exploit;
+
+ * Ingenuity in methods used to discover vulnerabilities;
+ and/or Minimal size of Exploit to achieve the effect.
+
+ (#) the Quantity of Exploits: Participants that submit more
+ Exploits in their Summary (but no more than 10) may receive
+ a higher ranking, weighted by quality. However, it is still
+ possible that a Participant who submits one Exploit could
+ still outweigh a Participant that submits several Exploits.
+
+ Considering each of the factors described above, the Judges will
+ give each Summary a "Score" from 1-10 that represents the Judges
+ evaluation of the Summary. This "score" will determine which
+ participants move from the first round of judging to the second
+ round of judging, and which participants will be selected as a
+ winner.
+
+ #. Winner Selection
+
+ Judges will review the Summaries as discussed in the "Judging"
+ section, above. The Summaries with the five (5) highest scores
+ will be selected as potentially winning Participants. In the
+ event of a tie ranking for two or more Summaries, the
+ Participant whose Summary had the highest ranking for "Severity"
+ will receive the higher prize. In the event of a second tie, the
+ Participant whose Summary had the highest ranking for "Scope"
+ will receive the higher prize. Odds of winning depend on the
+ number of eligible entries received and the skill of the
+ Participants.
+
+ The Judges are under no obligation to provide feedback on their
+ decisions or on their judgment on specific Exploits they
+ consider.
+
+ #. Team Winners
+
+ A special note about the prize distribution process for
+ Participants who are entering as part of a team:
+
+ A single member of each team shall be designated to receive the
+ prize, if any, awarded to such team at the initial registration
+ of the team, and Google shall have no responsibility for
+ distribution of the prize among the team members.
+
+ Each individual that enters as part of a team, understands and
+ agrees that if his/her team is selected to receive a prize, the
+ team is responsible for ensuring the funds are appropriately
+ distributed to each member of the team. In addition, once a team
+ has registered, the team may not add, remove, or substitute any
+ members or otherwise change the composition of the team for the
+ duration of the Contest. If any member of a team does not comply
+ with these Terms, is ineligible or is disqualified, the team as
+ a whole may be disqualified in Google’s sole discretion.
+
+#. Prizes
+
+ 1. Information Required for Eligibility
+
+ (a) On or about May 15th 2009 and upon selection of potential
+ winners, Google will contact all winning Participants using
+ the email addresses submitted at registration. In order to
+ win the Contest and receive prizes, Participants, including
+ each individual on a team, must provide additional
+ information including:
+
+ * first and last name;
+
+ * address;
+
+ * phone number; and
+
+ * all other necessary information required by the US tax and
+ legal authorities and /or the authorities of the countries
+ they reside in.
+
+ (#) All Participants will need to verify their identity with
+ Google, before receiving their prize; however, Participants
+ may provide an alias for use in any public documentation and
+ marketing material issued publicly by Google, subject to
+ limitations of the law and as required by law
+ enforcement. Please be aware that in some jurisdictions, a
+ list of winners must be made available and your name, and
+ not the alias, will be provided on that list. If a
+ Participant, or in the case of a team, any individual member
+ of the team, refuses or fails to provide the necessary
+ information to Google within 14 days of the Contest
+ administrators' request for the required information, then
+ Google may, in its sole discretion, disqualify the
+ Participant's entry and select as an alternative potential
+ winner the Participant with the next highest overall
+ ranking. Google will not be held responsible for any failure
+ of potential winners to receive notification that they are
+ potential winners. Except where prohibited by law, each
+ potential winner may be required to sign and return a
+ Declaration of Eligibility, Liability & Publicity Release
+ and Release of Rights and provide any additional information
+ that may be required by Google. If required, potential
+ winners must return all such required documents within 14
+ calendar days following attempted notification or such
+ potential winner will be deemed to have forfeited the prize
+ and Google will select the Participant with the next highest
+ overall ranking as the potential winner.
+
+ (#) Prizes will be awarded within 6 months after the Contest End Date.
+
+ (#) If fewer than 5 Participants or teams are found eligible,
+ fewer than 5 winners will be selected.
+
+ (#) Prizes are not transferable or substitutable, except by
+ Google in its sole discretion in the event a prize becomes
+ unavailable for any reason. In such an instance, Google will
+ award a prize of equal or greater value.
+
+ (#) LIMIT: Only one prize per Participant.
+
+ #. Prize Amounts and Announcement
+
+ Provided that the Participant has complied with these Terms,
+ eligible Participants that are ranked in the top 5 positions of
+ the competition by Judges will receive the following awards in
+ U.S. Dollars based on their rank: 1st prize: $8,192.00, 2nd
+ prize: $4,096.00, 3rd prize: $2,048.00, 4th prize: $1,024.00,
+ 5th prize: $1,024.00. Winning Entries will be announced on or
+ about December 7th.
+
+ #. Distribution of a Prize
+
+ Google is not responsible for any division or distribution of
+ the prizes among or between team members. Distribution or
+ division of the prize among individual team members is the sole
+ responsibility of the participating team. Google will award the
+ prize only to the one (1) member of the team, who was identified
+ by the Participant to receive the prize as part of the
+ registration process. Google will attempt to reach only the
+ designated recipient for purposes of distribution of the prize.
+
+ Prizes are awarded without warranty of any kind from Google,
+ express or implied, without limitation, except where this would
+ be contrary to federal, state, provincial, or local laws or
+ regulations. All federal, state, provincial and local laws and
+ regulations apply.
+
+ #. Taxes
+
+ Payments to potential prize winners are subject to the express
+ requirement that they submit to Google all documentation
+ requested by Google to permit it to comply with all applicable
+ US, state, local and foreign (including provincial) tax
+ reporting and withholding requirements. All prizes will be net
+ of any taxes Google is required by law to withhold. All taxes
+ imposed on the prize are the sole responsibility of the prize
+ recipient.
+
+ In order to receive a prize, potential prize recipients must
+ submit the tax documentation requested by Google or otherwise
+ required by applicable law, to Google or the relevant tax
+ authority, all as determined by applicable law, including, where
+ relevant, the law of the potential prize recipient's country of
+ residence. The potential prize recipient is responsible for
+ ensuring that (s)he complies with all the applicable tax laws
+ and filing requirements. If a potential prize recipient fails to
+ provide such documentation or comply with such laws, the prize
+ may be forfeited and Google may, in its sole discretion, select
+ an alternative potential prize recipient.
+
+#. General Conditions
+
+ 1. Right to Disqualify. A Participant may be prohibited from
+ participating in or be disqualified from this Contest if, in
+ Google's sole discretion, it reasonably believes that the
+ Participant or any member of a Participant team has attempted to
+ undermine the legitimate operation of the Contest by cheating,
+ deception, or other unfair playing practices or annoys, abuses,
+ threatens or harasses any other Participants, Google, or the
+ Judges. Google further reserves the right to disqualify any
+ Issue that it believes in its sole and unfettered discretion
+ infringes upon or violates the rights of any third party,
+ otherwise does not comply with these Terms, or violates U.S. or
+ applicable local law in Participant's country of residence.
+
+ Google further reserves the right to disqualify any Participant
+ who tampers with the submission process or any other part of the
+ Contest. Any attempt by a Participant to deliberately damage any
+ web site or undermine the legitimate operation of the Contest is
+ a violation of criminal and civil laws and should such an
+ attempt be made, Google reserves the right to seek damages from
+ any such Participant to the fullest extent of the applicable
+ law.
+
+ #. Internet Disclaimer. Google is not responsible for any
+ malfunction of the entire Contest, the web site displaying the
+ Contest terms and entry information, or any late, lost, damaged,
+ misdirected, incomplete, illegible, undeliverable, or destroyed
+ Exploits, Issues or Summaries due to system errors, failed,
+ incomplete or garbled computer or other telecommunication
+ transmission malfunctions, hardware or software failures of any
+ kind, lost or unavailable network connections, typographical or
+ system/human errors and failures, technical malfunction(s) of
+ any telephone network or lines, cable connections, satellite
+ transmissions, servers or providers, or computer equipment,
+ traffic congestion on the Internet or at the web site displaying
+ the Contest or any combination thereof, including other
+ telecommunication, cable, digital or satellite malfunctions
+ which may limit an entrant’s ability to participate. Google is
+ not responsible for availability of the `Native Client Issue
+ Tracker <http://code.google.com/p/nativeclient/issues/list>`_
+ from your preferred point of Internet access. In the event of a
+ technical disruption, Google may, in its sole discretion, extend
+ the Contest End Date for a reasonable period. Google will
+ attempt to notify Participants of any such extension by email at
+ the email address in the registration information, but shall
+ have no liability for any failure of such notification.
+
+ #. Exploits Independently Discovered by Google. You acknowledge and
+ understand that Google may discover Exploits independently that
+ may be similar to or identical to your Issues in terms of
+ function, vulnerability, or in other respects. You agree that
+ you will not be entitled to any rights in, or compensation in
+ connection with, any such similar or identical applications
+ and/or ideas. You acknowledge that you have submitted your entry
+ voluntarily and not in confidence or in trust.
+
+ #. No Contract for Employment. You acknowledge that no
+ confidential, fiduciary, agency or other relationship or
+ implied-in-fact contract now exists between you and Google and
+ that no such relationship is established by your submission of
+ an entry to Google in this Contest. Under no circumstances shall
+ the submission of an entry in the Contest, the awarding of a
+ prize, or anything in these Terms be construed as an offer or
+ contract of employment with Google.
+
+ #. Intellectual Property Rights and License. Participants warrant
+ that their Exploit and Summary are their own original work and,
+ as such, they are the sole and exclusive owner and rights holder
+ of the submitted Exploit and Summary and that they have the
+ right to submit the Exploit and Summary in the Contest and grant
+ all required licenses. Each Participant agrees not to submit any
+ Exploit and Summary that (a) infringes any third party
+ proprietary rights, intellectual property rights, industrial
+ property rights, personal or moral rights or any other rights,
+ including without limitation, copyright, trademark, patent,
+ trade secret, privacy, publicity or confidentiality obligations;
+ or (b) otherwise violates the applicable state, federal,
+ provincial or local law.
+
+ As between Google and the Participant, the Participant retains
+ ownership of all intellectual and industrial property rights in
+ and to the Issues and Summary that Participant created. As a
+ condition of entry, Participant grants Google a perpetual,
+ irrevocable, worldwide, royalty-free, and non-exclusive license
+ to use, reproduce, publicly perform, publicly display,
+ distribute, sublicense and create a derivative work from, any
+ Issue or Summary that Participant submits to this Contest for
+ the purposes of allowing Google to test, evaluate and fix or
+ remedy the Issue and Summary for purposes of the Contest and
+ modifying or improving the Native Client software or any other
+ current or future Google product or service.
+
+ Participant also grants Google the right to reproduce and
+ distribute the Issue and the Summary. In addition, Participant
+ specifically agrees that Google shall have the right to use,
+ reproduce, publicly perform, and publicly display the Issue and
+ Summary in connection with the advertising and promotion of the
+ Native Client software or any other current or future Google
+ product or service via communication to the public or other
+ groups, including, but not limited to, the right to make
+ screenshots, animations and video clips available for
+ promotional purposes.
+
+ #. Privacy. Participants agree that personal data provided to
+ Google during the Contest, including name, mailing address,
+ phone number, and email address may be processed, stored, and
+ otherwise used for the purposes and within the context of the
+ Contest. This data will be maintained in accordance with the
+ Google Privacy Policy found at
+ http://www.google.com/privacypolicy.html. This data will also be
+ transferred into the United States. By entering, Participants
+ agree to the transmission, processing, and storage of this
+ personal data in the United States.
+
+ Participants also understand this data may be used by Google in
+ order to verify a Participant's identity, postal address and
+ telephone number in the event a Participant qualifies for a
+ prize. Participants have the right to access, review, rectify or
+ cancel any personal data held by Google in connection with the
+ Contest by writing to Google at the address listed below in the
+ section entitled "Winner’s List."
+
+ For residents of the European Union:
+
+ Pursuant to EU law pertaining to data collection and processing,
+ you are informed that:
+
+ * The data controller is Google and the data recipients are
+ Google and its agents;
+
+ * Your data is collected for purposes of administration of the
+ Native Client Security Contest;
+
+ * You have a right of access to and withdrawal of your personal
+ data. You also have a right of opposition to the data
+ collection, under certain circumstances. To exercise such
+ right, You may write to: Native Client Security Contest,
+ Google Inc., 1600 Amphitheater Parkway, Mountain View, CA
+ 94043, USA.
+
+ * Your personal data will be transferred to the U.S.
+
+ #. Indemnity. To the maximum extent permitted by law, each
+ Participant indemnifies and agrees to keep indemnified Google
+ and Judges at all times from and against any liability, claims,
+ demands, losses, damages, costs and expenses resulting from any
+ act, default or omission of the Participant and/or a breach of
+ any warranty set forth herein. To the maximum extent permitted
+ by law, each Participant agrees to defend, indemnify and hold
+ harmless Google, its affiliates and their respective directors,
+ officers, employees and agents from and against any and all
+ claims, actions, suits or proceedings, as well as any and all
+ losses, liabilities, damages, costs and expenses (including
+ reasonable attorneys fees) arising out of or accruing from:
+
+ (a) any material uploaded or otherwise provided by the
+ Participant that infringes any copyright, trademark, trade
+ secret, trade dress, patent or other intellectual property
+ right of any person or defames any person or violates their
+ rights of publicity or privacy,
+
+ (b) any misrepresentation made by the Participant in connection
+ with the Contest;
+
+ (c) any non-compliance by the Participant with these Terms; and
+
+ (d) claims brought by persons or entities other than the parties
+ to these Terms arising from or related to the Participant's
+ involvement with the Contest.
+
+ To the extent permitted by law, Participant agrees to hold
+ Google, its respective directors, officers, employees and
+ assigns harmless for any injury or damage caused or claimed to
+ be caused by participation in the Contest and/or use or
+ acceptance of any prize, except to the extent that any death or
+ personal injury is caused by the negligence of Google.
+
+ #. Elimination. Any false information provided within the context
+ of the Contest by any Participant including information
+ concerning identity, mailing address, telephone number, email
+ address, or ownership of right, or non-compliance with these
+ Terms or the like may result in the immediate elimination of the
+ Participant from the Contest. In the event an individual who is
+ a member of a team supplies information that is covered by this
+ section, the entire team shall be disqualified.
+
+ #. Right to Cancel. If for any reason the Contest is not capable of
+ running as planned, including infection by computer virus, bugs,
+ tampering, unauthorized intervention, fraud, technical failures,
+ or any other causes which corrupt or affect the administration,
+ security, fairness, integrity, or proper conduct of the Contest,
+ Google reserves the right at its sole discretion to cancel,
+ terminate, modify or suspend the Contest.
+
+ #. Forum and Recourse to Judicial Procedures. These Terms shall be
+ governed by, subject to, and construed in accordance with the
+ laws of the State of California, United States of America,
+ excluding all conflict of law rules. If any provision(s) of
+ these Terms are held to be invalid or unenforceable, all
+ remaining provisions hereof will remain in full force and
+ effect. To the extent permitted by law, the rights to litigate,
+ seek injunctive relief or make any other recourse to judicial or
+ any other procedure in case of disputes or claims resulting from
+ or in connection with this Contest are hereby excluded, and all
+ Participants expressly waive any and all such rights.
+
+ #. Arbitration. By entering the Contest, you agree that exclusive
+ jurisdiction for any dispute, claim, or demand related in any
+ way to the Contest will be decided by binding arbitration. All
+ disputes between you and Google, of whatsoever kind or nature
+ arising out of these Terms, shall be submitted to Judicial
+ Arbitration and Mediation Services, Inc. ("JAMS") for binding
+ arbitration under its rules then in effect in the San Jose,
+ California, USA area, before one arbitrator to be mutually
+ agreed upon by both parties. The parties agree to share equally
+ in the arbitration costs incurred.
+
+ #. Winner List
+
+ You may request a list of winners after December 7th, 2009 by
+ writing to:
+
+ | Native Client Security Contest
+ | Google Inc.
+ | 1600 Amphitheater Parkway
+ | Mountain View, CA 94043
+ | USA
+
+ (Residents of Vermont need not supply postage).
diff --git a/native_client_sdk/src/doc/community/security-contest/contest-warning.txt b/native_client_sdk/src/doc/community/security-contest/contest-warning.txt
new file mode 100644
index 0000000000..2023513e55
--- /dev/null
+++ b/native_client_sdk/src/doc/community/security-contest/contest-warning.txt
@@ -0,0 +1,10 @@
+
+.. Note::
+ :class: caution
+
+ The Native Client Security Contest has ended---check out the
+ :ref:`winning submissions<contest_winners>`. We welcome your
+ continued involvement in the project. You can help by submitting
+ `bugs <http://code.google.com/p/nativeclient/issues/list>`_ and
+ participating in the `Native Client discussion group
+ <http://groups.google.com/group/native-client-discuss>`_.
diff --git a/native_client_sdk/src/doc/community/security-contest/index.rst b/native_client_sdk/src/doc/community/security-contest/index.rst
new file mode 100644
index 0000000000..a26db993d6
--- /dev/null
+++ b/native_client_sdk/src/doc/community/security-contest/index.rst
@@ -0,0 +1,222 @@
+.. _contest_archive:
+
+########################
+Security Contest Archive
+########################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+The Native Client team at Google has gone to exceptional measures to
+make Native Client a secure system, including holding a public
+security contest. This page archives information from that contest,
+including the list of contest winners and the lineup of security
+experts who served as judges.
+
+Although the security contest has ended, the Native Client team
+welcomes your continued involvement in the project. You can help by
+submitting bugs and participating in the Native Client discussion
+group.
+
+Contest overview
+================
+
+The Native Client team held a contest in 2009 to test the security of
+Native Client and help make the system more secure. Participants were
+invited to discover security bugs in Native Client technology in order
+to compete for cash prizes.
+
+Here was the challenge put forth by the Native Client team:
+
+ Do you think it is impossible to safely run untrusted x86 code on
+ the web? Do you want a chance to impress a panel of some of the top
+ security experts in the world? Then submit an exploit to the Native
+ Client Security contest and you could also win cash prizes, not to
+ mention bragging rights.
+
+The contest judges evaluated exploits designed to defeat Native Client
+security measures based on severity, scope, reliability, and
+style. The winning teams and entries are listed below.
+
+.. _contest_winners:
+
+Contest winners
+===============
+
+The Native Client team thanks everyone who participated in the contest
+for their contributions to improving the quality and security of the
+Native Client system. The judges reviewed the submitted exploits and
+identified the following teams as winners:
+
+.. list-table::
+
+ * - .. image:: /images/medal-64_1st.png
+ :alt: First place medal
+
+ - **Team**: Beached As
+
+ **Members**: Mark Dowd, Ben Hawkes
+
+ **Submitted issues**: 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 62, 63
+
+ Mark Dowd and Ben Hawkes are application security specialists
+ hailing from Australia and New Zealand, respectively. Mark
+ works for IBM ISS X-Force R&D, whereas Ben currently performs
+ independent research while simultaneously pursuing a
+ mathematics and computing science degree. Both have uncovered
+ major security flaws in ubiquitous Internet software, in terms
+ of both exploitable bugs and weaknesses in system protection
+ mechanisms. Both have spoken at numerous security conferences
+ in recent years, including BlackHat, Ruxcon, KiwiCon, and
+ Cansec West.
+
+ * - .. image:: /images/medal-64_2nd.png
+ :alt: Second place medal
+
+ - **Team**: CJETM
+
+ **Members**: Jason Carpenter, Eric Monti, Chris Rohlf
+
+ **Submitted issues**: 42, 44, 49, 70
+
+ Team CJETM is comprised of security vulnerability researchers
+ Chris Rohlf, Jason Carpenter and Eric Monti. All three have
+ abused software professionally for a long time.
+
+ * - .. image:: /images/medal-64_3rd.png
+ :alt: Third place medal
+
+ - **Team**: 0xdead
+
+ **Members**: Gabriel Campana
+
+ **Submitted issues**: 45
+
+ Gabriel Campana is a security researcher working at Sogeti ESEC
+ R&D labs. His research interests are mainly focused on
+ vulnerability research, exploitation methods, and Linux kernel
+ security. Lately he has been working on automated vulnerability
+ research, especially fuzzing. In his spare time, he plays with
+ embedded network devices.
+
+ * - .. image:: /images/medal-64_4th.png
+ :alt: Fourth place medal
+
+ (tie)
+
+ - **Team**: teamfkmr
+
+ **Members**: Daiki Fukumori
+
+ **Submitted issues**: 66, 67
+
+ Daiki Fukumori is a web security researcher. He has given talks
+ at POC Korea and AVTokyo on Web 2.0 Hacking, and he introduced
+ Native Client security at Shibuya.pm. He currently has an
+ interest in cloud security.
+
+ * - .. image:: /images/medal-64_4th.png
+ :alt: Fourth place medal
+
+ (tie)
+
+ - **Team**: Alex Rad
+
+ **Members**: Alex Radocea
+
+ **Submitted issues**: 81
+
+ Alex Radocea is a 20-year old student at Rensselaer Polytechnic
+ Institute. In the realm of computer security he is really
+ excited about proactively designed technology which can help
+ wipe out entire bug classes. Currently he is helping improve
+ Native Client through Google Summer of Code.
+
+.. _contest_judges:
+
+Panel of judges
+===============
+
+Google recruited the following group of distinguished security experts
+to serve as judges for the Native Client security contest:
+
+Chair
+-----
+
++----------------------------------------+
+| Edward Felten |
++----------------------------------------+
+| Princeton University |
++----------------------------------------+
+| http://www.cs.princeton.edu/~felten/ |
++----------------------------------------+
+
+Judges
+------
+
+.. list-table::
+
+ * - Alex Halderman
+ - Niels Provos
+ - Bennet Yee
+
+ * - University of Michigan
+ - Google
+ - Google
+
+ * - http://www.cse.umich.edu/~jhalderm/
+ - http://www.citi.umich.edu/u/provos/
+ - http://www.bennetyee.org/
+
+ * - Brad Karp
+ - Stefan Savage
+ - Nickolai Zeldovich
+
+ * - University of College London
+ - University of California San Diego
+ - MIT
+
+ * - http://www.cs.ucl.ac.uk/staff/B.Karp/
+ - http://www.cs.ucsd.edu/~savage
+ - http://people.csail.mit.edu/nickolai/
+
+ * - Greg Morrisett
+ - Dan Wallach
+ - .. raw:: html
+
+ &nbsp;
+
+ * - Harvard University
+ - Rice University
+ - .. raw:: html
+
+ &nbsp;
+
+ * - http://www.eecs.harvard.edu/~greg/
+ - http://www.cs.rice.edu/~dwallach/
+ - .. raw:: html
+
+ &nbsp;
+
+
+Additional information
+======================
+
+For additional information about the Native Client security contest,
+see the archived
+:doc:`Contest Announcement <contest-announcement>`,
+:doc:`FAQ <contest-faq>` and
+:doc:`Terms & Conditions <contest-terms>`.
+
+If you'd like to get involved with Native Client, you can:
+
+* Use the
+ `Native Client SDK <https://developers.google.com/native-client/sdk>`_
+ to build Native Client web applications.
+* Submit `bugs <http://code.google.com/p/nativeclient/issues/list>`_
+ and participate in the Native Client
+ `discussion group <http://groups.google.com/group/native-client-discuss>`_.
+* Contribute to the
+ `Native Client open-source project <http://code.google.com/p/nativeclient/>`_.
diff --git a/native_client_sdk/src/doc/conf.py b/native_client_sdk/src/doc/conf.py
index 7182b7fe7f..d21fc7ea67 100644
--- a/native_client_sdk/src/doc/conf.py
+++ b/native_client_sdk/src/doc/conf.py
@@ -165,4 +165,19 @@ html_use_smartypants = True
# Output file base name for HTML help builder.
htmlhelp_basename = 'NativeClientdoc'
+linkcheck_ignore = [
+ # General links not worth checking
+ r'http://localhost.*',
+ r'about:.*',
+ r'chrome:.*',
+ r'.*local_extensions\.css',
+
+ #
+ # Specific known bad cases go here.
+ #
+
+ # linkcheck's anchor checker can't check these because they are
+ # server-generated and don't actually appear in the HTML of the page.
+ r'https://code.google.com.*browse#svn.*',
+ ]
diff --git a/native_client_sdk/src/doc/devguide/_toc.yaml b/native_client_sdk/src/doc/devguide/_toc.yaml
new file mode 100644
index 0000000000..87b98ffb96
--- /dev/null
+++ b/native_client_sdk/src/doc/devguide/_toc.yaml
@@ -0,0 +1,10 @@
+toc:
+- title: "Developer's Guide"
+ path: /native-client/${folder}/devguide
+ section:
+ - title: "Getting Started Tutorial"
+ path: /native-client/${folder}/devguide/tutorial
+ - include: /native-client/${folder}/devguide/devcycle/_toc.yaml
+ - include: /native-client/${folder}/devguide/coding/_toc.yaml
+ - title: "Distributing Your Application"
+ path: /native-client/${folder}/devguide/distributing
diff --git a/native_client_sdk/src/doc/devguide/coding/FileIO.rst b/native_client_sdk/src/doc/devguide/coding/FileIO.rst
index 347a89f12f..ed0867e987 100644
--- a/native_client_sdk/src/doc/devguide/coding/FileIO.rst
+++ b/native_client_sdk/src/doc/devguide/coding/FileIO.rst
@@ -6,3 +6,4 @@ File I/O
foo
+.. _enabling_file_access:
diff --git a/native_client_sdk/src/doc/devguide/coding/_toc.yaml b/native_client_sdk/src/doc/devguide/coding/_toc.yaml
new file mode 100644
index 0000000000..7c35926fba
--- /dev/null
+++ b/native_client_sdk/src/doc/devguide/coding/_toc.yaml
@@ -0,0 +1,24 @@
+toc:
+ - title: "Coding Your Application"
+ path: /native-client/dev/devguide/coding
+ section:
+ - title: "Application Structure"
+ path: /native-client/dev/devguide/coding/application-structure
+ - title: "Native Client Modules"
+ path: /native-client/dev/devguide/coding/nacl-modules
+ - title: "Memory Management"
+ path: /native-client/dev/devguide/coding/memory
+ - title: "Progress Events"
+ path: /native-client/dev/devguide/coding/progress-events
+ - title: "Messaging System"
+ path: /native-client/dev/devguide/coding/message-system
+ - title: "View Change, Focus, and Input Events"
+ path: /native-client/dev/devguide/coding/input-events
+ - title: "URL Loading"
+ path: /native-client/dev/devguide/coding/URLLoading
+ - title: "File IO"
+ path: /native-client/dev/devguide/coding/FileIO
+ - title: "Audio"
+ path: /native-client/dev/devguide/coding/audio
+ - title: "3D Graphics"
+ path: /native-client/dev/devguide/coding/3D-graphics
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 55e276eeb2..de613721a8 100644
--- a/native_client_sdk/src/doc/devguide/coding/application-structure.rst
+++ b/native_client_sdk/src/doc/devguide/coding/application-structure.rst
@@ -19,7 +19,7 @@ material presented in the :doc:`Technical Overview <../../overview>`.
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.
+ */getting_started/part1* directory in the Native Client SDK download.
Application components
======================
@@ -33,8 +33,9 @@ A Native Client application typically contains the following components:
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.
+* a Native Client module, written in C or C++, and compiled into a portable
+ executable file (with a .pexe extension) or (if using the Chrome Web Store),
+ architecture-specific executable files (with .nexe extensions).
Applications that are published in the `Chrome Web Store
@@ -46,15 +47,16 @@ 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:
+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" />
+ <embed id="hello_tutorial"
+ width=0 height=0
+ src="hello_tutorial.nmf"
+ type="application/x-pnacl" />
In the ``<embed>`` element:
@@ -72,8 +74,9 @@ src
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"
+ specifies the MIME type of the embedded content; for Portable Native Client
+ modules the type must be "application/x-pnacl". For architecture-specific
+ Native Client modules the type must be "application/x-nacl"
.. _manifest_file:
@@ -92,44 +95,53 @@ 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.
+module (executable) to load. For PNaCl it specifies a single portable
+executable; otherwise it specifies one 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.
+
+Manifest files for applications that use PNaCl are simple. Here is the manifest
+for the hello world example:
+
+.. naclcode::
+
+ {
+ "program": {
+ "portable": {
+ "pnacl-translate": {
+ "url": "hello_tutorial.pexe"
+ }
+ }
+ }
+ }
-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:
+For Chrome Web Store applications that do not use PNaCl, 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.
+Here is an example:
.. naclcode::
{
"program": {
"x86-32": {
- "url": "hello_world_x86_32.nexe"
+ "url": "hello_tutorial_x86_32.nexe"
},
"x86-64": {
- "url": "hello_world_x86_64.nexe"
+ "url": "hello_tutorial_x86_64.nexe"
},
"arm": {
- "url": "hello_world_arm.nexe"
+ "url": "hello_tutorial_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
@@ -138,26 +150,28 @@ 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.
+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). The manifest file format is also
+:doc:`documented<../../reference/nacl-manifest-format>`.
Modules and instances
=====================
-A Native Client **module** is C or C++ code compiled into an executable .nexe file.
+A Native Client **module** is C or C++ code compiled into a PNaCl .pexe file or
+a NaCl .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.
+references a Native Client manifest file that loads the appropriate version of
+the module (either portable, or specific to the end-user's 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.
Native Client modules: A closer look
@@ -169,13 +183,14 @@ A Native Client module must include three components:
* 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:
+In the "Hello tutorial" example (in the ``getting_started/part1`` directory of
+the NaCl SDK), these three components are specified in the file
+``hello_tutorial.cc``. Here is the factory function:
.. naclcode::
Module* CreateModule() {
- return new hello_world::HelloWorldModule();
+ return new HelloTutorialModule();
}
Native Client modules do not have a ``main()`` function. The ``CreateModule()``
@@ -185,39 +200,38 @@ 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:
+Below is the Module class from the "Hello tutorial" example:
.. naclcode::
- class HelloWorldModule : public pp::Module {
+ class HelloTutorialModule : public pp::Module {
public:
- HelloWorldModule() : pp::Module() {}
- virtual ~HelloWorldModule() {}
+ HelloTutorialModule() : pp::Module() {}
+ virtual ~HelloTutorialModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
- return new HelloWorldInstance(instance);
+ return new HelloTutorialInstance(instance);
}
};
+The Module class must include a ``CreateInstance()`` method. The browser calls
+the ``CreateInstance()`` method 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.
-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:
+Below is the Instance class from the "Hello tutorial" example:
.. naclcode::
- class HelloWorldInstance : public pp::Instance {
+ class HelloTutorialInstance : public pp::Instance {
public:
- explicit HelloWorldInstance(PP_Instance instance) : pp::Instance(instance) {}
- virtual ~HelloWorldInstance() {}
+ explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance) {}
+ virtual ~HelloTutorialInstance() {}
- virtual void HandleMessage(const pp::Var& var_message);
+ 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
@@ -225,31 +239,8 @@ 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 ca7bd4d637..a0ff02a62b 100644
--- a/native_client_sdk/src/doc/devguide/coding/message-system.rst
+++ b/native_client_sdk/src/doc/devguide/coding/message-system.rst
@@ -145,7 +145,7 @@ Step 2: From example.js
}
// In the index.html we have set up the appropriate divs:
- <body {{attrs}}>
+ <body {attrs}>
<!-- ... -->
<div id="listener"></div>
<div id="log"></div>
diff --git a/native_client_sdk/src/doc/devguide/coding/native-client-modules.rst b/native_client_sdk/src/doc/devguide/coding/native-client-modules.rst
index f95714387a..582b2fb0ee 100644
--- a/native_client_sdk/src/doc/devguide/coding/native-client-modules.rst
+++ b/native_client_sdk/src/doc/devguide/coding/native-client-modules.rst
@@ -4,10 +4,10 @@
Native Client Modules
#####################
-This document describes the classes and functions that you need to
-implement in a Native Client module in order for Chrome to load,
-initialize, and run a Native Client module. The requirements depend on
-whether the module is written in C or C++.
+This document describes the classes and functions that you need to implement in
+a Native Client module in order for Chrome to load, initialize, and run it. The
+requirements are the same regardless of whether or not the module uses PNaCl,
+but depend on whether the module is written in C or C++.
.. contents::
:local:
@@ -129,17 +129,15 @@ When you implement a Native Client module in C++ you must include these componen
* Code that defines your own Instance class (derived from the ``pp:Instance``
class)
-TODO: this example no longer exists. Update this paragraph and the the hello
-world reference in the paragraph below.
-In the interactive "Hello, World" example (examples/hello_world_interactive),
-these three components are specified in the file ``hello_world.cc``. Here is
-the factory function:
+In the "Hello tutorial" example (in the ``getting_started/part1`` directory of
+the NaCl SDK), these three components are specified in the file
+``hello_tutorial.cc``. Here is the factory function:
.. naclcode::
namespace pp {
Module* CreateModule() {
- return new hello_world::HelloWorldModule();
+ return new HelloTutorialModule();
}
}
@@ -149,20 +147,37 @@ 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:
+Below is the Module class from the "Hello tutorial" example:
.. naclcode::
- class HelloWorldModule : public pp::Module {
+ class HelloTutorialModule : public pp::Module {
public:
- HelloWorldModule() : pp::Module() {}
- virtual ~HelloWorldModule() {}
+ HelloTutorialModule() : pp::Module() {}
+ virtual ~HelloTutorialModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
- return new HelloWorldInstance(instance);
+ return new HelloTutorialInstance(instance);
}
};
+The Module class must include a ``CreateInstance()`` method. The browser calls
+the ``CreateInstance()`` method 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 tutorial" example:
+
+.. naclcode::
+
+ class HelloTutorialInstance : public pp::Instance {
+ public:
+ explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance) {}
+ virtual ~HelloTutorialInstance() {}
+
+ 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
@@ -171,30 +186,8 @@ 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
+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 documents in the
Developer's Guide build on these code samples and add more interesting
functionality.
-
-
-Threading
-=========
-
-TODO: Update/remove this.
-Currently, calls from the browser to a Native Client module always execute on
-the main thread of the module. Similarly, all Pepper API calls, both C and C++,
-must be made on the main thread of the module, with the exception of
-pp::Core::CallOnMainThread() and PPB_Core::CallOnMainThread().
diff --git a/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml b/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml
new file mode 100644
index 0000000000..5481d8e381
--- /dev/null
+++ b/native_client_sdk/src/doc/devguide/devcycle/_toc.yaml
@@ -0,0 +1,14 @@
+toc:
+ - title: "Development Cycle"
+ path: /native-client/${folder}/devguide/devcycle
+ section:
+ - title: "Building"
+ path: /native-client/${folder}/devguide/devcycle/building
+ - title: "Dynamic Linking and Loading with glibc"
+ path: /native-client/${folder}/devguide/devcycle/dynamic-loading
+ - title: "Running"
+ path: /native-client/${folder}/devguide/devcycle/running
+ - title: "Debugging"
+ path: /native-client/${folder}/devguide/devcycle/debugging
+ - title: "Debugging with Visual Studio"
+ path: /native-client/${folder}/devguide/devcycle/vs-addin
diff --git a/native_client_sdk/src/doc/devguide/devcycle/building.rst b/native_client_sdk/src/doc/devguide/devcycle/building.rst
index 48cca76693..7fbbe07f9d 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/building.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/building.rst
@@ -9,7 +9,6 @@ Building
:backlinks: none
:depth: 2
-
Introduction
============
@@ -24,65 +23,82 @@ with those.
Target architectures
--------------------
-Native Client modules are written in C or C++ and compiled into executable
-files ending in a .nexe extension using one of the toolchains in the Native
-Client SDK. Chrome can load .nexe files embedded in web pages and execute the
-.nexe files as part of a web application.
+Portable Native Client (PNaCl) modules are written in C or C++ and compiled
+into an executable file ending in a **.pexe** extension using the PNaCl
+toolchain in the Native Client SDK. Chrome can load **pexe** files
+embedded in web pages and execute them as part of a web application.
+
+As explained in the Technical Overview, PNaCl modules are
+operating-system-independent **and** processor-independent. The same
+**pexe** will run on Windows, Mac, Linux, and ChromeOS and it will run on
+any processor, e.g., x86-32, x86-64, and ARM.
+
+Native Client also supports architecture-specific **nexe** files.
+These **nexe** files are **also** operating-system-independent,
+but they are **not** processor-independent. To support a wide-variety of
+devices you must compile separate versions of your Native Client module
+for different processors on end-user machines. A
+:ref:`manifest file <application_files>` will then specify which version
+of the module to load based on the end-user's architecture. The SDK
+includes a script---``create_nmf.py`` (in the ``tools/`` directory)---to
+generate manifest files. For examples of how to compile modules
+for multiple target architectures and how to generate manifest files, see the
+Makefiles included with the SDK examples.
-As explained in the Technical Overview, Native Client modules are
-operating-system-independent, not processor-independent. Therefore, you must
-compile separate versions of your Native Client module for different processors
-on end-user machines, such as x86-32, x86-64, and ARM. The list below shows
-which .nexe modules run on which target architectures:
+This section will mostly cover PNaCl, but also describes how to build
+nexe applications.
-**x86 32-bit .nexe modules run on**:
+C libraries
+-----------
-* Windows 32-bit
-* Mac
-* Linux 32-bit
-* Linux 64-bit (but only with 32-bit Chrome)
+The PNaCl SDK has a single choice of C library:
+`newlib <http://sourceware.org/newlib/>`_.
-**x86 64-bit .nexe modules run on**:
+The Native Client SDK also has a GCC-based toolchain for building
+**nexes**. The GCC-based toolchain has support for two C libraries:
+`newlib <http://sourceware.org/newlib/>`_ and
+`glibc <http://www.gnu.org/software/libc/>`_.
+See :doc:`Dynamic Linking & Loading with glibc <dynamic-loading>`
+for information about these libraries, including factors to help you
+decide which to use.
-* Windows 64-bit
-* Linux 64-bit (but only with 64-bit Chrome).
-**ARM .nexe modules run on**:
+C++ libraries
+-------------
-* ARM devices
+The PNaCl SDK can use either
+`libstdc++ <http://gcc.gnu.org/libstdc++>`_ (the current default)
+or LLVM's `libc++ <http://libcxx.llvm.org/>`_ (preliminary support).
+The ``-stdlib=[libstdc++|libc++]`` command line argument can be used
+to choose which standard library to use.
-In general, you must compile a module for the 32-bit and 64-bit x86 target
-architectures (we also strongly recommend compiling modules for the ARM
-architecture), and create a :ref:`manifest file <application_files>` that
-specifies which version of the module to load based on the end-user's
-architecture. The SDK includes a script, ``create_nmf.py`` (in the ``tools/``
-directory) to generate manifest files. For examples of how to compile modules
-for multiple target architectures and how to generate manifest files, see the
-Makefiles included with the SDK examples.
+The GCC-based Native Client SDK only has support for
+`libstdc++ <http://gcc.gnu.org/libstdc++>`_.
-C libraries
------------
-
-The Native Client SDK comes with two C libraries: `newlib
-<http://sourceware.org/newlib/>`_ and `glibc
-<http://www.gnu.org/software/libc/>`_. See :doc:`Dynamic Linking & Loading with
-glibc <dynamic-loading>` for information about these libraries, including
-factors to help you decide which to use.
+C++11 library support is only complete in libc++ but other non-library
+language features should work regardless of which standard library is
+used. The ``-std=[c++98|c++11]`` command line argument can be used to
+indicate which C++ language standard to use.
SDK toolchains
--------------
-The Native Client SDK includes multiple toolchains, differentiated by target
-architectures and C libraries. The toolchains are located in directories named
-``toolchain/<platform>_<architecture>_<library>``, where:
+The Native Client SDK includes multiple toolchains. It has one PNaCl toolchain
+and it has multiple GCC-based toolchains that are differentiated by target
+architectures and C libraries. The single PNaCl toolchain is located
+in a directory named ``toolchain/<OS_platform>_pnacl``, and the GCC-based
+toolchains are located in directories named
+``toolchain/<OS_platform>_<architecture>_<library>``, where:
* *<platform>* is the platform of your development machine (win, mac, or linux)
* *<architecture>* is your target architecture (x86 or arm)
* *<library>* is the C library you are compiling with (newlib or glibc)
-The compilers, linkers, and other tools are located in the bin/ subdirectory in
-each toolchain. For example, the tools in the Windows SDK for the x86 target
-architecture using the newlib library are in ``toolchain/win_x86_newlib/bin``.
+The compilers, linkers, and other tools are located in the ``bin/``
+subdirectory in each toolchain. For example, the tools in the Windows SDK
+for PNaCl has a C++ compiler in ``toolchain/win_pnacl/bin/pnacl-clang++``.
+As another example, the GCC-based C++ compiler that targets the x86 and uses the
+newlib library, is located at ``toolchain/win_x86_newlib/bin/x86_64-nacl-g++``.
.. Note::
:class: note
@@ -96,50 +112,235 @@ architecture using the newlib library are in ``toolchain/win_x86_newlib/bin``.
SDK toolchains versus your hosted toolchain
-------------------------------------------
-To build .nexe files, you must use one of the Native Client toolchains included
-in the SDK. The SDK toolchains use a variety of techniques to ensure that your
-``.nexe`` files comply with the security constraints of the Native Client
-sandbox.
+To build NaCl modules, you must use one of the Native Client toolchains
+included in the SDK. The SDK toolchains use a variety of techniques to
+ensure that your NaCl modules comply with the security constraints of
+the Native Client sandbox.
During development, you have another choice: You can build modules using a
-standard GNU toolchain, such as the hosted toolchain on your development
-machine. The benefit of using a standard GNU toolchain is that you can develop
-modules in your favorite IDE and use your favorite debugging and profiling
-tools. The drawback is that modules compiled in this manner can only run as
-Pepper plugins in Chrome. To publish and distribute Native Client modules as
-part of a web application, you must eventually use a toolchain in the Native
-Client SDK to create ``.nexe`` files.
+*standard* toolchain, such as the hosted toolchain on your development
+machine. This can be Visual Studio's standard compiler, XCode, LLVM, or
+GNU-based compilers on your development machine. These standard toolchains
+will not produce executables that comply with the Native Client sandbox
+security constraints. They are also not portable across operating systems
+and not portable across different processors. However, using a standard
+toolchain allows you to develop modules in your favorite IDE and use
+your favorite debugging and profiling tools. The drawback is that modules
+compiled in this manner can only run as Pepper (PPAPI) plugins in Chrome.
+To publish and distribute Native Client modules as part of a web
+application, you must eventually use a toolchain in the Native
+Client SDK.
.. Note::
:class: note
- * Documentation on how to compile and run modules as Pepper plugins will be
- published soon.
- * In the future, additional tools will be available to compile Native Client
- modules written in other programming languages, such as C#. But this
- document covers only compiling C and C++ code, using the modified GNU
- toolchains provided in the SDK.
+ In the future, additional tools will be available to compile Native Client
+ modules written in other programming languages, such as C#. But this
+ document covers only compiling C and C++ code, using the toolchains
+ provided in the SDK.
+
+
+The PNaCl toolchain
+===================
+
+The PNaCl toolchain contains modified versions of the tools in the
+LLVM toolchain, as wells as linkers and other tools from binutils.
+To determine which version of LLVM or binutils the tools are based upon,
+run the tool with the ``--version`` commandline flag. These tools
+are used to compile and link applications into .pexe files. The toolchain
+also contains a tool to translate a .pexe file into a
+architecture-specific .nexe (e.g., for debugging purposes).
+
+Each tool's name is preceded by the prefix "pnacl-". Some of the useful
+tools include:
+
+pnacl-ar
+ Creates archives (e.g., static libraries)
+pnacl-clang
+ C-compiler and compiler driver
+pnacl-clang++
+ C++-compiler and compiler driver
+pnacl-dis
+ Disassembler for both **pexe** files and **nexe** files
+pnacl-finalize
+ Finalizes **pexe** files for deployment
+pnacl-ld
+ Bitcode linker
+pnacl-nm
+ Lists symbols in bitcode files, native code, and libraries
+pnacl-ranlib
+ Generates a symbol table for archives (e.g., static libraries)
+pnacl-translate
+ Translates a **pexe** to a native architecture, outside of the browser
+
+For the full list of tools, see the
+``<NACL_SDK_ROOT>/toolchain/<platform>_pnacl/bin`` directory.
+
+Using the PNaCl tools to compile, link, debug, and deploy
+=========================================================
+
+To build an application with the PNaCl SDK toolchain, you must compile
+your code, link it, test and debug it, and then deploy it. This section goes
+over some examples of how to use the tools.
+
+Compile
+-------
+
+To compile a simple application consisting of ``file1.cc`` and ``file2.cc`` into
+``hello_world.pexe`` with a single command, use the ``pnacl-clang++`` tool
+
+.. naclcode::
+ :prettyprint: 0
+
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-clang++ file1.cc file2.cc ^
+ -I<NACL_SDK_ROOT>/include -L<NACL_SDK_ROOT>/lib/pnacl/Release ^
+ -o hello_world.pexe -g -O2 -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. ``<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_31``.)
+
+However, the typical application consists of many files. In that case,
+each file can be compiled separately so that only files that are
+affected by a change need to be recompiled. To compile an individual
+file from your application, you must use either the ``pnacl-clang`` C
+compiler, or the ``pnacl-clang++`` C++ compiler. The compiler produces
+separate bitcode files. For example:
+
+.. naclcode::
+ :prettyprint: 0
+
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-clang++ hello_world.cc ^
+ -I<NACL_SDK_ROOT>/include -c -o hello_world.o -g -O0
+
+For a description of each commandline flag, run ``pnacl-clang --help``.
+For convenience, here is a description of some of the flags used in
+the example.
+
+.. _compile_flags:
+
+``-c``
+ indicates that ``pnacl-clang++`` should only compile an individual file,
+ rather than continue the build process and link together the
+ full application.
+
+``-o<output_file>``
+ indicates the **output** filename.
+
+``-g``
+ tells the compiler to include debug information in the result.
+ This debug information can be used during development, and then **stripped**
+ before actually deploying the application to keep the application's
+ download size small.
+
+``-On``
+ sets the optimization level to n. Use 0 when debugging, and -O2 or -O3
+ for profiling and deployment.
+
+ The main difference between -O2 and -O3 is whether the compiler performs
+ optimizations that involve a space-speed tradeoff. It could be the case that
+ ``-O3`` optimizations are not desirable due to increased **pexe**
+ download size; you should make your own performance measurements to determine
+ which level of optimization is right for you. When looking at code size,
+ note that what you generally care about is not the size of the pexe
+ produced by pnacl-clang, but the size of the compressed pexe that you upload
+ your application to the server or to the Chrome Web Store.
+ Optimizations that increase the size of a pexe may not increase the size of
+ the compressed pexe that much.
+
+``-I<directory>``
+ adds a directory to the search path for **include** files. The SDK has
+ Pepper (PPAPI) headers located at ``<NACL_SDK_ROOT>/include``, so add
+ that directory when compiling to be able to include the headers.
-Tools
-=====
-The Native Client toolchains contain modified versions of the tools in the
-standard GNU toolchain, including the gcc compilers (currently version 4.4) and
-the linkers and other tools from binutils (currently version 2.20).
+Create a static library
+-----------------------
-In the toolchain for the ARM target architecture, each tool's name is preceded
-by the prefix "arm-nacl-".
+The ``pnacl-ar`` and ``pnacl-ranlib`` tools allow you to create a
+**static** library from a set of bitcode files, which can later be linked
+into the full application.
-In the toolchains for the x86 target architecture, there are actually two
-versions of each tool—one to build Native Client modules for the x86-32 target
-architecture, and one to build modules for the x86-64 target architecture. Each
-tool's name is preceded by one of the following prefixes:
+.. naclcode::
+ :prettyprint: 0
-i686-nacl-
- prefix for tools used to build 32-bit .nexes
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-ar cr libfoo.a ^
+ foo1.o foo2.o foo3.o
-x86_64-nacl-
- prefix for tools used to build 64-bit .nexes
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-ranlib libfoo.a
+
+
+Link the application
+--------------------
+
+The ``pnacl-clang++`` tool is used to compile applications, but it can
+also be used link together compiled bitcode and libraries into a
+full application.
+
+.. naclcode::
+ :prettyprint: 0
+
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-clang++ -o hello_world.pexe ^
+ hello_world.o -L<NACL_SDK_ROOT>/lib/pnacl/Debug -lfoo -lppapi_cpp -lppapi
+
+This links the hello world bitcode with the ``foo`` library in the example
+as well as the *Debug* version of the Pepper libraries which are located
+in ``<NACL_SDK_ROOT>/lib/pnacl/Debug``. If you wish to link against the
+*Release* version of the Pepper libraries, change the
+``-L<NACL_SDK_ROOT>/lib/pnacl/Debug`` to
+``-L<NACL_SDK_ROOT>/lib/pnacl/Release``.
+
+
+Finalizing the **pexe** for deployment
+--------------------------------------
+
+Typically you would run the application to test it and debug it if needed
+before deploying. See the :doc:`running <running>` documentation for how
+to run a PNaCl application, and see the :doc:`debugging <debugging>`
+documentation for debugging techniques and workflow. After testing a PNaCl
+application, you must **"finalize"** it. The ``pnacl-finalize``
+tool handles this.
+
+.. naclcode::
+ :prettyprint: 0
+
+ <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-finalize ^
+ hello_world.pexe -o hello_world.final.pexe
+
+Prior to finalization, the application **pexe** is stored in a binary
+format that is subject to change. After finalization, the application
+pexe is **rewritten** into a different binary format that is **stable**
+and will be supported by future versions of PNaCl. The finalization step
+also helps minimize the size of your application for distribution by
+stripping out debug information and other metadata.
+
+Once the application is finalized, be sure to adjust the manifest file to
+refer to the final version of the application before deployment.
+The ``create_nmf.py`` tool helps generate an ``.nmf`` file, but ``.nmf``
+files can also be written by hand.
+
+
+The GNU-based toolchains
+========================
+
+Besides the PNaCl toolchain, the Native Client SDK also includes modified
+versions of the tools in the standard GNU toolchain, including the GCC
+compilers and the linkers and other tools from binutils. These tools only
+support building **nexe** files. Run the tool with the ``--version``
+commandline flag to determine the current version of the tools.
+
+Each tool in the toolchain is prefixed with the name of the target
+architecture. In the toolchain for the ARM target architecture, each
+tool's name is preceded by the prefix "arm-nacl-". In the toolchains for
+the x86 target architecture, there are actually two versions of each
+tool---one to build Native Client modules for the x86-32
+target architecture, and one to build modules for the x86-64 target
+architecture. "i686-nacl-" is the prefix for tools used to build
+32-bit .nexes, and "x86_64-nacl-" is the prefix for tools used to
+build 64-bit .nexes
These prefixes conform to gcc naming standards and make it easy to use tools
like autoconf. As an example, you can use ``i686-nacl-gcc`` to compile 32-bit
@@ -148,7 +349,7 @@ typically override a tool's default target architecture with command line
flags, e.g., you can specify ``x86_64-nacl-gcc -m32`` to compile a 32-bit
.nexe.
-The SDK toolchains include the following tools:
+The GNU-based SDK toolchains include the following tools:
* <prefix>addr2line
* <prefix>ar
@@ -172,93 +373,53 @@ The SDK toolchains include the following tools:
* <prefix>strings
* <prefix>strip
+
Compiling
-=========
+---------
-To create a .nexe file, use a compiler in one of the Native Client toolchains.
+Compiling files with the GNU-based toolchain is similar to compiling
+files with the PNaCl-based toolchain, except that the output is
+architecture specific.
For example, assuming you're developing on a Windows machine, targeting the x86
architecture, and using the newlib library, you can compile a 32-bit .nexe for
-the hello_world example with the following command::
+the hello_world example with the following command:
- <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/i686-nacl-gcc hello_world.c ^
- -o hello_world_x86_32.nexe -m32 -g -O0 -lppapi
+.. naclcode::
+ :prettyprint: 0
-(The carat ``^`` allows the command to span multiple lines on Windows; to do the
-same on Mac and Linux use a back slash 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``.)
+ <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/i686-nacl-gcc hello_world.c ^
+ -I<NACL_SDK_ROOT>/include -L<NACL_SDK_ROOT>/lib/newlib/Release ^
+ -o hello_world_x86_32.nexe -m32 -g -O2 -lppapi
To compile a 64-bit .nexe, you can run the same command but use -m64 instead of
-m32. Alternatively, you could also use the version of the compiler that
targets the x86-64 architecture, i.e., ``x86_64-nacl-gcc``.
-You should name executable modules with a ``.nexe`` filename extension,
+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
-=================================================
+Creating libraries and Linking
+------------------------------
-To optimize the performance of your .nexe module, you must use the correct set
-of flags when you compile with nacl-gcc. If you're used to working with an IDE
-rather than with a command-line compiler like gcc, you may not be familiar with
-which flags you need to specify. The table below summarizes which flags to
-specify based on different development scenarios.
+Creating libraries and linking with the GNU-based toolchain is similar
+to doing the same with the PNaCl toolchain. The relevant tools
+for creating **static** libraries are ``<prefix>ar`` and ``<prefix>ranlib``.
+Linking can be done with ``<prefix>g++``. See the
+:doc:`Dynamic Linking & Loading with glibc <dynamic-loading>`
+section on how to create **shared** libraries.
-===================== =================================================================
-Development scenarios Flags for nacl-gcc
-===================== =================================================================
-debugging -g -O0
-profile [-g] -O{2|3} -msse -mfpmath=sse -ffast-math -fomit-frame-pointer
-deploy -s -O{2|3} -msse -mfpmath=sse -ffast-math -fomit-frame-pointer
-===================== =================================================================
-A few of these flags are described below:
-
--g
- Produce debugging information.
-
--On
- Optimize the executable for both performance and code size. A higher n
- increases the level of optimization. Use -O0 when debugging, and -O2 or -O3
- for profiling and deployment.
+Finalizing a **nexe** for deployment
+------------------------------------
- The main difference between -O2 and -O3 is whether the compiler performs
- optimizations that involve a space-speed tradeoff. It could be the case that
- these optimizations are not desirable due to .nexe download size; you should
- make your own performance measurements to determine which level of
- optimization is right for you. When looking at code size, note that what you
- generally care about is not the size of the .nexe produced by nacl-gcc, but
- the size of the compressed .nexe that you upload to the Chrome Web Store.
- Optimizations that increase the size of a .nexe may not increase the size of
- the compressed .nexe that much.
-
- For additional information about optimizations, see the `gcc optimization
- options <http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html>`_. Note
- that the -Os option (optimize for size) is not currently supported.
-
--s
- Strip the .nexe, i.e., remove all symbol table and relocation information
- from the executable.
-
- As an alternative to using the -s option, you can store a copy of the
- non-stripped .nexe somewhere so that you can extract symbol information from
- it if necessary, and use the nacl-strip tool in the SDK to strip symbol
- information from the .nexe that you deploy.
-
-.. Note::
- :class: note
+Unlike the PNaCl toolchain, no separate finalization step is required
+for **nexe** files. The nexe files are always in a **stable** format.
+However, the nexe file may contain debug information and symbol information
+which may make the nexe file larger than needed for distribution.
+To minimize the size of the distributed file, you can run the
+``<prefix>strip`` tool to strip out debug information.
- To see how the examples in the SDK are built, run make in any of the example
- subdirectories (e.g., examples/hello_world). The make tool displays the full
- command lines it runs for each step of the build process (compiling, linking,
- and generating Native Client manifest files).
-
-For additional information about compiler options, see `gcc command options
-<http://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html>`_.
Using make
==========
@@ -268,150 +429,139 @@ This document doesn't cover how to use ``make``, but if you want to use
ones in the SDK examples.
The Makefiles for the SDK examples build most of the examples in multiple
-configurations (using different C libraries, targeting different architectures,
-and using different levels of optimization). With a few exceptions (tumbler,
-debugging, and dlopen), running ``make`` in each example's directory does the
-following:
+configurations (using PNaCl vs NaCl, using different C libraries,
+targeting different architectures, and using different levels of optimization).
+To select a specific toolchain, set the **environment variable**
+``TOOLCHAIN`` to either ``pnacl``, ``newlib``, ``glibc``, or ``host``.
+To select a specific level of optimization set the **environment
+variable** ``CONFIG`` to either ``Debug``, or ``Release``. Running
+``make`` in each example's directory does **one** of the following,
+depending on the setting of the environment variables.
+
+* If ``TOOLCHAIN=pnacl`` creates a subdirectory called ``pnacl``;
+
+ * builds a .pexe (architecture-independent Native Client executable) using
+ the newlib library
+ * generates a Native Client manifest (.nmf) file for the pnacl version of the
+ example
-* creates a subdirectory called ``newlib``;
+* If ``TOOLCHAIN=newlib`` creates a subdirectory called ``newlib``;
* builds .nexes for the x86-32, x86-64, and ARM architectures using the
- newlib library;
+ newlib library
* generates a Native Client manifest (.nmf) file for the newlib version of
- the example;
+ the example
-* creates a subdirectory called ``glibc``;
+* If ``TOOLCHAIN=glibc`` creates a subdirectory called ``glibc``;
* builds .nexes for the x86-32 and x86-64 architectures using the glibc
- library;
+ library
* generates a Native Client manifest (.nmf) file for the glibc version of the
- example;
+ example
-* creates a subdirectory called ``windows``, ``linux``, or ``mac`` (depending
- on your development machine);
+* If ``TOOLCHAIN=host`` creates a subdirectory called ``windows``, ``linux``,
+ or ``mac`` (depending on your development machine);
* builds a Pepper plugin (.dll for Windows, .so for Linux/Mac) using the
- hosted toolchain on your development machine;
- * generates a Native Client manifest (.nmf) file for the glibc version of the
- example;
+ hosted toolchain on your development machine
+ * generates a Native Client manifest (.nmf) file for the host Pepper plugin
+ version of the example
-* creates a subdirectory called ``pnacl``;
-
- * builds a .pexe (architecture-independent Native Client executable) using
- the newlib library; and
- * generates a Native Client manifest (.nmf) file for the pnacl version of the
- example;
.. Note::
:class: note
- * The examples are also built using different optimization levels, and the
- executable and manifest files are actually located in subdirectories called
- "Debug" and "Release".
- * The glibc library is not yet available for the ARM and PNaCl toolchains.
- * Chrome does not yet directly support .pexe files, but the PNaCl toolchain
- contains a tool to translate .pexes into .nexes.
-
- Your Makefile can be simpler since you will not likely want to build so many
- different configurations of your module. The example Makefiles define
- numerous variables near the top (e.g., ``GLIBC_CCFLAGS``) that make it easy
- to customize the commands that are executed for your project and the options
- for each command.
-
- In addition to building .nexe files, the example Makefiles also generate
- Native Client manifest (.nmf) files, which your application points to from
- the ``src`` attribute of an ``<embed>`` tag in its HTML file. For information
- about Native Client manifest files, see the :ref:`Technical Overview
- <application_files>`. The SDK includes a script called ``create_nmf.py`` (in
- the ``tools/`` directory) that you can use to generate .nmf files. Run
- "``python create_nmf.py --help``" to see the script's command-line options,
- and look at the Makefiles in the SDK examples to see how to use the script to
- generate a manifest file for modules compiled with either toolchain.
-
- For details on how to use make, see the `GNU 'make' Manual
- <http://www.gnu.org/software/make/manual/make.html>`_.
+ The glibc library is not yet available for the ARM and PNaCl toolchains.
+
+Here is how to build the examples with PNaCl in Release mode on Windows.
+The resulting files for ``examples/api/audio`` will be in
+``examples/api/audio/pnacl/Release``, and the directory layout is similar for
+other examples.
+
+.. naclcode::
+ :prettyprint: 0
+
+ set TOOLCHAIN=pnacl
+ set CONFIG=Release
+ make
+
+Your Makefile can be simpler since you will not likely want to build so many
+different configurations of your module. The example Makefiles define
+numerous variables near the top (e.g., ``CFLAGS``) that make it easy
+to customize the commands that are executed for your project and the options
+for each command.
+
+For details on how to use make, see the `GNU 'make' Manual
+<http://www.gnu.org/software/make/manual/make.html>`_.
Libraries and header files provided with the SDK
================================================
The Native Client SDK includes modified versions of standard toolchain-support
-libraries, such as iberty, nosys, pthread, and valgrind, plus the relevant
-header files.
-
-The libraries are located in the following directories:
+libraries, such as libpthread and libc, plus the relevant header files.
+The standard libraries are located in the following directories:
-* x86 toolchains: toolchain/<platform>_x86_<library>/x86_64-nacl/lib32 and
- /lib64 (for the 32-bit and 64-bit target architectures, respectively)
-* ARM toolchain: toolchain/<platform>_arm_<library>/arm-nacl/lib
+* PNaCl toolchain: ``toolchain/<platform>_pnacl/usr/lib``
+* x86 toolchains: ``toolchain/<platform>_x86_<library>/x86_64-nacl/lib32`` and
+ ``/lib64`` (for the 32-bit and 64-bit target architectures, respectively)
+* ARM toolchain: ``toolchain/<platform>_arm_<library>/arm-nacl/lib``
For example, on Windows, the libraries for the x86-64 architecture in the
-newlib toolchain are in toolchain/win_x86_newlib/x86_64-nacl/lib64.
-
-The standard gcc libraries are also available, in
-toolchain/<platform>_<architecture>_<library>/lib.
+newlib toolchain are in ``toolchain/win_x86_newlib/x86_64-nacl/lib64``.
The header files are in:
-* x86 toolchains: toolchain/<platform>_x86_<library>/x86_64-nacl/include
-* ARM toolchain: toolchain/<platform>_arm_<library>/arm-nacl/include
-
-The toolchains intentionally leave out some standard libraries and header
-files; in particular, for sandboxing reasons, the SDK doesn't support some
-POSIX-specified items. For example, ``open(2)`` isn't included, and
-``close(2)`` doesn't precisely match the POSIX version.
+* PNaCl toolchain: ``toolchain/<platform>_pnacl/usr/include``
+* x86 toolchains: ``toolchain/<platform>_x86_<library>/x86_64-nacl/include``
+* ARM toolchain: ``toolchain/<platform>_arm_<library>/arm-nacl/include``
Many other libraries have been ported for use with Native Client; for more
information, see the `naclports <http://code.google.com/p/naclports/>`_
project. If you port an open-source library for your own use, we recommend
adding it to naclports.
-Here are descriptions of some of the Native Client-specific libraries provided
-in the SDK:
+Besides the standard libraries, the SDK includes Pepper libraries.
+The PNaCl Pepper libraries are located in the the
+``<NACL_SDK_ROOT>/lib/pnacl/<Release or Debug>`` directory.
+The GNU-based toolchain has Pepper libraries in
+``<NACL_SDK_ROOT>/lib/newlib_<arch>/<Release or Debug>``
+and ``<NACL_SDK_ROOT>/lib/glibc_<arch>/<Release or Debug>``.
+The libraries provided by the SDK allow the application to use Pepper,
+as well as convenience libraries to simplify porting an application that
+uses POSIX functions. Here are descriptions of the Pepper libraries provided
+in the SDK.
+
+.. _devcycle-building-nacl-io:
libppapi.a
- Implements the Pepper (PPAPI) C interface (needed for all applications that
- use Pepper).
+ Implements the Pepper (PPAPI) C interface. Needed for all applications that
+ use Pepper (even C++ applications).
libppapi_cpp.a
- Implements the Pepper (PPAPI) C++ interface.
-
-libpthread.a
- Implements the Native Client pthread interface.
-
-libsrpc.a
- Implements the Native Client RPC layer, and is used to implement the Pepper C
- layer.
-
-libimc.a
- Implements the intermodule communications layer (IMC), which is used to
- implement SRPC, the Native Client RPC library.
-
-libgio.a
- Used to implement Native Client logging and some other features in
- nacl_platform.
-
-libplatform.a
- Provides some platform abstractions, and is used to implement some other
- Native Client libraries.
-
-The top-level /lib directory contains two additional Native Client libraries of
-interest:
-
-libnacl_mounts.a
- Provides a virtual file system that a module can "mount" in a given directory
- tree. Once a module has mounted a file system, it can use standard C library
- file operations: fopen, fread, fwrite, fseek, and fclose. For a list of the
- types of file systems that can be mounted, see
- include/nacl_mounts/nacl_mounts.h. For an example of how to use nacl_mounts,
- see examples/hello_nacl_mounts.
-
-libppapi_main.a
+ Implements the Pepper (PPAPI) C++ interface. Needed by C++ applications that
+ use Pepper.
+
+libppapi_gles2.a
+ Implements the Pepper (PPAPI) GLES interface. Needed by applications
+ that use the 3D graphics API.
+
+libnacl_io.a
+ Provides a POSIX layer for NaCl. In particular, the library provides a
+ virtual file system and support for sockets. The virtual file system
+ allows a module to "mount" a given directory tree. Once a module has
+ mounted a file system, it can use standard C library file operations:
+ ``fopen``, ``fread``, ``fwrite``, ``fseek``, and ``fclose``.
+ For more detail, see the header ``include/nacl_io/nacl_io.h``.
+ For an example of how to use nacl_io, see ``examples/demo/nacl_io``.
+
+libppapi_simple.a
Provides a familiar C programming environment by letting a module have a
- simple entry point called ppapi_main(), which is similar to the standard C
- main() function, complete with argc and argv[] parameters. This library also
- lets modules use standard C functions such as printf(), fopen(), and
- fwrite(). For details see include/ppapi_main/ppapi_main.h. For an example of
- how to use ppapi_main, see examples/hello_world_stdio.
+ simple entry point that is registered by ``PPAPI_SIMPLE_REGISTER_MAIN``.
+ The entry point is similar to the standard C ``main()`` function, complete
+ with ``argc`` and ``argv[]`` parameters. For details see
+ ``include/ppapi_simple/ps.h``. For an example of
+ how to use ppapi_simple, ``see examples/tutorial/using_ppapi_simple``.
+
.. Note::
:class: note
@@ -432,27 +582,41 @@ Troubleshooting
Some common problems, and how to fix them:
"Undefined reference" error
- An "undefined reference" error may indicate incorrect link order and/or
- missing libraries. For example, if you leave out -lppapi when compiling the
- hello_world example, you'll see a series of undefined reference errors.
-
- One common type of "undefined reference" error is with respect to certain
- system calls, e.g., "undefined reference to 'mkdir'". For security reasons,
- Native Client does not support a number of system calls. Depending on how
- your code uses such system calls, you have a few options:
-
- #. Link with the -lnosys flag to provide empty/always-fail versions of
- unsupported system calls. This will at least get you past the link stage.
- #. Find and remove use of the unsupported system calls.
- #. Create your own implementation of the unsupported system calls to do
- something useful for your application.
-
- If your code uses mkdir or other file system calls, you might find nacl-mounts
- useful. Nacl-mounts essentially does option (3) for you: It lets your code
- use POSIX-like file system calls, and implements the calls using various
- technologies (e.g., App Engine or an in-memory filesystem).
+---------------------------
+
+An "undefined reference" error may indicate incorrect link order and/or
+missing libraries. For example, if you leave out ``-lppapi`` when
+compiling Pepper applications you'll see a series of undefined
+reference errors.
+
+One common type of "undefined reference" error is with respect to certain
+system calls, e.g., "undefined reference to 'mkdir'". For security reasons,
+Native Client does not support a number of system calls. Depending on how
+your code uses such system calls, you have a few options:
+
+#. Link with the ``-lnosys`` flag to provide empty/always-fail versions of
+ unsupported system calls. This will at least get you past the link stage.
+#. Find and remove use of the unsupported system calls.
+#. Create your own implementation of the unsupported system calls to do
+ something useful for your application.
+
+If your code uses mkdir or other file system calls, you might find the
+:ref:`nacl_io <devcycle-building-nacl-io>` library useful.
+The nacl_io library essentially does option (3) for you: It lets your
+code use POSIX-like file system calls, and implements the calls using
+various technologies (e.g., HTML5 file system, read-only filesystems that
+use URL loaders, or an in-memory filesystem).
Can't find libraries containing necessary symbols
- Here is one way to find the appropriate library for a given symbol::
+-------------------------------------------------
+
+Here is one way to find the appropriate library for a given symbol:
+
+.. naclcode::
+ :prettyprint: 0
+
+ <NACL_SDK_ROOT>/toolchain/<platform>_pnacl/bin/pnacl-nm -o \
+ toolchain/<platform>_pnacl/usr/lib/*.a | grep <MySymbolName>
- nm -o toolchain/<platform>_x86_<library>/x86_64-nacl/lib64/*.a | grep <MySymbolName>
+.. TODO(jvoung): Add some notes about debugging GNU-extensions not
+.. supported by PNaCl ABI stabilization passes, like computed gotos?
diff --git a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
index de2fd2c69c..199ff3f28a 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
@@ -4,4 +4,450 @@
Debugging
#########
-foo
+This document describes tools and techniques you can use to debug, monitor,
+and measure your application's performance.
+
+.. contents:: Table Of Contents
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Diagnostic information
+======================
+
+Viewing process statistics with the task manager
+------------------------------------------------
+
+You can use Chrome's Task Manager to display information about a Native Client
+application:
+
+#. Open the Task Manager by clicking the menu icon |menu-icon| and choosing
+ **Tools > Task manager**.
+#. When the Task Manager window appears, verify that the columns displaying
+ memory information are visible. If they are not, right click in the header
+ row and select the memory items from the popup menu that appears.
+
+A browser window running a Native Client application will have at least two
+processes associated with it: a process for the app's top level (the render
+process managing the page including its HTML and any JavaScript) and one or
+more processes for each instance of a Native Client module embedded in the page
+(each process running native code from one nexe file). The top-level process
+appears with the application's icon and begins with the text "App:". A Native
+Client process appears with a Chrome extension icon (a jigsaw puzzle piece
+|puzzle|) and begins with the text "Native Client module" followed by the URL
+of its manifest file.
+
+From the Task Manager you can view the changing memory allocations of all the
+processes associated with a Native Client application. Each process has its own
+memory footprint. You can also see the rendering rate displayed as frames per
+second (FPS). Note that the computation of render frames can be performed in
+any process, but the rendering itself is always done in the top level
+application process, so look for the rendering rate there.
+
+Controlling the level of Native Client error and warning messages
+-----------------------------------------------------------------
+
+Native Client prints warning and error messages to stdout and stderr. You can
+increase the amount of Native Client's diagnostic output by setting the
+following `environment variables
+<http://en.wikipedia.org/wiki/Environment_variable>`_:
+
+* NACL_DEBUG_ENABLE=1
+* PPAPI_BROWSER_DEBUG=1
+* NACL_PLUGIN_DEBUG=1
+* NACL_PPAPI_PROXY_DEBUG=1
+* NACL_SRPC_DEBUG=[1-255] (use a higher number for more verbose debug output)
+* NACLVERBOSITY=[1-255]
+
+Basic debugging
+===============
+
+Writing messages to the JavaScript console
+------------------------------------------
+
+You can send messages from your C/C++ code to JavaScript using the PostMessage
+call in the :doc:`Pepper messaging system <../coding/message-system>`. When the
+JavaScript code receives a message, its message event handler can call
+`console.log() <https://developer.mozilla.org/en/DOM/console.log>`_ to write
+the message to the JavaScript `console
+<https://developers.google.com/chrome-developer-tools/docs/console>`_ in
+Chrome's Developer Tools.
+
+Debugging with printf
+---------------------
+
+Your C/C++ code can perform inline printf debugging to stdout and stderr by
+calling fprintf() directly, or by using cover functions like these:
+
+.. naclcode::
+
+ #include <stdio.h>
+ void logmsg(const char* pMsg){
+ fprintf(stdout,"logmsg: %s\n",pMsg);
+ }
+ void errormsg(const char* pMsg){
+ fprintf(stderr,"logerr: %s\n",pMsg);
+ }
+
+By default stdout and stderr will appear in Chrome's stdout and stderr stream
+but they can also be redirected as described below.
+
+Redirecting output to log files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can redirect stdout and stderr to output files by setting these environment variables:
+
+* ``NACL_EXE_STDOUT=c:\nacl_stdout.log``
+* ``NACL_EXE_STDERR=c:\nacl_stderr.log``
+
+There is another variable, ``NACLLOG``, that you can use to redirect Native
+Client's internally-generated messages. This variable is set to stderr by
+default; you can redirect these messages to an output file by setting the
+variable as follows:
+
+* ``NACLLOG=c:\nacl.log``
+
+.. Note::
+ :class: note
+
+ **Note:** If you set the NACL_EXE_STDOUT, NACL_EXE_STDERR, or NACLLOG
+ variables to redirect output to a file, you must run Chrome with the
+ ``--no-sandbox`` flag. You must also be careful that each variable points to
+ a different file.
+
+Redirecting output to the JavaScript console
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can also cause output from printf statements in your C/C++ code to be
+relayed to the JavaScript side of your application through the Pepper messaging
+system, where you can then write the output to the JavaScript console. Follow
+these steps:
+
+#. Set the NACL_EXE_STDOUT and NACL_EXE_STDERR environment variables as
+ follows:
+
+ * NACL_EXE_STDOUT=DEBUG_ONLY:dev://postmessage
+ * NACL_EXE_STDERR=DEBUG_ONLY:dev://postmessage
+
+ These settings tell Native Client to use PostMessage() to send output that
+ your Native Client module writes to stdout and stderr to the JavaScript side
+ of your application.
+
+#. Register a JavaScript handler to receive messages from your Native Client
+ module:
+
+ .. naclcode::
+
+ <div id="nacl_container">
+ <script type="text/javascript">
+ var container = document.getElementById('nacl_container');
+ container.addEventListener('message', handleMessage, true);
+ </script>
+ <embed id="nacl_module"
+ src="my_application.nmf"
+ type="application/x-nacl" />
+ </div>
+
+#. Implement a simple JavaScript handler that logs the messages it receives to
+ the JavaScript console:
+
+ .. naclcode::
+
+ function handleMessage(message_event) {
+ console.log(message_event.data);
+ }
+
+ This handler works in the simple case where the only messages your Native
+ Client module sends to JavaScript are messages with the output from stdout
+ and stderr. If your Native Client module also sends other messages to
+ JavaScript, your handler will need to be more complex.
+
+ Once you've implemented a message handler and set up the environment
+ variables as described above, you can check the JavaScript console to see
+ output that your Native Client module prints to stdout and stderr. Keep in
+ mind that your module makes a call to PostMessage() every time it flushes
+ stdout or stderr. Your application's performance will degrade considerably
+ if your module prints and flushes frequently, or if it makes frequent Pepper
+ calls to begin with (e.g., to render).
+
+Logging calls to Pepper interfaces
+----------------------------------
+
+You can log all Pepper calls your module makes by passing the following flags
+to Chrome on startup::
+
+ --vmodule=ppb*=4 --enable-logging=stderr
+
+
+The ``vmodule`` flag tells Chrome to log all calls to C Pepper interfaces that
+begin with "ppb" (that is, the interfaces that are implemented by the browser
+and that your module calls). The ``enable-logging`` flag tells Chrome to log
+the calls to stderr.
+
+.. _visual_studio:
+
+Debugging with Visual Studio
+----------------------------
+
+If you develop on a Windows platform you can use the Native :doc:`Client Visual
+Studio add-in <vs-addin>` to write and debug your code. The add-in defines new
+project platforms that let you run your module in two different modes: As a
+Pepper plugin and as a Native Client module. When running as a Pepper plugin
+you can use the built-in Visual Studio debugger. When running as a Native
+Client module Visual Studio will launch an instance of nacl-gdb for you and
+link it to the running code.
+
+Debugging with nacl-gdb
+-----------------------
+
+The Native Client SDK includes a command-line debugger that you can use to
+debug Native Client modules. The debugger is based on the GNU debugger `gdb
+<http://www.gnu.org/software/gdb/>`_, and is located at
+``toolchain/<platform>_<architecture>_<library>/bin/<prefix>-nacl-gdb``, where:
+
+* *<platform>* is the platform of your development machine (win, mac, or linux)
+* *<architecture>* is your target architecture (x86 or arm)
+* *<library>* is the C library you are compiling with (newlib or glibc)
+* *<prefix>* depends on the module you are debugging (i686- for x86 32-bit
+ modules, x86_64- for x86 64-bit modules, arm- for ARM modules)
+
+For example, to debug an x86 64-bit module built with glibc on Windows, you
+would use ``toolchain/win_x86_glibc/bin/x86_64-nacl-gdb``.
+
+.. Note::
+ :class: note
+
+ **Prerequisites for using nacl-gdb**:
+
+ * You must use the pepper_23 bundle (or greater) in the SDK.
+ * Your version of Chrome must be greater than or equal to the Pepper bundle
+ that you are using. For example, if you are using the pepper_23 bundle, you
+ must use Chrome 23 or greater. Type about:chrome in the Chrome address bar
+ to find out what version of Chrome you have. You may want to install and
+ use Chrome Canary on Windows and Mac OS; it's the newest version of Chrome
+ that's available, and it runs side-by-side with your current version of
+ Chrome.
+
+Before you start using nacl-gdb, make sure you can :doc:`build <building>` your
+module and :doc:`run <running>` your application normally. This will verify
+that you have created all the required :doc:`application parts
+<../coding/application-structure>` (.html, .nmf, and .nexe files, shared
+libraries, etc.), that your server can access those resources, and that you've
+configured Chrome correctly to run your application. The instructions below
+assume that you are using a :ref:`local server <web_server>` to run your
+application; one benefit of doing it this way is that you can check the web
+server output to confirm that your application is loading the correct
+resources. However, some people prefer to run their application as an unpacked
+extension, as described in :doc:`Running Native Client Applications <running>`.
+
+Follow the instructions below to debug your module with nacl-gdb:
+
+#. Compile your module with the ``-g`` flag so that your .nexe retains symbols
+ and other debugging information (see the :ref:`recommended compile flags
+ <compile_flags>`).
+#. Launch a local web server (e.g., the :ref:`web server <web_server>` included
+ in the SDK).
+#. Launch Chrome with these three required flags: ``--enable-nacl --enable-nacl-debug --no-sandbox``.
+
+ You may also want to use some of the optional flags listed below. A typical
+ command looks like this::
+
+ chrome --enable-nacl --enable-nacl-debug --no-sandbox --disable-hang-monitor localhost:5103
+
+ **Required flags:**
+
+ ``--enable-nacl``
+ Enables Native Client for all applications, including those that are
+ launched outside the Chrome Web Store.
+
+ ``--enable-nacl-debug``
+ Turns on the Native Client debug stub, opens TCP port 4014, and pauses
+ Chrome to let the debugger connect.
+
+ ``--no-sandbox``
+ Turns off the Chrome sandbox (not the Native Client sandbox). This enables
+ the stdout and stderr streams, and lets the debugger connect.
+
+ **Optional flagsa:**
+
+ ``--disable-hang-monitor``
+ Prevents Chrome from displaying a warning when a tab is unresponsive.
+
+ ``--user-data-dir=<directory>``
+ Specifies the `user data directory
+ <http://www.chromium.org/user-experience/user-data-directory>`_ from which
+ Chrome should load its state. You can specify a different user data
+ directory so that changes you make to Chrome in your debugging session do
+ not affect your personal Chrome data (history, cookies, bookmarks, themes,
+ and settings).
+
+ ``<URL>``
+ Specifies the URL Chrome should open when it launches. The local server
+ that comes with the SDK listens on port 5103 by default, so the URL when
+ you're debugging is typically ``localhost:5103`` (assuming that your
+ application's page is called index.html and that you run the local server
+ in the directory where that page is located).
+
+#. Navigate to your application's page in Chrome. (You don't need to do this if
+ you specified a URL when you launched Chrome in the previous step.) Chrome
+ will start loading the application, then pause and wait until you start
+ nacl-gdb and run the ``continue`` command.
+
+#. Go to the directory with your source code, and run nacl-gdb from there. For
+ example::
+
+ cd <NACL_SDK_ROOT>/examples/hello_world_gles
+ <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb
+
+ The debugger will start and show you a gdb prompt::
+
+ (gdb)
+
+#. Run the following three commands from the gdb command line::
+
+ (gdb) nacl-manifest <path-to-your-.nmf-file>
+ (gdb) nacl-irt <path-to-Chrome-NaCl-integrated-runtime>
+ (gdb) target remote localhost:4014
+
+ These commands are described below:
+
+ ``nacl-manifest <path>``
+ Tells the debugger about your Native Client application by pointing it to
+ the application's manifest (.nmf) file. The manifest file lists your
+ application's executable (.nexe) files, as well as any libraries that are
+ linked with the application dynamically.
+
+ ``nacl-irt <path>``
+ Tells the debugger where to find the Native Client Integrated Runtime
+ (IRT). The IRT is located in the same directory as the Chrome executable,
+ or in a subdirectory named after the Chrome version. For example, if
+ you're running Chrome canary on Windows, the path to the IRT typically
+ looks something like ``C:/Users/<username>/AppData/Local/Google/Chrome
+ SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe``.
+
+ ``target remote localhost:4014``
+ Tells the debugger how to connect to the debug stub in the Native Client
+ application loader. This connection occurs through TCP port 4014 (note
+ that this port is distinct from the port which the local web server uses
+ to listen for incoming requests, typically port 5103).
+
+ A couple of notes on how to specify path names in the nacl-gdb commands
+ above:
+
+ * You can use a forward slash to separate directories on Linux, Mac, and
+ Windows. If you use a backslash to separate directories on Windows, you
+ must escape the backslash by using a double backslash "\\" between
+ directories.
+ * If any directories in the path have spaces in their name, you must put
+ quotation marks around the path.
+
+ As an example, here is a what these nacl-gdb commands might look like on
+ Windows::
+
+ nacl-manifest "C:/<NACL_SDK_ROOT>/examples/hello_world_gles/newlib/Debug/hello_world_gles.nmf"
+ nacl-irt "C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe"
+ target remote localhost:4014
+
+ To save yourself some typing, you can put put these nacl-gdb commands in a
+ script file, and execute the file when you run nacl-gdb, like so::
+
+ <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb -x <nacl-script-file>
+
+ If nacl-gdb connects successfully to Chrome, it displays a message such as
+ the one below, followed by a gdb prompt::
+
+ 0x000000000fc00200 in _start ()
+ (gdb)
+
+ If nacl-gdb can't connect to Chrome, it displays a message such as
+ "``localhost:4014: A connection attempt failed``" or "``localhost:4014:
+ Connection timed out.``" If you see a message like that, make sure that you
+ have launched a web server, launched Chrome, and navigated to your
+ application's page before starting nacl-gdb.
+
+Once nacl-gdb connects to Chrome, you can run standard gdb commands to execute
+your module and inspect its state. Some commonly used commands are listed
+below.
+
+``break <location>``
+ set a breakpoint at <location>, e.g.::
+
+ break hello_world.cc:79
+ break hello_world::HelloWorldInstance::HandleMessage
+ break Render
+
+``continue``
+ resume normal execution of the program
+
+``next``
+ execute the next source line, stepping over functions
+
+``step``
+ execute the next source line, stepping into functions
+
+``print <expression>``
+ print the value of <expression> (e.g., variables)
+
+``backtrace``
+ print a stack backtrace
+
+``info breakpoints``
+ print a table of all breakpoints
+
+``delete <breakpoint>``
+ delete the specified breakpoint (you can use the breakpoint number displayed
+ by the info command)
+
+``help <command>``
+ print documentation for the specified gdb <command>
+
+``quit``
+ quit gdb
+
+See the `gdb documentation
+<http://sourceware.org/gdb/current/onlinedocs/gdb/#toc_Top>`_ for a
+comprehensive list of gdb commands. Note that you can abbreviate most commands
+to just their first letter (``b`` for break, ``c`` for continue, and so on).
+
+To interrupt execution of your module, press <Ctrl-c>. When you're done
+debugging, close the Chrome window and type ``q`` to quit gdb.
+
+Debugging with other tools
+==========================
+
+If you cannot use the :ref:`Visual Studio add-in <visual_studio>`, or you want
+to use a debugger other than nacl-gdb, you must manually build your module as a
+Pepper plugin (sometimes referred to as a `"trusted
+<http://www.chromium.org/nativeclient/getting-started/getting-started-background-and-basics#TOC-Trusted-vs-Untrusted>`_"
+or "in-process" plugin). Pepper plugins (.DLL files on Windows; .so files on
+Linux; .bundle files on Mac) are loaded directly in either the Chrome renderer
+process or a separate plugin process, rather than in Native Client. Building a
+module as a trusted Pepper plugin allows you to use standard debuggers and
+development tools on your system, but when you're finished developing the
+plugin, you need to port it to Native Client (i.e., build the module with one
+of the toolchains in the NaCl SDK so that the module runs in Native Client).
+For details on this advanced development technique, see `Debugging a Trusted
+Plugin
+<http://www.chromium.org/nativeclient/how-tos/debugging-documentation/debugging-a-trusted-plugin>`_.
+Note that starting with the ``pepper_22`` bundle, the NaCl SDK for Windows
+includes pre-built libraries and library source code, making it much easier to
+build a module into a .DLL.
+
+Open source profiling tools
+---------------------------
+
+For the brave-hearted there are open source tools at `Chromium.org
+<http://www.chromium.org/nativeclient>`_ that describe how to do profiling on
+`64-bit Windows
+<https://sites.google.com/a/chromium.org/dev/nativeclient/how-tos/profiling-nacl-apps-on-64-bit-windows>`_
+and `Linux
+<http://www.chromium.org/nativeclient/how-tos/limited-profiling-with-oprofile-on-x86-64>`_
+machines.
+
+
+
+
+
+
+.. |menu-icon| image:: /images/menu-icon.png
+.. |puzzle| image:: /images/puzzle.png
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 c19fa8244a..a0f8255b54 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/dynamic-loading.rst
@@ -10,6 +10,14 @@ Dynamic Linking and Loading with glibc
Introduction
============
+.. Note::
+ :class: caution
+
+ Portable Native Client currently only supports static linking, and the
+ only C library available for it is newlib. This page is only valid for
+ Native Client, though PNaCl will eventually support some form of
+ dynamic linking.
+
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
diff --git a/native_client_sdk/src/doc/devguide/devcycle/running.rst b/native_client_sdk/src/doc/devguide/devcycle/running.rst
index 28739e0b08..17d8ad5e49 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/running.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/running.rst
@@ -4,4 +4,430 @@
Running
#######
-foo
+.. contents:: Table Of Contents
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Introduction
+============
+
+This document describes how to run Native Client applications during
+development.
+
+Before reading about how to run Native Client applications, it's important to
+understand a little bit about how Native Client applications are distributed.
+As explained in :doc:`Distributing Your Application <../distributing>`, Native
+Client applications must currently be distributed through the **Chrome Web
+Store (CWS)**. Applications in the CWS are one of three types:
+
+* A **hosted application** is an application that you host on a server of your
+ choice. To distribute an application as a hosted application, you upload
+ application metadata to the CWS.
+
+* A **packaged application** is an application that is hosted in the CWS and
+ downloaded to the user's machine. To distribute an application as a packaged
+ application, you upload the entire application, including all application
+ assets and metadata, to the CWS.
+
+* An **extension** is a packaged application that has a tiny UI component
+ (extensions are typically used to extend the functionality of the Chrome
+ browser). To distribute an application as an extension, you upload the entire
+ application, including all application assets and metadata, to the CWS.
+
+It's clearly not convenient to package and upload files to the Chrome Web Store
+every time you want to run a new build of your application, but there are four
+alternative techniques you can use to run the application during development.
+These techniques are listed in the following table and described in detail
+below. Each technique has certain requirements (NaCl flag, web server, and/or
+CWS metadata); these are explained in the :ref:`Requirements <requirements>`
+section below.
+
++-----------+----------------------+---------------------+-----------------------+-------------+
+| Technique | Requires NaCl flag | Requires web server | Requires CWS metadata | Description |
++===========+======================+=====================+=======================+=============+
+| 1 | local server | | | |
++-----------+----------------------+---------------------+-----------------------+-------------+
+| 2 | packaged application | | | |
+| | loaded as an | | | |
+| | unpacked extension | | | |
++-----------+----------------------+---------------------+-----------------------+-------------+
+| 3 | hosted application | | | |
+| | loaded as an unpacked| | | |
+| | extension | | | |
++-----------+----------------------+---------------------+-----------------------+-------------+
+| 4 | Chrome Web Store | | | |
+| | application with | | | |
+| | trusted testers | | | |
++-----------+----------------------+---------------------+-----------------------+-------------+
+
+Which of the above techniques you use to run your application during
+development is largely a matter of personal preference (i.e., would you rather
+start a local server or create CWS metadata?). As a general rule, once you have
+an idea of how you plan to distribute your application, you should use the
+corresponding technique during development (technique # 2 for packaged
+applications and extensions; technique # 3 for hosted applications). Choosing a
+distribution option depends on a number of factors such as application size,
+application start-up time, hosting costs, offline functionality, etc. (see
+:doc:`Distributing Your Application <../distributing>` for details), but you
+don't need to make a decision about how to distribute your application at the
+outset.
+
+The next two sections of this document describe a couple of prerequisites for
+running applications during development (using the correct version of Chrome
+and turning off the Chrome cache), and explain the three requirements listed in
+the table above (NaCl flag, web server, and CWS metadata). The subsequent
+sections of the document provide instructions for how to use each of the four
+techniques.
+
+Prerequisites
+=============
+
+Browser and Pepper versions
+---------------------------
+
+Before you run a new build of your application, make sure that you're using the
+correct version of Chrome. Each version of Chrome supports a corresponding
+version of the Pepper API. You (and your users) must use a version of Chrome
+that is equal to or higher than the version of the Pepper API that your
+application uses. For example, if you compiled your application using the
+``pepper_28`` bundle, your application uses the Pepper 28 API, and you must run
+the application in Chrome 28 or higher. To check which version of Chrome you're
+using, type ``about:chrome`` or ``about:version`` in the Chrome address bar
+(the latter address shows additional information such as the Chrome command
+line and profile path).
+
+If your application requires a minimum version of Chrome, you are encouraged to
+include code in the application to check that the user's browser is compatible
+with the application. For sample code that checks the user's browser version,
+refer to the ``load_progress`` example in the Native Client SDK.
+
+Chrome Cache
+------------
+
+Chrome caches resources aggressively. You should disable Chrome's cache
+whenever you are developing a Native Client application in order to make sure
+Chrome loads new versions of your application. To disable the cache:
+
+#. Open Chrome's developer tools by clicking the menu icon |menu-icon| and
+ choosing **Tools > Developer tools**.
+#. Click the gear icon in the bottom right corner of the Chrome window.
+#. Under the "General" settings, check the box next to "Disable cache".
+
+.. _requirements:
+
+Requirements
+============
+
+.. _flag:
+
+Native Client flag
+------------------
+
+Native Client is automatically enabled for applications that are installed from
+the Chrome Web Store. To enable Native Client for applications that are not
+installed from the Chrome Web Store, you must explicitly turn on the Native
+Client flag in Chrome as follows:
+
+#. Type ``about:flags`` in the Chrome address bar.
+#. Scroll down to "Native Client".
+#. If the link below "Native Client" says "Disable", then Native Client is
+ already enabled and you don't need to do anything else.
+#. If the link below "Native Client" says "Enable":
+
+ * Click the "Enable" link.
+ * Scroll down to the bottom of the page and click the "Relaunch Now" button.
+ **Native Client will not be enabled until you relaunch your browser**. All
+ browser windows will restart when you relaunch Chrome.
+
+If you enable the Native Client flag and still can't run applications from
+outside the Chrome Web Store, you may need to enable the Native Client plugin:
+
+#. Type ``about:plugins`` in the Chrome address bar.
+#. Scroll down to "Native Client".
+#. If the link below "Native Client" says "Enable", click the link to enable
+ the Native Client plugin. You do not need to relaunch Chrome after enabling
+ the Native Client plugin.
+
+
+.. _web_server:
+
+Web server
+----------
+
+For security reasons, Native Client applications must come from a server (you
+can't simply drag HTML files into your browser). The Native Client SDK comes
+with a lightweight Python web server that you can run to serve your application
+locally. The server is included in the ``examples`` directory in the SDK
+bundles (e.g., ``pepper_28/examples``). Here is how to run the server:
+
+* Windows::
+
+ cd examples
+ httpd.cmd
+
+* Mac, Linux::
+
+ cd examples
+ python httpd.py
+
+By default, the server listens for requests on port 5103. To use a different
+port, simply specify a different port number, e.g.: ``python httpd.py 5104``.
+
+You can use the server to run any application under the ``examples`` directory
+where you started the server. For example, to run the
+``hello_world_interactive`` example in the SDK, start the server as described
+above and point your browser to
+http://localhost:5103/hello_world_interactive/hello_world.html.
+
+.. _metadata:
+
+Chrome Web Store metadata
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Applications published in the Chrome Web Store must be accompanied by CWS
+metadata—specifically, a Chrome Web Store manifest file named
+``manifest.json``, and at least one icon.
+
+Below is an example of a CWS manifest file for a **hosted application**::
+
+ {
+ "name": "My NaCl App",
+ "description": "Simple game implemented using Native Client",
+ "version": "0.1",
+ "icons": {
+ "128": "nacl_icon_128.jpg"
+ },
+ "app": {
+ "urls": [
+ "http://mysubdomain.example.com/"
+ ],
+ "launch": {
+ "web_url": "http://mysubdomain.example.com/my_app_main_page.html"
+ }
+ }
+ }
+
+
+For a **packaged application**, you can omit the urls field, and replace the
+``web_url`` field with a ``local_path`` field, as shown below::
+
+ {
+ "name": "My NaCl App",
+ "description": "Simple game implemented using Native Client",
+ "version": "0.1",
+ "icons": {
+ "16": "nacl_icon_16.jpg",
+ "128": "nacl_icon_128.jpg"
+ },
+ "app": {
+ "launch": {
+ "local_path": "my_app_main_page.html"
+ }
+ }
+ }
+
+You must put the ``manifest.json`` file in the same directory as your
+application's main HTML page.
+
+If you don't have icons for your application, you can use the following icons
+as placeholders: nacl_icon_16.jpg and nacl_icon_128.jpg. Put the icons in the
+same directory as the CWS manifest file.
+
+For more information about CWS manifest files and application icons, see:
+
+* `Chrome Web Store Tutorial: Getting Started
+ <https://developers.google.com/chrome/web-store/docs/get_started_simple>`_
+* `Chrome Web Store Formats: Manifest Files
+ <http://code.google.com/chrome/extensions/manifest.html>`_
+
+Technique 1: Local server
+=========================
+
+To run your application from a local server:
+
+* Enable the :ref:`Native Client flag <flag>` in Chrome.
+* Start a :ref:`local web server <web_server>`.
+* Put your application under the examples directory in the SDK bundle you are
+ using (e.g., in the directory ``pepper_28/examples/my_app``).
+* Access your application on the local server by typing the location of its
+ HTML file in Chrome, e.g.:
+ ``http://localhost:5103/my_app/my_app_main_page.html``.
+
+.. Note::
+ :class: note
+
+ **Note:** You don't have to use a local web server---you can use another
+ server if you already have one running. You must still enable the Native
+ Client flag in order to run your application from your server.
+
+Technique 2: Packaged application loaded as an unpacked extension
+=================================================================
+
+For development purposes, Chrome lets you load a packaged application as an
+unpacked extension. To load and run your packaged application as an unpacked
+extension:
+
+#. Create a Chrome Web Store manifest file and one or more icons for your
+ application.
+
+ * Follow the instructions above under Chrome Web Store metadata to create
+ these files.
+ * Note that the CWS manifest file should contain the ``local_path`` field
+ rather than the ``web_url`` field.
+#. Put the CWS manifest file and the application icon(s) in the same directory
+ as your application's main HTML page.
+#. Load the application as an unpacked extension in Chrome:
+
+ * Bring up the extensions management page in Chrome by clicking the menu
+ icon |menu-icon| and choosing **Tools > Extensions**.
+ * Check the box for **Developer mode** and then click the **Load unpacked
+ extension** button:
+ |extensions|
+ * In the file dialog that appears, select your application directory. Unless
+ you get an error dialog, you've now installed your app in Chrome.
+#. Open a new tab in Chrome and click the **Apps** link at the bottom of the
+ page to show your installed apps:
+ |new-tab-apps|
+#. The icon for your newly installed app should appear on the New Tab page.
+ Click the icon to launch the app.
+
+For additional information about how to create CWS metadata and load your
+application into Chrome (including troubleshooting information), see the
+`Chrome Web Store Tutorial: Getting Started
+<https://developers.google.com/chrome/web-store/docs/get_started_simple>`_.
+
+Technique 3: Hosted application loaded as an unpacked extension
+===============================================================
+
+
+For development purposes, Chrome lets you load a hosted application as an
+unpacked extension. To load and run your hosted application as an unpacked
+extension:
+
+#. Start a web server to serve your application.
+
+ * You can use the :ref:`local web server <web_server>` included with the
+ Native Client SDK if you want.
+#. Upload your application (.html, .nmf, .nexe, .css, .js, image files, etc.)
+ to the server.
+
+ * If you're using the local server included with the Native Client SDK,
+ simply put your application under the ``examples`` directory in the SDK
+ bundle you are using (e.g., in the directory
+ ``pepper_28/examples/my_app``).
+#. Create a Chrome Web Store manifest file and one or more icons for your
+ application.
+
+ * Follow the instructions above under :ref:`Chrome Web Store metadata
+ <metadata>` to create these files.
+ * In the CWS manifest file, the ``web_url`` field should specify the
+ location of your application on your server. If you're using the local
+ server included with the SDK, the ``web_url`` field should look something
+ like ``http://localhost:5103/my_app/my_app_main_page.html``.
+#. Put the CWS manifest file and the application icon(s) in the same directory
+ as your application's main HTML page.
+#. Load the application as an unpacked extension in Chrome:
+
+ * Bring up the extensions management page in Chrome by clicking the menu
+ icon |menu-icon| and choosing **Tools > Extensions**.
+ * Check the box for **Developer mode** and then click the **Load unpacked
+ extension** button:
+ |extensions|
+ * In the file dialog that appears, select your application directory. Unless
+ you get an error dialog, you've now installed your app in Chrome.
+#. Open a new tab in Chrome and click the **Apps** link at the bottom of the
+ page to show your installed apps:
+ |new-tab-apps|
+#. The icon for your newly installed app should appear on the New Tab page.
+ Click the icon to launch the app.
+
+For additional information about how to create CWS metadata and load your
+application into Chrome (including troubleshooting information), see the
+`Chrome Web Store Tutorial: Getting Started
+<https://developers.google.com/chrome/web-store/docs/get_started_simple>`_.
+
+Technique 4: Chrome Web Store application with trusted testers
+==============================================================
+
+When you're ready to test your application more broadly, you can upload the
+application to the Chrome Web Store and let some trusted testers run it. Here
+is how to do so:
+
+#. Create the Chrome Web Store metadata required to publish your application:
+
+ * First, create a Chrome Web Store manifest file and one or more icons for
+ your application, as described above under :ref:`Chrome Web Store metadata
+ <metadata>`. Note that packaged applications must have at least two icons
+ (a 16x16 icon and a 128x128 icon).
+ * You also need to create the following additional assets before you can publish your application:
+
+ * a screenshot (size must be 640x400 or 1280x800)
+ * a promotional image called a "small tile" (size must be 440x280)
+
+#. For a **packaged application**:
+
+ * Create a zip file with the CWS manifest file, the application icons, and
+ all your application files (.html, .nmf, .nexe, .css, .js, image files,
+ etc.)
+
+#. For a **hosted application**:
+
+ * Create a zip file with the CWS manifest file and the application icon(s).
+ * Upload the application files (.html, .nmf, .nexe, .css, .js, image files,
+ etc.) to the server on which the application is being hosted.
+ * Use `Google Webmaster Tools <http://www.google.com/webmasters/tools/>`_ to
+ verify ownership of the web site on which the application runs.
+
+#. Log in to the `Chrome Web Store Developer Dashboard
+ <https://chrome.google.com/webstore/developer/dashboard>`_.
+
+ * The first time you log in, click the "Add new item" button to display the
+ Google Chrome Web Store Developer Agreement. Review and accept the
+ agreement and then return to the `Developer Dashboard
+ <https://chrome.google.com/webstore/developer/dashboard>`_.
+
+#. Click "Edit your tester accounts" at the bottom of the Developer Dashboard.
+#. Enter a series of email addresses for your testers (separated by commas or
+ whitespace), and click the "Save Changes" button.
+#. Click the "Add new item" button to add your application to the Chrome Web
+ Store.
+#. Click the "Choose file" button and select the zip file you created earlier.
+#. Click the "Upload" button; this uploads your zip file and opens the "Edit
+ item" page.
+#. Edit the following required fields on the "Edit item" page:
+
+ * Upload an application icon.
+ * Upload a screenshot.
+ * Upload a small tile.
+ * Select a category for your application (accounting application, action
+ game, etc.).
+ * Select a language for your application.
+#. If you are an owner or manager of a Google Group, you can select that group
+ in the "Trusted testers" field.
+
+ * You may want to create a Google Group specifically for your testers. When
+ you add a group to the "Trusted testers" field, all group members will be
+ able to test the application, in addition to the individuals you added to
+ the "trusted tester accounts" field on the Developer Dashboard.
+#. Click the "Publish to test accounts" button at the bottom of the page and
+ click "OK".
+#. A page comes up that shows your application's listing in the Chrome Web
+ Store. Copy the URL and mail it to your trusted testers.
+
+ * When you publish an application to test accounts, the application's CWS
+ listing is visible only to you and to people who are logged into those
+ accounts. Your application won't appear in search results, so you need to
+ give testers a direct link to your application's CWS listing. Users won't
+ be able to find the application by searching in the CWS.
+
+To publish an application to the world after publishing it to test accounts,
+you must first unpublish the application. For additional information see
+`Publishing Your App
+<https://developers.google.com/chrome/web-store/docs/publish>`_, and in
+particular `Publishing to test accounts
+<https://developers.google.com/chrome/web-store/docs/publish#testaccounts>`_.
+
+.. |menu-icon| image:: /images/menu-icon.png
+.. |extensions| image:: /images/extensions-management.png
+.. |new-tab-apps| image:: /images/new-tab-apps.png
diff --git a/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst b/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst
new file mode 100644
index 0000000000..d09b6b5f95
--- /dev/null
+++ b/native_client_sdk/src/doc/devguide/devcycle/vs-addin.rst
@@ -0,0 +1,8 @@
+############################
+Debugging With Visual Studio
+############################
+
+.. contents:: Table Of Contents
+ :local:
+ :backlinks: none
+ :depth: 2
diff --git a/native_client_sdk/src/doc/faq.rst b/native_client_sdk/src/doc/faq.rst
index 0d7eecec0a..44760dd92a 100644
--- a/native_client_sdk/src/doc/faq.rst
+++ b/native_client_sdk/src/doc/faq.rst
@@ -4,7 +4,6 @@
Frequently Asked Questions
##########################
-
.. contents::
:local:
:backlinks: none
@@ -20,6 +19,7 @@ If you have questions that aren't covered in this FAQ:
* Scan through the :doc:`Release Notes <sdk/release-notes>`.
* Search through or ask on the :doc:`Native Client Forums <help>`.
+
What is Native Client Good For?
===============================
@@ -29,16 +29,44 @@ Why did Google build Native Client?
* **Performance:** Native Client modules run nearly as fast as native
compiled code.
* **Security:** Native Client lets users run native compiled code in the
- browser with the same level of security as traditional web apps. Users
- get the performance boost of running compiled code without having to
- install a plugin.
-* **Convenience:** Developers can leverage existing C and C++ code in
- their web apps.
-* **Portability:** Native Client applications run on Windows, Mac, and
- Linux. When development of `Portable Native Client
- <http://nativeclient.googlecode.com/svn/data/site/pnacl.pdf>`__.
- (PDF) is complete, Native Client applications will also be
- processor-independent.
+ browser with the same level of security and privacy as traditional web
+ applications.
+* **Convenience:**
+
+ * Developers can leverage existing code, written in C/C++ or other
+ languages, in their applications without forcing users to install a
+ plugin.
+ * This code can interact with the embedding web page as part of an
+ HTML and JavaScript web application, or it can be a self-contained
+ and immersive experience.
+
+* **Portability:** Native Client and Portable Native Client applications
+ can execute on:
+
+ * The Windows, Mac, Linux or ChromeOS operating systems.
+ * Processors with the x86-32, x86-64, or ARM instruction set
+ architectures. Native Client also has experimental support for MIPS.
+
+Portable Native client further enhances the above:
+
+* **Performance:** Each PNaCl release brings with it more performance
+ enhancements. Already-released applications get faster over time,
+ conserving user's battery.
+* **Security:** Users are kept secure with an ever-improving sandbox
+ model which adapts to novel attacks, without affecting
+ already-released applications.
+* **Convenience:** Developers only need to ship a single ``.pexe`` file,
+ not one ``.nexe`` file per supported architecture.
+* **Portability:** Developers and users don't need to worry about
+ already-released applications not working on new hardware: PNaCl
+ already supports all architectures NaCl does, and as PNaCl evolves it
+ gains support for new processors and fully uses their capabilities.
+
+.. TODO Expand on the PNaCl performance section in another document, and
+.. link to it here.
+
+For more details, refer to the :doc:`history behind and comparison of
+NaCl and PNaCl <nacl-and-pnacl>`.
When should I use Native Client?
--------------------------------
@@ -46,25 +74,31 @@ When should I use Native Client?
The following are some typical use cases. For details, see the
:doc:`Technical Overview <overview>`.
-* Porting existing software components for use in a web app.
+* Porting existing software components for use in a web application.
* Porting legacy desktop applications.
* Handling browser-side encryption and decryption for an enterprise
application.
-* Handling multimedia for a web app.
+* Handling multimedia for a web application.
* Handling various aspects of web-based games, including physics engines
and AI.
Native Client is a versatile technology; we expect that it will also be
-used in many other contexts.
+used in many other contexts outside of Chrome.
+
+When should I use Portable Native Client?
+-----------------------------------------
+
+See :doc:`NaCl and PNaCl <nacl-and-pnacl>`. In short: PNaCl works on the
+open web whereas NaCl only works on the Chrome Web Store.
How fast does code run in Native Client?
----------------------------------------
-Fast! Initial benchmarks on x86-32 measured an average performance
-overhead of less than 5% compared to native C/C++ on applications such
-as Quake, bzip2, and Google Earth. For details of those benchmarks, see
-`Native Client: A Sandbox for Portable, Untrusted x86 Code
-<http://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
+Fast! Benchmarks on x86-32 measured an average performance overhead of
+less than 5% compared to native C/C++ on applications such as Quake,
+bzip2, and Google Earth. For details of those benchmarks, see `Native
+Client: A Sandbox for Portable, Untrusted x86 Code
+<https://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
(PDF).
Benchmarks on x86-64 and ARM measured an average performance overhead of
@@ -73,75 +107,108 @@ bimodal for x86-64, so different use cases are likely to achieve either
significantly better or significantly worse performance than that
average. For details, see `Adapting Software Fault Isolation to
Contemporary CPU Architectures
-<http://nativeclient.googlecode.com/svn/data/site/NaCl_SFI.pdf>`_ (PDF).
+<https://nativeclient.googlecode.com/svn/data/site/NaCl_SFI.pdf>`_ (PDF).
+
+.. TODO Update performance numbers.
+
+If your code isn't performing as close to native speed as you'd expect,
+:doc:`let us know <help>`!
+
+Why use Portable Native Client instead of *<technology X>*?
+-----------------------------------------------------------
-Why use Native Client instead of Flash, Java, Silverlight, ActiveX, .NET, or other such technologies?
------------------------------------------------------------------------------------------------------
+Many other technologies can be compared to Portable Native Client:
+Flash, Java, Silverlight, ActiveX, .NET, asm.js, etc...
Different technologies have different strengths and weaknesses. In
-appropriate contexts, Native Client can be faster, more secure, and/or
-more compatible across operating systems than some other technologies.
+appropriate contexts, Portable Native Client can be faster, more secure,
+and/or more compatible across operating systems and architectures than
+other technologies.
-Native Client complements other technologies by giving web developers a
-new capability: the ability to run fast, native code from a web browser.
+Portable Native Client complement other technologies by giving web
+developers a new capability: the ability to run fast, secure native code
+from a web browser in an architecture-independent way.
If I want direct access to the OS, should I use Native Client?
--------------------------------------------------------------
-No --- Native Client does not provide direct access to the OS or
-devices, or otherwise bypass the JavaScript security model. For more
-information, see later sections of this FAQ.
+No---Native Client does not provide direct access to the OS or devices,
+or otherwise bypass the JavaScript security model. For more information,
+see later sections of this FAQ.
+
Development Environments and Tools
==================================
-Can I develop on Windows/Mac/Linux? What development environment do you recommend?
-----------------------------------------------------------------------------------
+What development environment and development operating system do you recommend?
+-------------------------------------------------------------------------------
+
+You can develop on Windows, Mac, or Linux, and the resulting Native
+Client or Portable Native Client application will run inside the Google
+Chrome browser on all those platforms as well as ChromeOS. You can also
+develop on ChromeOS with `Crouton
+<https://github.com/dnschneid/crouton>`_, and we're working on
+self-hosting a full development environment on Portable Native Client.
+
+Any editor+shell combination should work as well as IDEs like Eclipse,
+Visual Studio with the `Native Client Add-In
+<https://developers.google.com/native-client/dev/devguide/devcycle/vs-addin>`_
+on Windows, or Xcode on Mac OSX.
-Yes, you can develop on Windows, Mac, or Linux, and the resulting Native
-Client application will run inside the browser for Google Chrome users
-on all those platforms as well as ChromeOS.
+.. TODO: update link to Visual Studio when ReST-ified.
-On all three platforms, you can use Eclipse for C/C++ developers --- or
-you can simply use your own favorite editor and compile on the command
-line. If you're developing in Mac OS X, you can use Xcode. For Windows,
-we will be supporting Microsoft Visual Studio in a future release.
+I'm not familiar with native development tools, can I still use the Native Client SDK?
+--------------------------------------------------------------------------------------
-I'm not familiar with tools like GCC, make, Eclipse, Visual Studio, or Xcode. Can I still use the Native Client SDK?
---------------------------------------------------------------------------------------------------------------------
+You may find our :doc:`Tutorial <devguide/tutorial>` and :doc:`Building
+instructions <devguide/devcycle/building>` useful, and you can look at
+the code and Makefiles for the SDK examples to understand how the
+examples are built and run.
-You'll need to learn how to use some of those tools before you can get
-very far with the SDK. Try seaching for an `introduction to GCC
-<htp://www.google.com/search?q=gcc+introduction>`_.
+You'll need to learn how to use some tools (like GCC, LLVM, make,
+Eclipse, Visual Studio, or Xcode) before you can get very far with the
+SDK. Try seaching for an `introduction to GCC
+<https://www.google.com/search?q=gcc+introduction>`_.
-You may also find our :doc:`Tutorial <devguide/tutorial>` and
-:doc:`Building instructions <devguide/devcycle/building>` useful, and
-you can look at the code and Makefiles for the SDK examples to
-understand how the examples are built and run.
Openness, and Supported Architectures and Languages
===================================================
-
Is Native Client open? Is it a standard?
----------------------------------------
Native Client is completely open: the executable format is open and the
-source code is open. Right now the Native Client project is in its early
-stages, so it's premature to consider Native Client for standardization.
-
-What are the supported instruction set architectures? Will Native Client modules run only on Intel/AMD x86 processors? If so, why are you putting architecture-dependent technology on the web?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-Native Client modules currently run on the x86-32, x86-64, and ARM
-architectures, but an important goal of Native Client is to be
-platform-independent. We are developing a technology called `Portable
-Native Client
-<http://nativeclient.googlecode.com/svn/data/site/pnacl.pdf>`__ (PDF)
-that will provide an instruction-set-neutral format. With Portable
-Native Client we believe we can deliver a system that has comparable
-portability to JavaScript. The web is better when it's
-platform-independent, and we'd like it to stay that way.
+`source code is open <https://code.google.com/p/nativeclient/>`_. Right
+now the Native Client project is in its early stages, so it's premature
+to consider Native Client for standardization.
+
+We consistenly try to document our design and implementation and hope to
+standardize Portable Native Client when it gains more traction. A good
+example is our `PNaCl bitcode reference manual
+<http://www.chromium.org/nativeclient/pnacl/bitcode-abi>`_.
+
+.. TODO Update the above bitcode-abi link to a :doc: once 3693 is fixed.
+
+What are the supported instruction set architectures?
+-----------------------------------------------------
+
+Portable Native Client uses an architecture-independent format (the
+``.pexe``) which can currently be translated to execute on processors
+with the x86-32, x86-64, and ARM instruction set architectures, as well
+as experimental support for MIPS. As new architectures come along and
+become popular we expect Portable Native Client to support them without
+developers having to recompile their code.
+
+Native Client can currently execute on the same architectures as
+Portable Native Client but is only supported on the Chrome Web
+Store. Native Client's ``.nexe`` files are architecture-dependent and
+cannot adapt to new architectures without recompilation, we therefore
+deem them better suited to a web store than to the open web.
+
+With Portable Native Client we deliver a system that has comparable
+portability to JavaScript and can adapt to new instruction set
+architectures without requiring recompilation. The web is better when
+it's platform-independent, and we'd like it to stay that way.
Do I have to use C or C++? I'd really like to use another language.
-------------------------------------------------------------------
@@ -150,23 +217,30 @@ Right now only C and C++ are supported directly by the toolchain in the
SDK. C# and other languages in the .NET family are supported via the
`Mono port <https://github.com/elijahtaylor/mono>`_ for Native
Client. Moreover, there are several ongoing projects to support
-additional language runtimes as well as to compile more languages to
-LLVM, C, or C++.
+additional language runtimes (e.g. `naclports supports Lua, Python and
+Ruby
+<https://code.google.com/p/naclports/source/browse#svn%2Ftrunk%2Fsrc%2Fexamples%2Ftools>`_)
+as well as to compile more languages to LLVM's intermediate
+representation (e.g. support Haskell with `GHC
+<http://www.haskell.org/ghc/docs/latest/html/users_guide/code-generators.html>`_
+or support Fortran with `flang
+<https://flang-gsoc.blogspot.ie/2013/09/end-of-gsoc-report.html>`_), or
+transpile languages to C/C++ (source-to-source compilation).
If you're interested in getting other languages working, please contact
the Native Client team by way of the `native-client-discuss mailing list
-<http://groups.google.com/group/native-client-discuss>`_.
+<https://groups.google.com/group/native-client-discuss>`_.
Will you only support Chrome? What about other browsers?
--------------------------------------------------------
We aim to support multiple browsers. However, a number of features that
-we consider requirements for a production-quality system are difficult
-to implement without help from the browser. Specific examples are an
-out-of-process plugin architecture and appropriate interfaces for
-integrated 3D graphics. We have worked closely with Chromium developers
-to deliver these features and we would be eager to collaborate with
-developers from other browsers.
+we consider requirements for a production-quality system that keeps the
+user safe are difficult to implement without help from the
+browser. Specific examples are an out-of-process plugin architecture and
+appropriate interfaces for integrated 3D graphics. We have worked
+closely with Chromium developers to deliver these features and we are
+eager to collaborate with developers from other browsers.
What's the difference between NPAPI and Pepper?
-----------------------------------------------
@@ -184,83 +258,126 @@ NPAPI is not supported by the Native Client SDK, and is `deprecated in
Chrome
<http://blog.chromium.org/2013/09/saying-goodbye-to-our-old-friend-npapi.html>`_.
-Does Native Client support SSE and NEON?
+Does Native Client support SIMD vector instructions?
+----------------------------------------------------
+
+Native Client currently supports SSE on x86 and NEON on ARM. Support for
+AVX on x86 is under way.
+
+Portable Native Client should support SIMD vectors in the near future.
+
+Can I use Native Client for 3D graphics?
----------------------------------------
-Yes.
+Yes. Native Client supports `OpenGL ES 2.0
+<https://www.khronos.org/opengles/>`_.
+
+
+To alert the user regarding their hardware platform's 3D feature set
+before loading a large NaCl application, see `Vetting the driver in
+Javascript
+<https://developers.google.com/native-client/devguide/coding/3D-graphics>`_.
+
+.. TODO Update link to point to the right place in the document once
+.. it's ReST-ified.
+
+Some GL extensions are exposed to Native Client applications, see the
+`GL ES 2 file
+<https://src.chromium.org/viewvc/chrome/trunk/src/ppapi/lib/gl/gles2/gles2.c>`_.
+This file is part of the GL wrapper supplied by the library
+``ppapi_gles2`` which you'll want to include in your project. In most
+cases extensions map to extensions available on other platforms, or
+differ very slightly (if they differ, the extension is usually CHROMIUM
+or ANGLE instead of EXT).
+
+.. TODO Improve documentation for GL extensions.
+
+Does Native Client support concurrency/parallelism?
+---------------------------------------------------
+
+Native Client and Portable Native Client both support pthreads,
+C11/C++11 threads, and low-level synchronization primitives (mutex,
+barriers, atomic read/modify/write, compare-and-exchange, etc...), thus
+allowing your Native Client application to utilize several CPU cores.
+Note that this allows you to modify datastructures concurrently without
+needing to copy them, which is often a limitation of shared-nothing
+systems.
+
+Native Client doesn't support HTML5 Web Workers directly but can
+interact with JavaScript code which does.
+
+.. TODO Add link to relevant documentation, once written.
+
Coming Soon
===========
+Do Native Client modules have access to external devices?
+---------------------------------------------------------
-Do Native Client modules have access to serial ports, camera devices, or microphones?
--------------------------------------------------------------------------------------
-
-Not at this time; Native Client can only use native resources that
-today's browsers can access. However, we intend to recommend such
-features to the standards bodies and piggyback on their efforts to make
-these resources available inside the browser.
+At this time Native Client modules do not have access to serial ports,
+camera devices, or microphones: Native Client can only use native
+resources that today's browsers can access. However, we intend to
+recommend such features to the standards bodies and piggyback on their
+efforts to make these resources available inside the browser.
You can generally think of Pepper as the C/C++ bindings to the
capabilities of HTML5. The goal is for Pepper and JavaScript to evolve
together and stay on par with each other with respect to features and
capabilities.
-Can I use Native Client for 3D graphics?
-----------------------------------------
-
-Yes. Native Client supports `OpenGL ES 2.0
-<http://www.khronos.org/opengles/>`_.
-
-Does Native Client support HTML5 native Web Workers?
-----------------------------------------------------
-
-No, but we do support pthreads, thus allowing your Native Client app to
-utilize several CPU cores.
Security and Privacy
====================
-If I use Native Client, will Google collect my data, sell my data, own my application, trace the usage, or steal my dog?
-------------------------------------------------------------------------------------------------------------------------
+What happens to my data when I use Native Client?
+-------------------------------------------------
-No, none of the above. If you opt in to sending usage statistics in
-Chrome, then if Native Client crashes, Chrome will send debug
-information to Google. But crashes in your code won't send your
-information to Google; Google counts the number of such crashes, but
-does so anonymously.
+Users can opt-in to sending usage statistics and crash information in
+Chrome, which includes usage statistics and crash information about
+Native Client. Crashes in your code won't otherwise send your
+information to Google: Google counts the number of such crashes, but
+does so anonymously without sending your application's data or its debug
+information.
For additional information about privacy and Chrome, see the `Google
Chrome privacy policy
-<http://www.google.com/chrome/intl/en/privacy.html>`_ and the `Google
+<https://www.google.com/chrome/intl/en/privacy.html>`_ and the `Google
Chrome Terms of Service
-<http://www.google.com/chrome/intl/en/eula_text.html>`_.
+<https://www.google.com/chrome/intl/en/eula_text.html>`_.
-How does Native Client prevent sandboxed code from getting out and doing Bad Things? How can Google predict all possible code that could break out of the sandbox?
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
+How does Native Client prevent sandboxed code from doing Bad Things?
+--------------------------------------------------------------------
Native Client's sandbox works by validating the untrusted code (the
compiled Native Client module) before running it. The validator checks
the following:
-* Data integrity. No loads or stores are permitted outside of the data
- sandbox. In particular this means that once loaded into memory, the
- binary is not writable. This is enforced by operating system
+* **Data integrity:** No loads or stores are permitted outside of the
+ data sandbox. In particular this means that once loaded into memory,
+ the binary is not writable. This is enforced by operating system
protection mechanisms. While new instructions can be inserted at
runtime to support things like JIT compilers, such instructions will
be subject to runtime verification according to the following
constraints before they are executed.
-* No unsafe instructions. The validator ensures that the Native Client
- application does not contain any unsafe instructions. Examples of
- unsafe instructions are ``syscall``, ``int``, and ``lds``.
-* Control flow integrity. The validator ensures that all direct and
+* **No unsafe instructions:** The validator ensures that the Native
+ Client application does not contain any unsafe instructions. Examples
+ of unsafe instructions are ``syscall``, ``int``, and ``lds``.
+* **Control flow integrity:** The validator ensures that all direct and
indirect branches target a safe instruction.
+The beauty of the Native Client sandbox is in reducing "safe" code to a
+few simple rules that can be verified by a small trusted validator: the
+compiler isn't trusted. The same applies to Portable Native Client where
+even the ``.pexe`` to ``.nexe`` translator, a simplified compiler
+backend, isn't trusted: it is validated before executing, and so is its
+output.
+
In addition to static analysis of untrusted code, the Native Client
runtime also includes an outer sandbox that mediates system calls. For
more details about both sandboxes, see `Native Client: A Sandbox for
Portable, Untrusted x86 Code
-<http://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
+<https://src.chromium.org/viewvc/native_client/data/docs_tarball/nacl/googleclient/native_client/documentation/nacl_paper.pdf>`_
(PDF).
How does Google know that the safety measures in Native Client are sufficient?
@@ -277,11 +394,11 @@ works, including:
.. TODO: Fix security contest link once ReST-ified.
-Google is committed to making Native Client as safe as, or safer than,
-JavaScript and other popular browser technologies. If you have
-suggestions for security improvements, let the team know, by way of the
-`native-client-discuss mailing list
-<http://groups.google.com/group/native-client-discuss>`_.
+Google is committed to making Native Client safer than JavaScript and
+other popular browser technologies. If you have suggestions for security
+improvements, let the team know, by way of the `native-client-discuss
+mailing list <https://groups.google.com/group/native-client-discuss>`_.
+
Development
===========
@@ -289,131 +406,144 @@ Development
How do I debug?
---------------
-Use of a debugger isn't yet supported in Native Client, though you may
-be able to debug Native Client modules with some :doc:`alternative
-approaches <devguide/devcycle/debugging>`. We're actively working on
-providing integrated debugging support. For further developments, keep
-an eye on the `native-client-announce mailing list
-<http://groups.google.com/group/native-client-announce>`_.
-
-How do I build x86-64 or ARM ``.nexes``?
-----------------------------------------
-
-By default, the applications in the ``/examples`` folder compile for
-x86-32, x86-64, and ARM. To specifically target x86-64, compile your
-module using ``<platform>_x86_<library>/bin/x86_64-nacl-g++``. To
-specifically target ARM, compile your module using
-``<platform>_arm_newlib/bin/arm-nacl-g++``. For more information, see
-the :doc:`Building instructions <devguide/devcycle/building>`.
-
-How can my web app determine whether to load the x86-32, x86-64, or ARM ``.nexe``?
-----------------------------------------------------------------------------------
-
-Your application does not need to make that decision explicitly --- the
-Native Client runtime examines a manifest file (.nmf) to pick the right
-``.nexe`` file for a given user. You can generate a manifest file using
-a Python script that's included in the SDK (see the Makefile in any of
-the SDK examples for an illustration of how to do so). Your HTML file
-specifies the manifest filename in the ``src`` attribute of the
-``<embed>`` tag. You can see the way the pieces fit together by
-examining the examples included in the SDK.
-
-.. Note::
- :class: note
-
- The forthcoming `Portable Native Client
- <http://blog.chromium.org/2010/03/native-client-and-web-portability.html>`__
- technology (also known as "PNaCl") will remove the requirement to
- build multiple ``.nexe`` files to support multiple architectures.
+Instructions on :ref:`debugging the SDK examples
+<debugging_the_sdk_examples>` using GDB are available. You can also
+debug Native Client modules with some :doc:`alternative approaches
+<devguide/devcycle/debugging>`.
+
+How do I build x86-32, x86-64 or ARM ``.nexes``?
+------------------------------------------------
+
+By default, the applications in the ``/examples`` folder create
+architecture-independent ``.pexe`` for Portable Native Client. To
+generate a ``.nexe`` targetting one specific architecture using the
+Native Client or Portable Native Client toolchains, see the
+:doc:`Building instructions <devguide/devcycle/building>`.
+
+How can my web application determine which ``.nexe`` to load?
+-------------------------------------------------------------
+
+Your application does not need to make the decision of loading an
+x86-32, x86-64 or ARM ``.nexe`` explicitly---the Native Client runtime
+examines a manifest file (``.nmf``) to pick the right ``.nexe`` file for
+a given user. You can generate a manifest file using a Python script
+that's included in the SDK (see the ``Makefile`` in any of the SDK
+examples for an illustration of how to do so). Your HTML file specifies
+the manifest filename in the ``src`` attribute of the ``<embed>``
+tag. You can see the way the pieces fit together by examining the
+examples included in the SDK.
Is it possible to build a Native Client module with just plain C (not C++)?
---------------------------------------------------------------------------
-Yes. See the Hello, World in C example in the SDK (in
-``examples/tutorial/using_ppapi_simple/``).
+Yes. See the ``"Hello, World!"`` in C example in the SDK under
+``examples/tutorial/using_ppapi_simple/``, or the Game of Life example
+under ``examples/demo/life/life.c``.
What UNIX system calls can I make through Native Client?
--------------------------------------------------------
-Native Client doesn't expose any of the host OS's system calls directly,
-because of the inherent security risks and because the resulting app
-would not be portable across operating systems. Instead, Native Client
-provides varying degrees of wrapping or proxying of the host OS's
-functionality or emulation of UNIX system calls. For example, Native
-Client provides an ``mmap()`` system call that behaves much like the
-standard UNIX ``mmap()`` system call.
+Native Client doesn't directly expose any system calls from the host OS
+because of the inherent security risks and because the resulting
+application would not be portable across operating systems. Instead,
+Native Client provides portable cross-OS abstractions wrapping or
+proxying OS functionality or emulating UNIX system calls. For example,
+Native Client provides an ``mmap()`` system call that behaves much like
+the standard UNIX ``mmap()`` system call.
Is my favorite third-party library available for Native Client?
---------------------------------------------------------------
Google has ported several third-party libraries to Native Client; such
libraries are available in the `naclports
-<http://code.google.com/p/naclports>`_ project. We encourage you to
+<https://code.google.com/p/naclports>`_ project. We encourage you to
contribute libraries to naclports, and/or to host your own ported
libraries, and to `let the team know about it
-<http://groups.google.com/group/native-client-discuss>`_ when you do.
+<https://groups.google.com/group/native-client-discuss>`_ when you do.
-Do all the files in a Native Client application need to be served from the same domain?
----------------------------------------------------------------------------------------
+Do all the files in an application need to be served from the same domain?
+--------------------------------------------------------------------------
-The ``.html``, ``.nmf``, and ``.nexe`` files must be served from the
-same domain and the Chrome Web Store manifest file must include the
+The ``.html``, ``.nmf``, and ``.nexe`` or ``.pexe`` files must be served
+from the same domain and the Chrome Web Store manifest file (for
+applications installed from the Chrome Web Store) must include the
correct, verified domain. Other files can be served from the same or
another domain.
+.. TODO This isn't the case anymore. +ncbray?
+
+
Portability
===========
-Do I have to do anything special to make my Native Client web app run on different operating systems?
------------------------------------------------------------------------------------------------------
+Do I have to do anything special to make my application run on different operating systems?
+-------------------------------------------------------------------------------------------
-No. Native Client apps run without modification on all supported
-operating systems.
+No. Native Client and Portable Native Client applications run without
+modification on all supported operating systems.
However, to run on different instruction set architectures (such as
-x86-32 and x86-64), you currently have to build and supply a separate
-``.nexe`` file for each architecture. See :doc:`target architectures
-<devguide/devcycle/building>` for details about which ``.nexe`` files
-will run on which architectures.
+x86-32, x86-64 or ARM), you currently have to either:
-`Portable Native Client
-<http://blog.chromium.org/2010/03/native-client-and-web-portability.html>`__
-will remove the requirement to build multiple ``.nexe`` files.
+* Use Portable Native Client.
+* Build and supply a separate ``.nexe`` file for each architecture, and
+ make them available on the Chrome Web Store. See :doc:`target
+ architectures <devguide/devcycle/building>` for details about which
+ ``.nexe`` files will run on which architectures.
How easy is it to port my existing native code to Native Client?
----------------------------------------------------------------
-In most cases, you won't have to rewrite a lot of code. The Native
-Client-specific GNU tools, such as ``x86_64-nacl-g++``, take care of
-most of the necessary changes. You may need to make some changes to your
-operating system calls and interactions with external devices to work in
-the web world; but (for example) porting existing Linux libraries is
+In most cases you won't have to rewrite much, if any, code. The Native
+Client-specific tools, such as ``pnacl-clang++`` or ``x86_64-nacl-g++``,
+take care of most of the necessary changes. You may need to make some
+changes to your operating system calls and interactions with external
+devices to work with the web. Porting existing Linux libraries is
generally straightforward, with large libraries often requiring no
source change.
-The following kinds of code may be hard to port:
+The following kinds of code may be more challenging to port:
-* Code that does direct TCP/IP or UDP networking. For security reasons,
- Native Client is restricted to the networking otherwise available in
- the browser.
+* Code that does direct TCP/IP or UDP networking. For security reasons
+ these APIs are only available to packaged applications, not on the
+ open web, after asking for the appropriate permissions. Native Client
+ is otherwise restricted to the networking APIs available in the
+ browser.
+* Code that creates processes, including UNIX forks. Creating processes
+ is not supported for security reasons. However, threads are supported.
* Code that needs to do local file I/O. Native Client is restricted to
accessing URLs and to local storage in the browser (the Pepper file
I/O API has access to the same per-application storage that JavaScript
- has via Local Storage).
-* Code that creates processes, including UNIX forks. Creating processes
- is not supported for security reasons. However, threads are supported.
+ has via Local Storage). HTML5 File System can be used, among
+ others. You can also use nacl_io.
+
+.. TODO More on nacl_io, and a link.
+
.. _faq_troubleshooting:
Troubleshooting
===============
+My ``.pexe`` isn't loading, help!
+---------------------------------
+
+* You must use Google Chrome version 31 or greater for Portable Native
+ Client. Make sure you have Portable Native Client installed in
+ ``about:nacl``; if not open ``about:components`` and "Check for
+ update" for PNaCl.
+* PNaCl ``.pexe`` must be compiled with pepper_31 SDK or higher (earlier
+ SDK versions had experimental support for PNaCl, now deprecated).
+* Your application can verify that Portable Native Client is supported
+ in JavaScript with ``navigator.mimeTypes['application/x-pnacl'] !==
+ undefined``. This is preferred over checking the Chrome version.
+
My ``.nexe`` files never finish loading. What gives?
----------------------------------------------------
Here are ways to resolve some common problems that can prevent loading:
-* You must use Google Chrome version 14 or greater.
+* You must use Google Chrome version 14 or greater for Native Client.
* If you haven't already done so, enable the Native Client flag in
Google Chrome. Type ``about:flags`` in the Chrome address bar, scroll
down to "Native Client", click the "Enable" link, scroll down to the
@@ -434,12 +564,10 @@ Here are ways to resolve some common problems that can prevent loading:
* The ``.nexe`` files must have been compiled using SDK version 0.5 or
greater.
* You must load the correct ``.nexe`` file for your machine's specific
- instruction set architecture (such as x86-32 or x86-64). You can
- ensure you're loading the correct ``.nexe`` file by building a
- separate ``.nexe`` for each architecture, and using a ``.nmf``
- manifest file to let the browser select the correct ``.nexe``
- file. Note: the need to select a processor-specifc ``.nexe`` will go
- away with `Portable Native Client
- <http://blog.chromium.org/2010/03/native-client-and-web-portability.html>`__.
-* If things still aren't working, `drop a note to the team
- <http://groups.google.com/group/native-client-discuss>`_.
+ instruction set architecture (x86-32, x86-64 or ARM). You can ensure
+ you're loading the correct ``.nexe`` file by building a separate
+ ``.nexe`` for each architecture, and using a ``.nmf`` manifest file to
+ let the browser select the correct ``.nexe`` file. Note: the need to
+ select a processor-specific ``.nexe`` goes away with Portable Native
+ Client.
+* If things still aren't working, :doc:`ask for help <help>`!
diff --git a/native_client_sdk/src/doc/images/calendar-32.gif b/native_client_sdk/src/doc/images/calendar-32.gif
new file mode 100644
index 0000000000..cb810021d7
--- /dev/null
+++ b/native_client_sdk/src/doc/images/calendar-32.gif
Binary files differ
diff --git a/native_client_sdk/src/doc/images/code-32.gif b/native_client_sdk/src/doc/images/code-32.gif
new file mode 100644
index 0000000000..845c6bdf9b
--- /dev/null
+++ b/native_client_sdk/src/doc/images/code-32.gif
Binary files differ
diff --git a/native_client_sdk/src/doc/images/gift-32.gif b/native_client_sdk/src/doc/images/gift-32.gif
new file mode 100644
index 0000000000..845ad6fff3
--- /dev/null
+++ b/native_client_sdk/src/doc/images/gift-32.gif
Binary files differ
diff --git a/native_client_sdk/src/doc/index.rst b/native_client_sdk/src/doc/index.rst
index a51ef96cc2..a9da55748a 100644
--- a/native_client_sdk/src/doc/index.rst
+++ b/native_client_sdk/src/doc/index.rst
@@ -11,9 +11,10 @@ Contents:
quick-start.rst
nacl-and-pnacl.rst
glossary.rst
+ sdk/index.rst
sdk/download.rst
sdk/examples.rst
- sdk/index.rst
+ sdk/release-notes.rst
sdk/release-notes.rst
devguide/index.rst
devguide/tutorial.rst
@@ -21,6 +22,7 @@ Contents:
devguide/devcycle/building.rst
devguide/devcycle/running.rst
devguide/devcycle/debugging.rst
+ devguide/devcycle/vs-addin.rst
devguide/devcycle/dynamic-loading.rst
devguide/coding/3D-graphics.rst
devguide/coding/audio.rst
@@ -34,7 +36,15 @@ Contents:
devguide/distributing.rst
community/application-gallery.rst
community/middleware.rst
+ community/security-contest/index.rst
+ community/security-contest/contest-announcement.rst
+ community/security-contest/contest-terms.rst
+ community/security-contest/contest-faq.rst
peppercpp/index.rst
+ reference/index.rst
+ reference/pnacl-bitcode-abi.rst
+ reference/nacl-manifest-format.rst
+ publications-and-presentations.rst
faq.rst
help.rst
version.rst
diff --git a/native_client_sdk/src/doc/nacl-and-pnacl.rst b/native_client_sdk/src/doc/nacl-and-pnacl.rst
index 3881297675..82cde79699 100644
--- a/native_client_sdk/src/doc/nacl-and-pnacl.rst
+++ b/native_client_sdk/src/doc/nacl-and-pnacl.rst
@@ -4,97 +4,114 @@
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
+This document describes the differences between **Native Client** and
+**Portable Native Client**, and provides recommendations for when to use each.
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Native Client (NaCl)
+====================
+
+Native Client enables the execution of native code
+securely inside web applications through the use of advanced
+`Software Fault Isolation (SFI) techniques <https://developers.google.com/native-client/community/talks#research>`_.
+Since its launch in 2011, Native Client has provided
+developers with the ability to harness a 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
+While Native Client provides operating system independence, it requires
+developers to generate architecture-specific executable modules
+(**nexe** modules) for each hardware platform. This is not only inconvenient
+for developers, but architecture-specific machine code is not portable and thus
+not well-suited for the open web. The traditional method of application
+distribution on the web is through a self-contained bundle of HTML, CSS,
+JavaScript, and other resources (images, etc.) that can be hosted on a server
+and run inside a web browser. With this type of distribution, a website
+created today should still work years later, on all platforms.
+Architecture-specific executables are clearly not a good fit for distribution
+on the web. As a consequence, Native Client has been restricted to
+applications and browser extensions that are installed through the
+Chrome Web Store.
+
+Portable Native Client (PNaCl)
+==============================
+
+PNaCl solves the portability problem by splitting the compilation process
+into two parts:
+
+#. compiling the source code to a portable bitcode format, and
+#. translating the bitcode to a host-specific executable.
+
+PNaCl enables developers
+to distribute **portable executables** (**pexe** modules) that the hosting
+environment (e.g., the Chrome browser) can translate to native code before
+executing. This portability aligns Native Client with existing open web
+technologies such as JavaScript: A developer can distribute a **pexe**
+as part of an application (along with HTML, CSS, and JavaScript),
+and the user's machine is simply able to run it.
+
+With PNaCl, a developer generates a single pexe from source code,
+rather than multiple platform-specific nexes. The pexe provides
+both architecture- and OS-independence. Since the pexe uses an abstract,
+architecture-independent format, it does not suffer from the portability problem
+described above. Future versions of hosting environments
+should have no problem executing the pexe, even on new architectures.
+Moreover, if an existing architecture is subsequently enhanced, the pexe
+doesn't even have to be recompiled---in some cases the client-side
+translation will automatically be able to take advantage of the new
+capabilities.
+
+**In short, PNaCl combines the portability of existing web technologies with
+the performance and security benefits of Native Client.**
+
+With the advent of PNaCl, the distribution restriction of Native Client can be
+lifted. Specifically, a pexe module can be part of any 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.
+PNaCl is a new technology, and as such it still has a few limitations
+as compared to NaCl. These limitations are described below.
+
+When to use PNaCl
+=================
-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 subject to one
+of the narrow limitations described below
+(see :ref:`When to use NaCl<when-to-use-nacl>`), you should 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 browser supports translation of
+pexe modules and their use in web applications, without requiring
+any installation (either of a browser plugin or of the applications themselves).
+Native Client and PNaCl are open-source technologies, and our hope is that they
+will be added to other hosting platforms in the future.
-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.
+If controlled distribution through the Chrome Web Store is an important part
+of your product plan, the benefits of PNaCl are less critical for you. But
+you can still use the PNaCl toolchain and distribute your application
+through the Chrome Web Store, and thereby take advantage of the
+conveniences of PNaCl, such as not having to explicitly compile your application
+for all supported architectures.
-When to use non-portable NaCl
-=============================
+.. _when-to-use-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.
+When to use NaCl
+================
-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:
+The limitations below apply to the initial release of PNaCl. If
+any of these limitations are critical for your application, you should use
+non-portable NaCl:
* 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
+ an application (i.e., 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.
+* Currently PNaCl only supports static linking with the ``newlib``
+ C standard library (the Native Client SDK provides a PNaCl port of
+ ``newlib``). Dynamic linking and ``glibc`` are not yet 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/overview.rst b/native_client_sdk/src/doc/overview.rst
index d6a96f4026..3a5efed8ed 100644
--- a/native_client_sdk/src/doc/overview.rst
+++ b/native_client_sdk/src/doc/overview.rst
@@ -13,22 +13,21 @@ Introduction
============
**Native Client** (NaCl) is an open-source technology for running native
-applications in the browser, with the goal of maintaining the portability
-and safety that people expect from web applications. Native Client expands web
+compiled code in the browser, with the goal of maintaining the portability
+and safety that users expect from web applications. Native Client expands web
programming beyond JavaScript, enabling developers to enhance their web
-applications using their preferred language. This document describes a few of
-the key benefits of Native Client, as well as current limitations and common use
-cases.
+applications using their preferred language. This document describes some of
+the key benefits and common use cases of Native Client.
Google has implemented the open-source `Native Client project
<http://www.chromium.org/nativeclient>`_ in the Chrome browser on Windows, Mac,
Linux, and Chrome OS. The :doc:`Native Client Software Development Kit (SDK)
<sdk/index>`, itself an open-source project, lets developers create web
-applications that use NaCl and run in Chrome across OS platforms.
+applications that use NaCl and run in Chrome across multiple platforms.
-A web application that uses NaCl generally consists of a combination of
+A web application that uses Native Client generally consists of a combination of
JavaScript, HTML, CSS, and a NaCl module that is written in a language supported
-by the SDK. The NaCl SDK currently supports C and C++. As compilers for
+by the SDK. The NaCl SDK currently supports C and C++; as compilers for
additional languages are developed, the SDK will be updated to support those
languages as well.
@@ -37,15 +36,16 @@ languages as well.
Why use Native Client?
======================
-The Native Client open-source technology is designed to run compiled code
+Native Client open-source technology is designed to run compiled code
securely inside a browser at near-native speeds. Native Client puts web
-applications on the same playing field as traditional (locally-run) software; it
-provides the means to fully harness the system's computational resources for
-applications like 3D games and multimedia editors. Native Client also aims to
-give C and C++ (and eventually other languages) the same level of portability
-and safety that JavaScript provides on the web today.
+applications on the same playing field as traditional (locally-run)
+software---it provides the means to fully harness the client's computational
+resources for applications such as 3D games, multimedia editors, CAD modeling,
+client-side data analytics, and interactive simulations.
+Native Client also aims to give C and C++ (and eventually other languages) the
+same level of portability and safety that JavaScript provides on the web today.
-Here are some of the key features that Native Client offers:
+Here are a few of the key benefits that Native Client offers:
* **Graphics, audio, and much more:** Run native code modules that render 2D
and 3D graphics, play audio, respond to mouse and keyboard events, run on
@@ -53,7 +53,7 @@ Here are some of the key features that Native Client offers:
the user to install a plugin.
* **Portability:** Write your applications once and you'll be able to run them
across operating systems (Windows, Linux, Mac, and Chrome OS) and CPU
- architectures (x86, ARM).
+ architectures (x86 and ARM).
* **Easy migration path to the web:** Many developers and companies have years
of work invested in existing desktop applications. Native Client makes the
transition from the desktop to a web application significantly easier because
@@ -62,48 +62,47 @@ Here are some of the key features that Native Client offers:
the user's system from malicious or buggy applications. This model offers the
safety of traditional web applications without sacrificing performance and
without requiring users to install a plugin.
-* **Performance:** Native Client allows your application to run at a speed
- comparable to a desktop app (within 5-15% of native speed); it also allows
- harnessing all available CPU cores via a threading API. This capability
- enables demanding applications such as console-quality games to run inside the
- browser.
+* **Performance:** Native Client allows web applications to run at speeds
+ comparable to desktop applications (within 5-15% of native speed).
+ Native Client also allows applications to harness all available CPU cores via
+ a threading API; this enables demanding applications such as console-quality
+ games to run inside the browser.
Common use cases
================
Typical use cases for Native Client include the following:
-* **Existing software components:** With its C and C++ language support, Native
- Client enables you to reuse current software modules in a web
- application---you don't need to spend time reinventing and debugging code
+* **Existing software components:** With support for C and C++, Native
+ Client enables you to reuse existing software modules in
+ web applications---you don't need to rewrite and debug code
that's already proven to work well.
* **Legacy desktop applications:** Native Client provides a smooth migration
path from desktop applications to the web. You can port and recompile existing
code for the computation engine of your application directly to Native Client,
and need repurpose only the user interface and event handling portions to the
new browser platform. Native Client allows you to embed existing functionality
- directly into the browser. At the same time, your application takes advantage
- of things the browser does well: handling user interaction and processing
- events, based on the latest developments in HTML5.
-* **Heavy computation in enterprise applications:** Native Client handles the
+ directly into the browser. At the same time, your application can take
+ advantage of things the browser does well: handling user interaction and
+ processing events, based on the latest developments in HTML5.
+* **Heavy computation in enterprise applications:** Native Client can handle the
number crunching required by large-scale enterprise applications. To ensure
protection of user data, Native Client enables you to build complex
cryptographic algorithms directly into the browser so that unencrypted data
never goes out over the network.
* **Multimedia applications:** Codecs for processing sounds, images, and movies
can be added to the browser in a Native Client module.
-* **Games:** Native Client enables a web application to run close to native
- speed, reusing existing multithreaded/multicore C/C++ code bases, combined
- with low-level access to low-latency audio, networking APIs and OpenGL ES with
- programmable shaders. Programming to Native Client also enables your binary to
- run unchanged across many platforms. Native Client is a natural fit for
- running a physics engine or artificial intelligence module that powers a
- sophisticated web game.
+* **Games:** Native Client lets web applications run at close to native
+ speed, reuse existing multithreaded/multicore C/C++ code bases, and
+ access low-latency audio, networking APIs, and OpenGL ES with programmable
+ shaders. Native Client is a natural fit for running a physics engine or
+ artificial intelligence module that powers a sophisticated web game.
+ Native Client also enables applications to run unchanged across
+ many platforms.
* **Any application that requires acceleration**: Native Client fits seamlessly
- into any web application, so it is up to the developer to decide to what
- extent to utilize it. Native Client usage covers the full spectrum from
- complete applications to small optimized routines that accelerate vital parts
- of traditional web applications.
+ into web applications---it's up to you to decide to what extent to use it.
+ Use of Native Client covers the full spectrum from complete applications to
+ small optimized routines that accelerate vital parts of web apps.
.. _link_how_nacl_works:
@@ -118,73 +117,87 @@ At a high level, Native Client consists of:
* **Toolchains**: collections of development tools (compilers, linkers, etc.)
that transform C/C++ code to Native Client modules.
-* **Runtime components**: embedded in the browser (or another host platform),
- that allow to execute Native Client modules securely and efficiently.
+* **Runtime components**: components embedded in the browser or other
+ host platforms that allow execution of Native Client modules
+ securely and efficiently.
The following diagram shows how these components interact:
.. image:: /images/nacl-pnacl-component-diagram.png
-Native Client executables and sandbox
--------------------------------------
+The left side of the diagram shows how to use Portable Native Client
+(PNaCl, pronounced "pinnacle"). Developers use the PNaCl toolchain
+to produce a single, portable (**pexe**) module. At runtime, a translator
+built into the browser translates the pexe into native code for the
+relevant client architecture.
-Since Native Client permits executing native code on the client's machine,
-special security measures have to be implemented. The security is achieved
-through the following means:
+The right side of the diagram shows how to use traditional (non-portable)
+Native Client. Developers use a nacl-gcc based toolchain to produce multiple
+architecture-dependent (**nexe**) modules, which are packaged into an
+application. At runtime, the browser decides which nexe to load based
+on the architecture of the client machine.
+
+Security
+--------
+
+Since Native Client permits the execution of native code on client machines,
+special security measures have to be implemented:
* The NaCl sandbox ensures that code accesses system resources only through
safe, whitelisted APIs, and operates within its limits without attempting to
- interfere with other code running within the browser or outside it.
-* The NaCl validator is used prior to running native code to statically analyze
- the code and make sure it only uses allowed and safe code and data patterns.
-
-These come in addition to the existing sandbox in the browser---the Native
-Client module always executes within a process with restricted permissions. The
-only interaction of this process with the outside world is through sanctioned
-browser interfaces. For this reason, we say that Native Client employs a *double
-sandbox* design.
-
-PNaCl and NaCl
---------------
-
-*PNaCl* (Portable Native Client) employs state-of-the-art compiler technology to
-compile C/C++ source code to a portable bitcode executable (**pexe**). PNaCl
-bitcode is an OS- and architecture-independent format that can be freely
-distributed on the web and :ref:`embedded in web
+ interfere with other code running either within the browser or outside it.
+* The NaCl validator statically analyzes code prior to running it
+ to make sure it only uses code and data patterns that are permitted and safe.
+
+The above security measures are in addition to the existing sandbox in the
+Chrome browser---the Native Client module always executes in a process with
+restricted permissions. The only interaction between this process and the
+outside world is through sanctioned browser interfaces. Because of the
+combination of the NaCl sandbox and the Chrome sandbox, we say that
+Native Client employs a double sandbox design.
+
+Portability
+-----------
+
+Portable Native Client (PNaCl, prounounced "pinnacle") employs state-of-the-art
+compiler technology to compile C/C++ source code to a portable bitcode
+executable (**pexe**). PNaCl bitcode is an OS- and architecture-independent
+format that can be freely distributed on the web and :ref:`embedded in web
applications<link_nacl_in_web_apps>`.
-The *PNaCl translator* is a component embedded in the web browser; its task is
-to run a **pexe**. Internally, the translator compiles a **pexe** to a **nexe**
-(a native executable for the host platform's architecture) and then executes it
-within the Native Client sandbox as described above. It also uses intelligent
-caching to avoid re-compiling the **pexe** if it was already compiled on the
-client's browser.
+The PNaCl translator is a component embedded in the Chrome browser; its task is
+to run pexe modules. Internally, the translator compiles a pexe to a nexe
+(a native executable for the client platform's architecture), and then executes
+the nexe within the Native Client sandbox as described above. It also uses
+intelligent caching to avoid re-compiling the pexe if it was previously compiled
+on the client's browser.
-Native Client also supports running a **nexe** directly in the browser. However,
-since a **nexe** contains architecture-specific machine code, distributing
-**nexe** modules on the open web is not allowed. **nexe** modules can only be
-used as part of applications that are installed from the Chrome Web Store and in
-browser extensions.
+Native Client also supports the execution of nexe modules directly in the
+browser. However, since nexes contain architecture-specific machine code,
+they are not allowed to be distributed on the open web---they can only be
+used as part of applications and extensions that are installed from the
+Chrome Web Store.
-For more details, see :doc:`NaCl and PNaCl <nacl-and-pnacl>`.
+For more details on the difference between NaCl and PNaCl, see
+:doc:`NaCl and PNaCl <nacl-and-pnacl>`.
Toolchains
----------
-A *toolchain* is a set of tools used to create an application from a set of
+A toolchain is a set of tools used to create an application from a set of
source files. In the case of Native Client, a toolchain consists of a compiler,
-linker, assembler and other tools that are used by the developer to convert an
-application written in C/C++ into a module loadable by the browser.
+linker, assembler and other tools that are used to convert an
+application written in C/C++ into a module that is loadable by the browser.
The Native Client SDK provides two toolchains:
-* A PNaCl toolchain for generating portable NaCl modules (**pexe**).
-* A gcc-based toolchain (**nacl-gcc**) for generating native NaCl modules
- (**nexe**).
+* a **PNaCl toolchain** for generating portable NaCl modules (pexe files)
+* a **gcc-based toolchain (nacl-gcc)** for generating non-portable NaCl modules
+ (nexe files)
-For most applications, the PNaCl toolchain is recommended. The **nacl-gcc**
-toolchain should only be used if the application will not be available on the
-open web.
+The PNaCl toolchain is recommended for most applications. The nacl-gcc
+toolchain should only be used for applications that will not be distributed
+on the open web.
.. _link_nacl_in_web_apps:
@@ -195,15 +208,15 @@ Native Client in a web application
A Native Client application consists of a set of files:
-* **HTML web page**, **CSS**, and **JavaScript** files, as in any modern web
- application. The JavaScript is also responsible for communicating with the
+* **HTML**, **CSS**, and **JavaScript** files, as in any modern web
+ application. The JavaScript code is responsible for communicating with the
NaCl module.
-* The **pexe** (portable NaCl module). This module uses the :ref:`Pepper
+* A **pexe** (portable NaCl) file. This module uses the :ref:`Pepper
<link_pepper>` API, which provides the bridge to JavaScript and
browser resources.
-* A **manifest** file that specifies the **pexe** to load with some loading
- options. This manifest file is embedded into the HTML page through an
- ``<embed>`` tag.
+* A Native Client **manifest** file that specifies the pexe to load, along with
+ some loading options. This manifest file is embedded into the HTML page
+ through an ``<embed>`` tag, as shown in the figure below.
.. image:: /images/nacl-in-a-web-app.png
@@ -217,20 +230,20 @@ Pepper Plugin API
The Pepper Plugin API (PPAPI), called **Pepper** for convenience, is an
open-source, cross-platform C/C++ API for web browser plugins. From the point
-of view of NaCl, Pepper allows a C/C++ NaCl module to communicate with the
-hosting browser and get access to system-level functions in a safe and portable
-way. One of the security constraints in NaCl is that modules cannot make any
-OS-level calls directly. Pepper provides analogous APIs that modules can target
-instead.
+of view of Native Client, Pepper allows a C/C++ module to communicate with
+the hosting browser and get access to system-level functions in a safe and
+portable way. One of the security constraints in Native Client is that modules
+cannot make any OS-level calls directly. Pepper provides analogous APIs that
+modules can target instead.
You can use the Pepper APIs to gain access to the full array of browser
capabilities, including:
-* :doc:`Talk to the JavaScript code in your application
+* :doc:`Talking to the JavaScript code in your application
<devguide/coding/message-system>` from the C++ code in your NaCl module.
-* :doc:`Do file I/O <devguide/coding/FileIO>`.
-* :doc:`Play audio <devguide/coding/audio>`.
-* :doc:`Render 3D graphics <devguide/coding/3D-graphics>`.
+* :doc:`Doing file I/O <devguide/coding/FileIO>`.
+* :doc:`Playing audio <devguide/coding/audio>`.
+* :doc:`Rendering 3D graphics <devguide/coding/3D-graphics>`.
Pepper includes both a C API and a C++ API. The C++ API is a set of bindings
written on top of the C API. For additional information about Pepper, see
@@ -240,7 +253,7 @@ Versioning
==========
Chrome is released on a six week cycle, and developer versions of Chrome are
-pushed to the public beta channel three weeks before release. As with any
+pushed to the public beta channel three weeks before each release. As with any
software, each release of Chrome may include changes to Native Client and the
Pepper interfaces that may require modification to existing applications.
However, modules compiled for one version of Pepper/Chrome should work with
@@ -249,10 +262,9 @@ subsequent versions of Pepper/Chrome. The SDK includes multiple `versions
help developers make adjustments to API changes and take advantage of new
features.
-Where to go next
-================
+Where to start
+==============
-The :doc:`quick start <quick-start>` document provides links to downloads and
+The :doc:`Quick Start <quick-start>` document provides links to downloads and
documentation that should help you get started with developing and distributing
-NaCl applications.
-
+Native Client applications.
diff --git a/native_client_sdk/src/doc/publications-and-presentations.rst b/native_client_sdk/src/doc/publications-and-presentations.rst
new file mode 100644
index 0000000000..5d27f0c371
--- /dev/null
+++ b/native_client_sdk/src/doc/publications-and-presentations.rst
@@ -0,0 +1,200 @@
+.. _publications_and_presentations:
+
+##############################
+Publications and Presentations
+##############################
+
+This page lists Native Client and Portable Native Client talks, demos,
+and publications from various conferences and academic symposiums.
+
+Recent talks and demos
+----------------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - Date
+ - Event
+ - Talk
+ * - 2013/05/16
+ - `Google I/O 2013 <https://developers.google.com/events/io/2013>`_
+ - `Introduction to Portable Native Client
+ <https://www.youtube.com/watch?v=5RFjOec-TI0>`_
+ * - 2012/12/11
+ - `Google Developers Live <https://developers.google.com/live/>`_
+ - `Native Client Acceleration Modules
+ <https://developers.google.com/live/shows/7320022-5002/>`_ Learn
+ how to use Native Client to deliver performance where it counts
+ (`source code <https://github.com/johnmccutchan/NaClAMBase/>`__)
+ * - 2012/07/26
+ - `Casual Connect Seattle 2012
+ <http://casualconnect.org/seattle/content.html>`_
+ - `Take your C++ To the Web with Native Client
+ <https://www.youtube.com/watch?v=RV7SMC3IJNo>`_ Includes an
+ overview of Native Client technology, porting legacy applications
+ from the Windows desktop, and current third-party use of Native
+ Client in middleware and games
+ * - 2012/06/28
+ - `Google I/O 2012 <https://developers.google.com/events/io/2012>`_
+ - `Native Client Live
+ <https://www.youtube.com/watch?v=1zvhs5FR0X8>`_ Demonstrates how
+ to port an existing C application to Native Client using a Visual
+ Studio add-in that lets developers debug their code as a trusted
+ Chrome plugin
+ * - 2012/06/28
+ - `Google I/O 2012 <https://developers.google.com/events/io/2012>`_
+ - `The Life of a Native Client Instruction
+ <https://www.youtube.com/watch?v=KOsJIhmeXoc>`_ (`slides
+ <https://nacl-instruction-io12.appspot.com>`__)
+ * - 2012/03/05
+ - `GDC 2012 <http://www.gdcvault.com/free/gdc-12>`_
+ - `Get Your Port On <https://www.youtube.com/watch?v=R281PhQufHo>`_
+ Porting Your C++ Game to Native Client
+ * - 2011/08/12
+ - ---
+ - `Native Client Update and Showcase
+ <https://www.youtube.com/watch?v=g3aBfkFbPWk>`_
+ * - 2011/05/11
+ - `Google I/O 2011
+ <https://www.google.com/events/io/2011/index-live.html>`_
+ - `Beyond JavaScript: Programming the Web with Native Client
+ <https://www.google.com/events/io/2011/sessions/beyond-javascript-programming-the-web-with-native-client.html>`_
+ * - 2010/11/04
+ - `2010 LLVM Developers' Meeting
+ <http://llvm.org/devmtg/2010-11/>`_
+ - `Portable Native Client
+ <http://llvm.org/devmtg/2010-11/videos/Sehr_NativeClient-desktop.mp4>`_
+
+Publications
+------------
+
+.. list-table::
+ :header-rows: 1
+
+ * - Title
+ - Authors
+ - Published in
+ * - `Language-Independent Sandboxing of Just-In-Time Compilation and
+ Self-Modifying Code
+ <http://research.google.com/pubs/archive/37204.pdf>`_
+ - Jason Ansel, Petr Marchenko, `Úlfar Erlingsson
+ <http://research.google.com/pubs/ulfar.html>`_, Elijah Taylor,
+ `Brad Chen <http://research.google.com/pubs/author37895.html>`_,
+ Derek Schuff, David Sehr, `Cliff L. Biffle
+ <http://research.google.com/pubs/author38542.html>`_, Bennet
+ S. Yee
+ - ACM SIGPLAN Conference on Programming Language Design and
+ Implementation (PLDI), 2011
+ * - `Adapting Software Fault Isolation to Contemporary CPU
+ Architectures <http://research.google.com/pubs/pub35649.html>`_
+ - David Sehr, Robert Muth, `Cliff L. Biffle
+ <http://research.google.com/pubs/author38542.html>`_, Victor
+ Khimenko, Egor Pasko, Bennet S. Yee, Karl Schimpf, `Brad Chen
+ <http://research.google.com/pubs/author37895.html>`_
+ - 19th USENIX Security Symposium, 2010, pp. 1-11
+ * - `Native Client: A Sandbox for Portable, Untrusted x86 Native Code
+ <http://research.google.com/pubs/pub34913.html>`_
+ - Bennet S. Yee, David Sehr, Greg Dardyk, `Brad Chen
+ <http://research.google.com/pubs/author37895.html>`_, Robert
+ Muth, Tavis Ormandy, Shiki Okasaka, Neha Narula, Nicholas
+ Fullagar
+ - IEEE Symposium on Security and Privacy (Oakland '09), 2009
+ * - `PNaCl: Portable Native Client Executables
+ <http://nativeclient.googlecode.com/svn/data/site/pnacl.pdf>`_
+ - Alan Donovan, Robert Muth, Brad Chen, David Sehr
+ - February 2010
+
+External Publications
+---------------------
+
+In these articles outside developers and Google engineers describe their
+experience porting libraries and applications to Native Client and
+Portable Native Client. They share their insights and provide some tips
+and instructions for how to port your own code.
+
+Porting Nebula3 to Portable Native Client
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Andre Weissflog ported his Nebula3 engine to Portable Native Client (see
+`his demos <http://www.flohofwoe.net/demos.html>`__). He discusses
+`build systems
+<http://flohofwoe.blogspot.de/2013/08/emscripten-and-pnacl-build-systems.html>`__
+and `app entry
+<http://flohofwoe.blogspot.de/2013/09/emscripten-and-pnacl-app-entry-in-pnacl.html>`__.
+
+Porting Go Home Dinosaurs
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+`Fire Hose Games <http://firehosegames.com>`_ developed a new webgame
+`Go Home Dinosaurs
+<https://chrome.google.com/webstore/detail/icefnknicgejiphafapflechfoeelbeo>`_.
+It features tower defense, dinosaurs, and good old fashioned BBQ. This
+article explains their experiences developing for Native Client
+including useful lessons learned to help you get started.
+
+`Read more <http://www.gamasutra.com/view/feature/175210/the_ins_and_outs_of_native_client.php>`__
+
+Porting Zombie Track Meat
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+`Fuzzycube Software <http://www.fuzzycubesoftware.com>`_, traditionally
+a mobile game development studio, talks about their adventure into the
+web, porting the undead decathlon `Zombie Track Meat
+<https://chrome.google.com/webstore/detail/jmfhnfnjfdoplkgbkmibfkdjolnemfdk/reviews>`_
+from Objective C to Native Client.
+
+`Read more <http://fuzzycube.blogspot.com/2012/04/zombie-track-meat-post-mortem.html>`__
+
+Porting AirMech
+^^^^^^^^^^^^^^^
+
+`Carbon Games <http://carbongames.com/>`_ chose Native Client as a
+solution for cross-platform delivery of their PC game `AirMech
+<https://chrome.google.com/webstore/detail/hdahlabpinmfcemhcbcfoijcpoalfgdn>`_
+to Linux and Macintosh in lieu of native ports. They describe the
+porting process on their blog.
+
+`Read more <http://carbongames.com/2012/01/Native-Client>`__
+
+Porting XaoS
+^^^^^^^^^^^^
+
+Google engineers ported `XaoS <http://xaos.sourceforge.net/english.php>`_, an
+interactive graphical exploration tool for fractals, to Native Client. Many of
+the porting problems they encountered are quite common, and the techniques
+described here should help with similar porting efforts. Some of the background
+information might also benefit those who are writing new Native Client
+applications.
+
+`Read more
+<https://developers.google.com/native-client/community/porting/xaos>`__
+
+.. TODO Fix link once it is ReST-ified.
+
+Porting MAME
+^^^^^^^^^^^^
+
+Multiple Arcade Machine Emulator (`MAME <http://mamedev.org>`_) is an
+emulator for a large number of classic arcade games. Google engineers
+ported it to Native Client. This article discusses the overall porting
+strategy, dealing with ``newlib`` incompatibilities, and handling
+binaries that are built and run as part of the build process.
+
+`Read more
+<https://developers.google.com/native-client/community/porting/MAME>`__
+
+.. TODO Fix link once it is ReST-ified.
+
+How to Port SDL Games
+^^^^^^^^^^^^^^^^^^^^^
+
+`Simple Directmedia Layer <http://www.libsdl.org>`_ (SDL) is a popular
+library that many games and applications use to access sound and video
+capabilities on end-user machines. Native Client bindings for SDL are
+available on naclports, making it possible to port SDL-based games to
+Native Client. This article by Google engineers describes how to
+complete such a port, focusing on writing the glue code for fusing your
+game with the Pepper APIs.
+
+`Read more
+<https://developers.google.com/native-client/community/porting/SDLgames>`__
diff --git a/native_client_sdk/src/doc/reference/index.rst b/native_client_sdk/src/doc/reference/index.rst
new file mode 100644
index 0000000000..d33887ef2a
--- /dev/null
+++ b/native_client_sdk/src/doc/reference/index.rst
@@ -0,0 +1,14 @@
+#########
+Reference
+#########
+
+The Native Client Reference section includes details about Native Client
+that may be of interest to developers. For example, it contains details
+about the NaCl manifest file format, and details about the Portable
+Native Client bitcode.
+
+If there are any additional details about Native Client that would
+be of interest to developers and should be included in this References
+section, please send feedback to the
+`native-client-discuss group
+<https://groups.google.com/group/native-client-discuss>`_.
diff --git a/native_client_sdk/src/doc/reference/nacl-manifest-format.rst b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
new file mode 100644
index 0000000000..a218a6956c
--- /dev/null
+++ b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
@@ -0,0 +1,265 @@
+###################################
+Native Client Manifest (nmf) Format
+###################################
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 2
+
+Overview
+========
+
+Every Native Client application has a `JSON-formatted <http://www.json.org/>`_
+NaCl Manifest File (``nmf``). The ``nmf`` tells the browser where to
+download and load your Native Client application files and libraries.
+The file can also contain configuration options.
+
+
+Field summary
+=============
+
+The following shows the supported top-level manifest fields. There is one
+section that discusses each field in detail. The only field that is required
+is the ``program`` field.
+
+.. naclcode::
+
+ {
+ // Required
+ "program": { ... }
+
+ // Only required for glibc
+ "files": { ... }
+ }
+
+Field details
+=============
+
+program
+-------
+
+The ``program`` field specifies the main program that will be loaded
+in the Native Client runtime environment. For a Portable Native Client
+application, this is a URL for the statically linked bitcode ``pexe`` file.
+For architecture-specific Native Client applications, this is a list
+of URLs, one URL for each supported architecture (currently the choices
+are "arm", "x86-32", and "x86-64"). For a dynamically linked executable,
+``program`` is the dynamic loader used to load the dynamic executable
+and its dynamic libraries. See the :ref:`semantics <nmf_url_resolution>`
+section for the rules on URL resolution.
+
+Example of a ``program`` for Portable Native Client:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ {
+ "program": {
+ "pnacl-translate": {
+ // url is required
+ "url": "url_to_my_pexe"
+
+ // optlevel is optional
+ "optlevel": 0
+ }
+ }
+ }
+
+Portable Native Client applications can also specify an ``optlevel`` field.
+The ``optlevel`` field is an optimization level *hint*, which is a number
+(zero and higher). Higher numbers indicate more optimization effort.
+Setting a higher optimization level will improve the application's
+performance, but it will also slow down the first load experience.
+The default is ``optlevel`` is currently ``2``, and values higher
+than 2 are no different than 2. If compute speed is not as important
+as first load speed, an application could specify an ``optlevel``
+of ``0``. Note that ``optlevel`` is only a *hint*. In the future, the
+Portable Native Client translator and runtime may *automatically* choose
+an ``optlevel`` to best balance load time and application performance.
+
+
+Example of a ``program`` for statically linked Native Client executables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ {
+ "program": {
+ // Required: at least one entry
+ // Add one of these for each architecture supported by the application.
+ "arm": { "url": "url_to_arm_nexe" },
+ "x86-32": { "url": "url_to_x86_32_nexe" },
+ "x86-64": { "url": "url_to_x86_64_nexe" }
+ }
+ }
+
+Example of a ``program`` for dynamically linked Native Client executables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. naclcode::
+
+ {
+ "program": {
+ // Required: at least one entry
+ // Add one of these for each architecture supported by the application.
+ "x86-32": { "url": "lib32/runnable-ld.so" },
+ "x86-64": { "url": "lib64/runnable-ld.so" }
+ },
+ // discussed in next section
+ "files": {
+ "main.nexe": {
+ "x86-32": { "url": "url_to_x86_32_nexe" },
+ "x86-64": { "url": "url_to_x86_64_nexe" }
+ },
+ // ...
+ }
+ }
+
+
+files
+-----
+
+The ``files`` field specifies a dictionary of file resources to be
+used by a Native Client application. This is not supported and
+not needed by Portable Native Client applications (use the PPAPI
+`URL Loader interfaces
+<https://developers.google.com/native-client/peppercpp/classpp_1_1_u_r_l_loader>`_
+to load resources instead). However, the ``files`` manifest field
+is important for dynamically linked executables, which must
+load files before PPAPI is initialized. The ``files`` dictionary
+should include the main dynamic program and its dynamic libraries.
+There should be one file entry that corresponds to each a
+dynamic library. Each file entry is a dictionary of supported architectures
+and the URLs where the appropriate Native Client shared object
+(``.so``) for that architecture may be found.
+
+Since ``program`` is used to refer to the dynamic linker that comes
+with the NaCl port of glibc, the main program is specified in the
+``files`` dictionary. The main program is specified under the
+``"main.nexe"`` field of the ``files`` dictionary.
+
+
+.. naclcode::
+
+ {
+ "program": {
+ "x86-64": {"url": "lib64/runnable-ld.so"},
+ "x86-32": {"url": "lib32/runnable-ld.so"}
+ },
+ "files": {
+ "main.nexe" : {
+ "x86-64": {"url": "pi_generator_x86_64.nexe"},
+ "x86-32": {"url": "pi_generator_x86_32.nexe"}
+ },
+ "libpthread.so.5055067a" : {
+ "x86-64": {"url": "lib64/libpthread.so.5055067a"},
+ "x86-32": {"url": "lib32/libpthread.so.5055067a"}
+ },
+ "libppapi_cpp.so" : {
+ "x86-64": {"url": "lib64/libppapi_cpp.so"},
+ "x86-32": {"url": "lib32/libppapi_cpp.so"}
+ },
+ "libstdc++.so.6" : {
+ "x86-64": {"url": "lib64/libstdc++.so.6"},
+ "x86-32": {"url": "lib32/libstdc++.so.6"}
+ },
+ "libm.so.5055067a" : {
+ "x86-64": {"url": "lib64/libm.so.5055067a"},
+ "x86-32": {"url": "lib32/libm.so.5055067a"}
+ },
+ "libgcc_s.so.1" : {
+ "x86-64": {"url": "lib64/libgcc_s.so.1"},
+ "x86-32": {"url": "lib32/libgcc_s.so.1"}
+ },
+ "libc.so.5055067a" : {
+ "x86-64": {"url": "lib64/libc.so.5055067a"},
+ "x86-32": {"url": "lib32/libc.so.5055067a"}
+ }
+ }
+ }
+
+
+Dynamic libraries that the dynamic program depends upon and links in
+at program startup must be listed in the ``files`` dictionary.
+Library files that are loaded after startup using ``dlopen()`` should either
+be listed in the ``files`` dictionary, or should be made accessible
+by the ``nacl_io`` library. The ``nacl_io`` library provides various
+file system *mounts* such as HTTP-based file systems and memory-based
+file systems. The Native Client SDK includes helpful tools for
+determining library dependencies and generating NaCl manifest files
+for programs that that use dynamic linking. See
+`Generating a Native Client manifest file for a dynamically linked application
+<https://developers.google.com/native-client/devguide/devcycle/dynamic-loading#manifest>`_.
+
+.. TODO(jvoung) update the link when glibc document is linkable.
+
+
+Semantics
+=========
+
+Schema validation
+-----------------
+
+Manifests are validated before the program files are downloaded.
+Schema validation checks the following properties:
+
+* The schema must be valid JSON.
+* The schema must conform to the grammar given above.
+* If the program is not a PNaCl program, then the manifest
+ must contain at least one applicable match for the current ISA
+ in "program" and in every entry within "files".
+
+If the manifest contains a field that is not in the official
+set of supported fields, it is ignored. This allows the grammar to be
+extended without breaking compatibility with older browsers.
+
+
+Nexe matching
+-------------
+
+For Portable Native Client, there are no architecture variations, so
+matching is simple.
+
+For Native Client, the main nexe for the application is determined by
+looking up the browser's current architecture in the ``"program"``
+dictionary. Failure to provide an entry for the browser's architecture
+will result in a load error.
+
+
+File matching
+-------------
+
+All files (shared objects and other assets, typically) are looked up
+by a UTF8 string that is the file name. To load a library with a certain
+file name, the browser searches the ``"files"`` dictionary for an entry
+corresponding to that file name. Failure to find that name in the
+``"files"`` dictionary is a run-time error. The architecture matching
+rule for all files is from most to least specific. That is, if there
+is an exact match for the current architecture (e.g., "x86-32") it is
+used in preference to more general "portable". This is useful for
+non-architecture-specific asset files. Note that ``"files"`` is only
+useful for files that must be loaded early in application startup
+(before PPAPI interfaces are initialized to provide the standard
+file loading mechanisms).
+
+
+URL of the nmf file, from ``<embed>`` src, and data URI
+-------------------------------------------------------
+
+The URL for the manifest file should be specified by the ``src`` attribute
+of the ``<embed>`` tag for a Native Client module instance. The URL for
+a manifest file can refer to an actual file, or it can be a
+`data URI <http://en.wikipedia.org/wiki/Data_URI_scheme>`_
+representing the contents of the file. Specifying the ``nmf`` contents
+inline with a data URI can help reduce the amount of network traffic
+required to load the Native Client application.
+
+.. _nmf_url_resolution:
+
+URL resolution
+--------------
+
+All URLs contained in a manifest are resolved relative to the URL of
+the manifest. If the manifest was specified as a data URI, the URLs must
+all be absolute.
diff --git a/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst b/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst
new file mode 100644
index 0000000000..b4cf4e817e
--- /dev/null
+++ b/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst
@@ -0,0 +1,536 @@
+==============================
+PNaCl Bitcode Reference Manual
+==============================
+
+.. contents::
+ :local:
+ :backlinks: none
+ :depth: 3
+
+Introduction
+============
+
+This document is a reference manual for the PNaCl bitcode format. It describes
+the bitcode on a *semantic* level; the physical encoding level will be described
+elsewhere. For the purpose of this document, the textual form of LLVM IR is
+used to describe instructions and other bitcode constructs.
+
+Since the PNaCl bitcode is based to a large extent on LLVM IR, many sections
+in this document point to a relevant section of the LLVM language reference
+manual. Only the changes, restrictions and variations specific to PNaCl are
+described---full semantic descriptions are not duplicated from the LLVM
+reference manual.
+
+High Level Structure
+====================
+
+A PNaCl portable executable (**pexe** in short) is a single LLVM IR module.
+
+Data Model
+----------
+
+The data model for PNaCl bitcode is fixed at little-endian ILP32: pointers are
+32 bits in size. 64-bit integer types are also supported natively via the i64
+type (for example, a front-end can generate these from the C/C++ type
+``long long``).
+
+Floating point support is fixed at IEEE 754 32-bit and 64-bit values (f32 and
+f64, respectively).
+
+.. _bitcode_linkagetypes:
+
+Linkage Types
+-------------
+
+`LLVM LangRef: Linkage Types
+<http://llvm.org/releases/3.3/docs/LangRef.html#linkage>`_
+
+The linkage types supported by PNaCl bitcode are ``internal`` and ``external``.
+A single function in the pexe, named ``_start``, has the linkage type
+``external``. All the other functions and globals have the linkage type
+``internal``.
+
+Calling Conventions
+-------------------
+
+`LLVM LangRef: Calling Conventions
+<http://llvm.org/releases/3.3/docs/LangRef.html#callingconv>`_
+
+The only calling convention supported by PNaCl bitcode is ``ccc`` - the C
+calling convention.
+
+Visibility Styles
+-----------------
+
+`LLVM LangRef: Visibility Styles
+<http://llvm.org/releases/3.3/docs/LangRef.html#visibility-styles>`_
+
+PNaCl bitcode does not support visibility styles.
+
+.. _bitcode_globalvariables:
+
+Global Variables
+----------------
+
+`LLVM LangRef: Global Variables
+<http://llvm.org/releases/3.3/docs/LangRef.html#globalvars>`_
+
+Restrictions on global variables:
+
+* PNaCl bitcode does not support LLVM IR TLS models.
+* Restrictions on :ref:`linkage types <bitcode_linkagetypes>`.
+* The ``addrspace``, ``section``, ``unnamed_addr`` and
+ ``externally_initialized`` attributes are not supported.
+
+.. TODO: link to developer's guide to explain TLS in more detail
+
+Every global variable must have an initializer. Each initializer must be
+either a *SimpleElement* or a *CompoundElement*, defined as follows.
+
+A *SimpleElement* is one of the following:
+
+1) An i8 array literal or ``zeroinitializer``:
+
+.. naclcode::
+ :prettyprint: 0
+
+ [SIZE x i8] c"DATA"
+ [SIZE x i8] zeroinitializer
+
+2) A reference to a *GlobalValue* (a function or global variable) with an
+ optional 32-bit byte offset added to it (the addend, which may be
+ negative):
+
+.. naclcode::
+ :prettyprint: 0
+
+ ptrtoint (TYPE* @GLOBAL to i32)
+ add (i32 ptrtoint (TYPE* @GLOBAL to i32), i32 ADDEND)
+
+A *CompoundElement* is a unnamed, packed struct containing more than one
+*SimpleElement*.
+
+Functions
+---------
+
+`LLVM LangRef: Functions
+<http://llvm.org/releases/3.3/docs/LangRef.html#functionstructure>`_
+
+The restrictions on :ref:`linkage types <bitcode_linkagetypes>`, calling
+conventions and visibility styles apply to functions. In addition, the following
+are not supported for functions:
+
+* Function attributes (either for the the function itself, its parameters or its
+ return type).
+* Garbage collector name (``gc``).
+* Functions with a variable number of arguments (*vararg*).
+* Alignment (``align``).
+
+Aliases
+-------
+
+`LLVM LangRef: Aliases
+<http://llvm.org/releases/3.3/docs/LangRef.html#aliases>`_
+
+PNaCl bitcode does not support aliases.
+
+Named Metadata
+--------------
+
+`LLVM LangRef: Named Metadata
+<http://llvm.org/releases/3.3/docs/LangRef.html#namedmetadatastructure>`_
+
+While PNaCl bitcode has provisions for debugging metadata, it is not considered
+part of the stable ABI. It exists for tool support and should not appear in
+distributed pexes.
+
+Other kinds of LLVM metadata are not supported.
+
+Module-Level Inline Assembly
+----------------------------
+
+`LLVM LangRef: Module-Level Inline Assembly
+<http://llvm.org/releases/3.3/docs/LangRef.html#moduleasm>`_
+
+PNaCl bitcode does not support inline assembly.
+
+Volatile Memory Accesses
+------------------------
+
+`LLVM LangRef: Volatile Memory Accesses
+<http://llvm.org/releases/3.3/docs/LangRef.html#volatile>`_
+
+PNaCl bitcode does not support volatile memory accesses. The
+``volatile`` attribute on loads and stores is not supported. See the
+`PNaCl Developer's Guide <PNaClDeveloperGuide.html>`_ for more details.
+
+.. TODO: link to developers guide once it's ported
+
+Memory Model for Concurrent Operations
+--------------------------------------
+
+`LLVM LangRef: Memory Model for Concurrent Operations
+<http://llvm.org/releases/3.3/docs/LangRef.html#memmodel>`_
+
+See the `PNaCl Developer's Guide <PNaClDeveloperGuide.html>`_ for more
+details.
+
+Fast-Math Flags
+---------------
+
+`LLVM LangRef: Fast-Math Flags
+<http://llvm.org/releases/3.3/docs/LangRef.html#fastmath>`_
+
+Fast-math mode is not currently supported by the PNaCl bitcode.
+
+Type System
+===========
+
+`LLVM LangRef: Type System
+<http://llvm.org/releases/3.3/docs/LangRef.html#typesystem>`_
+
+The LLVM types allowed in PNaCl bitcode are restricted, as follows:
+
+Scalar types
+------------
+
+* The only scalar types allowed are integer, float (32-bit floating point),
+ double (64-bit floating point) and void.
+
+ * The only integer sizes allowed are i1, i8, i16, i32 and i64.
+ * The only integer sizes allowed for function arguments and function return
+ values are i32 and i64.
+
+Array and struct types
+----------------------
+
+Array and struct types are only allowed in
+:ref:`global variable initializers <bitcode_globalvariables>`.
+
+.. _bitcode_pointertypes:
+
+Pointer types
+-------------
+
+Only the following pointer types are allowed:
+
+* Pointers to valid PNaCl bitcode scalar types, as specified above.
+* Pointers to functions.
+
+In addition, the address space for all pointers must be 0.
+
+A pointer is *inherent* when it represents the return value of an ``alloca``
+instruction, or is an address of a global value.
+
+A pointer is *normalized* if it's either:
+
+* *inherent*
+* Is the return value of a ``bitcast`` instruction.
+* Is the return value of a ``inttoptr`` instruction.
+
+Undefined Values
+----------------
+
+`LLVM LangRef: Undefined Values
+<http://llvm.org/releases/3.3/docs/LangRef.html#undefvalues>`_
+
+``undef`` is only allowed within functions, not in global variable initializers.
+
+Constant Expressions
+--------------------
+
+`LLVM LangRef: Constant Expressions
+<http://llvm.org/releases/3.3/docs/LangRef.html#constant-expressions>`_
+
+Constant expressions are only allowed in
+:ref:`global variable initializers <bitcode_globalvariables>`.
+
+Other Values
+============
+
+Metadata Nodes and Metadata Strings
+-----------------------------------
+
+`LLVM LangRef: Metadata Nodes and Metadata Strings
+<http://llvm.org/releases/3.3/docs/LangRef.html#metadata>`_
+
+While PNaCl bitcode has provisions for debugging metadata, it is not considered
+part of the stable ABI. It exists for tool support and should not appear in
+distributed pexes.
+
+Other kinds of LLVM metadata are not supported.
+
+Intrinsic Global Variables
+==========================
+
+`LLVM LangRef: Intrinsic Global Variables
+<http://llvm.org/releases/3.3/docs/LangRef.html#intrinsic-global-variables>`_
+
+PNaCl bitcode does not support intrinsic global variables.
+
+Instruction Reference
+=====================
+
+List of allowed instructions
+----------------------------
+
+This is a list of LLVM instructions supported by PNaCl bitcode. Where
+applicable, PNaCl-specific restrictions are provided.
+
+.. TODO: explain instructions or link in the future
+
+The following attributes are disallowed for all instructions:
+
+* ``nsw`` and ``nuw``
+* ``exact``
+
+Only the LLVM instructions listed here are supported by PNaCl bitcode.
+
+* ``ret``
+* ``br``
+* ``switch``
+
+ i1 values are disallowed for ``switch``.
+
+* ``add``, ``sub``, ``mul``, ``shl``, ``udiv``, ``sdiv``, ``urem``, ``srem``,
+ ``lshr``, ``ashr``
+
+ These arithmetic operations are disallowed on values of type ``i1``.
+
+ Integer division (``udiv``, ``sdiv``, ``urem``, ``srem``) by zero is
+ guaranteed to trap in PNaCl bitcode.
+
+* ``and``
+* ``or``
+* ``xor``
+* ``fadd``
+* ``fsub``
+* ``fmul``
+* ``fdiv``
+* ``frem``
+* ``alloca``
+
+ See :ref:`alloca instructions <bitcode_allocainst>`.
+
+* ``load``, ``store``
+
+ The pointer argument of these instructions must be a *normalized* pointer (see
+ :ref:`pointer types <bitcode_pointertypes>`). The ``volatile`` and ``atomic``
+ attributes are not supported. Loads and stores of the type ``i1`` are not
+ supported.
+
+ These instructions must use ``align 1`` on integer memory accesses, ``align 4``
+ for ``float`` accesses and ``align 8`` for ``double`` accesses.
+
+* ``trunc``
+* ``zext``
+* ``sext``
+* ``fptrunc``
+* ``fpext``
+* ``fptoui``
+* ``fptosi``
+* ``uitofp``
+* ``sitofp``
+
+* ``ptrtoint``
+
+ The pointer argument of a ``ptrtoint`` instruction must be a *normalized*
+ pointer (see :ref:`pointer types <bitcode_pointertypes>`) and the integer
+ argument must be an i32.
+
+* ``inttoptr``
+
+ The integer argument of a ``inttoptr`` instruction must be an i32.
+
+* ``bitcast``
+
+ The pointer argument of a ``bitcast`` instruction must be a *inherent* pointer
+ (see :ref:`pointer types <bitcode_pointertypes>`).
+
+* ``icmp``
+* ``fcmp``
+* ``phi``
+* ``select``
+* ``call``
+
+.. _bitcode_allocainst:
+
+``alloca``
+----------
+
+The only allowed type for ``alloca`` instructions in PNaCl bitcode is i8. The
+size argument must be an i32. For example:
+
+.. naclcode::
+ :prettyprint: 0
+
+ %buf = alloca i8, i32 8, align 4
+
+Intrinsic Functions
+===================
+
+`LLVM LangRef: Intrinsic Functions
+<http://llvm.org/releases/3.3/docs/LangRef.html#intrinsics>`_
+
+List of allowed intrinsics
+--------------------------
+
+The only intrinsics supported by PNaCl bitcode are the following.
+
+* ``llvm.memcpy``
+* ``llvm.memmove``
+* ``llvm.memset``
+
+ These intrinsics are only supported with an i32 ``len`` argument.
+
+* ``llvm.bswap``
+
+ The overloaded ``llvm.bswap`` intrinsic is only supported with the following
+ argument types: i16, i32, i64 (the types supported by C-style GCC builtins).
+
+* ``llvm.ctlz``
+* ``llvm.cttz``
+* ``llvm.ctpop``
+
+ The overloaded llvm.ctlz, llvm.cttz, and llvm.ctpop intrinsics are only
+ supported with the i32 and i64 argument types (the types supported by
+ C-style GCC builtins).
+
+* ``llvm.sqrt``
+
+ The overloaded ``llvm.sqrt`` intrinsic is only supported for float
+ and double arguments types. Unlike the standard LLVM intrinsic,
+ PNaCl guarantees that llvm.sqrt returns a QNaN for values less than -0.0.
+
+* ``llvm.stacksave``
+* ``llvm.stackrestore``
+
+ These intrinsics are used to implement language features like scoped automatic
+ variable sized arrays in C99. ``llvm.stacksave`` returns a value that
+ represents the current state of the stack. This value may only be used as the
+ argument to ``llvm.stackrestore``, which restores the stack to the given
+ state.
+
+* ``llvm.trap``
+
+ This intrinsic is lowered to a target dependent trap instruction, which aborts
+ execution.
+
+* ``llvm.nacl.read.tp``
+
+ See :ref:`thread pointer related intrinsics
+ <bitcode_threadpointerintrinsics>`.
+
+* ``llvm.nacl.longjmp``
+* ``llvm.nacl.setjmp``
+
+ See :ref:`Setjmp and Longjmp <bitcode_setjmplongjmp>`.
+
+* ``llvm.nacl.atomic.store``
+* ``llvm.nacl.atomic.load``
+* ``llvm.nacl.atomic.rmw``
+* ``llvm.nacl.atomic.cmpxchg``
+* ``llvm.nacl.atomic.fence``
+* ``llvm.nacl.atomic.fence.all``
+* ``llvm.nacl.atomic.is.lock.free``
+
+ See :ref:`atomic intrinsics <bitcode_atomicintrinsics>`.
+
+.. _bitcode_threadpointerintrinsics:
+
+Thread pointer related intrinsics
+---------------------------------
+
+.. naclcode::
+ :prettyprint: 0
+
+ declare i8* @llvm.nacl.read.tp()
+
+Returns a read-only thread pointer. The value is controlled by the embedding
+sandbox's runtime.
+
+.. _bitcode_setjmplongjmp:
+
+Setjmp and Longjmp
+------------------
+
+.. naclcode::
+ :prettyprint: 0
+
+ declare void @llvm.nacl.longjmp(i8* %jmpbuf, i32)
+ declare i32 @llvm.nacl.setjmp(i8* %jmpbuf)
+
+These intrinsics implement the semantics of C11 ``setjmp`` and ``longjmp``. The
+``jmpbuf`` pointer must be 64-bit aligned and point to at least 1024 bytes of
+allocated memory.
+
+.. _bitcode_atomicintrinsics:
+
+Atomic intrinsics
+-----------------
+
+.. naclcode::
+ :prettyprint: 0
+
+ declare iN @llvm.nacl.atomic.load.<size>(
+ iN* <source>, i32 <memory_order>)
+ declare void @llvm.nacl.atomic.store.<size>(
+ iN <operand>, iN* <destination>, i32 <memory_order>)
+ declare iN @llvm.nacl.atomic.rmw.<size>(
+ i32 <computation>, iN* <object>, iN <operand>, i32 <memory_order>)
+ declare iN @llvm.nacl.atomic.cmpxchg.<size>(
+ iN* <object>, iN <expected>, iN <desired>,
+ i32 <memory_order_success>, i32 <memory_order_failure>)
+ declare void @llvm.nacl.atomic.fence(i32 <memory_order>)
+ declare void @llvm.nacl.atomic.fence.all()
+
+Each of these intrinsics is overloaded on the ``iN`` argument, which is
+reflected through ``<size>`` in the overload's name. Integral types of
+8, 16, 32 and 64-bit width are supported for these arguments.
+
+The ``@llvm.nacl.atomic.rmw`` intrinsic implements the following
+read-modify-write operations, from the general and arithmetic sections
+of the C11/C++11 standards:
+
+ - ``add``
+ - ``sub``
+ - ``or``
+ - ``and``
+ - ``xor``
+ - ``exchange``
+
+For all of these read-modify-write operations, the returned value is
+that at ``object`` before the computation. The ``computation`` argument
+must be a compile-time constant.
+
+All atomic intrinsics also support C11/C++11 memory orderings, which
+must be compile-time constants.
+
+Integer values for these computations and memory orderings are defined
+in ``"llvm/IR/NaClAtomicIntrinsics.h"``.
+
+The ``@llvm.nacl.atomic.fence.all`` intrinsic is equivalent to the
+``@llvm.nacl.atomic.fence`` intrinsic with sequentially consistent
+ordering and compiler barriers preventing most non-atomic memory
+accesses from reordering around it.
+
+.. Note::
+ :class: note
+
+ These intrinsics allow PNaCl to support C11/C++11 style atomic
+ operations as well as some legacy GCC-style ``__sync_*`` builtins
+ while remaining stable as the LLVM codebase changes. The user isn't
+ expected to use these intrinsics directly.
+
+.. naclcode::
+ :prettyprint: 0
+
+ declare i1 @llvm.nacl.atomic.is.lock.free(i32 <byte_size>, i8* <address>)
+
+The ``llvm.nacl.atomic.is.lock.free`` intrinsic is designed to
+determine at translation time whether atomic operations of a certain
+``byte_size`` (a compile-time constant), at a particular ``address``,
+are lock-free or not. This reflects the C11 ``atomic_is_lock_free``
+function from header ``<stdatomic.h>`` and the C++11 ``is_lock_free``
+member function in header ``<atomic>``. It can be used through the
+``__nacl_atomic_is_lock_free`` builtin.
diff --git a/native_client_sdk/src/doc/rest-devsite-examples.rst b/native_client_sdk/src/doc/rest-devsite-examples.rst
index 3aa193c446..f2ae7c2e48 100644
--- a/native_client_sdk/src/doc/rest-devsite-examples.rst
+++ b/native_client_sdk/src/doc/rest-devsite-examples.rst
@@ -28,7 +28,8 @@ Basic markup
In general, follow the rules from http://sphinx-doc.org/rest.html
-Some **bold text** and *italic text* and ``fixed-font text``.
+Some **bold text** and *italic text* and ``fixed-font text``. Non marked-up text
+can follow these immediately by using a backslash: **pexe**\s.
For pleasant collaborative editing, please use the accepted coding guidelines:
wrap at 80 columns, no tabs, etc.
@@ -41,6 +42,15 @@ Quotes (``<blockquote>``) are created by indenting the paragraph:
Here's an en-dash -- and an m-dash --- too.
+Unicode samples
+---------------
+
+Copyright sign |copy|, and uacute |Uacute|.
+
+.. |copy| unicode:: 0xA9 .. copyright
+.. |Uacute| unicode:: U+000DA
+
+
Images
======
diff --git a/native_client_sdk/src/doc/sdk/_toc.yaml b/native_client_sdk/src/doc/sdk/_toc.yaml
new file mode 100644
index 0000000000..d889d5ec97
--- /dev/null
+++ b/native_client_sdk/src/doc/sdk/_toc.yaml
@@ -0,0 +1,10 @@
+toc:
+- title: "SDK"
+ path: /native-client/${folder}/sdk
+ section:
+ - title: "Download"
+ path: /native-client/${folder}/sdk/download
+ - title: "Examples"
+ path: /native-client/${folder}/sdk/sdk-examples
+ - title: "Release Notes"
+ path: /native-client/${folder}/sdk/release-notes
diff --git a/native_client_sdk/src/doc/sdk/download.rst b/native_client_sdk/src/doc/sdk/download.rst
index d43395a8eb..8f4f5125bb 100644
--- a/native_client_sdk/src/doc/sdk/download.rst
+++ b/native_client_sdk/src/doc/sdk/download.rst
@@ -5,70 +5,75 @@ Download the Native Client SDK
Follow the steps below to download and install the SDK:
-1. Prerequisites:
-
- * Make sure you have Python 2.6 or 2.7 installed, and that the Python
- executable is in your path.
-
- * On Mac/Linux, Python is probably preinstalled. Run the command ``"python
- -V``" in a terminal window, and make sure that the version of Python you
- have is 2.6.x or 2.7.x (if it's not, upgrade to one of those versions).
- * On Windows, you may need to install Python. Go to
- `http://www.python.org/download/ <http://www.python.org/download/>`_ and
- select the latest 2.x version. In addition, be sure to add the Python
- directory (for example, ``C:\python27``) to the PATH `environment
- variable <http://en.wikipedia.org/wiki/Environment_variable>`_. After
- you've installed Python, run the command ``"python -V``" in a Command
- Prompt window and verify that the version of Python you have is 2.6.x or
- 2.7.x.
- * Note that Python 3.x is not yet supported.
-
- * On the Mac, you need to install the ``make`` command on your system before
- you can build and run the examples. One easy way to get ``make``, along
- with several other useful tools, is to install `Xcode Developer Tools
- <https://developer.apple.com/technologies/tools/>`_. After installing
- Xcode, go to the Preferences menu, select Downloads and Components, and
- verify that Command Line Tools are installed. If you'd rather not install
- Xcode, you can download and build an `open source version
- <http://mac.softpedia.com/dyn-postdownload.php?p=44632&t=4&i=1>`_ of
- ``make``. In order to build the command you may also need to download and
- install a copy of `gcc
- <https://github.com/kennethreitz/osx-gcc-installer>`_.
-
-2. Download the SDK update utility: `nacl_sdk.zip
+Prerequisites
+-------------
+
+* Python: Make sure you have Python 2.6 or 2.7 installed, and that the Python
+ executable is in your path.
+
+ * On Mac/Linux, Python is probably preinstalled. Run the command ``"python
+ -V``" in a terminal window, and make sure that the version of Python you
+ have is 2.6.x or 2.7.x (if it's not, upgrade to one of those versions).
+ * On Windows, you may need to install Python. Go to
+ `http://www.python.org/download/ <http://www.python.org/download/>`_ and
+ select the latest 2.x version. In addition, be sure to add the Python
+ directory (for example, ``C:\python27``) to the PATH `environment
+ variable <http://en.wikipedia.org/wiki/Environment_variable>`_. After
+ you've installed Python, run the command ``"python -V``" in a Command
+ Prompt window and verify that the version of Python you have is 2.6.x or
+ 2.7.x.
+ * Note that Python 3.x is not yet supported.
+
+* Make: On the Mac, you need to install the ``make`` command on your system before
+ you can build and run the examples. One easy way to get ``make``, along
+ with several other useful tools, is to install `Xcode Developer Tools
+ <https://developer.apple.com/technologies/tools/>`_. After installing
+ Xcode, go to the Preferences menu, select Downloads and Components, and
+ verify that Command Line Tools are installed. If you'd rather not install
+ Xcode, you can download and build an `open source version
+ <http://mac.softpedia.com/dyn-postdownload.php?p=44632&t=4&i=1>`_ of
+ ``make``. In order to build the command you may also need to download and
+ install a copy of `gcc
+ <https://github.com/kennethreitz/osx-gcc-installer>`_.
+
+Download Steps
+--------------
+
+#. Download the SDK update utility: `nacl_sdk.zip
<http://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip>`_.
-3. Unzip the SDK update utility:
+#. Unzip the SDK update utility:
- * On Mac/Linux, run the command "``unzip nacl_sdk.zip``" in a Terminal window.
- * On Windows, right-click on the .zip file and select "Extract All...". A
- dialog box will open; enter a location and click "Extract".
+ * On Mac/Linux, run the command "``unzip nacl_sdk.zip``" in a Terminal window.
+ * On Windows, right-click on the .zip file and select "Extract All...". A
+ dialog box will open; enter a location and click "Extract".
- Unzipping the SDK update utility creates a directory called ``nacl_sdk`` with
- the following files and directories:
+ Unzipping the SDK update utility creates a directory called ``nacl_sdk`` with
+ the following files and directories:
- * ``naclsdk`` (and ``naclsdk.bat`` for Windows) --- the front end of the update
- utility, i.e., the command you run to download the latest bundles
- * ``sdk_cache`` --- a directory with a manifest file that lists the bundles you
- have already downloaded
- * ``sdk_tools`` --- the back end of the update utility, also known as the
- "sdk_tools" bundle
+ * ``naclsdk`` (and ``naclsdk.bat`` for Windows) --- the front end of the update
+ utility, i.e., the command you run to download the latest bundles
+ * ``sdk_cache`` --- a directory with a manifest file that lists the bundles you
+ have already downloaded
+ * ``sdk_tools`` --- the back end of the update utility, also known as the
+ "sdk_tools" bundle
-4. Go to the ``nacl_sdk`` directory and run ``naclsdk`` with the "list"
- command to see a list of available bundles. The SDK includes a separate
- bundle for each version of Chrome/Pepper (see versioning information).
+#. See which SDK versions are available: Go to the ``nacl_sdk`` directory and
+ run ``naclsdk`` with the ``"list"`` command to see a list of available bundles.
+ The SDK includes a separate bundle for each version of Chrome/Pepper
+ (see versioning information).
- On Mac/Linux::
+ On Mac/Linux::
- $ cd nacl_sdk
- $ ./naclsdk list
+ $ cd nacl_sdk
+ $ ./naclsdk list
- On Windows::
+ On Windows::
- > cd nacl_sdk
- > naclsdk list
+ > cd nacl_sdk
+ > naclsdk list
- You should see output similar to this::
+ You should see output similar to this::
Bundles:
I: installed
@@ -76,60 +81,68 @@ Follow the steps below to download and install the SDK:
I sdk_tools (stable)
vs_addin (dev)
- pepper_25 (post_stable)
pepper_26 (post_stable)
pepper_27 (post_stable)
- pepper_28 (stable)
- pepper_29 (beta)
- pepper_30 (dev)
+ pepper_28 (post_stable)
+ pepper_29 (post_stable)
+ pepper_30 (stable)
+ pepper_31 (beta)
pepper_canary (canary)
- This sample output shows many bundles available for download, and that you
- have already installed the latest revision of the sdk_tools bundle (it was
- included in the zip file you downloaded). Note that the bundles are labelled
- "post-stable", "stable", "beta", "dev" and "canary". These labels correspond
- to the current versions of Chrome. In this example, Chrome 28 is stable,
- Chrome 29 is beta, etc. Therefore ``pepper_28`` is the recommended bundle to
- download, because if you released an application that used it today, it
- could be used by all current Chrome users. Note that Native Client is
- designed to be backward compatible---users of Chrome 29 can use the features
- of ``pepper_28`` and earlier.
-
-5. Run ``naclsdk`` with the "update" command to download particular bundles that
+ This sample output shows many bundles available for download, and that you
+ have already installed the latest revision of the sdk_tools bundle (it was
+ included in the zip file you downloaded). Note that the bundles are labelled
+ "post-stable", "stable", "beta", "dev" and "canary". These labels correspond
+ to the current versions of Chrome. In this example, Chrome 30 is stable,
+ Chrome 31 is beta, etc. Therefore ``pepper_30`` is the recommended bundle to
+ download, because if you released an application that used it today, it
+ could be used by all current Chrome users. Note that Native Client is
+ designed to be backward compatible---users of Chrome 31 can use the features
+ of ``pepper_30`` and earlier.
+
+#. Run ``naclsdk`` with the "update" command to download particular bundles that
are available.
- On Mac/Linux::
+ On Mac/Linux::
- $ ./naclsdk update
+ $ ./naclsdk update
- On Windows::
+ On Windows::
- > naclsdk update
+ > naclsdk update
- By default, ``naclsdk`` only downloads bundles that are recommended. In
- general, only the "stable" bundles are recommended. Continuing with the
- earlier example, the "update" command would only download the ``pepper_28``
- bundles, since the bundles ``pepper_29`` and greater are not yet recommended.
- If you want the ``pepper_29`` bundle, you must ask for it explicitly::
+ By default, ``naclsdk`` only downloads bundles that are recommended. In
+ general, only the "stable" bundles are recommended. Continuing with the
+ earlier example, the "update" command would only download the ``pepper_30``
+ bundles, since the bundles ``pepper_31`` and greater are not yet recommended.
+ If you want the ``pepper_31`` bundle, you must ask for it explicitly::
- $ ./naclsdk update pepper_29
+ $ ./naclsdk update pepper_31
- Note that you never need update the ``sdk_tools`` bundle, it is
- updated automatically as necessary whenever ``naclsdk`` is run.
+ Note that you never need update the ``sdk_tools`` bundle, it is
+ updated automatically as necessary whenever ``naclsdk`` is run.
-6. Run ``naclsdk`` with the "list" command again; this will show you the list of
+.. Note::
+ :class: note
+
+ The minimum SDK version that supports PNaCl is ``pepper_31``.
+
+Staying up-to-date and getting new versions
+-------------------------------------------
+
+#. Run ``naclsdk`` with the "list" command again; this will show you the list of
available bundles and verify which bundles are installed.
- On Mac/Linux::
+ On Mac/Linux::
- $ ./naclsdk list
+ $ ./naclsdk list
- On Windows::
+ On Windows::
- > naclsdk list
+ > naclsdk list
- Continuing with the earlier example, if you previously downloaded the
- ``pepper_28`` bundle, you should see output similar to this::
+ Continuing with the earlier example, if you previously downloaded the
+ ``pepper_30`` bundle, you should see output similar to this::
Bundles:
I: installed
@@ -137,32 +150,32 @@ Follow the steps below to download and install the SDK:
I sdk_tools (stable)
vs_addin (dev)
- pepper_25 (post_stable)
pepper_26 (post_stable)
pepper_27 (post_stable)
- I pepper_28 (stable)
- pepper_29 (beta)
- pepper_30 (dev)
+ pepper_28 (post_stable)
+ pepper_29 (post_stable)
+ I pepper_30 (stable)
+ pepper_31 (beta)
pepper_canary (canary)
-7. Running ``naclsdk`` with the "update" command again will verify that your
+#. Running ``naclsdk`` with the "update" command again will verify that your
bundles are up-to-date, or warn if you there are new versions of previously
installed bundles.
- On Mac/Linux::
+ On Mac/Linux::
- $ ./naclsdk update
+ $ ./naclsdk update
- On Windows::
+ On Windows::
- > naclsdk update
+ > naclsdk update
- Continuing with the earlier example, you should see output similar to this::
+ Continuing with the earlier example, you should see output similar to this::
- pepper_28 is already up-to-date.
+ pepper_30 is already up-to-date.
- To check if there is a new version of a previously installed bundle, you can
- run the "list" command again::
+#. To check if there is a new version of a previously installed bundle, you can
+ run the "list" command again::
Bundles:
I: installed
@@ -170,52 +183,49 @@ Follow the steps below to download and install the SDK:
I sdk_tools (stable)
vs_addin (dev)
- pepper_25 (post_stable)
pepper_26 (post_stable)
pepper_27 (post_stable)
- I* pepper_28 (stable)
- pepper_29 (beta)
- pepper_30 (dev)
+ pepper_28 (post_stable)
+ pepper_29 (post_stable)
+ I* pepper_30 (stable)
+ pepper_31 (beta)
pepper_canary (canary)
- The asterisk next to the bundle name indicates that there is an update
- available. If you run the "update" command now, ``naclsdk`` will warn you
- with a message similar to this::
+ The asterisk next to the bundle name indicates that there is an update
+ available. If you run the "update" command now, ``naclsdk`` will warn you
+ with a message similar to this::
- WARNING: pepper_28 already exists, but has an update available.
- Run update with the --force option to overwrite the existing directory.
- Warning: This will overwrite any modifications you have made within this directory.
+ WARNING: pepper_30 already exists, but has an update available.
+ Run update with the --force option to overwrite the existing directory.
+ Warning: This will overwrite any modifications you have made within this directory.
- To dowload the new version of a bundle and overwrite the existing directory
- for that bundle, run ``naclsdk`` with the ``--force`` option.
+ To dowload the new version of a bundle and overwrite the existing directory
+ for that bundle, run ``naclsdk`` with the ``--force`` option.
- On Mac/Linux::
+ On Mac/Linux::
- $ ./naclsdk update --force
+ $ ./naclsdk update --force
- On Windows::
+ On Windows::
- > naclsdk update --force
+ > naclsdk update --force
-8. For more information about the ``naclsdk`` utility, run:
+#. For more information about the ``naclsdk`` utility, run:
- On Mac/Linux::
+ On Mac/Linux::
- $ ./naclsdk help
+ $ ./naclsdk help
- On Windows::
+ On Windows::
- > naclsdk help
+ > naclsdk help
Next steps:
- * Browse through the `Release Notes
- <https://developers.google.com/native-client/sdk/release-notes>`_ for
- important information about the SDK and new bundles.
- * If you're just getting started with Native Client, we recommend reading
- the :doc:`Technical Overview <../overview>` and walking through the
- `Getting Started Tutorial
- <https://developers.google.com/native-client/devguide/tutorial>`_.
- * If you'd rather dive into information about the toolchains, see `Building
- Native Client Modules
- <https://developers.google.com/native-client/devguide/devcycle/building>`_.
+* Browse through the :doc:`Release Notes <release-notes>` for important
+ information about the SDK and new bundles.
+* If you're just getting started with Native Client, we recommend reading
+ the :doc:`Technical Overview <../overview>` and walking through the
+ :doc:`Getting Started Tutorial </devguide/tutorial>`.
+* If you'd rather dive into information about the toolchains, see
+ :doc:`Building Native Client Modules </devguide/devcycle/building>`.
diff --git a/native_client_sdk/src/doc/sdk/examples.rst b/native_client_sdk/src/doc/sdk/examples.rst
index 46b3bea30f..f849bb302f 100644
--- a/native_client_sdk/src/doc/sdk/examples.rst
+++ b/native_client_sdk/src/doc/sdk/examples.rst
@@ -11,17 +11,22 @@ on this page to build and run the examples.
Configure the Google Chrome Browser
-----------------------------------
-1. Your version of Chrome must be equal to or greater than the version of
- your SDK bundle. For example, if you're developing with the ``pepper_28``
- bundle, you must use Google Chrome version 28 or greater. To find out what
+#. Your version of Chrome must be equal to or greater than the version of
+ your SDK bundle. For example, if you're developing with the ``pepper_31``
+ bundle, you must use Google Chrome version 31 or greater. To find out what
version of Chrome you're using, type ``about:chrome`` or ``about:version``
in the Chrome address bar.
-2. Enable the Native Client flag. Native Client is enabled by default only
- for applications distributed through the Chrome Web Store. To run Native
- Client applications that are not distributed through the Chrome Web Store,
- like the SDK examples, you must specifically enable the Native Client flag
- in Chrome:
+#. For Portable Native Client, no extra Chrome flags are needed as of
+ Chrome version 31.
+
+ For other Native Client applications, or to **debug** Portable Native
+ Client applications by translating the **pexe** to a **nexe** ahead of
+ time, enable the Native Client flag. Native Client is enabled by default
+ only for applications distributed through the Chrome Web Store. To run
+ Native Client applications that are not distributed through the Chrome
+ Web Store, like the SDK examples, you must specifically enable the Native
+ Client flag in Chrome:
* Type ``about:flags`` in the Chrome address bar and scroll down to
"Native Client".
@@ -31,7 +36,7 @@ Configure the Google Chrome Browser
link, scroll down to the bottom of the page, and click the "Relaunch
Now" button. All browser windows will restart when you relaunch Chrome.
-3. Disable the Chrome cache. Chrome caches resources aggressively; when you
+#. Disable the Chrome cache. Chrome caches resources aggressively; when you
are building a Native Client application you should disable the cache to
make sure that Chrome loads the latest version:
@@ -53,85 +58,85 @@ toolchains).
To build all the examples, go to the examples directory in a specific SDK
bundle and run ``make``::
- $ cd pepper_28/examples
- $ make
- make -C api all
- make[1]: Entering directory `pepper_28/examples/api'
- make -C audio all
- make[2]: Entering directory `pepper_28/examples/api/audio'
- CXX newlib/Debug/audio_x86_32.o
- LINK newlib/Debug/audio_x86_32.nexe
- CXX newlib/Debug/audio_x86_64.o
- LINK newlib/Debug/audio_x86_64.nexe
- CXX newlib/Debug/audio_arm.o
- LINK newlib/Debug/audio_arm.nexe
- CREATE_NMF newlib/Debug/audio.nmf
- make[2]: Leaving directory `pepper_28/examples/api/audio'
- make -C url_loader all
- make[2]: Entering directory `pepper_28/examples/api/url_loader'
- CXX newlib/Debug/url_loader_x86_32.o
- ...
+ $ cd pepper_31/examples
+ $ make
+ make -C api all
+ make[1]: Entering directory `pepper_31/examples/api'
+ make -C audio all
+ make[2]: Entering directory `pepper_31/examples/api/audio'
+ CXX newlib/Debug/audio_x86_32.o
+ LINK newlib/Debug/audio_x86_32.nexe
+ CXX newlib/Debug/audio_x86_64.o
+ LINK newlib/Debug/audio_x86_64.nexe
+ CXX newlib/Debug/audio_arm.o
+ LINK newlib/Debug/audio_arm.nexe
+ CREATE_NMF newlib/Debug/audio.nmf
+ make[2]: Leaving directory `pepper_31/examples/api/audio'
+ make -C url_loader all
+ make[2]: Entering directory `pepper_31/examples/api/url_loader'
+ CXX newlib/Debug/url_loader_x86_32.o
+ ...
Calling ``make`` from inside a particular example's directory will build only
that example::
- $ cd pepper_28/examples/api/core
- $ make
- CXX newlib/Debug/core_x86_32.o
- LINK newlib/Debug/core_x86_32.nexe
- CXX newlib/Debug/core_x86_64.o
- LINK newlib/Debug/core_x86_64.nexe
- CXX newlib/Debug/core_arm.o
- LINK newlib/Debug/core_arm.nexe
- CREATE_NMF newlib/Debug/core.nmf
+ $ cd pepper_31/examples/api/core
+ $ make
+ CXX newlib/Debug/core_x86_32.o
+ LINK newlib/Debug/core_x86_32.nexe
+ CXX newlib/Debug/core_x86_64.o
+ LINK newlib/Debug/core_x86_64.nexe
+ CXX newlib/Debug/core_arm.o
+ LINK newlib/Debug/core_arm.nexe
+ CREATE_NMF newlib/Debug/core.nmf
You can call ``make`` with the ``TOOLCHAIN`` and ``CONFIG`` parameters to
override the defaults::
- $ make TOOLCHAIN=pnacl CONFIG=Release
- CXX pnacl/Release/core_pnacl.o
- LINK pnacl/Release/core.bc
- FINALIZE pnacl/Release/core.pexe
- CREATE_NMF pnacl/Release/core.nmf
+ $ make TOOLCHAIN=pnacl CONFIG=Release
+ CXX pnacl/Release/core_pnacl.o
+ LINK pnacl/Release/core.bc
+ FINALIZE pnacl/Release/core.pexe
+ CREATE_NMF pnacl/Release/core.nmf
You can also set ``TOOLCHAIN`` to "all" to build one or more examples with
all available toolchains::
- $ make TOOLCHAIN=all
- make TOOLCHAIN=newlib
- make[1]: Entering directory `pepper_31/examples/api/core'
- CXX newlib/Debug/core_x86_32.o
- LINK newlib/Debug/core_x86_32.nexe
- CXX newlib/Debug/core_x86_64.o
- LINK newlib/Debug/core_x86_64.nexe
- CXX newlib/Debug/core_arm.o
- LINK newlib/Debug/core_arm.nexe
- CREATE_NMF newlib/Debug/core.nmf
- make[1]: Leaving directory `pepper_31/examples/api/core'
- make TOOLCHAIN=glibc
- make[1]: Entering directory `pepper_31/examples/api/core'
- CXX glibc/Debug/core_x86_32.o
- LINK glibc/Debug/core_x86_32.nexe
- CXX glibc/Debug/core_x86_64.o
- LINK glibc/Debug/core_x86_64.nexe
- CREATE_NMF glibc/Debug/core.nmf
- make[1]: Leaving directory `pepper_31/examples/api/core'
- make TOOLCHAIN=pnacl
- make[1]: Entering directory `pepper_31/examples/api/core'
- CXX pnacl/Debug/core_pnacl.o
- LINK pnacl/Debug/core.bc
- FINALIZE pnacl/Debug/core.pexe
- TRANSLATE pnacl/Debug/core_x86_32.nexe
- TRANSLATE pnacl/Debug/core_x86_64.nexe
- TRANSLATE pnacl/Debug/core_arm.nexe
- CREATE_NMF pnacl/Debug/core.nmf
- make[1]: Leaving directory `pepper_31/examples/api/core'
- make TOOLCHAIN=linux
- make[1]: Entering directory `pepper_31/examples/api/core'
- CXX linux/Debug/core.o
- LINK linux/Debug/core.so
- make[1]: Leaving directory `pepper_31/examples/api/core'
+ $ make TOOLCHAIN=all
+ make TOOLCHAIN=newlib
+ make[1]: Entering directory `pepper_31/examples/api/core'
+ CXX newlib/Debug/core_x86_32.o
+ LINK newlib/Debug/core_x86_32.nexe
+ CXX newlib/Debug/core_x86_64.o
+ LINK newlib/Debug/core_x86_64.nexe
+ CXX newlib/Debug/core_arm.o
+ LINK newlib/Debug/core_arm.nexe
+ CREATE_NMF newlib/Debug/core.nmf
+ make[1]: Leaving directory `pepper_31/examples/api/core'
+ make TOOLCHAIN=glibc
+ make[1]: Entering directory `pepper_31/examples/api/core'
+ CXX glibc/Debug/core_x86_32.o
+ LINK glibc/Debug/core_x86_32.nexe
+ CXX glibc/Debug/core_x86_64.o
+ LINK glibc/Debug/core_x86_64.nexe
+ CREATE_NMF glibc/Debug/core.nmf
+ make[1]: Leaving directory `pepper_31/examples/api/core'
+ make TOOLCHAIN=pnacl
+ make[1]: Entering directory `pepper_31/examples/api/core'
+ CXX pnacl/Debug/core_pnacl.o
+ LINK pnacl/Debug/core.bc
+ FINALIZE pnacl/Debug/core.pexe
+ TRANSLATE pnacl/Debug/core_x86_32.nexe
+ TRANSLATE pnacl/Debug/core_x86_64.nexe
+ TRANSLATE pnacl/Debug/core_arm.nexe
+ CREATE_NMF pnacl/Debug/core.nmf
+ make[1]: Leaving directory `pepper_31/examples/api/core'
+ make TOOLCHAIN=linux
+ make[1]: Entering directory `pepper_31/examples/api/core'
+ CXX linux/Debug/core.o
+ LINK linux/Debug/core.so
+ make[1]: Leaving directory `pepper_31/examples/api/core'
After running ``make``, each example directory will contain one or more of
@@ -159,8 +164,8 @@ Run the SDK examples
To run the SDK examples, you can use the ``make run`` command::
- $ cd pepper_28/examples/api/core
- $ make run
+ $ cd pepper_31/examples/api/core
+ $ make run
This will launch a local HTTP server which will serve the data for the
example. It then launches Chrome with the address of this server, usually
@@ -171,30 +176,31 @@ This command will try to find an executable named ``google-chrome`` in your
``PATH`` environment variable. If it can't, you'll get an error message like
this::
- pepper_31/tools/common.mk:415: No valid Chrome found at CHROME_PATH=
- pepper_31/tools/common.mk:415: *** Set CHROME_PATH via an environment variable, or command-line.. Stop.
+ pepper_31/tools/common.mk:415: No valid Chrome found at CHROME_PATH=
+ pepper_31/tools/common.mk:415: *** Set CHROME_PATH via an environment variable, or command-line.. Stop.
Set the CHROME_PATH environment variable to the location of your Chrome
-executable **TODO(binji):** use default Chrome paths here, especially
-important for Mac:
+executable.
- On Windows::
+On Windows::
- > set CHROME_PATH=<Path to chrome.exe>
+ > set CHROME_PATH=<Path to chrome.exe>
- On Linux::
+On Linux::
- $ export CHROME_PATH=<Path to google-chrome>
+ $ export CHROME_PATH=<Path to google-chrome>
- On Mac::
+On Mac::
- $ export CHROME_PATH=<Path to chrome>
+ $ export CHROME_PATH=<Path to chrome>
+.. **TODO(binji):** use default Chrome paths here, especially
+.. important for Mac:
You can run via a different toolchain or configuration by using the
``TOOLCHAIN`` and ``CONFIG`` parameters to make::
- $ make run TOOLCHAIN=pnacl CONFIG=Debug
+ $ make run TOOLCHAIN=pnacl CONFIG=Debug
Run the SDK examples as packaged apps
@@ -210,11 +216,18 @@ Some Pepper features, such as TCP/UDP socket access, are only allowed in
packaged apps. The examples that use these features must be run as packaged
apps, by using the ``make run_package`` command::
- $ make run_package
+ $ make run_package
You can use ``TOOLCHAIN`` and ``CONFIG`` parameters as above to run with a
different toolchain or configuration.
+.. **TODO(jvoung)**: That doesn't seem to work in pepper_canary.
+.. It just picks newlib.
+.. https://code.google.com/p/chromium/issues/detail?id=307724
+
+
+.. _debugging_the_sdk_examples:
+
Debugging the SDK examples
--------------------------
@@ -222,7 +235,7 @@ The NaCl SDK uses `GDB <https://www.gnu.org/software/gdb/>`_ to debug Native
Client code. The SDK includes a prebuilt version of GDB that is compatible with
NaCl code. To use it, run the ``make debug`` command from an example directory::
- $ make debug
+ $ make debug
This will launch Chrome with the ``--enable-nacl-debug`` flag set. This flag
will cause Chrome to pause when a NaCl module is first loaded, waiting for a
@@ -230,13 +243,13 @@ connection from gdb. The ``make debug`` command also simultaneously launches
GDB and loads the symbols for that NEXE. To connect GDB to Chrome, in the GDB
console, type::
- (gdb) target remote :4014
+ (gdb) target remote :4014
This tells GDB to connect to a TCP port on localhost:4014--the port that
Chrome is listening on. GDB will respond::
- Remote debugging using :4014
- 0x000000000fa00080 in ?? ()
+ Remote debugging using :4014
+ 0x000000000fa00080 in ?? ()
At this point, you can use the standard GDB commands to debug your NaCl module.
The most common commands you will use to debug are ``continue``, ``step``,
diff --git a/native_client_sdk/src/doc/sdk/release-notes.rst b/native_client_sdk/src/doc/sdk/release-notes.rst
index 41f98dd6fc..9ff317ce5a 100644
--- a/native_client_sdk/src/doc/sdk/release-notes.rst
+++ b/native_client_sdk/src/doc/sdk/release-notes.rst
@@ -1,8 +1,521 @@
.. _sdk-release-notes:
-#################
-SDK Release Notes
-#################
+#############
+Release Notes
+#############
-foo
+This page provides notes for all releases of the Native Client SDK (including
+releases that have been or will be published subsequent to Pepper 28).
+PNaCl in Chrome 30 Dev channel (01 Aug 2013)
+============================================
+
+* Portable Native Client (PNaCl) is currently available for preview in Chrome
+ 30 (currently in the Dev channel). Apps and sites built with PNaCl can run in
+ Chrome 30 without an explicit flag.
+* See `Introduction to Portable Native Client
+ <http://www.chromium.org/nativeclient/pnacl/introduction-to-portable-native-client>`_
+ for information on developing for PNaCl. More documentation will be available
+ soon.
+* Please note that the `PNaCl bitcode ABI
+ <http://www.chromium.org/nativeclient/pnacl/bitcode-abi>`_ may still change
+ before the official public release; if you're developing a PNaCl-based
+ application, be sure to build your code with the latest version of the Native
+ Client SDK.
+* Update: PNaCl is not enabled by default in beta or stable versions of M30.
+
+PNaCl (15 May 2013)
+===================
+
+* Portable Native Client (PNaCl) is currently available for developer preview
+ in Chrome 29 or higher.
+* To produce a PNaCl executable (.pexe) file, you must use the pnacl toolchain
+ in the current ``pepper_canary`` bundle. Chrome 29 does not support .pexe
+ files produced by earlier versions of the pnacl toolchain (that is,
+ executables compiled with the ``pepper_28`` bundle or earlier).
+* To run an application with a PNaCl module, you must launch Chrome 29 with the
+ ``--enable-pnacl`` flag (for `packaged apps
+ <http://developer.chrome.com/apps/about_apps.html>`_), or the
+ ``--enable-nacl`` flag (for other apps).
+* When you launch Chrome with the ``--enable-pnacl`` flag, Chrome loads a PNaCl
+ translator in the background. Wait about a minute after you launch Chrome and
+ check `chrome://nacl <chrome://nacl>`_ to verify that the translator loaded.
+* PNaCl translators are currently available for 32-bit x86, 64-bit x86, and ARM
+ architectures.
+* PNaCl applications must use the newlib C library (glibc and dynamic linking
+ are not supported yet).
+* The intermediate representation (IR) format may change prior to the release
+ of PNaCl. If so, you will need to recompile your application with the pnacl
+ toolchain in a new SDK bundle.
+
+Pepper 27 (12 April 2013)
+=========================
+
+The Pepper 27 bundle features a significant number of new libraries that have
+been incorporated directly into the SDK.
+
+Libraries
+---------
+
+* A number of libraries from the naclports project have been incorporated
+ directly into the Native Client SDK. These libraries include:
+
+ * image encoding/decoding: jpeg, tiff, png, webp
+ * multimedia: openal, freealut, ogg, vorbis
+ * XML parsing: tinyxml, xml2
+ * miscellaneous: zlib (general purpose compression), freetype (font
+ rendering), lua (Lua interpreter)
+
+ The libraries are located in ``ports/lib``, and the header files are in
+ ``ports/include``.
+
+* The ``httpfs`` filesystem in the nacl_io library now caches content in memory
+ by default; this improves performance considerably.
+* For applications compiled with a glibc toolchain, ``dlopen()`` can now be
+ used to open shared libraries that are not specified in an application's
+ Native Client manifest (.nmf) file. This allows applications, for example, to
+ download a shared object and then use ``dlopen()`` to access the shared
+ object. The ``dlopen`` example has been modified to demonstrate this
+ functionality: reverse.cc is built into a shared object (.so) file, which is
+ downloaded and opened using an ``httpfs`` mount.
+
+Examples
+--------
+
+* Each example now has a single ``index.html`` file, instead of multiple HTML
+ files corresponding to NaCl modules built using different toolchains and
+ configurations. By default, most examples are built using one toolchain
+ (newlib) and one configuration (Debug). If you build an example using
+ multiple toolchains or configurations, you can specify which version to run
+ in Chrome using the query parameters ``tc`` and ``config``. For example,
+ assuming you are serving an example from the local server localhost:5103, you
+ can run a version of the example built with the glibc toolchain in the
+ Release configuration by specifying the following URL in Chrome:
+ ``http://localhost:5103/index.html?tc=glibc&config=Release``. For additional
+ information about how different NaCl modules are loaded into ``index.html``,
+ see the ``common.js`` file in each example.
+
+Build tools and toolchains
+--------------------------
+
+* Common makefiles, including ``tools/common.mk``, can now handle source files
+ located outside of an application's root directory. For example, a Makefile
+ for an application can specify a source file to compile such as
+ ``../../some/other/place.cpp``.
+
+Pepper 26 (29 March 2013)
+=========================
+
+The Pepper 26 bundle includes a new HTTP filesystem type in the nacl_mounts
+library (which has been renamed nacl_io), changes to the example Makefiles, a
+simple new 3D example, and a threaded file IO example.
+
+Build tools and toolchains
+--------------------------
+
+* Makefiles have been changed significantly:
+
+ * Build commands are now specified in a number of common files
+ (``tools/*.mk``), which are included in the Makefiles in the examples.
+ * By default, make displays a simplified list of build steps (e.g., ``CC
+ newlib/Debug/hello_world_x86_32.o``) rather than the actual build commands.
+ To see the actual build commands, run ``make V=1``.
+ * By default, most examples are built using one toolchain (newlib) and one
+ configuration (Debug). To build an example using a different toolchain or
+ configuration, run ``make`` with the parameters ``TOOLCHAIN=<x>`` or
+ ``CONFIG=<y>``. You can also run make ``all_versions`` to build an example
+ with all toolchains.
+
+* Header files have been moved out of the toolchains. All toolchains now share
+ the same set of header files as host builds. Previously host and NaCl builds
+ used different headers, which could cause build problems.
+
+Libraries
+---------
+
+* The nacl_mounts library has been renamed **nacl_io**, and has been expanded
+ with a new type of mount, httpfs, which can be used to read URLs via HTTP.
+ For details see ``include/nacl_io/nacl_io.h``, as well as the
+ ``hello_nacl_io`` example.
+
+Examples
+--------
+
+* A new example, **hello_world_instance3d**, has been added to demonstrate a
+ simplified 3D app.
+* The **file_io** example has been rewritten to do all file operations on a
+ thread. The example demonstrates how to use the MessageLoop API and blocking
+ callbacks on a thread.
+
+General
+-------
+
+* Old bundles (``pepper_20`` and earlier) have been removed from the Native
+ Client SDK Manifest, and will no longer be updated by the ``naclsdk``
+ command.
+
+Pepper 25 (21 December 2012)
+============================
+
+The Pepper 25 bundle features an ARM toolchain to build Native Client modules
+for ARM devices, two new Pepper APIs (including the MessageLoop API, which lets
+you make Pepper calls on background threads), two new libraries (nacl_mounts,
+which provides a virtual file system that you can use with standard C file
+operations, and ppapi_main, which lets you implement a Native Client module
+using a simple ppapi_main function), and two new examples that demonstrate how
+to use the nacl_mounts and ppapi_main libraries.
+
+Build tools and toolchains
+--------------------------
+
+* The SDK includes a new toolchain to build Native Client executables (.nexe
+ files) for **ARM devices**.
+
+ * Currently the ARM toolchain can only be used to compile modules that use
+ the :ref:`newlib C library <c_libraries>`. You cannot use the ARM toolchain
+ to compile modules that use the glibc library.
+ * The ARM toolchain is in the directory
+ ``pepper_25/toolchain/<host>_arm_newlib``. The bin subdirectory contains
+ the compiler (``arm-nacl-gcc``), the linker (``arm-nacl-g++``), and the
+ other tools in the toolchain.
+ * Take a look at the ``hello_world`` example to see how to use the ARM
+ toolchain. Go to ``examples/hello_world`` and run ``make``. When the build
+ finishes, the newlib/Debug and newlib/Release subdirectories will contain
+ .nexe files for the x86-32, x86-64, and ARM target architecutes, and a
+ Native Client manifest (.nmf file) that references those three .nexe files.
+
+* The simple web server included in the SDK, ``httpd.py``, has been moved from
+ the ``examples/`` directory to the ``tools/`` directory. On Windows, you can
+ run ``httpd.cmd`` (in the ``examples/`` directory) to start the server.
+
+PPAPI
+-----
+
+Pepper 25 includes two new APIs:
+
+* The `Console API
+ <https://developers.google.com/native-client/dev/pepperc/struct_p_p_b___console__1__0>`_
+ lets your module log messages to the JavaScript console in the Chrome browser.
+* The `MessageLoop
+ <https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_message_loop>`_
+ API lets your module make PPAPI calls on a background thread. Once you've
+ created a message loop resource, attached it to a thread, and run it, you can
+ post work to the thread, including completion callbacks for asynchronous
+ operations. For a C++ example of how to use the MessageLoop API,
+ see ``pepper_25/include/ppapi/utility/threading/simple_thread.h``. Note that
+ you cannot make asynchronous PPAPI calls on a background thread without
+ creating and using a message loop.
+
+Libraries
+---------
+
+The SDK includes two new libraries:
+
+* The **nacl_mounts** library provides a virtual file system that your module
+ can "mount" in a given directory tree. The file system can be one of several
+ types:
+
+ * "memfs" is an in-memory file system,
+ * "dev" is a file system with various utility nodes (e.g., ``/dev/null``,
+ ``/dev/console[0-3]``, ``/dev/tty``), and
+ * "html5fs" is a persistent file system.
+
+ Once you've mounted a file system in your module, you can use standard C
+ library file operations: fopen, fread, fwrite, fseek, and fclose. How those
+ operations are performed depends on the type of file system (e.g., for
+ html5fs, the operations are performed using the Pepper FileIO API). For a
+ list of the types of file systems you can mount, see
+ include/nacl_mounts/nacl_mounts.h. For an example of how to use nacl_mounts,
+ see examples/hello_nacl_mounts. Note that html5fs is subject to the same
+ constraints as persistent :ref:`local file IO <devguide-coding-fileio>` in
+ Chrome (for example, prior to using an html5fs file system, you must `enable
+ local file IO <enabling_file_access>`_).
+
+* The **ppapi_main** library simplifies the creation of a NaCl module by
+ providing a familiar C programming environment. With this library, your
+ module can have a simple entry point called ppapi_main(), which is similar to
+ the standard C main() function, complete with argc and argv[] parameters.
+ Your module can also use standard C functions such as printf(), fopen(), and
+ fwrite(). For details see include/ppapi_main/ppapi_main.h. For an example of
+ how to use ppapi_main, see examples/hello_world_stdio.
+
+Header files for the new libraries are in the ``include/`` directory, source
+files are in the ``src/`` directory, and compiled libraries are in the ``lib/``
+directory.
+
+Examples
+--------
+
+* The SDK includes two new examples:
+
+ * **hello_nacl_mounts** illustrates how to use standard C library file
+ operations in a Native Client module through the use of the nacl_mounts
+ library.
+ * **hello_world_stdio** illustrates how to implement a Native Client module
+ with a ppapi_main() function, and how to write to STDOUT and STDERR in a
+ module, through the use of the nacl_mounts and ppapi_main libraries. This
+ example makes it easy for new users to get started with Native Client by
+ letting them start making changes in a familiar C environment.
+
+* With a few exceptions, the Makefile for each example now builds the following
+ versions of each example:
+
+ * glibc toolchain: 32-bit and 64-bit .nexes for the x86 target architecture
+ * newlib toolchain: 32-bit and 64-bit .nexes for the x86 target architecture,
+ and ARM .nexe for the ARM architecture
+ * pnacl toolchain: .pexe (which is subsequently tranlsated to .nexes for the
+ x86-32, x86-64, and ARM architectures)
+ * hosted toolchain: .so or .dll (to be executed as a Pepper plug-in in
+ Chrome)
+
+* Additionally, each version is built in both a Debug and a Release
+ configuration.
+* The Makefile for each example includes two new targets: ``make RUN`` and
+ ``make LAUNCH``. These targets, which are interchangeable, launch a local
+ server and an instance of Chrome to run an example. When the instance of
+ Chrome is closed, the local server is shut down as well.
+* The hello_world_stdio example includes a simplified Makefile that only lists
+ source dependencies, and invokes the build rules in a separate file
+ (common.mk).
+
+Pepper 24 (5 December 2012)
+===========================
+
+The Pepper 24 bundle features a new, experimental toolchain called PNaCl (short
+for "Portable Native Client"), a new library (pthreads-win32) for the Windows
+SDK, and an expanded list of attributes for Pepper 3D contexts that lets
+applications specify a GPU preference for low power or performance.
+
+Build tools and toolchains
+--------------------------
+
+* The SDK includes a new, experimental toolchain called `PNaCl
+ <http://nativeclient.googlecode.com/svn/data/site/pnacl.pdf>`_ (pronounced
+ "pinnacle"). The PNaCl toolchain produces architecture-independent executable
+ files (.pexe files). Chrome doesn't yet support .pexe files directly, but if
+ you want to experiment with this early preview of PNaCl, the toolchain
+ includes a tool to translate .pexe files into architecture-specific .nexe
+ files. Take a look at the ``hello_world`` example to see how to build a .pexe
+ file and translate it into multiple .nexe files. Note that PNaCl is currently
+ restricted to the newlib C standard library – if your application uses glibc,
+ you can't build it with PNaCl.
+* The ``create_nmf.py`` script uses ELF headers (rather than file names) to
+ determine the architecture of .nexe files. That means you can change the
+ names of your .nexe files and ``create_nmf.py`` will still be able to
+ generate the appropriate Native Client manifest file for your application.
+
+Examples
+--------
+
+* The SDK examples now build with four toolchains: the glibc and newlib
+ toolchains, the experimental PNaCl toolchain, and the hosted toolchain on
+ your development machine. Within each toolchain build, each example also
+ builds both a debug and a release version.
+* The example Makefiles use dependency (.d) files to enable incremental builds.
+* The pong example has been cleaned up and modified to run more smoothly. The
+ drawing function is now set up as the Flush() callback, which allows 2D
+ drawing to occur as quickly as possible.
+
+PPAPI
+-----
+
+* When creating a 3D rendering context, the `attribute list
+ <https://developers.google.com/native-client/dev/pepperc/group___enums#ga7df48e1c55f6401beea2a1b9c07967e8>`_
+ for the context can specify whether to prefer low power or performance for
+ the GPU. Contexts with a low power preference may be created on an integrated
+ GPU; contexts with a performance preference may be created on a discrete GPU.
+
+Windows SDK
+-----------
+
+* The Windows SDK includes the pthreads-win32 library to assist in porting from
+ win32 code. You can use this library when developing your module as a Pepper
+ plug-in (.dll). See pepper_24/include/win/pthread.h and
+ pepper_24/src/pthread/README for additional information.
+* The update utility naclsdk.bat works when it is run from a path with spaces.
+
+Pepper 23 (15 October 2012)
+===========================
+
+The Pepper 23 bundle includes support for the nacl-gdb debugger on Mac and
+32-bit Windows, resources to enable hosted development on Linux, and changes to
+make the SDK examples compliant with version 2 of the Chrome Web Store manifest
+file format.
+
+Tools
+-----
+
+* The `nacl-gdb debugger
+ <https://developers.google.com/native-client/pepper23/devguide/devcycle/debugging#gdb>`_
+ now works on all systems (Mac, Windows, and Linux).
+
+* The output of the SDK update utility has been simplified. When you run the
+ command ``naclsdk list``, the utility displays one line for each available
+ bundle, annotated with an "``I``" if the bundle is already installed on your
+ system, and a "``*``" if the bundle has an update available. To see full
+ information about a bundle, use the command ``naclsdk info <bundle>`` (for
+ example, ``naclsdk info pepper_28``).
+
+Linux SDK
+---------
+
+* Developers using the Linux SDK now have resources, including pre-built
+ libraries and example Makefiles, that make it easier to **build a module as a
+ Pepper plugin** (sometimes called a "trusted" or "in-process" plugin) using
+ the native C/C++ compiler on their development system. In essence this makes
+ developing a Native Client module a two-step process:
+
+ #. Build the module into a shared library (.so file) using your system's
+ C/C++ compiler. Test and debug the .so file using the tools in your normal
+ development environment.
+ #. Build the module into a .nexe file using the compiler from one of the
+ Native Client toolchains in the SDK (nacl-gcc or nacl-g++). Test and debug
+ the .nexe file using nacl-gdb.
+
+ This two step development process has many benefits—in particular, you can
+ use the compilers, debuggers, profilers, and other tools that you're already
+ familiar with. But there are a few potential issues to keep in mind:
+
+ * Chrome uses different threading models for trusted plugins and Native
+ Client modules.
+ * Certain operations such as platform-specific library calls and system calls
+ may succeed during trusted development, but fail in Native Client.
+
+ Here are the resources you can use to build your module into a Pepper plugin:
+
+ * header files are in ``pepper_23/include``
+ * source files are in ``pepper_23/src``
+ * pre-built libraries are in ``pepper_23/lib``
+
+ You can now build and run most of the examples in the SDK as Pepper plugins.
+
+ * Look at the example Makefiles or run ``make`` in the example directories to
+ see the commands and flags used to build modules as Pepper plugins.
+ * Run ``make LAUNCH`` in the example directories to see how to use the
+ ``--register-pepper-plugins`` argument to load a Pepper plugin in Chrome.
+ Note that you must set the ``CHROME_PATH`` environment variable and start a
+ :ref:`local server <web_server>` prior to running this command.
+
+Examples
+--------
+
+* On Linux and Windows systems, most of the examples now build with three
+ toolchains: the Native Client glibc and newlib toolchains, and the native
+ toolchain on the host system. Modules built with the native toolchain on the
+ host system can only run as Pepper plugins.
+* All examples in the SDK now comply with version 2 of the Chrome Web Store
+ `manifest file format
+ <http://developer.chrome.com/extensions/manifest.html>`_. By default,
+ applications that use version 2 of the manifest file format apply a strict
+ `content security policy
+ <http://developer.chrome.com/extensions/contentSecurityPolicy.html>`_, which
+ includes a restriction against inline JavaScript. This restriction prohibits
+ both inline ``<script>`` blocks and inline event handlers (e.g., ``<button
+ onclick="...">``). See `Manifest Version
+ <http://developer.chrome.com/extensions/manifestVersion.html>`_ for a list of
+ changes between version 1 and version 2 of the manifest file format, and a
+ support schedule for applications that use version 1.
+
+PPAPI
+-----
+
+* `PP_InputEvent_Modifier
+ <https://developers.google.com/native-client/pepper23/pepperc/group___enums#ga21b811ac0484a214a8751aa3e1c959d9>`_
+ has two new enum values (_ISLEFT and _ISRIGHT).
+* The memory leak in the `WebSocket
+ <https://developers.google.com/native-client/pepper23/pepperc/struct_p_p_b___web_socket__1__0>`_
+ API has been fixed.
+
+Pepper 22 (22 August 2012)
+==========================
+
+The Pepper 22 bundle includes a **command-line debugger**, resources to enable
+**hosted development on Windows**, and changes to the example Makefiles (each
+example now builds both a debug and a release version).
+
+Tools
+-----
+
+* The SDK now includes a **command-line debugger** that you can use to debug
+ Native Client modules. See :ref:`Debugging with nacl-gdb
+ <devcycle-debugging>` for instructions on how to use this debugger. For now,
+ nacl-gdb only works on 64-bit Windows, 64-bit Linux, and 32-bit Linux
+ systems. Support for Mac and 32-bit Windows systems will be added soon.
+
+Windows SDK
+-----------
+
+* Developers using the Windows SDK can now **build a module as a Pepper
+ plugin** (sometimes called a "trusted" or "in-process" plugin) using the
+ native C/C++ compiler on their development system. In essence this makes
+ developing a Native Client module a two-step process:
+
+ #. Build the module into a DLL using your system's C/C++ compiler. Test and
+ debug the DLL using the tools in your normal development environment.
+ #. Build the module into a .nexe using the compiler from one of the Native
+ Client toolchains in the SDK (nacl-gcc or nacl-g++). Test and debug the
+ .nexe using nacl-gdb.
+
+ This two step development process has many benefits—in particular, you can
+ use the compilers, debuggers, profilers, and other tools that you're already
+ familiar with. But there are a few potential issues to keep in mind:
+
+ * Some libraries that are commonly used with Native Client may not build
+ easily on Windows.
+ * You may need to put in extra effort to get source code to compile with
+ multiple compilers, e.g., Microsoft Visual Studio and GCC.
+ * Chrome uses different threading models for trusted plugins and Native
+ Client modules.
+ * Certain operations such as platform-specific library calls and system calls
+ may succeed during trusted development, but fail in Native Client.
+
+ Here are the resources you can use to build your module into a DLL:
+
+ * header files are in ``pepper_22\include``
+ * source files are in ``pepper_22\src``
+ * pre-built libraries are in ``pepper_22\lib``
+
+* A Visual Studio add-in will be available in the near future with
+ configurations that include platforms for both Pepper plugins and NaCl
+ modules.
+
+.. Note::
+ :class: note
+
+ **Note:** It's also possible to build a module as a trusted plugin on Mac and
+ Linux systems, but doing so requires more work because the SDK does not yet
+ include the above resources (library source files and pre-built libraries)
+ for Mac and Linux systems. To build and debug a trusted plugin on Mac and
+ Linux systems, you need to `get the Chromium code
+ <http://dev.chromium.org/developers/how-tos/get-the-code>`_ and then follow
+ the `Mac instructions
+ <http://www.chromium.org/nativeclient/how-tos/debugging-documentation/debugging-a-trusted-plugin/trusted-debugging-on-mac>`_
+ or `Linux instructions
+ <http://www.chromium.org/nativeclient/how-tos/debugging-documentation/debugging-a-trusted-plugin/debugging-a-trusted-plugin-on-linux>`_.
+ In the future, the SDK will include resources for hosted development on Mac
+ and Linux as well as Windows.
+
+Examples
+--------
+
+* Each example in the SDK now builds both a debug and a release version. As
+ before, most examples also build newlib and glibc versions, which means that
+ there are now four versions for each example. Take a look at the Makefiles in
+ the examples to see the compiler flags that are used for debug and release
+ versions. For a description of those flags, see :ref:`Compile flags for
+ different development scenarios <compile_flags>`.
+* Comments have been added to common.js, which is used in all the examples. The
+ JavaScript in common.js inserts an <embed> element that loads the NaCl module
+ in each example's web page, attaches event listeners to monitor the loading
+ of the module, and implements handleMessage() to respond to messages sent
+ from the NaCl module to the JavaScript side of the application
+
+PPAPI
+-----
+
+* The ``CompletionCallbackFactory`` class template now takes a thread traits
+ class as its second parameter. For details see the `CompletionCallbackFactory
+ class template reference
+ <https://developers.google.com/native-client/pepper22/peppercpp/classpp_1_1_completion_callback_factory#details>`_.
+
+.. TODO: Port release notes for older releases
diff --git a/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc b/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
index 3920839f75..abe5aec3a1 100644
--- a/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
+++ b/native_client_sdk/src/examples/api/graphics_3d/graphics_3d.cc
@@ -380,6 +380,8 @@ class Graphics3DInstance : public pp::Instance {
glBindTexture(GL_TEXTURE_2D, texture_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
diff --git a/native_client_sdk/src/examples/api/socket/echo_server.cc b/native_client_sdk/src/examples/api/socket/echo_server.cc
new file mode 100644
index 0000000000..a88a82ef7f
--- /dev/null
+++ b/native_client_sdk/src/examples/api/socket/echo_server.cc
@@ -0,0 +1,171 @@
+// 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 "echo_server.h"
+
+#include <string.h>
+#include <sstream>
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+#ifdef WIN32
+#undef PostMessage
+#endif
+
+// Number of connections to queue up on the listening
+// socket before new ones get "Connection Refused"
+static const int kBacklog = 10;
+
+// Implement htons locally. Even though this is provided by
+// nacl_io we don't want to include nacl_io in this simple
+// example.
+static uint16_t Htons(uint16_t hostshort) {
+ uint8_t result_bytes[2];
+ result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
+ result_bytes[1] = (uint8_t) (hostshort & 0xFF);
+
+ uint16_t result;
+ memcpy(&result, result_bytes, 2);
+ return result;
+}
+
+void EchoServer::Start(uint16_t port) {
+ if (!pp::TCPSocket::IsAvailable()) {
+ instance_->PostMessage("TCPSocket not available");
+ return;
+ }
+
+ listening_socket_ = pp::TCPSocket(instance_);
+ if (listening_socket_.is_null()) {
+ instance_->PostMessage("Error creating TCPSocket.");
+ return;
+ }
+
+ std::ostringstream status;
+ status << "Starting server on port: " << port;
+ instance_->PostMessage(status.str());
+
+ // Attempt to listen on all interfaces (0.0.0.0)
+ // on the given port number.
+ PP_NetAddress_IPv4 ipv4_addr = { Htons(port), { 0 } };
+ pp::NetAddress addr(instance_, ipv4_addr);
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnBindCompletion);
+ int32_t rtn = listening_socket_.Bind(addr, callback);
+ if (rtn != PP_OK_COMPLETIONPENDING) {
+ instance_->PostMessage("Error binding listening socket.");
+ return;
+ }
+}
+
+void EchoServer::OnBindCompletion(int32_t result) {
+ if (result != PP_OK) {
+ std::ostringstream status;
+ status << "server: Bind failed with: " << result;
+ instance_->PostMessage(status.str());
+ return;
+ }
+
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnListenCompletion);
+
+ int32_t rtn = listening_socket_.Listen(kBacklog, callback);
+ if (rtn != PP_OK_COMPLETIONPENDING) {
+ instance_->PostMessage("server: Error listening on server socket.");
+ return;
+ }
+}
+
+void EchoServer::OnListenCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result != PP_OK) {
+ status << "server: Listen failed with: " << result;
+ instance_->PostMessage(status.str());
+ return;
+ }
+
+ pp::NetAddress addr = listening_socket_.GetLocalAddress();
+ status << "server: Listening on: " << addr.DescribeAsString(true).AsString();
+ instance_->PostMessage(status.str());
+
+ TryAccept();
+}
+
+void EchoServer::OnAcceptCompletion(int32_t result, pp::TCPSocket socket) {
+ std::ostringstream status;
+
+ if (result != PP_OK) {
+ status << "server: Accept failed: " << result;
+ instance_->PostMessage(status.str());
+ return;
+ }
+
+ pp::NetAddress addr = socket.GetLocalAddress();
+ status << "server: New connection from: ";
+ status << addr.DescribeAsString(true).AsString();
+ instance_->PostMessage(status.str());
+ incoming_socket_ = socket;
+
+ TryRead();
+}
+
+void EchoServer::OnReadCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result <= 0) {
+ if (result == 0)
+ status << "server: client disconnected";
+ else
+ status << "server: Read failed: " << result;
+ instance_->PostMessage(status.str());
+
+ // Remove the current incoming socket and try
+ // to accept the next one.
+ incoming_socket_.Close();
+ incoming_socket_ = pp::TCPSocket();
+ TryAccept();
+ return;
+ }
+
+ status << "server: Read " << result << " bytes";
+ instance_->PostMessage(status.str());
+
+ // Echo the bytes back to the client
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnWriteCompletion);
+ result = incoming_socket_.Write(receive_buffer_, result, callback);
+ if (result != PP_OK_COMPLETIONPENDING) {
+ status << "server: Write failed: " << result;
+ instance_->PostMessage(status.str());
+ }
+}
+
+void EchoServer::OnWriteCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result < 0) {
+ status << "server: Write failed: " << result;
+ instance_->PostMessage(status.str());
+ return;
+ }
+
+ status << "server: Wrote " << result << " bytes";
+ instance_->PostMessage(status.str());
+
+ // Try and read more bytes from the client
+ TryRead();
+}
+
+void EchoServer::TryRead() {
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnReadCompletion);
+ incoming_socket_.Read(receive_buffer_, kBufferSize, callback);
+}
+
+void EchoServer::TryAccept() {
+ pp::CompletionCallbackWithOutput<pp::TCPSocket> callback =
+ callback_factory_.NewCallbackWithOutput(
+ &EchoServer::OnAcceptCompletion);
+ listening_socket_.Accept(callback);
+}
diff --git a/native_client_sdk/src/examples/api/socket/echo_server.h b/native_client_sdk/src/examples/api/socket/echo_server.h
new file mode 100644
index 0000000000..db35d7a1ea
--- /dev/null
+++ b/native_client_sdk/src/examples/api/socket/echo_server.h
@@ -0,0 +1,46 @@
+// 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.
+
+#ifndef ECHO_SERVER_H_
+#define ECHO_SERVER_H_
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/tcp_socket.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+static const int kBufferSize = 1024;
+
+// Simple "echo" server based on a listening pp::TCPSocket.
+// This server handles just one connection at a time and will
+// echo back whatever bytes get sent to it.
+class EchoServer {
+ public:
+ EchoServer(pp::Instance* instance, uint16_t port)
+ : instance_(instance),
+ callback_factory_(this) {
+ Start(port);
+ }
+
+ protected:
+ void Start(uint16_t port);
+
+ // Callback functions
+ void OnBindCompletion(int32_t result);
+ void OnListenCompletion(int32_t result);
+ void OnAcceptCompletion(int32_t result, pp::TCPSocket socket);
+ void OnReadCompletion(int32_t result);
+ void OnWriteCompletion(int32_t result);
+
+ void TryRead();
+ void TryAccept();
+
+ pp::Instance* instance_;
+ pp::CompletionCallbackFactory<EchoServer> callback_factory_;
+ pp::TCPSocket listening_socket_;
+ pp::TCPSocket incoming_socket_;
+
+ char receive_buffer_[kBufferSize];
+};
+
+#endif // ECHO_SERVER_H_
diff --git a/native_client_sdk/src/examples/api/socket/example.dsc b/native_client_sdk/src/examples/api/socket/example.dsc
index 347f0b5cd7..a573c829b7 100644
--- a/native_client_sdk/src/examples/api/socket/example.dsc
+++ b/native_client_sdk/src/examples/api/socket/example.dsc
@@ -4,14 +4,13 @@
{
'NAME' : 'socket',
'TYPE' : 'main',
- 'SOURCES' : ['socket.cc'],
+ 'SOURCES' : ['socket.cc', 'echo_server.cc', 'echo_server.h'],
'LIBS': ['ppapi_cpp', 'ppapi']
}
],
'DATA': [
'example.js',
],
- 'PRE': '''\nCHROME_ARGS = --allow-nacl-socket-api=localhost\n''',
'DEST': 'examples/api',
'NAME': 'socket',
'TITLE': 'socket',
diff --git a/native_client_sdk/src/examples/api/socket/example.js b/native_client_sdk/src/examples/api/socket/example.js
index a7a753529b..51ec94ff34 100644
--- a/native_client_sdk/src/examples/api/socket/example.js
+++ b/native_client_sdk/src/examples/api/socket/example.js
@@ -8,9 +8,6 @@ function attachListeners() {
document.getElementById('sendForm').addEventListener('submit', doSend);
document.getElementById('listenForm').addEventListener('submit', doListen);
document.getElementById('closeButton').addEventListener('click', doClose);
- if (typeof chrome.socket === 'undefined') {
- document.getElementById('createServer').style.display = 'none';
- }
}
// Called by the common.js module.
@@ -24,6 +21,7 @@ var msgTcpCreate = 't;'
var msgUdpCreate = 'u;'
var msgSend = 's;'
var msgClose = 'c;'
+var msgListen = 'l;'
function doConnect(event) {
// Send a request message. See also socket.cc for the request format.
@@ -31,14 +29,11 @@ function doConnect(event) {
var hostname = document.getElementById('hostname').value;
var type = document.getElementById('connect_type').value;
common.logMessage(type);
- if (type == 'tcp')
-
-{
- common.logMessage(type);
+ if (type == 'tcp') {
common.naclModule.postMessage(msgTcpCreate + hostname);
-}
- else
+ } else {
common.naclModule.postMessage(msgUdpCreate + hostname);
+ }
}
function doSend(event) {
@@ -50,114 +45,12 @@ function doSend(event) {
common.naclModule.postMessage(msgSend + message);
}
-var listeningSocket = -1;
-var creatingServer = false;
-
-function runUDPEchoServer(port) {
- common.logMessage("Listening on UDP port: " + port);
- chrome.socket.create("udp", {}, function(createInfo) {
- listeningSocket = createInfo.socketId;
- creatingServer = false;
- chrome.socket.bind(listeningSocket,
- '127.0.0.1',
- port,
- function(result) {
- if (result !== 0) {
- common.logMessage("Bind failed: " + result);
- return;
- }
-
- var recvCallback = function(recvFromInfo) {
- if (recvFromInfo.resultCode <= 0) {
- common.logMessage("recvFrom failed: " + recvFromInfo.resultCode);
- return;
- }
-
- chrome.socket.sendTo(listeningSocket,
- recvFromInfo.data,
- recvFromInfo.address,
- recvFromInfo.port,
- function(sendToInfo) {
- if (readInfo.resultCode < 0) {
- common.logMessage("SentTo failed: " + sendToInfo.bytesWritten);
- return;
- }
- })
-
- chrome.socket.recvFrom(listeningSocket, recvCallback);
- }
-
- chrome.socket.recvFrom(listeningSocket, recvCallback);
- })
- })
-}
-
-function runTCPEchoServer(port) {
- common.logMessage("Listening on TCP port: " + port);
- chrome.socket.create("tcp", {}, function(createInfo) {
- listeningSocket = createInfo.socketId;
- creatingServer = false;
- chrome.socket.listen(listeningSocket,
- '0.0.0.0',
- port,
- 10,
- function(result) {
- if (result !== 0) {
- common.logMessage("Listen failed: " + result);
- return;
- }
-
- chrome.socket.accept(listeningSocket, function(acceptInfo) {
- if (result !== 0) {
- common.logMessage("Accept failed: " + result);
- return;
- }
-
- var newSock = acceptInfo.socketId;
-
- var readCallback = function(readInfo) {
- if (readInfo.resultCode < 0) {
- common.logMessage("Read failed: " + readInfo.resultCode);
- chrome.socket.destroy(newSock);
- return;
- }
-
- chrome.socket.write(newSock, readInfo.data, function(writeInfo) {})
- chrome.socket.read(newSock, readCallback);
- }
-
- chrome.socket.read(newSock, readCallback);
- })
- })
- })
-}
-
function doListen(event) {
// Listen a the given port.
event.preventDefault();
- if (typeof chrome.socket === 'undefined') {
- common.logMessage("Local JavaScript echo server is only available in " +
- "the packaged version of the this example.");
- return;
- }
-
var port = document.getElementById('port').value;
var type = document.getElementById('listen_type').value;
- port = parseInt(port);
-
- if (listeningSocket !== -1) {
- chrome.socket.destroy(listeningSocket);
- listeningSocket = -1;
- }
-
- if (creatingServer)
- return;
- creatingServer = true;
-
- if (type == 'tcp')
- runTCPEchoServer(port)
- else
- runUDPEchoServer(port)
+ common.naclModule.postMessage(msgListen + port);
}
function doClose() {
diff --git a/native_client_sdk/src/examples/api/socket/index.html b/native_client_sdk/src/examples/api/socket/index.html
index 305e2c642b..eefe5ebb1e 100644
--- a/native_client_sdk/src/examples/api/socket/index.html
+++ b/native_client_sdk/src/examples/api/socket/index.html
@@ -16,6 +16,10 @@ found in the LICENSE file.
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
<p>The socket example demonstrates how to use the TCP and UDP socket API.<br>
+ This API is normally only available to packaged apps with the requisite
+ socket permission, but can be enabled for debugging purposes using the
+ <code>--allow-nacl-socket-api=&lt;hostname&gt;</code> command line
+ flag.<br>
First set a server address in the form of 'hostname:port', then push the
"Connect" button to establish a connection.<br>
"Send" button sends the message of the text area to the the remote host.
@@ -43,11 +47,11 @@ found in the LICENSE file.
<button id="closeButton">Close</button>
- <div id="createServer">
+ <div>
<h2>Create a local server:</h2>
- <p>The "Listen" button can be used create a local TCP or UDP echo server listenting
- on the port specified. This is implemented using the 'chrome.socket' javascript
- API which will only work when this application is run as a packaged app.<br>
+ <p>The "Listen" button can be used create a local TCP or UDP echo server
+ listenting on the port specified. Once started this server can be connected
+ to by entering <code>localhost:&lt;port&gt;<br> above.
</p>
<p>
<form id="listenForm">
diff --git a/native_client_sdk/src/examples/api/socket/socket.cc b/native_client_sdk/src/examples/api/socket/socket.cc
index 7f8b4a5f00..a988081428 100644
--- a/native_client_sdk/src/examples/api/socket/socket.cc
+++ b/native_client_sdk/src/examples/api/socket/socket.cc
@@ -6,6 +6,8 @@
#include <string.h>
#include <sstream>
+#include "echo_server.h"
+
#include "ppapi/cpp/host_resolver.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
@@ -20,16 +22,18 @@
#pragma warning(disable : 4355)
#endif
-static const int s_buffer_size = 1024;
-
class ExampleInstance : public pp::Instance {
public:
explicit ExampleInstance(PP_Instance instance)
: pp::Instance(instance),
callback_factory_(this),
- send_outstanding_(false) {}
+ send_outstanding_(false),
+ echo_server_(NULL) {}
+
+ virtual ~ExampleInstance() {
+ delete echo_server_;
+ }
- virtual ~ExampleInstance() {}
virtual void HandleMessage(const pp::Var& var_message);
private:
@@ -52,14 +56,17 @@ class ExampleInstance : public pp::Instance {
pp::UDPSocket udp_socket_;
pp::HostResolver resolver_;
pp::NetAddress remote_host_;
- char receive_buffer_[s_buffer_size];
+
+ char receive_buffer_[kBufferSize];
bool send_outstanding_;
+ EchoServer* echo_server_;
};
#define MSG_CREATE_TCP 't'
#define MSG_CREATE_UDP 'u'
#define MSG_SEND 's'
#define MSG_CLOSE 'c'
+#define MSG_LISTEN 'l'
void ExampleInstance::HandleMessage(const pp::Var& var_message) {
if (!var_message.is_string())
@@ -85,11 +92,23 @@ void ExampleInstance::HandleMessage(const pp::Var& var_message) {
// The command 'c' requests to close without any argument like "c;"
Close();
break;
+ case MSG_LISTEN:
+ {
+ // The command 'l' starts a listening socket (server).
+ int port = atoi(message.substr(2).c_str());
+ echo_server_ = new EchoServer(this, port);
+ break;
+ }
case MSG_SEND:
// The command 't' requests to send a message as a text frame. The
// message passed as an argument like "t;message".
Send(message.substr(2));
break;
+ default:
+ std::ostringstream status;
+ status << "Unhandled message from JavaScript: " << message;
+ PostMessage(status.str());
+ break;
}
}
@@ -155,7 +174,7 @@ void ExampleInstance::Connect(const std::string& host, bool tcp) {
port = atoi(host.substr(pos+1).c_str());
}
- pp::CompletionCallback callback = \
+ pp::CompletionCallback callback =
callback_factory_.NewCallback(&ExampleInstance::OnResolveCompletion);
PP_HostResolver_Hint hint = { PP_NETADDRESS_FAMILY_UNSPECIFIED, 0 };
resolver_.Resolve(hostname.c_str(), port, hint, callback);
@@ -172,7 +191,7 @@ void ExampleInstance::OnResolveCompletion(int32_t result) {
PostMessage(std::string("Resolved: ") +
addr.DescribeAsString(true).AsString());
- pp::CompletionCallback callback = \
+ pp::CompletionCallback callback =
callback_factory_.NewCallback(&ExampleInstance::OnConnectCompletion);
if (IsUDP()) {
@@ -216,7 +235,7 @@ void ExampleInstance::Send(const std::string& message) {
uint32_t size = message.size();
const char* data = message.c_str();
- pp::CompletionCallback callback = \
+ pp::CompletionCallback callback =
callback_factory_.NewCallback(&ExampleInstance::OnSendCompletion);
int32_t result;
if (IsUDP())
@@ -240,16 +259,16 @@ void ExampleInstance::Send(const std::string& message) {
}
void ExampleInstance::Receive() {
- memset(receive_buffer_, 0, s_buffer_size);
+ memset(receive_buffer_, 0, kBufferSize);
if (IsUDP()) {
- pp::CompletionCallbackWithOutput<pp::NetAddress> callback = \
+ pp::CompletionCallbackWithOutput<pp::NetAddress> callback =
callback_factory_.NewCallbackWithOutput(
&ExampleInstance::OnReceiveFromCompletion);
- udp_socket_.RecvFrom(receive_buffer_, s_buffer_size-1, callback);
+ udp_socket_.RecvFrom(receive_buffer_, kBufferSize, callback);
} else {
- pp::CompletionCallback callback = \
+ pp::CompletionCallback callback =
callback_factory_.NewCallback(&ExampleInstance::OnReceiveCompletion);
- tcp_socket_.Read(receive_buffer_, s_buffer_size-1, callback);
+ tcp_socket_.Read(receive_buffer_, kBufferSize, callback);
}
}
@@ -285,7 +304,7 @@ void ExampleInstance::OnReceiveCompletion(int32_t result) {
return;
}
- PostMessage(std::string("Received: ") + receive_buffer_);
+ PostMessage(std::string("Received: ") + std::string(receive_buffer_, result));
Receive();
}
diff --git a/native_client_sdk/src/examples/api/url_loader/example.js b/native_client_sdk/src/examples/api/url_loader/example.js
index 9c62dce42f..dd61454aab 100644
--- a/native_client_sdk/src/examples/api/url_loader/example.js
+++ b/native_client_sdk/src/examples/api/url_loader/example.js
@@ -20,19 +20,19 @@ function loadUrl() {
// Called by the common.js module.
function handleMessage(message_event) {
- var logElt = document.getElementById('generalOutput');
+ var logEl = document.getElementById('output');
// Find the first line break. This separates the URL data from the
// result text. Note that the result text can contain any number of
// '\n' characters, so split() won't work here.
var url = message_event.data;
var result = '';
- var eol_pos = message_event.data.indexOf("\n");
- if (eol_pos != -1) {
- url = message_event.data.substring(0, eol_pos);
- if (eol_pos < message_event.data.length - 1) {
- result = message_event.data.substring(eol_pos + 1);
+ var eolPos = message_event.data.indexOf('\n');
+ if (eolPos != -1) {
+ url = message_event.data.substring(0, eolPos);
+ if (eolPos < message_event.data.length - 1) {
+ result = message_event.data.substring(eolPos + 1);
}
}
- logElt.textContent += 'FULLY QUALIFIED URL: ' + url + '\n';
- logElt.textContent += 'RESULT:\n' + result + '\n';
+ logEl.textContent += 'FULLY QUALIFIED URL: ' + url + '\n';
+ logEl.textContent += 'RESULT:\n' + result + '\n';
}
diff --git a/native_client_sdk/src/examples/api/url_loader/index.html b/native_client_sdk/src/examples/api/url_loader/index.html
index 828ff1fe66..eaffdab3e5 100644
--- a/native_client_sdk/src/examples/api/url_loader/index.html
+++ b/native_client_sdk/src/examples/api/url_loader/index.html
@@ -21,7 +21,7 @@ found in the LICENSE file.
load completes.</p>
<table border=5 cellpadding=5% summary="A title and a result log">
<tr>
- <td valign=top><pre id='generalOutput' class='notrun'></pre></td>
+ <td valign=top><pre id='output'></pre></td>
</tr>
</table>
<input id="button" type="button" value="Get URL">
diff --git a/native_client_sdk/src/examples/api/url_loader/test.js b/native_client_sdk/src/examples/api/url_loader/test.js
new file mode 100644
index 0000000000..914df1f275
--- /dev/null
+++ b/native_client_sdk/src/examples/api/url_loader/test.js
@@ -0,0 +1,32 @@
+// 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.
+
+function addTests() {
+ common.tester.addAsyncTest('get_url', function(test) {
+ test.log('Clicking the button');
+ document.getElementById('button').dispatchEvent(new MouseEvent('click'));
+
+ var outputEl = document.getElementById('output');
+ outputEl.textContent = '';
+
+ test.log('Waiting for the URL to load.');
+ var intervalId = window.setInterval(function() {
+ if (!outputEl.textContent)
+ return;
+
+ window.clearInterval(intervalId);
+ test.log('Output box changed...');
+ var expectedMessage = 'part of the test output';
+ if (outputEl.textContent.indexOf(expectedMessage) === -1) {
+ test.fail('Expected to find "' + expectedMessage + '" in the output,' +
+ 'instead got "' + outputEl.textContent + '"');
+ return;
+ } else {
+ test.log('OK, found "' + expectedMessage + '".');
+ }
+
+ test.pass();
+ }, 100);
+ });
+}
diff --git a/native_client_sdk/src/examples/demo/earth/earth.cc b/native_client_sdk/src/examples/demo/earth/earth.cc
index 559cc79754..eef5c38dcd 100644
--- a/native_client_sdk/src/examples/demo/earth/earth.cc
+++ b/native_client_sdk/src/examples/demo/earth/earth.cc
@@ -209,6 +209,7 @@ class Planet {
void SetLight(float zoom);
void SetTexture(const std::string& name, int width, int height,
uint32_t* pixels);
+ void SpinPlanet(pp::Point new_point, pp::Point last_point);
void Reset();
void RequestTextures();
@@ -226,6 +227,7 @@ class Planet {
float ui_zoom_;
float ui_spin_x_;
float ui_spin_y_;
+ pp::Point ui_last_point_;
// Various settings for position & orientation of planet. Do not change
// these variables, instead use SetPlanet*() functions.
@@ -327,6 +329,7 @@ void Planet::Reset() {
ui_light_ = 1.0f;
ui_spin_x_ = 0.01f;
ui_spin_y_ = 0.0f;
+ ui_last_point_ = pp::Point(0, 0);
// Set up reasonable default values.
SetPlanetXYZR(0.0f, 0.0f, 48.0f, 4.0f);
@@ -670,6 +673,16 @@ void Planet::SetTexture(const std::string& name, int width, int height,
}
}
+void Planet::SpinPlanet(pp::Point new_point, pp::Point last_point) {
+ float delta_x = static_cast<float>(new_point.x() - last_point.x());
+ float delta_y = static_cast<float>(new_point.y() - last_point.y());
+ float spin_x = std::min(10.0f, std::max(-10.0f, delta_x * 0.5f));
+ float spin_y = std::min(10.0f, std::max(-10.0f, delta_y * 0.5f));
+ ui_spin_x_ = spin_x / 100.0f;
+ ui_spin_y_ = spin_y / 100.0f;
+ ui_last_point_ = new_point;
+}
+
// Handle input events from the user and messages from JS.
void Planet::HandleEvent(PSEvent* ps_event) {
// Give the 2D context a chance to process the event.
@@ -687,17 +700,14 @@ void Planet::HandleEvent(PSEvent* ps_event) {
StartBenchmark();
break;
}
- case PP_INPUTEVENT_TYPE_MOUSEMOVE:
- case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
pp::MouseInputEvent mouse = pp::MouseInputEvent(event);
if (mouse.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
- PP_Point delta = mouse.GetMovement();
- float delta_x = static_cast<float>(delta.x);
- float delta_y = static_cast<float>(delta.y);
- float spin_x = std::min(4.0f, std::max(-4.0f, delta_x * 0.5f));
- float spin_y = std::min(4.0f, std::max(-4.0f, delta_y * 0.5f));
- ui_spin_x_ = spin_x / 100.0f;
- ui_spin_y_ = spin_y / 100.0f;
+ if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN)
+ SpinPlanet(mouse.GetPosition(), mouse.GetPosition());
+ else
+ SpinPlanet(mouse.GetPosition(), ui_last_point_);
}
break;
}
@@ -709,6 +719,23 @@ void Planet::HandleEvent(PSEvent* ps_event) {
PostUpdateMessage("set_zoom", ui_zoom_);
break;
}
+ case PP_INPUTEVENT_TYPE_TOUCHSTART:
+ case PP_INPUTEVENT_TYPE_TOUCHMOVE: {
+ pp::TouchInputEvent touches = pp::TouchInputEvent(event);
+ uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES);
+ if (count > 0) {
+ // Use first touch point to spin planet.
+ pp::TouchPoint touch =
+ touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, 0);
+ pp::Point screen_point(touch.position().x(),
+ touch.position().y());
+ if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART)
+ SpinPlanet(screen_point, screen_point);
+ else
+ SpinPlanet(screen_point, ui_last_point_);
+ }
+ break;
+ }
default:
break;
}
diff --git a/native_client_sdk/src/examples/demo/life/life.c b/native_client_sdk/src/examples/demo/life/life.c
index 17a3bfba92..d9d9def3fb 100644
--- a/native_client_sdk/src/examples/demo/life/life.c
+++ b/native_client_sdk/src/examples/demo/life/life.c
@@ -4,6 +4,7 @@
*/
#include <assert.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -125,6 +126,27 @@ void DrawCell(int32_t x, int32_t y) {
}
}
+void ProcessTouchEvent(PSEvent* event) {
+ uint32_t count = g_pTouchInput->GetTouchCount(event->as_resource,
+ PP_TOUCHLIST_TYPE_TOUCHES);
+ uint32_t i, j;
+ for (i = 0; i < count; i++) {
+ struct PP_TouchPoint touch = g_pTouchInput->GetTouchByIndex(
+ event->as_resource, PP_TOUCHLIST_TYPE_TOUCHES, i);
+ int radius = (int)touch.radius.x;
+ int x = (int)touch.position.x;
+ int y = (int)touch.position.y;
+ /* num = 1/100th the area of touch point */
+ int num = (int)(M_PI * radius * radius / 100.0f);
+ for (j = 0; j < num; j++) {
+ int dx = rand() % (radius * 2) - radius;
+ int dy = rand() % (radius * 2) - radius;
+ /* only plot random cells within the touch area */
+ if (dx * dx + dy * dy <= radius * radius)
+ DrawCell(x + dx, y + dy);
+ }
+ }
+}
void ProcessEvent(PSEvent* event) {
switch(event->type) {
@@ -143,23 +165,21 @@ void ProcessEvent(PSEvent* event) {
g_pInputEvent->GetModifiers(event->as_resource);
switch(type) {
- case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
struct PP_Point location =
g_pMouseInput->GetPosition(event->as_resource);
- DrawCell(location.x, location.y);
+ /* If the button is down, draw */
+ if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
+ DrawCell(location.x, location.y);
+ }
break;
}
- case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
- struct PP_Point location =
- g_pMouseInput->GetPosition(event->as_resource);
-
- /* If the button is down, draw */
- if (modifiers & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
- DrawCell(location.x, location.y);
- }
+ case PP_INPUTEVENT_TYPE_TOUCHSTART:
+ case PP_INPUTEVENT_TYPE_TOUCHMOVE:
+ ProcessTouchEvent(event);
break;
- }
case PP_INPUTEVENT_TYPE_KEYDOWN: {
PP_Bool fullscreen = g_pFullscreen->IsFullscreen(PSGetInstanceId());
@@ -167,6 +187,7 @@ void ProcessEvent(PSEvent* event) {
fullscreen ? PP_FALSE : PP_TRUE);
break;
}
+
default:
break;
}
diff --git a/native_client_sdk/src/examples/demo/nacl_io/example.js b/native_client_sdk/src/examples/demo/nacl_io/example.js
index 87eedd59f1..6de6afbbb2 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/example.js
+++ b/native_client_sdk/src/examples/demo/nacl_io/example.js
@@ -194,20 +194,85 @@ function mkdirResult(dirname) {
common.logMessage('Directory ' + dirname + ' created successfully.');
}
+function rmdir(e) {
+ var dirname = document.getElementById('rmdirDirname').value;
+ nacl_module.postMessage(makeCall('rmdir', dirname));
+}
+
+function rmdirResult(dirname) {
+ common.logMessage('Directory ' + dirname + ' removed successfully.');
+}
+
+function chdir(e) {
+ var dirname = document.getElementById('chdirDirname').value;
+ nacl_module.postMessage(makeCall('chdir', dirname));
+}
+
+function chdirResult(dirname) {
+ common.logMessage('Changed directory to: ' + dirname + '.');
+}
+
+function getcwd(e) {
+ nacl_module.postMessage(makeCall('getcwd'));
+}
+
+function getcwdResult(dirname) {
+ common.logMessage('getcwd: ' + dirname + '.');
+}
+
function gethostbyname(e) {
var name = document.getElementById('gethostbynameName').value;
nacl_module.postMessage(makeCall('gethostbyname', name));
}
-
function gethostbynameResult(name, addr_type) {
- common.logMessage('gethostbyname returned successfully\n');
- common.logMessage('h_name = ' + name + '.\n');
- common.logMessage('h_addr_type = ' + addr_type + '.\n');
+ common.logMessage('gethostbyname returned successfully');
+ common.logMessage('h_name = ' + name + '.');
+ common.logMessage('h_addr_type = ' + addr_type + '.');
for (var i = 2; i < arguments.length; i++) {
- common.logMessage('Address number ' + (i-1) + ' = ' + arguments[i] + '.\n');
+ common.logMessage('Address number ' + (i-1) + ' = ' + arguments[i] + '.');
}
- common.logMessage('\n');
+}
+
+function connect(e) {
+ var host = document.getElementById('connectHost').value;
+ var port = document.getElementById('connectPort').value;
+ nacl_module.postMessage(makeCall('connect', host, port));
+}
+
+function connectResult(sockhandle) {
+ common.logMessage('connected');
+ addNameToSelectElements('.sock-handle', sockhandle, '[socket]');
+}
+
+function recv(e) {
+ var handle = document.getElementById('recvHandle').value;
+ var bufferSize = document.getElementById('recvBufferSize').value;
+ nacl_module.postMessage(makeCall('recv', handle, bufferSize));
+}
+
+function recvResult(messageLen, message) {
+ common.logMessage("received " + messageLen + ' bytes: ' + message);
+}
+
+function send(e) {
+ var handle = document.getElementById('sendHandle').value;
+ var message = document.getElementById('sendMessage').value;
+ nacl_module.postMessage(makeCall('send', handle, message));
+}
+
+function sendResult(sentBytes) {
+ common.logMessage("sent bytes: " + sentBytes);
+}
+
+function close(e) {
+ var handle = document.getElementById('closeHandle').value;
+ nacl_module.postMessage(makeCall('close', handle));
+}
+
+function closeResult(sock) {
+ removeNameFromSelectElements('.sock-handle', sock, "[socket]");
+ common.logMessage("closed socket: " + sock);
}
/**
diff --git a/native_client_sdk/src/examples/demo/nacl_io/handlers.c b/native_client_sdk/src/examples/demo/nacl_io/handlers.c
index 2ec655929e..c2cbcfcda2 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/handlers.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/handlers.c
@@ -1,18 +1,19 @@
/* 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.
- */
+ * found in the LICENSE file. */
#include "handlers.h"
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
+#include <limits.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -31,12 +32,14 @@
/**
* A mapping from int -> FILE*, so the JavaScript messages can refer to an open
- * File. */
+ * File.
+ */
static FILE* g_OpenFiles[MAX_OPEN_FILES];
/**
* A mapping from int -> DIR*, so the JavaScript messages can refer to an open
- * Directory. */
+ * Directory.
+ */
static void* g_OpenDirs[MAX_OPEN_DIRS];
/**
@@ -111,14 +114,16 @@ static void* GetFromIndexString(void** map,
* Add the file to the g_OpenFiles map.
* @param[in] file The file to add to g_OpenFiles.
* @return int The index of the FILE in g_OpenFiles, or -1 if there are too many
- * open files. */
+ * open files.
+ */
static int AddFileToMap(FILE* file) {
return AddToMap((void**)g_OpenFiles, MAX_OPEN_FILES, file);
}
/**
* Remove the file from the g_OpenFiles map.
- * @param[in] i The index of the file handle to remove. */
+ * @param[in] i The index of the file handle to remove.
+ */
static void RemoveFileFromMap(int i) {
RemoveFromMap((void**)g_OpenFiles, MAX_OPEN_FILES, i);
}
@@ -140,14 +145,16 @@ static FILE* GetFileFromIndexString(const char* s, int* file_index) {
* Add the dir to the g_OpenDirs map.
* @param[in] dir The dir to add to g_OpenDirs.
* @return int The index of the DIR in g_OpenDirs, or -1 if there are too many
- * open dirs. */
+ * open dirs.
+ */
static int AddDirToMap(DIR* dir) {
return AddToMap((void**)g_OpenDirs, MAX_OPEN_DIRS, dir);
}
/**
* Remove the dir from the g_OpenDirs map.
- * @param[in] i The index of the dir handle to remove. */
+ * @param[in] i The index of the dir handle to remove.
+ */
static void RemoveDirFromMap(int i) {
RemoveFromMap((void**)g_OpenDirs, MAX_OPEN_DIRS, i);
}
@@ -179,7 +186,8 @@ static DIR* GetDirFromIndexString(const char* s, int* dir_index) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleFopen(int num_params, char** params, char** output) {
FILE* file;
int file_index;
@@ -187,7 +195,7 @@ int HandleFopen(int num_params, char** params, char** output) {
const char* mode;
if (num_params != 2) {
- *output = PrintfToNewString("Error: fopen takes 2 parameters.");
+ *output = PrintfToNewString("fopen takes 2 parameters.");
return 1;
}
@@ -196,14 +204,14 @@ int HandleFopen(int num_params, char** params, char** output) {
file = fopen(filename, mode);
if (!file) {
- *output = PrintfToNewString("Error: fopen returned a NULL FILE*.");
+ *output = PrintfToNewString("fopen returned a NULL FILE*.");
return 2;
}
file_index = AddFileToMap(file);
if (file_index == -1) {
*output = PrintfToNewString(
- "Error: Example only allows %d open file handles.", MAX_OPEN_FILES);
+ "Example only allows %d open file handles.", MAX_OPEN_FILES);
return 3;
}
@@ -226,7 +234,8 @@ int HandleFopen(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleFwrite(int num_params, char** params, char** output) {
FILE* file;
const char* file_index_string;
@@ -235,7 +244,7 @@ int HandleFwrite(int num_params, char** params, char** output) {
size_t bytes_written;
if (num_params != 2) {
- *output = PrintfToNewString("Error: fwrite takes 2 parameters.");
+ *output = PrintfToNewString("fwrite takes 2 parameters.");
return 1;
}
@@ -246,7 +255,7 @@ int HandleFwrite(int num_params, char** params, char** output) {
if (!file) {
*output =
- PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
+ PrintfToNewString("Unknown file handle %s.", file_index_string);
return 2;
}
@@ -254,7 +263,7 @@ int HandleFwrite(int num_params, char** params, char** output) {
if (ferror(file)) {
*output = PrintfToNewString(
- "Error: Wrote %d bytes, but ferror() returns true.", bytes_written);
+ "Wrote %d bytes, but ferror() returns true.", bytes_written);
return 3;
}
@@ -278,7 +287,8 @@ int HandleFwrite(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleFread(int num_params, char** params, char** output) {
FILE* file;
const char* file_index_string;
@@ -287,7 +297,7 @@ int HandleFread(int num_params, char** params, char** output) {
size_t bytes_read;
if (num_params != 2) {
- *output = PrintfToNewString("Error: fread takes 2 parameters.");
+ *output = PrintfToNewString("fread takes 2 parameters.");
return 1;
}
@@ -297,7 +307,7 @@ int HandleFread(int num_params, char** params, char** output) {
if (!file) {
*output =
- PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
+ PrintfToNewString("Unknown file handle %s.", file_index_string);
return 2;
}
@@ -307,7 +317,7 @@ int HandleFread(int num_params, char** params, char** output) {
if (ferror(file)) {
*output = PrintfToNewString(
- "Error: Read %d bytes, but ferror() returns true.", bytes_read);
+ "Read %d bytes, but ferror() returns true.", bytes_read);
return 3;
}
@@ -335,7 +345,8 @@ int HandleFread(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleFseek(int num_params, char** params, char** output) {
FILE* file;
const char* file_index_string;
@@ -344,7 +355,7 @@ int HandleFseek(int num_params, char** params, char** output) {
int result;
if (num_params != 3) {
- *output = PrintfToNewString("Error: fseek takes 3 parameters.");
+ *output = PrintfToNewString("fseek takes 3 parameters.");
return 1;
}
@@ -355,20 +366,20 @@ int HandleFseek(int num_params, char** params, char** output) {
if (!file) {
*output =
- PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
+ PrintfToNewString("Unknown file handle %s.", file_index_string);
return 2;
}
result = fseek(file, offset, whence);
if (result) {
- *output = PrintfToNewString("Error: fseek returned error %d.", result);
+ *output = PrintfToNewString("fseek returned error %d.", result);
return 3;
}
offset = ftell(file);
if (offset < 0) {
*output = PrintfToNewString(
- "Error: fseek succeeded, but ftell returned error %d.", offset);
+ "fseek succeeded, but ftell returned error %d.", offset);
return 4;
}
@@ -389,7 +400,8 @@ int HandleFseek(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleFclose(int num_params, char** params, char** output) {
FILE* file;
int file_index;
@@ -397,7 +409,7 @@ int HandleFclose(int num_params, char** params, char** output) {
int result;
if (num_params != 1) {
- *output = PrintfToNewString("Error: fclose takes 1 parameters.");
+ *output = PrintfToNewString("fclose takes 1 parameters.");
return 1;
}
@@ -405,13 +417,13 @@ int HandleFclose(int num_params, char** params, char** output) {
file = GetFileFromIndexString(file_index_string, &file_index);
if (!file) {
*output =
- PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
+ PrintfToNewString("Unknown file handle %s.", file_index_string);
return 2;
}
result = fclose(file);
if (result) {
- *output = PrintfToNewString("Error: fclose returned error %d.", result);
+ *output = PrintfToNewString("fclose returned error %d.", result);
return 3;
}
@@ -435,14 +447,15 @@ int HandleFclose(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleStat(int num_params, char** params, char** output) {
const char* filename;
int result;
struct stat buf;
if (num_params != 1) {
- *output = PrintfToNewString("Error: stat takes 1 parameter.");
+ *output = PrintfToNewString("stat takes 1 parameter.");
return 1;
}
@@ -451,7 +464,7 @@ int HandleStat(int num_params, char** params, char** output) {
memset(&buf, 0, sizeof(buf));
result = stat(filename, &buf);
if (result == -1) {
- *output = PrintfToNewString("Error: stat returned error %d.", errno);
+ *output = PrintfToNewString("stat returned error %d.", errno);
return 2;
}
@@ -473,10 +486,11 @@ int HandleStat(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleOpendir(int num_params, char** params, char** output) {
#if defined(WIN32)
- *output = PrintfToNewString("Error: Win32 does not support opendir.");
+ *output = PrintfToNewString("Win32 does not support opendir.");
return 1;
#else
DIR* dir;
@@ -484,7 +498,7 @@ int HandleOpendir(int num_params, char** params, char** output) {
const char* dirname;
if (num_params != 1) {
- *output = PrintfToNewString("Error: opendir takes 1 parameter.");
+ *output = PrintfToNewString("opendir takes 1 parameter.");
return 1;
}
@@ -492,14 +506,14 @@ int HandleOpendir(int num_params, char** params, char** output) {
dir = opendir(dirname);
if (!dir) {
- *output = PrintfToNewString("Error: opendir returned a NULL DIR*.");
+ *output = PrintfToNewString("opendir returned a NULL DIR*.");
return 2;
}
dir_index = AddDirToMap(dir);
if (dir_index == -1) {
*output = PrintfToNewString(
- "Error: Example only allows %d open dir handles.", MAX_OPEN_DIRS);
+ "Example only allows %d open dir handles.", MAX_OPEN_DIRS);
return 3;
}
@@ -522,10 +536,11 @@ int HandleOpendir(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleReaddir(int num_params, char** params, char** output) {
#if defined(WIN32)
- *output = PrintfToNewString("Error: Win32 does not support readdir.");
+ *output = PrintfToNewString("Win32 does not support readdir.");
return 1;
#else
DIR* dir;
@@ -533,7 +548,7 @@ int HandleReaddir(int num_params, char** params, char** output) {
struct dirent* entry;
if (num_params != 1) {
- *output = PrintfToNewString("Error: readdir takes 1 parameter.");
+ *output = PrintfToNewString("readdir takes 1 parameter.");
return 1;
}
@@ -541,8 +556,7 @@ int HandleReaddir(int num_params, char** params, char** output) {
dir = GetDirFromIndexString(dir_index_string, NULL);
if (!dir) {
- *output = PrintfToNewString("Error: Unknown dir handle %s.",
- dir_index_string);
+ *output = PrintfToNewString("Unknown dir handle %s.", dir_index_string);
return 2;
}
@@ -571,10 +585,11 @@ int HandleReaddir(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleClosedir(int num_params, char** params, char** output) {
#if defined(WIN32)
- *output = PrintfToNewString("Error: Win32 does not support closedir.");
+ *output = PrintfToNewString("Win32 does not support closedir.");
return 1;
#else
DIR* dir;
@@ -583,21 +598,21 @@ int HandleClosedir(int num_params, char** params, char** output) {
int result;
if (num_params != 1) {
- *output = PrintfToNewString("Error: closedir takes 1 parameters.");
+ *output = PrintfToNewString("closedir takes 1 parameters.");
return 1;
}
dir_index_string = params[0];
dir = GetDirFromIndexString(dir_index_string, &dir_index);
if (!dir) {
- *output = PrintfToNewString("Error: Unknown dir handle %s.",
+ *output = PrintfToNewString("Unknown dir handle %s.",
dir_index_string);
return 2;
}
result = closedir(dir);
if (result) {
- *output = PrintfToNewString("Error: closedir returned error %d.", result);
+ *output = PrintfToNewString("closedir returned error %d.", result);
return 3;
}
@@ -622,14 +637,15 @@ int HandleClosedir(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleMkdir(int num_params, char** params, char** output) {
const char* dirname;
int result;
int mode;
if (num_params != 2) {
- *output = PrintfToNewString("Error: mkdir takes 2 parameters.");
+ *output = PrintfToNewString("mkdir takes 2 parameters.");
return 1;
}
@@ -638,7 +654,7 @@ int HandleMkdir(int num_params, char** params, char** output) {
result = mkdir(dirname, mode);
if (result != 0) {
- *output = PrintfToNewString("Error: mkdir returned error: %d", errno);
+ *output = PrintfToNewString("mkdir returned error: %d", errno);
return 2;
}
@@ -647,6 +663,89 @@ int HandleMkdir(int num_params, char** params, char** output) {
}
/**
+ * Handle a call to rmdir() made by JavaScript.
+ *
+ * rmdir expects 1 parameter:
+ * 0: The name of the directory to remove
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleRmdir(int num_params, char** params, char** output) {
+ if (num_params != 1) {
+ *output = PrintfToNewString("rmdir takes 1 parameter.");
+ return 1;
+ }
+
+ const char* dirname = params[0];
+ int result = rmdir(dirname);
+ if (result != 0) {
+ *output = PrintfToNewString("rmdir returned error: %d", errno);
+ return 2;
+ }
+
+ *output = PrintfToNewString("rmdir\1%s", dirname);
+ return 0;
+}
+
+/**
+ * Handle a call to chdir() made by JavaScript.
+ *
+ * chdir expects 1 parameter:
+ * 0: The name of the directory
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleChdir(int num_params, char** params, char** output) {
+ if (num_params != 1) {
+ *output = PrintfToNewString("chdir takes 1 parameter.");
+ return 1;
+ }
+
+ const char* dirname = params[0];
+ int result = chdir(dirname);
+ if (result != 0) {
+ *output = PrintfToNewString("chdir returned error: %d", errno);
+ return 2;
+ }
+
+ *output = PrintfToNewString("chdir\1%s", dirname);
+ return 0;
+}
+
+/**
+ * Handle a call to getcwd() made by JavaScript.
+ *
+ * getcwd expects 0 parameters.
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleGetcwd(int num_params, char** params, char** output) {
+ if (num_params != 0) {
+ *output = PrintfToNewString("getcwd takes 0 parameters.");
+ return 1;
+ }
+
+ char cwd[PATH_MAX];
+ char* result = getcwd(cwd, PATH_MAX);
+ if (result == NULL) {
+ *output = PrintfToNewString("getcwd returned error: %d", errno);
+ return 1;
+ }
+
+ *output = PrintfToNewString("getcwd\1%s", cwd);
+ return 0;
+}
+
+/**
* Handle a call to gethostbyname() made by JavaScript.
*
* gethostbyname expects 1 parameter:
@@ -662,7 +761,8 @@ int HandleMkdir(int num_params, char** params, char** output) {
* @param[in] num_params The number of params in |params|.
* @param[in] params An array of strings, parameters to this function.
* @param[out] output A string to write informational function output to.
- * @return An errorcode; 0 means success, anything else is a failure. */
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
int HandleGethostbyname(int num_params, char** params, char** output) {
struct hostent* info;
struct in_addr **addr_list;
@@ -674,7 +774,7 @@ int HandleGethostbyname(int num_params, char** params, char** output) {
int i;
if (num_params != 1) {
- *output = PrintfToNewString("Error: gethostbyname takes 1 parameter.");
+ *output = PrintfToNewString("gethostbyname takes 1 parameter.");
return 1;
}
@@ -682,7 +782,7 @@ int HandleGethostbyname(int num_params, char** params, char** output) {
info = gethostbyname(name);
if (!info) {
- *output = PrintfToNewString("Error: gethostbyname failed, error is \"%s\"",
+ *output = PrintfToNewString("gethostbyname failed, error is \"%s\"",
hstrerror(h_errno));
return 2;
}
@@ -706,7 +806,7 @@ int HandleGethostbyname(int num_params, char** params, char** output) {
*output = (char*) calloc(output_len + 1, 1);
if (!*output) {
- *output = PrintfToNewString("Error: out of memory.");
+ *output = PrintfToNewString("out of memory.");
return 3;
}
snprintf(*output, non_variable_len + 1, "gethostbyname\1%s\1%s",
@@ -724,3 +824,149 @@ int HandleGethostbyname(int num_params, char** params, char** output) {
}
return 0;
}
+
+/**
+ * Handle a call to connect() made by JavaScript.
+ *
+ * This call expects 2 parameters:
+ * 0: The hostname to connect to.
+ * 1: The port number to connect to.
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleConnect(int num_params, char** params, char** output) {
+ if (num_params != 2) {
+ *output = PrintfToNewString("connect takes 2 parameters.");
+ return 1;
+ }
+
+ struct sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+ const char* hostname = params[0];
+ int port = strtol(params[1], NULL, 10);
+
+ // Lookup host
+ struct hostent* hostent = gethostbyname(hostname);
+ if (hostent == NULL) {
+ *output = PrintfToNewString("gethostbyname() returned error: %d", errno);
+ return 1;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ memcpy(&addr.sin_addr.s_addr, hostent->h_addr_list[0], hostent->h_length);
+
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ *output = PrintfToNewString("socket() failed: %s", strerror(errno));
+ return 1;
+ }
+
+ int result = connect(sock, (struct sockaddr*)&addr, addrlen);
+ if (result != 0) {
+ *output = PrintfToNewString("connect() failed: %s", strerror(errno));
+ close(sock);
+ return 1;
+ }
+
+ *output = PrintfToNewString("connect\1%d", sock);
+ return 0;
+}
+
+/**
+ * Handle a call to send() made by JavaScript.
+ *
+ * This call expects 2 parameters:
+ * 0: The socket file descriptor to send using.
+ * 1: The NULL terminated string to send.
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleSend(int num_params, char** params, char** output) {
+ if (num_params != 2) {
+ *output = PrintfToNewString("send takes 2 parameters.");
+ return 1;
+ }
+
+ int sock = strtol(params[0], NULL, 10);
+ const char* buffer = params[1];
+ int result = send(sock, buffer, strlen(buffer), 0);
+ if (result <= 0) {
+ *output = PrintfToNewString("send failed: %s", strerror(errno));
+ return 1;
+ }
+
+ *output = PrintfToNewString("send\1%d", result);
+ return 0;
+}
+
+/**
+ * Handle a call to recv() made by JavaScript.
+ *
+ * This call expects 2 parameters:
+ * 0: The socket file descriptor to recv from.
+ * 1: The size of the buffer to pass to recv.
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleRecv(int num_params, char** params, char** output) {
+ if (num_params != 2) {
+ *output = PrintfToNewString("recv takes 2 parameters.");
+ return 1;
+ }
+
+ int sock = strtol(params[0], NULL, 10);
+ int buffersize = strtol(params[1], NULL, 10);
+ if (buffersize < 0 || buffersize > 65 * 1024) {
+ *output = PrintfToNewString("recv buffersize must be between 0 and 65k.");
+ return 1;
+ }
+
+ char* buffer = alloca(buffersize);
+ memset(buffer, 0, buffersize);
+ int result = recv(sock, buffer, buffersize, 0);
+ if (result <= 0) {
+ *output = PrintfToNewString("recv failed: %s", strerror(errno));
+ return 2;
+ }
+
+ *output = PrintfToNewString("recv\1%d\1%s", result, buffer);
+ return 0;
+}
+
+/**
+ * Handle a call to close() made by JavaScript.
+ *
+ * This call expects 1 parameters:
+ * 0: The socket file descriptor to close.
+ *
+ * @param[in] num_params The number of params in |params|.
+ * @param[in] params An array of strings, parameters to this function.
+ * @param[out] output A string to write informational function output to.
+ * @return An errorcode; 0 means success, anything else is a failure.
+ */
+int HandleClose(int num_params, char** params, char** output) {
+ if (num_params != 1) {
+ *output = PrintfToNewString("close takes 1 parameters.");
+ return 1;
+ }
+
+ int sock = strtol(params[0], NULL, 10);
+ int result = close(sock);
+ if (result != 0) {
+ *output = PrintfToNewString("close returned error: %d", errno);
+ return 2;
+ }
+
+ *output = PrintfToNewString("close\1%d", sock);
+ return 0;
+}
diff --git a/native_client_sdk/src/examples/demo/nacl_io/handlers.h b/native_client_sdk/src/examples/demo/nacl_io/handlers.h
index 595f96ae53..a84d7654e2 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/handlers.h
+++ b/native_client_sdk/src/examples/demo/nacl_io/handlers.h
@@ -1,7 +1,6 @@
/* 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.
- */
+ * found in the LICENSE file. */
#ifndef HANDLERS_H_
#define HANDLERS_H_
@@ -16,10 +15,20 @@ int HandleFread(int num_params, char** params, char** output);
int HandleFseek(int num_params, char** params, char** output);
int HandleFclose(int num_params, char** params, char** output);
int HandleStat(int num_params, char** params, char** output);
+
int HandleOpendir(int num_params, char** params, char** output);
int HandleReaddir(int num_params, char** params, char** output);
int HandleClosedir(int num_params, char** params, char** output);
+
int HandleMkdir(int num_params, char** params, char** output);
+int HandleRmdir(int num_params, char** params, char** output);
+int HandleChdir(int num_params, char** params, char** output);
+int HandleGetcwd(int num_params, char** params, char** output);
+
int HandleGethostbyname(int num_params, char** params, char** output);
+int HandleConnect(int num_params, char** params, char** output);
+int HandleSend(int num_params, char** params, char** output);
+int HandleRecv(int num_params, char** params, char** output);
+int HandleClose(int num_params, char** params, char** output);
#endif /* HANDLERS_H_ */
diff --git a/native_client_sdk/src/examples/demo/nacl_io/index.html b/native_client_sdk/src/examples/demo/nacl_io/index.html
index 1b132c1f78..f368a52ec8 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/index.html
+++ b/native_client_sdk/src/examples/demo/nacl_io/index.html
@@ -46,16 +46,12 @@ found in the LICENSE file.
<p><b>File Operations:</b></p>
<div>
<span>
- <input type="radio" id="radiofopen" name="filegroup" checked="checked">fopen
- <input type="radio" id="radiofclose" name="filegroup">fclose
- <input type="radio" id="radiofread" name="filegroup">fread
- <input type="radio" id="radiofwrite" name="filegroup">fwrite
- <input type="radio" id="radiofseek" name="filegroup">fseek
- <input type="radio" id="radiostat" name="filegroup">stat
- <input type="radio" id="radioopendir" name="filegroup">opendir
- <input type="radio" id="radioreaddir" name="filegroup">readdir
- <input type="radio" id="radioclosedir" name="filegroup">closedir
- <input type="radio" id="radiomkdir" name="filegroup">mkdir
+ <input type="radio" id="radiofopen" name="group" checked="checked">fopen
+ <input type="radio" id="radiofclose" name="group">fclose
+ <input type="radio" id="radiofread" name="group">fread
+ <input type="radio" id="radiofwrite" name="group">fwrite
+ <input type="radio" id="radiofseek" name="group">fseek
+ <input type="radio" id="radiostat" name="group">stat
</span>
</div>
<div class="function" id="fopen">
@@ -116,6 +112,19 @@ found in the LICENSE file.
<button>stat</button>
</span>
</div>
+ <hr>
+ <p><b>Directory Operations:</b></p>
+ <div>
+ <span>
+ <input type="radio" id="radioopendir" name="group">opendir
+ <input type="radio" id="radioreaddir" name="group">readdir
+ <input type="radio" id="radioclosedir" name="group">closedir
+ <input type="radio" id="radiomkdir" name="group">mkdir
+ <input type="radio" id="radiormdir" name="group">rmdir
+ <input type="radio" id="radiochdir" name="group">chdir
+ <input type="radio" id="radiogetcwd" name="group">getcwd
+ </span>
+ </div>
<div class="function" id="opendir" hidden>
<span>
Dirname:
@@ -144,20 +153,74 @@ found in the LICENSE file.
<button>mkdir</button>
</span>
</div>
+ <div class="function" id="rmdir" hidden>
+ <span>
+ Dirname:
+ <input type="text" id="rmdirDirname">
+ <button>rmdir</button>
+ </span>
+ </div>
+ <div class="function" id="chdir" hidden>
+ <span>
+ Dirname:
+ <input type="text" id="chdirDirname">
+ <button>chdir</button>
+ </span>
+ </div>
+ <div class="function" id="getcwd" hidden>
+ <span>
+ <button>getcwd</button>
+ </span>
+ </div>
<hr>
<p><b>Socket Operations:</b></p>
<div>
<span>
- <input type="radio" id="radiogethostbyname" name="socketgroup" checked="checked">gethostbyname
+ <input type="radio" id="radiogethostbyname" name="group">gethostbyname
+ <input type="radio" id="radioconnect" name="group">connect
+ <input type="radio" id="radiosend" name="group">send
+ <input type="radio" id="radiorecv" name="group">recv
+ <input type="radio" id="radioclose" name="group">close
</span>
</div>
- <div class="function" id="gethostbyname">
+ <div class="function" id="gethostbyname" hidden>
<span>
- Name:
- <input type="text" id="gethostbynameName">
+ Hostname:
+ <input type="text" id="gethostbynameName" value="google.com">
<button>gethostbyname</button>
</span>
</div>
+ <div class="function" id="connect" hidden>
+ <span>
+ Host:
+ <input type="text" id="connectHost" value="google.com">
+ Port:
+ <input type="text" id="connectPort" value="80">
+ <button>connect</button>
+ </span>
+ </div>
+ <div class="function" id="send" hidden>
+ <span>
+ <select class="sock-handle" id="sendHandle"></select>
+ Message:
+ <input type="text" id="sendMessage" value="Hello!">
+ <button>send</button>
+ </span>
+ </div>
+ <div class="function" id="recv" hidden>
+ <span>
+ <select class="sock-handle" id="recvHandle"></select>
+ Buffer Size:
+ <input type="text" id="recvBufferSize" value="256">
+ <button>recv</button>
+ </span>
+ </div>
+ <div class="function" id="close" hidden>
+ <span>
+ <select class="sock-handle" id="closeHandle"></select>
+ <button>close</button>
+ </span>
+ </div>
<hr>
<p><b>Log:</b></p>
diff --git a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
index ff2489603d..eed1721597 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
@@ -53,7 +53,14 @@ static FuncNameMapping g_function_map[] = {
{"readdir", HandleReaddir},
{"closedir", HandleClosedir},
{"mkdir", HandleMkdir},
+ {"rmdir", HandleRmdir},
+ {"chdir", HandleChdir},
+ {"getcwd", HandleGetcwd},
{"gethostbyname", HandleGethostbyname},
+ {"connect", HandleConnect},
+ {"send", HandleSend},
+ {"recv", HandleRecv},
+ {"close", HandleClose},
{NULL, NULL},
};
@@ -63,7 +70,8 @@ static pthread_t g_handle_message_thread;
/**
* Create a new PP_Var from a C string.
* @param[in] str The string to convert.
- * @return A new PP_Var with the contents of |str|. */
+ * @return A new PP_Var with the contents of |str|.
+ */
struct PP_Var CStrToVar(const char* str) {
if (ppb_var_interface != NULL) {
return ppb_var_interface->VarFromUtf8(str, strlen(str));
@@ -97,7 +105,8 @@ char* VprintfToNewString(const char* format, va_list args) {
* Printf to a newly allocated C string.
* @param[in] format A print format string.
* @param[in] ... The printf arguments.
- * @return The newly constructed string. Caller takes ownership. */
+ * @return The newly constructed string. Caller takes ownership.
+ */
char* PrintfToNewString(const char* format, ...) {
va_list args;
char* result;
@@ -111,7 +120,8 @@ char* PrintfToNewString(const char* format, ...) {
* Printf to a new PP_Var.
* @param[in] format A print format string.
* @param[in] ... The printf arguments.
- * @return A new PP_Var. */
+ * @return A new PP_Var.
+ */
struct PP_Var PrintfToVar(const char* format, ...) {
if (ppb_var_interface != NULL) {
char* string;
@@ -136,7 +146,8 @@ struct PP_Var PrintfToVar(const char* format, ...) {
* @param[in] var The PP_Var to convert.
* @param[out] buffer The buffer to write to.
* @param[in] length The length of |buffer|.
- * @return The number of characters written. */
+ * @return The number of characters written.
+ */
uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length) {
if (ppb_var_interface != NULL) {
uint32_t var_length;
@@ -172,7 +183,8 @@ uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length) {
* @param[out] out_function The function name.
* @param[out] out_params An array of strings, one for each parameter parsed.
* @param[in] max_params The maximum number of parameters to parse.
- * @return The number of parameters parsed. */
+ * @return The number of parameters parsed.
+ */
static size_t ParseMessage(char* message,
char** out_function,
char** out_params,
@@ -208,7 +220,8 @@ static size_t ParseMessage(char* message,
/**
* Given a function name, look up its handler function.
* @param[in] function_name The function name to look up.
- * @return The handler function mapped to |function_name|. */
+ * @return The handler function mapped to |function_name|.
+ */
static HandleFunc GetFunctionByName(const char* function_name) {
FuncNameMapping* map_iter = g_function_map;
for (; map_iter->name; ++map_iter) {
@@ -220,9 +233,11 @@ static HandleFunc GetFunctionByName(const char* function_name) {
return NULL;
}
-/** Handle as message from JavaScript on the worker thread.
+/**
+ * Handle as message from JavaScript on the worker thread.
*
- * @param[in] message The message to parse and handle. */
+ * @param[in] message The message to parse and handle.
+ */
static void HandleMessage(char* message) {
char* function_name;
char* params[MAX_PARAMS];
@@ -248,15 +263,12 @@ static void HandleMessage(char* message) {
/* Error. */
struct PP_Var var;
if (output != NULL) {
- var = PrintfToVar("Error: Function \"%s\" returned error %d. "
- "Additional output: %s",
- function_name,
- result,
- output);
+ var = PrintfToVar("Error: \"%s\" failed: %d: %s.", function_name,
+ result, output);
free(output);
} else {
var = PrintfToVar(
- "Error: Function \"%s\" returned error %d.", function_name, result);
+ "Error: \"%s\" failed: %d.", function_name, result);
}
/* Post the error to JavaScript, so the user can see it. */
@@ -271,9 +283,11 @@ static void HandleMessage(char* message) {
}
}
-/** A worker thread that handles messages from JavaScript.
+/**
+ * A worker thread that handles messages from JavaScript.
* @param[in] user_data Unused.
- * @return unused. */
+ * @return unused.
+ */
void* HandleMessageThread(void* user_data) {
while (1) {
char* message = DequeueMessage();
diff --git a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h
index 25de39553b..6eccb5ebd1 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h
+++ b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.h
@@ -1,7 +1,6 @@
/* 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.
- */
+ * found in the LICENSE file. */
#ifndef NACL_IO_DEMO_H_
#define NACL_IO_DEMO_H_
diff --git a/native_client_sdk/src/examples/demo/voronoi/index.html b/native_client_sdk/src/examples/demo/voronoi/index.html
index 7cbbd19deb..2f6633b250 100644
--- a/native_client_sdk/src/examples/demo/voronoi/index.html
+++ b/native_client_sdk/src/examples/demo/voronoi/index.html
@@ -21,8 +21,8 @@ found in the LICENSE file.
<br>
Number of points:
<input type="range" id="pointRange"
- min="1" max="1024" step="1" value="256" />
- <label id="pointCount" >256 points</label>
+ min="1" max="1024" step="1" value="48" />
+ <label id="pointCount" >48 points</label>
<br>
Number of threads (0 is main thread):
<input type="radio" name="threadCount" id="radio0" value="0"
diff --git a/native_client_sdk/src/examples/demo/voronoi/voronoi.cc b/native_client_sdk/src/examples/demo/voronoi/voronoi.cc
index 48f311871f..99cf566ec0 100644
--- a/native_client_sdk/src/examples/demo/voronoi/voronoi.cc
+++ b/native_client_sdk/src/examples/demo/voronoi/voronoi.cc
@@ -39,7 +39,7 @@ const float kTwoPI = kPI * 2.0f;
const int kFramesToBenchmark = 100;
const unsigned int kRandomStartSeed = 0xC0DE533D;
const int kMaxPointCount = 1024;
-const int kStartPointCount = 256;
+const int kStartPointCount = 48;
const int kDefaultNumRegions = 256;
unsigned int g_rand_state = kRandomStartSeed;
@@ -448,6 +448,21 @@ void Voronoi::HandleEvent(PSEvent* ps_event) {
StartBenchmark();
break;
}
+ case PP_INPUTEVENT_TYPE_TOUCHSTART:
+ case PP_INPUTEVENT_TYPE_TOUCHMOVE: {
+ pp::TouchInputEvent touches = pp::TouchInputEvent(event);
+ uint32_t count = touches.GetTouchCount(PP_TOUCHLIST_TYPE_TOUCHES);
+ // Touch points 0..n directly set position of points 0..n in
+ // Voronoi diagram.
+ for (uint32_t i = 0; i < count; i++) {
+ pp::TouchPoint touch =
+ touches.GetTouchByIndex(PP_TOUCHLIST_TYPE_TOUCHES, i);
+ pp::FloatPoint point = touch.position();
+ positions_[i].Set(point.x() / ps_context_->width,
+ point.y() / ps_context_->height);
+ }
+ break;
+ }
default:
break;
}
diff --git a/native_client_sdk/src/examples/tutorial/debugging/debugging.c b/native_client_sdk/src/examples/tutorial/debugging/debugging.c
index 99b56a281e..a4c0985155 100644
--- a/native_client_sdk/src/examples/tutorial/debugging/debugging.c
+++ b/native_client_sdk/src/examples/tutorial/debugging/debugging.c
@@ -65,29 +65,7 @@ void* NexeMain(void* data) {
return 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();
-}
-
-static void PostCompletionCallback(void* user_data, int32_t result) {
- const char* str = (const char*)user_data;
- ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str));
- free(user_data);
-}
-
void PostMessage(const char* str) {
- struct PP_CompletionCallback cb;
-
if (NULL == str)
return;
if (NULL == ppb_messaging_interface)
@@ -95,55 +73,27 @@ void PostMessage(const char* str) {
if (0 == g_Instance)
return;
- if (strncmp(str, "ERR:", 4)) {
- fprintf(stderr, "%s\n", str);
- fflush(stderr);
- } else {
- fprintf(stdout, "%s\n", str);
- fflush(stdout);
- }
+ fprintf(stdout, "%s\n", str);
+ fflush(stdout);
- /* If on Main Pepper thread, then call interface directly. */
- if (pthread_self() == g_PPAPIThread) {
- ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str));
- return;
+ if (ppb_var_interface != NULL) {
+ struct PP_Var var = ppb_var_interface->VarFromUtf8(str, strlen(str));
+ ppb_messaging_interface->PostMessage(g_Instance, var);
+ ppb_var_interface->Release(var);
}
-
- /* Otherwise use call on main thread. */
- cb = PP_MakeCompletionCallback(PostCompletionCallback, strdup(str));
- ppb_core_interface->CallOnMainThread(0, cb, 0);
}
void DumpJson(const char* json) {
- char* out = (char*)malloc(strlen(json) + 5);
- strcpy(out, "TRC: ");
+ const char kTrcPrefix[] = "TRC: ";
+ size_t size = sizeof(kTrcPrefix) + strlen(json) + 1; // +1 for NULL.
+ char* out = (char*)malloc(size);
+ strcpy(out, kTrcPrefix);
strcat(out, json);
PostMessage(out);
free(out);
}
-/**
- * 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
- * instantiation of the NaCl module, which is each time the <embed> tag for
- * this module is encountered.
- *
- * If this function reports a failure (by returning @a PP_FALSE), the NaCl
- * module will be deleted and DidDestroy will be called.
- * @param[in] instance The identifier of the new instance representing this
- * NaCl module.
- * @param[in] argc The number of arguments contained in @a argn and @a argv.
- * @param[in] argn An array of argument names. These argument names are
- * supplied in the <embed> tag, for example:
- * <embed id="nacl_module" dimensions="2">
- * will produce two arguments, one named "id" and one named "dimensions".
- * @param[in] argv An array of argument values. These are the values of the
- * arguments listed in the <embed> tag. In the above example, there will
- * be two elements in this array, "nacl_module" and "2". The indices of
- * these values match the indices of the corresponding names in @a argn.
- * @return @a PP_TRUE on success.
- */
+
static PP_Bool Instance_DidCreate(PP_Instance instance,
uint32_t argc,
const char* argn[],
@@ -166,62 +116,15 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
return PP_TRUE;
}
-/**
- * Called when the NaCl module is destroyed. This will always be called,
- * even if DidCreate returned failure. This routine should deallocate any data
- * associated with the instance.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- */
static void Instance_DidDestroy(PP_Instance instance) {}
-/**
- * Called when the position, the size, or the clip rect of the element in the
- * browser that corresponds to this NaCl module has changed.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] position The location on the page of this NaCl module. This is
- * relative to the top left corner of the viewport, which changes as the
- * page is scrolled.
- * @param[in] clip The visible region of the NaCl module. This is relative to
- * the top left of the plugin's coordinate system (not the page). If the
- * plugin is invisible, @a clip will be (0, 0, 0, 0).
- */
static void Instance_DidChangeView(PP_Instance instance,
PP_Resource view_resource) {}
-/**
- * Notification that the given NaCl module has gained or lost focus.
- * Having focus means that keyboard events will be sent to the NaCl module
- * represented by @a instance. A NaCl module's default condition is that it
- * will not have focus.
- *
- * Note: clicks on NaCl modules will give focus only if you handle the
- * click event. You signal if you handled it by returning @a true from
- * HandleInputEvent. Otherwise the browser will bubble the event and give
- * focus to the element on the page that actually did end up consuming it.
- * If you're not getting focus, check to make sure you're returning true from
- * the mouse click in HandleInputEvent.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] has_focus Indicates whether this NaCl module gained or lost
- * event focus.
- */
static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
-/**
- * Handler that gets called after a full-frame module is instantiated based on
- * registered MIME types. This function is not called on NaCl modules. This
- * function is essentially a place-holder for the required function pointer in
- * the PPP_Instance structure.
- * @param[in] instance The identifier of the instance representing this NaCl
- * module.
- * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance.
- * @return PP_FALSE.
- */
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
- /* NaCl modules do not need to handle the document load function. */
return PP_FALSE;
}
@@ -236,15 +139,8 @@ static void Messaging_HandleMessage(PP_Instance instance,
g_CrashTime = 1;
}
-/**
- * Entry points for the module.
- * Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
- * @param[in] a_module_id module ID
- * @param[in] get_browser pointer to PPB_GetInterface
- * @return PP_OK on success, any other value on failure.
- */
-PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
- PPB_GetInterface get_browser) {
+PP_EXPORT int32_t
+PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser) {
ppb_messaging_interface =
(PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
@@ -252,20 +148,14 @@ PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
return PP_OK;
}
-/**
- * Returns an interface pointer for the interface of the given name, or NULL
- * if the interface is not supported.
- * @param[in] interface_name name of the interface
- * @return pointer to the interface
- */
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
- &Instance_DidCreate,
- &Instance_DidDestroy,
- &Instance_DidChangeView,
- &Instance_DidChangeFocus,
- &Instance_HandleDocumentLoad,
+ &Instance_DidCreate,
+ &Instance_DidDestroy,
+ &Instance_DidChangeView,
+ &Instance_DidChangeFocus,
+ &Instance_HandleDocumentLoad,
};
return &instance_interface;
}
@@ -278,7 +168,4 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
return NULL;
}
-/**
- * Called before the plugin module is unloaded.
- */
PP_EXPORT void PPP_ShutdownModule() {}
diff --git a/native_client_sdk/src/examples/tutorial/debugging/example.dsc b/native_client_sdk/src/examples/tutorial/debugging/example.dsc
index a9233e4de7..f7e20ead5c 100644
--- a/native_client_sdk/src/examples/tutorial/debugging/example.dsc
+++ b/native_client_sdk/src/examples/tutorial/debugging/example.dsc
@@ -13,13 +13,6 @@
'LIBS' : ['ppapi', 'pthread']
}
],
-
- 'POST': """
-
-#
-# Specify the MAP files to be created.
-#
-$(eval $(call MAP_RULE,$(TARGET),$(TARGET)))""",
'DATA': [
'example.js',
],
diff --git a/native_client_sdk/src/examples/tutorial/debugging/example.js b/native_client_sdk/src/examples/tutorial/debugging/example.js
index 6f637f83d4..7542844b42 100644
--- a/native_client_sdk/src/examples/tutorial/debugging/example.js
+++ b/native_client_sdk/src/examples/tutorial/debugging/example.js
@@ -22,14 +22,14 @@ function findAddress(addr, map) {
if (map.length < 1) {
return 'MAP Unavailable';
}
- if (addr < map[0].offs) {
+ if (addr < map[0].offs) {
return 'Invalid Address';
}
- for (var i=1; i < map.length; i++) {
+ for (var i = 1; i < map.length; i++) {
if (addr < map[i].offs) {
- var offs = addr - map[i-1].offs;
- var filename = map[i-1].file;
+ var offs = addr - map[i - 1].offs;
+ var filename = map[i - 1].file;
// Force filename to 50 chars
if (filename) {
@@ -40,41 +40,71 @@ function findAddress(addr, map) {
filename = 'Unknown';
}
while (filename.length < 50) {
- filename = ' ' + filename
+ filename = ' ' + filename;
}
- return filename + ' ' + map[i-1].name + ' + 0x' + offs.toString(16);
+ return filename + ' ' + map[i - 1].name + ' + 0x' + offs.toString(16);
}
}
var last = map.length - 1;
- return filename + ' ' + map[last].name + ' + 0x' + offs.toString(16);
+ return filename + ' ' + map[last].name + ' + 0x' + offs.toString(16);
}
function buildTextMap(map) {
- map = map.split('\n');
+ // The expected format of the map file is this:
+ // ...
+ // .text 0x00000000000201e0 0x10e0 newlib/Debug/debugging_x86_64.o
+ // 0x0000000000020280 layer5
+ // 0x00000000000202e0 layer4
+ // 0x0000000000020320 layer3
+ // 0x0000000000020380 layer2
+ // 0x00000000000203e0 layer1
+ // 0x0000000000020460 NexeMain
+ // ...
+ var lines = map.split('\n');
var orderedMap = [];
- for (var i=0; i < map.length; i++) {
- var line = map[i].replace('\t', ' ');
- var vals = line.split(' ');
- var obj = {
- offs: parseInt(vals[0], 16),
- name: vals[2],
- file: vals[3]
- }
- if (vals[1] && vals[1].toUpperCase() == 'T') {
+ var inTextSection = false;
+ var fileName = '';
+
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+
+ if (inTextSection) {
+ // <hex address> <symbol name>
+ var vals = line.trim().split(/\s+/);
+ if (vals.length != 2) {
+ inTextSection = false;
+ continue;
+ }
+
+ var obj = {
+ offs: parseInt(vals[0], 16),
+ name: vals[1],
+ file: fileName
+ };
+
orderedMap.push(obj);
+ } else {
+ // If line starts with .text:
+ if (line.lastIndexOf(' .text', 0) === 0) {
+ inTextSection = true;
+ // .text <hex address> <size> <filename>
+ var vals = line.trim().split(/\s+/);
+ fileName = vals[3];
+ }
}
}
- orderedMap.sort(function(a,b) { return a.offs - b.offs; });
+
+ orderedMap.sort(function(a, b) { return a.offs - b.offs; });
return orderedMap;
}
function updateStack(traceinfo, map) {
map = buildTextMap(map);
var text = 'Stack Trace\n';
- for (var i=0; i < traceinfo.frames.length; i++) {
+ for (var i = 0; i < traceinfo.frames.length; i++) {
var frame = traceinfo.frames[i];
- var addr = findAddress(frame.prog_ctr, map)
+ var addr = findAddress(frame.prog_ctr, map);
text += '[' + i.toString(10) + '] ' + addr + '\n';
}
document.getElementById('trace').value = text;
@@ -85,7 +115,7 @@ function fetchMap(url, traceinfo) {
xmlhttp.open('GET', url, true);
xmlhttp.onload = function() {
updateStack(traceinfo, this.responseText);
- }
+ };
xmlhttp.traceinfo = traceinfo;
xmlhttp.send();
}
@@ -98,9 +128,6 @@ function handleMessage(message_event) {
document.getElementById('log').value += msg_data + '\n';
return;
}
- if (msg_type == 'STS:') {
- updateStatus(msg_data);
- }
if (msg_type == 'TRC:') {
crashed = true;
document.getElementById('json').value = msg_data;
@@ -112,15 +139,11 @@ function handleMessage(message_event) {
}
}
-function handleCrash(message) {
- updateStatus(message);
-}
-
function updateStatus(message) {
common.updateStatus(message);
if (message)
- document.getElementById('log').value += message + '\n'
+ document.getElementById('log').value += message + '\n';
}
function boom() {
diff --git a/native_client_sdk/src/examples/tutorial/debugging/index.html b/native_client_sdk/src/examples/tutorial/debugging/index.html
index 571984abd2..eb836ab415 100644
--- a/native_client_sdk/src/examples/tutorial/debugging/index.html
+++ b/native_client_sdk/src/examples/tutorial/debugging/index.html
@@ -17,9 +17,14 @@
<p> This example illustrates techniques for tracking the state of a NaCl
module via PostMessage and status of the module's lastError attribute.
Messages from the modules are in the form of
- <li>"LOG: <data>" which adds the message to the log.</li>
- <li>"STS: <data>" which updates the status string.</li>
- <li>"TRC: <data>" which provides a JSON string defining an exception.</li>
+ <ul>
+ <li>
+ "LOG: &lt;data&gt;" which adds the message to the log.
+ </li>
+ <li>
+ "TRC: &lt;data&gt;" which provides a JSON string defining an exception.
+ </li>
+ </ul>
<h2> Exception API </h2>
<p> As of Chrome 28, NativeClient exception handling is possible without
requiring special command-line flags. This feature is not always available
@@ -34,7 +39,7 @@
both a handler and an exception stack. We use a separate stack since we
do not know the state of stack for the thread handling the exception.
Next, we create a worker thread which will take the exception. It is
- recommended that modules do as much work as possible off the main thread.
+ recommended that modules do as much work as possible off the main thread.
Failure to do so can block the browser, making the page unresponsive and/or
preventing communication with JavaScript. In addition blocking calls,
which can greatly simplify code, are only allowed off the main thread.</p>
diff --git a/native_client_sdk/src/getting_started/part2/example.dsc b/native_client_sdk/src/getting_started/part2/example.dsc
index 9e10783cd6..faf995723c 100644
--- a/native_client_sdk/src/getting_started/part2/example.dsc
+++ b/native_client_sdk/src/getting_started/part2/example.dsc
@@ -11,7 +11,8 @@
}
],
'DATA': [
- 'example.js'
+ 'example.js',
+ 'README',
],
'DEST': 'getting_started',
'NAME': 'part2',
diff --git a/native_client_sdk/src/gonacl_appengine/README b/native_client_sdk/src/gonacl_appengine/README
index 788ae6c4fd..ab51466d2e 100644
--- a/native_client_sdk/src/gonacl_appengine/README
+++ b/native_client_sdk/src/gonacl_appengine/README
@@ -3,7 +3,7 @@ This is a new App Engine Python 2.7 application for http://gonacl.com
At this time it presents the existing functionality of redirecting
to http://developers.google.com/native-client/
-Also, a PNaCl demo is added at /static/pnacl-demo/index.html
+Also, there are PNaCl demos added at /static/pnacl-demo-<name>/index.html
To upload, run this from the root directory of the AppEngine SDK:
@@ -15,6 +15,11 @@ be tried before actually being activated, by going to the "Versions" section on
the AppEngine dashboard. Note that the newly uploaded version only becomes
active when it's set as the "default" version in the dashboard.
-In static/pnacl-demo we have the files for the modified Earth demo. Only the
-source files (HTML and JS) are kept in source control. The pexe and images
-should be copied over from an SDK build when uploading to AppEngine.
+Included demos:
+
+* static/pnacl-demo-earth: the modified Earth demo.
+* static/pnacl-demo-bullet: a demo of bullet physics, using NaCl acceleration
+ modules.
+
+Only the source files (HTML and JS) are kept in source control. The pexe and
+images should be copied over from an SDK build when uploading to AppEngine.
diff --git a/native_client_sdk/src/gonacl_appengine/app.yaml b/native_client_sdk/src/gonacl_appengine/app.yaml
index 05885d3cd4..60a8fa1442 100644
--- a/native_client_sdk/src/gonacl_appengine/app.yaml
+++ b/native_client_sdk/src/gonacl_appengine/app.yaml
@@ -5,6 +5,18 @@ api_version: 1
threadsafe: true
handlers:
+- url: /static/pnacl-demo-(.*)/
+ static_files: static/pnacl-demo-\1/index.html
+ upload: static/pnacl-demo-.*/index\.html
+
+- url: /static/pnacl-demo/
+ static_files: static/pnacl-demo-earth/index.html
+ upload: static/pnacl-demo-earth/index\.html
+
+- url: /static/pnacl-demo/(.*)
+ static_files: static/pnacl-demo-earth/\1
+ upload: static/pnacl-demo-earth/.*
+
- url: /static
static_dir: static
diff --git a/native_client_sdk/src/gonacl_appengine/src/bullet/.gitignore b/native_client_sdk/src/gonacl_appengine/src/bullet/.gitignore
new file mode 100644
index 0000000000..bd339019dd
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/bullet/.gitignore
@@ -0,0 +1,3 @@
+NaClAMBase
+naclports
+NaClAMBullet.pexe
diff --git a/native_client_sdk/src/gonacl_appengine/src/bullet/Makefile b/native_client_sdk/src/gonacl_appengine/src/bullet/Makefile
new file mode 100644
index 0000000000..85de2ba85b
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/bullet/Makefile
@@ -0,0 +1,38 @@
+# 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.
+
+# GNU Makefile based on shared rules provided by the Native Client SDK.
+# See README.Makefiles for more details.
+
+VALID_TOOLCHAINS := pnacl
+
+NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../../..)
+include $(NACL_SDK_ROOT)/tools/common.mk
+
+TARGET = NaClAMBullet
+LIBS = BulletDynamics BulletCollision LinearMath ppapi pthread
+
+USR_INCLUDE=$(dir $(PNACL_BIN))/usr/include
+BULLET_INCLUDE=$(USR_INCLUDE)/bullet
+
+CFLAGS = -I$(CURDIR) -I$(BULLET_INCLUDE)
+CFLAGS += -Wall -Wno-overloaded-virtual -Wno-unused-variable
+SOURCES = \
+ NaClAMBase/NaClAMBase.cpp \
+ NaClAMBase/NaClAMMessageCollector.cpp \
+ NaClAMBase/jsoncpp.cpp \
+ NaClAMBullet/NaClAMBullet.cpp
+
+# Build rules generated by macros from common.mk:
+
+$(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS))))
+
+ifeq ($(CONFIG),Release)
+$(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS)))
+$(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped))
+else
+$(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
+endif
+
+$(eval $(call NMF_RULE,$(TARGET),))
diff --git a/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh b/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh
new file mode 100755
index 0000000000..a327933390
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/src/bullet/build.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# 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.
+
+set -o nounset
+set -o errexit
+
+if [ -z "${NACL_SDK_ROOT:-}" ]; then
+ echo "-------------------------------------------------------------------"
+ echo "NACL_SDK_ROOT is unset."
+ echo "This environment variable needs to be pointed at some version of"
+ echo "the Native Client SDK (the directory containing toolchain/)."
+ echo "NOTE: set this to an absolute path."
+ echo "-------------------------------------------------------------------"
+ exit -1
+fi
+
+Banner() {
+ echo "######################################################################"
+ echo $*
+ echo "######################################################################"
+}
+
+# echo a command to stdout and then execute it.
+LogExecute() {
+ echo $*
+ $*
+}
+
+Clone() {
+ local url=$1
+ local dir=$2
+ if [ ! -d $dir ]; then
+ LogExecute git clone $url $dir
+ else
+ pushd $dir
+ LogExecute git pull origin master
+ popd
+ fi
+}
+
+readonly OS_NAME=$(uname -s)
+if [ $OS_NAME = "Darwin" ]; then
+ OS_JOBS=4
+elif [ $OS_NAME = "Linux" ]; then
+ OS_JOBS=`nproc`
+else
+ OS_JOBS=1
+fi
+
+NACLPORTS_URL=https://chromium.googlesource.com/external/naclports
+NACLPORTS_DIR=naclports
+NACLAM_URL=https://github.com/johnmccutchan/NaClAMBase
+NACLAM_DIR=NaClAMBase
+
+Banner Cloning naclports
+Clone ${NACLPORTS_URL} ${NACLPORTS_DIR}
+
+Banner Building bullet
+pushd ${NACLPORTS_DIR}
+make NACL_ARCH=pnacl bullet
+popd
+
+Banner Cloning NaClAMBase
+Clone ${NACLAM_URL} ${NACLAM_DIR}
+
+Banner Building NaClAM
+LogExecute cp Makefile ${NACLAM_DIR}
+pushd ${NACLAM_DIR}
+LogExecute make -j${OS_JOBS}
+popd
+
+LogExecute cp ${NACLAM_DIR}/pnacl/Release/NaClAMBullet.{pexe,nmf} .
+
+Banner Done!
diff --git a/native_client_sdk/src/gonacl_appengine/src/Makefile b/native_client_sdk/src/gonacl_appengine/src/earth/Makefile
index 9be4476206..9be4476206 100644
--- a/native_client_sdk/src/gonacl_appengine/src/Makefile
+++ b/native_client_sdk/src/gonacl_appengine/src/earth/Makefile
diff --git a/native_client_sdk/src/gonacl_appengine/src/earth.cc b/native_client_sdk/src/gonacl_appengine/src/earth/earth.cc
index 1e6f473164..10ff53e52b 100644
--- a/native_client_sdk/src/gonacl_appengine/src/earth.cc
+++ b/native_client_sdk/src/gonacl_appengine/src/earth/earth.cc
@@ -186,7 +186,7 @@ class Planet : public pp::Instance {
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
- virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip);
+ virtual void DidChangeView(const pp::View& view);
// Catch events.
virtual bool HandleInputEvent(const pp::InputEvent& event);
@@ -294,6 +294,8 @@ class Planet : public pp::Instance {
ThreadPool* workers_;
int width_;
int height_;
+ bool hidden_;
+ PP_Point last_mouse_pos_;
uint32_t stride_in_pixels_;
uint32_t* pixel_buffer_;
int benchmark_frame_counter_;
@@ -386,6 +388,7 @@ Planet::Planet(PP_Instance instance) : pp::Instance(instance),
num_regions_(256) {
width_ = 0;
height_ = 0;
+ hidden_ = false;
stride_in_pixels_ = 0;
pixel_buffer_ = NULL;
benchmark_frame_counter_ = 0;
@@ -393,6 +396,7 @@ Planet::Planet(PP_Instance instance) : pp::Instance(instance),
base_tex_ = NULL;
night_tex_ = NULL;
name_for_tex_ = "";
+ last_mouse_pos_ = PP_MakePoint(0, 0);
Reset();
@@ -674,7 +678,10 @@ void Planet::UpdateSim() {
SetPlanetSpin(x, y);
}
-void Planet::DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
+void Planet::DidChangeView(const pp::View& view) {
+ pp::Rect position = view.GetRect();
+ // Update hidden_ state
+ hidden_ = !view.IsVisible();
if (position.size().width() == width_ &&
position.size().height() == height_)
return; // Size didn't change, no need to update anything.
@@ -743,17 +750,24 @@ bool Planet::HandleInputEvent(const pp::InputEvent& event) {
StartBenchmark();
break;
}
- case PP_INPUTEVENT_TYPE_MOUSEMOVE:
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
pp::MouseInputEvent mouse = pp::MouseInputEvent(event);
+ last_mouse_pos_ = mouse.GetPosition();
+ ui_spin_x_ = 0.0f;
+ ui_spin_y_ = 0.0f;
+ break;
+ }
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
+ pp::MouseInputEvent mouse = pp::MouseInputEvent(event);
if (mouse.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) {
- PP_Point delta = mouse.GetMovement();
- float delta_x = static_cast<float>(delta.x);
- float delta_y = static_cast<float>(delta.y);
- float spin_x = std::min(4.0f, std::max(-4.0f, delta_x * 0.5f));
- float spin_y = std::min(4.0f, std::max(-4.0f, delta_y * 0.5f));
+ PP_Point mouse_pos = mouse.GetPosition();
+ float delta_x = static_cast<float>(mouse_pos.x - last_mouse_pos_.x);
+ float delta_y = static_cast<float>(mouse_pos.y - last_mouse_pos_.y);
+ float spin_x = std::min(10.0f, std::max(-10.0f, delta_x * 0.5f));
+ float spin_y = std::min(10.0f, std::max(-10.0f, delta_y * 0.5f));
ui_spin_x_ = spin_x / 100.0f;
ui_spin_y_ = spin_y / 100.0f;
+ last_mouse_pos_ = mouse_pos;
}
break;
}
@@ -821,6 +835,13 @@ void Planet::FlushPixelBuffer() {
}
void Planet::Update() {
+ // If view is hidden, don't render, but periodically (every 33ms) chain w/
+ // CallOnMainThread().
+ if (hidden_) {
+ pp::Module::Get()->core()->CallOnMainThread(33,
+ pp::CompletionCallback(&FlushCallback, this));
+ return;
+ }
// Don't call FlushPixelBuffer() when benchmarking - vsync is enabled by
// default, and will throttle the benchmark results.
do {
diff --git a/native_client_sdk/src/gonacl_appengine/static/common.css b/native_client_sdk/src/gonacl_appengine/static/common.css
new file mode 100644
index 0000000000..e64fd0df25
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/common.css
@@ -0,0 +1,97 @@
+/* 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. */
+
+body {
+ /* from http://css-tricks.com/snippets/css/better-helvetica/ */
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
+ "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+ font-weight: 300;
+ overflow: hidden;
+}
+.absolute-fill-parent {
+ position: relative;
+}
+.absolute-fill {
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+.flex-container {
+ margin: 0;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ width: 100%;
+ height: 100%;
+}
+.main {
+ background-color: #000;
+ -moz-box-flex: 1;
+ -ms-flex: 1;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ flex: 1;
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+.flex-column {
+ -moz-box-orient: vertical;
+ -ms-flex-direction: column;
+ -webkit-box-orient: vertical;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+}
+.flex-justify-center {
+ -moz-box-pack: center;
+ -ms-flex-pack: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+}
+#message {
+ text-align: center;
+ width: 100%;
+}
+#statusField {
+ display: none;
+ color: #fff;
+ font-size: 34px;
+ text-align: center;
+ width: 100%;
+}
+#progress {
+ display: none;
+ margin: auto;
+ width: 300px;
+}
+#nacl_module {
+ height: 100%;
+ width: 100%;
+}
+.sidebar {
+ padding: 0 8px;
+ overflow-y: auto;
+ width: 350px;
+}
+#config {
+ width: 100%;
+}
+#config .name {
+ font-weight: bold;
+ padding-right: 8px;
+ text-align: right;
+ white-space: nowrap;
+ width: 1px;
+}
+#threadCount, #lightRange, #zoomRange {
+ width: 100%;
+}
+.small {
+ font-size: 12px;
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAM.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAM.js
new file mode 100644
index 0000000000..ee59a5ea63
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAM.js
@@ -0,0 +1,224 @@
+// 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.
+
+function NaClAMMessage() {
+ this.header = {};
+ this.frames = new Array();
+}
+
+NaClAMMessage.prototype.reset = function() {
+ this.header = {};
+ this.frames = new Array();
+}
+
+function NaClAM(embedId) {
+ this.embedId = embedId;
+ this.requestId = 0;
+ this.message = new NaClAMMessage();
+ this.state = 0;
+ this.framesLeft = 0;
+ this.listeners_ = Object.create(null);
+ this.handleMesssage_ = this.handleMesssage_.bind(this);
+}
+
+NaClAM.prototype.enable = function() {
+ window.addEventListener('message', this.handleMesssage_, true);
+}
+
+NaClAM.prototype.disable = function() {
+ window.removeEventListener('message', this.handleMesssage_, true);
+}
+
+NaClAM.prototype.log_ = function(msg) {
+ console.log(msg);
+}
+
+NaClAM.prototype.handleMesssage_ = function(event) {
+ var STATE_WAITING_FOR_HEADER = 0;
+ var STATE_COLLECTING_FRAMES = 1;
+ if (this.state == STATE_WAITING_FOR_HEADER) {
+ var header;
+ try {
+ header = JSON.parse(String(event.data));
+ } catch (e) {
+ console.log(e);
+ console.log(event.data);
+ return;
+ }
+ // Special case our log print command
+ if (header['cmd'] == 'NaClAMPrint') {
+ this.log_(header['print'])
+ return;
+ }
+ if (typeof(header['request']) != "number") {
+ console.log('Header message requestId is not a number.');
+ return;
+ }
+ if (typeof(header['frames']) != "number") {
+ console.log('Header message frames is not a number.');
+ return;
+ }
+ this.framesLeft = header['frames'];
+ this.state = STATE_COLLECTING_FRAMES;
+ this.message.header = header;
+ } else if (this.state == STATE_COLLECTING_FRAMES) {
+ this.framesLeft--;
+ this.message.frames.push(event.data);
+ }
+ if (this.state == STATE_COLLECTING_FRAMES && this.framesLeft == 0) {
+ this.dispatchEvent(this.message);
+ this.message.reset();
+ this.state = STATE_WAITING_FOR_HEADER;
+ }
+}
+
+NaClAM.prototype.messageHeaderIsValid_ = function(header) {
+ if (header['cmd'] == undefined) {
+ console.log('NaClAM: Message header does not contain cmd.');
+ return false;
+ }
+ if (typeof(header['cmd']) != "string") {
+ console.log('NaClAm: Message cmd is not a string.');
+ return false;
+ }
+ if (header['frames'] == undefined) {
+ console.log('NaClAM: Message header does not contain frames.');
+ return false;
+ }
+ if (typeof(header['frames']) != "number") {
+ console.log('NaClAm: Message frames is not a number.');
+ return false;
+ }
+ if (header['request'] == undefined) {
+ console.log('NaClAM: Message header does not contain request.');
+ return false;
+ }
+ if (typeof(header['request']) != "number") {
+ console.log('NaClAm: Message request is not a number.');
+ return false;
+ }
+ return true;
+}
+
+NaClAM.prototype.framesIsValid_ = function(frames) {
+ var i;
+ if (!frames) {
+ // No frames.
+ return true;
+ }
+ if (Array.isArray(frames) == false) {
+ console.log('NaClAM: Frames must be an array.');
+ return false;
+ }
+ for (i = 0; i < frames.length; i++) {
+ var e = frames[i];
+ if (typeof(e) == "string") {
+ continue;
+ }
+ if ((e instanceof ArrayBuffer) == false) {
+ console.log('NaClAM: Frame is not a string or ArrayBuffer');
+ return false;
+ }
+ }
+ return true;
+}
+
+NaClAM.prototype.framesLength_ = function(frames) {
+ if (!frames) {
+ // No frames.
+ return 0;
+ }
+ return frames.length;
+}
+
+NaClAM.prototype.sendMessage = function(cmdName, arguments, frames) {
+ if (this.framesIsValid_(frames) == false) {
+ console.log('NaClAM: Not sending message because frames is invalid.');
+ return undefined;
+ }
+ var numFrames = this.framesLength_(frames);
+ this.requestId++;
+ var msgHeader = {
+ cmd: cmdName,
+ frames: numFrames,
+ request: this.requestId,
+ args: arguments
+ };
+ if (this.messageHeaderIsValid_(msgHeader) == false) {
+ console.log('NaClAM: Not sending message because header is invalid.');
+ return undefined;
+ }
+ var AM = document.getElementById(this.embedId);
+ if (!AM) {
+ console.log('NaClAM: Not sending message because Acceleration Module is not there.');
+ return undefined;
+ }
+ AM.postMessage(JSON.stringify(msgHeader));
+ var i;
+ for (i = 0; i < numFrames; i++) {
+ AM.postMessage(frames[i]);
+ }
+ return this.requestId;
+}
+
+/**
+ * Adds an event listener to this Acceleration Module.
+ * @param {string} type The name of the command.
+ * @param handler The handler for the cmomand. This is called whenever the command is received.
+ */
+NaClAM.prototype.addEventListener = function(type, handler) {
+ if (!this.listeners_) {
+ this.listeners_ = Object.create(null);
+ }
+ if (!(type in this.listeners_)) {
+ this.listeners_[type] = [handler];
+ } else {
+ var handlers = this.listeners_[type];
+ if (handlers.indexOf(handler) < 0) {
+ handlers.push(handler);
+ }
+ }
+}
+
+/**
+ * Removes an event listener from this Acceleration Module.
+ * @param {string} type The name of the command.
+ * @param handler The handler for the cmomand. This is called whenever the command is received.
+ */
+NaClAM.prototype.removeEventListener = function(type, handler) {
+ if (!this.listeners_) {
+ // No listeners
+ return;
+ }
+ if (type in this.listeners_) {
+ var handlers = this.listeners_[type];
+ var index = handlers.indexOf(handler);
+ if (index >= 0) {
+ if (handlers.length == 1) {
+ // Listeners list would be empty, delete it
+ delete this.listeners_[type];
+ } else {
+ // Remove the handler
+ handlers.splice(index, 1);
+ }
+ }
+ }
+}
+
+/**
+ *
+ */
+NaClAM.prototype.dispatchEvent = function(event) {
+ if (!this.listeners_) {
+ return true;
+ }
+ var type = event.header.cmd;
+ if (type in this.listeners_) {
+ // Make a copy to walk over
+ var handlers = this.listeners_[type].concat();
+ for (var i = 0, handler; handler = handlers[i]; i++) {
+ handler.call(this, event);
+ }
+ }
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAMBullet.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAMBullet.js
new file mode 100644
index 0000000000..7169f5cad3
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/NaClAMBullet.js
@@ -0,0 +1,48 @@
+// 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.
+
+function NaClAMBulletInit() {
+ aM.addEventListener('sceneloaded', NaClAMBulletSceneLoadedHandler);
+ aM.addEventListener('noscene', NaClAMBulletStepSceneHandler);
+ aM.addEventListener('sceneupdate', NaClAMBulletStepSceneHandler);
+}
+
+function NaClAMBulletLoadScene(sceneDescription) {
+ aM.sendMessage('loadscene', sceneDescription);
+}
+
+function NaClAMBulletSceneLoadedHandler(msg) {
+ console.log('Scene loaded.');
+ console.log('Scene object count = ' + msg.header.sceneobjectcount);
+}
+
+function NaClAMBulletPickObject(objectTableIndex, cameraPos, hitPos) {
+ aM.sendMessage('pickobject', {index: objectTableIndex, cpos: [cameraPos.x, cameraPos.y, cameraPos.z], pos: [hitPos.x,hitPos.y,hitPos.z]});
+}
+
+function NaClAMBulletDropObject() {
+ aM.sendMessage('dropobject', {});
+}
+
+function NaClAMBulletStepSceneHandler(msg) {
+ // Step the scene
+ var i;
+ var j;
+ var numTransforms = 0;
+ if (msg.header.cmd == 'sceneupdate') {
+ if (skipSceneUpdates > 0) {
+ skipSceneUpdates--;
+ return;
+ }
+ var simTime = msg.header.simtime;
+ document.getElementById('simulationTime').textContent = simTime;
+ TransformBuffer = new Float32Array(msg.frames[0]);
+ numTransforms = TransformBuffer.length/16;
+ for (i = 0; i < numTransforms; i++) {
+ for (j = 0; j < 16; j++) {
+ objects[i].matrixWorld.elements[j] = TransformBuffer[i*16+j];
+ }
+ }
+ }
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/box.json b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/box.json
new file mode 100644
index 0000000000..85565ade3e
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/box.json
@@ -0,0 +1,238 @@
+{
+ "shapes": [
+ {
+ "name": "box",
+ "type": "cube",
+ "wx": 1,
+ "wy": 1,
+ "wz": 1
+ }
+ ],
+ "bodies": [
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 1.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 2.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 3.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 4.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 5.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 6.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 7.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 8.0,
+ "z": 1.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 9.0,
+ "z": 2.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 0.0,
+ "y": 10.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 1.5
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 2.0,
+ "y": 1.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 2.0,
+ "y": 2.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 2.0,
+ "y": 3.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 2.0,
+ "y": 4.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ },
+ {
+ "shape": "box",
+ "position": {
+ "x": 2.0,
+ "y": 5.0,
+ "z": 0.0
+ },
+ "rotation": {
+ "x": 0.0,
+ "y": 0.0,
+ "z": 0.0
+ },
+ "mass": 1.0,
+ "friction": 0.5
+ }
+ ]
+} \ No newline at end of file
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/index.html b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/index.html
new file mode 100644
index 0000000000..3ab6eab3ee
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/index.html
@@ -0,0 +1,88 @@
+<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>
+ <title>Bullet Physics</title>
+ <script type="text/javascript" src="NaClAM.js"></script>
+ <script type="text/javascript" src="NaClAMBullet.js"></script>
+ <script type="text/javascript" src="http://commondatastorage.googleapis.com/gonacl/pnacl-demo-bullet/three.min.js"></script>
+ <script type="text/javascript" src="scene.js"></script>
+ <script type="text/javascript" src="world.js"></script>
+ <script type="text/javascript" src="scenes.js"></script>
+ <link href="/static/common.css" rel="stylesheet" type="text/css">
+ <style>
+ .main {
+ background-color: #fff;
+ }
+ #curtain {
+ background-color: rgba(0, 0, 0, 1.0);
+ }
+ #curtain.lift {
+ -webkit-transition: background-color 1s;
+ background-color: rgba(0, 0, 0, 0);
+ pointer-events: none;
+ }
+ .no-pointer-events {
+ pointer-events: none;
+ }
+ button {
+ display: block;
+ }
+ </style>
+</head>
+<body>
+ <div class="absolute-fill">
+ <div class="flex-container">
+ <div class="main absolute-fill-parent">
+ <div id="rendererContainer" class="absolute-fill"></div>
+ <div id="curtain" class="absolute-fill"></div>
+ <div class="absolute-fill no-pointer-events">
+ <div class="flex-container flex-column flex-justify-center">
+ <div id="message">
+ <div id="statusField"></div>
+ <progress id="progress"></progress>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="sidebar">
+ <h1>Bullet Physics</h1>
+ <div id="config">
+ <button id="jenga10">Block Tower (10 blocks)</button>
+ <button id="jenga20">Block Tower (20 blocks)</button>
+ <button id="randomShapes">Random Shapes</button>
+ <button id="randomCube250">Random Cubes (250)</button>
+ <button id="randomCylinder500">Random Cylinders (500)</button>
+ <button id="randomCube1000">Random Cubes (1000)</button>
+ <button id="randomCube2000">Random Cubes (2000)</button>
+ <button id="reload">Reload Scene</button>
+ </div>
+ <ul>
+ <li>Hold "h" to pick up an object</li>
+ <li>Click and drag to rotate the camera</li>
+ <li>Use the mousewheel to zoom in/out</li>
+ </ul>
+ <p class="small">
+ More info about Bullet Physics can be found at <a
+ href="http://bulletphysics.org/">http://bulletphysics.org</a>.
+ </p>
+ <p class="small">
+ This demo was implemented by <a
+ href="http://www.johnmccutchan.com">John McCutchan</a>. Read his
+ blog post about Native Client acceleration modules <a
+ href="http://www.johnmccutchan.com/2012/10/bullet-native-client-acceleration-module.html">here</a>,
+ and see the source for this demo <a
+ href="https://github.com/johnmccutchan/NaClAMBase">here</a>.
+ </p>
+ <p class="small">
+ Simulation time: <span id="simulationTime">0</span>&mu;s.
+ </p>
+ </div>
+ </div>
+ </div>
+</body>
+<script type="text/javascript" src="main.js"></script>
+</html>
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/main.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/main.js
new file mode 100644
index 0000000000..b84c2acfc7
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/main.js
@@ -0,0 +1,82 @@
+// 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.
+
+aM = null;
+
+function moduleLoad() {
+ hideStatus();
+ init();
+ animate();
+ NaClAMBulletInit();
+ loadJenga20();
+
+ document.querySelector('#curtain').classList.add('lift');
+}
+
+function moduleLoadError() {
+ updateStatus('Load failed.');
+}
+
+function moduleLoadProgress(event) {
+ $('progress').style.display = 'block';
+
+ var loadPercent = 0.0;
+ var bar = document.getElementById('progress');
+ if (event.lengthComputable && event.total > 0) {
+ loadPercent = event.loaded / event.total * 100.0;
+ bar.value = loadPercent;
+ bar.max = 100;
+ } else {
+ // The total length is not yet known.
+ loadPercent = -1.0;
+ }
+}
+
+function moduleCrash(event) {
+ if (naclModule.exitStatus == -1) {
+ updateStatus('CRASHED');
+ } else {
+ updateStatus('EXITED [' + naclModule.exitStatus + ']');
+ }
+}
+
+function updateStatus(opt_message) {
+ document.querySelector('#curtain').classList.remove('lift');
+
+ var statusField = $('statusField');
+ if (statusField) {
+ statusField.style.display = 'block';
+ statusField.textContent = opt_message;
+ }
+}
+
+function hideStatus() {
+ $('statusField').style.display = 'none';
+ $('progress').style.display = 'none';
+}
+
+function pageDidLoad() {
+ updateStatus('Loading...');
+ console.log('started');
+
+ aM = new NaClAM('NaClAM');
+ aM.enable();
+
+ var embedWrap = document.createElement('div');
+ embedWrap.addEventListener('load', moduleLoad, true);
+ embedWrap.addEventListener('error', moduleLoadError, true);
+ embedWrap.addEventListener('progress', moduleLoadProgress, true);
+ embedWrap.addEventListener('crash', moduleCrash, true);
+ document.body.appendChild(embedWrap);
+
+ var embed = document.createElement('embed');
+ embed.setAttribute('id', 'NaClAM');
+ embed.setAttribute('width', '0');
+ embed.setAttribute('height', '0');
+ embed.setAttribute('type', 'application/x-pnacl');
+ embed.setAttribute('src', 'http://commondatastorage.googleapis.com/gonacl/pnacl-demo-bullet/NaClAMBullet.portable.nmf');
+ embedWrap.appendChild(embed);
+}
+
+window.addEventListener("load", pageDidLoad, false);
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js
new file mode 100644
index 0000000000..6740155dfa
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scene.js
@@ -0,0 +1,292 @@
+// 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.
+
+var container, stats;
+var camera, controls, scene, projector, renderer;
+var plane;
+var lastSceneDescription;
+var skipSceneUpdates = 0;
+var hold = false;
+var holdObjectIndex = -1;
+
+var mouse = new THREE.Vector2();
+var offset = new THREE.Vector3();
+var INTERSECTED, SELECTED;
+
+var sceneDescription = [];
+
+var shapes = {};
+var objects = [];
+
+function clearWorld() {
+ for (var i = 0; i < objects.length; i++) {
+ scene.remove(objects[i]);
+ }
+ objects = [];
+ shapes = {};
+ // Make sure we drop the object.
+ hold = false;
+ SELECTED = undefined;
+ NaClAMBulletDropObject();
+}
+
+function loadShape(shape) {
+ if (shapes[shape.name] != undefined) {
+ return shapes[shape.name];
+ }
+
+ if (shape.type == "cube") {
+ shapes[shape.name] = new THREE.CubeGeometry(shape['wx'], shape['wy'], shape['wz']);
+ return shapes[shape.name];
+ }
+
+ if (shape.type == "convex") {
+ var vertices = [];
+ for (var i = 0; i < shape['points'].length; i++) {
+ vertices.push(new THREE.Vector3(shape['points'][i][0], shape['points'][i][1], shape['points'][i][2]));
+ }
+ shapes[shape.name] = new THREE.ConvexGeometry(vertices);
+ return shapes[shape.name];
+ }
+
+ if (shape.type == "cylinder") {
+ shapes[shape.name] = new THREE.CylinderGeometry(shape['radius'], shape['radius'], shape['height'])
+ return shapes[shape.name];
+ }
+
+ if (shape.type == "sphere") {
+ shapes[shape.name] = new THREE.SphereGeometry(shape['radius']);
+ return shapes[shape.name];
+ }
+
+ return undefined;
+}
+
+function loadBody(body) {
+ var shape = shapes[body.shape];
+ if (shape == undefined) {
+ return shape;
+ }
+
+ var object = new THREE.Mesh( shape, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
+
+ object.material.ambient = object.material.color;
+
+ object.position.x = body.position.x;
+ object.position.y = body.position.y;
+ object.position.z = body.position.z;
+
+ object.rotation.x = body.rotation.x;
+ object.rotation.y = body.rotation.y;
+ object.rotation.z = body.rotation.z;
+
+ object.updateMatrixWorld(true);
+ var T = [object.matrixWorld.elements[0],
+ object.matrixWorld.elements[1],
+ object.matrixWorld.elements[2],
+ object.matrixWorld.elements[3],
+ object.matrixWorld.elements[4],
+ object.matrixWorld.elements[5],
+ object.matrixWorld.elements[6],
+ object.matrixWorld.elements[7],
+ object.matrixWorld.elements[8],
+ object.matrixWorld.elements[9],
+ object.matrixWorld.elements[10],
+ object.matrixWorld.elements[11],
+ object.matrixWorld.elements[12],
+ object.matrixWorld.elements[13],
+ object.matrixWorld.elements[14],
+ object.matrixWorld.elements[15]];
+ body.transform = T;
+
+ object.castShadow = false;
+ object.receiveShadow = false;
+ object.matrixAutoUpdate = false;
+ object.objectTableIndex = objects.length;
+ scene.add(object);
+ objects.push(object);
+
+ return object;
+}
+
+function loadWorld(worldDescription) {
+ clearWorld();
+ var i;
+ var shapes = worldDescription['shapes'];
+ var bodies = worldDescription['bodies'];
+ for (i = 0; i < shapes.length; i++) {
+ if (loadShape(shapes[i]) == undefined) {
+ console.log('Could not load shape ' + shapes[i].name);
+ }
+ }
+
+ for (i = 0; i < bodies.length; i++) {
+ if (loadBody(bodies[i]) == undefined) {
+ console.log('Could not make body.');
+ }
+ }
+
+ var r = verifyWorldDescription(worldDescription);
+ if (r == false) {
+ alert('Invalid scene description. See console.');
+ return;
+ }
+ skipSceneUpdates = 4;
+ NaClAMBulletLoadScene(worldDescription);
+ lastSceneDescription = worldDescription;
+}
+
+function reloadScene() {
+ if (lastSceneDescription)
+ loadWorld(lastSceneDescription);
+}
+
+function $(id) {
+ return document.getElementById(id);
+}
+
+function init() {
+ var rendererContainer = $('rendererContainer');
+ var rcW = rendererContainer.clientWidth;
+ var rcH = rendererContainer.clientHeight;
+
+ camera = new THREE.PerspectiveCamera(
+ 70,
+ rcW / rcH, 1, 10000);
+ camera.position.y = 20.0;
+ camera.position.z = 40;
+
+ scene = new THREE.Scene();
+
+ scene.add( new THREE.AmbientLight( 0x505050 ) );
+
+ var light = new THREE.SpotLight( 0xffffff, 1.5 );
+ light.position.set( 0, 500, 2000 );
+ light.castShadow = true;
+
+ light.shadowCameraNear = 200;
+ light.shadowCameraFar = camera.far;
+ light.shadowCameraFov = 50;
+
+ light.shadowBias = -0.00022;
+ light.shadowDarkness = 0.5;
+
+ light.shadowMapWidth = 2048;
+ light.shadowMapHeight = 2048;
+
+ scene.add( light );
+
+ plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200, 100, 100), new THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe: true } ) );
+ plane.rotation.x = Math.PI * 0.5;
+ plane.visible = true;
+ scene.add( plane );
+ projector = new THREE.Projector();
+
+ renderer = new THREE.WebGLRenderer( { antialias: true } );
+ renderer.sortObjects = false;
+ renderer.setSize( rcW, rcH );
+ lastRendererWidth = rcW;
+ lastRendererWidth = rcH;
+
+ renderer.shadowMapEnabled = true;
+ renderer.shadowMapSoft = true;
+
+ rendererContainer.appendChild(renderer.domElement);
+
+ controls = new THREE.OrbitControls (camera, rendererContainer);
+
+ var idFuncHash = {
+ jenga10: loadJenga10,
+ jenga20: loadJenga20,
+ randomShapes: loadRandomShapes,
+ randomCube250: load250RandomCubes,
+ randomCylinder500: load500RandomCylinders,
+ randomCube1000: load1000RandomCubes,
+ randomCube2000: load2000RandomCubes
+ };
+
+ for (var id in idFuncHash) {
+ var func = idFuncHash[id];
+ $(id).addEventListener('click', func, false);
+ }
+
+ $('reload').addEventListener('click', reloadScene, false);
+
+ renderer.domElement.addEventListener('mousemove', onDocumentMouseMove, false );
+ window.addEventListener('keydown', onDocumentKeyDown, false);
+ window.addEventListener('keyup', onDocumentKeyUp, false);
+
+ window.setInterval(pollForRendererResize, 10);
+}
+
+function pollForRendererResize() {
+ var rendererContainer = $('rendererContainer');
+ var w = rendererContainer.clientWidth;
+ var h = rendererContainer.clientHeight;
+ if (w == lastRendererWidth && h == lastRendererHeight)
+ return;
+
+ camera.aspect = w / h;
+ camera.updateProjectionMatrix();
+ renderer.setSize( w, h );
+ lastRendererWidth = w;
+ lastRendererHeight = h;
+}
+
+function onDocumentKeyDown(event) {
+ if (event.keyCode == 72 || event.keyCode == 104) {
+ if (SELECTED != undefined) {
+ return;
+ }
+ hold = true;
+ var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
+ projector.unprojectVector( vector, camera );
+ var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
+ var intersects = ray.intersectObjects( objects );
+ if (intersects.length > 0) {
+ if (intersects[0].object != plane) {
+ SELECTED = intersects[0].object;
+ //console.log(SELECTED.objectTableIndex);
+ NaClAMBulletPickObject(SELECTED.objectTableIndex, camera.position, intersects[0].point);
+ }
+ }
+ }
+}
+
+function onDocumentKeyUp(event) {
+ if (event.keyCode == 72 || event.keyCode == 104) {
+ hold = false;
+ SELECTED = undefined;
+ NaClAMBulletDropObject();
+ }
+}
+
+function onDocumentMouseMove( event ) {
+ event.preventDefault();
+
+ var rendererContainer = $('rendererContainer');
+ var w = rendererContainer.clientWidth;
+ var h = rendererContainer.clientHeight;
+
+ mouse.x = ( event.clientX / w ) * 2 - 1;
+ mouse.y = - ( event.clientY / h ) * 2 + 1;
+ var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
+ projector.unprojectVector( vector, camera );
+ offset.x = vector.x;
+ offset.y = vector.y;
+ offset.z = vector.z;
+}
+
+//
+
+function animate() {
+ window.requestAnimationFrame(animate);
+ aM.sendMessage('stepscene', {rayFrom: [camera.position.x, camera.position.y, camera.position.z], rayTo: [offset.x, offset.y, offset.z]});
+ render();
+}
+
+function render() {
+ controls.update();
+ renderer.render( scene, camera );
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scenes.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scenes.js
new file mode 100644
index 0000000000..75ff039e35
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/scenes.js
@@ -0,0 +1,232 @@
+// 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.
+
+function randomCubeScene(numObjects, zwidth) {
+ var worldDescription = {};
+ worldDescription.shapes = [];
+ worldDescription.shapes.push({
+ name: 'box',
+ type: 'cube',
+ wx: 1,
+ wy: 1,
+ wz: 1
+ });
+ worldDescription.bodies = [];
+ for ( var i = 0; i < numObjects; i ++ ) {
+ var body = {};
+ body.shape = 'box';
+ body.position = {};
+ body.position.x = Math.random() * 30 - 15;
+ body.position.y = Math.random() * 50 + 10;
+ body.position.z = Math.random() * zwidth - (zwidth/2);
+ body.rotation = {};
+ body.rotation.x = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.y = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.z = ( Math.random() * 360 ) * Math.PI / 180;
+ body.mass = 1.0;
+ body.friction = 0.8;
+ worldDescription.bodies.push(body);
+ }
+ return worldDescription;
+}
+
+function randomCylinderScene(numObjects, zwidth) {
+ var worldDescription = {};
+ worldDescription.shapes = [];
+ worldDescription.shapes.push({
+ name: 'box',
+ type: 'cylinder',
+ height: 1.0,
+ radius: 0.5
+ });
+ worldDescription.bodies = [];
+ for ( var i = 0; i < numObjects; i ++ ) {
+ var body = {};
+ body.shape = 'box';
+ body.position = {};
+ body.position.x = Math.random() * 30 - 15;
+ body.position.y = Math.random() * 50 + 10;
+ body.position.z = Math.random() * zwidth - (zwidth/2);
+ body.rotation = {};
+ body.rotation.x = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.y = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.z = ( Math.random() * 360 ) * Math.PI / 180;
+ body.mass = 1.0;
+ body.friction = 0.2;
+ worldDescription.bodies.push(body);
+ }
+ return worldDescription;
+}
+
+function jengaScene(height) {
+ var worldDescription = {};
+ worldDescription.shapes = [];
+ worldDescription.shapes.push({
+ name: 'boxX',
+ type: 'cube',
+ wx: 5,
+ wy: 1,
+ wz: 1
+ });
+ worldDescription.shapes.push({
+ name: 'boxZ',
+ type: 'cube',
+ wx: 1,
+ wy: 1,
+ wz: 5
+ });
+ worldDescription.bodies = [];
+ var baseHeight = 0.55;
+ for (var i = 0; i < height; i++) {
+ var y = i * 1.0 + baseHeight;
+ if (i % 2 == 0) {
+ for (var j = 0; j < 5; j++) {
+ var z = j * 1.0;
+ var x = 2.5;
+
+ var body = {};
+ body.shape = 'boxX';
+ body.position = {};
+ body.position.x = x;
+ body.position.y = y;
+ body.position.z = z;
+ body.rotation = {};
+ body.rotation.x = 0.0;
+ body.rotation.y = 0.0;
+ body.rotation.z = 0.0;
+ body.mass = 1.0;
+ body.friction = 0.5;
+ worldDescription.bodies.push(body);
+ }
+ } else {
+ for (var j = 0; j < 5; j++) {
+ var z = 2.5;
+ var x = j * 1.0;
+
+ var body = {};
+ body.shape = 'boxZ';
+ body.position = {};
+ body.position.x = x;
+ body.position.y = y;
+ body.position.z = z;
+ body.rotation = {};
+ body.rotation.x = 0.0;
+ body.rotation.y = 0.0;
+ body.rotation.z = 0.0;
+ body.mass = 1.0;
+ body.friction = 0.5;
+ worldDescription.bodies.push(body);
+ }
+ }
+ }
+ return worldDescription;
+}
+
+function randomShapeScene(numObjects) {
+ var worldDescription = {};
+ worldDescription.shapes = [];
+ worldDescription.shapes.push({
+ name: 'stick',
+ type: 'cube',
+ wx: 1,
+ wy: 1,
+ wz: 5
+ });
+ worldDescription.shapes.push({
+ name: 'tube',
+ type: 'cylinder',
+ radius: 1.0,
+ height: 2.0
+ });
+ worldDescription.shapes.push({
+ name: 'sphere',
+ type: 'sphere',
+ radius: 3.0
+ });
+ worldDescription.shapes.push({
+ name: 'tri',
+ type: 'convex',
+ points: [
+ [0.0, 0.0, 0.0],
+ [0.0, 1.0, 0.0],
+ [0.0, 0.0, 1.0],
+ [0.0, 0.0, 1.0],
+ [2.0, 5.0, 1.0],
+ [1.0, 1.0, 1.0]
+ ]
+ });
+
+ var numShapes = 4;
+ worldDescription.bodies = [];
+ for (var i = 0; i < numObjects; i++) {
+ var body = {};
+ if (i % numShapes == 0) {
+ body.shape = 'stick';
+ } else if (i % numShapes == 1) {
+ body.shape = 'tube';
+ } else if (i % numShapes == 2) {
+ body.shape = 'sphere';
+ } else if (i % numShapes == 3) {
+ body.shape = 'tri';
+ }
+ body.position = {};
+ body.position.x = Math.random() * 30 - 15;
+ body.position.y = Math.random() * 50 + 1;
+ body.position.z = Math.random() * 10 - 5;
+ body.rotation = {};
+ body.rotation.x = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.y = ( Math.random() * 360 ) * Math.PI / 180;
+ body.rotation.z = ( Math.random() * 360 ) * Math.PI / 180;
+ body.mass = 1.0;
+ body.friction = 0.4;
+ worldDescription.bodies.push(body);
+ }
+ return worldDescription;
+}
+
+function loadJenga10() {
+ loadWorld(jengaScene(10));
+}
+
+function loadJenga20() {
+ loadWorld(jengaScene(20));
+}
+
+function loadRandomShapes() {
+ loadWorld(randomShapeScene(100));
+}
+
+function load250RandomCubes() {
+ loadWorld(randomCubeScene(250, 10));
+}
+
+function load500RandomCylinders() {
+ loadWorld(randomCylinderScene(500, 15));
+}
+
+function load1000RandomCubes() {
+ loadWorld(randomCubeScene(1000, 20));
+}
+
+function load2000RandomCubes() {
+ loadWorld(randomCubeScene(2000, 20));
+}
+
+function loadTextScene(evt) {
+ var txt = evt.target.result;
+ if (txt == undefined) {
+ alert('Could not load file.');
+ return;
+ }
+ var sceneDescription;
+
+ try {
+ sceneDescription = JSON.parse(txt);
+ } catch(e) {
+ alert(e);
+ return;
+ }
+
+ loadWorld(sceneDescription);
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/world.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/world.js
new file mode 100644
index 0000000000..a07465efc5
--- /dev/null
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-bullet/world.js
@@ -0,0 +1,140 @@
+// 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.
+
+function verifyWorldDescription(description) {
+ var shapes = description['shapes'];
+ var bodies = description['bodies'];
+ //var constraints = description['constraints'];
+
+ var i;
+ var r;
+ for (i = 0; i < shapes.length; i++) {
+ r = verifyShapeDescription(shapes[i]);
+ if (r == false) {
+ return false;
+ }
+ }
+
+ for (i = 0; i < bodies.length; i++) {
+ r = verifyBodyDescription(bodies[i], shapes);
+ if (r == false) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function verifyShapeExists(name, shapes) {
+ var i;
+ for (i = 0; i < shapes.length; i++) {
+ if (shapes[i].name == name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function verifyBodyDescription(body, shapes) {
+ var shapeName = body['shape'];
+ var mass = body['mass'];
+ var friction = body['friction'];
+ var transform = body['transform'];
+ if (shapeName == undefined) {
+ console.log('Body needs a shapename.');
+ return false;
+ }
+ if (mass == undefined) {
+ console.log('Body needs a mass.');
+ return false;
+ }
+ if (friction == undefined) {
+ console.log('Body needs a friction.');
+ return false;
+ }
+ if (transform == undefined) {
+ console.log('Body needs a transform.');
+ return false;
+ }
+ if (transform[0] == undefined) {
+ console.log('Body needs a transform array.');
+ return false;
+ }
+ return verifyShapeExists(shapeName, shapes);
+}
+
+function verifyShapeDescription(shape) {
+ if (shape['name'] == undefined) {
+ console.log('Shape needs a name.');
+ return false;
+ }
+
+ var type = shape['type'];
+
+ if (type != "cube" &&
+ type != "sphere" &&
+ type != "cylinder" &&
+ type != "convex") {
+ console.log('Shape type - ' + type + ' not supported.');
+ return false;
+ }
+
+ if (type == "cube") {
+ return verifyCubeDescription(shape);
+ }
+
+ if (type == "sphere") {
+ return verifySphereDescription(shape);
+ }
+
+ if (type == "cylinder") {
+ return verifyCylinderDescription(shape);
+ }
+
+ if (type == "convex") {
+ return verifyConvexDescription(shape);
+ }
+
+ return false;
+}
+
+function verifyCubeDescription(shape) {
+ if (shape['wx'] == undefined) {
+ return false;
+ }
+ if (shape['wy'] == undefined) {
+ return false;
+ }
+ if (shape['wz'] == undefined) {
+ return false;
+ }
+ return true;
+}
+
+function verifySphereDescription(shape) {
+ if (shape['radius'] == undefined) {
+ return false;
+ }
+ return true;
+}
+
+function verifyCylinderDescription(shape) {
+ if (shape['radius'] == undefined) {
+ return false;
+ }
+ if (shape['height'] == undefined) {
+ return false;
+ }
+ return true;
+}
+
+function verifyConvexDescription(shape) {
+ if (shape['points'] == undefined) {
+ return false;
+ }
+ if (shape['points'][0] == undefined) {
+ return false;
+ }
+ return true;
+}
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo/example.js b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/example.js
index fac8405faa..fac8405faa 100644
--- a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo/example.js
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/example.js
diff --git a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo/index.html b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/index.html
index ad6922e8af..bb01c1d8fb 100644
--- a/native_client_sdk/src/gonacl_appengine/static/pnacl-demo/index.html
+++ b/native_client_sdk/src/gonacl_appengine/static/pnacl-demo-earth/index.html
@@ -6,106 +6,10 @@ 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">
<meta charset="UTF-8">
<title>Multi-Threaded Raycasted Earth</title>
<script type="text/javascript" src="example.js"></script>
- <style>
- body {
- /* from http://css-tricks.com/snippets/css/better-helvetica/ */
- font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
- "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
- font-weight: 300;
- overflow: hidden;
- }
- .absolute-fill-parent {
- position: relative;
- }
- .absolute-fill {
- bottom: 0;
- left: 0;
- position: absolute;
- right: 0;
- top: 0;
- }
- .flex-container {
- margin: 0;
- display: -moz-box;
- display: -ms-flexbox;
- display: -webkit-box;
- display: -webkit-flex;
- display: flex;
- width: 100%;
- height: 100%;
- }
- .main {
- background-color: #000;
- -moz-box-flex: 1;
- -ms-flex: 1;
- -webkit-box-flex: 1;
- -webkit-flex: 1;
- flex: 1;
- position: relative;
- width: 100%;
- height: 100%;
- }
- .flex-column {
- -moz-box-orient: vertical;
- -ms-flex-direction: column;
- -webkit-box-orient: vertical;
- -webkit-flex-direction: column;
- flex-direction: column;
- }
- .flex-justify-center {
- -moz-box-pack: center;
- -ms-flex-pack: center;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- justify-content: center;
- }
- #message {
- text-align: center;
- width: 100%;
- }
- #statusField {
- display: none;
- color: #fff;
- font-size: 34px;
- text-align: center;
- width: 100%;
- }
- #progress {
- display: none;
- margin: auto;
- width: 300px;
- }
- #nacl_module {
- height: 100%;
- width: 100%;
- }
- .sidebar {
- padding: 0 8px;
- overflow-y: auto;
- width: 350px;
- }
- #config {
- width: 100%;
- }
- #config .name {
- font-weight: bold;
- padding-right: 8px;
- text-align: right;
- white-space: nowrap;
- width: 1px;
- }
- #threadCount, #lightRange, #zoomRange {
- width: 100%;
- }
- .small {
- font-size: 12px;
- }
- </style>
+ <link href="/static/common.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="absolute-fill">
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
index 27a5ba4f0c..a357beabe6 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
@@ -27,10 +27,11 @@ class EventEmitterPipe : public EventEmitterStream {
size_t Read_Locked(char* data, size_t len);
size_t Write_Locked(const char* data, size_t len);
+ protected:
virtual FIFOChar* in_fifo() { return &fifo_; }
virtual FIFOChar* out_fifo() { return &fifo_; }
-private:
+ private:
FIFOChar fifo_;
DISALLOW_COPY_AND_ASSIGN(EventEmitterPipe);
};
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
index 600f234b18..5c636abbea 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
@@ -39,7 +39,12 @@ void EventEmitterStream::UpdateStatus_Locked() {
RaiseEvents_Locked(status);
}
+uint32_t EventEmitterStream::BytesInOutputFIFO() {
+ return out_fifo()->ReadAvailable();
+}
-} // namespace nacl_io
-
+uint32_t EventEmitterStream::SpaceInInputFIFO() {
+ return in_fifo()->WriteAvailable();
+}
+} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
index 34afec273d..1b40b01e94 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
@@ -26,10 +26,13 @@ class EventEmitterStream : public EventEmitter {
void DetachStream();
MountNodeStream* stream() { return stream_; }
- virtual FIFOInterface* in_fifo() = 0;
- virtual FIFOInterface* out_fifo() = 0;
+
+ uint32_t BytesInOutputFIFO();
+ uint32_t SpaceInInputFIFO();
protected:
+ virtual FIFOInterface* in_fifo() = 0;
+ virtual FIFOInterface* out_fifo() = 0;
void UpdateStatus_Locked();
protected:
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
index 24d7cdd4ee..8e1125837b 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
@@ -16,7 +16,6 @@ namespace nacl_io {
EventEmitterTCP::EventEmitterTCP(size_t rsize, size_t wsize)
: in_fifo_(std::max<size_t>(65536, rsize)),
out_fifo_(std::max<size_t>(65536, wsize)) {
- UpdateStatus_Locked();
}
uint32_t EventEmitterTCP::ReadIn_Locked(char* data, uint32_t len) {
@@ -47,7 +46,21 @@ uint32_t EventEmitterTCP::WriteOut_Locked(const char* data, uint32_t len) {
return count;
}
+void EventEmitterTCP::ConnectDone_Locked() {
+ RaiseEvents_Locked(POLLOUT);
+ UpdateStatus_Locked();
+}
-} // namespace nacl_io
+void EventEmitterTCP::SetAcceptedSocket_Locked(PP_Resource socket) {
+ accepted_socket_ = socket;
+ RaiseEvents_Locked(POLLIN);
+}
+PP_Resource EventEmitterTCP::GetAcceptedSocket_Locked() {
+ int rtn = accepted_socket_;
+ accepted_socket_ = 0;
+ ClearEvents_Locked(POLLIN);
+ return rtn;
+}
+} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
index 99a559aeb6..2b40e29a84 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
@@ -8,12 +8,17 @@
#include "nacl_io/event_emitter_stream.h"
#include "nacl_io/fifo_char.h"
+#include <ppapi/c/pp_resource.h>
+
#include "sdk_util/macros.h"
#include "sdk_util/scoped_ref.h"
+
namespace nacl_io {
class EventEmitterTCP;
+class MountNode;
+
typedef sdk_util::ScopedRef<EventEmitterTCP> ScopedEventEmitterTCP;
class EventEmitterTCP : public EventEmitterStream {
@@ -26,12 +31,18 @@ class EventEmitterTCP : public EventEmitterStream {
uint32_t ReadOut_Locked(char* buffer, uint32_t len);
uint32_t WriteOut_Locked(const char* buffer, uint32_t len);
+ void ConnectDone_Locked();
+ PP_Resource GetAcceptedSocket_Locked();
+ void SetAcceptedSocket_Locked(PP_Resource socket);
+
+ protected:
virtual FIFOChar* in_fifo() { return &in_fifo_; }
virtual FIFOChar* out_fifo() { return &out_fifo_; }
-protected:
+ private:
FIFOChar in_fifo_;
FIFOChar out_fifo_;
+ PP_Resource accepted_socket_;
DISALLOW_COPY_AND_ASSIGN(EventEmitterTCP);
};
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
index c0ef09c008..d3fbd89571 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
@@ -28,6 +28,7 @@ class EventEmitterTTY : public EventEmitterStream {
size_t Read_Locked(char* data, size_t len);
size_t Write_Locked(const char* data, size_t len);
+ protected:
virtual FIFOChar* in_fifo() { return &fifo_; }
virtual FIFONull* out_fifo() { return &null_; }
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
index 02d64a4e90..cb64fbc73f 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
@@ -27,10 +27,11 @@ class EventEmitterUDP : public EventEmitterStream {
Packet* ReadTXPacket_Locked();
void WriteTXPacket_Locked(Packet* packet);
+protected:
virtual FIFOPacket* in_fifo() { return &in_fifo_; }
virtual FIFOPacket* out_fifo() { return &out_fifo_; }
-protected:
+private:
FIFOPacket in_fifo_;
FIFOPacket out_fifo_;
DISALLOW_COPY_AND_ASSIGN(EventEmitterUDP);
diff --git a/native_client_sdk/src/libraries/nacl_io/event_listener.cc b/native_client_sdk/src/libraries/nacl_io/event_listener.cc
index ce679f8030..8ad13bd5b3 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_listener.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_listener.cc
@@ -53,7 +53,7 @@ EventListenerLock::~EventListenerLock() {
}
void EventListenerLock::ReceiveEvents(EventEmitter* emitter,
- uint32_t events) {
+ uint32_t events) {
// We are using the emitter's mutex, which is already locked.
pthread_cond_signal(&signal_cond_);
}
@@ -67,8 +67,8 @@ Error EventListenerLock::WaitOnEvent(uint32_t events, int ms_timeout) {
int return_code;
if (ms_timeout >= 0) {
return_code = pthread_cond_timedwait(&signal_cond_,
- emitter_->GetLock().mutex(),
- &timeout);
+ emitter_->GetLock().mutex(),
+ &timeout);
} else {
return_code = pthread_cond_wait(&signal_cond_,
emitter_->GetLock().mutex());
@@ -89,7 +89,7 @@ Error EventListenerLock::WaitOnEvent(uint32_t events, int ms_timeout) {
}
void EventListenerPoll::ReceiveEvents(EventEmitter* emitter,
- uint32_t events) {
+ uint32_t events) {
AUTO_LOCK(signal_lock_);
emitters_[emitter]->events |= events;
signaled_++;
@@ -97,8 +97,8 @@ void EventListenerPoll::ReceiveEvents(EventEmitter* emitter,
}
Error EventListenerPoll::WaitOnAny(EventRequest* requests,
- size_t cnt,
- int ms_timeout) {
+ size_t cnt,
+ int ms_timeout) {
signaled_ = 0;
@@ -114,8 +114,8 @@ Error EventListenerPoll::WaitOnAny(EventRequest* requests,
// responsible for it's own request.
for (size_t index = 0; index < cnt; index++) {
EventRequest* request = requests + index;
- requests->emitter->RegisterListener(this, request->filter);
- uint32_t events = requests->emitter->GetEventStatus() & request->filter;
+ request->emitter->RegisterListener(this, request->filter);
+ uint32_t events = request->emitter->GetEventStatus() & request->filter;
if (events) {
AUTO_LOCK(signal_lock_);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
index 37d3fa43b7..eab3ce81dc 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
@@ -5,11 +5,11 @@
#include "nacl_io/kernel_handle.h"
#include <errno.h>
-#include <fcntl.h>
#include <pthread.h>
#include "nacl_io/mount.h"
#include "nacl_io/mount_node.h"
+#include "nacl_io/mount_node_socket.h"
#include "nacl_io/osunistd.h"
#include "sdk_util/auto_lock.h"
@@ -18,10 +18,10 @@ namespace nacl_io {
// It is only legal to construct a handle while the kernel lock is held.
KernelHandle::KernelHandle()
- : mount_(NULL), node_(NULL), offs_(0) {}
+ : mount_(NULL), node_(NULL) {}
KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node)
- : mount_(mnt), node_(node), offs_(0) {}
+ : mount_(mnt), node_(node) {}
KernelHandle::~KernelHandle() {
// Force release order for cases where mount_ is not ref'd by mounting.
@@ -30,15 +30,17 @@ KernelHandle::~KernelHandle() {
}
// Returns the MountNodeSocket* if this node is a socket.
-MountNodeSocket* KernelHandle::socket_node() {
+MountNodeSocket* KernelHandle::socket_node() {
if (node_.get() && node_->IsaSock())
return reinterpret_cast<MountNodeSocket*>(node_.get());
return NULL;
}
-Error KernelHandle::Init(int open_mode) {
- if (open_mode & O_APPEND) {
- Error error = node_->GetSize(&offs_);
+Error KernelHandle::Init(int open_flags) {
+ handle_attr_.flags = open_flags;
+
+ if (open_flags & O_APPEND) {
+ Error error = node_->GetSize(&handle_attr_.offs);
if (error)
return error;
}
@@ -52,7 +54,7 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
size_t base;
size_t node_size;
- AUTO_LOCK(offs_lock_);
+ AUTO_LOCK(handle_lock_);
Error error = node_->GetSize(&node_size);
if (error)
return error;
@@ -64,7 +66,7 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
base = 0;
break;
case SEEK_CUR:
- base = offs_;
+ base = handle_attr_.offs;
break;
case SEEK_END:
base = node_size;
@@ -84,32 +86,134 @@ Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
return EINVAL;
}
- *out_offset = offs_ = new_offset;
+ *out_offset = handle_attr_.offs = new_offset;
return 0;
}
Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
- AUTO_LOCK(offs_lock_);
- Error error = node_->Read(offs_, buf, nbytes, cnt);
+ AUTO_LOCK(handle_lock_);
+ Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
if (0 == error)
- offs_ += *cnt;
+ handle_attr_.offs += *cnt;
return error;
}
Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
- AUTO_LOCK(offs_lock_);
- Error error = node_->Write(offs_, buf, nbytes, cnt);
+ AUTO_LOCK(handle_lock_);
+ Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
if (0 == error)
- offs_ += *cnt;
+ handle_attr_.offs += *cnt;
return error;
}
Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
- AUTO_LOCK(offs_lock_);
- Error error = node_->GetDents(offs_, pdir, nbytes, cnt);
+ AUTO_LOCK(handle_lock_);
+ Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
if (0 == error)
- offs_ += *cnt;
+ handle_attr_.offs += *cnt;
return error;
}
+Error KernelHandle::Fcntl(int request, int* result, ...) {
+ va_list ap;
+ va_start(ap, result);
+ Error rtn = VFcntl(request, result, ap);
+ va_end(ap);
+ return rtn;
+}
+
+Error KernelHandle::VFcntl(int request, int* result, va_list args) {
+ switch (request) {
+ case F_GETFL: {
+ *result = handle_attr_.flags;
+ return 0;
+ }
+ case F_SETFL: {
+ AUTO_LOCK(handle_lock_);
+ int flags = va_arg(args, int);
+ if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
+ // Attempt to clear O_APPEND.
+ return EPERM;
+ }
+ // Only certain flags are mutable
+ const int mutable_flags = O_ASYNC | O_NONBLOCK;
+ flags &= mutable_flags;
+ handle_attr_.flags &= ~mutable_flags;
+ handle_attr_.flags |= flags;
+ return 0;
+ }
+ }
+ return ENOSYS;
+}
+
+Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr,
+ socklen_t* len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->Accept(handle_attr_, new_sock, addr, len);
+}
+
+Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->Connect(handle_attr_, addr, len);
+}
+
+Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->Recv(handle_attr_, buf, len, flags, out_len);
+}
+
+Error KernelHandle::RecvFrom(void* buf,
+ size_t len,
+ int flags,
+ struct sockaddr* src_addr,
+ socklen_t* addrlen,
+ int* out_len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
+ out_len);
+}
+
+Error KernelHandle::Send(const void* buf,
+ size_t len,
+ int flags,
+ int* out_len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->Send(handle_attr_, buf, len, flags, out_len);
+}
+
+Error KernelHandle::SendTo(const void* buf,
+ size_t len,
+ int flags,
+ const struct sockaddr* dest_addr,
+ socklen_t addrlen,
+ int* out_len) {
+ MountNodeSocket* sock = socket_node();
+ if (!sock)
+ return ENOTSOCK;
+
+ AUTO_LOCK(handle_lock_);
+ return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
+ out_len);
+}
+
} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
index fd76ddecfc..a4609c3606 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
@@ -5,11 +5,14 @@
#ifndef LIBRARIES_NACL_IO_KERNEL_HANDLE_H_
#define LIBRARIES_NACL_IO_KERNEL_HANDLE_H_
+#include <fcntl.h>
#include <pthread.h>
+#include <ppapi/c/pp_resource.h>
#include "nacl_io/error.h"
#include "nacl_io/mount.h"
#include "nacl_io/mount_node.h"
+#include "nacl_io/ossocket.h"
#include "nacl_io/ostypes.h"
#include "sdk_util/macros.h"
@@ -19,40 +22,68 @@
namespace nacl_io {
-class MountNode;
class MountNodeSocket;
+// HandleAttr struct is passed the MountNode in calls
+// to Read and Write. It contains handle specific state
+// such as the file offset and the open flags.
+struct HandleAttr {
+ HandleAttr() : offs(0), flags(0) {}
+ bool IsBlocking() const { return !(flags & O_NONBLOCK); }
+
+ size_t offs;
+ int flags;
+};
+
// KernelHandle provides a reference counted container for the open
// file information, such as it's mount, node, access type and offset.
// KernelHandle can only be referenced when the KernelProxy lock is held.
class KernelHandle : public sdk_util::RefObject {
public:
+
KernelHandle();
KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node);
~KernelHandle();
Error Init(int open_flags);
+ Error Accept(PP_Resource* new_sock, struct sockaddr* addr, socklen_t* len);
+ Error Connect(const struct sockaddr* addr, socklen_t len);
+ Error Fcntl(int request, int* result, ...);
+ Error VFcntl(int request, int* result, va_list args);
+ Error GetDents(struct dirent* pdir, size_t count, int* bytes_written);
+ Error Read(void* buf, size_t nbytes, int* bytes_read);
+ Error Recv(void* buf, size_t len, int flags, int* out_len);
+ Error RecvFrom(void* buf,
+ size_t len,
+ int flags,
+ struct sockaddr* src_addr,
+ socklen_t* addrlen,
+ int* out_len);
// Assumes |out_offset| is non-NULL.
Error Seek(off_t offset, int whence, off_t* out_offset);
-
- // Dispatches Read, Write, GetDents to atomically update offs_.
- Error Read(void* buf, size_t nbytes, int* bytes_read);
+ Error Send(const void* buf, size_t len, int flags, int* out_len);
+ Error SendTo(const void* buf,
+ size_t len,
+ int flags,
+ const struct sockaddr* dest_addr,
+ socklen_t addrlen,
+ int* out_len);
Error Write(const void* buf, size_t nbytes, int* bytes_written);
- Error GetDents(struct dirent* pdir, size_t count, int* bytes_written);
const ScopedMountNode& node() { return node_; }
const ScopedMount& mount() { return mount_; }
+ const HandleAttr& Attr() { return handle_attr_; }
+private:
// Returns the MountNodeSocket* if this node is a socket otherwise returns
// NULL.
MountNodeSocket* socket_node();
-private:
ScopedMount mount_;
ScopedMountNode node_;
- sdk_util::SimpleLock offs_lock_;
- size_t offs_;
+ sdk_util::SimpleLock handle_lock_;
+ HandleAttr handle_attr_;
friend class KernelProxy;
DISALLOW_COPY_AND_ASSIGN(KernelHandle);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
index 373b93a9dc..4083d4f110 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -100,6 +100,11 @@ int ki_chmod(const char *path, mode_t mode) {
return s_kp->chmod(path, mode);
}
+int ki_fchmod(int fd, mode_t mode) {
+ ON_NOSYS_RETURN(-1);
+ return s_kp->fchmod(fd, mode);
+}
+
int ki_stat(const char *path, struct stat *buf) {
ON_NOSYS_RETURN(-1);
return s_kp->stat(path, buf);
@@ -221,14 +226,14 @@ int ki_open_resource(const char* file) {
ON_NOSYS_RETURN(-1); return s_kp->open_resource(file);
}
-int ki_fcntl(int d, int request, char* argp) {
+int ki_fcntl(int d, int request, va_list args) {
ON_NOSYS_RETURN(-1);
- return s_kp->fcntl(d, request, argp);
+ return s_kp->fcntl(d, request, args);
}
-int ki_ioctl(int d, int request, char* argp) {
+int ki_ioctl(int d, int request, va_list args) {
ON_NOSYS_RETURN(-1);
- return s_kp->ioctl(d, request, argp);
+ return s_kp->ioctl(d, request, args);
}
int ki_chown(const char* path, uid_t owner, gid_t group) {
@@ -316,6 +321,7 @@ int ki_getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
return s_kp->getsockname(fd, addr, len);
}
+
int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
return s_kp->getsockopt(fd, lvl, optname, optval, len);
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
index f8ebeedb80..3fbb87a4ba 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -5,6 +5,8 @@
#ifndef LIBRARIES_NACL_IO_KERNEL_INTERCEPT_H_
#define LIBRARIES_NACL_IO_KERNEL_INTERCEPT_H_
+#include <stdarg.h>
+
#include <ppapi/c/ppb.h>
#include <ppapi/c/pp_instance.h>
@@ -37,6 +39,7 @@ char* ki_getwd(char* buf);
int ki_dup(int oldfd);
int ki_dup2(int oldfd, int newfd);
int ki_chmod(const char* path, mode_t mode);
+int ki_fchmod(int fd, mode_t mode);
int ki_stat(const char* path, struct stat* buf);
int ki_mkdir(const char* path, mode_t mode);
int ki_rmdir(const char* path);
@@ -63,8 +66,8 @@ void* ki_mmap(void* addr, size_t length, int prot, int flags, int fd,
off_t offset);
int ki_munmap(void* addr, size_t length);
int ki_open_resource(const char* file);
-int ki_fcntl(int d, int request, char* argp);
-int ki_ioctl(int d, int request, char* argp);
+int ki_fcntl(int d, int request, va_list args);
+int ki_ioctl(int d, int request, va_list args);
int ki_chown(const char* path, uid_t owner, gid_t group);
int ki_fchown(int fd, uid_t owner, gid_t group);
int ki_lchown(const char* path, uid_t owner, gid_t group);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 82a3ec1837..fd5f6b506a 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -4,7 +4,6 @@
#include "nacl_io/kernel_proxy.h"
-
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -155,18 +154,18 @@ int KernelProxy::open_resource(const char* path) {
return AllocateFD(handle);
}
-int KernelProxy::open(const char* path, int oflags) {
+int KernelProxy::open(const char* path, int open_flags) {
ScopedMount mnt;
ScopedMountNode node;
- Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
+ Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
if (error) {
errno = error;
return -1;
}
ScopedKernelHandle handle(new KernelHandle(mnt, node));
- error = handle->Init(oflags);
+ error = handle->Init(open_flags);
if (error) {
errno = error;
return -1;
@@ -539,7 +538,7 @@ int KernelProxy::isatty(int fd) {
return 0;
}
-int KernelProxy::ioctl(int fd, int request, char* argp) {
+int KernelProxy::ioctl(int fd, int request, va_list args) {
ScopedKernelHandle handle;
Error error = AcquireHandle(fd, &handle);
if (error) {
@@ -547,7 +546,7 @@ int KernelProxy::ioctl(int fd, int request, char* argp) {
return -1;
}
- error = handle->node()->Ioctl(request, argp);
+ error = handle->node()->VIoctl(request, args);
if (error) {
errno = error;
return -1;
@@ -624,7 +623,7 @@ int KernelProxy::fchmod(int fd, int mode) {
return 0;
}
-int KernelProxy::fcntl(int fd, int request, char *argp) {
+int KernelProxy::fcntl(int fd, int request, va_list args) {
ScopedKernelHandle handle;
Error error = AcquireHandle(fd, &handle);
if (error) {
@@ -632,9 +631,14 @@ int KernelProxy::fcntl(int fd, int request, char *argp) {
return -1;
}
- // TODO(sbc): Needs implementation.
- errno = ENOSYS;
- return -1;
+ int rtn = 0;
+ error = handle->VFcntl(request, &rtn, args);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ return rtn;
}
int KernelProxy::access(const char* path, int amode) {
@@ -1015,7 +1019,6 @@ int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
}
-
// Socket Functions
int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
if (NULL == addr || NULL == len) {
@@ -1024,11 +1027,33 @@ int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
- errno = EINVAL;
- return -1;
+ PP_Resource new_sock = 0;
+ error = handle->Accept(&new_sock, addr, len);
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+
+ MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
+
+ // The MountNodeSocket now holds a reference to the new socket
+ // so we release ours.
+ ppapi_->ReleaseResource(new_sock);
+ error = sock->Init(S_IREAD | S_IWRITE);
+ if (error != 0) {
+ errno = error;
+ return -1;
+ }
+
+ ScopedMountNode node(sock);
+ ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
+ return AllocateFD(new_handle);
}
int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
@@ -1057,12 +1082,15 @@ int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
- Error err = handle->socket_node()->Connect(addr, len);
- if (err != 0) {
- errno = err;
+ error = handle->Connect(addr, len);
+ if (error != 0) {
+ errno = error;
return -1;
}
@@ -1112,10 +1140,10 @@ int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
}
int KernelProxy::getsockopt(int fd,
- int lvl,
- int optname,
- void* optval,
- socklen_t* len) {
+ int lvl,
+ int optname,
+ void* optval,
+ socklen_t* len) {
if (NULL == optval || NULL == len) {
errno = EFAULT;
return -1;
@@ -1125,8 +1153,13 @@ int KernelProxy::getsockopt(int fd,
if (AcquireSocketHandle(fd, &handle) == -1)
return -1;
- errno = EINVAL;
- return -1;
+ Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
+ if (err != 0) {
+ errno = err;
+ return -1;
+ }
+
+ return 0;
}
int KernelProxy::listen(int fd, int backlog) {
@@ -1134,8 +1167,13 @@ int KernelProxy::listen(int fd, int backlog) {
if (AcquireSocketHandle(fd, &handle) == -1)
return -1;
- errno = EOPNOTSUPP;
- return -1;
+ Error err = handle->socket_node()->Listen(backlog);
+ if (err != 0) {
+ errno = err;
+ return -1;
+ }
+
+ return 0;
}
ssize_t KernelProxy::recv(int fd,
@@ -1148,13 +1186,16 @@ ssize_t KernelProxy::recv(int fd,
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
int out_len = 0;
- Error err = handle->socket_node()->Recv(buf, len, flags, &out_len);
- if (err != 0) {
- errno = err;
+ error = handle->Recv(buf, len, flags, &out_len);
+ if (error != 0) {
+ errno = error;
return -1;
}
@@ -1178,18 +1219,16 @@ ssize_t KernelProxy::recvfrom(int fd,
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
int out_len = 0;
- Error err = handle->socket_node()->RecvFrom(buf,
- len,
- flags,
- addr,
- addrlen,
- &out_len);
- if (err != 0) {
- errno = err;
+ error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
+ if (error != 0) {
+ errno = error;
return -1;
}
@@ -1217,13 +1256,16 @@ ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
int out_len = 0;
- Error err = handle->socket_node()->Send(buf, len, flags, &out_len);
- if (err != 0) {
- errno = err;
+ error = handle->Send(buf, len, flags, &out_len);
+ if (error != 0) {
+ errno = error;
return -1;
}
@@ -1247,15 +1289,16 @@ ssize_t KernelProxy::sendto(int fd,
}
ScopedKernelHandle handle;
- if (AcquireSocketHandle(fd, &handle) == -1)
+ Error error = AcquireHandle(fd, &handle);
+ if (error) {
+ errno = error;
return -1;
+ }
int out_len = 0;
- Error err =
- handle->socket_node()->SendTo(buf, len, flags, addr, addrlen, &out_len);
-
- if (err != 0) {
- errno = err;
+ error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
+ if (error != 0) {
+ errno = error;
return -1;
}
@@ -1290,8 +1333,13 @@ int KernelProxy::setsockopt(int fd,
if (AcquireSocketHandle(fd, &handle) == -1)
return -1;
- errno = EINVAL;
- return -1;
+ Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
+ if (err != 0) {
+ errno = err;
+ return -1;
+ }
+
+ return 0;
}
int KernelProxy::shutdown(int fd, int how) {
@@ -1330,13 +1378,14 @@ int KernelProxy::socket(int domain, int type, int protocol) {
}
ScopedMountNode node(sock);
- if (sock->Init(S_IREAD | S_IWRITE) == 0) {
- ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
- return AllocateFD(handle);
+ Error rtn = sock->Init(S_IREAD | S_IWRITE);
+ if (rtn != 0) {
+ errno = rtn;
+ return -1;
}
- // If we failed to init, assume we don't have access.
- return EACCES;
+ ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
+ return AllocateFD(handle);
}
int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index de175f8300..82768b7c01 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -55,7 +55,7 @@ class KernelProxy : protected KernelObject {
virtual int open_resource(const char* file);
// KernelHandle and FD allocation and manipulation functions.
- virtual int open(const char* path, int oflag);
+ virtual int open(const char* path, int open_flags);
virtual int close(int fd);
virtual int dup(int fd);
virtual int dup2(int fd, int newfd);
@@ -95,13 +95,13 @@ class KernelProxy : protected KernelObject {
virtual ssize_t write(int fd, const void *buf, size_t nbyte);
virtual int fchmod(int fd, int prot);
- virtual int fcntl(int fd, int request, char *argp);
+ virtual int fcntl(int fd, int request, va_list args);
virtual int fstat(int fd, struct stat *buf);
virtual int getdents(int fd, void *buf, unsigned int count);
virtual int ftruncate(int fd, off_t length);
virtual int fsync(int fd);
virtual int isatty(int fd);
- virtual int ioctl(int fd, int request, char *argp);
+ virtual int ioctl(int fd, int request, va_list args);
// lseek() relies on the mount's Stat() to determine whether or not the
// file handle corresponding to fd is a directory
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
index db77914096..8903775587 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
@@ -13,6 +13,7 @@
#include <dirent.h>
#include <errno.h>
#include <irt.h>
+#include <irt_dev.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -44,7 +45,7 @@ EXTERN_C_BEGIN
#define USE_WRAP(group, name) \
__libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \
-extern void __libnacl_irt_filename_init(void);
+extern void __libnacl_irt_dev_filename_init(void);
extern struct nacl_irt_fdio __libnacl_irt_fdio;
extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
@@ -139,7 +140,7 @@ int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
static void assign_real_pointers() {
static bool assigned = false;
if (!assigned) {
- __libnacl_irt_filename_init();
+ __libnacl_irt_dev_filename_init();
EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
assigned = true;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc
index 024592883d..4b74345383 100644
--- a/native_client_sdk/src/libraries/nacl_io/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -66,6 +66,7 @@
"syscalls/chmod.c",
"syscalls/chown.c",
"syscalls/connect.c",
+ "syscalls/fchmod.c",
"syscalls/fchown.c",
"syscalls/fcntl.c",
"syscalls/fdopen.c",
@@ -116,6 +117,7 @@
"syscalls/sigset.c",
"syscalls/socket.c",
"syscalls/socketpair.c",
+ "syscalls/symlink.c",
"syscalls/unlink.c",
"syscalls/umount.c",
"syscalls/uname.c",
diff --git a/native_client_sdk/src/libraries/nacl_io/mount.cc b/native_client_sdk/src/libraries/nacl_io/mount.cc
index ef5a70a959..92f977a403 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount.cc
@@ -39,9 +39,9 @@ Error Mount::OpenResource(const Path& path, ScopedMountNode* out_node) {
return EINVAL;
}
-int Mount::OpenModeToPermission(int mode) {
+int Mount::OpenFlagsToPermission(int open_flags) {
int out;
- switch (mode & 3) {
+ switch (open_flags & 3) {
case O_RDONLY:
out = S_IREAD;
case O_WRONLY:
diff --git a/native_client_sdk/src/libraries/nacl_io/mount.h b/native_client_sdk/src/libraries/nacl_io/mount.h
index 4374c9b6f2..e480d89f56 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount.h
@@ -54,7 +54,7 @@ class Mount : public sdk_util::RefObject {
// MountNode is created with a ref count of 1.
// Assumes that |out_node| is non-NULL.
virtual Error Open(const Path& path,
- int o_flags,
+ int open_flags,
ScopedMountNode* out_node) = 0;
// OpenResource is only used to read files from the NaCl NMF file. No mount
@@ -69,8 +69,8 @@ class Mount : public sdk_util::RefObject {
virtual Error Rmdir(const Path& path) = 0;
virtual Error Remove(const Path& path) = 0;
- // Convert from R,W,R/W open flags to STAT permission flags
- static int OpenModeToPermission(int mode);
+ // Convert from R,W,R/W open flags to STAT permissions.
+ static int OpenFlagsToPermission(int open_flags);
// Assumes that |node| is non-NULL.
void OnNodeCreated(MountNode* node);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
index 3c7ffe01a7..b0c2d5b52a 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
@@ -34,8 +34,11 @@ class RealNode : public MountNode {
public:
RealNode(Mount* mount, int fd);
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -49,8 +52,11 @@ class NullNode : public MountNodeCharDevice {
public:
explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -60,7 +66,7 @@ class ConsoleNode : public MountNodeCharDevice {
public:
ConsoleNode(Mount* mount, PP_LogLevel level);
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -73,8 +79,11 @@ class ZeroNode : public MountNode {
public:
explicit ZeroNode(Mount* mount);
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -84,8 +93,11 @@ class UrandomNode : public MountNode {
public:
explicit UrandomNode(Mount* mount);
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -101,7 +113,10 @@ RealNode::RealNode(Mount* mount, int fd) : MountNode(mount), fd_(fd) {
stat_.st_mode = S_IFCHR;
}
-Error RealNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error RealNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
size_t readcnt;
@@ -113,7 +128,7 @@ Error RealNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
return 0;
}
-Error RealNode::Write(size_t offs,
+Error RealNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -130,12 +145,15 @@ Error RealNode::Write(size_t offs,
Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
-Error NullNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error NullNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
return 0;
}
-Error NullNode::Write(size_t offs,
+Error NullNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -147,7 +165,7 @@ ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level)
: MountNodeCharDevice(mount), level_(level) {
}
-Error ConsoleNode::Write(size_t offs,
+Error ConsoleNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -159,9 +177,9 @@ Error ConsoleNode::Write(size_t offs,
if (!(var_intr && con_intr))
return ENOSYS;
- const char* data = static_cast<const char*>(buf);
+ const char* var_data = static_cast<const char*>(buf);
uint32_t len = static_cast<uint32_t>(count);
- struct PP_Var val = var_intr->VarFromUtf8(data, len);
+ struct PP_Var val = var_intr->VarFromUtf8(var_data, len);
con_intr->Log(mount_->ppapi()->GetInstance(), level_, val);
*out_bytes = count;
@@ -170,13 +188,16 @@ Error ConsoleNode::Write(size_t offs,
ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
-Error ZeroNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error ZeroNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
memset(buf, 0, count);
*out_bytes = count;
return 0;
}
-Error ZeroNode::Write(size_t offs,
+Error ZeroNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -193,7 +214,10 @@ UrandomNode::UrandomNode(Mount* mount) : MountNode(mount) {
#endif
}
-Error UrandomNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error UrandomNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
#if defined(__native_client__)
@@ -229,7 +253,7 @@ Error UrandomNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
#endif
}
-Error UrandomNode::Write(size_t offs,
+Error UrandomNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -252,11 +276,13 @@ Error MountDev::Access(const Path& path, int a_mode) {
return 0;
}
-Error MountDev::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountDev::Open(const Path& path,
+ int open_flags,
+ ScopedMountNode* out_node) {
out_node->reset(NULL);
// Don't allow creating any files.
- if (mode & O_CREAT)
+ if (open_flags & O_CREAT)
return EINVAL;
return root_->FindChild(path.Join(), out_node);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.h b/native_client_sdk/src/libraries/nacl_io/mount_dev.h
index a967f5a205..5b253cdcf2 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.h
@@ -15,7 +15,9 @@ class MountNode;
class MountDev : public Mount {
public:
virtual Error Access(const Path& path, int a_mode);
- virtual Error Open(const Path& path, int mode, ScopedMountNode* out_node);
+ virtual Error Open(const Path& path,
+ int open_flags,
+ ScopedMountNode* out_node);
virtual Error Unlink(const Path& path);
virtual Error Mkdir(const Path& path, int permissions);
virtual Error Rmdir(const Path& path);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
index 9d364d75fe..f4d9a6ddf7 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
@@ -33,7 +33,7 @@ Error MountHtml5Fs::Access(const Path& path, int a_mode) {
}
Error MountHtml5Fs::Open(const Path& path,
- int mode,
+ int open_flags,
ScopedMountNode* out_node) {
out_node->reset(NULL);
Error error = BlockUntilFilesystemOpen();
@@ -46,7 +46,7 @@ Error MountHtml5Fs::Open(const Path& path,
return ENOENT;
ScopedMountNode node(new MountNodeHtml5Fs(this, fileref));
- error = node->Init(mode);
+ error = node->Init(open_flags);
if (error)
return error;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_http.cc b/native_client_sdk/src/libraries/nacl_io/mount_http.cc
index 2a37a6a1d3..6ced25df4f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_http.cc
@@ -15,12 +15,12 @@
#include <vector>
-#include <ppapi/c/pp_errors.h>
-
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount_node_dir.h"
#include "nacl_io/mount_node_http.h"
#include "nacl_io/osinttypes.h"
#include "nacl_io/osunistd.h"
+#include <ppapi/c/pp_errors.h>
#include "sdk_util/string_util.h"
namespace nacl_io {
@@ -63,7 +63,7 @@ Error MountHttp::Access(const Path& path, int a_mode) {
return 0;
}
-Error MountHttp::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountHttp::Open(const Path& path, int flags, ScopedMountNode* out_node) {
out_node->reset(NULL);
assert(url_root_.empty() || url_root_[url_root_.length() - 1] == '/');
@@ -76,7 +76,7 @@ Error MountHttp::Open(const Path& path, int mode, ScopedMountNode* out_node) {
// If we can't find the node in the cache, create it
std::string url = MakeUrl(path);
ScopedMountNode node(new MountNodeHttp(this, url, cache_content_));
- Error error = node->Init(mode);
+ Error error = node->Init(OpenFlagsToPermission(flags));
if (error)
return error;
@@ -381,7 +381,7 @@ Error MountHttp::LoadManifest(const std::string& manifest_name,
char* text = new char[size + 1];
int len;
- error = manifest_node->Read(0, text, size, &len);
+ error = manifest_node->Read(HandleAttr(), text, size, &len);
if (error)
return error;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_mem.cc b/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
index 715d49a8e4..295959921d 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
@@ -29,7 +29,7 @@ Error MountMem::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
return error;
root_.reset(new MountNodeDir(this));
- error = root_->Init(S_IREAD | S_IWRITE);
+ error = root_->Init(S_IREAD | S_IWRITE | S_IEXEC);
if (error) {
root_.reset(NULL);
return error;
@@ -93,14 +93,14 @@ Error MountMem::Access(const Path& path, int a_mode) {
return 0;
}
-Error MountMem::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountMem::Open(const Path& path, int flags, ScopedMountNode* out_node) {
out_node->reset(NULL);
ScopedMountNode node;
Error error = FindNode(path, 0, &node);
if (error) {
// If the node does not exist and we can't create it, fail
- if ((mode & O_CREAT) == 0)
+ if ((flags & O_CREAT) == 0)
return ENOENT;
// Now first find the parent directory to see if we can add it
@@ -110,7 +110,7 @@ Error MountMem::Open(const Path& path, int mode, ScopedMountNode* out_node) {
return error;
node.reset(new MountNodeMem(this));
- error = node->Init(OpenModeToPermission(mode));
+ error = node->Init(OpenFlagsToPermission(flags));
if (error)
return error;
@@ -123,16 +123,16 @@ Error MountMem::Open(const Path& path, int mode, ScopedMountNode* out_node) {
}
// Directories can only be opened read-only.
- if (node->IsaDir() && (mode & 3) != O_RDONLY)
+ if (node->IsaDir() && (flags & 3) != O_RDONLY)
return EISDIR;
// If we were expected to create it exclusively, fail
- if (mode & O_EXCL)
+ if (flags & O_EXCL)
return EEXIST;
// Verify we got the requested permissions.
- int req_mode = OpenModeToPermission(mode);
- int obj_mode = node->GetMode() & OpenModeToPermission(O_RDWR);
+ int req_mode = OpenFlagsToPermission(flags);
+ int obj_mode = node->GetMode() & (S_IREAD | S_IWRITE);
if ((obj_mode & req_mode) != req_mode)
return EACCES;
@@ -166,7 +166,7 @@ Error MountMem::Mkdir(const Path& path, int mode) {
// it will get ref counted again. In either case, release the
// recount we have on exit.
node.reset(new MountNodeDir(this));
- error = node->Init(S_IREAD | S_IWRITE);
+ error = node->Init(S_IREAD | S_IWRITE | S_IEXEC);
if (error)
return error;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.cc b/native_client_sdk/src/libraries/nacl_io/mount_node.cc
index 1f0dc2485e..787db32a2a 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node.cc
@@ -13,6 +13,7 @@
#include <algorithm>
#include <string>
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_wrap_real.h"
#include "nacl_io/mount.h"
#include "nacl_io/osmman.h"
@@ -38,8 +39,8 @@ MountNode::MountNode(Mount* mount) : mount_(mount) {
MountNode::~MountNode() {}
-Error MountNode::Init(int perm) {
- stat_.st_mode |= perm;
+Error MountNode::Init(int mode) {
+ stat_.st_mode |= mode;
return 0;
}
@@ -76,14 +77,25 @@ Error MountNode::GetStat(struct stat* pstat) {
return 0;
}
-Error MountNode::Ioctl(int request, char* arg) { return EINVAL; }
+Error MountNode::Ioctl(int request, ...) {
+ va_list ap;
+ va_start(ap, request);
+ Error rtn = VIoctl(request, ap);
+ va_end(ap);
+ return rtn;
+}
+
+Error MountNode::VIoctl(int request, va_list args) { return EINVAL; }
-Error MountNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNode::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
return EINVAL;
}
-Error MountNode::Write(size_t offs,
+Error MountNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -115,8 +127,11 @@ Error MountNode::MMap(void* addr,
return mmap_error;
}
+ HandleAttr data;
+ data.offs = offset;
+ data.flags = 0;
int bytes_read;
- Error read_error = Read(offset, new_addr, length, &bytes_read);
+ Error read_error = Read(data, new_addr, length, &bytes_read);
if (read_error) {
_real_munmap(new_addr, length);
return read_error;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.h b/native_client_sdk/src/libraries/nacl_io/mount_node.h
index 37847c9bd5..e998f2b3cc 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node.h
@@ -5,6 +5,7 @@
#ifndef LIBRARIES_NACL_IO_MOUNT_NODE_H_
#define LIBRARIES_NACL_IO_MOUNT_NODE_H_
+#include <stdarg.h>
#include <string>
#include "nacl_io/error.h"
@@ -21,6 +22,7 @@ namespace nacl_io {
class Mount;
class MountNode;
+struct HandleAttr;
typedef sdk_util::ScopedRef<MountNode> ScopedMountNode;
@@ -32,8 +34,8 @@ class MountNode : public sdk_util::RefObject {
virtual ~MountNode();
protected:
- // Initialize with node specific flags, in this case stat permissions.
- virtual Error Init(int flags);
+ // Initialize with stat mode flags
+ virtual Error Init(int mode);
virtual void Destroy();
public:
@@ -57,11 +59,15 @@ class MountNode : public sdk_util::RefObject {
// Assume that |stat| is non-NULL.
virtual Error GetStat(struct stat* stat);
// Assume that |arg| is non-NULL.
- virtual Error Ioctl(int request, char* arg);
+ Error Ioctl(int request, ...);
+ virtual Error VIoctl(int request, va_list args);
// Assume that |buf| and |out_bytes| are non-NULL.
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
// Assume that |buf| and |out_bytes| are non-NULL.
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -87,7 +93,6 @@ class MountNode : public sdk_util::RefObject {
virtual bool IsaSock();
virtual bool IsaTTY();
-
// Number of children for this node (directory)
virtual int ChildCount();
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
index ae565509f1..4ce1c72d8d 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
@@ -34,14 +34,17 @@ MountNodeDir::~MountNodeDir() {
}
}
-Error MountNodeDir::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeDir::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
return EISDIR;
}
Error MountNodeDir::FTruncate(off_t size) { return EISDIR; }
-Error MountNodeDir::Write(size_t offs,
+Error MountNodeDir::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
index 867afd4298..049a3af020 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
@@ -35,8 +35,9 @@ class MountNodeDir : public MountNode {
struct dirent* pdir,
size_t count,
int* out_bytes);
- virtual Error Read(size_t offs, void *buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs, const void *buf,
+ virtual Error Read(const HandleAttr& attr, void *buf,
+ size_t count, int* out_bytes);
+ virtual Error Write(const HandleAttr& attr, const void *buf,
size_t count, int* out_bytes);
// Adds a finds or adds a directory entry as an INO, updating the refcount
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
index 3d4b1d1899..19ebeaaa20 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
@@ -13,7 +13,9 @@
#include <ppapi/c/ppb_file_io.h>
#include <string.h>
#include <vector>
+
#include "nacl_io/getdents_helper.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount.h"
#include "nacl_io/osdirent.h"
#include "nacl_io/pepper_interface.h"
@@ -41,30 +43,30 @@ void* GetOutputBuffer(void* user_data, uint32_t count, uint32_t size) {
return output->data;
}
-int32_t ModeToOpenFlags(int mode) {
- int32_t open_flags = 0;
+int32_t OpenFlagsToPPAPIOpenFlags(int open_flags) {
+ int32_t ppapi_flags = 0;
- switch (mode & 3) {
+ switch (open_flags & 3) {
default:
case O_RDONLY:
- open_flags = PP_FILEOPENFLAG_READ;
+ ppapi_flags = PP_FILEOPENFLAG_READ;
break;
case O_WRONLY:
- open_flags = PP_FILEOPENFLAG_WRITE;
+ ppapi_flags = PP_FILEOPENFLAG_WRITE;
break;
case O_RDWR:
- open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
+ ppapi_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
break;
}
- if (mode & O_CREAT)
- open_flags |= PP_FILEOPENFLAG_CREATE;
- if (mode & O_TRUNC)
- open_flags |= PP_FILEOPENFLAG_TRUNCATE;
- if (mode & O_EXCL)
- open_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
+ if (open_flags & O_CREAT)
+ ppapi_flags |= PP_FILEOPENFLAG_CREATE;
+ if (open_flags & O_TRUNC)
+ ppapi_flags |= PP_FILEOPENFLAG_TRUNCATE;
+ if (open_flags & O_EXCL)
+ ppapi_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
- return open_flags;
+ return ppapi_flags;
}
} // namespace
@@ -169,7 +171,7 @@ Error MountNodeHtml5Fs::GetStat(struct stat* stat) {
return 0;
}
-Error MountNodeHtml5Fs::Read(size_t offs,
+Error MountNodeHtml5Fs::Read(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes) {
@@ -180,7 +182,7 @@ Error MountNodeHtml5Fs::Read(size_t offs,
int32_t result =
mount_->ppapi()->GetFileIoInterface()->Read(fileio_resource_,
- offs,
+ attr.offs,
static_cast<char*>(buf),
static_cast<int32_t>(count),
PP_BlockUntilComplete());
@@ -202,7 +204,7 @@ Error MountNodeHtml5Fs::FTruncate(off_t size) {
return 0;
}
-Error MountNodeHtml5Fs::Write(size_t offs,
+Error MountNodeHtml5Fs::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -213,7 +215,7 @@ Error MountNodeHtml5Fs::Write(size_t offs,
int32_t result = mount_->ppapi()->GetFileIoInterface()
->Write(fileio_resource_,
- offs,
+ attr.offs,
static_cast<const char*>(buf),
static_cast<int32_t>(count),
PP_BlockUntilComplete());
@@ -259,8 +261,8 @@ MountNodeHtml5Fs::MountNodeHtml5Fs(Mount* mount, PP_Resource fileref_resource)
fileref_resource_(fileref_resource),
fileio_resource_(0) {}
-Error MountNodeHtml5Fs::Init(int perm) {
- Error error = MountNode::Init(Mount::OpenModeToPermission(perm));
+Error MountNodeHtml5Fs::Init(int open_flags) {
+ Error error = MountNode::Init(Mount::OpenFlagsToPermission(open_flags));
if (error)
return error;
@@ -274,16 +276,15 @@ Error MountNodeHtml5Fs::Init(int perm) {
if (query_result == PP_OK && file_info.type == PP_FILETYPE_DIRECTORY)
return 0;
- fileio_resource_ = mount_->ppapi()->GetFileIoInterface()
- ->Create(mount_->ppapi()->GetInstance());
+ FileIoInterface* file_io = mount_->ppapi()->GetFileIoInterface();
+ fileio_resource_ = file_io->Create(mount_->ppapi()->GetInstance());
if (!fileio_resource_)
return ENOSYS;
- int32_t open_result =
- mount_->ppapi()->GetFileIoInterface()->Open(fileio_resource_,
- fileref_resource_,
- ModeToOpenFlags(perm),
- PP_BlockUntilComplete());
+ int32_t open_result = file_io->Open(fileio_resource_,
+ fileref_resource_,
+ OpenFlagsToPPAPIOpenFlags(open_flags),
+ PP_BlockUntilComplete());
if (open_result != PP_OK)
return PPErrorToErrno(open_result);
return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
index 6a4c0f59a6..d8ef90bb72 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
@@ -23,9 +23,12 @@ class MountNodeHtml5Fs : public MountNode {
size_t count,
int* out_bytes);
virtual Error GetStat(struct stat* stat);
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
virtual Error FTruncate(off_t size);
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
@@ -39,7 +42,7 @@ class MountNodeHtml5Fs : public MountNode {
MountNodeHtml5Fs(Mount* mount, PP_Resource fileref);
// Init with standard open flags
- virtual Error Init(int o_mode);
+ virtual Error Init(int open_flags);
virtual void Destroy();
private:
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
index ce299a19bd..a9ff7ca492 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
@@ -11,6 +11,7 @@
#include <ppapi/c/pp_errors.h>
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount_http.h"
#include "nacl_io/osinttypes.h"
@@ -215,7 +216,7 @@ Error MountNodeHttp::GetStat(struct stat* stat) {
return 0;
}
-Error MountNodeHttp::Read(size_t offs,
+Error MountNodeHttp::Read(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes) {
@@ -229,15 +230,15 @@ Error MountNodeHttp::Read(size_t offs,
return error;
}
- return ReadPartialFromCache(offs, buf, count, out_bytes);
+ return ReadPartialFromCache(attr.offs, buf, count, out_bytes);
}
- return DownloadPartial(offs, buf, count, out_bytes);
+ return DownloadPartial(attr.offs, buf, count, out_bytes);
}
Error MountNodeHttp::FTruncate(off_t size) { return ENOSYS; }
-Error MountNodeHttp::Write(size_t offs,
+Error MountNodeHttp::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
index c027ba6218..f920907cd6 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
@@ -25,9 +25,12 @@ class MountNodeHttp : public MountNode {
size_t count,
int* out_bytes);
virtual Error GetStat(struct stat* stat);
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
virtual Error FTruncate(off_t size);
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
index 5f195f1cf9..bd983beca4 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
@@ -9,6 +9,7 @@
#include <algorithm>
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/osstat.h"
#include "sdk_util/auto_lock.h"
@@ -29,7 +30,10 @@ MountNodeMem::MountNodeMem(Mount* mount)
MountNodeMem::~MountNodeMem() {}
-Error MountNodeMem::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeMem::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
AUTO_LOCK(node_lock_);
@@ -38,16 +42,16 @@ Error MountNodeMem::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
size_t size = stat_.st_size;
- if (offs + count > size) {
- count = size - offs;
+ if (attr.offs + count > size) {
+ count = size - attr.offs;
}
- memcpy(buf, &data_[offs], count);
+ memcpy(buf, &data_[attr.offs], count);
*out_bytes = static_cast<int>(count);
return 0;
}
-Error MountNodeMem::Write(size_t offs,
+Error MountNodeMem::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
@@ -57,12 +61,12 @@ Error MountNodeMem::Write(size_t offs,
if (count == 0)
return 0;
- if (count + offs > stat_.st_size) {
- Resize(count + offs);
- count = stat_.st_size - offs;
+ if (count + attr.offs > stat_.st_size) {
+ Resize(count + attr.offs);
+ count = stat_.st_size - attr.offs;
}
- memcpy(&data_[offs], buf, count);
+ memcpy(&data_[attr.offs], buf, count);
*out_bytes = static_cast<int>(count);
return 0;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
index 6f0bc1fafe..ef2ba492e7 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
@@ -20,8 +20,11 @@ class MountNodeMem : public MountNode {
public:
// Normal read/write operations on a file
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
index 20d3ab246e..cc27a1fa62 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
@@ -11,6 +11,7 @@
#include "nacl_io/event_emitter_pipe.h"
#include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
namespace {
const size_t kDefaultPipeSize = 512 * 1024;
@@ -27,11 +28,11 @@ EventEmitter* MountNodePipe::GetEventEmitter() {
return pipe_.get();
}
-Error MountNodePipe::Read(size_t offs,
+Error MountNodePipe::Read(const HandleAttr& attr,
void *buf,
size_t count,
int* out_bytes) {
- int ms = (GetMode() & O_NONBLOCK) ? 0 : read_timeout_;
+ int ms = attr.IsBlocking() ? read_timeout_ : 0;
EventListenerLock wait(GetEventEmitter());
Error err = wait.WaitOnEvent(POLLIN, ms);
@@ -42,11 +43,11 @@ Error MountNodePipe::Read(size_t offs,
return 0;
}
-Error MountNodePipe::Write(size_t offs,
+Error MountNodePipe::Write(const HandleAttr& attr,
const void *buf,
size_t count,
int* out_bytes) {
- int ms = (GetMode() & O_NONBLOCK) ? 0 : write_timeout_;
+ int ms = attr.IsBlocking() ? write_timeout_ : 0;
EventListenerLock wait(GetEventEmitter());
Error err = wait.WaitOnEvent(POLLOUT, ms);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
index b7ae7f5af3..a109af9f4f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
@@ -18,8 +18,9 @@ class MountNodePipe : public MountNodeStream {
explicit MountNodePipe(Mount* mnt);
virtual EventEmitter* GetEventEmitter();
- virtual Error Read(size_t offs, void *buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs, const void *buf,
+ virtual Error Read(const HandleAttr& attr, void *buf, size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr, const void *buf,
size_t count, int* out_bytes);
protected:
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc
index abaf55ba1e..05716590f5 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc
@@ -7,8 +7,8 @@
#include <errno.h>
#include <string.h>
-#include <sys/fcntl.h>
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount.h"
#include "nacl_io/mount_node_socket.h"
#include "nacl_io/pepper_interface.h"
@@ -28,6 +28,17 @@ MountNodeSocket::MountNodeSocket(Mount* mount)
stat_.st_mode |= S_IFSOCK;
}
+MountNodeSocket::MountNodeSocket(Mount* mount, PP_Resource socket)
+ : MountNodeStream(mount),
+ socket_resource_(socket),
+ local_addr_(0),
+ remote_addr_(0),
+ socket_flags_(0),
+ last_errno_(0) {
+ stat_.st_mode |= S_IFSOCK;
+ mount_->ppapi()->AddRefResource(socket_resource_);
+}
+
void MountNodeSocket::Destroy() {
if (socket_resource_)
mount_->ppapi()->ReleaseResource(socket_resource_);
@@ -53,18 +64,18 @@ Error MountNodeSocket::MMap(void* addr,
// Normal read/write operations on a Socket are equivalent to
// send/recv with a flag value of 0.
-Error MountNodeSocket::Read(size_t offs,
+Error MountNodeSocket::Read(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes) {
- return Recv(buf, count, 0, out_bytes);
+ return Recv(attr, buf, count, 0, out_bytes);
}
-Error MountNodeSocket::Write(size_t offs,
- const void* buf,
- size_t count,
- int* out_bytes) {
- return Send(buf, count, 0, out_bytes);
+Error MountNodeSocket::Write(const HandleAttr& attr,
+ const void* buf,
+ size_t count,
+ int* out_bytes) {
+ return Send(attr, buf, count, 0, out_bytes);
}
@@ -181,12 +192,16 @@ bool MountNodeSocket::IsEquivalentAddress(PP_Resource addr1,
return memcmp(saddr1, saddr2, len1) == 0;
}
-
-Error MountNodeSocket::Accept(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeSocket::Accept(const HandleAttr& attr,
+ PP_Resource* new_sock,
+ struct sockaddr* addr,
+ socklen_t* len) {
return ENOSYS;
}
-Error MountNodeSocket::Connect(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeSocket::Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len) {
if (len < 1)
return EINVAL;
@@ -204,34 +219,72 @@ Error MountNodeSocket::GetSockOpt(int lvl,
int optname,
void* optval,
socklen_t* len) {
- return EINVAL;
+ if (lvl != SOL_SOCKET)
+ return ENOPROTOOPT;
+
+ switch (optname) {
+ case SO_REUSEADDR: {
+ // SO_REUSEADDR is effectivly always on since we can't
+ // disable it with PPAPI sockets.
+ int value = 1;
+ int copy_bytes = std::min(sizeof(int), *len);
+ memcpy(optval, &value, copy_bytes);
+ *len = sizeof(int);
+ return 0;
+ }
+ case SO_ERROR: {
+ int copy_bytes = std::min(sizeof(int), *len);
+ memcpy(optval, &last_errno_, copy_bytes);
+ *len = sizeof(int);
+ last_errno_ = 0;
+ return 0;
+ }
+ }
+
+ return ENOPROTOOPT;
}
Error MountNodeSocket::SetSockOpt(int lvl,
int optname,
const void* optval,
socklen_t len) {
- return EINVAL;
+ if (lvl != SOL_SOCKET)
+ return ENOPROTOOPT;
+
+ switch (optname) {
+ case SO_REUSEADDR: {
+ // SO_REUSEADDR is effectivly always on since we can't
+ // disable it with PPAPI sockets. Just return success
+ // here regardless.
+ return 0;
+ }
+ }
+
+ return ENOPROTOOPT;
}
Error MountNodeSocket::Bind(const struct sockaddr* addr, socklen_t len) {
return EINVAL;
}
-
-Error MountNodeSocket::Recv(void* buf, size_t len, int flags, int* out_len) {
- return RecvFrom(buf, len, flags, NULL, 0, out_len);
+Error MountNodeSocket::Recv(const HandleAttr& attr,
+ void* buf,
+ size_t len,
+ int flags,
+ int* out_len) {
+ return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
}
-Error MountNodeSocket::RecvFrom(void* buf,
+Error MountNodeSocket::RecvFrom(const HandleAttr& attr,
+ void* buf,
size_t len,
int flags,
struct sockaddr* src_addr,
socklen_t* addrlen,
int* out_len) {
- PP_Resource addr;
- Error err = RecvHelper(buf, len, flags, &addr, out_len);
- if (0 != addr) {
+ PP_Resource addr = 0;
+ Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
+ if (0 == err && 0 != addr) {
if (src_addr)
*addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
@@ -241,7 +294,8 @@ Error MountNodeSocket::RecvFrom(void* buf,
return err;
}
-Error MountNodeSocket::RecvHelper(void* buf,
+Error MountNodeSocket::RecvHelper(const HandleAttr& attr,
+ void* buf,
size_t len,
int flags,
PP_Resource* addr,
@@ -250,7 +304,7 @@ Error MountNodeSocket::RecvHelper(void* buf,
return EBADF;
int ms = read_timeout_;
- if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK))
+ if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
ms = 0;
//TODO(noelallen) BUG=295177
@@ -273,15 +327,16 @@ Error MountNodeSocket::RecvHelper(void* buf,
return err;
}
-
-Error MountNodeSocket::Send(const void* buf,
- size_t len,
- int flags,
- int* out_len) {
- return SendHelper(buf, len, flags, remote_addr_, out_len);
+Error MountNodeSocket::Send(const HandleAttr& attr,
+ const void* buf,
+ size_t len,
+ int flags,
+ int* out_len) {
+ return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
}
-Error MountNodeSocket::SendTo(const void* buf,
+Error MountNodeSocket::SendTo(const HandleAttr& attr,
+ const void* buf,
size_t len,
int flags,
const struct sockaddr* dest_addr,
@@ -291,16 +346,16 @@ Error MountNodeSocket::SendTo(const void* buf,
return EDESTADDRREQ;
PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
- if (addr) {
- Error err = SendHelper(buf, len, flags, addr, out_len);
- mount_->ppapi()->ReleaseResource(addr);
- return err;
- }
+ if (0 == addr)
+ return EINVAL;
- return EINVAL;
+ Error err = SendHelper(attr, buf, len, flags, addr, out_len);
+ mount_->ppapi()->ReleaseResource(addr);
+ return err;
}
-Error MountNodeSocket::SendHelper(const void* buf,
+Error MountNodeSocket::SendHelper(const HandleAttr& attr,
+ const void* buf,
size_t len,
int flags,
PP_Resource addr,
@@ -312,7 +367,7 @@ Error MountNodeSocket::SendHelper(const void* buf,
return ENOTCONN;
int ms = write_timeout_;
- if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK))
+ if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
ms = 0;
EventListenerLock wait(GetEventEmitter());
@@ -372,4 +427,4 @@ Error MountNodeSocket::GetSockName(struct sockaddr* addr, socklen_t* len) {
} // namespace nacl_io
-#endif // PROVIDES_SOCKET_API \ No newline at end of file
+#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
index 5cd4ba21b4..7254c64eea 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
@@ -8,6 +8,7 @@
#include "nacl_io/ossocket.h"
#ifdef PROVIDES_SOCKET_API
+#include <sys/fcntl.h>
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_resource.h>
#include <ppapi/c/ppb_net_address.h>
@@ -28,27 +29,29 @@ class MountStream;
class MountNodeSocket : public MountNodeStream {
public:
explicit MountNodeSocket(Mount* mount);
+ MountNodeSocket(Mount* mount, PP_Resource socket);
protected:
virtual void Destroy();
- virtual Error Init(int flags) = 0;
public:
// Normal read/write operations on a file (recv/send).
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
- // Unsuported Functions
- virtual Error Accept(const struct sockaddr* addr, socklen_t len);
- virtual Error Listen(int backlog);
virtual Error GetSockOpt(int lvl, int optname, void* optval, socklen_t* len);
virtual Error SetSockOpt(int lvl,
int optname,
const void* optval,
socklen_t len);
+
+ // Unsupported Functions
virtual Error Shutdown(int how);
virtual Error MMap(void* addr,
size_t length,
@@ -58,18 +61,35 @@ class MountNodeSocket : public MountNodeStream {
void** out_addr);
// Socket Functions.
+ virtual Error Accept(const HandleAttr& attr,
+ PP_Resource* new_sock,
+ struct sockaddr* addr,
+ socklen_t* len);
virtual Error Bind(const struct sockaddr* addr, socklen_t len);
- virtual Error Connect(const struct sockaddr* addr, socklen_t len);
- virtual Error Recv(void* buf, size_t len, int flags, int* out_len);
- virtual Error RecvFrom(void* buf,
+ virtual Error Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len);
+ virtual Error Listen(int backlog);
+ virtual Error Recv(const HandleAttr& attr,
+ void* buf,
+ size_t len,
+ int flags,
+ int* out_len);
+ virtual Error RecvFrom(const HandleAttr& attr,
+ void* buf,
size_t len,
int flags,
struct sockaddr* src_addr,
socklen_t* addrlen,
int* out_len);
- virtual Error Send(const void* buf, size_t len, int flags, int* out_len);
- virtual Error SendTo(const void* buf,
+ virtual Error Send(const HandleAttr& attr,
+ const void* buf,
+ size_t len,
+ int flags,
+ int* out_len);
+ virtual Error SendTo(const HandleAttr& attr,
+ const void* buf,
size_t len,
int flags,
const struct sockaddr* dest_addr,
@@ -80,21 +100,25 @@ class MountNodeSocket : public MountNodeStream {
virtual Error GetSockName(struct sockaddr* addr, socklen_t* len);
PP_Resource socket_resource() { return socket_resource_; }
+ PP_Resource remote_addr() { return remote_addr_; }
// Updates socket's state, recording last error.
void SetError_Locked(int pp_error_num);
+
protected:
// Wraps common error checks, timeouts, work pump for send.
- Error SendHelper(const void* buf,
+ Error SendHelper(const HandleAttr& attr,
+ const void* buf,
size_t len,
int flags,
PP_Resource addr,
int* out_len);
// Wraps common error checks, timeouts, work pump for recv.
- Error RecvHelper(void* buf,
+ Error RecvHelper(const HandleAttr& attr,
+ void* buf,
size_t len,
int flags,
PP_Resource* addr,
@@ -140,4 +164,4 @@ class MountNodeSocket : public MountNodeStream {
#endif // PROVIDES_SOCKET_API
-#endif // LIBRARIES_NACL_IO_MOUNT_NODE_SOCKET_H_ \ No newline at end of file
+#endif // LIBRARIES_NACL_IO_MOUNT_NODE_SOCKET_H_
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
index c3cbc23c32..0623976993 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
@@ -23,9 +23,9 @@ MountNodeStream::MountNodeStream(Mount* mnt)
stream_state_flags_(0) {
}
-Error MountNodeStream::Init(int perm) {
- MountNode::Init(perm);
- if (perm & O_NONBLOCK)
+Error MountNodeStream::Init(int open_flags) {
+ MountNode::Init(Mount::OpenFlagsToPermission(open_flags));
+ if (open_flags & O_NONBLOCK)
SetStreamFlags(SSF_NON_BLOCK);
return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
index c855aff6ed..fedd5aba11 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
@@ -24,8 +24,11 @@ enum StreamStateFlags {
SSF_SENDING = 0x0002,
SSF_RECVING = 0x0004,
SSF_CLOSING = 0x0008,
+ SSF_LISTENING = 0x000f,
SSF_CAN_SEND = 0x0020,
SSF_CAN_RECV = 0x0040,
+ SSF_CAN_ACCEPT = 0x0080,
+ SSF_CAN_CONNECT = 0x00f0,
SSF_NON_BLOCK = 0x1000,
SSF_ERROR = 0x4000,
SSF_CLOSED = 0x8000
@@ -36,7 +39,7 @@ class MountNodeStream : public MountNode {
public:
explicit MountNodeStream(Mount* mnt);
- virtual Error Init(int perm);
+ virtual Error Init(int open_flags);
// Attempts to pump input and output
virtual void QueueInput();
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
index bdc4b10204..d34cf7ceb2 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
@@ -6,10 +6,12 @@
#include "nacl_io/ossocket.h"
#ifdef PROVIDES_SOCKET_API
+#include <assert.h>
#include <errno.h>
#include <string.h>
#include <algorithm>
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount_node_tcp.h"
#include "nacl_io/mount_stream.h"
#include "nacl_io/pepper_interface.h"
@@ -42,7 +44,6 @@ class TCPWork : public MountStream::Work {
char* data_;
};
-
class TCPSendWork : public TCPWork {
public:
explicit TCPSendWork(const ScopedEventEmitterTCP& emitter)
@@ -58,9 +59,8 @@ class TCPSendWork : public TCPWork {
// If not currently sending...
if (!stream->TestStreamFlags(SSF_SENDING)) {
- size_t tx_data_avail = emitter_->out_fifo()->ReadAvailable();
- int capped_len =
- static_cast<int32_t>(std::min(tx_data_avail, kMaxPacketSize));
+ size_t tx_data_avail = emitter_->BytesInOutputFIFO();
+ int capped_len = std::min(tx_data_avail, kMaxPacketSize);
if (capped_len == 0)
return false;
@@ -115,7 +115,7 @@ class TCPRecvWork : public TCPWork {
// If we are not currently receiving
if (!stream->TestStreamFlags(SSF_RECVING)) {
- size_t rx_space_avail = emitter_->in_fifo()->WriteAvailable();
+ size_t rx_space_avail = emitter_->SpaceInInputFIFO();
int capped_len =
static_cast<int32_t>(std::min(rx_space_avail, kMaxPacketSize));
@@ -125,9 +125,9 @@ class TCPRecvWork : public TCPWork {
stream->SetStreamFlags(SSF_RECVING);
data_ = new char[capped_len];
int err = TCPInterface()->Read(stream->socket_resource(),
- data_,
- capped_len,
- mount()->GetRunCompletion(this));
+ data_,
+ capped_len,
+ mount()->GetRunCompletion(this));
if (err == PP_OK_COMPLETIONPENDING)
return true;
@@ -145,6 +145,7 @@ class TCPRecvWork : public TCPWork {
if (stream) {
if (length_error > 0) {
emitter_->WriteIn_Locked(data_, length_error);
+ stream->ClearStreamFlags(SSF_RECVING);
stream->QueueInput();
} else {
stream->SetError_Locked(length_error);
@@ -153,6 +154,109 @@ class TCPRecvWork : public TCPWork {
}
};
+class TCPAcceptWork : public MountStream::Work {
+ public:
+ explicit TCPAcceptWork(MountStream* stream,
+ const ScopedEventEmitterTCP& emitter)
+ : MountStream::Work(stream),
+ emitter_(emitter) {}
+
+ TCPSocketInterface* TCPInterface() {
+ return mount()->ppapi()->GetTCPSocketInterface();
+ }
+
+ virtual bool Start(int32_t val) {
+ AUTO_LOCK(emitter_->GetLock());
+ MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+ // Does the stream exist, and can it accept?
+ if (NULL == node)
+ return false;
+
+ // If we are not currently accepting
+ if (!node->TestStreamFlags(SSF_LISTENING))
+ return false;
+
+ int err = TCPInterface()->Accept(node->socket_resource(),
+ &new_socket_,
+ mount()->GetRunCompletion(this));
+
+ if (err != PP_OK_COMPLETIONPENDING)
+ // Anything else, we should assume the socket has gone bad.
+ node->SetError_Locked(err);
+
+ return true;
+ }
+
+ virtual void Run(int32_t error) {
+ AUTO_LOCK(emitter_->GetLock());
+ MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+ if (node == NULL)
+ return;
+
+ if (error != PP_OK) {
+ node->SetError_Locked(error);
+ return;
+ }
+
+ emitter_->SetAcceptedSocket_Locked(new_socket_);
+ }
+
+ protected:
+ PP_Resource new_socket_;
+ ScopedEventEmitterTCP emitter_;
+};
+
+class TCPConnectWork : public MountStream::Work {
+ public:
+ explicit TCPConnectWork(MountStream* stream,
+ const ScopedEventEmitterTCP& emitter)
+ : MountStream::Work(stream),
+ emitter_(emitter) {}
+
+ TCPSocketInterface* TCPInterface() {
+ return mount()->ppapi()->GetTCPSocketInterface();
+ }
+
+ virtual bool Start(int32_t val) {
+ AUTO_LOCK(emitter_->GetLock());
+ MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+ // Does the stream exist, and can it connect?
+ if (NULL == node)
+ return false;
+
+ int err = TCPInterface()->Connect(node->socket_resource(),
+ node->remote_addr(),
+ mount()->GetRunCompletion(this));
+
+ if (err != PP_OK_COMPLETIONPENDING)
+ // Anything else, we should assume the socket has gone bad.
+ node->SetError_Locked(err);
+
+ return true;
+ }
+
+ virtual void Run(int32_t error) {
+ AUTO_LOCK(emitter_->GetLock());
+ MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+ if (node == NULL)
+ return;
+
+ if (error != PP_OK) {
+ node->ConnectFailed_Locked();
+ node->SetError_Locked(error);
+ return;
+ }
+
+ node->ConnectDone_Locked();
+ }
+
+ protected:
+ ScopedEventEmitterTCP emitter_;
+};
MountNodeTCP::MountNodeTCP(Mount* mount)
: MountNodeSocket(mount),
@@ -160,36 +264,100 @@ MountNodeTCP::MountNodeTCP(Mount* mount)
emitter_->AttachStream(this);
}
+MountNodeTCP::MountNodeTCP(Mount* mount, PP_Resource socket)
+ : MountNodeSocket(mount, socket),
+ emitter_(new EventEmitterTCP(kDefaultFifoSize, kDefaultFifoSize)) {
+ emitter_->AttachStream(this);
+}
+
void MountNodeTCP::Destroy() {
emitter_->DetachStream();
MountNodeSocket::Destroy();
}
-Error MountNodeTCP::Init(int flags) {
+Error MountNodeTCP::Init(int open_flags) {
+ Error err = MountNodeSocket::Init(open_flags);
+ if (err != 0)
+ return err;
+
if (TCPInterface() == NULL)
return EACCES;
- socket_resource_ = TCPInterface()->Create(mount_->ppapi()->GetInstance());
- if (0 == socket_resource_)
- return EACCES;
+ SetStreamFlags(SSF_CAN_CONNECT);
+
+ if (socket_resource_ != 0) {
+ // TCP sockets that are contructed with an existing socket_resource_
+ // are those that generated from calls to Accept() and therefore are
+ // already connected.
+ remote_addr_ = TCPInterface()->GetRemoteAddress(socket_resource_);
+ ConnectDone_Locked();
+ } else {
+ socket_resource_ = TCPInterface()->Create(mount_->ppapi()->GetInstance());
+ if (0 == socket_resource_)
+ return EACCES;
+ }
return 0;
}
-EventEmitterTCP* MountNodeTCP::GetEventEmitter() {
+EventEmitter* MountNodeTCP::GetEventEmitter() {
return emitter_.get();
}
+void MountNodeTCP::QueueAccept() {
+ MountStream::Work* work = new TCPAcceptWork(mount_stream(), emitter_);
+ mount_stream()->EnqueueWork(work);
+}
+
+void MountNodeTCP::QueueConnect() {
+ MountStream::Work* work = new TCPConnectWork(mount_stream(), emitter_);
+ mount_stream()->EnqueueWork(work);
+}
+
void MountNodeTCP::QueueInput() {
- TCPRecvWork* work = new TCPRecvWork(emitter_);
+ MountStream::Work* work = new TCPRecvWork(emitter_);
mount_stream()->EnqueueWork(work);
}
void MountNodeTCP::QueueOutput() {
- TCPSendWork* work = new TCPSendWork(emitter_);
+ MountStream::Work* work = new TCPSendWork(emitter_);
mount_stream()->EnqueueWork(work);
}
+Error MountNodeTCP::Accept(const HandleAttr& attr,
+ PP_Resource* out_sock,
+ struct sockaddr* addr,
+ socklen_t* len) {
+ EventListenerLock wait(GetEventEmitter());
+
+ if (!TestStreamFlags(SSF_LISTENING))
+ return EINVAL;
+
+ // Either block forever or not at all
+ int ms = attr.IsBlocking() ? -1 : 0;
+
+ Error err = wait.WaitOnEvent(POLLIN, ms);
+
+ if (ETIMEDOUT == err)
+ return EWOULDBLOCK;
+
+ int s = emitter_->GetAcceptedSocket_Locked();
+ // Non-blocking case.
+ if (s == 0)
+ return EAGAIN;
+
+ // Consume the new socket and start listening for the next one
+ *out_sock = s;
+ emitter_->ClearEvents_Locked(POLLIN);
+
+ // Set the out paramaters
+ PP_Resource remote_addr = TCPInterface()->GetRemoteAddress(*out_sock);
+ *len = ResourceToSockAddr(remote_addr, *len, addr);
+ mount_->ppapi()->ReleaseResource(remote_addr);
+
+ QueueAccept();
+ return 0;
+}
// We can not bind a client socket with PPAPI. For now we ignore the
// bind but report the correct address later, just in case someone is
@@ -198,58 +366,101 @@ void MountNodeTCP::QueueOutput() {
Error MountNodeTCP::Bind(const struct sockaddr* addr, socklen_t len) {
AUTO_LOCK(node_lock_);
- if (0 == socket_resource_)
- return EBADF;
-
/* Only bind once. */
if (local_addr_ != 0)
return EINVAL;
- /* Lie, we won't know until we connect. */
+ local_addr_ = SockAddrToResource(addr, len);
+ int err = TCPInterface()->Bind(socket_resource_,
+ local_addr_,
+ PP_BlockUntilComplete());
+
+ // If we fail, release the local addr resource
+ if (err != PP_OK) {
+ mount_->ppapi()->ReleaseResource(local_addr_);
+ local_addr_ = 0;
+ return PPErrorToErrno(err);
+ }
+
return 0;
}
-Error MountNodeTCP::Connect(const struct sockaddr* addr, socklen_t len) {
- AUTO_LOCK(node_lock_);
+Error MountNodeTCP::Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len) {
+ EventListenerLock wait(GetEventEmitter());
- if (0 == socket_resource_)
- return EBADF;
+ if (TestStreamFlags(SSF_CONNECTING))
+ return EALREADY;
- if (remote_addr_ != 0)
+ if (remote_addr_ != 0) {
return EISCONN;
+ }
remote_addr_ = SockAddrToResource(addr, len);
if (0 == remote_addr_)
return EINVAL;
- int err = TCPInterface()->Connect(socket_resource_,
- remote_addr_,
- PP_BlockUntilComplete());
+ int ms = attr.IsBlocking() ? -1 : 0;
+
+ SetStreamFlags(SSF_CONNECTING);
+ QueueConnect();
+
+ Error err = wait.WaitOnEvent(POLLOUT, ms);
+ if (ETIMEDOUT == err)
+ return EINPROGRESS;
// If we fail, release the dest addr resource
- if (err != PP_OK) {
- mount_->ppapi()->ReleaseResource(remote_addr_);
- remote_addr_ = 0;
- return PPErrorToErrno(err);
+ if (err != 0) {
+ ConnectFailed_Locked();
+ return err;
}
+ ConnectDone_Locked();
+ return 0;
+}
+
+void MountNodeTCP::ConnectDone_Locked() {
local_addr_ = TCPInterface()->GetLocalAddress(socket_resource_);
- mount_->ppapi()->AddRefResource(local_addr_);
// Now that we are connected, we can start sending and receiving.
+ ClearStreamFlags(SSF_CONNECTING | SSF_CAN_CONNECT);
SetStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
+ emitter_->ConnectDone_Locked();
+
// Begin the input pump
QueueInput();
- return 0;
}
+void MountNodeTCP::ConnectFailed_Locked() {
+ mount_->ppapi()->ReleaseResource(remote_addr_);
+ remote_addr_ = 0;
+}
+
+Error MountNodeTCP::Listen(int backlog) {
+ AUTO_LOCK(node_lock_);
+ if (0 == local_addr_)
+ return EINVAL;
+
+ int err = TCPInterface()->Listen(socket_resource_,
+ backlog,
+ PP_BlockUntilComplete());
+ if (err != PP_OK)
+ return PPErrorToErrno(err);
+
+ ClearStreamFlags(SSF_CAN_CONNECT);
+ SetStreamFlags(SSF_LISTENING);
+ QueueAccept();
+ return 0;
+}
Error MountNodeTCP::Recv_Locked(void* buf,
size_t len,
PP_Resource* out_addr,
int* out_len) {
- *out_len = emitter_->in_fifo()->Read(buf, len);
+ assert(emitter_.get());
+ *out_len = emitter_->ReadIn_Locked((char*)buf, len);
*out_addr = remote_addr_;
// Ref the address copy we pass back.
@@ -262,11 +473,12 @@ Error MountNodeTCP::Send_Locked(const void* buf,
size_t len,
PP_Resource,
int* out_len) {
- *out_len = emitter_->out_fifo()->Write(buf, len);
+ assert(emitter_.get());
+ *out_len = emitter_->WriteOut_Locked((char*)buf, len);
return 0;
}
} // namespace nacl_io
-#endif // PROVIDES_SOCKET_API \ No newline at end of file
+#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
index 077276fc96..afd593a79b 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
@@ -20,19 +20,32 @@ namespace nacl_io {
class MountNodeTCP : public MountNodeSocket {
public:
explicit MountNodeTCP(Mount* mount);
+ MountNodeTCP(Mount* mount, PP_Resource socket);
protected:
- virtual Error Init(int flags);
+ virtual Error Init(int open_flags);
virtual void Destroy();
public:
- virtual EventEmitterTCP* GetEventEmitter();
+ virtual EventEmitter* GetEventEmitter();
+ virtual void QueueAccept();
+ virtual void QueueConnect();
virtual void QueueInput();
virtual void QueueOutput();
+ virtual Error Accept(const HandleAttr& attr,
+ PP_Resource* out_sock,
+ struct sockaddr* addr,
+ socklen_t* len);
virtual Error Bind(const struct sockaddr* addr, socklen_t len);
- virtual Error Connect(const struct sockaddr* addr, socklen_t len);
+ virtual Error Listen(int backlog);
+ virtual Error Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len);
+
+ void ConnectDone_Locked();
+ void ConnectFailed_Locked();
protected:
virtual Error Recv_Locked(void* buf,
@@ -46,6 +59,7 @@ class MountNodeTCP : public MountNodeSocket {
int* out_len);
ScopedEventEmitterTCP emitter_;
+ PP_Resource accepted_socket_;
};
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 4b6c5652d0..af9b7543a1 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
@@ -15,6 +15,7 @@
#include <algorithm>
#include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount.h"
#include "nacl_io/pepper_interface.h"
#include "sdk_util/auto_lock.h"
@@ -76,11 +77,10 @@ EventEmitter* MountNodeTty::GetEventEmitter() {
return emitter_.get();
}
-Error MountNodeTty::Write(size_t offs,
- const void* buf,
- size_t count,
- int* out_bytes) {
-
+Error MountNodeTty::Write(const HandleAttr& attr,
+ const void* buf,
+ size_t count,
+ int* out_bytes) {
AUTO_LOCK(output_lock_);
*out_bytes = 0;
@@ -102,7 +102,10 @@ Error MountNodeTty::Write(size_t offs,
}
-Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeTty::Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
EventListenerLock wait(GetEventEmitter());
*out_bytes = 0;
@@ -151,7 +154,8 @@ Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
Error MountNodeTty::Echo(const char* string, int count) {
int wrote;
- Error error = Write(0, string, count, &wrote);
+ HandleAttr data;
+ Error error = Write(data, string, count, &wrote);
if (error != 0 || wrote != count) {
// TOOD(sbc): Do something more useful in response to a
// failure to echo.
@@ -228,9 +232,10 @@ Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) {
return 0;
}
-Error MountNodeTty::Ioctl(int request, char* arg) {
+Error MountNodeTty::VIoctl(int request, va_list args) {
switch (request) {
case TIOCNACLOUTPUT: {
+ struct tioc_nacl_output* arg = va_arg(args, struct tioc_nacl_output*);
AUTO_LOCK(output_lock_);
if (arg == NULL) {
output_handler_.handler = NULL;
@@ -238,18 +243,18 @@ Error MountNodeTty::Ioctl(int request, char* arg) {
}
if (output_handler_.handler != NULL)
return EALREADY;
- output_handler_ = *reinterpret_cast<tioc_nacl_output*>(arg);
+ output_handler_ = *arg;
return 0;
}
case TIOCNACLINPUT: {
// This ioctl is used to deliver data from the user to this tty node's
// input buffer.
struct tioc_nacl_input_string* message =
- reinterpret_cast<struct tioc_nacl_input_string*>(arg);
+ va_arg(args, struct tioc_nacl_input_string*);
return ProcessInput(message);
}
case TIOCSWINSZ: {
- struct winsize* size = reinterpret_cast<struct winsize*>(arg);
+ struct winsize* size = va_arg(args, struct winsize*);
{
AUTO_LOCK(node_lock_);
rows_ = size->ws_row;
@@ -266,7 +271,7 @@ Error MountNodeTty::Ioctl(int request, char* arg) {
return 0;
}
case TIOCGWINSZ: {
- struct winsize* size = reinterpret_cast<struct winsize*>(arg);
+ struct winsize* size = va_arg(args, struct winsize*);
size->ws_row = rows_;
size->ws_col = cols_;
return 0;
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 1c8e65d392..b47396f895 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
@@ -23,15 +23,14 @@ class MountNodeTty : public MountNodeCharDevice {
virtual EventEmitter* GetEventEmitter();
- virtual Error Ioctl(int request,
- char* arg);
+ virtual Error VIoctl(int request, va_list args);
- virtual Error Read(size_t offs,
+ virtual Error Read(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes);
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
index cb8c23e78c..29886b1257 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
@@ -170,7 +170,11 @@ EventEmitterUDP* MountNodeUDP::GetEventEmitter() {
return emitter_.get();
}
-Error MountNodeUDP::Init(int flags) {
+Error MountNodeUDP::Init(int open_flags) {
+ Error err = MountNodeSocket::Init(open_flags);
+ if (err != 0)
+ return err;
+
if (UDPInterface() == NULL)
return EACCES;
@@ -219,7 +223,9 @@ Error MountNodeUDP::Bind(const struct sockaddr* addr, socklen_t len) {
return 0;
}
-Error MountNodeUDP::Connect(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeUDP::Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len) {
if (0 == socket_resource_)
return EBADF;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
index 2fef5139ef..95f28897d0 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
@@ -22,7 +22,7 @@ class MountNodeUDP : public MountNodeSocket {
explicit MountNodeUDP(Mount* mount);
protected:
- virtual Error Init(int flags);
+ virtual Error Init(int open_flags);
virtual void Destroy();
public:
@@ -32,7 +32,9 @@ class MountNodeUDP : public MountNodeSocket {
virtual void QueueOutput();
virtual Error Bind(const struct sockaddr* addr, socklen_t len);
- virtual Error Connect(const struct sockaddr* addr, socklen_t len);
+ virtual Error Connect(const HandleAttr& attr,
+ const struct sockaddr* addr,
+ socklen_t len);
protected:
virtual Error Recv_Locked(void* buf,
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
index a84d4c5998..f4c9951aec 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
@@ -3,7 +3,10 @@
// found in the LICENSE file.
#include "nacl_io/mount_passthrough.h"
+
#include <errno.h>
+
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_wrap_real.h"
namespace nacl_io {
@@ -24,11 +27,14 @@ class MountNodePassthrough : public MountNode {
public:
// Normal read/write operations on a file
- virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+ virtual Error Read(const HandleAttr& attr,
+ void* buf,
+ size_t count,
+ int* out_bytes) {
*out_bytes = 0;
off_t new_offset;
- int err = _real_lseek(real_fd_, offs, 0, &new_offset);
+ int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset);
if (err)
return err;
@@ -41,14 +47,14 @@ class MountNodePassthrough : public MountNode {
return 0;
}
- virtual Error Write(size_t offs,
+ virtual Error Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
*out_bytes = 0;
off_t new_offset;
- int err = _real_lseek(real_fd_, offs, 0, &new_offset);
+ int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset);
if (err)
return err;
diff --git a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
index 95f802ae44..c6678026df 100644
--- a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
+++ b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
@@ -115,6 +115,7 @@ BEGIN_INTERFACE(NetAddressInterface, PPB_NetAddress_1_0,
struct PP_NetAddress_IPv4*)
METHOD2(NetAddressInterface, PP_Bool, DescribeAsIPv6Address, PP_Resource,
struct PP_NetAddress_IPv6*)
+ METHOD2(NetAddressInterface, PP_Var, DescribeAsString, PP_Resource, PP_Bool)
END_INTERFACE(NetAddressInterface, PPB_NetAddress_1_0)
BEGIN_INTERFACE(URLLoaderInterface, PPB_URLLoader_1_0,
@@ -141,9 +142,15 @@ BEGIN_INTERFACE(URLResponseInfoInterface, PPB_URLResponseInfo_1_0,
PP_URLResponseProperty)
END_INTERFACE(URLResponseInfoInterface, PPB_URLResponseInfo_1_0)
-BEGIN_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_0,
- PPB_TCPSOCKET_INTERFACE_1_0)
+BEGIN_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_1,
+ PPB_TCPSOCKET_INTERFACE_1_1)
METHOD1(TCPSocketInterface, PP_Resource, Create, PP_Instance)
+ METHOD3(TCPSocketInterface, int32_t, Bind, PP_Resource, PP_Resource,
+ PP_CompletionCallback)
+ METHOD3(TCPSocketInterface, int32_t, Listen, PP_Resource, int32_t,
+ PP_CompletionCallback)
+ METHOD3(TCPSocketInterface, int32_t, Accept, PP_Resource, PP_Resource*,
+ PP_CompletionCallback)
METHOD1(TCPSocketInterface, PP_Bool, IsTCPSocket, PP_Resource)
METHOD3(TCPSocketInterface, int32_t, Connect, PP_Resource, PP_Resource,
PP_CompletionCallback)
@@ -156,7 +163,7 @@ BEGIN_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_0,
METHOD1(TCPSocketInterface, void, Close, PP_Resource)
METHOD4(TCPSocketInterface, int32_t, SetOption, PP_Resource,
PP_TCPSocket_Option, PP_Var, PP_CompletionCallback)
-END_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_0)
+END_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_1)
BEGIN_INTERFACE(UDPSocketInterface, PPB_UDPSocket_1_0,
PPB_UDPSOCKET_INTERFACE_1_0)
diff --git a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
index 53a8a0f1c8..3fcc7a0b1d 100644
--- a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
+++ b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
@@ -3,11 +3,13 @@
// found in the LICENSE file.
#include "nacl_io/real_pepper_interface.h"
+
#include <assert.h>
#include <stdio.h>
-
#include <ppapi/c/pp_errors.h>
+#include "nacl_io/dbgprint.h"
+
namespace nacl_io {
#include "nacl_io/pepper/undef_macros.h"
@@ -79,10 +81,15 @@ RealPepperInterface::RealPepperInterface(PP_Instance instance,
#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
-#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
- BaseClass##interface_ = new Real##BaseClass( \
- static_cast<const PPInterface*>( \
- get_browser_interface(InterfaceString)));
+#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) { \
+ const PPInterface* iface = static_cast<const PPInterface*>( \
+ get_browser_interface(InterfaceString)); \
+ BaseClass##interface_ = NULL; \
+ if (iface) \
+ BaseClass##interface_ = new Real##BaseClass(iface); \
+ else \
+ dbgprintf("nacl_io: interface missing: %s\n", InterfaceString); \
+ }
#include "nacl_io/pepper/all_interfaces.h"
}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c b/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c
new file mode 100644
index 0000000000..1958f15ad4
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c
@@ -0,0 +1,10 @@
+/* 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 "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+int fchmod(int fd, mode_t mode) {
+ return ki_fchmod(fd, mode);
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
index e96ed38c84..11f7182942 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
@@ -10,7 +10,7 @@
int fcntl(int fd, int cmd, ...) {
va_list ap;
va_start(ap, cmd);
- char* arg = va_arg(ap, char*);
+ int rtn = ki_fcntl(fd, cmd, ap);
va_end(ap);
- return ki_fcntl(fd, cmd, arg);
+ return rtn;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
index c1cd7d004a..472eed2559 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
@@ -6,11 +6,12 @@
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_wrap.h"
+#include "nacl_io/dbgprint.h"
int ioctl(int fd, unsigned long request, ...) {
va_list ap;
va_start(ap, request);
- char* arg = va_arg(ap, char*);
+ int rtn = ki_ioctl(fd, request, ap);
va_end(ap);
- return ki_ioctl(fd, request, arg);
+ return rtn;
}
diff --git a/native_client_sdk/src/libraries/ppapi/library.dsc b/native_client_sdk/src/libraries/ppapi/library.dsc
index 620f61fdd5..506e51711b 100644
--- a/native_client_sdk/src/libraries/ppapi/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi/library.dsc
@@ -93,6 +93,7 @@
'ppb_cursor_control_dev.h',
'ppb_device_ref_dev.h',
'ppb_file_chooser_dev.h',
+ 'ppb_file_io_dev.h',
'ppb_find_dev.h',
'ppb_font_dev.h',
'ppb_gles_chromium_texture_mapping_dev.h',
diff --git a/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc b/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
index 785eaacd5f..c4fd361897 100644
--- a/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_cpp_private/library.dsc
@@ -13,8 +13,7 @@
'file_io_private.cc',
'host_resolver_private.cc',
'net_address_private.cc',
- # TODO(binji): Remove comment when this file is added.
- # 'output_protection_private.cc',
+ 'output_protection_private.cc',
'pass_file_handle.cc',
'tcp_socket_private.cc',
'tcp_server_socket_private.cc',
@@ -49,8 +48,7 @@
'file_io_private.h',
'host_resolver_private.h',
'net_address_private.h',
- # TODO(binji): Remove comment when this file is added.
- # 'output_protection_private.h',
+ 'output_protection_private.h',
'pass_file_handle.h',
'tcp_server_socket_private.h',
'tcp_socket_private.h',
diff --git a/native_client_sdk/src/resources/Makefile.example.template b/native_client_sdk/src/resources/Makefile.example.template
index 8c6375690c..3c710d7431 100644
--- a/native_client_sdk/src/resources/Makefile.example.template
+++ b/native_client_sdk/src/resources/Makefile.example.template
@@ -32,6 +32,10 @@ VALID_TOOLCHAINS := {{' '.join(tools)}}
NACL_SDK_ROOT ?= $(abspath $(CURDIR)/{{rel_sdk}})
include $(NACL_SDK_ROOT)/tools/common.mk
+[[if desc.get('SOCKET_PERMISSIONS'):]]
+CHROME_ARGS += --allow-nacl-socket-api=localhost
+[[]]
+
TARGET = {{targets[0]['NAME']}}
[[ExpandDict('DEPS', targets[0].get('DEPS', []))]]
[[ExpandDict('LIBS', targets[0].get('LIBS', []), pre_list=['$(DEPS)'])]]
diff --git a/native_client_sdk/src/resources/common.js b/native_client_sdk/src/resources/common.js
index 6a78d42801..af5e5b0579 100644
--- a/native_client_sdk/src/resources/common.js
+++ b/native_client_sdk/src/resources/common.js
@@ -433,8 +433,17 @@ document.addEventListener('DOMContentLoaded', function() {
var tc = toolchains.indexOf(searchVars.tc) !== -1 ?
searchVars.tc : toolchains[0];
- var config = configs.indexOf(searchVars.config) !== -1 ?
- searchVars.config : configs[0];
+
+ // If the config value is included in the search vars, use that.
+ // Otherwise default to Release if it is valid, or the first value if
+ // Release is not valid.
+ if (configs.indexOf(searchVars.config) !== -1)
+ var config = searchVars.config;
+ else if (configs.indexOf('Release') !== -1)
+ var config = 'Release';
+ else
+ var config = configs[0];
+
var pathFormat = body.dataset.path;
var path = pathFormat.replace('{tc}', tc).replace('{config}', config);
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.cc b/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.cc
new file mode 100644
index 0000000000..7a0a65cced
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.cc
@@ -0,0 +1,179 @@
+// 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 "echo_server.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+#ifdef WIN32
+#undef PostMessage
+#endif
+
+// Number of connections to queue up on the listening
+// socket before new ones get "Connection Refused"
+static const int kBacklog = 10;
+
+// Implement htons locally. Even though this is provided by
+// nacl_io we don't want to include nacl_io in this simple
+// example.
+static uint16_t Htons(uint16_t hostshort) {
+ uint8_t result_bytes[2];
+ result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
+ result_bytes[1] = (uint8_t) (hostshort & 0xFF);
+
+ uint16_t result;
+ memcpy(&result, result_bytes, 2);
+ return result;
+}
+
+void EchoServer::Start(uint16_t port) {
+ if (!pp::TCPSocket::IsAvailable()) {
+ Log("TCPSocket not available");
+ return;
+ }
+
+ listening_socket_ = pp::TCPSocket(instance_);
+ if (listening_socket_.is_null()) {
+ Log("Error creating TCPSocket.");
+ return;
+ }
+
+ std::ostringstream status;
+ status << "Starting server on port: " << port;
+ Log(status.str().c_str());
+
+ // Attempt to listen on all interfaces (0.0.0.0)
+ // on the given port number.
+ PP_NetAddress_IPv4 ipv4_addr = { Htons(port), { 0 } };
+ pp::NetAddress addr(instance_, ipv4_addr);
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnBindCompletion);
+ int32_t rtn = listening_socket_.Bind(addr, callback);
+ if (rtn != PP_OK_COMPLETIONPENDING) {
+ Log("Error binding listening socket.");
+ return;
+ }
+}
+
+void EchoServer::OnBindCompletion(int32_t result) {
+ if (result != PP_OK) {
+ std::ostringstream status;
+ status << "server: Bind failed with: " << result;
+ Log(status.str().c_str());
+ return;
+ }
+
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnListenCompletion);
+
+ int32_t rtn = listening_socket_.Listen(kBacklog, callback);
+ if (rtn != PP_OK_COMPLETIONPENDING) {
+ Log("server: Error listening on server socket.");
+ return;
+ }
+}
+
+void EchoServer::OnListenCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result != PP_OK) {
+ status << "server: Listen failed with: " << result;
+ Log(status.str().c_str());
+ return;
+ }
+
+ pp::NetAddress addr = listening_socket_.GetLocalAddress();
+ status << "server: Listening on: " << addr.DescribeAsString(true).AsString();
+ Log(status.str().c_str());
+
+ ready_ = true;
+ if (ready_cond_) {
+ pthread_mutex_lock(ready_lock_);
+ pthread_cond_signal(ready_cond_);
+ pthread_mutex_unlock(ready_lock_);
+ }
+
+ TryAccept();
+}
+
+void EchoServer::OnAcceptCompletion(int32_t result, pp::TCPSocket socket) {
+ std::ostringstream status;
+
+ if (result != PP_OK) {
+ status << "server: Accept failed: " << result;
+ Log(status.str().c_str());
+ return;
+ }
+
+ pp::NetAddress addr = socket.GetLocalAddress();
+ status << "server: New connection from: ";
+ status << addr.DescribeAsString(true).AsString();
+ Log(status.str().c_str());
+ incoming_socket_ = socket;
+
+ TryRead();
+}
+
+void EchoServer::OnReadCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result <= 0) {
+ if (result == 0)
+ status << "server: client disconnected";
+ else
+ status << "server: Read failed: " << result;
+ Log(status.str().c_str());
+
+ // Remove the current incoming socket and try
+ // to accept the next one.
+ incoming_socket_.Close();
+ incoming_socket_ = pp::TCPSocket();
+ TryAccept();
+ return;
+ }
+
+ status << "server: Read " << result << " bytes";
+ Log(status.str().c_str());
+
+ // Echo the bytes back to the client
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnWriteCompletion);
+ result = incoming_socket_.Write(receive_buffer_, result, callback);
+ if (result != PP_OK_COMPLETIONPENDING) {
+ status << "server: Write failed: " << result;
+ Log(status.str().c_str());
+ }
+}
+
+void EchoServer::OnWriteCompletion(int32_t result) {
+ std::ostringstream status;
+ if (result < 0) {
+ status << "server: Write failed: " << result;
+ Log(status.str().c_str());
+ return;
+ }
+
+ status << "server: Wrote " << result << " bytes";
+ Log(status.str().c_str());
+
+ // Try and read more bytes from the client
+ TryRead();
+}
+
+void EchoServer::TryRead() {
+ pp::CompletionCallback callback =
+ callback_factory_.NewCallback(&EchoServer::OnReadCompletion);
+ incoming_socket_.Read(receive_buffer_, kBufferSize, callback);
+}
+
+void EchoServer::TryAccept() {
+ pp::CompletionCallbackWithOutput<pp::TCPSocket> callback =
+ callback_factory_.NewCallbackWithOutput(
+ &EchoServer::OnAcceptCompletion);
+ listening_socket_.Accept(callback);
+}
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.h b/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.h
new file mode 100644
index 0000000000..435160d4d4
--- /dev/null
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/echo_server.h
@@ -0,0 +1,65 @@
+// 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.
+
+#ifndef ECHO_SERVER_H_
+#define ECHO_SERVER_H_
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/tcp_socket.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+static const int kBufferSize = 1024;
+
+// Simple "echo" server based on a listening pp::TCPSocket.
+// This server handles just one connection at a time and will
+// echo back whatever bytes get sent to it.
+class EchoServer {
+ typedef void (*LogFunction)(const char*);
+
+ public:
+ EchoServer(pp::Instance* instance,
+ uint16_t port,
+ LogFunction log_function=NULL,
+ pthread_cond_t* ready_cond=NULL,
+ pthread_mutex_t* ready_lock=NULL)
+ : instance_(instance),
+ callback_factory_(this),
+ ready_(false),
+ ready_cond_(ready_cond),
+ ready_lock_(ready_lock),
+ log_function_(log_function) {
+ Start(port);
+ }
+
+ protected:
+ void Start(uint16_t port);
+
+ // Callback functions
+ void OnBindCompletion(int32_t result);
+ void OnListenCompletion(int32_t result);
+ void OnAcceptCompletion(int32_t result, pp::TCPSocket socket);
+ void OnReadCompletion(int32_t result);
+ void OnWriteCompletion(int32_t result);
+
+ void TryRead();
+ void TryAccept();
+
+ void Log(const char* msg) {
+ if (log_function_)
+ log_function_(msg);
+ }
+
+ pp::Instance* instance_;
+ pp::CompletionCallbackFactory<EchoServer> callback_factory_;
+ pp::TCPSocket listening_socket_;
+ pp::TCPSocket incoming_socket_;
+
+ char receive_buffer_[kBufferSize];
+ bool ready_;
+ pthread_cond_t* ready_cond_;
+ pthread_mutex_t* ready_lock_;
+ LogFunction log_function_;
+};
+
+#endif // ECHO_SERVER_H_
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/example.dsc b/native_client_sdk/src/tests/nacl_io_socket_test/example.dsc
index 842a84ca20..ff2f05c190 100644
--- a/native_client_sdk/src/tests/nacl_io_socket_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/example.dsc
@@ -7,6 +7,8 @@
'SOURCES' : [
'main.cc',
'socket_test.cc',
+ 'echo_server.cc',
+ 'echo_server.h',
],
'DEPS': ['ppapi_simple', 'nacl_io'],
# Order matters here: gtest has a "main" function that will be used if
@@ -23,7 +25,6 @@
'DEST': 'tests',
'NAME': 'nacl_io_socket_test',
'TITLE': 'NaCl IO Socket test',
- 'PRE': '''\nCHROME_ARGS = --allow-nacl-socket-api=localhost\n''',
'SOCKET_PERMISSIONS': [
"tcp-listen:*:*",
"tcp-connect",
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/example.js b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
index 1a6a8bf868..72b21ce94e 100644
--- a/native_client_sdk/src/tests/nacl_io_socket_test/example.js
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
@@ -3,50 +3,10 @@
// found in the LICENSE file.
// Called by the common.js module.
-function runTCPEchoServer(port) {
- console.log("Starting server on TCP port: " + port);
- chrome.socket.create("tcp", {}, function(createInfo) {
- var listeningSocket = createInfo.socketId;
- chrome.socket.listen(listeningSocket,
- '127.0.0.1',
- port,
- 10,
- function(result) {
- if (result !== 0) {
- console.log("Listen failed: " + result);
- return;
- }
-
- chrome.socket.accept(listeningSocket, function(acceptInfo) {
- if (result !== 0) {
- console.log("Accept failed: " + result);
- return;
- }
-
- var newSock = acceptInfo.socketId;
-
- var readCallback = function(readInfo) {
- if (readInfo.resultCode < 0) {
- console.log("Read failed: " + readInfo.resultCode);
- chrome.socket.destroy(newSock);
- return;
- }
-
- chrome.socket.write(newSock, readInfo.data, function(writeInfo) {})
- chrome.socket.read(newSock, readCallback);
- }
-
- chrome.socket.read(newSock, readCallback);
- })
- })
- })
-}
-
function moduleDidLoad() {
// The module is not hidden by default so we can easily see if the plugin
// failed to load.
common.hideModule();
- runTCPEchoServer(4006);
}
var currentTestEl = null;
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc b/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
index e9391d0595..c0c8c9c660 100644
--- a/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
@@ -14,43 +14,53 @@
#include <map>
#include <string>
+#include "echo_server.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/ostypes.h"
+#include "ppapi/cpp/message_loop.h"
+#include "ppapi_simple/ps.h"
#ifdef PROVIDES_SOCKET_API
using namespace nacl_io;
using namespace sdk_util;
-// No error expected
-#define ENONE 0
#define LOCAL_HOST 0x7F000001
#define PORT1 4006
#define PORT2 4007
#define ANY_PORT 0
-
namespace {
-class SocketTest : public ::testing::Test {
- public:
- SocketTest() : sock1(0), sock2(0) {}
- ~SocketTest() {
- EXPECT_EQ(0, close(sock1));
- EXPECT_EQ(0, close(sock2));
- }
+void IP4ToSockAddr(uint32_t ip, uint16_t port, struct sockaddr_in* addr) {
+ memset(addr, 0, sizeof(*addr));
- void IP4ToSockAddr(uint32_t ip, uint16_t port, struct sockaddr_in* addr) {
- memset(addr, 0, sizeof(*addr));
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(port);
+ addr->sin_addr.s_addr = htonl(ip);
+}
+
+void SetNonBlocking(int sock) {
+ int flags = fcntl(sock, F_GETFL);
+ ASSERT_NE(-1, flags);
+ flags |= O_NONBLOCK;
+ ASSERT_EQ(0, fcntl(sock, F_SETFL, flags));
+ ASSERT_EQ(flags, fcntl(sock, F_GETFL));
+}
+
+class SocketTest : public ::testing::Test {
+ public:
+ SocketTest() : sock1(-1), sock2(-1) {}
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- addr->sin_addr.s_addr = htonl(ip);
+ void TearDown() {
+ if (sock1 != -1)
+ EXPECT_EQ(0, close(sock1));
+ if (sock2 != -1)
+ EXPECT_EQ(0, close(sock2));
}
int Bind(int fd, uint32_t ip, uint16_t port) {
@@ -58,18 +68,13 @@ class SocketTest : public ::testing::Test {
socklen_t addrlen = sizeof(addr);
IP4ToSockAddr(ip, port, &addr);
- int err = bind(fd, (sockaddr*) &addr, addrlen);
+ int err = bind(fd, (sockaddr*)&addr, addrlen);
if (err == -1)
return errno;
return 0;
}
- void SetupPorts() {
- EXPECT_EQ(Bind(sock1, LOCAL_HOST, 0), ENONE);
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, 0), ENONE);
- }
-
public:
int sock1;
int sock2;
@@ -77,26 +82,86 @@ class SocketTest : public ::testing::Test {
class SocketTestUDP : public SocketTest {
public:
- SocketTestUDP() {
+ SocketTestUDP() {}
+
+ void SetUp() {
sock1 = socket(AF_INET, SOCK_DGRAM, 0);
sock2 = socket(AF_INET, SOCK_DGRAM, 0);
- EXPECT_LT(-1, sock1);
- EXPECT_LT(-1, sock2);
+ EXPECT_GT(sock1, -1);
+ EXPECT_GT(sock2, -1);
}
};
class SocketTestTCP : public SocketTest {
public:
- SocketTestTCP() {
+ SocketTestTCP() {}
+
+ void SetUp() {
sock1 = socket(AF_INET, SOCK_STREAM, 0);
sock2 = socket(AF_INET, SOCK_STREAM, 0);
- EXPECT_LT(-1, sock1);
- EXPECT_LT(-1, sock2);
+ EXPECT_GT(sock1, -1);
+ EXPECT_GT(sock2, -1);
}
};
+class SocketTestWithServer : public ::testing::Test {
+ public:
+ SocketTestWithServer() : instance_(PSGetInstanceId()) {
+ pthread_mutex_init(&ready_lock_, NULL);
+ pthread_cond_init(&ready_cond_, NULL);
+ }
+
+ void ServerThreadMain() {
+ loop_.AttachToCurrentThread();
+ pp::Instance instance(PSGetInstanceId());
+ EchoServer server(&instance, PORT1, ServerLog, &ready_cond_, &ready_lock_);
+ loop_.Run();
+ }
+
+ static void* ServerThreadMainStatic(void* arg) {
+ SocketTestWithServer* test = (SocketTestWithServer*)arg;
+ test->ServerThreadMain();
+ return NULL;
+ }
+
+ void SetUp() {
+ loop_ = pp::MessageLoop(&instance_);
+ pthread_mutex_lock(&ready_lock_);
+
+ // Start an echo server on a background thread.
+ pthread_create(&server_thread_, NULL, ServerThreadMainStatic, this);
+
+ // Wait for thread to signal that it is ready to accept connections.
+ pthread_cond_wait(&ready_cond_, &ready_lock_);
+ pthread_mutex_unlock(&ready_lock_);
+
+ sock_ = socket(AF_INET, SOCK_STREAM, 0);
+ EXPECT_GT(sock_, -1);
+ }
+
+ void TearDown() {
+ // Stop the echo server and the background thread it runs on
+ loop_.PostQuit(true);
+ pthread_join(server_thread_, NULL);
+ ASSERT_EQ(0, close(sock_));
+ }
+
+ static void ServerLog(const char* msg) {
+ // Uncomment to see logs of echo server on stdout
+ //printf("server: %s\n", msg);
+ }
+
+ protected:
+ int sock_;
+ pp::MessageLoop loop_;
+ pp::Instance instance_;
+ pthread_cond_t ready_cond_;
+ pthread_mutex_t ready_lock_;
+ pthread_t server_thread_;
+};
+
} // namespace
TEST(SocketTestSimple, Socket) {
@@ -125,20 +190,19 @@ TEST(SocketTestSimple, Socket) {
TEST_F(SocketTestUDP, Bind) {
// Bind away.
- EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), ENONE);
+ EXPECT_EQ(0, Bind(sock1, LOCAL_HOST, PORT1));
// Invalid to rebind a socket.
- EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), EINVAL);
+ EXPECT_EQ(EINVAL, Bind(sock1, LOCAL_HOST, PORT1));
// Addr in use.
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT1), EADDRINUSE);
+ EXPECT_EQ(EADDRINUSE, Bind(sock2, LOCAL_HOST, PORT1));
// Bind with a wildcard.
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, ANY_PORT), ENONE);
+ EXPECT_EQ(0, Bind(sock2, LOCAL_HOST, ANY_PORT));
// Invalid to rebind after wildcard
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT1), EINVAL);
-
+ EXPECT_EQ(EINVAL, Bind(sock2, LOCAL_HOST, PORT1));
}
TEST_F(SocketTestUDP, SendRcv) {
@@ -148,8 +212,8 @@ TEST_F(SocketTestUDP, SendRcv) {
memset(outbuf, 1, sizeof(outbuf));
memset(inbuf, 0, sizeof(inbuf));
- EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), ENONE);
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT2), ENONE);
+ EXPECT_EQ(0, Bind(sock1, LOCAL_HOST, PORT1));
+ EXPECT_EQ(0, Bind(sock2, LOCAL_HOST, PORT2));
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
@@ -174,25 +238,25 @@ TEST_F(SocketTestUDP, SendRcv) {
EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
}
-const size_t queue_size = 65536 * 8;
+const size_t kQueueSize = 65536 * 8;
TEST_F(SocketTestUDP, FullFifo) {
char outbuf[16 * 1024];
- EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), ENONE);
- EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT2), ENONE);
+ EXPECT_EQ(0, Bind(sock1, LOCAL_HOST, PORT1));
+ EXPECT_EQ(0, Bind(sock2, LOCAL_HOST, PORT2));
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
IP4ToSockAddr(LOCAL_HOST, PORT2, &addr);
size_t total = 0;
- while (total < queue_size * 8) {
+ while (total < kQueueSize * 8) {
int len = sendto(sock1, outbuf, sizeof(outbuf), MSG_DONTWAIT,
(sockaddr *) &addr, addrlen);
if (len <= 0) {
EXPECT_EQ(-1, len);
- EXPECT_EQ(errno, EWOULDBLOCK);
+ EXPECT_EQ(EWOULDBLOCK, errno);
break;
}
@@ -202,35 +266,207 @@ TEST_F(SocketTestUDP, FullFifo) {
}
}
- EXPECT_GT(total, queue_size -1);
- EXPECT_LT(total, queue_size * 8);
+ EXPECT_GT(total, kQueueSize - 1);
+ EXPECT_LT(total, kQueueSize * 8);
}
-// TODO(noelallen) BUG=294412
-// Re-enable testing on bots when server sockets are available.
-TEST_F(SocketTestTCP, DISABLED_Connect) {
+TEST_F(SocketTestWithServer, TCPConnect) {
char outbuf[256];
char inbuf[512];
memset(outbuf, 1, sizeof(outbuf));
+
+ sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+
+ IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
+
+ ASSERT_EQ(0, connect(sock_, (sockaddr*) &addr, addrlen))
+ << "Failed with " << errno << ": " << strerror(errno) << "\n";
+
+ // Send two different messages to the echo server and verify the
+ // response matches.
+ strcpy(outbuf, "hello");
memset(inbuf, 0, sizeof(inbuf));
+ ASSERT_EQ(sizeof(outbuf), write(sock_, outbuf, sizeof(outbuf)));
+ ASSERT_EQ(sizeof(outbuf), read(sock_, inbuf, sizeof(inbuf)));
+ EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
+
+ strcpy(outbuf, "world");
+ memset(inbuf, 0, sizeof(inbuf));
+ ASSERT_EQ(sizeof(outbuf), write(sock_, outbuf, sizeof(outbuf)));
+ ASSERT_EQ(sizeof(outbuf), read(sock_, inbuf, sizeof(inbuf)));
+ EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
+}
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- EXPECT_NE(-1, sock);
+TEST_F(SocketTestWithServer, TCPConnectNonBlock) {
+ char outbuf[256];
+ //char inbuf[512];
+
+ memset(outbuf, 1, sizeof(outbuf));
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
- int err = connect(sock, (sockaddr*) &addr, addrlen);
- EXPECT_EQ(ENONE, err) << "Failed with errno: " << errno << "\n";
+ SetNonBlocking(sock_);
+ ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
+ ASSERT_EQ(EINPROGRESS, errno)
+ << "expected EINPROGRESS but got: " << strerror(errno) << "\n";
+ ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
+ ASSERT_EQ(EALREADY, errno);
- EXPECT_EQ(sizeof(outbuf), write(sock, outbuf, sizeof(outbuf)));
- EXPECT_EQ(sizeof(outbuf), read(sock, inbuf, sizeof(inbuf)));
+ // Wait for the socket connection to complete using poll()
+ struct pollfd pollfd = { sock_, POLLIN|POLLOUT, 0 };
+ ASSERT_EQ(1, poll(&pollfd, 1, -1));
+ ASSERT_EQ(POLLOUT, pollfd.revents);
- // Now they should be the same
- EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
+ // Attempts to connect again should yield EISCONN
+ ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
+ ASSERT_EQ(EISCONN, errno);
+
+ // And SO_ERROR should be 0.
+}
+
+TEST_F(SocketTest, Getsockopt) {
+ sock1 = socket(AF_INET, SOCK_STREAM, 0);
+ EXPECT_GT(sock1, -1);
+ int socket_error = 99;
+ socklen_t len = sizeof(socket_error);
+
+ // Test for valid option (SO_ERROR) which should be 0 when a socket
+ // is first created.
+ ASSERT_EQ(0, getsockopt(sock1, SOL_SOCKET, SO_ERROR, &socket_error, &len));
+ ASSERT_EQ(0, socket_error);
+ ASSERT_EQ(sizeof(socket_error), len);
+
+ int reuse = 0;
+ len = sizeof(reuse);
+ ASSERT_EQ(0, getsockopt(sock1, SOL_SOCKET, SO_REUSEADDR, &reuse, &len));
+ ASSERT_EQ(1, reuse);
+
+ // Test for an invalid option (-1)
+ ASSERT_EQ(-1, getsockopt(sock1, SOL_SOCKET, -1, &socket_error, &len));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+}
+
+TEST_F(SocketTest, Setsockopt) {
+ sock1 = socket(AF_INET, SOCK_STREAM, 0);
+ EXPECT_GT(sock1, -1);
+
+ // It should not be possible to set SO_ERROR using setsockopt.
+ int socket_error = 10;
+ socklen_t len = sizeof(socket_error);
+ ASSERT_EQ(-1, setsockopt(sock1, SOL_SOCKET, SO_ERROR, &socket_error, len));
+ ASSERT_EQ(ENOPROTOOPT, errno);
+
+ int reuse = 1;
+ len = sizeof(reuse);
+ ASSERT_EQ(0, setsockopt(sock1, SOL_SOCKET, SO_REUSEADDR, &reuse, len));
+}
+
+TEST_F(SocketTestUDP, Listen) {
+ EXPECT_EQ(-1, listen(sock1, 10));
+ EXPECT_EQ(errno, ENOTSUP);
+}
+
+TEST_F(SocketTestTCP, Listen) {
+ sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+
+ int server_sock = sock1;
+
+ // Accept before listen should fail
+ ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
+
+ // Listen should fail on unbound socket
+ ASSERT_EQ(-1, listen(server_sock, 10));
+
+ // Bind and Listen
+ ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
+ ASSERT_EQ(0, listen(server_sock, 10))
+ << "listen failed with: " << strerror(errno);
+
+ // Connect to listening socket
+ int client_sock = sock2;
+ IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
+ addrlen = sizeof(addr);
+ ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
+ << "Failed with " << errno << ": " << strerror(errno) << "\n";
+
+ ASSERT_EQ(5, send(client_sock, "hello", 5, 0));
+
+ // Pass in addrlen that is larger than our actual address to make
+ // sure that it is correctly set back to sizeof(sockaddr_in)
+ addrlen = sizeof(addr) + 10;
+ int new_socket = accept(server_sock, (sockaddr*)&addr, &addrlen);
+ ASSERT_GT(new_socket, -1)
+ << "accept failed with " << errno << ": " << strerror(errno) << "\n";
+
+ // Verify addr and addrlen were set correctly
+ ASSERT_EQ(addrlen, sizeof(sockaddr_in));
+ sockaddr_in client_addr;
+ ASSERT_EQ(0, getsockname(client_sock, (sockaddr*)&client_addr, &addrlen));
+ ASSERT_EQ(client_addr.sin_family, addr.sin_family);
+ ASSERT_EQ(client_addr.sin_port, addr.sin_port);
+ ASSERT_EQ(client_addr.sin_addr.s_addr, addr.sin_addr.s_addr);
+
+ char inbuf[512];
+ ASSERT_EQ(5, recv(new_socket, inbuf, 5, 0));
+ ASSERT_EQ(0, close(new_socket));
+}
+
+TEST_F(SocketTestTCP, ListenNonBlocking) {
+ int server_sock = sock1;
+
+ // Set non-blocking
+ SetNonBlocking(server_sock);
+
+ // bind and listen
+ ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
+ ASSERT_EQ(0, listen(server_sock, 10))
+ << "listen failed with: " << strerror(errno);
+
+ // Accept should fail with EAGAIN since there is no incomming
+ // connection.
+ sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+ ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
+ ASSERT_EQ(EAGAIN, errno);
+
+ // If we poll the listening socket it should also return
+ // not readable to indicate that no connections are available
+ // to accept.
+ struct pollfd pollfd = { server_sock, POLLIN|POLLOUT, 0 };
+ ASSERT_EQ(0, poll(&pollfd, 1, 0));
+
+ // Connect to listening socket
+ int client_sock = sock2;
+ IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
+ addrlen = sizeof(addr);
+ ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
+ << "Failed with " << errno << ": " << strerror(errno) << "\n";
+
+ // Not poll again but with an infintie timeout.
+ pollfd.fd = server_sock;
+ pollfd.events = POLLIN | POLLOUT;
+ ASSERT_EQ(1, poll(&pollfd, 1, -1));
+
+ // Now non-blocking accept should return the new socket
+ int new_socket = accept(server_sock, (sockaddr*)&addr, &addrlen);
+ ASSERT_NE(-1, new_socket)
+ << "accept failed with: " << strerror(errno) << "\n";
+ ASSERT_EQ(0, close(new_socket));
+
+ // Accept calls should once again fail with EAGAIN
+ ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
+ ASSERT_EQ(EAGAIN, errno);
+
+ // As should polling the listening socket
+ pollfd.fd = server_sock;
+ pollfd.events = POLLIN | POLLOUT;
+ ASSERT_EQ(0, poll(&pollfd, 1, 0));
}
#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/tests/nacl_io_test/event_test.cc b/native_client_sdk/src/tests/nacl_io_test/event_test.cc
index 3ba14c5cbe..f04ec08d4c 100644
--- a/native_client_sdk/src/tests/nacl_io_test/event_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/event_test.cc
@@ -105,7 +105,7 @@ class EmitterTest : public ::testing::Test {
waiting_++;
EXPECT_EQ(0, listener.WaitOnEvent(POLLIN, -1));
emitter_.ClearEvents_Locked(POLLIN);
- signaled_ ++;
+ signaled_++;
return NULL;
}
@@ -123,9 +123,6 @@ TEST_F(EmitterTest, MultiThread) {
for (int a=0; a <NUM_THREADS; a++)
CreateThread();
- sleep(1);
- EXPECT_EQ(0, signaled_);
-
{
AUTO_LOCK(emitter_.GetLock());
@@ -133,10 +130,15 @@ TEST_F(EmitterTest, MultiThread) {
while(waiting_ < NUM_THREADS)
pthread_cond_wait(&multi_cond_, emitter_.GetLock().mutex());
+ ASSERT_EQ(0, signaled_);
+
emitter_.RaiseEvents_Locked(POLLIN);
}
- sleep(1);
+ // sleep for 50 milliseconds
+ struct timespec sleeptime = { 0, 50 * 1000 * 1000 };
+ nanosleep(&sleeptime, NULL);
+
EXPECT_EQ(1, signaled_);
{
@@ -144,7 +146,7 @@ TEST_F(EmitterTest, MultiThread) {
emitter_.RaiseEvents_Locked(POLLIN);
}
- sleep(1);
+ nanosleep(&sleeptime, NULL);
EXPECT_EQ(2, signaled_);
// Clean up remaining threads.
@@ -154,6 +156,21 @@ TEST_F(EmitterTest, MultiThread) {
}
}
+TEST(EventListenerPollTest, WaitForAny) {
+ ScopedEventEmitter emitter1(new EventEmitter());
+ ScopedEventEmitter emitter2(new EventEmitter());
+ ScopedEventEmitter emitter3(new EventEmitter());
+ EventListenerPoll listener;
+ EventRequest requests[3] = {
+ { emitter1, 0, 0 },
+ { emitter2, 0, 0 },
+ { emitter3, 0, 0 },
+ };
+ Error error = listener.WaitOnAny(requests,
+ sizeof(requests)/sizeof(requests[0]),
+ 1);
+ ASSERT_EQ(ETIMEDOUT, error);
+}
TEST(PipeTest, Listener) {
const char hello[] = "Hello World.";
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_mock.h b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_mock.h
index ab770074eb..45b5c85bb7 100644
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_mock.h
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_mock.h
@@ -26,15 +26,16 @@ class KernelProxyMock : public nacl_io::KernelProxy {
MOCK_METHOD1(close, int(int));
MOCK_METHOD1(dup, int(int));
MOCK_METHOD2(dup2, int(int, int));
+ MOCK_METHOD2(fchmod, int(int, int));
MOCK_METHOD3(fchown, int(int, uid_t, gid_t));
- MOCK_METHOD3(fcntl, int(int, int, char*));
+ MOCK_METHOD3(fcntl, int(int, int, va_list));
MOCK_METHOD2(ftruncate, int(int, off_t));
MOCK_METHOD2(fstat, int(int, struct stat*));
MOCK_METHOD1(fsync, int(int));
MOCK_METHOD2(getcwd, char*(char*, size_t));
MOCK_METHOD3(getdents, int(int, void*, unsigned int));
MOCK_METHOD1(getwd, char*(char*));
- MOCK_METHOD3(ioctl, int(int, int, char*));
+ MOCK_METHOD3(ioctl, int(int, int, va_list));
MOCK_METHOD1(isatty, int(int));
MOCK_METHOD2(kill, int(int, int));
MOCK_METHOD3(lchown, int(const char*, uid_t, gid_t));
@@ -44,15 +45,16 @@ class KernelProxyMock : public nacl_io::KernelProxy {
MOCK_METHOD6(mmap, void*(void*, size_t, int, int, int, size_t));
MOCK_METHOD5(mount, int(const char*, const char*, const char*, unsigned long,
const void*));
+ MOCK_METHOD2(munmap, int(void*, size_t));
MOCK_METHOD2(open, int(const char*, int));
MOCK_METHOD1(pipe, int(int[2]));
MOCK_METHOD3(read, ssize_t(int, void*, size_t));
MOCK_METHOD1(remove, int(const char*));
MOCK_METHOD1(rmdir, int(const char*));
- MOCK_METHOD2(signal, sighandler_t(int, sighandler_t));
MOCK_METHOD2(sigset, sighandler_t(int, sighandler_t));
MOCK_METHOD2(stat, int(const char*, struct stat*));
MOCK_METHOD2(symlink, int(const char*, const char*));
+ MOCK_METHOD2(tcflush, int(int, int));
MOCK_METHOD2(tcgetattr, int(int, struct termios*));
MOCK_METHOD3(tcsetattr, int(int, int, const struct termios*));
MOCK_METHOD1(umount, int(const char*));
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 65bdb4553f..d3ec3c9c0d 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
@@ -9,25 +9,25 @@
#include "kernel_proxy_mock.h"
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_wrap.h"
+#include "nacl_io/osmman.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/ostermios.h"
using namespace nacl_io;
using ::testing::_;
+using ::testing::DoAll;
using ::testing::Return;
using ::testing::StrEq;
namespace {
-static const int DUMMY_FD = 5678;
-
-#define COMPARE_FIELD(f) \
- if (arg->f != statbuf->f) { \
- *result_listener << "mismatch of field \""#f"\". " \
- "expected: " << statbuf->f << \
- " actual: " << arg->f; \
- return false; \
+#define COMPARE_FIELD(f) \
+ if (arg->f != statbuf->f) { \
+ *result_listener << "mismatch of field \"" #f \
+ "\". " \
+ "expected: " << statbuf->f << " actual: " << arg->f; \
+ return false; \
}
MATCHER_P(IsEqualToStatbuf, statbuf, "") {
@@ -60,7 +60,6 @@ ACTION_P(SetStat, statbuf) {
arg1->st_atime = statbuf->st_atime;
arg1->st_mtime = statbuf->st_mtime;
arg1->st_ctime = statbuf->st_ctime;
- return 0;
}
void MakeDummyStatbuf(struct stat* statbuf) {
@@ -78,120 +77,154 @@ void MakeDummyStatbuf(struct stat* statbuf) {
statbuf->st_ctime = 11;
}
+const int kDummyInt = 0xdedbeef;
+const int kDummyInt2 = 0xcabba6e;
+const int kDummyInt3 = 0xf00ba4;
+const int kDummyInt4 = 0xabacdba;
+const size_t kDummySizeT = 0x60067e;
+const char* kDummyConstChar = "foobar";
+const char* kDummyConstChar2 = "g00gl3";
+const char* kDummyConstChar3 = "fr00gl3";
+const void* kDummyVoidPtr = "blahblah";
const uid_t kDummyUid = 1001;
const gid_t kDummyGid = 1002;
class KernelWrapTest : public ::testing::Test {
public:
- KernelWrapTest() {
+ KernelWrapTest() {}
+
+ virtual void SetUp() {
// Initializing the KernelProxy opens stdin/stdout/stderr.
EXPECT_CALL(mock, open(_, _))
- .WillOnce(Return(0))
- .WillOnce(Return(1))
- .WillOnce(Return(2));
+ .WillOnce(Return(0))
+ .WillOnce(Return(1))
+ .WillOnce(Return(2));
// And will call mount / and /dev.
EXPECT_CALL(mock, mount(_, _, _, _, _))
- .WillOnce(Return(0))
- .WillOnce(Return(0));
+ .WillOnce(Return(0))
+ .WillOnce(Return(0));
ki_init(&mock);
}
- ~KernelWrapTest() {
- ki_uninit();
- }
+ virtual void TearDown() { ki_uninit(); }
KernelProxyMock mock;
};
} // namespace
-
TEST_F(KernelWrapTest, access) {
- EXPECT_CALL(mock, access(StrEq("access"), 12)).Times(1);
- access("access", 12);
+ EXPECT_CALL(mock, access(kDummyConstChar, kDummyInt))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, access(kDummyConstChar, kDummyInt));
}
TEST_F(KernelWrapTest, chdir) {
- EXPECT_CALL(mock, chdir(StrEq("chdir"))).Times(1);
- chdir("chdir");
+ EXPECT_CALL(mock, chdir(kDummyConstChar)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, chdir(kDummyConstChar));
}
TEST_F(KernelWrapTest, chmod) {
- EXPECT_CALL(mock, chmod(StrEq("chmod"), 23)).Times(1);
- chmod("chmod", 23);
+ EXPECT_CALL(mock, chmod(kDummyConstChar, kDummyInt))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, chmod(kDummyConstChar, kDummyInt));
}
TEST_F(KernelWrapTest, chown) {
- uid_t uid = kDummyUid;
- gid_t gid = kDummyGid;
- EXPECT_CALL(mock, chown(StrEq("chown"), uid, gid)).Times(1);
- chown("chown", uid, gid);
+ EXPECT_CALL(mock, chown(kDummyConstChar, kDummyUid, kDummyGid))
+ .WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, chown(kDummyConstChar, kDummyUid, kDummyGid));
}
TEST_F(KernelWrapTest, close) {
- EXPECT_CALL(mock, close(34)).Times(1);
- close(34);
+ // The way we wrap close does not support returning arbitrary values, so we
+ // test 0 and -1.
+ EXPECT_CALL(mock, close(kDummyInt))
+ .WillOnce(Return(0))
+ .WillOnce(Return(-1));
+
+ EXPECT_EQ(0, close(kDummyInt));
+ EXPECT_EQ(-1, close(kDummyInt));
}
TEST_F(KernelWrapTest, dup) {
- EXPECT_CALL(mock, dup(DUMMY_FD)).Times(1);
- dup(DUMMY_FD);
+ EXPECT_CALL(mock, dup(kDummyInt)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, dup(kDummyInt));
}
TEST_F(KernelWrapTest, dup2) {
- EXPECT_CALL(mock, dup2(DUMMY_FD, 234)).Times(1);
- dup2(DUMMY_FD, 234);
+ // The way we wrap dup2 does not support returning aribtrary values, only -1
+ // or the value of the new fd.
+ EXPECT_CALL(mock, dup2(kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt2))
+ .WillOnce(Return(-1));
+ EXPECT_EQ(kDummyInt2, dup2(kDummyInt, kDummyInt2));
+ EXPECT_EQ(-1, dup2(kDummyInt, kDummyInt2));
+}
+
+TEST_F(KernelWrapTest, fchmod) {
+ EXPECT_CALL(mock, fchmod(kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, fchmod(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, fchown) {
- uid_t uid = kDummyUid;
- gid_t gid = kDummyGid;
- EXPECT_CALL(mock, fchown(DUMMY_FD, uid, gid)).Times(1);
- fchown(DUMMY_FD, uid, gid);
+ EXPECT_CALL(mock, fchown(kDummyInt, kDummyUid, kDummyGid))
+ .WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, fchown(kDummyInt, kDummyUid, kDummyGid));
}
TEST_F(KernelWrapTest, fcntl) {
char buffer[] = "fcntl";
- EXPECT_CALL(mock, fcntl(012, 345, StrEq("fcntl"))).Times(1);
- fcntl(012, 345, buffer);
+ EXPECT_CALL(mock, fcntl(kDummyInt, kDummyInt2, _))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, fcntl(kDummyInt, kDummyInt2, buffer));
}
TEST_F(KernelWrapTest, fstat) {
+ // The way we wrap fstat does not support returning aribtrary values, only 0
+ // or -1.
struct stat in_statbuf;
MakeDummyStatbuf(&in_statbuf);
- EXPECT_CALL(mock, fstat(DUMMY_FD, _))
- .Times(1)
- .WillOnce(SetStat(&in_statbuf));
+ EXPECT_CALL(mock, fstat(kDummyInt, _))
+ .WillOnce(DoAll(SetStat(&in_statbuf), Return(0)))
+ .WillOnce(Return(-1));
struct stat out_statbuf;
- fstat(DUMMY_FD, &out_statbuf);
+ EXPECT_EQ(0, fstat(kDummyInt, &out_statbuf));
EXPECT_THAT(&in_statbuf, IsEqualToStatbuf(&out_statbuf));
+ EXPECT_EQ(-1, fstat(kDummyInt, &out_statbuf));
}
TEST_F(KernelWrapTest, ftruncate) {
- EXPECT_CALL(mock, ftruncate(456, 0)).Times(1);
- ftruncate(456, 0);
+ EXPECT_CALL(mock, ftruncate(kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, ftruncate(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, fsync) {
- EXPECT_CALL(mock, fsync(345)).Times(1);
- fsync(345);
+ EXPECT_CALL(mock, fsync(kDummyInt)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, fsync(kDummyInt));
}
TEST_F(KernelWrapTest, getcwd) {
- EXPECT_CALL(mock, getcwd(StrEq("getcwd"), 1)).Times(1);
+ char result[] = "getcwd_result";
char buffer[] = "getcwd";
- getcwd(buffer, 1);
+ EXPECT_CALL(mock, getcwd(buffer, kDummySizeT)).WillOnce(Return(result));
+ EXPECT_EQ(result, getcwd(buffer, kDummySizeT));
}
TEST_F(KernelWrapTest, getdents) {
#ifndef __GLIBC__
// TODO(sbc): Find a way to test the getdents wrapper under glibc.
- // It looks like the only way to excerside it is to call readdir(2).
+ // It looks like the only way to exercise it is to call readdir(2).
// There is an internal glibc function __getdents that will call the
// IRT but that cannot be accessed from here as glibc does not export it.
- EXPECT_CALL(mock, getdents(456, NULL, 567)).WillOnce(Return(678));
- EXPECT_EQ(getdents(456, NULL, 567), 678);
+ int dummy_val;
+ void* void_ptr = &dummy_val;
+ EXPECT_CALL(mock, getdents(kDummyInt, void_ptr, kDummyInt2))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, getdents(kDummyInt, void_ptr, kDummyInt2));
#endif
}
@@ -200,9 +233,10 @@ TEST_F(KernelWrapTest, getdents) {
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
TEST_F(KernelWrapTest, getwd) {
- EXPECT_CALL(mock, getwd(StrEq("getwd"))).Times(1);
+ char result[] = "getwd_result";
char buffer[] = "getwd";
- getwd(buffer);
+ EXPECT_CALL(mock, getwd(buffer)).WillOnce(Return(result));
+ EXPECT_EQ(result, getwd(buffer));
}
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
@@ -210,235 +244,384 @@ TEST_F(KernelWrapTest, getwd) {
TEST_F(KernelWrapTest, ioctl) {
char buffer[] = "ioctl";
- EXPECT_CALL(mock, ioctl(012, 345, StrEq("ioctl"))).Times(1);
- ioctl(012, 345, buffer);
+ EXPECT_CALL(mock, ioctl(kDummyInt, kDummyInt2, _))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, ioctl(kDummyInt, kDummyInt2, buffer));
}
TEST_F(KernelWrapTest, isatty) {
- EXPECT_CALL(mock, isatty(678)).Times(1);
- isatty(678);
+ EXPECT_CALL(mock, isatty(kDummyInt)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, isatty(kDummyInt));
}
TEST_F(KernelWrapTest, kill) {
- EXPECT_CALL(mock, kill(22, 33)).Times(1);
- kill(22, 33);
+ EXPECT_CALL(mock, kill(kDummyInt, kDummyInt2)).WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, kill(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, lchown) {
- uid_t uid = kDummyUid;
- gid_t gid = kDummyGid;
- EXPECT_CALL(mock, lchown(StrEq("lchown"), uid, gid)).Times(1);
- lchown("lchown", uid, gid);
+ EXPECT_CALL(mock, lchown(kDummyConstChar, kDummyUid, kDummyGid))
+ .WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, lchown(kDummyConstChar, kDummyUid, kDummyGid));
+}
+
+TEST_F(KernelWrapTest, link) {
+ EXPECT_CALL(mock, link(kDummyConstChar, kDummyConstChar2))
+ .WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, link(kDummyConstChar, kDummyConstChar2));
}
TEST_F(KernelWrapTest, lseek) {
- EXPECT_CALL(mock, lseek(789, 891, 912)).Times(1);
- lseek(789, 891, 912);
+ EXPECT_CALL(mock, lseek(kDummyInt, kDummyInt2, kDummyInt3))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(kDummyInt4, lseek(kDummyInt, kDummyInt2, kDummyInt3));
}
TEST_F(KernelWrapTest, mkdir) {
#if defined(WIN32)
- EXPECT_CALL(mock, mkdir(StrEq("mkdir"), 0777)).Times(1);
- mkdir("mkdir");
+ EXPECT_CALL(mock, mkdir(kDummyConstChar, 0777)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, mkdir(kDummyConstChar));
#else
- EXPECT_CALL(mock, mkdir(StrEq("mkdir"), 1234)).Times(1);
- mkdir("mkdir", 1234);
+ EXPECT_CALL(mock, mkdir(kDummyConstChar, kDummyInt))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, mkdir(kDummyConstChar, kDummyInt));
#endif
}
+TEST_F(KernelWrapTest, mmap) {
+ // We only wrap mmap if |flags| has the MAP_ANONYMOUS bit unset.
+ int flags = kDummyInt2 & ~MAP_ANONYMOUS;
+
+ const size_t kDummySizeT2 = 0xbadf00d;
+ int dummy1 = 123;
+ int dummy2 = 456;
+ void* kDummyVoidPtr1 = &dummy1;
+ void* kDummyVoidPtr2 = &dummy2;
+ EXPECT_CALL(mock,
+ mmap(kDummyVoidPtr1,
+ kDummySizeT,
+ kDummyInt,
+ flags,
+ kDummyInt3,
+ kDummySizeT2)).WillOnce(Return(kDummyVoidPtr2));
+ EXPECT_EQ(kDummyVoidPtr2,
+ mmap(kDummyVoidPtr1,
+ kDummySizeT,
+ kDummyInt,
+ flags,
+ kDummyInt3,
+ kDummySizeT2));
+}
+
TEST_F(KernelWrapTest, mount) {
EXPECT_CALL(mock,
- mount(StrEq("mount1"), StrEq("mount2"), StrEq("mount3"), 2345, NULL))
- .Times(1);
- mount("mount1", "mount2", "mount3", 2345, NULL);
+ mount(kDummyConstChar,
+ kDummyConstChar2,
+ kDummyConstChar3,
+ kDummyInt,
+ kDummyVoidPtr)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2,
+ mount(kDummyConstChar,
+ kDummyConstChar2,
+ kDummyConstChar3,
+ kDummyInt,
+ kDummyVoidPtr));
+}
+
+TEST_F(KernelWrapTest, munmap) {
+ // The way we wrap munmap, calls the "real" mmap as well as the intercepted
+ // one. The result returned is from the "real" mmap.
+ int dummy1 = 123;
+ void* kDummyVoidPtr = &dummy1;
+ size_t kDummySizeT = sizeof(kDummyVoidPtr);
+ EXPECT_CALL(mock, munmap(kDummyVoidPtr, kDummySizeT));
+ munmap(kDummyVoidPtr, kDummySizeT);
}
+
TEST_F(KernelWrapTest, open) {
- EXPECT_CALL(mock, open(StrEq("open"), 3456)).Times(1);
- open("open", 3456);
+ EXPECT_CALL(mock, open(kDummyConstChar, kDummyInt))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, open(kDummyConstChar, kDummyInt));
}
TEST_F(KernelWrapTest, pipe) {
- int fds[2] = { 1, 2 };
-
- EXPECT_CALL(mock, pipe(fds)).Times(1);
- pipe(fds);
+ int fds[] = {1, 2};
+ EXPECT_CALL(mock, pipe(fds)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, pipe(fds));
}
TEST_F(KernelWrapTest, read) {
- EXPECT_CALL(mock, read(4567, NULL, 5678)).Times(1);
- read(4567, NULL, 5678);
+ int dummy_value;
+ void* dummy_void_ptr = &dummy_value;
+ EXPECT_CALL(mock, read(kDummyInt, dummy_void_ptr, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, read(kDummyInt, dummy_void_ptr, kDummyInt2));
}
#ifdef __GLIBC__
TEST_F(KernelWrapTest, remove) {
- EXPECT_CALL(mock, remove(StrEq("remove"))).Times(1);
- remove("remove");
+ EXPECT_CALL(mock, remove(kDummyConstChar)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, remove(kDummyConstChar));
}
#endif
TEST_F(KernelWrapTest, rmdir) {
- EXPECT_CALL(mock, rmdir(StrEq("rmdir"))).Times(1);
- rmdir("rmdir");
+ EXPECT_CALL(mock, rmdir(kDummyConstChar)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, rmdir(kDummyConstChar));
}
-static void handler(int) {
-}
+static void new_handler(int) {}
+static void old_handler(int) {}
TEST_F(KernelWrapTest, sigset) {
- EXPECT_CALL(mock, sigset(22, handler)).Times(1);
- sigset(22, handler);
+ EXPECT_CALL(mock, sigset(kDummyInt, new_handler))
+ .WillOnce(Return(old_handler));
+ EXPECT_EQ(&old_handler, sigset(kDummyInt, new_handler));
}
TEST_F(KernelWrapTest, signal) {
- EXPECT_CALL(mock, sigset(22, handler)).Times(1);
- signal(22, handler);
+ // KernelIntercept forwards calls to signal to KernelProxy::sigset.
+ EXPECT_CALL(mock, sigset(kDummyInt, new_handler))
+ .WillOnce(Return(old_handler));
+ EXPECT_EQ(&old_handler, signal(kDummyInt, new_handler));
}
TEST_F(KernelWrapTest, stat) {
+ // The way we wrap stat does not support returning aribtrary values, only 0
+ // or -1.
struct stat in_statbuf;
MakeDummyStatbuf(&in_statbuf);
- EXPECT_CALL(mock, stat(StrEq("stat"), _))
- .Times(1)
- .WillOnce(SetStat(&in_statbuf));
+ EXPECT_CALL(mock, stat(StrEq(kDummyConstChar), _))
+ .WillOnce(DoAll(SetStat(&in_statbuf), Return(0)))
+ .WillOnce(Return(-1));
struct stat out_statbuf;
- stat("stat", &out_statbuf);
+ EXPECT_EQ(0, stat(kDummyConstChar, &out_statbuf));
EXPECT_THAT(&in_statbuf, IsEqualToStatbuf(&out_statbuf));
+ EXPECT_EQ(-1, stat(kDummyConstChar, &out_statbuf));
+}
+
+TEST_F(KernelWrapTest, symlink) {
+ EXPECT_CALL(mock, symlink(kDummyConstChar, kDummyConstChar2))
+ .WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, symlink(kDummyConstChar, kDummyConstChar2));
+}
+
+TEST_F(KernelWrapTest, tcflush) {
+ EXPECT_CALL(mock, tcflush(kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, tcflush(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, tcgetattr) {
struct termios term;
- EXPECT_CALL(mock, tcgetattr(DUMMY_FD, &term)).Times(1);
- tcgetattr(DUMMY_FD, &term);
+ EXPECT_CALL(mock, tcgetattr(kDummyInt, &term)).WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, tcgetattr(kDummyInt, &term));
}
TEST_F(KernelWrapTest, tcsetattr) {
struct termios term;
- EXPECT_CALL(mock, tcsetattr(DUMMY_FD, 0, &term)).Times(1);
- tcsetattr(DUMMY_FD, 0, &term);
+ EXPECT_CALL(mock, tcsetattr(kDummyInt, kDummyInt2, &term))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, tcsetattr(kDummyInt, kDummyInt2, &term));
}
TEST_F(KernelWrapTest, umount) {
- EXPECT_CALL(mock, umount(StrEq("umount"))).Times(1);
- umount("umount");
+ EXPECT_CALL(mock, umount(kDummyConstChar)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, umount(kDummyConstChar));
}
TEST_F(KernelWrapTest, unlink) {
- EXPECT_CALL(mock, unlink(StrEq("unlink"))).Times(1);
- unlink("unlink");
+ EXPECT_CALL(mock, unlink(kDummyConstChar)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, unlink(kDummyConstChar));
}
TEST_F(KernelWrapTest, utime) {
const struct utimbuf* times = NULL;
- EXPECT_CALL(mock, utime(StrEq("utime"), times));
- utime("utime", times);
+ EXPECT_CALL(mock, utime(kDummyConstChar, times)).WillOnce(Return(kDummyInt));
+ EXPECT_EQ(kDummyInt, utime(kDummyConstChar, times));
}
TEST_F(KernelWrapTest, write) {
- EXPECT_CALL(mock, write(6789, NULL, 7891)).Times(1);
- write(6789, NULL, 7891);
+ EXPECT_CALL(mock, write(kDummyInt, kDummyVoidPtr, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, write(kDummyInt, kDummyVoidPtr, kDummyInt2));
}
#ifdef PROVIDES_SOCKET_API
TEST_F(KernelWrapTest, poll) {
- EXPECT_CALL(mock, poll(NULL, 5, -1));
- poll(NULL, 5, -1);
+ struct pollfd fds;
+ EXPECT_CALL(mock, poll(&fds, kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, poll(&fds, kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, select) {
- EXPECT_CALL(mock, select(123, NULL, NULL, NULL, NULL));
- select(123, NULL, NULL, NULL, NULL);
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ EXPECT_CALL(mock, select(kDummyInt, &readfds, &writefds, &exceptfds, NULL))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2,
+ select(kDummyInt, &readfds, &writefds, &exceptfds, NULL));
}
// Socket Functions
TEST_F(KernelWrapTest, accept) {
- EXPECT_CALL(mock, accept(DUMMY_FD, NULL, NULL)).Times(1);
- accept(DUMMY_FD, NULL, NULL);
+ struct sockaddr addr;
+ socklen_t len;
+ EXPECT_CALL(mock, accept(kDummyInt, &addr, &len))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, accept(kDummyInt, &addr, &len));
}
TEST_F(KernelWrapTest, bind) {
- EXPECT_CALL(mock, bind(DUMMY_FD, NULL, 456)).Times(1);
- bind(DUMMY_FD, NULL, 456);
+ struct sockaddr addr;
+ EXPECT_CALL(mock, bind(kDummyInt, &addr, kDummyInt2))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, bind(kDummyInt, &addr, kDummyInt2));
}
TEST_F(KernelWrapTest, connect) {
- EXPECT_CALL(mock, connect(DUMMY_FD, NULL, 456)).Times(1);
- connect(DUMMY_FD, NULL, 456);
+ struct sockaddr addr;
+ EXPECT_CALL(mock, connect(kDummyInt, &addr, kDummyInt2))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, connect(kDummyInt, &addr, kDummyInt2));
}
TEST_F(KernelWrapTest, gethostbyname) {
- EXPECT_CALL(mock, gethostbyname(NULL)).Times(1);
- gethostbyname(NULL);
+ struct hostent result;
+ EXPECT_CALL(mock, gethostbyname(kDummyConstChar)).WillOnce(Return(&result));
+ EXPECT_EQ(&result, gethostbyname(kDummyConstChar));
}
TEST_F(KernelWrapTest, getpeername) {
- EXPECT_CALL(mock, getpeername(DUMMY_FD, NULL, NULL)).Times(1);
- getpeername(DUMMY_FD, NULL, NULL);
+ struct sockaddr addr;
+ socklen_t len;
+ EXPECT_CALL(mock, getpeername(kDummyInt, &addr, &len))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, getpeername(kDummyInt, &addr, &len));
}
TEST_F(KernelWrapTest, getsockname) {
- EXPECT_CALL(mock, getsockname(DUMMY_FD, NULL, NULL)).Times(1);
- getsockname(DUMMY_FD, NULL, NULL);
+ struct sockaddr addr;
+ socklen_t len;
+ EXPECT_CALL(mock, getsockname(kDummyInt, &addr, &len))
+ .WillOnce(Return(kDummyInt2));
+ EXPECT_EQ(kDummyInt2, getsockname(kDummyInt, &addr, &len));
}
TEST_F(KernelWrapTest, getsockopt) {
- EXPECT_CALL(mock, getsockopt(DUMMY_FD, 456, 789, NULL, NULL)).Times(1);
- getsockopt(DUMMY_FD, 456, 789, NULL, NULL);
+ int dummy_val;
+ void* dummy_void_ptr = &dummy_val;
+ socklen_t len;
+ EXPECT_CALL(
+ mock, getsockopt(kDummyInt, kDummyInt2, kDummyInt3, dummy_void_ptr, &len))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(
+ kDummyInt4,
+ getsockopt(kDummyInt, kDummyInt2, kDummyInt3, dummy_void_ptr, &len));
}
TEST_F(KernelWrapTest, listen) {
- EXPECT_CALL(mock, listen(DUMMY_FD, 456)).Times(1);
- listen(DUMMY_FD, 456);
+ EXPECT_CALL(mock, listen(kDummyInt, kDummyInt2)).WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, listen(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, recv) {
- EXPECT_CALL(mock, recv(DUMMY_FD, NULL, 456, 789)).Times(1);
- recv(DUMMY_FD, NULL, 456, 789);
+ int dummy_val;
+ void* dummy_void_ptr = &dummy_val;
+ EXPECT_CALL(mock, recv(kDummyInt, dummy_void_ptr, kDummySizeT, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3,
+ recv(kDummyInt, dummy_void_ptr, kDummySizeT, kDummyInt2));
}
TEST_F(KernelWrapTest, recvfrom) {
- EXPECT_CALL(mock, recvfrom(DUMMY_FD, NULL, 456, 789, NULL, NULL)).Times(1);
- recvfrom(DUMMY_FD, NULL, 456, 789, NULL, NULL);
+ int dummy_val;
+ void* dummy_void_ptr = &dummy_val;
+ struct sockaddr addr;
+ socklen_t len;
+ EXPECT_CALL(
+ mock,
+ recvfrom(kDummyInt, dummy_void_ptr, kDummyInt2, kDummyInt3, &addr, &len))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(
+ kDummyInt4,
+ recvfrom(kDummyInt, dummy_void_ptr, kDummyInt2, kDummyInt3, &addr, &len));
}
TEST_F(KernelWrapTest, recvmsg) {
- EXPECT_CALL(mock, recvmsg(DUMMY_FD, NULL, 456)).Times(1);
- recvmsg(DUMMY_FD, NULL, 456);
+ struct msghdr msg;
+ EXPECT_CALL(mock, recvmsg(kDummyInt, &msg, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, recvmsg(kDummyInt, &msg, kDummyInt2));
}
TEST_F(KernelWrapTest, send) {
- EXPECT_CALL(mock, send(DUMMY_FD, NULL, 456, 789)).Times(1);
- send(DUMMY_FD, NULL, 456, 789);
+ EXPECT_CALL(mock, send(kDummyInt, kDummyVoidPtr, kDummySizeT, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3,
+ send(kDummyInt, kDummyVoidPtr, kDummySizeT, kDummyInt2));
}
TEST_F(KernelWrapTest, sendto) {
- EXPECT_CALL(mock, sendto(DUMMY_FD, NULL, 456, 789, NULL, 314)).Times(1);
- sendto(DUMMY_FD, NULL, 456, 789, NULL, 314);
+ const socklen_t kDummySockLen = 0x50cc5;
+ struct sockaddr addr;
+ EXPECT_CALL(mock,
+ sendto(kDummyInt,
+ kDummyVoidPtr,
+ kDummyInt2,
+ kDummyInt3,
+ &addr,
+ kDummySockLen)).WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(kDummyInt4,
+ sendto(kDummyInt,
+ kDummyVoidPtr,
+ kDummyInt2,
+ kDummyInt3,
+ &addr,
+ kDummySockLen));
}
TEST_F(KernelWrapTest, sendmsg) {
- EXPECT_CALL(mock, sendmsg(DUMMY_FD, NULL, 456)).Times(1);
- sendmsg(DUMMY_FD, NULL, 456);
+ struct msghdr msg;
+ EXPECT_CALL(mock, sendmsg(kDummyInt, &msg, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, sendmsg(kDummyInt, &msg, kDummyInt2));
}
TEST_F(KernelWrapTest, setsockopt) {
- EXPECT_CALL(mock, setsockopt(DUMMY_FD, 456, 789, NULL, 314)).Times(1);
- setsockopt(DUMMY_FD, 456, 789, NULL, 314);
+ const socklen_t kDummySockLen = 0x50cc5;
+ EXPECT_CALL(
+ mock,
+ setsockopt(
+ kDummyInt, kDummyInt2, kDummyInt3, kDummyVoidPtr, kDummySockLen))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(
+ kDummyInt4,
+ setsockopt(
+ kDummyInt, kDummyInt2, kDummyInt3, kDummyVoidPtr, kDummySockLen));
}
TEST_F(KernelWrapTest, shutdown) {
- EXPECT_CALL(mock, shutdown(DUMMY_FD, 456)).Times(1);
- shutdown(DUMMY_FD, 456);
+ EXPECT_CALL(mock, shutdown(kDummyInt, kDummyInt2))
+ .WillOnce(Return(kDummyInt3));
+ EXPECT_EQ(kDummyInt3, shutdown(kDummyInt, kDummyInt2));
}
TEST_F(KernelWrapTest, socket) {
- EXPECT_CALL(mock, socket(DUMMY_FD, 456, 789)).Times(1);
- socket(DUMMY_FD, 456, 789);
+ EXPECT_CALL(mock, socket(kDummyInt, kDummyInt2, kDummyInt3))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(kDummyInt4, socket(kDummyInt, kDummyInt2, kDummyInt3));
}
TEST_F(KernelWrapTest, socketpair) {
- EXPECT_CALL(mock, socketpair(DUMMY_FD, 456, 789, NULL)).Times(1);
- socketpair(DUMMY_FD, 456, 789, NULL);
+ int dummy_val;
+ EXPECT_CALL(mock, socketpair(kDummyInt, kDummyInt2, kDummyInt3, &dummy_val))
+ .WillOnce(Return(kDummyInt4));
+ EXPECT_EQ(kDummyInt4,
+ socketpair(kDummyInt, kDummyInt2, kDummyInt3, &dummy_val));
}
-#endif // PROVIDES_SOCKET_API
+#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_html5fs_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_html5fs_test.cc
index 906e5ca589..c7fa6ccee4 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_html5fs_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_html5fs_test.cc
@@ -17,6 +17,7 @@
#include <windows.h> // For Sleep()
#endif
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount_html5fs.h"
#include "nacl_io/osdirent.h"
#include "nacl_io/osunistd.h"
@@ -199,12 +200,13 @@ TEST_F(MountHtml5FsTest, OpenForCreate) {
EXPECT_EQ(ENOENT, mnt->Access(path, F_OK));
ScopedMountNode node;
- EXPECT_EQ(0, mnt->Open(path, O_CREAT | O_RDWR, &node));
+ ASSERT_EQ(0, mnt->Open(path, O_CREAT | O_RDWR, &node));
// Write some data.
char contents[] = "contents";
int bytes_written = 0;
- EXPECT_EQ(0, node->Write(0, &contents[0], strlen(contents), &bytes_written));
+ EXPECT_EQ(0, node->Write(HandleAttr(), &contents[0], strlen(contents),
+ &bytes_written));
EXPECT_EQ(strlen(contents), bytes_written);
// Create again.
@@ -234,7 +236,6 @@ TEST_F(MountHtml5FsTest, Read) {
EXPECT_TRUE(
ppapi_html5_.filesystem_template()->AddFile("/file", contents, NULL));
EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
-
StringMap_t map;
ScopedRef<MountHtml5FsForTesting> mnt(
new MountHtml5FsForTesting(map, &ppapi_));
@@ -244,28 +245,33 @@ TEST_F(MountHtml5FsTest, Read) {
char buffer[10] = {0};
int bytes_read = 0;
- EXPECT_EQ(0, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ HandleAttr attr;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(strlen(contents), bytes_read);
EXPECT_STREQ(contents, buffer);
// Read nothing past the end of the file.
- EXPECT_EQ(0, node->Read(100, &buffer[0], sizeof(buffer), &bytes_read));
+ attr.offs = 100;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(0, bytes_read);
// Read part of the data.
- EXPECT_EQ(0, node->Read(4, &buffer[0], sizeof(buffer), &bytes_read));
+ attr.offs = 4;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
ASSERT_EQ(strlen(contents) - 4, bytes_read);
buffer[bytes_read] = 0;
EXPECT_STREQ("ents", buffer);
// Writing should fail.
int bytes_written = 1; // Set to a non-zero value.
- EXPECT_EQ(EACCES, node->Write(0, &buffer[0], sizeof(buffer), &bytes_written));
+ attr.offs = 0;
+ EXPECT_EQ(EACCES, node->Write(attr, &buffer[0], sizeof(buffer),
+ &bytes_written));
EXPECT_EQ(0, bytes_written);
// Reading from a directory should fail.
EXPECT_EQ(0, mnt->Open(Path("/dir"), O_RDONLY, &node));
- EXPECT_EQ(EISDIR, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(EISDIR, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
}
TEST_F(MountHtml5FsTest, Write) {
@@ -284,24 +290,27 @@ TEST_F(MountHtml5FsTest, Write) {
// Reading should fail.
char buffer[10];
int bytes_read = 1; // Set to a non-zero value.
- EXPECT_EQ(EACCES, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ HandleAttr attr;
+ EXPECT_EQ(EACCES, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(0, bytes_read);
// Reopen as read-write.
ASSERT_EQ(0, mnt->Open(Path("/file"), O_RDWR, &node));
int bytes_written = 1; // Set to a non-zero value.
- EXPECT_EQ(0, node->Write(3, "struct", 6, &bytes_written));
+ attr.offs = 3;
+ EXPECT_EQ(0, node->Write(attr, "struct", 6, &bytes_written));
EXPECT_EQ(6, bytes_written);
- EXPECT_EQ(0, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ attr.offs = 0;
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(9, bytes_read);
buffer[bytes_read] = 0;
EXPECT_STREQ("construct", buffer);
// Writing to a directory should fail.
EXPECT_EQ(0, mnt->Open(Path("/dir"), O_RDWR, &node));
- EXPECT_EQ(EISDIR, node->Write(0, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(EISDIR, node->Write(attr, &buffer[0], sizeof(buffer), &bytes_read));
}
TEST_F(MountHtml5FsTest, GetStat) {
@@ -378,19 +387,20 @@ TEST_F(MountHtml5FsTest, FTruncate) {
ScopedMountNode node;
ASSERT_EQ(0, mnt->Open(Path("/file"), O_RDWR, &node));
+ HandleAttr attr;
char buffer[10] = {0};
int bytes_read = 0;
// First make the file shorter...
EXPECT_EQ(0, node->FTruncate(4));
- EXPECT_EQ(0, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(4, bytes_read);
buffer[bytes_read] = 0;
EXPECT_STREQ("cont", buffer);
// Now make the file longer...
EXPECT_EQ(0, node->FTruncate(8));
- EXPECT_EQ(0, node->Read(0, &buffer[0], sizeof(buffer), &bytes_read));
+ EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
EXPECT_EQ(8, bytes_read);
buffer[bytes_read] = 0;
EXPECT_STREQ("cont\0\0\0\0", buffer);
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
index 013c546098..f9aba9b6ec 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_http_test.cc
@@ -11,6 +11,7 @@
#include <sys/types.h>
#include "mock_util.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/mount_http.h"
#include "nacl_io/mount_node_dir.h"
@@ -444,14 +445,16 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadCached) {
ExpectHeaders("");
SetResponse(200, "Content-Length: 42\n");
SetResponseBody("Here is some response text. And some more.");
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("Here is s", &buf[0]);
ResetMocks();
// Further reads should be cached.
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("Here is s", &buf[0]);
- EXPECT_EQ(0, node_->Read(10, buf, sizeof(buf) - 1, &result_bytes));
+ attr.offs = 10;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("me respon", &buf[0]);
EXPECT_EQ(0, node_->GetSize(&result_size));
@@ -482,14 +485,16 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadCachedNoContentLength) {
char buf[10];
memset(&buf[0], 0, sizeof(buf));
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("Here is s", &buf[0]);
ResetMocks();
// Further reads should be cached.
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("Here is s", &buf[0]);
- EXPECT_EQ(0, node_->Read(10, buf, sizeof(buf) - 1, &result_bytes));
+ attr.offs = 10;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_STREQ("me respon", &buf[0]);
EXPECT_EQ(0, node_->GetSize(&result_size));
@@ -517,7 +522,8 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadCachedUnderrun) {
ExpectHeaders("");
SetResponse(200, "Content-Length: 100\n");
SetResponseBody("abcdefghijklmnopqrstuvwxyz");
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("abcdefghi", &buf[0]);
ResetMocks();
@@ -547,7 +553,9 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadCachedOverrun) {
ExpectHeaders("");
SetResponse(200, "Content-Length: 15\n");
SetResponseBody("01234567890123456789");
- EXPECT_EQ(0, node_->Read(10, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ attr.offs = 10;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(5, result_bytes);
EXPECT_STREQ("01234", &buf[0]);
ResetMocks();
@@ -575,7 +583,8 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadPartial) {
ExpectHeaders("Range: bytes=0-8\n");
SetResponse(206, "Content-Length: 9\nContent-Range: bytes=0-8\n");
SetResponseBody("012345678");
- EXPECT_EQ(0, node_->Read(0, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("012345678", &buf[0]);
ResetMocks();
@@ -585,7 +594,8 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadPartial) {
ExpectHeaders("Range: bytes=10-18\n");
SetResponse(206, "Content-Length: 9\nContent-Range: bytes=10-18\n");
SetResponseBody("abcdefghi");
- EXPECT_EQ(0, node_->Read(10, buf, sizeof(buf) - 1, &result_bytes));
+ attr.offs = 10;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("abcdefghi", &buf[0]);
}
@@ -609,7 +619,9 @@ TEST_F(MountHttpNodeTest, DISABLED_ReadPartialNoServerSupport) {
ExpectHeaders("Range: bytes=10-18\n");
SetResponse(200, "Content-Length: 20\n");
SetResponseBody("0123456789abcdefghij");
- EXPECT_EQ(0, node_->Read(10, buf, sizeof(buf) - 1, &result_bytes));
+ HandleAttr attr;
+ attr.offs = 10;
+ EXPECT_EQ(0, node_->Read(attr, buf, sizeof(buf) - 1, &result_bytes));
EXPECT_EQ(sizeof(buf) - 1, result_bytes);
EXPECT_STREQ("abcdefghi", &buf[0]);
}
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_node_mock.h b/native_client_sdk/src/tests/nacl_io_test/mount_node_mock.h
index 3354682c7b..2edd76725b 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_node_mock.h
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_node_mock.h
@@ -7,11 +7,13 @@
#include "gmock/gmock.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount.h"
class MountNodeMock : public nacl_io::MountNode {
public:
typedef nacl_io::Error Error;
+ typedef nacl_io::HandleAttr HandleAttr;
typedef nacl_io::ScopedMountNode ScopedMountNode;
explicit MountNodeMock(nacl_io::Mount*);
@@ -23,9 +25,9 @@ class MountNodeMock : public nacl_io::MountNode {
MOCK_METHOD1(FTruncate, Error(off_t));
MOCK_METHOD4(GetDents, Error(size_t, struct dirent*, size_t, int*));
MOCK_METHOD1(GetStat, Error(struct stat*));
- MOCK_METHOD2(Ioctl, Error(int, char*));
- MOCK_METHOD4(Read, Error(size_t, void*, size_t, int*));
- MOCK_METHOD4(Write, Error(size_t, const void*, size_t, int*));
+ MOCK_METHOD2(Ioctl, Error(int, va_list));
+ MOCK_METHOD4(Read, Error(const HandleAttr&, void*, size_t, int*));
+ MOCK_METHOD4(Write, Error(const HandleAttr&, const void*, size_t, int*));
MOCK_METHOD6(MMap, Error(void*, size_t, int, int, size_t, void**));
MOCK_METHOD0(GetLinks, int());
MOCK_METHOD0(GetMode, int());
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_node_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_node_test.cc
index 58e0e1b8ec..f2d638d42f 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_node_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_node_test.cc
@@ -12,8 +12,10 @@
#include "nacl_io/error.h"
#include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/mount_dev.h"
+#include "nacl_io/mount_mem.h"
#include "nacl_io/mount_node.h"
#include "nacl_io/mount_node_dir.h"
#include "nacl_io/mount_node_mem.h"
@@ -25,11 +27,21 @@ using namespace nacl_io;
static int s_AllocNum = 0;
-class MockMemory : public MountNodeMem {
+class MockMount : public MountMem {
public:
- MockMemory() : MountNodeMem(NULL) { s_AllocNum++; }
+ MockMount() {
+ StringMap_t map;
+ EXPECT_EQ(0, Init(1, map, NULL));
+ }
+
+ int num_nodes() { return inode_pool_.size(); }
+};
- ~MockMemory() { s_AllocNum--; }
+class MockNode : public MountNodeMem {
+ public:
+ MockNode() : MountNodeMem(NULL) { s_AllocNum++; }
+
+ ~MockNode() { s_AllocNum--; }
using MountNodeMem::Init;
using MountNodeMem::AddChild;
@@ -50,7 +62,7 @@ class MockDir : public MountNodeDir {
};
TEST(MountNodeTest, File) {
- MockMemory file;
+ MockNode file;
ScopedMountNode result_node;
size_t result_size = 0;
int result_bytes = 0;
@@ -72,18 +84,19 @@ TEST(MountNodeTest, File) {
for (size_t a = 0; a < sizeof(buf1); a++)
buf1[a] = a;
memset(buf2, 0, sizeof(buf2));
+ HandleAttr attr;
EXPECT_EQ(0, file.GetSize(&result_size));
EXPECT_EQ(0, result_size);
- EXPECT_EQ(0, file.Read(0, buf2, sizeof(buf2), &result_bytes));
+ EXPECT_EQ(0, file.Read(attr, buf2, sizeof(buf2), &result_bytes));
EXPECT_EQ(0, result_bytes);
EXPECT_EQ(0, file.GetSize(&result_size));
EXPECT_EQ(0, result_size);
- EXPECT_EQ(0, file.Write(0, buf1, sizeof(buf1), &result_bytes));
+ EXPECT_EQ(0, file.Write(attr, buf1, sizeof(buf1), &result_bytes));
EXPECT_EQ(sizeof(buf1), result_bytes);
EXPECT_EQ(0, file.GetSize(&result_size));
EXPECT_EQ(sizeof(buf1), result_size);
- EXPECT_EQ(0, file.Read(0, buf2, sizeof(buf2), &result_bytes));
+ EXPECT_EQ(0, file.Read(attr, buf2, sizeof(buf2), &result_bytes));
EXPECT_EQ(sizeof(buf1), result_bytes);
EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
@@ -102,7 +115,7 @@ TEST(MountNodeTest, File) {
}
TEST(MountNodeTest, FTruncate) {
- MockMemory file;
+ MockNode file;
size_t result_size = 0;
int result_bytes = 0;
@@ -114,9 +127,10 @@ TEST(MountNodeTest, FTruncate) {
data[a] = a;
memset(buffer, 0, sizeof(buffer));
memset(zero, 0, sizeof(zero));
+ HandleAttr attr;
// Write the data to the file.
- ASSERT_EQ(0, file.Write(0, data, sizeof(data), &result_bytes));
+ ASSERT_EQ(0, file.Write(attr, data, sizeof(data), &result_bytes));
ASSERT_EQ(sizeof(data), result_bytes);
// Double the size of the file.
@@ -125,12 +139,13 @@ TEST(MountNodeTest, FTruncate) {
EXPECT_EQ(sizeof(data) * 2, result_size);
// Read the first half of the file, it shouldn't have changed.
- EXPECT_EQ(0, file.Read(0, buffer, sizeof(buffer), &result_bytes));
+ EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
EXPECT_EQ(sizeof(buffer), result_bytes);
EXPECT_EQ(0, memcmp(buffer, data, sizeof(buffer)));
// Read the second half of the file, it should be all zeroes.
- EXPECT_EQ(0, file.Read(sizeof(data), buffer, sizeof(buffer), &result_bytes));
+ attr.offs = sizeof(data);
+ EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
EXPECT_EQ(sizeof(buffer), result_bytes);
EXPECT_EQ(0, memcmp(buffer, zero, sizeof(buffer)));
@@ -140,11 +155,37 @@ TEST(MountNodeTest, FTruncate) {
EXPECT_EQ(100, result_size);
// Data should still be there.
- EXPECT_EQ(0, file.Read(0, buffer, sizeof(buffer), &result_bytes));
+ attr.offs = 0;
+ EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
EXPECT_EQ(100, result_bytes);
EXPECT_EQ(0, memcmp(buffer, data, 100));
}
+TEST(MountNodeTest, Fcntl) {
+ MockNode* node = new MockNode();
+ ScopedMount mnt(new MockMount());
+ ScopedMountNode file(node);
+ KernelHandle handle(mnt, file);
+ ASSERT_EQ(0, handle.Init(O_CREAT|O_APPEND));
+
+ // Test F_GETFL
+ ASSERT_EQ(0, node->Init(S_IREAD | S_IWRITE));
+ int flags = 0;
+ ASSERT_EQ(0, handle.Fcntl(F_GETFL, &flags));
+ ASSERT_EQ(O_CREAT|O_APPEND, flags);
+
+ // Test F_SETFL
+ // Test adding of O_NONBLOCK
+ flags = O_NONBLOCK|O_APPEND;
+ ASSERT_EQ(0, handle.Fcntl(F_SETFL, NULL, flags));
+ ASSERT_EQ(0, handle.Fcntl(F_GETFL, &flags));
+ ASSERT_EQ(O_CREAT|O_APPEND|O_NONBLOCK, flags);
+
+ // Clearing of O_APPEND should generate EPERM;
+ flags = O_NONBLOCK;
+ ASSERT_EQ(EPERM, handle.Fcntl(F_SETFL, NULL, flags));
+}
+
TEST(MountNodeTest, Directory) {
s_AllocNum = 0;
MockDir root;
@@ -166,13 +207,14 @@ TEST(MountNodeTest, Directory) {
// IO operations should fail
char buf1[1024];
+ HandleAttr attr;
EXPECT_EQ(0, root.GetSize(&result_size));
EXPECT_EQ(0, result_size);
- EXPECT_EQ(EISDIR, root.Read(0, buf1, sizeof(buf1), &result_bytes));
- EXPECT_EQ(EISDIR, root.Write(0, buf1, sizeof(buf1), &result_bytes));
+ EXPECT_EQ(EISDIR, root.Read(attr, buf1, sizeof(buf1), &result_bytes));
+ EXPECT_EQ(EISDIR, root.Write(attr, buf1, sizeof(buf1), &result_bytes));
// Test directory operations
- MockMemory* raw_file = new MockMemory;
+ MockNode* raw_file = new MockNode;
EXPECT_EQ(0, raw_file->Init(S_IREAD | S_IWRITE));
ScopedMountNode file(raw_file);
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_node_tty_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_node_tty_test.cc
index dc4798bf46..02adb153ab 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_node_tty_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_node_tty_test.cc
@@ -47,7 +47,7 @@ class TtyTest : public ::testing::Test {
TEST_F(TtyTest, InvalidIoctl) {
// 123 is not a valid ioctl request.
- EXPECT_EQ(EINVAL, dev_tty_->Ioctl(123, NULL));
+ EXPECT_EQ(EINVAL, dev_tty_->Ioctl(123));
}
TEST_F(TtyTest, TtyInput) {
@@ -69,19 +69,19 @@ TEST_F(TtyTest, TtyInput) {
memset(backup_buffer, 'a', 100);
// Now we actually send the data
- EXPECT_EQ(0, dev_tty_->Ioctl(TIOCNACLINPUT,
- reinterpret_cast<char*>(&packaged_message)));
+ EXPECT_EQ(0, dev_tty_->Ioctl(TIOCNACLINPUT, &packaged_message));
// We read a small chunk first to ensure it doesn't give us
// more than we ask for.
- EXPECT_EQ(0, dev_tty_->Read(0, buffer, 5, &bytes_read));
+ HandleAttr attrs;
+ EXPECT_EQ(0, dev_tty_->Read(attrs, buffer, 5, &bytes_read));
EXPECT_EQ(bytes_read, 5);
EXPECT_EQ(0, memcmp(message.data(), buffer, 5));
EXPECT_EQ(0, memcmp(buffer + 5, backup_buffer + 5, 95));
// Now we ask for more data than is left in the tty, to ensure
// it doesn't give us more than is there.
- EXPECT_EQ(0, dev_tty_->Read(0, buffer + 5, 95, &bytes_read));
+ EXPECT_EQ(0, dev_tty_->Read(attrs, buffer + 5, 95, &bytes_read));
EXPECT_EQ(bytes_read, message.size() - 5);
EXPECT_EQ(0, memcmp(message.data(), buffer, message.size()));
EXPECT_EQ(0, memcmp(buffer + message.size(),
@@ -106,7 +106,8 @@ TEST_F(TtyTest, TtyOutput) {
int bytes_written = 10;
const char* message = "hello\n";
int message_len = strlen(message);
- EXPECT_EQ(EIO, dev_tty_->Write(0, message, message_len, &bytes_written));
+ HandleAttr attrs;
+ EXPECT_EQ(EIO, dev_tty_->Write(attrs, message, message_len, &bytes_written));
// Setup output handler with user_data to record calls.
user_data_t user_data;
@@ -117,21 +118,27 @@ TEST_F(TtyTest, TtyOutput) {
handler.handler = output_handler;
handler.user_data = &user_data;
- EXPECT_EQ(0, dev_tty_->Ioctl(TIOCNACLOUTPUT,
- reinterpret_cast<char*>(&handler)));
+ EXPECT_EQ(0, dev_tty_->Ioctl(TIOCNACLOUTPUT, &handler));
- EXPECT_EQ(0, dev_tty_->Write(0, message, message_len, &bytes_written));
+ EXPECT_EQ(0, dev_tty_->Write(attrs, message, message_len, &bytes_written));
EXPECT_EQ(message_len, bytes_written);
EXPECT_EQ(message_len, user_data.output_count);
EXPECT_EQ(0, strncmp(user_data.output_buf, message, message_len));
}
+static int ki_ioctl_wrapper(int fd, int request, ...) {
+ va_list ap;
+ va_start(ap, request);
+ int rtn = ki_ioctl(fd, request, ap);
+ va_end(ap);
+ return rtn;
+}
+
static int TtyWrite(int fd, const char* string) {
struct tioc_nacl_input_string input;
- input.buffer =string;
+ input.buffer = string;
input.length = strlen(input.buffer);
- char* ioctl_arg = reinterpret_cast<char*>(&input);
- return ki_ioctl(fd, TIOCNACLINPUT, ioctl_arg);
+ return ki_ioctl_wrapper(fd, TIOCNACLINPUT, &input);
}
// Returns:
@@ -242,8 +249,7 @@ void sighandler(int sig) {
TEST_F(TtyTest, WindowSize) {
// Get current window size
struct winsize old_winsize = { 0 };
- ASSERT_EQ(0, dev_tty_->Ioctl(TIOCGWINSZ,
- reinterpret_cast<char*>(&old_winsize)));
+ ASSERT_EQ(0, dev_tty_->Ioctl(TIOCGWINSZ, &old_winsize));
// Install signal handler
sighandler_t new_handler = sighandler;
@@ -254,8 +260,7 @@ TEST_F(TtyTest, WindowSize) {
struct winsize winsize;
winsize.ws_col = 100;
winsize.ws_row = 200;
- EXPECT_EQ(0, dev_tty_->Ioctl(TIOCSWINSZ,
- reinterpret_cast<char*>(&winsize)));
+ EXPECT_EQ(0, dev_tty_->Ioctl(TIOCSWINSZ, &winsize));
EXPECT_EQ(g_recieved_signal, SIGWINCH);
// Restore old signal handler
@@ -264,14 +269,12 @@ TEST_F(TtyTest, WindowSize) {
// Verify new window size can be queried correctly.
winsize.ws_col = 0;
winsize.ws_row = 0;
- EXPECT_EQ(0, dev_tty_->Ioctl(TIOCGWINSZ,
- reinterpret_cast<char*>(&winsize)));
+ EXPECT_EQ(0, dev_tty_->Ioctl(TIOCGWINSZ, &winsize));
EXPECT_EQ(winsize.ws_col, 100);
EXPECT_EQ(winsize.ws_row, 200);
// Restore original windows size.
- EXPECT_EQ(0, dev_tty_->Ioctl(TIOCSWINSZ,
- reinterpret_cast<char*>(&old_winsize)));
+ EXPECT_EQ(0, dev_tty_->Ioctl(TIOCSWINSZ, &old_winsize));
}
/*
@@ -284,7 +287,7 @@ static void* resize_thread_main(void* arg) {
struct winsize winsize;
winsize.ws_col = 100;
winsize.ws_row = 200;
- ki_ioctl(*tty_fd, TIOCSWINSZ, reinterpret_cast<char*>(&winsize));
+ ki_ioctl_wrapper(*tty_fd, TIOCSWINSZ, &winsize);
return NULL;
}
diff --git a/native_client_sdk/src/tests/nacl_io_test/mount_test.cc b/native_client_sdk/src/tests/nacl_io_test/mount_test.cc
index b5e3909224..f256624437 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mount_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mount_test.cc
@@ -11,6 +11,7 @@
#include "gtest/gtest.h"
#include "mount_dev_mock.h"
#include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
#include "nacl_io/mount.h"
#include "nacl_io/mount_mem.h"
#include "nacl_io/osdirent.h"
@@ -93,14 +94,16 @@ TEST(MountTest, Sanity) {
EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/foo"), O_RDWR));
EXPECT_EQ(2, mnt.num_nodes());
+ HandleAttr attrs;
+
// Attempt to READ/WRITE
EXPECT_EQ(0, file->GetSize(&result_size));
EXPECT_EQ(0, result_size);
- EXPECT_EQ(0, file->Write(0, buf1, sizeof(buf1), &result_bytes));
+ EXPECT_EQ(0, file->Write(attrs, buf1, sizeof(buf1), &result_bytes));
EXPECT_EQ(sizeof(buf1), result_bytes);
EXPECT_EQ(0, file->GetSize(&result_size));
EXPECT_EQ(sizeof(buf1), result_size);
- EXPECT_EQ(0, file->Read(0, buf1, sizeof(buf1), &result_bytes));
+ EXPECT_EQ(0, file->Read(attrs, buf1, sizeof(buf1), &result_bytes));
EXPECT_EQ(sizeof(buf1), result_bytes);
EXPECT_EQ(2, mnt.num_nodes());
EXPECT_EQ(2, file->RefCount());
@@ -207,13 +210,14 @@ TEST(MountTest, DevNull) {
// Writing to /dev/null should write everything.
const char msg[] = "Dummy test message.";
- EXPECT_EQ(0, dev_null->Write(0, &msg[0], strlen(msg), &result_bytes));
+ HandleAttr attrs;
+ EXPECT_EQ(0, dev_null->Write(attrs, &msg[0], strlen(msg), &result_bytes));
EXPECT_EQ(strlen(msg), result_bytes);
// Reading from /dev/null should read nothing.
const int kBufferLength = 100;
char buffer[kBufferLength];
- EXPECT_EQ(0, dev_null->Read(0, &buffer[0], kBufferLength, &result_bytes));
+ EXPECT_EQ(0, dev_null->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
EXPECT_EQ(0, result_bytes);
}
@@ -228,8 +232,9 @@ TEST(MountTest, DevZero) {
ASSERT_NE(NULL_NODE, dev_zero.get());
// Writing to /dev/zero should write everything.
+ HandleAttr attrs;
const char msg[] = "Dummy test message.";
- EXPECT_EQ(0, dev_zero->Write(0, &msg[0], strlen(msg), &result_bytes));
+ EXPECT_EQ(0, dev_zero->Write(attrs, &msg[0], strlen(msg), &result_bytes));
EXPECT_EQ(strlen(msg), result_bytes);
// Reading from /dev/zero should read all zeroes.
@@ -237,7 +242,7 @@ TEST(MountTest, DevZero) {
char buffer[kBufferLength];
// First fill with all 1s.
memset(&buffer[0], 0x1, kBufferLength);
- EXPECT_EQ(0, dev_zero->Read(0, &buffer[0], kBufferLength, &result_bytes));
+ EXPECT_EQ(0, dev_zero->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
EXPECT_EQ(kBufferLength, result_bytes);
char zero_buffer[kBufferLength];
@@ -258,7 +263,8 @@ TEST(MountTest, DISABLED_DevUrandom) {
// Writing to /dev/urandom should write everything.
const char msg[] = "Dummy test message.";
- EXPECT_EQ(0, dev_urandom->Write(0, &msg[0], strlen(msg), &result_bytes));
+ HandleAttr attrs;
+ EXPECT_EQ(0, dev_urandom->Write(attrs, &msg[0], strlen(msg), &result_bytes));
EXPECT_EQ(strlen(msg), result_bytes);
// Reading from /dev/urandom should read random bytes.
@@ -271,8 +277,8 @@ TEST(MountTest, DISABLED_DevUrandom) {
unsigned char buffer[kSampleBatchSize];
for (int batch = 0; batch < kSampleBatches; ++batch) {
int bytes_read = 0;
- EXPECT_EQ(0,
- dev_urandom->Read(0, &buffer[0], kSampleBatchSize, &bytes_read));
+ EXPECT_EQ(0, dev_urandom->Read(attrs, &buffer[0], kSampleBatchSize,
+ &bytes_read));
EXPECT_EQ(kSampleBatchSize, bytes_read);
for (int i = 0; i < bytes_read; ++i) {
@@ -290,4 +296,3 @@ TEST(MountTest, DISABLED_DevUrandom) {
// Approximate chi-squared value for p-value 0.05, 255 degrees-of-freedom.
EXPECT_LE(chi_squared, 293.24);
}
-
diff --git a/native_client_sdk/src/tests/nacl_io_test/socket_test.cc b/native_client_sdk/src/tests/nacl_io_test/socket_test.cc
index 90c59dd99c..808a7ed99d 100644
--- a/native_client_sdk/src/tests/nacl_io_test/socket_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/socket_test.cc
@@ -221,11 +221,16 @@ TEST_F(SocketTest, Setsockopt) {
socklen_t len = 10;
char optval[len];
- EXPECT_LT(ki_setsockopt(123, SOL_SOCKET, SO_ACCEPTCONN, NULL, len), 0);
+ // Passing a bad address as optval should generate EFAULT
+ EXPECT_EQ(-1, ki_setsockopt(123, SOL_SOCKET, SO_ACCEPTCONN, NULL, len));
EXPECT_EQ(errno, EFAULT);
- EXPECT_LT(ki_setsockopt(-1, SOL_SOCKET, SO_ACCEPTCONN, optval, len), 0);
+
+ // Passing a bad socket descriptor should generate EBADF
+ EXPECT_EQ(-1, ki_setsockopt(-1, SOL_SOCKET, SO_ACCEPTCONN, optval, len));
EXPECT_EQ(errno, EBADF);
- EXPECT_LT(ki_setsockopt(0, SOL_SOCKET, SO_ACCEPTCONN, optval, len), 0);
+
+ // Passing an FD that is valid but not a socket should generate ENOTSOCK
+ EXPECT_EQ(-1, ki_setsockopt(0, SOL_SOCKET, SO_ACCEPTCONN, optval, len));
EXPECT_EQ(errno, ENOTSOCK);
}
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
index dd43ecac4c..e8ecc5a6c7 100644
--- a/native_client_sdk/src/tools/common.mk
+++ b/native_client_sdk/src/tools/common.mk
@@ -101,9 +101,14 @@ else # TOOLCHAIN is valid...
#
# 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 Release configuration.
+# this will build a Release configuration. When debugging via "make debug",
+# build the debug configuration by default instead.
#
+ifneq (,$(findstring debug,$(MAKECMDGOALS)))
+CONFIG ?= Debug
+else
CONFIG ?= Release
+endif
#
@@ -289,6 +294,8 @@ endif
#
ifeq ($(CONFIG),Release)
POSIX_FLAGS ?= -g -O2 -pthread -MMD -DNDEBUG
+NACL_LDFLAGS ?= -O2
+PNACL_LDFLAGS ?= -O2
else
POSIX_FLAGS ?= -g -O0 -pthread -MMD -DNACL_SDK_DEBUG
endif
@@ -299,7 +306,7 @@ endif
NACL_CFLAGS ?= -Wno-long-long -Werror
NACL_CXXFLAGS ?= -Wno-long-long -Werror
-NACL_LDFLAGS ?= -Wl,-as-needed
+NACL_LDFLAGS += -Wl,-as-needed
#
# Default Paths
diff --git a/native_client_sdk/src/tools/host_gcc.mk b/native_client_sdk/src/tools/host_gcc.mk
index 67f273bcaf..594e33b797 100644
--- a/native_client_sdk/src/tools/host_gcc.mk
+++ b/native_client_sdk/src/tools/host_gcc.mk
@@ -93,6 +93,7 @@ $(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a
all: $(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src)))
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,LIB,$$@,$(HOST_LIB) -cr $$@ $$^)
endef
diff --git a/native_client_sdk/src/tools/httpd.py b/native_client_sdk/src/tools/httpd.py
index 88d8f98e6c..7a98397b66 100755
--- a/native_client_sdk/src/tools/httpd.py
+++ b/native_client_sdk/src/tools/httpd.py
@@ -38,7 +38,7 @@ def SanityCheckDirectory(dirname):
logging.error('For security, httpd.py should only be run from within the')
logging.error('example directory tree.')
logging.error('Attempting to serve from %s.' % abs_serve_dir)
- logging.error('Run with --no_dir_check to bypass this check.')
+ logging.error('Run with --no-dir-check to bypass this check.')
sys.exit(1)
@@ -282,17 +282,16 @@ def main(args):
parser = optparse.OptionParser()
parser.add_option('-C', '--serve-dir',
help='Serve files out of this directory.',
- dest='serve_dir', default=os.path.abspath('.'))
+ default=os.path.abspath('.'))
parser.add_option('-p', '--port',
- help='Run server on this port.',
- dest='port', default=5103)
- parser.add_option('--no_dir_check',
+ help='Run server on this port.', default=5103)
+ parser.add_option('--no-dir-check', '--no_dir_check',
help='No check to ensure serving from safe directory.',
dest='do_safe_check', action='store_false', default=True)
parser.add_option('--test-mode',
help='Listen for posts to /ok or /fail and shut down the server with '
' errorcodes 0 and 1 respectively.',
- dest='test_mode', action='store_true')
+ action='store_true')
options, args = parser.parse_args(args)
if options.do_safe_check:
SanityCheckDirectory(options.serve_dir)
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index c176d9bf47..5a3065d12c 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -229,12 +229,14 @@ ifneq (,$(findstring x86_32,$(ARCHES)))
all: $(OUTDIR)/lib$(1)_x86_32.a
$(OUTDIR)/lib$(1)_x86_32.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_32))
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,LIB ,$$@,$(X86_32_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
install: $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a: $(OUTDIR)/lib$(1)_x86_32.a
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,CP ,$$@,$(OSHELPERS) cp $$^ $$@)
endif
@@ -242,6 +244,7 @@ ifneq (,$(findstring x86_64,$(ARCHES)))
all: $(OUTDIR)/lib$(1)_x86_64.a
$(OUTDIR)/lib$(1)_x86_64.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_64))
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,LIB ,$$@,$(X86_64_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
@@ -256,6 +259,7 @@ ifneq ($(TOOLCHAIN),glibc)
all: $(OUTDIR)/lib$(1)_arm.a
$(OUTDIR)/lib$(1)_arm.a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm))
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,LIB ,$$@,$(ARM_LIB) -cr $$@ $$^)
$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index 00fb87d358..6ed84dd01b 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -80,6 +80,7 @@ $(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
all: $(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
$(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_pnacl))
$(MKDIR) -p $$(dir $$@)
+ $(RM) $$@
$(call LOG,LIB,$$@,$(PNACL_LIB) -cr $$@ $$^ $(3))
endef
@@ -111,7 +112,7 @@ $(1).pexe: $(1).bc
$(call LOG,FINALIZE,$$@,$(PNACL_FINALIZE) -o $$@ $$^)
$(1).bc: $(2) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
- $(call LOG,LINK,$$@,$(PNACL_LINK) -o $$@ $(2) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
+ $(call LOG,LINK,$$@,$(PNACL_LINK) -o $$@ $(2) $(PNACL_LDFLAGS) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
endef