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 from telemetry.page import page_measurement |
| 6 from metrics import network |
| 7 |
| 8 |
| 9 class ChromeProxyMetricException(page_measurement.MeasurementFailure): |
| 10 pass |
| 11 |
| 12 |
| 13 CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' |
| 14 CHROME_PROXY_VIA_HEADER_DEPRECATED = '1.1 Chrome Compression Proxy' |
| 15 |
| 16 |
| 17 class ChromeProxyResponse(network.HTTPResponse): |
| 18 """ Represents an HTTP response from a timeleine event.""" |
| 19 def __init__(self, event): |
| 20 super(ChromeProxyResponse, self).__init__(event) |
| 21 |
| 22 def ShouldHaveChromeProxyViaHeader(self): |
| 23 resp = self.response |
| 24 # Ignore https and data url |
| 25 if resp.url.startswith('https') or resp.url.startswith('data:'): |
| 26 return False |
| 27 # Ignore 304 Not Modified. |
| 28 if resp.status == 304: |
| 29 return False |
| 30 return True |
| 31 |
| 32 def HasChromeProxyViaHeader(self): |
| 33 via_header = self.response.GetHeader('Via') |
| 34 if not via_header: |
| 35 return False |
| 36 vias = [v.strip(' ') for v in via_header.split(',')] |
| 37 # The Via header is valid if it is the old format or the new format |
| 38 # with 4-character version prefix, for example, |
| 39 # "1.1 Chrome-Compression-Proxy". |
| 40 return (CHROME_PROXY_VIA_HEADER_DEPRECATED in vias or |
| 41 any(v[4:] == CHROME_PROXY_VIA_HEADER for v in vias)) |
| 42 |
| 43 def IsValidByViaHeader(self): |
| 44 return (not self.ShouldHaveChromeProxyViaHeader() or |
| 45 self.HasChromeProxyViaHeader()) |
| 46 |
| 47 def IsSafebrowsingResponse(self): |
| 48 if (self.response.status == 307 and |
| 49 self.response.GetHeader('X-Malware-Url') == '1' and |
| 50 self.IsValidByViaHeader() and |
| 51 self.response.GetHeader('Location') == self.response.url): |
| 52 return True |
| 53 return False |
| 54 |
| 55 |
| 56 class ChromeProxyMetric(network.NetworkMetric): |
| 57 """A Chrome proxy timeline metric.""" |
| 58 |
| 59 def __init__(self): |
| 60 super(ChromeProxyMetric, self).__init__() |
| 61 self.compute_data_saving = True |
| 62 |
| 63 def SetEvents(self, events): |
| 64 """Used for unittest.""" |
| 65 self._events = events |
| 66 |
| 67 def ResponseFromEvent(self, event): |
| 68 return ChromeProxyResponse(event) |
| 69 |
| 70 def AddResults(self, tab, results): |
| 71 raise NotImplementedError |
| 72 |
| 73 def AddResultsForDataSaving(self, tab, results): |
| 74 resources_via_proxy = 0 |
| 75 resources_from_cache = 0 |
| 76 resources_direct = 0 |
| 77 |
| 78 super(ChromeProxyMetric, self).AddResults(tab, results) |
| 79 for resp in self.IterResponses(tab): |
| 80 if resp.response.served_from_cache: |
| 81 resources_from_cache += 1 |
| 82 if resp.HasChromeProxyViaHeader(): |
| 83 resources_via_proxy += 1 |
| 84 else: |
| 85 resources_direct += 1 |
| 86 |
| 87 results.Add('resources_via_proxy', 'count', resources_via_proxy) |
| 88 results.Add('resources_from_cache', 'count', resources_from_cache) |
| 89 results.Add('resources_direct', 'count', resources_direct) |
| 90 |
| 91 def AddResultsForHeaderValidation(self, tab, results): |
| 92 via_count = 0 |
| 93 for resp in self.IterResponses(tab): |
| 94 if resp.IsValidByViaHeader(): |
| 95 via_count += 1 |
| 96 else: |
| 97 r = resp.response |
| 98 raise ChromeProxyMetricException, ( |
| 99 '%s: Via header (%s) is not valid (refer=%s, status=%d)' % ( |
| 100 r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status)) |
| 101 results.Add('checked_via_header', 'count', via_count) |
| 102 |
| 103 def AddResultsForBypass(self, tab, results): |
| 104 bypass_count = 0 |
| 105 for resp in self.IterResponses(tab): |
| 106 if resp.HasChromeProxyViaHeader(): |
| 107 r = resp.response |
| 108 raise ChromeProxyMetricException, ( |
| 109 '%s: Should not have Via header (%s) (refer=%s, status=%d)' % ( |
| 110 r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status)) |
| 111 bypass_count += 1 |
| 112 results.Add('bypass', 'count', bypass_count) |
| 113 |
| 114 def AddResultsForSafebrowsing(self, tab, results): |
| 115 count = 0 |
| 116 safebrowsing_count = 0 |
| 117 for resp in self.IterResponses(tab): |
| 118 count += 1 |
| 119 if resp.IsSafebrowsingResponse(): |
| 120 safebrowsing_count += 1 |
| 121 else: |
| 122 r = resp.response |
| 123 raise ChromeProxyMetricException, ( |
| 124 '%s: Not a valid safe browsing response.\n' |
| 125 'Reponse: status=(%d, %s)\nHeaders:\n %s' % ( |
| 126 r.url, r.status, r.status_text, r.headers)) |
| 127 if count == safebrowsing_count: |
| 128 results.Add('safebrowsing', 'boolean', True) |
| 129 else: |
| 130 raise ChromeProxyMetricException, ( |
| 131 'Safebrowsing failed (count=%d, safebrowsing_count=%d)\n' % ( |
| 132 count, safebrowsing_count)) |
OLD | NEW |