mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This makes skydb pass a command_port to prompt.cc as a commandline argument. I removed passing of the url and instead pass the url via a separate /load command. This has the nice side effect of guarenteeing that the sky instance is up and ready to respond to commands when skydb exits. It also prepares us for running more than one copy of prompt.cc as jamesr requested for both Release and Debug or for on both your android device as well as your local machine. R=abarth@chromium.org, jamesr@chromium.org BUG= Review URL: https://codereview.chromium.org/841113003
219 lines
7.6 KiB
Python
Executable File
219 lines
7.6 KiB
Python
Executable File
#!/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.
|
|
|
|
from skypy.paths import Paths
|
|
from skypy.skyserver import SkyServer
|
|
import argparse
|
|
import json
|
|
import logging
|
|
import os
|
|
import requests
|
|
import signal
|
|
import skypy.configuration as configuration
|
|
import subprocess
|
|
import urlparse
|
|
import time
|
|
|
|
|
|
SUPPORTED_MIME_TYPES = [
|
|
'text/html',
|
|
'text/sky',
|
|
'text/plain',
|
|
]
|
|
|
|
DEFAULT_SKY_COMMAND_PORT = 7777
|
|
SKY_SERVER_PORT = 9999
|
|
PID_FILE_PATH = "/tmp/skydb.pids"
|
|
DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/examples/home.sky"
|
|
|
|
|
|
class SkyDebugger(object):
|
|
def __init__(self):
|
|
self.paths = None
|
|
self.pids = {}
|
|
|
|
def _server_root_for_url(self, url_or_path):
|
|
path = os.path.abspath(url_or_path)
|
|
if os.path.commonprefix([path, self.paths.src_root]) == self.paths.src_root:
|
|
server_root = self.paths.src_root
|
|
else:
|
|
server_root = os.path.dirname(path)
|
|
logging.warn(
|
|
'%s is outside of mojo root, using %s as server root' %
|
|
(path, server_root))
|
|
return server_root
|
|
|
|
def _in_chromoting(self):
|
|
return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False)
|
|
|
|
def _build_mojo_shell_command(self, args):
|
|
self.paths = Paths(os.path.join('out', args.configuration))
|
|
|
|
content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer')
|
|
for mime_type in SUPPORTED_MIME_TYPES]
|
|
shell_command = [
|
|
self.paths.mojo_shell_path,
|
|
'--v=1',
|
|
'--content-handlers=%s' % ','.join(content_handlers),
|
|
'--url-mappings=mojo:window_manager=mojo:sky_debugger',
|
|
'--args-for=mojo:sky_debugger_prompt %d' % args.command_port,
|
|
'mojo:window_manager',
|
|
]
|
|
if args.use_osmesa:
|
|
shell_command.append('--args-for=mojo:native_viewport_service --use-osmesa')
|
|
|
|
if args.gdb:
|
|
shell_command = ['gdb', '--args'] + shell_command
|
|
|
|
return shell_command
|
|
|
|
def start_command(self, args):
|
|
shell_command = self._build_mojo_shell_command(args)
|
|
if args.show_command:
|
|
print " ".join(shell_command)
|
|
return
|
|
|
|
self.stop_command(None) # Quit any existing process.
|
|
|
|
print args.url_or_path
|
|
# We only start a server for paths:
|
|
if not urlparse.urlparse(args.url_or_path).scheme:
|
|
server_root = self._server_root_for_url(args.url_or_path)
|
|
sky_server = SkyServer(self.paths, SKY_SERVER_PORT,
|
|
args.configuration, server_root)
|
|
self.pids['sky_server_pid'] = sky_server.start()
|
|
self.pids['sky_server_port'] = sky_server.port
|
|
self.pids['sky_server_root'] = sky_server.root
|
|
|
|
self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid
|
|
self.pids['sky_command_port'] = args.command_port
|
|
|
|
if not self._wait_for_sky_command_port():
|
|
logging.error('Failed to start sky')
|
|
self.stop_command(None)
|
|
else:
|
|
self.load_command(args)
|
|
|
|
def _kill_if_exists(self, key, name):
|
|
pid = self.pids.pop(key, None)
|
|
if not pid:
|
|
logging.info('No pid for %s, nothing to do.' % name)
|
|
return
|
|
logging.info('Killing %s (%s).' % (name, pid))
|
|
try:
|
|
os.kill(pid, signal.SIGTERM)
|
|
except OSError:
|
|
logging.info('%s (%s) already gone.' % (name, pid))
|
|
|
|
def stop_command(self, args):
|
|
# FIXME: Send /quit to sky prompt instead of killing.
|
|
# self._send_command_to_sky('/quit')
|
|
self._kill_if_exists('mojo_shell_pid', 'mojo_shell')
|
|
self._kill_if_exists('sky_server_pid', 'sky_server')
|
|
|
|
def load_command(self, args):
|
|
if not urlparse.urlparse(args.url_or_path).scheme:
|
|
url = SkyServer.url_for_path(self.pids['sky_server_port'],
|
|
self.pids['sky_server_root'], args.url_or_path)
|
|
else:
|
|
url = args.url_or_path
|
|
self._send_command_to_sky('/load', url)
|
|
|
|
def _command_base_url(self):
|
|
return 'http://localhost:%s' % self.pids['sky_command_port']
|
|
|
|
def _send_command_to_sky(self, command_path, payload=None):
|
|
url = 'http://localhost:%s%s' % (
|
|
self.pids['sky_command_port'], command_path)
|
|
if payload:
|
|
response = requests.post(url, payload)
|
|
else:
|
|
response = requests.get(url)
|
|
print response.text
|
|
|
|
# FIXME: These could be made into a context object with __enter__/__exit__.
|
|
def _load_pid_file(self, path):
|
|
try:
|
|
with open(path, 'r') as pid_file:
|
|
return json.load(pid_file)
|
|
except:
|
|
if os.path.exists(path):
|
|
logging.warn('Failed to read pid file: %s' % path)
|
|
return {}
|
|
|
|
def _write_pid_file(self, path, pids):
|
|
try:
|
|
with open(path, 'w') as pid_file:
|
|
json.dump(pids, pid_file)
|
|
except:
|
|
logging.warn('Failed to write pid file: %s' % path)
|
|
|
|
def _add_basic_command(self, subparsers, name, url_path, help_text):
|
|
parser = subparsers.add_parser(name, help=help_text)
|
|
command = lambda args: self._send_command_to_sky(url_path)
|
|
parser.set_defaults(func=command)
|
|
|
|
def _wait_for_sky_command_port(self):
|
|
tries = 0
|
|
while True:
|
|
try:
|
|
self._send_command_to_sky('/')
|
|
return True
|
|
except:
|
|
tries += 1
|
|
if tries == 3:
|
|
logging.warn('Still waiting for sky on port %s' %
|
|
self.pids['sky_command_port'])
|
|
if tries > 10:
|
|
return False
|
|
time.sleep(1)
|
|
|
|
def main(self):
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
self.pids = self._load_pid_file(PID_FILE_PATH)
|
|
|
|
parser = argparse.ArgumentParser(description='Sky launcher/debugger')
|
|
subparsers = parser.add_subparsers(help='sub-command help')
|
|
|
|
start_parser = subparsers.add_parser('start',
|
|
help='launch a new mojo_shell with sky')
|
|
configuration.add_arguments(start_parser)
|
|
start_parser.add_argument('--gdb', action='store_true')
|
|
start_parser.add_argument('--command-port', type=int,
|
|
default=DEFAULT_SKY_COMMAND_PORT)
|
|
start_parser.add_argument('--use-osmesa', action='store_true',
|
|
default=self._in_chromoting())
|
|
start_parser.add_argument('url_or_path', nargs='?', type=str,
|
|
default=DEFAULT_URL)
|
|
start_parser.add_argument('--show-command', action='store_true',
|
|
help='Display the shell command and exit')
|
|
start_parser.set_defaults(func=self.start_command)
|
|
|
|
stop_parser = subparsers.add_parser('stop',
|
|
help=('stop sky (as listed in %s)' % PID_FILE_PATH))
|
|
stop_parser.set_defaults(func=self.stop_command)
|
|
|
|
self._add_basic_command(subparsers, 'trace', '/trace',
|
|
'toggle tracing')
|
|
self._add_basic_command(subparsers, 'reload', '/reload',
|
|
'reload the current page')
|
|
self._add_basic_command(subparsers, 'inspect', '/inspect',
|
|
'stop the running sky instance')
|
|
|
|
load_parser = subparsers.add_parser('load',
|
|
help='load a new page in the currently running sky')
|
|
load_parser.add_argument('url_or_path', type=str)
|
|
load_parser.set_defaults(func=self.load_command)
|
|
|
|
args = parser.parse_args()
|
|
args.func(args)
|
|
|
|
self._write_pid_file(PID_FILE_PATH, self.pids)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
SkyDebugger().main()
|