Remove ExtensionPrefs::SetDidExtensionEscalatePermissions.
[chromium-blink-merge.git] / tools / chrome_proxy / integration_tests / chrome_proxy_measurements.py
blob69d88d04ef6a1a0613bdf60f2de2498f9036c1e9
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.
5 import base64
6 import logging
7 import urlparse
9 from common.chrome_proxy_measurements import ChromeProxyValidation
10 from integration_tests import chrome_proxy_metrics as metrics
11 from metrics import loading
12 from telemetry.core import exceptions
13 from telemetry.page import page_test
16 class ChromeProxyDataSaving(page_test.PageTest):
17 """Chrome proxy data saving measurement."""
18 def __init__(self, *args, **kwargs):
19 super(ChromeProxyDataSaving, self).__init__(*args, **kwargs)
20 self._metrics = metrics.ChromeProxyMetric()
21 self._enable_proxy = True
23 def CustomizeBrowserOptions(self, options):
24 if self._enable_proxy:
25 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
27 def WillNavigateToPage(self, page, tab):
28 tab.ClearCache(force=True)
29 self._metrics.Start(page, tab)
31 def ValidateAndMeasurePage(self, page, tab, results):
32 # Wait for the load event.
33 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
34 self._metrics.Stop(page, tab)
35 self._metrics.AddResultsForDataSaving(tab, results)
38 class ChromeProxyHeaders(ChromeProxyValidation):
39 """Correctness measurement for response headers."""
41 def __init__(self):
42 super(ChromeProxyHeaders, self).__init__(
43 restart_after_each_page=True,
44 metrics=metrics.ChromeProxyMetric())
46 def AddResults(self, tab, results):
47 self._metrics.AddResultsForHeaderValidation(tab, results)
50 class ChromeProxyBypass(ChromeProxyValidation):
51 """Correctness measurement for bypass responses."""
53 def __init__(self):
54 super(ChromeProxyBypass, self).__init__(
55 restart_after_each_page=True,
56 metrics=metrics.ChromeProxyMetric())
58 def AddResults(self, tab, results):
59 self._metrics.AddResultsForBypass(tab, results)
62 class ChromeProxyCorsBypass(ChromeProxyValidation):
63 """Correctness measurement for bypass responses for CORS requests."""
65 def __init__(self):
66 super(ChromeProxyCorsBypass, self).__init__(
67 restart_after_each_page=True,
68 metrics=metrics.ChromeProxyMetric())
70 def ValidateAndMeasurePage(self, page, tab, results):
71 # The test page sets window.xhrRequestCompleted to true when the XHR fetch
72 # finishes.
73 tab.WaitForJavaScriptExpression('window.xhrRequestCompleted', 300)
74 super(ChromeProxyCorsBypass,
75 self).ValidateAndMeasurePage(page, tab, results)
77 def AddResults(self, tab, results):
78 self._metrics.AddResultsForCorsBypass(tab, results)
81 class ChromeProxyBlockOnce(ChromeProxyValidation):
82 """Correctness measurement for block-once responses."""
84 def __init__(self):
85 super(ChromeProxyBlockOnce, self).__init__(
86 restart_after_each_page=True,
87 metrics=metrics.ChromeProxyMetric())
89 def AddResults(self, tab, results):
90 self._metrics.AddResultsForBlockOnce(tab, results)
93 class ChromeProxySafebrowsingOn(ChromeProxyValidation):
94 """Correctness measurement for safebrowsing."""
96 def __init__(self):
97 super(ChromeProxySafebrowsingOn, self).__init__(
98 metrics=metrics.ChromeProxyMetric())
100 def AddResults(self, tab, results):
101 self._metrics.AddResultsForSafebrowsingOn(tab, results)
103 class ChromeProxySafebrowsingOff(ChromeProxyValidation):
104 """Correctness measurement for safebrowsing."""
106 def __init__(self):
107 super(ChromeProxySafebrowsingOff, self).__init__(
108 metrics=metrics.ChromeProxyMetric())
110 def AddResults(self, tab, results):
111 self._metrics.AddResultsForSafebrowsingOff(tab, results)
113 _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff'
114 _TEST_SERVER = 'chromeproxy-test.appspot.com'
115 _TEST_SERVER_DEFAULT_URL = 'http://' + _TEST_SERVER + '/default'
118 # We rely on the chromeproxy-test server to facilitate some of the tests.
119 # The test server code is at <TBD location> and runs at _TEST_SERVER
121 # The test server allow request to override response status, headers, and
122 # body through query parameters. See GetResponseOverrideURL.
123 def GetResponseOverrideURL(url=_TEST_SERVER_DEFAULT_URL, respStatus=0,
124 respHeader="", respBody=""):
125 """ Compose the request URL with query parameters to override
126 the chromeproxy-test server response.
129 queries = []
130 if respStatus > 0:
131 queries.append('respStatus=%d' % respStatus)
132 if respHeader:
133 queries.append('respHeader=%s' % base64.b64encode(respHeader))
134 if respBody:
135 queries.append('respBody=%s' % base64.b64encode(respBody))
136 if len(queries) == 0:
137 return url
138 "&".join(queries)
139 # url has query already
140 if urlparse.urlparse(url).query:
141 return url + '&' + "&".join(queries)
142 else:
143 return url + '?' + "&".join(queries)
146 class ChromeProxyHTTPFallbackProbeURL(ChromeProxyValidation):
147 """Correctness measurement for proxy fallback.
149 In this test, the probe URL does not return 'OK'. Chrome is expected
150 to use the fallback proxy.
153 def __init__(self):
154 super(ChromeProxyHTTPFallbackProbeURL, self).__init__(
155 restart_after_each_page=True,
156 metrics=metrics.ChromeProxyMetric())
158 def CustomizeBrowserOptions(self, options):
159 super(ChromeProxyHTTPFallbackProbeURL,
160 self).CustomizeBrowserOptions(options)
161 # Set the secure proxy check URL to the google.com favicon, which will be
162 # interpreted as a secure proxy check failure since the response body is not
163 # "OK". The google.com favicon is used because it will load reliably fast,
164 # and there have been problems with chromeproxy-test.appspot.com being slow
165 # and causing tests to flake.
166 options.AppendExtraBrowserArgs(
167 '--data-reduction-proxy-secure-proxy-check-url='
168 'http://www.google.com/favicon.ico')
170 def AddResults(self, tab, results):
171 self._metrics.AddResultsForHTTPFallback(tab, results)
174 class ChromeProxyHTTPFallbackViaHeader(ChromeProxyValidation):
175 """Correctness measurement for proxy fallback.
177 In this test, the configured proxy is the chromeproxy-test server which
178 will send back a response without the expected Via header. Chrome is
179 expected to use the fallback proxy and add the configured proxy to the
180 bad proxy list.
183 def __init__(self):
184 super(ChromeProxyHTTPFallbackViaHeader, self).__init__(
185 restart_after_each_page=True,
186 metrics=metrics.ChromeProxyMetric())
188 def CustomizeBrowserOptions(self, options):
189 super(ChromeProxyHTTPFallbackViaHeader,
190 self).CustomizeBrowserOptions(options)
191 options.AppendExtraBrowserArgs('--ignore-certificate-errors')
192 options.AppendExtraBrowserArgs(
193 '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER)
195 def AddResults(self, tab, results):
196 self._metrics.AddResultsForHTTPFallback(tab, results)
199 class ChromeProxyClientVersion(ChromeProxyValidation):
200 """Correctness measurement for version directives in Chrome-Proxy header.
202 The test verifies that the version information provided in the Chrome-Proxy
203 request header overrides any version, if specified, that is provided in the
204 user agent string.
207 def __init__(self):
208 super(ChromeProxyClientVersion, self).__init__(
209 metrics=metrics.ChromeProxyMetric())
211 def CustomizeBrowserOptions(self, options):
212 super(ChromeProxyClientVersion,
213 self).CustomizeBrowserOptions(options)
214 options.AppendExtraBrowserArgs('--user-agent="Chrome/32.0.1700.99"')
216 def AddResults(self, tab, results):
217 self._metrics.AddResultsForClientVersion(tab, results)
220 class ChromeProxyClientType(ChromeProxyValidation):
221 """Correctness measurement for Chrome-Proxy header client type directives."""
223 def __init__(self):
224 super(ChromeProxyClientType, self).__init__(
225 restart_after_each_page=True,
226 metrics=metrics.ChromeProxyMetric())
227 self._chrome_proxy_client_type = None
229 def AddResults(self, tab, results):
230 # Get the Chrome-Proxy client type from the first page in the page set, so
231 # that the client type value can be used to determine which of the later
232 # pages in the page set should be bypassed.
233 if not self._chrome_proxy_client_type:
234 client_type = self._metrics.GetClientTypeFromRequests(tab)
235 if client_type:
236 self._chrome_proxy_client_type = client_type
238 self._metrics.AddResultsForClientType(tab,
239 results,
240 self._chrome_proxy_client_type,
241 self._page.bypass_for_client_type)
244 class ChromeProxyLoFi(ChromeProxyValidation):
245 """Correctness measurement for Lo-Fi in Chrome-Proxy header."""
247 def __init__(self):
248 super(ChromeProxyLoFi, self).__init__(restart_after_each_page=True,
249 metrics=metrics.ChromeProxyMetric())
251 def CustomizeBrowserOptions(self, options):
252 super(ChromeProxyLoFi, self).CustomizeBrowserOptions(options)
253 options.AppendExtraBrowserArgs('--enable-data-reduction-proxy-lo-fi')
255 def AddResults(self, tab, results):
256 self._metrics.AddResultsForLoFi(tab, results)
258 class ChromeProxyExpDirective(ChromeProxyValidation):
259 """Correctness measurement for experiment directives in Chrome-Proxy header.
261 This test verifies that "exp=test" in the Chrome-Proxy request header
262 causes a bypass on the experiment test page.
265 def __init__(self):
266 super(ChromeProxyExpDirective, self).__init__(
267 restart_after_each_page=True,
268 metrics=metrics.ChromeProxyMetric())
270 def CustomizeBrowserOptions(self, options):
271 super(ChromeProxyExpDirective, self).CustomizeBrowserOptions(options)
272 options.AppendExtraBrowserArgs('--data-reduction-proxy-experiment=test')
274 def AddResults(self, tab, results):
275 self._metrics.AddResultsForBypass(tab, results, url_pattern='/exptest/')
277 class ChromeProxyPassThrough(ChromeProxyValidation):
278 """Correctness measurement for Chrome-Proxy pass-through directives.
280 This test verifies that "pass-through" in the Chrome-Proxy request header
281 causes a resource to be loaded without Data Reduction Proxy transformations.
284 def __init__(self):
285 super(ChromeProxyPassThrough, self).__init__(
286 restart_after_each_page=True,
287 metrics=metrics.ChromeProxyMetric())
289 def CustomizeBrowserOptions(self, options):
290 super(ChromeProxyPassThrough, self).CustomizeBrowserOptions(options)
292 def AddResults(self, tab, results):
293 self._metrics.AddResultsForPassThrough(tab, results)
295 class ChromeProxyHTTPToDirectFallback(ChromeProxyValidation):
296 """Correctness measurement for HTTP proxy fallback to direct."""
298 def __init__(self):
299 super(ChromeProxyHTTPToDirectFallback, self).__init__(
300 restart_after_each_page=True,
301 metrics=metrics.ChromeProxyMetric())
303 def CustomizeBrowserOptions(self, options):
304 super(ChromeProxyHTTPToDirectFallback,
305 self).CustomizeBrowserOptions(options)
306 # Set the primary proxy to something that will fail to be resolved so that
307 # this test will run using the HTTP fallback proxy.
308 options.AppendExtraBrowserArgs(
309 '--spdy-proxy-auth-origin=http://nonexistent.googlezip.net')
311 def WillNavigateToPage(self, page, tab):
312 super(ChromeProxyHTTPToDirectFallback, self).WillNavigateToPage(page, tab)
313 # Attempt to load a page through the nonexistent primary proxy in order to
314 # cause a proxy fallback, and have this test run starting from the HTTP
315 # fallback proxy.
316 tab.Navigate(_TEST_SERVER_DEFAULT_URL)
317 tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
319 def AddResults(self, tab, results):
320 self._metrics.AddResultsForHTTPToDirectFallback(tab, results, _TEST_SERVER)
323 class ChromeProxyReenableAfterBypass(ChromeProxyValidation):
324 """Correctness measurement for re-enabling proxies after bypasses.
326 This test loads a page that causes all data reduction proxies to be bypassed
327 for 1 to 5 minutes, then waits 5 minutes and verifies that the proxy is no
328 longer bypassed.
331 def __init__(self):
332 super(ChromeProxyReenableAfterBypass, self).__init__(
333 restart_after_each_page=True,
334 metrics=metrics.ChromeProxyMetric())
336 def AddResults(self, tab, results):
337 self._metrics.AddResultsForReenableAfterBypass(
338 tab, results, self._page.bypass_seconds_min,
339 self._page.bypass_seconds_max)
342 class ChromeProxySmoke(ChromeProxyValidation):
343 """Smoke measurement for basic chrome proxy correctness."""
345 def __init__(self):
346 super(ChromeProxySmoke, self).__init__(restart_after_each_page=True,
347 metrics=metrics.ChromeProxyMetric())
349 def WillNavigateToPage(self, page, tab):
350 super(ChromeProxySmoke, self).WillNavigateToPage(page, tab)
352 def AddResults(self, tab, results):
353 # Map a page name to its AddResults func.
354 page_to_metrics = {
355 'header validation': [self._metrics.AddResultsForHeaderValidation],
356 'compression: image': [
357 self._metrics.AddResultsForHeaderValidation,
358 self._metrics.AddResultsForDataSaving,
360 'compression: javascript': [
361 self._metrics.AddResultsForHeaderValidation,
362 self._metrics.AddResultsForDataSaving,
364 'compression: css': [
365 self._metrics.AddResultsForHeaderValidation,
366 self._metrics.AddResultsForDataSaving,
368 'bypass': [self._metrics.AddResultsForBypass],
370 if not self._page.name in page_to_metrics:
371 raise page_test.MeasurementFailure(
372 'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
373 self._page.name, page_to_metrics.keys()))
374 for add_result in page_to_metrics[self._page.name]:
375 add_result(tab, results)
378 PROXIED = metrics.PROXIED
379 DIRECT = metrics.DIRECT
381 class ChromeProxyVideoValidation(page_test.PageTest):
382 """Validation for video pages.
384 Measures pages using metrics.ChromeProxyVideoMetric. Pages can be fetched
385 either direct from the origin server or via the proxy. If a page is fetched
386 both ways, then the PROXIED and DIRECT measurements are compared to ensure
387 the same video was loaded in both cases.
390 def __init__(self):
391 super(ChromeProxyVideoValidation, self).__init__(
392 needs_browser_restart_after_each_page=True,
393 clear_cache_before_each_run=True)
394 # The type is _allMetrics[url][PROXIED,DIRECT][metricName] = value,
395 # where (metricName,value) is a metric computed by videowrapper.js.
396 self._allMetrics = {}
398 def CustomizeBrowserOptionsForSinglePage(self, page, options):
399 if page.use_chrome_proxy:
400 options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
401 options.AppendExtraBrowserArgs('--data-reduction-proxy-experiment=video')
403 def DidNavigateToPage(self, page, tab):
404 self._currMetrics = metrics.ChromeProxyVideoMetric(tab)
405 self._currMetrics.Start(page, tab)
407 def ValidateAndMeasurePage(self, page, tab, results):
408 assert self._currMetrics
409 self._currMetrics.Stop(page, tab)
410 if page.url not in self._allMetrics:
411 self._allMetrics[page.url] = {}
413 # Verify this page.
414 if page.use_chrome_proxy:
415 self._currMetrics.AddResultsForProxied(tab, results)
416 self._allMetrics[page.url][PROXIED] = self._currMetrics.videoMetrics
417 else:
418 self._currMetrics.AddResultsForDirect(tab, results)
419 self._allMetrics[page.url][DIRECT] = self._currMetrics.videoMetrics
420 self._currMetrics = None
422 # Compare proxied and direct results for this url, if they exist.
423 m = self._allMetrics[page.url]
424 if PROXIED in m and DIRECT in m:
425 self._CompareProxiedAndDirectMetrics(page.url, m[PROXIED], m[DIRECT])
427 def _CompareProxiedAndDirectMetrics(self, url, pm, dm):
428 """Compare metrics from PROXIED and DIRECT fetches.
430 Compares video metrics computed by videowrapper.js for pages that were
431 fetch both PROXIED and DIRECT.
433 Args:
434 url: The url for the page being tested.
435 pm: Metrics when loaded by the Flywheel proxy.
436 dm: Metrics when loaded directly from the origin server.
438 Raises:
439 ChromeProxyMetricException on failure.
441 def err(s):
442 raise ChromeProxyMetricException, s
444 if not pm['ready']:
445 err('Proxied page did not load video: %s' % page.url)
446 if not dm['ready']:
447 err('Direct page did not load video: %s' % page.url)
449 # Compare metrics that should match for PROXIED and DIRECT.
450 for x in ('video_height', 'video_width', 'video_duration',
451 'decoded_frames'):
452 if x not in pm:
453 err('Proxied page has no %s: %s' % (x, page.url))
454 if x not in dm:
455 err('Direct page has no %s: %s' % (x, page.url))
456 if pm[x] != dm[x]:
457 err('Mismatch for %s (proxied=%s direct=%s): %s' %
458 (x, str(pm[x]), str(dm[x]), page.url))
460 # Proxied XOCL should match direct CL.
461 pxocl = pm['x_original_content_length_header']
462 dcl = dm['content_length_header']
463 if pxocl != dcl:
464 err('Mismatch for content length (proxied=%s direct=%s): %s' %
465 (str(pxocl), str(dcl), page.url))