| OLD | NEW |
| (Empty) |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import base64 | |
| 6 import logging | |
| 7 import urlparse | |
| 8 | |
| 9 from metrics import chrome_proxy | |
| 10 from metrics import loading | |
| 11 from telemetry.core import util | |
| 12 from telemetry.page import page_measurement | |
| 13 | |
| 14 | |
| 15 class ChromeProxyLatency(page_measurement.PageMeasurement): | |
| 16 """Chrome proxy latency measurement.""" | |
| 17 | |
| 18 def __init__(self, *args, **kwargs): | |
| 19 super(ChromeProxyLatency, self).__init__(*args, **kwargs) | |
| 20 | |
| 21 def WillNavigateToPage(self, page, tab): | |
| 22 tab.ClearCache(force=True) | |
| 23 | |
| 24 def MeasurePage(self, page, tab, results): | |
| 25 # Wait for the load event. | |
| 26 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300) | |
| 27 loading.LoadingMetric().AddResults(tab, results) | |
| 28 | |
| 29 | |
| 30 class ChromeProxyDataSaving(page_measurement.PageMeasurement): | |
| 31 """Chrome proxy data daving measurement.""" | |
| 32 def __init__(self, *args, **kwargs): | |
| 33 super(ChromeProxyDataSaving, self).__init__(*args, **kwargs) | |
| 34 self._metrics = chrome_proxy.ChromeProxyMetric() | |
| 35 | |
| 36 def WillNavigateToPage(self, page, tab): | |
| 37 tab.ClearCache(force=True) | |
| 38 self._metrics.Start(page, tab) | |
| 39 | |
| 40 def MeasurePage(self, page, tab, results): | |
| 41 # Wait for the load event. | |
| 42 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300) | |
| 43 self._metrics.Stop(page, tab) | |
| 44 self._metrics.AddResultsForDataSaving(tab, results) | |
| 45 | |
| 46 | |
| 47 class ChromeProxyValidation(page_measurement.PageMeasurement): | |
| 48 """Base class for all chrome proxy correctness measurements.""" | |
| 49 | |
| 50 def __init__(self, restart_after_each_page=False): | |
| 51 super(ChromeProxyValidation, self).__init__( | |
| 52 needs_browser_restart_after_each_page=restart_after_each_page) | |
| 53 self._metrics = chrome_proxy.ChromeProxyMetric() | |
| 54 self._page = None | |
| 55 # Whether a timeout exception is expected during the test. | |
| 56 self._expect_timeout = False | |
| 57 | |
| 58 def CustomizeBrowserOptions(self, options): | |
| 59 # Enable the chrome proxy (data reduction proxy). | |
| 60 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth') | |
| 61 | |
| 62 def WillNavigateToPage(self, page, tab): | |
| 63 tab.ClearCache(force=True) | |
| 64 assert self._metrics | |
| 65 self._metrics.Start(page, tab) | |
| 66 | |
| 67 def MeasurePage(self, page, tab, results): | |
| 68 self._page = page | |
| 69 # Wait for the load event. | |
| 70 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300) | |
| 71 assert self._metrics | |
| 72 self._metrics.Stop(page, tab) | |
| 73 self.AddResults(tab, results) | |
| 74 | |
| 75 def AddResults(self, tab, results): | |
| 76 raise NotImplementedError | |
| 77 | |
| 78 def StopBrowserAfterPage(self, browser, page): # pylint: disable=W0613 | |
| 79 if hasattr(page, 'restart_after') and page.restart_after: | |
| 80 return True | |
| 81 return False | |
| 82 | |
| 83 def RunNavigateSteps(self, page, tab): | |
| 84 # The redirect from safebrowsing causes a timeout. Ignore that. | |
| 85 try: | |
| 86 super(ChromeProxyValidation, self).RunNavigateSteps(page, tab) | |
| 87 except util.TimeoutException, e: | |
| 88 if self._expect_timeout: | |
| 89 logging.warning('Navigation timeout on page %s', | |
| 90 page.name if page.name else page.url) | |
| 91 else: | |
| 92 raise e | |
| 93 | |
| 94 | |
| 95 class ChromeProxyHeaders(ChromeProxyValidation): | |
| 96 """Correctness measurement for response headers.""" | |
| 97 | |
| 98 def __init__(self): | |
| 99 super(ChromeProxyHeaders, self).__init__(restart_after_each_page=True) | |
| 100 | |
| 101 def AddResults(self, tab, results): | |
| 102 self._metrics.AddResultsForHeaderValidation(tab, results) | |
| 103 | |
| 104 | |
| 105 class ChromeProxyBypass(ChromeProxyValidation): | |
| 106 """Correctness measurement for bypass responses.""" | |
| 107 | |
| 108 def __init__(self): | |
| 109 super(ChromeProxyBypass, self).__init__(restart_after_each_page=True) | |
| 110 | |
| 111 def AddResults(self, tab, results): | |
| 112 self._metrics.AddResultsForBypass(tab, results) | |
| 113 | |
| 114 | |
| 115 class ChromeProxySafebrowsing(ChromeProxyValidation): | |
| 116 """Correctness measurement for safebrowsing.""" | |
| 117 | |
| 118 def __init__(self): | |
| 119 super(ChromeProxySafebrowsing, self).__init__() | |
| 120 | |
| 121 def WillNavigateToPage(self, page, tab): | |
| 122 super(ChromeProxySafebrowsing, self).WillNavigateToPage(page, tab) | |
| 123 self._expect_timeout = True | |
| 124 | |
| 125 def AddResults(self, tab, results): | |
| 126 self._metrics.AddResultsForSafebrowsing(tab, results) | |
| 127 | |
| 128 | |
| 129 _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff' | |
| 130 _TEST_SERVER = 'chromeproxy-test.appspot.com' | |
| 131 _TEST_SERVER_DEFAULT_URL = 'http://' + _TEST_SERVER + '/default' | |
| 132 | |
| 133 | |
| 134 # We rely on the chromeproxy-test server to facilitate some of the tests. | |
| 135 # The test server code is at <TBD location> and runs at _TEST_SERVER | |
| 136 # | |
| 137 # The test server allow request to override response status, headers, and | |
| 138 # body through query parameters. See GetResponseOverrideURL. | |
| 139 def GetResponseOverrideURL(url, respStatus=0, respHeader="", respBody=""): | |
| 140 """ Compose the request URL with query parameters to override | |
| 141 the chromeproxy-test server response. | |
| 142 """ | |
| 143 | |
| 144 queries = [] | |
| 145 if respStatus > 0: | |
| 146 queries.append('respStatus=%d' % respStatus) | |
| 147 if respHeader: | |
| 148 queries.append('respHeader=%s' % base64.b64encode(respHeader)) | |
| 149 if respBody: | |
| 150 queries.append('respBody=%s' % base64.b64encode(respBody)) | |
| 151 if len(queries) == 0: | |
| 152 return url | |
| 153 "&".join(queries) | |
| 154 # url has query already | |
| 155 if urlparse.urlparse(url).query: | |
| 156 return url + '&' + "&".join(queries) | |
| 157 else: | |
| 158 return url + '?' + "&".join(queries) | |
| 159 | |
| 160 | |
| 161 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation): | |
| 162 """Correctness measurement for proxy fallback. | |
| 163 | |
| 164 In this test, the probe URL does not return 'OK'. Chrome is expected | |
| 165 to use the fallback proxy. | |
| 166 """ | |
| 167 | |
| 168 def __init__(self): | |
| 169 super(ChromeProxyHTTPFallbackProbeURL, self).__init__() | |
| 170 | |
| 171 def CustomizeBrowserOptions(self, options): | |
| 172 super(ChromeProxyHTTPFallbackProbeURL, | |
| 173 self).CustomizeBrowserOptions(options) | |
| 174 # Use the test server probe URL which returns the response | |
| 175 # body as specified by respBody. | |
| 176 probe_url = GetResponseOverrideURL( | |
| 177 _TEST_SERVER_DEFAULT_URL, | |
| 178 respBody='not OK') | |
| 179 options.AppendExtraBrowserArgs( | |
| 180 '--data-reduction-proxy-probe-url=%s' % probe_url) | |
| 181 | |
| 182 def AddResults(self, tab, results): | |
| 183 self._metrics.AddResultsForHTTPFallback(tab, results) | |
| 184 | |
| 185 | |
| 186 # Depends on the fix of http://crbug.com/330342. | |
| 187 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation): | |
| 188 """Correctness measurement for proxy fallback. | |
| 189 | |
| 190 In this test, the configured proxy is the chromeproxy-test server which | |
| 191 will send back a response without the expected Via header. Chrome is | |
| 192 expected to use the fallback proxy and add the configured proxy to the | |
| 193 bad proxy list. | |
| 194 """ | |
| 195 | |
| 196 def __init__(self): | |
| 197 super(ChromeProxyHTTPFallbackViaHeader, self).__init__() | |
| 198 | |
| 199 def CustomizeBrowserOptions(self, options): | |
| 200 super(ChromeProxyHTTPFallbackViaHeader, | |
| 201 self).CustomizeBrowserOptions(options) | |
| 202 options.AppendExtraBrowserArgs('--ignore-certificate-errors') | |
| 203 options.AppendExtraBrowserArgs( | |
| 204 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER) | |
| 205 options.AppendExtraBrowserArgs( | |
| 206 '--spdy-proxy-auth-value=%s' % _FAKE_PROXY_AUTH_VALUE) | |
| 207 | |
| 208 def AddResults(self, tab, results): | |
| 209 proxies = [ | |
| 210 _TEST_SERVER + ":80", | |
| 211 self._metrics.effective_proxies['fallback'], | |
| 212 self._metrics.effective_proxies['direct']] | |
| 213 bad_proxies = [_TEST_SERVER + ":80"] | |
| 214 self._metrics.AddResultsForHTTPFallback(tab, results, proxies, bad_proxies) | |
| 215 | |
| 216 | |
| 217 class ChromeProxySmoke(ChromeProxyValidation): | |
| 218 """Smoke measurement for basic chrome proxy correctness.""" | |
| 219 | |
| 220 def __init__(self): | |
| 221 super(ChromeProxySmoke, self).__init__() | |
| 222 | |
| 223 def WillNavigateToPage(self, page, tab): | |
| 224 super(ChromeProxySmoke, self).WillNavigateToPage(page, tab) | |
| 225 if page.name == 'safebrowsing': | |
| 226 self._expect_timeout = True | |
| 227 | |
| 228 def AddResults(self, tab, results): | |
| 229 # Map a page name to its AddResults func. | |
| 230 page_to_metrics = { | |
| 231 'header validation': [self._metrics.AddResultsForHeaderValidation], | |
| 232 'compression: image': [ | |
| 233 self._metrics.AddResultsForHeaderValidation, | |
| 234 self._metrics.AddResultsForDataSaving, | |
| 235 ], | |
| 236 'compression: javascript': [ | |
| 237 self._metrics.AddResultsForHeaderValidation, | |
| 238 self._metrics.AddResultsForDataSaving, | |
| 239 ], | |
| 240 'compression: css': [ | |
| 241 self._metrics.AddResultsForHeaderValidation, | |
| 242 self._metrics.AddResultsForDataSaving, | |
| 243 ], | |
| 244 'bypass': [self._metrics.AddResultsForBypass], | |
| 245 'safebrowsing': [self._metrics.AddResultsForSafebrowsing], | |
| 246 } | |
| 247 if not self._page.name in page_to_metrics: | |
| 248 raise page_measurement.MeasurementFailure( | |
| 249 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % ( | |
| 250 self._page.name, page_to_metrics.keys())) | |
| 251 for add_result in page_to_metrics[self._page.name]: | |
| 252 add_result(tab, results) | |
| OLD | NEW |