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 |