diff options
author | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-12 00:20:15 +0000 |
---|---|---|
committer | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-12 00:20:15 +0000 |
commit | cd620f78098c40d38c56a72e2c859565c283c412 (patch) | |
tree | 860381c0d8af35eeb3de1c92503c76e10769b7e8 /native_client_sdk | |
parent | 4e1b91e07236c42f35c24029064aac623722d536 (diff) | |
download | chromium_src-cd620f78098c40d38c56a72e2c859565c283c412.zip chromium_src-cd620f78098c40d38c56a72e2c859565c283c412.tar.gz chromium_src-cd620f78098c40d38c56a72e2c859565c283c412.tar.bz2 |
[NaCl SDK] Add tool for creating html scaffolding.
This tool can create and basic html page for a nexe
as well as calling create_nmf to create the nmf.
It can be given a .nexe or a .nmf file.
BUG=243407
R=binji@chromium.org
Review URL: https://codereview.chromium.org/16599018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205682 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r-- | native_client_sdk/src/build_tools/sdk_files.list | 1 | ||||
-rwxr-xr-x | native_client_sdk/src/test_all.py | 1 | ||||
-rwxr-xr-x | native_client_sdk/src/tools/create_html.py | 177 | ||||
-rwxr-xr-x | native_client_sdk/src/tools/create_nmf.py | 6 | ||||
-rwxr-xr-x | native_client_sdk/src/tools/tests/create_html_test.py | 56 |
5 files changed, 239 insertions, 2 deletions
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list index 67eafd0..a715914 100644 --- a/native_client_sdk/src/build_tools/sdk_files.list +++ b/native_client_sdk/src/build_tools/sdk_files.list @@ -989,6 +989,7 @@ toolchain/${PLATFORM}_x86_pnacl/newlib/sdk/include/semaphore.h toolchain/${PLATFORM}_x86_pnacl/* tools/common.mk tools/compiler-wrapper.py +tools/create_html.py tools/create_nmf.py tools/decode_dump.py [linux,mac]tools/dump_syms diff --git a/native_client_sdk/src/test_all.py b/native_client_sdk/src/test_all.py index 3fde5db..4091948 100755 --- a/native_client_sdk/src/test_all.py +++ b/native_client_sdk/src/test_all.py @@ -14,6 +14,7 @@ sys.path.append(os.path.join(SCRIPT_DIR, 'build_tools', 'tests')) TEST_MODULES = [ 'getos_test', + 'create_html_test', 'create_nmf_test', 'easy_template_test', 'getos_test', diff --git a/native_client_sdk/src/tools/create_html.py b/native_client_sdk/src/tools/create_html.py new file mode 100755 index 0000000..b981aac --- /dev/null +++ b/native_client_sdk/src/tools/create_html.py @@ -0,0 +1,177 @@ +#!/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. + +"""Script for creating HTML needed to run a NaCl module. + +This script is designed to make the process of creating running +Native Client executables in the browers simple by creating +boilderplate a .html (and optionally a .nmf) file for a given +Native Client executable (.nexe). + +If the script if given a .nexe file it will produce both html +the nmf files. If it is given an nmf it will only create +the html file. +""" + +import optparse +import os +import sys +import subprocess + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +HTML_TEMPLATE = '''\ +<!DOCTYPE html> +<!-- +Sample html container for embedded NaCl module. This file was auto-generated +by the create_html tool which is part of the NaCl SDK. + +The embed tag is setup with ps_stdout and ps_stderr attributes which, for +applications linked with ppapi_simple, will cause stdout and stderr to be sent +to javascript via postMessage. Also, the postMessage listener assumes that +all messages sent via postMessage are strings to be displayed in the output +textarea. +--> +<html> +<head> + <meta http-equiv="Pragma" content="no-cache"> + <meta http-equiv="Expires" content="-1"> + <title>%(title)s</title> + +</head> +<body> + <h2>Native Client Module: %(module_name)s</h2> + <p>Status: <code id="status">Loading</code></p> + + <div id="listener"> + <embed id="nacl_module" name="%(module_name)s" src="%(nmf)s" + type="application/x-nacl" ps_stdout="/dev/tty" ps_stderr="/dev/tty" + width=640 height=480 /> + </div> + + <p>Standard output/error:</p> + <textarea id="stdout" rows="25" cols="80"> +</textarea> + + <script> +listenerDiv = document.getElementById("listener") +stdout = document.getElementById("stdout") +nacl_module = document.getElementById("nacl_module") + +function updateStatus(message) { + document.getElementById("status").innerHTML = message +} + +function addToStdout(message) { + stdout.value += message; + stdout.scrollTop = stdout.scrollHeight; +} + +function handleMessage(message) { + addToStdout(message.data) +} + +function handleCrash(event) { + updateStatus("Crashed/exited with status: " + nacl_module.exitStatus) +} + +function handleLoad(event) { + updateStatus("Loaded") +} + +listenerDiv.addEventListener("load", handleLoad, true); +listenerDiv.addEventListener("message", handleMessage, true); +listenerDiv.addEventListener("crash", handleCrash, true); + </script> +</body> +</html> +''' + + +class Error(Exception): + pass + + +def Log(msg): + if Log.enabled: + sys.stderr.write(str(msg) + '\n') +Log.enabled = False + + +def CreateHTML(filename, options): + if not os.path.exists(filename): + raise Error('file not found: %s' % filename) + + if not os.path.isfile(filename): + raise Error('specified input is not a file: %s' % filename) + + basename, ext = os.path.splitext(filename) + if ext not in ('.nexe', '.pexe', '.nmf'): + raise Error('input file must be .nexe, .pexe or .nmf: %s' % filename) + + if ext in ('.nexe', '.pexe'): + nmf = basename + '.nmf' + Log('creating nmf: %s' % nmf) + create_nmf = os.path.join(SCRIPT_DIR, 'create_nmf.py') + staging = os.path.dirname(nmf) + if not staging: + staging = '.' + cmd = [create_nmf, '-s', staging, '-o', nmf, filename] + if options.verbose: + cmd.append('-v') + Log(cmd) + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + raise Error('create_nmf failed') + else: + nmf = filename + + htmlfile = options.output + if not htmlfile: + htmlfile = basename + '.html' + + Log('creating html: %s' % htmlfile) + with open(htmlfile, 'w') as outfile: + args = {} + args['title'] = basename + args['module_name'] = basename + args['nmf'] = nmf + outfile.write(HTML_TEMPLATE % args) + + +def main(argv): + usage = 'Usage: %prog [options] <.nexe/.pexe or .nmf>' + parser = optparse.OptionParser(usage) + parser.add_option('-v', '--verbose', action='store_true', + help='Verbose output') + parser.add_option('-o', '--output', dest='output', + help='Name of html file to write (default is ' + 'input name with .html extension)', + metavar='FILE') + + options, args = parser.parse_args(argv) + if len(args) > 1: + parser.error('more than one input file specified') + + if not args: + parser.error('no input file specified') + + if options.verbose: + Log.enabled = True + + CreateHTML(args[0], options) + return 0 + + +if __name__ == '__main__': + try: + rtn = main(sys.argv[1:]) + except Error, e: + sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) + rtn = 1 + except KeyboardInterrupt: + sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) + rtn = 1 + sys.exit(rtn) diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py index a9aad54..f6ee703 100755 --- a/native_client_sdk/src/tools/create_nmf.py +++ b/native_client_sdk/src/tools/create_nmf.py @@ -110,7 +110,10 @@ def ParseElfHeader(path): with open(path, 'rb') as f: header = f.read(elf_header_size) - header = struct.unpack(elf_header_format, header) + try: + header = struct.unpack(elf_header_format, header) + except struct.error: + raise Error("error parsing elf header: %s" % path) e_ident, _, e_machine = header[:3] elf_magic = '\x7fELF' @@ -725,7 +728,6 @@ def main(argv): return 0 -# Invoke this file directly for simple testing. if __name__ == '__main__': try: rtn = main(sys.argv[1:]) diff --git a/native_client_sdk/src/tools/tests/create_html_test.py b/native_client_sdk/src/tools/tests/create_html_test.py new file mode 100755 index 0000000..91e6ca6 --- /dev/null +++ b/native_client_sdk/src/tools/tests/create_html_test.py @@ -0,0 +1,56 @@ +#!/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 os +import unittest +import shutil +import sys +import tempfile + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +PARENT_DIR = os.path.dirname(SCRIPT_DIR) +CHROME_SRC = os.path.dirname(os.path.dirname(os.path.dirname(PARENT_DIR))) +MOCK_DIR = os.path.join(CHROME_SRC, "third_party", "pymock") + +sys.path.append(PARENT_DIR) +sys.path.append(MOCK_DIR) + +import create_html +import mock + +class TestCreateHtml(unittest.TestCase): + def setUp(self): + self.tempdir = None + + def tearDown(self): + if self.tempdir: + shutil.rmtree(self.tempdir) + + def testBadInput(self): + # Non-existant file + self.assertRaises(create_html.Error, create_html.main, ['foo.nexe']) + # Existing file with wrong extension + self.assertRaises(create_html.Error, create_html.main, [__file__]) + # Existing directory + self.assertRaises(create_html.Error, create_html.main, [PARENT_DIR]) + + def testCreatesOutput(self): + self.tempdir = tempfile.mkdtemp("_sdktest") + expected_html = os.path.join(self.tempdir, 'foo.html') + nmf_file = os.path.join(self.tempdir, 'foo.nmf') + with mock.patch('sys.stdout'): + with mock.patch('os.path.exists'): + with mock.patch('os.path.isfile'): + options = mock.MagicMock(return_value=False) + options.output = None + create_html.CreateHTML(nmf_file, options) + # Assert that the file was created + self.assertTrue(os.path.exists(expected_html)) + # Assert that nothing else was created + self.assertEqual(os.listdir(self.tempdir), + [os.path.basename(expected_html)]) + + +if __name__ == '__main__': + unittest.main() |