Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 from skypy.paths import Paths | 6 from skypy.paths import Paths |
| 7 from skypy.skyserver import SkyServer | 7 from skypy.skyserver import SkyServer |
| 8 import argparse | 8 import argparse |
| 9 import json | |
| 9 import logging | 10 import logging |
| 10 import os | 11 import os |
| 12 import requests | |
| 13 import signal | |
| 11 import skypy.configuration as configuration | 14 import skypy.configuration as configuration |
| 12 import subprocess | 15 import subprocess |
| 13 import urlparse | 16 import urlparse |
| 14 | 17 |
| 15 | 18 |
| 16 SUPPORTED_MIME_TYPES = [ | 19 SUPPORTED_MIME_TYPES = [ |
| 17 'text/html', | 20 'text/html', |
| 18 'text/sky', | 21 'text/sky', |
| 19 'text/plain', | 22 'text/plain', |
| 20 ] | 23 ] |
| 21 | 24 |
| 22 | |
| 23 HTTP_PORT = 9999 | 25 HTTP_PORT = 9999 |
| 26 PID_FILE_PATH = "/tmp/skydb.pids" | |
| 24 | 27 |
| 25 | 28 |
| 26 class SkyDebugger(object): | 29 class SkyDebugger(object): |
| 27 def __init__(self): | 30 def __init__(self): |
| 28 self.paths = None | 31 self.paths = None |
| 32 self.pids = {} | |
| 33 # FIXME: This is not android aware nor aware of the port | |
| 34 # skyserver is listening on. | |
| 35 self.base_url = 'http://localhost:7777' | |
| 29 | 36 |
| 30 def _server_root_and_url_from_path_arg(self, url_or_path): | 37 def _server_root_and_url_from_path_arg(self, url_or_path): |
| 31 # This is already a valid url we don't need a local server. | 38 # This is already a valid url we don't need a local server. |
| 32 if urlparse.urlparse(url_or_path).scheme: | 39 if urlparse.urlparse(url_or_path).scheme: |
| 33 return None, url_or_path | 40 return None, url_or_path |
| 34 | 41 |
| 35 path = os.path.abspath(url_or_path) | 42 path = os.path.abspath(url_or_path) |
| 36 if os.path.commonprefix([path, self.paths.src_root]) == self.paths.src_r oot: | 43 if os.path.commonprefix([path, self.paths.src_root]) == self.paths.src_r oot: |
| 37 server_root = self.paths.src_root | 44 server_root = self.paths.src_root |
| 38 else: | 45 else: |
| 39 server_root = os.path.dirname(path) | 46 server_root = os.path.dirname(path) |
| 40 logging.warn( | 47 logging.warn( |
| 41 '%s is outside of mojo root, using %s as server root' % | 48 '%s is outside of mojo root, using %s as server root' % |
| 42 (path, server_root)) | 49 (path, server_root)) |
| 43 local_url = SkyServer.url_for_path(HTTP_PORT, server_root, path) | 50 local_url = SkyServer.url_for_path(HTTP_PORT, server_root, path) |
| 44 return server_root, local_url | 51 return server_root, local_url |
| 45 | 52 |
| 46 def _in_chromoting(self): | 53 def _in_chromoting(self): |
| 47 return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False) | 54 return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False) |
| 48 | 55 |
| 49 def main(self): | 56 def start_command(self, args): |
| 50 logging.basicConfig(level=logging.INFO) | 57 self.stop_command([]) # Quit any existing process. |
| 51 | |
| 52 parser = argparse.ArgumentParser(description='Sky launcher/debugger') | |
| 53 parser.add_argument('--gdb', action='store_true') | |
| 54 parser.add_argument('--use-osmesa', action='store_true', | |
| 55 default=self._in_chromoting()) | |
| 56 parser.add_argument('url_or_path', nargs='?', type=str) | |
| 57 configuration.add_arguments(parser) | |
| 58 args = parser.parse_args() | |
| 59 | 58 |
| 60 self.paths = Paths(os.path.join('out', args.configuration)) | 59 self.paths = Paths(os.path.join('out', args.configuration)) |
| 61 | 60 |
| 62 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') | 61 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') |
| 63 for mime_type in SUPPORTED_MIME_TYPES] | 62 for mime_type in SUPPORTED_MIME_TYPES] |
| 64 shell_command = [ | 63 shell_command = [ |
| 65 self.paths.mojo_shell_path, | 64 self.paths.mojo_shell_path, |
| 66 '--v=1', | 65 '--v=1', |
| 67 '--content-handlers=%s' % ','.join(content_handlers), | 66 '--content-handlers=%s' % ','.join(content_handlers), |
| 68 '--url-mappings=mojo:window_manager=mojo:sky_debugger', | 67 '--url-mappings=mojo:window_manager=mojo:sky_debugger', |
| 69 'mojo:window_manager', | 68 'mojo:window_manager', |
| 70 ] | 69 ] |
| 71 if args.use_osmesa: | 70 if args.use_osmesa: |
| 72 shell_command.append('--args-for=mojo:native_viewport_service --use- osmesa') | 71 shell_command.append('--args-for=mojo:native_viewport_service --use- osmesa') |
| 73 | 72 |
| 74 server_root = None | |
| 75 | |
| 76 if args.url_or_path: | 73 if args.url_or_path: |
| 77 # Check if we need a local server for the url/path arg: | 74 # Check if we need a local server for the url/path arg: |
| 78 server_root, url = \ | 75 server_root, url = \ |
| 79 self._server_root_and_url_from_path_arg(args.url_or_path) | 76 self._server_root_and_url_from_path_arg(args.url_or_path) |
| 77 server = SkyServer(self.paths, HTTP_PORT, args.configuration, | |
| 78 server_root) | |
| 79 self.pids['sky_server_pid'] = server.start() | |
| 80 | |
| 80 prompt_args = '--args-for=mojo:sky_debugger_prompt %s' % url | 81 prompt_args = '--args-for=mojo:sky_debugger_prompt %s' % url |
| 81 shell_command.append(prompt_args) | 82 shell_command.append(prompt_args) |
| 82 | 83 |
| 83 if args.gdb: | 84 if args.gdb: |
| 84 shell_command = ['gdb', '--args'] + shell_command | 85 shell_command = ['gdb', '--args'] + shell_command |
| 85 | 86 |
| 86 if server_root: | 87 self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid |
| 87 with SkyServer(self.paths, HTTP_PORT, args.configuration, | 88 |
| 88 server_root): | 89 def _kill_if_exists(self, key, name): |
| 89 subprocess.check_call(shell_command) | 90 pid = self.pids.pop(key, None) |
| 91 if not pid: | |
| 92 logging.info('No pid for %s, nothing to do.' % name) | |
| 93 return | |
| 94 logging.info('Killing %s (%s).' % (name, pid)) | |
| 95 try: | |
| 96 os.kill(pid, signal.SIGTERM) | |
| 97 except OSError: | |
| 98 logging.info('%s (%s) already gone.' % (name, pid)) | |
| 99 | |
| 100 def stop_command(self, args): | |
| 101 # FIXME: Send /quit to sky prompt instead of killing. | |
| 102 # self._send_command_to_sky('/quit') | |
| 103 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') | |
| 104 self._kill_if_exists('sky_server_pid', 'sky_server') | |
| 105 | |
| 106 def load_command(self, args): | |
| 107 self._send_command_to_sky('/load', args[0]) | |
| 108 | |
| 109 def _send_command_to_sky(self, command_path, payload=None): | |
| 110 url = self.base_url + command_path | |
| 111 if payload: | |
| 112 response = requests.post(url, payload) | |
| 90 else: | 113 else: |
| 91 subprocess.check_call(shell_command) | 114 response = requests.get(url) |
| 115 print response.text | |
| 116 | |
| 117 # FIXME: These could be made into a context object with __enter__/__exit__. | |
| 118 def _load_pid_file(self, path): | |
| 119 try: | |
| 120 with open(path, 'r') as pid_file: | |
| 121 return json.load(pid_file) | |
| 122 except: | |
| 123 if os.path.exists(path): | |
| 124 logging.warn('Failed to read pid file: %s' % path) | |
| 125 return {} | |
| 126 | |
| 127 def _write_pid_file(self, path, pids): | |
| 128 try: | |
| 129 with open(path, 'w') as pid_file: | |
| 130 json.dump(pids, pid_file) | |
| 131 except: | |
| 132 logging.warn('Failed to write pid file: %s' % path) | |
| 133 | |
| 134 def _add_basic_command(self, subparsers, name, url_path, help_text): | |
| 135 parser = subparsers.add_parser(name, help=help_text) | |
| 136 command = lambda args: self._send_command_to_sky(url_path) | |
| 137 parser.set_defaults(func=command) | |
| 138 | |
| 139 def main(self): | |
| 140 logging.basicConfig(level=logging.INFO) | |
| 141 | |
| 142 self.pids = self._load_pid_file(PID_FILE_PATH) | |
| 143 | |
| 144 parser = argparse.ArgumentParser(description='Sky launcher/debugger') | |
| 145 subparsers = parser.add_subparsers(help='sub-command help') | |
| 146 | |
| 147 start_parser = subparsers.add_parser('start', | |
| 148 help='launch a new mojo_shell with sky') | |
| 149 configuration.add_arguments(start_parser) | |
| 150 start_parser.add_argument('--gdb', action='store_true') | |
| 151 start_parser.add_argument('--use-osmesa', action='store_true', | |
| 152 default=self._in_chromoting()) | |
| 153 start_parser.add_argument('url_or_path', nargs='?', type=str) | |
| 154 start_parser.set_defaults(func=self.start_command) | |
| 155 | |
| 156 stop_parser = subparsers.add_parser('stop', | |
| 157 help='launch a new mojo_shell with sky') | |
|
ojan
2015/01/07 23:49:54
This help is wrong?
| |
| 158 stop_parser.set_defaults(func=self.stop_command) | |
| 159 | |
| 160 self._add_basic_command(subparsers, 'trace', '/trace', | |
| 161 'toggle tracing') | |
| 162 self._add_basic_command(subparsers, 'reload', '/reload', | |
| 163 'reload the current page') | |
| 164 self._add_basic_command(subparsers, 'inspect', '/inspect', | |
| 165 'stop the running sky instance') | |
| 166 | |
| 167 load_parser = subparsers.add_parser('load', | |
| 168 help='load a new page in the currently running sky') | |
| 169 load_parser.set_defaults(func=self.load_command) | |
| 170 | |
| 171 args = parser.parse_args() | |
| 172 args.func(args) | |
| 173 | |
| 174 self._write_pid_file(PID_FILE_PATH, self.pids) | |
| 92 | 175 |
| 93 | 176 |
| 94 if __name__ == '__main__': | 177 if __name__ == '__main__': |
| 95 SkyDebugger().main() | 178 SkyDebugger().main() |
| OLD | NEW |