summaryrefslogtreecommitdiff
path: root/native_client_sdk
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-05-09 18:35:53 +0100
committerTorne (Richard Coles) <torne@google.com>2013-05-13 13:57:14 +0100
commitc2e0dbddbe15c98d52c4786dac06cb8952a8ae6d (patch)
tree1dbdbb0624cc869ab25ee7f46971984c6fee3e7a /native_client_sdk
parent2d519ce2457219605d4f472da8d2ffd469796035 (diff)
downloadchromium_org-c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d.tar.gz
Merge from Chromium at DEPS revision r198571
This commit was generated by merge_to_master.py. Change-Id: I951118a03836157090561764dd2627f0add8118f
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/README.naclports14
-rwxr-xr-xnative_client_sdk/src/build_tools/build_app.py131
-rwxr-xr-xnative_client_sdk/src/build_tools/build_examples.py73
-rw-r--r--native_client_sdk/src/build_tools/build_paths.py19
-rwxr-xr-xnative_client_sdk/src/build_tools/build_projects.py238
-rwxr-xr-xnative_client_sdk/src/build_tools/build_sdk.py248
-rwxr-xr-xnative_client_sdk/src/build_tools/build_updater.py2
-rw-r--r--native_client_sdk/src/build_tools/build_utils.py14
-rw-r--r--native_client_sdk/src/build_tools/build_version.py64
-rw-r--r--native_client_sdk/src/build_tools/buildbot_common.py60
-rwxr-xr-xnative_client_sdk/src/build_tools/easy_template.py38
-rw-r--r--native_client_sdk/src/build_tools/generate_index.py112
-rw-r--r--[-rwxr-xr-x]native_client_sdk/src/build_tools/generate_make.py402
-rwxr-xr-xnative_client_sdk/src/build_tools/generate_notice.py6
-rw-r--r--native_client_sdk/src/build_tools/json/naclsdk_manifest2.json32
-rw-r--r--native_client_sdk/src/build_tools/library.mk2
-rw-r--r--native_client_sdk/src/build_tools/make_simple.py2
-rw-r--r--native_client_sdk/src/build_tools/manifest_util.py4
-rwxr-xr-xnative_client_sdk/src/build_tools/nacl-mono-archive.py2
-rwxr-xr-xnative_client_sdk/src/build_tools/nacl-mono-buildbot.py6
-rwxr-xr-xnative_client_sdk/src/build_tools/nacl-mono-builder.py35
-rwxr-xr-xnative_client_sdk/src/build_tools/nacl-mono-runtime.sh110
-rw-r--r--native_client_sdk/src/build_tools/parse_dsc.py238
-rw-r--r--native_client_sdk/src/build_tools/sdk_tools/command/update.py154
-rw-r--r--native_client_sdk/src/build_tools/sdk_tools/config.py19
-rwxr-xr-xnative_client_sdk/src/build_tools/sdk_tools/sdk_update_main.py27
-rwxr-xr-xnative_client_sdk/src/build_tools/sdk_tools/set_nacl_env.py492
-rw-r--r--native_client_sdk/src/build_tools/template.mk18
-rwxr-xr-xnative_client_sdk/src/build_tools/test_sdk.py76
-rwxr-xr-xnative_client_sdk/src/build_tools/tests/parse_dsc_test.py (renamed from native_client_sdk/src/build_tools/tests/generate_make_test.py)7
-rwxr-xr-xnative_client_sdk/src/build_tools/tests/sdktools_commands_test.py54
-rwxr-xr-xnative_client_sdk/src/build_tools/tests/sdktools_test.py12
-rwxr-xr-xnative_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py228
-rwxr-xr-xnative_client_sdk/src/build_tools/update_nacl_manifest.py152
-rw-r--r--native_client_sdk/src/examples/Makefile4
-rw-r--r--native_client_sdk/src/examples/api/audio/example.dsc19
-rw-r--r--native_client_sdk/src/examples/api/audio/example.js (renamed from native_client_sdk/src/examples/sine_synth/example.js)0
-rw-r--r--native_client_sdk/src/examples/api/audio/index.html (renamed from native_client_sdk/src/examples/sine_synth/index.html)4
-rw-r--r--native_client_sdk/src/examples/api/audio/sine_synth.cc (renamed from native_client_sdk/src/examples/sine_synth/sine_synth.cc)21
-rw-r--r--native_client_sdk/src/examples/api/core/core.cc67
-rw-r--r--native_client_sdk/src/examples/api/core/example.dsc19
-rw-r--r--native_client_sdk/src/examples/api/core/example.js68
-rw-r--r--native_client_sdk/src/examples/api/core/index.html47
-rw-r--r--native_client_sdk/src/examples/api/file_io/example.dsc (renamed from native_client_sdk/src/examples/file_io/example.dsc)6
-rw-r--r--native_client_sdk/src/examples/api/file_io/example.js (renamed from native_client_sdk/src/examples/file_io/example.js)0
-rw-r--r--native_client_sdk/src/examples/api/file_io/file_io.cc (renamed from native_client_sdk/src/examples/file_io/file_io.cc)47
-rw-r--r--native_client_sdk/src/examples/api/file_io/index.html (renamed from native_client_sdk/src/examples/file_io/index.html)4
-rw-r--r--native_client_sdk/src/examples/api/gamepad/example.dsc (renamed from native_client_sdk/src/examples/gamepad/example.dsc)9
-rw-r--r--native_client_sdk/src/examples/api/gamepad/gamepad.cc (renamed from native_client_sdk/src/examples/gamepad/gamepad.cc)8
-rw-r--r--native_client_sdk/src/examples/api/gamepad/gamepad.h (renamed from native_client_sdk/src/examples/gamepad/gamepad.h)18
-rw-r--r--native_client_sdk/src/examples/api/gamepad/gamepad_module.cc (renamed from native_client_sdk/src/examples/gamepad/gamepad_module.cc)6
-rw-r--r--native_client_sdk/src/examples/api/gamepad/index.html (renamed from native_client_sdk/src/examples/gamepad/index.html)4
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/example.dsc (renamed from native_client_sdk/src/examples/hello_world_gles/example.dsc)11
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag (renamed from native_client_sdk/src/examples/hello_world_gles/fragment_shader_es2.frag)0
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/hello.raw (renamed from native_client_sdk/src/examples/hello_world_gles/hello.raw)bin49152 -> 49152 bytes
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/hello_world.cc (renamed from native_client_sdk/src/examples/hello_world_gles/hello_world.cc)223
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/index.html (renamed from native_client_sdk/src/examples/hello_world_gles/index.html)2
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/matrix.cc140
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/matrix.h (renamed from native_client_sdk/src/examples/hello_world_gles/matrix.h)20
-rw-r--r--native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert (renamed from native_client_sdk/src/examples/hello_world_gles/vertex_shader_es2.vert)0
-rw-r--r--native_client_sdk/src/examples/api/input_event/custom_events.cc (renamed from native_client_sdk/src/examples/input_events/custom_events.cc)61
-rw-r--r--native_client_sdk/src/examples/api/input_event/custom_events.h (renamed from native_client_sdk/src/examples/input_events/custom_events.h)92
-rw-r--r--native_client_sdk/src/examples/api/input_event/example.dsc24
-rw-r--r--native_client_sdk/src/examples/api/input_event/example.js (renamed from native_client_sdk/src/examples/input_events/example.js)13
-rw-r--r--native_client_sdk/src/examples/api/input_event/index.html (renamed from native_client_sdk/src/examples/input_events/index.html)24
-rw-r--r--native_client_sdk/src/examples/api/input_event/input_events.cc (renamed from native_client_sdk/src/examples/input_events/input_events.cc)225
-rw-r--r--native_client_sdk/src/examples/api/input_event/shared_queue.h151
-rw-r--r--native_client_sdk/src/examples/api/mouse_lock/check_browser.js (renamed from native_client_sdk/src/examples/load_progress/check_browser.js)0
-rw-r--r--native_client_sdk/src/examples/api/mouse_lock/example.dsc17
-rw-r--r--native_client_sdk/src/examples/api/mouse_lock/index.html (renamed from native_client_sdk/src/examples/mouselock/index.html)7
-rw-r--r--native_client_sdk/src/examples/api/mouse_lock/mouselock.cc (renamed from native_client_sdk/src/examples/mouselock/mouselock.cc)106
-rw-r--r--native_client_sdk/src/examples/api/mouse_lock/mouselock.h (renamed from native_client_sdk/src/examples/mouselock/mouselock.h)11
-rw-r--r--native_client_sdk/src/examples/api/url_loader/example.dsc (renamed from native_client_sdk/src/examples/geturl/example.dsc)12
-rw-r--r--native_client_sdk/src/examples/api/url_loader/example.js (renamed from native_client_sdk/src/examples/geturl/example.js)0
-rw-r--r--native_client_sdk/src/examples/api/url_loader/geturl.cc (renamed from native_client_sdk/src/examples/geturl/geturl.cc)6
-rw-r--r--native_client_sdk/src/examples/api/url_loader/geturl_handler.cc (renamed from native_client_sdk/src/examples/geturl/geturl_handler.cc)21
-rw-r--r--native_client_sdk/src/examples/api/url_loader/geturl_handler.h (renamed from native_client_sdk/src/examples/geturl/geturl_handler.h)12
-rw-r--r--native_client_sdk/src/examples/api/url_loader/geturl_success.html (renamed from native_client_sdk/src/examples/geturl/geturl_success.html)0
-rw-r--r--native_client_sdk/src/examples/api/url_loader/index.html (renamed from native_client_sdk/src/examples/geturl/index.html)4
-rw-r--r--native_client_sdk/src/examples/api/var_array_buffer/example.dsc19
-rw-r--r--native_client_sdk/src/examples/api/var_array_buffer/example.js (renamed from native_client_sdk/src/examples/file_histogram/example.js)0
-rw-r--r--native_client_sdk/src/examples/api/var_array_buffer/file_histogram.cc (renamed from native_client_sdk/src/examples/file_histogram/file_histogram.cc)29
-rw-r--r--native_client_sdk/src/examples/api/var_array_buffer/index.html (renamed from native_client_sdk/src/examples/file_histogram/index.html)4
-rw-r--r--native_client_sdk/src/examples/api/websocket/example.dsc18
-rw-r--r--native_client_sdk/src/examples/api/websocket/example.js (renamed from native_client_sdk/src/examples/websocket/example.js)4
-rw-r--r--native_client_sdk/src/examples/api/websocket/index.html (renamed from native_client_sdk/src/examples/websocket/index.html)12
-rw-r--r--native_client_sdk/src/examples/api/websocket/websocket.cc (renamed from native_client_sdk/src/examples/websocket/websocket.cc)25
-rw-r--r--native_client_sdk/src/examples/common.js34
-rw-r--r--native_client_sdk/src/examples/debugging/example.dsc46
-rw-r--r--native_client_sdk/src/examples/debugging/example.js70
-rw-r--r--native_client_sdk/src/examples/debugging/handler.py124
-rw-r--r--native_client_sdk/src/examples/debugging/index.html58
-rw-r--r--native_client_sdk/src/examples/debugging/string_stream.h31
-rw-r--r--native_client_sdk/src/examples/debugging/untrusted_crash_dump.c270
-rw-r--r--native_client_sdk/src/examples/debugging/untrusted_crash_dump.h27
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/example.dsc25
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/example.js (renamed from native_client_sdk/src/examples/hello_nacl_io/example.js)59
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/handlers.c (renamed from native_client_sdk/src/examples/hello_nacl_io/handlers.c)76
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/handlers.h (renamed from native_client_sdk/src/examples/hello_nacl_io/handlers.h)3
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.c (renamed from native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.c)69
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.h (renamed from native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.h)2
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/index.html (renamed from native_client_sdk/src/examples/hello_nacl_io/index.html)12
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/queue.c (renamed from native_client_sdk/src/examples/hello_nacl_io/queue.c)8
-rw-r--r--native_client_sdk/src/examples/demo/nacl_io/queue.h (renamed from native_client_sdk/src/examples/hello_nacl_io/queue.h)4
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/example.dsc (renamed from native_client_sdk/src/examples/pi_generator/example.dsc)9
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/example.js (renamed from native_client_sdk/src/examples/pi_generator/example.js)0
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/index.html (renamed from native_client_sdk/src/examples/pi_generator/index.html)0
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc (renamed from native_client_sdk/src/examples/pi_generator/pi_generator.cc)45
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/pi_generator.h (renamed from native_client_sdk/src/examples/pi_generator/pi_generator.h)24
-rw-r--r--native_client_sdk/src/examples/demo/pi_generator/pi_generator_module.cc (renamed from native_client_sdk/src/examples/pi_generator/pi_generator_module.cc)4
-rw-r--r--native_client_sdk/src/examples/file_histogram/example.dsc25
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/callback.h32
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/cube.cc61
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/cube.h21
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/example.dsc1
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/index.html5
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.cc28
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.h20
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/opengl_context_ptrs.h1
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.cc9
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.h4
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/shader_util.cc6
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/shader_util.h6
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/transforms.cc14
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/transforms.h5
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/tumbler.cc31
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/tumbler.h9
-rw-r--r--native_client_sdk/src/examples/fullscreen_tumbler/tumbler_module.cc9
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world/example.dsc18
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world/example.js13
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world/hello_world.c (renamed from native_client_sdk/src/examples/hello_world/hello_world.c)30
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world/index.html29
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.dsc19
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.js13
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/hello_world.c (renamed from native_client_sdk/src/examples/hello_world_stdio/hello_world.c)18
-rw-r--r--native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/index.html (renamed from native_client_sdk/src/examples/hello_world_stdio/index.html)22
-rw-r--r--native_client_sdk/src/examples/hello_nacl_io/example.dsc31
-rw-r--r--native_client_sdk/src/examples/hello_world/example.dsc25
-rw-r--r--native_client_sdk/src/examples/hello_world/example.js24
-rw-r--r--native_client_sdk/src/examples/hello_world/index.html36
-rw-r--r--native_client_sdk/src/examples/hello_world_gles/matrix.cc136
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/example.dsc9
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc154
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/index.html9
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/matrix.cc106
-rw-r--r--native_client_sdk/src/examples/hello_world_instance3d/matrix.h20
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/example.dsc8
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/example.js11
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/hello_world.cc15
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/helper_functions.cc5
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/helper_functions.h1
-rw-r--r--native_client_sdk/src/examples/hello_world_interactive/index.html15
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/example.dsc28
-rw-r--r--native_client_sdk/src/examples/hello_world_stdio/example.js24
-rw-r--r--native_client_sdk/src/examples/input_events/example.dsc31
-rw-r--r--native_client_sdk/src/examples/input_events/shared_queue.h158
-rw-r--r--native_client_sdk/src/examples/load_progress/example.dsc26
-rw-r--r--native_client_sdk/src/examples/mouselock/example.dsc22
-rw-r--r--native_client_sdk/src/examples/pong/example.dsc1
-rw-r--r--native_client_sdk/src/examples/pong/pong_input.cc7
-rw-r--r--native_client_sdk/src/examples/pong/pong_instance.cc26
-rw-r--r--native_client_sdk/src/examples/pong/pong_model.cc49
-rw-r--r--native_client_sdk/src/examples/pong/pong_model.h2
-rw-r--r--native_client_sdk/src/examples/pong/pong_module.cc4
-rw-r--r--native_client_sdk/src/examples/pong/pong_view.cc14
-rw-r--r--native_client_sdk/src/examples/pong/pong_view.h3
-rw-r--r--native_client_sdk/src/examples/resources/background.js13
-rw-r--r--native_client_sdk/src/examples/resources/button_close.pngbin0 -> 326 bytes
-rw-r--r--native_client_sdk/src/examples/resources/button_close_hover.pngbin0 -> 405 bytes
-rw-r--r--native_client_sdk/src/examples/resources/icon128.pngbin0 -> 10729 bytes
-rw-r--r--native_client_sdk/src/examples/resources/index.css88
-rw-r--r--native_client_sdk/src/examples/resources/index.html.template45
-rw-r--r--native_client_sdk/src/examples/resources/index.js72
-rw-r--r--native_client_sdk/src/examples/resources/manifest.json.template20
-rw-r--r--native_client_sdk/src/examples/resources/promo440.pngbin0 -> 86991 bytes
-rw-r--r--native_client_sdk/src/examples/resources/screenshot_gles_1280.pngbin0 -> 60899 bytes
-rw-r--r--native_client_sdk/src/examples/resources/screenshot_pi_1280.pngbin0 -> 100971 bytes
-rw-r--r--native_client_sdk/src/examples/sine_synth/example.dsc24
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/example.dsc35
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/example.js131
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/hello_world.c (renamed from native_client_sdk/src/examples/debugging/hello_world.c)80
-rw-r--r--native_client_sdk/src/examples/tutorial/debugging/index.html82
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc (renamed from native_client_sdk/src/examples/dlopen/dlopen.cc)87
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/eightball.cc (renamed from native_client_sdk/src/examples/dlopen/eightball.cc)16
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/eightball.h (renamed from native_client_sdk/src/examples/dlopen/eightball.h)3
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/example.dsc (renamed from native_client_sdk/src/examples/dlopen/example.dsc)15
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/example.js (renamed from native_client_sdk/src/examples/dlopen/example.js)5
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/index.html (renamed from native_client_sdk/src/examples/dlopen/index.html)11
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/reverse.cc (renamed from native_client_sdk/src/examples/dlopen/reverse.cc)0
-rw-r--r--native_client_sdk/src/examples/tutorial/dlopen/reverse.h (renamed from native_client_sdk/src/examples/dlopen/reverse.h)4
-rw-r--r--native_client_sdk/src/examples/tutorial/load_progress/check_browser.js (renamed from native_client_sdk/src/examples/mouselock/check_browser.js)0
-rw-r--r--native_client_sdk/src/examples/tutorial/load_progress/example.dsc19
-rw-r--r--native_client_sdk/src/examples/tutorial/load_progress/example.js (renamed from native_client_sdk/src/examples/load_progress/example.js)32
-rw-r--r--native_client_sdk/src/examples/tutorial/load_progress/index.html (renamed from native_client_sdk/src/examples/load_progress/index.html)9
-rw-r--r--native_client_sdk/src/examples/tutorial/load_progress/load_progress.cc (renamed from native_client_sdk/src/examples/load_progress/load_progress.cc)6
-rw-r--r--native_client_sdk/src/examples/websocket/example.dsc25
-rw-r--r--native_client_sdk/src/libraries/error_handling/error_handling.c266
-rw-r--r--native_client_sdk/src/libraries/error_handling/error_handling.h85
-rw-r--r--native_client_sdk/src/libraries/error_handling/library.dsc24
-rw-r--r--native_client_sdk/src/libraries/error_handling/string_stream.c (renamed from native_client_sdk/src/examples/debugging/string_stream.c)20
-rw-r--r--native_client_sdk/src/libraries/error_handling/string_stream.h30
-rw-r--r--native_client_sdk/src/libraries/gtest_ppapi/gtest_runner.h2
-rw-r--r--native_client_sdk/src/libraries/gtest_ppapi/thread_condition.h2
-rw-r--r--native_client_sdk/src/libraries/jsoncpp/library.dsc49
-rw-r--r--native_client_sdk/src/libraries/libjpeg/library.dsc1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_object.h6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc54
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_html5fs.h6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_http.cc59
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_mem.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node.cc8
-rw-r--r--native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc27
-rw-r--r--native_client_sdk/src/libraries/nacl_io/path.cc2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/path.h2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h28
-rw-r--r--native_client_sdk/src/libraries/nacl_io/pepper_interface.h8
-rw-r--r--native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/real_pepper_interface.h7
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/kernel_object_test.cc6
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc204
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/mount_http_test.cc14
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/mount_test.cc2
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.cc6
-rw-r--r--native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.h7
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/library.dsc2
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_event.h4
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc147
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h55
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.cc87
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.h36
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc123
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h31
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_main.h24
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc2
-rw-r--r--native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h4
-rw-r--r--native_client_sdk/src/libraries/utils/macros.h2
-rw-r--r--native_client_sdk/src/libraries/zlib/library.dsc1
-rwxr-xr-xnative_client_sdk/src/test_all.py2
-rw-r--r--native_client_sdk/src/tools/common.mk15
-rwxr-xr-xnative_client_sdk/src/tools/decode_dump.py6
-rwxr-xr-xnative_client_sdk/src/tools/getos.py4
-rw-r--r--native_client_sdk/src/tools/host_gcc.mk22
-rw-r--r--native_client_sdk/src/tools/host_vc.mk23
-rw-r--r--native_client_sdk/src/tools/nacl_gcc.mk106
-rw-r--r--native_client_sdk/src/tools/nacl_llvm.mk20
-rwxr-xr-xnative_client_sdk/src/tools/oshelpers.py6
-rwxr-xr-xnative_client_sdk/src/tools/tests/create_nmf_test.py6
-rwxr-xr-xnative_client_sdk/src/tools/tests/getos_test.py8
-rw-r--r--native_client_sdk/src/web/manifest.html15
252 files changed, 5288 insertions, 4410 deletions
diff --git a/native_client_sdk/src/README.naclports b/native_client_sdk/src/README.naclports
new file mode 100644
index 0000000000..ed6fa76900
--- /dev/null
+++ b/native_client_sdk/src/README.naclports
@@ -0,0 +1,14 @@
+NaCl Ports
+==========
+
+This folder contains headers and pre-built libraries for several
+of the more commonly used open source third-party libraries.
+
+These libraries were built from the naclports project. For access
+to the full sources, or to rebuild or modify these libraries please
+follow the instructions on naclports:
+
+ https://code.google.com/p/naclports/
+
+Please note that each of libraries libraries is licensed under its
+own specific license. See NOTICE for full list of license terms.
diff --git a/native_client_sdk/src/build_tools/build_app.py b/native_client_sdk/src/build_tools/build_app.py
new file mode 100755
index 0000000000..af5d0656e9
--- /dev/null
+++ b/native_client_sdk/src/build_tools/build_app.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# 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.
+
+import optparse
+import os
+import re
+import sys
+
+if sys.version_info < (2, 6, 0):
+ sys.stderr.write("python 2.6 or later is required run this script\n")
+ sys.exit(1)
+
+import buildbot_common
+import build_projects
+import build_utils
+import easy_template
+import parse_dsc
+
+from build_paths import SDK_SRC_DIR, OUT_DIR, SDK_EXAMPLE_DIR
+
+sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
+import getos
+import oshelpers
+
+
+def RemoveBuildCruft(outdir):
+ for root, _, files in os.walk(outdir):
+ for f in files:
+ path = os.path.join(root, f)
+ ext = os.path.splitext(path)[1]
+ if (ext in ('.d', '.o') or
+ f == 'dir.stamp' or
+ re.search(r'_unstripped_.*?\.nexe', f)):
+ buildbot_common.RemoveFile(path)
+
+
+def StripNexes(outdir, platform, pepperdir):
+ for root, _, files in os.walk(outdir):
+ for f in files:
+ path = os.path.join(root, f)
+ m = re.search(r'lib(32|64).*\.so', path)
+ arch = None
+ if m:
+ # System .so file. Must be x86, because ARM doesn't support glibc yet.
+ arch = 'x86_' + m.group(1)
+ else:
+ basename, ext = os.path.splitext(f)
+ if ext in ('.nexe', '.so'):
+ # We can get the arch from the filename...
+ valid_arches = ('x86_64', 'x86_32', 'arm')
+ for a in valid_arches:
+ if basename.endswith(a):
+ arch = a
+ break
+ if not arch:
+ continue
+
+ strip = GetStrip(pepperdir, platform, arch, 'newlib')
+ buildbot_common.Run([strip, path])
+
+
+def GetStrip(pepperdir, platform, arch, toolchain):
+ base_arch = {'x86_32': 'x86', 'x86_64': 'x86', 'arm': 'arm'}[arch]
+ bin_dir = os.path.join(pepperdir, 'toolchain',
+ '%s_%s_%s' % (platform, base_arch, toolchain), 'bin')
+ strip_prefix = {'x86_32': 'i686', 'x86_64': 'x86_64', 'arm': 'arm'}[arch]
+ strip_name = '%s-nacl-strip' % strip_prefix
+ return os.path.join(bin_dir, strip_name)
+
+
+def main(args):
+ parser = optparse.OptionParser()
+ _, args = parser.parse_args(args[1:])
+
+ toolchains = ['newlib', 'glibc']
+
+ pepper_ver = str(int(build_utils.ChromeMajorVersion()))
+ pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
+ app_dir = os.path.join(OUT_DIR, 'naclsdk_app')
+ app_examples_dir = os.path.join(app_dir, 'examples')
+ sdk_resources_dir = os.path.join(SDK_EXAMPLE_DIR, 'resources')
+ platform = getos.GetPlatform()
+
+ buildbot_common.RemoveDir(app_dir)
+ buildbot_common.MakeDir(app_dir)
+
+ # Add some dummy directories so build_projects doesn't complain...
+ buildbot_common.MakeDir(os.path.join(app_dir, 'tools'))
+ buildbot_common.MakeDir(os.path.join(app_dir, 'toolchain'))
+
+ config = 'Release'
+
+ filters = {}
+ filters['DISABLE_PACKAGE'] = False
+ filters['EXPERIMENTAL'] = False
+ filters['TOOLS'] = toolchains
+ filters['DEST'] = ['examples/api', 'examples/getting_started',
+ 'examples/demo', 'examples/tutorial']
+ tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, filters=filters)
+ build_projects.UpdateHelpers(app_dir, platform, clobber=True)
+ build_projects.UpdateProjects(app_dir, platform, tree, clobber=False,
+ toolchains=toolchains, configs=[config],
+ first_toolchain=True)
+
+ easy_template.RunTemplateFile(
+ os.path.join(sdk_resources_dir, 'manifest.json.template'),
+ os.path.join(app_examples_dir, 'manifest.json'),
+ {'version': build_utils.ChromeVersionNoTrunk()})
+ for filename in ['background.js', 'icon128.png']:
+ buildbot_common.CopyFile(os.path.join(sdk_resources_dir, filename),
+ os.path.join(app_examples_dir, filename))
+
+ os.environ['NACL_SDK_ROOT'] = pepperdir
+
+ build_projects.BuildProjects(app_dir, platform, tree, deps=True, clean=False,
+ config=config)
+
+ RemoveBuildCruft(app_dir)
+ StripNexes(app_dir, platform, pepperdir)
+
+ app_zip = os.path.join(app_dir, 'examples.zip')
+ os.chdir(app_examples_dir)
+ oshelpers.Zip([app_zip, '-r', '*'])
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/native_client_sdk/src/build_tools/build_examples.py b/native_client_sdk/src/build_tools/build_examples.py
deleted file mode 100755
index 0e985212d0..0000000000
--- a/native_client_sdk/src/build_tools/build_examples.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import optparse
-import os
-import sys
-
-import build_sdk
-import build_utils
-import test_sdk
-
-sys.path.append(os.path.join(build_sdk.SDK_SRC_DIR, 'tools'))
-import getos
-
-
-def main(args):
- parser = optparse.OptionParser()
- parser.add_option('--copy',
- help='Only copy the files, don\'t build.',
- action='store_true' )
- parser.add_option('--clobber-examples',
- help='Don\'t examples directory before copying new files',
- action='store_true' )
- parser.add_option('--test-examples',
- help='Run the pyauto tests for examples.', action='store_true')
- parser.add_option('--experimental',
- help='build experimental examples and libraries', action='store_true')
- parser.add_option('-t', '--toolchain',
- help='Build using toolchain. Can be passed more than once.',
- action='append')
- parser.add_option('--gyp',
- help='Use gyp to build examples/libraries/Makefiles.',
- action='store_true')
-
- options, args = parser.parse_args(args[1:])
-
- valid_toolchains = ['newlib', 'glibc', 'pnacl', 'host']
- if not options.toolchain:
- toolchains = valid_toolchains
- else:
- invalid_toolchains = set(options.toolchain) - set(valid_toolchains)
- if invalid_toolchains:
- print 'Ignoring invalid toolchains: %s' % (', '.join(invalid_toolchains),)
- toolchains = list(set(options.toolchain) - invalid_toolchains)
-
- pepper_ver = str(int(build_utils.ChromeMajorVersion()))
- pepperdir = os.path.join(build_sdk.OUT_DIR, 'pepper_' + pepper_ver)
- platform = getos.GetPlatform()
-
- build_sdk.options = options
-
- build_sdk.BuildStepCopyBuildHelpers(pepperdir, platform)
- build_sdk.BuildStepCopyExamples(pepperdir, toolchains, options.experimental,
- options.clobber_examples)
- test_sdk.BuildStepCopyTests(pepperdir, toolchains, options.experimental,
- options.clobber_examples)
- if options.copy:
- return 0
-
- # False = don't clean after building the libraries directory.
- build_sdk.BuildStepBuildLibraries(pepperdir, platform, 'src', False)
- test_sdk.BuildStepBuildExamples(pepperdir, platform)
- test_sdk.BuildStepBuildTests(pepperdir, platform)
- if options.test_examples:
- test_sdk.BuildStepRunPyautoTests(pepperdir, platform, pepper_ver)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/native_client_sdk/src/build_tools/build_paths.py b/native_client_sdk/src/build_tools/build_paths.py
new file mode 100644
index 0000000000..a01671b4b3
--- /dev/null
+++ b/native_client_sdk/src/build_tools/build_paths.py
@@ -0,0 +1,19 @@
+# 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.
+
+import os
+
+# Create the various paths of interest
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
+SDK_EXAMPLE_DIR = os.path.join(SDK_SRC_DIR, 'examples')
+SDK_LIBRARY_DIR = os.path.join(SDK_SRC_DIR, 'libraries')
+SDK_DIR = os.path.dirname(SDK_SRC_DIR)
+SRC_DIR = os.path.dirname(SDK_DIR)
+NACL_DIR = os.path.join(SRC_DIR, 'native_client')
+OUT_DIR = os.path.join(SRC_DIR, 'out')
+PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi')
+NACLPORTS_DIR = os.path.join(OUT_DIR, 'naclports')
+
+GSTORE = 'https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/'
diff --git a/native_client_sdk/src/build_tools/build_projects.py b/native_client_sdk/src/build_tools/build_projects.py
new file mode 100755
index 0000000000..0b6659bc30
--- /dev/null
+++ b/native_client_sdk/src/build_tools/build_projects.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python
+# 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.
+
+import optparse
+import os
+import sys
+
+import buildbot_common
+import build_version
+import generate_make
+import parse_dsc
+
+from build_paths import NACL_DIR, SDK_SRC_DIR, OUT_DIR, SDK_EXAMPLE_DIR
+from build_paths import GSTORE
+from generate_index import LandingPage
+
+sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
+sys.path.append(os.path.join(NACL_DIR, 'build'))
+import getos
+import http_download
+
+
+MAKE = 'nacl_sdk/make_3_81/make.exe'
+LIB_DICT = {
+ 'linux': [],
+ 'mac': [],
+ 'win': ['x86_32']
+}
+
+
+def CopyFilesFromTo(filelist, srcdir, dstdir):
+ for filename in filelist:
+ srcpath = os.path.join(srcdir, filename)
+ dstpath = os.path.join(dstdir, filename)
+ buildbot_common.CopyFile(srcpath, dstpath)
+
+
+def UpdateHelpers(pepperdir, platform, clobber=False):
+ if not os.path.exists(os.path.join(pepperdir, 'tools')):
+ buildbot_common.ErrorExit('Examples depend on missing tools.')
+
+ exampledir = os.path.join(pepperdir, 'examples')
+ if clobber:
+ buildbot_common.RemoveDir(exampledir)
+ buildbot_common.MakeDir(exampledir)
+
+ # Copy files for individual bild and landing page
+ files = ['favicon.ico', 'httpd.cmd']
+ CopyFilesFromTo(files, SDK_EXAMPLE_DIR, exampledir)
+
+ resourcesdir = os.path.join(SDK_EXAMPLE_DIR, 'resources')
+ files = ['index.css', 'index.js', 'button_close.png',
+ 'button_close_hover.png']
+ CopyFilesFromTo(files, resourcesdir, exampledir)
+
+ # Copy tools scripts and make includes
+ buildbot_common.CopyDir(os.path.join(SDK_SRC_DIR, 'tools', '*.py'),
+ os.path.join(pepperdir, 'tools'))
+ buildbot_common.CopyDir(os.path.join(SDK_SRC_DIR, 'tools', '*.mk'),
+ os.path.join(pepperdir, 'tools'))
+
+ # On Windows add a prebuilt make
+ if platform == 'win':
+ buildbot_common.BuildStep('Add MAKE')
+ http_download.HttpDownload(GSTORE + MAKE,
+ os.path.join(pepperdir, 'tools', 'make.exe'))
+
+
+def UpdateProjects(pepperdir, platform, project_tree, toolchains,
+ clobber=False, configs=None, first_toolchain=False):
+ if configs is None:
+ configs = ['Debug', 'Release']
+ if not os.path.exists(os.path.join(pepperdir, 'tools')):
+ buildbot_common.ErrorExit('Examples depend on missing tools.')
+ if not os.path.exists(os.path.join(pepperdir, 'toolchain')):
+ buildbot_common.ErrorExit('Examples depend on missing toolchains.')
+
+
+ # Create the library output directories
+ libdir = os.path.join(pepperdir, 'lib')
+ for config in configs:
+ for arch in LIB_DICT[platform]:
+ dirpath = os.path.join(libdir, '%s_%s_host' % (platform, arch), config)
+ if clobber:
+ buildbot_common.RemoveDir(dirpath)
+ buildbot_common.MakeDir(dirpath)
+
+ landing_page = None
+ for branch, projects in project_tree.iteritems():
+ dirpath = os.path.join(pepperdir, branch)
+ if clobber:
+ buildbot_common.RemoveDir(dirpath)
+ buildbot_common.MakeDir(dirpath)
+ depth = len(branch.split('/'))
+ targets = [desc['NAME'] for desc in projects]
+
+ # Generate master make for this branch of projects
+ generate_make.GenerateMasterMakefile(os.path.join(pepperdir, branch),
+ targets, depth)
+
+ if branch.startswith('examples') and not landing_page:
+ landing_page = LandingPage()
+
+ # Generate individual projects
+ for desc in projects:
+ srcroot = os.path.dirname(desc['FILEPATH'])
+ generate_make.ProcessProject(srcroot, pepperdir, desc, toolchains,
+ configs=configs,
+ first_toolchain=first_toolchain)
+
+ if branch.startswith('examples'):
+ landing_page.AddDesc(desc)
+
+ if landing_page:
+ # Generate the landing page text file.
+ index_html = os.path.join(pepperdir, 'examples', 'index.html')
+ example_resources_dir = os.path.join(SDK_EXAMPLE_DIR, 'resources')
+ index_template = os.path.join(example_resources_dir,
+ 'index.html.template')
+ with open(index_html, 'w') as fh:
+ out = landing_page.GeneratePage(index_template)
+ fh.write(out)
+
+ # Generate top Make for examples
+ targets = ['api', 'demos', 'getting_started', 'tutorials']
+ targets = [x for x in targets if 'examples/'+x in project_tree]
+ branch_name = 'examples'
+ depth = len(branch_name.split('/'))
+ generate_make.GenerateMasterMakefile(os.path.join(pepperdir, branch_name),
+ targets, depth)
+
+
+def BuildProjectsBranch(pepperdir, platform, branch, deps=True, clean=False,
+ config='Debug'):
+ make_dir = os.path.join(pepperdir, branch)
+ print "\n\nMake: " + make_dir
+ if platform == 'win':
+ # We need to modify the environment to build host on Windows.
+ make = os.path.join(make_dir, 'make.bat')
+ else:
+ make = 'make'
+
+ extra_args = ['CONFIG='+config]
+ if not deps:
+ extra_args += ['IGNORE_DEPS=1']
+
+ try:
+ buildbot_common.Run([make, '-j8', 'all_versions'] + extra_args,
+ cwd=make_dir)
+ except:
+ print 'Failed to build ' + branch
+ raise
+
+ if clean:
+ # Clean to remove temporary files but keep the built
+ buildbot_common.Run([make, '-j8', 'clean'] + extra_args,
+ cwd=make_dir)
+
+
+def BuildProjects(pepperdir, platform, project_tree, deps=True,
+ clean=False, config='Debug'):
+ # First build libraries
+ build_order = ['src', 'testlibs']
+ for branch in build_order:
+ if branch in project_tree:
+ BuildProjectsBranch(pepperdir, platform, branch, deps, clean, config)
+
+ # Build everything else.
+ for branch in project_tree:
+ if branch not in build_order:
+ BuildProjectsBranch(pepperdir, platform, branch, deps, clean, config)
+
+
+def main(args):
+ parser = optparse.OptionParser()
+ parser.add_option('--clobber',
+ help='Clobber project directories before copying new files',
+ action='store_true', default=False)
+ parser.add_option('-b', '--build',
+ help='Build the projects.', action='store_true')
+ parser.add_option('-x', '--experimental',
+ help='Build experimental projects', action='store_true')
+ parser.add_option('-t', '--toolchain',
+ help='Build using toolchain. Can be passed more than once.',
+ action='append', default=[])
+ parser.add_option('-d', '--dest',
+ help='Select which build destinations (project types) are valid.',
+ action='append')
+ parser.add_option('-p', '--project',
+ help='Select which projects are valid.',
+ action='append')
+ parser.add_option('-v', '--verbose', action='store_true')
+
+ options, files = parser.parse_args(args[1:])
+ if len(files):
+ parser.error('Not expecting files.')
+ return 1
+
+ pepper_ver = str(int(build_version.ChromeMajorVersion()))
+ pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
+ platform = getos.GetPlatform()
+
+ if not options.toolchain:
+ options.toolchain = ['newlib', 'glibc', 'pnacl', 'host']
+
+ if 'host' in options.toolchain:
+ options.toolchain.append(platform)
+ print 'Adding platform: ' + platform
+
+ filters = {}
+ if options.toolchain:
+ filters['TOOLS'] = options.toolchain
+ print 'Filter by toolchain: ' + str(options.toolchain)
+ if not options.experimental:
+ filters['EXPERIMENTAL'] = False
+ if options.dest:
+ filters['DEST'] = options.dest
+ print 'Filter by type: ' + str(options.dest)
+ if options.project:
+ filters['NAME'] = options.project
+ print 'Filter by name: ' + str(options.project)
+
+ project_tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, verbose=options.verbose,
+ filters=filters)
+ parse_dsc.PrintProjectTree(project_tree)
+
+ UpdateHelpers(pepperdir, platform, clobber=options.clobber)
+ UpdateProjects(pepperdir, platform, project_tree, options.toolchain,
+ clobber=options.clobber)
+ if options.build:
+ BuildProjects(pepperdir, platform, project_tree)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 4f0fbfbf8e..2e7d4eb750 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -23,7 +23,6 @@ import datetime
import optparse
import os
import re
-import subprocess
import sys
if sys.version_info < (2, 6, 0):
@@ -32,35 +31,25 @@ if sys.version_info < (2, 6, 0):
# local includes
import buildbot_common
+import build_projects
import build_updater
-import build_utils
+import build_version
import generate_make
import generate_notice
import manifest_util
+import parse_dsc
import test_sdk
-# Create the various paths of interest
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
-SDK_EXAMPLE_DIR = os.path.join(SDK_SRC_DIR, 'examples')
-SDK_LIBRARY_DIR = os.path.join(SDK_SRC_DIR, 'libraries')
-SDK_DIR = os.path.dirname(SDK_SRC_DIR)
-SRC_DIR = os.path.dirname(SDK_DIR)
-NACL_DIR = os.path.join(SRC_DIR, 'native_client')
-OUT_DIR = os.path.join(SRC_DIR, 'out')
-PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi')
-NACLPORTS_DIR = os.path.join(OUT_DIR, 'naclports')
+from build_paths import SDK_SRC_DIR, SRC_DIR, NACL_DIR, OUT_DIR
+from build_paths import PPAPI_DIR, NACLPORTS_DIR, GSTORE
# Add SDK make tools scripts to the python path.
sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
sys.path.append(os.path.join(NACL_DIR, 'build'))
import getos
-import http_download
import oshelpers
-GSTORE = 'https://commondatastorage.googleapis.com/nativeclient-mirror/nacl/'
-MAKE = 'nacl_sdk/make_3_81/make.exe'
CYGTAR = os.path.join(NACL_DIR, 'build', 'cygtar.py')
NACLPORTS_URL = 'https://naclports.googlecode.com/svn/trunk/src'
@@ -262,6 +251,7 @@ HEADER_MAP = {
'nacl/dynamic_annotations.h':
'src/untrusted/valgrind/dynamic_annotations.h',
'nacl/nacl_dyncode.h': 'src/untrusted/nacl/nacl_dyncode.h',
+ 'nacl/nacl_exception.h': 'src/include/nacl/nacl_exception.h',
'nacl/nacl_startup.h': 'src/untrusted/nacl/nacl_startup.h',
'nacl/nacl_thread.h': 'src/untrusted/nacl/nacl_thread.h',
'pnacl.h': 'src/untrusted/nacl/pnacl.h',
@@ -272,6 +262,7 @@ HEADER_MAP = {
'nacl/dynamic_annotations.h':
'src/untrusted/valgrind/dynamic_annotations.h',
'nacl/nacl_dyncode.h': 'src/untrusted/nacl/nacl_dyncode.h',
+ 'nacl/nacl_exception.h': 'src/include/nacl/nacl_exception.h',
'nacl/nacl_startup.h': 'src/untrusted/nacl/nacl_startup.h',
'nacl/nacl_thread.h': 'src/untrusted/nacl/nacl_thread.h',
'pnacl.h': 'src/untrusted/nacl/pnacl.h',
@@ -594,55 +585,6 @@ def BuildStepBuildToolchains(pepperdir, platform, toolchains):
'newlib')
-def BuildStepCopyBuildHelpers(pepperdir, platform):
- buildbot_common.BuildStep('Copy build helpers')
- buildbot_common.CopyDir(os.path.join(SDK_SRC_DIR, 'tools', '*.py'),
- os.path.join(pepperdir, 'tools'))
- buildbot_common.CopyDir(os.path.join(SDK_SRC_DIR, 'tools', '*.mk'),
- os.path.join(pepperdir, 'tools'))
- if platform == 'win':
- buildbot_common.BuildStep('Add MAKE')
- http_download.HttpDownload(GSTORE + MAKE,
- os.path.join(pepperdir, 'tools', 'make.exe'))
-
-
-EXAMPLE_LIST = [
- 'debugging',
- 'dlopen',
- 'file_histogram',
- 'file_io',
- 'gamepad',
- 'geturl',
- 'hello_nacl_io',
- 'hello_world_stdio',
- 'hello_world',
- 'hello_world_gles',
- 'hello_world_instance3d',
- 'hello_world_interactive',
- 'input_events',
- 'load_progress',
- 'mouselock',
- 'pi_generator',
- 'sine_synth',
- 'websocket',
-]
-
-LIBRARY_LIST = [
- 'libjpeg',
- 'nacl_io',
- 'ppapi',
- 'ppapi_cpp',
- 'ppapi_gles2',
- 'ppapi_main',
- 'pthread',
- 'zlib',
-]
-
-LIB_DICT = {
- 'linux': [],
- 'mac': [],
- 'win': ['x86_32']
-}
def MakeDirectoryOrClobber(pepperdir, dirname, clobber):
@@ -654,97 +596,27 @@ def MakeDirectoryOrClobber(pepperdir, dirname, clobber):
return dirpath
-def BuildStepCopyExamples(pepperdir, toolchains, build_experimental, clobber):
- buildbot_common.BuildStep('Copy examples')
-
- if not os.path.exists(os.path.join(pepperdir, 'tools')):
- buildbot_common.ErrorExit('Examples depend on missing tools.')
- if not os.path.exists(os.path.join(pepperdir, 'toolchain')):
- buildbot_common.ErrorExit('Examples depend on missing toolchains.')
-
- exampledir = MakeDirectoryOrClobber(pepperdir, 'examples', clobber)
- libdir = MakeDirectoryOrClobber(pepperdir, 'lib', clobber)
-
- plat = getos.GetPlatform()
- for arch in LIB_DICT[plat]:
- buildbot_common.MakeDir(os.path.join(libdir, '%s_%s_host' % (plat, arch)))
- if options.gyp and plat != 'win':
- configs = ['debug', 'release']
- else:
- configs = ['Debug', 'Release']
- for config in configs:
- buildbot_common.MakeDir(os.path.join(libdir, '%s_%s_host' % (plat, arch),
- config))
-
- MakeDirectoryOrClobber(pepperdir, 'src', clobber)
-
- # Copy individual files
- files = ['favicon.ico', 'httpd.cmd']
- for filename in files:
- oshelpers.Copy(['-v', os.path.join(SDK_EXAMPLE_DIR, filename),
- exampledir])
-
- args = ['--dstroot=%s' % pepperdir, '--master']
- for toolchain in toolchains:
- if toolchain != 'arm':
- args.append('--' + toolchain)
-
- for example in EXAMPLE_LIST:
- dsc = os.path.join(SDK_EXAMPLE_DIR, example, 'example.dsc')
- args.append(dsc)
-
- for library in LIBRARY_LIST:
- dsc = os.path.join(SDK_LIBRARY_DIR, library, 'library.dsc')
- args.append(dsc)
-
- if build_experimental:
- args.append('--experimental')
-
- print "Generting Makefiles: %s" % str(args)
- if generate_make.main(args):
- buildbot_common.ErrorExit('Failed to build examples.')
-
-
-def GetWindowsEnvironment():
- sys.path.append(os.path.join(NACL_DIR, 'buildbot'))
- import buildbot_standard
-
- # buildbot_standard.SetupWindowsEnvironment expects a "context" object. We'll
- # fake enough of that here to work.
- class FakeContext(object):
- def __init__(self):
- self.env = os.environ
-
- def GetEnv(self, key):
- return self.env[key]
-
- def __getitem__(self, key):
- return self.env[key]
+def BuildStepUpdateHelpers(pepperdir, platform, clobber):
+ buildbot_common.BuildStep('Update project helpers')
+ build_projects.UpdateHelpers(pepperdir, platform, clobber=clobber)
- def SetEnv(self, key, value):
- self.env[key] = value
- def __setitem__(self, key, value):
- self.env[key] = value
+def BuildStepUpdateUserProjects(pepperdir, platform, toolchains,
+ build_experimental, clobber):
+ buildbot_common.BuildStep('Update examples and libraries')
- context = FakeContext()
- buildbot_standard.SetupWindowsEnvironment(context)
+ filters = {}
+ if not build_experimental:
+ filters['EXPERIMENTAL'] = False
+ if toolchains:
+ filters['TOOLS'] = toolchains
- # buildbot_standard.SetupWindowsEnvironment adds the directory which contains
- # vcvarsall.bat to the path, but not the directory which contains cl.exe,
- # link.exe, etc.
- # Running vcvarsall.bat adds the correct directories to the path, which we
- # extract below.
- process = subprocess.Popen('vcvarsall.bat x86 > NUL && set',
- stdout=subprocess.PIPE, env=context.env, shell=True)
- stdout, _ = process.communicate()
+ # Update examples and libraries
+ filters['DEST'] = ['examples', 'src']
- # Parse environment from "set" command above.
- # It looks like this:
- # KEY1=VALUE1\r\n
- # KEY2=VALUE2\r\n
- # ...
- return dict(line.split('=') for line in stdout.split('\r\n')[:-1])
+ tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, filters=filters)
+ build_projects.UpdateProjects(pepperdir, platform, tree, clobber=clobber,
+ toolchains=toolchains)
def BuildStepMakeAll(pepperdir, platform, directory, step_name,
@@ -754,11 +626,8 @@ def BuildStepMakeAll(pepperdir, platform, directory, step_name,
print "\n\nMake: " + make_dir
if platform == 'win':
- # We need to modify the environment to build host on Windows.
- env = GetWindowsEnvironment()
make = os.path.join(make_dir, 'make.bat')
else:
- env = os.environ
make = 'make'
extra_args = ['CONFIG='+config]
@@ -766,11 +635,10 @@ def BuildStepMakeAll(pepperdir, platform, directory, step_name,
extra_args += ['IGNORE_DEPS=1']
buildbot_common.Run([make, '-j8', 'all_versions'] + extra_args,
- cwd=make_dir, env=env)
+ cwd=make_dir)
if clean:
# Clean to remove temporary files but keep the built libraries.
- buildbot_common.Run([make, '-j8', 'clean'] + extra_args,
- cwd=make_dir, env=env)
+ buildbot_common.Run([make, '-j8', 'clean'] + extra_args, cwd=make_dir)
def BuildStepBuildLibraries(pepperdir, platform, directory, clean=True):
@@ -780,20 +648,24 @@ def BuildStepBuildLibraries(pepperdir, platform, directory, clean=True):
clean=clean, config='Release')
-def BuildStepGenerateNotice(pepperdir):
+def GenerateNotice(fileroot, output_filename='NOTICE', extra_files=None):
# Look for LICENSE files
- license_filenames_re = re.compile('LICENSE|COPYING')
+ license_filenames_re = re.compile('LICENSE|COPYING|COPYRIGHT')
license_files = []
- for root, _, files in os.walk(pepperdir):
+ for root, _, files in os.walk(fileroot):
for filename in files:
if license_filenames_re.match(filename):
path = os.path.join(root, filename)
license_files.append(path)
+
+ if extra_files:
+ license_files += [os.path.join(fileroot, f) for f in extra_files]
print '\n'.join(license_files)
- notice_filename = os.path.join(pepperdir, 'NOTICE')
- generate_notice.Generate(notice_filename, pepperdir, license_files)
+ if not os.path.isabs(output_filename):
+ output_filename = os.path.join(fileroot, output_filename)
+ generate_notice.Generate(output_filename, fileroot, license_files)
def BuildStepTarBundle(pepper_ver, tarfile):
@@ -806,15 +678,20 @@ def BuildStepTarBundle(pepper_ver, tarfile):
def BuildStepRunUnittests():
buildbot_common.BuildStep('Run unittests')
test_all_py = os.path.join(SDK_SRC_DIR, 'test_all.py')
- buildbot_common.Run([sys.executable, test_all_py])
+
+ # Our tests shouldn't be using the proxy; they should all be connecting to
+ # localhost. Some slaves can't route HTTP traffic through the proxy to
+ # localhost (we get 504 gateway errors), so we clear it here.
+ env = dict(os.environ)
+ if 'http_proxy' in env:
+ del env['http_proxy']
+ buildbot_common.Run([sys.executable, test_all_py], env=env)
def BuildStepTestSDK():
args = []
if options.build_experimental:
args.append('--experimental')
- if options.run_pyauto_tests:
- args.append('--pyauto')
test_sdk.main(args)
@@ -842,14 +719,14 @@ def GetManifestBundle(pepper_ver, revision, tarfile, archive_url):
def BuildStepArchiveBundle(name, pepper_ver, revision, tarfile):
buildbot_common.BuildStep('Archive %s' % name)
bucket_path = 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
- build_utils.ChromeVersion(),)
+ build_version.ChromeVersion(),)
tarname = os.path.basename(tarfile)
tarfile_dir = os.path.dirname(tarfile)
buildbot_common.Archive(tarname, bucket_path, tarfile_dir)
# generate "manifest snippet" for this archive.
archive_url = GSTORE + 'nacl_sdk/%s/%s' % (
- build_utils.ChromeVersion(), tarname)
+ build_version.ChromeVersion(), tarname)
bundle = GetManifestBundle(pepper_ver, revision, tarfile, archive_url)
manifest_snippet_file = os.path.join(OUT_DIR, tarname + '.json')
@@ -869,7 +746,7 @@ def BuildStepArchiveSDKTools():
buildbot_common.BuildStep('Archive SDK Tools')
bucket_path = 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
- build_utils.ChromeVersion(),)
+ build_version.ChromeVersion(),)
buildbot_common.Archive('sdk_tools.tgz', bucket_path, OUT_DIR,
step_link=False)
buildbot_common.Archive('nacl_sdk.zip', bucket_path, OUT_DIR,
@@ -880,7 +757,7 @@ def BuildStepSyncNaClPorts():
"""Pull the pinned revision of naclports from SVN."""
buildbot_common.BuildStep('Sync naclports')
if not os.path.exists(NACLPORTS_DIR):
- # chedckout new copy of naclports
+ # checkout new copy of naclports
cmd = ['svn', 'checkout', '-q', '-r', str(NACLPORTS_REV), NACLPORTS_URL,
'naclports']
buildbot_common.Run(cmd, cwd=os.path.dirname(NACLPORTS_DIR))
@@ -906,16 +783,27 @@ def BuildStepBuildNaClPorts(pepper_ver, pepperdir):
out_dir = os.path.join(bundle_dir, 'pepper_XX')
out_dir_final = os.path.join(bundle_dir, 'pepper_%s' % pepper_ver)
+ buildbot_common.RemoveDir(out_dir_final)
buildbot_common.Move(out_dir, out_dir_final)
+ # Some naclports do not include a standalone LICENSE/COPYING file
+ # so we explicitly list those here for inclusion.
+ extra_licenses = ('tinyxml/readme.txt',
+ 'jpeg-8d/README',
+ 'zlib-1.2.3/README')
+ src_root = os.path.join(NACLPORTS_DIR, 'out', 'repository-i686')
+ output_license = os.path.join(out_dir_final, 'ports', 'LICENSE')
+ GenerateNotice(src_root , output_license, extra_licenses)
+ readme = os.path.join(out_dir_final, 'ports', 'README')
+ oshelpers.Copy(['-v', os.path.join(SDK_SRC_DIR, 'README.naclports'), readme])
+
def BuildStepTarNaClPorts(pepper_ver, tarfile):
"""Create tar archive containing headers and libs from naclports build."""
buildbot_common.BuildStep('Tar naclports Bundle')
buildbot_common.MakeDir(os.path.dirname(tarfile))
pepper_dir = 'pepper_%s' % pepper_ver
- archive_dirs = [os.path.join(pepper_dir, 'ports', 'lib'),
- os.path.join(pepper_dir, 'ports', 'include')]
+ archive_dirs = [os.path.join(pepper_dir, 'ports')]
ports_out = os.path.join(NACLPORTS_DIR, 'out', 'sdk_bundle')
cmd = [sys.executable, CYGTAR, '-C', ports_out, '-cjf', tarfile]
@@ -927,8 +815,6 @@ def main(args):
parser = optparse.OptionParser()
parser.add_option('--run-tests',
help='Run tests. This includes building examples.', action='store_true')
- parser.add_option('--run-pyauto-tests',
- help='Run the pyauto tests for examples.', action='store_true')
parser.add_option('--skip-tar', help='Skip generating a tarball.',
action='store_true')
parser.add_option('--archive', help='Force the archive step.',
@@ -955,12 +841,8 @@ def main(args):
arch = 'x86'
generate_make.use_gyp = options.gyp
-
- # TODO(binji) for now, only test examples on non-trybots. Trybots don't build
- # pyauto Chrome.
if buildbot_common.IsSDKBuilder():
options.run_tests = True
- options.run_pyauto_tests = True
options.archive = True
options.build_ports = True
@@ -973,8 +855,8 @@ def main(args):
if options.archive and options.skip_tar:
parser.error('Incompatible arguments with archive.')
- chrome_version = int(build_utils.ChromeMajorVersion())
- clnumber = build_utils.ChromeRevision()
+ chrome_version = int(build_version.ChromeMajorVersion())
+ clnumber = build_version.ChromeRevision()
pepper_ver = str(chrome_version)
pepper_old = str(chrome_version - 1)
pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
@@ -1004,12 +886,14 @@ def main(args):
BuildStepCopyTextFiles(pepperdir, pepper_ver, clnumber)
BuildStepBuildToolchains(pepperdir, platform, toolchains)
InstallCommonHeaders(os.path.join(pepperdir, 'include'))
- BuildStepCopyBuildHelpers(pepperdir, platform)
- BuildStepCopyExamples(pepperdir, toolchains, options.build_experimental, True)
+
+ BuildStepUpdateHelpers(pepperdir, platform, True)
+ BuildStepUpdateUserProjects(pepperdir, platform, toolchains,
+ options.build_experimental, True)
# Ship with libraries prebuilt, so run that first.
BuildStepBuildLibraries(pepperdir, platform, 'src')
- BuildStepGenerateNotice(pepperdir)
+ GenerateNotice(pepperdir)
if not options.skip_tar:
BuildStepTarBundle(pepper_ver, tarfile)
diff --git a/native_client_sdk/src/build_tools/build_updater.py b/native_client_sdk/src/build_tools/build_updater.py
index e945359d16..050fe0a029 100755
--- a/native_client_sdk/src/build_tools/build_updater.py
+++ b/native_client_sdk/src/build_tools/build_updater.py
@@ -178,7 +178,7 @@ def BuildUpdater(out_dir, revision_number=None):
def main(args):
parser = optparse.OptionParser()
parser.add_option('-o', '--out', help='output directory',
- dest='out_dir', default='out')
+ dest='out_dir', default=os.path.join(SRC_DIR, 'out'))
parser.add_option('-r', '--revision', help='revision number of this updater',
dest='revision', default=None)
options, args = parser.parse_args(args[1:])
diff --git a/native_client_sdk/src/build_tools/build_utils.py b/native_client_sdk/src/build_tools/build_utils.py
index 83df030057..ffe8cf0d38 100644
--- a/native_client_sdk/src/build_tools/build_utils.py
+++ b/native_client_sdk/src/build_tools/build_utils.py
@@ -31,8 +31,18 @@ def ChromeVersion():
if info.url.startswith('/trunk/'):
return 'trunk.%s' % info.revision
else:
- exec(open(VERSION_PATH).read())
- return '%s.%s.%s.%s' % (MAJOR, MINOR, BUILD, PATCH)
+ return ChromeVersionNoTrunk()
+
+
+def ChromeVersionNoTrunk():
+ '''Extract the chrome version from src/chrome/VERSION.
+ Ignore whether this is a trunk build.
+
+ Returns:
+ Chrome version string.
+ '''
+ exec(open(VERSION_PATH).read())
+ return '%s.%s.%s.%s' % (MAJOR, MINOR, BUILD, PATCH)
def ChromeMajorVersion():
diff --git a/native_client_sdk/src/build_tools/build_version.py b/native_client_sdk/src/build_tools/build_version.py
new file mode 100644
index 0000000000..ffe8cf0d38
--- /dev/null
+++ b/native_client_sdk/src/build_tools/build_version.py
@@ -0,0 +1,64 @@
+# 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.
+
+"""Small utility library of python functions used during SDK building.
+"""
+
+import os
+import sys
+
+# pylint: disable=E0602
+
+# Reuse last change utility code.
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
+sys.path.append(os.path.join(SRC_DIR, 'build/util'))
+import lastchange
+
+
+# Location of chrome's version file.
+VERSION_PATH = os.path.join(SRC_DIR, 'chrome', 'VERSION')
+
+
+def ChromeVersion():
+ '''Extract chrome version from src/chrome/VERSION + svn.
+
+ Returns:
+ Chrome version string or trunk + svn rev.
+ '''
+ info = lastchange.FetchVersionInfo(None)
+ if info.url.startswith('/trunk/'):
+ return 'trunk.%s' % info.revision
+ else:
+ return ChromeVersionNoTrunk()
+
+
+def ChromeVersionNoTrunk():
+ '''Extract the chrome version from src/chrome/VERSION.
+ Ignore whether this is a trunk build.
+
+ Returns:
+ Chrome version string.
+ '''
+ exec(open(VERSION_PATH).read())
+ return '%s.%s.%s.%s' % (MAJOR, MINOR, BUILD, PATCH)
+
+
+def ChromeMajorVersion():
+ '''Extract chrome major version from src/chrome/VERSION.
+
+ Returns:
+ Chrome major version.
+ '''
+ exec(open(VERSION_PATH, 'r').read())
+ return str(MAJOR)
+
+
+def ChromeRevision():
+ '''Extract chrome revision from svn.
+
+ Returns:
+ The Chrome revision as a string. e.g. "12345"
+ '''
+ return lastchange.FetchVersionInfo(None).revision
diff --git a/native_client_sdk/src/build_tools/buildbot_common.py b/native_client_sdk/src/build_tools/buildbot_common.py
index 82bbeaa195..4de37f8d83 100644
--- a/native_client_sdk/src/build_tools/buildbot_common.py
+++ b/native_client_sdk/src/build_tools/buildbot_common.py
@@ -10,12 +10,9 @@ import os
import subprocess
import sys
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
-SDK_DIR = os.path.dirname(SDK_SRC_DIR)
-SRC_DIR = os.path.dirname(SDK_DIR)
-sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
+from build_paths import SDK_SRC_DIR, NACL_DIR
+sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import oshelpers
def IsSDKBuilder():
@@ -46,6 +43,48 @@ def ErrorExit(msg):
sys.exit(1)
+def GetWindowsEnvironment():
+ sys.path.append(os.path.join(NACL_DIR, 'buildbot'))
+ import buildbot_standard
+
+ # buildbot_standard.SetupWindowsEnvironment expects a "context" object. We'll
+ # fake enough of that here to work.
+ class FakeContext(object):
+ def __init__(self):
+ self.env = os.environ
+
+ def GetEnv(self, key):
+ return self.env[key]
+
+ def __getitem__(self, key):
+ return self.env[key]
+
+ def SetEnv(self, key, value):
+ self.env[key] = value
+
+ def __setitem__(self, key, value):
+ self.env[key] = value
+
+ context = FakeContext()
+ buildbot_standard.SetupWindowsEnvironment(context)
+
+ # buildbot_standard.SetupWindowsEnvironment adds the directory which contains
+ # vcvarsall.bat to the path, but not the directory which contains cl.exe,
+ # link.exe, etc.
+ # Running vcvarsall.bat adds the correct directories to the path, which we
+ # extract below.
+ process = subprocess.Popen('vcvarsall.bat x86 > NUL && set',
+ stdout=subprocess.PIPE, env=context.env, shell=True)
+ stdout, _ = process.communicate()
+
+ # Parse environment from "set" command above.
+ # It looks like this:
+ # KEY1=VALUE1\r\n
+ # KEY2=VALUE2\r\n
+ # ...
+ return dict(line.split('=') for line in stdout.split('\r\n')[:-1])
+
+
def BuildStep(name):
"""Annotate a buildbot build step."""
sys.stdout.flush()
@@ -60,6 +99,14 @@ def Run(args, cwd=None, env=None, shell=False):
shell is not False, the process is launched via the shell to provide shell
interpretation of the arguments. Shell behavior can differ between platforms
so this should be avoided when not using platform dependent shell scripts."""
+
+ # We need to modify the environment to build host on Windows.
+ if not env:
+ if sys.platform.startswith('cygwin') or sys.platform.startswith('win'):
+ env = GetWindowsEnvironment()
+ else:
+ env = os.environ
+
print 'Running: ' + ' '.join(args)
sys.stdout.flush()
sys.stderr.flush()
@@ -116,7 +163,8 @@ LOCAL_GSUTIL = 'gsutil'
def GetGsutil():
- if os.environ.get('BUILDBOT_BUILDERNAME'):
+ if os.environ.get('BUILDBOT_BUILDERNAME') \
+ and not os.environ.get('BUILDBOT_FAKE'):
return BOT_GSUTIL
else:
return LOCAL_GSUTIL
diff --git a/native_client_sdk/src/build_tools/easy_template.py b/native_client_sdk/src/build_tools/easy_template.py
index b2bfa71c7a..d439ea0304 100755
--- a/native_client_sdk/src/build_tools/easy_template.py
+++ b/native_client_sdk/src/build_tools/easy_template.py
@@ -6,6 +6,7 @@
import copy
import cStringIO
import optparse
+import os
import re
import sys
@@ -49,27 +50,42 @@ def TemplateToPython(template, statement_re, expr_re):
return output.getvalue()
-def RunTemplate(src, dst, template_dict, statement_re=None, expr_re=None):
+def RunTemplate(srcfile, dstfile, template_dict, statement_re=None,
+ expr_re=None):
statement_re = statement_re or re.compile(STATEMENT_RE)
expr_re = expr_re or re.compile(EXPR_RE)
- script = TemplateToPython(src.read(), statement_re, expr_re)
+ script = TemplateToPython(srcfile.read(), statement_re, expr_re)
template_dict = copy.copy(template_dict)
- template_dict['__outfile__'] = dst
+ template_dict['__outfile__'] = dstfile
exec script in template_dict
-def RunTemplateFile(srcfile, dstfile, template_dict, statement_re=None,
+def RunTemplateFile(srcpath, dstpath, template_dict, statement_re=None,
expr_re=None):
- with open(srcfile) as src:
- with open(dstfile, 'w') as dst:
- RunTemplate(src, dst, template_dict, statement_re, expr_re)
+ with open(srcpath) as srcfile:
+ with open(dstpath, 'w') as dstfile:
+ RunTemplate(srcfile, dstfile, template_dict, statement_re, expr_re)
+
+
+def RunTemplateFileIfChanged(srcpath, dstpath, replace):
+ dststr = cStringIO.StringIO()
+ with open(srcpath) as srcfile:
+ RunTemplate(srcfile, dststr, replace)
+
+ if os.path.exists(dstpath):
+ with open(dstpath) as dstfile:
+ if dstfile.read() == dststr.getvalue():
+ return
+
+ with open(dstpath, 'w') as dstfile:
+ dstfile.write(dststr.getvalue())
def RunTemplateString(src, template_dict, statement_re=None, expr_re=None):
- srcf = cStringIO.StringIO(src)
- dstf = cStringIO.StringIO()
- RunTemplate(srcf, dstf, template_dict, statement_re, expr_re)
- return dstf.getvalue()
+ srcstr = cStringIO.StringIO(src)
+ dststr = cStringIO.StringIO()
+ RunTemplate(srcstr, dststr, template_dict, statement_re, expr_re)
+ return dststr.getvalue()
def main(args):
diff --git a/native_client_sdk/src/build_tools/generate_index.py b/native_client_sdk/src/build_tools/generate_index.py
index 5bfe23a861..2aed35c878 100644
--- a/native_client_sdk/src/build_tools/generate_index.py
+++ b/native_client_sdk/src/build_tools/generate_index.py
@@ -2,109 +2,33 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-HTML_TOP = '''
-<!--
- 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.
--->
-
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-dt {
- font-weight: bold;
-}
-dd {
- margin-bottom: 12pt;
- width: 800px;
-}
-</style>
-<link href="http://code.google.com/css/codesite.css" rel="stylesheet"
- type="text/css" />
-<title>Native Client Examples</title>
-</head>
-<body>
-<h1>Native Client Examples</h1>
-<dd><p>This page lists all of the examples available in the most recent Native
- Client SDK bundle. Each example is designed to teach a few specific Native
- Client programming concepts. You will need to setup the build environment
- including a path to 'make' which can be found in the 'tools' directory for
- Windows, and the variable NACL_SDK_ROOT which points to one of the pepper
- bundles found under the SDK install location. Calling make from the examples
- directory will build all the projects, while calling make from an individual
- example directory will build only that example.
-</p></dd>
-'''
-
-HTML_END = '''
-</body>
-</html>
-'''
-
-SECTIONS = {
- 'API': """
-<h3>Common APIs</h3>
-<dd><p>The following set of examples illustrate various Pepper APIs including
-audio, 2D, 3D, file I/O, input and urls.</p></dd>
- """,
- 'Concepts': """
-<h3>Common Concepts</h3>
-<dd><p>The following set of examples illustrate various common concepts such as
-showing load progress, using Shared Objects (dynamic libraries),
-mulithreading...</p></dd>
-""",
- 'Tools': """
-<h3>Using the Tools</h3>
-<dd><p>The following "hello_world" examples, show the basic outline of a
-several types of Native Client applications. The simplest, "Hello World Stdio"
-uses several provided libraries to simplify startup and provides a
-simplified make showing a single build configuration. The other examples in
-this SDK however, are designed to build and run with multiple toolsets, build
-configurations, etc...
-making the build much more complex. In all cases we are using <a
-href="http://www.gnu.org/software/make/manual/make.html">GNU Make</a>.
-See the link for further information.
-</p></dd>
-""",
-}
+import collections
+import easy_template
+def CmpByName(x, y):
+ return cmp(x['NAME'], y['NAME'])
+
class LandingPage(object):
def __init__(self):
- self.section_list = ['Tools', 'API', 'Concepts']
- self.section_map = {}
- for section in self.section_list:
- self.section_map[section] = []
+ self.section_list = ['Getting Started', 'API', 'Demo', 'Tutorial']
+ self.section_map = collections.defaultdict(list)
- def _ExampleDescription(self, index_path, title, details, focus):
- return '''
- <dt><a href="%s/index.html">%s</a></dt>
- <dd>%s
- <p>Teaching focus: %s</p>
- </dd>
-''' % (index_path, title, details, focus)
+ def GeneratePage(self, template_path):
+ with open(template_path) as template_file:
+ template = template_file.read()
- def _GenerateSection(self, section):
- out = SECTIONS[section]
- for desc in self.section_map[section]:
- index_path = desc['NAME']
- title = desc['TITLE']
- details = desc['DESC']
- focus = desc['FOCUS']
- out += self._ExampleDescription(index_path, title, details, focus)
- return out
+ sec_map = {}
+ for section_name in self.section_map:
+ items = self.section_map[section_name]
+ items = sorted(items, cmp=CmpByName)
+ sec_map[section_name] = items
+ print 'Add section ' + section_name
- def GeneratePage(self):
- out = HTML_TOP
- for section in self.section_list:
- out += self._GenerateSection(section)
- out += HTML_END
- return out
+ template_dict = { 'section_map': sec_map }
+ return easy_template.RunTemplateString(template, template_dict)
def AddDesc(self, desc):
group = desc['GROUP']
assert group in self.section_list
self.section_map[group].append(desc)
-
diff --git a/native_client_sdk/src/build_tools/generate_make.py b/native_client_sdk/src/build_tools/generate_make.py
index ef37e9771a..802a3482a3 100755..100644
--- a/native_client_sdk/src/build_tools/generate_make.py
+++ b/native_client_sdk/src/build_tools/generate_make.py
@@ -1,31 +1,14 @@
-#!/usr/bin/env python
# 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.
-import cStringIO
-import optparse
import os
import sys
import buildbot_common
from buildbot_common import ErrorExit
-import easy_template
-from generate_index import LandingPage
-
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
-SDK_EXAMPLE_DIR = os.path.join(SDK_SRC_DIR, 'examples')
-SDK_DIR = os.path.dirname(SDK_SRC_DIR)
-SRC_DIR = os.path.dirname(SDK_DIR)
-OUT_DIR = os.path.join(SRC_DIR, 'out')
-PPAPI_DIR = os.path.join(SRC_DIR, 'ppapi')
-
-use_gyp = False
-
-# Add SDK make tools scripts to the python path.
-sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
-import getos
+from easy_template import RunTemplateFileIfChanged
+from build_paths import SCRIPT_DIR, SDK_EXAMPLE_DIR
def Trace(msg):
if Trace.verbose:
@@ -33,9 +16,9 @@ def Trace(msg):
Trace.verbose = False
-
def ShouldProcessHTML(desc):
- return desc['DEST'] in ('examples', 'tests')
+ dest = desc['DEST']
+ return dest.startswith('examples') or dest.startswith('tests')
def GenerateSourceCopyList(desc):
@@ -53,21 +36,6 @@ def GenerateSourceCopyList(desc):
return sources
-def RunTemplateFile(srcfile, dstfile, replace):
- dst = cStringIO.StringIO()
- with open(srcfile) as srcf:
- easy_template.RunTemplate(srcf, dst, replace)
-
- if os.path.exists(dstfile):
- with open(dstfile) as dstf:
- if dstf.read() == dst.getvalue():
- Trace('Generated %s is the same. Skipping' % dstfile)
- return
-
- with open(dstfile, 'w') as dstf:
- dstf.write(dst.getvalue())
-
-
def GetSourcesDict(sources):
source_map = {}
for key in ['.c', '.cc']:
@@ -87,129 +55,21 @@ def GetProjectObjects(source_dict):
return object_list
-def GetPlatforms(plat_list, plat_filter):
+def GetPlatforms(plat_list, plat_filter, first_toolchain):
platforms = []
for plat in plat_list:
if plat in plat_filter:
platforms.append(plat)
- return platforms
-
-# 'KEY' : ( <TYPE>, [Accepted Values], <Required?>)
-DSC_FORMAT = {
- 'TOOLS' : (list, ['newlib:arm', 'newlib:x64', 'newlib:x86', 'newlib',
- 'glibc', 'pnacl', 'win', 'linux'], True),
- 'CONFIGS' : (list, ['Debug', 'Release'], False),
- 'PREREQ' : (list, '', False),
- 'TARGETS' : (list, {
- 'NAME': (str, '', True),
- 'TYPE': (str, ['main', 'lib', 'so'], True),
- 'SOURCES': (list, '', True),
- 'CCFLAGS': (list, '', False),
- 'CXXFLAGS': (list, '', False),
- 'DEFINES': (list, '', False),
- 'LDFLAGS': (list, '', False),
- 'INCLUDES': (list, '', False),
- 'LIBS' : (list, '', False),
- 'DEPS' : (list, '', False)
- }, True),
- 'HEADERS': (list, {
- 'FILES': (list, '', True),
- 'DEST': (str, '', True),
- }, False),
- 'SEARCH': (list, '', False),
- 'POST': (str, '', False),
- 'PRE': (str, '', False),
- 'DEST': (str, ['examples', 'src', 'testlibs', 'tests'], True),
- 'NAME': (str, '', False),
- 'DATA': (list, '', False),
- 'TITLE': (str, '', False),
- 'DESC': (str, '', False),
- 'FOCUS': (str, '', False),
- 'GROUP': (str, '', False),
- 'EXPERIMENTAL': (bool, [True, False], False)
-}
+ if first_toolchain:
+ return [platforms[0]]
+ return platforms
def ErrorMsgFunc(text):
sys.stderr.write(text + '\n')
-def ValidateFormat(src, dsc_format, ErrorMsg=ErrorMsgFunc):
- failed = False
-
- # Verify all required keys are there
- for key in dsc_format:
- (exp_type, exp_value, required) = dsc_format[key]
- if required and key not in src:
- ErrorMsg('Missing required key %s.' % key)
- failed = True
-
- # For each provided key, verify it's valid
- for key in src:
- # Verify the key is known
- if key not in dsc_format:
- ErrorMsg('Unexpected key %s.' % key)
- failed = True
- continue
-
- exp_type, exp_value, required = dsc_format[key]
- value = src[key]
-
- # Verify the key is of the expected type
- if exp_type != type(value):
- ErrorMsg('Key %s expects %s not %s.' % (
- key, exp_type.__name__.upper(), type(value).__name__.upper()))
- failed = True
- continue
-
- # Verify the value is non-empty if required
- if required and not value:
- ErrorMsg('Expected non-empty value for %s.' % key)
- failed = True
- continue
-
- # If it's a bool, the expected values are always True or False.
- if exp_type is bool:
- continue
-
- # If it's a string and there are expected values, make sure it matches
- if exp_type is str:
- if type(exp_value) is list and exp_value:
- if value not in exp_value:
- ErrorMsg("Value '%s' not expected for %s." % (value, key))
- failed = True
- continue
-
- # if it's a list, then we need to validate the values
- if exp_type is list:
- # If we expect a dictionary, then call this recursively
- if type(exp_value) is dict:
- for val in value:
- if not ValidateFormat(val, exp_value, ErrorMsg):
- failed = True
- continue
- # If we expect a list of strings
- if type(exp_value) is str:
- for val in value:
- if type(val) is not str:
- ErrorMsg('Value %s in %s is not a string.' % (val, key))
- failed = True
- continue
- # if we expect a particular string
- if type(exp_value) is list:
- for val in value:
- if val not in exp_value:
- ErrorMsg('Value %s not expected in %s.' % (val, key))
- failed = True
- continue
-
- # If we got this far, it's an unexpected type
- ErrorMsg('Unexpected type %s for key %s.' % (str(type(src[key])), key))
- continue
- return not failed
-
-
def AddMakeBat(pepperdir, makepath):
"""Create a simple batch file to execute Make.
@@ -253,59 +113,23 @@ def IsNexe(desc):
return False
-def ProcessHTML(srcroot, dstroot, desc, toolchains):
+def ProcessHTML(srcroot, dstroot, desc, toolchains, configs, first_toolchain):
name = desc['NAME']
+ nmf = desc['TARGETS'][0]['NAME']
outdir = os.path.join(dstroot, desc['DEST'], name)
- srcfile = os.path.join(srcroot, 'index.html')
- dstfile = os.path.join(outdir, 'index.html')
- tools = GetPlatforms(toolchains, desc['TOOLS'])
-
- if use_gyp and getos.GetPlatform() != 'win':
- configs = ['debug', 'release']
- else:
- configs = ['Debug', 'Release']
-
- if use_gyp:
- path = "build/{tc}-{config}"
- else:
- path = "{tc}/{config}"
+ srcpath = os.path.join(srcroot, 'index.html')
+ dstpath = os.path.join(outdir, 'index.html')
+
+ tools = GetPlatforms(toolchains, desc['TOOLS'], first_toolchain)
+ path = "{tc}/{config}"
replace = {
'title': desc['TITLE'],
'attrs':
'data-name="%s" data-tools="%s" data-configs="%s" data-path="%s"' % (
- name, ' '.join(tools), ' '.join(configs), path),
+ nmf, ' '.join(tools), ' '.join(configs), path),
}
- RunTemplateFile(srcfile, dstfile, replace)
-
-
-def LoadProject(filename, toolchains):
- """Generate a Master Makefile that builds all examples.
-
- Load a project desciption file, verifying it conforms and checking
- if it matches the set of requested toolchains. Return None if the
- project is filtered out."""
-
- Trace('Processing %s...' % filename)
- # Default src directory is the directory the description was found in
- desc = open(filename, 'r').read()
- desc = eval(desc, {}, {})
-
- # Verify the format of this file
- if not ValidateFormat(desc, DSC_FORMAT):
- ErrorExit('Failed to validate: ' + filename)
-
- # Check if we are actually interested in this example
- match = False
- for toolchain in toolchains:
- if toolchain in desc['TOOLS']:
- match = True
- break
- if not match:
- return None
-
- desc['FILENAME'] = filename
- return desc
+ RunTemplateFileIfChanged(srcpath, dstpath, replace)
def FindAndCopyFiles(src_files, root, search_dirs, dst_dir):
@@ -323,11 +147,15 @@ def FindAndCopyFiles(src_files, root, search_dirs, dst_dir):
buildbot_common.CopyFile(src_file, dst_file)
-def ProcessProject(srcroot, dstroot, desc, toolchains):
+def ProcessProject(srcroot, dstroot, desc, toolchains, configs=None,
+ first_toolchain=False):
+ if not configs:
+ configs = ['Debug', 'Release']
+
name = desc['NAME']
out_dir = os.path.join(dstroot, desc['DEST'], name)
buildbot_common.MakeDir(out_dir)
- srcdirs = desc.get('SEARCH', ['.', '..'])
+ srcdirs = desc.get('SEARCH', ['.', '..', '../..'])
# Copy sources to example directory
sources = GenerateSourceCopyList(desc)
@@ -341,163 +169,53 @@ def ProcessProject(srcroot, dstroot, desc, toolchains):
make_path = os.path.join(out_dir, 'Makefile')
- if use_gyp:
- # Process the dsc file to produce gyp input
- dsc = desc['FILENAME']
- dsc2gyp = os.path.join(SDK_SRC_DIR, 'build_tools/dsc2gyp.py')
- gypfile = os.path.join(OUT_DIR, 'tmp', name, name + '.gyp')
- buildbot_common.Run([sys.executable, dsc2gyp, dsc, '-o', gypfile],
- cwd=out_dir)
-
- # Run gyp on the generated gyp file
- if sys.platform == 'win32':
- generator = 'msvs'
- else:
- generator = os.path.join(SCRIPT_DIR, "make_simple.py")
- gyp = os.path.join(SDK_SRC_DIR, '..', '..', 'tools', 'gyp', 'gyp')
- if sys.platform == 'win32':
- gyp += '.bat'
- buildbot_common.Run([gyp, '-Gstandalone', '--format', generator,
- '--toplevel-dir=.', gypfile], cwd=out_dir)
-
- if sys.platform == 'win32' or not use_gyp:
- if IsNexe(desc):
- template = os.path.join(SCRIPT_DIR, 'template.mk')
- else:
- template = os.path.join(SCRIPT_DIR, 'library.mk')
-
- tools = {}
- tool_list = []
- for tool in desc['TOOLS']:
- if ':' in tool:
- tool, arch = tool.split(':')
- else:
- arch = None
- # Ignore tools that are not enabled in this SDK build
- if tool not in toolchains:
- continue
- tools.setdefault(tool, [])
- if tool not in tool_list:
- tool_list.append(tool)
- if arch:
- tools[tool].append(arch)
-
- template_dict = {
- 'pre': desc.get('PRE', ''),
- 'tools': tool_list,
- 'targets': desc['TARGETS'],
- }
- RunTemplateFile(template, make_path, template_dict)
+ if IsNexe(desc):
+ template = os.path.join(SCRIPT_DIR, 'template.mk')
+ else:
+ template = os.path.join(SCRIPT_DIR, 'library.mk')
+
+ # Ensure the order of |tools| is the same as toolchains; that way if
+ # first_toolchain is set, it will choose based on the order of |toolchains|.
+ tools = [tool for tool in toolchains if tool in desc['TOOLS']]
+ if first_toolchain:
+ tools = [tools[0]]
+ template_dict = {
+ 'rel_sdk': '/'.join(['..'] * (len(desc['DEST'].split('/')) + 1)),
+ 'pre': desc.get('PRE', ''),
+ 'post': desc.get('POST', ''),
+ 'tools': tools,
+ 'targets': desc['TARGETS'],
+ }
+ RunTemplateFileIfChanged(template, make_path, template_dict)
outdir = os.path.dirname(os.path.abspath(make_path))
pepperdir = os.path.dirname(os.path.dirname(outdir))
AddMakeBat(pepperdir, outdir)
+
+ if ShouldProcessHTML(desc):
+ ProcessHTML(srcroot, dstroot, desc, toolchains, configs,
+ first_toolchain)
+
return (name, desc['DEST'])
-def GenerateMasterMakefile(in_path, out_path, projects):
- """Generate a Master Makefile that builds all examples. """
- project_names = [project['NAME'] for project in projects]
- template_dict = { 'projects': project_names }
- RunTemplateFile(in_path, out_path, template_dict)
+def GenerateMasterMakefile(out_path, targets, depth):
+ """Generate a Master Makefile that builds all examples.
+ Args:
+ out_path: Root for output such that out_path+NAME = full path
+ targets: List of targets names
+ depth: How deep in from NACL_SDK_ROOT
+ """
+ in_path = os.path.join(SDK_EXAMPLE_DIR, 'Makefile')
+ out_path = os.path.join(out_path, 'Makefile')
+ template_dict = {
+ 'projects': targets,
+ 'rel_sdk' : '/'.join(['..'] * depth)
+ }
+ RunTemplateFileIfChanged(in_path, out_path, template_dict)
outdir = os.path.dirname(os.path.abspath(out_path))
pepperdir = os.path.dirname(outdir)
AddMakeBat(pepperdir, outdir)
-def main(argv):
- usage = "usage: generate_make [options] <dsc_file ..>"
- parser = optparse.OptionParser(usage=usage)
- parser.add_option('--dstroot', help='Set root for destination.',
- default=os.path.join(OUT_DIR, 'pepper_canary'))
- parser.add_option('--master', help='Create master Makefile.',
- action='store_true')
- parser.add_option('--newlib', help='Create newlib examples.',
- action='store_true')
- parser.add_option('--glibc', help='Create glibc examples.',
- action='store_true')
- parser.add_option('--pnacl', help='Create pnacl examples.',
- action='store_true')
- parser.add_option('--host', help='Create host examples.',
- action='store_true')
- parser.add_option('--experimental', help='Create experimental examples.',
- action='store_true')
- parser.add_option('-v', '--verbose', help='Verbose output',
- action='store_true')
-
- toolchains = []
- platform = getos.GetPlatform()
-
- options, args = parser.parse_args(argv)
- if options.verbose:
- Trace.verbose = True
- if options.newlib:
- toolchains.append('newlib')
- if options.glibc:
- toolchains.append('glibc')
- if options.pnacl:
- toolchains.append('pnacl')
- if options.host:
- toolchains.append(platform)
-
- if not args:
- ErrorExit('Please specify one or more projects to generate Makefiles for.')
-
- # By default support newlib and glibc
- if not toolchains:
- toolchains = ['newlib', 'glibc', 'pnacl']
-
- master_projects = {}
-
- landing_page = LandingPage()
- for i, filename in enumerate(args):
- if i:
- # Print two newlines between each dsc file we process
- Trace('\n')
- desc = LoadProject(filename, toolchains)
- if not desc:
- Trace('Skipping %s, not in [%s].' % (filename, ', '.join(toolchains)))
- continue
-
- if desc.get('EXPERIMENTAL', False) and not options.experimental:
- Trace('Skipping %s, experimental only.' % (filename,))
- continue
-
- srcroot = os.path.dirname(os.path.abspath(filename))
- if not ProcessProject(srcroot, options.dstroot, desc, toolchains):
- ErrorExit('\n*** Failed to process project: %s ***' % filename)
-
- # if this is an example update it's html file.
- if ShouldProcessHTML(desc):
- ProcessHTML(srcroot, options.dstroot, desc, toolchains)
-
- # if this is an example, update landing page html file.
- if desc['DEST'] == 'examples':
- Trace('Adding desc: %s' % filename)
- landing_page.AddDesc(desc)
-
- # Create a list of projects for each DEST. This will be used to generate a
- # master makefile.
- master_projects.setdefault(desc['DEST'], []).append(desc)
-
- # Generate the landing page text file.
- index_html = os.path.join(options.dstroot, 'examples', 'index.html')
- with open(index_html, 'w') as fh:
- fh.write(landing_page.GeneratePage())
-
- if options.master:
- if use_gyp:
- master_in = os.path.join(SDK_EXAMPLE_DIR, 'Makefile_gyp')
- else:
- master_in = os.path.join(SDK_EXAMPLE_DIR, 'Makefile')
- for dest, projects in master_projects.iteritems():
- master_out = os.path.join(options.dstroot, dest, 'Makefile')
- GenerateMasterMakefile(master_in, master_out, projects)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
-
diff --git a/native_client_sdk/src/build_tools/generate_notice.py b/native_client_sdk/src/build_tools/generate_notice.py
index ffc376bcc8..c7d81d245a 100755
--- a/native_client_sdk/src/build_tools/generate_notice.py
+++ b/native_client_sdk/src/build_tools/generate_notice.py
@@ -34,6 +34,7 @@ def CreateLicenseDict(files):
license_dict = {}
for filename in files:
license_text = open(filename).read()
+ license_text = license_text.replace('\r\n', '\n')
license_dict.setdefault(license_text, []).append(filename)
# Flip the dictionary (map tuple of filenames -> license text).
@@ -53,15 +54,16 @@ def WriteLicense(output_file, root, license_text, license_filenames):
output_file.write(' (Cf. %s):\n' % (filename,))
output_file.write('=' * 70 + '\n')
output_file.write(license_text)
- output_file.write('\n\n\n')
def Generate(output_filename, root, files):
found_files = FindFiles(files)
license_dict = CreateLicenseDict(found_files)
with open(output_filename, 'w') as output_file:
- for license_filenames in sorted(license_dict.iterkeys()):
+ for i, license_filenames in enumerate(sorted(license_dict.iterkeys())):
license_text = license_dict[license_filenames]
+ if i:
+ output_file.write('\n\n\n')
WriteLicense(output_file, root, license_text, license_filenames)
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 728cf44dfd..0803943139 100644
--- a/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
+++ b/native_client_sdk/src/build_tools/json/naclsdk_manifest2.json
@@ -34,16 +34,6 @@
"revision": 1507
},
{
- "name": "pepper_21",
- "description": "Chrome 21 bundle, revision xxxxx",
- "stability": "post_stable",
- "recommended": "no",
- "version": 21,
- "repath": "pepper_21",
- "archives": [],
- "revision": 0
- },
- {
"name": "pepper_22",
"description": "Chrome 22 bundle, revision xxxxx",
"stability": "post_stable",
@@ -56,8 +46,8 @@
{
"name": "pepper_23",
"description": "Chrome 23 bundle, revision xxxxx",
- "stability": "stable",
- "recommended": "yes",
+ "stability": "post_stable",
+ "recommended": "no",
"version": 23,
"repath": "pepper_23",
"archives": [],
@@ -66,7 +56,7 @@
{
"name": "pepper_24",
"description": "Chrome 24 bundle, revision xxxxx",
- "stability": "beta",
+ "stability": "post_stable",
"recommended": "no",
"version": 24,
"repath": "pepper_24",
@@ -76,7 +66,7 @@
{
"name": "pepper_25",
"description": "Chrome 25 bundle, revision xxxxx",
- "stability": "dev",
+ "stability": "post_stable",
"recommended": "no",
"version": 25,
"repath": "pepper_25",
@@ -86,14 +76,24 @@
{
"name": "pepper_26",
"description": "Chrome 26 bundle, revision xxxxx",
- "stability": "dev",
- "recommended": "no",
+ "stability": "stable",
+ "recommended": "yes",
"version": 26,
"repath": "pepper_26",
"archives": [],
"revision": 0
},
{
+ "name": "pepper_27",
+ "description": "Chrome 27 bundle, revision xxxxx",
+ "stability": "beta",
+ "recommended": "no",
+ "version": 27,
+ "repath": "pepper_27",
+ "archives": [],
+ "revision": 0
+ },
+ {
"name": "pepper_canary",
"description": "Chrome Canary",
"stability": "canary",
diff --git a/native_client_sdk/src/build_tools/library.mk b/native_client_sdk/src/build_tools/library.mk
index 8a48c90919..89b18f0f47 100644
--- a/native_client_sdk/src/build_tools/library.mk
+++ b/native_client_sdk/src/build_tools/library.mk
@@ -10,7 +10,7 @@
# Default configuration
#
-# By default we will build a Debug configuration using the GCC newlib toolcahin
+# By default we will build a Debug configuration using the GCC newlib toolchain
# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
# the make command-line or in this file prior to including common.mk. The
# toolchain we use by default will be the first valid one listed
diff --git a/native_client_sdk/src/build_tools/make_simple.py b/native_client_sdk/src/build_tools/make_simple.py
index e43d14ba0e..fecf480911 100644
--- a/native_client_sdk/src/build_tools/make_simple.py
+++ b/native_client_sdk/src/build_tools/make_simple.py
@@ -294,7 +294,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
WriteTarget(makefile, target_info)
makefile.write('''
-# include (if they exists) the .d dependancy files that the compiler generates
+# include (if they exists) the .d dependency files that the compiler generates
-include $(DEPFILES)
endif
diff --git a/native_client_sdk/src/build_tools/manifest_util.py b/native_client_sdk/src/build_tools/manifest_util.py
index fad583a3a5..51cf24ccd7 100644
--- a/native_client_sdk/src/build_tools/manifest_util.py
+++ b/native_client_sdk/src/build_tools/manifest_util.py
@@ -156,7 +156,7 @@ class Archive(dict):
"""Update the size and checksum information for this archive
based on the content currently at the URL.
- This allows the template mandifest to be maintained without
+ This allows the template manifest to be maintained without
the need to size and checksums to be present.
"""
template = string.Template(self['url'])
@@ -528,7 +528,7 @@ class SDKManifest(object):
local_bundle.MergeWithBundle(bundle)
def MergeManifest(self, manifest):
- '''Merge another manifest into this manifest, disallowing overiding.
+ '''Merge another manifest into this manifest, disallowing overriding.
Args
manifest: The manifest to merge.
diff --git a/native_client_sdk/src/build_tools/nacl-mono-archive.py b/native_client_sdk/src/build_tools/nacl-mono-archive.py
index 131fe52212..066bceeee9 100755
--- a/native_client_sdk/src/build_tools/nacl-mono-archive.py
+++ b/native_client_sdk/src/build_tools/nacl-mono-archive.py
@@ -43,7 +43,7 @@ def main(args):
options.tar_path = options.tar_path.replace('%pepperrev%',
options.pepper_revision)
- install_folders = ['bin', 'etc', 'include', 'lib', 'lib32', 'share']
+ install_folders = ['bin', 'etc', 'include', 'lib', 'lib32', 'libarm', 'share']
buildbot_common.BuildStep('Archive Build')
tar_file = None
diff --git a/native_client_sdk/src/build_tools/nacl-mono-buildbot.py b/native_client_sdk/src/build_tools/nacl-mono-buildbot.py
index 7931799045..5d7d28cd3a 100755
--- a/native_client_sdk/src/build_tools/nacl-mono-buildbot.py
+++ b/native_client_sdk/src/build_tools/nacl-mono-buildbot.py
@@ -10,6 +10,7 @@ import sys
import buildbot_common
import build_utils
+from build_paths import SCRIPT_DIR
GS_MANIFEST_PATH = 'gs://nativeclient-mirror/nacl/nacl_sdk/'
SDK_MANIFEST = 'naclsdk_manifest2.json'
@@ -29,6 +30,9 @@ def build_and_upload_mono(sdk_revision, pepper_revision, sdk_url,
buildbot_common.Run([sys.executable, 'nacl-mono-builder.py',
'--arch', 'x86-64', '--install-dir', install_dir] +
revision_opt + url_opt + args)
+ buildbot_common.Run([sys.executable, 'nacl-mono-builder.py',
+ '--arch', 'arm', '--install-dir', install_dir] +
+ revision_opt + url_opt + args)
buildbot_common.Run([sys.executable, 'nacl-mono-archive.py',
'--upload-path', upload_path,
'--pepper-revision', pepper_revision,
@@ -160,7 +164,7 @@ def main(args):
buildbot_revision = os.environ.get('BUILDBOT_REVISION', '')
buildername = os.environ.get('BUILDBOT_BUILDERNAME', '')
- os.chdir(buildbot_common.SCRIPT_DIR)
+ os.chdir(SCRIPT_DIR)
if buildername == 'linux-sdk-mono32':
assert buildbot_revision
diff --git a/native_client_sdk/src/build_tools/nacl-mono-builder.py b/native_client_sdk/src/build_tools/nacl-mono-builder.py
index d9bc8d537a..731b194396 100755
--- a/native_client_sdk/src/build_tools/nacl-mono-builder.py
+++ b/native_client_sdk/src/build_tools/nacl-mono-builder.py
@@ -9,8 +9,9 @@ import sys
import tarfile
import buildbot_common
+from build_paths import SCRIPT_DIR
-SDK_BUILD_DIR = buildbot_common.SCRIPT_DIR
+SDK_BUILD_DIR = SCRIPT_DIR
MONO_BUILD_DIR = os.path.join(SDK_BUILD_DIR, 'mono_build')
MONO_DIR = os.path.join(MONO_BUILD_DIR, 'nacl-mono')
@@ -79,10 +80,26 @@ def main(args):
buildbot_common.BuildStep(build_prefix + 'Checkout Mono')
# TODO(elijahtaylor): Get git URL from master/trigger to make this
# more flexible for building from upstream and release branches.
- git_url = 'git://github.com/elijahtaylor/mono.git'
- git_rev = 'HEAD'
+ if options.arch == 'arm':
+ git_url = 'git://github.com/igotti-google/mono.git'
+ git_rev = 'arm_nacl'
+ else:
+ git_url = 'git://github.com/elijahtaylor/mono.git'
+ git_rev = 'HEAD'
if buildbot_revision:
- git_rev = buildbot_revision.split(':')[1]
+ # Unfortunately, we use different git branches/revisions
+ # for ARM and x86 now, so ignore buildbot_revision variable for ARM.
+ # Need to rethink this approach, if we'll plan to support
+ # more flexible repo selection mechanism.
+ if options.arch != 'arm':
+ git_rev = buildbot_revision.split(':')[1]
+ # ARM and x86 is built out of different git trees, so distinguish
+ # them by appending the arch. It also makes 32 and 64 bit x86 separated,
+ # which is good.
+ # TODO(olonho): maybe we need to avoid modifications of global.
+ global MONO_DIR
+ tag = options.arch
+ MONO_DIR = "%s-%s" % (MONO_DIR, tag)
if not os.path.exists(MONO_DIR):
buildbot_common.MakeDir(MONO_DIR)
buildbot_common.Run(['git', 'clone', git_url, MONO_DIR])
@@ -93,7 +110,7 @@ def main(args):
arch_to_bitsize = {'x86-32': '32',
'x86-64': '64',
- 'arm': 'pnacl'}
+ 'arm': 'arm'}
arch_to_output_folder = {'x86-32': 'runtime-x86-32-build',
'x86-64': 'runtime-x86-64-build',
'arm': 'runtime-arm-build'}
@@ -114,9 +131,11 @@ def main(args):
options.install_dir],
cwd=SDK_BUILD_DIR)
- buildbot_common.BuildStep(build_prefix + 'Test Mono')
- buildbot_common.Run(['make', 'check', '-j8'],
- cwd=os.path.join(SDK_BUILD_DIR, arch_to_output_folder[options.arch]))
+ # TODO(elijahtaylor,olonho): Re-enable tests on arm when they compile/run.
+ if options.arch != 'arm':
+ buildbot_common.BuildStep(build_prefix + 'Test Mono')
+ buildbot_common.Run(['make', 'check', '-j8'],
+ cwd=os.path.join(SDK_BUILD_DIR, arch_to_output_folder[options.arch]))
return 0
diff --git a/native_client_sdk/src/build_tools/nacl-mono-runtime.sh b/native_client_sdk/src/build_tools/nacl-mono-runtime.sh
index 7dfffd871a..ffc6f4764b 100755
--- a/native_client_sdk/src/build_tools/nacl-mono-runtime.sh
+++ b/native_client_sdk/src/build_tools/nacl-mono-runtime.sh
@@ -11,13 +11,16 @@ if [[ $# -ne 3 ]]; then
exit -1
fi
+readonly CLEAN=1
+readonly DEBUG=0
+readonly PARALLEL=0
readonly MONO_DIR=$(readlink -f $1)
readonly BUILD_DIR=$(readlink -f $2)
readonly INSTALL_DIR=$(readlink -f $3)
readonly ORIGINAL_CWD=$(pwd)
set +e
-if [ -f ${BUILD_DIR}/Makefile ]; then
+if [ -f ${BUILD_DIR}/Makefile -a ${CLEAN} != 0 ]; then
cd ${BUILD_DIR}
make distclean
fi
@@ -27,34 +30,61 @@ cd $ORIGINAL_CWD
case "${TARGET_ARCH}" in
x86-32)
readonly USE_PNACL=0
+ readonly USE_NEWLIB=0
+ readonly TC_FLAVOUR=linux_x86_glibc
readonly NACL_CROSS_PREFIX_DASH=i686-nacl-
- readonly CONFIG_OPTS="--host=i686-pc-linux-gnu \
- --build=i686-pc-linux-gnu \
- --target=i686-pc-linux-gnu"
+ CONFIG_OPTS="--host=i686-pc-linux-gnu \
+ --build=i686-pc-linux-gnu \
+ --target=i686-pc-linux-gnu"
readonly LIBDIR=lib32
- readonly CUSTOM_CFLAGS=""
+ CUSTOM_CFLAGS=""
readonly CUSTOM_LDFLAGS=""
;;
x86-64)
readonly USE_PNACL=0
+ readonly USE_NEWLIB=0
+ readonly TC_FLAVOUR=linux_x86_glibc
readonly NACL_CROSS_PREFIX_DASH=x86_64-nacl-
- readonly CONFIG_OPTS="--host=x86_64-pc-linux-gnu \
- --build=x86_64-pc-linux-gnu \
- --target=x86_64-pc-linux-gnu"
+ CONFIG_OPTS="--host=x86_64-pc-linux-gnu \
+ --build=x86_64-pc-linux-gnu \
+ --target=x86_64-pc-linux-gnu"
readonly LIBDIR=lib
- readonly CUSTOM_CFLAGS=""
+ CUSTOM_CFLAGS=""
readonly CUSTOM_LDFLAGS=""
;;
arm)
+ readonly USE_PNACL=0
+ readonly USE_NEWLIB=1
+ readonly TC_FLAVOUR=linux_arm_newlib
+ readonly NACL_CROSS_PREFIX_DASH=arm-nacl-
+ CONFIG_OPTS="--host=armv7l-unknown-linux-gnueabi \
+ --build=x86_64-pc-linux-gnu \
+ --target=armv7l-unknown-linux-gnueabi \
+ --with-jumptables=yes"
+ readonly LIBDIR=libarm
+ # TODO(olonho): move it to Mono's configure, once nacl target implemented.
+ CUSTOM_CFLAGS="\
+-DARM_FPU_VFP=1 \
+-D__ARM_ARCH_7__ \
+-Dtimezone=_timezone \
+-DDISABLE_SOCKETS \
+-DDISABLE_ATTACH \
+"
+ readonly CUSTOM_LDFLAGS=""
+ ;;
+arm-pnacl)
readonly USE_PNACL=1
+ readonly USE_NEWLIB=1
+ readonly TC_FLAVOUR=linux_x86_pnacl/newlib
readonly NACL_CROSS_PREFIX_DASH=pnacl-
readonly PNACL_LINK_ARGS="-arch armv7 -O2"
- readonly CONFIG_OPTS="--host=armv7l-unknown-linux-gnueabi \
+ CONFIG_OPTS="--host=armv7l-unknown-linux-gnueabi \
--build=x86_64-pc-linux-gnu \
- --target=armv7l-unknown-linux-gnueabi"
+ --target=armv7l-unknown-linux-gnueabi \
+ --with-jumptables=yes"
readonly LIBDIR=libarm
# TODO(olonho): move it to Mono's configure, once nacl target implemented.
- readonly CUSTOM_CFLAGS="\
+ CUSTOM_CFLAGS="\
-D__arm__ \
-D__ARM_ARCH_7__ \
-D__portable_native_client__ \
@@ -62,33 +92,42 @@ arm)
-Dtimezone=_timezone \
-DDISABLE_SOCKETS \
-DDISABLE_ATTACH \
--DUSE_NEWLIB \
"
readonly CUSTOM_LDFLAGS=${PNACL_LINK_ARGS}
;;
+*)
+ echo "Unsupported target ${TARGET_ARCH}"
+ exit 1
esac
-# UGLY hack to allow dynamic linking
-sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
+if [ ${USE_NEWLIB} == 1 ]; then
+ CUSTOM_CFLAGS="${CUSTOM_CFLAGS} -DUSE_NEWLIB"
+ CONFIG_OPTS="${CONFIG_OPTS} --enable-shared=no"
+else
+ CONFIG_OPTS="${CONFIG_OPTS} --enable-shared=yes"
+ # UGLY hack to allow dynamic linking
+ sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
${MONO_DIR}/configure
-sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
+ sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
${MONO_DIR}/libgc/configure
-sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
+ sed -i -e s/elf_i386/elf_nacl/ -e s/elf_x86_64/elf64_nacl/ \
${MONO_DIR}/eglib/configure
+fi
-rm -rf ${BUILD_DIR}
-mkdir -p ${BUILD_DIR}
+if [ ${CLEAN} != 0 ]; then
+ rm -rf ${BUILD_DIR}
+ mkdir -p ${BUILD_DIR}
+fi
cd ${BUILD_DIR}
mkdir -p ${INSTALL_DIR}
+readonly NACL_BIN_PATH=${NACL_SDK_ROOT}/toolchain/${TC_FLAVOUR}/bin
+
if [ ${USE_PNACL} == 1 ]; then
- readonly NACL_BIN_PATH="\
-${NACL_SDK_ROOT}/toolchain/linux_x86_pnacl/newlib/bin"
readonly NACLCC=${NACL_BIN_PATH}/pnacl-clang
readonly NACLCXX=${NACL_BIN_PATH}/pnacl-clang++
else
- readonly NACL_BIN_PATH=${NACL_SDK_ROOT}/toolchain/linux_x86_glibc/bin
readonly NACLCC=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}gcc
readonly NACLCXX=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}g++
fi
@@ -98,7 +137,21 @@ readonly NACLLD=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}ld
readonly NACLOBJDUMP=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}objdump
readonly NACLSTRIP=${NACL_BIN_PATH}/${NACL_CROSS_PREFIX_DASH}strip
-CFLAGS="-g -O2 -D_POSIX_PATH_MAX=256 -DPATH_MAX=256 $CUSTOM_CFLAGS"
+if [ ${DEBUG} == 1 ]; then
+ CFLAGS="$CUSTOM_CFLAGS"
+ CONFIG_OPTS="${CONFIG_OPTS} --enable-debug=yes"
+else
+ CFLAGS="-g $CUSTOM_CFLAGS"
+ CONFIG_OPTS="${CONFIG_OPTS} --enable-debug=no"
+fi
+
+if [ ${PARALLEL} == 1 ]; then
+ readonly JOBS="-j16"
+else
+ readonly JOBS=
+fi
+
+
LDFLAGS="$CUSTOM_LDFLAGS"
LIBS="-lnacl_dyncode -lc -lg -lnosys -lpthread"
@@ -126,9 +179,14 @@ ${MONO_DIR}/configure ${CONFIG_OPTS} \
--enable-nls=no \
--enable-nacl-codegen \
--disable-system-aot \
- --enable-shared \
--disable-parallel-mark \
--with-static-mono=no
-make
-make install
+if [ ${USE_NEWLIB} == 1 ]; then
+ # Newlib build doesn't support building shared libs, and unfortunately, this
+ # leads to libmonoruntime.la no being built as well, unless we'll do that
+ # explicitly.
+ make ${JOBS} -C mono/metadata libmonoruntime.la
+fi
+make ${JOBS}
+make ${JOBS} install
diff --git a/native_client_sdk/src/build_tools/parse_dsc.py b/native_client_sdk/src/build_tools/parse_dsc.py
new file mode 100644
index 0000000000..a0ccb37cf1
--- /dev/null
+++ b/native_client_sdk/src/build_tools/parse_dsc.py
@@ -0,0 +1,238 @@
+# 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.
+
+import collections
+import fnmatch
+import optparse
+import os
+import sys
+
+# 'KEY' : ( <TYPE>, [Accepted Values], <Required?>)
+DSC_FORMAT = {
+ 'DISABLE': (bool, [True, False], False),
+ 'DISABLE_PACKAGE': (bool, [True, False], False),
+ 'TOOLS' : (list, ['newlib:arm', 'newlib:x64', 'newlib:x86', 'newlib',
+ 'glibc', 'pnacl', 'win', 'linux'], True),
+ 'CONFIGS' : (list, ['Debug', 'Release'], False),
+ 'PREREQ' : (list, '', False),
+ 'TARGETS' : (list, {
+ 'NAME': (str, '', True),
+ # main = nexe target
+ # lib = library target
+ # so = shared object target, automatically added to NMF
+ # so-standalone = shared object target, not put into NMF
+ 'TYPE': (str, ['main', 'lib', 'so', 'so-standalone'], True),
+ 'SOURCES': (list, '', True),
+ 'CCFLAGS': (list, '', False),
+ 'CXXFLAGS': (list, '', False),
+ 'DEFINES': (list, '', False),
+ 'LDFLAGS': (list, '', False),
+ 'INCLUDES': (list, '', False),
+ 'LIBS' : (list, '', False),
+ 'DEPS' : (list, '', False)
+ }, True),
+ 'HEADERS': (list, {
+ 'FILES': (list, '', True),
+ 'DEST': (str, '', True),
+ }, False),
+ 'SEARCH': (list, '', False),
+ 'POST': (str, '', False),
+ 'PRE': (str, '', False),
+ 'DEST': (str, ['examples/getting_started', 'examples/api',
+ 'examples/demo', 'examples/tutorial',
+ 'src', 'testlibs', 'tests'], True),
+ 'NAME': (str, '', False),
+ 'DATA': (list, '', False),
+ 'TITLE': (str, '', False),
+ 'GROUP': (str, '', False),
+ 'EXPERIMENTAL': (bool, [True, False], False),
+}
+
+def IgnoreMsgFunc(test):
+ pass
+
+
+def ErrorMsgFunc(text):
+ sys.stderr.write(text + '\n')
+
+
+def ValidateFormat(src, dsc_format, ErrorMsg=ErrorMsgFunc):
+ failed = False
+
+ # Verify all required keys are there
+ for key in dsc_format:
+ (exp_type, exp_value, required) = dsc_format[key]
+ if required and key not in src:
+ ErrorMsg('Missing required key %s.' % key)
+ failed = True
+
+ # For each provided key, verify it's valid
+ for key in src:
+ # Verify the key is known
+ if key not in dsc_format:
+ ErrorMsg('Unexpected key %s.' % key)
+ failed = True
+ continue
+
+ exp_type, exp_value, required = dsc_format[key]
+ value = src[key]
+
+ # Verify the key is of the expected type
+ if exp_type != type(value):
+ ErrorMsg('Key %s expects %s not %s.' % (
+ key, exp_type.__name__.upper(), type(value).__name__.upper()))
+ failed = True
+ continue
+
+ # Verify the value is non-empty if required
+ if required and not value:
+ ErrorMsg('Expected non-empty value for %s.' % key)
+ failed = True
+ continue
+
+ # If it's a bool, the expected values are always True or False.
+ if exp_type is bool:
+ continue
+
+ # If it's a string and there are expected values, make sure it matches
+ if exp_type is str:
+ if type(exp_value) is list and exp_value:
+ if value not in exp_value:
+ ErrorMsg("Value '%s' not expected for %s." % (value, key))
+ failed = True
+ continue
+
+ # if it's a list, then we need to validate the values
+ if exp_type is list:
+ # If we expect a dictionary, then call this recursively
+ if type(exp_value) is dict:
+ for val in value:
+ if not ValidateFormat(val, exp_value, ErrorMsg):
+ failed = True
+ continue
+ # If we expect a list of strings
+ if type(exp_value) is str:
+ for val in value:
+ if type(val) is not str:
+ ErrorMsg('Value %s in %s is not a string.' % (val, key))
+ failed = True
+ continue
+ # if we expect a particular string
+ if type(exp_value) is list:
+ for val in value:
+ if val not in exp_value:
+ ErrorMsg('Value %s not expected in %s.' % (val, key))
+ failed = True
+ continue
+
+ # If we got this far, it's an unexpected type
+ ErrorMsg('Unexpected type %s for key %s.' % (str(type(src[key])), key))
+ continue
+ return not failed
+
+
+def LoadProject(filename, ErrorMsg=ErrorMsgFunc, verbose=False):
+ if verbose:
+ errmsg = ErrorMsgFunc
+ else:
+ errmsg = IgnoreMsgFunc
+
+ with open(filename, 'r') as descfile:
+ desc = eval(descfile.read(), {}, {})
+ if desc.get('DISABLE', False):
+ return None
+ if not ValidateFormat(desc, DSC_FORMAT, errmsg):
+ ErrorMsg('Failed to validate: ' + filename)
+ return None
+ desc['FILEPATH'] = os.path.abspath(filename)
+ return desc
+
+
+def AcceptProject(desc, filters):
+ # Check if we should filter node this on toolchain
+ if not filters:
+ return True
+
+ for key, expected in filters.iteritems():
+ # For any filtered key which is unspecified, assumed False
+ value = desc.get(key, False)
+
+ # If we provide an expected list, match at least one
+ if type(expected) != list:
+ expected = set([expected])
+ if type(value) != list:
+ value = set([value])
+
+ if not set(expected) & set(value):
+ return False
+
+ # If we fall through, then we matched the filters
+ return True
+
+
+def PruneTree(tree, filters):
+ out = collections.defaultdict(list)
+ for branch, projects in tree.iteritems():
+ for desc in projects:
+ if AcceptProject(desc, filters):
+ out[branch].append(desc)
+
+ return out
+
+
+def LoadProjectTree(srcpath, toolchains=None, verbose=False, filters=None,
+ ErrorMsg=ErrorMsgFunc, InfoMsg=ErrorMsgFunc):
+ # Build the tree
+ out = collections.defaultdict(list)
+ for root, _, files in os.walk(srcpath):
+ for filename in files:
+ if fnmatch.fnmatch(filename, '*.dsc'):
+ filepath = os.path.join(root, filename)
+ desc = LoadProject(filepath, ErrorMsg, verbose)
+ if desc:
+ key = desc['DEST']
+ out[key].append(desc)
+
+ # Filter if needed
+ if filters:
+ out = PruneTree(out, filters)
+ return out
+
+
+def PrintProjectTree(tree, InfoMsg=ErrorMsgFunc):
+ for key in tree:
+ print key + ':'
+ for val in tree[key]:
+ print '\t' + val['NAME']
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('-e', '--experimental',
+ help='build experimental examples and libraries', action='store_true')
+ parser.add_option('-t', '--toolchain',
+ help='Build using toolchain. Can be passed more than once.',
+ action='append')
+
+ options, files = parser.parse_args(argv[1:])
+ filters = {}
+
+ if len(files):
+ parser.error('Not expecting files.')
+ return 1
+
+ if options.toolchain:
+ filters['TOOLS'] = options.toolchain
+
+ if not options.experimental:
+ filters['EXPERIMENTAL'] = False
+
+ tree = LoadProjectTree('.', filters=filters)
+ PrintProjectTree(tree)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/native_client_sdk/src/build_tools/sdk_tools/command/update.py b/native_client_sdk/src/build_tools/sdk_tools/command/update.py
index 3ae4f0d46a..f485804f13 100644
--- a/native_client_sdk/src/build_tools/sdk_tools/command/update.py
+++ b/native_client_sdk/src/build_tools/sdk_tools/command/update.py
@@ -2,9 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import hashlib
import copy
import logging
import os
+import subprocess
import sys
import urlparse
import urllib2
@@ -30,6 +32,7 @@ except ImportError:
RECOMMENDED = 'recommended'
SDK_TOOLS = 'sdk_tools'
HTTP_CONTENT_LENGTH = 'Content-Length' # HTTP Header field for content length
+DEFAULT_CACHE_SIZE = 512 * 1024 * 1024 # 1/2 Gb cache by default
class UpdateDelegate(object):
@@ -45,18 +48,88 @@ class UpdateDelegate(object):
class RealUpdateDelegate(UpdateDelegate):
- def __init__(self, user_data_dir, install_dir):
+ def __init__(self, user_data_dir, install_dir, cfg):
UpdateDelegate.__init__(self)
- self.user_data_dir = user_data_dir
+ self.archive_cache = os.path.join(user_data_dir, 'archives')
self.install_dir = install_dir
+ self.cache_max = getattr(cfg, 'cache_max', DEFAULT_CACHE_SIZE)
def BundleDirectoryExists(self, bundle_name):
bundle_path = os.path.join(self.install_dir, bundle_name)
return os.path.isdir(bundle_path)
+ def VerifyDownload(self, filename, archive):
+ """Verify that a local filename in the cache matches the given
+ online archive.
+
+ Returns True if both size and sha1 match, False otherwise.
+ """
+ filename = os.path.join(self.archive_cache, filename)
+ if not os.path.exists(filename):
+ logging.info('File does not exist: %s.' % filename)
+ return False
+ size = os.path.getsize(filename)
+ if size != archive.size:
+ logging.info('File size does not match (%d vs %d): %s.' % (size,
+ archive.size, filename))
+ return False
+ sha1_hash = hashlib.sha1()
+ with open(filename) as f:
+ sha1_hash.update(f.read())
+ if sha1_hash.hexdigest() != archive.GetChecksum():
+ logging.info('File hash does not match: %s.' % filename)
+ return False
+ return True
+
+ def BytesUsedInCache(self):
+ """Determine number of bytes currently be in local archive cache."""
+ total = 0
+ for root, _, files in os.walk(self.archive_cache):
+ for filename in files:
+ total += os.path.getsize(os.path.join(root, filename))
+ return total
+
+ def CleanupCache(self):
+ """Remove archives from the local filesystem cache until the
+ total size is below cache_max.
+
+ This is done my deleting the oldest archive files until the
+ condition is satisfied. If cache_max is zero then the entire
+ cache will be removed.
+ """
+ used = self.BytesUsedInCache()
+ logging.info('Cache usage: %d / %d' % (used, self.cache_max))
+ if used <= self.cache_max:
+ return
+ clean_bytes = used - self.cache_max
+
+ logging.info('Clearing %d bytes in archive cache' % clean_bytes)
+ file_timestamps = []
+ for root, _, files in os.walk(self.archive_cache):
+ for filename in files:
+ fullname = os.path.join(root, filename)
+ file_timestamps.append((os.path.getmtime(fullname), fullname))
+
+ file_timestamps.sort()
+ while clean_bytes > 0:
+ assert(file_timestamps)
+ filename_to_remove = file_timestamps[0][1]
+ clean_bytes -= os.path.getsize(filename_to_remove)
+ logging.info('Removing from cache: %s' % filename_to_remove)
+ os.remove(filename_to_remove)
+ # Also remove resulting empty parent directory structure
+ while True:
+ filename_to_remove = os.path.dirname(filename_to_remove)
+ if not os.listdir(filename_to_remove):
+ os.rmdir(filename_to_remove)
+ else:
+ break
+ file_timestamps = file_timestamps[1:]
+
def DownloadToFile(self, url, dest_filename):
- sdk_update_common.MakeDirs(self.user_data_dir)
- dest_path = os.path.join(self.user_data_dir, dest_filename)
+ dest_path = os.path.join(self.archive_cache, dest_filename)
+ sdk_update_common.MakeDirs(os.path.dirname(dest_path))
+
out_stream = None
url_stream = None
try:
@@ -101,28 +174,31 @@ class RealUpdateDelegate(UpdateDelegate):
raise Error('Unable to chdir into "%s".\n %s' % (extract_path, e))
for i, archive in enumerate(archives):
- archive_path = os.path.join(self.user_data_dir, archive)
+ archive_path = os.path.join(self.archive_cache, archive)
- try:
- logging.info('Opening file %s (%d/%d).' % (archive_path, i + 1,
- len(archives)))
+ if len(archives) > 1:
+ print '(file %d/%d - "%s")' % (
+ i + 1, len(archives), os.path.basename(archive_path))
+ logging.info('Extracting to %s' % (extract_path,))
+
+ if sys.platform == 'win32':
+ try:
+ logging.info('Opening file %s (%d/%d).' % (archive_path, i + 1,
+ len(archives)))
+ try:
+ tar_file = cygtar.CygTar(archive_path, 'r', verbose=True)
+ except Exception as e:
+ raise Error("Can't open archive '%s'.\n %s" % (archive_path, e))
+
+ tar_file.Extract()
+ finally:
+ if tar_file:
+ tar_file.Close()
+ else:
try:
- tar_file = cygtar.CygTar(archive_path, 'r', verbose=True)
- except Exception as e:
- raise Error('Can\'t open archive "%s".\n %s' % (archive_path, e))
-
- logging.info('Extracting to %s' % (extract_path,))
- if len(archives) > 1:
- print '(file %d/%d - "%s")' % (
- i + 1, len(archives), os.path.basename(archive_path))
- tar_file.Extract()
- finally:
- if tar_file:
- tar_file.Close()
-
- # Remove the archive.
- if os.path.exists(archive_path):
- os.remove(archive_path)
+ subprocess.check_call(['tar', 'xf', archive_path])
+ except subprocess.CalledProcessError:
+ raise Error('Error extracting archive: %s' % archive_path)
logging.info('Changing the directory to %s' % (curpath,))
os.chdir(curpath)
@@ -236,15 +312,20 @@ def _UpdateBundle(delegate, bundle, local_manifest):
archive_filenames = []
- print 'Downloading bundle %s' % (bundle.name,)
+ shown_banner = False
for i, archive in enumerate(archives):
- if len(archives) > 1:
- print '(file %d/%d - "%s")' % (
- i + 1, len(archives), os.path.basename(archive.url))
-
archive_filename = _GetFilenameFromURL(archive.url)
- sha1, size = delegate.DownloadToFile(archive.url, archive_filename)
- _ValidateArchive(archive, sha1, size)
+ archive_filename = os.path.join(bundle.name, archive_filename)
+
+ if not delegate.VerifyDownload(archive_filename, archive):
+ if not shown_banner:
+ shown_banner = True
+ print 'Downloading bundle %s' % (bundle.name,)
+ if len(archives) > 1:
+ print '(file %d/%d - "%s")' % (
+ i + 1, len(archives), os.path.basename(archive.url))
+ sha1, size = delegate.DownloadToFile(archive.url, archive_filename)
+ _ValidateArchive(archive, sha1, size)
archive_filenames.append(archive_filename)
@@ -271,17 +352,18 @@ def _UpdateBundle(delegate, bundle, local_manifest):
logging.info('Updating local manifest to include bundle %s' % (bundle.name))
local_manifest.MergeBundle(bundle)
+ delegate.CleanupCache()
def _GetFilenameFromURL(url):
- _, _, path, _, _, _ = urlparse.urlparse(url)
- return path.split('/')[-1]
+ path = urlparse.urlparse(url)[2]
+ return os.path.basename(path)
def _ValidateArchive(archive, actual_sha1, actual_size):
- if actual_sha1 != archive.GetChecksum():
- raise Error('SHA1 checksum mismatch on "%s". Expected %s but got %s' % (
- archive.name, archive.GetChecksum(), actual_sha1))
if actual_size != archive.size:
raise Error('Size mismatch on "%s". Expected %s but got %s bytes' % (
archive.name, archive.size, actual_size))
+ if actual_sha1 != archive.GetChecksum():
+ raise Error('SHA1 checksum mismatch on "%s". Expected %s but got %s' % (
+ archive.name, archive.GetChecksum(), actual_sha1))
diff --git a/native_client_sdk/src/build_tools/sdk_tools/config.py b/native_client_sdk/src/build_tools/sdk_tools/config.py
index e35e7d5e56..6fc9be07be 100644
--- a/native_client_sdk/src/build_tools/sdk_tools/config.py
+++ b/native_client_sdk/src/build_tools/sdk_tools/config.py
@@ -5,6 +5,7 @@
import json
import logging
import urlparse
+from sdk_update_common import Error
SOURCE_WHITELIST = [
'http://localhost/', # For testing.
@@ -33,14 +34,26 @@ class Config(dict):
else:
self.sources = []
+ def LoadJson(self, json_data):
+ try:
+ self.update(json.loads(json_data))
+ except Exception as e:
+ raise Error('Error reading json config:\n%s' % str(e))
+
def ToJson(self):
- return json.dumps(self, sort_keys=False, indent=2)
+ try:
+ return json.dumps(self, sort_keys=False, indent=2)
+ except Exception as e:
+ raise Error('Json encoding error writing config:\n%s' % e)
def __getattr__(self, name):
- return self.__getitem__(name)
+ if name in self:
+ return self[name]
+ else:
+ raise AttributeError('Config does not contain: %s' % name)
def __setattr__(self, name, value):
- return self.__setitem__(name, value)
+ self[name] = value
def AddSource(self, source):
if not IsSourceValid(source):
diff --git a/native_client_sdk/src/build_tools/sdk_tools/sdk_update_main.py b/native_client_sdk/src/build_tools/sdk_tools/sdk_update_main.py
index b38933dc9c..f763b26405 100755
--- a/native_client_sdk/src/build_tools/sdk_tools/sdk_update_main.py
+++ b/native_client_sdk/src/build_tools/sdk_tools/sdk_update_main.py
@@ -8,7 +8,6 @@
import config
import cStringIO
import download
-import json
import logging
import optparse
import os
@@ -56,23 +55,29 @@ def hide(fn):
def LoadConfig(raise_on_error=False):
path = os.path.join(USER_DATA_DIR, CONFIG_FILENAME)
+ cfg = config.Config()
if not os.path.exists(path):
- return config.Config()
+ return cfg
try:
try:
with open(path) as f:
- return config.Config(json.loads(f.read()))
+ file_data = f.read()
except IOError as e:
raise Error('Unable to read config from "%s".\n %s' % (path, e))
- except Exception as e:
+
+ try:
+ cfg.LoadJson(file_data)
+ except Error as e:
raise Error('Parsing config file from "%s" failed.\n %s' % (path, e))
+ return cfg
except Error as e:
if raise_on_error:
raise
else:
logging.warn(str(e))
- return config.Config()
+
+ return cfg
def WriteConfig(cfg):
@@ -82,10 +87,7 @@ def WriteConfig(cfg):
except Exception as e:
raise Error('Unable to create directory "%s".\n %s' % (USER_DATA_DIR, e))
- try:
- cfg_json = cfg.ToJson()
- except Exception as e:
- raise Error('Json encoding error writing config "%s".\n %s' % (path, e))
+ cfg_json = cfg.ToJson()
try:
with open(path, 'w') as f:
@@ -210,7 +212,7 @@ def CMDupdate(parser, args):
try:
delegate = command.update.RealUpdateDelegate(USER_DATA_DIR,
- DEFAULT_SDK_ROOT)
+ DEFAULT_SDK_ROOT, cfg)
command.update.Update(delegate, remote_manifest, local_manifest, args,
options.force)
finally:
@@ -260,9 +262,10 @@ def CMDreinstall(parser, args):
parser.error('No bundles given')
return 0
+ cfg = LoadConfig()
try:
delegate = command.update.RealUpdateDelegate(USER_DATA_DIR,
- DEFAULT_SDK_ROOT)
+ DEFAULT_SDK_ROOT, cfg)
command.update.Reinstall(delegate, local_manifest, args)
finally:
# Always write out the local manifest, we may have successfully updated one
@@ -348,7 +351,7 @@ def UpdateSDKTools(options, args):
try:
delegate = command.update.RealUpdateDelegate(USER_DATA_DIR,
- DEFAULT_SDK_ROOT)
+ DEFAULT_SDK_ROOT, cfg)
command.update.UpdateBundleIfNeeded(
delegate,
remote_manifest,
diff --git a/native_client_sdk/src/build_tools/sdk_tools/set_nacl_env.py b/native_client_sdk/src/build_tools/sdk_tools/set_nacl_env.py
deleted file mode 100755
index c2aaf695af..0000000000
--- a/native_client_sdk/src/build_tools/sdk_tools/set_nacl_env.py
+++ /dev/null
@@ -1,492 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-''' A tool to setup the NaCl build env and invoke a command such as make '''
-
-__author__ = 'gwink@google.com (Georges Winkenbach)'
-
-import optparse
-import os
-import subprocess
-import sys
-
-# The default sdk platform to use if the user doesn't specify one.
-__DEFAULT_SDK_PLATFORM = 'pepper_15'
-
-# Usage info.
-__GLOBAL_HELP = '''%prog options [command]
-
-set-nacl-env is a utility that sets up the environment required to build
-NaCl modules and invokes an optional command in a shell. If no command
-is specified, set-nacl-env spawns a new shell instead. Optionally, the user
-can request that the settings are printed to stdout.
-'''
-
-# Map the string stored in |sys.platform| into a toolchain host specifier.
-__PLATFORM_TO_HOST_MAP = {
- 'win32': 'windows',
- 'cygwin': 'windows',
- 'linux2': 'linux',
- 'darwin': 'mac',
- }
-
-# Map key triplet of (host, arch, variant) keys to the corresponding subdir in
-# the toolchain path. For instance (mac, x86-32, newlib) maps to mac_x86_newlib.
-# Note to NaCl eng.: this map is duplicated in nack_utils.py; you must keep them
-# synched.
-__HOST_TO_TOOLCHAIN_MAP = {
- 'mac': { # Host arch variant
- 'x86-32': {
- 'newlib': 'mac_x86_newlib', # Mac x86-32 newlib
- 'glibc' : 'mac_x86'}, # Mac x86-32 glibc
- 'x86-64': {
- 'newlib': 'mac_x86_newlib', # Mac x86-64 newlib
- 'glibc' : 'mac_x86'}, # Mac x86-64 glibc
- },
- 'windows': {
- 'x86-32': {
- 'newlib': 'win_x86_newlib', # Windows x86-32 newlib
- 'glibc' : 'win_x86'}, # Windows x86-32 glibc
- 'x86-64': {
- 'newlib': 'win_x86_newlib', # Windows x86-64 newlib
- 'glibc' : 'win_x86'}, # Windows x86-64 glibc
- },
- 'linux': {
- 'x86-32': {
- 'newlib': 'linux_x86_newlib', # Windows x86-32 newlib
- 'glibc' : 'linux_x86'}, # Windows x86-32 glibc
- 'x86-64': {
- 'newlib': 'linux_x86_newlib', # Windows x86-64 newlib
- 'glibc' : 'linux_x86'}, # Windows x86-64 glibc
- },
- }
-
-# Map architecture specification to the corresponding tool-name prefix.
-# @private
-__VALID_ARCH_SPECS = {
- 'x86-32': 'i686',
- 'x86-64': 'x86_64',
- }
-
-# Valid lib variants.
-__VALID_VARIANT = ['glibc', 'newlib']
-
-# Lists of env keys for build tools. Note: Each matching value is actually a
-# format template with fields for 'prefix' such as 'i686-nacl-' and 'extras'
-# such as ' -m64'.
-__BUILD_TOOLS = {
- 'CC': '{prefix}gcc{extras}',
- 'CXX': '{prefix}g++{extras}',
- 'AR': '{prefix}ar{extras}',
- 'LINK': '{prefix}g++{extras}',
- 'STRIP': '{prefix}strip',
- 'RANLIB': '{prefix}ranlib',
- }
-
-# List of env keys for build options with corresponding settings that are
-# common to all build configurations.
-__BUILD_OPTIONS = {
- 'CFLAGS': ['-std=gnu99', '-Wall', '-Wswitch-enum', '-g'],
- 'CXXFLAGS': ['-std=gnu++98', '-Wswitch-enum', '-g', '-pthread'],
- 'CPPFLAGS': ['-D_GNU_SOURCE=1', '-D__STDC_FORMAT_MACROS=1'],
- 'LDFLAGS': [],
- }
-
-# All the build-flags env keys in one list.
-__ALL_ENV_KEYS = __BUILD_TOOLS.keys() + __BUILD_OPTIONS.keys()
-
-# Map build types to the corresponding build flags.
-__BUILD_TYPES = {
- 'debug': ['-O0'],
- 'release': ['-O3'],
- }
-
-
-def FormatOptionList(option_list, prefix='', separator=' '):
- ''' Format a list of build-option items into a string.
-
- Format a list of build-option items into a string suitable for output.
-
- Args:
- prefix: a prefix string to prepend to each list item. For instance,
- prefix='-D' with item='__DEBUG' generates '-D__DEBUG'.
- separator: a separator string to insert between items.
-
- Returns:
- A formatted string. An empty string if list is empty.
- '''
- return separator.join([prefix + item for item in option_list])
-
-
-def GetNaclSdkRoot():
- ''' Produce a string with the full path to the NaCl SDK root.
-
- The path to nacl-sdk root is derived from one of two sources. First, if
- NACL_SDK_ROOT is defined in env it is assumed to contain the desired sdk
- root. That makes it possible for this tool to run from any location. If
- NACL_SDK_ROOT is not defined or is empty, the sdk root is taken as the
- parent directory to this script's file. This works well when this script
- is ran from the sdk_tools directory in the standard SDK installation.
-
- Returns:
- A string with the path to the NaCl SDK root.
- '''
- if 'NACL_SDK_ROOT' in os.environ:
- return os.environ['NACL_SDK_ROOT']
- else:
- SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
- SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
- return os.path.join(SRC_DIR, 'native_client')
-
-
-def GetToolchainPath(options):
- ''' Build the path to the toolchain directory.
-
- Given the host, sdk-root directory, sdk platform, architecture and library
- variant, this function builds the path to the toolchain directory.
-
- Examples:
- For
- sdk_root == 'c:/cool_code/nacl_sdk'
- arch == 'x86-32'
- lib variant == 'newlib'
- nacl platform = 'pepper_17'
- host == 'mac'
- this function returns :
- toolchain_path == /cool_code/nacl_sdk/pepper_17/toolchain/mac_x86_newlib
-
- Args:
- options: the options instances containing attributes options.host,
- options.arch, options.lib_variant, options.sdk_root and
- options.sdk_platform.
-
- Returns:
- A string containing the absolute path to the base directory for the
- toolchain.
- '''
- host = options.host
- arch = options.arch
- variant = options.lib_variant
- toolchain_dir = __HOST_TO_TOOLCHAIN_MAP[host][arch][variant]
- base_dir = os.path.abspath(options.sdk_root)
- return os.path.join(base_dir, options.sdk_platform, 'toolchain',
- toolchain_dir)
-
-
-def ConfigureBaseEnv(merge):
- ''' Configure and return a new env instance with the essential options.
-
- Create and return a new env instance with the base configuration. That env
- contains at least an empty entry for each key defined in __ALL_ENV_KEYS.
- However, if merge is True, a copy of the current os.environ is used to seed
- env.
-
- Argument:
- merge: True ==> merge build configuration with os.environ..
-
- Returns:
- A base env map.
- '''
- env = {}
- if merge:
- for key, value in os.environ.items():
- env[key] = [value]
- # Ensure that every env key has a default definition.
- for key in __ALL_ENV_KEYS:
- env.setdefault(key, [])
- return env
-
-
-def SetBuildTools(env, tool_bin_path, tool_prefix, extras_flags=''):
- ''' Configure the build tools build flags in env.
-
- Given the absolute path to the toolchain's bin directory, tool_prefix and
- optional extra_flags build flags, set the entries for the build tools
- in env. For instance, using the sample path from GetToolchainPath above and
- tool_prefix = 'i686-nacl-' we would get
-
- env['CC'] =
- '/cool_code/nacl_sdk/pepper_17/toolchain/mac_x86_newlib/bin/i686-nacl-gcc'
-
- Args:
- env: the env map to setup.
- tool_bin_path: the absolute path to the toolchain's bin directory.
- tool_prefix: a string with the tool's prefix, such as 'i686-nacl-'.
- extra_flags: optional extra flags, such as ' -m64'.
- '''
- for key, val in __BUILD_TOOLS.iteritems():
- tool_name = val.format(prefix=tool_prefix, extras=extras_flags)
- env[key] = os.path.join(tool_bin_path, tool_name)
-
-
-def SetRuntimeTools(env, tool_runtime_path):
- ''' Setup the runtime tools in env.
-
- Given an absolute path to the toolchain's runtime directory, setup the
- entries for the runtime tools in env.
-
- Args:
- env: the env map to setup.
- tool_runtime_path: the absolute path to the toolchain's runtime directory.
- '''
- env['NACL_IRT_CORE32'] = os.path.join(tool_runtime_path,
- 'irt_core_x86_32.nexe')
- env['NACL_IRT_CORE64'] = os.path.join(tool_runtime_path,
- 'irt_core_x86_64.nexe')
-
-
-def SetCommonBuildOptions(env, options):
- ''' Set the common build options, such as CFLAGS.
-
- Set the build options, such as CFLAGS that are common to all build
- configurations, given the built type.
-
- Args:
- env: the env map to set.
- build_type: one of 'debug' or 'release'.
- '''
- # Set the build flags from __BUILD_OPTIONS.
- for key, val in __BUILD_OPTIONS.iteritems():
- env[key].extend(val)
- # Add the build-type specific flags.
- env['CFLAGS'].extend(__BUILD_TYPES[options.build_type])
- env['CXXFLAGS'].extend(__BUILD_TYPES[options.build_type])
- if not options.no_ppapi:
- env['LDFLAGS'].extend(['-lppapi'])
-
-
-def SetupX86Env(options):
- ''' Generate a new env map for X86 builds.
-
- Generate and return a new env map for x86-NN architecture. The NN bit
- size is derived from options.arch.
-
- Argument:
- options: the cmd-line options.
-
- Returns:
- A new env map with the build configuration flags set.
- '''
- env = ConfigureBaseEnv(options.merge)
-
- # Where to find tools and libraries within the toolchain directory.
- tool_bin_path = os.path.join(options.toolchain_path, 'bin')
- tool_runtime_path = os.path.join(options.toolchain_path, 'runtime')
-
- # Store the bin paths into env. This isn't really part of the build
- # environment. But it's nice to have there for reference.
- env['NACL_TOOL_BIN_PATH'] = tool_bin_path
- env['NACL_TOOL_RUNTIME_PATH'] = tool_runtime_path
-
- if options.arch == 'x86-32':
- SetBuildTools(env, tool_bin_path, 'i686-nacl-', extras_flags=' -m32')
- else:
- assert(options.arch == 'x86-64')
- SetBuildTools(env, tool_bin_path, 'x86_64-nacl-', extras_flags=' -m64')
- SetRuntimeTools(env, tool_runtime_path)
- SetCommonBuildOptions(env, options)
- return env
-
-
-def dump(options, env, template):
- ''' Dump the build settings in env to stdout.
-
- Args:
- options: the cmd-line options, used to output the target buid configuartion.
- env: the env map with the build flags.
- template: a fiormatting template used to format options output. It must
- contain format fields 'option' and 'value'.
- '''
- if options.pretty_print:
- print '\nConfiguration:'
- print '-------------'
- print ' Host = %s' % options.host
- print ' NaCl SDK root = %s' % options.sdk_root
- print ' SDK platform = %s' % options.sdk_platform
- print ' Target architecture = %s' % options.arch
- print ' Lib variant = %s' % options.lib_variant
-
- if options.pretty_print:
- print '\nNaCl toolchain paths:'
- print '-------------------------'
- print ' toolchain = %s' % options.toolchain_path
- print ' toolchain bin = %s' % env['NACL_TOOL_BIN_PATH']
- print ' toolchain runtime = %s' % env['NACL_TOOL_RUNTIME_PATH']
-
- if options.pretty_print:
- print '\nBuild tools:'
- print '-----------'
- print template.format(option='CC', value=env['CC'])
- print template.format(option='CXX', value=env['CXX'])
- print template.format(option='AR', value=env['AR'])
- print template.format(option='LINK', value=env['LINK'])
- print template.format(option='STRIP', value=env['STRIP'])
- print template.format(option='RANLIB', value=env['RANLIB'])
-
- if options.pretty_print:
- print '\nBuild settings:'
- print '--------------'
- print template.format(option='CFLAGS',
- value=FormatOptionList(option_list=env['CFLAGS']))
- print template.format(option='CXXFLAGS',
- value=FormatOptionList(option_list=env['CXXFLAGS']))
- print template.format(option='LDFLAGS',
- value=FormatOptionList(option_list=env['LDFLAGS']))
- print template.format(option='CPPFLAGS',
- value=FormatOptionList(option_list=env['CPPFLAGS']))
- if options.pretty_print:
- print '\nRuntime tools:'
- print '-------------'
- print template.format(option='NACL_IRT_CORE32', value=env['NACL_IRT_CORE32'])
- print template.format(option='NACL_IRT_CORE64', value=env['NACL_IRT_CORE64'])
- print ''
-
-
-def NormalizeEnv(env):
- ''' Returns a copy of env normalized.
-
- Internally, this script uses lists to keep track of build settings in env.
- This function converts these list to space-separated strings of items,
- suitable for use as a subprocess env.
-
- Argument:
- env: env map that must be normalized.
-
- Returns:
- A copy of env with lists converted to strings.
- '''
- norm_env = {}
- for key, value in env.iteritems():
- if isinstance(value, list):
- norm_env[key] = ' '.join(value)
- else:
- norm_env[key] = value
- return norm_env
-
-
-def RunCommandOrShell(cmd_list, env):
- ''' Run the command in cmd_list or a shell if cmd_list is empty.
-
- Run the command in cmd_list using a normalized copy of env. For instance,
- cmd_list might contain the items ['make', 'application'], which would
- cause command 'make application' to run in the current directory. If cmd_list
- is empty, this function will spawn a new sbushell instead.
-
- Args:
- cmd_list: the command list to run.
- env: the environment to use.
- '''
- # If cmd_list is empty, set it up to spawn a shell instead. If cmd_list
- # isn't empty, it will run in the current shell (for security and so that the
- # user can see the output).
- new_shell = False
- if cmd_list:
- # Normalize cmd_list by building a list of individual arguments.
- new_cmd_list = []
- for item in cmd_list:
- new_cmd_list += item.split()
- cmd_list = new_cmd_list
- else:
- # Build a shell command.
- new_shell = True
- if sys.platform == 'win32':
- cmd_list = ['cmd']
- else:
- cmd_list = ['/bin/bash', '-s']
- return subprocess.call(cmd_list, env=NormalizeEnv(env), shell=new_shell)
-
-
-def GenerateBuildSettings(options, args):
- ''' Generate the build settings and dump them or invoke a command.
-
- Given the cmd-line options and remaining cmd-line arguments, generate the
- required build settings and either dump them to stdout or invoke a shell
- command.
-
- Args:
- options: cmd-line options.
- args: unconsumed cmd-line arguments.
-
- Returns:
- 0 in case of success or a command result code otherwise.
- '''
- # A few generated options, which we store in options for convenience.
- options.host = __PLATFORM_TO_HOST_MAP[sys.platform]
- options.sdk_root = GetNaclSdkRoot()
- options.toolchain_path = GetToolchainPath(options)
-
- env = SetupX86Env(options)
- if options.dump:
- dump(options, env, template=options.format_template)
- return 0
- else:
- return RunCommandOrShell(args, env)
-
-
-def main(argv):
- ''' Do main stuff, mainly.
- '''
- parser = optparse.OptionParser(usage=__GLOBAL_HELP)
- parser.add_option(
- '-a', '--arch', dest='arch',
- choices=['x86-32', 'x86-64'],
- default='x86-64',
- help='The target architecture; one of x86-32 or x86-64. '
- '[default = %default.]')
- parser.add_option(
- '-A', '--no_ppapi', dest='no_ppapi',
- default=False,
- action='store_true',
- help='Do not add -lppapi to the link settings.')
- parser.add_option(
- '-d', '--dump', dest='dump',
- default=False,
- action='store_true',
- help='Dump the build settings to stdout')
- parser.add_option(
- '-D', '--pretty_print', dest='pretty_print',
- default=False,
- action='store_true',
- help='Print section headers when dumping to stdout')
- parser.add_option(
- '-f', '--format_template', dest='format_template',
- default=' {option}={value}',
- help="The formatting template used to output (option, value) pairs."
- "[default='%default.']")
- parser.add_option(
- '-n', '--no_merge', dest='merge',
- default=True,
- action='store_false',
- help='Do not merge the build options with current environment. By default'
- ' %prog merges the build flags with the current environment vars.'
- ' This option turns that off.')
- parser.add_option(
- '-p', '--platform', dest='sdk_platform',
- default=__DEFAULT_SDK_PLATFORM,
- help='The SDK platform to use; e.g. pepper_16. [default = %default.]')
- parser.add_option(
- '-t', '--build_type', dest='build_type',
- choices=__BUILD_TYPES.keys(),
- default='debug',
- help='The desired build type; one of debug or release.'
- ' [default = %default.]')
- parser.add_option(
- '-v', '--variant', dest='lib_variant',
- choices=['glibc', 'newlib'], default='newlib',
- help='The lib variant to use; one of glibc or newlib. '
- '[default = %default.]')
-
- (options, args) = parser.parse_args(argv)
-
- # Verify that we're running on a supported host.
- if sys.platform not in __PLATFORM_TO_HOST_MAP:
- sys.stderr.write('Platform %s is not supported.' % sys.platform)
- return 1
-
- return GenerateBuildSettings(options, args)
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
diff --git a/native_client_sdk/src/build_tools/template.mk b/native_client_sdk/src/build_tools/template.mk
index 1cf39a9feb..1b3e5fede9 100644
--- a/native_client_sdk/src/build_tools/template.mk
+++ b/native_client_sdk/src/build_tools/template.mk
@@ -12,7 +12,7 @@
#
# Default configuration
#
-# By default we will build a Debug configuration using the GCC newlib toolcahin
+# By default we will build a Debug configuration using the GCC newlib toolchain
# to override this, specify TOOLCHAIN=newlib|glibc or CONFIG=Debug|Release on
# the make command-line or in this file prior to including common.mk. The
# toolchain we use by default will be the first valid one listed
@@ -27,7 +27,7 @@ VALID_TOOLCHAINS:={{' '.join(tools)}}
# If NACL_SDK_ROOT is not set, then assume it can be found relative to
# to this Makefile.
#
-NACL_SDK_ROOT?=$(abspath $(CURDIR)/../..)
+NACL_SDK_ROOT?=$(abspath $(CURDIR)/{{rel_sdk}})
include $(NACL_SDK_ROOT)/tools/common.mk
@@ -62,7 +62,7 @@ TARGET={{targets[0]['NAME']}}
# switches.
#
# We break this list down into two parts, the set we need to rebuild (DEPS)
-# and the set we do not. This example does not havea any additional library
+# and the set we do not. This example does not have a any additional library
# dependencies.
#
DEPS={{' '.join(targets[0].get('DEPS', []))}}
@@ -91,11 +91,21 @@ $(foreach src,$({{name}}_SOURCES),$(eval $(call COMPILE_RULE,$(src),{{flags}})))
[[ name = target['NAME'] ]]
[[ if target['TYPE'] == 'so':]]
$(eval $(call SO_RULE,{{name}},$({{name}}_SOURCES)))
+[[ elif target['TYPE'] == 'so-standalone':]]
+$(eval $(call SO_RULE,{{name}},$({{name}}_SOURCES),,,1))
[[ else:]]
+ifeq ($(CONFIG),Release)
+$(eval $(call LINK_RULE,{{name}}_unstripped,$({{name}}_SOURCES),$(LIBS),$(DEPS)))
+$(eval $(call STRIP_RULE,{{name}},{{name}}_unstripped))
+else
$(eval $(call LINK_RULE,{{name}},$({{name}}_SOURCES),$(LIBS),$(DEPS)))
+endif
[[]]
#
-# Specify the NMF to be created with no additional arugments.
+# Specify the NMF to be created with no additional arguments.
#
$(eval $(call NMF_RULE,$(TARGET),))
+
+{{post}}
+
diff --git a/native_client_sdk/src/build_tools/test_sdk.py b/native_client_sdk/src/build_tools/test_sdk.py
index f245fb40b1..bd1223a2f1 100755
--- a/native_client_sdk/src/build_tools/test_sdk.py
+++ b/native_client_sdk/src/build_tools/test_sdk.py
@@ -4,15 +4,15 @@
# found in the LICENSE file.
-import copy
import optparse
import os
import sys
import buildbot_common
-import build_utils
+import build_projects
import build_sdk
-import generate_make
+import build_version
+import parse_dsc
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SDK_SRC_DIR = os.path.dirname(SCRIPT_DIR)
@@ -37,33 +37,30 @@ TEST_LIBRARY_LIST = [
def BuildStepBuildExamples(pepperdir, platform):
- build_sdk.BuildStepMakeAll(pepperdir, platform, 'examples', 'Build Examples',
- deps=False)
+ build_sdk.BuildStepMakeAll(pepperdir, platform, 'examples',
+ 'Build Examples (Debug)',
+ deps=False, config='Debug')
+ build_sdk.BuildStepMakeAll(pepperdir, platform, 'examples',
+ 'Build Examples (Release)',
+ deps=False, config='Release')
def BuildStepCopyTests(pepperdir, toolchains, build_experimental, clobber):
buildbot_common.BuildStep('Copy Tests')
- build_sdk.MakeDirectoryOrClobber(pepperdir, 'testlibs', clobber)
- build_sdk.MakeDirectoryOrClobber(pepperdir, 'tests', clobber)
-
- args = ['--dstroot=%s' % pepperdir, '--master']
- for toolchain in toolchains:
- args.append('--' + toolchain)
-
- for library in TEST_LIBRARY_LIST:
- dsc = os.path.join(SDK_LIBRARY_DIR, library, 'library.dsc')
- args.append(dsc)
-
- for example in TEST_EXAMPLE_LIST:
- dsc = os.path.join(SDK_LIBRARY_DIR, example, 'example.dsc')
- args.append(dsc)
+ # Update test libraries and test apps
+ filters = {
+ 'DEST': ['testlibs', 'tests']
+ }
+ if not build_experimental:
+ filters['EXPERIMENTAL'] = False
- if build_experimental:
- args.append('--experimental')
+ tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, filters=filters)
+ platform = getos.GetPlatform()
+ build_projects.UpdateHelpers(pepperdir, platform, clobber=clobber)
+ build_projects.UpdateProjects(pepperdir, platform, tree, clobber=clobber,
+ toolchains=toolchains)
- if generate_make.main(args):
- buildbot_common.ErrorExit('Failed to build tests.')
def BuildStepBuildTests(pepperdir, platform):
@@ -73,52 +70,21 @@ def BuildStepBuildTests(pepperdir, platform):
deps=False)
-def BuildStepRunPyautoTests(pepperdir, platform, pepper_ver):
- buildbot_common.BuildStep('Test Examples')
- env = copy.copy(os.environ)
- env['PEPPER_VER'] = pepper_ver
- env['NACL_SDK_ROOT'] = pepperdir
-
- pyauto_script = os.path.join(SRC_DIR, 'chrome', 'test',
- 'functional', 'nacl_sdk.py')
- pyauto_script_args = ['nacl_sdk.NaClSDKTest.NaClSDKExamples']
-
- if platform == 'linux' and buildbot_common.IsSDKBuilder():
- # linux buildbots need to run the pyauto tests through xvfb. Running
- # using runtest.py does this.
- #env['PYTHON_PATH'] = '.:' + env.get('PYTHON_PATH', '.')
- build_dir = os.path.dirname(SRC_DIR)
- runtest_py = os.path.join(build_dir, '..', '..', '..', 'scripts', 'slave',
- 'runtest.py')
- buildbot_common.Run([sys.executable, runtest_py, '--target', 'Release',
- '--build-dir', 'src/build', sys.executable,
- pyauto_script] + pyauto_script_args,
- cwd=build_dir, env=env)
- else:
- buildbot_common.Run([sys.executable, 'nacl_sdk.py',
- 'nacl_sdk.NaClSDKTest.NaClSDKExamples'],
- cwd=os.path.dirname(pyauto_script),
- env=env)
-
-
def main(args):
parser = optparse.OptionParser()
parser.add_option('--experimental', help='build experimental tests',
action='store_true')
- parser.add_option('--pyauto', help='Run pyauto tests', action='store_true')
options, args = parser.parse_args(args[1:])
platform = getos.GetPlatform()
- pepper_ver = str(int(build_utils.ChromeMajorVersion()))
+ pepper_ver = str(int(build_version.ChromeMajorVersion()))
pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
toolchains = ['newlib', 'glibc', 'pnacl', 'host']
BuildStepBuildExamples(pepperdir, platform)
BuildStepCopyTests(pepperdir, toolchains, options.experimental, True)
BuildStepBuildTests(pepperdir, platform)
- if options.pyauto:
- BuildStepRunPyautoTests(pepperdir, platform, pepper_ver)
return 0
diff --git a/native_client_sdk/src/build_tools/tests/generate_make_test.py b/native_client_sdk/src/build_tools/tests/parse_dsc_test.py
index cc8dd27278..c74539fa35 100755
--- a/native_client_sdk/src/build_tools/tests/generate_make_test.py
+++ b/native_client_sdk/src/build_tools/tests/parse_dsc_test.py
@@ -16,6 +16,7 @@ BUILD_TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
sys.path.append(BUILD_TOOLS_DIR)
import generate_make
+import parse_dsc
BASIC_DESC = {
'TOOLS': ['newlib', 'glibc'],
@@ -26,7 +27,7 @@ BASIC_DESC = {
'SOURCES' : ['hello_world.c'],
},
],
- 'DEST' : 'examples'
+ 'DEST' : 'examples/api'
}
class TestValidateFormat(unittest.TestCase):
@@ -35,9 +36,9 @@ class TestValidateFormat(unittest.TestCase):
return self.result
def _validate(self, src, msg):
- format = generate_make.DSC_FORMAT
+ format = parse_dsc.DSC_FORMAT
self.result = ''
- result = generate_make.ValidateFormat(src, format,
+ result = parse_dsc.ValidateFormat(src, format,
lambda msg: self._append_result(msg))
if msg:
self.assertEqual(self.result, msg)
diff --git a/native_client_sdk/src/build_tools/tests/sdktools_commands_test.py b/native_client_sdk/src/build_tools/tests/sdktools_commands_test.py
index 15933e1111..d5e984127f 100755
--- a/native_client_sdk/src/build_tools/tests/sdktools_commands_test.py
+++ b/native_client_sdk/src/build_tools/tests/sdktools_commands_test.py
@@ -46,7 +46,7 @@ class TestCommands(SdkToolsTestCase):
try:
dummy_path = os.path.join(temp_dir, filename)
with open(dummy_path, 'w') as stream:
- stream.write('Dummy stuff for %s' % (bundle_name,))
+ stream.write('Dummy stuff for %s' % bundle_name)
# Build the tarfile directly into the server's directory.
tar_path = os.path.join(self.basedir, tarname)
@@ -179,7 +179,7 @@ class TestCommands(SdkToolsTestCase):
"""The update command should install the contents of a bundle to the SDK."""
self._AddDummyBundle(self.manifest, 'pepper_23')
self._WriteManifest()
- output = self._Run(['update', 'pepper_23'])
+ self._Run(['update', 'pepper_23'])
self.assertTrue(os.path.exists(
os.path.join(self.basedir, 'nacl_sdk', 'pepper_23', 'dummy.txt')))
@@ -189,7 +189,7 @@ class TestCommands(SdkToolsTestCase):
self._AddDummyBundle(self.manifest, 'pepper_23')
self._WriteCacheManifest(self.manifest)
self._WriteManifest()
- output = self._Run(['update', 'pepper_23'])
+ self._Run(['update', 'pepper_23'])
self.assertTrue(os.path.exists(
os.path.join(self.basedir, 'nacl_sdk', 'pepper_23', 'dummy.txt')))
@@ -349,6 +349,54 @@ class TestCommands(SdkToolsTestCase):
output = self._Run(['list', '-r'])
self.assertTrue(re.search('I\*\s+pepper_23.*?r1337.*?r1338', output))
+ def testArchiveCacheBasic(self):
+ """Downloaded archives should be stored in the cache by default."""
+ self._AddDummyBundle(self.manifest, 'pepper_23')
+ self._WriteManifest()
+ self._Run(['update', 'pepper_23'])
+ archive_cache = os.path.join(self.cache_dir, 'archives')
+ cache_contents = os.listdir(archive_cache)
+ self.assertEqual(cache_contents, ['pepper_23'])
+ cache_contents = os.listdir(os.path.join(archive_cache, 'pepper_23'))
+ self.assertEqual(cache_contents, ['pepper_23.tar.bz2'])
+
+ def testArchiveCacheEviction(self):
+ archive_cache = os.path.join(self.cache_dir, 'archives')
+ self._AddDummyBundle(self.manifest, 'pepper_23')
+ self._AddDummyBundle(self.manifest, 'pepper_22')
+ self._WriteManifest()
+
+ # First install pepper_23
+ self._Run(['update', 'pepper_23'])
+ archive = os.path.join(archive_cache, 'pepper_23', 'pepper_23.tar.bz2')
+ archive_size = os.path.getsize(archive)
+
+ # Set the mtime on the pepper_23 bundle to be a few seconds in the past.
+ # This is needed so that the two bundles don't end up with the same
+ # timestamp which can happen on systems that don't report sub-second
+ # timestamps.
+ atime = os.path.getatime(archive)
+ mtime = os.path.getmtime(archive)
+ os.utime(archive, (atime, mtime-10))
+
+ # Set cache limit to size of pepper archive * 1.5
+ self._WriteConfig('{ "cache_max": %d }' % int(archive_size * 1.5))
+
+ # Now install pepper_22, which should cause pepper_23 to be evicted
+ self._Run(['update', 'pepper_22'])
+ cache_contents = os.listdir(archive_cache)
+ self.assertEqual(cache_contents, ['pepper_22'])
+
+ def testArchiveCacheZero(self):
+ """Archives should not be cached when cache_max is zero."""
+ self._AddDummyBundle(self.manifest, 'pepper_23')
+ self._WriteConfig('{ "cache_max": 0 }')
+ self._AddDummyBundle(self.manifest, 'pepper_23')
+ self._WriteManifest()
+ self._Run(['update', 'pepper_23'])
+ archive_cache = os.path.join(self.cache_dir, 'archives')
+ # Archive folder should be completely remove by cache cleanup
+ self.assertFalse(os.path.exists(archive_cache))
if __name__ == '__main__':
unittest.main()
diff --git a/native_client_sdk/src/build_tools/tests/sdktools_test.py b/native_client_sdk/src/build_tools/tests/sdktools_test.py
index 078f2121fb..6f5a6eeb69 100755
--- a/native_client_sdk/src/build_tools/tests/sdktools_test.py
+++ b/native_client_sdk/src/build_tools/tests/sdktools_test.py
@@ -40,6 +40,7 @@ class SdkToolsTestCase(unittest.TestCase):
def SetupWithBaseDirPrefix(self, basedir_prefix, tmpdir=None):
self.basedir = tempfile.mkdtemp(prefix=basedir_prefix, dir=tmpdir)
+ self.cache_dir = os.path.join(self.basedir, 'nacl_sdk', 'sdk_cache')
# We have to make sure that we build our updaters with a version that is at
# least as large as the version in the sdk_tools bundle. If not, update
# tests may fail because the "current" version (according to the sdk_cache)
@@ -65,19 +66,22 @@ class SdkToolsTestCase(unittest.TestCase):
This manifest should only contain the sdk_tools bundle.
"""
- manifest_filename = os.path.join(self.basedir, 'nacl_sdk', 'sdk_cache',
- MANIFEST_BASENAME)
+ manifest_filename = os.path.join(self.cache_dir, MANIFEST_BASENAME)
self.manifest = manifest_util.SDKManifest()
self.manifest.LoadDataFromString(open(manifest_filename).read())
self.sdk_tools_bundle = self.manifest.GetBundle('sdk_tools')
+ def _WriteConfig(self, config_data):
+ config_filename = os.path.join(self.cache_dir, 'naclsdk_config.json')
+ with open(config_filename, 'w') as stream:
+ stream.write(config_data)
+
def _WriteCacheManifest(self, manifest):
"""Write the manifest at nacl_sdk/sdk_cache.
This is useful for faking having installed a bundle.
"""
- manifest_filename = os.path.join(self.basedir, 'nacl_sdk', 'sdk_cache',
- MANIFEST_BASENAME)
+ manifest_filename = os.path.join(self.cache_dir, MANIFEST_BASENAME)
with open(manifest_filename, 'w') as stream:
stream.write(manifest.GetDataAsString())
diff --git a/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py b/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
index 9cccfcb807..4763d63f39 100755
--- a/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
+++ b/native_client_sdk/src/build_tools/tests/update_nacl_manifest_test.py
@@ -188,6 +188,7 @@ class TestDelegate(update_nacl_manifest.Delegate):
self.version_mapping = version_mapping
self.dryrun = 0
self.called_gsutil_cp = False
+ self.called_sendmail = False
def GetRepoManifest(self):
return self.manifest
@@ -227,6 +228,9 @@ class TestDelegate(update_nacl_manifest.Delegate):
# eat all informational messages
pass
+ def SendMail(self, subject, text):
+ self.called_sendmail = True
+
# Shorthand for premade bundles/versions
V18_0_1025_163 = '18.0.1025.163'
@@ -237,19 +241,19 @@ V19_0_1084_67 = '19.0.1084.67'
V21_0_1145_0 = '21.0.1145.0'
V21_0_1166_0 = '21.0.1166.0'
V26_0_1386_0 = '26.0.1386.0'
-VTRUNK_138079 = 'trunk.138079'
-B18_0_1025_163_R1_MLW = MakePlatformBundle(18, 1, V18_0_1025_163, OS_MLW)
-B18_0_1025_184_R1_MLW = MakePlatformBundle(18, 1, V18_0_1025_184, OS_MLW)
-B18_R1_NONE = MakePlatformBundle(18)
-B19_0_1084_41_R1_MLW = MakePlatformBundle(19, 1, V19_0_1084_41, OS_MLW)
-B19_0_1084_67_R1_MLW = MakePlatformBundle(19, 1, V19_0_1084_67, OS_MLW)
-B19_R1_NONE = MakePlatformBundle(19)
-BCANARY_R1_NONE = MakePlatformBundle(0, stability=CANARY)
-B21_0_1145_0_R1_MLW = MakePlatformBundle(21, 1, V21_0_1145_0, OS_MLW)
-B21_0_1166_0_R1_MW = MakePlatformBundle(21, 1, V21_0_1166_0, OS_MW)
-B26_R1_NONE = MakePlatformBundle(26)
-B26_0_1386_0_R1_MLW = MakePlatformBundle(26, 1, V26_0_1386_0, OS_MLW)
-BTRUNK_138079_R1_MLW = MakePlatformBundle(21, 1, VTRUNK_138079, OS_MLW)
+VTRUNK_140819 = 'trunk.140819'
+B18_0_1025_163_MLW = MakePlatformBundle(18, 132135, V18_0_1025_163, OS_MLW)
+B18_0_1025_184_MLW = MakePlatformBundle(18, 134900, V18_0_1025_184, OS_MLW)
+B18_NONE = MakePlatformBundle(18)
+B19_0_1084_41_MLW = MakePlatformBundle(19, 134854, V19_0_1084_41, OS_MLW)
+B19_0_1084_67_MLW = MakePlatformBundle(19, 142000, V19_0_1084_67, OS_MLW)
+B19_NONE = MakePlatformBundle(19)
+BCANARY_NONE = MakePlatformBundle(0, stability=CANARY)
+B21_0_1145_0_MLW = MakePlatformBundle(21, 138079, V21_0_1145_0, OS_MLW)
+B21_0_1166_0_MW = MakePlatformBundle(21, 140819, V21_0_1166_0, OS_MW)
+B26_NONE = MakePlatformBundle(26)
+B26_0_1386_0_MLW = MakePlatformBundle(26, 177362, V26_0_1386_0, OS_MLW)
+BTRUNK_140819_MLW = MakePlatformBundle(21, 140819, VTRUNK_140819, OS_MLW)
NON_PEPPER_BUNDLE_NOARCHIVES = MakeNonPepperBundle('foo')
NON_PEPPER_BUNDLE_ARCHIVES = MakeNonPepperBundle('bar', with_archives=True)
@@ -303,104 +307,104 @@ class TestUpdateManifest(unittest.TestCase):
for platform, channel, version, date in csv.reader(history_stream)]
def testNoUpdateNeeded(self):
- self.manifest = MakeManifest(B18_0_1025_163_R1_MLW)
+ self.manifest = MakeManifest(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self.assertFalse(self._HasUploadedManifest())
# Add another bundle, make sure it still doesn't update
- self.manifest.AddBundle(B19_0_1084_41_R1_MLW)
+ self.manifest.AddBundle(B19_0_1084_41_MLW)
self._Run(OS_MLW)
self.assertFalse(self._HasUploadedManifest())
def testSimpleUpdate(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testOnePlatformHasNewerRelease(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_M, BETA, V18_0_1025_175) # Mac has newer version
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testMultipleMissingPlatformsInHistory(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_ML, BETA, V18_0_1025_184)
self.history.Add(OS_M, BETA, V18_0_1025_175)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testUpdateOnlyOneBundle(self):
- self.manifest = MakeManifest(B18_R1_NONE, B19_0_1084_41_R1_MLW)
+ self.manifest = MakeManifest(B18_NONE, B19_0_1084_41_MLW)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
- self._AssertUploadedManifestHasBundle(B19_0_1084_41_R1_MLW, DEV)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
def testUpdateTwoBundles(self):
- self.manifest = MakeManifest(B18_R1_NONE, B19_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE, B19_NONE)
self.history.Add(OS_MLW, DEV, V19_0_1084_41)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
- self.files.Add(B19_0_1084_41_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
+ self.files.Add(B19_0_1084_41_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
- self._AssertUploadedManifestHasBundle(B19_0_1084_41_R1_MLW, DEV)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B19_0_1084_41_MLW, DEV)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 2)
def testUpdateWithMissingPlatformsInArchives(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_184)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_184_R1_MLW, add_archive_for_os=OS_M)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_184_MLW, add_archive_for_os=OS_M)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testUpdateWithMissingManifestSnippets(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_184)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_184_R1_MLW, add_json_for_os=OS_ML)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_184_MLW, add_json_for_os=OS_ML)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testRecommendedIsStable(self):
for channel in STABLE, BETA, DEV, CANARY:
self.setUp()
- bundle = copy.deepcopy(B18_R1_NONE)
+ bundle = copy.deepcopy(B18_NONE)
self.manifest = MakeManifest(bundle)
self.history.Add(OS_MLW, channel, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
@@ -413,29 +417,29 @@ class TestUpdateManifest(unittest.TestCase):
def testNoUpdateWithNonPepperBundle(self):
self.manifest = MakeManifest(NON_PEPPER_BUNDLE_NOARCHIVES,
- B18_0_1025_163_R1_MLW)
+ B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self.assertFalse(self._HasUploadedManifest())
def testUpdateWithHistoryWithExtraneousPlatforms(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_ML, BETA, V18_0_1025_184)
self.history.Add(OS_CR, BETA, V18_0_1025_184)
self.history.Add(OS_CR, BETA, V18_0_1025_175)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_163_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_163_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testSnippetWithStringRevisionAndVersion(self):
# This test exists because some manifest snippets were uploaded with
# strings for their revisions and versions. I want to make sure the
# resulting manifest is still consistent with the old format.
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
bundle_string_revision = MakePlatformBundle('18', '1234', V18_0_1025_163,
OS_MLW)
@@ -452,32 +456,32 @@ class TestUpdateManifest(unittest.TestCase):
# Note that the bundle in naclsdk_manifest2.json will be called
# CANARY_BUNDLE_NAME, whereas the bundle in the manifest "snippet" will be
# called "pepper_21".
- canary_bundle = copy.deepcopy(BCANARY_R1_NONE)
+ canary_bundle = copy.deepcopy(BCANARY_NONE)
self.manifest = MakeManifest(canary_bundle)
self.history.Add(OS_MW, CANARY, V21_0_1145_0)
- self.files.Add(B21_0_1145_0_R1_MLW)
+ self.files.Add(B21_0_1145_0_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B21_0_1145_0_R1_MLW, CANARY)
+ self._AssertUploadedManifestHasBundle(B21_0_1145_0_MLW, CANARY)
def testUpdateCanaryUseTrunkArchives(self):
- canary_bundle = copy.deepcopy(BCANARY_R1_NONE)
+ canary_bundle = copy.deepcopy(BCANARY_NONE)
self.manifest = MakeManifest(canary_bundle)
self.history.Add(OS_MW, CANARY, V21_0_1166_0)
- self.files.Add(B21_0_1166_0_R1_MW)
- self.files.Add(BTRUNK_138079_R1_MLW)
- self.version_mapping[V21_0_1166_0] = VTRUNK_138079
+ self.files.Add(B21_0_1166_0_MW)
+ self.files.Add(BTRUNK_140819_MLW)
+ self.version_mapping[V21_0_1166_0] = VTRUNK_140819
self._MakeDelegate()
self._Run(OS_MLW)
self._ReadUploadedManifest()
- test_bundle = copy.deepcopy(B21_0_1166_0_R1_MW)
- test_bundle.AddArchive(BTRUNK_138079_R1_MLW.GetArchive('linux'))
+ test_bundle = copy.deepcopy(B21_0_1166_0_MW)
+ test_bundle.AddArchive(BTRUNK_140819_MLW.GetArchive('linux'))
self._AssertUploadedManifestHasBundle(test_bundle, CANARY)
def testCanaryUseOnlyTrunkArchives(self):
- self.manifest = MakeManifest(copy.deepcopy(BCANARY_R1_NONE))
+ self.manifest = MakeManifest(copy.deepcopy(BCANARY_NONE))
history = """win,canary,21.0.1163.0,2012-06-04 12:35:44.784446
mac,canary,21.0.1163.0,2012-06-04 11:54:09.433166"""
self._AddCsvHistory(history)
@@ -490,12 +494,12 @@ mac,canary,21.0.1163.0,2012-06-04 11:54:09.433166"""
self._AssertUploadedManifestHasBundle(my_bundle, CANARY)
def testCanaryShouldOnlyUseCanaryVersions(self):
- canary_bundle = copy.deepcopy(BCANARY_R1_NONE)
+ canary_bundle = copy.deepcopy(BCANARY_NONE)
self.manifest = MakeManifest(canary_bundle)
self.history.Add(OS_MW, CANARY, V21_0_1166_0)
self.history.Add(OS_MW, BETA, V19_0_1084_41)
- self.files.Add(B19_0_1084_41_R1_MLW)
- self.version_mapping[V21_0_1166_0] = VTRUNK_138079
+ self.files.Add(B19_0_1084_41_MLW)
+ self.version_mapping[V21_0_1166_0] = VTRUNK_140819
self._MakeDelegate()
self.assertRaises(Exception, self._Run, OS_MLW)
@@ -516,7 +520,7 @@ win,canary,21.0.1156.1,2012-05-30 22:28:01.872056
mac,canary,21.0.1156.1,2012-05-30 21:20:29.920390
win,canary,21.0.1156.0,2012-05-30 12:46:48.046627
mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
- self.manifest = MakeManifest(copy.deepcopy(BCANARY_R1_NONE))
+ self.manifest = MakeManifest(copy.deepcopy(BCANARY_NONE))
self._AddCsvHistory(history)
self.version_mapping = {
'21.0.1160.0': 'trunk.139984',
@@ -536,9 +540,9 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
def testExtensionWorksAsBz2(self):
# Allow old bundles with just .bz2 extension to work
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- bundle = copy.deepcopy(B18_0_1025_163_R1_MLW)
+ bundle = copy.deepcopy(B18_0_1025_163_MLW)
archive_url = bundle.GetArchive('mac').url
bundle.GetArchive('mac').url = archive_url.replace('.tar', '')
self.files.Add(bundle)
@@ -549,29 +553,33 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testOnlyOneStableBundle(self):
- self.manifest = MakeManifest(B18_R1_NONE, B19_R1_NONE)
- self.history.Add(OS_MLW, STABLE, V18_0_1025_163)
- self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
- self.files.Add(B18_0_1025_163_R1_MLW)
- self.files.Add(B19_0_1084_41_R1_MLW)
- self._MakeDelegate()
- self._Run(OS_MLW)
- self._ReadUploadedManifest()
- p18_bundle = self.uploaded_manifest.GetBundle(B18_R1_NONE.name)
- self.assertEqual(p18_bundle.stability, POST_STABLE)
- self.assertEqual(p18_bundle.recommended, 'no')
- p19_bundle = self.uploaded_manifest.GetBundle(B19_R1_NONE.name)
- self.assertEqual(p19_bundle.stability, STABLE)
- self.assertEqual(p19_bundle.recommended, 'yes')
+ # Make sure that any bundle that has an older version than STABLE is marked
+ # as POST_STABLE, even if the last version we found was BETA, DEV, etc.
+ for channel in STABLE, BETA, DEV, CANARY:
+ self.setUp()
+ self.manifest = MakeManifest(B18_NONE, B19_NONE)
+ self.history.Add(OS_MLW, channel, V18_0_1025_163)
+ self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
+ self.files.Add(B18_0_1025_163_MLW)
+ self.files.Add(B19_0_1084_41_MLW)
+ self._MakeDelegate()
+ self._Run(OS_MLW)
+ self._ReadUploadedManifest()
+ p18_bundle = self.uploaded_manifest.GetBundle(B18_NONE.name)
+ self.assertEqual(p18_bundle.stability, POST_STABLE)
+ self.assertEqual(p18_bundle.recommended, 'no')
+ p19_bundle = self.uploaded_manifest.GetBundle(B19_NONE.name)
+ self.assertEqual(p19_bundle.stability, STABLE)
+ self.assertEqual(p19_bundle.recommended, 'yes')
def testDontPushIfNoChange(self):
# Make an online manifest that already has this bundle.
- online_manifest = MakeManifest(B18_0_1025_163_R1_MLW)
+ online_manifest = MakeManifest(B18_0_1025_163_MLW)
self.files.AddOnlineManifest(online_manifest.GetDataAsString())
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, DEV, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
@@ -579,33 +587,33 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
def testDontPushIfRollback(self):
# Make an online manifest that has a newer bundle
- online_manifest = MakeManifest(B18_0_1025_184_R1_MLW)
+ online_manifest = MakeManifest(B18_0_1025_184_MLW)
self.files.AddOnlineManifest(online_manifest.GetDataAsString())
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, DEV, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
self.assertFalse(self.delegate.called_gsutil_cp)
def testRunWithFixedBundleVersions(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
- self.files.Add(B18_0_1025_184_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
+ self.files.Add(B18_0_1025_184_MLW)
self._MakeDelegate()
self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
self._ReadUploadedManifest()
- self._AssertUploadedManifestHasBundle(B18_0_1025_184_R1_MLW, BETA)
+ self._AssertUploadedManifestHasBundle(B18_0_1025_184_MLW, BETA)
self.assertEqual(len(self.uploaded_manifest.GetBundles()), 1)
def testRunWithMissingFixedBundleVersions(self):
- self.manifest = MakeManifest(B18_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE)
self.history.Add(OS_MLW, BETA, V18_0_1025_163)
- self.files.Add(B18_0_1025_163_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
self._MakeDelegate()
self._Run(OS_MLW, None, [('pepper_18', '18.0.1025.184')])
@@ -613,9 +621,9 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
self.assertFalse(self.delegate.called_gsutil_cp)
def testDontIncludeRandomBundles(self):
- self.manifest = MakeManifest(B26_R1_NONE)
+ self.manifest = MakeManifest(B26_NONE)
self.history.Add(OS_MLW, BETA, V26_0_1386_0)
- self.files.Add(B26_0_1386_0_R1_MLW)
+ self.files.Add(B26_0_1386_0_MLW)
some_other_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
some_other_archive = MakeNonPlatformArchive('some_other.tar.bz2',
@@ -630,9 +638,9 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
self.assertEqual(1, len(uploaded_bundle.GetHostOSArchives()))
def testNaclportsBundle(self):
- self.manifest = MakeManifest(B26_R1_NONE)
+ self.manifest = MakeManifest(B26_NONE)
self.history.Add(OS_MLW, BETA, V26_0_1386_0)
- self.files.Add(B26_0_1386_0_R1_MLW)
+ self.files.Add(B26_0_1386_0_MLW)
# NaclPorts "bundle".
naclports_bundle = MakePepperBundle(26, 1, V26_0_1386_0, BETA)
@@ -653,14 +661,14 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
# newer than the online bundle), it was added to the end of the list.
# Make an online manifest that already has B18.
- online_manifest = MakeManifest(B18_0_1025_163_R1_MLW)
+ online_manifest = MakeManifest(B18_0_1025_163_MLW)
self.files.AddOnlineManifest(online_manifest.GetDataAsString())
- self.manifest = MakeManifest(B18_R1_NONE, B19_R1_NONE)
+ self.manifest = MakeManifest(B18_NONE, B19_NONE)
self.history.Add(OS_MLW, STABLE, V18_0_1025_163)
self.history.Add(OS_MLW, STABLE, V19_0_1084_41)
- self.files.Add(B18_0_1025_163_R1_MLW)
- self.files.Add(B19_0_1084_41_R1_MLW)
+ self.files.Add(B18_0_1025_163_MLW)
+ self.files.Add(B19_0_1084_41_MLW)
self._MakeDelegate()
self._Run(OS_MLW)
@@ -672,6 +680,30 @@ mac,canary,21.0.1156.0,2012-05-30 12:14:21.305090"""
self.assertEqual('pepper_18', bundles[0].name)
self.assertEqual('pepper_19', bundles[1].name)
+ def testBundleWithoutHistoryUsesOnline(self):
+ online_manifest = MakeManifest(B18_0_1025_163_MLW)
+ self.files.AddOnlineManifest(online_manifest.GetDataAsString())
+
+ self.manifest = MakeManifest(B18_NONE)
+
+ self._MakeDelegate()
+ # This should not raise.
+ self._Run(OS_MLW)
+ self._ReadUploadedManifest()
+
+ # But it should have sent an email nagging the users to lock this bundle
+ # manually.
+ self.assertTrue(self.delegate.called_sendmail)
+
+ uploaded_bundle = self.uploaded_manifest.GetBundle('pepper_18')
+ self.assertEqual(uploaded_bundle, B18_0_1025_163_MLW)
+
+ def testBundleWithoutHistoryOrOnlineRaises(self):
+ self.manifest = MakeManifest(B18_NONE)
+ self._MakeDelegate()
+ self.assertRaises(update_nacl_manifest.UnknownLockedBundleException,
+ self._Run, OS_MLW)
+
class TestUpdateVitals(unittest.TestCase):
def setUp(self):
diff --git a/native_client_sdk/src/build_tools/update_nacl_manifest.py b/native_client_sdk/src/build_tools/update_nacl_manifest.py
index ecc683a16e..c4d0acd008 100755
--- a/native_client_sdk/src/build_tools/update_nacl_manifest.py
+++ b/native_client_sdk/src/build_tools/update_nacl_manifest.py
@@ -176,12 +176,24 @@ class Delegate(object):
"""Print a message."""
raise NotImplementedError()
+ def SendMail(self, subject, text):
+ """Send an email.
+
+ Args:
+ subject: The subject of the email.
+ text: The text of the email.
+ """
+ raise NotImplementedError()
+
class RealDelegate(Delegate):
- def __init__(self, dryrun=False, gsutil=None, verbose=False):
+ def __init__(self, dryrun=False, gsutil=None, verbose=False,
+ mailfrom=None, mailto=None):
super(RealDelegate, self).__init__()
self.dryrun = dryrun
self.verbose = verbose
+ self.mailfrom = mailfrom
+ self.mailto = mailto
if gsutil:
self.gsutil = gsutil
else:
@@ -237,6 +249,19 @@ class RealDelegate(Delegate):
if self.verbose:
self.Print(*args)
+ def SendMail(self, subject, text):
+ """See Delegate.SendMail"""
+ if self.mailfrom and self.mailto:
+ msg = email.MIMEMultipart.MIMEMultipart()
+ msg['From'] = self.mailfrom
+ msg['To'] = ', '.join(self.mailto)
+ msg['Date'] = email.Utils.formatdate(localtime=True)
+ msg['Subject'] = subject
+ msg.attach(email.MIMEText.MIMEText(text))
+ smtp_obj = smtplib.SMTP('localhost')
+ smtp_obj.sendmail(self.mailfrom, self.mailto, msg.as_string())
+ smtp_obj.close()
+
def _RunGsUtil(self, stdin, *args):
"""Run gsutil as a subprocess.
@@ -266,6 +291,10 @@ class RealDelegate(Delegate):
return stdout
+class NoSharedVersionException(Exception):
+ pass
+
+
class VersionFinder(object):
"""Finds a version of a pepper bundle that all desired platforms share.
@@ -398,7 +427,7 @@ class VersionFinder(object):
for version, channel, missing_archives in skipped_versions:
archive_msg = '(missing %s)' % (', '.join(missing_archives))
msg += ' %s (%s) %s\n' % (version, channel, archive_msg)
- raise Exception(msg)
+ raise NoSharedVersionException(msg)
archives, missing_archives = self.GetAvailablePlatformArchivesFor(
version, allow_trunk_revisions)
@@ -507,10 +536,15 @@ class VersionFinder(object):
return filter(lambda a: a + '.json' in manifests, archives)
+class UnknownLockedBundleException(Exception):
+ pass
+
+
class Updater(object):
def __init__(self, delegate):
self.delegate = delegate
self.versions_to_update = []
+ self.locked_bundles = []
self.online_manifest = manifest_util.SDKManifest()
self._FetchOnlineManifest()
@@ -524,6 +558,18 @@ class Updater(object):
archives: A sequence of archive URLs for this bundle."""
self.versions_to_update.append((bundle_name, version, channel, archives))
+ def AddLockedBundle(self, bundle_name):
+ """Add a "locked" bundle to the updater.
+
+ A locked bundle is a bundle that wasn't found in the history. When this
+ happens, the bundle is now "locked" to whatever was last found. We want to
+ ensure that the online manifest has this bundle.
+
+ Args:
+ bundle_name: The name of the locked bundle.
+ """
+ self.locked_bundles.append(bundle_name)
+
def Update(self, manifest):
"""Update a manifest and upload it.
@@ -541,6 +587,28 @@ class Updater(object):
# Add 0 in case there are no stable versions.
max_stable_version = max([0] + stable_major_versions)
+ # Ensure that all locked bundles exist in the online manifest.
+ for bundle_name in self.locked_bundles:
+ online_bundle = self.online_manifest.GetBundle(bundle_name)
+ if online_bundle:
+ manifest.SetBundle(online_bundle)
+ else:
+ msg = ('Attempted to update bundle "%s", but no shared versions were '
+ 'found, and there is no online bundle with that name.')
+ raise UnknownLockedBundleException(msg % bundle_name)
+
+ if self.locked_bundles:
+ # Send a nagging email that we shouldn't be wasting time looking for
+ # bundles that are no longer in the history.
+ scriptname = os.path.basename(sys.argv[0])
+ subject = '[%s] Reminder: remove bundles from %s' % (scriptname,
+ MANIFEST_BASENAME)
+ text = 'These bundles are not in the omahaproxy history anymore: ' + \
+ ', '.join(self.locked_bundles)
+ self.delegate.SendMail(subject, text)
+
+
+ # Update all versions.
for bundle_name, version, channel, archives in self.versions_to_update:
self.delegate.Print('Updating %s to %s...' % (bundle_name, version))
bundle = manifest.GetBundle(bundle_name)
@@ -552,18 +620,9 @@ class Updater(object):
platform_bundle.name = bundle_name
bundle.MergeWithBundle(platform_bundle)
- # Check to ensure this bundle is newer than the online bundle.
- online_bundle = self.online_manifest.GetBundle(bundle_name)
- if online_bundle and online_bundle.revision >= bundle.revision:
- self.delegate.Print(
- ' Revision %s is not newer than than online revision %s. '
- 'Skipping.' % (bundle.revision, online_bundle.revision))
-
- manifest.SetBundle(online_bundle)
- continue
-
+ # Fix the stability and recommended values
major_version = SplitVersion(version)[0]
- if major_version < max_stable_version and channel == 'stable':
+ if major_version < max_stable_version:
bundle.stability = 'post_stable'
else:
bundle.stability = channel
@@ -572,6 +631,21 @@ class Updater(object):
bundle.recommended = 'yes'
else:
bundle.recommended = 'no'
+
+ # Check to ensure this bundle is newer than the online bundle.
+ online_bundle = self.online_manifest.GetBundle(bundle_name)
+ if online_bundle:
+ # This test used to be online_bundle.revision >= bundle.revision.
+ # That doesn't do quite what we want: sometimes the metadata changes
+ # but the revision stays the same -- we still want to push those
+ # changes.
+ if online_bundle.revision > bundle.revision or online_bundle == bundle:
+ self.delegate.Print(
+ ' Revision %s is not newer than than online revision %s. '
+ 'Skipping.' % (bundle.revision, online_bundle.revision))
+
+ manifest.SetBundle(online_bundle)
+ continue
self._UploadManifest(manifest)
self.delegate.Print('Done.')
@@ -680,11 +754,17 @@ def Run(delegate, platforms, extra_archives, fixed_bundle_versions=None):
updater = Updater(delegate)
for bundle in auto_update_bundles:
- if bundle.name == CANARY_BUNDLE_NAME:
- version, channel, archives = version_finder.GetMostRecentSharedCanary()
- else:
- version, channel, archives = version_finder.GetMostRecentSharedVersion(
- bundle.version)
+ try:
+ if bundle.name == CANARY_BUNDLE_NAME:
+ version, channel, archives = version_finder.GetMostRecentSharedCanary()
+ else:
+ version, channel, archives = version_finder.GetMostRecentSharedVersion(
+ bundle.version)
+ except NoSharedVersionException:
+ # If we can't find a shared version, make sure that there is an uploaded
+ # bundle with that name already.
+ updater.AddLockedBundle(bundle.name)
+ continue
if bundle.name in fixed_bundle_versions:
# Ensure this version is valid for all platforms.
@@ -706,27 +786,6 @@ def Run(delegate, platforms, extra_archives, fixed_bundle_versions=None):
updater.Update(manifest)
-def SendMail(send_from, send_to, subject, text, smtp='localhost'):
- """Send an email.
-
- Args:
- send_from: The sender's email address.
- send_to: A list of addresses to send to.
- subject: The subject of the email.
- text: The text of the email.
- smtp: The smtp server to use. Default is localhost.
- """
- msg = email.MIMEMultipart.MIMEMultipart()
- msg['From'] = send_from
- msg['To'] = ', '.join(send_to)
- msg['Date'] = email.Utils.formatdate(localtime=True)
- msg['Subject'] = subject
- msg.attach(email.MIMEText.MIMEText(text))
- smtp_obj = smtplib.SMTP(smtp)
- smtp_obj.sendmail(send_from, send_to, msg.as_string())
- smtp_obj.close()
-
-
class CapturedFile(object):
"""A file-like object that captures text written to it, but also passes it
through to an underlying file-like object."""
@@ -778,11 +837,14 @@ def main(args):
try:
try:
- delegate = RealDelegate(options.dryrun, options.gsutil, options.verbose)
- # Only look for naclports archives > 26.0.1391.0 = r178222
- extra_archives = [('naclports.tar.bz2', '26.0.1391.0')]
+ delegate = RealDelegate(options.dryrun, options.gsutil, options.verbose,
+ options.mailfrom, options.mailto)
+ # Only look for naclports archives >= 27. The old ports bundles don't
+ # include license information.
+ extra_archives = [('naclports.tar.bz2', '27.0.0.0')]
Run(delegate, ('mac', 'win', 'linux'), extra_archives,
fixed_bundle_versions)
+ return 0
except Exception:
if options.mailfrom and options.mailto:
traceback.print_exc()
@@ -790,15 +852,15 @@ def main(args):
subject = '[%s] Failed to update manifest' % (scriptname,)
text = '%s failed.\n\nSTDERR:\n%s\n' % (scriptname,
sys.stderr.getvalue())
- SendMail(options.mailfrom, options.mailto, subject, text)
- sys.exit(1)
+ delegate.SendMail(subject, text)
+ return 1
else:
raise
except manifest_util.Error as e:
if options.debug:
raise
print e
- sys.exit(1)
+ return 1
if __name__ == '__main__':
diff --git a/native_client_sdk/src/examples/Makefile b/native_client_sdk/src/examples/Makefile
index 9eb356dd8a..0218488948 100644
--- a/native_client_sdk/src/examples/Makefile
+++ b/native_client_sdk/src/examples/Makefile
@@ -12,6 +12,8 @@ PROJECTS:= \
{{project}} \
[[]]
+HTTPD:={{rel_sdk}}/tools/httpd.py
+
# Define the default target
all:
@@ -54,4 +56,4 @@ clean: $(CLEAN_LIST)
.PHONY: RUN
RUN: all
@echo Starting up python webserver.
- python ../tools/httpd.py
+ python $(HTTPD)
diff --git a/native_client_sdk/src/examples/api/audio/example.dsc b/native_client_sdk/src/examples/api/audio/example.dsc
new file mode 100644
index 0000000000..e401dc7ea4
--- /dev/null
+++ b/native_client_sdk/src/examples/api/audio/example.dsc
@@ -0,0 +1,19 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'sine_synth',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['sine_synth.cc'],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'audio',
+ 'TITLE': 'Audio',
+ 'GROUP': 'API',
+}
+
diff --git a/native_client_sdk/src/examples/sine_synth/example.js b/native_client_sdk/src/examples/api/audio/example.js
index 6a7398ad39..6a7398ad39 100644
--- a/native_client_sdk/src/examples/sine_synth/example.js
+++ b/native_client_sdk/src/examples/api/audio/example.js
diff --git a/native_client_sdk/src/examples/sine_synth/index.html b/native_client_sdk/src/examples/api/audio/index.html
index f2f66a37ba..70e8ed21b6 100644
--- a/native_client_sdk/src/examples/sine_synth/index.html
+++ b/native_client_sdk/src/examples/api/audio/index.html
@@ -15,8 +15,10 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The Sine Wave Synthesizer example demonstrates playing sound (a sine
+ wave). Enter the desired frequency and hit play to start, stop to end.</p>
- <p>Click the button to start and stop the sine wave playing.</p>
+ <p>Click the buttons to start and stop the sine wave playing.</p>
<button id="playButton">Play</button>
<button id="stopButton">Stop</button>
diff --git a/native_client_sdk/src/examples/sine_synth/sine_synth.cc b/native_client_sdk/src/examples/api/audio/sine_synth.cc
index 99bdf7f7d2..3e31930266 100644
--- a/native_client_sdk/src/examples/sine_synth/sine_synth.cc
+++ b/native_client_sdk/src/examples/api/audio/sine_synth.cc
@@ -113,16 +113,13 @@ bool SineSynthInstance::Init(uint32_t argc,
const char* argn[],
const char* argv[]) {
// Ask the device for an appropriate sample count size.
- sample_frame_count_ =
- pp::AudioConfig::RecommendSampleFrameCount(this,
- PP_AUDIOSAMPLERATE_44100,
- kSampleFrameCount);
- audio_ = pp::Audio(this,
- pp::AudioConfig(this,
- PP_AUDIOSAMPLERATE_44100,
- sample_frame_count_),
- SineWaveCallback,
- this);
+ sample_frame_count_ = pp::AudioConfig::RecommendSampleFrameCount(
+ this, PP_AUDIOSAMPLERATE_44100, kSampleFrameCount);
+ audio_ = pp::Audio(
+ this,
+ pp::AudioConfig(this, PP_AUDIOSAMPLERATE_44100, sample_frame_count_),
+ SineWaveCallback,
+ this);
return true;
}
@@ -178,7 +175,5 @@ class SineSynthModule : public pp::Module {
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
-Module* CreateModule() {
- return new sine_synth::SineSynthModule();
-}
+Module* CreateModule() { return new sine_synth::SineSynthModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/api/core/core.cc b/native_client_sdk/src/examples/api/core/core.cc
new file mode 100644
index 0000000000..59489697f9
--- /dev/null
+++ b/native_client_sdk/src/examples/api/core/core.cc
@@ -0,0 +1,67 @@
+// 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 <string>
+
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+/// The Instance class. One of these exists for each instance of your NaCl
+/// module on the web page. The browser will ask the Module object to create
+/// a new Instance for each occurrence of the <embed> tag that has these
+/// attributes:
+/// type="application/x-nacl"
+/// src="file_histogram.nmf"
+class CoreInstance : public pp::Instance {
+ public:
+ /// The constructor creates the plugin-side instance.
+ /// @param[in] instance the handle to the browser-side plugin instance.
+ explicit CoreInstance(PP_Instance instance)
+ : pp::Instance(instance), callback_factory_(this) {}
+
+ private:
+ /// Handler for messages coming in from the browser via postMessage(). The
+ /// @a var_message will contain the requested delay time.
+ ///
+ /// @param[in] var_message The message posted by the browser.
+ virtual void HandleMessage(const pp::Var& var_message) {
+ int32_t delay = var_message.AsInt();
+ if (delay) {
+ // If a delay is requested, issue a callback after delay ms.
+ last_receive_time_ = pp::Module::Get()->core()->GetTimeTicks();
+ pp::Module::Get()->core()->CallOnMainThread(
+ delay, callback_factory_.NewCallback(&CoreInstance::DelayedPost), 0);
+ } else {
+ // If no delay is requested, reply immediately with zero time elapsed.
+ pp::Var msg(0);
+ PostMessage(msg);
+ }
+ }
+
+ void DelayedPost(int32_t) {
+ // Send the time elapsed until the callbacked fired.
+ pp::Var msg(pp::Module::Get()->core()->GetTimeTicks() - last_receive_time_);
+ PostMessage(msg);
+ }
+
+ private:
+ pp::CompletionCallbackFactory<CoreInstance> callback_factory_;
+ PP_TimeTicks last_receive_time_;
+};
+
+class CoreModule : public pp::Module {
+ public:
+ CoreModule() : pp::Module() {}
+ virtual ~CoreModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new CoreInstance(instance);
+ }
+};
+
+namespace pp {
+Module* CreateModule() { return new CoreModule(); }
+} // namespace pp
diff --git a/native_client_sdk/src/examples/api/core/example.dsc b/native_client_sdk/src/examples/api/core/example.dsc
new file mode 100644
index 0000000000..885ad10dfe
--- /dev/null
+++ b/native_client_sdk/src/examples/api/core/example.dsc
@@ -0,0 +1,19 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'core',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['core.cc'],
+ 'LIBS' : ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'core',
+ 'TITLE': 'Core',
+ 'GROUP': 'API'
+}
+
diff --git a/native_client_sdk/src/examples/api/core/example.js b/native_client_sdk/src/examples/api/core/example.js
new file mode 100644
index 0000000000..99875eb6e8
--- /dev/null
+++ b/native_client_sdk/src/examples/api/core/example.js
@@ -0,0 +1,68 @@
+// 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 itrMax = 1000;
+var itrCount = 0;
+var itrSend = new Float64Array(itrMax);
+var itrNaCl = new Float64Array(itrMax);
+var itrRecv = new Float64Array(itrMax);
+var delay = 0;
+
+function attachListeners() {
+ document.getElementById('start').addEventListener('click',
+ startTest);
+ count_pp = document.getElementById('count')
+ count_pp.textContent = itrMax;
+}
+
+function startTest() {
+ if (common.naclModule) {
+ var startButton = document.getElementById('start');
+ startButton.disabled = true;
+
+ var delayControl = document.getElementById('delay');
+ delay = parseInt(delayControl.value, 10);
+
+ common.updateStatus('Running Test');
+ itrCount = 0;
+ itrSend[0] = (new Date()).getTime();
+ common.naclModule.postMessage(delay);
+ }
+}
+
+function setStats(nacl, compute, total) {
+ var statNaCl = document.getElementById('NaCl');
+ var statRound = document.getElementById('Round');
+ var statAll = document.getElementById('Total');
+
+ statNaCl.textContent = (nacl / itrMax) + ' ms';
+ statRound.textContent = (compute / itrMax) + ' ms';
+ statAll.textContent = (total / itrMax) + ' ms';
+}
+
+// Called by the common.js module.
+function handleMessage(message_event) {
+ // Convert NaCl Seconds elapsed to MS
+ itrNaCl[itrCount] = message_event.data * 1000.0;
+ itrRecv[itrCount] = (new Date()).getTime();
+ itrCount++;
+
+ if (itrCount == itrMax) {
+ common.updateStatus('Test Finished');
+ var startButton = document.getElementById('start');
+ startButton.disabled = false;
+
+ var naclMS = 0.0;
+ var computeMS = 0.0;
+ for (var i=0; i < itrMax; i++) {
+ naclMS += itrNaCl[i];
+ computeMS += itrRecv[i] - itrSend[i];
+ }
+
+ setStats(naclMS, computeMS, itrRecv[itrMax - 1] - itrSend[0]);
+ } else {
+ itrSend[itrCount] = (new Date()).getTime();
+ common.naclModule.postMessage(delay);
+ }
+}
diff --git a/native_client_sdk/src/examples/api/core/index.html b/native_client_sdk/src/examples/api/core/index.html
new file mode 100644
index 0000000000..a3fa8650c5
--- /dev/null
+++ b/native_client_sdk/src/examples/api/core/index.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+<head>
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Expires" content="-1">
+ <title>{{title}}</title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type ="text/javascript" src="example.js"></script>
+</head>
+<body {{attrs}}>
+ <h1>{{title}}</h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The Core API example demonstrates the basic use of the Time and Callback
+ functions.</p>
+ <p> Push 'Start Test' to run <span id="count">0</span> iterations. Each
+ iteration will send a message to the NaCl module containing the number of
+ milliseconds to delay. The modules will immediately post a message back
+ if the delay is zero, otherwise, it will issue a CallOnMainThread with
+ the delay specified.</p>
+ <p> Once the test completes, it will calculate the average time spent
+ between the message reception and the callback triggering (NaCl Delay),
+ the average time for a single round trip (Round Trip), and the
+ average iteration including other JS overhead (Total). </p>
+ <div>
+ NaCl Delay
+ <input type="number" id="delay" value="0" min="0" max="20"
+ style="text-align:right"> ms
+ <input type="button" id="start" value="Start Test">
+ <table style="border:1px solid black">
+ <tr>
+ <th>NaCl Delay</th><th>Round Trip</th><th>Total</th>
+ </tr>
+ <tr>
+ <td id="NaCl">Unknown</td>
+ <td id="Round">Unknown</td>
+ <td id="Total">Unknown</td>
+ </tr>
+ </table>
+ </div>
+ <div id="listener"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/file_io/example.dsc b/native_client_sdk/src/examples/api/file_io/example.dsc
index b9bf3e6a27..ac5e916375 100644
--- a/native_client_sdk/src/examples/file_io/example.dsc
+++ b/native_client_sdk/src/examples/api/file_io/example.dsc
@@ -11,13 +11,9 @@
'DATA': [
'example.js',
],
- 'DEST': 'examples',
+ 'DEST': 'examples/api',
'NAME': 'file_io',
'TITLE': 'File I/O',
- 'DESC': """
-The File IO example demonstrates saving, loading, and deleting files
-from the persistent file store.""",
- 'FOCUS': 'File input and output.',
'GROUP': 'API'
}
diff --git a/native_client_sdk/src/examples/file_io/example.js b/native_client_sdk/src/examples/api/file_io/example.js
index e73f4b9462..e73f4b9462 100644
--- a/native_client_sdk/src/examples/file_io/example.js
+++ b/native_client_sdk/src/examples/api/file_io/example.js
diff --git a/native_client_sdk/src/examples/file_io/file_io.cc b/native_client_sdk/src/examples/api/file_io/file_io.cc
index ebd15ef4b0..9de72f8f6a 100644
--- a/native_client_sdk/src/examples/file_io/file_io.cc
+++ b/native_client_sdk/src/examples/api/file_io/file_io.cc
@@ -43,7 +43,7 @@ const char* const kDeletePrefix = "de";
/// The Instance class. One of these exists for each instance of your NaCl
/// module on the web page. The browser will ask the Module object to create
-/// a new Instance for each occurence of the <embed> tag that has these
+/// a new Instance for each occurrence of the <embed> tag that has these
/// attributes:
/// type="application/x-nacl"
/// src="file_io.nmf"
@@ -56,15 +56,13 @@ class FileIoInstance : public pp::Instance {
callback_factory_(this),
file_system_(this, PP_FILESYSTEMTYPE_LOCALPERSISTENT),
file_system_ready_(false),
- file_thread_(this) {
- }
+ file_thread_(this) {}
- virtual ~FileIoInstance() {
- file_thread_.Join();
- }
+ virtual ~FileIoInstance() { file_thread_.Join(); }
- virtual bool Init(uint32_t /*argc*/, const char* /*argn*/[],
- const char* /*argv*/[]) {
+ virtual bool Init(uint32_t /*argc*/,
+ const char * /*argn*/ [],
+ const char * /*argv*/ []) {
file_thread_.Start();
// Open the file system on the file_thread_. Since this is the first
// operation we perform there, and because we do everything on the
@@ -125,10 +123,8 @@ class FileIoInstance : public pp::Instance {
// Read the rest of the message as the file text
reader.ignore(1); // Eat the delimiter
std::string file_text = message.substr(reader.tellg());
- file_thread_.message_loop().PostWork(
- callback_factory_.NewCallback(&FileIoInstance::Save,
- file_name,
- file_text));
+ file_thread_.message_loop().PostWork(callback_factory_.NewCallback(
+ &FileIoInstance::Save, file_name, file_text));
return;
}
@@ -140,7 +136,7 @@ class FileIoInstance : public pp::Instance {
}
void OpenFileSystem(int32_t /* result */) {
- int32_t rv = file_system_.Open(1024*1024, pp::CompletionCallback());
+ int32_t rv = file_system_.Open(1024 * 1024, pp::CompletionCallback());
if (rv == PP_OK) {
file_system_ready_ = true;
// Notify the user interface that we're ready
@@ -150,7 +146,8 @@ class FileIoInstance : public pp::Instance {
}
}
- void Save(int32_t /* result */, const std::string& file_name,
+ void Save(int32_t /* result */,
+ const std::string& file_name,
const std::string& file_contents) {
if (!file_system_ready_) {
ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
@@ -159,10 +156,11 @@ class FileIoInstance : public pp::Instance {
pp::FileRef ref(file_system_, file_name.c_str());
pp::FileIO file(this);
- int32_t open_result = file.Open(
- ref,
- PP_FILEOPENFLAG_WRITE|PP_FILEOPENFLAG_CREATE|PP_FILEOPENFLAG_TRUNCATE,
- pp::CompletionCallback());
+ int32_t open_result =
+ file.Open(ref,
+ PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
+ PP_FILEOPENFLAG_TRUNCATE,
+ pp::CompletionCallback());
if (open_result != PP_OK) {
ShowErrorMessage("File open for write failed", open_result);
return;
@@ -207,8 +205,8 @@ class FileIoInstance : public pp::Instance {
pp::FileRef ref(file_system_, file_name.c_str());
pp::FileIO file(this);
- int32_t open_result = file.Open(ref, PP_FILEOPENFLAG_READ,
- pp::CompletionCallback());
+ int32_t open_result =
+ file.Open(ref, PP_FILEOPENFLAG_READ, pp::CompletionCallback());
if (open_result == PP_ERROR_FILENOTFOUND) {
ShowStatusMessage("File not found");
return;
@@ -232,7 +230,9 @@ class FileIoInstance : public pp::Instance {
int64_t offset = 0;
int32_t bytes_read = 0;
do {
- bytes_read = file.Read(offset, &data[offset], data.size() - offset,
+ bytes_read = file.Read(offset,
+ &data[offset],
+ data.size() - offset,
pp::CompletionCallback());
if (bytes_read > 0)
offset += bytes_read;
@@ -304,8 +304,5 @@ namespace pp {
/// CreateInstance() method on the object you return to make instances. There
/// is one instance per <embed> tag on the page. This is the main binding
/// point for your NaCl module with the browser.
-Module* CreateModule() {
- return new FileIoModule();
-}
+Module* CreateModule() { return new FileIoModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/file_io/index.html b/native_client_sdk/src/examples/api/file_io/index.html
index 64767b2f48..7625bd69c0 100644
--- a/native_client_sdk/src/examples/file_io/index.html
+++ b/native_client_sdk/src/examples/api/file_io/index.html
@@ -15,6 +15,8 @@
<body data-width="200" data-height="200" data-custom-load="true" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The File IO example demonstrates saving, loading, and deleting files
+ from the persistent file store.</p>
<textarea id="fileEditor"
cols="40"
@@ -22,7 +24,7 @@
wrap="hard"
placeholder="Enter some text to save in a file..."></textarea>
<br>File Name
- <input type="text" id="fileName" action="">
+ <input type="text" id="fileName" action="" value="/filename.txt">
<button id="saveButton" action="">Save</button>
<button id="loadButton" action="">Load</button>
<button id="deleteButton" action="">Delete</button>
diff --git a/native_client_sdk/src/examples/gamepad/example.dsc b/native_client_sdk/src/examples/api/gamepad/example.dsc
index 2d6102e473..65a61bc36f 100644
--- a/native_client_sdk/src/examples/gamepad/example.dsc
+++ b/native_client_sdk/src/examples/api/gamepad/example.dsc
@@ -8,14 +8,9 @@
'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
}
],
- 'DEST': 'examples',
+ 'DEST': 'examples/api',
'NAME': 'gamepad',
- 'TITLE': 'Gamepad Example.',
- 'DESC': """
-Attached gamepad values should appear, left to right, once they've been
-interacted with. Buttons, esp triggers are analog.
-""",
- 'FOCUS': 'Gamepad interface.',
+ 'TITLE': 'Gamepad',
'GROUP': 'API'
}
diff --git a/native_client_sdk/src/examples/gamepad/gamepad.cc b/native_client_sdk/src/examples/api/gamepad/gamepad.cc
index 9730e1724d..8e8b588fda 100644
--- a/native_client_sdk/src/examples/gamepad/gamepad.cc
+++ b/native_client_sdk/src/examples/api/gamepad/gamepad.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Native Client Authors. All rights reserved.
+// 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.
@@ -67,7 +67,11 @@ void Gamepad::DidChangeView(const pp::View& view) {
Paint();
}
-void FillRect(pp::ImageData* image, int left, int top, int width, int height,
+void FillRect(pp::ImageData* image,
+ int left,
+ int top,
+ int width,
+ int height,
uint32_t color) {
for (int y = std::max(0, top);
y < std::min(image->size().height() - 1, top + height);
diff --git a/native_client_sdk/src/examples/gamepad/gamepad.h b/native_client_sdk/src/examples/api/gamepad/gamepad.h
index dcb92de0f0..67649e0e48 100644
--- a/native_client_sdk/src/examples/gamepad/gamepad.h
+++ b/native_client_sdk/src/examples/api/gamepad/gamepad.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 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.
@@ -34,9 +34,7 @@ class Gamepad : public pp::Instance {
// Flushes its contents of |pixel_buffer_| to the 2D graphics context.
void Paint();
- bool quit() const {
- return quit_;
- }
+ bool quit() const { return quit_; }
int width() const {
return pixel_buffer_ ? pixel_buffer_->size().width() : 0;
@@ -47,12 +45,8 @@ class Gamepad : public pp::Instance {
// Indicate whether a flush is pending. This can only be called from the
// main thread; it is not thread safe.
- bool flush_pending() const {
- return flush_pending_;
- }
- void set_flush_pending(bool flag) {
- flush_pending_ = flag;
- }
+ bool flush_pending() const { return flush_pending_; }
+ void set_flush_pending(bool flag) { flush_pending_ = flag; }
private:
// Create and initialize the 2D context used for drawing.
@@ -64,9 +58,7 @@ class Gamepad : public pp::Instance {
// and do not flush.
void FlushPixelBuffer();
- bool IsContextValid() const {
- return graphics_2d_context_ != NULL;
- }
+ bool IsContextValid() const { return graphics_2d_context_ != NULL; }
pp::Graphics2D* graphics_2d_context_;
pp::ImageData* pixel_buffer_;
diff --git a/native_client_sdk/src/examples/gamepad/gamepad_module.cc b/native_client_sdk/src/examples/api/gamepad/gamepad_module.cc
index cac2570283..f24968cf19 100644
--- a/native_client_sdk/src/examples/gamepad/gamepad_module.cc
+++ b/native_client_sdk/src/examples/api/gamepad/gamepad_module.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Native Client Authors. All rights reserved.
+// 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.
@@ -28,7 +28,5 @@ class GamepadModule : public pp::Module {
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
-Module* CreateModule() {
- return new gamepad::GamepadModule();
-}
+Module* CreateModule() { return new gamepad::GamepadModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/gamepad/index.html b/native_client_sdk/src/examples/api/gamepad/index.html
index 108319b448..8b580db8e6 100644
--- a/native_client_sdk/src/examples/gamepad/index.html
+++ b/native_client_sdk/src/examples/api/gamepad/index.html
@@ -14,10 +14,10 @@ found in the LICENSE file.
<body data-width="800" data-height="200" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <!-- The NaCl plugin will be embedded inside the element with id "listener".
- See common.js.-->
<p> Attached gamepad values should appear, left to right, once they've been
interacted with. Buttons, esp triggers are analog. </p>
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
<div id="listener"></div>
</body>
</html>
diff --git a/native_client_sdk/src/examples/hello_world_gles/example.dsc b/native_client_sdk/src/examples/api/graphics_3d/example.dsc
index 5178253cf4..ea8377f99c 100644
--- a/native_client_sdk/src/examples/hello_world_gles/example.dsc
+++ b/native_client_sdk/src/examples/api/graphics_3d/example.dsc
@@ -17,14 +17,9 @@
'hello.raw',
'vertex_shader_es2.vert'
],
- 'DEST': 'examples',
- 'NAME': 'hello_world_gles',
- 'TITLE': 'Hello World GLES 2.0',
- 'DESC': """
-The Hello World GLES 2.0 example demonstrates how to create a 3D cube
-that rotates. This is a simpler example than the tumbler example, and
-written in C. It loads the assets using URLLoader.""",
- 'FOCUS': '3D graphics, URL Loader.',
+ 'DEST': 'examples/api',
+ 'NAME': 'graphics_3d',
+ 'TITLE': 'Graphics 3D',
'GROUP': 'API'
}
diff --git a/native_client_sdk/src/examples/hello_world_gles/fragment_shader_es2.frag b/native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag
index 247c559f8c..247c559f8c 100644
--- a/native_client_sdk/src/examples/hello_world_gles/fragment_shader_es2.frag
+++ b/native_client_sdk/src/examples/api/graphics_3d/fragment_shader_es2.frag
diff --git a/native_client_sdk/src/examples/hello_world_gles/hello.raw b/native_client_sdk/src/examples/api/graphics_3d/hello.raw
index 3320575072..3320575072 100644
--- a/native_client_sdk/src/examples/hello_world_gles/hello.raw
+++ b/native_client_sdk/src/examples/api/graphics_3d/hello.raw
Binary files differ
diff --git a/native_client_sdk/src/examples/hello_world_gles/hello_world.cc b/native_client_sdk/src/examples/api/graphics_3d/hello_world.cc
index c29c165d06..9ba19411e4 100644
--- a/native_client_sdk/src/examples/hello_world_gles/hello_world.cc
+++ b/native_client_sdk/src/examples/api/graphics_3d/hello_world.cc
@@ -57,12 +57,12 @@ static PPB_URLLoader* ppb_urlloader_interface = NULL;
static PP_Instance g_instance;
static PP_Resource g_context;
-GLuint g_positionLoc;
-GLuint g_texCoordLoc;
-GLuint g_colorLoc;
-GLuint g_MVPLoc;
-GLuint g_vboID;
-GLuint g_ibID;
+GLuint g_positionLoc;
+GLuint g_texCoordLoc;
+GLuint g_colorLoc;
+GLuint g_MVPLoc;
+GLuint g_vboID;
+GLuint g_ibID;
GLubyte g_Indices[36];
GLuint g_programObj;
@@ -78,24 +78,23 @@ float g_fSpinY = 0.0f;
//-----------------------------------------------------------------------------
// Rendering Assets
//-----------------------------------------------------------------------------
-struct Vertex
-{
+struct Vertex {
float tu, tv;
float color[3];
float loc[3];
};
-Vertex *g_quadVertices = NULL;
-const char *g_TextureData = NULL;
-const char *g_VShaderData = NULL;
-const char *g_FShaderData = NULL;
+Vertex* g_quadVertices = NULL;
+const char* g_TextureData = NULL;
+const char* g_VShaderData = NULL;
+const char* g_FShaderData = NULL;
int g_LoadCnt = 0;
//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
-void PostMessage(const char *fmt, ...);
-char* LoadFile(const char *fileName);
+void PostMessage(const char* fmt, ...);
+char* LoadFile(const char* fileName);
void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]);
Vertex* BuildCube(void);
@@ -104,7 +103,6 @@ void InitGL(void);
void InitProgram(void);
void Render(void);
-
static struct PP_Var CStrToVar(const char* str) {
if (ppb_var_interface != NULL) {
return ppb_var_interface->VarFromUtf8(str, strlen(str));
@@ -112,8 +110,7 @@ static struct PP_Var CStrToVar(const char* str) {
return PP_MakeUndefined();
}
-
-void PostMessage(const char *fmt, ...) {
+void PostMessage(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -141,8 +138,7 @@ void MainLoop(void* foo, int bar) {
}
}
-void InitGL(void)
-{
+void InitGL(void) {
int32_t attribs[] = {
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
@@ -154,34 +150,30 @@ void InitGL(void)
PP_GRAPHICS3DATTRIB_NONE
};
- g_context = ppb_g3d_interface->Create(g_instance, 0, attribs);
+ g_context = ppb_g3d_interface->Create(g_instance, 0, attribs);
int32_t success = ppb_instance_interface->BindGraphics(g_instance, g_context);
- if (success == PP_FALSE)
- {
+ if (success == PP_FALSE) {
glSetCurrentContextPPAPI(0);
printf("Failed to set context.\n");
return;
}
glSetCurrentContextPPAPI(g_context);
- glViewport(0,0, 640,480);
- glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glViewport(0, 0, 640, 480);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
-
-GLuint compileShader(GLenum type, const char *data) {
- const char *shaderStrings[1];
+GLuint compileShader(GLenum type, const char* data) {
+ const char* shaderStrings[1];
shaderStrings[0] = data;
GLuint shader = glCreateShader(type);
- glShaderSource(shader, 1, shaderStrings, NULL );
+ glShaderSource(shader, 1, shaderStrings, NULL);
glCompileShader(shader);
return shader;
}
-
-void InitProgram( void )
-{
+void InitProgram(void) {
glSetCurrentContextPPAPI(g_context);
g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData);
@@ -194,12 +186,16 @@ void InitProgram( void )
glGenBuffers(1, &g_vboID);
glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(Vertex), (void*)&g_quadVertices[0],
+ glBufferData(GL_ARRAY_BUFFER,
+ 24 * sizeof(Vertex),
+ (void*)&g_quadVertices[0],
GL_STATIC_DRAW);
glGenBuffers(1, &g_ibID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(char), (void*)&g_Indices[0],
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ 36 * sizeof(char),
+ (void*)&g_Indices[0],
GL_STATIC_DRAW);
//
@@ -207,9 +203,16 @@ void InitProgram( void )
//
glGenTextures(1, &g_textureID);
glBindTexture(GL_TEXTURE_2D, g_textureID);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE,
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ 128,
+ 128,
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
g_TextureData);
//
@@ -222,7 +225,6 @@ void InitProgram( void )
g_MVPLoc = glGetUniformLocation(g_programObj, "a_MVP");
}
-
void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f };
static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f };
@@ -233,14 +235,13 @@ void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
verts[i].loc[axis[0]] = X[i] * depth;
verts[i].loc[axis[1]] = Y[i] * depth;
verts[i].loc[axis[2]] = depth;
- for (int j = 0; j < 3; j++)
+ for (int j = 0; j < 3; j++)
verts[i].color[j] = color[j] * (Y[i] + 1.0f) / 2.0f;
}
}
-
-Vertex *BuildCube() {
- Vertex *verts = new Vertex[24];
+Vertex* BuildCube() {
+ Vertex* verts = new Vertex[24];
for (int i = 0; i < 3; i++) {
int Faxis[3];
int Baxis[3];
@@ -258,38 +259,38 @@ Vertex *BuildCube() {
BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
}
- for(int i = 0; i < 6; i++) {
- g_Indices[i*6 + 0] = 2 + i * 4;
- g_Indices[i*6 + 1] = 1 + i * 4;
- g_Indices[i*6 + 2] = 0 + i * 4;
- g_Indices[i*6 + 3] = 3 + i * 4;
- g_Indices[i*6 + 4] = 2 + i * 4;
- g_Indices[i*6 + 5] = 0 + i * 4;
+ for (int i = 0; i < 6; i++) {
+ g_Indices[i * 6 + 0] = 2 + i * 4;
+ g_Indices[i * 6 + 1] = 1 + i * 4;
+ g_Indices[i * 6 + 2] = 0 + i * 4;
+ g_Indices[i * 6 + 3] = 3 + i * 4;
+ g_Indices[i * 6 + 4] = 2 + i * 4;
+ g_Indices[i * 6 + 5] = 0 + i * 4;
}
return verts;
}
-
-void Render( void )
-{
+void Render(void) {
static float xRot = 0.0;
static float yRot = 0.0;
xRot += 2.0f;
yRot += 0.5f;
- if (xRot >= 360.0f) xRot = 0.0;
- if (yRot >= 360.0f) yRot = 0.0;
+ if (xRot >= 360.0f)
+ xRot = 0.0;
+ if (yRot >= 360.0f)
+ yRot = 0.0;
- glClearColor(0.5,0.5,0.5,1);
+ glClearColor(0.5, 0.5, 0.5, 1);
glClearDepthf(1.0);
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//set what program to use
- glUseProgram( g_programObj );
- glActiveTexture ( GL_TEXTURE0 );
- glBindTexture ( GL_TEXTURE_2D,g_textureID );
- glUniform1i ( g_textureLoc, 0 );
+ glUseProgram(g_programObj);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, g_textureID);
+ glUniform1i(g_textureLoc, 0);
//create our perspective matrix
float mpv[16];
@@ -297,32 +298,43 @@ void Render( void )
float rot[16];
identity_matrix(mpv);
- glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f,1, 10);
+ glhPerspectivef2(&mpv[0], 45.0f, 640.0f / 480.0f, 1, 10);
translate_matrix(0, 0, -4.0, trs);
- rotate_matrix(xRot, yRot , 0.0f ,rot);
+ rotate_matrix(xRot, yRot, 0.0f, rot);
multiply_matrix(trs, rot, trs);
multiply_matrix(mpv, trs, mpv);
- glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*) mpv);
+ glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv);
//define the attributes of the vertex
glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glVertexAttribPointer(g_positionLoc, 3, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,loc));
+ glVertexAttribPointer(g_positionLoc,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, loc));
glEnableVertexAttribArray(g_positionLoc);
- glVertexAttribPointer(g_texCoordLoc, 2, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,tu));
+ glVertexAttribPointer(g_texCoordLoc,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, tu));
glEnableVertexAttribArray(g_texCoordLoc);
- glVertexAttribPointer(g_colorLoc, 3, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,color));
+ glVertexAttribPointer(g_colorLoc,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, color));
glEnableVertexAttribArray(g_colorLoc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glDrawElements ( GL_TRIANGLES, 36, GL_UNSIGNED_BYTE ,0 );
+ glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
}
-
-typedef void (*OpenCB)(void *dataPtr);
+typedef void (*OpenCB)(void* dataPtr);
struct OpenRequest {
PP_Resource loader_;
PP_Resource request_;
@@ -333,7 +345,6 @@ struct OpenRequest {
OpenCB cb_;
};
-
void FreeRequest(OpenRequest* req) {
if (req) {
ppb_core_interface->ReleaseResource(req->request_);
@@ -342,9 +353,8 @@ void FreeRequest(OpenRequest* req) {
}
}
-
static void URLPartialRead(void* user_data, int mode) {
- OpenRequest* req = (OpenRequest *) user_data;
+ OpenRequest* req = (OpenRequest*)user_data;
int64_t total;
int32_t cnt;
@@ -361,8 +371,10 @@ static void URLPartialRead(void* user_data, int mode) {
cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
// If we still have more to do, re-issue the read.
if (cnt > 0) {
- int32_t bytes = ppb_urlloader_interface->ReadResponseBody(req->loader_,
- (void *) &req->buf_[req->avail_], cnt,
+ int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
+ req->loader_,
+ (void*)&req->buf_[req->avail_],
+ cnt,
PP_MakeCompletionCallback(URLPartialRead, req));
// If the reissue completes immediately, then process it.
@@ -370,17 +382,16 @@ static void URLPartialRead(void* user_data, int mode) {
URLPartialRead(user_data, bytes);
}
return;
- }
-
+ }
+
// Nothing left, so signal complete.
req->cb_(req);
FreeRequest(req);
printf("Loaded\n");
}
-
static void URLOpened(void* user_data, int mode) {
- OpenRequest* req = (OpenRequest *) user_data;
+ OpenRequest* req = (OpenRequest*)user_data;
int64_t cur, total;
int32_t cnt;
@@ -395,23 +406,27 @@ static void URLOpened(void* user_data, int mode) {
}
// Otherwise allocate a buffer with enough space for a terminating
- // NUL in case we need one.
+ // NULL in case we need one.
cnt = (total > LONG_MAX) ? LONG_MAX : (int32_t) total;
- req->buf_ = (char *) malloc(cnt + 1);
+ req->buf_ = (char*)malloc(cnt + 1);
req->buf_[cnt] = 0;
req->size_ = cnt;
- int32_t bytes = ppb_urlloader_interface->ReadResponseBody(req->loader_,
- req->buf_, cnt, PP_MakeCompletionCallback(URLPartialRead, req));
+ int32_t bytes = ppb_urlloader_interface->ReadResponseBody(
+ req->loader_,
+ req->buf_,
+ cnt,
+ PP_MakeCompletionCallback(URLPartialRead, req));
// Usually we are pending.
- if (bytes == PP_OK_COMPLETIONPENDING) return;
+ if (bytes == PP_OK_COMPLETIONPENDING)
+ return;
// But if we did complete the read, then dispatch the handler.
URLPartialRead(req, bytes);
}
-void LoadURL(PP_Instance inst, const char *url, OpenCB cb, void *data) {
- OpenRequest* req = (OpenRequest*) malloc(sizeof(OpenRequest));
+void LoadURL(PP_Instance inst, const char* url, OpenCB cb, void* data) {
+ OpenRequest* req = (OpenRequest*)malloc(sizeof(OpenRequest));
memset(req, 0, sizeof(OpenRequest));
req->loader_ = ppb_urlloader_interface->Create(inst);
@@ -425,15 +440,17 @@ void LoadURL(PP_Instance inst, const char *url, OpenCB cb, void *data) {
return;
}
- ppb_urlrequestinfo_interface->SetProperty(req->request_,
- PP_URLREQUESTPROPERTY_URL, CStrToVar(url));
- ppb_urlrequestinfo_interface->SetProperty(req->request_,
- PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET"));
- ppb_urlrequestinfo_interface->SetProperty(req->request_,
- PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, PP_MakeBool(PP_TRUE));
+ ppb_urlrequestinfo_interface->SetProperty(
+ req->request_, PP_URLREQUESTPROPERTY_URL, CStrToVar(url));
+ ppb_urlrequestinfo_interface->SetProperty(
+ req->request_, PP_URLREQUESTPROPERTY_METHOD, CStrToVar("GET"));
+ ppb_urlrequestinfo_interface->SetProperty(
+ req->request_,
+ PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS,
+ PP_MakeBool(PP_TRUE));
- int val = ppb_urlloader_interface->Open(req->loader_, req->request_,
- PP_MakeCompletionCallback(URLOpened, req));
+ int val = ppb_urlloader_interface->Open(
+ req->loader_, req->request_, PP_MakeCompletionCallback(URLOpened, req));
if (val != PP_OK_COMPLETIONPENDING) {
cb(NULL);
@@ -442,9 +459,9 @@ void LoadURL(PP_Instance inst, const char *url, OpenCB cb, void *data) {
}
void Loaded(void* data) {
- OpenRequest *req = (OpenRequest *) data;
+ OpenRequest* req = (OpenRequest*)data;
if (req && req->buf_) {
- char **pptr = (char **) req->data_;
+ char** pptr = (char**)req->data_;
*pptr = req->buf_;
g_LoadCnt++;
return;
@@ -452,7 +469,6 @@ void Loaded(void* data) {
PostMessage("Failed to load asset.\n");
}
-
/**
* 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
@@ -487,7 +503,6 @@ 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
@@ -539,9 +554,7 @@ static void Instance_DidChangeView(PP_Instance instance,
* @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) {
-}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
/**
* Handler that gets called after a full-frame module is instantiated based on
@@ -559,7 +572,6 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
return PP_FALSE;
}
-
/**
* Entry points for the module.
* Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
@@ -584,7 +596,6 @@ 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.
@@ -605,9 +616,7 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
return NULL;
}
-
/**
* Called before the plugin module is unloaded.
*/
-PP_EXPORT void PPP_ShutdownModule() {
-}
+PP_EXPORT void PPP_ShutdownModule() {}
diff --git a/native_client_sdk/src/examples/hello_world_gles/index.html b/native_client_sdk/src/examples/api/graphics_3d/index.html
index b07ff78cda..665ce4e0c7 100644
--- a/native_client_sdk/src/examples/hello_world_gles/index.html
+++ b/native_client_sdk/src/examples/api/graphics_3d/index.html
@@ -14,6 +14,8 @@ found in the LICENSE file.
<body data-width="640" data-height="480" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The Hello World GLES 2.0 example demonstrates how to create a 3D cube
+ that rotates. It loads the assets using URLLoader.</p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/api/graphics_3d/matrix.cc b/native_client_sdk/src/examples/api/graphics_3d/matrix.cc
new file mode 100644
index 0000000000..b87d496cb1
--- /dev/null
+++ b/native_client_sdk/src/examples/api/graphics_3d/matrix.cc
@@ -0,0 +1,140 @@
+/* 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.
+ */
+
+/** @file matrix.cc
+ * Implements simple matrix manipulation functions.
+ */
+
+//-----------------------------------------------------------------------------
+#include <stdlib.h>
+#include <string.h>
+#include "matrix.h"
+#define deg_to_rad(x) (x * (M_PI / 180.0f))
+
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar) {
+ float temp, temp2, temp3, temp4;
+ temp = 2.0f * znear;
+ temp2 = right - left;
+ temp3 = top - bottom;
+ temp4 = zfar - znear;
+ mat[0] = temp / temp2;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = 0.0f;
+ mat[5] = temp / temp3;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = (right + left) / temp2;
+ mat[9] = (top + bottom) / temp3;
+ mat[10] = (-zfar - znear) / temp4;
+ mat[11] = -1.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (-temp * zfar) / temp4;
+ mat[15] = 0.0f;
+}
+
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar) {
+ float ymax, xmax;
+ ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
+ xmax = ymax * aspectRatio;
+ glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
+}
+
+void identity_matrix(Matrix_t mat) {
+ memset(mat, 0, sizeof(Matrix_t));
+ mat[0] = 1.0;
+ mat[5] = 1.0;
+ mat[10] = 1.0;
+ mat[15] = 1.0;
+}
+
+void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
+ // Generate to a temporary first in case the output matrix and input
+ // matrix are the same.
+ Matrix_t out;
+
+ out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
+ out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
+ out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
+ out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
+
+ out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
+ out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
+ out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
+ out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
+
+ out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
+ out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
+ out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
+ out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
+
+ out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
+ out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
+ out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
+ out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
+
+ memcpy(mat, out, sizeof(Matrix_t));
+}
+
+void rotate_x_matrix(GLfloat x_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[5] = cosf(x_rad);
+ mat[6] = -sinf(x_rad);
+ mat[9] = -mat[6];
+ mat[10] = mat[5];
+}
+
+void rotate_y_matrix(GLfloat y_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(y_rad);
+ mat[2] = sinf(y_rad);
+ mat[8] = -mat[2];
+ mat[10] = mat[0];
+}
+
+void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[0] = cosf(z_rad);
+ mat[1] = sinf(z_rad);
+ mat[4] = -mat[1];
+ mat[5] = mat[0];
+}
+
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat) {
+ GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
+ GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
+ GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
+
+ Matrix_t x_matrix;
+ Matrix_t y_matrix;
+ Matrix_t z_matrix;
+
+ rotate_x_matrix(x_rad, x_matrix);
+ rotate_y_matrix(y_rad, y_matrix);
+ rotate_z_matrix(z_rad, z_matrix);
+
+ Matrix_t xy_matrix;
+ multiply_matrix(y_matrix, x_matrix, xy_matrix);
+ multiply_matrix(z_matrix, xy_matrix, mat);
+}
+
+void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
+ identity_matrix(mat);
+ mat[12] += x;
+ mat[13] += y;
+ mat[14] += z;
+}
diff --git a/native_client_sdk/src/examples/hello_world_gles/matrix.h b/native_client_sdk/src/examples/api/graphics_3d/matrix.h
index 7db7985244..ed094eda09 100644
--- a/native_client_sdk/src/examples/hello_world_gles/matrix.h
+++ b/native_client_sdk/src/examples/api/graphics_3d/matrix.h
@@ -21,12 +21,19 @@ typedef GLfloat Matrix_t[16];
/// Since GLES2 doesn't have all the nifty matrix transform functions that GL
/// has, we emulate some of them here for the sake of sanity from:
/// http://www.opengl.org/wiki/GluPerspective_code
-void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
- GLfloat top, GLfloat znear, GLfloat zfar);
-
-void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
- GLfloat aspectRatio, GLfloat znear, GLfloat zfar);
-
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar);
+
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar);
void identity_matrix(Matrix_t mat);
void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat);
@@ -34,4 +41,3 @@ void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat);
void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat);
#endif // EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
-
diff --git a/native_client_sdk/src/examples/hello_world_gles/vertex_shader_es2.vert b/native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert
index da616cb92a..da616cb92a 100644
--- a/native_client_sdk/src/examples/hello_world_gles/vertex_shader_es2.vert
+++ b/native_client_sdk/src/examples/api/graphics_3d/vertex_shader_es2.vert
diff --git a/native_client_sdk/src/examples/input_events/custom_events.cc b/native_client_sdk/src/examples/api/input_event/custom_events.cc
index 9e22808d5c..9f2e6f4586 100644
--- a/native_client_sdk/src/examples/input_events/custom_events.cc
+++ b/native_client_sdk/src/examples/api/input_event/custom_events.cc
@@ -50,41 +50,32 @@ std::string ModifierToString(uint32_t modifier) {
return s;
}
-
std::string KeyEvent::ToString() const {
std::ostringstream stream;
- stream << " Key event:"
+ stream << "Key event:"
<< " modifier:" << string_event_modifiers()
- << " key_code:" << key_code_
- << " time:" << timestamp_
- << " text:" << text_
- << "\n";
+ << " key_code:" << key_code_ << " time:" << timestamp_
+ << " text:" << text_ << "\n";
return stream.str();
}
std::string MouseEvent::ToString() const {
std::ostringstream stream;
- stream << " Mouse event:"
+ stream << "Mouse event:"
<< " modifier:" << string_event_modifiers()
<< " button:" << MouseButtonToString(mouse_button_)
- << " x:" << x_position_
- << " y:" << y_position_
- << " click_count:" << click_count_
- << " time:" << timestamp_
- << "\n";
+ << " x:" << x_position_ << " y:" << y_position_
+ << " click_count:" << click_count_ << " time:" << timestamp_ << "\n";
return stream.str();
}
std::string WheelEvent::ToString() const {
std::ostringstream stream;
- stream << "Wheel event."
- << " modifier:" << string_event_modifiers()
- << " deltax:" << delta_x_
- << " deltay:" << delta_y_
- << " wheel_ticks_x:" << ticks_x_
+ stream << "Wheel event:"
+ << " modifier:" << string_event_modifiers() << " deltax:" << delta_x_
+ << " deltay:" << delta_y_ << " wheel_ticks_x:" << ticks_x_
<< " wheel_ticks_y:" << ticks_y_
- << " scroll_by_page: " << scroll_by_page_
- << " time:" << timestamp_
+ << " scroll_by_page: " << scroll_by_page_ << " time:" << timestamp_
<< "\n";
return stream.str();
}
@@ -101,9 +92,7 @@ std::string MouseEvent::MouseButtonToString(MouseButton button) const {
return "Right";
default:
std::ostringstream stream;
- stream << "Unrecognized ("
- << static_cast<int32_t>(button)
- << ")";
+ stream << "Unrecognized (" << static_cast<int32_t>(button) << ")";
return stream.str();
}
}
@@ -122,15 +111,18 @@ std::string TouchEvent::KindToString(Kind kind) const {
return "Cancel";
default:
std::ostringstream stream;
- stream << "Unrecognized ("
- << static_cast<int32_t>(kind)
- << ")";
+ stream << "Unrecognized (" << static_cast<int32_t>(kind) << ")";
return stream.str();
}
}
-void TouchEvent::AddTouch(uint32_t id, float x, float y, float radii_x,
- float radii_y, float angle, float pressure) {
+void TouchEvent::AddTouch(uint32_t id,
+ float x,
+ float y,
+ float radii_x,
+ float radii_y,
+ float angle,
+ float pressure) {
Touch touch;
touch.id = id;
touch.x = x;
@@ -144,20 +136,19 @@ void TouchEvent::AddTouch(uint32_t id, float x, float y, float radii_x,
std::string TouchEvent::ToString() const {
std::ostringstream stream;
- stream << " Touch event:" << KindToString(kind_)
+ stream << "Touch event:" << KindToString(kind_)
<< " modifier:" << string_event_modifiers();
for (size_t i = 0; i < touches.size(); ++i) {
const Touch& touch = touches[i];
- stream << " x[" << touch.id << "]:" << touch.x
- << " y[" << touch.id << "]:" << touch.y
- << " radii_x[" << touch.id << "]:" << touch.radii_x
- << " radii_y[" << touch.id << "]:" << touch.radii_y
- << " angle[" << touch.id << "]:" << touch.angle
- << " pressure[" << touch.id << "]:" << touch.pressure;
+ stream << " x[" << touch.id << "]:" << touch.x << " y[" << touch.id
+ << "]:" << touch.y << " radii_x[" << touch.id
+ << "]:" << touch.radii_x << " radii_y[" << touch.id
+ << "]:" << touch.radii_y << " angle[" << touch.id
+ << "]:" << touch.angle << " pressure[" << touch.id
+ << "]:" << touch.pressure;
}
stream << " time:" << timestamp_ << "\n";
return stream.str();
}
} // end namespace
-
diff --git a/native_client_sdk/src/examples/input_events/custom_events.h b/native_client_sdk/src/examples/api/input_event/custom_events.h
index 2f7b10cd1b..fec2561a5c 100644
--- a/native_client_sdk/src/examples/input_events/custom_events.h
+++ b/native_client_sdk/src/examples/api/input_event/custom_events.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-
namespace event_queue {
// These functions and classes are used to define a non-Pepper set of
@@ -43,9 +42,8 @@ class Event {
// |modifiers| is an int that uses bit fields to set specific
// changes, such as the Alt key, specific button, etc. See
// ModifierToString() and constants defined in custom_events.cc.
- explicit Event(uint32_t modifiers)
- : event_modifiers_(modifiers) {}
- uint32_t event_modifiers() const {return event_modifiers_;}
+ explicit Event(uint32_t modifiers) : event_modifiers_(modifiers) {}
+ uint32_t event_modifiers() const { return event_modifiers_; }
std::string string_event_modifiers() const {
return ModifierToString(event_modifiers_);
}
@@ -53,8 +51,8 @@ class Event {
virtual std::string ToString() const = 0;
virtual ~Event() {}
- private:
- uint32_t event_modifiers_;
+ private:
+ uint32_t event_modifiers_;
};
// Class for a keyboard event.
@@ -63,34 +61,44 @@ class KeyEvent : public Event {
// KeyEvent Constructor. |modifiers| is passed to Event base class.
// |keycode| is the ASCII value, |time| is a timestamp,
// |text| is the value as a string.
- KeyEvent(uint32_t modifiers, uint32_t keycode, double time,
- std::string text) :
- Event(modifiers), key_code_(keycode),
- timestamp_(time), text_(text) {}
+ KeyEvent(uint32_t modifiers, uint32_t keycode, double time, std::string text)
+ : Event(modifiers), key_code_(keycode), timestamp_(time), text_(text) {}
// Convert the WheelEvent to a string
virtual std::string ToString() const;
private:
- uint32_t key_code_;
- double timestamp_;
- std::string text_;
+ uint32_t key_code_;
+ double timestamp_;
+ std::string text_;
};
class MouseEvent : public Event {
public:
// Specify a mouse button, with kNone available for initialization.
- enum MouseButton {kNone, kLeft, kMiddle, kRight};
+ enum MouseButton {
+ kNone,
+ kLeft,
+ kMiddle,
+ kRight
+ };
// MouseEvent Constructor. |modifiers| is passed to Event base class.
// |button| specifies which button
// |xpos| and |ypos| give the location,
// |clicks| is how many times this same |xpos|,|ypos|
// has been clicked in a row. |time| is a timestamp,
- MouseEvent(uint32_t modifiers, MouseButton button, uint32_t xpos,
- uint32_t ypos, uint32_t clicks, double time)
- : Event(modifiers), mouse_button_(button),
- x_position_(xpos), y_position_(ypos),
- click_count_(clicks), timestamp_(time) {}
+ MouseEvent(uint32_t modifiers,
+ MouseButton button,
+ uint32_t xpos,
+ uint32_t ypos,
+ uint32_t clicks,
+ double time)
+ : Event(modifiers),
+ mouse_button_(button),
+ x_position_(xpos),
+ y_position_(ypos),
+ click_count_(clicks),
+ timestamp_(time) {}
// Convert the WheelEvent to a string
virtual std::string ToString() const;
@@ -104,19 +112,26 @@ class MouseEvent : public Event {
std::string MouseButtonToString(MouseButton button) const;
};
-
class WheelEvent : public Event {
public:
// WheelEvent Constructor. |modifiers| is passed to Event base class.
// |xticks| and |yticks| specify number of mouse wheel ticks.
// |scroll_by_page| indicates if we have scrolled past the current
// page. |time| is a timestamp,
- WheelEvent(int modifiers, uint32_t dx, uint32_t dy,
- uint32_t xticks, uint32_t yticks, bool scroll_by_page,
- float time) :
- Event(modifiers), delta_x_(dx), delta_y_(dy),
- ticks_x_(xticks), ticks_y_(yticks),
- scroll_by_page_(scroll_by_page), timestamp_(time) {}
+ WheelEvent(int modifiers,
+ uint32_t dx,
+ uint32_t dy,
+ uint32_t xticks,
+ uint32_t yticks,
+ bool scroll_by_page,
+ float time)
+ : Event(modifiers),
+ delta_x_(dx),
+ delta_y_(dy),
+ ticks_x_(xticks),
+ ticks_y_(yticks),
+ scroll_by_page_(scroll_by_page),
+ timestamp_(time) {}
// Convert the WheelEvent to a string
virtual std::string ToString() const;
@@ -129,20 +144,28 @@ class WheelEvent : public Event {
double timestamp_;
};
-
class TouchEvent : public Event {
public:
// The kind of touch event that occurred.
- enum Kind { kNone, kStart, kMove, kEnd, kCancel };
+ enum Kind {
+ kNone,
+ kStart,
+ kMove,
+ kEnd,
+ kCancel
+ };
// TouchEvent constructor.
- TouchEvent(int modifiers, Kind kind, float time) :
- Event(modifiers),
- kind_(kind),
- timestamp_(time) {}
+ TouchEvent(int modifiers, Kind kind, float time)
+ : Event(modifiers), kind_(kind), timestamp_(time) {}
// Add a changed touch to this touch event.
- void AddTouch(uint32_t id, float x, float y, float radii_x, float radii_y,
- float angle, float pressure);
+ void AddTouch(uint32_t id,
+ float x,
+ float y,
+ float radii_x,
+ float radii_y,
+ float angle,
+ float pressure);
// Convert the TouchEvent to a string
virtual std::string ToString() const;
@@ -164,7 +187,6 @@ class TouchEvent : public Event {
double timestamp_;
};
-
} // end namespace
#endif // CUSTOM_EVENTS_H
diff --git a/native_client_sdk/src/examples/api/input_event/example.dsc b/native_client_sdk/src/examples/api/input_event/example.dsc
new file mode 100644
index 0000000000..4c88c56a6c
--- /dev/null
+++ b/native_client_sdk/src/examples/api/input_event/example.dsc
@@ -0,0 +1,24 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux', 'win'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'input_event',
+ 'TYPE' : 'main',
+ 'SOURCES' : [
+ 'custom_events.cc',
+ 'custom_events.h',
+ 'input_events.cc',
+ 'shared_queue.h',
+ ],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'input_event',
+ 'TITLE': 'Input Events',
+ 'GROUP': 'API',
+}
+
diff --git a/native_client_sdk/src/examples/input_events/example.js b/native_client_sdk/src/examples/api/input_event/example.js
index eb335f00ed..003e8439d2 100644
--- a/native_client_sdk/src/examples/input_events/example.js
+++ b/native_client_sdk/src/examples/api/input_event/example.js
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-var kMaxArraySize = 20;
-var messageArray = new Array();
-
// Called by the common.js module.
function moduleDidLoad() {
common.naclModule.style.backgroundColor = 'gray';
@@ -17,15 +14,7 @@ function attachListeners() {
// Called by the common.js module.
function handleMessage(message) {
- // Show last |kMaxArraySize| events in html.
- messageArray.push(message.data);
- if (messageArray.length > kMaxArraySize) {
- messageArray.shift();
- }
- var newData = messageArray.join('<BR>');
- document.getElementById('eventString').innerHTML = newData;
- // Print event to console.
- console.log(message.data);
+ common.logMessage(message.data);
}
function cancelQueue() {
diff --git a/native_client_sdk/src/examples/input_events/index.html b/native_client_sdk/src/examples/api/input_event/index.html
index a77af1f8d2..2e97b9884b 100644
--- a/native_client_sdk/src/examples/input_events/index.html
+++ b/native_client_sdk/src/examples/api/input_event/index.html
@@ -15,28 +15,24 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <button id="killButton">Kill worker thread and queue</button>
-
- <p>This example demonstrates handling of input events in PPAPI.</p>
- <p>Each time an input event happens in the context of the gray box, the main
- thread in the embedded NaCl module converts it from a Pepper input event to a
- non-Pepper event and puts this custom event onto a shared queue. A worker
- thread in the embedded NaCl module reads events from the queue, and converts
- each event to a string and then uses CallOnMainThread to post a message
- describing the event back to JavaScript, which prints a message to the
- JavaScript console in Chrome and to a string on the page.</p>
+ <p>The Input Events example shows how to handle input events in a
+ multi-threaded application. The main thread converts input events to
+ non-pepper events and puts them on a queue. The worker thread pulls them
+ off of the queue, converts them to a string, and then uses
+ CallOnMainThread so that PostMessage can be send the result of the worker
+ thread to the browser.</p>
<p>If you press the 'Kill worker thread and queue' button, then the main
thread (which puts events on the queue) will call CancelQueue, indicating
that the main thread will no longer put events on the queue. When the worker
sees that the shared queue has been cancelled, the worker thread will
terminate.</p>
+ <button id="killButton">Kill worker thread and queue</button>
+
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
- <h2>Events</h2>
- <pre>
- <p><b id='eventString'>None</b></p>
- </pre>
+ <h2>Events:</h2>
+ <pre id="log" style="font-weight: bold"></pre>
</body>
</html>
diff --git a/native_client_sdk/src/examples/input_events/input_events.cc b/native_client_sdk/src/examples/api/input_event/input_events.cc
index 1a0a9f8f11..1a6b190850 100644
--- a/native_client_sdk/src/examples/input_events/input_events.cc
+++ b/native_client_sdk/src/examples/api/input_event/input_events.cc
@@ -27,11 +27,11 @@
#endif
namespace event_queue {
-const char* const kDidChangeView = "DidChangeView";
-const char* const kHandleInputEvent = "DidHandleInputEvent";
-const char* const kDidChangeFocus = "DidChangeFocus";
-const char* const kHaveFocus = "HaveFocus";
-const char* const kDontHaveFocus = "DontHaveFocus";
+const char* const kDidChangeView = "DidChangeView\n";
+const char* const kHandleInputEvent = "DidHandleInputEvent\n";
+const char* const kDidChangeFocus = "DidChangeFocus\n";
+const char* const kHaveFocus = "HaveFocus\n";
+const char* const kDontHaveFocus = "DontHaveFocus\n";
const char* const kCancelMessage = "CANCEL";
// Convert a pepper inputevent modifier value into a
@@ -77,19 +77,15 @@ unsigned int ConvertEventModifier(uint32_t pp_modifier) {
class EventInstance : public pp::Instance {
public:
explicit EventInstance(PP_Instance instance)
- : pp::Instance(instance),
- event_thread_(NULL),
- callback_factory_(this) {
- RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL
- | PP_INPUTEVENT_CLASS_TOUCH);
+ : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) {
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL |
+ PP_INPUTEVENT_CLASS_TOUCH);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
}
// Not guaranteed to be called in Pepper, but a good idea to cancel the
// queue and signal to workers to die if it is called.
- virtual ~EventInstance() {
- CancelQueueAndWaitForWorker();
- }
+ virtual ~EventInstance() { CancelQueueAndWaitForWorker(); }
// Create the 'worker thread'.
bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
@@ -128,7 +124,8 @@ class EventInstance : public pp::Instance {
virtual void HandleMessage(const pp::Var& var_message) {
std::string message = var_message.AsString();
if (kCancelMessage == message) {
- std::string reply = "Received cancel : only Focus events will be "
+ std::string reply =
+ "Received cancel : only Focus events will be "
"displayed. Worker thread for mouse/wheel/keyboard will exit.";
PostMessage(pp::Var(reply));
printf("Calling cancel queue\n");
@@ -153,104 +150,104 @@ class EventInstance : public pp::Instance {
case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
case PP_INPUTEVENT_TYPE_IME_TEXT:
- // these cases are not handled...fall through below...
+ // these cases are not handled...fall through below...
case PP_INPUTEVENT_TYPE_UNDEFINED:
break;
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
case PP_INPUTEVENT_TYPE_MOUSEUP:
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
case PP_INPUTEVENT_TYPE_MOUSEENTER:
- case PP_INPUTEVENT_TYPE_MOUSELEAVE:
- {
- pp::MouseInputEvent mouse_event(event);
- PP_InputEvent_MouseButton pp_button = mouse_event.GetButton();
- MouseEvent::MouseButton mouse_button = MouseEvent::kNone;
- switch (pp_button) {
- case PP_INPUTEVENT_MOUSEBUTTON_NONE:
- mouse_button = MouseEvent::kNone;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
- mouse_button = MouseEvent::kLeft;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
- mouse_button = MouseEvent::kMiddle;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
- mouse_button = MouseEvent::kRight;
- break;
- }
- event_ptr = new MouseEvent(
- ConvertEventModifier(mouse_event.GetModifiers()),
- mouse_button, mouse_event.GetPosition().x(),
- mouse_event.GetPosition().y(), mouse_event.GetClickCount(),
- mouse_event.GetTimeStamp());
- }
- break;
- case PP_INPUTEVENT_TYPE_WHEEL:
- {
- pp::WheelInputEvent wheel_event(event);
- event_ptr = new WheelEvent(
- ConvertEventModifier(wheel_event.GetModifiers()),
- wheel_event.GetDelta().x(), wheel_event.GetDelta().y(),
- wheel_event.GetTicks().x(), wheel_event.GetTicks().y(),
- wheel_event.GetScrollByPage(), wheel_event.GetTimeStamp());
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
+ pp::MouseInputEvent mouse_event(event);
+ PP_InputEvent_MouseButton pp_button = mouse_event.GetButton();
+ MouseEvent::MouseButton mouse_button = MouseEvent::kNone;
+ switch (pp_button) {
+ case PP_INPUTEVENT_MOUSEBUTTON_NONE:
+ mouse_button = MouseEvent::kNone;
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
+ mouse_button = MouseEvent::kLeft;
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
+ mouse_button = MouseEvent::kMiddle;
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
+ mouse_button = MouseEvent::kRight;
+ break;
}
- break;
+ event_ptr =
+ new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()),
+ mouse_button,
+ mouse_event.GetPosition().x(),
+ mouse_event.GetPosition().y(),
+ mouse_event.GetClickCount(),
+ mouse_event.GetTimeStamp());
+ } break;
+ case PP_INPUTEVENT_TYPE_WHEEL: {
+ pp::WheelInputEvent wheel_event(event);
+ event_ptr =
+ new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()),
+ wheel_event.GetDelta().x(),
+ wheel_event.GetDelta().y(),
+ wheel_event.GetTicks().x(),
+ wheel_event.GetTicks().y(),
+ wheel_event.GetScrollByPage(),
+ wheel_event.GetTimeStamp());
+ } break;
case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
case PP_INPUTEVENT_TYPE_KEYDOWN:
case PP_INPUTEVENT_TYPE_KEYUP:
case PP_INPUTEVENT_TYPE_CHAR:
- case PP_INPUTEVENT_TYPE_CONTEXTMENU:
- {
- pp::KeyboardInputEvent key_event(event);
- event_ptr = new KeyEvent(
- ConvertEventModifier(key_event.GetModifiers()),
- key_event.GetKeyCode(), key_event.GetTimeStamp(),
- key_event.GetCharacterText().DebugString());
- }
- break;
+ case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
+ pp::KeyboardInputEvent key_event(event);
+ event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()),
+ key_event.GetKeyCode(),
+ key_event.GetTimeStamp(),
+ key_event.GetCharacterText().DebugString());
+ } break;
case PP_INPUTEVENT_TYPE_TOUCHSTART:
case PP_INPUTEVENT_TYPE_TOUCHMOVE:
case PP_INPUTEVENT_TYPE_TOUCHEND:
- case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
- {
- pp::TouchInputEvent touch_event(event);
+ case PP_INPUTEVENT_TYPE_TOUCHCANCEL: {
+ pp::TouchInputEvent touch_event(event);
- TouchEvent::Kind touch_kind = TouchEvent::kNone;
- if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART)
- touch_kind = TouchEvent::kStart;
- else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHMOVE)
- touch_kind = TouchEvent::kMove;
- else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHEND)
- touch_kind = TouchEvent::kEnd;
- else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHCANCEL)
- touch_kind = TouchEvent::kCancel;
+ TouchEvent::Kind touch_kind = TouchEvent::kNone;
+ if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART)
+ touch_kind = TouchEvent::kStart;
+ else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHMOVE)
+ touch_kind = TouchEvent::kMove;
+ else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHEND)
+ touch_kind = TouchEvent::kEnd;
+ else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHCANCEL)
+ touch_kind = TouchEvent::kCancel;
- TouchEvent* touch_event_ptr = new TouchEvent(
- ConvertEventModifier(touch_event.GetModifiers()),
- touch_kind, touch_event.GetTimeStamp());
- event_ptr = touch_event_ptr;
+ TouchEvent* touch_event_ptr =
+ new TouchEvent(ConvertEventModifier(touch_event.GetModifiers()),
+ touch_kind,
+ touch_event.GetTimeStamp());
+ event_ptr = touch_event_ptr;
- uint32_t touch_count =
- touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES);
- for (uint32_t i = 0; i < touch_count; ++i) {
- pp::TouchPoint point = touch_event.GetTouchByIndex(
- PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, i);
- touch_event_ptr->AddTouch(point.id(), point.position().x(),
- point.position().y(), point.radii().x(), point.radii().y(),
- point.rotation_angle(), point.pressure());
- }
+ uint32_t touch_count =
+ touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES);
+ for (uint32_t i = 0; i < touch_count; ++i) {
+ pp::TouchPoint point =
+ touch_event.GetTouchByIndex(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, i);
+ touch_event_ptr->AddTouch(point.id(),
+ point.position().x(),
+ point.position().y(),
+ point.radii().x(),
+ point.radii().y(),
+ point.rotation_angle(),
+ point.pressure());
}
- break;
- default:
- {
- // For any unhandled events, send a message to the browser
- // so that the user is aware of these and can investigate.
- std::stringstream oss;
- oss << "Default (unhandled) event, type=" << event.GetType();
- PostMessage(oss.str());
- }
- break;
+ } break;
+ default: {
+ // For any unhandled events, send a message to the browser
+ // so that the user is aware of these and can investigate.
+ std::stringstream oss;
+ oss << "Default (unhandled) event, type=" << event.GetType();
+ PostMessage(oss.str());
+ } break;
}
event_queue_.Push(event_ptr);
return true;
@@ -260,7 +257,7 @@ class EventInstance : public pp::Instance {
// to occur if the queue is empty. Set |was_queue_cancelled| to indicate
// whether the queue was cancelled. If it was cancelled, then the
// Event* will be NULL.
- const Event* GetEventFromQueue(bool *was_queue_cancelled) {
+ const Event* GetEventFromQueue(bool* was_queue_cancelled) {
Event* event = NULL;
QueueGetResult result = event_queue_.GetItem(&event, kWait);
if (result == kQueueWasCancelled) {
@@ -303,9 +300,8 @@ class EventInstance : public pp::Instance {
// Need to invoke callback on main thread.
pp::Module::Get()->core()->CallOnMainThread(
0,
- event_instance->callback_factory().NewCallback(
- &EventInstance::PostStringToBrowser,
- event_string));
+ event_instance->callback_factory()
+ .NewCallback(&EventInstance::PostStringToBrowser, event_string));
} // end of while loop.
return 0;
}
@@ -317,21 +313,21 @@ class EventInstance : public pp::Instance {
return callback_factory_;
}
- private:
- // Cancels the queue (which will cause the thread to exit).
- // Wait for the thread. Set |event_thread_| to NULL so we only
- // execute the body once.
- void CancelQueueAndWaitForWorker() {
- if (event_thread_) {
- event_queue_.CancelQueue();
- pthread_join(*event_thread_, NULL);
- delete event_thread_;
- event_thread_ = NULL;
- }
+ private:
+ // Cancels the queue (which will cause the thread to exit).
+ // Wait for the thread. Set |event_thread_| to NULL so we only
+ // execute the body once.
+ void CancelQueueAndWaitForWorker() {
+ if (event_thread_) {
+ event_queue_.CancelQueue();
+ pthread_join(*event_thread_, NULL);
+ delete event_thread_;
+ event_thread_ = NULL;
}
- pthread_t* event_thread_;
- LockingQueue<Event*> event_queue_;
- pp::CompletionCallbackFactory<EventInstance> callback_factory_;
+ }
+ pthread_t* event_thread_;
+ LockingQueue<Event*> event_queue_;
+ pp::CompletionCallbackFactory<EventInstance> callback_factory_;
};
// The EventModule provides an implementation of pp::Module that creates
@@ -353,8 +349,5 @@ class EventModule : public pp::Module {
// kind of Module (in this case, EventModule). This is part of the glue code
// that makes our example accessible to ppapi.
namespace pp {
- Module* CreateModule() {
- return new event_queue::EventModule();
- }
+Module* CreateModule() { return new event_queue::EventModule(); }
}
-
diff --git a/native_client_sdk/src/examples/api/input_event/shared_queue.h b/native_client_sdk/src/examples/api/input_event/shared_queue.h
new file mode 100644
index 0000000000..ff13996f7f
--- /dev/null
+++ b/native_client_sdk/src/examples/api/input_event/shared_queue.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHARED_QUEUE_H
+#define SHARED_QUEUE_H
+
+#include <pthread.h>
+#include <cassert>
+#include <deque>
+
+namespace event_queue {
+
+// This file provides a queue that uses a mutex and condition variable so that
+// one thread can put pointers into the queue and another thread can pull items
+// out of the queue.
+
+// Specifies whether we want to wait for the queue.
+enum QueueWaitingFlag {
+ kWait = 0,
+ kDontWait
+};
+
+// Indicates if we got an item, did not wait, or if the queue was cancelled.
+enum QueueGetResult {
+ kReturnedItem = 0,
+ kDidNotWait = 1,
+ kQueueWasCancelled
+};
+
+// A simple scoped mutex lock.
+// For most cases, pp::AutoLock in "ppapi/utility/threading/lock.h" can be
+// used; LockingQueue needs to use the pthread_mutex_t directly in
+// pthread_cond_wait so we reimplement a scoped lock here.
+class ScopedLock {
+ public:
+ explicit ScopedLock(pthread_mutex_t* mutex) : mutex_(mutex) {
+ const int kPthreadMutexSuccess = 0;
+ if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) {
+ mutex_ = NULL;
+ }
+ }
+ ~ScopedLock() {
+ if (mutex_ != NULL) {
+ pthread_mutex_unlock(mutex_);
+ }
+ }
+
+ private:
+ pthread_mutex_t* mutex_; // Weak reference, passed in to constructor.
+
+ // Disable copy and assign.
+ ScopedLock& operator=(const ScopedLock&);
+ ScopedLock(const ScopedLock&);
+};
+
+// LockingQueue contains a collection of <T>, such as a collection of
+// objects or pointers. The Push() method is used to add items to the
+// queue in a thread-safe manner. The GetItem() is used to retrieve
+// items from the queue in a thread-safe manner.
+template <class T> class LockingQueue {
+ public:
+ LockingQueue() : quit_(false) {
+ int result = pthread_mutex_init(&queue_mutex_, NULL);
+ assert(result == 0);
+ result = pthread_cond_init(&queue_condition_var_, NULL);
+ assert(result == 0);
+ }
+ ~LockingQueue() { pthread_mutex_destroy(&queue_mutex_); }
+
+ // The producer (who instantiates the queue) calls this to tell the
+ // consumer that the queue is no longer being used.
+ void CancelQueue() {
+ ScopedLock scoped_mutex(&queue_mutex_);
+ quit_ = true;
+ // Signal the condition var so that if a thread is waiting in
+ // GetItem the thread will wake up and see that the queue has
+ // been cancelled.
+ pthread_cond_signal(&queue_condition_var_);
+ }
+
+ // The consumer calls this to see if the queue has been cancelled by
+ // the producer. If so, the thread should not call GetItem and may
+ // need to terminate -- i.e. in a case where the producer created
+ // the consumer thread.
+ bool IsCancelled() {
+ ScopedLock scoped_mutex(&queue_mutex_);
+ return quit_;
+ }
+
+ // Grabs the mutex and pushes a new item to the end of the queue if the
+ // queue is not full. Signals the condition variable so that a thread
+ // that is waiting will wake up and grab the item.
+ void Push(const T& item) {
+ ScopedLock scoped_mutex(&queue_mutex_);
+ the_queue_.push_back(item);
+ pthread_cond_signal(&queue_condition_var_);
+ }
+
+ // Tries to pop the front element from the queue; returns an enum:
+ // kReturnedItem if an item is returned in |item_ptr|,
+ // kDidNotWait if |wait| was kDontWait and the queue was empty,
+ // kQueueWasCancelled if the producer called CancelQueue().
+ // If |wait| is kWait, GetItem will wait to return until the queue
+ // contains an item (unless the queue is cancelled).
+ QueueGetResult GetItem(T* item_ptr, QueueWaitingFlag wait) {
+ ScopedLock scoped_mutex(&queue_mutex_);
+ // Use a while loop to get an item. If the user does not want to wait,
+ // we will exit from the loop anyway, unlocking the mutex.
+ // If the user does want to wait, we will wait for pthread_cond_wait,
+ // and the while loop will check is_empty_no_locking() one more
+ // time so that a spurious wake-up of pthread_cond_wait is handled.
+ // If |quit_| has been set, break out of the loop.
+ while (!quit_ && is_empty_no_locking()) {
+ // If user doesn't want to wait, return...
+ if (kDontWait == wait) {
+ return kDidNotWait;
+ }
+ // Wait for signal to occur.
+ pthread_cond_wait(&queue_condition_var_, &queue_mutex_);
+ }
+ // Check to see if quit_ woke us up
+ if (quit_) {
+ return kQueueWasCancelled;
+ }
+
+ // At this point, the queue was either not empty or, if it was empty,
+ // we called pthread_cond_wait (which released the mutex, waited for the
+ // signal to occur, and then atomically reacquired the mutex).
+ // Thus, if we are here, the queue cannot be empty because we either
+ // had the mutex and verified it was not empty, or we waited for the
+ // producer to put an item in and signal a single thread (us).
+ T& item = the_queue_.front();
+ *item_ptr = item;
+ the_queue_.pop_front();
+ return kReturnedItem;
+ }
+
+ private:
+ std::deque<T> the_queue_;
+ bool quit_;
+ pthread_mutex_t queue_mutex_;
+ pthread_cond_t queue_condition_var_;
+
+ // This is used by methods that already have the lock.
+ bool is_empty_no_locking() const { return the_queue_.empty(); }
+};
+
+} // end of unnamed namespace
+
+#endif // SHARED_QUEUE_H
diff --git a/native_client_sdk/src/examples/load_progress/check_browser.js b/native_client_sdk/src/examples/api/mouse_lock/check_browser.js
index 0c54ba4c07..0c54ba4c07 100644
--- a/native_client_sdk/src/examples/load_progress/check_browser.js
+++ b/native_client_sdk/src/examples/api/mouse_lock/check_browser.js
diff --git a/native_client_sdk/src/examples/api/mouse_lock/example.dsc b/native_client_sdk/src/examples/api/mouse_lock/example.dsc
new file mode 100644
index 0000000000..566c2c5e7a
--- /dev/null
+++ b/native_client_sdk/src/examples/api/mouse_lock/example.dsc
@@ -0,0 +1,17 @@
+{
+ 'DISABLE_PACKAGE': True,
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'mouselock',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['mouselock.cc', 'mouselock.h'],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'mouse_lock',
+ 'TITLE': 'Mouse Lock',
+ 'GROUP': 'API'
+}
+
diff --git a/native_client_sdk/src/examples/mouselock/index.html b/native_client_sdk/src/examples/api/mouse_lock/index.html
index 2e1cdeb645..c50377b6c4 100644
--- a/native_client_sdk/src/examples/mouselock/index.html
+++ b/native_client_sdk/src/examples/api/mouse_lock/index.html
@@ -14,7 +14,6 @@ found in the LICENSE file.
<body data-width="300" data-height="300" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <h1>Full-screen and Mouse-lock Example</h1>
<ul>
<li>There are two different kinds of fullscreen mode: "tab fullscreen" and
"browser fullscreen".
@@ -38,9 +37,9 @@ found in the LICENSE file.
<li>Involuntary fullscreen or mouselock loss.
<ul>
<li>Pressing the Esc key will cause the browser to revoke mouselock
- or tab fullscreen priviledge.</li>
+ or tab fullscreen privilege.</li>
<li>When in browser fullscreen, pressing F11 will also revoke mouselock
- or tab fullscreen priviledge.</li>
+ or tab fullscreen privilege.</li>
</ul>
</li>
</ul>
@@ -49,7 +48,7 @@ found in the LICENSE file.
is outside of the grey box.</p>
<p> By clicking on the grey box, we set focus and turn on mouse lock. Now all
mouse messages are sent to the module.</p>
- <p> This behavoir is maintianed even in tab and/or browser fullscreen.</p>
+ <p> This behavior is maintained even in tab and/or browser fullscreen.</p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/mouselock/mouselock.cc b/native_client_sdk/src/examples/api/mouse_lock/mouselock.cc
index 9aefac1396..4305b18caa 100644
--- a/native_client_sdk/src/examples/mouselock/mouselock.cc
+++ b/native_client_sdk/src/examples/api/mouse_lock/mouselock.cc
@@ -22,10 +22,10 @@
// view. These values are used to determine which 2D quadrant the needle lies
// in.
typedef enum {
- kLeft = 0,
- kRight = 1,
- kUp = 2,
- kDown = 3
+ kLeft = 0,
+ kRight = 1,
+ kUp = 2,
+ kDown = 3
} MouseDirection;
namespace {
@@ -45,8 +45,7 @@ MouseLockInstance::~MouseLockInstance() {
bool MouseLockInstance::Init(uint32_t argc,
const char* argn[],
const char* argv[]) {
- RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
- PP_INPUTEVENT_CLASS_KEYBOARD);
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_KEYBOARD);
return true;
}
@@ -56,8 +55,8 @@ bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) {
if (mouse_locked_) {
UnlockMouse();
} else {
- LockMouse(callback_factory_.NewCallback(
- &MouseLockInstance::DidLockMouse));
+ LockMouse(
+ callback_factory_.NewCallback(&MouseLockInstance::DidLockMouse));
}
return true;
}
@@ -123,15 +122,17 @@ void MouseLockInstance::DidChangeView(const pp::View& view) {
if ((size_ == view.GetRect().size()) &&
(was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
- Log("DidChangeView SKIP %d,%d FULL=%s CTX Bound=%s",
- view.GetRect().width(), view.GetRect().height(),
- view.IsFullscreen() ? "true" : "false",
- is_context_bound_ ? "true" : "false");
+ Log("DidChangeView SKIP %d,%d FULL=%s CTX Bound=%s",
+ view.GetRect().width(),
+ view.GetRect().height(),
+ view.IsFullscreen() ? "true" : "false",
+ is_context_bound_ ? "true" : "false");
return;
}
Log("DidChangeView DO %d,%d FULL=%s CTX Bound=%s",
- view.GetRect().width(), view.GetRect().height(),
+ view.GetRect().width(),
+ view.GetRect().height(),
view.IsFullscreen() ? "true" : "false",
is_context_bound_ ? "true" : "false");
@@ -181,7 +182,8 @@ void MouseLockInstance::DidLockMouse(int32_t result) {
}
void MouseLockInstance::DidFlush(int32_t result) {
- if (result != 0) Log("Flushed failed with error number %d.\n", result);
+ if (result != 0)
+ Log("Flushed failed with error number %d.\n", result);
waiting_for_flush_completion_ = false;
}
@@ -203,7 +205,6 @@ void MouseLockInstance::Paint() {
callback_factory_.NewCallback(&MouseLockInstance::DidFlush));
}
-
pp::ImageData MouseLockInstance::PaintImage(const pp::Size& size) {
pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
if (image.is_null() || image.data() == NULL) {
@@ -252,10 +253,9 @@ void MouseLockInstance::DrawCenterSpot(pp::ImageData* image,
pp::Point left_top(std::max(0, center_x - region_of_interest_radius),
std::max(0, center_y - region_of_interest_radius));
- pp::Point right_bottom(std::min(image->size().width(),
- center_x + region_of_interest_radius),
- std::min(image->size().height(),
- center_y + region_of_interest_radius));
+ pp::Point right_bottom(
+ std::min(image->size().width(), center_x + region_of_interest_radius),
+ std::min(image->size().height(), center_y + region_of_interest_radius));
for (int y = left_top.y(); y < right_bottom.y(); ++y) {
for (int x = left_top.x(); x < right_bottom.x(); ++x) {
if (GetDistance(x, y, center_x, center_y) < kCentralSpotRadius) {
@@ -287,42 +287,38 @@ void MouseLockInstance::DrawNeedle(pp::ImageData* image,
MouseDirection direction = kLeft;
if (abs_mouse_x >= abs_mouse_y) {
- anchor_1.set_x(center_x);
- anchor_1.set_y(center_y - kCentralSpotRadius);
- anchor_2.set_x(center_x);
- anchor_2.set_y(center_y + kCentralSpotRadius);
- direction = (mouse_movement_.x() < 0) ? kLeft : kRight;
- if (direction == kLeft)
- anchor_1.swap(anchor_2);
+ anchor_1.set_x(center_x);
+ anchor_1.set_y(center_y - kCentralSpotRadius);
+ anchor_2.set_x(center_x);
+ anchor_2.set_y(center_y + kCentralSpotRadius);
+ direction = (mouse_movement_.x() < 0) ? kLeft : kRight;
+ if (direction == kLeft)
+ anchor_1.swap(anchor_2);
} else {
- anchor_1.set_x(center_x + kCentralSpotRadius);
- anchor_1.set_y(center_y);
- anchor_2.set_x(center_x - kCentralSpotRadius);
- anchor_2.set_y(center_y);
- direction = (mouse_movement_.y() < 0) ? kUp : kDown;
- if (direction == kUp)
- anchor_1.swap(anchor_2);
+ anchor_1.set_x(center_x + kCentralSpotRadius);
+ anchor_1.set_y(center_y);
+ anchor_2.set_x(center_x - kCentralSpotRadius);
+ anchor_2.set_y(center_y);
+ direction = (mouse_movement_.y() < 0) ? kUp : kDown;
+ if (direction == kUp)
+ anchor_1.swap(anchor_2);
}
pp::Point left_top(std::max(0, center_x - abs_mouse_x),
std::max(0, center_y - abs_mouse_y));
- pp::Point right_bottom(std::min(image->size().width(),
- center_x + abs_mouse_x),
- std::min(image->size().height(),
- center_y + abs_mouse_y));
+ pp::Point right_bottom(
+ std::min(image->size().width(), center_x + abs_mouse_x),
+ std::min(image->size().height(), center_y + abs_mouse_y));
for (int y = left_top.y(); y < right_bottom.y(); ++y) {
for (int x = left_top.x(); x < right_bottom.x(); ++x) {
- bool within_bound_1 =
- ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
- ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
- bool within_bound_2 =
- ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
- ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
- bool within_bound_3 =
- (direction == kUp && y < center_y) ||
- (direction == kDown && y > center_y) ||
- (direction == kLeft && x < center_x) ||
- (direction == kRight && x > center_x);
+ bool within_bound_1 = ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
+ ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
+ bool within_bound_2 = ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
+ ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
+ bool within_bound_3 = (direction == kUp && y < center_y) ||
+ (direction == kDown && y > center_y) ||
+ (direction == kLeft && x < center_x) ||
+ (direction == kRight && x > center_x);
if (within_bound_1 && within_bound_2 && within_bound_3) {
*image->GetAddr32(pp::Point(x, y)) = needle_color;
@@ -331,12 +327,13 @@ void MouseLockInstance::DrawNeedle(pp::ImageData* image,
}
}
-
void MouseLockInstance::Log(const char* format, ...) {
- static PPB_Console* console = (PPB_Console*)
- pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE);
+ static PPB_Console* console =
+ (PPB_Console*)pp::Module::Get()->GetBrowserInterface(
+ PPB_CONSOLE_INTERFACE);
- if (NULL == console) return;
+ if (NULL == console)
+ return;
va_list args;
va_start(args, format);
char buf[512];
@@ -366,9 +363,6 @@ class MouseLockModule : public pp::Module {
namespace pp {
// Factory function for your specialization of the Module object.
-Module* CreateModule() {
- return new MouseLockModule();
-}
+Module* CreateModule() { return new MouseLockModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/mouselock/mouselock.h b/native_client_sdk/src/examples/api/mouse_lock/mouselock.h
index 56be1d72d4..2e1d190077 100644
--- a/native_client_sdk/src/examples/mouselock/mouselock.h
+++ b/native_client_sdk/src/examples/api/mouse_lock/mouselock.h
@@ -37,8 +37,7 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
fullscreen_(this),
is_context_bound_(false),
was_fullscreen_(false),
- background_scanline_(NULL) {
- }
+ background_scanline_(NULL) {}
virtual ~MouseLockInstance();
// Called by the browser when the NaCl module is loaded and all ready to go.
@@ -56,8 +55,10 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
private:
// Return the Cartesian distance between two points.
- double GetDistance(int point_1_x, int point_1_y,
- int point_2_x, int point_2_y) {
+ double GetDistance(int point_1_x,
+ int point_1_y,
+ int point_2_x,
+ int point_2_y) {
return sqrt(pow(static_cast<double>(point_1_x - point_2_x), 2) +
pow(static_cast<double>(point_1_y - point_2_y), 2));
}
@@ -78,7 +79,7 @@ class MouseLockInstance : public pp::Instance, public pp::MouseLock {
// movement in it. Return the new pp::ImageData.
pp::ImageData PaintImage(const pp::Size& size);
- // Fill the image with the backgroud color.
+ // Fill the image with the background color.
void ClearToBackground(pp::ImageData* image);
void DrawCenterSpot(pp::ImageData* image, uint32_t spot_color);
diff --git a/native_client_sdk/src/examples/geturl/example.dsc b/native_client_sdk/src/examples/api/url_loader/example.dsc
index eff4fc35c8..a5c4503da4 100644
--- a/native_client_sdk/src/examples/geturl/example.dsc
+++ b/native_client_sdk/src/examples/api/url_loader/example.dsc
@@ -12,15 +12,9 @@
'example.js',
'geturl_success.html',
],
- 'DEST': 'examples',
- 'NAME': 'geturl',
- 'TITLE': 'Get URL',
- 'DESC': """
-The Get URL example demonstrates fetching an URL and then displaying
-its contents. Clicking the GetURL button will cause a geturl_success.html
-file to get loaded asynchronously, then displayed in a text box when the
-load completes.""",
- 'FOCUS': 'URL loading.',
+ 'DEST': 'examples/api',
+ 'NAME': 'url_loader',
+ 'TITLE': 'URL Loader',
'GROUP': 'API'
}
diff --git a/native_client_sdk/src/examples/geturl/example.js b/native_client_sdk/src/examples/api/url_loader/example.js
index 2ebdfeb29e..2ebdfeb29e 100644
--- a/native_client_sdk/src/examples/geturl/example.js
+++ b/native_client_sdk/src/examples/api/url_loader/example.js
diff --git a/native_client_sdk/src/examples/geturl/geturl.cc b/native_client_sdk/src/examples/api/url_loader/geturl.cc
index fa3838da8a..db7abe20c8 100644
--- a/native_client_sdk/src/examples/geturl/geturl.cc
+++ b/native_client_sdk/src/examples/api/url_loader/geturl.cc
@@ -69,7 +69,6 @@ void GetURLInstance::HandleMessage(const pp::Var& var_message) {
}
}
-
// The Module class. The browser calls the CreateInstance() method to create
// an instance of you NaCl module on the web page. The browser creates a new
// instance for each <embed> tag with type="application/x-nacl".
@@ -90,8 +89,5 @@ class GetURLModule : public pp::Module {
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
-Module* CreateModule() {
- return new GetURLModule();
-}
+Module* CreateModule() { return new GetURLModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/geturl/geturl_handler.cc b/native_client_sdk/src/examples/api/url_loader/geturl_handler.cc
index 20008547a6..e13ca1f5e1 100644
--- a/native_client_sdk/src/examples/geturl/geturl_handler.cc
+++ b/native_client_sdk/src/examples/api/url_loader/geturl_handler.cc
@@ -25,8 +25,7 @@ GetURLHandler* GetURLHandler::Create(pp::Instance* instance,
return new GetURLHandler(instance, url);
}
-GetURLHandler::GetURLHandler(pp::Instance* instance,
- const std::string& url)
+GetURLHandler::GetURLHandler(pp::Instance* instance, const std::string& url)
: instance_(instance),
url_(url),
url_request_(instance),
@@ -39,13 +38,12 @@ GetURLHandler::GetURLHandler(pp::Instance* instance,
}
GetURLHandler::~GetURLHandler() {
- delete [] buffer_;
+ delete[] buffer_;
buffer_ = NULL;
}
void GetURLHandler::Start() {
- pp::CompletionCallback cc =
- cc_factory_.NewCallback(&GetURLHandler::OnOpen);
+ pp::CompletionCallback cc = cc_factory_.NewCallback(&GetURLHandler::OnOpen);
url_loader_.Open(url_request_, cc);
}
@@ -87,16 +85,15 @@ void GetURLHandler::AppendDataBytes(const char* buffer, int32_t num_bytes) {
// Note that we do *not* try to minimally increase the amount of allocated
// memory here by calling url_response_body_.reserve(). Doing so causes a
// lot of string reallocations that kills performance for large files.
- url_response_body_.insert(url_response_body_.end(),
- buffer,
- buffer + num_bytes);
+ url_response_body_.insert(
+ url_response_body_.end(), buffer, buffer + num_bytes);
}
void GetURLHandler::OnRead(int32_t result) {
if (result == PP_OK) {
// Streaming the file is complete, delete the read buffer since it is
// no longer needed.
- delete [] buffer_;
+ delete[] buffer_;
buffer_ = NULL;
ReportResultAndDie(url_, url_response_body_, true);
} else if (result > 0) {
@@ -106,9 +103,8 @@ void GetURLHandler::OnRead(int32_t result) {
ReadBody();
} else {
// A read error occurred.
- ReportResultAndDie(url_,
- "pp::URLLoader::ReadResponseBody() result<0",
- false);
+ ReportResultAndDie(
+ url_, "pp::URLLoader::ReadResponseBody() result<0", false);
}
}
@@ -163,4 +159,3 @@ void GetURLHandler::ReportResult(const std::string& fname,
instance_->PostMessage(var_result);
}
}
-
diff --git a/native_client_sdk/src/examples/geturl/geturl_handler.h b/native_client_sdk/src/examples/api/url_loader/geturl_handler.h
index 4caffa1bb5..cad71b01ba 100644
--- a/native_client_sdk/src/examples/geturl/geturl_handler.h
+++ b/native_client_sdk/src/examples/api/url_loader/geturl_handler.h
@@ -34,8 +34,7 @@ class GetURLHandler {
// Creates instance of GetURLHandler on the heap.
// GetURLHandler objects shall be created only on the heap (they
// self-destroy when all data is in).
- static GetURLHandler* Create(pp::Instance* instance_,
- const std::string& url);
+ static GetURLHandler* Create(pp::Instance* instance_, const std::string& url);
// Initiates page (URL) download.
void Start();
@@ -43,14 +42,14 @@ class GetURLHandler {
GetURLHandler(pp::Instance* instance_, const std::string& url);
~GetURLHandler();
- // Callback fo the pp::URLLoader::Open().
+ // Callback for the pp::URLLoader::Open().
// Called by pp::URLLoader when response headers are received or when an
// error occurs (in response to the call of pp::URLLoader::Open()).
// Look at <ppapi/c/ppb_url_loader.h> and
// <ppapi/cpp/url_loader.h> for more information about pp::URLLoader.
void OnOpen(int32_t result);
- // Callback fo the pp::URLLoader::ReadResponseBody().
+ // Callback for the pp::URLLoader::ReadResponseBody().
// |result| contains the number of bytes read or an error code.
// Appends data from this->buffer_ to this->url_response_body_.
void OnRead(int32_t result);
@@ -74,10 +73,10 @@ class GetURLHandler {
bool success);
pp::Instance* instance_; // Weak pointer.
- std::string url_; // URL to be downloaded.
+ std::string url_; // URL to be downloaded.
pp::URLRequestInfo url_request_;
pp::URLLoader url_loader_; // URLLoader provides an API to download URLs.
- char* buffer_; // Temporary buffer for reads.
+ char* buffer_; // Temporary buffer for reads.
std::string url_response_body_; // Contains accumulated downloaded data.
pp::CompletionCallbackFactory<GetURLHandler> cc_factory_;
@@ -86,4 +85,3 @@ class GetURLHandler {
};
#endif // EXAMPLES_GETURL_GETURL_HANDLER_H_
-
diff --git a/native_client_sdk/src/examples/geturl/geturl_success.html b/native_client_sdk/src/examples/api/url_loader/geturl_success.html
index f5a3b8bdc6..f5a3b8bdc6 100644
--- a/native_client_sdk/src/examples/geturl/geturl_success.html
+++ b/native_client_sdk/src/examples/api/url_loader/geturl_success.html
diff --git a/native_client_sdk/src/examples/geturl/index.html b/native_client_sdk/src/examples/api/url_loader/index.html
index ceb42ade13..cdaa241be0 100644
--- a/native_client_sdk/src/examples/geturl/index.html
+++ b/native_client_sdk/src/examples/api/url_loader/index.html
@@ -15,6 +15,10 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The Get URL example demonstrates fetching an URL and then displaying its
+ contents. Clicking the GetURL button will cause a geturl_success.html
+ file to get loaded asynchronously, then displayed in a text box when the
+ 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>
diff --git a/native_client_sdk/src/examples/api/var_array_buffer/example.dsc b/native_client_sdk/src/examples/api/var_array_buffer/example.dsc
new file mode 100644
index 0000000000..43da81536d
--- /dev/null
+++ b/native_client_sdk/src/examples/api/var_array_buffer/example.dsc
@@ -0,0 +1,19 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'file_histogram',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['file_histogram.cc'],
+ 'LIBS' : ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'var_array_buffer',
+ 'TITLE': 'Var Array Buffer',
+ 'GROUP': 'API'
+}
+
diff --git a/native_client_sdk/src/examples/file_histogram/example.js b/native_client_sdk/src/examples/api/var_array_buffer/example.js
index 816a064fe6..816a064fe6 100644
--- a/native_client_sdk/src/examples/file_histogram/example.js
+++ b/native_client_sdk/src/examples/api/var_array_buffer/example.js
diff --git a/native_client_sdk/src/examples/file_histogram/file_histogram.cc b/native_client_sdk/src/examples/api/var_array_buffer/file_histogram.cc
index 26d4b193ba..ce293e9294 100644
--- a/native_client_sdk/src/examples/file_histogram/file_histogram.cc
+++ b/native_client_sdk/src/examples/api/var_array_buffer/file_histogram.cc
@@ -57,7 +57,7 @@ const size_t kHistogramSize = 256u;
/// The Instance class. One of these exists for each instance of your NaCl
/// module on the web page. The browser will ask the Module object to create
-/// a new Instance for each occurence of the <embed> tag that has these
+/// a new Instance for each occurrence of the <embed> tag that has these
/// attributes:
/// type="application/x-nacl"
/// src="file_histogram.nmf"
@@ -69,10 +69,8 @@ class FileHistogramInstance : public pp::Instance {
: pp::Instance(instance),
callback_factory_(this),
flushing_(false),
- histogram_() {
- }
- virtual ~FileHistogramInstance() {
- }
+ histogram_() {}
+ virtual ~FileHistogramInstance() {}
private:
/// Handler for messages coming in from the browser via postMessage(). The
@@ -95,13 +93,11 @@ class FileHistogramInstance : public pp::Instance {
/// given <code>size</code>.
pp::ImageData MakeBlankImageData(const pp::Size& size) {
const bool init_to_zero = false;
- pp::ImageData image_data = pp::ImageData(this,
- PP_IMAGEDATAFORMAT_BGRA_PREMUL,
- size,
- init_to_zero);
+ pp::ImageData image_data =
+ pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, init_to_zero);
uint32_t* image_buffer = static_cast<uint32_t*>(image_data.data());
for (int i = 0; i < size.GetArea(); ++i)
- image_buffer[i] = kBlack;
+ image_buffer[i] = kBlack;
return image_data;
}
@@ -147,8 +143,8 @@ class FileHistogramInstance : public pp::Instance {
if (size_ != view.GetRect().size()) {
size_ = view.GetRect().size();
const bool is_always_opaque = true;
- graphics_2d_context_ = pp::Graphics2D(this, view.GetRect().size(),
- is_always_opaque);
+ graphics_2d_context_ =
+ pp::Graphics2D(this, view.GetRect().size(), is_always_opaque);
BindGraphics(graphics_2d_context_);
// The images in our queue are the wrong size, so we won't paint them.
// We'll only draw the most recently computed histogram.
@@ -177,9 +173,8 @@ class FileHistogramInstance : public pp::Instance {
/// <code>paint_queue_</code> to paint later.
void DrawHistogram() {
pp::ImageData image_data = MakeBlankImageData(size_);
- for (int i = 0;
- i < std::min(static_cast<int>(kHistogramSize),
- image_data.size().width());
+ for (int i = 0; i < std::min(static_cast<int>(kHistogramSize),
+ image_data.size().width());
++i) {
DrawBar(i, histogram_[i], &image_data);
}
@@ -231,7 +226,5 @@ namespace pp {
/// CreateInstance() method on the object you return to make instances. There
/// is one instance per <embed> tag on the page. This is the main binding
/// point for your NaCl module with the browser.
-Module* CreateModule() {
- return new FileHistogramModule();
-}
+Module* CreateModule() { return new FileHistogramModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/file_histogram/index.html b/native_client_sdk/src/examples/api/var_array_buffer/index.html
index 74fb107c1a..53858d930f 100644
--- a/native_client_sdk/src/examples/file_histogram/index.html
+++ b/native_client_sdk/src/examples/api/var_array_buffer/index.html
@@ -15,6 +15,10 @@
<body data-width="256" data-height="256" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The File Histogram example demonstrates prompting the user for a file,
+ passing the file contents to NativeClient as a VarArrayBuffer, then
+ drawing a histogram representing the contents of the file to a 2D
+ square.</p>
<input type="file" id="fileInput" multiple>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
diff --git a/native_client_sdk/src/examples/api/websocket/example.dsc b/native_client_sdk/src/examples/api/websocket/example.dsc
new file mode 100644
index 0000000000..c3d02fcedd
--- /dev/null
+++ b/native_client_sdk/src/examples/api/websocket/example.dsc
@@ -0,0 +1,18 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'websocket',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['websocket.cc'],
+ 'LIBS': ['ppapi_cpp', 'ppapi']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/api',
+ 'NAME': 'websocket',
+ 'TITLE': 'Websocket',
+ 'GROUP': 'API'
+}
diff --git a/native_client_sdk/src/examples/websocket/example.js b/native_client_sdk/src/examples/api/websocket/example.js
index cc99dd309b..561d044e32 100644
--- a/native_client_sdk/src/examples/websocket/example.js
+++ b/native_client_sdk/src/examples/api/websocket/example.js
@@ -34,3 +34,7 @@ function doClose() {
// Send a request message. See also websocket.cc for the request format.
common.naclModule.postMessage('c;');
}
+
+function handleMessage(message) {
+ common.logMessage(message.data + '\n');
+}
diff --git a/native_client_sdk/src/examples/websocket/index.html b/native_client_sdk/src/examples/api/websocket/index.html
index 2bd2b18f10..f077fcdc7e 100644
--- a/native_client_sdk/src/examples/websocket/index.html
+++ b/native_client_sdk/src/examples/api/websocket/index.html
@@ -15,10 +15,12 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <div>Set a server URL, then push "Connect" button to establish a connection.
- <br>"Send" button sends text message on the left text area.
- <br>"Close" button closes the connection.
- <div>
+ <p>The Websocket example demonstrates how to use the Websocket API.<br>
+ First set a server URL (or use the default), then push "Connect" button to
+ establish a connection.<br>
+ "Send" button sends text message on the left text area.<br>
+ "Close" button closes the connection.
+ </p>
<form id="connectForm">
<input type="text" id="url" style="width: 400px"
value="ws://html5rocks.websocket.org/echo?encoding=text">
@@ -31,7 +33,7 @@ found in the LICENSE file.
</form>
<button id="closeButton">Close</button>
+ <pre id="log" style="font-weight: bold"></pre>
<div id="listener"></div>
- <div id="log"></div>
</body>
</html>
diff --git a/native_client_sdk/src/examples/websocket/websocket.cc b/native_client_sdk/src/examples/api/websocket/websocket.cc
index fc1f0ed73d..bc5949b794 100644
--- a/native_client_sdk/src/examples/websocket/websocket.cc
+++ b/native_client_sdk/src/examples/api/websocket/websocket.cc
@@ -12,8 +12,7 @@
class WebSocketInstance : public pp::Instance {
public:
explicit WebSocketInstance(PP_Instance instance)
- : pp::Instance(instance),
- websocket_(NULL) {}
+ : pp::Instance(instance), websocket_(NULL) {}
virtual ~WebSocketInstance() {}
virtual void HandleMessage(const pp::Var& var_message);
@@ -77,7 +76,7 @@ void WebSocketInstance::Open(const std::string& url) {
if (!websocket_)
return;
websocket_->Connect(pp::Var(url), NULL, 0, callback);
- PostMessage(pp::Var("log:connecting..."));
+ PostMessage(pp::Var("connecting..."));
}
void WebSocketInstance::Close() {
@@ -92,7 +91,7 @@ void WebSocketInstance::Send(const std::string& message) {
if (!IsConnected())
return;
websocket_->SendMessage(pp::Var(message));
- PostMessage(pp::Var(std::string("log:send: ") + message));
+ PostMessage(pp::Var(std::string("send: ") + message));
}
void WebSocketInstance::Receive() {
@@ -104,26 +103,23 @@ void WebSocketInstance::Receive() {
void WebSocketInstance::OnConnectCompletion(int32_t result) {
if (result != PP_OK) {
- PostMessage(pp::Var("alert:connection failed"));
+ PostMessage(pp::Var("connection failed"));
return;
}
- PostMessage(pp::Var("log:connected"));
+ PostMessage(pp::Var("connected"));
Receive();
}
void WebSocketInstance::OnCloseCompletion(int32_t result) {
- PostMessage(pp::Var(PP_OK == result ?
- "log:closed" :
- "alert:abnormally closed"));
+ PostMessage(pp::Var(PP_OK == result ? "closed" : "abnormally closed"));
}
void WebSocketInstance::OnReceiveCompletion(int32_t result) {
if (result == PP_OK) {
if (receive_var_.is_array_buffer())
- PostMessage(pp::Var("log: receive: binary data"));
+ PostMessage(pp::Var("receive: binary data"));
else
- PostMessage(pp::Var(std::string("log:receive: ") +
- receive_var_.AsString()));
+ PostMessage(pp::Var(std::string("receive: ") + receive_var_.AsString()));
}
Receive();
}
@@ -158,11 +154,8 @@ class WebSocketModule : public pp::Module {
}
};
-
// Implement the required pp::CreateModule function that creates our specific
// kind of Module.
namespace pp {
-Module* CreateModule() {
- return new WebSocketModule();
-}
+Module* CreateModule() { return new WebSocketModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/common.js b/native_client_sdk/src/examples/common.js
index bd0a6b22a3..79988ed783 100644
--- a/native_client_sdk/src/examples/common.js
+++ b/native_client_sdk/src/examples/common.js
@@ -27,6 +27,7 @@ var common = (function () {
moduleEl.setAttribute('id', 'nacl_module');
moduleEl.setAttribute('width', width);
moduleEl.setAttribute('height',height);
+ moduleEl.setAttribute('path', path);
moduleEl.setAttribute('src', path + '/' + name + '.nmf');
// Add any optional arguments
@@ -80,16 +81,29 @@ var common = (function () {
var listenerDiv = document.getElementById('listener');
listenerDiv.addEventListener('load', moduleDidLoad, true);
listenerDiv.addEventListener('message', handleMessage, true);
-
+ listenerDiv.addEventListener('crash', handleCrash, true);
if (typeof window.attachListeners !== 'undefined') {
window.attachListeners();
}
}
+
+ /**
+ * Called when the Browser can not communicate with the Module
+ *
+ * This event listener is registered in attachDefaultListeners above.
+ */
+ function handleCrash(event) {
+ updateStatus('CRASHED')
+ if (typeof window.handleCrash !== 'undefined') {
+ window.handleCrash(common.naclModule.lastError);
+ }
+ }
+
/**
* Called when the NaCl module is loaded.
*
- * This event listener is registered in createNaClModule above.
+ * This event listener is registered in attachDefaultListeners above.
*/
function moduleDidLoad() {
common.naclModule = document.getElementById('nacl_module');
@@ -126,16 +140,25 @@ var common = (function () {
return s.lastIndexOf(prefix, 0) === 0;
}
+ /** Maximum length of logMessageArray. */
+ var kMaxLogMessageLength = 20;
+
+ /** An array of messages to display in the element with id "log". */
+ var logMessageArray = [];
+
/**
- * Add a message to an element with id "log", separated by a <br> element.
+ * Add a message to an element with id "log".
*
* This function is used by the default "log:" message handler.
*
* @param {string} message The message to log.
*/
function logMessage(message) {
- var logEl = document.getElementById('log');
- logEl.innerHTML += message + '<br>';
+ logMessageArray.push(message);
+ if (logMessageArray.length > kMaxLogMessageLength)
+ logMessageArray.shift();
+
+ document.getElementById('log').textContent = logMessageArray.join('');
console.log(message)
}
@@ -236,6 +259,7 @@ var common = (function () {
domContentLoaded: domContentLoaded,
createNaClModule: createNaClModule,
hideModule: hideModule,
+ logMessage: logMessage,
updateStatus: updateStatus
};
diff --git a/native_client_sdk/src/examples/debugging/example.dsc b/native_client_sdk/src/examples/debugging/example.dsc
deleted file mode 100644
index cb6abddd93..0000000000
--- a/native_client_sdk/src/examples/debugging/example.dsc
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- 'TOOLS': ['newlib'],
- 'SEARCH': [
- '.',
- '..',
- '../../tools',
- ],
- 'TARGETS': [
- {
- 'NAME' : 'debugging',
- 'TYPE' : 'main',
- 'SOURCES' : [
- 'hello_world.c',
- 'string_stream.c',
- 'string_stream.h',
- 'untrusted_crash_dump.c',
- 'untrusted_crash_dump.h'
- ],
- 'CCFLAGS': ['-fno-omit-frame-pointer'],
- 'LIBS' : ['ppapi', 'pthread']
- }
- ],
-
- # The debugging example needs to use a different HTTP server to handle POST
- # messages from the NaCl module.
- 'PRE': """
-CHROME_ARGS+=--no-sandbox
-CHROME_ENV:=NACL_DANGEROUS_ENABLE_FILE_ACCESS=1
-CHROME_ENV+=NACL_SECURITY_DISABLE=1
-CHROME_ENV+=NACL_UNTRUSTED_EXCEPTION_HANDLING=1
-""",
-
- 'DATA': [
- 'example.js',
- 'handler.py'
- ],
- 'DEST': 'examples',
- 'NAME': 'debugging',
- 'TITLE': 'Debugging',
- 'DESC': """
-Debugging example shows how to use developer only features to enable
-catching an exception, and then using that to create a stacktrace.""",
- 'FOCUS': 'Debugging, Stacktraces.',
- 'GROUP': 'Concepts'
-}
-
diff --git a/native_client_sdk/src/examples/debugging/example.js b/native_client_sdk/src/examples/debugging/example.js
deleted file mode 100644
index 7fdc4bab58..0000000000
--- a/native_client_sdk/src/examples/debugging/example.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var lastModuleError = '';
-var crashed = false;
-
-function domContentLoaded(name, tc, config, width, height) {
- common.createNaClModule(name, tc, config, width, height);
- common.attachDefaultListeners();
-
- updateStatus('Page Loaded');
- heartBeat();
-}
-
-// Indicate success when the NaCl module has loaded.
-function moduleDidLoad() {
- updateStatus('LOADED');
- setTimeout(boom, 4000);
-}
-
-// Handle a message coming from the NaCl module.
-function handleMessage(message_event) {
- msg_type = message_event.data.substring(0, 4);
- msg_data = message_event.data.substring(5, message_event.data.length);
- if (msg_type == 'POP:') {
- alert(message_event.data);
- return;
- }
- if (msg_type == 'LOG:') {
- document.getElementById('log').value += msg_data + '\n';
- return;
- }
- if (msg_type == 'TRC:') {
- crashed = true;
- updateStatus('Crash Reported');
- xmlhttp = new XMLHttpRequest();
- xmlhttp.open('POST', common.naclModule.src, false);
- xmlhttp.send(msg_data);
- document.getElementById('trace').value = xmlhttp.responseText + '\n';
- return;
- }
-}
-
-function updateStatus(message) {
- common.updateStatus(message);
-
- if (message)
- document.getElementById('log').value += message + '\n'
-}
-
-function boom() {
- if (!crashed) {
- updateStatus('Send BOOM');
- common.naclModule.postMessage('BOOM');
- setTimeout(boom, 1000);
- }
-}
-
-function heartBeat() {
- if (common.naclModule && common.naclModule.lastError) {
- if (lastModuleError != common.naclModule.lastError) {
- lastModuleError = common.naclModule.lastError;
- updateStatus('Missed heartbeat: ' + common.naclModule.lastError);
- crashed = true;
- }
- } else {
- setTimeout(heartBeat, 1000);
- }
-}
diff --git a/native_client_sdk/src/examples/debugging/handler.py b/native_client_sdk/src/examples/debugging/handler.py
deleted file mode 100644
index 4593223a22..0000000000
--- a/native_client_sdk/src/examples/debugging/handler.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# 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.
-
-"""Wrap the standard run.py to handle additional POST messages needed for
-debugging.
-
-See <NACL_SDK_ROOT>/tools/run.py for more information.
-"""
-
-import os
-import SimpleHTTPServer # pylint: disable=W0611
-import sys
-import urlparse
-
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-NACL_SDK_ROOT = os.path.dirname(os.path.dirname(SCRIPT_DIR))
-TOOLS_DIR = os.path.join(NACL_SDK_ROOT, 'tools')
-
-sys.path.append(TOOLS_DIR)
-import decode_dump
-import getos
-
-
-last_nexe = None
-last_nmf = None
-
-
-# "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not
-# exist in |pair|, then the entire |pair| is the key and the value is set to an
-# empty string.
-def KeyValuePair(pair, sep='='):
- if sep in pair:
- return pair.split(sep)
- else:
- return [pair, '']
-
-
-# $(NACL_SDK_ROOT)/tools/run.py looks for a file named handler.py in any
-# directory serving a file, then uses the class name HTTPRequestHandlerDelegate
-# to handle GET and POST requests for that directory.
-class HTTPRequestHandlerDelegate(object):
- def send_head(self, handler):
- """Common code for GET and HEAD commands.
-
- This sends the response code and MIME headers.
-
- Return value is either a file object (which has to be copied
- to the outputfile by the caller unless the command was HEAD,
- and must be closed by the caller under all circumstances), or
- None, in which case the caller has nothing further to do.
-
- """
- path = handler.translate_path(handler.path)
- f = None
- if os.path.isdir(path):
- if not handler.path.endswith('/'):
- # redirect browser - doing basically what apache does
- handler.send_response(301)
- handler.send_header("Location", handler.path + "/")
- handler.end_headers()
- return None
- for index in "index.html", "index.htm":
- index = os.path.join(path, index)
- if os.path.exists(index):
- path = index
- break
- else:
- return handler.list_directory(path)
- ctype = handler.guess_type(path)
- try:
- # Always read in binary mode. Opening files in text mode may cause
- # newline translations, making the actual size of the content
- # transmitted *less* than the content-length!
- f = open(path, 'rb')
- except IOError:
- handler.send_error(404, "File not found")
- return None
- handler.send_response(200)
- handler.send_header("Content-type", ctype)
- fs = os.fstat(f.fileno())
- handler.send_header("Content-Length", str(fs[6]))
- handler.send_header("Last-Modified", handler.date_time_string(fs.st_mtime))
- handler.send_header('Cache-Control','no-cache, must-revalidate')
- handler.send_header('Expires','-1')
- handler.end_headers()
- return f
-
- def do_GET(self, handler):
- global last_nexe, last_nmf
- (_, _, path, query, _) = urlparse.urlsplit(handler.path)
- url_params = dict([KeyValuePair(key_value)
- for key_value in query.split('&')])
- if 'quit' in url_params and '1' in url_params['quit']:
- handler.send_response(200, 'OK')
- handler.send_header('Content-type', 'text/html')
- handler.send_header('Content-length', '0')
- handler.end_headers()
- handler.server.shutdown()
- return
-
- if path.endswith('.nexe'):
- last_nexe = path
- if path.endswith('.nmf'):
- last_nmf = path
-
- handler.base_do_GET()
-
- def do_POST(self, handler):
- if 'Content-Length' in handler.headers:
- if not NACL_SDK_ROOT:
- handler.wfile('Could not find NACL_SDK_ROOT to decode trace.')
- return
- data = handler.rfile.read(int(handler.headers['Content-Length']))
- nexe = '.' + last_nexe
- nmf = '.' + last_nmf
- addr = os.path.join(NACL_SDK_ROOT, 'toolchain',
- getos.GetPlatform() + '_x86_newlib',
- 'bin', 'x86_64-nacl-addr2line')
- decoder = decode_dump.CoreDecoder(nexe, nmf, addr, None, None)
- info = decoder.Decode(data)
- trace = decoder.StackTrace(info)
- decoder.PrintTrace(trace, sys.stdout)
- decoder.PrintTrace(trace, handler.wfile)
diff --git a/native_client_sdk/src/examples/debugging/index.html b/native_client_sdk/src/examples/debugging/index.html
deleted file mode 100644
index d5d518bcb5..0000000000
--- a/native_client_sdk/src/examples/debugging/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html>
- <!--
- Copyright (c) 2012 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
- -->
-<head>
- <meta http-equiv="Pragma" content="no-cache" />
- <meta http-equiv="Expires" content="-1" />
- <title>Logging and Stack Trace</title>
- <script type="text/javascript" src="common.js"></script>
- <script type="text/javascript" src="example.js"></script>
-</head>
-<body data-width="100" data-height="100" data-custom-load="true" {{attrs}}>
- <h1>Native Client Debugging Example: Generating a Stack Trace.</h1>
- <h2>How the example works</h2>
- <p>This example shows how to trap an untrusted exception (such as a illegal
- memory reference in the NEXE). This debugging technique can only be used
- for development since it requires several command-line switches, and
- environment variables. The test works by loading the module and communicating
- with it through PostMessage. Messages from the module are sent to the Status
- line and/or the Log window in the page. Four seconds after the module is
- loaded, the JavaScript on this page sends a 'BOOM' message to the module that
- causes the module to dereference an illegal location in memory.</p>
-
- <p>If your setup is correct (you launched Chrome with the appropriate
- command-line arguments and environment variables), the Log window below
- should show that the crash dump facilities are turned on. When the crash data
- arrives from the module, the data is forwarded to the HTTP server, which
- drives a decoder and sends back a stack trace to the web page.</p>
-
- <p>If setup incorrectly, the NaCl module may or may not load. If the module
- loads, it sends a "LOADED" message to the log and crash after four seconds.
- Since the stack trace facilities are not enables, the script will determine
- that the module has crashed by detecting a missed heartbeat which the
- application would normally send.
- </p>
-
- <h2>Running the example</h2>
- In a terminal window, to automatically start Chrome with the correct
- environment variables and command-line switches:
- <ul>
- <li>Set the CHROME_PATH environment variable to the fully qualified path of
- your Chrome executable.</li>
- <li>From the debugging directory type: <b>make RUN</b></li>
- </ul>
-
- <div id="listener"></div>
- <hr>
- <h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <h2>Log</h2>
- <textarea id="log" rows="10" cols="130" readonly="readonly"></textarea>
- <br>
- <h2>Stack Trace</h2>
- <textarea id="trace" rows="10" cols="130" readonly="readonly"></textarea>
-</body>
-</html>
diff --git a/native_client_sdk/src/examples/debugging/string_stream.h b/native_client_sdk/src/examples/debugging/string_stream.h
deleted file mode 100644
index a9855165f5..0000000000
--- a/native_client_sdk/src/examples/debugging/string_stream.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef STRING_STREAM_H
-#define STRING_STREAM_H
-
-/*
- * Support for a stream stream in 'C', which is appened to via an sprintf-like
- * function.
- */
-
-#include <stdarg.h>
-#include <stdint.h>
-
-typedef struct {
- char *data;
- size_t length;
-} sstream_t;
-
-void ssinit(sstream_t *stream);
-void ssfree(sstream_t *stream);
-
-/* Returns the number of bytes added to the stream. */
-int ssvprintf(sstream_t *sstream, const char *format, va_list args);
-int ssprintf(sstream_t *sstream, const char *format, ...);
-
-
-#endif
diff --git a/native_client_sdk/src/examples/debugging/untrusted_crash_dump.c b/native_client_sdk/src/examples/debugging/untrusted_crash_dump.c
deleted file mode 100644
index 959ad9e6fe..0000000000
--- a/native_client_sdk/src/examples/debugging/untrusted_crash_dump.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2012 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include <assert.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-
-#ifdef __GLIBC__
-#include <elf.h>
-#include <link.h>
-#endif /* __GLIBC__ */
-
-#include "untrusted_crash_dump.h"
-#include "string_stream.h"
-#include "irt.h"
-
-struct NaClExceptionContext {
- uint32_t prog_ctr;
- uint32_t stack_ptr;
- uint32_t frame_ptr;
- /*
- * Pad this up to an even multiple of 8 bytes so this struct will add
- * a predictable amount of space to the various ExceptionFrame structures
- * used on each platform. This allows us to verify stack layout with dead
- * reckoning, without access to the ExceptionFrame structure used to set up
- * the call stack.
- */
- uint32_t pad;
-};
-
-#define CRASH_PAGE_CHUNK (64 * 1024)
-#define CRASH_STACK_SIZE (CRASH_PAGE_CHUNK * 4)
-#define CRASH_STACK_GUARD_SIZE CRASH_PAGE_CHUNK
-#define CRASH_STACK_COMPLETE_SIZE (CRASH_STACK_GUARD_SIZE + CRASH_STACK_SIZE)
-
-
-static pthread_key_t g_CrashStackKey;
-static struct nacl_irt_dev_exception_handling g_ExceptionHandling;
-static int g_ExceptionHandlingEnabled = 0;
-
-
-#ifdef __GLIBC__
-
-struct ProgramTableData {
- sstream_t *core;
- int first;
-};
-
-static void WriteJsonString(const char *str, sstream_t *core) {
- char ch;
-
- ssprintf(core, "\"");
- for (;;) {
- ch = *str++;
- if (ch == '\0') {
- break;
- } else if (ch == '"') {
- ssprintf(core, "\\\"");
- } else if (ch == '\\') {
- ssprintf(core, "\\\\");
- } else if (ch < 32 || ch > 126) {
- ssprintf(core, "\\x%02x", (uint8_t)ch);
- } else {
- ssprintf(core, "%c", ch);
- }
- }
- ssprintf(core, "\"");
-}
-
-static int PrintSegmentsOne(
- struct dl_phdr_info *info, size_t size, void *data) {
- int i;
- struct ProgramTableData *ptd = (struct ProgramTableData*) data;
-
- if (ptd->first) {
- ptd->first = 0;
- } else {
- fprintf(ptd->core, ",\n");
- }
- fprintf(ptd->core, "{\n");
- fprintf(ptd->core, "\"dlpi_name\": ");
- WriteJsonString(info->dlpi_name, ptd->core);
- fprintf(ptd->core, ",\n");
- fprintf(ptd->core, "\"dlpi_addr\": %u,\n",
- (uintptr_t) info->dlpi_addr);
- fprintf(ptd->core, "\"dlpi_phdr\": [\n");
- for (i = 0; i < info->dlpi_phnum; i++) {
- /* Skip non-LOAD type segments. */
- if (info->dlpi_phdr[i].p_type != PT_LOAD) {
- continue;
- }
- if (i != 0) {
- fprintf(ptd->core, ",\n");
- }
- fprintf(ptd->core, "{\n");
- fprintf(ptd->core, "\"p_vaddr\": %u,\n",
- (uintptr_t) info->dlpi_phdr[i].p_vaddr);
- fprintf(ptd->core, "\"p_memsz\": %u\n",
- (uintptr_t) info->dlpi_phdr[i].p_memsz);
- fprintf(ptd->core, "}\n");
- }
- fprintf(ptd->core, "]\n");
- fprintf(ptd->core, "}\n");
- return 0;
-}
-
-static void PrintSegments(sstream_t *core) {
- struct ProgramTableData data;
- data.core = core;
- data.first = 1;
- dl_iterate_phdr(PrintSegmentsOne, &data);
-}
-
-#else /* __GLIBC__ */
-
-static void PrintSegments(sstream_t *core) {
-}
-
-#endif /* __GLIBC__ */
-
-
-void PostMessage(const char *str);
-
-
-uintptr_t SafeRead(uintptr_t a) {
- /* TODO(bradnelson): use exception handling to recover from reads. */
- return *(uintptr_t*)a;
-}
-
-static void StackWalk(sstream_t *core, struct NaClExceptionContext *context) {
- uintptr_t next;
- uintptr_t i;
- int first = 1;
- uintptr_t prog_ctr = context->prog_ctr;
- uintptr_t frame_ptr = context->frame_ptr;
- uintptr_t args_start;
-
- ssprintf(core, "\"frames\": [\n");
- for (;;) {
- next = SafeRead(frame_ptr);
- if (next <= frame_ptr || next == 0) {
- break;
- }
- if (first) {
- first = 0;
- } else {
- ssprintf(core, ",");
- }
- ssprintf(core, "{\n");
- ssprintf(core, "\"frame_ptr\": %u,\n", frame_ptr);
- ssprintf(core, "\"prog_ctr\": %u,\n", prog_ctr);
- ssprintf(core, "\"data\": [\n");
-#if defined(__x86_64__)
- args_start = frame_ptr + 8;
-#else
- args_start = frame_ptr + 16;
-#endif
- for (i = args_start; i < next && i - args_start < 100; i += 4) {
- if (i != args_start) {
- ssprintf(core, ",");
- }
- ssprintf(core, "%u\n", SafeRead(i));
- }
- ssprintf(core, "]\n");
- ssprintf(core, "}\n");
-
- if (next - frame_ptr > 10000) break;
-#if defined(__x86_64__)
- prog_ctr = SafeRead(frame_ptr + 8);
-#else
- prog_ctr = SafeRead(frame_ptr + 4);
-#endif
- frame_ptr = next;
- }
-
- ssprintf(core, "]\n");
-}
-
-void CrashHandler(struct NaClExceptionContext *context) {
- sstream_t ss;
- FILE* handle = fopen("naclcorejson", "wb");
-
- ssinit(&ss);
- ssprintf(&ss, "TRC: {\n");
-
- ssprintf(&ss, "\"segments\": [");
- PrintSegments(&ss);
- ssprintf(&ss, "],\n");
-
- ssprintf(&ss, "\"handler\": {\n");
- ssprintf(&ss, "\"prog_ctr\": %u,\n", context->prog_ctr);
- ssprintf(&ss, "\"stack_ptr\": %u,\n", context->stack_ptr);
- ssprintf(&ss, "\"frame_ptr\": %u\n", context->frame_ptr);
- ssprintf(&ss, "},\n");
-
- StackWalk(&ss, context);
-
- ssprintf(&ss, "}\n");
-
- if (handle != NULL) {
- fprintf(handle, "%s", &ss.data[5]);
- fclose(handle);
- }
-
- PostMessage(ss.data);
-
- while(1);
-}
-
-void NaClCrashDumpThreadDestructor(void *arg) {
- munmap(arg, CRASH_STACK_COMPLETE_SIZE);
-}
-
-int NaClCrashDumpInit(void) {
- int result;
-
- assert(g_ExceptionHandlingEnabled == 0);
- if (nacl_interface_query(NACL_IRT_DEV_EXCEPTION_HANDLING_v0_1,
- &g_ExceptionHandling,
- sizeof(g_ExceptionHandling)) == 0) {
- fprintf(stderr, "ERROR: failed nacl_interface_query\n");
- return 0;
- }
- result = pthread_key_create(&g_CrashStackKey, NaClCrashDumpThreadDestructor);
- assert(result == 0);
- if (g_ExceptionHandling.exception_handler(CrashHandler, NULL) != 0) {
- fprintf(stderr, "ERROR: failed exception_handler\n");
- return 0;
- }
- g_ExceptionHandlingEnabled = 1;
- if (!NaClCrashDumpInitThread()) {
- g_ExceptionHandlingEnabled = 0;
- fprintf(stderr, "ERROR: failed InitThread\n");
- return 0;
- }
- return 1;
-}
-
-int NaClCrashDumpInitThread(void) {
- void *stack;
- void *guard;
- int result;
-
- if (!g_ExceptionHandlingEnabled) {
- return 0;
- }
- /*
- * NOTE: Setting up a per thread stack is only particularly interesting
- * for stack overflow.
- */
- stack = mmap(NULL, CRASH_STACK_COMPLETE_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- assert(stack != MAP_FAILED);
- guard = mmap(stack, CRASH_STACK_GUARD_SIZE,
- PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- assert(guard == stack);
- pthread_setspecific(g_CrashStackKey, stack);
- result = g_ExceptionHandling.exception_stack(
- stack, CRASH_STACK_COMPLETE_SIZE);
- return result == 0;
-}
diff --git a/native_client_sdk/src/examples/debugging/untrusted_crash_dump.h b/native_client_sdk/src/examples/debugging/untrusted_crash_dump.h
deleted file mode 100644
index 8cd973a5ad..0000000000
--- a/native_client_sdk/src/examples/debugging/untrusted_crash_dump.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2012 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Untrusted crash dumper.
- */
-
-#ifndef NATIVE_CLIENT_SRC_UNTRUSTED_CRASH_DUMP_UNTRUSTED_CRASH_DUMP_H__
-#define NATIVE_CLIENT_SRC_UNTRUSTED_CRASH_DUMP_UNTRUSTED_CRASH_DUMP_H__ 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These return non-zero on success. */
-int NaClCrashDumpInit(void);
-int NaClCrashDumpInitThread(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* NATIVE_CLIENT_SRC_UNTRUSTED_CRASH_DUMP_UNTRUSTED_CRASH_DUMP_H__ */
diff --git a/native_client_sdk/src/examples/demo/nacl_io/example.dsc b/native_client_sdk/src/examples/demo/nacl_io/example.dsc
new file mode 100644
index 0000000000..f390187e9f
--- /dev/null
+++ b/native_client_sdk/src/examples/demo/nacl_io/example.dsc
@@ -0,0 +1,25 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'nacl_io',
+ 'TYPE' : 'main',
+ 'SOURCES' : [
+ 'handlers.c',
+ 'handlers.h',
+ 'hello_nacl_io.c',
+ 'hello_nacl_io.h',
+ 'queue.c',
+ 'queue.h',
+ ],
+ 'LIBS': ['ppapi', 'pthread', 'nacl_io']
+ }
+ ],
+ 'DATA': [
+ 'example.js'
+ ],
+ 'DEST': 'examples/demo',
+ 'NAME': 'nacl_io',
+ 'TITLE': 'Nacl IO Demo',
+ 'GROUP': 'Demo'
+}
diff --git a/native_client_sdk/src/examples/hello_nacl_io/example.js b/native_client_sdk/src/examples/demo/nacl_io/example.js
index c355b4d08a..5221e5d013 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/example.js
+++ b/native_client_sdk/src/examples/demo/nacl_io/example.js
@@ -30,6 +30,7 @@ function attachListeners() {
document.getElementById('freadExecute').addEventListener('click', fread);
document.getElementById('fwriteExecute').addEventListener('click', fwrite);
document.getElementById('fseekExecute').addEventListener('click', fseek);
+ document.getElementById('statExecute').addEventListener('click', stat);
}
function onRadioClicked(e) {
@@ -74,11 +75,11 @@ function fopen(e) {
nacl_module.postMessage(makeCall('fopen', filename, access));
}
-function fopen_result(filename, filehandle) {
+function fopenResult(filename, filehandle) {
filehandle_map[filehandle] = filename;
addFilenameToSelectElements(filehandle, filename)
- logMessage('File ' + filename + ' opened successfully.');
+ common.logMessage('File ' + filename + ' opened successfully.\n');
}
function fclose(e) {
@@ -86,10 +87,10 @@ function fclose(e) {
nacl_module.postMessage(makeCall('fclose', filehandle));
}
-function fclose_result(filehandle) {
+function fcloseResult(filehandle) {
var filename = filehandle_map[filehandle];
removeFilenameFromSelectElements(filehandle, filename);
- logMessage('File ' + filename + ' closed successfully.');
+ common.logMessage('File ' + filename + ' closed successfully.\n');
}
function fread(e) {
@@ -98,9 +99,9 @@ function fread(e) {
nacl_module.postMessage(makeCall('fread', filehandle, numBytes));
}
-function fread_result(filehandle, data) {
+function freadResult(filehandle, data) {
var filename = filehandle_map[filehandle];
- logMessage('Read "' + data + '" from file ' + filename + '.');
+ common.logMessage('Read "' + data + '" from file ' + filename + '.\n');
}
function fwrite(e) {
@@ -109,9 +110,10 @@ function fwrite(e) {
nacl_module.postMessage(makeCall('fwrite', filehandle, data));
}
-function fwrite_result(filehandle, bytes_written) {
+function fwriteResult(filehandle, bytes_written) {
var filename = filehandle_map[filehandle];
- logMessage('Wrote ' + bytes_written + ' bytes to file ' + filename + '.');
+ common.logMessage('Wrote ' + bytes_written + ' bytes to file ' + filename +
+ '.\n');
}
function fseek(e) {
@@ -121,9 +123,19 @@ function fseek(e) {
nacl_module.postMessage(makeCall('fseek', filehandle, offset, whence));
}
-function fseek_result(filehandle, filepos) {
+function fseekResult(filehandle, filepos) {
var filename = filehandle_map[filehandle];
- logMessage('Seeked to location ' + filepos + ' in file ' + filename + '.');
+ common.logMessage('Seeked to location ' + filepos + ' in file ' + filename +
+ '.\n');
+}
+
+function stat(e) {
+ var filename = document.getElementById('statFilename').value;
+ nacl_module.postMessage(makeCall('stat', filename));
+}
+
+function statResult(filename, size) {
+ common.logMessage('File ' + filename + ' has size ' + size + '.\n');
}
/**
@@ -138,19 +150,6 @@ function startsWith(s, prefix) {
return s.lastIndexOf(prefix, 0) === 0;
}
-function logMessage(msg) {
- var logEl = document.getElementById('log');
-
- // Perform some basic escaping.
- msg = msg.replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&apos;');
-
- logEl.innerHTML += msg + '<br>';
-}
-
function makeCall(func) {
var message = func;
for (var i = 1; i < arguments.length; ++i) {
@@ -164,19 +163,19 @@ function makeCall(func) {
function handleMessage(message_event) {
var msg = message_event.data;
if (startsWith(msg, 'Error:')) {
- logMessage(msg);
+ common.logMessage(msg + '\n');
} else {
// Result from a function call.
var params = msg.split('\1');
- var func_name = params[0];
- var func_result_name = func_name + '_result';
- var result_func = window[func_result_name];
+ var funcName = params[0];
+ var funcResultName = funcName + 'Result';
+ var resultFunc = window[funcResultName];
- if (!result_func) {
- logMessage('Error: Bad message received from NaCl module.');
+ if (!resultFunc) {
+ common.logMessage('Error: Bad message received from NaCl module.\n');
return;
}
- result_func.apply(null, params.slice(1));
+ resultFunc.apply(null, params.slice(1));
}
}
diff --git a/native_client_sdk/src/examples/hello_nacl_io/handlers.c b/native_client_sdk/src/examples/demo/nacl_io/handlers.c
index 062a41fb34..46d8594b9e 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/handlers.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/handlers.c
@@ -6,9 +6,11 @@
#include "handlers.h"
#include <assert.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include "hello_nacl_io.h"
@@ -19,7 +21,6 @@
* File. */
static FILE* g_OpenFiles[MAX_OPEN_FILES];
-
/**
* Add the file to the g_OpenFiles map.
* @param[in] file The file to add to g_OpenFiles.
@@ -75,7 +76,6 @@ static FILE* GetFileFromIndexString(const char* s, int* file_index) {
return GetFileFromMap(result);
}
-
/**
* Handle a call to fopen() made by JavaScript.
*
@@ -157,15 +157,21 @@ int HandleFwrite(int num_params, char** params, char** output) {
data_len = strlen(data);
if (!file) {
- *output = PrintfToNewString("Error: Unknown file handle %s.",
- file_index_string);
+ *output =
+ PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
return 2;
}
bytes_written = fwrite(data, 1, data_len, file);
- *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string,
- bytes_written);
+ if (ferror(file)) {
+ *output = PrintfToNewString(
+ "Error: Wrote %d bytes, but ferror() returns true.", bytes_written);
+ return 3;
+ }
+
+ *output =
+ PrintfToNewString("fwrite\1%s\1%d", file_index_string, bytes_written);
return 0;
}
@@ -202,8 +208,8 @@ int HandleFread(int num_params, char** params, char** output) {
data_len = strtol(params[1], NULL, 10);
if (!file) {
- *output = PrintfToNewString("Error: Unknown file handle %s.",
- file_index_string);
+ *output =
+ PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
return 2;
}
@@ -211,6 +217,12 @@ int HandleFread(int num_params, char** params, char** output) {
bytes_read = fread(buffer, 1, data_len, file);
buffer[bytes_read] = 0;
+ if (ferror(file)) {
+ *output = PrintfToNewString(
+ "Error: Read %d bytes, but ferror() returns true.", bytes_read);
+ return 3;
+ }
+
*output = PrintfToNewString("fread\1%s\1%s", file_index_string, buffer);
free(buffer);
return 0;
@@ -254,8 +266,8 @@ int HandleFseek(int num_params, char** params, char** output) {
whence = strtol(params[2], NULL, 10);
if (!file) {
- *output = PrintfToNewString("Error: Unknown file handle %s.",
- file_index_string);
+ *output =
+ PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
return 2;
}
@@ -304,8 +316,8 @@ int HandleFclose(int num_params, char** params, char** output) {
file_index_string = params[0];
file = GetFileFromIndexString(file_index_string, &file_index);
if (!file) {
- *output = PrintfToNewString("Error: Unknown file handle %s.",
- file_index_string);
+ *output =
+ PrintfToNewString("Error: Unknown file handle %s.", file_index_string);
return 2;
}
@@ -320,3 +332,43 @@ int HandleFclose(int num_params, char** params, char** output) {
*output = PrintfToNewString("fclose\1%s", file_index_string);
return 0;
}
+
+/**
+ * Handle a call to stat() made by JavaScript.
+ *
+ * stat expects 1 parameter:
+ * 0: The name of the file
+ * on success, stat returns a result in |output| separated by \1:
+ * 0: "stat"
+ * 1: the file name
+ * 2: the size of the file
+ * on failure, stat returns an error string in |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. */
+int HandleStat(int num_params, char** params, char** output) {
+ FILE* file;
+ int file_index;
+ const char* filename;
+ const char* mode;
+
+ if (num_params != 1) {
+ *output = PrintfToNewString("Error: stat takes 1 parameter.");
+ return 1;
+ }
+
+ filename = params[0];
+
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ int result = stat(filename, &buf);
+ if (result == -1) {
+ *output = PrintfToNewString("Error: stat returned error %d.", errno);
+ return 2;
+ }
+
+ *output = PrintfToNewString("stat\1%s\1%d", filename, buf.st_size);
+ return 0;
+}
diff --git a/native_client_sdk/src/examples/hello_nacl_io/handlers.h b/native_client_sdk/src/examples/demo/nacl_io/handlers.h
index 9510dc77f2..d1cd37b05c 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/handlers.h
+++ b/native_client_sdk/src/examples/demo/nacl_io/handlers.h
@@ -15,5 +15,6 @@ int HandleFwrite(int num_params, char** params, char** output);
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);
-#endif /* HANDLERS_H_ */
+#endif /* HANDLERS_H_ */
diff --git a/native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.c b/native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.c
index fde9c1e761..b56e1c67de 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.c
@@ -36,7 +36,6 @@ typedef struct {
HandleFunc function;
} FuncNameMapping;
-
static PP_Instance g_instance = 0;
static PPB_GetInterface get_browser_interface = NULL;
static PPB_Messaging* ppb_messaging_interface = NULL;
@@ -48,6 +47,7 @@ static FuncNameMapping g_function_map[] = {
{ "fread", HandleFread },
{ "fseek", HandleFseek },
{ "fclose", HandleFclose },
+ { "stat", HandleStat },
{ NULL, NULL },
};
@@ -78,7 +78,7 @@ char* VprintfToNewString(const char* format, va_list args) {
va_copy(args_copy, args);
length = vsnprintf(NULL, 0, format, args);
- buffer = (char*)malloc(length + 1); /* +1 for NULL-terminator. */
+ buffer = (char*)malloc(length + 1); /* +1 for NULL-terminator. */
result = vsnprintf(&buffer[0], length + 1, format, args_copy);
assert(result == length);
return buffer;
@@ -180,7 +180,7 @@ static size_t ParseMessage(char* message,
return num_params;
}
- *separator = 0; /* NULL-terminate function. */
+ *separator = 0; /* NULL-terminate function. */
while (separator && num_params < max_params) {
param_start = separator + 1;
@@ -237,13 +237,15 @@ 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: Function \"%s\" returned error %d. "
+ "Additional output: %s",
+ function_name,
+ result,
+ output);
free(output);
} else {
- var = PrintfToVar("Error: Function \"%s\" returned error %d.",
- function_name, result);
+ var = PrintfToVar(
+ "Error: Function \"%s\" returned error %d.", function_name, result);
}
/* Post the error to JavaScript, so the user can see it. */
@@ -269,26 +271,30 @@ void* HandleMessageThread(void* user_data) {
}
}
-
static PP_Bool Instance_DidCreate(PP_Instance instance,
uint32_t argc,
const char* argn[],
const char* argv[]) {
g_instance = instance;
nacl_io_init_ppapi(instance, get_browser_interface);
- mount(
- "", /* source */
- "/persistent", /* target */
- "html5fs", /* filesystemtype */
- 0, /* mountflags */
- "type=PERSISTENT,expected_size=1048576"); /* data */
-
- mount(
- "", /* source. Use relative URL */
- "/http", /* target */
- "httpfs", /* filesystemtype */
- 0, /* mountflags */
- ""); /* data */
+
+ // By default, nacl_io mounts / to pass through to the original NaCl
+ // filesystem (which doesn't do much). Let's remount it to a memfs
+ // filesystem.
+ umount("/");
+ mount("", "/", "memfs", 0, "");
+
+ mount("", /* source */
+ "/persistent", /* target */
+ "html5fs", /* filesystemtype */
+ 0, /* mountflags */
+ "type=PERSISTENT,expected_size=1048576"); /* data */
+
+ mount("", /* source. Use relative URL */
+ "/http", /* target */
+ "httpfs", /* filesystemtype */
+ 0, /* mountflags */
+ ""); /* data */
pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
InitializeMessageQueue();
@@ -296,17 +302,12 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
return PP_TRUE;
}
-
-static void Instance_DidDestroy(PP_Instance instance) {
-}
+static void Instance_DidDestroy(PP_Instance instance) {}
static void Instance_DidChangeView(PP_Instance instance,
- PP_Resource view_resource) {
-}
+ PP_Resource view_resource) {}
-static void Instance_DidChangeFocus(PP_Instance instance,
- PP_Bool has_focus) {
-}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
@@ -321,8 +322,7 @@ static void Messaging_HandleMessage(PP_Instance instance,
if (!EnqueueMessage(strdup(buffer))) {
struct PP_Var var;
var = PrintfToVar(
- "Warning: dropped message \"%s\" because the queue was full.",
- message);
+ "Warning: dropped message \"%s\" because the queue was full.", message);
ppb_messaging_interface->PostMessage(g_instance, var);
}
}
@@ -336,7 +336,6 @@ PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
return PP_OK;
}
-
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
@@ -356,6 +355,4 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
return NULL;
}
-
-PP_EXPORT void PPP_ShutdownModule() {
-}
+PP_EXPORT void PPP_ShutdownModule() {}
diff --git a/native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.h b/native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.h
index 82bf0568bb..f3bcd101da 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/hello_nacl_io.h
+++ b/native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.h
@@ -15,4 +15,4 @@ char* PrintfToNewString(const char* format, ...);
struct PP_Var PrintfToVar(const char* format, ...);
uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length);
-#endif /* HELLO_NACL_IO_H_ */
+#endif /* HELLO_NACL_IO_H_ */
diff --git a/native_client_sdk/src/examples/hello_nacl_io/index.html b/native_client_sdk/src/examples/demo/nacl_io/index.html
index 8695747116..5871b46004 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/index.html
+++ b/native_client_sdk/src/examples/demo/nacl_io/index.html
@@ -25,7 +25,7 @@ found in the LICENSE file.
directories, the mount determines how those operations should be performed.
</p>
<p>
- This example has three mounts by default.
+ This example has four mounts by default.
<ol>
<li><i>/</i> the root of the filesystem. This is a memory mount, and
is non-persistent.</li>
@@ -44,6 +44,7 @@ found in the LICENSE file.
<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">
@@ -97,9 +98,16 @@ found in the LICENSE file.
<button id="fseekExecute">fseek</button>
</span>
</div>
+ <div class="function" id="stat" hidden>
+ <span>
+ Filename:
+ <input type="text" id="statFilename">
+ <button id="statExecute">stat</button>
+ </span>
+ </div>
+ <pre id="log" style="font-weight: bold"></pre>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
- <div id="log"></div>
</body>
</html>
diff --git a/native_client_sdk/src/examples/hello_nacl_io/queue.c b/native_client_sdk/src/examples/demo/nacl_io/queue.c
index bd0c43868c..ab96440d36 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/queue.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/queue.c
@@ -42,17 +42,13 @@ static int g_queue_size = 0;
*
* NOTE: this function assumes g_queue_mutex lock is held.
* @return non-zero if the queue is empty. */
-static int IsQueueEmpty() {
- return g_queue_size == 0;
-}
+static int IsQueueEmpty() { return g_queue_size == 0; }
/** Return whether the queue is full.
*
* NOTE: this function assumes g_queue_mutex lock is held.
* @return non-zero if the queue is full. */
-static int IsQueueFull() {
- return g_queue_size == MAX_QUEUE_SIZE;
-}
+static int IsQueueFull() { return g_queue_size == MAX_QUEUE_SIZE; }
/** Initialize the message queue. */
void InitializeMessageQueue() {
diff --git a/native_client_sdk/src/examples/hello_nacl_io/queue.h b/native_client_sdk/src/examples/demo/nacl_io/queue.h
index ed267f8666..c7aff063a7 100644
--- a/native_client_sdk/src/examples/hello_nacl_io/queue.h
+++ b/native_client_sdk/src/examples/demo/nacl_io/queue.h
@@ -11,7 +11,7 @@
*
* There are techniques to implement a queue like this without using memory
* barriers or locks on x86, but ARM's memory system is different from x86, so
- * we cannot make the same assuptions about visibility order of writes. Using a
+ * we cannot make the same assumptions about visibility order of writes. Using a
* mutex is slower, but also simpler.
*
* We make the assumption that messages are only enqueued on the main thread
@@ -27,4 +27,4 @@ void InitializeMessageQueue();
int EnqueueMessage(char* message);
char* DequeueMessage();
-#endif /* QUEUE_H_ */
+#endif /* QUEUE_H_ */
diff --git a/native_client_sdk/src/examples/pi_generator/example.dsc b/native_client_sdk/src/examples/demo/pi_generator/example.dsc
index 3910abd66b..6a4b9a1676 100644
--- a/native_client_sdk/src/examples/pi_generator/example.dsc
+++ b/native_client_sdk/src/examples/demo/pi_generator/example.dsc
@@ -15,13 +15,8 @@
'DATA': [
'example.js',
],
- 'DEST': 'examples',
+ 'DEST': 'examples/demo',
'NAME': 'pi_generator',
'TITLE': 'Monte Carlo Estimate for Pi',
- 'DESC': """
-The Pi Generator example demonstrates creating a helper thread that
-estimate pi using the Monte Carlo method while randomly putting 1,000,000,000
-points inside a 2D square that shares two sides with a quarter circle.""",
- 'FOCUS': 'Thread creation, 2D graphics, view change events.',
- 'GROUP': 'Concepts'
+ 'GROUP': 'Demo'
}
diff --git a/native_client_sdk/src/examples/pi_generator/example.js b/native_client_sdk/src/examples/demo/pi_generator/example.js
index dfc77467a4..dfc77467a4 100644
--- a/native_client_sdk/src/examples/pi_generator/example.js
+++ b/native_client_sdk/src/examples/demo/pi_generator/example.js
diff --git a/native_client_sdk/src/examples/pi_generator/index.html b/native_client_sdk/src/examples/demo/pi_generator/index.html
index 7dc1df23e5..7dc1df23e5 100644
--- a/native_client_sdk/src/examples/pi_generator/index.html
+++ b/native_client_sdk/src/examples/demo/pi_generator/index.html
diff --git a/native_client_sdk/src/examples/pi_generator/pi_generator.cc b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
index 27bdbf9e40..bada6105c5 100644
--- a/native_client_sdk/src/examples/pi_generator/pi_generator.cc
+++ b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.cc
@@ -34,7 +34,7 @@ void FlushCallback(void* data, int32_t result) {
namespace pi_generator {
-// A small helper RAII class that implementes a scoped pthread_mutex lock.
+// A small helper RAII class that implements a scoped pthread_mutex lock.
class ScopedMutexLock {
public:
explicit ScopedMutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
@@ -46,9 +46,8 @@ class ScopedMutexLock {
if (mutex_)
pthread_mutex_unlock(mutex_);
}
- bool is_valid() const {
- return mutex_ != NULL;
- }
+ bool is_valid() const { return mutex_ != NULL; }
+
private:
pthread_mutex_t* mutex_; // Weak reference.
};
@@ -64,12 +63,11 @@ class ScopedPixelLock {
image_owner_->UnlockPixels();
}
- uint32_t* pixels() const {
- return pixels_;
- }
+ uint32_t* pixels() const { return pixels_; }
+
private:
PiGenerator* image_owner_; // Weak reference.
- uint32_t* pixels_; // Weak reference.
+ uint32_t* pixels_; // Weak reference.
ScopedPixelLock(); // Not implemented, do not use.
};
@@ -81,7 +79,8 @@ PiGenerator::PiGenerator(PP_Instance instance)
flush_pending_(false),
quit_(false),
thread_create_result_(0),
- pi_(0.0) {
+ pi_(0.0),
+ device_scale_(1.0) {
pthread_mutex_init(&pixel_buffer_mutex_, NULL);
}
@@ -98,13 +97,18 @@ PiGenerator::~PiGenerator() {
}
void PiGenerator::DidChangeView(const pp::View& view) {
- pp::Rect position = view.GetRect();
- if (pixel_buffer_ && position.size() == pixel_buffer_->size())
- return; // Size didn't change, no need to update anything.
-
- // Create a new device context with the new size.
+ pp::Size size = view.GetRect().size();
+ float device_scale = view.GetDeviceScale();
+ size.set_width(static_cast<int>(size.width() * device_scale));
+ size.set_height(static_cast<int>(size.height() * device_scale));
+ if (pixel_buffer_ && size == pixel_buffer_->size() &&
+ device_scale == device_scale_)
+ return; // Size and scale didn't change, no need to update anything.
+
+ // Create a new device context with the new size and scale.
DestroyContext();
- CreateContext(position.size());
+ device_scale_ = device_scale;
+ CreateContext(size, device_scale_);
// Delete the old pixel buffer and create a new one.
ScopedMutexLock scoped_mutex(&pixel_buffer_mutex_);
delete pixel_buffer_;
@@ -118,8 +122,8 @@ void PiGenerator::DidChangeView(const pp::View& view) {
}
bool PiGenerator::Init(uint32_t argc, const char* argn[], const char* argv[]) {
- thread_create_result_ = pthread_create(&compute_pi_thread_, NULL, ComputePi,
- this);
+ thread_create_result_ =
+ pthread_create(&compute_pi_thread_, NULL, ComputePi, this);
return thread_create_result_ == 0;
}
@@ -164,7 +168,7 @@ void PiGenerator::Paint() {
PostMessage(pi_estimate);
}
-void PiGenerator::CreateContext(const pp::Size& size) {
+void PiGenerator::CreateContext(const pp::Size& size, float device_scale) {
ScopedMutexLock scoped_mutex(&pixel_buffer_mutex_);
if (!scoped_mutex.is_valid()) {
return;
@@ -172,6 +176,11 @@ void PiGenerator::CreateContext(const pp::Size& size) {
if (IsContextValid())
return;
graphics_2d_context_ = new pp::Graphics2D(this, size, false);
+ // Scale the contents of the graphics context down by the inverse of the
+ // device scale. This makes each pixel in the context represent a single
+ // physical pixel on the device when running on high-DPI displays.
+ // See pp::Graphics2D::SetScale for more details.
+ graphics_2d_context_->SetScale(1.0 / device_scale);
if (!BindGraphics(*graphics_2d_context_)) {
printf("Couldn't bind the device context\n");
}
diff --git a/native_client_sdk/src/examples/pi_generator/pi_generator.h b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.h
index 556b091358..67b4781391 100644
--- a/native_client_sdk/src/examples/pi_generator/pi_generator.h
+++ b/native_client_sdk/src/examples/demo/pi_generator/pi_generator.h
@@ -56,14 +56,10 @@ class PiGenerator : public pp::Instance {
// method by posting the value back to the browser.
void Paint();
- bool quit() const {
- return quit_;
- }
+ bool quit() const { return quit_; }
// |pi_| is computed in the ComputePi() thread.
- double pi() const {
- return pi_;
- }
+ double pi() const { return pi_; }
int width() const {
return pixel_buffer_ ? pixel_buffer_->size().width() : 0;
@@ -74,16 +70,12 @@ class PiGenerator : public pp::Instance {
// Indicate whether a flush is pending. This can only be called from the
// main thread; it is not thread safe.
- bool flush_pending() const {
- return flush_pending_;
- }
- void set_flush_pending(bool flag) {
- flush_pending_ = flag;
- }
+ bool flush_pending() const { return flush_pending_; }
+ void set_flush_pending(bool flag) { flush_pending_ = flag; }
private:
// Create and initialize the 2D context used for drawing.
- void CreateContext(const pp::Size& size);
+ void CreateContext(const pp::Size& size, float device_scale);
// Destroy the 2D drawing context.
void DestroyContext();
// Push the pixels to the browser, then attempt to flush the 2D context. If
@@ -91,9 +83,7 @@ class PiGenerator : public pp::Instance {
// and do not flush.
void FlushPixelBuffer();
- bool IsContextValid() const {
- return graphics_2d_context_ != NULL;
- }
+ bool IsContextValid() const { return graphics_2d_context_ != NULL; }
mutable pthread_mutex_t pixel_buffer_mutex_;
pp::Graphics2D* graphics_2d_context_;
@@ -103,6 +93,7 @@ class PiGenerator : public pp::Instance {
pthread_t compute_pi_thread_;
int thread_create_result_;
double pi_;
+ float device_scale_;
// ComputePi() estimates Pi using Monte Carlo method and it is executed by a
// separate thread created in SetWindow(). ComputePi() puts kMaxPointCount
@@ -115,4 +106,3 @@ class PiGenerator : public pp::Instance {
} // namespace pi_generator
#endif // EXAMPLES_PI_GENERATOR_PI_GENERATOR_H_
-
diff --git a/native_client_sdk/src/examples/pi_generator/pi_generator_module.cc b/native_client_sdk/src/examples/demo/pi_generator/pi_generator_module.cc
index 2434a096ab..e5edebbbca 100644
--- a/native_client_sdk/src/examples/pi_generator/pi_generator_module.cc
+++ b/native_client_sdk/src/examples/demo/pi_generator/pi_generator_module.cc
@@ -28,7 +28,5 @@ class PiGeneratorModule : public pp::Module {
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
-Module* CreateModule() {
- return new pi_generator::PiGeneratorModule();
-}
+Module* CreateModule() { return new pi_generator::PiGeneratorModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/file_histogram/example.dsc b/native_client_sdk/src/examples/file_histogram/example.dsc
deleted file mode 100644
index da805c7f20..0000000000
--- a/native_client_sdk/src/examples/file_histogram/example.dsc
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'file_histogram',
- 'TYPE' : 'main',
- 'SOURCES' : ['file_histogram.cc'],
- 'LIBS' : ['ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'file_histogram',
- 'TITLE': 'File Histogram.',
- 'DESC': """
-The File Histogram example demonstrates prompting the user for a file,
-passing the file contents to NativeClient as a VarArrayBuffer, then drawing a
-histogram representing the contents of the file to a 2D square.
-""",
- 'FOCUS': 'VarArrayBuffer, 2D, File input.',
- 'GROUP': 'API'
-}
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/callback.h b/native_client_sdk/src/examples/fullscreen_tumbler/callback.h
index b7664c2793..781f7596eb 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/callback.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/callback.h
@@ -35,24 +35,20 @@ typedef std::map<std::string, std::string> MethodParameter;
class MethodCallbackExecutor {
public:
virtual ~MethodCallbackExecutor() {}
- virtual void Execute(
- const ScriptingBridge& bridge,
- const MethodParameter& parameters) = 0;
+ virtual void Execute(const ScriptingBridge& bridge,
+ const MethodParameter& parameters) = 0;
};
-template <class T>
-class MethodCallback : public MethodCallbackExecutor {
+template <class T> class MethodCallback : public MethodCallbackExecutor {
public:
- typedef void (T::*Method)(
- const ScriptingBridge& bridge,
- const MethodParameter& parameters);
+ typedef void(T::* Method)(const ScriptingBridge& bridge,
+ const MethodParameter& parameters);
MethodCallback(T* instance, Method method)
: instance_(instance), method_(method) {}
virtual ~MethodCallback() {}
- virtual void Execute(
- const ScriptingBridge& bridge,
- const MethodParameter& parameters) {
+ virtual void Execute(const ScriptingBridge& bridge,
+ const MethodParameter& parameters) {
// Use "this->" to force C++ to look inside our templatized base class; see
// Effective C++, 3rd Ed, item 43, p210 for details.
((this->instance_)->*(this->method_))(bridge, parameters);
@@ -63,19 +59,16 @@ class MethodCallback : public MethodCallbackExecutor {
Method method_;
};
-template <class T>
-class ConstMethodCallback : public MethodCallbackExecutor {
+template <class T> class ConstMethodCallback : public MethodCallbackExecutor {
public:
- typedef void (T::*ConstMethod)(
- const ScriptingBridge& bridge,
- const MethodParameter& parameters) const;
+ typedef void(T::* ConstMethod)(const ScriptingBridge& bridge,
+ const MethodParameter& parameters) const;
ConstMethodCallback(const T* instance, ConstMethod method)
: instance_(instance), const_method_(method) {}
virtual ~ConstMethodCallback() {}
- virtual void Execute(
- const ScriptingBridge& bridge,
- const MethodParameter& parameters) {
+ virtual void Execute(const ScriptingBridge& bridge,
+ const MethodParameter& parameters) {
// Use "this->" to force C++ to look inside our templatized base class; see
// Effective C++, 3rd Ed, item 43, p210 for details.
((this->instance_)->*(this->const_method_))(bridge, parameters);
@@ -89,4 +82,3 @@ class ConstMethodCallback : public MethodCallbackExecutor {
} // namespace tumbler
#endif // EXAMPLES_TUMBLER_CALLBACK_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/cube.cc b/native_client_sdk/src/examples/fullscreen_tumbler/cube.cc
index b9daf01adc..3a790b7c07 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/cube.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/cube.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include <algorithm>
#include <GLES2/gl2.h>
@@ -12,16 +11,13 @@
#include "shader_util.h"
#include "transforms.h"
-
namespace tumbler {
static const size_t kVertexCount = 24;
static const int kIndexCount = 36;
Cube::Cube(SharedOpenGLContext opengl_context)
- : opengl_context_(opengl_context),
- width_(1),
- height_(1) {
+ : opengl_context_(opengl_context), width_(1), height_(1) {
eye_[0] = eye_[1] = 0.0f;
eye_[2] = 2.0f;
orientation_[0] = 0.0f;
@@ -65,20 +61,12 @@ void Cube::Draw() {
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[0]);
glUseProgram(shader_program_object_);
glEnableVertexAttribArray(position_location_);
- glVertexAttribPointer(position_location_,
- 3,
- GL_FLOAT,
- GL_FALSE,
- 3 * sizeof(GLfloat),
- NULL);
+ glVertexAttribPointer(
+ position_location_, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(color_location_);
glBindBuffer(GL_ARRAY_BUFFER, cube_vbos_[1]);
- glVertexAttribPointer(color_location_,
- 3,
- GL_FLOAT,
- GL_FALSE,
- 3 * sizeof(GLfloat),
- NULL);
+ glVertexAttribPointer(
+ color_location_, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glUniformMatrix4fv(mvp_location_, 1, GL_FALSE, mvp_matrix_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_vbos_[2]);
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
@@ -88,32 +76,32 @@ void Cube::Draw() {
bool Cube::CreateShaders() {
const char vertex_shader_src[] =
- "uniform mat4 u_mvpMatrix; \n"
- "attribute vec4 a_position; \n"
- "attribute vec3 a_color; \n"
- "varying lowp vec4 v_color; \n"
- "void main() \n"
- "{ \n"
- " v_color.xyz = a_color; \n"
- " v_color.w = 1.0; \n"
- " gl_Position = u_mvpMatrix * a_position; \n"
- "} \n";
+ "uniform mat4 u_mvpMatrix; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec3 a_color; \n"
+ "varying lowp vec4 v_color; \n"
+ "void main() \n"
+ "{ \n"
+ " v_color.xyz = a_color; \n"
+ " v_color.w = 1.0; \n"
+ " gl_Position = u_mvpMatrix * a_position; \n"
+ "} \n";
const char fragment_shader_src[] =
- "varying lowp vec4 v_color; \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = v_color; \n"
- "} \n";
+ "varying lowp vec4 v_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = v_color; \n"
+ "} \n";
// Load the shaders and get a linked program object
shader_program_object_ =
shader_util::CreateProgramFromVertexAndFragmentShaders(
- vertex_shader_src, fragment_shader_src);
+ vertex_shader_src, fragment_shader_src);
if (shader_program_object_ == 0)
return false;
- position_location_ = glGetAttribLocation(shader_program_object_,
- "a_position");
+ position_location_ =
+ glGetAttribLocation(shader_program_object_, "a_position");
color_location_ = glGetAttribLocation(shader_program_object_, "a_color");
mvp_location_ = glGetUniformLocation(shader_program_object_, "u_mvpMatrix");
return true;
@@ -231,7 +219,7 @@ void Cube::CreateCube() {
}
void Cube::ComputeModelViewTransform(GLfloat* model_view) {
- // This method takes into account the possiblity that |orientation_|
+ // This method takes into account the possibility that |orientation_|
// might not be normalized.
double sqrx = orientation_[0] * orientation_[0];
double sqry = orientation_[1] * orientation_[1];
@@ -269,4 +257,3 @@ void Cube::ComputeModelViewTransform(GLfloat* model_view) {
}
} // namespace tumbler
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/cube.h b/native_client_sdk/src/examples/fullscreen_tumbler/cube.h
index a90e0364a2..dfe427f72c 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/cube.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/cube.h
@@ -37,13 +37,9 @@ class Cube {
void Draw();
// Accessor for width and height. To change these, call Resize.
- const int width() const {
- return width_;
- }
+ const int width() const { return width_; }
- const int height() const {
- return height_;
- }
+ const int height() const { return height_; }
// Accessor/mutator for the camera orientation.
void GetOrientation(std::vector<float>* orientation) const {
@@ -63,17 +59,17 @@ class Cube {
private:
// Create the shaders used to draw the cube, and link them into a program.
- // Initializes |shader_progam_object_|, |position_loction_| and
+ // Initializes |shader_program_object_|, |position_location_| and
// |mvp_location_|.
bool CreateShaders();
// Generates a cube as a series of GL_TRIANGLE_STRIPs, and initializes
// |index_count_| to the number of indices in the index list used as a VBO.
// Creates the |vbo_ids_| required for the vertex and index data and uploads
- // the the VBO data.
+ // the VBO data.
void CreateCube();
- // Build up the model-view transform from the eye and orienation properties.
+ // Build up the model-view transform from the eye and orientation properties.
// Assumes that |model_view| is a 4x4 matrix.
void ComputeModelViewTransform(GLfloat* model_view);
@@ -81,9 +77,9 @@ class Cube {
int width_;
int height_;
GLuint shader_program_object_; // The compiled shaders.
- GLint position_location_; // The position attribute location.
- GLint color_location_; // The color attribute location.
- GLint mvp_location_; // The Model-View-Projection composite matrix.
+ GLint position_location_; // The position attribute location.
+ GLint color_location_; // The color attribute location.
+ GLint mvp_location_; // The Model-View-Projection composite matrix.
GLuint cube_vbos_[3];
GLfloat eye_[3]; // The eye point of the virtual camera.
// The orientation of the virtual camera stored as a quaternion. The
@@ -96,4 +92,3 @@ class Cube {
} // namespace tumbler
#endif // EXAMPLES_TUMBLER_CUBE_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/example.dsc b/native_client_sdk/src/examples/fullscreen_tumbler/example.dsc
index 7ff58d26fc..bad22194c2 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/example.dsc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/example.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'pnacl'],
'TARGETS': [
{
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/index.html b/native_client_sdk/src/examples/fullscreen_tumbler/index.html
index 315743e45f..bf902f2d17 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/index.html
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/index.html
@@ -20,11 +20,6 @@ found in the LICENSE file.
<body data-width="480" data-height="480" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <p>
- The Native Client module executed in this page draws a 3D cube
- and allows you to rotate it using a virtual trackball method. To toggle
- the view to/from fullscreen, press the Enter key.
- </p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.cc b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.cc
index d1675fc213..153c7e3406 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include <pthread.h>
#include "ppapi/c/pp_graphics_3d.h"
@@ -11,7 +10,7 @@
#include "opengl_context.h"
namespace {
-// This is called by the brower when the 3D context has been flushed to the
+// This is called by the browser when the 3D context has been flushed to the
// browser window.
void FlushCallback(void* data, int32_t result) {
static_cast<tumbler::OpenGLContext*>(data)->set_flush_pending(false);
@@ -21,8 +20,7 @@ void FlushCallback(void* data, int32_t result) {
namespace tumbler {
OpenGLContext::OpenGLContext(pp::Instance* instance)
- : pp::Graphics3DClient(instance),
- flush_pending_(false) {
+ : pp::Graphics3DClient(instance), flush_pending_(false) {
pp::Module* module = pp::Module::Get();
assert(module);
gles2_interface_ = static_cast<const struct PPB_OpenGLES2*>(
@@ -30,9 +28,7 @@ OpenGLContext::OpenGLContext(pp::Instance* instance)
assert(gles2_interface_);
}
-OpenGLContext::~OpenGLContext() {
- glSetCurrentContextPPAPI(0);
-}
+OpenGLContext::~OpenGLContext() { glSetCurrentContextPPAPI(0); }
bool OpenGLContext::MakeContextCurrent(pp::Instance* instance) {
if (instance == NULL) {
@@ -42,14 +38,14 @@ bool OpenGLContext::MakeContextCurrent(pp::Instance* instance) {
// Lazily create the Pepper context.
if (context_.is_null()) {
int32_t attribs[] = {
- PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
- PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
- PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
- PP_GRAPHICS3DATTRIB_SAMPLES, 0,
- PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
- PP_GRAPHICS3DATTRIB_WIDTH, size_.width(),
- PP_GRAPHICS3DATTRIB_HEIGHT, size_.height(),
- PP_GRAPHICS3DATTRIB_NONE
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
+ PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_SAMPLES, 0,
+ PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
+ PP_GRAPHICS3DATTRIB_WIDTH, size_.width(),
+ PP_GRAPHICS3DATTRIB_HEIGHT, size_.height(),
+ PP_GRAPHICS3DATTRIB_NONE
};
context_ = pp::Graphics3D(instance, pp::Graphics3D(), attribs);
if (context_.is_null()) {
@@ -73,7 +69,6 @@ void OpenGLContext::ResizeContext(const pp::Size& size) {
}
}
-
void OpenGLContext::FlushContext() {
if (flush_pending()) {
// A flush is pending so do nothing; just drop this flush on the floor.
@@ -83,4 +78,3 @@ void OpenGLContext::FlushContext() {
context_.SwapBuffers(pp::CompletionCallback(&FlushCallback, this));
}
} // namespace tumbler
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.h b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.h
index 48a8462ecf..f2b284c0ed 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context.h
@@ -37,7 +37,7 @@ class OpenGLContext : public pp::Graphics3DClient {
/// context invalid.
virtual ~OpenGLContext();
- /// The Graphics3DClient interfcace.
+ /// The Graphics3DClient interface.
virtual void Graphics3DContextLost() {
assert(!"Unexpectedly lost graphics context");
}
@@ -62,23 +62,15 @@ class OpenGLContext : public pp::Graphics3DClient {
void ResizeContext(const pp::Size& size);
/// The OpenGL ES 2.0 interface.
- const struct PPB_OpenGLES2* gles2() const {
- return gles2_interface_;
- }
+ const struct PPB_OpenGLES2* gles2() const { return gles2_interface_; }
/// The PP_Resource needed to make GLES2 calls through the Pepper interface.
- const PP_Resource gl_context() const {
- return context_.pp_resource();
- }
+ const PP_Resource gl_context() const { return context_.pp_resource(); }
/// Indicate whether a flush is pending. This can only be called from the
/// main thread; it is not thread safe.
- bool flush_pending() const {
- return flush_pending_;
- }
- void set_flush_pending(bool flag) {
- flush_pending_ = flag;
- }
+ bool flush_pending() const { return flush_pending_; }
+ void set_flush_pending(bool flag) { flush_pending_ = flag; }
private:
pp::Size size_;
@@ -91,5 +83,3 @@ class OpenGLContext : public pp::Graphics3DClient {
} // namespace tumbler
#endif // EXAMPLES_TUMBLER_OPENGL_CONTEXT_H_
-
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context_ptrs.h b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context_ptrs.h
index 3a00d0bd01..d5da922e13 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context_ptrs.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/opengl_context_ptrs.h
@@ -19,4 +19,3 @@ typedef std::tr1::shared_ptr<OpenGLContext> SharedOpenGLContext;
} // namespace tumbler
#endif // EXAMPLES_TUMBLER_OPENGL_CONTEXT_PTRS_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.cc b/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.cc
index b44bb8e3a8..0cd49cdea2 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.cc
@@ -17,10 +17,10 @@ const std::string ScanToken(const std::string& token_string, size_t* pos) {
if (*pos == std::string::npos) {
return token;
}
- size_t token_start_pos = token_string.find_first_not_of(kWhiteSpaceCharacters,
- *pos);
- size_t token_end_pos = token_string.find_first_of(kWhiteSpaceCharacters,
- token_start_pos);
+ size_t token_start_pos =
+ token_string.find_first_not_of(kWhiteSpaceCharacters, *pos);
+ size_t token_end_pos =
+ token_string.find_first_of(kWhiteSpaceCharacters, token_start_pos);
if (token_start_pos != std::string::npos) {
token = token_string.substr(token_start_pos, token_end_pos);
}
@@ -93,4 +93,3 @@ bool ScriptingBridge::InvokeMethod(const std::string& method) {
}
} // namespace tumbler
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.h b/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.h
index e89d157199..f4ebfb4463 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/scripting_bridge.h
@@ -32,7 +32,7 @@ class ScriptingBridge {
public:
// Shared pointer type used in the method map.
typedef std::tr1::shared_ptr<MethodCallbackExecutor>
- SharedMethodCallbackExecutor;
+ SharedMethodCallbackExecutor;
virtual ~ScriptingBridge() {}
@@ -50,5 +50,5 @@ class ScriptingBridge {
};
} // namespace tumbler
-#endif // EXAMPLES_TUMBLER_SCRIPTING_BRIDGE_H_
+#endif // EXAMPLES_TUMBLER_SCRIPTING_BRIDGE_H_
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.cc b/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.cc
index e6a4ae7a17..ad6f5e965e 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.cc
@@ -11,7 +11,7 @@
namespace shader_util {
-GLuint CreateShaderOfType(GLenum type, const char *shader_src) {
+GLuint CreateShaderOfType(GLenum type, const char* shader_src) {
GLuint shader;
GLint compiled;
@@ -46,7 +46,8 @@ GLuint CreateShaderOfType(GLenum type, const char *shader_src) {
}
GLuint CreateProgramFromVertexAndFragmentShaders(
- const char *vertex_shader_src, const char *fragment_shader_src) {
+ const char* vertex_shader_src,
+ const char* fragment_shader_src) {
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program_object;
@@ -96,4 +97,3 @@ GLuint CreateProgramFromVertexAndFragmentShaders(
}
} // namespace shader_util
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.h b/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.h
index a9c908838a..f73360349d 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/shader_util.h
@@ -15,16 +15,16 @@ namespace shader_util {
// GL_FRAGMENT_SHADER. Returns a non-0 value representing the compiled
// shader on success, 0 on failure. The caller is responsible for deleting
// the returned shader using glDeleteShader().
-GLuint CreateShaderOfType(GLenum type, const char *shader_src);
+GLuint CreateShaderOfType(GLenum type, const char* shader_src);
// Load and compile the vertex and fragment shaders, then link these together
// into a complete program. Returns a non-0 value representing the program on,
// success or 0 on failure. The caller is responsible for deleting the
// returned program using glDeleteProgram().
GLuint CreateProgramFromVertexAndFragmentShaders(
- const char *vertex_shader_src, const char *fragment_shader_src);
+ const char* vertex_shader_src,
+ const char* fragment_shader_src);
} // namespace shader_util
#endif // EXAMPLES_TUMBLER_SHADER_UTIL_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/transforms.cc b/native_client_sdk/src/examples/fullscreen_tumbler/transforms.cc
index 75a7c2cdda..a15963f52e 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/transforms.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/transforms.cc
@@ -31,9 +31,9 @@ void Frustum(GLfloat* m,
GLfloat delta_z = far_z - near_z;
GLfloat frustum[16];
- if ((near_z <= 0.0f) || (far_z <= 0.0f) ||
- (delta_x <= 0.0f) || (delta_y <= 0.0f) || (delta_z <= 0.0f))
- return;
+ if ((near_z <= 0.0f) || (far_z <= 0.0f) || (delta_x <= 0.0f) ||
+ (delta_y <= 0.0f) || (delta_z <= 0.0f))
+ return;
frustum[0] = 2.0f * near_z / delta_x;
frustum[1] = frustum[2] = frustum[3] = 0.0f;
@@ -52,7 +52,6 @@ void Frustum(GLfloat* m,
transform_4x4::Multiply(m, frustum, m);
}
-
void Perspective(GLfloat* m,
GLfloat fovy,
GLfloat aspect,
@@ -62,11 +61,11 @@ void Perspective(GLfloat* m,
frustum_h = tanf((fovy * 0.5f) / 180.0f * kPI) * near_z;
frustum_w = frustum_h * aspect;
- transform_4x4::Frustum(m, -frustum_w, frustum_w, -frustum_h, frustum_h,
- near_z, far_z);
+ transform_4x4::Frustum(
+ m, -frustum_w, frustum_w, -frustum_h, frustum_h, near_z, far_z);
}
-void Multiply(GLfloat *m, GLfloat *a, GLfloat* b) {
+void Multiply(GLfloat* m, GLfloat* a, GLfloat* b) {
GLfloat tmp[16];
// tmp = a . b
GLfloat a0, a1, a2, a3;
@@ -114,4 +113,3 @@ void LoadIdentity(GLfloat* m) {
}
} // namespace transform_4x4
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/transforms.h b/native_client_sdk/src/examples/fullscreen_tumbler/transforms.h
index 37fcb246c6..70f6d10f6b 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/transforms.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/transforms.h
@@ -12,7 +12,7 @@
namespace transform_4x4 {
-// Pre-multply |m| with a projection transformation 4x4 matrix from a
+// Pre-multiply |m| with a projection transformation 4x4 matrix from a
// truncated pyramid viewing frustum.
void Frustum(GLfloat* m,
GLfloat left,
@@ -26,7 +26,7 @@ void Frustum(GLfloat* m,
void LoadIdentity(GLfloat* m);
// |m| <- |a| . |b|. |m| can point at the same memory as either |a| or |b|.
-void Multiply(GLfloat *m, GLfloat *a, GLfloat* b);
+void Multiply(GLfloat* m, GLfloat* a, GLfloat* b);
// Pre-multiply |m| with a single-point perspective matrix based on the viewing
// frustum whose view angle is |fovy|.
@@ -42,4 +42,3 @@ void Translate(GLfloat* m, GLfloat tx, GLfloat ty, GLfloat tz);
} // namespace transform_4x4
#endif // EXAMPLES_TUMBLER_TRANSFORMS_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.cc b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.cc
index 6640bf4c7d..3725f3aae8 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include <stdio.h>
#include <cstdlib>
@@ -29,11 +28,9 @@ const char* const kArrayDelimiter = ",";
// Return the value of parameter named |param_name| from |parameters|. If
// |param_name| doesn't exist, then return an empty string.
-std::string GetParameterNamed(
- const std::string& param_name,
- const tumbler::MethodParameter& parameters) {
- tumbler::MethodParameter::const_iterator i =
- parameters.find(param_name);
+std::string GetParameterNamed(const std::string& param_name,
+ const tumbler::MethodParameter& parameters) {
+ tumbler::MethodParameter::const_iterator i = parameters.find(param_name);
if (i == parameters.end()) {
return "";
}
@@ -51,7 +48,7 @@ std::vector<float> CreateArrayFromJSON(const std::string& json_array) {
if (array_start_pos == std::string::npos ||
array_end_pos == std::string::npos)
return float_array; // Malformed JSON: missing '[' or ']'.
- // Pull out the array elements.
+ // Pull out the array elements.
size_t token_pos = array_start_pos + 1;
while (token_pos < array_end_pos) {
float_array.push_back(strtof(json_array.data() + token_pos, NULL));
@@ -82,14 +79,14 @@ Tumbler::~Tumbler() {
}
bool Tumbler::Init(uint32_t /* argc */,
- const char* /* argn */[],
- const char* /* argv */[]) {
+ const char * /* argn */ [],
+ const char * /* argv */ []) {
// Add all the methods to the scripting bridge.
ScriptingBridge::SharedMethodCallbackExecutor set_orientation_method(
- new tumbler::MethodCallback<Tumbler>(
- this, &Tumbler::SetCameraOrientation));
+ new tumbler::MethodCallback<Tumbler>(this,
+ &Tumbler::SetCameraOrientation));
scripting_bridge_.AddMethodNamed("setCameraOrientation",
- set_orientation_method);
+ set_orientation_method);
return true;
}
@@ -161,9 +158,7 @@ void Tumbler::DidChangeView(const pp::View& view) {
DrawSelf();
}
-void Tumbler::DidChangeFocus(bool focus) {
- has_focus_ = focus;
-}
+void Tumbler::DidChangeFocus(bool focus) { has_focus_ = focus; }
void Tumbler::DrawSelf() {
if (cube_ == NULL || opengl_context_ == NULL)
@@ -188,9 +183,8 @@ void Tumbler::HandleKeyDownEvent(const pp::KeyboardInputEvent& key_event) {
}
}
-void Tumbler::SetCameraOrientation(
- const tumbler::ScriptingBridge& bridge,
- const tumbler::MethodParameter& parameters) {
+void Tumbler::SetCameraOrientation(const tumbler::ScriptingBridge& bridge,
+ const tumbler::MethodParameter& parameters) {
// |parameters| is expected to contain one object named "orientation", whose
// value is a JSON string that represents an array of four floats.
if (parameters.size() != 1 || cube_ == NULL)
@@ -205,4 +199,3 @@ void Tumbler::SetCameraOrientation(
}
} // namespace tumbler
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.h b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.h
index 7b2a9c62d7..80b4ea9b86 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.h
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler.h
@@ -21,7 +21,6 @@ namespace pp {
class KeyboardInputEvent;
} // namespace pp
-
namespace tumbler {
class Tumbler : public pp::Instance {
@@ -51,14 +50,13 @@ class Tumbler : public pp::Instance {
void InitializeMethods(ScriptingBridge* bridge);
// Set the camera orientation to the quaternion in |args[0]|. |args| must
- // have length at least 1; the first element is expeted to be an Array
+ // have length at least 1; the first element is expected to be an Array
// object containing 4 floating point number elements (the quaternion).
// This method is bound to the JavaScript "setCameraOrientation" method and
// is called like this:
// module.setCameraOrientation([0.0, 1.0, 0.0, 0.0]);
- void SetCameraOrientation(
- const tumbler::ScriptingBridge& bridge,
- const tumbler::MethodParameter& parameters);
+ void SetCameraOrientation(const tumbler::ScriptingBridge& bridge,
+ const tumbler::MethodParameter& parameters);
// Called to draw the contents of the module's browser area.
void DrawSelf();
@@ -81,4 +79,3 @@ class Tumbler : public pp::Instance {
} // namespace tumbler
#endif // EXAMPLES_TUMBLER_TUMBLER_H_
-
diff --git a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler_module.cc b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler_module.cc
index d1d103fc37..d34576ebeb 100644
--- a/native_client_sdk/src/examples/fullscreen_tumbler/tumbler_module.cc
+++ b/native_client_sdk/src/examples/fullscreen_tumbler/tumbler_module.cc
@@ -16,9 +16,7 @@
class TumberModule : public pp::Module {
public:
TumberModule() : pp::Module() {}
- virtual ~TumberModule() {
- glTerminatePPAPI();
- }
+ virtual ~TumberModule() { glTerminatePPAPI(); }
/// Called by the browser when the module is first loaded and ready to run.
/// This is called once per module, not once per instance of the module on
@@ -41,8 +39,5 @@ namespace pp {
/// CreateInstance() method on the object you return to make instances. There
/// is one instance per <embed> tag on the page. This is the main binding
/// point for your NaCl module with the browser.
-Module* CreateModule() {
- return new TumberModule();
-}
+Module* CreateModule() { return new TumberModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/getting_started/hello_world/example.dsc b/native_client_sdk/src/examples/getting_started/hello_world/example.dsc
new file mode 100644
index 0000000000..a02f5428ca
--- /dev/null
+++ b/native_client_sdk/src/examples/getting_started/hello_world/example.dsc
@@ -0,0 +1,18 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'hello_world',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['hello_world.c'],
+ 'LIBS': ['ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/getting_started',
+ 'NAME': 'hello_world',
+ 'TITLE': 'Hello World',
+ 'GROUP': 'Getting Started'
+}
diff --git a/native_client_sdk/src/examples/getting_started/hello_world/example.js b/native_client_sdk/src/examples/getting_started/hello_world/example.js
new file mode 100644
index 0000000000..7f269215fe
--- /dev/null
+++ b/native_client_sdk/src/examples/getting_started/hello_world/example.js
@@ -0,0 +1,13 @@
+// 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.
+
+// Once we load, hide the plugin
+function moduleDidLoad() {
+ common.hideModule();
+}
+
+// Called by the common.js module.
+function handleMessage(message) {
+ common.logMessage(message.data);
+}
diff --git a/native_client_sdk/src/examples/hello_world/hello_world.c b/native_client_sdk/src/examples/getting_started/hello_world/hello_world.c
index 8c01be08f5..ddfc0eefd2 100644
--- a/native_client_sdk/src/examples/hello_world/hello_world.c
+++ b/native_client_sdk/src/examples/getting_started/hello_world/hello_world.c
@@ -39,7 +39,6 @@ static PPB_Console* ppb_console_interface = NULL;
static PPB_Messaging* ppb_messaging_interface = NULL;
static PPB_Var* ppb_var_interface = NULL;
-
/**
* Creates new string PP_Var from C string. The resulting object will be a
* refcounted string object. It will be AddRef()ed for the caller. When the
@@ -54,11 +53,10 @@ static struct PP_Var CStrToVar(const char* str) {
return PP_MakeUndefined();
}
-
/**
* Post a message back to our JavaScript
*/
-static void SendMessage(PP_Instance instance, const char *str) {
+static void SendMessage(PP_Instance instance, const char* str) {
if (ppb_messaging_interface)
ppb_messaging_interface->PostMessage(instance, CStrToVar(str));
}
@@ -66,10 +64,9 @@ static void SendMessage(PP_Instance instance, const char *str) {
/**
* Send a message to the JavaScript Console
*/
-static void LogMessage(PP_Instance instance, const char *str) {
+static void LogMessage(PP_Instance instance, const char* str) {
if (ppb_console_interface)
- ppb_console_interface->Log(instance, PP_LOGLEVEL_ERROR,
- CStrToVar(str));
+ ppb_console_interface->Log(instance, PP_LOGLEVEL_ERROR, CStrToVar(str));
}
/**
@@ -108,7 +105,6 @@ 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
@@ -116,8 +112,7 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
* @param[in] instance The identifier of the instance representing this NaCl
* module.
*/
-static void Instance_DidDestroy(PP_Instance instance) {
-}
+static void Instance_DidDestroy(PP_Instance instance) {}
/**
* Called when the position, the size, or the clip rect of the element in the
@@ -132,8 +127,7 @@ static void Instance_DidDestroy(PP_Instance instance) {
* plugin is invisible, @a clip will be (0, 0, 0, 0).
*/
static void Instance_DidChangeView(PP_Instance instance,
- PP_Resource view_resource) {
-}
+ PP_Resource view_resource) {}
/**
* Notification that the given NaCl module has gained or lost focus.
@@ -152,9 +146,7 @@ static void Instance_DidChangeView(PP_Instance instance,
* @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) {
-}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
/**
* Handler that gets called after a full-frame module is instantiated based on
@@ -172,8 +164,6 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
return PP_FALSE;
}
-
-
/**
* Entry points for the module.
* Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
@@ -183,15 +173,13 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
*/
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
PPB_GetInterface get_browser) {
- ppb_console_interface =
- (PPB_Console*)(get_browser(PPB_CONSOLE_INTERFACE));
+ ppb_console_interface = (PPB_Console*)(get_browser(PPB_CONSOLE_INTERFACE));
ppb_messaging_interface =
(PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
return PP_OK;
}
-
/**
* Returns an interface pointer for the interface of the given name, or NULL
* if the interface is not supported.
@@ -212,9 +200,7 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
return NULL;
}
-
/**
* Called before the plugin module is unloaded.
*/
-PP_EXPORT void PPP_ShutdownModule() {
-}
+PP_EXPORT void PPP_ShutdownModule() {}
diff --git a/native_client_sdk/src/examples/getting_started/hello_world/index.html b/native_client_sdk/src/examples/getting_started/hello_world/index.html
new file mode 100644
index 0000000000..4ed29868dd
--- /dev/null
+++ b/native_client_sdk/src/examples/getting_started/hello_world/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta http-equiv="Pragma" content="no-cache">
+ <meta http-equiv="Expires" content="-1">
+ <title>{{title}}</title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
+</head>
+<body {{attrs}}>
+ <h1>{{title}}</h1>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>The Hello World In C example demonstrates the basic structure of all
+ Native Client applications. This example loads a Native Client module. The
+ page tracks the status of the module as it load. On a successful load, the
+ module will post a message containing the string "Hello World" back to
+ JavaScript which will display it as an alert.</p>
+ <h2>Output:</h2>
+ <pre id="log" style="font-weight: bold"></pre>
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+ <div id="listener"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.dsc b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.dsc
new file mode 100644
index 0000000000..2bb125af57
--- /dev/null
+++ b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.dsc
@@ -0,0 +1,19 @@
+{
+ 'TOOLS': ['newlib', 'glibc'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'hello_world_stdio',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['hello_world.c'],
+ 'LIBS': ['ppapi_main', 'nacl_io', 'ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/getting_started',
+ 'NAME': 'hello_world_ppapi_main',
+ 'TITLE': 'Hello World (libppapi_main)',
+ 'GROUP': 'Getting Started'
+}
+
diff --git a/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.js b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.js
new file mode 100644
index 0000000000..7f269215fe
--- /dev/null
+++ b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/example.js
@@ -0,0 +1,13 @@
+// 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.
+
+// Once we load, hide the plugin
+function moduleDidLoad() {
+ common.hideModule();
+}
+
+// Called by the common.js module.
+function handleMessage(message) {
+ common.logMessage(message.data);
+}
diff --git a/native_client_sdk/src/examples/hello_world_stdio/hello_world.c b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/hello_world.c
index be1c3978ff..1d3d6f10ff 100644
--- a/native_client_sdk/src/examples/hello_world_stdio/hello_world.c
+++ b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/hello_world.c
@@ -12,13 +12,13 @@
#include "ppapi_main/ppapi_main.h"
-
-// Have the Module object provided by ppapi_main create a basic
-// PPAPI instance with default arguments which mounts the dev
-// file system providing /dev/null, /dev/tty, and /devl/console3
-// for null STDIN, STDOUT directed to PostMessage and STDERR
-// directed to the JavaScript Console with LogLevel 'ERROR'
-PPAPI_MAIN_WITH_DEFAULT_ARGS
+// The default arguments to PPAPI_MAIN maps:
+// STDIN -> /dev/stdin
+// STDOUT -> /dev/stdout
+// STDERR -> /dev/console3
+// We use our own args here so that stdout sends messages to JavaScript via
+// PostMessage (/dev/tty).
+PPAPI_MAIN_WITH_ARGS("pm_stdout", "/dev/tty", NULL, NULL)
//
// The "main" entry point called by PPAPIInstance once initialization
@@ -30,7 +30,7 @@ PPAPI_MAIN_WITH_DEFAULT_ARGS
// argv[2] = "<VALUE>"
// Where the embed tag for this module uses KEY=VALUE
//
-int ppapi_main(int argc, const char *argv[]) {
+int ppapi_main(int argc, const char* argv[]) {
int index = 1;
// Use PostMessage to send "Hello World" to JavaScript.
@@ -43,7 +43,7 @@ int ppapi_main(int argc, const char *argv[]) {
// Print the arguments we received from the web page
printf("NAME: %s\n", argv[0]);
while (index + 2 < argc) {
- printf(" ARGS: %s=%s\n", argv[index+0], argv[index+1]);
+ printf(" ARGS: %s=%s\n", argv[index + 0], argv[index + 1]);
index += 2;
}
return 0;
diff --git a/native_client_sdk/src/examples/hello_world_stdio/index.html b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/index.html
index f317883b44..c6a4aa1ef4 100644
--- a/native_client_sdk/src/examples/hello_world_stdio/index.html
+++ b/native_client_sdk/src/examples/getting_started/hello_world_ppapi_main/index.html
@@ -15,23 +15,19 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <!-- The NaCl plugin will be embedded inside the element with id "listener".
- See common.js.-->
-
- <p>This example demonstrates using nacl_io ppapi_main to simplify the
- creation of a PPAPI application. The ppapi_main library handles the creation
- and initialization of a pp::Instance object. The nacl_io library
- intercepts standard file IO, allowing the remapping of STDOUT, and
- STDERR.</p>
+ <p>The Hello World Stdio example is the simplest one in the SDK. It uses the
+ ppapi_main library which creates an Module and Instance, using default
+ values to simplify setup and communication with the PPAPI system. In
+ addition, it uses the nacl_io library to remap IO to the Pepper API. This
+ simplifies IO by providing a standard blocking API and allowing STDERR to
+ go to the JavaScript console by default.</p>
<p>In main, we write to both STDOUT and STDERR, printing a hello world
- message.</p>
+ message.</p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
+ <h2>Output:</h2>
+ <pre id="log" style="font-weight:bold"></pre>
<div id="listener"></div>
- <h1>OUTPUT</h1>
- <pre>
- <p><b id='outputString'></b></p>
- </pre>
</body>
</html>
diff --git a/native_client_sdk/src/examples/hello_nacl_io/example.dsc b/native_client_sdk/src/examples/hello_nacl_io/example.dsc
deleted file mode 100644
index 8f6f75919b..0000000000
--- a/native_client_sdk/src/examples/hello_nacl_io/example.dsc
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win'],
- 'TARGETS': [
- {
- 'NAME' : 'hello_nacl_io',
- 'TYPE' : 'main',
- 'SOURCES' : [
- 'handlers.c',
- 'handlers.h',
- 'hello_nacl_io.c',
- 'hello_nacl_io.h',
- 'queue.c',
- 'queue.h',
- ],
- 'LIBS': ['ppapi', 'pthread', 'nacl_io']
- }
- ],
- 'DATA': [
- 'example.js'
- ],
- 'DEST': 'examples',
- 'NAME': 'hello_nacl_io',
- 'TITLE': 'Hello, Nacl IO!',
- 'DESC': """
-The NaCl IO example demonstrates mapping standard FILE such as fopen,
-fread, fwrite into mounts by linking in the nacl_io library. This allows
-developers to wrap Pepper API such as the File IO API or URL Loader into
-standard blocking calls.""",
- 'FOCUS': 'Using NaCl IO.',
- 'GROUP': 'Concepts'
-}
diff --git a/native_client_sdk/src/examples/hello_world/example.dsc b/native_client_sdk/src/examples/hello_world/example.dsc
deleted file mode 100644
index d7453d8960..0000000000
--- a/native_client_sdk/src/examples/hello_world/example.dsc
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'hello_world',
- 'TYPE' : 'main',
- 'SOURCES' : ['hello_world.c'],
- 'LIBS': ['ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'hello_world',
- 'TITLE': 'Hello World.',
- 'DESC': """
-The Hello World In C example demonstrates the basic structure of all
-Native Client applications. This example loads a Native Client module. The
-page tracks the status of the module as it load. On a successful load, the
-module will post a message containing the string "Hello World" back to
-JavaScript which will display it as an alert.""",
- 'FOCUS': 'Basic HTML, JavaScript, and module architecture.',
- 'GROUP': 'Tools'
-}
diff --git a/native_client_sdk/src/examples/hello_world/example.js b/native_client_sdk/src/examples/hello_world/example.js
deleted file mode 100644
index 13a99975e3..0000000000
--- a/native_client_sdk/src/examples/hello_world/example.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var kMaxArraySize = 20;
-var messageArray = new Array();
-
-// Once we load, hide the plugin
-function moduleDidLoad() {
- common.hideModule();
-}
-
-// Called by the common.js module.
-function handleMessage(message) {
- // Show last |kMaxArraySize| events in html.
- messageArray.push(message.data);
- if (messageArray.length > kMaxArraySize) {
- messageArray.shift();
- }
- var newData = messageArray.join('<BR>');
- document.getElementById('outputString').innerHTML = newData;
- // Print event to console.
- console.log(message.data);
-}
diff --git a/native_client_sdk/src/examples/hello_world/index.html b/native_client_sdk/src/examples/hello_world/index.html
deleted file mode 100644
index a91a547e6a..0000000000
--- a/native_client_sdk/src/examples/hello_world/index.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-Copyright (c) 2012 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<head>
- <meta http-equiv="Pragma" content="no-cache">
- <meta http-equiv="Expires" content="-1">
- <title>{{title}}</title>
- <script type="text/javascript" src="common.js"></script>
- <script type="text/javascript" src="example.js"></script>
-</head>
-<body {{attrs}}>
- <h1>{{title}}</h1>
- <h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <p>This example demonstrates a complete NaCl PPAPI application. In
-source file hello_world.c contains the three required PPAPI functions
- PPP_InitializeModule, PPP_GetInterface, PPP_ShutdownModule which initialize
-the application, provide a string name to callback interface mapping, and
-cleanup on shutdown respectively.</p>
- <p>The example will query for the Console, PostMessage and Var interfaces to
-send a message to JavaScript which will be added to the output box. In
-addition, it will send another message to the JavaScript Console to simulate
-logging for development.</p>
-
- <!-- The NaCl plugin will be embedded inside the element with id "listener".
- See common.js.-->
- <div id="listener"></div>
- <h1>OUTPUT</h1>
- <pre>
- <p><b id='outputString'></b></p>
- </pre>
-</body>
-</html>
diff --git a/native_client_sdk/src/examples/hello_world_gles/matrix.cc b/native_client_sdk/src/examples/hello_world_gles/matrix.cc
deleted file mode 100644
index a76e2bb1b7..0000000000
--- a/native_client_sdk/src/examples/hello_world_gles/matrix.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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.
- */
-
-/** @file matrix.cc
- * Implements simple matrix manipulation functions.
- */
-
-//-----------------------------------------------------------------------------
-#include <stdlib.h>
-#include <string.h>
-#include "matrix.h"
-#define deg_to_rad(x) (x * (M_PI/180.0f))
-
-void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
- GLfloat top, GLfloat znear, GLfloat zfar)
-{
- float temp, temp2, temp3, temp4;
- temp = 2.0f * znear;
- temp2 = right - left;
- temp3 = top - bottom;
- temp4 = zfar - znear;
- mat[0] = temp / temp2;
- mat[1] = 0.0f;
- mat[2] = 0.0f;
- mat[3] = 0.0f;
- mat[4] = 0.0f;
- mat[5] = temp / temp3;
- mat[6] = 0.0f;
- mat[7] = 0.0f;
- mat[8] = (right + left) / temp2;
- mat[9] = (top + bottom) / temp3;
- mat[10] = (-zfar - znear) / temp4;
- mat[11] = -1.0f;
- mat[12] = 0.0f;
- mat[13] = 0.0f;
- mat[14] = (-temp * zfar) / temp4;
- mat[15] = 0.0f;
-}
-
-void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
- GLfloat aspectRatio, GLfloat znear, GLfloat zfar)
-{
- float ymax, xmax;
- ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
- xmax = ymax * aspectRatio;
- glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
-}
-
-void identity_matrix(Matrix_t mat) {
- memset(mat, 0, sizeof(Matrix_t));
- mat[0] = 1.0;
- mat[5] = 1.0;
- mat[10] = 1.0;
- mat[15] = 1.0;
-}
-
-void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
- // Generate to a temporary first in case the output matrix and input
- // matrix are thes same.
- Matrix_t out;
-
- out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
- out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
- out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
- out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
-
- out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
- out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
- out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
- out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
-
- out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
- out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
- out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
- out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
-
- out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
- out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
- out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
- out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
-
- memcpy(mat, out, sizeof(Matrix_t));
-}
-
-void rotate_x_matrix(GLfloat x_rad, Matrix_t mat) {
- identity_matrix(mat);
- mat[5] = cosf(x_rad);
- mat[6] = -sinf(x_rad);
- mat[9] = -mat[6];
- mat[10] = mat[5];
-}
-
-void rotate_y_matrix(GLfloat y_rad, Matrix_t mat) {
- identity_matrix(mat);
- mat[0] = cosf(y_rad);
- mat[2] = sinf(y_rad);
- mat[8] = -mat[2];
- mat[10] = mat[0];
-}
-
-void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
- identity_matrix(mat);
- mat[0] = cosf(z_rad);
- mat[1] = sinf(z_rad);
- mat[4] = -mat[1];
- mat[5] = mat[0];
-}
-
-void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg,
- Matrix_t mat) {
- GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
- GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
- GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
-
- Matrix_t x_matrix;
- Matrix_t y_matrix;
- Matrix_t z_matrix;
-
- rotate_x_matrix(x_rad, x_matrix);
- rotate_y_matrix(y_rad, y_matrix);
- rotate_z_matrix(z_rad, z_matrix);
-
- Matrix_t xy_matrix;
- multiply_matrix(y_matrix, x_matrix, xy_matrix);
- multiply_matrix(z_matrix, xy_matrix, mat);
-}
-
-void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
- identity_matrix(mat);
- mat[12] += x;
- mat[13] += y;
- mat[14] += z;
-}
-
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/example.dsc b/native_client_sdk/src/examples/hello_world_instance3d/example.dsc
index 2ba6eb1be0..243af7ca9e 100644
--- a/native_client_sdk/src/examples/hello_world_instance3d/example.dsc
+++ b/native_client_sdk/src/examples/hello_world_instance3d/example.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'pnacl'],
'TARGETS': [
{
@@ -9,7 +10,8 @@
'-I../../src',
'-I../../src/ppapi/lib/gl'
],
- 'LIBS': ['ppapi_main', 'nacl_io', 'ppapi_gles2', 'ppapi_cpp', 'ppapi',
+ 'DEPS': ['ppapi_main', 'nacl_io'],
+ 'LIBS': ['ppapi_gles2', 'ppapi_cpp', 'ppapi',
'pthread']
}
],
@@ -21,11 +23,6 @@
'DEST': 'examples',
'NAME': 'hello_world_instance3d',
'TITLE': 'Hello World GLES 2.0 using ppapi_instance3d',
- 'DESC': """
-The Hello World GLES 2.0 example demonstrates how to create a 3D cube
-that rotates. This is a simpler example than the tumbler example, and
-written in C. It loads the assets using URLLoader.""",
- 'FOCUS': '3D graphics, URL Loader.',
'GROUP': 'API'
}
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc b/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc
index 9a86d94ee0..26515b7249 100644
--- a/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc
+++ b/native_client_sdk/src/examples/hello_world_instance3d/hello_world.cc
@@ -49,12 +49,12 @@
#include <GLES2/gl2.h>
#include "matrix.h"
-GLuint g_positionLoc;
-GLuint g_texCoordLoc;
-GLuint g_colorLoc;
-GLuint g_MVPLoc;
-GLuint g_vboID;
-GLuint g_ibID;
+GLuint g_positionLoc;
+GLuint g_texCoordLoc;
+GLuint g_colorLoc;
+GLuint g_MVPLoc;
+GLuint g_vboID;
+GLuint g_ibID;
GLubyte g_Indices[36];
GLuint g_programObj;
@@ -70,37 +70,33 @@ float g_fSpinY = 0.0f;
//----------------------------------------------------------------------------
// Rendering Assets
//----------------------------------------------------------------------------
-struct Vertex
-{
+struct Vertex {
float tu, tv;
float color[3];
float loc[3];
};
-Vertex *g_quadVertices = NULL;
-const char *g_TextureData = NULL;
-const char *g_VShaderData = NULL;
-const char *g_FShaderData = NULL;
+Vertex* g_quadVertices = NULL;
+const char* g_TextureData = NULL;
+const char* g_VShaderData = NULL;
+const char* g_FShaderData = NULL;
bool g_Loaded = false;
bool g_Ready = false;
-
float g_xSpin = 2.0f;
float g_ySpin = 0.5f;
-
-GLuint compileShader(GLenum type, const char *data) {
- const char *shaderStrings[1];
+GLuint compileShader(GLenum type, const char* data) {
+ const char* shaderStrings[1];
shaderStrings[0] = data;
GLuint shader = glCreateShader(type);
- glShaderSource(shader, 1, shaderStrings, NULL );
+ glShaderSource(shader, 1, shaderStrings, NULL);
glCompileShader(shader);
return shader;
}
-
void InitProgram(void) {
g_vertexShader = compileShader(GL_VERTEX_SHADER, g_VShaderData);
g_fragmentShader = compileShader(GL_FRAGMENT_SHADER, g_FShaderData);
@@ -112,23 +108,27 @@ void InitProgram(void) {
glGenBuffers(1, &g_vboID);
glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(Vertex),
- (void*)&g_quadVertices[0], GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER,
+ 24 * sizeof(Vertex),
+ (void*)&g_quadVertices[0],
+ GL_STATIC_DRAW);
glGenBuffers(1, &g_ibID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(char),
- (void*)&g_Indices[0], GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ 36 * sizeof(char),
+ (void*)&g_Indices[0],
+ GL_STATIC_DRAW);
//
// Create a texture to test out our fragment shader...
//
glGenTextures(1, &g_textureID);
glBindTexture(GL_TEXTURE_2D, g_textureID);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB,
- GL_UNSIGNED_BYTE, g_TextureData);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE,
+ g_TextureData);
//
// Locate some parameters by name so we can set them later...
@@ -141,7 +141,6 @@ void InitProgram(void) {
printf("Program initialized.\n");
}
-
void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
static float X[4] = { -1.0f, 1.0f, 1.0f, -1.0f };
static float Y[4] = { -1.0f, -1.0f, 1.0f, 1.0f };
@@ -157,9 +156,8 @@ void BuildQuad(Vertex* verts, int axis[3], float depth, float color[3]) {
}
}
-
-Vertex *BuildCube() {
- Vertex *verts = new Vertex[24];
+Vertex* BuildCube() {
+ Vertex* verts = new Vertex[24];
for (int i = 0; i < 3; i++) {
int Faxis[3];
int Baxis[3];
@@ -177,40 +175,40 @@ Vertex *BuildCube() {
BuildQuad(&verts[12 + i * 4], Baxis, -1.0f, Bcolor);
}
- for(int i = 0; i < 6; i++) {
- g_Indices[i*6 + 0] = 2 + i * 4;
- g_Indices[i*6 + 1] = 1 + i * 4;
- g_Indices[i*6 + 2] = 0 + i * 4;
- g_Indices[i*6 + 3] = 3 + i * 4;
- g_Indices[i*6 + 4] = 2 + i * 4;
- g_Indices[i*6 + 5] = 0 + i * 4;
+ for (int i = 0; i < 6; i++) {
+ g_Indices[i * 6 + 0] = 2 + i * 4;
+ g_Indices[i * 6 + 1] = 1 + i * 4;
+ g_Indices[i * 6 + 2] = 0 + i * 4;
+ g_Indices[i * 6 + 3] = 3 + i * 4;
+ g_Indices[i * 6 + 4] = 2 + i * 4;
+ g_Indices[i * 6 + 5] = 0 + i * 4;
}
return verts;
}
-
static float clamp(float val, float min, float max) {
- if (val < min) return min;
- if (val > max) return max;
+ if (val < min)
+ return min;
+ if (val > max)
+ return max;
return val;
}
-
void ProcessEvent(PPAPIEvent* event) {
if (event->event_type == PP_INPUTEVENT_TYPE_MOUSEMOVE) {
- PPAPIMouseEvent* mouse = (PPAPIMouseEvent*) event;
+ PPAPIMouseEvent* mouse = (PPAPIMouseEvent*)event;
g_ySpin = clamp((float) mouse->delta.x / 2, -4.0, 4.0);
g_xSpin = clamp((float) mouse->delta.y / 2, -4.0, 4.0);
}
if (event->event_type == PP_INPUTEVENT_TYPE_KEYUP) {
- PPAPIKeyEvent* key = (PPAPIKeyEvent*) event;
+ PPAPIKeyEvent* key = (PPAPIKeyEvent*)event;
if (key->key_code == 13) {
PPAPIInstance3D::GetInstance3D()->ToggleFullscreen();
}
}
}
-void PPAPIRender(uint32_t width, uint32_t height) {
+void PPAPIRender(PP_Resource ctx, uint32_t width, uint32_t height) {
if (!g_Ready) {
if (g_Loaded) {
InitProgram();
@@ -232,22 +230,26 @@ void PPAPIRender(uint32_t width, uint32_t height) {
xRot -= g_xSpin;
yRot -= g_ySpin;
- if (xRot >= 360.0f) xRot = 0.0;
- if (xRot <= -360.0f) xRot = 0.0;
+ if (xRot >= 360.0f)
+ xRot = 0.0;
+ if (xRot <= -360.0f)
+ xRot = 0.0;
- if (yRot >= 360.0f) yRot = 0.0;
- if (yRot <= -360.0f) yRot = 0.0;
+ if (yRot >= 360.0f)
+ yRot = 0.0;
+ if (yRot <= -360.0f)
+ yRot = 0.0;
- glClearColor(0.5,0.5,0.5,1);
+ glClearColor(0.5, 0.5, 0.5, 1);
glClearDepthf(1.0);
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//set what program to use
- glUseProgram( g_programObj );
- glActiveTexture ( GL_TEXTURE0 );
- glBindTexture ( GL_TEXTURE_2D,g_textureID );
- glUniform1i ( g_textureLoc, 0 );
+ glUseProgram(g_programObj);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, g_textureID);
+ glUniform1i(g_textureLoc, 0);
//create our perspective matrix
float mpv[16];
@@ -255,33 +257,44 @@ void PPAPIRender(uint32_t width, uint32_t height) {
float rot[16];
identity_matrix(mpv);
- glhPerspectivef2(&mpv[0], 45.0f, (float) (width) / (float) height, 1, 10);
+ glhPerspectivef2(&mpv[0], 45.0f, (float)(width) / (float) height, 1, 10);
translate_matrix(0, 0, -4.0, trs);
- rotate_matrix(xRot, yRot , 0.0f ,rot);
+ rotate_matrix(xRot, yRot, 0.0f, rot);
multiply_matrix(trs, rot, trs);
multiply_matrix(mpv, trs, mpv);
- glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*) mpv);
+ glUniformMatrix4fv(g_MVPLoc, 1, GL_FALSE, (GLfloat*)mpv);
//define the attributes of the vertex
glBindBuffer(GL_ARRAY_BUFFER, g_vboID);
- glVertexAttribPointer(g_positionLoc, 3, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,loc));
+ glVertexAttribPointer(g_positionLoc,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, loc));
glEnableVertexAttribArray(g_positionLoc);
- glVertexAttribPointer(g_texCoordLoc, 2, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,tu));
+ glVertexAttribPointer(g_texCoordLoc,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, tu));
glEnableVertexAttribArray(g_texCoordLoc);
- glVertexAttribPointer(g_colorLoc, 3, GL_FLOAT, GL_FALSE,
- sizeof(Vertex), (void*)offsetof(Vertex,color));
+ glVertexAttribPointer(g_colorLoc,
+ 3,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Vertex),
+ (void*)offsetof(Vertex, color));
glEnableVertexAttribArray(g_colorLoc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ibID);
- glDrawElements ( GL_TRIANGLES, 36, GL_UNSIGNED_BYTE ,0 );
+ glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);
}
-
-const char *LoadData(const char *url) {
- char *buf;
+const char* LoadData(const char* url) {
+ char* buf;
struct stat stat_buf;
int fp = open(url, O_RDONLY);
@@ -289,14 +302,13 @@ const char *LoadData(const char *url) {
int len = static_cast<int>(stat_buf.st_size);
buf = new char[len + 1];
- int read_size = read(fp, buf, len);
+ int read_size = read(fp, buf, len);
buf[len] = 0;
return buf;
}
-
PPAPI_MAIN_USE(PPAPI_CreateInstance3D, PPAPI_MAIN_DEFAULT_ARGS)
-int ppapi_main(int argc, const char *argv[]) {
+int ppapi_main(int argc, const char* argv[]) {
printf("Started main.\n");
// Mount URL loads to /http
@@ -307,7 +319,7 @@ int ppapi_main(int argc, const char *argv[]) {
g_FShaderData = LoadData("/http/fragment_shader_es2.frag");
g_quadVertices = BuildCube();
- fprintf(stderr,"Loaded\n");
+ fprintf(stderr, "Loaded\n");
g_Loaded = true;
return 0;
}
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/index.html b/native_client_sdk/src/examples/hello_world_instance3d/index.html
index b07ff78cda..fa132dc7fd 100644
--- a/native_client_sdk/src/examples/hello_world_instance3d/index.html
+++ b/native_client_sdk/src/examples/hello_world_instance3d/index.html
@@ -14,6 +14,15 @@ found in the LICENSE file.
<body data-width="640" data-height="480" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <p>
+ The Hello World instance3d example is similar to the Hello World GLES 2.0
+ example, but uses the ppapi_main and nacl_io libraries to simplify the code:
+ <ul>
+ <li>URL loading is handled by a synchronous read from an HTTP mount.</li>
+ <li>Instance creation is hidden; instead the functions ppapi_main and
+ PPAPIRender are used.</li>
+ </ul>
+ </p>
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc b/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc
index 32200c73d4..b87d496cb1 100644
--- a/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc
+++ b/native_client_sdk/src/examples/hello_world_instance3d/matrix.cc
@@ -11,41 +11,47 @@
#include <stdlib.h>
#include <string.h>
#include "matrix.h"
-#define deg_to_rad(x) (x * (M_PI/180.0f))
-
-void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
- GLfloat top, GLfloat znear, GLfloat zfar)
-{
- float temp, temp2, temp3, temp4;
- temp = 2.0f * znear;
- temp2 = right - left;
- temp3 = top - bottom;
- temp4 = zfar - znear;
- mat[0] = temp / temp2;
- mat[1] = 0.0f;
- mat[2] = 0.0f;
- mat[3] = 0.0f;
- mat[4] = 0.0f;
- mat[5] = temp / temp3;
- mat[6] = 0.0f;
- mat[7] = 0.0f;
- mat[8] = (right + left) / temp2;
- mat[9] = (top + bottom) / temp3;
- mat[10] = (-zfar - znear) / temp4;
- mat[11] = -1.0f;
- mat[12] = 0.0f;
- mat[13] = 0.0f;
- mat[14] = (-temp * zfar) / temp4;
- mat[15] = 0.0f;
+#define deg_to_rad(x) (x * (M_PI / 180.0f))
+
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar) {
+ float temp, temp2, temp3, temp4;
+ temp = 2.0f * znear;
+ temp2 = right - left;
+ temp3 = top - bottom;
+ temp4 = zfar - znear;
+ mat[0] = temp / temp2;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = 0.0f;
+ mat[5] = temp / temp3;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = (right + left) / temp2;
+ mat[9] = (top + bottom) / temp3;
+ mat[10] = (-zfar - znear) / temp4;
+ mat[11] = -1.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (-temp * zfar) / temp4;
+ mat[15] = 0.0f;
}
-void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
- GLfloat aspectRatio, GLfloat znear, GLfloat zfar)
-{
- float ymax, xmax;
- ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
- xmax = ymax * aspectRatio;
- glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar) {
+ float ymax, xmax;
+ ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
+ xmax = ymax * aspectRatio;
+ glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
}
void identity_matrix(Matrix_t mat) {
@@ -58,26 +64,26 @@ void identity_matrix(Matrix_t mat) {
void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
// Generate to a temporary first in case the output matrix and input
- // matrix are thes same.
+ // matrix are the same.
Matrix_t out;
- out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
- out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
- out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
- out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
+ out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
+ out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
+ out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
+ out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
- out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
- out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
- out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
- out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
+ out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
+ out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
+ out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
+ out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
- out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
- out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
- out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
- out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
+ out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
+ out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
+ out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
+ out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
- out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
- out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
+ out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
+ out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
@@ -108,8 +114,7 @@ void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
mat[5] = mat[0];
}
-void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg,
- Matrix_t mat) {
+void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat) {
GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
@@ -133,4 +138,3 @@ void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
mat[13] += y;
mat[14] += z;
}
-
diff --git a/native_client_sdk/src/examples/hello_world_instance3d/matrix.h b/native_client_sdk/src/examples/hello_world_instance3d/matrix.h
index 7db7985244..ed094eda09 100644
--- a/native_client_sdk/src/examples/hello_world_instance3d/matrix.h
+++ b/native_client_sdk/src/examples/hello_world_instance3d/matrix.h
@@ -21,12 +21,19 @@ typedef GLfloat Matrix_t[16];
/// Since GLES2 doesn't have all the nifty matrix transform functions that GL
/// has, we emulate some of them here for the sake of sanity from:
/// http://www.opengl.org/wiki/GluPerspective_code
-void glhFrustumf2(Matrix_t mat, GLfloat left, GLfloat right, GLfloat bottom,
- GLfloat top, GLfloat znear, GLfloat zfar);
-
-void glhPerspectivef2(Matrix_t mat, GLfloat fovyInDegrees,
- GLfloat aspectRatio, GLfloat znear, GLfloat zfar);
-
+void glhFrustumf2(Matrix_t mat,
+ GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat znear,
+ GLfloat zfar);
+
+void glhPerspectivef2(Matrix_t mat,
+ GLfloat fovyInDegrees,
+ GLfloat aspectRatio,
+ GLfloat znear,
+ GLfloat zfar);
void identity_matrix(Matrix_t mat);
void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat);
@@ -34,4 +41,3 @@ void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat);
void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat);
#endif // EXAMPLES_HELLO_WORLD_GLES_MATRIX_H
-
diff --git a/native_client_sdk/src/examples/hello_world_interactive/example.dsc b/native_client_sdk/src/examples/hello_world_interactive/example.dsc
index 6f0d65c3ff..da6e5547d0 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/example.dsc
+++ b/native_client_sdk/src/examples/hello_world_interactive/example.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
'TARGETS': [
{
@@ -18,13 +19,6 @@
'DEST': 'examples',
'NAME': 'hello_world_interactive',
'TITLE': 'Interactive Hello World in C++',
- 'DESC': """
-The Interactive Hello World C++ example demonstrates the basic structure
-of all Native Client applications. This example loads a Native Client module
-which uses two way interaction with JavaScript whenever a button is clicked.
-The NaCl module will respond with the number 42 or the reversed version of the
-string in the text box when the appropriate button is clicked.""",
- 'FOCUS': 'Basic HTML, JavaScript, C++ PPAPI, and Messaging API.',
'GROUP': 'Tools'
}
diff --git a/native_client_sdk/src/examples/hello_world_interactive/example.js b/native_client_sdk/src/examples/hello_world_interactive/example.js
index 9e2a88f99b..7058f732f5 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/example.js
+++ b/native_client_sdk/src/examples/hello_world_interactive/example.js
@@ -25,7 +25,12 @@ function reverseText() {
common.naclModule.postMessage('reverseText:' + inputBox.value);
}
-// Called by the common.js module.
-function handleMessage(message_event) {
- alert(message_event.data);
+function handleMessage(e) {
+ if (typeof e.data === 'string') {
+ // Received a reversed message.
+ common.logMessage('Received "' + e.data + '"\n');
+ } else if (typeof e.data === 'number') {
+ // Recived 42.
+ common.logMessage('Received "' + e.data + '"\n');
+ }
}
diff --git a/native_client_sdk/src/examples/hello_world_interactive/hello_world.cc b/native_client_sdk/src/examples/hello_world_interactive/hello_world.cc
index 438b7bff08..cd09c78e29 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/hello_world.cc
+++ b/native_client_sdk/src/examples/hello_world_interactive/hello_world.cc
@@ -35,9 +35,7 @@ static const char kMessageArgumentSeparator = ':';
/// This is the module's function that invokes FortyTwo and converts the return
/// value from an int32_t to a pp::Var for return.
-pp::Var MarshallFortyTwo() {
- return pp::Var(FortyTwo());
-}
+pp::Var MarshallFortyTwo() { return pp::Var(FortyTwo()); }
/// This function is passed the arg list from the JavaScript call to
/// @a reverseText.
@@ -94,7 +92,7 @@ void HelloWorldInstance::HandleMessage(const pp::Var& var_message) {
}
// Post the return result back to the browser. Note that HandleMessage() is
// always called on the main thread, so it's OK to post the return message
- // directly from here. The return post is asynhronous: PostMessage returns
+ // directly from here. The return post is asynchronous: PostMessage returns
// immediately.
PostMessage(return_var);
}
@@ -105,9 +103,7 @@ void HelloWorldInstance::HandleMessage(const pp::Var& var_message) {
/// <code>type="application/x-nacl"</code>.
class HelloWorldModule : public pp::Module {
public:
- HelloWorldModule() : pp::Module() {
- printf("Got here.\n");
- }
+ HelloWorldModule() : pp::Module() { printf("Got here.\n"); }
virtual ~HelloWorldModule() {}
/// Create and return a HelloWorldInstance object.
@@ -120,7 +116,6 @@ class HelloWorldModule : public pp::Module {
};
} // namespace hello_world
-
namespace pp {
/// Factory function called by the browser when the module is first loaded.
/// The browser keeps a singleton of this module. It calls the
@@ -129,7 +124,5 @@ namespace pp {
/// point for your NaCl module with the browser.
/// @return new HelloWorldModule.
/// @note The browser is responsible for deleting returned @a Module.
-Module* CreateModule() {
- return new hello_world::HelloWorldModule();
-}
+Module* CreateModule() { return new hello_world::HelloWorldModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/hello_world_interactive/helper_functions.cc b/native_client_sdk/src/examples/hello_world_interactive/helper_functions.cc
index 2b43c6052a..898749367c 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/helper_functions.cc
+++ b/native_client_sdk/src/examples/hello_world_interactive/helper_functions.cc
@@ -8,9 +8,7 @@
namespace hello_world {
-int32_t FortyTwo() {
- return 42;
-}
+int32_t FortyTwo() { return 42; }
std::string ReverseText(const std::string& text) {
std::string reversed_string(text);
@@ -19,4 +17,3 @@ std::string ReverseText(const std::string& text) {
return reversed_string;
}
} // namespace hello_world
-
diff --git a/native_client_sdk/src/examples/hello_world_interactive/helper_functions.h b/native_client_sdk/src/examples/hello_world_interactive/helper_functions.h
index 50763005f1..78b03f1a69 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/helper_functions.h
+++ b/native_client_sdk/src/examples/hello_world_interactive/helper_functions.h
@@ -31,4 +31,3 @@ std::string ReverseText(const std::string& text);
} // namespace hello_world
#endif // EXAMPLES_HELLO_WORLD_HELPER_FUNCTIONS_H_
-
diff --git a/native_client_sdk/src/examples/hello_world_interactive/index.html b/native_client_sdk/src/examples/hello_world_interactive/index.html
index 44e0b30d0c..bba2379389 100644
--- a/native_client_sdk/src/examples/hello_world_interactive/index.html
+++ b/native_client_sdk/src/examples/hello_world_interactive/index.html
@@ -15,13 +15,22 @@
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <!-- The NaCl plugin will be embedded inside the element with id "listener".
- See common.js.-->
- <div id="listener"></div>
+ <p>The Interactive Hello World C++ example demonstrates the basic structure
+ of all Native Client applications. This example loads a Native Client
+ module which uses two way interaction with JavaScript whenever a button
+ is clicked. The NaCl module will respond with the number 42 or the
+ reversed version of the string in the text box when the appropriate
+ button is clicked.</p>
<textarea id="inputBox" rows="4" cols="50">Hello World</textarea>
<div>
<button id="fortyTwo">Call fortyTwo()</button>
<button id="reverseText">Call reverseText()</button>
<div/>
+ <h2>Output:</h2>
+ <pre id="log" style="font-weight:bold"></pre>
+
+ <!-- The NaCl plugin will be embedded inside the element with id "listener".
+ See common.js.-->
+ <div id="listener"></div>
</body>
</html>
diff --git a/native_client_sdk/src/examples/hello_world_stdio/example.dsc b/native_client_sdk/src/examples/hello_world_stdio/example.dsc
deleted file mode 100644
index bc887275e7..0000000000
--- a/native_client_sdk/src/examples/hello_world_stdio/example.dsc
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc'],
- 'TARGETS': [
- {
- 'NAME' : 'hello_world_stdio',
- 'TYPE' : 'main',
- 'SOURCES' : ['hello_world.c'],
- 'LIBS': ['ppapi_main', 'nacl_io', 'ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'hello_world_stdio',
- 'TITLE': 'Hello World STDIO.',
- 'DESC': """
-
- The Hello World Stdio example is the simplest one in the SDK. It uses the
-ppapi_main library which creates an Module and Instance, using default values
-to simplify setup and communication with the PPAPI system. In addition, it
-uses the nacl_io library to remap IO to the Pepper API. This
-simplifies IO by providing a standard blocking API and allowing STDERR to go to
-the JavaScript console by default.""",
- 'FOCUS': 'Basic HTML, JavaScript, Minimal App.',
- 'GROUP': 'Tools'
-}
-
diff --git a/native_client_sdk/src/examples/hello_world_stdio/example.js b/native_client_sdk/src/examples/hello_world_stdio/example.js
deleted file mode 100644
index 13a99975e3..0000000000
--- a/native_client_sdk/src/examples/hello_world_stdio/example.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var kMaxArraySize = 20;
-var messageArray = new Array();
-
-// Once we load, hide the plugin
-function moduleDidLoad() {
- common.hideModule();
-}
-
-// Called by the common.js module.
-function handleMessage(message) {
- // Show last |kMaxArraySize| events in html.
- messageArray.push(message.data);
- if (messageArray.length > kMaxArraySize) {
- messageArray.shift();
- }
- var newData = messageArray.join('<BR>');
- document.getElementById('outputString').innerHTML = newData;
- // Print event to console.
- console.log(message.data);
-}
diff --git a/native_client_sdk/src/examples/input_events/example.dsc b/native_client_sdk/src/examples/input_events/example.dsc
deleted file mode 100644
index cdcd287073..0000000000
--- a/native_client_sdk/src/examples/input_events/example.dsc
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux', 'win'],
- 'TARGETS': [
- {
- 'NAME' : 'input_events',
- 'TYPE' : 'main',
- 'SOURCES' : [
- 'custom_events.cc',
- 'custom_events.h',
- 'input_events.cc',
- 'shared_queue.h',
- ],
- 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'input_events',
- 'TITLE': 'Input Events',
- 'DESC': """The Input Events example shows how to handle input events in a
-multi-threaded application. The main thread converts input events to
-non-pepper events and puts them on a queue. The worker thread pulls them off of
-the queue, converts them to a string, and then uses CallOnMainThread so that
-PostMessage can be send the result of the worker thread to the browser.""",
- 'FOCUS': """Multi-threading, keyboard and mouse input, view change, and focus
-events.""",
- 'GROUP': 'API',
-}
-
diff --git a/native_client_sdk/src/examples/input_events/shared_queue.h b/native_client_sdk/src/examples/input_events/shared_queue.h
deleted file mode 100644
index 48b70b3620..0000000000
--- a/native_client_sdk/src/examples/input_events/shared_queue.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SHARED_QUEUE_H
-#define SHARED_QUEUE_H
-
-#include <pthread.h>
-#include <cassert>
-#include <deque>
-
-namespace event_queue {
-
-// This file provides a queue that uses a mutex and condition variable so that
-// one thread can put pointers into the queue and another thread can pull items
-// out of the queue.
-
-// Specifies whether we want to wait for the queue.
-enum QueueWaitingFlag {
- kWait = 0,
- kDontWait
-};
-
-// Indicates if we got an item, did not wait, or if the queue was cancelled.
-enum QueueGetResult {
- kReturnedItem = 0,
- kDidNotWait = 1,
- kQueueWasCancelled
-};
-
-// A simple scoped mutex lock.
-// For most cases, pp::AutoLock in "ppapi/utility/threading/lock.h" can be
-// used; LockingQueue needs to use the pthread_mutex_t directly in
-// pthread_cond_wait so we reimplement a scoped lock here.
-class ScopedLock {
- public:
- explicit ScopedLock(pthread_mutex_t* mutex)
- : mutex_(mutex) {
- const int kPthreadMutexSuccess = 0;
- if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) {
- mutex_ = NULL;
- }
- }
- ~ScopedLock() {
- if (mutex_ != NULL) {
- pthread_mutex_unlock(mutex_);
- }
- }
-
- private:
- pthread_mutex_t* mutex_; // Weak reference, passed in to constructor.
-
- // Disable copy and assign.
- ScopedLock& operator =(const ScopedLock&);
- ScopedLock(const ScopedLock&);
-};
-
-// LockingQueue contains a collection of <T>, such as a collection of
-// objects or pointers. The Push() method is used to add items to the
-// queue in a thread-safe manner. The GetItem() is used to retrieve
-// items from the queue in a thread-safe manner.
-template <class T>
-class LockingQueue {
- public:
- LockingQueue() : quit_(false) {
- int result = pthread_mutex_init(&queue_mutex_, NULL);
- assert(result == 0);
- result = pthread_cond_init(&queue_condition_var_, NULL);
- assert(result == 0);
- }
- ~LockingQueue() {
- pthread_mutex_destroy(&queue_mutex_);
- }
-
- // The producer (who instantiates the queue) calls this to tell the
- // consumer that the queue is no longer being used.
- void CancelQueue() {
- ScopedLock scoped_mutex(&queue_mutex_);
- quit_ = true;
- // Signal the condition var so that if a thread is waiting in
- // GetItem the thread will wake up and see that the queue has
- // been cancelled.
- pthread_cond_signal(&queue_condition_var_);
- }
-
- // The consumer calls this to see if the queue has been cancelled by
- // the producer. If so, the thread should not call GetItem and may
- // need to terminate -- i.e. in a case where the producer created
- // the consumer thread.
- bool IsCancelled() {
- ScopedLock scoped_mutex(&queue_mutex_);
- return quit_;
- }
-
- // Grabs the mutex and pushes a new item to the end of the queue if the
- // queue is not full. Signals the condition variable so that a thread
- // that is waiting will wake up and grab the item.
- void Push(const T& item) {
- ScopedLock scoped_mutex(&queue_mutex_);
- the_queue_.push_back(item);
- pthread_cond_signal(&queue_condition_var_);
- }
-
- // Tries to pop the front element from the queue; returns an enum:
- // kReturnedItem if an item is returned in |item_ptr|,
- // kDidNotWait if |wait| was kDontWait and the queue was empty,
- // kQueueWasCancelled if the producer called CancelQueue().
- // If |wait| is kWait, GetItem will wait to return until the queue
- // contains an item (unless the queue is cancelled).
- QueueGetResult GetItem(T* item_ptr, QueueWaitingFlag wait) {
- ScopedLock scoped_mutex(&queue_mutex_);
- // Use a while loop to get an item. If the user does not want to wait,
- // we will exit from the loop anyway, unlocking the mutex.
- // If the user does want to wait, we will wait for pthread_cond_wait,
- // and the while loop will check is_empty_no_locking() one more
- // time so that a spurious wake-up of pthread_cond_wait is handled.
- // If |quit_| has been set, break out of the loop.
- while (!quit_ && is_empty_no_locking()) {
- // If user doesn't want to wait, return...
- if (kDontWait == wait) {
- return kDidNotWait;
- }
- // Wait for signal to occur.
- pthread_cond_wait(&queue_condition_var_, &queue_mutex_);
- }
- // Check to see if quit_ woke us up
- if (quit_) {
- return kQueueWasCancelled;
- }
-
- // At this point, the queue was either not empty or, if it was empty,
- // we called pthread_cond_wait (which released the mutex, waited for the
- // signal to occur, and then atomically reacquired the mutex).
- // Thus, if we are here, the queue cannot be empty because we either
- // had the mutex and verified it was not empty, or we waited for the
- // producer to put an item in and signal a single thread (us).
- T& item = the_queue_.front();
- *item_ptr = item;
- the_queue_.pop_front();
- return kReturnedItem;
- }
-
- private:
- std::deque<T> the_queue_;
- bool quit_;
- pthread_mutex_t queue_mutex_;
- pthread_cond_t queue_condition_var_;
-
- // This is used by methods that already have the lock.
- bool is_empty_no_locking() const {
- return the_queue_.empty();
- }
-};
-
-} // end of unnamed namespace
-
-#endif // SHARED_QUEUE_H
-
diff --git a/native_client_sdk/src/examples/load_progress/example.dsc b/native_client_sdk/src/examples/load_progress/example.dsc
deleted file mode 100644
index 22372cce69..0000000000
--- a/native_client_sdk/src/examples/load_progress/example.dsc
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'load_progress',
- 'TYPE' : 'main',
- 'SOURCES' : ['load_progress.cc'],
- 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'load_progress',
- 'TITLE': 'Load Progress',
- 'DESC': """
-The Load Progress example demonstrates how to listen for and handle
-events that occur while a NaCl module loads. This example listens for
-different load event types and dispatches different events to their
-respective handler. This example also checks for valid browser version and
-shows how to calculate and display loading progress.""",
- 'FOCUS': 'Progress event handling.',
- 'GROUP': 'Concepts'
-}
-
diff --git a/native_client_sdk/src/examples/mouselock/example.dsc b/native_client_sdk/src/examples/mouselock/example.dsc
deleted file mode 100644
index 03fb60a10e..0000000000
--- a/native_client_sdk/src/examples/mouselock/example.dsc
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'mouselock',
- 'TYPE' : 'main',
- 'SOURCES' : ['mouselock.cc', 'mouselock.h'],
- 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DEST': 'examples',
- 'NAME': 'mouselock',
- 'TITLE': 'Mouse Lock',
- 'DESC': """
-The Mouselock example demonstrates how to use the MouseLock API to hide
-the mouse cursor. Mouse lock is only available in full-screen mode. You can
-lock and unlock the mouse while in full-screen mode by pressing the Enter key.
-""",
- 'FOCUS': 'Mouse lock, Full-screen.',
- 'GROUP': 'Concepts'
-}
-
diff --git a/native_client_sdk/src/examples/pong/example.dsc b/native_client_sdk/src/examples/pong/example.dsc
index cd4dd4e5c5..d7b0d64733 100644
--- a/native_client_sdk/src/examples/pong/example.dsc
+++ b/native_client_sdk/src/examples/pong/example.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'pnacl'],
'TARGETS': [
{
diff --git a/native_client_sdk/src/examples/pong/pong_input.cc b/native_client_sdk/src/examples/pong/pong_input.cc
index 4d3f9035a5..be58f5de28 100644
--- a/native_client_sdk/src/examples/pong/pong_input.cc
+++ b/native_client_sdk/src/examples/pong/pong_input.cc
@@ -21,8 +21,7 @@ const int kPaddleAIDeadZone = 20;
}
PongInputKeyboard::PongInputKeyboard(PongInputKeyboardDelegate* delegate)
- : delegate_(delegate) {
-}
+ : delegate_(delegate) {}
MoveDirection PongInputKeyboard::GetMove(const PongModel& model,
bool is_left_paddle) {
@@ -38,8 +37,8 @@ MoveDirection PongInputAI::GetMove(const PongModel& model,
bool is_left_paddle) {
// A highly advanced AI algorithm that moves the paddle toward the y position
// of the ball.
- const PaddleModel& paddle = is_left_paddle ? model.left_paddle() :
- model.right_paddle();
+ const PaddleModel& paddle =
+ is_left_paddle ? model.left_paddle() : model.right_paddle();
int ball_center_y = model.ball().rect.CenterPoint().y();
int paddle_center_y = paddle.rect.CenterPoint().y();
int distance_y = labs(paddle_center_y - ball_center_y);
diff --git a/native_client_sdk/src/examples/pong/pong_instance.cc b/native_client_sdk/src/examples/pong/pong_instance.cc
index 3da5df954d..5f5cf62c7c 100644
--- a/native_client_sdk/src/examples/pong/pong_instance.cc
+++ b/native_client_sdk/src/examples/pong/pong_instance.cc
@@ -55,8 +55,8 @@ bool PongInstance::Init(uint32_t argc, const char* argn[], const char* argv[]) {
void PongInstance::DidChangeView(const pp::View& view) {
if (!view_->DidChangeView(this, view, is_initial_view_change_)) {
- PostMessage(pp::Var(
- "ERROR DidChangeView failed. Could not bind graphics?"));
+ PostMessage(
+ pp::Var("ERROR DidChangeView failed. Could not bind graphics?"));
return;
}
@@ -106,18 +106,13 @@ void PongInstance::OnScoreChanged() {
UpdateScoreDisplay();
}
-void PongInstance::OnPlayerScored() {
- model_->ResetPositions();
-}
+void PongInstance::OnPlayerScored() { model_->ResetPositions(); }
-bool PongInstance::IsKeyDown(int key_code) {
- return key_map_[key_code];
-}
+bool PongInstance::IsKeyDown(int key_code) { return key_map_[key_code]; }
void PongInstance::ScheduleUpdate() {
pp::Module::Get()->core()->CallOnMainThread(
- kUpdateInterval,
- factory_.NewCallback(&PongInstance::UpdateCallback));
+ kUpdateInterval, factory_.NewCallback(&PongInstance::UpdateCallback));
}
void PongInstance::UpdateCallback(int32_t result) {
@@ -130,13 +125,14 @@ void PongInstance::UpdateCallback(int32_t result) {
model_->Update(left_move, right_move);
}
-void PongInstance::ResetScore() {
- model_->SetScore(0, 0);
-}
+void PongInstance::ResetScore() { model_->SetScore(0, 0); }
void PongInstance::UpdateScoreDisplay() {
char buffer[100];
- snprintf(&buffer[0], sizeof(buffer), "You %d: Computer %d",
- model_->left_score(), model_->right_score());
+ snprintf(&buffer[0],
+ sizeof(buffer),
+ "You %d: Computer %d",
+ model_->left_score(),
+ model_->right_score());
PostMessage(pp::Var(buffer));
}
diff --git a/native_client_sdk/src/examples/pong/pong_model.cc b/native_client_sdk/src/examples/pong/pong_model.cc
index 20592fad8f..6af4b11d75 100644
--- a/native_client_sdk/src/examples/pong/pong_model.cc
+++ b/native_client_sdk/src/examples/pong/pong_model.cc
@@ -60,11 +60,12 @@ const float kPaddleSpinDown = 0.8f;
* @return The left position of the object, in the range [0, region_max -
* object_width].
*/
-int GetFractionalPos(int region_min, int region_max,
+int GetFractionalPos(int region_min,
+ int region_max,
int object_width,
float fraction) {
return region_min +
- static_cast<int>((region_max - object_width - region_min) * fraction);
+ static_cast<int>((region_max - object_width - region_min) * fraction);
}
/**
@@ -77,22 +78,23 @@ int GetFractionalPos(int region_min, int region_max,
* @param[in] y_fraction A value in the range [0, 1]. 0 is on the top, 1 is on
* the bottom of the court.
*/
-void SetFractionalPosition(const pp::Rect& court, pp::Rect* object,
- float x_fraction, float y_fraction) {
- object->set_x(GetFractionalPos(court.x(), court.right(), object->width(),
- x_fraction));
- object->set_y(GetFractionalPos(court.y(), court.bottom(), object->height(),
- y_fraction));
+void SetFractionalPosition(const pp::Rect& court,
+ pp::Rect* object,
+ float x_fraction,
+ float y_fraction) {
+ object->set_x(
+ GetFractionalPos(court.x(), court.right(), object->width(), x_fraction));
+ object->set_y(GetFractionalPos(
+ court.y(), court.bottom(), object->height(), y_fraction));
}
} // namespace
-PaddleModel::PaddleModel()
- : rect(kPaddleWidth, kPaddleHeight) {
-}
+PaddleModel::PaddleModel() : rect(kPaddleWidth, kPaddleHeight) {}
void PaddleModel::SetPosition(const pp::Rect& court,
- float x_fraction, float y_fraction) {
+ float x_fraction,
+ float y_fraction) {
SetFractionalPosition(court, &rect, x_fraction, y_fraction);
}
@@ -131,11 +133,11 @@ PaddleCollision PaddleModel::GetPaddleCollision(float collision_y) const {
BallModel::BallModel()
: rect(kBallWidth, kBallHeight),
dx(kBallUpdateDistance),
- dy(kBallUpdateDistance) {
-}
+ dy(kBallUpdateDistance) {}
void BallModel::SetPosition(const pp::Rect& court,
- float x_fraction, float y_fraction) {
+ float x_fraction,
+ float y_fraction) {
SetFractionalPosition(court, &rect, x_fraction, y_fraction);
}
@@ -192,10 +194,10 @@ float BallModel::GetCourtCollisionTime(const pp::Rect& court) const {
// When the ball is moving up, only check for collision with the top of the
// court. Likewise, if the ball is moving down only check for collision with
// the bottom of the court.
- float y_collision_t = dy < 0 ?
- (court.y() - rect.y()) / static_cast<float>(dy) :
- (court.bottom() - rect.bottom()) / static_cast<float>(dy);
-
+ float y_collision_t =
+ dy < 0 ? (court.y() - rect.y()) / static_cast<float>(dy)
+ : (court.bottom() - rect.bottom()) / static_cast<float>(dy);
+
return y_collision_t;
}
@@ -218,14 +220,9 @@ void BallModel::ApplyPaddleCollision(PaddleCollision collision) {
}
PongModel::PongModel(PongModelDelegate* delegate)
- : delegate_(delegate),
- left_score_(0),
- right_score_(0) {
-}
+ : delegate_(delegate), left_score_(0), right_score_(0) {}
-void PongModel::SetCourtSize(const pp::Size& size) {
- court_.set_size(size);
-}
+void PongModel::SetCourtSize(const pp::Size& size) { court_.set_size(size); }
void PongModel::SetScore(int left_score, int right_score) {
left_score_ = left_score;
diff --git a/native_client_sdk/src/examples/pong/pong_model.h b/native_client_sdk/src/examples/pong/pong_model.h
index d864e27f09..789f69bf55 100644
--- a/native_client_sdk/src/examples/pong/pong_model.h
+++ b/native_client_sdk/src/examples/pong/pong_model.h
@@ -119,7 +119,7 @@ class PongModelDelegate {
* when a player scores. */
virtual void OnScoreChanged() = 0;
/** Called only when a player scores, not when the score is changed
- * programatically. */
+ * programmatically. */
virtual void OnPlayerScored() = 0;
};
diff --git a/native_client_sdk/src/examples/pong/pong_module.cc b/native_client_sdk/src/examples/pong/pong_module.cc
index 2d05a29685..9d99526c9c 100644
--- a/native_client_sdk/src/examples/pong/pong_module.cc
+++ b/native_client_sdk/src/examples/pong/pong_module.cc
@@ -26,7 +26,5 @@ class PongModule : public pp::Module {
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
-Module* CreateModule() {
- return new PongModule();
-}
+Module* CreateModule() { return new PongModule(); }
} // namespace pp
diff --git a/native_client_sdk/src/examples/pong/pong_view.cc b/native_client_sdk/src/examples/pong/pong_view.cc
index 35fec2cdc1..1c76d73d75 100644
--- a/native_client_sdk/src/examples/pong/pong_view.cc
+++ b/native_client_sdk/src/examples/pong/pong_view.cc
@@ -27,8 +27,7 @@ PongView::PongView(PongModel* model)
model_(model),
graphics_2d_(NULL),
pixel_buffer_(NULL),
- needs_erase_(false) {
-}
+ needs_erase_(false) {}
PongView::~PongView() {
delete graphics_2d_;
@@ -44,8 +43,8 @@ bool PongView::DidChangeView(pp::Instance* instance,
return true;
delete graphics_2d_;
- graphics_2d_ = new pp::Graphics2D(instance, new_size,
- true); // is_always_opaque
+ graphics_2d_ =
+ new pp::Graphics2D(instance, new_size, true); // is_always_opaque
if (!instance->BindGraphics(*graphics_2d_)) {
delete graphics_2d_;
graphics_2d_ = NULL;
@@ -56,7 +55,8 @@ bool PongView::DidChangeView(pp::Instance* instance,
// write to this buffer directly, and copy regions of it to the graphics
// context's backing store to draw to the screen.
delete pixel_buffer_;
- pixel_buffer_ = new pp::ImageData(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ pixel_buffer_ = new pp::ImageData(instance,
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL,
new_size,
true); // init_to_zero
@@ -177,9 +177,7 @@ void PongView::DrawPaddle(const PaddleModel& paddle) {
DrawRect(paddle.rect, kWhite);
}
-void PongView::EraseBall(const BallModel& ball) {
- DrawRect(ball.rect, kBlack);
-}
+void PongView::EraseBall(const BallModel& ball) { DrawRect(ball.rect, kBlack); }
void PongView::ErasePaddle(const PaddleModel& paddle) {
DrawRect(paddle.rect, kBlack);
diff --git a/native_client_sdk/src/examples/pong/pong_view.h b/native_client_sdk/src/examples/pong/pong_view.h
index 8f80e6f62f..7197d3aee7 100644
--- a/native_client_sdk/src/examples/pong/pong_view.h
+++ b/native_client_sdk/src/examples/pong/pong_view.h
@@ -22,7 +22,8 @@ class PongView {
explicit PongView(PongModel* model);
~PongView();
- bool DidChangeView(pp::Instance* instance, const pp::View& view,
+ bool DidChangeView(pp::Instance* instance,
+ const pp::View& view,
bool first_view_change);
pp::Size GetSize() const;
void StartDrawLoop();
diff --git a/native_client_sdk/src/examples/resources/background.js b/native_client_sdk/src/examples/resources/background.js
new file mode 100644
index 0000000000..1fc5a19b3a
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/background.js
@@ -0,0 +1,13 @@
+// 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 onLaunched(launchData) {
+ chrome.app.window.create('index.html', {
+ width: 1024,
+ height: 800,
+ frame: 'none'
+ });
+}
+
+chrome.app.runtime.onLaunched.addListener(onLaunched);
diff --git a/native_client_sdk/src/examples/resources/button_close.png b/native_client_sdk/src/examples/resources/button_close.png
new file mode 100644
index 0000000000..02a927ed18
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/button_close.png
Binary files differ
diff --git a/native_client_sdk/src/examples/resources/button_close_hover.png b/native_client_sdk/src/examples/resources/button_close_hover.png
new file mode 100644
index 0000000000..2df566d6e4
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/button_close_hover.png
Binary files differ
diff --git a/native_client_sdk/src/examples/resources/icon128.png b/native_client_sdk/src/examples/resources/icon128.png
new file mode 100644
index 0000000000..a10c52a5de
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/icon128.png
Binary files differ
diff --git a/native_client_sdk/src/examples/resources/index.css b/native_client_sdk/src/examples/resources/index.css
new file mode 100644
index 0000000000..93f26634a2
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/index.css
@@ -0,0 +1,88 @@
+/* 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. */
+
+html {
+ color: #222;
+ font-family: Arial, san-serif;
+}
+body {
+ margin: 0;
+}
+.main-column {
+ background-color: #fff;
+ display: -webkit-flex;
+ height: 100%;
+ position: absolute;
+ -webkit-flex-direction: column;
+ width: 100%;
+}
+.header, .footer, .left-border, .right-border {
+ background-color: #444;
+ -webkit-flex: none;
+}
+.header {
+ color: #fff;
+ font-size: 150%;
+ font-weight: bold;
+ padding: 2px;
+ -webkit-app-region: drag;
+}
+.left-border, .right-border {
+ width: 2px;
+}
+.footer {
+ height: 2px;
+}
+.close-button {
+ background-image: url('button_close.png');
+ float: right;
+ height: 17px;
+ margin: 8px 2px;
+ text-align: center;
+ -webkit-app-region: no-drag;
+ width: 17px;
+}
+.close-button:hover {
+ background-image: url('button_close_hover.png');
+}
+.main {
+ display: -webkit-flex;
+ min-height: 0;
+ -webkit-flex: 1;
+ -webkit-flex-direction: row;
+}
+.nav-wrapper {
+ overflow-y: auto;
+}
+.nav {
+ padding: 8px;
+ -webkit-flex: initial;
+}
+.nav-group-header {
+ font-weight: bold;
+ padding: 4px 0;
+}
+.nav-item {
+ cursor: pointer;
+ font-size: 13px;
+ padding: 4px 0;
+}
+.nav-item:hover {
+ background-color: #eee;
+}
+.selected {
+ color: #dd4b39;
+}
+.nav-title {
+ padding-left: 8px;
+}
+.iframe-wrapper {
+ overflow-y: auto;
+ -webkit-flex: auto;
+}
+iframe {
+ border: none;
+ width: 100%;
+ height: auto;
+}
diff --git a/native_client_sdk/src/examples/resources/index.html.template b/native_client_sdk/src/examples/resources/index.html.template
new file mode 100644
index 0000000000..207afdb6c5
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/index.html.template
@@ -0,0 +1,45 @@
+<!--
+ 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.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Native Client SDK</title>
+ <link href="index.css" rel="stylesheet" type="text/css">
+ <script src="index.js"></script>
+</head>
+<body>
+ <div class="main-column">
+ <div class="header">
+ Native Client SDK
+ <div class="close-button"></div>
+ </div>
+ <div class="main">
+ <div class="left-border"></div>
+ <div class="nav-wrapper">
+ <div class="nav">
+[[for section in section_map:]]
+ <div class="nav-group-header">{{section}}</div>
+[[ for desc in section_map[section]:]]
+[[ index_path = (desc['DEST'] + '/' + desc['NAME'])]]
+[[ index_path = '/'.join(index_path.split('/')[1:])]]
+ <div class="nav-item" data-href="{{index_path}}/index.html">
+ <div class="nav-title">
+ {{desc['TITLE']}}
+ </div>
+ </div>
+[[]]
+ </div>
+ </div>
+ <div class="iframe-wrapper">
+ <iframe scrolling="no">
+ </iframe>
+ </div>
+ <div class="right-border"></div>
+ </div>
+ <div class="footer"></div>
+ </div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/resources/index.js b/native_client_sdk/src/examples/resources/index.js
new file mode 100644
index 0000000000..ab4b4ff618
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/index.js
@@ -0,0 +1,72 @@
+// 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 iframeUpdateIntervalID;
+
+function selectExample(el) {
+ setIframeSrc(el.dataset.href);
+ deselectAllNavItems();
+ selectNavItem(el);
+}
+
+function selectNavItem(el) {
+ el.classList.add('selected');
+}
+
+function deselectAllNavItems() {
+ var navItemEls = document.querySelectorAll('.nav-item');
+ for (var i = 0; i < navItemEls.length; ++i) {
+ navItemEls[i].classList.remove('selected');
+ }
+}
+
+function setIframeSrc(src) {
+ var iframeEl = document.querySelector('iframe');
+
+ window.clearInterval(iframeUpdateIntervalID);
+ iframeEl.style.height = '';
+ iframeEl.src = src;
+}
+
+document.addEventListener('DOMContentLoaded', function () {
+ var iframeEl = document.querySelector('iframe');
+ var iframeWrapperEl = document.querySelector('.iframe-wrapper');
+ var navItemEls = document.querySelectorAll('.nav-item');
+
+ for (var i = 0; i < navItemEls.length; ++i) {
+ navItemEls[i].addEventListener('click', function (e) {
+ selectExample(this);
+ });
+ }
+
+ iframeEl.addEventListener('load', function () {
+ var iframeDocument = this.contentWindow.document;
+ var iframeBodyEl = iframeDocument.body;
+ iframeEl.style.height = iframeBodyEl.scrollHeight + 'px';
+
+ // HACK: polling the body height to update the iframe. There's got to be a
+ // better way to do this...
+ var prevBodyHeight;
+ var prevWrapperHeight;
+ iframeUpdateIntervalID = window.setInterval(function () {
+ var bodyHeight = iframeBodyEl.getBoundingClientRect().height;
+ var wrapperHeight = iframeWrapperEl.clientHeight;
+ if (bodyHeight != prevBodyHeight || wrapperHeight != prevWrapperHeight) {
+ // HACK: magic 4... without it, the scrollbar is always visible. :(
+ var newHeight = Math.max(wrapperHeight - 4, bodyHeight);
+ iframeEl.style.height = newHeight + 'px';
+ prevBodyHeight = bodyHeight;
+ prevWrapperHeight = wrapperHeight;
+ }
+ }, 100); // .1s
+ }, false);
+
+ var closeButtonEl = document.querySelector('.close-button');
+ closeButtonEl.addEventListener('click', function () {
+ window.close();
+ });
+
+ // select the first example.
+ selectExample(document.querySelector('.nav-item'));
+});
diff --git a/native_client_sdk/src/examples/resources/manifest.json.template b/native_client_sdk/src/examples/resources/manifest.json.template
new file mode 100644
index 0000000000..8287eae7d7
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/manifest.json.template
@@ -0,0 +1,20 @@
+{
+ "name": "Native Client SDK",
+ "version": "{{version}}",
+ "manifest_version": 2,
+ "description": "Native Client SDK examples, showing API use and key concepts.",
+ "offline_enabled": true,
+ "icons": {
+ "128": "icon128.png"
+ },
+ "app": {
+ "background": {
+ "scripts": ["background.js"]
+ }
+ },
+ "permissions": [
+ "fullscreen",
+ "pointerLock",
+ "unlimitedStorage"
+ ]
+}
diff --git a/native_client_sdk/src/examples/resources/promo440.png b/native_client_sdk/src/examples/resources/promo440.png
new file mode 100644
index 0000000000..2d9b521375
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/promo440.png
Binary files differ
diff --git a/native_client_sdk/src/examples/resources/screenshot_gles_1280.png b/native_client_sdk/src/examples/resources/screenshot_gles_1280.png
new file mode 100644
index 0000000000..853a6bc2f8
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/screenshot_gles_1280.png
Binary files differ
diff --git a/native_client_sdk/src/examples/resources/screenshot_pi_1280.png b/native_client_sdk/src/examples/resources/screenshot_pi_1280.png
new file mode 100644
index 0000000000..4dad188131
--- /dev/null
+++ b/native_client_sdk/src/examples/resources/screenshot_pi_1280.png
Binary files differ
diff --git a/native_client_sdk/src/examples/sine_synth/example.dsc b/native_client_sdk/src/examples/sine_synth/example.dsc
deleted file mode 100644
index ceb5112b28..0000000000
--- a/native_client_sdk/src/examples/sine_synth/example.dsc
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'sine_synth',
- 'TYPE' : 'main',
- 'SOURCES' : ['sine_synth.cc'],
- 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'sine_synth',
- 'TITLE': 'Sine Wave Synthesizer',
- 'DESC': """
-The Sine Wave Synthesizer example demonstrates playing sound (a sine
-wave). Enter the desired frequency and hit play to start, stop to end. The
-frequency box will display "Loading, please wait." while the module loads.""",
- 'FOCUS': 'Audio.',
- 'GROUP': 'API',
-}
-
diff --git a/native_client_sdk/src/examples/tutorial/debugging/example.dsc b/native_client_sdk/src/examples/tutorial/debugging/example.dsc
new file mode 100644
index 0000000000..72cd94b61f
--- /dev/null
+++ b/native_client_sdk/src/examples/tutorial/debugging/example.dsc
@@ -0,0 +1,35 @@
+{
+ 'DISABLE_PACKAGE': True, # Doesn't work in packaged apps yet.
+ 'TOOLS': ['newlib'],
+ 'SEARCH': [
+ '.',
+ '../..',
+ ],
+ 'TARGETS': [
+ {
+ 'NAME' : 'debugging',
+ 'TYPE' : 'main',
+ 'SOURCES' : [
+ 'hello_world.c',
+ ],
+ 'CCFLAGS': ['-fno-omit-frame-pointer'],
+ 'DEPS' : ['error_handling'],
+ 'LIBS' : ['ppapi', 'pthread']
+ }
+ ],
+
+ 'POST': """
+#
+# Specify the MAP files to be created.
+#
+$(eval $(call MAP_RULE,$(TARGET),$(TARGET)))
+""",
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/tutorial',
+ 'NAME': 'debugging',
+ 'TITLE': 'Debugging',
+ 'GROUP': 'Tutorial'
+}
+
diff --git a/native_client_sdk/src/examples/tutorial/debugging/example.js b/native_client_sdk/src/examples/tutorial/debugging/example.js
new file mode 100644
index 0000000000..6f637f83d4
--- /dev/null
+++ b/native_client_sdk/src/examples/tutorial/debugging/example.js
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var lastModuleError = '';
+var crashed = false;
+
+function domContentLoaded(name, tc, config, width, height) {
+ common.createNaClModule(name, tc, config, width, height);
+ common.attachDefaultListeners();
+
+ updateStatus('Page Loaded');
+}
+
+// Indicate success when the NaCl module has loaded.
+function moduleDidLoad() {
+ updateStatus('LOADED');
+ setTimeout(boom, 2000);
+}
+
+function findAddress(addr, map) {
+ if (map.length < 1) {
+ return 'MAP Unavailable';
+ }
+ if (addr < map[0].offs) {
+ return 'Invalid Address';
+ }
+
+ 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;
+
+ // Force filename to 50 chars
+ if (filename) {
+ if (filename.length > 50) {
+ filename = '...' + filename.substr(filename.length - 47);
+ }
+ } else {
+ filename = 'Unknown';
+ }
+ while (filename.length < 50) {
+ filename = ' ' + filename
+ }
+ return filename + ' ' + map[i-1].name + ' + 0x' + offs.toString(16);
+ }
+ }
+
+ var last = map.length - 1;
+ return filename + ' ' + map[last].name + ' + 0x' + offs.toString(16);
+}
+
+function buildTextMap(map) {
+ map = 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') {
+ orderedMap.push(obj);
+ }
+ }
+ 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++) {
+ var frame = traceinfo.frames[i];
+ var addr = findAddress(frame.prog_ctr, map)
+ text += '[' + i.toString(10) + '] ' + addr + '\n';
+ }
+ document.getElementById('trace').value = text;
+}
+
+function fetchMap(url, traceinfo) {
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open('GET', url, true);
+ xmlhttp.onload = function() {
+ updateStack(traceinfo, this.responseText);
+ }
+ xmlhttp.traceinfo = traceinfo;
+ xmlhttp.send();
+}
+
+// Handle a message coming from the NaCl module.
+function handleMessage(message_event) {
+ msg_type = message_event.data.substring(0, 4);
+ msg_data = message_event.data.substring(5, message_event.data.length);
+ if (msg_type == 'LOG:') {
+ 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;
+ crash_info = JSON.parse(msg_data);
+ updateStatus('Crash Reported');
+ src = common.naclModule.getAttribute('path');
+ fetchMap(src + '/debugging_' + crash_info['arch'] + '.map', crash_info);
+ return;
+ }
+}
+
+function handleCrash(message) {
+ updateStatus(message);
+}
+
+function updateStatus(message) {
+ common.updateStatus(message);
+
+ if (message)
+ document.getElementById('log').value += message + '\n'
+}
+
+function boom() {
+ if (!crashed) {
+ updateStatus('Send BOOM');
+ common.naclModule.postMessage('BOOM');
+ }
+}
diff --git a/native_client_sdk/src/examples/debugging/hello_world.c b/native_client_sdk/src/examples/tutorial/debugging/hello_world.c
index a5dd33342f..200165155f 100644
--- a/native_client_sdk/src/examples/debugging/hello_world.c
+++ b/native_client_sdk/src/examples/tutorial/debugging/hello_world.c
@@ -25,8 +25,7 @@
#include <pthread.h>
-#include "string_stream.h"
-#include "untrusted_crash_dump.h"
+#include "error_handling/error_handling.h"
PPB_Messaging* ppb_messaging_interface = NULL;
PPB_Var* ppb_var_interface = NULL;
@@ -38,35 +37,27 @@ PP_Instance g_Instance;
volatile int g_CrashTime = 0;
-
-void PostMessage(const char *str);
-
+void PostMessage(const char* str);
void layer5(int x, int y) {
if (g_CrashTime) {
- *(volatile int *) x = y;
+ *(volatile int*)x = y;
}
}
-void layer4(int x) {
- layer5(x, 1);
-}
+void layer4(int x) { layer5(x, 1); }
-void layer3(int a, int b, int c) {
- layer4(a + b + c);
-}
+void layer3(int a, int b, int c) { layer4(a + b + c); }
-void layer2(int i, int j) {
- layer3(i, j, 7);
-}
+void layer2(int i, int j) { layer3(i, j, 7); }
void layer1(int s, int t) {
- int *junk = (int*)alloca(sizeof(int)* 1234);
+ int* junk = (int*)alloca(sizeof(int) * 1234);
junk[0] = s + 5;
layer2(junk[0], t + 1);
}
-void *NexeMain(void *data) {
+void* NexeMain(void* data) {
PostMessage("Running Boom thread.");
while (1) {
layer1(2, 9);
@@ -88,25 +79,26 @@ static struct PP_Var CStrToVar(const char* str) {
return PP_MakeUndefined();
}
-
static void PostCompletionCallback(void* user_data, int32_t result) {
- const char *str = (const char *) user_data;
+ const char* str = (const char*)user_data;
ppb_messaging_interface->PostMessage(g_Instance, CStrToVar(str));
free(user_data);
}
-void PostMessage(const char *str) {
+void PostMessage(const char* str) {
struct PP_CompletionCallback cb;
- if (NULL == str) return;
- if (NULL == ppb_messaging_interface) return;
- if (0 == g_Instance) return;
+ if (NULL == str)
+ return;
+ if (NULL == ppb_messaging_interface)
+ return;
+ if (0 == g_Instance)
+ return;
if (strncmp(str, "ERR:", 4)) {
fprintf(stderr, "%s\n", str);
fflush(stderr);
- }
- else {
+ } else {
fprintf(stdout, "%s\n", str);
fflush(stdout);
}
@@ -122,7 +114,14 @@ void PostMessage(const char *str) {
ppb_core_interface->CallOnMainThread(0, cb, 0);
}
+void DumpJson(const char* json) {
+ char* out = (char*)malloc(strlen(json) + 5);
+ strcpy(out, "TRC: ");
+ 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
@@ -153,17 +152,20 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
g_PPAPIThread = pthread_self();
PostMessage("LOG: DidCreate");
- if (!NaClCrashDumpInit()) {
- PostMessage("LOG: Failed to set up crash dump.");
- }
- else {
- PostMessage("LOG: Crash Dump On");
+
+ /* Request exception callbacks with JSON. */
+ EHRequestExceptionsJson(DumpJson);
+
+ /* Report back if the request was honored. */
+ if (!EHHanderInstalled()) {
+ PostMessage("LOG: Stack traces not available, so don't expect them.\n");
+ } else {
+ PostMessage("LOG: Stack traces are on.");
}
pthread_create(&g_NexeThread, NULL, NexeMain, NULL);
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
@@ -171,8 +173,7 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
* @param[in] instance The identifier of the instance representing this NaCl
* module.
*/
-static void Instance_DidDestroy(PP_Instance instance) {
-}
+static void Instance_DidDestroy(PP_Instance instance) {}
/**
* Called when the position, the size, or the clip rect of the element in the
@@ -187,8 +188,7 @@ static void Instance_DidDestroy(PP_Instance instance) {
* plugin is invisible, @a clip will be (0, 0, 0, 0).
*/
static void Instance_DidChangeView(PP_Instance instance,
- PP_Resource view_resource) {
-}
+ PP_Resource view_resource) {}
/**
* Notification that the given NaCl module has gained or lost focus.
@@ -207,9 +207,7 @@ static void Instance_DidChangeView(PP_Instance instance,
* @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) {
-}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
/**
* Handler that gets called after a full-frame module is instantiated based on
@@ -227,7 +225,6 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
return PP_FALSE;
}
-
/**
* Handles message from JavaScript.
*
@@ -255,7 +252,6 @@ 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.
@@ -282,9 +278,7 @@ PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
return NULL;
}
-
/**
* Called before the plugin module is unloaded.
*/
-PP_EXPORT void PPP_ShutdownModule() {
-}
+PP_EXPORT void PPP_ShutdownModule() {}
diff --git a/native_client_sdk/src/examples/tutorial/debugging/index.html b/native_client_sdk/src/examples/tutorial/debugging/index.html
new file mode 100644
index 0000000000..da90b010e4
--- /dev/null
+++ b/native_client_sdk/src/examples/tutorial/debugging/index.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+<head>
+ <meta http-equiv="Pragma" content="no-cache" />
+ <meta http-equiv="Expires" content="-1" />
+ <title>Logging and Crash Handling</title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="example.js"></script>
+</head>
+<body data-width="0" data-height="0" data-custom-load="true" {{attrs}}>
+ <h1>Logging and Crash Handling</h1>
+ <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>
+ <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
+ so developers should avoid requring it under normal operation. However it
+ can be a very useful tool for diagnosing crashes, especially in the field.
+ NativeClient provides a library called "error_handling" for registering
+ the exception handler, as well as unwinding the exception context.
+ <br><b>NOTE: The library requires '-fno-omit-frame-pointer' to facilitate
+ unwinding the stack.</b></p>
+ <h2> Trace Walkthrough </h2>
+ <p> First we request the exception handler interface, and use it to register
+ 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.
+ 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>
+ <p> After two seconds, JavaScript sends a message to the module which will
+ cause it take an exception on the worker thread. The exception handler
+ unwinds the stack while creating a stringified JSON object containing the
+ stack frame information. Once unwound, or the buffer is exhausted, the
+ JSON object is sent to JavaScript for processing.
+ <p> The message handler in JavaScript takes the JSON object and uses the
+ arch key to load the appropriate MAP file using an XMLHttpRequest. It
+ then processes the MAP file and prints out a stack trace using the exception
+ data in the JSON object.</p>
+ <h2> Exception Handling in the Field </h2>
+ <p>
+ For real world applications, it's important to get the crash information
+ back the developer. In this case, the JSON object could be sent via
+ XMLHttpRequest. The JSON object can the be processed by the developers
+ QA team to manage bugs in the field. The handler.py script provided in
+ the example sources shows how the JSON object can be used with the tools
+ to provide a better stack trace. Simply cut and paste the JSON object
+ to a text file and run the handler.py script on it.
+ </p>
+
+ <div id="listener"></div>
+ <hr>
+ <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+ <table>
+ <tr>
+ <td><h2>Log</h2></td>
+ <td><h2>JSON</h2></td>
+ </tr>
+ <tr>
+ <td>
+ <textarea id="log" rows="10" cols="60" readonly="readonly"></textarea>
+ </td>
+ <td>
+ <textarea id="json" rows="10" cols="60" readonly="readonly"></textarea>
+ </td>
+ </tr>
+ </table>
+ <br>
+ <h2>Stack Trace</h2>
+ <textarea id="trace" rows="10" cols="130" readonly="readonly"></textarea>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/dlopen/dlopen.cc b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
index f77930a4cf..90a59fdd0f 100644
--- a/native_client_sdk/src/examples/dlopen/dlopen.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
@@ -13,9 +13,9 @@
/// method on the object returned by CreateModule(). If the CreateInstance
/// returns successfully, then Init function is called, which will load the
/// shared object on a worker thread. We use a worker because dlopen is
-/// a blocking call, which is not alowed on the main thread.
+/// a blocking call, which is not allowed on the main thread.
-#include <dlfcn.h>
+#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -30,6 +30,15 @@
#include "nacl_io/nacl_io.h"
#include "reverse.h"
+#if defined(NACL_SDK_DEBUG)
+#define CONFIG_NAME "Debug"
+#else
+#define CONFIG_NAME "Release"
+#endif
+
+#define XSTRINGIFY(x) STRINGIFY(x)
+#define STRINGIFY(x) #x
+#define NACL_ARCH_STRING XSTRINGIFY(NACL_ARCH)
class DlopenInstance : public pp::Instance {
public:
@@ -41,23 +50,24 @@ class DlopenInstance : public pp::Instance {
reverse_(NULL),
tid_(NULL) {}
- virtual ~DlopenInstance(){};
+ virtual ~DlopenInstance() {}
+ ;
// Helper function to post a message back to the JS and stdout functions.
- void logmsg(const char* pStr){
+ void logmsg(const char* pStr) {
PostMessage(pp::Var(std::string("log:") + pStr));
fprintf(stdout, pStr);
}
// Initialize the module, staring a worker thread to load the shared object.
- virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
nacl_io_init_ppapi(pp_instance(),
pp::Module::Get()->get_browser_interface());
// Mount a HTTP mount at /http. All reads from /http/* will read from the
// server.
mount("", "/http", "httpfs", 0, "");
- logmsg("Spawning thread to cache .so files...");
+ logmsg("Spawning thread to cache .so files...\n");
if (pthread_create(&tid_, NULL, LoadLibrariesOnWorker, this)) {
logmsg("ERROR; pthread_create() failed.\n");
return false;
@@ -69,11 +79,13 @@ class DlopenInstance : public pp::Instance {
// the shared object. In addition, note that this function does NOT call
// dlclose, which would close the shared object and unload it from memory.
void LoadLibrary() {
+ const char reverse_so_path[] =
+ "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH_STRING ".so";
const int32_t IMMEDIATELY = 0;
eightball_so_ = dlopen("libeightball.so", RTLD_LAZY);
- reverse_so_ = dlopen("/http/glibc/Debug/libreverse_x86_64.so", RTLD_LAZY);
+ reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
pp::CompletionCallback cc(LoadDoneCB, this);
- pp::Module::Get()->core()->CallOnMainThread(IMMEDIATELY, cc , 0);
+ pp::Module::Get()->core()->CallOnMainThread(IMMEDIATELY, cc, 0);
}
// This function will run on the main thread and use the handle it stored by
@@ -84,57 +96,56 @@ class DlopenInstance : public pp::Instance {
intptr_t offset = (intptr_t) dlsym(eightball_so_, "Magic8Ball");
eightball_ = (TYPE_eightball) offset;
if (NULL == eightball_) {
- std::string message = "dlsym() returned NULL: ";
- message += dlerror();
- message += "\n";
- logmsg(message.c_str());
- return;
+ std::string message = "dlsym() returned NULL: ";
+ message += dlerror();
+ message += "\n";
+ logmsg(message.c_str());
+ return;
}
- logmsg("Loaded libeightball.so");
+ logmsg("Loaded libeightball.so\n");
} else {
- logmsg("libeightball.so did not load");
+ logmsg("libeightball.so did not load\n");
}
-
if (reverse_so_ != NULL) {
intptr_t offset = (intptr_t) dlsym(reverse_so_, "Reverse");
reverse_ = (TYPE_reverse) offset;
if (NULL == reverse_) {
- std::string message = "dlsym() returned NULL: ";
- message += dlerror();
- message += "\n";
- logmsg(message.c_str());
- return;
+ std::string message = "dlsym() returned NULL: ";
+ message += dlerror();
+ message += "\n";
+ logmsg(message.c_str());
+ return;
}
- logmsg("Loaded libreverse.so");
+ logmsg("Loaded libreverse.so\n");
} else {
- logmsg("libreverse.so did not load");
+ logmsg("libreverse.so did not load\n");
}
}
// Called by the browser to handle the postMessage() call in Javascript.
virtual void HandleMessage(const pp::Var& var_message) {
if (!var_message.is_string()) {
- logmsg("Message is not a string.");
+ logmsg("Message is not a string.\n");
return;
}
std::string message = var_message.AsString();
if (message == "eightball") {
- if (NULL == eightball_){
- logmsg("Eightball library not loaded");
+ if (NULL == eightball_) {
+ logmsg("Eightball library not loaded\n");
return;
}
std::string ballmessage = "The Magic 8-Ball says: ";
ballmessage += eightball_();
- ballmessage += "!";
+ ballmessage += "!\n";
logmsg(ballmessage.c_str());
} else if (message.find("reverse:") == 0) {
if (NULL == reverse_) {
- logmsg("Reverse library not loaded");
+ logmsg("Reverse library not loaded\n");
return;
}
@@ -143,7 +154,7 @@ class DlopenInstance : public pp::Instance {
std::string message = "Your string reversed: \"";
message += result;
- message += "\"";
+ message += "\"\n";
free(result);
@@ -155,14 +166,14 @@ class DlopenInstance : public pp::Instance {
}
}
- static void* LoadLibrariesOnWorker(void *pInst) {
- DlopenInstance *inst = static_cast<DlopenInstance *>(pInst);
+ static void* LoadLibrariesOnWorker(void* pInst) {
+ DlopenInstance* inst = static_cast<DlopenInstance*>(pInst);
inst->LoadLibrary();
return NULL;
}
- static void LoadDoneCB(void *pInst, int32_t result) {
- DlopenInstance *inst = static_cast<DlopenInstance *>(pInst);
+ static void LoadDoneCB(void* pInst, int32_t result) {
+ DlopenInstance* inst = static_cast<DlopenInstance*>(pInst);
inst->UseLibrary();
}
@@ -172,13 +183,13 @@ class DlopenInstance : public pp::Instance {
TYPE_eightball eightball_;
TYPE_reverse reverse_;
pthread_t tid_;
- };
+};
// The Module class. The browser calls the CreateInstance() method to create
// an instance of your NaCl module on the web page. The browser creates a new
// instance for each <embed> tag with type="application/x-nacl".
class dlOpenModule : public pp::Module {
- public:
+ public:
dlOpenModule() : pp::Module() {}
virtual ~dlOpenModule() {}
@@ -188,15 +199,11 @@ class dlOpenModule : public pp::Module {
}
};
-
// Factory function called by the browser when the module is first loaded.
// The browser keeps a singleton of this module. It calls the
// CreateInstance() method on the object you return to make instances. There
// is one instance per <embed> tag on the page. This is the main binding
// point for your NaCl module with the browser.
namespace pp {
- Module* CreateModule() {
- return new dlOpenModule();
- }
+Module* CreateModule() { return new dlOpenModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/dlopen/eightball.cc b/native_client_sdk/src/examples/tutorial/dlopen/eightball.cc
index 531f8a619c..bf7d352931 100644
--- a/native_client_sdk/src/examples/dlopen/eightball.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/eightball.cc
@@ -7,18 +7,10 @@
#include "eightball.h"
-extern "C" const char *Magic8Ball() {
+extern "C" const char* Magic8Ball() {
const int NSIDES = 8;
- const char* answer[NSIDES] = {
- "YES",
- "NO",
- "MAYBE",
- "MAYBE NOT",
- "DEFINITELY",
- "ASK ME TOMORROW",
- "PARTLY CLOUDY",
- "42",
- };
+ const char* answer[NSIDES] = { "YES", "NO", "MAYBE", "MAYBE NOT",
+ "DEFINITELY", "ASK ME TOMORROW",
+ "PARTLY CLOUDY", "42", };
return answer[rand() % NSIDES];
}
-
diff --git a/native_client_sdk/src/examples/dlopen/eightball.h b/native_client_sdk/src/examples/tutorial/dlopen/eightball.h
index df3d9979ad..0c818e53d2 100644
--- a/native_client_sdk/src/examples/dlopen/eightball.h
+++ b/native_client_sdk/src/examples/tutorial/dlopen/eightball.h
@@ -9,5 +9,4 @@
typedef char* (*TYPE_eightball)(void);
extern "C" const char* Magic8Ball();
-#endif /* EIGHTBALL_H_ */
-
+#endif /* EIGHTBALL_H_ */
diff --git a/native_client_sdk/src/examples/dlopen/example.dsc b/native_client_sdk/src/examples/tutorial/dlopen/example.dsc
index 4983a57544..5282218de6 100644
--- a/native_client_sdk/src/examples/dlopen/example.dsc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/example.dsc
@@ -16,7 +16,9 @@
},
{
'NAME' : 'libreverse',
- 'TYPE' : 'so',
+ # This .so file is manually loaded by dlopen; we don't want to include it
+ # in the .nmf, or it will be automatically loaded on startup.
+ 'TYPE' : 'so-standalone',
'SOURCES' : ['reverse.cc', 'reverse.h'],
'CXXFLAGS': ['-fPIC'],
'LIBS' : ['ppapi_cpp', 'ppapi', 'pthread']
@@ -25,16 +27,9 @@
'DATA': [
'example.js',
],
- 'DEST': 'examples',
+ 'DEST': 'examples/tutorial',
'NAME': 'dlopen',
'TITLE': 'Dynamic Library Open',
- 'DESC': """
-The dlopen example demonstrates how build dynamic libraries and then
-open and use them at runtime. When the page loads, type in a question and
-hit enter or click the ASK! button. The question and answer will be
-displayed in the page under the text entry box. Shared libraries are only
-available with the GLIBC toolchain.""",
- 'FOCUS': 'Using shared objects.',
- 'GROUP': 'Concepts'
+ 'GROUP': 'Tutorial'
}
diff --git a/native_client_sdk/src/examples/dlopen/example.js b/native_client_sdk/src/examples/tutorial/dlopen/example.js
index bb658cdad3..5e1b1e3cd9 100644
--- a/native_client_sdk/src/examples/dlopen/example.js
+++ b/native_client_sdk/src/examples/tutorial/dlopen/example.js
@@ -19,7 +19,7 @@ function askBall(event) {
var questionEl = document.getElementById('question');
var query = questionEl.value;
questionEl.value = '';
- document.getElementById('log').innerHTML += 'You asked:' + query + '<br>';
+ common.logMessage('You asked: ' + query + '\n');
common.naclModule.postMessage('eightball');
event.preventDefault();
}
@@ -28,7 +28,6 @@ function reverseString(event) {
var questionEl = document.getElementById('question');
var query = questionEl.value;
questionEl.value = '';
-
- document.getElementById('log').innerHTML += 'Reversing:' + query + '<br>';
+ common.logMessage('Reversing: ' + query + '\n');
common.naclModule.postMessage('reverse:' + query);
}
diff --git a/native_client_sdk/src/examples/dlopen/index.html b/native_client_sdk/src/examples/tutorial/dlopen/index.html
index 4ad4f54721..0e535b4c66 100644
--- a/native_client_sdk/src/examples/dlopen/index.html
+++ b/native_client_sdk/src/examples/tutorial/dlopen/index.html
@@ -15,8 +15,13 @@ found in the LICENSE file.
<body {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <div>Magic eightball: type a question below, press the button, and get a
- response.</div>
+ <p>The dlopen example demonstrates how build dynamic libraries and then
+ open and use them at runtime. When the page loads, type in a question and
+ hit enter or click the ASK! button. The question and answer will be
+ displayed in the page under the text entry box. Shared libraries are only
+ available with the GLIBC toolchain.</p>
+ <p>Magic eightball: type a question below, press the button, and get a
+ response.</p>
<form>
<input type="text" id="question" value="">
<input type="submit" value="ASK!">
@@ -26,6 +31,6 @@ found in the LICENSE file.
<!-- The NaCl plugin will be embedded inside the element with id "listener".
See common.js.-->
<div id="listener"></div>
- <div id="log"></div>
+ <pre id="log" style="font-weight: bold"></pre>
</body>
</html>
diff --git a/native_client_sdk/src/examples/dlopen/reverse.cc b/native_client_sdk/src/examples/tutorial/dlopen/reverse.cc
index 94eaaef2b6..94eaaef2b6 100644
--- a/native_client_sdk/src/examples/dlopen/reverse.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/reverse.cc
diff --git a/native_client_sdk/src/examples/dlopen/reverse.h b/native_client_sdk/src/examples/tutorial/dlopen/reverse.h
index f0414ab2a1..b4e4bbafa5 100644
--- a/native_client_sdk/src/examples/dlopen/reverse.h
+++ b/native_client_sdk/src/examples/tutorial/dlopen/reverse.h
@@ -7,6 +7,6 @@
/* Allocate a new string that is the reverse of the given string. */
typedef char* (*TYPE_reverse)(const char*);
-extern "C" char* Reverse(const char *);
+extern "C" char* Reverse(const char*);
-#endif /* REVERSE_H_ */
+#endif /* REVERSE_H_ */
diff --git a/native_client_sdk/src/examples/mouselock/check_browser.js b/native_client_sdk/src/examples/tutorial/load_progress/check_browser.js
index 0c54ba4c07..0c54ba4c07 100644
--- a/native_client_sdk/src/examples/mouselock/check_browser.js
+++ b/native_client_sdk/src/examples/tutorial/load_progress/check_browser.js
diff --git a/native_client_sdk/src/examples/tutorial/load_progress/example.dsc b/native_client_sdk/src/examples/tutorial/load_progress/example.dsc
new file mode 100644
index 0000000000..3f8397f7bd
--- /dev/null
+++ b/native_client_sdk/src/examples/tutorial/load_progress/example.dsc
@@ -0,0 +1,19 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'load_progress',
+ 'TYPE' : 'main',
+ 'SOURCES' : ['load_progress.cc'],
+ 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread']
+ }
+ ],
+ 'DATA': [
+ 'example.js',
+ ],
+ 'DEST': 'examples/tutorial',
+ 'NAME': 'load_progress',
+ 'TITLE': 'Load Progress',
+ 'GROUP': 'Tutorial'
+}
+
diff --git a/native_client_sdk/src/examples/load_progress/example.js b/native_client_sdk/src/examples/tutorial/load_progress/example.js
index 37c3079500..8e7c00dfdd 100644
--- a/native_client_sdk/src/examples/load_progress/example.js
+++ b/native_client_sdk/src/examples/tutorial/load_progress/example.js
@@ -20,7 +20,7 @@ function domContentLoaded(name, tc, config, width, height) {
// event is always triggered when an <EMBED> tag has a MIME type of
// application/x-nacl.
function moduleDidStartLoad() {
- appendToEventLog('loadstart');
+ common.logMessage('loadstart\n');
}
// Progress event handler. |event| contains a couple of interesting
@@ -44,8 +44,8 @@ function moduleLoadProgress(event) {
loadPercent = -1.0;
loadPercentString = 'Computing...';
}
- appendToEventLog('progress: ' + loadPercentString +
- ' (' + event.loaded + ' of ' + event.total + ' bytes)');
+ common.logMessage('progress: ' + loadPercentString +
+ ' (' + event.loaded + ' of ' + event.total + ' bytes)\n');
}
// Handler that gets called if an error occurred while loading the NaCl
@@ -53,17 +53,17 @@ function moduleLoadProgress(event) {
// the error, you have to check lastError on the <EMBED> element to find
// out what happened.
function moduleLoadError() {
- appendToEventLog('error: ' + common.naclModule.lastError);
+ common.logMessage('error: ' + common.naclModule.lastError + '\n');
}
// Handler that gets called if the NaCl module load is aborted.
function moduleLoadAbort() {
- appendToEventLog('abort');
+ common.logMessage('abort\n');
}
// When the NaCl module has loaded indicate success.
function moduleDidLoad() {
- appendToEventLog('load');
+ common.logMessage('load\n');
common.updateStatus('SUCCESS');
}
@@ -74,27 +74,15 @@ function moduleDidLoad() {
// that if the NaCl module loads successfully, you will get both a 'load'
// event and a 'loadend' event.
function moduleDidEndLoad() {
- appendToEventLog('loadend');
+ common.logMessage('loadend\n');
var lastError = event.target.lastError;
if (lastError == undefined || lastError.length == 0) {
- lastError = '&lt;none&gt;';
+ lastError = '<none>';
}
- appendToEventLog('lastError: ' + lastError);
+ common.logMessage('lastError: ' + lastError + '\n');
}
// Handle a message coming from the NaCl module.
function handleMessage(message_event) {
- alert(message_event.data);
-}
-
-// Append an event name to the 'log' element. Event names
-// are separated by a <br> tag so they get listed one per line.
-// logMessage The message to append to the log.
-function appendToEventLog(logMessage) {
- var eventLogField = document.getElementById('log');
- if (eventLogField.innerHTML.length == 0) {
- eventLogField.innerHTML = logMessage;
- } else {
- eventLogField.innerHTML = eventLogField.innerHTML + '<br>' + logMessage;
- }
+ common.logMessage('Received PostMessage: ' + message_event.data + '\n');
}
diff --git a/native_client_sdk/src/examples/load_progress/index.html b/native_client_sdk/src/examples/tutorial/load_progress/index.html
index 8b2c0b6c9e..108fc05b83 100644
--- a/native_client_sdk/src/examples/load_progress/index.html
+++ b/native_client_sdk/src/examples/tutorial/load_progress/index.html
@@ -15,8 +15,13 @@ found in the LICENSE file.
<body data-width="256" data-height="256" data-custom-load="true" {{attrs}}>
<h1>{{title}}</h1>
<h2>Status: <code id="statusField">NO-STATUS</code></h2>
- <h2>Event Log</h2>
+ <p>The Load Progress example demonstrates how to listen for and handle events
+ that occur while a NaCl module loads. This example listens for different
+ load event types and dispatches different events to their respective
+ handler. This example also checks for valid browser version and shows
+ how to calculate and display loading progress.</p>
+ <h2>Events:</h2>
+ <pre id="log" style="font-weight: bold"></pre>
<div id="listener"></div>
- <div id="log"></div>
</body>
</html>
diff --git a/native_client_sdk/src/examples/load_progress/load_progress.cc b/native_client_sdk/src/examples/tutorial/load_progress/load_progress.cc
index 0610c5ed4e..3ed7583c4c 100644
--- a/native_client_sdk/src/examples/load_progress/load_progress.cc
+++ b/native_client_sdk/src/examples/tutorial/load_progress/load_progress.cc
@@ -53,7 +53,6 @@ class LoadProgressModule : public pp::Module {
};
} // namespace load_progress
-
namespace pp {
/// Factory function called by the browser when the module is first loaded.
/// The browser keeps a singleton of this module. It calls the
@@ -62,8 +61,5 @@ namespace pp {
/// point for your NaCl module with the browser.
/// @return new LoadProgressModule.
/// @note The browser is responsible for deleting returned @a Module.
-Module* CreateModule() {
- return new load_progress::LoadProgressModule();
-}
+Module* CreateModule() { return new load_progress::LoadProgressModule(); }
} // namespace pp
-
diff --git a/native_client_sdk/src/examples/websocket/example.dsc b/native_client_sdk/src/examples/websocket/example.dsc
deleted file mode 100644
index bf98bfc2ac..0000000000
--- a/native_client_sdk/src/examples/websocket/example.dsc
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- 'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
- 'TARGETS': [
- {
- 'NAME' : 'websocket',
- 'TYPE' : 'main',
- 'SOURCES' : ['websocket.cc'],
- 'LIBS': ['ppapi_cpp', 'ppapi']
- }
- ],
- 'DATA': [
- 'example.js',
- ],
- 'DEST': 'examples',
- 'NAME': 'websocket',
- 'TITLE': 'Websocket',
- 'DESC': """
-The Websocket example demonstrates how to use the Websocket API. The
-user first connects to the test server: ws://html5rocks.websocket.org/echo by
-clicking on the 'Connect'' button. Then hitting Send' will cause the app to
-send the message to the server and retrieve the reply.""",
- 'FOCUS': 'Websockets',
- 'GROUP': 'API'
-}
-
diff --git a/native_client_sdk/src/libraries/error_handling/error_handling.c b/native_client_sdk/src/libraries/error_handling/error_handling.c
new file mode 100644
index 0000000000..e2fec208df
--- /dev/null
+++ b/native_client_sdk/src/libraries/error_handling/error_handling.c
@@ -0,0 +1,266 @@
+/*
+ * 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 <assert.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifdef __GLIBC__
+#include <elf.h>
+#include <link.h>
+#endif /* __GLIBC__ */
+
+#include "irt.h"
+#include "nacl/nacl_exception.h"
+
+#include "error_handling/error_handling.h"
+#include "error_handling/string_stream.h"
+
+
+#define PAGE_CHUNK_SIZE (64 * 1024)
+#define PAGE_CHUNK_MASK (PAGE_CHUNK_SIZE - 1)
+#define STACK_SIZE_MIN (PAGE_CHUNK_SIZE * 4)
+
+#define MAX_FRAME_SIZE (10 * 1024)
+#define MAX_FRAME_CAP 128
+
+static pthread_key_t s_eh_stack_info_key;
+static EHJsonHandler s_eh_json_callback = NULL;
+static int s_eh_exception_enabled = 0;
+static struct nacl_irt_exception_handling s_exception_handling;
+
+
+typedef struct {
+ void* stack;
+ size_t size;
+} EHStackInfo;
+
+static uintptr_t EHReadPointer(uintptr_t offset) {
+ return *((uintptr_t*) offset);
+}
+
+static void EHPrintArch(sstream_t* ss, struct NaClExceptionContext* context) {
+#if defined(__x86_64__)
+ ssprintf(ss, "\"arch\": \"x86_64\",\n");
+#elif defined(__i386__)
+ ssprintf(ss, "\"arch\": \"x86_32\",\n");
+#elif defined(__arm__)
+ ssprintf(ss, "\"arch\": \"arm\",\n");
+#elif defined(__mips__)
+ ssprintf(ss, "\"arch\": \"mips\",\n");
+#else
+#error Unknown ARCH
+#endif
+}
+
+static void EHPrintSegments(sstream_t* ss,
+ struct NaClExceptionContext* context) {
+ ssprintf(ss, "\"segments\": [");
+ ssprintf(ss, "],\n");
+}
+
+static void EHPrintFrame(sstream_t* ss, EHFrame* frame) {
+ uintptr_t start;
+ uintptr_t i;
+
+ ssprintf(ss, "{\n");
+ ssprintf(ss, "\"frame_ptr\": %u,\n", frame->frame_ptr);
+ ssprintf(ss, "\"prog_ctr\": %u,\n", frame->prog_ctr);
+ ssprintf(ss, "\"data\": [\n");
+
+#if defined(__x86_64__)
+ start = frame->frame_ptr + 8;
+#else
+ start = frame->frame_ptr + 16;
+#endif
+ /* Capture the stack, no mare than 128 bytes to keep the size sane. */
+ for (i = start; i < frame->next_ptr && i - start < MAX_FRAME_CAP; i += 4) {
+ if (i != start) {
+ ssprintf(ss, ",");
+ }
+ ssprintf(ss, "%u\n", EHReadPointer(i));
+ }
+ ssprintf(ss, "]\n}\n");
+}
+
+
+static void EHPrintMainContext(sstream_t* ss,
+ struct NaClExceptionContext* context) {
+ struct NaClExceptionPortableContext* portable_context =
+ nacl_exception_context_get_portable(context);
+ ssprintf(ss, "\"handler\": {\n");
+ ssprintf(ss, "\"prog_ctr\": %u,\n", portable_context->prog_ctr);
+ ssprintf(ss, "\"stack_ptr\": %u,\n", portable_context->stack_ptr);
+ ssprintf(ss, "\"frame_ptr\": %u\n", portable_context->frame_ptr);
+ ssprintf(ss, "},\n");
+}
+
+
+int EHGetTopFrame(sstream_t* ss, struct NaClExceptionContext* context,
+ EHFrame* frame) {
+ struct NaClExceptionPortableContext* portable_context =
+ nacl_exception_context_get_portable(context);
+
+ frame->prog_ctr = portable_context->prog_ctr;
+ frame->frame_ptr = portable_context->frame_ptr;
+ frame->next_ptr = EHReadPointer(portable_context->frame_ptr);
+ return 1;
+}
+
+
+int EHUnwindFrame(EHFrame* frame) {
+ uintptr_t frame_ptr;
+ uintptr_t next;
+
+ // Verify the current frame
+ if (NULL == frame) return 0;
+
+ frame_ptr = frame->frame_ptr;
+ next = frame->next_ptr;
+
+ // Abort if done or unwind moves us in the wrong direction
+ if (next <= frame_ptr || next == 0) return 0;
+
+ // Abort if frame is > 10K
+ if (next - frame_ptr > MAX_FRAME_SIZE) return 0;
+
+ // Unwind the frame
+ frame->frame_ptr = next;
+ frame->next_ptr = EHReadPointer(frame->frame_ptr);
+#if defined(__x86_64__)
+ frame->prog_ctr = EHReadPointer(frame_ptr + 8);
+#else
+ frame->prog_ctr = EHReadPointer(frame_ptr + 4);
+#endif
+ return 1;
+}
+
+
+static void EHStackInfoDestructor(void *arg) {
+ EHStackInfo* info = (EHStackInfo*) arg;
+
+ if (info) {
+ munmap(info->stack, info->size);
+ }
+ free(info);
+}
+
+
+void EHDefaultJsonHandler(struct NaClExceptionContext* context) {
+ if (s_eh_json_callback) {
+ EHFrame frame;
+ sstream_t ss;
+ ssinit(&ss);
+
+ ssprintf(&ss, "{\n");
+ EHPrintArch(&ss, context);
+ EHPrintSegments(&ss, context);
+ EHPrintMainContext(&ss, context);
+
+ EHGetTopFrame(&ss, context, &frame);
+ int first = 1;
+
+ ssprintf(&ss, "\"frames\": [\n");
+ do {
+ if (!first) ssprintf(&ss, ",");
+ EHPrintFrame(&ss, &frame);
+ first = 0;
+ } while (EHUnwindFrame(&frame));
+
+ /* End frame LIST and context DICT */
+ ssprintf(&ss, "]\n}\n");
+ s_eh_json_callback(ss.data);
+
+ ssfree(&ss);
+ while(1) sleep(9999);
+ }
+}
+
+
+void EHRequestExceptionsRaw(EHRawHandler callback) {
+ size_t interface_size = sizeof(s_exception_handling);
+ if (s_eh_exception_enabled) {
+ fprintf(stderr, "ERROR: EHInit already initialized.\n");
+ return;
+ }
+ if (NULL == callback) {
+ fprintf(stderr, "ERROR: EHInit called with NULL callback.\n");
+ return;
+ }
+
+ /* Expect an exact match on the interface structure size. */
+ if (nacl_interface_query(NACL_IRT_EXCEPTION_HANDLING_v0_1,
+ &s_exception_handling,
+ interface_size) != interface_size) {
+ fprintf(stderr, "ERROR: EHInit failed nacl_interface_query\n");
+ return;
+ }
+
+ if (s_exception_handling.exception_handler(callback, NULL) != 0) {
+ fprintf(stderr, "ERROR: EHInit failed to install exception_handler\n");
+ return;
+ }
+
+ s_eh_exception_enabled = 1;
+
+ // Create a TLS key for storing per thread stack info
+ pthread_key_create(&s_eh_stack_info_key, EHStackInfoDestructor);
+}
+
+
+void *EHRequestExceptionStackOnThread(size_t stack_size) {
+ void* stack;
+ void* guard;
+ EHStackInfo* stack_info;
+
+ // Set the stack size
+ stack_size = (stack_size + PAGE_CHUNK_MASK) & PAGE_CHUNK_MASK;
+ if (stack_size < STACK_SIZE_MIN) stack_size = STACK_SIZE_MIN;
+
+ // Allocate stack + guard page
+ stack = mmap(NULL, stack_size + PAGE_CHUNK_SIZE,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (MAP_FAILED == stack) return MAP_FAILED;
+
+ // Remap to mprotect which may not be available
+ guard = mmap(stack, PAGE_CHUNK_SIZE,
+ PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (guard != stack) {
+ fprintf(stderr, "WARNING: Failed to add guard page for alt stack.\n");
+ }
+
+ if (!s_exception_handling.exception_stack(stack, stack_size)) {
+ fprintf(stderr, "ERROR: Failed to assign stack.\n");
+ munmap(stack, stack_size);
+ return MAP_FAILED;
+ }
+
+ // Allocate stack tracking information for this thread
+ stack_info = (EHStackInfo*) malloc(sizeof(EHStackInfo));
+ stack_info->stack = stack;
+ stack_info->size = stack_size + PAGE_CHUNK_SIZE;
+ pthread_setspecific(s_eh_stack_info_key, stack_info);
+ return stack;
+}
+
+
+void EHRequestExceptionsJson(EHJsonHandler callback) {
+ if (NULL == callback) return;
+
+ EHRequestExceptionsRaw(EHDefaultJsonHandler);
+ if (s_eh_exception_enabled) s_eh_json_callback = callback;
+}
+
+
+int EHHanderInstalled() {
+ return s_eh_exception_enabled;
+} \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/error_handling/error_handling.h b/native_client_sdk/src/libraries/error_handling/error_handling.h
new file mode 100644
index 0000000000..29b4aca96d
--- /dev/null
+++ b/native_client_sdk/src/libraries/error_handling/error_handling.h
@@ -0,0 +1,85 @@
+/*
+ * 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 ERROR_HANDLING_ERROR_HANDLING_H_
+#define ERROR_HANDLING_ERROR_HANDLING_H_
+
+#include "error_handling/string_stream.h"
+#include "utils/macros.h"
+
+EXTERN_C_BEGIN
+
+struct NaClExceptionContext;
+
+typedef void (*EHRawHandler)(struct NaClExceptionContext* context);
+typedef void (*EHJsonHandler)(const char* str);
+
+typedef struct {
+ uint32_t prog_ctr;
+ uint32_t frame_ptr;
+ uint32_t next_ptr;
+} EHFrame;
+
+
+/** Initialize error handling.
+ *
+ * Initializes the error handling to catch untrusted exceptions. The init
+ * functions will install an untrusted exception handler.
+ *
+ * The raw form will install the provided handler directly to the exception
+ * system.
+ *
+ * The json form will install a default handler which will walk the stack
+ * creating a valid JSON string which is passed to the provided handler.
+ *
+ * NOTE: Exception handling is enabled process wide.
+ * NOTE: Exception handling is not guaranteed to be available so it should
+ * not be considered an error if the request fails.
+ */
+void EHRequestExceptionsRaw(EHRawHandler callback);
+void EHRequestExceptionsJson(EHJsonHandler callback);
+
+
+/** Request an alternate signal handling stack for this thread.
+ *
+ * Specifies an alternate stack which will be used when this thread enters
+ * the exception handler. This is useful in cases when the threads original
+ * stack may have overflowed or may be too small to handler the exception.
+ *
+ * Returns the allocated stack or MAP_FAILED.
+ *
+ * NOTE: Unlike the handler, this is a per thread call.
+ * NOTE: If the allocation fails, the exception will still take place on the
+ * thread's original stack.
+ */
+void *EHRequestExceptionStackOnThread(size_t stack_size);
+
+
+/** Determine if NaCl will forward exceptions.
+ *
+ * Returns non-zero if a hander has been installed and exceptions will
+ * be forwarded.
+ *
+ * NOTE: Exception handling is not guarenteed to be available so it should
+ * not be considered an error if the request fails.
+ */
+int EHHanderInstalled();
+
+
+/** Fill an exception frame from an exception context. */
+int EHGetTopFrame(sstream_t* ss, struct NaClExceptionContext* context,
+ EHFrame* frame);
+
+
+/** Unwind the stack by one frame.
+ *
+ * Returns zero once it failes to unwind.
+ */
+int EHUnwindFrame(EHFrame* frame);
+
+EXTERN_C_END
+
+#endif // ERROR_HANDLING_ERROR_HANDLING_H_ \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/error_handling/library.dsc b/native_client_sdk/src/libraries/error_handling/library.dsc
new file mode 100644
index 0000000000..f8ff7b6083
--- /dev/null
+++ b/native_client_sdk/src/libraries/error_handling/library.dsc
@@ -0,0 +1,24 @@
+{
+ 'TOOLS': ['newlib'],
+ 'TARGETS': [
+ {
+ 'NAME' : 'error_handling',
+ 'TYPE' : 'lib',
+ 'SOURCES' : [
+ "error_handling.c",
+ "string_stream.c"
+ ],
+ }
+ ],
+ 'HEADERS': [
+ {
+ 'FILES': [
+ "error_handling.h",
+ "string_stream.h",
+ ],
+ 'DEST': 'include/error_handling',
+ },
+ ],
+ 'DEST': 'src',
+ 'NAME': 'error_handling',
+}
diff --git a/native_client_sdk/src/examples/debugging/string_stream.c b/native_client_sdk/src/libraries/error_handling/string_stream.c
index 08783ccdd9..81046a96f5 100644
--- a/native_client_sdk/src/examples/debugging/string_stream.c
+++ b/native_client_sdk/src/libraries/error_handling/string_stream.c
@@ -1,24 +1,29 @@
+/*
+ * 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include "string_stream.h"
-
-void ssinit(sstream_t *stream) {
+#include "error_handling/string_stream.h"
+void ssinit(sstream_t* stream) {
stream->data = NULL;
stream->length = 0;
}
-void ssfree(sstream_t *stream) {
+void ssfree(sstream_t* stream) {
free(stream->data);
stream->data = 0;
stream->length = 0;
}
-int ssvprintf(sstream_t *stream, const char *format, va_list args) {
+int ssvprintf(sstream_t* stream, const char* format, va_list args) {
va_list hold;
int len;
- char *outstr;
+ char* outstr;
va_copy(hold, args);
len = vsnprintf(NULL, 0, format, args);
@@ -32,10 +37,11 @@ int ssvprintf(sstream_t *stream, const char *format, va_list args) {
stream->data = outstr;
vsprintf(&stream->data[stream->length], format, hold);
stream->length += len;
+
return len;
}
-int ssprintf(sstream_t *stream, const char *format, ...) {
+int ssprintf(sstream_t* stream, const char* format, ...) {
int out;
va_list args;
va_start(args, format);
diff --git a/native_client_sdk/src/libraries/error_handling/string_stream.h b/native_client_sdk/src/libraries/error_handling/string_stream.h
new file mode 100644
index 0000000000..b35bc80303
--- /dev/null
+++ b/native_client_sdk/src/libraries/error_handling/string_stream.h
@@ -0,0 +1,30 @@
+/*
+ * 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 ERROR_HANDLING_STRING_STREAM_H
+#define ERROR_HANDLING_STRING_STREAM_H
+
+/*
+ * Support for a stream stream in 'C', which is appended to via an sprintf-like
+ * function.
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+
+typedef struct {
+ char* data;
+ size_t length;
+} sstream_t;
+
+void ssinit(sstream_t* stream);
+void ssfree(sstream_t* stream);
+
+/* Returns the number of bytes added to the stream. */
+int ssvprintf(sstream_t* sstream, const char* format, va_list args);
+int ssprintf(sstream_t* sstream, const char* format, ...);
+
+#endif /* ERROR_HANDLING_STRING_STREAM_H */
diff --git a/native_client_sdk/src/libraries/gtest_ppapi/gtest_runner.h b/native_client_sdk/src/libraries/gtest_ppapi/gtest_runner.h
index c9c3256f48..b7e489c048 100644
--- a/native_client_sdk/src/libraries/gtest_ppapi/gtest_runner.h
+++ b/native_client_sdk/src/libraries/gtest_ppapi/gtest_runner.h
@@ -16,7 +16,7 @@ class GTestRunner {
public:
// Factory function to create the background gtest thread and associated
// GTestRunner singleton. It is an error to call the factory function more
- // than once that raises an assert in debug mde.
+ // than once that raises an assert in debug mode.
//
// Parameters:
// instance: the NaCl instance.
diff --git a/native_client_sdk/src/libraries/gtest_ppapi/thread_condition.h b/native_client_sdk/src/libraries/gtest_ppapi/thread_condition.h
index 5da015206a..d7af353349 100644
--- a/native_client_sdk/src/libraries/gtest_ppapi/thread_condition.h
+++ b/native_client_sdk/src/libraries/gtest_ppapi/thread_condition.h
@@ -41,7 +41,7 @@ class ThreadCondition {
}
// Wait for a Signal(). Note that this can spuriously return, so you should
- // have a guard bool to see if the condtion is really true. E.g., in the
+ // have a guard bool to see if the condition is really true. E.g., in the
// calling thread:
// cond_lock->Lock();
// cond_true = true;
diff --git a/native_client_sdk/src/libraries/jsoncpp/library.dsc b/native_client_sdk/src/libraries/jsoncpp/library.dsc
new file mode 100644
index 0000000000..44401fd175
--- /dev/null
+++ b/native_client_sdk/src/libraries/jsoncpp/library.dsc
@@ -0,0 +1,49 @@
+{
+ 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux', 'win'],
+ 'SEARCH': [
+ '../../../../third_party/jsoncpp/overrides/include/json',
+ '../../../../third_party/jsoncpp/overrides/src/lib_json',
+ '../../../../third_party/jsoncpp/source/include/json',
+ '../../../../third_party/jsoncpp/source/src/lib_json',
+ '../../../../third_party/jsoncpp',
+ ],
+ 'TARGETS': [
+ {
+ 'NAME' : 'jsoncpp',
+ 'TYPE' : 'lib',
+ 'DEFINES': ['JSON_USE_EXCEPTION=0'],
+ 'SOURCES' : [
+ 'json_reader.cpp',
+ 'json_value.cpp',
+ 'json_writer.cpp',
+ ],
+ }
+ ],
+ 'HEADERS': [
+ {
+ 'DEST': 'include/json',
+ 'FILES': [
+ 'assertions.h',
+ 'autolink.h',
+ 'config.h',
+ 'features.h',
+ 'forwards.h',
+ 'json.h',
+ 'reader.h',
+ 'value.h',
+ 'writer.h',
+ ],
+ },
+ ],
+ 'DATA': [
+ 'LICENSE',
+ 'README.chromium',
+ 'json_batchallocator.h',
+ 'json_internalarray.inl',
+ 'json_internalmap.inl',
+ 'json_tool.h',
+ 'json_valueiterator.inl',
+ ],
+ 'DEST': 'src',
+ 'NAME': 'jsoncpp',
+}
diff --git a/native_client_sdk/src/libraries/libjpeg/library.dsc b/native_client_sdk/src/libraries/libjpeg/library.dsc
index 0d40f3c4d6..d5dd5c367c 100644
--- a/native_client_sdk/src/libraries/libjpeg/library.dsc
+++ b/native_client_sdk/src/libraries/libjpeg/library.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'linux', 'win'],
'SEARCH': [
'../../../../third_party/libjpeg',
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_object.cc b/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
index 95223f6974..75e84c9355 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.cc
@@ -115,7 +115,7 @@ void KernelObject::ReleaseHandle(KernelHandle* handle) {
}
// Helper function to properly sort FD order in the heap, forcing
-// lower numberd FD to be available first.
+// lower numbered FD to be available first.
static bool FdOrder(int i, int j) {
return i > j;
}
@@ -148,7 +148,7 @@ void KernelObject::FreeAndReassignFD(int fd, KernelHandle* handle) {
} else {
AutoLock lock(&process_lock_);
- // Acquire the new handle first incase they are the same.
+ // Acquire the new handle first in case they are the same.
if (handle) {
handle->Acquire();
handle->mount_->Acquire();
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_object.h b/native_client_sdk/src/libraries/nacl_io/kernel_object.h
index d50aabc274..9e853a944e 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_object.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_object.h
@@ -16,7 +16,7 @@ class KernelHandle;
class Mount;
// KernelObject provides basic functionality for threadsafe
-// acces to kernel objects such as file descriptors and
+// access to kernel objects such as file descriptors and
// file handles. It also provides access to the CWD for
// path resolution.
class KernelObject {
@@ -41,7 +41,7 @@ class KernelObject {
Mount* AcquireMountAndPath(const std::string& relpath, Path *pobj);
void ReleaseMount(Mount* mnt);
- // Convert from FD to KernelHandle, and aquire the handle.
+ // Convert from FD to KernelHandle, and acquire the handle.
KernelHandle* AcquireHandle(int fd);
void ReleaseHandle(KernelHandle* handle);
@@ -64,7 +64,7 @@ class KernelObject {
// Kernel lock protects kernel wide resources such as the mount table...
pthread_mutex_t kernel_lock_;
- // Process lock proctects process wide resources such as CWD, file handles...
+ // Process lock protects process wide resources such as CWD, file handles...
pthread_mutex_t process_lock_;
DISALLOW_COPY_AND_ASSIGN(KernelObject);
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 745a680154..82731a2501 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -389,6 +389,8 @@ off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
// check if fd is valid and handle exists
if (NULL == handle) return -1;
+
+ AutoLock lock(&handle->lock_);
int ret = handle->Seek(offset, whence);
ReleaseHandle(handle);
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 37a58e5423..bf32144acf 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
@@ -24,6 +24,8 @@ EXTERN_C_BEGIN
#define STRUCT_NAME(group) __libnacl_irt_##group
#define DECLARE_STRUCT(group) \
extern struct nacl_irt_##group STRUCT_NAME(group);
+#define DECLARE_STRUCT_VERSION(group, version) \
+ extern struct nacl_irt_##group##_##version STRUCT_NAME(group);
#define MUX(group, name) STRUCT_NAME(group).name
#define DECLARE(group, name) typeof(MUX(group, name)) REAL(name);
#define DO_WRAP(group, name) do { \
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 abe62e6f4a..9b995359ae 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
@@ -25,8 +25,10 @@ int64_t strtoull(const char* nptr, char** endptr, int base) {
} // namespace
MountNode *MountHtml5Fs::Open(const Path& path, int mode) {
- if (!IsFilesystemOpen())
+ if (BlockUntilFilesystemOpen() != PP_OK) {
+ errno = ENODEV;
return NULL;
+ }
PP_Resource fileref = ppapi()->GetFileRefInterface()->Create(
filesystem_resource_, path.Join().c_str());
@@ -47,8 +49,8 @@ int MountHtml5Fs::Unlink(const Path& path) {
}
int MountHtml5Fs::Mkdir(const Path& path, int permissions) {
- if (!IsFilesystemOpen()) {
- errno = EINVAL;
+ if (BlockUntilFilesystemOpen() != PP_OK) {
+ errno = ENODEV;
return -1;
}
@@ -75,8 +77,8 @@ int MountHtml5Fs::Rmdir(const Path& path) {
}
int MountHtml5Fs::Remove(const Path& path) {
- if (!IsFilesystemOpen()) {
- errno = EINVAL;
+ if (BlockUntilFilesystemOpen() != PP_OK) {
+ errno = ENODEV;
return -1;
}
@@ -102,7 +104,8 @@ int MountHtml5Fs::Remove(const Path& path) {
MountHtml5Fs::MountHtml5Fs()
: filesystem_resource_(0),
- filesystem_open_(false) {
+ filesystem_open_has_result_(false),
+ filesystem_open_result_(PP_OK) {
}
bool MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
@@ -112,6 +115,8 @@ bool MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
if (!ppapi)
return false;
+ pthread_cond_init(&filesystem_open_cond_, NULL);
+
// Parse mount args.
PP_FileSystemType filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT;
int64_t expected_size = 0;
@@ -135,22 +140,41 @@ bool MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
if (filesystem_resource_ == 0)
return false;
- // Open the filesystem. Don't block, this could be called from the main
- // thread.
- ppapi->GetFileSystemInterface()->Open(filesystem_resource_, expected_size,
+ // We can't block the main thread, so make an asynchronous call if on main
+ // thread. If we are off-main-thread, then don't make an asynchronous call;
+ // otherwise we require a message loop.
+ bool main_thread = ppapi->IsMainThread();
+ PP_CompletionCallback cc = main_thread ?
PP_MakeCompletionCallback(&MountHtml5Fs::FilesystemOpenCallbackThunk,
- this));
+ this) :
+ PP_BlockUntilComplete();
- return true;
+ int32_t result = ppapi->GetFileSystemInterface()->Open(
+ filesystem_resource_, expected_size, cc);
+
+ if (!main_thread) {
+ filesystem_open_has_result_ = true;
+ filesystem_open_result_ = result;
+
+ return filesystem_open_result_ == PP_OK;
+ } else {
+ // We have to assume the call to Open will succeed; there is no better
+ // result to return here.
+ return true;
+ }
}
void MountHtml5Fs::Destroy() {
ppapi_->ReleaseResource(filesystem_resource_);
+ pthread_cond_destroy(&filesystem_open_cond_);
}
-bool MountHtml5Fs::IsFilesystemOpen() {
+int32_t MountHtml5Fs::BlockUntilFilesystemOpen() {
AutoLock lock(&lock_);
- return filesystem_open_;
+ while (!filesystem_open_has_result_) {
+ pthread_cond_wait(&filesystem_open_cond_, &lock_);
+ }
+ return filesystem_open_result_;
}
// static
@@ -162,5 +186,7 @@ void MountHtml5Fs::FilesystemOpenCallbackThunk(void* user_data,
void MountHtml5Fs::FilesystemOpenCallback(int32_t result) {
AutoLock lock(&lock_);
- filesystem_open_ = result == PP_OK;
+ filesystem_open_has_result_ = true;
+ filesystem_open_result_ = result;
+ pthread_cond_signal(&filesystem_open_cond_);
}
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h
index 1e532b5ac2..a6633be8af 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h
@@ -27,14 +27,16 @@ class MountHtml5Fs: public Mount {
virtual bool Init(int dev, StringMap_t& args, PepperInterface* ppapi);
virtual void Destroy();
- bool IsFilesystemOpen();
+ int32_t BlockUntilFilesystemOpen();
private:
static void FilesystemOpenCallbackThunk(void* user_data, int32_t result);
void FilesystemOpenCallback(int32_t result);
PP_Resource filesystem_resource_;
- bool filesystem_open_; // protected by lock_.
+ bool filesystem_open_has_result_; // protected by lock_.
+ int32_t filesystem_open_result_; // protected by lock_.
+ pthread_cond_t filesystem_open_cond_;
friend class Mount;
};
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 6d8856f293..9e862e38a0 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_http.cc
@@ -164,6 +164,8 @@ class MountNodeHttp : public MountNode {
virtual int Write(size_t offs, const void* buf, size_t count);
virtual size_t GetSize();
+ void SetCachedSize(off_t size);
+
protected:
MountNodeHttp(Mount* mount, const std::string& url, bool cache_content);
@@ -185,10 +187,17 @@ class MountNodeHttp : public MountNode {
std::vector<char> buffer_;
bool cache_content_;
+ bool has_cached_size_;
std::vector<char> cached_data_;
- friend class ::MountHttp;
+
+ friend class MountHttp;
};
+void MountNodeHttp::SetCachedSize(off_t size) {
+ has_cached_size_ = true;
+ stat_.st_size = size;
+}
+
int MountNodeHttp::FSync() {
errno = ENOSYS;
return -1;
@@ -224,10 +233,14 @@ int MountNodeHttp::GetStat(struct stat* stat) {
size_t entity_length;
- if (ParseContentLength(response_headers, &entity_length))
- stat_.st_size = static_cast<off_t>(entity_length);
- else
+ if (ParseContentLength(response_headers, &entity_length)) {
+ SetCachedSize(static_cast<off_t>(entity_length));
+ } else if (cache_content_ && !has_cached_size_) {
+ DownloadToCache();
+ } else {
+ // Don't use SetCachedSize here -- it is actually unknown.
stat_.st_size = 0;
+ }
stat_.st_atime = 0; // TODO(binji): Use "Last-Modified".
stat_.st_mtime = 0;
@@ -269,6 +282,14 @@ int MountNodeHttp::Write(size_t offs, const void* buf, size_t count) {
size_t MountNodeHttp::GetSize() {
// TODO(binji): This value should be cached properly; i.e. obey the caching
// headers returned by the server.
+ AutoLock lock(&lock_);
+ if (!has_cached_size_) {
+ // Even if DownloadToCache fails, the best result we can return is what
+ // was written to stat_.st_size.
+ if (cache_content_)
+ DownloadToCache();
+ }
+
return stat_.st_size;
}
@@ -276,7 +297,8 @@ MountNodeHttp::MountNodeHttp(Mount* mount, const std::string& url,
bool cache_content)
: MountNode(mount),
url_(url),
- cache_content_(cache_content) {
+ cache_content_(cache_content),
+ has_cached_size_(false) {
}
bool MountNodeHttp::OpenUrl(const char* method,
@@ -389,17 +411,17 @@ int MountNodeHttp::DownloadToCache() {
if (real_size < 0)
return -1;
- stat_.st_size = real_size;
+ SetCachedSize(real_size);
cached_data_.resize(real_size);
return real_size;
}
// We don't know how big the file is. Read in chunks.
cached_data_.resize(MAX_READ_BUFFER_SIZE);
- char* buf = cached_data_.data();
size_t total_bytes_read = 0;
size_t bytes_to_read = MAX_READ_BUFFER_SIZE;
while (true) {
+ char* buf = cached_data_.data() + total_bytes_read;
int bytes_read = DownloadToBuffer(loader, buf, bytes_to_read);
if (bytes_read < 0)
return -1;
@@ -407,12 +429,11 @@ int MountNodeHttp::DownloadToCache() {
total_bytes_read += bytes_read;
if (bytes_read < bytes_to_read) {
- stat_.st_size = total_bytes_read;
+ SetCachedSize(total_bytes_read);
cached_data_.resize(total_bytes_read);
return total_bytes_read;
}
- buf += bytes_read;
cached_data_.resize(total_bytes_read + bytes_to_read);
}
}
@@ -748,9 +769,9 @@ bool MountHttp::ParseManifest(char *text) {
path.Range(1, path.Size()) :
path.Join());
- MountNode* node = new MountNodeHttp(this, url, cache_content_);
+ MountNodeHttp* node = new MountNodeHttp(this, url, cache_content_);
node->Init(mode);
- node->stat_.st_size = atoi(lenstr);
+ node->SetCachedSize(atoi(lenstr));
MountNodeDir* dir_node = FindOrCreateDir(path.Parent());
dir_node->AddChild(path.Basename(), node);
@@ -763,19 +784,19 @@ bool MountHttp::ParseManifest(char *text) {
return true;
}
-char *MountHttp::LoadManifest(const std::string& manifestName) {
- Path manifestPath(manifestName);
- MountNode* manifiestNode = Open(manifestPath, O_RDONLY);
+char *MountHttp::LoadManifest(const std::string& manifest_name) {
+ Path manifest_path(manifest_name);
+ MountNode* manifest_node = Open(manifest_path, O_RDONLY);
- if (manifiestNode) {
- char *text = new char[manifiestNode->GetSize() + 1];
- off_t len = manifiestNode->Read(0, text, manifiestNode->GetSize());
- manifiestNode->Release();
+ if (manifest_node) {
+ char *text = new char[manifest_node->GetSize() + 1];
+ off_t len = manifest_node->Read(0, text, manifest_node->GetSize());
+ manifest_node->Release();
text[len] = 0;
return text;
}
- fprintf(stderr, "Could not open manifest: %s\n", manifestName.c_str());
+ fprintf(stderr, "Could not open manifest: %s\n", manifest_name.c_str());
return NULL;
}
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 e14ed3d21b..fa3035cbcc 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
@@ -115,7 +115,7 @@ MountNode* MountMem::Open(const Path& path, int mode) {
// If the node does not exist and we can't create it, fail
if ((mode & O_CREAT) == 0) return NULL;
- // Otherwise, create it with a single refernece
+ // Otherwise, create it with a single reference
mode = OpenModeToPermission(mode);
node = AllocateData(mode);
if (NULL == node) return NULL;
@@ -134,7 +134,7 @@ MountNode* MountMem::Open(const Path& path, int mode) {
return NULL;
}
- // Verify we got the requested permisions.
+ // Verify we got the requested permissions.
int req_mode = OpenModeToPermission(mode);
int obj_mode = node->GetMode() & OpenModeToPermission(O_RDWR);
if ((obj_mode & req_mode) != req_mode) {
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 d31b99fc27..823a138d68 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node.cc
@@ -85,15 +85,15 @@ void* MountNode::MMap(void* addr, size_t length, int prot, int flags,
void* new_addr = addr;
int err = _real_mmap(&new_addr, length, prot | PROT_WRITE, flags |
MAP_ANONYMOUS, -1, 0);
- if (addr == MAP_FAILED) {
- _real_munmap(addr, length);
+ if (new_addr == MAP_FAILED) {
+ _real_munmap(new_addr, length);
errno = err;
return MAP_FAILED;
}
- ssize_t cnt = Read(offset, addr, length);
+ ssize_t cnt = Read(offset, new_addr, length);
if (cnt == -1) {
- _real_munmap(addr, length);
+ _real_munmap(new_addr, length);
errno = ENOSYS;
return MAP_FAILED;
}
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 b4ca52ebe4..b5400140f9 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
@@ -8,6 +8,7 @@
#include <errno.h>
#include <fcntl.h>
#include <ppapi/c/pp_completion_callback.h>
+#include <ppapi/c/pp_directory_entry.h>
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_file_info.h>
#include <ppapi/c/ppb_file_io.h>
@@ -75,13 +76,6 @@ int MountNodeHtml5Fs::FSync() {
}
int MountNodeHtml5Fs::GetDents(size_t offs, struct dirent* pdir, size_t size) {
- // The directory reader interface is a dev interface, if it doesn't exist,
- // just fail.
- if (!mount_->ppapi()->GetDirectoryReaderInterface()) {
- errno = ENOSYS;
- return -1;
- }
-
// If the buffer pointer is invalid, fail
if (NULL == pdir) {
errno = EINVAL;
@@ -94,28 +88,19 @@ int MountNodeHtml5Fs::GetDents(size_t offs, struct dirent* pdir, size_t size) {
return -1;
}
- ScopedResource directory_reader(
- mount_->ppapi(),
- mount_->ppapi()->GetDirectoryReaderInterface()->Create(
- fileref_resource_));
- if (!directory_reader.pp_resource()) {
- errno = ENOSYS;
- return -1;
- }
-
OutputBuffer output_buf = { NULL, 0 };
PP_ArrayOutput output = { &GetOutputBuffer, &output_buf };
- int32_t result = mount_->ppapi()->GetDirectoryReaderInterface()->ReadEntries(
- directory_reader.pp_resource(), output,
- PP_BlockUntilComplete());
+ int32_t result =
+ mount_->ppapi()->GetFileRefInterface()->ReadDirectoryEntries(
+ fileref_resource_, output, PP_BlockUntilComplete());
if (result != PP_OK) {
errno = PPErrorToErrno(result);
return -1;
}
std::vector<struct dirent> dirents;
- PP_DirectoryEntry_Dev* entries =
- static_cast<PP_DirectoryEntry_Dev*>(output_buf.data);
+ PP_DirectoryEntry* entries =
+ static_cast<PP_DirectoryEntry*>(output_buf.data);
for (int i = 0; i < output_buf.element_count; ++i) {
PP_Var file_name_var = mount_->ppapi()->GetFileRefInterface()->GetName(
diff --git a/native_client_sdk/src/libraries/nacl_io/path.cc b/native_client_sdk/src/libraries/nacl_io/path.cc
index 463e9d4f44..6cab36a441 100644
--- a/native_client_sdk/src/libraries/nacl_io/path.cc
+++ b/native_client_sdk/src/libraries/nacl_io/path.cc
@@ -180,7 +180,7 @@ StringArray_t Path::Split(const std::string& path) {
while (next != std::string::npos) {
next = path.find('/', offs);
- // Remove extra seperators
+ // Remove extra separators
if (next == offs) {
++offs;
continue;
diff --git a/native_client_sdk/src/libraries/nacl_io/path.h b/native_client_sdk/src/libraries/nacl_io/path.h
index d1a381ba0e..7ac41f2f25 100644
--- a/native_client_sdk/src/libraries/nacl_io/path.h
+++ b/native_client_sdk/src/libraries/nacl_io/path.h
@@ -61,7 +61,7 @@ class Path {
private:
// Internal representation of the path stored an array of string representing
- // the directory traversal. The first string is a "/" if this is an abolute
+ // the directory traversal. The first string is a "/" if this is an absolute
// path.
StringArray_t paths_;
};
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 8af45c8744..679573607d 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
@@ -18,18 +18,11 @@
* END_INTERFACE(FrobInterface, PPB_Frob)
*/
-BEGIN_INTERFACE(ConsoleInterface, PPB_Console, PPB_CONSOLE_INTERFACE)
+BEGIN_INTERFACE(ConsoleInterface, PPB_Console, PPB_CONSOLE_INTERFACE_1_0)
METHOD3(ConsoleInterface, void, Log, PP_Instance, PP_LogLevel, struct PP_Var)
END_INTERFACE(ConsoleInterface, PPB_Console)
-BEGIN_INTERFACE(DirectoryReaderInterface, PPB_DirectoryReader_Dev,
- PPB_DIRECTORYREADER_DEV_INTERFACE)
- METHOD1(DirectoryReaderInterface, PP_Resource, Create, PP_Resource)
- METHOD3(DirectoryReaderInterface, int32_t, ReadEntries, PP_Resource,
- PP_ArrayOutput, PP_CompletionCallback)
-END_INTERFACE(DirectoryReaderInterface, PPB_DirectoryReader_Dev)
-
-BEGIN_INTERFACE(FileIoInterface, PPB_FileIO, PPB_FILEIO_INTERFACE)
+BEGIN_INTERFACE(FileIoInterface, PPB_FileIO, PPB_FILEIO_INTERFACE_1_0)
METHOD1(FileIoInterface, void, Close, PP_Resource)
METHOD1(FileIoInterface, PP_Resource, Create, PP_Resource)
METHOD2(FileIoInterface, int32_t, Flush, PP_Resource,
@@ -46,31 +39,34 @@ BEGIN_INTERFACE(FileIoInterface, PPB_FileIO, PPB_FILEIO_INTERFACE)
const char*, int32_t, PP_CompletionCallback)
END_INTERFACE(FileIoInterface, PPB_FileIO)
-BEGIN_INTERFACE(FileRefInterface, PPB_FileRef, PPB_FILEREF_INTERFACE)
+BEGIN_INTERFACE(FileRefInterface, PPB_FileRef, PPB_FILEREF_INTERFACE_1_0)
METHOD2(FileRefInterface, PP_Resource, Create, PP_Resource, const char*)
METHOD2(FileRefInterface, int32_t, Delete, PP_Resource, PP_CompletionCallback)
METHOD1(FileRefInterface, PP_Var, GetName, PP_Resource)
METHOD3(FileRefInterface, int32_t, MakeDirectory, PP_Resource, PP_Bool,
PP_CompletionCallback)
+ METHOD3(FileRefInterface, int32_t, ReadDirectoryEntries, PP_Resource,
+ const PP_ArrayOutput&, PP_CompletionCallback)
END_INTERFACE(FileRefInterface, PPB_FileRef)
-BEGIN_INTERFACE(FileSystemInterface, PPB_FileSystem, PPB_FILESYSTEM_INTERFACE)
+BEGIN_INTERFACE(FileSystemInterface, PPB_FileSystem,
+ PPB_FILESYSTEM_INTERFACE_1_0)
METHOD2(FileSystemInterface, PP_Resource, Create, PP_Instance,
PP_FileSystemType)
METHOD3(FileSystemInterface, int32_t, Open, PP_Resource, int64_t,
PP_CompletionCallback)
END_INTERFACE(FileSystemInterface, PPB_FileSystem)
-BEGIN_INTERFACE(MessagingInterface, PPB_Messaging, PPB_MESSAGING_INTERFACE)
+BEGIN_INTERFACE(MessagingInterface, PPB_Messaging, PPB_MESSAGING_INTERFACE_1_0)
METHOD2(MessagingInterface, void, PostMessage, PP_Instance, struct PP_Var)
END_INTERFACE(MessagingInterface, PPB_Messaging)
-BEGIN_INTERFACE(VarInterface, PPB_Var, PPB_VAR_INTERFACE)
+BEGIN_INTERFACE(VarInterface, PPB_Var, PPB_VAR_INTERFACE_1_1)
METHOD2(VarInterface, struct PP_Var, VarFromUtf8, const char *, uint32_t)
METHOD2(VarInterface, const char*, VarToUtf8, PP_Var, uint32_t*)
END_INTERFACE(VarInterface, PPB_Var)
-BEGIN_INTERFACE(URLLoaderInterface, PPB_URLLoader, PPB_URLLOADER_INTERFACE)
+BEGIN_INTERFACE(URLLoaderInterface, PPB_URLLoader, PPB_URLLOADER_INTERFACE_1_0)
METHOD1(URLLoaderInterface, PP_Resource, Create, PP_Instance)
METHOD3(URLLoaderInterface, int32_t, Open, PP_Resource, PP_Resource,
PP_CompletionCallback)
@@ -81,14 +77,14 @@ BEGIN_INTERFACE(URLLoaderInterface, PPB_URLLoader, PPB_URLLOADER_INTERFACE)
END_INTERFACE(URLLoaderInterface, PPB_URLLoader)
BEGIN_INTERFACE(URLRequestInfoInterface, PPB_URLRequestInfo,
- PPB_URLREQUESTINFO_INTERFACE)
+ PPB_URLREQUESTINFO_INTERFACE_1_0)
METHOD1(URLRequestInfoInterface, PP_Resource, Create, PP_Instance)
METHOD3(URLRequestInfoInterface, PP_Bool, SetProperty, PP_Resource,
PP_URLRequestProperty, PP_Var)
END_INTERFACE(URLRequestInfoInterface, PPB_URLRequestInfo)
BEGIN_INTERFACE(URLResponseInfoInterface, PPB_URLResponseInfo,
- PPB_URLRESPONSEINFO_INTERFACE)
+ PPB_URLRESPONSEINFO_INTERFACE_1_0)
METHOD2(URLResponseInfoInterface, PP_Var, GetProperty, PP_Resource,
PP_URLResponseProperty)
END_INTERFACE(URLResponseInfoInterface, PPB_URLResponseInfo)
diff --git a/native_client_sdk/src/libraries/nacl_io/pepper_interface.h b/native_client_sdk/src/libraries/nacl_io/pepper_interface.h
index edeb0367b0..512fd6fdbf 100644
--- a/native_client_sdk/src/libraries/nacl_io/pepper_interface.h
+++ b/native_client_sdk/src/libraries/nacl_io/pepper_interface.h
@@ -5,7 +5,6 @@
#ifndef LIBRARIES_NACL_IO_PEPPER_INTERFACE_H_
#define LIBRARIES_NACL_IO_PEPPER_INTERFACE_H_
-#include <ppapi/c/dev/ppb_directory_reader_dev.h>
#include <ppapi/c/pp_completion_callback.h>
#include <ppapi/c/pp_file_info.h>
#include <ppapi/c/pp_instance.h>
@@ -33,12 +32,12 @@
// Forward declare interface classes.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
class BaseClass;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
int PPErrorToErrno(int32_t err);
@@ -48,17 +47,19 @@ class PepperInterface {
virtual PP_Instance GetInstance() = 0;
virtual void AddRefResource(PP_Resource) = 0;
virtual void ReleaseResource(PP_Resource) = 0;
+ virtual bool IsMainThread() = 0;
// Interface getters.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
virtual BaseClass* Get##BaseClass() = 0;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
};
// Interface class definitions.
+#include "nacl_io/pepper/undef_macros.h"
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
class BaseClass { \
public: \
@@ -77,7 +78,6 @@ class PepperInterface {
Type4) \
virtual ReturnType MethodName(Type0, Type1, Type2, Type3, Type4) = 0;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
class ScopedResource {
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 cbe7558e99..ea74756f0d 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
@@ -104,6 +104,10 @@ void RealPepperInterface::ReleaseResource(PP_Resource resource) {
core_interface_->ReleaseResource(resource);
}
+bool RealPepperInterface::IsMainThread() {
+ return core_interface_->IsMainThread();
+}
+
// Define getter function.
#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
diff --git a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.h b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.h
index 09346cee7b..2f7fc2fbd4 100644
--- a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.h
+++ b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.h
@@ -11,12 +11,12 @@
#include "pepper_interface.h"
// Forward declare interface classes.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
class Real##BaseClass;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
class RealPepperInterface : public PepperInterface {
public:
@@ -26,14 +26,15 @@ class RealPepperInterface : public PepperInterface {
virtual PP_Instance GetInstance();
virtual void AddRefResource(PP_Resource);
virtual void ReleaseResource(PP_Resource);
+ virtual bool IsMainThread();
// Interface getters.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
virtual BaseClass* Get##BaseClass();
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
int32_t InitializeMessageLoop();
@@ -43,12 +44,12 @@ class RealPepperInterface : public PepperInterface {
const PPB_MessageLoop* message_loop_interface_;
// Interface pointers.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
Real##BaseClass* BaseClass##interface_;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
};
#endif // LIBRARIES_NACL_IO_REAL_PEPPER_INTERFACE_H_
diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_object_test.cc b/native_client_sdk/src/libraries/nacl_io_test/kernel_object_test.cc
index 01b0573c89..268c6f51a6 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/kernel_object_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_object_test.cc
@@ -105,7 +105,7 @@ TEST_F(KernelObjectTest, Referencing) {
EXPECT_EQ(4, mnt->RefCount());
EXPECT_EQ(2, handle2->RefCount());
- // Handles are expectd to come out in order
+ // Handles are expected to come out in order
EXPECT_EQ(0, fd1);
EXPECT_EQ(1, fd2);
EXPECT_EQ(2, fd3);
@@ -114,7 +114,7 @@ TEST_F(KernelObjectTest, Referencing) {
EXPECT_EQ(handle, proxy->AcquireHandle(fd1));
EXPECT_EQ(handle, proxy->AcquireHandle(fd2));
- // A non existant fd should fail
+ // A non existent fd should fail
EXPECT_EQ(NULL, proxy->AcquireHandle(-1));
EXPECT_EQ(EBADF, errno);
EXPECT_EQ(NULL, proxy->AcquireHandle(100));
@@ -162,7 +162,7 @@ TEST_F(KernelObjectTest, FreeAndReassignFD) {
EXPECT_EQ(1, handle_count);
EXPECT_EQ(1, handle->RefCount());
- // Assign to a non-existant FD
+ // Assign to a non-existent FD
proxy->FreeAndReassignFD(2, handle);
EXPECT_EQ((KernelHandle*)NULL, proxy->AcquireHandle(0));
EXPECT_EQ((KernelHandle*)NULL, proxy->AcquireHandle(1));
diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
index d6a15308d7..c84b761a6a 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
@@ -7,8 +7,12 @@
#include <string.h>
#include <gmock/gmock.h>
#include <ppapi/c/ppb_file_io.h>
+#include <ppapi/c/pp_directory_entry.h>
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_instance.h>
+#if defined(WIN32)
+#include <windows.h> // For Sleep()
+#endif
#include "mock_util.h"
#include "nacl_io/mount_html5fs.h"
@@ -19,6 +23,7 @@ using ::testing::_;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Return;
+using ::testing::SaveArg;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::WithArgs;
@@ -40,32 +45,44 @@ class MountHtml5FsTest : public ::testing::Test {
public:
MountHtml5FsTest();
~MountHtml5FsTest();
- void SetUpFilesystem(PP_FileSystemType, int);
+ void SetUpFilesystemExpectations(PP_FileSystemType, int,
+ bool async_callback=false);
protected:
PepperInterfaceMock* ppapi_;
+ PP_CompletionCallback open_filesystem_callback_;
static const PP_Instance instance_ = 123;
static const PP_Resource filesystem_resource_ = 234;
};
MountHtml5FsTest::MountHtml5FsTest()
- : ppapi_(NULL) {
+ : ppapi_(new PepperInterfaceMock(instance_)) {
}
MountHtml5FsTest::~MountHtml5FsTest() {
delete ppapi_;
}
-void MountHtml5FsTest::SetUpFilesystem(PP_FileSystemType fstype,
- int expected_size) {
- ppapi_ = new PepperInterfaceMock(instance_);
+void MountHtml5FsTest::SetUpFilesystemExpectations(
+ PP_FileSystemType fstype,
+ int expected_size,
+ bool async_callback) {
FileSystemInterfaceMock* filesystem = ppapi_->GetFileSystemInterface();
EXPECT_CALL(*filesystem, Create(instance_, fstype))
.Times(1)
.WillOnce(Return(filesystem_resource_));
- EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
- .WillOnce(CallCallback<2>(int32_t(PP_OK)));
+
+ if (async_callback) {
+ EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
+ .WillOnce(DoAll(SaveArg<2>(&open_filesystem_callback_),
+ Return(int32_t(PP_OK))));
+ EXPECT_CALL(*ppapi_, IsMainThread()).WillOnce(Return(PP_TRUE));
+ } else {
+ EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
+ .WillOnce(CallCallback<2>(int32_t(PP_OK)));
+ EXPECT_CALL(*ppapi_, IsMainThread()).WillOnce(Return(PP_FALSE));
+ }
EXPECT_CALL(*ppapi_, ReleaseResource(filesystem_resource_));
}
@@ -76,6 +93,10 @@ class MountHtml5FsNodeTest : public MountHtml5FsTest {
virtual void SetUp();
virtual void TearDown();
+ void SetUpNodeExpectations();
+ void InitFilesystem();
+ void InitNode();
+
protected:
MountHtml5FsMock* mnt_;
MountNode* node_;
@@ -99,13 +120,18 @@ MountHtml5FsNodeTest::MountHtml5FsNodeTest()
}
void MountHtml5FsNodeTest::SetUp() {
- SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
- StringMap_t map;
- mnt_ = new MountHtml5FsMock(map, ppapi_);
-
fileref_ = ppapi_->GetFileRefInterface();
fileio_ = ppapi_->GetFileIoInterface();
+}
+
+void MountHtml5FsNodeTest::TearDown() {
+ if (mnt_) {
+ mnt_->ReleaseNode(node_);
+ delete mnt_;
+ }
+}
+void MountHtml5FsNodeTest::SetUpNodeExpectations() {
// Open.
EXPECT_CALL(*fileref_, Create(filesystem_resource_, StrEq(&path_[0])))
.WillOnce(Return(fileref_resource_));
@@ -121,36 +147,143 @@ void MountHtml5FsNodeTest::SetUp() {
EXPECT_CALL(*ppapi_, ReleaseResource(fileref_resource_));
EXPECT_CALL(*ppapi_, ReleaseResource(fileio_resource_));
EXPECT_CALL(*fileio_, Flush(fileio_resource_, _));
+}
+
+void MountHtml5FsNodeTest::InitFilesystem() {
+ StringMap_t map;
+ mnt_ = new MountHtml5FsMock(map, ppapi_);
+}
+void MountHtml5FsNodeTest::InitNode() {
node_ = mnt_->Open(Path(path_), O_CREAT | O_RDWR);
ASSERT_NE((MountNode*)NULL, node_);
}
-void MountHtml5FsNodeTest::TearDown() {
- mnt_->ReleaseNode(node_);
- delete mnt_;
+// Node test where the filesystem is opened synchronously; that is, the
+// creation of the mount blocks until the filesystem is ready.
+class MountHtml5FsNodeSyncTest : public MountHtml5FsNodeTest {
+ public:
+ virtual void SetUp();
+};
+
+void MountHtml5FsNodeSyncTest::SetUp() {
+ MountHtml5FsNodeTest::SetUp();
+ SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
+ InitFilesystem();
+ SetUpNodeExpectations();
+ InitNode();
}
-void ReadEntriesAction(const PP_ArrayOutput& output) {
+void ReadDirectoryEntriesAction(const PP_ArrayOutput& output) {
const int fileref_resource_1 = 238;
const int fileref_resource_2 = 239;
- std::vector<PP_DirectoryEntry_Dev> entries;
- PP_DirectoryEntry_Dev entry1 = { fileref_resource_1, PP_FILETYPE_REGULAR };
- PP_DirectoryEntry_Dev entry2 = { fileref_resource_2, PP_FILETYPE_REGULAR };
+ std::vector<PP_DirectoryEntry> entries;
+ PP_DirectoryEntry entry1 = { fileref_resource_1, PP_FILETYPE_REGULAR };
+ PP_DirectoryEntry entry2 = { fileref_resource_2, PP_FILETYPE_REGULAR };
entries.push_back(entry1);
entries.push_back(entry2);
void* dest = output.GetDataBuffer(
- output.user_data, 2, sizeof(PP_DirectoryEntry_Dev));
- memcpy(dest, &entries[0], sizeof(PP_DirectoryEntry_Dev) * 2);
+ output.user_data, 2, sizeof(PP_DirectoryEntry));
+ memcpy(dest, &entries[0], sizeof(PP_DirectoryEntry) * 2);
+}
+
+class MountHtml5FsNodeAsyncTest : public MountHtml5FsNodeTest {
+ public:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ private:
+ static void* ThreadThunk(void* param);
+ void Thread();
+
+ enum {
+ STATE_INIT,
+ STATE_INIT_NODE,
+ STATE_INIT_NODE_FINISHED,
+ } state_;
+
+ pthread_t thread_;
+ pthread_cond_t cond_;
+ pthread_mutex_t mutex_;
+};
+
+void MountHtml5FsNodeAsyncTest::SetUp() {
+ MountHtml5FsNodeTest::SetUp();
+
+ state_ = STATE_INIT;
+
+ pthread_create(&thread_, NULL, &MountHtml5FsNodeAsyncTest::ThreadThunk, this);
+ pthread_mutex_init(&mutex_, NULL);
+ pthread_cond_init(&cond_, NULL);
+
+ // This test shows that even if the filesystem open callback happens after an
+ // attempt to open a node, it still works (opening the node blocks until the
+ // filesystem is ready).
+ // true => asynchronous filesystem open.
+ SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0, true);
+ InitFilesystem();
+ SetUpNodeExpectations();
+
+ // Signal the other thread to try opening a Node.
+ pthread_mutex_lock(&mutex_);
+ state_ = STATE_INIT_NODE;
+ pthread_cond_signal(&cond_);
+ pthread_mutex_unlock(&mutex_);
+
+ // Wait for a bit...
+ // TODO(binji): this will be flaky. How to test this better?
+#if defined(WIN32)
+ Sleep(500); // milliseconds
+#else
+ usleep(500*1000); // microseconds
+#endif
+
+ // Call the filesystem open callback.
+ (*open_filesystem_callback_.func)(open_filesystem_callback_.user_data, PP_OK);
+
+ // Wait for the other thread to unblock and signal us.
+ pthread_mutex_lock(&mutex_);
+ while (state_ != STATE_INIT_NODE_FINISHED)
+ pthread_cond_wait(&cond_, &mutex_);
+ pthread_mutex_unlock(&mutex_);
+}
+
+void MountHtml5FsNodeAsyncTest::TearDown() {
+ pthread_cond_destroy(&cond_);
+ pthread_mutex_destroy(&mutex_);
+
+ MountHtml5FsNodeTest::TearDown();
+}
+
+void* MountHtml5FsNodeAsyncTest::ThreadThunk(void* param) {
+ static_cast<MountHtml5FsNodeAsyncTest*>(param)->Thread();
+ return NULL;
+}
+
+void MountHtml5FsNodeAsyncTest::Thread() {
+ // Wait for the "main" thread to tell us to open the Node.
+ pthread_mutex_lock(&mutex_);
+ while (state_ != STATE_INIT_NODE)
+ pthread_cond_wait(&cond_, &mutex_);
+ pthread_mutex_unlock(&mutex_);
+
+ // Opening the node blocks until the filesystem is open...
+ InitNode();
+
+ // Signal the "main" thread to tell it we're unblocked.
+ pthread_mutex_lock(&mutex_);
+ state_ = STATE_INIT_NODE_FINISHED;
+ pthread_cond_signal(&cond_);
+ pthread_mutex_unlock(&mutex_);
}
} // namespace
TEST_F(MountHtml5FsTest, FilesystemType) {
- SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 100);
+ SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 100);
StringMap_t map;
map["type"] = "PERSISTENT";
@@ -163,7 +296,7 @@ TEST_F(MountHtml5FsTest, Mkdir) {
const PP_Resource fileref_resource = 235;
// These are the default values.
- SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
+ SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
FileRefInterfaceMock* fileref = ppapi_->GetFileRefInterface();
@@ -186,7 +319,7 @@ TEST_F(MountHtml5FsTest, Remove) {
const PP_Resource fileref_resource = 235;
// These are the default values.
- SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
+ SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
FileRefInterfaceMock* fileref = ppapi_->GetFileRefInterface();
@@ -203,10 +336,13 @@ TEST_F(MountHtml5FsTest, Remove) {
ASSERT_EQ(0, result);
}
-TEST_F(MountHtml5FsNodeTest, OpenAndClose) {
+TEST_F(MountHtml5FsNodeAsyncTest, AsyncFilesystemOpen) {
+}
+
+TEST_F(MountHtml5FsNodeSyncTest, OpenAndClose) {
}
-TEST_F(MountHtml5FsNodeTest, Write) {
+TEST_F(MountHtml5FsNodeSyncTest, Write) {
const int offset = 10;
const int count = 20;
const char buffer[30] = {0};
@@ -218,7 +354,7 @@ TEST_F(MountHtml5FsNodeTest, Write) {
EXPECT_EQ(count, result);
}
-TEST_F(MountHtml5FsNodeTest, Read) {
+TEST_F(MountHtml5FsNodeSyncTest, Read) {
const int offset = 10;
const int count = 20;
char buffer[30] = {0};
@@ -230,7 +366,7 @@ TEST_F(MountHtml5FsNodeTest, Read) {
EXPECT_EQ(count, result);
}
-TEST_F(MountHtml5FsNodeTest, GetStat) {
+TEST_F(MountHtml5FsNodeSyncTest, GetStat) {
const int size = 123;
const int creation_time = 1000;
const int access_time = 2000;
@@ -259,7 +395,7 @@ TEST_F(MountHtml5FsNodeTest, GetStat) {
EXPECT_EQ(creation_time, statbuf.st_ctime);
}
-TEST_F(MountHtml5FsNodeTest, Truncate) {
+TEST_F(MountHtml5FsNodeSyncTest, Truncate) {
const int size = 123;
EXPECT_CALL(*fileio_, SetLength(fileio_resource_, size, _))
.WillOnce(Return(int32_t(PP_OK)));
@@ -268,8 +404,7 @@ TEST_F(MountHtml5FsNodeTest, Truncate) {
EXPECT_EQ(0, result);
}
-TEST_F(MountHtml5FsNodeTest, GetDents) {
- const int dir_reader_resource = 237;
+TEST_F(MountHtml5FsNodeSyncTest, GetDents) {
const int fileref_resource_1 = 238;
const int fileref_resource_2 = 239;
@@ -286,13 +421,9 @@ TEST_F(MountHtml5FsNodeTest, GetDents) {
fileref_name_2.value.as_id = fileref_name_id_2;
VarInterfaceMock* var = ppapi_->GetVarInterface();
- DirectoryReaderInterfaceMock* dir_reader =
- ppapi_->GetDirectoryReaderInterface();
- EXPECT_CALL(*dir_reader, Create(fileref_resource_))
- .WillOnce(Return(dir_reader_resource));
- EXPECT_CALL(*dir_reader, ReadEntries(dir_reader_resource, _, _))
- .WillOnce(DoAll(WithArgs<1>(Invoke(ReadEntriesAction)),
+ EXPECT_CALL(*fileref_, ReadDirectoryEntries(fileref_resource_, _, _))
+ .WillOnce(DoAll(WithArgs<1>(Invoke(ReadDirectoryEntriesAction)),
Return(int32_t(PP_OK))));
EXPECT_CALL(*fileref_, GetName(fileref_resource_1))
@@ -305,7 +436,6 @@ TEST_F(MountHtml5FsNodeTest, GetDents) {
EXPECT_CALL(*var, VarToUtf8(IsEqualToVar(fileref_name_2), _))
.WillOnce(Return(fileref_name_cstr_2));
- EXPECT_CALL(*ppapi_, ReleaseResource(dir_reader_resource));
EXPECT_CALL(*ppapi_, ReleaseResource(fileref_resource_1));
EXPECT_CALL(*ppapi_, ReleaseResource(fileref_resource_2));
diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_http_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_http_test.cc
index f117093061..350874d34d 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/mount_http_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/mount_http_test.cc
@@ -312,16 +312,18 @@ TEST_F(MountHttpNodeTest, ReadCachedNoContentLength) {
OpenNode();
ResetMocks();
- // Unknown size.
- EXPECT_EQ(0, node_->GetSize());
-
- char buf[10];
- memset(&buf[0], 0, sizeof(buf));
-
ExpectOpen("GET");
ExpectHeaders("");
SetResponse(200, ""); // No Content-Length response here.
SetResponseBody("Here is some response text. And some more.");
+
+ // GetSize will Read() because it didn't get the content length from the HEAD
+ // request.
+ EXPECT_EQ(42, node_->GetSize());
+
+ char buf[10];
+ memset(&buf[0], 0, sizeof(buf));
+
node_->Read(0, buf, sizeof(buf) - 1);
EXPECT_STREQ("Here is s", &buf[0]);
ResetMocks();
diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
index 3b8df4ddb4..1604ccafd3 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
@@ -56,7 +56,7 @@ TEST(MountTest, Sanity) {
// A memory mount starts with one directory node: the root.
EXPECT_EQ(1, mnt->num_nodes());
- // Fail to open non existant file
+ // Fail to open non existent file
EXPECT_EQ(NULL_NODE, mnt->Open(Path("/foo"), O_RDWR));
EXPECT_EQ(errno, ENOENT);
diff --git a/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.cc b/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.cc
index 0822028089..95699256ae 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.cc
@@ -9,12 +9,12 @@ PepperInterfaceMock::PepperInterfaceMock(PP_Instance instance)
: instance_(instance),
// Initialize interfaces.
+#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 BaseClass##Mock),
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
// Dummy value so we can ensure that no interface ends the initializer list.
dummy_(0) {
@@ -23,12 +23,12 @@ PepperInterfaceMock::PepperInterfaceMock(PP_Instance instance)
PepperInterfaceMock::~PepperInterfaceMock() {
// Delete interfaces.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
delete BaseClass##interface_;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
}
@@ -37,6 +37,7 @@ PP_Instance PepperInterfaceMock::GetInstance() {
}
// Define Getter functions, constructors, destructors.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
@@ -48,4 +49,3 @@ PP_Instance PepperInterfaceMock::GetInstance() {
BaseClass##Mock::~BaseClass##Mock() { \
}
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
diff --git a/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.h b/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.h
index 0fe3743181..c11cce890d 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.h
+++ b/native_client_sdk/src/libraries/nacl_io_test/pepper_interface_mock.h
@@ -9,6 +9,7 @@
#include "nacl_io/pepper_interface.h"
// Mock interface class definitions.
+#include "nacl_io/pepper/undef_macros.h"
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
class BaseClass##Mock : public BaseClass { \
public: \
@@ -28,7 +29,6 @@
Type4) \
MOCK_METHOD5(MethodName, ReturnType(Type0, Type1, Type2, Type3, Type4));
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
class PepperInterfaceMock : public PepperInterface {
@@ -39,25 +39,26 @@ class PepperInterfaceMock : public PepperInterface {
virtual PP_Instance GetInstance();
MOCK_METHOD1(AddRefResource, void(PP_Resource));
MOCK_METHOD1(ReleaseResource, void(PP_Resource));
+ MOCK_METHOD0(IsMainThread, bool());
// Interface getters.
+#include "nacl_io/pepper/undef_macros.h"
#include "nacl_io/pepper/define_empty_macros.h"
#undef BEGIN_INTERFACE
#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
virtual BaseClass##Mock* Get##BaseClass();
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
private:
PP_Instance instance_;
// Interface pointers.
+#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##Mock* BaseClass##interface_;
#include "nacl_io/pepper/all_interfaces.h"
-#include "nacl_io/pepper/undef_macros.h"
int dummy_;
};
diff --git a/native_client_sdk/src/libraries/ppapi_main/library.dsc b/native_client_sdk/src/libraries/ppapi_main/library.dsc
index 3386c5a90d..366fde4b6a 100644
--- a/native_client_sdk/src/libraries/ppapi_main/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_main/library.dsc
@@ -6,6 +6,7 @@
'TYPE' : 'lib',
'SOURCES' : [
"ppapi_instance.cc",
+ "ppapi_instance2d.cc",
"ppapi_instance3d.cc",
"ppapi_main.cc",
"ppapi_queue.cc",
@@ -17,6 +18,7 @@
'FILES': [
"ppapi_event.h",
"ppapi_instance.h",
+ "ppapi_instance2d.h",
"ppapi_instance3d.h",
"ppapi_main.h",
"ppapi_queue.h",
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h
index 6d222db1be..d991192fe6 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_event.h
@@ -18,7 +18,7 @@ EXTERN_C_BEGIN
/*
* Event Structures
*
- * The following event structures are based on the equivilent structs
+ * The following event structures are based on the equivalent structs
* defined in ppapi/c/ppb_input_event.h.
*
*/
@@ -78,4 +78,4 @@ typedef struct {
EXTERN_C_END
-#endif // PPAPI_MAIN_PPAPI_EVENT_H_ \ No newline at end of file
+#endif // PPAPI_MAIN_PPAPI_EVENT_H_
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
index 2dc6f792d8..2816c74817 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.cc
@@ -40,31 +40,67 @@ struct StartInfo {
const char** argv_;
};
-void* PPAPIInstance::StartMain(void *info) {
- StartInfo* si = static_cast<StartInfo*>(info);
- si->inst_->main_loop_.AttachToCurrentThread();
- if (NULL != info) {
- ppapi_main(si->argc_, si->argv_);
+//
+// The starting point for 'main'. We create this thread to hide the real
+// main pepper thread which must never be blocked.
+//
+void* PPAPIInstance::MainThreadThunk(void *info) {
+ StartInfo* si = static_cast<StartInfo*>(info);
+ int ret = si->inst_->MainThread(si->argc_, si->argv_);
- for (uint32_t i = 0; i < si->argc_; i++) {
- delete[] si->argv_[i];
- }
- delete[] si->argv_;
- delete si;
- }
- else {
- const char *argv[] = { "NEXE", NULL };
- ppapi_main(1, argv);
+ printf("Main thread returned with %d.\n", ret);
+ for (uint32_t i = 0; i < si->argc_; i++) {
+ delete[] si->argv_[i];
}
+ delete[] si->argv_;
+ delete si;
+
+ return NULL;
+}
+
+//
+// Enabled with pm_use_main=False this creates a second thread where we
+// send all input, view change, buffer swap, etc... messages. This allows us
+// avoid blocking the main pepper thread which would otherwise recieves these
+// messages, and may need to lock to act on them.
+//
+void *PPAPIInstance::EventThreadThunk(void *this_ptr) {
+ PPAPIInstance *pInst = static_cast<PPAPIInstance*>(this_ptr);
+ return pInst->EventThread();
+}
+
+
+//
+// The default implementation supports running a 'C' main.
+//
+int PPAPIInstance::MainThread(int argc, const char *argv[]) {
+ return ppapi_main(argc, argv);
+}
+
+//
+// The default implementation just waits to processes forwarded events.
+//
+void* PPAPIInstance::EventThread() {
+ render_loop_.AttachToCurrentThread();
+ render_loop_.Run();
+ printf("Event thread exiting.\n");
return NULL;
}
+
PPAPIInstance::PPAPIInstance(PP_Instance instance, const char *args[])
: pp::Instance(instance),
main_loop_(this),
- has_focus_(false) {
+ has_focus_(false),
+ fullscreen_(this),
+ is_context_bound_(false),
+ callback_factory_(this),
+ use_main_thread_(true),
+ render_loop_(this) {
+
+ // Place PPAPI_MAIN_USE arguments into properties map
while (*args) {
std::string key = *args++;
std::string val = *args++;
@@ -77,20 +113,28 @@ PPAPIInstance::PPAPIInstance(PP_Instance instance, const char *args[])
PP_INPUTEVENT_CLASS_TOUCH);
}
-PPAPIInstance::~PPAPIInstance() {
-}
+PPAPIInstance::~PPAPIInstance() {}
+
bool PPAPIInstance::Init(uint32_t arg,
const char* argn[],
const char* argv[]) {
StartInfo* si = new StartInfo;
+
si->inst_ = this;
si->argc_ = 1;
si->argv_ = new const char *[arg*2+1];
si->argv_[0] = NULL;
+ // Process arguments passed into Module INIT from JavaScript
for (uint32_t i=0; i < arg; i++) {
+ if (argv[i]) {
+ printf("ARG %s=%s\n", argn[i], argv[i]);
+ } else {
+ printf("ARG %s\n", argn[i]);
+ }
+
// If we start with PM prefix set the instance argument map
if (0 == strncmp(argn[i], "pm_", 3)) {
std::string key = argn[i];
@@ -128,9 +172,10 @@ bool PPAPIInstance::Init(uint32_t arg,
si->argv_[0] = name;
}
+
if (ProcessProperties()) {
pthread_t main_thread;
- int ret = pthread_create(&main_thread, NULL, StartMain,
+ int ret = pthread_create(&main_thread, NULL, MainThreadThunk,
static_cast<void*>(si));
return ret == 0;
}
@@ -152,13 +197,13 @@ bool PPAPIInstance::ProcessProperties() {
const char* stderr_path = GetProperty("pm_stderr", "/dev/console3");
const char* queue_size = GetProperty("pm_queue_size", "1024");
- // Force a miniumum size of 4
+ // Build the event Queue with a minimum size of 4
uint32_t queue_size_int = atoi(queue_size);
if (queue_size_int < 4) queue_size_int = 4;
event_queue_.SetSize(queue_size_int);
+ // Enable NaCl IO to map STDIN, STDOUT, and STDERR
nacl_io_init_ppapi(PPAPI_GetInstanceId(), PPAPI_GetInterface);
-
int fd0 = open(stdin_path, O_RDONLY);
dup2(fd0, 0);
@@ -170,11 +215,23 @@ bool PPAPIInstance::ProcessProperties() {
setvbuf(stderr, NULL, _IOLBF, 0);
setvbuf(stdout, NULL, _IOLBF, 0);
+
+ const char *use_main_str = GetProperty("pm_use_main", "true");
+ use_main_thread_ = !strcasecmp(use_main_str, "true");
+
+ // Create seperate thread for processing events.
+ printf("Events on main thread = %s.\n", use_main_str);
+ if (!use_main_thread_) {
+ pthread_t event_thread;
+ int ret = pthread_create(&event_thread, NULL, EventThreadThunk,
+ static_cast<void*>(this));
+ return ret == 0;
+ }
return true;
}
-void PPAPIInstance::HandleMessage(const pp::Var& message) {}
-
+void PPAPIInstance::HandleMessage(const pp::Var& message) {
+}
bool PPAPIInstance::HandleInputEvent(const pp::InputEvent& event) {
PPAPIEvent* event_ptr;
@@ -266,9 +323,53 @@ void PPAPIInstance::ReleaseInputEvent(PPAPIEvent* event) {
event_queue_.ReleaseTopMessage(event);
}
-void PPAPIInstance::DidChangeView(const pp::View&) {
+void PPAPIInstance::DidChangeView(const pp::View& view) {
+ pp::Size new_size = view.GetRect().size();
+ printf("View changed: %dx%d\n", new_size.width(), new_size.height());
+
+ // Build or update the 3D context when the view changes.
+ if (use_main_thread_) {
+ // If using the main thread, update the context immediately
+ BuildContext(0, new_size);
+ } else {
+ // If using a seperate thread, then post the message so we can build the
+ // context on the correct thread.
+ render_loop_.PostWork(callback_factory_.NewCallback(
+ &PPAPIInstance::BuildContext, new_size));
+ }
}
void PPAPIInstance::DidChangeFocus(bool focus) {
has_focus_ = focus;
}
+
+bool PPAPIInstance::ToggleFullscreen() {
+ // Ignore switch if in transition
+ if (!is_context_bound_)
+ return false;
+
+ if (fullscreen_.IsFullscreen()) {
+ if (!fullscreen_.SetFullscreen(false)) {
+ printf("Could not leave fullscreen mode\n");
+ return false;
+ }
+ } else {
+ if (!fullscreen_.SetFullscreen(true)) {
+ printf("Could not enter fullscreen mode\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+// The default implementation calls the 'C' render function.
+void PPAPIInstance::Render(PP_Resource ctx, uint32_t width, uint32_t height) {
+}
+
+void PPAPIInstance::Flushed(int32_t result) {
+}
+
+void PPAPIInstance::BuildContext(int32_t result, const pp::Size& new_size) {
+ size_ = new_size;
+ printf("Resized: %dx%d.\n", size_.width(), size_.height());
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
index 47be29b032..1172cd8c45 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance.h
@@ -11,10 +11,14 @@
#include "ppapi/cpp/fullscreen.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/message_loop.h"
+#include "ppapi/cpp/mouse_lock.h"
+
+#include "ppapi/utility/completion_callback_factory.h"
#include "ppapi_main/ppapi_event.h"
#include "ppapi_main/ppapi_queue.h"
+
typedef std::map<std::string, std::string> PropertyMap_t;
class PPAPIInstance : public pp::Instance {
@@ -22,6 +26,10 @@ class PPAPIInstance : public pp::Instance {
PPAPIInstance(PP_Instance instance, const char *args[]);
virtual ~PPAPIInstance();
+ //
+ // Callback functions triggered by Pepepr
+ //
+
// Called by the browser when the NaCl module is loaded and all ready to go.
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
@@ -37,30 +45,61 @@ class PPAPIInstance : public pp::Instance {
// Called by the browser to handle incoming input events.
virtual bool HandleInputEvent(const pp::InputEvent& event);
- // Accessors for the PPAPIQueue object. Use Acquire to fetch the top
- // event if one is available, then release when done. Events must be
- // acquired and released one at a time.
+ // Called when the graphics flush completes
+ virtual void Flushed(int result);
+
+ // Called when we need to rebuild the Graphics device context. This usually
+ // happens as a result of DidChangeView.
+ virtual void BuildContext(int32_t result, const pp::Size& new_size);
+
+ // Called with the current graphics context, current size and width, when
+ // the application is ready to render, either due to a newly build
+ // Context, or a successful Flush of the previous frame.
+ virtual void Render(PP_Resource ctx, uint32_t width, uint32_t height);
+
+ //
+ // Thread entry points
+ //
+ virtual int MainThread(int argc, const char* argv[]);
+ virtual void* EventThread();
+
+ //
+ // Request API
+ //
+ bool ToggleFullscreen();
virtual PPAPIEvent* AcquireInputEvent();
virtual void ReleaseInputEvent(PPAPIEvent* event);
-
static PPAPIInstance* GetInstance();
protected:
- // Called to launch ppapi_main
- static void* StartMain(void *start_info);
+ // Called to run ppapi_main.
+ static void* MainThreadThunk(void *start_info);
+
+ // Called if message processing and rendering happens off the main thread.
+ static void* EventThreadThunk(void *this_ptr);
// Called by Init to processes default and embed tag arguments prior to
// launching the 'ppapi_main' thread.
virtual bool ProcessProperties();
- // Returns value based on KEY or default
+ // Returns value based on KEY or default.
const char* GetProperty(const char* key, const char* def = NULL);
- private:
+ protected:
pp::MessageLoop main_loop_;
+ pp::Fullscreen fullscreen_;
+ pp::MessageLoop render_loop_;
+ pp::CompletionCallbackFactory<PPAPIInstance> callback_factory_;
+
PropertyMap_t properties_;
PPAPIQueue event_queue_;
+
+ pp::Size size_;
bool has_focus_;
+ bool is_context_bound_;
+ bool was_fullscreen_;
+ bool mouse_locked_;
+ bool use_main_thread_;
};
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.cc
new file mode 100644
index 0000000000..f6e54be62e
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.cc
@@ -0,0 +1,87 @@
+// 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 <stdio.h>
+
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/message_loop.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+
+#include "ppapi/utility/completion_callback_factory.h"
+
+#include "ppapi_main/ppapi_instance2d.h"
+#include "ppapi_main/ppapi_main.h"
+
+
+void* PPAPI_CreateInstance2D(PP_Instance inst, const char *args[]) {
+ return static_cast<void*>(new PPAPIInstance2D(inst, args));
+}
+
+
+PPAPIInstance2D* PPAPIInstance2D::GetInstance2D() {
+ return static_cast<PPAPIInstance2D*>(PPAPI_GetInstanceObject());
+}
+
+
+void PPAPIInstance2D::Flushed(int result) {
+ if (result != 0) {
+ printf("Flush result=%d.\n", result);
+ }
+
+ if (is_context_bound_) {
+ Render(device_context_.pp_resource(), size_.width(), size_.height());
+
+ int result;
+ result = device_context_.Flush(callback_factory_.NewCallback(
+ &PPAPIInstance::Flushed));
+ if (result == PP_OK_COMPLETIONPENDING) return;
+ printf("Failed Flush with %d.\n", result);
+ }
+
+ // Failed to draw, so add a callback for the future. This could
+ // an application choice or the browser dealing with an event such as
+ // fullscreen toggle. We add a delay of 100ms (to prevent burnning CPU
+ // in cases where the context will not be available for a while.
+ pp::MessageLoop::GetCurrent().PostWork(callback_factory_.NewCallback(
+ &PPAPIInstance::Flushed), 100);
+}
+
+void PPAPIInstance2D::BuildContext(int32_t result, const pp::Size& new_size) {
+ printf("Building context.\n");
+
+ size_ = new_size;
+ device_context_ = pp::Graphics2D(this, size_ ,true);
+ printf("Got Context!\n");
+
+ is_context_bound_ = BindGraphics(device_context_);
+ printf("Context is bound=%d\n", is_context_bound_);
+
+ if (is_context_bound_) {
+ PPAPIBuildContext(size_.width(), size_.height());
+ device_context_.Flush(callback_factory_.NewCallback(
+ &PPAPIInstance::Flushed));
+ } else {
+ fprintf(stderr, "Failed to bind context for %dx%d.\n", size_.width(),
+ size_.height());
+ }
+}
+
+// The default implementation calls the 'C' render function.
+void PPAPIInstance2D::Render(PP_Resource ctx, uint32_t width,
+ uint32_t height) {
+ PPAPIRender(ctx, width, height);
+}
+
+PPAPIInstance2D::PPAPIInstance2D(PP_Instance instance, const char *args[])
+ : PPAPIInstance(instance, args) {
+}
+
+
+PPAPIInstance2D::~PPAPIInstance2D() {
+ if (is_context_bound_) {
+ is_context_bound_ = false;
+ // Cleanup code?
+ }
+}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.h
new file mode 100644
index 0000000000..ac600c2c27
--- /dev/null
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance2d.h
@@ -0,0 +1,36 @@
+// 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 PPAPI_MAIN_PPAPI_INSTANCE2D_H_
+#define PPAPI_MAIN_PPAPI_INSTANCE2D_H_
+
+#include "ppapi/c/pp_instance.h"
+
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/size.h"
+
+#include "ppapi_main/ppapi_instance.h"
+
+
+class PPAPIInstance2D : public PPAPIInstance {
+ public:
+ PPAPIInstance2D(PP_Instance instance, const char *args[]);
+ virtual ~PPAPIInstance2D();
+
+ // Called when we need to rebuild the context
+ virtual void BuildContext(int32_t result, const pp::Size& new_size);
+
+ // Called whenever a swap takes place
+ virtual void Flushed(int result);
+
+ virtual void Render(PP_Resource ctx, uint32_t width, uint32_t height);
+ static PPAPIInstance2D* GetInstance2D();
+
+ protected:
+ pp::Graphics2D device_context_;
+};
+
+
+#endif // PPAPI_MAIN_PPAPI_INSTANCE2D_H_
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc
index ef8092eadb..3ff74a69d2 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.cc
@@ -2,30 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <fcntl.h>
-#include <pthread.h>
#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <cstdlib>
-#include <cstring>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "nacl_io/nacl_io.h"
-
-#include "ppapi/cpp/fullscreen.h"
#include "ppapi/cpp/graphics_3d.h"
-#include "ppapi/cpp/input_event.h"
-#include "ppapi/cpp/message_loop.h"
-#include "ppapi/cpp/mouse_lock.h"
-#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
-#include "ppapi/cpp/var.h"
#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
#include "ppapi/lib/gl/include/GLES2/gl2.h"
@@ -37,9 +17,6 @@
#include "ppapi_main/ppapi_main.h"
-static const uint32_t kReturnKeyCode = 13;
-
-
void* PPAPI_CreateInstance3D(PP_Instance inst, const char *args[]) {
return static_cast<void*>(new PPAPIInstance3D(inst, args));
}
@@ -75,32 +52,27 @@ PPAPIInstance3D* PPAPIInstance3D::GetInstance3D() {
return static_cast<PPAPIInstance3D*>(PPAPI_GetInstanceObject());
}
-
-void *PPAPIInstance3D::RenderLoop(void *this_ptr) {
- PPAPIInstance3D *pInst = static_cast<PPAPIInstance3D*>(this_ptr);
- pInst->render_loop_.AttachToCurrentThread();
- pInst->render_loop_.Run();
- return NULL;
-}
-
-
-void PPAPIInstance3D::Swapped(int result) {
+void PPAPIInstance3D::Flushed(int result) {
if (result != 0) {
printf("Swapped result=%d.\n", result);
}
if (is_context_bound_) {
- PPAPIRender(size_.width(), size_.height());
+ Render(device_context_.pp_resource(), size_.width(), size_.height());
+
int result;
result = device_context_.SwapBuffers(callback_factory_.NewCallback(
- &PPAPIInstance3D::Swapped));
+ &PPAPIInstance::Flushed));
if (result == PP_OK_COMPLETIONPENDING) return;
printf("Failed swap with %d.\n", result);
}
- // Failed to draw, so add a callback for the future.
+ // Failed to draw, so add a callback for the future. This could
+ // an application choice or the browser dealing with an event such as
+ // fullscreen toggle. We add a delay of 100ms (to prevent burnning CPU
+ // in cases where the context will not be available for a while.
pp::MessageLoop::GetCurrent().PostWork(callback_factory_.NewCallback(
- &PPAPIInstance3D::Swapped), 100);
+ &PPAPIInstance::Flushed), 100);
}
void PPAPIInstance3D::BuildContext(int32_t result, const pp::Size& new_size) {
@@ -141,27 +113,26 @@ void PPAPIInstance3D::BuildContext(int32_t result, const pp::Size& new_size) {
is_context_bound_ = BindGraphics(device_context_);
printf("Context is bound=%d\n", is_context_bound_);
- // The the context regardless to make sure we have a valid one
+ // Set the context regardless to make sure we have a valid one
glSetCurrentContextPPAPI(device_context_.pp_resource());
if (is_context_bound_) {
PPAPIBuildContext(size_.width(), size_.height());
device_context_.SwapBuffers(callback_factory_.NewCallback(
- &PPAPIInstance3D::Swapped));
+ &PPAPIInstance::Flushed));
} else {
fprintf(stderr, "Failed to bind context for %dx%d.\n", size_.width(),
size_.height());
}
}
+// The default implementation calls the 'C' render function.
+void PPAPIInstance3D::Render(PP_Resource ctx, uint32_t width,
+ uint32_t height) {
+ PPAPIRender(ctx, width, height);
+}
+
PPAPIInstance3D::PPAPIInstance3D(PP_Instance instance, const char *args[])
- : PPAPIInstance(instance, args),
- mouse_locked_(false),
- callback_factory_(this),
- fullscreen_(this),
- is_context_bound_(false),
- was_fullscreen_(false),
- render_loop_(this),
- main_thread_3d_(true) {
+ : PPAPIInstance(instance, args) {
glInitializePPAPI(pp::Module::Get()->get_browser_interface());
}
@@ -172,61 +143,3 @@ PPAPIInstance3D::~PPAPIInstance3D() {
// Cleanup code?
}
}
-
-bool PPAPIInstance3D::Init(uint32_t arg,
- const char* argn[],
- const char* argv[]) {
- if (!PPAPIInstance::Init(arg, argn, argv)) {
- return false;
- }
-
- for (uint32_t a=0; a < arg; a++) {
- printf("%s=%s\n", argn[a], argv[a]);
- }
-
- const char *use_main = GetProperty("pm_main3d", "true");
- main_thread_3d_ = !strcasecmp(use_main, "true");
- printf("Using 3D on main thread = %s.\n", use_main);
- if (!main_thread_3d_) {
- pthread_t render_thread;
- int ret = pthread_create(&render_thread, NULL, RenderLoop,
- static_cast<void*>(this));
- return ret == 0;
- }
- return true;
-}
-
-void PPAPIInstance3D::DidChangeView(const pp::View& view) {
- pp::Size new_size = view.GetRect().size();
- printf("View changed: %dx%d\n", new_size.width(), new_size.height());
-
- // Build or update the 3D context when the view changes.
- if (main_thread_3d_) {
- // If using the main thread, update the context immediately
- BuildContext(0, new_size);
- } else {
- // If using a seperate thread, then post the message so we can build the
- // context on the correct thread.
- render_loop_.PostWork(callback_factory_.NewCallback(
- &PPAPIInstance3D::BuildContext, new_size));
- }
-}
-
-bool PPAPIInstance3D::ToggleFullscreen() {
- // Ignore switch if in transition
- if (!is_context_bound_)
- return false;
-
- if (fullscreen_.IsFullscreen()) {
- if (!fullscreen_.SetFullscreen(false)) {
- printf("Could not leave fullscreen mode\n");
- return false;
- }
- } else {
- if (!fullscreen_.SetFullscreen(true)) {
- printf("Could not enter fullscreen mode\n");
- return false;
- }
- }
- return true;
-}
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h
index 8c392809f2..410b952170 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_instance3d.h
@@ -8,13 +8,11 @@
#include <map>
#include "ppapi/c/pp_instance.h"
-#include "ppapi/cpp/fullscreen.h"
+#include "ppapi/c/pp_resource.h"
+
#include "ppapi/cpp/graphics_3d.h"
-#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/instance.h"
-#include "ppapi/cpp/message_loop.h"
-#include "ppapi/cpp/mouse_lock.h"
-#include "ppapi/utility/completion_callback_factory.h"
+#include "ppapi/cpp/size.h"
#include "ppapi_main/ppapi_instance.h"
@@ -24,35 +22,18 @@ class PPAPIInstance3D : public PPAPIInstance {
PPAPIInstance3D(PP_Instance instance, const char *args[]);
virtual ~PPAPIInstance3D();
- // Called during initialization
- virtual bool Init(uint32_t arg, const char* argn[], const char* argv[]);
-
- // Called whenever the in-browser window changes size.
- virtual void DidChangeView(const pp::View& view);
-
// Called when we need to rebuild the context
virtual void BuildContext(int32_t result, const pp::Size& new_size);
// Called whenever a swap takes place
- virtual void Swapped(int result);
-
- // Toggle in and out of Fullscreen mode
- virtual bool ToggleFullscreen();
+ virtual void Flushed(int result);
+ virtual void Render(PP_Resource ctx, uint32_t width, uint32_t height);
static PPAPIInstance3D* GetInstance3D();
protected:
- static void *RenderLoop(void *this_ptr);
-
- pp::CompletionCallbackFactory<PPAPIInstance3D> callback_factory_;
- pp::Fullscreen fullscreen_;
pp::Graphics3D device_context_;
- pp::Size size_;
- pp::MessageLoop render_loop_;
- bool is_context_bound_;
- bool was_fullscreen_;
- bool mouse_locked_;
- bool main_thread_3d_;
+
};
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
index af5217a341..2f2c4e31d8 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_main.h
@@ -33,24 +33,20 @@ void* PPAPI_CreateInstance3D(PP_Instance inst, const char *args[]);
PPAPIEvent* PPAPI_AcquireEvent();
void PPAPI_ReleaseEvent(PPAPIEvent* event);
-
-// Functions for 3D instances
+// Functions for Graphic Instances
int32_t *PPAPIGet3DAttribs(uint32_t width, uint32_t height);
void PPAPIBuildContext(uint32_t width, uint32_t height);
-void PPAPIRender(uint32_t width, uint32_t height);
+void PPAPIRender(PP_Resource ctx, uint32_t width, uint32_t height);
-EXTERN_C_END
-#define PPAPI_MAIN_DEFAULT_ARGS \
- { \
- NULL, NULL \
- }
+EXTERN_C_END
+#define PPAPI_MAIN_DEFAULT_ARGS NULL, NULL
-#define PPAPI_MAIN_USE(factory, args) \
-void* UserCreateInstance(PP_Instance inst) { \
- static const char *params[] = args; \
- return factory(inst, params); \
+#define PPAPI_MAIN_USE(factory, ...) \
+void* UserCreateInstance(PP_Instance inst) { \
+ static const char *params[] = { __VA_ARGS__ }; \
+ return factory(inst, params); \
}
#define PPAPI_MAIN_WITH_DEFAULT_ARGS \
@@ -59,8 +55,8 @@ void* UserCreateInstance(PP_Instance inst) { \
#define PPAPI_MAIN_3D_WITH_DEFAULT_ARGS \
PPAPI_MAIN_USE(PPAPI_CreateInstance3D, PPAPI_MAIN_DEFAULT_ARGS)
-#define PPAPI_MAIN_WITH_ARGS(args) \
- PPAPI_MAIN_USE(PPAPI_CreateInstance, args)
+#define PPAPI_MAIN_WITH_ARGS(...) \
+ PPAPI_MAIN_USE(PPAPI_CreateInstance, __VA_ARGS__)
#endif // PPAPI_MAIN_PPAPI_MAIN_H_
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc
index ff5ed382f9..9ecce6680e 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.cc
@@ -35,7 +35,7 @@ bool PPAPIQueue::SetSize(uint32_t queue_size) {
}
bool PPAPIQueue::AddNewMessage(void* msg) {
- // Writting a NULL message is illegal
+ // Writing a NULL message is illegal
assert(array_ != NULL);
assert(msg != NULL);
diff --git a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h
index b40c3ec000..f022dcf0b3 100644
--- a/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h
+++ b/native_client_sdk/src/libraries/ppapi_main/ppapi_queue.h
@@ -61,7 +61,7 @@ class PPAPIQueue {
// available NULL will be returned. Once the consumer is done with the
// message, ReleaseTopMessage is called to signal that the payload is no
// longer visible to the consumer and can be recycled or destroyed.
- // Since messages are freed in order, it is recquired that messages are
+ // Since messages are freed in order, it is required that messages are
// consumed in order. For this reason, it is illegal to call Acquire again
// after a non-NULL message pointer is returned, until Release is called on
// the old message. This means the consumer can only look at one message
@@ -81,4 +81,4 @@ class PPAPIQueue {
};
-#endif // PPAPI_MAIN_PPAPI_QUEUE_H \ No newline at end of file
+#endif // PPAPI_MAIN_PPAPI_QUEUE_H
diff --git a/native_client_sdk/src/libraries/utils/macros.h b/native_client_sdk/src/libraries/utils/macros.h
index 8731e255dd..718d83fce9 100644
--- a/native_client_sdk/src/libraries/utils/macros.h
+++ b/native_client_sdk/src/libraries/utils/macros.h
@@ -17,7 +17,7 @@
#define MEMBER_SIZE(struct_name, member) sizeof(((struct_name*)0)->member)
/**
- * Macros to prevent name mangling of defnitions, allowing them to be
+ * Macros to prevent name mangling of definitions, allowing them to be
* referenced from C.
*/
#ifdef __cplusplus
diff --git a/native_client_sdk/src/libraries/zlib/library.dsc b/native_client_sdk/src/libraries/zlib/library.dsc
index 2ce423a32d..035479941b 100644
--- a/native_client_sdk/src/libraries/zlib/library.dsc
+++ b/native_client_sdk/src/libraries/zlib/library.dsc
@@ -1,4 +1,5 @@
{
+ 'DISABLE': True,
'TOOLS': ['newlib', 'glibc', 'linux', 'win'],
'SEARCH': [
'../../../../third_party/zlib',
diff --git a/native_client_sdk/src/test_all.py b/native_client_sdk/src/test_all.py
index 4c37c78b42..0a1374f3df 100755
--- a/native_client_sdk/src/test_all.py
+++ b/native_client_sdk/src/test_all.py
@@ -21,7 +21,7 @@ TEST_MODULES = [
'sdktools_test',
'sdktools_commands_test',
'update_nacl_manifest_test',
- 'generate_make_test'
+ 'parse_dsc_test'
]
def main():
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
index 3e3388cc28..040abfe233 100644
--- a/native_client_sdk/src/tools/common.mk
+++ b/native_client_sdk/src/tools/common.mk
@@ -6,7 +6,7 @@
# GNU Make based build file. For details on GNU Make see:
# http://www.gnu.org/software/make/manual/make.html
#
-#
+
#
# Toolchain
@@ -26,6 +26,13 @@ TOP_MAKE:=$(word 1,$(MAKEFILE_LIST))
#
+# Figure out which OS we are running on.
+#
+GETOS=python $(NACL_SDK_ROOT)/tools/getos.py
+OSNAME:=$(shell $(GETOS))
+
+
+#
# Verify we selected a valid toolchain for this example
#
ifeq (,$(findstring $(TOOLCHAIN),$(VALID_TOOLCHAINS)))
@@ -44,6 +51,7 @@ endif
CONFIG?=Debug
+#
# Note for Windows:
# The GCC and LLVM toolchains (include the version of Make.exe that comes
# with the SDK) expect and are capable of dealing with the '/' seperator.
@@ -115,8 +123,6 @@ endif
#
# Compute path to requested NaCl Toolchain
#
-GETOS=python $(NACL_SDK_ROOT)/tools/getos.py
-OSNAME:=$(shell $(GETOS))
TC_PATH:=$(abspath $(NACL_SDK_ROOT)/toolchain)
@@ -172,6 +178,7 @@ all_versions: $(TOOLCHAIN_LIST)
OUTBASE?=.
OUTDIR:=$(OUTBASE)/$(TOOLCHAIN)/$(CONFIG)
STAMPDIR?=$(OUTDIR)
+LIBDIR?=$(NACL_SDK_ROOT)/lib
#
@@ -239,7 +246,7 @@ endif
ifeq ($(CONFIG),Release)
POSIX_FLAGS?=-g -O2 -pthread -MMD
else
-POSIX_FLAGS?=-g -O0 -pthread -MMD
+POSIX_FLAGS?=-g -O0 -pthread -MMD -DNACL_SDK_DEBUG
endif
NACL_CFLAGS?=-Wno-long-long -Werror
diff --git a/native_client_sdk/src/tools/decode_dump.py b/native_client_sdk/src/tools/decode_dump.py
index e2717ff209..74d07a03fb 100755
--- a/native_client_sdk/src/tools/decode_dump.py
+++ b/native_client_sdk/src/tools/decode_dump.py
@@ -1,5 +1,5 @@
#!/usr/bin/python
-# Copyright (c) 2012 The Native Client Authors. All rights reserved.
+# 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.
@@ -25,7 +25,7 @@ class CoreDecoder(object):
Args:
main_nexe: nexe to resolve NaClMain references from.
- nmf_filename: nmf to resovle references from.
+ nmf_filename: nmf to resolve references from.
addr2line: path to appropriate addr2line.
library_paths: list of paths to search for libraries.
platform: platform string to use in nmf files.
@@ -141,7 +141,7 @@ class CoreDecoder(object):
Args:
core_path: source file containing a dump.
Returns:
- An embelished core dump dict (decoded code addresses).
+ An embellished core dump dict (decoded code addresses).
"""
core = json.load(open(core_path))
for frame in core['frames']:
diff --git a/native_client_sdk/src/tools/getos.py b/native_client_sdk/src/tools/getos.py
index 6e2813c6f2..bd312b4b90 100755
--- a/native_client_sdk/src/tools/getos.py
+++ b/native_client_sdk/src/tools/getos.py
@@ -118,13 +118,13 @@ def GetChromePath():
def GetNaClArch(platform):
if platform == 'win':
- # On windows the nacl arch always maches to system arch
+ # On windows the nacl arch always matches to system arch
return GetSystemArch(platform)
elif platform == 'mac':
# On Mac the nacl arch is currently always 32-bit.
return 'x86_32'
- # On linux the nacl arch matches to chrome arch, so we inspect the chome
+ # On linux the nacl arch matches to chrome arch, so we inspect the chrome
# binary using objdump
chrome_path = GetChromePath()
diff --git a/native_client_sdk/src/tools/host_gcc.mk b/native_client_sdk/src/tools/host_gcc.mk
index f7767390b6..702c633dae 100644
--- a/native_client_sdk/src/tools/host_gcc.mk
+++ b/native_client_sdk/src/tools/host_gcc.mk
@@ -19,6 +19,7 @@ HOST_CC?=gcc
HOST_CXX?=g++
HOST_LINK?=g++
HOST_LIB?=ar r
+HOST_STRIP?=strip
ifeq (,$(findstring gcc,$(shell $(WHICH) gcc)))
$(warning To skip the host build use:)
@@ -83,11 +84,11 @@ endef
#
#
define LIB_RULE
-$(STAMPDIR)/$(1).stamp: $(NACL_SDK_ROOT)/lib/$(OSNAME)_host/$(CONFIG)/lib$(1).a
+$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(OSNAME)_host/$(CONFIG)/lib$(1).a
@echo "TOUCHED $$@" > $(STAMPDIR)/$(1).stamp
-all: $(NACL_SDK_ROOT)/lib/$(OSNAME)_host/$(CONFIG)/lib$(1).a
-$(NACL_SDK_ROOT)/lib/$(OSNAME)_host/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src)))
+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 $$@)
$(call LOG,LIB,$$@,$(HOST_LIB) $$@ $$^)
endef
@@ -125,3 +126,18 @@ $(call LINKER_RULE,$(OUTDIR)/$(1)$(HOST_EXT),$(foreach src,$(2),$(call SRC_TO_OB
endef
all : $(LIB_LIST) $(DEPS_LIST)
+
+
+#
+# Strip Macro
+# The host build makes shared libraries, so the best we can do is strip-debug.
+# We cannot strip the symbol names.
+#
+# $1 = Target Name
+# $2 = Input Name
+#
+define STRIP_RULE
+all: $(OUTDIR)/$(1)$(HOST_EXT)
+$(OUTDIR)/$(1)$(HOST_EXT): $(OUTDIR)/$(2)$(HOST_EXT)
+ $(call LOG,STRIP,$$@,$(HOST_STRIP) --strip-debug -o $$@ $$^)
+endef
diff --git a/native_client_sdk/src/tools/host_vc.mk b/native_client_sdk/src/tools/host_vc.mk
index fb62167c6a..318b46eaaa 100644
--- a/native_client_sdk/src/tools/host_vc.mk
+++ b/native_client_sdk/src/tools/host_vc.mk
@@ -28,7 +28,7 @@ endif
ifeq ('Debug','$(CONFIG)')
-WIN_OPT_FLAGS?=/Od /MTd /Z7
+WIN_OPT_FLAGS?=/Od /MTd /Z7 -D NACL_SDK_DEBUG
else
WIN_OPT_FLAGS?=/O2 /MT /Z7
endif
@@ -74,11 +74,11 @@ endef
#
#
define LIB_RULE
-$(STAMPDIR)/$(1).stamp : $(NACL_SDK_ROOT)/lib/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib
+$(STAMPDIR)/$(1).stamp : $(LIBDIR)/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib
@echo "TOUCHED $$@" > $(STAMPDIR)/$(1).stamp
-all:$(NACL_SDK_ROOT)/lib/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib
-$(NACL_SDK_ROOT)/lib/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib : $(foreach src,$(2),$(OUTDIR)/$(basename $(src)).o)
+all:$(LIBDIR)/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib
+$(LIBDIR)/$(OSNAME)_x86_32_host/$(CONFIG)/$(1).lib : $(foreach src,$(2),$(OUTDIR)/$(basename $(src)).o)
$(MKDIR) -p $$(dir $$@)
$(call LOG,LIB,$$@,$(HOST_LIB) /OUT:$$@ $$^ $(WIN_LDFLAGS))
endef
@@ -115,4 +115,19 @@ define LINK_RULE
$(call LINKER_RULE,$(OUTDIR)/$(1)$(HOST_EXT),$(foreach src,$(2),$(OUTDIR)/$(basename $(src)).o),$(3),$(4),$(LIB_PATHS),$(6))
endef
+
+#
+# Strip Macro
+# This is a nop (copy) since visual studio already keeps debug info
+# separate from the binaries
+#
+# $1 = Target Name
+# $2 = Input Name
+#
+define STRIP_RULE
+all: $(OUTDIR)/$(1)$(HOST_EXT)
+$(OUTDIR)/$(1)$(HOST_EXT): $(OUTDIR)/$(2)$(HOST_EXT)
+ $(call LOG,COPY,$$@,$(CP) $$^ $$@)
+endef
+
all : $(LIB_LIST) $(DEPS_LIST)
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index 51ed4b6b31..d73a9f793d 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -28,18 +28,33 @@ X86_32_CC?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-gcc
X86_32_CXX?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-g++
X86_32_LINK?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-g++
X86_32_LIB?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-ar
+X86_32_STRIP?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-strip
+X86_32_NM?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/i686-nacl-nm
X86_64_CC?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-gcc
X86_64_CXX?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-g++
X86_64_LINK?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-g++
X86_64_LIB?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-ar
+X86_64_STRIP?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-strip
+X86_64_NM?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/x86_64-nacl-nm
ARM_CC?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-gcc
ARM_CXX?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-g++
ARM_LINK?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-g++
ARM_LIB?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-ar
+ARM_STRIP?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-strip
+ARM_NM?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-nm
+# Architecture-specific flags
+X86_32_CFLAGS?=-DNACL_ARCH=x86_32
+X86_64_CFLAGS?=-DNACL_ARCH=x86_64
+ARM_CFLAGS?=-DNACL_ARCH=arm
+
+X86_32_CXXFLAGS?=-DNACL_ARCH=x86_32
+X86_64_CXXFLAGS?=-DNACL_ARCH=x86_64
+ARM_CXXFLAGS?=-DNACL_ARCH=arm
+
#
# Compile Macro
#
@@ -49,29 +64,29 @@ ARM_LIB?=$(TC_PATH)/$(OSNAME)_arm_$(TOOLCHAIN)/bin/arm-nacl-ar
define C_COMPILER_RULE
-include $(call SRC_TO_DEP,$(1),_x86_32)
$(call SRC_TO_OBJ,$(1),_x86_32): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CC,$$@,$(X86_32_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS))
+ $(call LOG,CC,$$@,$(X86_32_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS) $(X86_32_CFLAGS))
-include $(call SRC_TO_DEP,$(1),_x86_64)
$(call SRC_TO_OBJ,$(1),_x86_64): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CC,$$@,$(X86_64_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS))
+ $(call LOG,CC,$$@,$(X86_64_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS) $(X86_64_CFLAGS))
-include $(call SRC_TO_DEP,$(1),_arm)
$(call SRC_TO_OBJ,$(1),_arm): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CC,$$@,$(ARM_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS))
+ $(call LOG,CC,$$@,$(ARM_CC) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CFLAGS) $(ARM_CFLAGS))
endef
define CXX_COMPILER_RULE
-include $(call SRC_TO_DEP,$(1),_x86_32)
$(call SRC_TO_OBJ,$(1),_x86_32): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CXX,$$@,$(X86_32_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS))
+ $(call LOG,CXX,$$@,$(X86_32_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS) $(X86_32_CXXFLAGS))
-include $(call SRC_TO_DEP,$(1),_x86_64)
$(call SRC_TO_OBJ,$(1),_x86_64): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CXX,$$@,$(X86_64_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS))
+ $(call LOG,CXX,$$@,$(X86_64_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS) $(X86_64_CXXFLAGS))
-include $(call SRC_TO_DEP,$(1),_arm)
$(call SRC_TO_OBJ,$(1),_arm): $(1) $(TOP_MAKE) | $(dir $(call SRC_TO_OBJ,$(1)))dir.stamp
- $(call LOG,CXX,_$$@,$(ARM_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS))
+ $(call LOG,CXX,$$@,$(ARM_CXX) -o $$@ -c $$< $(POSIX_FLAGS) $(2) $(NACL_CXXFLAGS) $(ARM_CXXFLAGS))
endef
@@ -129,29 +144,29 @@ endef
# $4 = VC Link Flags (unused)
#
define LIB_RULE
-$(STAMPDIR)/$(1).stamp : $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
-$(STAMPDIR)/$(1).stamp : $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
+$(STAMPDIR)/$(1).stamp : $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
+$(STAMPDIR)/$(1).stamp : $(LIBDIR)/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
ifneq ('glibc','$(TOOLCHAIN)')
-$(STAMPDIR)/$(1).stamp : $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
+$(STAMPDIR)/$(1).stamp : $(LIBDIR)/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
endif
$(STAMPDIR)/$(1).stamp :
@echo "TOUCHED $$@" > $(STAMPDIR)/$(1).stamp
-all: $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
-$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_32))
+all: $(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a
+$(LIBDIR)/$(TOOLCHAIN)_x86_32/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_32))
$(MKDIR) -p $$(dir $$@)
$(call LOG,LIB,$$@,$(X86_32_LIB) -r $$@ $$^)
-all: $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
-$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_64))
+all: $(LIBDIR)/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a
+$(LIBDIR)/$(TOOLCHAIN)_x86_64/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_x86_64))
$(MKDIR) -p $$(dir $$@)
$(call LOG,LIB,$$@,$(X86_64_LIB) -r $$@ $$^)
ifneq ('glibc','$(TOOLCHAIN)')
-all: $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
+all: $(LIBDIR)/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a
endif
-$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm))
+$(LIBDIR)/$(TOOLCHAIN)_arm/$(CONFIG)/lib$(1).a : $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm))
$(MKDIR) -p $$(dir $$@)
$(call LOG,LIB,$$@,$(ARM_LIB) -r $$@ $$^)
endef
@@ -195,6 +210,66 @@ endef
#
+# Strip Macro for each arch (e.g., each arch supported by LINKER_RULE).
+#
+# $1 = Target Name
+# $2 = Source Name
+#
+define STRIP_ALL_RULE
+$(OUTDIR)/$(1)_x86_32.nexe : $(OUTDIR)/$(2)_x86_32.nexe
+ $(call LOG,STRIP,$$@,$(X86_32_STRIP) -o $$@ $$^)
+
+$(OUTDIR)/$(1)_x86_64.nexe : $(OUTDIR)/$(2)_x86_64.nexe
+ $(call LOG,STRIP,$$@,$(X86_64_STRIP) -o $$@ $$^)
+
+$(OUTDIR)/$(1)_arm.nexe : $(OUTDIR)/$(2)_arm.nexe
+ $(call LOG,STRIP,$$@,$(ARM_STRIP) -o $$@ $$^)
+endef
+
+
+#
+# Top-level Strip Macro
+#
+# $1 = Target Basename
+# $2 = Source Basename
+#
+define STRIP_RULE
+$(call STRIP_ALL_RULE,$(1),$(2))
+endef
+
+
+#
+# Strip Macro for each arch (e.g., each arch supported by MAP_RULE).
+#
+# $1 = Target Name
+# $2 = Source Name
+#
+define MAP_ALL_RULE
+$(OUTDIR)/$(1)_x86_32.map : $(OUTDIR)/$(2)_x86_32.nexe
+ $(call LOG,MAP,$$@,$(X86_32_NM) -l $$^ > $$@)
+
+$(OUTDIR)/$(1)_x86_64.map : $(OUTDIR)/$(2)_x86_64.nexe
+ $(call LOG,MAP,$$@,$(X86_64_NM) -l $$^ > $$@)
+
+$(OUTDIR)/$(1)_arm.map : $(OUTDIR)/$(2)_arm.nexe
+ $(call LOG,MAP,$$@,$(ARM_NM) -l $$^ > $$@ )
+
+all: $(OUTDIR)/$(1)_x86_32.map $(OUTDIR)/$(1)_x86_64.map $(OUTDIR)/$(1)_arm.map
+endef
+
+
+#
+# Top-level MAP Generation Macro
+#
+# $1 = Target Basename
+# $2 = Source Basename
+#
+define MAP_RULE
+$(call MAP_ALL_RULE,$(1),$(2))
+endef
+
+
+#
# Determine which architectures to build for. The user can set NACL_ARCH or
# ARCHES in the environment to control this.
#
@@ -212,6 +287,7 @@ else
ARCHES?=${VALID_ARCHES}
endif
+
#
# Generate NMF_TARGETS
#
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index 429b6e3928..bc16169b38 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -16,7 +16,7 @@ PNACL_CC?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/newlib/bin/pnacl-clang -c
PNACL_CXX?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/newlib/bin/pnacl-clang++ -c
PNACL_LINK?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/newlib/bin/pnacl-clang++
PNACL_LIB?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/newlib/bin/pnacl-ar r
-
+PNACL_STRIP?=$(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/newlib/bin/pnacl-finalize
#
# Compile Macro
@@ -71,11 +71,11 @@ endef
# $3 = POSIX Link Flags
# $4 = VC Link Flags (unused)
define LIB_RULE
-$(STAMPDIR)/$(1).stamp: $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
+$(STAMPDIR)/$(1).stamp: $(LIBDIR)/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
@echo "TOUCHED $$@" > $(STAMPDIR)/$(1).stamp
-all: $(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a
-$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)/$(CONFIG)/lib$(1).a: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_pnacl))
+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 $$@)
$(call LOG,LIB,$$@,$(PNACL_LIB) $$@ $$^ $(3))
endef
@@ -113,6 +113,18 @@ $(call LINKER_RULE,$(OUTDIR)/$(1).pexe,$(foreach src,$(2),$(call SRC_TO_OBJ,$(sr
endef
+#
+# Strip Macro
+#
+# $1 = Target Name
+# $2 = Input Name
+#
+define STRIP_RULE
+all: $(OUTDIR)/$(1).pexe
+$(OUTDIR)/$(1).pexe: $(OUTDIR)/$(2).pexe
+ $(call LOG,STRIP,$$@,$(PNACL_STRIP) -o $$@ $$^)
+endef
+
#
# NMF Manifiest generation
diff --git a/native_client_sdk/src/tools/oshelpers.py b/native_client_sdk/src/tools/oshelpers.py
index b144eef1b2..2ae8c4a2f3 100755
--- a/native_client_sdk/src/tools/oshelpers.py
+++ b/native_client_sdk/src/tools/oshelpers.py
@@ -108,7 +108,7 @@ def Copy(args):
Copies multiple sources to a single destination using the normal cp
semantics. In addition, it support inclusion and exclusion filters which
allows the copy to skip certain types of files."""
- parser = optparse.OptionParser(usage='usage: cp [Options] souces... dest')
+ parser = optparse.OptionParser(usage='usage: cp [Options] sources... dest')
parser.add_option(
'-R', '-r', '--recursive', dest='recursive', action='store_true',
default=False,
@@ -172,7 +172,7 @@ def Mkdir(args):
if os.path.isdir(dst):
if options.parents:
continue
- raise OSError('mkdir: Already exsists: ' + dst)
+ raise OSError('mkdir: Already exists: ' + dst)
else:
raise OSError('mkdir: Failed to create: ' + dst)
return 0
@@ -209,7 +209,7 @@ def MovePath(options, src, dst):
def Move(args):
- parser = optparse.OptionParser(usage='usage: mv [Options] souces... dest')
+ parser = optparse.OptionParser(usage='usage: mv [Options] sources... dest')
parser.add_option(
'-v', '--verbose', dest='verbose', action='store_true',
default=False,
diff --git a/native_client_sdk/src/tools/tests/create_nmf_test.py b/native_client_sdk/src/tools/tests/create_nmf_test.py
index aee66e039f..e8fec58e6b 100755
--- a/native_client_sdk/src/tools/tests/create_nmf_test.py
+++ b/native_client_sdk/src/tools/tests/create_nmf_test.py
@@ -138,7 +138,7 @@ class TestNmfUtils(unittest.TestCase):
self.assertEqual(archfile.arch, 'x86-32')
def StripDependencies(self, deps):
- """Strip the dirnames and version suffixs from
+ """Strip the dirnames and version suffixes from
a list of nexe dependencies.
e.g:
@@ -157,7 +157,7 @@ class TestNmfUtils(unittest.TestCase):
needed = nmf.GetNeeded()
names = needed.keys()
- # this nexe has 5 dependancies
+ # this nexe has 5 dependencies
expected = set(self.dyn_deps)
expected.add(os.path.basename(self.dyn_nexe))
@@ -168,7 +168,7 @@ class TestNmfUtils(unittest.TestCase):
self.Mktemp()
nmf = self.CreateNmfUtils()
- # Stage dependancies
+ # Stage dependencies
nmf.StageDependencies(self.tempdir)
# Verify directory contents
diff --git a/native_client_sdk/src/tools/tests/getos_test.py b/native_client_sdk/src/tools/tests/getos_test.py
index 9c46071252..3a6ad60c1e 100755
--- a/native_client_sdk/src/tools/tests/getos_test.py
+++ b/native_client_sdk/src/tools/tests/getos_test.py
@@ -48,7 +48,7 @@ class TestGetos(TestCaseExtended):
self.patch2.stop()
def testGetSDKPath(self):
- """honors enironment variable."""
+ """honors environment variable."""
with mock.patch.dict('os.environ', {'NACL_SDK_ROOT': 'dummy'}):
self.assertEqual(getos.GetSDKPath(), 'dummy')
@@ -63,7 +63,7 @@ class TestGetos(TestCaseExtended):
self.assertIn(platform, ('mac', 'linux', 'win'))
def testGetSystemArch(self):
- """returns a valid architecuture."""
+ """returns a valid architecture."""
arch = getos.GetSystemArch(getos.GetPlatform())
self.assertIn(arch, ('x86_64', 'x86_32', 'arm'))
@@ -79,7 +79,7 @@ class TestGetos(TestCaseExtended):
self.assertRaises(getos.Error, getos.GetChromePath)
def testGetChromePathCheckExists(self):
- """checks that existence of explictly CHROME_PATH is checked."""
+ """checks that existence of explicitly CHROME_PATH is checked."""
mock_location = '/bin/ls'
if getos.GetPlatform() == 'win':
mock_location = 'c:\\nowhere'
@@ -117,7 +117,7 @@ class TestGetos(TestCaseExtended):
mock_exists.assert_called_with(loader)
def testGetNaClArch(self):
- """returns a valid architecuture."""
+ """returns a valid architecture."""
platform = getos.GetPlatform()
# Since the unix implementation of GetNaClArch will run objdump on the
# chrome binary, and we want to be able to run this test without chrome
diff --git a/native_client_sdk/src/web/manifest.html b/native_client_sdk/src/web/manifest.html
index 553d856ff4..49574b4006 100644
--- a/native_client_sdk/src/web/manifest.html
+++ b/native_client_sdk/src/web/manifest.html
@@ -31,6 +31,7 @@
border-style: solid;
border-color: rgb(100, 100, 100);
border-width: 0px 0px 2px 0px;
+ text-align: center;
}
tbody tr:nth-child(odd) {
@@ -85,7 +86,9 @@
// Create the column headers.
var tr = document.createElement('tr');
- var columns = ['name', 'version', 'revision', 'win', 'mac', 'linux'];
+ var columns = [
+ 'name', 'version', 'revision', 'win', 'mac', 'linux', 'all'
+ ];
for (var i = 0; i < columns.length; ++i) {
var td = document.createElement('td');
var text = document.createTextNode(columns[i]);
@@ -94,7 +97,7 @@
}
columnsElm.appendChild(tr);
- var platforms = ['win', 'mac', 'linux'];
+ var platforms = ['win', 'mac', 'linux', 'all'];
for (var i = 0; i < data.length; ++i) {
var tr = document.createElement('tr');
@@ -105,9 +108,13 @@
var archives = data[i].archives;
for (var k = 0; k < archives.length; ++k) {
if (columns[j] == archives[k].host_os) {
+ var url = archives[k].url;
+ var lastSlash = url.lastIndexOf('/');
+ var nextDot = url.indexOf('.', lastSlash);
+ name = url.substr(lastSlash + 1, nextDot - lastSlash - 1);
node = document.createElement('a');
- node.setAttribute('href', archives[k].url);
- node.appendChild(document.createTextNode(columns[j]));
+ node.setAttribute('href', url);
+ node.appendChild(document.createTextNode(name));
td.appendChild(node);
}
}