| /* |
| * 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; |