Home | History | Annotate | Download | only in tracing
      1 // Copyright (c) 2013 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 'use strict';
      6 
      7 /**
      8  * @fileoverview RecordSelectionDialog presents the available categories
      9  * to be enabled/disabled during tracing.
     10  */
     11 base.requireStylesheet('tracing.record_selection_dialog');
     12 base.requireTemplate('tracing.record_selection_dialog');
     13 
     14 base.require('base.utils');
     15 base.require('tracing.filter');
     16 base.require('ui.overlay');
     17 
     18 base.exportTo('tracing', function() {
     19   var RecordSelectionDialog = ui.define('div');
     20 
     21   RecordSelectionDialog.prototype = {
     22     __proto__: ui.Overlay.prototype,
     23 
     24     decorate: function() {
     25       ui.Overlay.prototype.decorate.call(this);
     26 
     27       this.className = 'record-dialog-overlay';
     28       this.obeyCloseEvents = true;
     29 
     30       var node = base.instantiateTemplate('#record-selection-dialog-template');
     31       this.appendChild(node);
     32 
     33       this.formEl_ = this.querySelector('form');
     34 
     35       this.recordButtonEl_ = this.querySelector('.record-categories');
     36       this.recordButtonEl_.onclick = this.onRecord_.bind(this);
     37 
     38       this.continuousTracingBn_ =
     39           this.querySelector('.continuous-tracing-button');
     40       this.continuousTracingBn_.onchange = this.updateDlgSetting_.bind(this);
     41 
     42       this.systemTracingBn_ = this.querySelector('.system-tracing-button');
     43       this.systemTracingBn_.onchange = this.updateDlgSetting_.bind(this);
     44 
     45       this.samplingBn_ = this.querySelector('.sampling-button');
     46       this.samplingBn_.onchange = this.updateDlgSetting_.bind(this);
     47 
     48       this.systemTracingLabelEl_ = this.querySelector('.system-tracing-label');
     49       this.systemTracingLabelEl_.style.display = 'none';
     50 
     51       this.enabledCategoriesContainerEl_ =
     52           this.querySelector('.default-enabled-categories .categories');
     53 
     54       this.disabledCategoriesContainerEl_ =
     55           this.querySelector('.default-disabled-categories .categories');
     56 
     57       this.createGroupSelectButtons_(
     58           this.querySelector('.default-enabled-categories'));
     59       this.createGroupSelectButtons_(
     60           this.querySelector('.default-disabled-categories'));
     61 
     62       this.addEventListener('visibleChange', this.onVisibleChange_.bind(this));
     63     },
     64 
     65     updateDlgSetting_: function(e) {
     66       var checkbox = e.target;
     67       this.settings_.set(checkbox.value, checkbox.checked, 'record_dlg');
     68     },
     69 
     70     set categories(c) {
     71       this.categories_ = c;
     72     },
     73 
     74     set settings_key(k) {
     75       this.settings_key_ = k;
     76     },
     77 
     78     set settings(s) {
     79       this.settings_ = s;
     80 
     81       this.continuousTracingBn_.checked =
     82           this.settings_.get('continuousTracing', true, 'record_dlg');
     83       this.systemTracingBn_.checked =
     84           this.settings_.get('systemTracing', false, 'record_dlg');
     85       this.samplingBn_.checked =
     86           this.settings_.get('enableSampling', false, 'record_dlg');
     87     },
     88 
     89     set recordCallback(cb) {
     90       this.recordCallback_ = cb;
     91     },
     92 
     93     set showSystemTracing(isEnabled) {
     94       if ((this.settings_ === undefined) ||
     95           (this.settings_.get('systemTracing',
     96                               undefined,
     97                               'record_dlg') === undefined)) {
     98         this.systemTracingBn_.checked = isEnabled;
     99       }
    100 
    101       this.systemTracingLabelEl_.style.display =
    102           isEnabled ? 'inline-block' : 'none';
    103     },
    104 
    105     isContinuousTracingEnabled: function() {
    106       return this.continuousTracingBn_.checked;
    107     },
    108 
    109     isSystemTracingEnabled: function() {
    110       return this.systemTracingBn_.checked;
    111     },
    112 
    113     isSamplingEnabled: function() {
    114       return this.samplingBn_.checked;
    115     },
    116 
    117     categoryFilter: function() {
    118       var categories = this.unselectedCategories_();
    119       var categories_length = categories.length;
    120       var negated_categories = [];
    121       for (var i = 0; i < categories_length; ++i) {
    122         // Skip any category with a , as it will cause issues when we negate.
    123         // Both sides should have been added as separate categories, these can
    124         // only come from settings.
    125         if (categories[i].match(/,/))
    126           continue;
    127         negated_categories.push('-' + categories[i]);
    128       }
    129       categories = negated_categories.join(',');
    130 
    131       var disabledCategories = this.enabledDisabledByDefaultCategories_();
    132       disabledCategories = disabledCategories.join(',');
    133 
    134       var results = [];
    135       if (categories !== '')
    136         results.push(categories);
    137       if (disabledCategories !== '')
    138         results.push(disabledCategories);
    139 
    140       return results.join(',');
    141     },
    142 
    143     onRecord_: function() {
    144       this.visible = false;
    145       this.recordCallback_();
    146       return false;
    147     },
    148 
    149     collectInputs_: function(inputs, isChecked) {
    150       var inputs_length = inputs.length;
    151       var categories = [];
    152       for (var i = 0; i < inputs_length; ++i) {
    153         var input = inputs[i];
    154         if (input.checked === isChecked)
    155           categories.push(input.value);
    156       }
    157       return categories;
    158     },
    159 
    160     unselectedCategories_: function() {
    161       var inputs =
    162           this.enabledCategoriesContainerEl_.querySelectorAll('input');
    163       return this.collectInputs_(inputs, false);
    164     },
    165 
    166     enabledDisabledByDefaultCategories_: function() {
    167       var inputs =
    168           this.disabledCategoriesContainerEl_.querySelectorAll('input');
    169       return this.collectInputs_(inputs, true);
    170     },
    171 
    172     onVisibleChange_: function() {
    173       if (this.visible) {
    174         this.updateForm_();
    175       }
    176     },
    177 
    178     buildInputs_: function(inputs, checkedDefault, parent) {
    179       var inputs_length = inputs.length;
    180       for (var i = 0; i < inputs_length; i++) {
    181         var category = inputs[i];
    182 
    183         var inputEl = document.createElement('input');
    184         inputEl.type = 'checkbox';
    185         inputEl.id = category;
    186         inputEl.value = category;
    187 
    188         inputEl.checked = this.settings_.get(
    189             category, checkedDefault, this.settings_key_);
    190         inputEl.onclick = this.updateSetting_.bind(this);
    191 
    192         var labelEl = document.createElement('label');
    193         labelEl.textContent = category.replace('disabled-by-default-', '');
    194         labelEl.setAttribute('for', category);
    195 
    196         var divEl = document.createElement('div');
    197         divEl.appendChild(inputEl);
    198         divEl.appendChild(labelEl);
    199 
    200         parent.appendChild(divEl);
    201       }
    202     },
    203 
    204     updateForm_: function() {
    205       this.enabledCategoriesContainerEl_.innerHTML = ''; // Clear old categories
    206       this.disabledCategoriesContainerEl_.innerHTML = '';
    207 
    208       this.recordButtonEl_.focus();
    209 
    210       // Dedup the categories. We may have things in settings that are also
    211       // returned when we query the category list.
    212       var set = {};
    213       var allCategories =
    214           this.categories_.concat(this.settings_.keys(this.settings_key_));
    215       var allCategoriesLength = allCategories.length;
    216       for (var i = 0; i < allCategoriesLength; ++i) {
    217         set[allCategories[i]] = true;
    218       }
    219 
    220       var categories = [];
    221       var disabledCategories = [];
    222       for (var category in set) {
    223         if (category.indexOf('disabled-by-default-') == 0)
    224           disabledCategories.push(category);
    225         else
    226           categories.push(category);
    227       }
    228       disabledCategories = disabledCategories.sort();
    229       categories = categories.sort();
    230 
    231       this.buildInputs_(categories, true, this.enabledCategoriesContainerEl_);
    232 
    233       if (disabledCategories.length > 0) {
    234         this.disabledCategoriesContainerEl_.hidden = false;
    235         this.buildInputs_(disabledCategories, false,
    236             this.disabledCategoriesContainerEl_);
    237       }
    238     },
    239 
    240     updateSetting_: function(e) {
    241       var checkbox = e.target;
    242       this.settings_.set(checkbox.value, checkbox.checked, this.settings_key_);
    243     },
    244 
    245     createGroupSelectButtons_: function(parent) {
    246       var flipInputs = function(dir) {
    247         var inputs = parent.querySelectorAll('input');
    248         for (var i = 0; i < inputs.length; i++) {
    249           if (inputs[i].checked === dir)
    250             continue;
    251           // click() is used so the settings will be correclty stored. Setting
    252           // checked does not trigger the onclick (or onchange) callback.
    253           inputs[i].click();
    254         }
    255       };
    256 
    257       var allBtn = parent.querySelector('.all-btn');
    258       allBtn.onclick = function(evt) {
    259         flipInputs(true);
    260         evt.preventDefault();
    261       };
    262 
    263       var noneBtn = parent.querySelector('.none-btn');
    264       noneBtn.onclick = function(evt) {
    265         flipInputs(false);
    266         evt.preventDefault();
    267       };
    268     }
    269   };
    270 
    271   return {
    272     RecordSelectionDialog: RecordSelectionDialog
    273   };
    274 });
    275