Chromium Code Reviews| Index: tools/perf/metrics/chrome_proxy.py |
| diff --git a/tools/perf/metrics/chrome_proxy.py b/tools/perf/metrics/chrome_proxy.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..234002d34c1a0faedf58bca275c42cbcf5b40330 |
| --- /dev/null |
| +++ b/tools/perf/metrics/chrome_proxy.py |
| @@ -0,0 +1,128 @@ |
| +# Copyright 2014 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +from telemetry.page import page_measurement |
| +from metrics import network |
| + |
| + |
| +class ChromeProxyMetricException(page_measurement.MeasurementFailure): |
| + pass |
|
bengr
2014/03/26 22:45:55
Shouldn't this have an implementation?
bolian
2014/03/27 00:43:32
No, it will just take an error message when thrown
|
| + |
| + |
| +CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' |
| +CHROME_PROXY_VIA_HEADER_OLD = '1.1 Chrome Compression Proxy' |
|
bengr
2014/03/26 22:45:55
OLD -> DEPRECATED
bolian
2014/03/27 00:43:32
Done.
|
| + |
| + |
| +class ChromeProxyResponse(network.HTTPResponse): |
| + """ Represents an HTTP response from a timeleine event.""" |
| + def __init__(self, event): |
| + super(ChromeProxyResponse, self).__init__(event) |
| + |
| + def ShouldHaveChromeProxyViaHeader(self): |
| + resp = self.response |
| + # Ignore https and data url |
| + if resp.url.startswith('https') or resp.url.startswith('data:'): |
|
bengr
2014/03/26 22:45:55
Is there any way to do something similar for incog
bolian
2014/03/27 00:43:32
Not sure how to know it is incognito from Telemetr
|
| + return False |
| + # Ignore 304 Not Modified. |
| + if resp.status == 304: |
| + return False |
| + return True |
| + |
| + def HasChromeProxyViaHeader(self): |
| + via_header = self.response.GetHeader('Via') |
| + if not via_header: |
| + return False |
| + vias = [v.strip(' ') for v in via_header.split(',')] |
| + # The Via header is valid if it is the old format or the new format |
| + # with 4-character version prefix, for example, |
| + # "1.1 Chrome-Compression-Proxy". |
| + return (CHROME_PROXY_VIA_HEADER_OLD in vias or |
| + any(v[4:] == CHROME_PROXY_VIA_HEADER for v in vias)) |
| + |
| + def IsValidByViaHeader(self): |
| + return (not self.ShouldHaveChromeProxyViaHeader() or |
| + self.HasChromeProxyViaHeader()) |
| + |
| + def IsSafebrowsingResponse(self): |
| + if (self.response.status == 307 and |
| + self.response.GetHeader('X-Malware-Url') == '1' and |
| + self.IsValidByViaHeader() and |
| + self.response.GetHeader('Location') == self.response.url): |
| + return True |
| + return False |
| + |
| + |
| +class ChromeProxyMetric(network.NetworkMetric): |
| + """A Chrome proxy timeline metric.""" |
| + |
| + def __init__(self): |
| + super(ChromeProxyMetric, self).__init__() |
| + self.compute_data_saving = True |
| + |
| + def ResponseFromEvent(self, event): |
| + return ChromeProxyResponse(event) |
| + |
| + def AddResults(self, tab, results): |
| + raise NotImplementedError |
| + |
| + def AddResultsForDataSaving(self, tab, results): |
| + resources_via_proxy = 0 |
| + resources_from_cache = 0 |
| + resources_direct = 0 |
| + |
| + super(ChromeProxyMetric, self).AddResults(tab, results) |
| + for resp in self.IterResponses(tab): |
| + if resp.response.served_from_cache: |
| + resources_from_cache += 1 |
| + if resp.HasChromeProxyViaHeader(): |
| + resources_via_proxy += 1 |
| + else: |
| + resources_direct += 1 |
| + |
| + results.Add('resources_via_proxy', 'count', resources_via_proxy) |
| + results.Add('resources_from_cache', 'count', resources_from_cache) |
| + results.Add('resources_direct', 'count', resources_direct) |
| + |
| + def AddResultsForHeaderValidation(self, tab, results): |
| + via_count = 0 |
| + for resp in self.IterResponses(tab): |
| + if resp.IsValidByViaHeader(): |
| + via_count += 1 |
| + else: |
| + r = resp.response |
| + raise ChromeProxyMetricException, ( |
| + '%s: Via header (%s) is not valid (refer=%s, status=%d)' % ( |
| + r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status)) |
| + results.Add('checked_via_header', 'count', via_count) |
| + |
| + def AddResultsForBypass(self, tab, results): |
| + bypass_count = 0 |
| + for resp in self.IterResponses(tab): |
| + if resp.HasChromeProxyViaHeader(): |
| + r = resp.response |
| + raise ChromeProxyMetricException, ( |
| + '%s: Should not have Via header (%s) (refer=%s, status=%d)' % ( |
| + r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status)) |
| + bypass_count += 1 |
| + results.Add('bypass', 'count', bypass_count) |
| + |
| + def AddResultsForSafebrowsing(self, tab, results): |
| + count = 0 |
| + safebrowsing_count = 0 |
| + for resp in self.IterResponses(tab): |
| + count += 1 |
| + if resp.IsSafebrowsingResponse(): |
| + safebrowsing_count += 1 |
| + else: |
| + r = resp.response |
| + raise ChromeProxyMetricException, ( |
| + '%s: Not a valid safe browsing response.\n' |
| + 'Reponse: status=(%d, %s)\nHeaders:\n %s' % ( |
| + r.url, r.status, r.status_text, r.headers)) |
| + if count == safebrowsing_count: |
| + results.Add('safebrowsing', 'boolean', True) |
| + else: |
| + raise ChromeProxyMetricException, ( |
| + 'Safebrowsing failed (count=%d, safebrowsing_count=%d)\n' % ( |
| + count, safebrowsing_count)) |