|  | /* | 
|  | * Copyright (C) 2013 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. | 
|  | */ | 
|  | /** | 
|  | * @implements {UI.ViewLocationResolver} | 
|  | * @unrestricted | 
|  | */ | 
|  | export default class SettingsScreen extends UI.VBox { | 
|  | constructor() { | 
|  | super(true); | 
|  | this.registerRequiredCSS('settings/settingsScreen.css'); | 
|  |  | 
|  | this.contentElement.classList.add('settings-window-main'); | 
|  | this.contentElement.classList.add('vbox'); | 
|  |  | 
|  | const settingsLabelElement = createElement('div'); | 
|  | const settingsTitleElement = UI.createShadowRootWithCoreStyles(settingsLabelElement, 'settings/settingsScreen.css') | 
|  | .createChild('div', 'settings-window-title'); | 
|  |  | 
|  | UI.ARIAUtils.markAsHeading(settingsTitleElement, 1); | 
|  | settingsTitleElement.textContent = ls`Settings`; | 
|  |  | 
|  | this._tabbedLocation = | 
|  | UI.viewManager.createTabbedLocation(() => SettingsScreen._showSettingsScreen(), 'settings-view'); | 
|  | const tabbedPane = this._tabbedLocation.tabbedPane(); | 
|  | tabbedPane.leftToolbar().appendToolbarItem(new UI.ToolbarItem(settingsLabelElement)); | 
|  | tabbedPane.setShrinkableTabs(false); | 
|  | tabbedPane.makeVerticalTabLayout(); | 
|  | const shortcutsView = new UI.SimpleView(ls`Shortcuts`); | 
|  | UI.shortcutsScreen.createShortcutsTabView().show(shortcutsView.element); | 
|  | this._tabbedLocation.appendView(shortcutsView); | 
|  | tabbedPane.show(this.contentElement); | 
|  |  | 
|  | this.element.addEventListener('keydown', this._keyDown.bind(this), false); | 
|  | this._developerModeCounter = 0; | 
|  | this.setDefaultFocusedElement(this.contentElement); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {string=} name | 
|  | */ | 
|  | static _showSettingsScreen(name) { | 
|  | const settingsScreen = | 
|  | /** @type {!Settings.SettingsScreen} */ (self.runtime.sharedInstance(SettingsScreen)); | 
|  | if (settingsScreen.isShowing()) { | 
|  | return; | 
|  | } | 
|  | const dialog = new UI.Dialog(); | 
|  | dialog.contentElement.tabIndex = -1; | 
|  | dialog.addCloseButton(); | 
|  | dialog.setOutsideClickCallback(() => {}); | 
|  | dialog.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.PierceGlassPane); | 
|  | dialog.setOutsideTabIndexBehavior(UI.Dialog.OutsideTabIndexBehavior.PreserveMainViewTabIndex); | 
|  | settingsScreen.show(dialog.contentElement); | 
|  | dialog.show(); | 
|  | settingsScreen._selectTab(name || 'preferences'); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @override | 
|  | * @param {string} locationName | 
|  | * @return {?UI.ViewLocation} | 
|  | */ | 
|  | resolveLocation(locationName) { | 
|  | return this._tabbedLocation; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {string} name | 
|  | */ | 
|  | _selectTab(name) { | 
|  | UI.viewManager.showView(name); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Event} event | 
|  | */ | 
|  | _keyDown(event) { | 
|  | const shiftKeyCode = 16; | 
|  | if (event.keyCode === shiftKeyCode && ++this._developerModeCounter > 5) { | 
|  | this.contentElement.classList.add('settings-developer-mode'); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @unrestricted | 
|  | */ | 
|  | class SettingsTab extends UI.VBox { | 
|  | /** | 
|  | * @param {string} name | 
|  | * @param {string=} id | 
|  | */ | 
|  | constructor(name, id) { | 
|  | super(); | 
|  | this.element.classList.add('settings-tab-container'); | 
|  | if (id) { | 
|  | this.element.id = id; | 
|  | } | 
|  | const header = this.element.createChild('header'); | 
|  | header.createChild('h1').createTextChild(name); | 
|  | this.containerElement = this.element.createChild('div', 'settings-container-wrapper') | 
|  | .createChild('div', 'settings-tab settings-content settings-container'); | 
|  | } | 
|  |  | 
|  | /** | 
|  | *  @param {string=} name | 
|  | *  @return {!Element} | 
|  | */ | 
|  | _appendSection(name) { | 
|  | const block = this.containerElement.createChild('div', 'settings-block'); | 
|  | if (name) { | 
|  | UI.ARIAUtils.markAsGroup(block); | 
|  | const title = block.createChild('div', 'settings-section-title'); | 
|  | title.textContent = name; | 
|  | UI.ARIAUtils.markAsHeading(title, 2); | 
|  | UI.ARIAUtils.setAccessibleName(block, name); | 
|  | } | 
|  | return block; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @unrestricted | 
|  | */ | 
|  | export class GenericSettingsTab extends SettingsTab { | 
|  | constructor() { | 
|  | super(Common.UIString('Preferences'), 'preferences-tab-content'); | 
|  |  | 
|  | /** @const */ | 
|  | const explicitSectionOrder = | 
|  | ['', 'Appearance', 'Sources', 'Elements', 'Network', 'Performance', 'Console', 'Extensions']; | 
|  | /** @type {!Map<string, !Element>} */ | 
|  | this._nameToSection = new Map(); | 
|  | for (const sectionName of explicitSectionOrder) { | 
|  | this._sectionElement(sectionName); | 
|  | } | 
|  | self.runtime.extensions('setting').forEach(this._addSetting.bind(this)); | 
|  | self.runtime.extensions(UI.SettingUI).forEach(this._addSettingUI.bind(this)); | 
|  |  | 
|  | this._appendSection().appendChild( | 
|  | UI.createTextButton(Common.UIString('Restore defaults and reload'), restoreAndReload)); | 
|  |  | 
|  | function restoreAndReload() { | 
|  | Common.settings.clearAll(); | 
|  | Components.reload(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | * @return {boolean} | 
|  | */ | 
|  | static isSettingVisible(extension) { | 
|  | const descriptor = extension.descriptor(); | 
|  | if (!('title' in descriptor)) { | 
|  | return false; | 
|  | } | 
|  | if (!('category' in descriptor)) { | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | */ | 
|  | _addSetting(extension) { | 
|  | if (!GenericSettingsTab.isSettingVisible(extension)) { | 
|  | return; | 
|  | } | 
|  | const sectionElement = this._sectionElement(extension.descriptor()['category']); | 
|  | const setting = Common.moduleSetting(extension.descriptor()['settingName']); | 
|  | const settingControl = UI.SettingsUI.createControlForSetting(setting); | 
|  | if (settingControl) { | 
|  | sectionElement.appendChild(settingControl); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | */ | 
|  | _addSettingUI(extension) { | 
|  | const descriptor = extension.descriptor(); | 
|  | const sectionName = descriptor['category'] || ''; | 
|  | extension.instance().then(appendCustomSetting.bind(this)); | 
|  |  | 
|  | /** | 
|  | * @param {!Object} object | 
|  | * @this {Settings.GenericSettingsTab} | 
|  | */ | 
|  | function appendCustomSetting(object) { | 
|  | const settingUI = /** @type {!UI.SettingUI} */ (object); | 
|  | const element = settingUI.settingElement(); | 
|  | if (element) { | 
|  | this._sectionElement(sectionName).appendChild(element); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {string} sectionName | 
|  | * @return {!Element} | 
|  | */ | 
|  | _sectionElement(sectionName) { | 
|  | let sectionElement = this._nameToSection.get(sectionName); | 
|  | if (!sectionElement) { | 
|  | const uiSectionName = sectionName && Common.UIString(sectionName); | 
|  | sectionElement = this._appendSection(uiSectionName); | 
|  | this._nameToSection.set(sectionName, sectionElement); | 
|  | } | 
|  | return sectionElement; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @unrestricted | 
|  | */ | 
|  | export class ExperimentsSettingsTab extends SettingsTab { | 
|  | constructor() { | 
|  | super(Common.UIString('Experiments'), 'experiments-tab-content'); | 
|  |  | 
|  | const experiments = Root.Runtime.experiments.allConfigurableExperiments(); | 
|  | if (experiments.length) { | 
|  | const experimentsSection = this._appendSection(); | 
|  | experimentsSection.appendChild(this._createExperimentsWarningSubsection()); | 
|  | for (let i = 0; i < experiments.length; ++i) { | 
|  | experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i])); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return {!Element} element | 
|  | */ | 
|  | _createExperimentsWarningSubsection() { | 
|  | const subsection = createElement('div'); | 
|  | const warning = subsection.createChild('span', 'settings-experiments-warning-subsection-warning'); | 
|  | warning.textContent = Common.UIString('WARNING:'); | 
|  | subsection.createTextChild(' '); | 
|  | const message = subsection.createChild('span', 'settings-experiments-warning-subsection-message'); | 
|  | message.textContent = Common.UIString('These experiments could be dangerous and may require restart.'); | 
|  | return subsection; | 
|  | } | 
|  |  | 
|  | _createExperimentCheckbox(experiment) { | 
|  | const label = UI.CheckboxLabel.create(Common.UIString(experiment.title), experiment.isEnabled()); | 
|  | const input = label.checkboxElement; | 
|  | input.name = experiment.name; | 
|  | function listener() { | 
|  | experiment.setEnabled(input.checked); | 
|  | } | 
|  | input.addEventListener('click', listener, false); | 
|  |  | 
|  | const p = createElement('p'); | 
|  | p.className = experiment.hidden && !experiment.isEnabled() ? 'settings-experiment-hidden' : ''; | 
|  | p.appendChild(label); | 
|  | return p; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @implements {UI.ActionDelegate} | 
|  | * @unrestricted | 
|  | */ | 
|  | export class ActionDelegate { | 
|  | /** | 
|  | * @override | 
|  | * @param {!UI.Context} context | 
|  | * @param {string} actionId | 
|  | * @return {boolean} | 
|  | */ | 
|  | handleAction(context, actionId) { | 
|  | switch (actionId) { | 
|  | case 'settings.show': | 
|  | SettingsScreen._showSettingsScreen(); | 
|  | return true; | 
|  | case 'settings.documentation': | 
|  | Host.InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/'); | 
|  | return true; | 
|  | case 'settings.shortcuts': | 
|  | SettingsScreen._showSettingsScreen(Common.UIString('Shortcuts')); | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @implements {Common.Revealer} | 
|  | * @unrestricted | 
|  | */ | 
|  | export class Revealer { | 
|  | /** | 
|  | * @override | 
|  | * @param {!Object} object | 
|  | * @return {!Promise} | 
|  | */ | 
|  | reveal(object) { | 
|  | console.assert(object instanceof Common.Setting); | 
|  | const setting = /** @type {!Common.Setting} */ (object); | 
|  | let success = false; | 
|  |  | 
|  | self.runtime.extensions('setting').forEach(revealModuleSetting); | 
|  | self.runtime.extensions(UI.SettingUI).forEach(revealSettingUI); | 
|  | self.runtime.extensions('view').forEach(revealSettingsView); | 
|  |  | 
|  | return success ? Promise.resolve() : Promise.reject(); | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | */ | 
|  | function revealModuleSetting(extension) { | 
|  | if (!GenericSettingsTab.isSettingVisible(extension)) { | 
|  | return; | 
|  | } | 
|  | if (extension.descriptor()['settingName'] === setting.name) { | 
|  | Host.InspectorFrontendHost.bringToFront(); | 
|  | SettingsScreen._showSettingsScreen(); | 
|  | success = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | */ | 
|  | function revealSettingUI(extension) { | 
|  | const settings = extension.descriptor()['settings']; | 
|  | if (settings && settings.indexOf(setting.name) !== -1) { | 
|  | Host.InspectorFrontendHost.bringToFront(); | 
|  | SettingsScreen._showSettingsScreen(); | 
|  | success = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @param {!Root.Runtime.Extension} extension | 
|  | */ | 
|  | function revealSettingsView(extension) { | 
|  | const location = extension.descriptor()['location']; | 
|  | if (location !== 'settings-view') { | 
|  | return; | 
|  | } | 
|  | const settings = extension.descriptor()['settings']; | 
|  | if (settings && settings.indexOf(setting.name) !== -1) { | 
|  | Host.InspectorFrontendHost.bringToFront(); | 
|  | SettingsScreen._showSettingsScreen(extension.descriptor()['id']); | 
|  | success = true; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Legacy exported object */ | 
|  | self.Settings = self.Settings || {}; | 
|  |  | 
|  | /* Legacy exported object */ | 
|  | Settings = Settings || {}; | 
|  |  | 
|  | /** | 
|  | * @constructor | 
|  | */ | 
|  | Settings.SettingsScreen = SettingsScreen; | 
|  |  | 
|  | /** | 
|  | * @implements {UI.ActionDelegate} | 
|  | * @unrestricted | 
|  | * @constructor | 
|  | */ | 
|  | Settings.SettingsScreen.ActionDelegate = ActionDelegate; | 
|  |  | 
|  | /** | 
|  | * @implements {Common.Revealer} | 
|  | * @unrestricted | 
|  | * @constructor | 
|  | */ | 
|  | Settings.SettingsScreen.Revealer = Revealer; | 
|  |  | 
|  | /** | 
|  | * @constructor | 
|  | */ | 
|  | Settings.GenericSettingsTab = GenericSettingsTab; | 
|  |  | 
|  | /** | 
|  | * @constructor | 
|  | */ | 
|  | Settings.ExperimentsSettingsTab = ExperimentsSettingsTab; |