| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 import atexit | 5 import atexit |
| 6 import hashlib | 6 import hashlib |
| 7 import json | 7 import json |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import os.path | 10 import os.path |
| 11 import random | 11 import random |
| 12 import re | 12 import re |
| 13 import subprocess | 13 import subprocess |
| 14 import sys | 14 import sys |
| 15 import tempfile | 15 import tempfile |
| 16 import threading | 16 import threading |
| 17 import time | 17 import time |
| 18 | 18 |
| 19 from devtoolslib.http_server import start_http_server | 19 from devtoolslib.http_server import start_http_server |
| 20 from devtoolslib.shell import Shell | 20 from devtoolslib.shell import Shell |
| 21 from devtoolslib.utils import overrides |
| 21 | 22 |
| 22 | 23 |
| 23 # Tags used by mojo shell Java logging. | 24 # Tags used by mojo shell Java logging. |
| 24 _LOGCAT_JAVA_TAGS = [ | 25 _LOGCAT_JAVA_TAGS = [ |
| 25 'AndroidHandler', | 26 'AndroidHandler', |
| 26 'MojoFileHelper', | 27 'MojoFileHelper', |
| 27 'MojoMain', | 28 'MojoMain', |
| 28 'MojoShellActivity', | 29 'MojoShellActivity', |
| 29 'MojoShellApplication', | 30 'MojoShellApplication', |
| 30 ] | 31 ] |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 line) | 364 line) |
| 364 if match: | 365 if match: |
| 365 device_port = int(match.group(1)) | 366 device_port = int(match.group(1)) |
| 366 host_port = self._ForwardHostPortToDevice(0, device_port) | 367 host_port = self._ForwardHostPortToDevice(0, device_port) |
| 367 print ("Dart observatory available at the host at http://127.0.0.1:%d" | 368 print ("Dart observatory available at the host at http://127.0.0.1:%d" |
| 368 % host_port) | 369 % host_port) |
| 369 | 370 |
| 370 logcat_watch_thread = threading.Thread(target=_ForwardObservatoriesAsNeeded) | 371 logcat_watch_thread = threading.Thread(target=_ForwardObservatoriesAsNeeded) |
| 371 logcat_watch_thread.start() | 372 logcat_watch_thread.start() |
| 372 | 373 |
| 374 @overrides(Shell) |
| 373 def ServeLocalDirectory(self, local_dir_path, port=0): | 375 def ServeLocalDirectory(self, local_dir_path, port=0): |
| 374 """Serves the content of the local (host) directory, making it available to | |
| 375 the shell under the url returned by the function. | |
| 376 | |
| 377 The server will run on a separate thread until the program terminates. The | |
| 378 call returns immediately. | |
| 379 | |
| 380 Args: | |
| 381 local_dir_path: path to the directory to be served | |
| 382 port: port at which the server will be available to the shell | |
| 383 | |
| 384 Returns: | |
| 385 The url that the shell can use to access the content of |local_dir_path|. | |
| 386 """ | |
| 387 assert local_dir_path | 376 assert local_dir_path |
| 388 mappings = [('', local_dir_path)] | 377 mappings = [('', local_dir_path)] |
| 389 server_address = start_http_server(mappings, host_port=port) | 378 server_address = start_http_server(mappings, host_port=port) |
| 390 | 379 |
| 391 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( | 380 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( |
| 392 port, server_address[1]) | 381 port, server_address[1]) |
| 393 | 382 |
| 383 @overrides(Shell) |
| 394 def ServeLocalDirectories(self, mappings, port=0): | 384 def ServeLocalDirectories(self, mappings, port=0): |
| 395 """Serves the content of the local (host) directories, making it available | |
| 396 to the shell under the url returned by the function. | |
| 397 | |
| 398 The server will run on a separate thread until the program terminates. The | |
| 399 call returns immediately. | |
| 400 | |
| 401 Args: | |
| 402 mappings: List of tuples (prefix, local_base_path) mapping URLs that start | |
| 403 with |prefix| to local directory at |local_base_path|. The prefixes | |
| 404 should skip the leading slash. The first matching prefix will be used | |
| 405 each time. | |
| 406 port: port at which the server will be available to the shell | |
| 407 | |
| 408 Returns: | |
| 409 The url that the shell can use to access the content of |local_dir_path|. | |
| 410 """ | |
| 411 assert mappings | 385 assert mappings |
| 412 server_address = start_http_server(mappings, host_port=port) | 386 server_address = start_http_server(mappings, host_port=port) |
| 413 | 387 |
| 414 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( | 388 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( |
| 415 port, server_address[1]) | 389 port, server_address[1]) |
| 416 | 390 |
| 391 @overrides(Shell) |
| 417 def ForwardHostPortToShell(self, host_port): | 392 def ForwardHostPortToShell(self, host_port): |
| 418 """Forwards a port on the host machine to the same port wherever the shell | |
| 419 is running. | |
| 420 | |
| 421 This is a no-op if the shell is running locally. | |
| 422 """ | |
| 423 self._ForwardHostPortToDevice(host_port, host_port) | 393 self._ForwardHostPortToDevice(host_port, host_port) |
| 424 | 394 |
| 395 @overrides(Shell) |
| 425 def Run(self, arguments): | 396 def Run(self, arguments): |
| 426 """Runs the shell with given arguments until shell exits, passing the stdout | |
| 427 mingled with stderr produced by the shell onto the stdout. | |
| 428 | |
| 429 Returns: | |
| 430 Exit code retured by the shell or None if the exit code cannot be | |
| 431 retrieved. | |
| 432 """ | |
| 433 self.CleanLogs() | 397 self.CleanLogs() |
| 434 self.ForwardObservatoryPorts() | 398 self.ForwardObservatoryPorts() |
| 435 | 399 |
| 436 # If we are running as root, don't carry over the native logs from logcat - | 400 # If we are running as root, don't carry over the native logs from logcat - |
| 437 # we will have these in the stdout. | 401 # we will have these in the stdout. |
| 438 p = self.ShowLogs(include_native_logs=(not self._RunAdbAsRoot())) | 402 p = self.ShowLogs(include_native_logs=(not self._RunAdbAsRoot())) |
| 439 self.StartShell(arguments, sys.stdout, p.terminate) | 403 self.StartShell(arguments, sys.stdout, p.terminate) |
| 440 p.wait() | 404 p.wait() |
| 441 return None | 405 return None |
| 442 | 406 |
| 407 @overrides(Shell) |
| 443 def RunAndGetOutput(self, arguments, timeout=None): | 408 def RunAndGetOutput(self, arguments, timeout=None): |
| 444 """Runs the shell with given arguments until shell exits and returns the | |
| 445 output. | |
| 446 | |
| 447 Args: | |
| 448 arguments: list of arguments for the shell | |
| 449 timeout: maximum running time in seconds, after which the shell will be | |
| 450 terminated | |
| 451 | |
| 452 Returns: | |
| 453 A tuple of (return_code, output, did_time_out). |return_code| is the exit | |
| 454 code returned by the shell or None if the exit code cannot be retrieved. | |
| 455 |output| is the stdout mingled with the stderr produced by the shell. | |
| 456 |did_time_out| is True iff the shell was terminated because it exceeded | |
| 457 the |timeout| and False otherwise. | |
| 458 """ | |
| 459 class Results: | 409 class Results: |
| 460 """Workaround for Python scoping rules that prevent assigning to variables | 410 """Workaround for Python scoping rules that prevent assigning to variables |
| 461 from the outer scope. | 411 from the outer scope. |
| 462 """ | 412 """ |
| 463 output = None | 413 output = None |
| 464 | 414 |
| 465 def do_run(): | 415 def do_run(): |
| 466 (r, w) = os.pipe() | 416 (r, w) = os.pipe() |
| 467 with os.fdopen(r, "r") as rf: | 417 with os.fdopen(r, "r") as rf: |
| 468 with os.fdopen(w, "w") as wf: | 418 with os.fdopen(w, "w") as wf: |
| 469 self.StartShell(arguments, wf, wf.close) | 419 self.StartShell(arguments, wf, wf.close) |
| 470 Results.output = rf.read() | 420 Results.output = rf.read() |
| 471 | 421 |
| 472 run_thread = threading.Thread(target=do_run) | 422 run_thread = threading.Thread(target=do_run) |
| 473 run_thread.start() | 423 run_thread.start() |
| 474 run_thread.join(timeout) | 424 run_thread.join(timeout) |
| 475 | 425 |
| 476 if run_thread.is_alive(): | 426 if run_thread.is_alive(): |
| 477 self.StopShell() | 427 self.StopShell() |
| 478 return None, Results.output, True | 428 return None, Results.output, True |
| 479 return None, Results.output, False | 429 return None, Results.output, False |
| OLD | NEW |