# Copyright 2020 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Utilities for setting up and tear down WPR and TsProxy service.""" from py_utils import ts_proxy_server from py_utils import webpagereplay_go_server from devil.android import forwarder PROXY_HOST_IP = '127.0.0.1' # From Catapult/WebPageReplay document. IGNORE_CERT_ERROR_SPKI_LIST = 'PhrPvGIaAMmd29hj8BCZOq096yj7uMpRNHpn5PDxI6I=' PROXY_SERVER = 'socks5://localhost' DEFAULT_DEVICE_PORT = 1080 DEFAULT_ROUND_TRIP_LATENCY_MS = 100 DEFAULT_DOWNLOAD_BANDWIDTH_KBPS = 72000 DEFAULT_UPLOAD_BANDWIDTH_KBPS = 72000 class WPRServer: """Utils to set up a webpagereplay_go_server instance.""" def __init__(self): self._archive_path = None self._host_http_port = 0 self._host_https_port = 0 self._record_mode = False self._server = None def StartServer(self, wpr_archive_path): """Starts a webpagereplay_go_server instance.""" if wpr_archive_path == self._archive_path and self._server: # Reuse existing webpagereplay_go_server instance. return if self._server: self.StopServer() replay_options = [] if self._record_mode: replay_options.append('--record') ports = {} if not self._server: self._server = webpagereplay_go_server.ReplayServer( wpr_archive_path, PROXY_HOST_IP, http_port=self._host_http_port, https_port=self._host_https_port, replay_options=replay_options) self._archive_path = wpr_archive_path ports = self._server.StartServer() self._host_http_port = ports['http'] self._host_https_port = ports['https'] def StopServer(self): """Stops the webpagereplay_go_server instance and resets archive.""" self._server.StopServer() self._server = None self._host_http_port = 0 self._host_https_port = 0 @staticmethod def SetServerBinaryPath(go_binary_path): """Sets the go_binary_path for webpagereplay_go_server.ReplayServer.""" webpagereplay_go_server.ReplayServer.SetGoBinaryPath(go_binary_path) @property def record_mode(self): return self._record_mode @record_mode.setter def record_mode(self, value): self._record_mode = value @property def http_port(self): return self._host_http_port @property def https_port(self): return self._host_https_port @property def archive_path(self): return self._archive_path class ChromeProxySession: """Utils to help set up a Chrome Proxy.""" def __init__(self, device_proxy_port=DEFAULT_DEVICE_PORT): self._device_proxy_port = device_proxy_port self._ts_proxy_server = ts_proxy_server.TsProxyServer(PROXY_HOST_IP) self._wpr_server = WPRServer() @property def wpr_record_mode(self): """Returns whether this proxy session was running in record mode.""" return self._wpr_server.record_mode @wpr_record_mode.setter def wpr_record_mode(self, value): self._wpr_server.record_mode = value @property def wpr_replay_mode(self): """Returns whether this proxy session was running in replay mode.""" return not self._wpr_server.record_mode @property def wpr_archive_path(self): """Returns the wpr archive file path used in this proxy session.""" return self._wpr_server.archive_path @property def device_proxy_port(self): return self._device_proxy_port def GetFlags(self): """Gets the chrome command line flags to be needed by ChromeProxySession.""" extra_flags = [] extra_flags.append('--ignore-certificate-errors-spki-list=%s' % IGNORE_CERT_ERROR_SPKI_LIST) extra_flags.append('--proxy-server=%s:%s' % (PROXY_SERVER, self._device_proxy_port)) return extra_flags @staticmethod def SetWPRServerBinary(go_binary_path): """Sets the WPR server go_binary_path.""" WPRServer.SetServerBinaryPath(go_binary_path) def Start(self, device, wpr_archive_path): """Starts the wpr_server as well as the ts_proxy server and setups env. Args: device: A DeviceUtils instance. wpr_archive_path: A abs path to the wpr archive file. """ self._wpr_server.StartServer(wpr_archive_path) self._ts_proxy_server.StartServer() # Maps device port to host port forwarder.Forwarder.Map( [(self._device_proxy_port, self._ts_proxy_server.port)], device) # Maps tsProxy port to wpr http/https ports self._ts_proxy_server.UpdateOutboundPorts( http_port=self._wpr_server.http_port, https_port=self._wpr_server.https_port) self._ts_proxy_server.UpdateTrafficSettings( round_trip_latency_ms=DEFAULT_ROUND_TRIP_LATENCY_MS, download_bandwidth_kbps=DEFAULT_DOWNLOAD_BANDWIDTH_KBPS, upload_bandwidth_kbps=DEFAULT_UPLOAD_BANDWIDTH_KBPS) def Stop(self, device): """Stops the wpr_server, and ts_proxy server and tears down env. Note that Stop does not reset wpr_record_mode, wpr_replay_mode, wpr_archive_path property. Args: device: A DeviceUtils instance. """ self._wpr_server.StopServer() self._ts_proxy_server.StopServer() forwarder.Forwarder.UnmapDevicePort(self._device_proxy_port, device)