| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Produces configured shell abstractions. | 5 """Produces configured shell abstractions. |
| 6 | 6 |
| 7 This module knows how to produce a configured shell abstraction based on | 7 This module knows how to produce a configured shell abstraction based on |
| 8 shell_config.ShellConfig. | 8 shell_config.ShellConfig. |
| 9 """ | 9 """ |
| 10 | 10 |
| 11 import os.path | 11 import os.path |
| 12 import sys | 12 import sys |
| 13 import urlparse | 13 import urlparse |
| 14 | 14 |
| 15 from devtoolslib.android_shell import AndroidShell | 15 from devtoolslib.android_shell import AndroidShell |
| 16 from devtoolslib.linux_shell import LinuxShell | 16 from devtoolslib.linux_shell import LinuxShell |
| 17 from devtoolslib.shell_config import ShellConfigurationException | 17 from devtoolslib.shell_config import ShellConfigurationException |
| 18 | 18 |
| 19 # When spinning up servers for local origins, we want to use predictable ports | 19 # When spinning up servers for local origins, we want to use predictable ports |
| 20 # so that caching works between subsequent runs with the same command line. | 20 # so that caching works between subsequent runs with the same command line. |
| 21 _LOCAL_ORIGIN_PORT = 31840 | 21 _LOCAL_ORIGIN_PORT = 31840 |
| 22 _MAPPINGS_BASE_PORT = 31841 | 22 _MAPPINGS_BASE_PORT = 31841 |
| 23 | 23 |
| 24 | 24 |
| 25 def _is_web_url(dest): | 25 def _is_web_url(dest): |
| 26 return True if urlparse.urlparse(dest).scheme else False | 26 return True if urlparse.urlparse(dest).scheme else False |
| 27 | 27 |
| 28 | 28 |
| 29 def _host_local_url_destination(shell, dest_file, port, free_host_port): | 29 def _host_local_url_destination(shell, dest_file, port, reuse_servers): |
| 30 """Starts a local server to host |dest_file|. | 30 """Starts a local server to host |dest_file|. |
| 31 | 31 |
| 32 Returns: | 32 Returns: |
| 33 Url of the hosted file. | 33 Url of the hosted file. |
| 34 """ | 34 """ |
| 35 directory = os.path.dirname(dest_file) | 35 directory = os.path.dirname(dest_file) |
| 36 if not os.path.exists(directory): | 36 if not os.path.exists(directory): |
| 37 raise ValueError('local path passed as --map-url destination ' | 37 raise ValueError('local path passed as --map-url destination ' |
| 38 'does not exist') | 38 'does not exist') |
| 39 mappings = [('', [directory])] | 39 mappings = [('', [directory])] |
| 40 server_url = shell.serve_local_directories(mappings, port, free_host_port) | 40 server_url = shell.serve_local_directories(mappings, port, reuse_servers) |
| 41 return server_url + os.path.relpath(dest_file, directory) | 41 return server_url + os.path.relpath(dest_file, directory) |
| 42 | 42 |
| 43 | 43 |
| 44 def _host_local_origin_destination(shell, dest_dir, port, free_host_port): | 44 def _host_local_origin_destination(shell, dest_dir, port, reuse_servers): |
| 45 """Starts a local server to host |dest_dir|. | 45 """Starts a local server to host |dest_dir|. |
| 46 | 46 |
| 47 Returns: | 47 Returns: |
| 48 Url of the hosted directory. | 48 Url of the hosted directory. |
| 49 """ | 49 """ |
| 50 mappings = [('', [dest_dir])] | 50 mappings = [('', [dest_dir])] |
| 51 return shell.serve_local_directories(mappings, port, free_host_port) | 51 return shell.serve_local_directories(mappings, port, reuse_servers) |
| 52 | 52 |
| 53 | 53 |
| 54 def _rewrite(mapping, host_destination_functon, shell, port, free_host_port): | 54 def _rewrite(mapping, host_destination_functon, shell, port, reuse_servers): |
| 55 """Takes a mapping given as <src>=<dest> and rewrites the <dest> part to be | 55 """Takes a mapping given as <src>=<dest> and rewrites the <dest> part to be |
| 56 hosted locally using the given function if <dest> is not a web url. | 56 hosted locally using the given function if <dest> is not a web url. |
| 57 """ | 57 """ |
| 58 parts = mapping.split('=') | 58 parts = mapping.split('=') |
| 59 if len(parts) != 2: | 59 if len(parts) != 2: |
| 60 raise ValueError('each mapping value should be in format ' | 60 raise ValueError('each mapping value should be in format ' |
| 61 '"<url>=<url-or-local-path>"') | 61 '"<url>=<url-or-local-path>"') |
| 62 if _is_web_url(parts[1]): | 62 if _is_web_url(parts[1]): |
| 63 # The destination is a web url, do nothing. | 63 # The destination is a web url, do nothing. |
| 64 return mapping | 64 return mapping |
| 65 | 65 |
| 66 src = parts[0] | 66 src = parts[0] |
| 67 dest = host_destination_functon(shell, parts[1], port, free_host_port) | 67 dest = host_destination_functon(shell, parts[1], port, reuse_servers) |
| 68 return src + '=' + dest | 68 return src + '=' + dest |
| 69 | 69 |
| 70 | 70 |
| 71 def _apply_mappings(shell, original_arguments, map_urls, map_origins, | 71 def _apply_mappings(shell, original_arguments, map_urls, map_origins, |
| 72 free_ports, free_host_ports): | 72 reuse_servers): |
| 73 """Applies mappings for specified urls and origins. For each local path | 73 """Applies mappings for specified urls and origins. For each local path |
| 74 specified as destination a local server will be spawned and the mapping will | 74 specified as destination a local server will be spawned and the mapping will |
| 75 be rewritten accordingly. | 75 be rewritten accordingly. |
| 76 | 76 |
| 77 Args: | 77 Args: |
| 78 shell: The shell that is being configured. | 78 shell: The shell that is being configured. |
| 79 original_arguments: Current list of shell arguments. | 79 original_arguments: Current list of shell arguments. |
| 80 map_urls: List of url mappings, each in the form of | 80 map_urls: List of url mappings, each in the form of |
| 81 <url>=<url-or-local-path>. | 81 <url>=<url-or-local-path>. |
| 82 map_origins: List of origin mappings, each in the form of | 82 map_origins: List of origin mappings, each in the form of |
| 83 <origin>=<url-or-local-path>. | 83 <origin>=<url-or-local-path>. |
| 84 free_ports: Iff True, run local development servers on system-allocated | 84 reuse_servers: Assume that the development servers are already running and |
| 85 ports. This defeats any performance benefits from caching. | 85 do not spawn any. |
| 86 free_host_ports: Only applicable on Android. Iff True, local development | |
| 87 servers are run on system-allocated ports, but are still forwarded from | |
| 88 fixed ports on the device. | |
| 89 | 86 |
| 90 Returns: | 87 Returns: |
| 91 The updated argument list. | 88 The updated argument list. |
| 92 """ | 89 """ |
| 93 next_port = 0 if free_ports else _MAPPINGS_BASE_PORT | 90 next_port = _MAPPINGS_BASE_PORT |
| 94 args = original_arguments | 91 args = original_arguments |
| 95 if map_urls: | 92 if map_urls: |
| 96 # Sort the mappings to preserve caching regardless of argument order. | 93 # Sort the mappings to preserve caching regardless of argument order. |
| 97 for map_url in sorted(map_urls): | 94 for map_url in sorted(map_urls): |
| 98 mapping = _rewrite(map_url, _host_local_url_destination, shell, next_port, | 95 mapping = _rewrite(map_url, _host_local_url_destination, shell, next_port, |
| 99 free_host_ports) | 96 reuse_servers) |
| 100 if not free_ports: | 97 next_port += 1 |
| 101 next_port += 1 | |
| 102 # All url mappings need to be coalesced into one shell argument. | 98 # All url mappings need to be coalesced into one shell argument. |
| 103 args = append_to_argument(args, '--url-mappings=', mapping) | 99 args = append_to_argument(args, '--url-mappings=', mapping) |
| 104 | 100 |
| 105 if map_origins: | 101 if map_origins: |
| 106 for map_origin in sorted(map_origins): | 102 for map_origin in sorted(map_origins): |
| 107 mapping = _rewrite(map_origin, _host_local_origin_destination, shell, | 103 mapping = _rewrite(map_origin, _host_local_origin_destination, shell, |
| 108 next_port, free_host_ports) | 104 next_port, reuse_servers) |
| 109 if not free_ports: | 105 next_port += 1 |
| 110 next_port += 1 | |
| 111 # Origin mappings are specified as separate, repeated shell arguments. | 106 # Origin mappings are specified as separate, repeated shell arguments. |
| 112 args.append('--map-origin=' + mapping) | 107 args.append('--map-origin=' + mapping) |
| 113 return args | 108 return args |
| 114 | 109 |
| 115 | 110 |
| 116 def configure_local_origin(shell, local_dir, port, free_host_port): | 111 def configure_local_origin(shell, local_dir, port, reuse_servers): |
| 117 """Sets up a local http server to serve files in |local_dir| along with | 112 """Sets up a local http server to serve files in |local_dir| along with |
| 118 device port forwarding if needed. | 113 device port forwarding if needed. |
| 119 | 114 |
| 120 Returns: | 115 Returns: |
| 121 The list of arguments to be appended to the shell argument list. | 116 The list of arguments to be appended to the shell argument list. |
| 122 """ | 117 """ |
| 123 mappings = [('', [local_dir])] | 118 mappings = [('', [local_dir])] |
| 124 origin_url = shell.serve_local_directories(mappings, port, free_host_port) | 119 origin_url = shell.serve_local_directories(mappings, port, reuse_servers) |
| 125 return ["--origin=" + origin_url] | 120 return ["--origin=" + origin_url] |
| 126 | 121 |
| 127 | 122 |
| 128 def append_to_argument(arguments, key, value, delimiter=","): | 123 def append_to_argument(arguments, key, value, delimiter=","): |
| 129 """Looks for an argument of the form "key=val1,val2" within |arguments| and | 124 """Looks for an argument of the form "key=val1,val2" within |arguments| and |
| 130 appends |value| to it. | 125 appends |value| to it. |
| 131 | 126 |
| 132 If the argument is not present in |arguments| it is added. | 127 If the argument is not present in |arguments| it is added. |
| 133 | 128 |
| 134 Args: | 129 Args: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 148 if not argument.startswith(key): | 143 if not argument.startswith(key): |
| 149 continue | 144 continue |
| 150 arguments[i] = argument + delimiter + value | 145 arguments[i] = argument + delimiter + value |
| 151 break | 146 break |
| 152 else: | 147 else: |
| 153 arguments.append(key + value) | 148 arguments.append(key + value) |
| 154 | 149 |
| 155 return arguments | 150 return arguments |
| 156 | 151 |
| 157 | 152 |
| 158 def _configure_dev_server(shell, shell_args, dev_server_config, free_host_port, | 153 def _configure_dev_server(shell, shell_args, dev_server_config, reuse_servers, |
| 159 verbose): | 154 verbose): |
| 160 """Sets up a dev server on the host according to |dev_server_config|. | 155 """Sets up a dev server on the host according to |dev_server_config|. |
| 161 | 156 |
| 162 Args: | 157 Args: |
| 163 shell: The shell that is being configured. | 158 shell: The shell that is being configured. |
| 164 shell_arguments: Current list of shell arguments. | 159 shell_arguments: Current list of shell arguments. |
| 165 dev_server_config: Instance of shell_config.DevServerConfig describing the | 160 dev_server_config: Instance of shell_config.DevServerConfig describing the |
| 166 dev server to be set up. | 161 dev server to be set up. |
| 167 | 162 |
| 168 Returns: | 163 Returns: |
| 169 The updated argument list. | 164 The updated argument list. |
| 170 """ | 165 """ |
| 171 port = dev_server_config.port if dev_server_config.port else 0 | 166 port = dev_server_config.port if dev_server_config.port else 0 |
| 172 server_url = shell.serve_local_directories(dev_server_config.mappings, | 167 server_url = shell.serve_local_directories( |
| 173 port=port, | 168 dev_server_config.mappings, port, reuse_servers) |
| 174 free_host_port=free_host_port) | |
| 175 shell_args.append('--map-origin=%s=%s' % (dev_server_config.host, server_url)) | 169 shell_args.append('--map-origin=%s=%s' % (dev_server_config.host, server_url)) |
| 176 | 170 |
| 177 if verbose: | 171 if verbose: |
| 178 print "Configured %s locally at %s to serve:" % (dev_server_config.host, | 172 print "Configured %s locally at %s to serve:" % (dev_server_config.host, |
| 179 server_url) | 173 server_url) |
| 180 for mapping_prefix, mapping_path in dev_server_config.mappings: | 174 for mapping_prefix, mapping_path in dev_server_config.mappings: |
| 181 print " /%s -> %s" % (mapping_prefix, mapping_path) | 175 print " /%s -> %s" % (mapping_prefix, mapping_path) |
| 182 return shell_args | 176 return shell_args |
| 183 | 177 |
| 184 | 178 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 else: | 210 else: |
| 217 if not shell_config.shell_path: | 211 if not shell_config.shell_path: |
| 218 raise ShellConfigurationException('Can not run without a shell binary. ' | 212 raise ShellConfigurationException('Can not run without a shell binary. ' |
| 219 'Please pass --shell-path.') | 213 'Please pass --shell-path.') |
| 220 shell = LinuxShell(shell_config.shell_path) | 214 shell = LinuxShell(shell_config.shell_path) |
| 221 if shell_config.use_osmesa: | 215 if shell_config.use_osmesa: |
| 222 shell_args.append('--args-for=mojo:native_viewport_service --use-osmesa') | 216 shell_args.append('--args-for=mojo:native_viewport_service --use-osmesa') |
| 223 | 217 |
| 224 shell_args = _apply_mappings(shell, shell_args, shell_config.map_url_list, | 218 shell_args = _apply_mappings(shell, shell_args, shell_config.map_url_list, |
| 225 shell_config.map_origin_list, | 219 shell_config.map_origin_list, |
| 226 shell_config.free_ports, | 220 shell_config.reuse_servers) |
| 227 shell_config.free_host_ports) | |
| 228 | 221 |
| 229 if shell_config.origin: | 222 if shell_config.origin: |
| 230 if _is_web_url(shell_config.origin): | 223 if _is_web_url(shell_config.origin): |
| 231 shell_args.append('--origin=' + shell_config.origin) | 224 shell_args.append('--origin=' + shell_config.origin) |
| 232 else: | 225 else: |
| 233 local_origin_port = 0 if shell_config.free_ports else _LOCAL_ORIGIN_PORT | 226 local_origin_port = _LOCAL_ORIGIN_PORT |
| 234 shell_args.extend(configure_local_origin(shell, shell_config.origin, | 227 shell_args.extend(configure_local_origin(shell, shell_config.origin, |
| 235 local_origin_port, | 228 local_origin_port, |
| 236 shell_config.free_host_ports)) | 229 shell_config.reuse_servers)) |
| 237 | 230 |
| 238 if shell_config.content_handlers: | 231 if shell_config.content_handlers: |
| 239 for (mime_type, | 232 for (mime_type, |
| 240 content_handler_url) in shell_config.content_handlers.iteritems(): | 233 content_handler_url) in shell_config.content_handlers.iteritems(): |
| 241 shell_args = append_to_argument(shell_args, '--content-handlers=', | 234 shell_args = append_to_argument(shell_args, '--content-handlers=', |
| 242 '%s,%s' % (mime_type, | 235 '%s,%s' % (mime_type, |
| 243 content_handler_url)) | 236 content_handler_url)) |
| 244 | 237 |
| 245 for dev_server_config in shell_config.dev_servers: | 238 for dev_server_config in shell_config.dev_servers: |
| 246 shell_args = _configure_dev_server(shell, shell_args, dev_server_config, | 239 shell_args = _configure_dev_server(shell, shell_args, dev_server_config, |
| 247 shell_config.free_host_ports, | 240 shell_config.reuse_servers, |
| 248 shell_config.verbose) | 241 shell_config.verbose) |
| 249 | 242 |
| 250 return shell, shell_args | 243 return shell, shell_args |
| OLD | NEW |