summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorsbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 00:20:15 +0000
committersbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 00:20:15 +0000
commitcd620f78098c40d38c56a72e2c859565c283c412 (patch)
tree860381c0d8af35eeb3de1c92503c76e10769b7e8 /native_client_sdk
parent4e1b91e07236c42f35c24029064aac623722d536 (diff)
downloadchromium_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.list1
-rwxr-xr-xnative_client_sdk/src/test_all.py1
-rwxr-xr-xnative_client_sdk/src/tools/create_html.py177
-rwxr-xr-xnative_client_sdk/src/tools/create_nmf.py6
-rwxr-xr-xnative_client_sdk/src/tools/tests/create_html_test.py56
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()