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 common import chrome_proxy_metrics | 9 from common import chrome_proxy_metrics |
9 from common import network_metrics | 10 from common import network_metrics |
10 from common.chrome_proxy_metrics import ChromeProxyMetricException | 11 from common.chrome_proxy_metrics import ChromeProxyMetricException |
11 from telemetry.page import page_test | 12 from telemetry.page import page_test |
12 from telemetry.value import scalar | 13 from telemetry.value import scalar |
13 | 14 |
14 | 15 |
15 class ChromeProxyMetric(network_metrics.NetworkMetric): | 16 class ChromeProxyMetric(network_metrics.NetworkMetric): |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 via_count += 1 | 520 via_count += 1 |
520 if via_count == 0: | 521 if via_count == 0: |
521 raise ChromeProxyMetricException, ( | 522 raise ChromeProxyMetricException, ( |
522 'Expected at least one response through the proxy after the bypass ' | 523 'Expected at least one response through the proxy after the bypass ' |
523 'expired, but zero such responses were received.') | 524 'expired, but zero such responses were received.') |
524 | 525 |
525 results.AddValue(scalar.ScalarValue( | 526 results.AddValue(scalar.ScalarValue( |
526 results.current_page, 'bypass', 'count', bypass_count)) | 527 results.current_page, 'bypass', 'count', bypass_count)) |
527 results.AddValue(scalar.ScalarValue( | 528 results.AddValue(scalar.ScalarValue( |
528 results.current_page, 'via', 'count', via_count)) | 529 results.current_page, 'via', 'count', via_count)) |
| 530 |
| 531 |
| 532 PROXIED = 'proxied' |
| 533 DIRECT = 'direct' |
| 534 |
| 535 class ChromeProxyVideoMetric(network_metrics.NetworkMetric): |
| 536 """Metrics for video pages. |
| 537 |
| 538 Wraps the video metrics produced by videowrapper.js, such as the video |
| 539 duration and size in pixels. Also checks a few basic HTTP response headers |
| 540 such as Content-Type and Content-Length in the video responses. |
| 541 """ |
| 542 |
| 543 def __init__(self, tab): |
| 544 super(ChromeProxyVideoMetric, self).__init__() |
| 545 with open(os.path.join(os.path.dirname(__file__), 'videowrapper.js')) as f: |
| 546 js = f.read() |
| 547 tab.ExecuteJavaScript(js) |
| 548 |
| 549 def Start(self, page, tab): |
| 550 tab.ExecuteJavaScript('window.__chromeProxyCreateVideoWrappers()') |
| 551 self.videoMetrics = None |
| 552 super(ChromeProxyVideoMetric, self).Start(page, tab) |
| 553 |
| 554 def Stop(self, page, tab): |
| 555 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoLoaded', 30) |
| 556 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
| 557 |
| 558 # Now wait for the video to stop playing. |
| 559 # Give it 2x the total duration to account for buffering. |
| 560 waitTime = 2 * m['video_duration'] |
| 561 tab.WaitForJavaScriptExpression('window.__chromeProxyVideoEnded', waitTime) |
| 562 |
| 563 # Load the final metrics. |
| 564 m = tab.EvaluateJavaScript('window.__chromeProxyVideoMetrics') |
| 565 self.videoMetrics = m |
| 566 # Cast this to an integer as it is often approximate (for an unknown reason) |
| 567 m['video_duration'] = int(m['video_duration']) |
| 568 super(ChromeProxyVideoMetric, self).Stop(page, tab) |
| 569 |
| 570 def ResponseFromEvent(self, event): |
| 571 return chrome_proxy_metrics.ChromeProxyResponse(event) |
| 572 |
| 573 def AddResults(self, tab, results): |
| 574 raise NotImplementedError |
| 575 |
| 576 def AddResultsForProxied(self, tab, results): |
| 577 return self._AddResultsShared(PROXIED, tab, results) |
| 578 |
| 579 def AddResultsForDirect(self, tab, results): |
| 580 return self._AddResultsShared(DIRECT, tab, results) |
| 581 |
| 582 def _AddResultsShared(self, kind, tab, results): |
| 583 def err(s): |
| 584 raise ChromeProxyMetricException, s |
| 585 |
| 586 # Should have played the video. |
| 587 if not self.videoMetrics['ready']: |
| 588 err('%s: video not played' % kind) |
| 589 |
| 590 # Should have an HTTP response for the video. |
| 591 wantContentType = 'video/webm' if kind == PROXIED else 'video/mp4' |
| 592 found = False |
| 593 for r in self.IterResponses(tab): |
| 594 resp = r.response |
| 595 if kind == DIRECT and r.HasChromeProxyViaHeader(): |
| 596 err('%s: page has proxied Via header' % kind) |
| 597 if resp.GetHeader('Content-Type') != wantContentType: |
| 598 continue |
| 599 if found: |
| 600 err('%s: multiple video responses' % kind) |
| 601 found = True |
| 602 |
| 603 cl = resp.GetHeader('Content-Length') |
| 604 xocl = resp.GetHeader('X-Original-Content-Length') |
| 605 if cl != None: |
| 606 self.videoMetrics['content_length_header'] = int(cl) |
| 607 if xocl != None: |
| 608 self.videoMetrics['x_original_content_length_header'] = int(xocl) |
| 609 |
| 610 # Should have CL always. |
| 611 if cl == None: |
| 612 err('%s: missing ContentLength' % kind) |
| 613 # Proxied: should have CL < XOCL |
| 614 # Direct: should not have XOCL |
| 615 if kind == PROXIED: |
| 616 if xocl == None or int(cl) >= int(xocl): |
| 617 err('%s: bigger response (%s > %s)' % (kind, str(cl), str(xocl))) |
| 618 else: |
| 619 if xocl != None: |
| 620 err('%s: has XOriginalContentLength' % kind) |
| 621 |
| 622 if not found: |
| 623 err('%s: missing video response' % kind) |
| 624 |
| 625 # Finally, add all the metrics to the results. |
| 626 for (k,v) in self.videoMetrics.iteritems(): |
| 627 k = "%s_%s" % (k, kind) |
| 628 results.AddValue(scalar.ScalarValue(results.current_page, k, "", v)) |
OLD | NEW |