| Index: tools/chrome_proxy/integration_tests/chrome_proxy_metrics_unittest.py | 
| diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics_unittest.py b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics_unittest.py | 
| index 37fdb5f9f3babec82c226bd275cb9cb06a5dff7d..9396a09dad9c410833ea638e17e739c7dde5392f 100644 | 
| --- a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics_unittest.py | 
| +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics_unittest.py | 
| @@ -12,7 +12,7 @@ from metrics import test_page_test_results | 
|  | 
| # Timeline events used in tests. | 
| # An HTML not via proxy. | 
| -EVENT_HTML_PROXY = network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| +EVENT_HTML_DIRECT = network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| url='http://test.html1', | 
| response_headers={ | 
| 'Content-Type': 'text/html', | 
| @@ -20,6 +20,32 @@ EVENT_HTML_PROXY = network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| }, | 
| body=network_unittest.HTML_BODY) | 
|  | 
| +# An HTML via proxy. | 
| +EVENT_HTML_PROXY_VIA = ( | 
| +    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| +    url='http://test.html2', | 
| +    response_headers={ | 
| +        'Content-Type': 'text/html', | 
| +        'Content-Encoding': 'gzip', | 
| +        'X-Original-Content-Length': str(len(network_unittest.HTML_BODY)), | 
| +        'Via': '1.1 ' + metrics.CHROME_PROXY_VIA_HEADER, | 
| +        }, | 
| +    body=network_unittest.HTML_BODY, | 
| +    remote_port=443)) | 
| + | 
| +# An HTML via the HTTP fallback proxy. | 
| +EVENT_HTML_PROXY_VIA_HTTP_FALLBACK = ( | 
| +    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| +    url='http://test.html2', | 
| +    response_headers={ | 
| +        'Content-Type': 'text/html', | 
| +        'Content-Encoding': 'gzip', | 
| +        'X-Original-Content-Length': str(len(network_unittest.HTML_BODY)), | 
| +        'Via': '1.1 ' + metrics.CHROME_PROXY_VIA_HEADER, | 
| +        }, | 
| +    body=network_unittest.HTML_BODY, | 
| +    remote_port=80)) | 
| + | 
| # An HTML via proxy with the deprecated Via header. | 
| EVENT_HTML_PROXY_DEPRECATED_VIA = ( | 
| network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| @@ -33,6 +59,34 @@ EVENT_HTML_PROXY_DEPRECATED_VIA = ( | 
| }, | 
| body=network_unittest.HTML_BODY)) | 
|  | 
| +# An image via proxy with Via header. | 
| +EVENT_IMAGE_PROXY_VIA = ( | 
| +    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| +    url='http://test.image', | 
| +    response_headers={ | 
| +        'Content-Type': 'image/jpeg', | 
| +        'Content-Encoding': 'gzip', | 
| +        'X-Original-Content-Length': str(network_unittest.IMAGE_OCL), | 
| +        'Via': '1.1 ' + metrics.CHROME_PROXY_VIA_HEADER, | 
| +        }, | 
| +    body=base64.b64encode(network_unittest.IMAGE_BODY), | 
| +    base64_encoded_body=True, | 
| +    remote_port=443)) | 
| + | 
| +# An image via the HTTP fallback proxy. | 
| +EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK = ( | 
| +    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| +    url='http://test.image', | 
| +    response_headers={ | 
| +        'Content-Type': 'image/jpeg', | 
| +        'Content-Encoding': 'gzip', | 
| +        'X-Original-Content-Length': str(network_unittest.IMAGE_OCL), | 
| +        'Via': '1.1 ' + metrics.CHROME_PROXY_VIA_HEADER, | 
| +        }, | 
| +    body=base64.b64encode(network_unittest.IMAGE_BODY), | 
| +    base64_encoded_body=True, | 
| +    remote_port=80)) | 
| + | 
| # An image via proxy with Via header and it is cached. | 
| EVENT_IMAGE_PROXY_CACHED = ( | 
| network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent( | 
| @@ -136,7 +190,7 @@ class ChromeProxyMetricTest(unittest.TestCase): | 
| def testChromeProxyMetricForDataSaving(self): | 
| metric = metrics.ChromeProxyMetric() | 
| events = [ | 
| -        EVENT_HTML_PROXY, | 
| +        EVENT_HTML_DIRECT, | 
| EVENT_HTML_PROXY_DEPRECATED_VIA, | 
| EVENT_IMAGE_PROXY_CACHED, | 
| EVENT_IMAGE_DIRECT] | 
| @@ -153,7 +207,7 @@ class ChromeProxyMetricTest(unittest.TestCase): | 
| def testChromeProxyMetricForHeaderValidation(self): | 
| metric = metrics.ChromeProxyMetric() | 
| metric.SetEvents([ | 
| -        EVENT_HTML_PROXY, | 
| +        EVENT_HTML_DIRECT, | 
| EVENT_HTML_PROXY_DEPRECATED_VIA, | 
| EVENT_IMAGE_PROXY_CACHED, | 
| EVENT_IMAGE_DIRECT]) | 
| @@ -178,7 +232,7 @@ class ChromeProxyMetricTest(unittest.TestCase): | 
| def testChromeProxyMetricForBypass(self): | 
| metric = metrics.ChromeProxyMetric() | 
| metric.SetEvents([ | 
| -        EVENT_HTML_PROXY, | 
| +        EVENT_HTML_DIRECT, | 
| EVENT_HTML_PROXY_DEPRECATED_VIA, | 
| EVENT_IMAGE_PROXY_CACHED, | 
| EVENT_IMAGE_DIRECT]) | 
| @@ -206,44 +260,24 @@ class ChromeProxyMetricTest(unittest.TestCase): | 
| metric.AddResultsForCorsBypass(None, results) | 
| results.AssertHasPageSpecificScalarValue('cors_bypass', 'count', 1) | 
|  | 
| - | 
| -  def testChromeProxyMetricForHTTPFallback(self): | 
| +  def testChromeProxyMetricForBlockOnce(self): | 
| metric = metrics.ChromeProxyMetric() | 
| -    metric.SetEvents([ | 
| -        EVENT_HTML_PROXY, | 
| -        EVENT_HTML_PROXY_DEPRECATED_VIA]) | 
| +    metric.SetEvents([EVENT_HTML_DIRECT, | 
| +                      EVENT_IMAGE_PROXY_VIA]) | 
| results = test_page_test_results.TestPageTestResults(self) | 
| +    metric.AddResultsForBlockOnce(None, results) | 
| +    results.AssertHasPageSpecificScalarValue('eligible_responses', 'count', 2) | 
| +    results.AssertHasPageSpecificScalarValue('bypass', 'count', 1) | 
|  | 
| -    fallback_exception = False | 
| -    info = {} | 
| -    info['enabled'] = False | 
| -    self._StubGetProxyInfo(info) | 
| -    try: | 
| -      metric.AddResultsForBypass(None, results) | 
| -    except metrics.ChromeProxyMetricException: | 
| -      fallback_exception = True | 
| -    self.assertTrue(fallback_exception) | 
| - | 
| -    fallback_exception = False | 
| -    info['enabled'] = True | 
| -    info['proxies'] = [ | 
| -        'something.else.com:80', | 
| -        metrics.PROXY_SETTING_DIRECT | 
| -        ] | 
| -    self._StubGetProxyInfo(info) | 
| +    metric.SetEvents([EVENT_HTML_DIRECT, | 
| +                      EVENT_IMAGE_DIRECT]) | 
| +    exception_occurred = False | 
| try: | 
| -      metric.AddResultsForBypass(None, results) | 
| +      metric.AddResultsForBlockOnce(None, results) | 
| except metrics.ChromeProxyMetricException: | 
| -      fallback_exception = True | 
| -    self.assertTrue(fallback_exception) | 
| - | 
| -    info['enabled'] = True | 
| -    info['proxies'] = [ | 
| -        metrics.PROXY_SETTING_HTTP, | 
| -        metrics.PROXY_SETTING_DIRECT | 
| -        ] | 
| -    self._StubGetProxyInfo(info) | 
| -    metric.AddResultsForHTTPFallback(None, results) | 
| +      exception_occurred = True | 
| +    # The second response was over direct, but was expected via proxy. | 
| +    self.assertTrue(exception_occurred) | 
|  | 
| def testChromeProxyMetricForSafebrowsing(self): | 
| metric = metrics.ChromeProxyMetric() | 
| @@ -258,3 +292,64 @@ class ChromeProxyMetricTest(unittest.TestCase): | 
| metric.SetEvents([]) | 
| metric.AddResultsForSafebrowsing(None, results) | 
| results.AssertHasPageSpecificScalarValue('safebrowsing', 'boolean', True) | 
| + | 
| +  def testChromeProxyMetricForHTTPFallback(self): | 
| +    metric = metrics.ChromeProxyMetric() | 
| +    metric.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK, | 
| +                      EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK]) | 
| +    results = test_page_test_results.TestPageTestResults(self) | 
| +    metric.AddResultsForHTTPFallback(None, results) | 
| +    results.AssertHasPageSpecificScalarValue('via_fallback', 'count', 2) | 
| + | 
| +    metric.SetEvents([EVENT_HTML_PROXY_VIA, | 
| +                       EVENT_IMAGE_PROXY_VIA]) | 
| +    exception_occurred = False | 
| +    try: | 
| +      metric.AddResultsForHTTPFallback(None, results) | 
| +    except metrics.ChromeProxyMetricException: | 
| +      exception_occurred = True | 
| +    # The responses came through the SPDY proxy, but were expected through the | 
| +    # HTTP fallback proxy. | 
| +    self.assertTrue(exception_occurred) | 
| + | 
| +  def testChromeProxyMetricForHTTPToDirectFallback(self): | 
| +    metric = metrics.ChromeProxyMetric() | 
| +    metric.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK, | 
| +                      EVENT_HTML_DIRECT, | 
| +                      EVENT_IMAGE_DIRECT]) | 
| +    results = test_page_test_results.TestPageTestResults(self) | 
| +    metric.AddResultsForHTTPToDirectFallback(None, results) | 
| +    results.AssertHasPageSpecificScalarValue('via_fallback', 'count', 1) | 
| +    results.AssertHasPageSpecificScalarValue('bypass', 'count', 2) | 
| + | 
| +    metric.SetEvents([EVENT_HTML_PROXY_VIA, | 
| +                       EVENT_HTML_DIRECT]) | 
| +    exception_occurred = False | 
| +    try: | 
| +      metric.AddResultsForHTTPToDirectFallback(None, results) | 
| +    except metrics.ChromeProxyMetricException: | 
| +      exception_occurred = True | 
| +    # The first response was expected through the HTTP fallback proxy. | 
| +    self.assertTrue(exception_occurred) | 
| + | 
| +    metric.SetEvents([EVENT_HTML_PROXY_VIA_HTTP_FALLBACK, | 
| +                       EVENT_HTML_PROXY_VIA_HTTP_FALLBACK, | 
| +                       EVENT_IMAGE_PROXY_VIA_HTTP_FALLBACK]) | 
| +    exception_occurred = False | 
| +    try: | 
| +      metric.AddResultsForHTTPToDirectFallback(None, results) | 
| +    except metrics.ChromeProxyMetricException: | 
| +      exception_occurred = True | 
| +    # All but the first response were expected to be over direct. | 
| +    self.assertTrue(exception_occurred) | 
| + | 
| +    metric.SetEvents([EVENT_HTML_DIRECT, | 
| +                       EVENT_HTML_DIRECT, | 
| +                       EVENT_IMAGE_DIRECT]) | 
| +    exception_occurred = False | 
| +    try: | 
| +      metric.AddResultsForHTTPToDirectFallback(None, results) | 
| +    except metrics.ChromeProxyMetricException: | 
| +      exception_occurred = True | 
| +    # The first response was expected through the HTTP fallback proxy. | 
| +    self.assertTrue(exception_occurred) | 
|  |