1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 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/ui/extras/about_tracing/record_selection_dialog.html">
9
10<script>
11'use strict';
12
13tr.exportTo('tr.ui.e.about_tracing', function() {
14  function beginRecording(tracingControllerClient) {
15    var finalPromiseResolver;
16    var finalPromise = new Promise(function(resolve, reject) {
17      finalPromiseResolver = {
18        resolve: resolve,
19        reject: reject
20      };
21    });
22    finalPromise.selectionDlg = undefined;
23    finalPromise.progressDlg = undefined;
24
25    function beginRecordingError(err) {
26      finalPromiseResolver.reject(err);
27    }
28
29    // Step 0: End recording. This is necessary when the user reloads the
30    // about:tracing page when we are recording. Window.onbeforeunload is not
31    // reliable to end recording on reload.
32    endRecording(tracingControllerClient).then(
33        getCategories,
34        getCategories);  // Ignore error.
35
36    // But just in case, bind onbeforeunload anyway.
37    window.onbeforeunload = function(e) {
38      endRecording(tracingControllerClient);
39    };
40
41    // Step 1: Get categories.
42    function getCategories() {
43      var p = tracingControllerClient.getCategories().then(
44          showTracingDialog,
45          beginRecordingError);
46      p.catch(function(err) {
47        beginRecordingError(err);
48      });
49    }
50
51    // Step 2: Show tracing dialog.
52    var selectionDlg;
53    function showTracingDialog(categories) {
54      selectionDlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
55      selectionDlg.categories = categories;
56      selectionDlg.settings_key =
57          'tr.ui.e.about_tracing.record_selection_dialog';
58      selectionDlg.addEventListener('recordclick', startTracing);
59      selectionDlg.addEventListener('closeclick', cancelRecording);
60      selectionDlg.visible = true;
61
62      finalPromise.selectionDlg = selectionDlg;
63    }
64
65    function cancelRecording() {
66      finalPromise.selectionDlg = undefined;
67      finalPromiseResolver.reject(new UserCancelledError());
68    }
69
70    // Step 2: Do the actual tracing dialog.
71    var progressDlg;
72    var bufferPercentFullDiv;
73    function startTracing() {
74      progressDlg = new tr.ui.b.Overlay();
75      progressDlg.textContent = 'Recording...';
76      progressDlg.userCanClose = false;
77
78      bufferPercentFullDiv = document.createElement('div');
79      progressDlg.appendChild(bufferPercentFullDiv);
80
81      var stopButton = document.createElement('button');
82      stopButton.textContent = 'Stop';
83      progressDlg.clickStopButton = function() {
84        stopButton.click();
85      };
86      progressDlg.appendChild(stopButton);
87
88      var recordingOptions = {
89        categoryFilter: selectionDlg.categoryFilter(),
90        useSystemTracing: selectionDlg.useSystemTracing,
91        tracingRecordMode: selectionDlg.tracingRecordMode,
92        useSampling: selectionDlg.useSampling
93      };
94
95
96      var requestPromise = tracingControllerClient.beginRecording(
97          recordingOptions);
98      requestPromise.then(
99          function() {
100            progressDlg.visible = true;
101            stopButton.focus();
102            updateBufferPercentFull('0');
103          },
104          recordFailed);
105
106      stopButton.addEventListener('click', function() {
107        // TODO(chrishenry): Currently, this only dismiss the progress
108        // dialog when tracingComplete event is received. When performing
109        // remote debugging, the tracingComplete event may be delayed
110        // considerable. We should indicate to user that we are waiting
111        // for tracingComplete event instead of being unresponsive. (For
112        // now, I disable the "stop" button, since clicking on the button
113        // again now cause exception.)
114        var recordingPromise = endRecording(tracingControllerClient);
115        recordingPromise.then(
116            recordFinished,
117            recordFailed);
118        stopButton.disabled = true;
119        bufferPercentFullDiv = undefined;
120      });
121      finalPromise.progressDlg = progressDlg;
122    }
123
124    function recordFinished(tracedData) {
125      progressDlg.visible = false;
126      finalPromise.progressDlg = undefined;
127      finalPromiseResolver.resolve(tracedData);
128    }
129
130    function recordFailed(err) {
131      progressDlg.visible = false;
132      finalPromise.progressDlg = undefined;
133      finalPromiseResolver.reject(err);
134    }
135
136    function getBufferPercentFull() {
137      if (!bufferPercentFullDiv)
138        return;
139
140      tracingControllerClient.beginGetBufferPercentFull().then(
141          updateBufferPercentFull);
142    }
143
144    function updateBufferPercentFull(percent_full) {
145      if (!bufferPercentFullDiv)
146        return;
147
148      percent_full = Math.round(100 * parseFloat(percent_full));
149      var newText = 'Buffer usage: ' + percent_full + '%';
150      if (bufferPercentFullDiv.textContent != newText)
151        bufferPercentFullDiv.textContent = newText;
152
153      window.setTimeout(getBufferPercentFull, 500);
154    }
155
156    // Thats it! We're done.
157    return finalPromise;
158  };
159
160  function endRecording(tracingControllerClient) {
161    return tracingControllerClient.endRecording();
162  }
163
164  function defaultTraceName(tracingControllerClient) {
165    return tracingControllerClient.defaultTraceName();
166  }
167
168  function UserCancelledError() {
169    Error.apply(this, arguments);
170  }
171  UserCancelledError.prototype = {
172    __proto__: Error.prototype
173  };
174
175  return {
176    beginRecording: beginRecording,
177    UserCancelledError: UserCancelledError,
178    defaultTraceName: defaultTraceName
179  };
180});
181</script>
182