blob: c2f0faa8689fda64fa83837daada1f39fc8ca8d2 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright 2017 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 * @implements {SDK.SDKModelObserver<!SDK.EmulationModel>}
7 */
8MobileThrottling.ThrottlingManager = class extends Common.Object {
9 constructor() {
10 super();
11 /** @type {!MobileThrottling.CPUThrottlingRates} */
12 this._cpuThrottlingRate = MobileThrottling.CPUThrottlingRates.NoThrottling;
13 /** @type {!Set<!UI.ToolbarComboBox>} */
14 this._cpuThrottlingControls = new Set();
15 this._cpuThrottlingRates = MobileThrottling.cpuThrottlingPresets;
16 /** @type {!Common.Setting<!Array<!SDK.NetworkManager.Conditions>>} */
17 this._customNetworkConditionsSetting = Common.moduleSetting('customNetworkConditions');
18 /** @type {!SDK.NetworkManager.Conditions} */
19 this._currentNetworkThrottlingConditions = SDK.NetworkManager.NoThrottlingConditions;
20 /** @type {!SDK.NetworkManager.Conditions} */
21 this._lastNetworkThrottlingConditions;
22
23 SDK.multitargetNetworkManager.addEventListener(SDK.MultitargetNetworkManager.Events.ConditionsChanged, () => {
24 this._lastNetworkThrottlingConditions = this._currentNetworkThrottlingConditions;
25 this._currentNetworkThrottlingConditions = SDK.multitargetNetworkManager.networkConditions();
26 });
27
28 SDK.targetManager.observeModels(SDK.EmulationModel, this);
29 }
30
31
32 /**
33 * @param {!HTMLSelectElement} selectElement
34 * @return {!MobileThrottling.NetworkThrottlingSelector}
35 */
36 decorateSelectWithNetworkThrottling(selectElement) {
37 let options = [];
38 const selector =
39 new MobileThrottling.NetworkThrottlingSelector(populate, select, this._customNetworkConditionsSetting);
40 selectElement.addEventListener('change', optionSelected, false);
41 return selector;
42
43 /**
44 * @param {!Array.<!MobileThrottling.NetworkThrottlingConditionsGroup>} groups
45 * @return {!Array<?SDK.NetworkManager.Conditions>}
46 */
47 function populate(groups) {
48 selectElement.removeChildren();
49 options = [];
50 for (let i = 0; i < groups.length; ++i) {
51 const group = groups[i];
52 const groupElement = selectElement.createChild('optgroup');
53 groupElement.label = group.title;
54 for (const conditions of group.items) {
55 const title = conditions.title;
56 const option = new Option(title, title);
57 groupElement.appendChild(option);
58 options.push(conditions);
59 }
60 if (i === groups.length - 1) {
61 groupElement.appendChild(new Option(Common.UIString('Add\u2026'), Common.UIString('Add\u2026')));
62 options.push(null);
63 }
64 }
65 return options;
66 }
67
68 function optionSelected() {
69 if (selectElement.selectedIndex === selectElement.options.length - 1)
70 selector.revealAndUpdate();
71 else
72 selector.optionSelected(options[selectElement.selectedIndex]);
73 }
74
75 /**
76 * @param {number} index
77 */
78 function select(index) {
79 if (selectElement.selectedIndex !== index)
80 selectElement.selectedIndex = index;
81 }
82 }
83
84 /**
85 * @return {!UI.ToolbarCheckbox}
86 */
87 createOfflineToolbarCheckbox() {
88 const checkbox = new UI.ToolbarCheckbox(
89 Common.UIString('Offline'), Common.UIString('Force disconnected from network'), forceOffline.bind(this));
90 SDK.multitargetNetworkManager.addEventListener(
91 SDK.MultitargetNetworkManager.Events.ConditionsChanged, networkConditionsChanged);
92 checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SDK.NetworkManager.OfflineConditions);
93
94 /**
95 * @this {!MobileThrottling.ThrottlingManager}
96 */
97 function forceOffline() {
98 if (checkbox.checked())
99 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions);
100 else
101 SDK.multitargetNetworkManager.setNetworkConditions(this._lastNetworkThrottlingConditions);
102 }
103
104 function networkConditionsChanged() {
105 checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SDK.NetworkManager.OfflineConditions);
106 }
107
108 return checkbox;
109 }
110
111
112 /**
113 * @return {!UI.ToolbarMenuButton}
114 */
115 createMobileThrottlingButton() {
116 const button = new UI.ToolbarMenuButton(appendItems);
117 button.setTitle(Common.UIString('Throttling'));
118 button.setGlyph('');
119 button.turnIntoSelect();
120 button.setDarkText();
121
122 /** @type {!MobileThrottling.ConditionsList} */
123 let options = [];
124 let selectedIndex = -1;
125 const selector = new MobileThrottling.MobileThrottlingSelector(populate, select);
126 return button;
127
128 /**
129 * @param {!UI.ContextMenu} contextMenu
130 */
131 function appendItems(contextMenu) {
132 for (let index = 0; index < options.length; ++index) {
133 const conditions = options[index];
134 if (!conditions)
135 continue;
136 if (conditions.title === MobileThrottling.CustomConditions.title &&
137 conditions.description === MobileThrottling.CustomConditions.description)
138 continue;
139 contextMenu.defaultSection().appendCheckboxItem(
140 Common.UIString(conditions.title),
141 selector.optionSelected.bind(selector, /** @type {!MobileThrottling.Conditions} */ (conditions)),
142 selectedIndex === index);
143 }
144 }
145
146 /**
147 * @param {!Array.<!MobileThrottling.MobileThrottlingConditionsGroup>} groups
148 * @return {!MobileThrottling.ConditionsList}
149 */
150 function populate(groups) {
151 options = [];
152 for (const group of groups) {
153 for (const conditions of group.items)
154 options.push(conditions);
155 options.push(null);
156 }
157 return options;
158 }
159
160 /**
161 * @param {number} index
162 */
163 function select(index) {
164 selectedIndex = index;
165 button.setText(options[index].title);
166 button.setTitle(options[index].description);
167 }
168 }
169
170 /**
171 * @return {number}
172 */
173 cpuThrottlingRate() {
174 return this._cpuThrottlingRate;
175 }
176
177 /**
178 * @param {!MobileThrottling.CPUThrottlingRates} rate
179 */
180 setCPUThrottlingRate(rate) {
181 this._cpuThrottlingRate = rate;
182 for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
183 emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate);
184 let icon = null;
185 if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrottling) {
186 Host.userMetrics.actionTaken(Host.UserMetrics.Action.CpuThrottlingEnabled);
187 icon = UI.Icon.create('smallicon-warning');
188 icon.title = Common.UIString('CPU throttling is enabled');
189 }
190 const index = this._cpuThrottlingRates.indexOf(this._cpuThrottlingRate);
191 for (const control of this._cpuThrottlingControls)
192 control.setSelectedIndex(index);
193 UI.inspectorView.setPanelIcon('timeline', icon);
194 this.dispatchEventToListeners(MobileThrottling.ThrottlingManager.Events.RateChanged, this._cpuThrottlingRate);
195 }
196
197 /**
198 * @override
199 * @param {!SDK.EmulationModel} emulationModel
200 */
201 modelAdded(emulationModel) {
202 if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrottling)
203 emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate);
204 }
205
206 /**
207 * @override
208 * @param {!SDK.EmulationModel} emulationModel
209 */
210 modelRemoved(emulationModel) {
211 }
212
213 /**
214 * @return {!UI.ToolbarComboBox}
215 */
216 createCPUThrottlingSelector() {
217 const control = new UI.ToolbarComboBox(
218 event => this.setCPUThrottlingRate(this._cpuThrottlingRates[event.target.selectedIndex]));
219 this._cpuThrottlingControls.add(control);
220 const currentRate = this._cpuThrottlingRate;
221
222 for (let i = 0; i < this._cpuThrottlingRates.length; ++i) {
223 const rate = this._cpuThrottlingRates[i];
224 const title = rate === 1 ? Common.UIString('No throttling') : Common.UIString('%d\xD7 slowdown', rate);
225 const option = control.createOption(title);
226 control.addOption(option);
227 if (currentRate === rate)
228 control.setSelectedIndex(i);
229 }
230 return control;
231 }
232};
233
234/** @enum {symbol} */
235MobileThrottling.ThrottlingManager.Events = {
236 RateChanged: Symbol('RateChanged')
237};
238
239/**
240 * @implements {UI.ActionDelegate}
241 */
242MobileThrottling.ThrottlingManager.ActionDelegate = class {
243 /**
244 * @override
245 * @param {!UI.Context} context
246 * @param {string} actionId
247 * @return {boolean}
248 */
249 handleAction(context, actionId) {
250 if (actionId === 'network-conditions.network-online') {
251 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.NoThrottlingConditions);
252 return true;
253 }
Erik Luo02da2892018-06-15 19:08:28254 if (actionId === 'network-conditions.network-low-end-mobile') {
255 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Slow3GConditions);
256 return true;
257 }
258 if (actionId === 'network-conditions.network-mid-tier-mobile') {
259 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Fast3GConditions);
260 return true;
261 }
Blink Reformat4c46d092018-04-07 15:32:37262 if (actionId === 'network-conditions.network-offline') {
263 SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions);
264 return true;
265 }
266 return false;
267 }
268};
269
270/**
271 * @return {!MobileThrottling.ThrottlingManager}
272 */
273MobileThrottling.throttlingManager = function() {
274 return self.singleton(MobileThrottling.ThrottlingManager);
275};