blob: 5dbdbafafea803a1a6568983bfd7237bdde7840f [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2014 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 argparse
import os.path
import requests
import subprocess
import sys
_MOJO_DEBUGGER_PORT = 7777
def _send_request(request, payload=None):
"""Sends a request to mojo:debugger."""
try:
url = 'http://localhost:%s/%s' % (_MOJO_DEBUGGER_PORT, request)
if payload:
return requests.post(url, payload)
else:
return requests.get(url)
except requests.exceptions.ConnectionError:
print 'Failed to connect to mojo:debugger, make sure the shell is running.'
return None
def _tracing_start(_):
"""Starts tracing."""
if not _send_request('start_tracing'):
return 1
print "Started tracing."
return 0
def _tracing_stop(args):
"""Stops tracing and writes trace to file."""
if args.file_name:
file_name = args.file_name
else:
for i in xrange(1000):
candidate_file_name = 'mojo_trace_%03d.json' % i
if not os.path.exists(candidate_file_name):
file_name = candidate_file_name
break
else:
print 'Failed to pick a name for the trace output file.'
return 1
response = _send_request('stop_tracing')
if not response:
return 1
with open(file_name, "wb") as trace_file:
trace_file.write('{"traceEvents":[')
trace_file.write(response.content)
trace_file.write(']}')
print "Trace saved in %s" % file_name
return 0
def _add_tracing_command(subparsers):
"""Sets up the command line parser to manage tracing."""
tracing_parser = subparsers.add_parser('tracing',
help='trace event profiler')
tracing_subparser = tracing_parser.add_subparsers(
help='the command to run')
start_tracing_parser = tracing_subparser.add_parser('start',
help='start tracing')
start_tracing_parser.set_defaults(func=_tracing_start)
stop_tracing_parser = tracing_subparser.add_parser('stop',
help='stop tracing and retrieve the result')
stop_tracing_parser.add_argument('file_name', type=str, nargs='?',
help='name of the output file (optional)')
stop_tracing_parser.set_defaults(func=_tracing_stop)
def _wm_load(args):
"""Loads (embeds) the given url in the window manager."""
if not _send_request('load', args.url):
return 1
return 0
def _add_wm_command(subparsers):
"""Sets up the parser for the 'wm' command."""
wm_parser = subparsers.add_parser('wm', help='window manager')
wm_subparser = wm_parser.add_subparsers(
help='the command to run')
wm_load_parser = wm_subparser.add_parser('load',
help='load (embed) the given url')
wm_load_parser.add_argument('url', type=str,
help='the url to load')
wm_load_parser.set_defaults(func=_wm_load)
def _device_stack(args):
"""Runs the device logcat through android_stack_parser."""
adb_path = args.adb_path if args.adb_path else 'adb'
logcat_cmd = [adb_path, 'logcat', '-d']
try:
logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE)
except OSError:
print 'failed to call adb, make sure it is in PATH or pass --adb-path'
return 1
devtools_dir = os.path.dirname(os.path.abspath(__file__))
stack_command = [os.path.join(devtools_dir, 'android_stack_parser', 'stack')]
if args.build_dir:
stack_command.append('--build-dir=' + os.path.abspath(args.build_dir))
if args.ndk_dir:
stack_command.append('--ndk-dir=' + os.path.abspath(args.ndk_dir))
stack_command.append('-')
stack = subprocess.Popen(stack_command, stdin=logcat.stdout)
logcat.wait()
stack.wait()
if logcat.returncode:
print 'adb logcat failed, make sure the device is connected and available'
return logcat.returncode
if stack.returncode:
return stack.returncode
return 0
def _add_device_command(subparsers):
"""Sets up the parser for the 'device' command."""
device_parser = subparsers.add_parser('device',
help='interact with the Android device (requires adb in PATH or passing '
'--adb-path)')
device_parser.add_argument('--adb-path', type=str,
help='path to the adb tool from the Android SDK')
device_subparser = device_parser.add_subparsers(
help='the command to run')
device_stack_parser = device_subparser.add_parser('stack',
help='symbolize the crash stacktraces from the device log')
device_stack_parser.add_argument('--build-dir', type=str,
help='path to the build directory')
device_stack_parser.add_argument('--ndk-dir', type=str,
help='path to the directory containing the Android NDK')
device_stack_parser.set_defaults(func=_device_stack)
def main():
parser = argparse.ArgumentParser(description='Command-line interface for '
'mojo:debugger')
subparsers = parser.add_subparsers(help='the tool to run')
_add_device_command(subparsers)
_add_tracing_command(subparsers)
_add_wm_command(subparsers)
args = parser.parse_args()
return args.func(args)
if __name__ == '__main__':
sys.exit(main())