| /* |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| import {ObjectWrapper} from './Object.js'; |
| |
| /** |
| * @unrestricted |
| */ |
| export class Settings { |
| /** |
| * @param {!SettingsStorage} globalStorage |
| * @param {!SettingsStorage} localStorage |
| */ |
| constructor(globalStorage, localStorage) { |
| this._globalStorage = globalStorage; |
| this._localStorage = localStorage; |
| this._sessionStorage = new SettingsStorage({}); |
| |
| this._eventSupport = new ObjectWrapper(); |
| /** @type {!Map<string, !Setting>} */ |
| this._registry = new Map(); |
| /** @type {!Map<string, !Setting>} */ |
| this._moduleSettings = new Map(); |
| self.runtime.extensions('setting').forEach(this._registerModuleSetting.bind(this)); |
| } |
| |
| /** |
| * @param {!Root.Runtime.Extension} extension |
| */ |
| _registerModuleSetting(extension) { |
| const descriptor = extension.descriptor(); |
| const settingName = descriptor['settingName']; |
| const isRegex = descriptor['settingType'] === 'regex'; |
| const defaultValue = descriptor['defaultValue']; |
| let storageType; |
| switch (descriptor['storageType']) { |
| case ('local'): |
| storageType = SettingStorageType.Local; |
| break; |
| case ('session'): |
| storageType = SettingStorageType.Session; |
| break; |
| case ('global'): |
| storageType = SettingStorageType.Global; |
| break; |
| default: |
| storageType = SettingStorageType.Global; |
| } |
| const setting = isRegex ? this.createRegExpSetting(settingName, defaultValue, undefined, storageType) : |
| this.createSetting(settingName, defaultValue, storageType); |
| if (extension.title()) { |
| setting.setTitle(extension.title()); |
| } |
| if (descriptor['userActionCondition']) { |
| setting.setRequiresUserAction(!!Root.Runtime.queryParam(descriptor['userActionCondition'])); |
| } |
| setting._extension = extension; |
| this._moduleSettings.set(settingName, setting); |
| } |
| |
| /** |
| * @param {string} settingName |
| * @return {!Setting} |
| */ |
| moduleSetting(settingName) { |
| const setting = this._moduleSettings.get(settingName); |
| if (!setting) { |
| throw new Error('No setting registered: ' + settingName); |
| } |
| return setting; |
| } |
| |
| /** |
| * @param {string} settingName |
| * @return {!Setting} |
| */ |
| settingForTest(settingName) { |
| const setting = this._registry.get(settingName); |
| if (!setting) { |
| throw new Error('No setting registered: ' + settingName); |
| } |
| return setting; |
| } |
| |
| /** |
| * @param {string} key |
| * @param {*} defaultValue |
| * @param {!SettingStorageType=} storageType |
| * @return {!Setting} |
| */ |
| createSetting(key, defaultValue, storageType) { |
| const storage = this._storageFromType(storageType); |
| if (!this._registry.get(key)) { |
| this._registry.set(key, new Setting(this, key, defaultValue, this._eventSupport, storage)); |
| } |
| return /** @type {!Setting} */ (this._registry.get(key)); |
| } |
| |
| /** |
| * @param {string} key |
| * @param {*} defaultValue |
| * @return {!Setting} |
| */ |
| createLocalSetting(key, defaultValue) { |
| return this.createSetting(key, defaultValue, SettingStorageType.Local); |
| } |
| |
| /** |
| * @param {string} key |
| * @param {string} defaultValue |
| * @param {string=} regexFlags |
| * @param {!SettingStorageType=} storageType |
| * @return {!RegExpSetting} |
| */ |
| createRegExpSetting(key, defaultValue, regexFlags, storageType) { |
| if (!this._registry.get(key)) { |
| this._registry.set( |
| key, |
| new RegExpSetting( |
| this, key, defaultValue, this._eventSupport, this._storageFromType(storageType), regexFlags)); |
| } |
| return /** @type {!RegExpSetting} */ (this._registry.get(key)); |
| } |
| |
| clearAll() { |
| this._globalStorage.removeAll(); |
| this._localStorage.removeAll(); |
| const versionSetting = Common.settings.createSetting(VersionController._currentVersionName, 0); |
| versionSetting.set(VersionController.currentVersion); |
| } |
| |
| /** |
| * @param {!SettingStorageType=} storageType |
| * @return {!SettingsStorage} |
| */ |
| _storageFromType(storageType) { |
| switch (storageType) { |
| case (SettingStorageType.Local): |
| return this._localStorage; |
| case (SettingStorageType.Session): |
| return this._sessionStorage; |
| case (SettingStorageType.Global): |
| return this._globalStorage; |
| } |
| return this._globalStorage; |
| } |
| } |
| |
| /** |
| * @unrestricted |
| */ |
| export class SettingsStorage { |
| /** |
| * @param {!Object} object |
| * @param {function(string, string)=} setCallback |
| * @param {function(string)=} removeCallback |
| * @param {function(string)=} removeAllCallback |
| * @param {string=} storagePrefix |
| */ |
| constructor(object, setCallback, removeCallback, removeAllCallback, storagePrefix) { |
| this._object = object; |
| this._setCallback = setCallback || function() {}; |
| this._removeCallback = removeCallback || function() {}; |
| this._removeAllCallback = removeAllCallback || function() {}; |
| this._storagePrefix = storagePrefix || ''; |
| } |
| |
| /** |
| * @param {string} name |
| * @param {string} value |
| */ |
| set(name, value) { |
| name = this._storagePrefix + name; |
| this._object[name] = value; |
| this._setCallback(name, value); |
| } |
| |
| /** |
| * @param {string} name |
| * @return {boolean} |
| */ |
| has(name) { |
| name = this._storagePrefix + name; |
| return name in this._object; |
| } |
| |
| /** |
| * @param {string} name |
| * @return {string} |
| */ |
| get(name) { |
| name = this._storagePrefix + name; |
| return this._object[name]; |
| } |
| |
| /** |
| * @param {string} name |
| */ |
| remove(name) { |
| name = this._storagePrefix + name; |
| delete this._object[name]; |
| this._removeCallback(name); |
| } |
| |
| removeAll() { |
| this._object = {}; |
| this._removeAllCallback(); |
| } |
| |
| _dumpSizes() { |
| Common.console.log('Ten largest settings: '); |
| |
| const sizes = {__proto__: null}; |
| for (const key in this._object) { |
| sizes[key] = this._object[key].length; |
| } |
| const keys = Object.keys(sizes); |
| |
| function comparator(key1, key2) { |
| return sizes[key2] - sizes[key1]; |
| } |
| |
| keys.sort(comparator); |
| |
| for (let i = 0; i < 10 && i < keys.length; ++i) { |
| Common.console.log('Setting: \'' + keys[i] + '\', size: ' + sizes[keys[i]]); |
| } |
| } |
| } |
| |
| /** |
| * @template V |
| * @unrestricted |
| */ |
| export class Setting { |
| /** |
| * @param {!Settings} settings |
| * @param {string} name |
| * @param {V} defaultValue |
| * @param {!ObjectWrapper} eventSupport |
| * @param {!SettingsStorage} storage |
| */ |
| constructor(settings, name, defaultValue, eventSupport, storage) { |
| this._settings = settings; |
| this._name = name; |
| this._defaultValue = defaultValue; |
| this._eventSupport = eventSupport; |
| this._storage = storage; |
| /** @type {string} */ |
| this._title = ''; |
| this._extension = null; |
| } |
| |
| /** |
| * @param {function(!Common.Event)} listener |
| * @param {!Object=} thisObject |
| * @return {!Common.EventTarget.EventDescriptor} |
| */ |
| addChangeListener(listener, thisObject) { |
| return this._eventSupport.addEventListener(this._name, listener, thisObject); |
| } |
| |
| /** |
| * @param {function(!Common.Event)} listener |
| * @param {!Object=} thisObject |
| */ |
| removeChangeListener(listener, thisObject) { |
| this._eventSupport.removeEventListener(this._name, listener, thisObject); |
| } |
| |
| get name() { |
| return this._name; |
| } |
| |
| /** |
| * @return {string} |
| */ |
| title() { |
| return this._title; |
| } |
| |
| /** |
| * @param {string} title |
| */ |
| setTitle(title) { |
| this._title = title; |
| } |
| |
| /** |
| * @param {boolean} requiresUserAction |
| */ |
| setRequiresUserAction(requiresUserAction) { |
| this._requiresUserAction = requiresUserAction; |
| } |
| |
| /** |
| * @return {V} |
| */ |
| get() { |
| if (this._requiresUserAction && !this._hadUserAction) { |
| return this._defaultValue; |
| } |
| |
| if (typeof this._value !== 'undefined') { |
| return this._value; |
| } |
| |
| this._value = this._defaultValue; |
| if (this._storage.has(this._name)) { |
| try { |
| this._value = JSON.parse(this._storage.get(this._name)); |
| } catch (e) { |
| this._storage.remove(this._name); |
| } |
| } |
| return this._value; |
| } |
| |
| /** |
| * @param {V} value |
| */ |
| set(value) { |
| this._hadUserAction = true; |
| this._value = value; |
| try { |
| const settingString = JSON.stringify(value); |
| try { |
| this._storage.set(this._name, settingString); |
| } catch (e) { |
| this._printSettingsSavingError(e.message, this._name, settingString); |
| } |
| } catch (e) { |
| Common.console.error('Cannot stringify setting with name: ' + this._name + ', error: ' + e.message); |
| } |
| this._eventSupport.dispatchEventToListeners(this._name, value); |
| } |
| |
| remove() { |
| this._settings._registry.delete(this._name); |
| this._settings._moduleSettings.delete(this._name); |
| this._storage.remove(this._name); |
| } |
| |
| /** |
| * @return {?Root.Runtime.Extension} |
| */ |
| extension() { |
| return this._extension; |
| } |
| |
| /** |
| * @param {string} message |
| * @param {string} name |
| * @param {string} value |
| */ |
| _printSettingsSavingError(message, name, value) { |
| const errorMessage = |
| 'Error saving setting with name: ' + this._name + ', value length: ' + value.length + '. Error: ' + message; |
| console.error(errorMessage); |
| Common.console.error(errorMessage); |
| this._storage._dumpSizes(); |
| } |
| } |
| |
| /** |
| * @unrestricted |
| */ |
| export class RegExpSetting extends Setting { |
| /** |
| * @param {!Settings} settings |
| * @param {string} name |
| * @param {string} defaultValue |
| * @param {!ObjectWrapper} eventSupport |
| * @param {!SettingsStorage} storage |
| * @param {string=} regexFlags |
| */ |
| constructor(settings, name, defaultValue, eventSupport, storage, regexFlags) { |
| super(settings, name, defaultValue ? [{pattern: defaultValue}] : [], eventSupport, storage); |
| this._regexFlags = regexFlags; |
| } |
| |
| /** |
| * @override |
| * @return {string} |
| */ |
| get() { |
| const result = []; |
| const items = this.getAsArray(); |
| for (let i = 0; i < items.length; ++i) { |
| const item = items[i]; |
| if (item.pattern && !item.disabled) { |
| result.push(item.pattern); |
| } |
| } |
| return result.join('|'); |
| } |
| |
| /** |
| * @return {!Array.<{pattern: string, disabled: (boolean|undefined)}>} |
| */ |
| getAsArray() { |
| return super.get(); |
| } |
| |
| /** |
| * @override |
| * @param {string} value |
| */ |
| set(value) { |
| this.setAsArray([{pattern: value}]); |
| } |
| |
| /** |
| * @param {!Array.<{pattern: string, disabled: (boolean|undefined)}>} value |
| */ |
| setAsArray(value) { |
| delete this._regex; |
| super.set(value); |
| } |
| |
| /** |
| * @return {?RegExp} |
| */ |
| asRegExp() { |
| if (typeof this._regex !== 'undefined') { |
| return this._regex; |
| } |
| this._regex = null; |
| try { |
| const pattern = this.get(); |
| if (pattern) { |
| this._regex = new RegExp(pattern, this._regexFlags || ''); |
| } |
| } catch (e) { |
| } |
| return this._regex; |
| } |
| } |
| |
| /** |
| * @unrestricted |
| */ |
| export class VersionController { |
| static get _currentVersionName() { |
| return 'inspectorVersion'; |
| } |
| |
| static get currentVersion() { |
| return 28; |
| } |
| |
| updateVersion() { |
| const localStorageVersion = window.localStorage ? window.localStorage[VersionController._currentVersionName] : 0; |
| const versionSetting = Common.settings.createSetting(VersionController._currentVersionName, 0); |
| const currentVersion = VersionController.currentVersion; |
| const oldVersion = versionSetting.get() || parseInt(localStorageVersion || '0', 10); |
| if (oldVersion === 0) { |
| // First run, no need to do anything. |
| versionSetting.set(currentVersion); |
| return; |
| } |
| const methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion); |
| for (let i = 0; i < methodsToRun.length; ++i) { |
| this[methodsToRun[i]].call(this); |
| } |
| versionSetting.set(currentVersion); |
| } |
| |
| /** |
| * @param {number} oldVersion |
| * @param {number} currentVersion |
| */ |
| _methodsToRunToUpdateVersion(oldVersion, currentVersion) { |
| const result = []; |
| for (let i = oldVersion; i < currentVersion; ++i) { |
| result.push('_updateVersionFrom' + i + 'To' + (i + 1)); |
| } |
| return result; |
| } |
| |
| _updateVersionFrom0To1() { |
| this._clearBreakpointsWhenTooMany(Common.settings.createLocalSetting('breakpoints', []), 500000); |
| } |
| |
| _updateVersionFrom1To2() { |
| Common.settings.createSetting('previouslyViewedFiles', []).set([]); |
| } |
| |
| _updateVersionFrom2To3() { |
| Common.settings.createSetting('fileSystemMapping', {}).set({}); |
| Common.settings.createSetting('fileMappingEntries', []).remove(); |
| } |
| |
| _updateVersionFrom3To4() { |
| const advancedMode = Common.settings.createSetting('showHeaSnapshotObjectsHiddenProperties', false); |
| moduleSetting('showAdvancedHeapSnapshotProperties').set(advancedMode.get()); |
| advancedMode.remove(); |
| } |
| |
| _updateVersionFrom4To5() { |
| const settingNames = { |
| 'FileSystemViewSidebarWidth': 'fileSystemViewSplitViewState', |
| 'elementsSidebarWidth': 'elementsPanelSplitViewState', |
| 'StylesPaneSplitRatio': 'stylesPaneSplitViewState', |
| 'heapSnapshotRetainersViewSize': 'heapSnapshotSplitViewState', |
| 'InspectorView.splitView': 'InspectorView.splitViewState', |
| 'InspectorView.screencastSplitView': 'InspectorView.screencastSplitViewState', |
| 'Inspector.drawerSplitView': 'Inspector.drawerSplitViewState', |
| 'layerDetailsSplitView': 'layerDetailsSplitViewState', |
| 'networkSidebarWidth': 'networkPanelSplitViewState', |
| 'sourcesSidebarWidth': 'sourcesPanelSplitViewState', |
| 'scriptsPanelNavigatorSidebarWidth': 'sourcesPanelNavigatorSplitViewState', |
| 'sourcesPanelSplitSidebarRatio': 'sourcesPanelDebuggerSidebarSplitViewState', |
| 'timeline-details': 'timelinePanelDetailsSplitViewState', |
| 'timeline-split': 'timelinePanelRecorsSplitViewState', |
| 'timeline-view': 'timelinePanelTimelineStackSplitViewState', |
| 'auditsSidebarWidth': 'auditsPanelSplitViewState', |
| 'layersSidebarWidth': 'layersPanelSplitViewState', |
| 'profilesSidebarWidth': 'profilesPanelSplitViewState', |
| 'resourcesSidebarWidth': 'resourcesPanelSplitViewState' |
| }; |
| const empty = {}; |
| for (const oldName in settingNames) { |
| const newName = settingNames[oldName]; |
| const oldNameH = oldName + 'H'; |
| |
| let newValue = null; |
| const oldSetting = Common.settings.createSetting(oldName, empty); |
| if (oldSetting.get() !== empty) { |
| newValue = newValue || {}; |
| newValue.vertical = {}; |
| newValue.vertical.size = oldSetting.get(); |
| oldSetting.remove(); |
| } |
| const oldSettingH = Common.settings.createSetting(oldNameH, empty); |
| if (oldSettingH.get() !== empty) { |
| newValue = newValue || {}; |
| newValue.horizontal = {}; |
| newValue.horizontal.size = oldSettingH.get(); |
| oldSettingH.remove(); |
| } |
| if (newValue) { |
| Common.settings.createSetting(newName, {}).set(newValue); |
| } |
| } |
| } |
| |
| _updateVersionFrom5To6() { |
| const settingNames = { |
| 'debuggerSidebarHidden': 'sourcesPanelSplitViewState', |
| 'navigatorHidden': 'sourcesPanelNavigatorSplitViewState', |
| 'WebInspector.Drawer.showOnLoad': 'Inspector.drawerSplitViewState' |
| }; |
| |
| for (const oldName in settingNames) { |
| const oldSetting = Common.settings.createSetting(oldName, null); |
| if (oldSetting.get() === null) { |
| oldSetting.remove(); |
| continue; |
| } |
| |
| const newName = settingNames[oldName]; |
| const invert = oldName === 'WebInspector.Drawer.showOnLoad'; |
| const hidden = oldSetting.get() !== invert; |
| oldSetting.remove(); |
| const showMode = hidden ? 'OnlyMain' : 'Both'; |
| |
| const newSetting = Common.settings.createSetting(newName, {}); |
| const newValue = newSetting.get() || {}; |
| newValue.vertical = newValue.vertical || {}; |
| newValue.vertical.showMode = showMode; |
| newValue.horizontal = newValue.horizontal || {}; |
| newValue.horizontal.showMode = showMode; |
| newSetting.set(newValue); |
| } |
| } |
| |
| _updateVersionFrom6To7() { |
| const settingNames = { |
| 'sourcesPanelNavigatorSplitViewState': 'sourcesPanelNavigatorSplitViewState', |
| 'elementsPanelSplitViewState': 'elementsPanelSplitViewState', |
| 'stylesPaneSplitViewState': 'stylesPaneSplitViewState', |
| 'sourcesPanelDebuggerSidebarSplitViewState': 'sourcesPanelDebuggerSidebarSplitViewState' |
| }; |
| |
| const empty = {}; |
| for (const name in settingNames) { |
| const setting = Common.settings.createSetting(name, empty); |
| const value = setting.get(); |
| if (value === empty) { |
| continue; |
| } |
| // Zero out saved percentage sizes, and they will be restored to defaults. |
| if (value.vertical && value.vertical.size && value.vertical.size < 1) { |
| value.vertical.size = 0; |
| } |
| if (value.horizontal && value.horizontal.size && value.horizontal.size < 1) { |
| value.horizontal.size = 0; |
| } |
| setting.set(value); |
| } |
| } |
| |
| _updateVersionFrom7To8() { |
| } |
| |
| _updateVersionFrom8To9() { |
| const settingNames = ['skipStackFramesPattern', 'workspaceFolderExcludePattern']; |
| |
| for (let i = 0; i < settingNames.length; ++i) { |
| const setting = Common.settings.createSetting(settingNames[i], ''); |
| let value = setting.get(); |
| if (!value) { |
| return; |
| } |
| if (typeof value === 'string') { |
| value = [value]; |
| } |
| for (let j = 0; j < value.length; ++j) { |
| if (typeof value[j] === 'string') { |
| value[j] = {pattern: value[j]}; |
| } |
| } |
| setting.set(value); |
| } |
| } |
| |
| _updateVersionFrom9To10() { |
| // This one is localStorage specific, which is fine. |
| if (!window.localStorage) { |
| return; |
| } |
| for (const key in window.localStorage) { |
| if (key.startsWith('revision-history')) { |
| window.localStorage.removeItem(key); |
| } |
| } |
| } |
| |
| _updateVersionFrom10To11() { |
| const oldSettingName = 'customDevicePresets'; |
| const newSettingName = 'customEmulatedDeviceList'; |
| const oldSetting = Common.settings.createSetting(oldSettingName, undefined); |
| const list = oldSetting.get(); |
| if (!Array.isArray(list)) { |
| return; |
| } |
| const newList = []; |
| for (let i = 0; i < list.length; ++i) { |
| const value = list[i]; |
| const device = {}; |
| device['title'] = value['title']; |
| device['type'] = 'unknown'; |
| device['user-agent'] = value['userAgent']; |
| device['capabilities'] = []; |
| if (value['touch']) { |
| device['capabilities'].push('touch'); |
| } |
| if (value['mobile']) { |
| device['capabilities'].push('mobile'); |
| } |
| device['screen'] = {}; |
| device['screen']['vertical'] = {width: value['width'], height: value['height']}; |
| device['screen']['horizontal'] = {width: value['height'], height: value['width']}; |
| device['screen']['device-pixel-ratio'] = value['deviceScaleFactor']; |
| device['modes'] = []; |
| device['show-by-default'] = true; |
| device['show'] = 'Default'; |
| newList.push(device); |
| } |
| if (newList.length) { |
| Common.settings.createSetting(newSettingName, []).set(newList); |
| } |
| oldSetting.remove(); |
| } |
| |
| _updateVersionFrom11To12() { |
| this._migrateSettingsFromLocalStorage(); |
| } |
| |
| _updateVersionFrom12To13() { |
| this._migrateSettingsFromLocalStorage(); |
| Common.settings.createSetting('timelineOverviewMode', '').remove(); |
| } |
| |
| _updateVersionFrom13To14() { |
| const defaultValue = {'throughput': -1, 'latency': 0}; |
| Common.settings.createSetting('networkConditions', defaultValue).set(defaultValue); |
| } |
| |
| _updateVersionFrom14To15() { |
| const setting = Common.settings.createLocalSetting('workspaceExcludedFolders', {}); |
| const oldValue = setting.get(); |
| const newValue = {}; |
| for (const fileSystemPath in oldValue) { |
| newValue[fileSystemPath] = []; |
| for (const entry of oldValue[fileSystemPath]) { |
| newValue[fileSystemPath].push(entry.path); |
| } |
| } |
| setting.set(newValue); |
| } |
| |
| _updateVersionFrom15To16() { |
| const setting = Common.settings.createSetting('InspectorView.panelOrder', {}); |
| const tabOrders = setting.get(); |
| for (const key of Object.keys(tabOrders)) { |
| tabOrders[key] = (tabOrders[key] + 1) * 10; |
| } |
| setting.set(tabOrders); |
| } |
| |
| _updateVersionFrom16To17() { |
| const setting = Common.settings.createSetting('networkConditionsCustomProfiles', []); |
| const oldValue = setting.get(); |
| const newValue = []; |
| if (Array.isArray(oldValue)) { |
| for (const preset of oldValue) { |
| if (typeof preset.title === 'string' && typeof preset.value === 'object' && |
| typeof preset.value.throughput === 'number' && typeof preset.value.latency === 'number') { |
| newValue.push({ |
| title: preset.title, |
| value: |
| {download: preset.value.throughput, upload: preset.value.throughput, latency: preset.value.latency} |
| }); |
| } |
| } |
| } |
| setting.set(newValue); |
| } |
| |
| _updateVersionFrom17To18() { |
| const setting = Common.settings.createLocalSetting('workspaceExcludedFolders', {}); |
| const oldValue = setting.get(); |
| const newValue = {}; |
| for (const oldKey in oldValue) { |
| let newKey = oldKey.replace(/\\/g, '/'); |
| if (!newKey.startsWith('file://')) { |
| if (newKey.startsWith('/')) { |
| newKey = 'file://' + newKey; |
| } else { |
| newKey = 'file:///' + newKey; |
| } |
| } |
| newValue[newKey] = oldValue[oldKey]; |
| } |
| setting.set(newValue); |
| } |
| |
| _updateVersionFrom18To19() { |
| const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true}; |
| const visibleColumnSettings = Common.settings.createSetting('networkLogColumnsVisibility', defaultColumns); |
| const visibleColumns = visibleColumnSettings.get(); |
| visibleColumns.name = true; |
| visibleColumns.timeline = true; |
| |
| const configs = {}; |
| for (const columnId in visibleColumns) { |
| if (!visibleColumns.hasOwnProperty(columnId)) { |
| continue; |
| } |
| configs[columnId.toLowerCase()] = {visible: visibleColumns[columnId]}; |
| } |
| const newSetting = Common.settings.createSetting('networkLogColumns', {}); |
| newSetting.set(configs); |
| visibleColumnSettings.remove(); |
| } |
| |
| _updateVersionFrom19To20() { |
| const oldSetting = Common.settings.createSetting('InspectorView.panelOrder', {}); |
| const newSetting = Common.settings.createSetting('panel-tabOrder', {}); |
| newSetting.set(oldSetting.get()); |
| oldSetting.remove(); |
| } |
| |
| _updateVersionFrom20To21() { |
| const networkColumns = Common.settings.createSetting('networkLogColumns', {}); |
| const columns = /** @type {!Object} */ (networkColumns.get()); |
| delete columns['timeline']; |
| delete columns['waterfall']; |
| networkColumns.set(columns); |
| } |
| |
| _updateVersionFrom21To22() { |
| const breakpointsSetting = Common.settings.createLocalSetting('breakpoints', []); |
| const breakpoints = breakpointsSetting.get(); |
| for (const breakpoint of breakpoints) { |
| breakpoint['url'] = breakpoint['sourceFileId']; |
| delete breakpoint['sourceFileId']; |
| } |
| breakpointsSetting.set(breakpoints); |
| } |
| |
| _updateVersionFrom22To23() { |
| // This update is no-op. |
| } |
| |
| _updateVersionFrom23To24() { |
| const oldSetting = Common.settings.createSetting('searchInContentScripts', false); |
| const newSetting = Common.settings.createSetting('searchInAnonymousAndContentScripts', false); |
| newSetting.set(oldSetting.get()); |
| oldSetting.remove(); |
| } |
| |
| _updateVersionFrom24To25() { |
| const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true}; |
| const networkLogColumnsSetting = Common.settings.createSetting('networkLogColumns', defaultColumns); |
| const columns = networkLogColumnsSetting.get(); |
| delete columns.product; |
| networkLogColumnsSetting.set(columns); |
| } |
| |
| _updateVersionFrom25To26() { |
| const oldSetting = Common.settings.createSetting('messageURLFilters', {}); |
| const urls = Object.keys(oldSetting.get()); |
| const textFilter = urls.map(url => `-url:${url}`).join(' '); |
| if (textFilter) { |
| const textFilterSetting = Common.settings.createSetting('console.textFilter', ''); |
| const suffix = textFilterSetting.get() ? ` ${textFilterSetting.get()}` : ''; |
| textFilterSetting.set(`${textFilter}${suffix}`); |
| } |
| oldSetting.remove(); |
| } |
| |
| _updateVersionFrom26To27() { |
| /** |
| * @param {string} settingName |
| * @param {string} from |
| * @param {string} to |
| */ |
| function renameKeyInObjectSetting(settingName, from, to) { |
| const setting = Common.settings.createSetting(settingName, {}); |
| const value = setting.get(); |
| if (from in value) { |
| value[to] = value[from]; |
| delete value[from]; |
| setting.set(value); |
| } |
| } |
| |
| /** |
| * @param {string} settingName |
| * @param {string} from |
| * @param {string} to |
| */ |
| function renameInStringSetting(settingName, from, to) { |
| const setting = Common.settings.createSetting(settingName, ''); |
| const value = setting.get(); |
| if (value === from) { |
| setting.set(to); |
| } |
| } |
| |
| renameKeyInObjectSetting('panel-tabOrder', 'audits2', 'audits'); |
| renameKeyInObjectSetting('panel-closeableTabs', 'audits2', 'audits'); |
| renameInStringSetting('panel-selectedTab', 'audits2', 'audits'); |
| } |
| |
| _updateVersionFrom27To28() { |
| const setting = Common.settings.createSetting('uiTheme', 'systemPreferred'); |
| if (setting.get() === 'default') { |
| setting.set('systemPreferred'); |
| } |
| } |
| |
| _migrateSettingsFromLocalStorage() { |
| // This step migrates all the settings except for the ones below into the browser profile. |
| const localSettings = new Set([ |
| 'advancedSearchConfig', 'breakpoints', 'consoleHistory', 'domBreakpoints', 'eventListenerBreakpoints', |
| 'fileSystemMapping', 'lastSelectedSourcesSidebarPaneTab', 'previouslyViewedFiles', 'savedURLs', |
| 'watchExpressions', 'workspaceExcludedFolders', 'xhrBreakpoints' |
| ]); |
| if (!window.localStorage) { |
| return; |
| } |
| |
| for (const key in window.localStorage) { |
| if (localSettings.has(key)) { |
| continue; |
| } |
| const value = window.localStorage[key]; |
| window.localStorage.removeItem(key); |
| Common.settings._globalStorage[key] = value; |
| } |
| } |
| |
| /** |
| * @param {!Setting} breakpointsSetting |
| * @param {number} maxBreakpointsCount |
| */ |
| _clearBreakpointsWhenTooMany(breakpointsSetting, maxBreakpointsCount) { |
| // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused |
| // periodical breakpoints duplication leading to inspector slowness. |
| if (breakpointsSetting.get().length > maxBreakpointsCount) { |
| breakpointsSetting.set([]); |
| } |
| } |
| } |
| |
| /** |
| * @enum {symbol} |
| */ |
| export const SettingStorageType = { |
| Global: Symbol('Global'), |
| Local: Symbol('Local'), |
| Session: Symbol('Session') |
| }; |
| |
| /** |
| * @param {string} settingName |
| * @return {!Setting} |
| */ |
| export function moduleSetting(settingName) { |
| return Common.settings.moduleSetting(settingName); |
| } |
| |
| /** |
| * @param {string} settingName |
| * @return {!Setting} |
| */ |
| export function settingForTest(settingName) { |
| return Common.settings.settingForTest(settingName); |
| } |