1<!DOCTYPE html>
2<!--
3Copyright (c) 2014 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/base/base.html">
9<link rel="import" href="/tracing/base/base64.html">
10
11<script>
12'use strict';
13
14tr.exportTo('tr.b', function() {
15  var Base64 = tr.b.Base64;
16
17  function computeUserTimingMarkName(groupName, functionName, opt_args) {
18    if (groupName === undefined)
19      throw new Error('getMeasureString should have group name');
20    if (functionName === undefined)
21      throw new Error('getMeasureString should have function name');
22    var userTimingMarkName = groupName + ':' + functionName;
23    if (opt_args !== undefined) {
24      userTimingMarkName += '/';
25      userTimingMarkName += Base64.btoa(JSON.stringify(opt_args));
26    }
27    return userTimingMarkName;
28  }
29
30  function Timing() {
31  }
32
33  Timing.nextMarkNumber = 0;
34
35  Timing.mark = function(groupName, functionName, opt_args) {
36    if (tr.isHeadless) {
37      return {
38        end: function() {}
39      };
40    }
41    var userTimingMarkName = computeUserTimingMarkName(
42      groupName, functionName, opt_args);
43    var markBeginName = 'tvcm.mark' + Timing.nextMarkNumber++;
44    var markEndName = 'tvcm.mark' + Timing.nextMarkNumber++;
45    window.performance.mark(markBeginName);
46    return {
47      end: function() {
48        window.performance.mark(markEndName);
49        window.performance.measure(userTimingMarkName,
50                                   markBeginName,
51                                   markEndName);
52      }
53    };
54  };
55
56  Timing.wrap = function(groupName, callback, opt_args) {
57    if (groupName === undefined)
58      throw new Error('Timing.wrap should have group name');
59    if (callback.name === '')
60      throw new Error('Anonymous function is not allowed');
61    return Timing.wrapNamedFunction(
62      groupName, callback.name, callback, opt_args);
63  };
64
65  Timing.wrapNamedFunction = function(groupName, functionName, callback,
66                                      opt_args) {
67    function timedNamedFunction() {
68      var markedTime = Timing.mark(groupName, functionName, opt_args);
69      try {
70        callback.apply(this, arguments);
71      } finally {
72        markedTime.end();
73      }
74    }
75    return timedNamedFunction;
76  };
77
78  function TimedNamedPromise(groupName, name, executor, opt_args) {
79    var markedTime = Timing.mark(groupName, name, opt_args);
80    var promise = new Promise(executor);
81    promise.then(function(result) {
82      markedTime.end();
83      return result;
84    }, function(e) {
85      markedTime.end();
86      throw e;
87    });
88    return promise;
89  }
90
91  return {
92    _computeUserTimingMarkName: computeUserTimingMarkName, // export for testing
93    TimedNamedPromise: TimedNamedPromise,
94    Timing: Timing
95  };
96});
97</script>
98