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 */ 11base.requireStylesheet('tracing.record_selection_dialog'); 12base.requireTemplate('tracing.record_selection_dialog'); 13 14base.require('base.utils'); 15base.require('tracing.filter'); 16base.require('ui.overlay'); 17 18base.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