Home | History | Annotate | Download | only in tracing
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 
      6 /**
      7  * @fileoverview State and UI for trace data collection.
      8  */
      9 cr.define('tracing', function() {
     10 
     11   function TracingController() {
     12     this.overlay_ = document.createElement('div');
     13     this.overlay_.className = 'tracing-overlay';
     14 
     15     cr.ui.decorate(this.overlay_, tracing.Overlay);
     16 
     17     this.statusDiv_ = document.createElement('div');
     18     this.overlay_.appendChild(this.statusDiv_);
     19 
     20     this.bufferPercentDiv_ = document.createElement('div');
     21     this.overlay_.appendChild(this.bufferPercentDiv_);
     22 
     23     this.stopButton_ = document.createElement('button');
     24     this.stopButton_.onclick = this.endTracing.bind(this);
     25     this.stopButton_.textContent = 'Stop tracing';
     26     this.overlay_.appendChild(this.stopButton_);
     27 
     28     this.traceEvents_ = [];
     29     this.systemTraceEvents_ = [];
     30 
     31     this.onKeydownBoundToThis_ = this.onKeydown_.bind(this);
     32     this.onKeypressBoundToThis_ = this.onKeypress_.bind(this);
     33 
     34     chrome.send('tracingControllerInitialized');
     35   }
     36 
     37   TracingController.prototype = {
     38     __proto__: cr.EventTarget.prototype,
     39 
     40     gpuInfo_: undefined,
     41     clientInfo_: undefined,
     42     tracingEnabled_: false,
     43     tracingEnding_: false,
     44     systemTraceDataFilename_: undefined,
     45 
     46     onRequestBufferPercentFullComplete: function(percent_full) {
     47       if (!this.overlay_.visible)
     48         return;
     49 
     50       window.setTimeout(this.beginRequestBufferPercentFull_.bind(this), 250);
     51 
     52       this.bufferPercentDiv_.textContent = 'Buffer usage: ' +
     53           Math.round(100 * percent_full) + '%';
     54     },
     55 
     56     /**
     57      * Begin requesting the buffer fullness
     58      */
     59     beginRequestBufferPercentFull_: function() {
     60       chrome.send('beginRequestBufferPercentFull');
     61     },
     62 
     63     /**
     64      * Called by info_view to empty the trace buffer
     65      */
     66     beginTracing: function(opt_systemTracingEnabled) {
     67       if (this.tracingEnabled_)
     68         throw Error('Tracing already begun.');
     69 
     70       this.stopButton_.hidden = false;
     71       this.statusDiv_.textContent = 'Tracing active.';
     72       this.overlay_.visible = true;
     73 
     74       this.tracingEnabled_ = true;
     75 
     76       console.log('Beginning to trace...');
     77       this.statusDiv_.textContent = 'Tracing active.';
     78 
     79       this.traceEvents_ = [];
     80       this.systemTraceEvents_ = [];
     81       chrome.send('beginTracing', [opt_systemTracingEnabled || false]);
     82       this.beginRequestBufferPercentFull_();
     83 
     84       var e = new cr.Event('traceBegun');
     85       e.events = this.traceEvents_;
     86       this.dispatchEvent(e);
     87 
     88       e = new cr.Event('traceEventsChanged');
     89       e.numEvents = this.traceEvents_.length;
     90       this.dispatchEvent(e);
     91 
     92       window.addEventListener('keypress', this.onKeypressBoundToThis_);
     93       window.addEventListener('keydown', this.onKeydownBoundToThis_);
     94     },
     95 
     96     onKeydown_: function(e) {
     97       if (e.keyCode == 27) {
     98         this.endTracing();
     99       }
    100     },
    101 
    102     onKeypress_: function(e) {
    103       if (e.keyIdentifier == 'Enter') {
    104         this.endTracing();
    105       }
    106     },
    107 
    108     /**
    109      * Called from gpu c++ code when ClientInfo is updated.
    110      */
    111     onClientInfoUpdate: function(clientInfo) {
    112       this.clientInfo_ = clientInfo;
    113     },
    114 
    115     /**
    116      * Called from gpu c++ code when GPU Info is updated.
    117      */
    118     onGpuInfoUpdate: function(gpuInfo) {
    119       this.gpuInfo_ = gpuInfo;
    120     },
    121 
    122     /**
    123      * Checks whether tracing is enabled
    124      */
    125     get isTracingEnabled() {
    126       return this.tracingEnabled_;
    127     },
    128 
    129     /**
    130      * Gets the currently traced events. If tracing is active, then
    131      * this can change on the fly.
    132      */
    133     get traceEvents() {
    134       return this.traceEvents_;
    135     },
    136 
    137     /**
    138      * Called by tracing c++ code when new trace data arrives.
    139      */
    140     onTraceDataCollected: function(events) {
    141       this.statusDiv_.textContent = 'Processing trace...';
    142       this.traceEvents_.push.apply(this.traceEvents_, events);
    143     },
    144 
    145     /**
    146      * Called to finish tracing and update all views.
    147      */
    148     endTracing: function() {
    149       if (!this.tracingEnabled_) throw new Error('Tracing not begun.');
    150       if (this.tracingEnding_) return;
    151       this.tracingEnding_ = true;
    152 
    153       this.statusDiv_.textContent = 'Ending trace...';
    154       console.log('Finishing trace');
    155       this.statusDiv_.textContent = 'Downloading trace data...';
    156       this.stopButton_.hidden = true;
    157       // delay sending endTracingAsync until we get a chance to
    158       // update the screen...
    159       window.setTimeout(function() {
    160         chrome.send('endTracingAsync');
    161       }, 100);
    162     },
    163 
    164     /**
    165      * Called by the browser when all processes complete tracing.
    166      */
    167     onEndTracingComplete: function() {
    168       window.removeEventListener('keydown', this.onKeydownBoundToThis_);
    169       window.removeEventListener('keypress', this.onKeypressBoundToThis_);
    170       this.overlay_.visible = false;
    171       this.tracingEnabled_ = false;
    172       this.tracingEnding_ = false;
    173       console.log('onEndTracingComplete p1 with ' +
    174                   this.traceEvents_.length + ' events.');
    175       var e = new cr.Event('traceEnded');
    176       e.events = this.traceEvents_;
    177       this.dispatchEvent(e);
    178     },
    179 
    180     /**
    181      * Called by tracing c++ code when new system trace data arrives.
    182      */
    183     onSystemTraceDataCollected: function(events) {
    184       console.log('onSystemTraceDataCollected with ' +
    185                   events.length + ' chars of data.');
    186       this.systemTraceEvents_ = events;
    187     },
    188 
    189     /**
    190      * Gets the currentl system trace events. If tracing is active, then
    191      * this can change on the fly.
    192      */
    193     get systemTraceEvents() {
    194       return this.systemTraceEvents_;
    195     },
    196 
    197     /**
    198      * Tells browser to put up a load dialog and load the trace file
    199      */
    200     beginLoadTraceFile: function() {
    201       chrome.send('loadTraceFile');
    202     },
    203 
    204     /**
    205      * Called by the browser when a trace file is loaded.
    206      */
    207     onLoadTraceFileComplete: function(data) {
    208       if (data.traceEvents) {
    209         this.traceEvents_ = data.traceEvents;
    210       } else { // path for loading traces saved without metadata
    211         if (!data.length)
    212           console.log('Expected an array when loading the trace file');
    213         else
    214           this.traceEvents_ = data;
    215       }
    216       if (data.systemTraceEvents) {
    217         this.systemTraceEvents_ = data.systemTraceEvents;
    218       } else { // path for loading traces saved without metadata
    219         if (!data.length)
    220           console.log('Expected an array when loading the trace file');
    221         else
    222           this.systemTraceEvents_ = data;
    223       }
    224       var e = new cr.Event('loadTraceFileComplete');
    225       e.events = this.traceEvents_;
    226       this.dispatchEvent(e);
    227     },
    228 
    229     /**
    230      * Called by the browser when loading a trace file was canceled.
    231      */
    232     onLoadTraceFileCanceled: function() {
    233       cr.dispatchSimpleEvent(this, 'loadTraceFileCanceled');
    234     },
    235 
    236     /**
    237      * Tells browser to put up a save dialog and save the trace file
    238      */
    239     beginSaveTraceFile: function(traceEvents, systemTraceEvents) {
    240       var data = {
    241         traceEvents: this.traceEvents_,
    242         systemTraceEvents: this.systemTraceEvents_,
    243         clientInfo: this.clientInfo_,
    244         gpuInfo: this.gpuInfo_
    245       };
    246       chrome.send('saveTraceFile', [JSON.stringify(data)]);
    247     },
    248 
    249     /**
    250      * Called by the browser when a trace file is saveed.
    251      */
    252     onSaveTraceFileComplete: function() {
    253       cr.dispatchSimpleEvent(this, 'saveTraceFileComplete');
    254     },
    255 
    256     /**
    257      * Called by the browser when saving a trace file was canceled.
    258      */
    259     onSaveTraceFileCanceled: function() {
    260       cr.dispatchSimpleEvent(this, 'saveTraceFileCanceled');
    261     },
    262 
    263     selfTest: function() {
    264       this.beginTracing();
    265       window.setTimeout(this.endTracing.bind(This), 500);
    266     }
    267   };
    268   return {
    269     TracingController: TracingController
    270   };
    271 });
    272