blob: 49e2b8b86aa3993f8233ae7dcc584e23ddf201a4 [file] [log] [blame]
# Copyright 2015 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.
"""Functions that configure the shell before it is run manipulating its argument
list.
"""
import os.path
import urlparse
# When spinning up servers for local origins, we want to use predictable ports
# so that caching works between subsequent runs with the same command line.
_LOCAL_ORIGIN_PORT = 31840
_MAPPINGS_BASE_PORT = 31841
# Port on which the mojo:debugger http server will be available on the host
# machine.
_MOJO_DEBUGGER_PORT = 7777
_SKY_SERVER_PORT = 9998
def _HostLocalUrlDestination(shell, dest_file, port):
"""Starts a local server to host |dest_file|.
Returns:
Url of the hosted file.
"""
directory = os.path.dirname(dest_file)
if not os.path.exists(directory):
raise ValueError('local path passed as --map-url destination '
'does not exist')
server_url = shell.ServeLocalDirectory(directory, port)
return server_url + os.path.relpath(dest_file, directory)
def _HostLocalOriginDestination(shell, dest_dir, port):
"""Starts a local server to host |dest_dir|.
Returns:
Url of the hosted directory.
"""
return shell.ServeLocalDirectory(dest_dir, port)
def _Rewrite(mapping, host_destination_functon, shell, port):
"""Takes a mapping given as <src>=<dest> and rewrites the <dest> part to be
hosted locally using the given function if <dest> is not a web url.
"""
parts = mapping.split('=')
if len(parts) != 2:
raise ValueError('each mapping value should be in format '
'"<url>=<url-or-local-path>"')
if urlparse.urlparse(parts[1])[0]:
# The destination is a web url, do nothing.
return mapping
src = parts[0]
dest = host_destination_functon(shell, parts[1], port)
return src + '=' + dest
def ApplyMappings(shell, original_arguments, map_urls, map_origins):
"""Applies mappings for specified urls and origins. For each local path
specified as destination a local server will be spawned and the mapping will
be rewritten accordingly.
Args:
shell: The shell that is being configured.
original_arguments: Current list of shell arguments.
map_urls: List of url mappings, each in the form of
<url>=<url-or-local-path>.
map_origins: List of origin mappings, each in the form of
<origin>=<url-or-local-path>.
Returns:
The updated argument list.
"""
next_port = _MAPPINGS_BASE_PORT
args = original_arguments
if map_urls:
# Sort the mappings to preserve caching regardless of argument order.
for map_url in sorted(map_urls):
mapping = _Rewrite(map_url, _HostLocalUrlDestination, shell, next_port)
next_port += 1
# All url mappings need to be coalesced into one shell argument.
args = AppendToArgument(args, '--url-mappings=', mapping)
if map_origins:
for map_origin in sorted(map_origins):
mapping = _Rewrite(map_origin, _HostLocalOriginDestination, shell,
next_port)
next_port += 1
# Origin mappings are specified as separate, repeated shell arguments.
args.append('--map-origin=' + mapping)
return args
def ConfigureDebugger(shell):
"""Configures mojo:debugger to run and sets up port forwarding for its http
server if the shell is running on a device.
Returns:
Arguments that need to be appended to the shell argument list in order to
run with the debugger.
"""
shell.ForwardHostPortToShell(_MOJO_DEBUGGER_PORT)
return ['mojo:debugger %d' % _MOJO_DEBUGGER_PORT]
def ConfigureSky(shell, root_path, sky_packages_path, sky_target):
"""Configures additional mappings and a server needed to run the given Sky
app.
Args:
root_path: Local path to the root from which Sky apps will be served.
sky_packages_path: Local path to the root from which Sky packages will be
served.
sky_target: Path to the Sky app to be run, relative to |root_path|.
Returns:
Arguments that need to be appended to the shell argument list.
"""
# Configure a server to serve the checkout root at / (so that Sky examples
# are accessible using a root-relative path) and Sky packages at /packages.
# This is independent from the server that potentially serves the origin
# directory containing the mojo: apps.
additional_mappings = [
('packages/', sky_packages_path),
]
server_url = shell.ServeLocalDirectory(root_path, port=_SKY_SERVER_PORT,
additional_mappings=additional_mappings)
args = []
# Configure the content type mappings for the sky_viewer. This is needed
# only for the Sky apps that do not declare mojo:sky_viewer in a shebang,
# and it is unfortunate as it configures the shell to map all items of the
# application/dart content-type as Sky apps.
# TODO(ppi): drop this part once we can rely on the Sky files declaring
# correct shebang.
args = AppendToArgument(args, '--content-handlers=',
'text/sky,mojo:sky_viewer')
args = AppendToArgument(args, '--content-handlers=',
'application/dart,mojo:sky_viewer')
# Configure the window manager to embed the sky_viewer.
sky_url = server_url + sky_target
args.append('mojo:window_manager %s' % sky_url)
return args
def ConfigureLocalOrigin(shell, local_dir, fixed_port=True):
"""Sets up a local http server to serve files in |local_dir| along with
device port forwarding if needed.
Returns:
The list of arguments to be appended to the shell argument list.
"""
origin_url = shell.ServeLocalDirectory(
local_dir, _LOCAL_ORIGIN_PORT if fixed_port else 0)
return ["--origin=" + origin_url]
def AppendToArgument(arguments, key, value, delimiter=","):
"""Looks for an argument of the form "key=val1,val2" within |arguments| and
appends |value| to it.
If the argument is not present in |arguments| it is added.
Args:
arguments: List of arguments for the shell.
key: Identifier of the argument, including the equal sign, eg.
"--content-handlers=".
value: The value to be appended, after |delimeter|, to the argument.
delimiter: The string used to separate values within the argument.
Returns:
The updated argument list.
"""
assert key and key.endswith('=')
assert value
for i, argument in enumerate(arguments):
if not argument.startswith(key):
continue
arguments[i] = argument + delimiter + value
break
else:
arguments.append(key + value)
return arguments