OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import logging | 5 import logging |
6 import os | |
6 import time | 7 import time |
7 | 8 |
8 from integration_tests import network_metrics | 9 from integration_tests import network_metrics |
9 from telemetry.page import page_test | 10 from telemetry.page import page_test |
10 from telemetry.value import scalar | 11 from telemetry.value import scalar |
11 | 12 |
12 | 13 |
13 class ChromeProxyMetricException(page_test.MeasurementFailure): | 14 class ChromeProxyMetricException(page_test.MeasurementFailure): |
14 pass | 15 pass |
15 | 16 |
16 | 17 |
17 CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' | 18 CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy' |
18 | 19 |
19 | 20 |
20 class ChromeProxyResponse(network_metrics.HTTPResponse): | 21 class ChromeProxyResponse(network_metrics.HTTPResponse): |
21 """ Represents an HTTP response from a timeleine event.""" | 22 """ Represents an HTTP response from a timeline event.""" |
22 def __init__(self, event): | 23 def __init__(self, event): |
23 super(ChromeProxyResponse, self).__init__(event) | 24 super(ChromeProxyResponse, self).__init__(event) |
24 | 25 |
25 def ShouldHaveChromeProxyViaHeader(self): | 26 def ShouldHaveChromeProxyViaHeader(self): |
26 resp = self.response | 27 resp = self.response |
27 # Ignore https and data url | 28 # Ignore https and data url |
28 if resp.url.startswith('https') or resp.url.startswith('data:'): | 29 if resp.url.startswith('https') or resp.url.startswith('data:'): |
29 return False | 30 return False |
30 # Ignore 304 Not Modified and cache hit. | 31 # Ignore 304 Not Modified and cache hit. |
31 if resp.status == 304 or resp.served_from_cache: | 32 if resp.status == 304 or resp.served_from_cache: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 def HasChromeProxyLoFi(self): | 75 def HasChromeProxyLoFi(self): |
75 if 'Chrome-Proxy' not in self.response.request_headers: | 76 if 'Chrome-Proxy' not in self.response.request_headers: |
76 return False | 77 return False |
77 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy'] | 78 chrome_proxy_request_header = self.response.request_headers['Chrome-Proxy'] |
78 values = [v.strip() for v in chrome_proxy_request_header.split(',')] | 79 values = [v.strip() for v in chrome_proxy_request_header.split(',')] |
79 for value in values: | 80 for value in values: |
80 if len(value) == 5 and value == 'q=low': | 81 if len(value) == 5 and value == 'q=low': |
81 return True | 82 return True |
82 return False | 83 return False |
83 | 84 |
85 | |
84 class ChromeProxyMetric(network_metrics.NetworkMetric): | 86 class ChromeProxyMetric(network_metrics.NetworkMetric): |
85 """A Chrome proxy timeline metric.""" | 87 """A Chrome proxy timeline metric.""" |
86 | 88 |
87 def __init__(self): | 89 def __init__(self): |
88 super(ChromeProxyMetric, self).__init__() | 90 super(ChromeProxyMetric, self).__init__() |
89 self.compute_data_saving = True | 91 self.compute_data_saving = True |
90 | 92 |
91 def SetEvents(self, events): | 93 def SetEvents(self, events): |
92 """Used for unittest.""" | 94 """Used for unittest.""" |
93 self._events = events | 95 self._events = events |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
552 via_count += 1 | 554 via_count += 1 |
553 if via_count == 0: | 555 if via_count == 0: |
554 raise ChromeProxyMetricException, ( | 556 raise ChromeProxyMetricException, ( |
555 'Expected at least one response through the proxy after the bypass ' | 557 'Expected at least one response through the proxy after the bypass ' |
556 'expired, but zero such responses were received.') | 558 'expired, but zero such responses were received.') |
557 | 559 |
558 results.AddValue(scalar.ScalarValue( | 560 results.AddValue(scalar.ScalarValue( |
559 results.current_page, 'bypass', 'count', bypass_count)) | 561 results.current_page, 'bypass', 'count', bypass_count)) |
560 results.AddValue(scalar.ScalarValue( | 562 results.AddValue(scalar.ScalarValue( |
561 results.current_page, 'via', 'count', via_count)) | 563 results.current_page, 'via', 'count', via_count)) |
564 | |
565 class ChromeProxyVideoMetric(network_metrics.NetworkMetric): | |
566 """A Chrome proxy video metric.""" | |
567 def __init__(self, tab): | |
568 super(ChromeProxyVideoMetric, self).__init__() | |
569 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f: | |
570 js = f.read() | |
571 tab.ExecuteJavaScript(js) | |
572 | |
573 def Start(self, page, tab): | |
574 tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()') | |
575 self.videoMetrics = None | |
576 super(ChromeProxyVideoMetric, self).Start(page, tab) | |
577 | |
578 def Stop(self, page, tab): | |
579 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoLoaded', 30) | |
580 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') | |
581 # Now wait for the video to stop playing. | |
582 # Give it 2x the total duration to account for buffering. | |
583 waitTime = 2 * m['video_duration'] | |
584 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoEnded', waitTime) | |
585 # Load the final metrics. | |
586 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') | |
587 self.videoMetrics = m | |
588 # Cast this to an integer as it is often approximate (for an unknown reason) | |
589 m['video_duration'] = int(m['video_duration']) | |
590 super(ChromeProxyVideoMetric, self).Stop(page, tab) | |
591 | |
592 def ResponseFromEvent(self, event): | |
593 return ChromeProxyResponse(event) | |
594 | |
595 def AddResults(self, tab, results): | |
596 raise NotImplementedError | |
597 | |
598 def AddResultsForProxied(self, tab, results): | |
599 return self._AddResultsShared('proxied', tab, results) | |
600 | |
601 def AddResultsForDirect(self, tab, results): | |
602 return self._AddResultsShared('direct', tab, results) | |
603 | |
604 def _AddResultsShared(self, kind, tab, results): | |
605 def err(s): | |
606 raise ChromeProxyMetricException, s | |
607 | |
608 # Should have played the video. | |
609 if not self.videoMetrics['ready']: | |
610 err('%s: video not played' % kind) | |
611 | |
612 # Should have an HTTP response for the video. | |
613 wantContentType = 'video/webm' if kind == 'proxied' else 'video/mp4' | |
614 found = False | |
615 for r in self.IterResponses(tab): | |
616 resp = r.response | |
617 if kind == 'direct' and r.HasChromeProxyViaHeader(): | |
618 err('%s: page has proxied Via header' % kind) | |
619 if resp.GetHeader('Content-Type') != wantContentType: | |
620 continue | |
621 if found: | |
bolian
2015/04/10 21:00:03
Can we not have restriction of only one video at t
Tom Bergan
2015/04/10 21:14:46
This is a good feature for Dan to add :-)
| |
622 err('%s: multiple video responses' % kind) | |
623 found = True | |
624 cl = resp.GetHeader('Content-Length') | |
625 xocl = resp.GetHeader('X-Original-Content-Length') | |
626 if cl != None: | |
627 self.videoMetrics['content_length_header'] = int(cl) | |
628 if xocl != None: | |
629 self.videoMetrics['x_original_content_length_header'] = int(xocl) | |
630 # Should have CL always. | |
631 if cl == None: | |
632 err('%s: missing ContentLength' % kind) | |
633 # Proxied: should have CL < XOCL | |
634 # Direct: should not have XOCL | |
635 if kind == 'proxied': | |
636 if xocl == None or int(cl) >= int(xocl): | |
637 err('%s: bigger response (%s > %s)' % (kind, str(cl), str(xocl))) | |
638 else: | |
639 if xocl != None: | |
640 err('%s: has XOriginalContentLength' % kind) | |
641 | |
642 if not found: | |
643 err('%s: missing video response' % kind) | |
644 | |
645 # Finally, add all the metrics to the results. | |
646 for (k,v) in self.videoMetrics.iteritems(): | |
647 k = "%s_%s" % (k, kind) | |
648 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) | |
OLD | NEW |