Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | |
| 4 /** | 5 /** |
| 5 * @unrestricted | 6 * @implements {SDK.SDKModelObserver<!SDK.EmulationModel>} |
| 6 */ | 7 */ |
| 7 MobileThrottling.NetworkConditionsSelector = class { | 8 MobileThrottling.ThrottlingManager = class extends Common.Object { |
| 8 /** | 9 constructor() { |
| 9 * @param {function(!Array<!MobileThrottling.NetworkConditionsGroup>):!Array<? SDK.NetworkManager.Conditions>} populateCallback | 10 super(); |
| 10 * @param {function(number)} selectCallback | 11 this._cpuThrottlingRate = MobileThrottling.CPUThrottlingRates.NoThrottling; |
| 11 */ | 12 /** @type {!Set<!UI.ToolbarComboBox>} */ |
| 12 constructor(populateCallback, selectCallback) { | 13 this._cpuThrottlingControls = new Set(); |
| 13 this._populateCallback = populateCallback; | 14 this._cpuThrottlingRates = [ |
|
dgozman
2017/06/30 23:21:49
Place next to other presets.
chenwilliam
2017/07/05 22:35:31
Done.
| |
| 14 this._selectCallback = selectCallback; | 15 MobileThrottling.CPUThrottlingRates.NoThrottling, |
| 15 this._customSetting = Common.moduleSetting('customNetworkConditions'); | 16 MobileThrottling.CPUThrottlingRates.MidTierMobile, |
| 16 this._customSetting.addChangeListener(this._populateOptions, this); | 17 MobileThrottling.CPUThrottlingRates.LowEndMobile, |
| 17 this._manager = SDK.multitargetNetworkManager; | 18 ]; |
| 18 this._manager.addEventListener( | 19 SDK.targetManager.observeModels(SDK.EmulationModel, this); |
|
dgozman
2017/06/30 23:21:49
Do this in a last line.
chenwilliam
2017/07/05 22:35:32
Done.
| |
| 19 SDK.MultitargetNetworkManager.Events.ConditionsChanged, this._conditions Changed, this); | 20 /** @type {!Common.Setting<!Array<!SDK.NetworkManager.Conditions>>} */ |
| 20 this._populateOptions(); | 21 this._customNetworkConditionsSetting = Common.moduleSetting('customNetworkCo nditions'); |
| 22 /** @type {!SDK.NetworkManager.Conditions} */ | |
| 23 this._currentNetworkThrottlingConditions = SDK.NetworkManager.NoThrottlingCo nditions; | |
| 24 /** @type {!SDK.NetworkManager.Conditions} */ | |
| 25 this._lastNetworkThrottlingConditions; | |
| 26 this._trackNetworkConditions(); | |
| 21 } | 27 } |
| 22 | 28 |
| 23 /** | |
| 24 * @param {number} throughput | |
| 25 * @param {boolean=} plainText | |
| 26 * @return {string} | |
| 27 */ | |
| 28 static throughputText(throughput, plainText) { | |
| 29 if (throughput < 0) | |
| 30 return ''; | |
| 31 var throughputInKbps = throughput / (1024 / 8); | |
| 32 var delimiter = plainText ? '' : ' '; | |
| 33 if (throughputInKbps < 1024) | |
| 34 return Common.UIString('%d%skb/s', throughputInKbps, delimiter); | |
| 35 if (throughputInKbps < 1024 * 10) | |
| 36 return Common.UIString('%.1f%sMb/s', throughputInKbps / 1024, delimiter); | |
| 37 return Common.UIString('%d%sMb/s', (throughputInKbps / 1024) | 0, delimiter) ; | |
| 38 } | |
| 39 | 29 |
| 40 /** | 30 /** |
| 41 * @param {!HTMLSelectElement} selectElement | 31 * @param {!HTMLSelectElement} selectElement |
| 32 * @return {!MobileThrottling.NetworkThrottlingSelector} | |
| 42 */ | 33 */ |
| 43 static decorateSelect(selectElement) { | 34 decorateSelectWithNetworkThrottling(selectElement) { |
| 44 var options = []; | 35 var options = []; |
| 45 var selector = new MobileThrottling.NetworkConditionsSelector(populate, sele ct); | 36 var selector = |
| 37 new MobileThrottling.NetworkThrottlingSelector(populate, select, this._c ustomNetworkConditionsSetting); | |
| 46 selectElement.addEventListener('change', optionSelected, false); | 38 selectElement.addEventListener('change', optionSelected, false); |
| 39 return selector; | |
| 47 | 40 |
| 48 /** | 41 /** |
| 49 * @param {!Array.<!MobileThrottling.NetworkConditionsGroup>} groups | 42 * @param {!Array.<!MobileThrottling.NetworkThrottlingConditionsGroup>} grou ps |
| 50 * @return {!Array<?SDK.NetworkManager.Conditions>} | 43 * @return {!Array<?SDK.NetworkManager.Conditions>} |
| 51 */ | 44 */ |
| 52 function populate(groups) { | 45 function populate(groups) { |
| 53 selectElement.removeChildren(); | 46 selectElement.removeChildren(); |
| 54 options = []; | 47 options = []; |
| 55 for (var i = 0; i < groups.length; ++i) { | 48 for (var i = 0; i < groups.length; ++i) { |
| 56 var group = groups[i]; | 49 var group = groups[i]; |
| 57 var groupElement = selectElement.createChild('optgroup'); | 50 var groupElement = selectElement.createChild('optgroup'); |
| 58 groupElement.label = group.title; | 51 groupElement.label = group.title; |
| 59 for (var conditions of group.items) { | 52 for (var conditions of group.items) { |
| 60 var title = Common.UIString(conditions.title); | 53 var title = conditions.title; |
| 61 var option = new Option(title, title); | 54 var option = new Option(title, title); |
| 62 groupElement.appendChild(option); | 55 groupElement.appendChild(option); |
| 63 options.push(conditions); | 56 options.push(conditions); |
| 64 } | 57 } |
| 65 if (i === groups.length - 1) { | 58 if (i === groups.length - 1) { |
| 66 groupElement.appendChild(new Option(Common.UIString('Add\u2026'), Comm on.UIString('Add\u2026'))); | 59 groupElement.appendChild(new Option(Common.UIString('Add\u2026'), Comm on.UIString('Add\u2026'))); |
| 67 options.push(null); | 60 options.push(null); |
| 68 } | 61 } |
| 69 } | 62 } |
| 70 return options; | 63 return options; |
| 71 } | 64 } |
| 72 | 65 |
| 73 function optionSelected() { | 66 function optionSelected() { |
| 74 if (selectElement.selectedIndex === selectElement.options.length - 1) | 67 if (selectElement.selectedIndex === selectElement.options.length - 1) |
| 75 selector.revealAndUpdate(); | 68 selector.revealAndUpdate(); |
| 76 else | 69 else |
| 77 selector.optionSelected(options[selectElement.selectedIndex]); | 70 selector.optionSelected(options[selectElement.selectedIndex]); |
| 78 } | 71 } |
| 79 | 72 |
| 80 /** | 73 /** |
| 81 * @param {number} index | 74 * @param {number} index |
| 82 */ | 75 */ |
| 83 function select(index) { | 76 function select(index) { |
| 84 if (selectElement.selectedIndex !== index) | 77 if (selectElement.selectedIndex !== index) |
| 85 selectElement.selectedIndex = index; | 78 selectElement.selectedIndex = index; |
| 86 } | 79 } |
| 87 } | 80 } |
| 88 | 81 |
| 89 /** | 82 /** |
| 83 * @return {!UI.ToolbarCheckbox} | |
| 84 */ | |
| 85 createOfflineToolbarCheckbox() { | |
| 86 var checkbox = new UI.ToolbarCheckbox( | |
| 87 Common.UIString('Offline'), Common.UIString('Force disconnected from net work'), forceOffline.bind(this)); | |
| 88 SDK.multitargetNetworkManager.addEventListener( | |
| 89 SDK.MultitargetNetworkManager.Events.ConditionsChanged, networkCondition sChanged); | |
| 90 checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SD K.NetworkManager.OfflineConditions); | |
| 91 | |
| 92 /** | |
| 93 * @this {!MobileThrottling.ThrottlingManager} | |
| 94 */ | |
| 95 function forceOffline() { | |
| 96 if (checkbox.checked()) | |
| 97 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Of flineConditions); | |
| 98 else | |
| 99 SDK.multitargetNetworkManager.setNetworkConditions(this._lastNetworkThro ttlingConditions); | |
| 100 } | |
| 101 | |
| 102 function networkConditionsChanged() { | |
| 103 checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SDK.NetworkManager.OfflineConditions); | |
| 104 } | |
| 105 | |
| 106 return checkbox; | |
| 107 } | |
| 108 | |
| 109 | |
| 110 /** | |
| 90 * @return {!UI.ToolbarMenuButton} | 111 * @return {!UI.ToolbarMenuButton} |
| 91 */ | 112 */ |
| 92 static createToolbarMenuButton() { | 113 createMobileThrottlingButton() { |
| 93 var button = new UI.ToolbarMenuButton(appendItems); | 114 var button = new UI.ToolbarMenuButton(appendItems); |
| 115 button.setTitle(Common.UIString('Throttling')); | |
| 94 button.setGlyph(''); | 116 button.setGlyph(''); |
| 95 button.turnIntoSelect(); | 117 button.turnIntoSelect(); |
| 96 | 118 |
| 97 /** @type {!Array<?SDK.NetworkManager.Conditions>} */ | 119 /** @type {!MobileThrottling.ConditionsList} */ |
| 98 var options = []; | 120 var options = []; |
| 99 var selectedIndex = -1; | 121 var selectedIndex = -1; |
| 100 var selector = new MobileThrottling.NetworkConditionsSelector(populate, sele ct); | 122 var selector = new MobileThrottling.MobileThrottlingSelector(populate, selec t); |
| 101 return button; | 123 return button; |
| 102 | 124 |
| 103 /** | 125 /** |
| 104 * @param {!UI.ContextMenu} contextMenu | 126 * @param {!UI.ContextMenu} contextMenu |
| 105 */ | 127 */ |
| 106 function appendItems(contextMenu) { | 128 function appendItems(contextMenu) { |
| 107 for (var index = 0; index < options.length; ++index) { | 129 for (var index = 0; index < options.length; ++index) { |
| 108 var conditions = options[index]; | 130 var conditions = options[index]; |
| 109 if (!conditions) { | 131 if (!conditions) { |
| 110 contextMenu.appendSeparator(); | 132 contextMenu.appendSeparator(); |
| 111 } else { | 133 continue; |
| 112 contextMenu.appendCheckboxItem( | |
| 113 Common.UIString(conditions.title), selector.optionSelected.bind(se lector, conditions), | |
| 114 selectedIndex === index); | |
| 115 } | 134 } |
| 135 if (conditions.title === MobileThrottling.CustomConditions.title && | |
| 136 conditions.description === MobileThrottling.CustomConditions.descrip tion) | |
| 137 continue; | |
| 138 contextMenu.appendCheckboxItem( | |
| 139 Common.UIString(conditions.title), | |
| 140 selector.optionSelected.bind(selector, /** @type {!MobileThrottling. Conditions} */ (conditions)), | |
| 141 selectedIndex === index); | |
| 116 } | 142 } |
| 117 contextMenu.appendItem(Common.UIString('Edit\u2026'), selector.revealAndUp date.bind(selector)); | |
| 118 } | 143 } |
| 119 | 144 |
| 120 /** | 145 /** |
| 121 * @param {!Array.<!MobileThrottling.NetworkConditionsGroup>} groups | 146 * @param {!Array.<!MobileThrottling.MobileThrottlingConditionsGroup>} group s |
| 122 * @return {!Array<?SDK.NetworkManager.Conditions>} | 147 * @return {!MobileThrottling.ConditionsList} |
| 123 */ | 148 */ |
| 124 function populate(groups) { | 149 function populate(groups) { |
| 125 options = []; | 150 options = []; |
| 126 for (var group of groups) { | 151 for (var group of groups) { |
| 127 for (var conditions of group.items) | 152 for (var conditions of group.items) |
| 128 options.push(conditions); | 153 options.push(conditions); |
| 129 options.push(null); | 154 options.push(null); |
| 130 } | 155 } |
| 131 return options; | 156 return options; |
| 132 } | 157 } |
| 133 | 158 |
| 134 /** | 159 /** |
| 135 * @param {number} index | 160 * @param {number} index |
| 136 */ | 161 */ |
| 137 function select(index) { | 162 function select(index) { |
| 138 selectedIndex = index; | 163 selectedIndex = index; |
| 139 button.setText(options[index].title); | 164 button.setText(options[index].title); |
| 165 button.setTitle(options[index].description); | |
| 140 } | 166 } |
| 141 } | 167 } |
| 142 | 168 |
| 143 /** | 169 /** |
| 144 * @return {!UI.ToolbarCheckbox} | 170 * @return {number} |
| 145 */ | 171 */ |
| 146 static createOfflineToolbarCheckbox() { | 172 cpuThrottlingRate() { |
| 147 var checkbox = new UI.ToolbarCheckbox( | 173 return this._cpuThrottlingRate; |
| 148 Common.UIString('Offline'), Common.UIString('Force disconnected from net work'), forceOffline); | |
| 149 SDK.multitargetNetworkManager.addEventListener( | |
| 150 SDK.MultitargetNetworkManager.Events.ConditionsChanged, networkCondition sChanged); | |
| 151 checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SD K.NetworkManager.OfflineConditions); | |
| 152 | |
| 153 function forceOffline() { | |
| 154 if (checkbox.checked()) { | |
| 155 MobileThrottling.NetworkConditionsSelector._lastNetworkConditions = | |
| 156 SDK.multitargetNetworkManager.networkConditions(); | |
| 157 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Of flineConditions); | |
| 158 } else { | |
| 159 SDK.multitargetNetworkManager.setNetworkConditions( | |
| 160 MobileThrottling.NetworkConditionsSelector._lastNetworkConditions); | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 function networkConditionsChanged() { | |
| 165 var conditions = SDK.multitargetNetworkManager.networkConditions(); | |
| 166 checkbox.setChecked(conditions === SDK.NetworkManager.OfflineConditions); | |
| 167 } | |
| 168 return checkbox; | |
| 169 } | |
| 170 | |
| 171 _populateOptions() { | |
| 172 var customGroup = {title: Common.UIString('Custom'), items: this._customSett ing.get()}; | |
| 173 var presetsGroup = {title: Common.UIString('Presets'), items: MobileThrottli ng.NetworkConditionsSelector.presets}; | |
| 174 var disabledGroup = {title: Common.UIString('Disabled'), items: [SDK.Network Manager.NoThrottlingConditions]}; | |
| 175 this._options = this._populateCallback([disabledGroup, presetsGroup, customG roup]); | |
| 176 if (!this._conditionsChanged()) { | |
| 177 for (var i = this._options.length - 1; i >= 0; i--) { | |
| 178 if (this._options[i]) { | |
| 179 this.optionSelected(/** @type {!SDK.NetworkManager.Conditions} */ (thi s._options[i])); | |
| 180 break; | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 revealAndUpdate() { | |
| 187 Common.Revealer.reveal(this._customSetting); | |
| 188 this._conditionsChanged(); | |
| 189 } | 174 } |
| 190 | 175 |
| 191 /** | 176 /** |
| 192 * @param {!SDK.NetworkManager.Conditions} conditions | 177 * @param {number} rate |
| 193 */ | 178 */ |
| 194 optionSelected(conditions) { | 179 setCPUThrottlingRate(rate) { |
| 195 this._manager.setNetworkConditions(conditions); | 180 this._cpuThrottlingRate = rate; |
| 181 for (var emulationModel of SDK.targetManager.models(SDK.EmulationModel)) | |
| 182 emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate); | |
| 183 var icon = null; | |
| 184 if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrott ling) { | |
| 185 Host.userMetrics.actionTaken(Host.UserMetrics.Action.CpuThrottlingEnabled) ; | |
| 186 icon = UI.Icon.create('smallicon-warning'); | |
| 187 icon.title = Common.UIString('CPU throttling is enabled'); | |
| 188 } | |
| 189 var index = this._cpuThrottlingRates.indexOf(this._cpuThrottlingRate); | |
| 190 for (var control of this._cpuThrottlingControls) | |
| 191 control.setSelectedIndex(index); | |
| 192 UI.inspectorView.setPanelIcon('timeline', icon); | |
| 193 this.dispatchEventToListeners(MobileThrottling.ThrottlingManager.Events.Rate Changed, this._cpuThrottlingRate); | |
| 196 } | 194 } |
| 197 | 195 |
| 198 /** | 196 /** |
| 199 * @return {boolean} | 197 * @override |
| 198 * @param {!SDK.EmulationModel} emulationModel | |
| 200 */ | 199 */ |
| 201 _conditionsChanged() { | 200 modelAdded(emulationModel) { |
| 202 var value = this._manager.networkConditions(); | 201 if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrott ling) |
| 203 for (var index = 0; index < this._options.length; ++index) { | 202 emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate); |
| 204 var option = this._options[index]; | 203 } |
| 205 if (option && option.download === value.download && option.upload === valu e.upload && | 204 |
| 206 option.latency === value.latency && option.title === value.title) { | 205 /** |
| 207 this._selectCallback(index); | 206 * @override |
| 208 return true; | 207 * @param {!SDK.EmulationModel} emulationModel |
| 209 } | 208 */ |
| 209 modelRemoved(emulationModel) { | |
| 210 } | |
| 211 | |
| 212 /** | |
| 213 * @return {!UI.ToolbarComboBox} | |
| 214 */ | |
| 215 createControl() { | |
|
dgozman
2017/06/30 23:21:49
createCPUThrottlingSelector
chenwilliam
2017/07/05 22:35:31
Done.
| |
| 216 var control = new UI.ToolbarComboBox( | |
| 217 event => this.setCPUThrottlingRate(this._cpuThrottlingRates[event.target .selectedIndex])); | |
| 218 this._cpuThrottlingControls.add(control); | |
| 219 var currentRate = this._cpuThrottlingRate; | |
| 220 | |
| 221 for (var i = 0; i < this._cpuThrottlingRates.length; ++i) { | |
| 222 var rate = this._cpuThrottlingRates[i]; | |
| 223 var title = rate === 1 ? Common.UIString('No throttling') : Common.UIStrin g('%d\xD7 slowdown', rate); | |
| 224 var option = control.createOption(title); | |
| 225 control.addOption(option); | |
| 226 if (currentRate === rate) | |
| 227 control.setSelectedIndex(i); | |
| 210 } | 228 } |
| 211 return false; | 229 return control; |
| 230 } | |
| 231 | |
| 232 _trackNetworkConditions() { | |
|
dgozman
2017/06/30 23:21:49
Let's inline it.
chenwilliam
2017/07/05 22:35:32
Done.
| |
| 233 SDK.multitargetNetworkManager.addEventListener( | |
| 234 SDK.MultitargetNetworkManager.Events.ConditionsChanged, networkCondition sChanged.bind(this)); | |
| 235 | |
| 236 /** | |
| 237 * @this {!MobileThrottling.ThrottlingManager} | |
| 238 */ | |
| 239 function networkConditionsChanged() { | |
|
dgozman
2017/06/30 23:21:49
arrow function ftw!
chenwilliam
2017/07/05 22:35:31
Done.
| |
| 240 this._lastNetworkThrottlingConditions = this._currentNetworkThrottlingCond itions; | |
| 241 this._currentNetworkThrottlingConditions = SDK.multitargetNetworkManager.n etworkConditions(); | |
| 242 } | |
| 212 } | 243 } |
| 213 }; | 244 }; |
| 214 | 245 |
| 215 /** @typedef {!{title: string, items: !Array<!SDK.NetworkManager.Conditions>}} * / | 246 /** @enum {symbol} */ |
| 216 MobileThrottling.NetworkConditionsGroup; | 247 MobileThrottling.ThrottlingManager.Events = { |
| 217 | 248 RateChanged: Symbol('RateChanged') |
| 218 | 249 }; |
| 219 /** @type {!Array.<!SDK.NetworkManager.Conditions>} */ | |
| 220 MobileThrottling.NetworkConditionsSelector.presets = [ | |
| 221 SDK.NetworkManager.OfflineConditions, | |
| 222 {title: 'Slow 3G', download: 500 * 1024 / 8 * .8, upload: 500 * 1024 / 8 * .8, latency: 400 * 5}, | |
| 223 {title: 'Fast 3G', download: 1.6 * 1024 * 1024 / 8 * .9, upload: 750 * 1024 / 8 * .9, latency: 150 * 3.75} | |
| 224 ]; | |
| 225 | 250 |
| 226 /** | 251 /** |
| 227 * @implements {UI.ActionDelegate} | 252 * @return {!MobileThrottling.ThrottlingManager} |
| 228 * @unrestricted | |
| 229 */ | 253 */ |
| 230 MobileThrottling.NetworkConditionsActionDelegate = class { | 254 MobileThrottling.throttlingManager = function() { |
|
dgozman
2017/06/30 23:21:49
return self.singleton(MobileThrottling.ThrottlingM
chenwilliam
2017/07/05 22:35:31
Done.
| |
| 231 /** | 255 if (!MobileThrottling._throttlingManager) { |
| 232 * @override | 256 /** @type {!MobileThrottling.ThrottlingManager} */ |
| 233 * @param {!UI.Context} context | 257 MobileThrottling._throttlingManager = new MobileThrottling.ThrottlingManager (); |
| 234 * @param {string} actionId | |
| 235 * @return {boolean} | |
| 236 */ | |
| 237 handleAction(context, actionId) { | |
| 238 if (actionId === 'network-conditions.network-online') { | |
| 239 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.NoTh rottlingConditions); | |
| 240 return true; | |
| 241 } | |
| 242 if (actionId === 'network-conditions.network-offline') { | |
| 243 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Offl ineConditions); | |
| 244 return true; | |
| 245 } | |
| 246 return false; | |
| 247 } | 258 } |
| 259 return MobileThrottling._throttlingManager; | |
| 248 }; | 260 }; |
| OLD | NEW |