| 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 logging | 5 import logging |
| 6 import os | 6 import os |
| 7 import shutil | 7 import shutil |
| 8 import tempfile | 8 import tempfile |
| 9 | 9 |
| 10 from telemetry.internal import forwarders |
| 10 from telemetry.internal.util import wpr_server | 11 from telemetry.internal.util import wpr_server |
| 11 from telemetry.internal.util import ts_proxy_server | |
| 12 from telemetry.util import wpr_modes | 12 from telemetry.util import wpr_modes |
| 13 | 13 |
| 14 import certutils | 14 import certutils |
| 15 import platformsettings | 15 import platformsettings |
| 16 | 16 |
| 17 | 17 |
| 18 class ArchiveDoesNotExistError(Exception): | 18 class ArchiveDoesNotExistError(Exception): |
| 19 """Raised when the archive path does not exist for replay mode.""" | 19 """Raised when the archive path does not exist for replay mode.""" |
| 20 pass | 20 pass |
| 21 | 21 |
| 22 | 22 |
| 23 class ReplayAndBrowserPortsError(Exception): | 23 class ReplayAndBrowserPortsError(Exception): |
| 24 """Raised an existing browser would get different remote replay ports.""" | 24 """Raised an existing browser would get different remote replay ports.""" |
| 25 pass | 25 pass |
| 26 | 26 |
| 27 | 27 |
| 28 class NetworkControllerBackend(object): | 28 class NetworkControllerBackend(object): |
| 29 """Control network settings and servers to simulate the Web. | 29 """Control network settings and servers to simulate the Web. |
| 30 | 30 |
| 31 Network changes include forwarding device ports to host platform ports. | 31 Network changes include forwarding device ports to host platform ports. |
| 32 Web Page Replay is used to record and replay HTTP/HTTPS responses. | 32 Web Page Replay is used to record and replay HTTP/HTTPS responses. |
| 33 """ | 33 """ |
| 34 | 34 |
| 35 def __init__(self, platform_backend): | 35 def __init__(self, platform_backend): |
| 36 self._platform_backend = platform_backend | 36 self._platform_backend = platform_backend |
| 37 self._wpr_mode = None | 37 self._wpr_mode = None |
| 38 self._extra_wpr_args = None | 38 self._extra_wpr_args = None |
| 39 self._wpr_port_pairs = None |
| 39 self._archive_path = None | 40 self._archive_path = None |
| 40 self._make_javascript_deterministic = None | 41 self._make_javascript_deterministic = None |
| 41 self._forwarder = None | 42 self._forwarder = None |
| 42 self._wpr_ca_cert_path = None | 43 self._wpr_ca_cert_path = None |
| 43 self._wpr_server = None | 44 self._wpr_server = None |
| 44 self._ts_proxy_server = None | |
| 45 self._port_pair = None | |
| 46 | |
| 47 def InitializeIfNeeded(self): | |
| 48 """ | |
| 49 This may, e.g., install test certificates and perform any needed setup | |
| 50 on the target platform. | |
| 51 | |
| 52 After network interactions are over, clients should call the Close method. | |
| 53 """ | |
| 54 assert bool(self._ts_proxy_server) == bool(self._forwarder) | |
| 55 if self._ts_proxy_server: | |
| 56 return | |
| 57 local_port = self._StartTsProxyServer() | |
| 58 self._forwarder = self._platform_backend.forwarder_factory.Create( | |
| 59 self._platform_backend.GetPortPairForForwarding(local_port)) | |
| 60 | 45 |
| 61 @property | 46 @property |
| 62 def is_open(self): | 47 def is_open(self): |
| 63 return self._wpr_mode is not None | 48 return self._wpr_mode is not None |
| 64 | 49 |
| 65 @property | 50 @property |
| 66 def is_replay_active(self): | 51 def is_replay_active(self): |
| 67 return self._forwarder is not None | 52 return self._forwarder is not None |
| 68 | 53 |
| 69 @property | 54 @property |
| (...skipping 18 matching lines...) Expand all Loading... |
| 88 on the target platform. | 73 on the target platform. |
| 89 | 74 |
| 90 After network interactions are over, clients should call the Close method. | 75 After network interactions are over, clients should call the Close method. |
| 91 | 76 |
| 92 Args: | 77 Args: |
| 93 wpr_mode: a mode for web page replay; available modes are | 78 wpr_mode: a mode for web page replay; available modes are |
| 94 wpr_modes.WPR_OFF, wpr_modes.APPEND, wpr_modes.WPR_REPLAY, or | 79 wpr_modes.WPR_OFF, wpr_modes.APPEND, wpr_modes.WPR_REPLAY, or |
| 95 wpr_modes.WPR_RECORD. | 80 wpr_modes.WPR_RECORD. |
| 96 extra_wpr_args: an list of extra arguments for web page replay. | 81 extra_wpr_args: an list of extra arguments for web page replay. |
| 97 """ | 82 """ |
| 98 self.InitializeIfNeeded() | |
| 99 assert not self.is_open, 'Network controller is already open' | 83 assert not self.is_open, 'Network controller is already open' |
| 100 self._wpr_mode = wpr_mode | 84 self._wpr_mode = wpr_mode |
| 101 self._extra_wpr_args = extra_wpr_args | 85 self._extra_wpr_args = extra_wpr_args |
| 86 self._wpr_port_pairs = self._platform_backend.GetWprPortPairs() |
| 102 self._InstallTestCa() | 87 self._InstallTestCa() |
| 103 | 88 |
| 104 def Close(self): | 89 def Close(self): |
| 105 """Undo changes in the target platform used for network control. | 90 """Undo changes in the target platform used for network control. |
| 106 | 91 |
| 107 Implicitly stops replay if currently active. | 92 Implicitly stops replay if currently active. |
| 108 """ | 93 """ |
| 109 self.StopReplay() | 94 self.StopReplay() |
| 110 self._StopForwarder() | |
| 111 self._StopTsProxyServer() | |
| 112 self._RemoveTestCa() | 95 self._RemoveTestCa() |
| 113 self._make_javascript_deterministic = None | 96 self._make_javascript_deterministic = None |
| 114 self._archive_path = None | 97 self._archive_path = None |
| 98 self._wpr_port_pairs = None |
| 115 self._extra_wpr_args = None | 99 self._extra_wpr_args = None |
| 116 self._wpr_mode = None | 100 self._wpr_mode = None |
| 117 | 101 |
| 118 def _InstallTestCa(self): | 102 def _InstallTestCa(self): |
| 119 if not self._platform_backend.supports_test_ca: | 103 if not self._platform_backend.supports_test_ca: |
| 120 return | 104 return |
| 121 assert not self.is_test_ca_installed, 'Test CA is already installed' | 105 assert not self.is_test_ca_installed, 'Test CA is already installed' |
| 122 if certutils.openssl_import_error: | 106 if certutils.openssl_import_error: |
| 123 logging.warning( | 107 logging.warning( |
| 124 'The OpenSSL module is unavailable. ' | 108 'The OpenSSL module is unavailable. ' |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 raise ArchiveDoesNotExistError( | 182 raise ArchiveDoesNotExistError( |
| 199 'Archive path does not exist: %s' % archive_path) | 183 'Archive path does not exist: %s' % archive_path) |
| 200 if (self._wpr_server is not None and | 184 if (self._wpr_server is not None and |
| 201 self._archive_path == archive_path and | 185 self._archive_path == archive_path and |
| 202 self._make_javascript_deterministic == make_javascript_deterministic): | 186 self._make_javascript_deterministic == make_javascript_deterministic): |
| 203 return # We may reuse the existing replay server. | 187 return # We may reuse the existing replay server. |
| 204 | 188 |
| 205 self._archive_path = archive_path | 189 self._archive_path = archive_path |
| 206 self._make_javascript_deterministic = make_javascript_deterministic | 190 self._make_javascript_deterministic = make_javascript_deterministic |
| 207 local_ports = self._StartReplayServer() | 191 local_ports = self._StartReplayServer() |
| 208 self._ts_proxy_server.UpdateOutboundPorts( | 192 self._StartForwarder(local_ports) |
| 209 http_port=local_ports.http, https_port=local_ports.https) | |
| 210 | |
| 211 def _StopForwarder(self): | |
| 212 if self._forwarder: | |
| 213 self._forwarder.Close() | |
| 214 self._forwarder = None | |
| 215 | 193 |
| 216 def StopReplay(self): | 194 def StopReplay(self): |
| 217 """Stop web page replay. | 195 """Stop web page replay. |
| 218 | 196 |
| 219 Stops both the replay server and the forwarder if currently active. | 197 Stops both the replay server and the forwarder if currently active. |
| 220 """ | 198 """ |
| 199 if self._forwarder: |
| 200 self._forwarder.Close() |
| 201 self._forwarder = None |
| 221 self._StopReplayServer() | 202 self._StopReplayServer() |
| 222 | 203 |
| 223 def _StartReplayServer(self): | 204 def _StartReplayServer(self): |
| 224 """Start the replay server and return the started local_ports.""" | 205 """Start the replay server and return the started local_ports.""" |
| 225 self._StopReplayServer() # In case it was already running. | 206 self._StopReplayServer() # In case it was already running. |
| 207 local_ports = self._wpr_port_pairs.local_ports |
| 226 self._wpr_server = wpr_server.ReplayServer( | 208 self._wpr_server = wpr_server.ReplayServer( |
| 227 self._archive_path, | 209 self._archive_path, |
| 228 self.host_ip, | 210 self.host_ip, |
| 229 http_port=0, | 211 local_ports.http, |
| 230 https_port=0, | 212 local_ports.https, |
| 231 dns_port=None, | 213 local_ports.dns, |
| 232 replay_options=self._ReplayCommandLineArgs()) | 214 self._ReplayCommandLineArgs()) |
| 233 return self._wpr_server.StartServer() | 215 return self._wpr_server.StartServer() |
| 234 | 216 |
| 235 def _StopReplayServer(self): | 217 def _StopReplayServer(self): |
| 236 """Stop the replay server only.""" | 218 """Stop the replay server only.""" |
| 237 if self._wpr_server: | 219 if self._wpr_server: |
| 238 self._wpr_server.StopServer() | 220 self._wpr_server.StopServer() |
| 239 self._wpr_server = None | 221 self._wpr_server = None |
| 240 | 222 |
| 241 def _StopTsProxyServer(self): | |
| 242 """Stop the replay server only.""" | |
| 243 if self._ts_proxy_server: | |
| 244 self._ts_proxy_server.StopServer() | |
| 245 self._ts_proxy_server = None | |
| 246 | |
| 247 def _ReplayCommandLineArgs(self): | 223 def _ReplayCommandLineArgs(self): |
| 248 wpr_args = list(self._extra_wpr_args) | 224 wpr_args = list(self._extra_wpr_args) |
| 249 if self._wpr_mode == wpr_modes.WPR_APPEND: | 225 if self._wpr_mode == wpr_modes.WPR_APPEND: |
| 250 wpr_args.append('--append') | 226 wpr_args.append('--append') |
| 251 elif self._wpr_mode == wpr_modes.WPR_RECORD: | 227 elif self._wpr_mode == wpr_modes.WPR_RECORD: |
| 252 wpr_args.append('--record') | 228 wpr_args.append('--record') |
| 253 if not self._make_javascript_deterministic: | 229 if not self._make_javascript_deterministic: |
| 254 wpr_args.append('--inject_scripts=') | 230 wpr_args.append('--inject_scripts=') |
| 255 if self._wpr_ca_cert_path: | 231 if self._wpr_ca_cert_path: |
| 256 wpr_args.extend([ | 232 wpr_args.extend([ |
| 257 '--should_generate_certs', | 233 '--should_generate_certs', |
| 258 '--https_root_ca_cert_path=%s' % self._wpr_ca_cert_path]) | 234 '--https_root_ca_cert_path=%s' % self._wpr_ca_cert_path]) |
| 259 return wpr_args | 235 return wpr_args |
| 260 | 236 |
| 261 def _StartTsProxyServer(self): | 237 def _StartForwarder(self, local_ports): |
| 262 assert not self._ts_proxy_server, 'ts_proxy_server is already started' | 238 """Start a forwarder from local_ports to the set WPR remote_ports.""" |
| 263 self._ts_proxy_server = ts_proxy_server.TsProxyServer(host_ip=self.host_ip) | 239 if self._forwarder is not None: |
| 264 self._ts_proxy_server.StartServer() | 240 if local_ports == self._forwarder.port_pairs.local_ports: |
| 265 return self._ts_proxy_server.port | 241 return # Safe to reuse existing forwarder. |
| 266 | 242 self._forwarder.Close() |
| 267 @property | 243 self._forwarder = self._platform_backend.forwarder_factory.Create( |
| 268 def forwarder(self): | 244 forwarders.PortPairs.Zip(local_ports, |
| 269 return self._forwarder | 245 self._wpr_port_pairs.remote_ports)) |
| 246 # Override port pairts with values after defaults have been resolved; |
| 247 # we should use the same set of ports when restarting replay. |
| 248 self._wpr_port_pairs = self._forwarder.port_pairs |
| OLD | NEW |