1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/** 32 * @constructor 33 * @param {!function()} onHide 34 * @extends {WebInspector.HelpScreen} 35 */ 36WebInspector.SettingsScreen = function(onHide) 37{ 38 WebInspector.HelpScreen.call(this); 39 this.element.id = "settings-screen"; 40 41 /** @type {function()} */ 42 this._onHide = onHide; 43 44 this._tabbedPane = new WebInspector.TabbedPane(); 45 this._tabbedPane.element.addStyleClass("help-window-main"); 46 var settingsLabelElement = document.createElement("div"); 47 settingsLabelElement.className = "help-window-label"; 48 settingsLabelElement.createTextChild(WebInspector.UIString("Settings")); 49 this._tabbedPane.element.insertBefore(settingsLabelElement, this._tabbedPane.element.firstChild); 50 this._tabbedPane.element.appendChild(this._createCloseButton()); 51 this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.General, WebInspector.UIString("General"), new WebInspector.GenericSettingsTab()); 52 if (!WebInspector.experimentsSettings.showOverridesInDrawer.isEnabled()) 53 this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Overrides, WebInspector.UIString("Overrides"), new WebInspector.OverridesSettingsTab()); 54 if (WebInspector.experimentsSettings.fileSystemProject.isEnabled()) 55 this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Workspace, WebInspector.UIString("Workspace"), new WebInspector.WorkspaceSettingsTab()); 56 if (WebInspector.experimentsSettings.experimentsEnabled) 57 this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Experiments, WebInspector.UIString("Experiments"), new WebInspector.ExperimentsSettingsTab()); 58 this._tabbedPane.appendTab(WebInspector.SettingsScreen.Tabs.Shortcuts, WebInspector.UIString("Shortcuts"), WebInspector.shortcutsScreen.createShortcutsTabView()); 59 this._tabbedPane.shrinkableTabs = false; 60 this._tabbedPane.verticalTabLayout = true; 61 62 this._lastSelectedTabSetting = WebInspector.settings.createSetting("lastSelectedSettingsTab", WebInspector.SettingsScreen.Tabs.General); 63 this.selectTab(this._lastSelectedTabSetting.get()); 64 this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); 65} 66 67WebInspector.SettingsScreen.Tabs = { 68 General: "general", 69 Overrides: "overrides", 70 Workspace: "workspace", 71 Experiments: "experiments", 72 Shortcuts: "shortcuts" 73} 74 75WebInspector.SettingsScreen.prototype = { 76 /** 77 * @param {string} tabId 78 */ 79 selectTab: function(tabId) 80 { 81 this._tabbedPane.selectTab(tabId); 82 }, 83 84 /** 85 * @param {WebInspector.Event} event 86 */ 87 _tabSelected: function(event) 88 { 89 this._lastSelectedTabSetting.set(this._tabbedPane.selectedTabId); 90 }, 91 92 /** 93 * @override 94 */ 95 wasShown: function() 96 { 97 this._tabbedPane.show(this.element); 98 WebInspector.HelpScreen.prototype.wasShown.call(this); 99 }, 100 101 /** 102 * @override 103 */ 104 isClosingKey: function(keyCode) 105 { 106 return [ 107 WebInspector.KeyboardShortcut.Keys.Enter.code, 108 WebInspector.KeyboardShortcut.Keys.Esc.code, 109 ].indexOf(keyCode) >= 0; 110 }, 111 112 /** 113 * @override 114 */ 115 willHide: function() 116 { 117 this._onHide(); 118 WebInspector.HelpScreen.prototype.willHide.call(this); 119 }, 120 121 __proto__: WebInspector.HelpScreen.prototype 122} 123 124/** 125 * @constructor 126 * @extends {WebInspector.View} 127 * @param {string} name 128 * @param {string=} id 129 */ 130WebInspector.SettingsTab = function(name, id) 131{ 132 WebInspector.View.call(this); 133 this.element.className = "settings-tab-container"; 134 if (id) 135 this.element.id = id; 136 var header = this.element.createChild("header"); 137 header.createChild("h3").appendChild(document.createTextNode(name)); 138 this.containerElement = this.element.createChild("div", "help-container-wrapper").createChild("div", "settings-tab help-content help-container"); 139} 140 141WebInspector.SettingsTab.prototype = { 142 /** 143 * @param {string=} name 144 * @return {!Element} 145 */ 146 _appendSection: function(name) 147 { 148 var block = this.containerElement.createChild("div", "help-block"); 149 if (name) 150 block.createChild("div", "help-section-title").textContent = name; 151 return block; 152 }, 153 154 /** 155 * @param {boolean=} omitParagraphElement 156 * @param {Element=} inputElement 157 */ 158 _createCheckboxSetting: function(name, setting, omitParagraphElement, inputElement) 159 { 160 var input = inputElement || document.createElement("input"); 161 input.type = "checkbox"; 162 input.name = name; 163 input.checked = setting.get(); 164 165 function listener() 166 { 167 setting.set(input.checked); 168 } 169 input.addEventListener("click", listener, false); 170 171 var label = document.createElement("label"); 172 label.appendChild(input); 173 label.appendChild(document.createTextNode(name)); 174 if (omitParagraphElement) 175 return label; 176 177 var p = document.createElement("p"); 178 p.appendChild(label); 179 return p; 180 }, 181 182 _createSelectSetting: function(name, options, setting) 183 { 184 var fieldsetElement = document.createElement("fieldset"); 185 fieldsetElement.createChild("label").textContent = name; 186 187 var select = document.createElement("select"); 188 var settingValue = setting.get(); 189 190 for (var i = 0; i < options.length; ++i) { 191 var option = options[i]; 192 select.add(new Option(option[0], option[1])); 193 if (settingValue === option[1]) 194 select.selectedIndex = i; 195 } 196 197 function changeListener(e) 198 { 199 setting.set(e.target.value); 200 } 201 202 select.addEventListener("change", changeListener, false); 203 fieldsetElement.appendChild(select); 204 205 var p = document.createElement("p"); 206 p.appendChild(fieldsetElement); 207 return p; 208 }, 209 210 _createRadioSetting: function(name, options, setting) 211 { 212 var pp = document.createElement("p"); 213 var fieldsetElement = document.createElement("fieldset"); 214 var legendElement = document.createElement("legend"); 215 legendElement.textContent = name; 216 fieldsetElement.appendChild(legendElement); 217 218 function clickListener(e) 219 { 220 setting.set(e.target.value); 221 } 222 223 var settingValue = setting.get(); 224 for (var i = 0; i < options.length; ++i) { 225 var p = document.createElement("p"); 226 var label = document.createElement("label"); 227 p.appendChild(label); 228 229 var input = document.createElement("input"); 230 input.type = "radio"; 231 input.name = setting.name; 232 input.value = options[i][0]; 233 input.addEventListener("click", clickListener, false); 234 if (settingValue == input.value) 235 input.checked = true; 236 237 label.appendChild(input); 238 label.appendChild(document.createTextNode(options[i][1])); 239 240 fieldsetElement.appendChild(p); 241 } 242 243 pp.appendChild(fieldsetElement); 244 return pp; 245 }, 246 247 /** 248 * @param {string} label 249 * @param {WebInspector.Setting} setting 250 * @param {boolean} numeric 251 * @param {number=} maxLength 252 * @param {string=} width 253 * @param {function(string):boolean=} validatorCallback 254 */ 255 _createInputSetting: function(label, setting, numeric, maxLength, width, validatorCallback) 256 { 257 var fieldset = document.createElement("fieldset"); 258 var p = fieldset.createChild("p"); 259 var labelElement = p.createChild("label"); 260 labelElement.textContent = label + " "; 261 var inputElement = labelElement.createChild("input"); 262 inputElement.value = setting.get(); 263 inputElement.type = "text"; 264 if (numeric) 265 inputElement.className = "numeric"; 266 if (maxLength) 267 inputElement.maxLength = maxLength; 268 if (width) 269 inputElement.style.width = width; 270 271 function onBlur() 272 { 273 if (validatorCallback && !validatorCallback(inputElement.value)) { 274 inputElement.value = setting.get(); 275 return; 276 } 277 setting.set(numeric ? Number(inputElement.value) : inputElement.value); 278 } 279 inputElement.addEventListener("blur", onBlur, false); 280 return fieldset; 281 }, 282 283 _createCustomSetting: function(name, element) 284 { 285 var p = document.createElement("p"); 286 var fieldsetElement = document.createElement("fieldset"); 287 fieldsetElement.createChild("label").textContent = name; 288 fieldsetElement.appendChild(element); 289 p.appendChild(fieldsetElement); 290 return p; 291 }, 292 293 __proto__: WebInspector.View.prototype 294} 295 296/** 297 * @constructor 298 * @extends {WebInspector.SettingsTab} 299 */ 300WebInspector.GenericSettingsTab = function() 301{ 302 WebInspector.SettingsTab.call(this, WebInspector.UIString("General")); 303 304 var p = this._appendSection(); 305 if (Preferences.exposeDisableCache) 306 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Disable cache"), WebInspector.settings.cacheDisabled)); 307 var disableJSElement = this._createCheckboxSetting(WebInspector.UIString("Disable JavaScript"), WebInspector.settings.javaScriptDisabled); 308 p.appendChild(disableJSElement); 309 WebInspector.settings.javaScriptDisabled.addChangeListener(this._javaScriptDisabledChanged, this); 310 this._disableJSCheckbox = disableJSElement.getElementsByTagName("input")[0]; 311 this._updateScriptDisabledCheckbox(); 312 313 p = this._appendSection(WebInspector.UIString("Appearance")); 314 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show toolbar icons"), WebInspector.settings.showToolbarIcons)); 315 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Split panels vertically when docked to right"), WebInspector.settings.splitVerticallyWhenDockedToRight)); 316 317 p = this._appendSection(WebInspector.UIString("Elements")); 318 p.appendChild(this._createRadioSetting(WebInspector.UIString("Color format"), [ 319 [ WebInspector.Color.Format.Original, WebInspector.UIString("As authored") ], 320 [ WebInspector.Color.Format.HEX, "HEX: #DAC0DE" ], 321 [ WebInspector.Color.Format.RGB, "RGB: rgb(128, 255, 255)" ], 322 [ WebInspector.Color.Format.HSL, "HSL: hsl(300, 80%, 90%)" ] ], WebInspector.settings.colorFormat)); 323 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show user agent styles"), WebInspector.settings.showUserAgentStyles)); 324 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Word wrap"), WebInspector.settings.domWordWrap)); 325 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show Shadow DOM"), WebInspector.settings.showShadowDOM)); 326 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show rulers"), WebInspector.settings.showMetricsRulers)); 327 328 p = this._appendSection(WebInspector.UIString("Rendering")); 329 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show paint rectangles"), WebInspector.settings.showPaintRects)); 330 WebInspector.settings.showPaintRects.addChangeListener(this._showPaintRectsChanged, this); 331 332 if (Capabilities.canShowDebugBorders) { 333 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show composited layer borders"), WebInspector.settings.showDebugBorders)); 334 WebInspector.settings.showDebugBorders.addChangeListener(this._showDebugBordersChanged, this); 335 } 336 if (Capabilities.canShowFPSCounter) { 337 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show FPS meter"), WebInspector.settings.showFPSCounter)); 338 WebInspector.settings.showFPSCounter.addChangeListener(this._showFPSCounterChanged, this); 339 } 340 if (Capabilities.canContinuouslyPaint) { 341 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Enable continuous page repainting"), WebInspector.settings.continuousPainting)); 342 WebInspector.settings.continuousPainting.addChangeListener(this._continuousPaintingChanged, this); 343 } 344 345 p = this._appendSection(WebInspector.UIString("Sources")); 346 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Search in content scripts"), WebInspector.settings.searchInContentScripts)); 347 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Enable source maps"), WebInspector.settings.sourceMapsEnabled)); 348 if (WebInspector.experimentsSettings.isEnabled("sass")) 349 p.appendChild(this._createCSSAutoReloadControls()); 350 var indentationElement = this._createSelectSetting(WebInspector.UIString("Indentation"), [ 351 [ WebInspector.UIString("2 spaces"), WebInspector.TextUtils.Indent.TwoSpaces ], 352 [ WebInspector.UIString("4 spaces"), WebInspector.TextUtils.Indent.FourSpaces ], 353 [ WebInspector.UIString("8 spaces"), WebInspector.TextUtils.Indent.EightSpaces ], 354 [ WebInspector.UIString("Tab character"), WebInspector.TextUtils.Indent.TabCharacter ] 355 ], WebInspector.settings.textEditorIndent); 356 indentationElement.firstChild.className = "toplevel"; 357 p.appendChild(indentationElement); 358 359 p = this._appendSection(WebInspector.UIString("Profiler")); 360 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show objects' hidden properties"), WebInspector.settings.showHeapSnapshotObjectsHiddenProperties)); 361 362 p = this._appendSection(WebInspector.UIString("Timeline")); 363 var checkbox = this._createCheckboxSetting(WebInspector.UIString("Limit number of captured JS stack frames"), WebInspector.settings.timelineLimitStackFramesFlag); 364 p.appendChild(checkbox); 365 var fieldset = this._createInputSetting(WebInspector.UIString("Frames to capture"), WebInspector.settings.timelineStackFramesToCapture, true, 2, "2em"); 366 fieldset.disabled = !WebInspector.settings.timelineLimitStackFramesFlag.get(); 367 WebInspector.settings.timelineLimitStackFramesFlag.addChangeListener(this._timelineLimitStackFramesChanged.bind(this, fieldset)); 368 checkbox.appendChild(fieldset); 369 370 if (Capabilities.timelineCanMonitorMainThread) 371 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show CPU activity on the ruler"), WebInspector.settings.showCpuOnTimelineRuler)); 372 373 p = this._appendSection(WebInspector.UIString("Console")); 374 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Log XMLHttpRequests"), WebInspector.settings.monitoringXHREnabled)); 375 p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Preserve log upon navigation"), WebInspector.settings.preserveConsoleLog)); 376 377 if (WebInspector.extensionServer.hasExtensions()) { 378 var handlerSelector = new WebInspector.HandlerSelector(WebInspector.openAnchorLocationRegistry); 379 p = this._appendSection(WebInspector.UIString("Extensions")); 380 p.appendChild(this._createCustomSetting(WebInspector.UIString("Open links in"), handlerSelector.element)); 381 } 382} 383 384WebInspector.GenericSettingsTab.prototype = { 385 _showPaintRectsChanged: function() 386 { 387 PageAgent.setShowPaintRects(WebInspector.settings.showPaintRects.get()); 388 }, 389 390 _showDebugBordersChanged: function() 391 { 392 PageAgent.setShowDebugBorders(WebInspector.settings.showDebugBorders.get()); 393 }, 394 395 _showFPSCounterChanged: function() 396 { 397 PageAgent.setShowFPSCounter(WebInspector.settings.showFPSCounter.get()); 398 }, 399 400 _continuousPaintingChanged: function() 401 { 402 PageAgent.setContinuousPaintingEnabled(WebInspector.settings.continuousPainting.get()); 403 }, 404 405 /** 406 * @param {HTMLFieldSetElement} fieldset 407 */ 408 _timelineLimitStackFramesChanged: function(fieldset) 409 { 410 fieldset.disabled = !WebInspector.settings.timelineLimitStackFramesFlag.get(); 411 }, 412 413 _updateScriptDisabledCheckbox: function() 414 { 415 function executionStatusCallback(error, status) 416 { 417 if (error || !status) 418 return; 419 420 switch (status) { 421 case "forbidden": 422 this._disableJSCheckbox.checked = true; 423 this._disableJSCheckbox.disabled = true; 424 break; 425 case "disabled": 426 this._disableJSCheckbox.checked = true; 427 break; 428 default: 429 this._disableJSCheckbox.checked = false; 430 break; 431 } 432 } 433 434 PageAgent.getScriptExecutionStatus(executionStatusCallback.bind(this)); 435 }, 436 437 _javaScriptDisabledChanged: function() 438 { 439 // We need to manually update the checkbox state, since enabling JavaScript in the page can actually uncover the "forbidden" state. 440 PageAgent.setScriptExecutionDisabled(WebInspector.settings.javaScriptDisabled.get(), this._updateScriptDisabledCheckbox.bind(this)); 441 }, 442 443 _createCSSAutoReloadControls: function() 444 { 445 var fragment = document.createDocumentFragment(); 446 var labelElement = fragment.createChild("label"); 447 var checkboxElement = labelElement.createChild("input"); 448 checkboxElement.type = "checkbox"; 449 checkboxElement.checked = WebInspector.settings.cssReloadEnabled.get(); 450 checkboxElement.addEventListener("click", checkboxClicked, false); 451 labelElement.appendChild(document.createTextNode(WebInspector.UIString("Auto-reload CSS upon Sass save"))); 452 453 var fieldsetElement = this._createInputSetting(WebInspector.UIString("Timeout (ms)"), WebInspector.settings.cssReloadTimeout, true, 8, "60px", validateReloadTimeout); 454 fieldsetElement.disabled = !checkboxElement.checked; 455 fragment.appendChild(fieldsetElement); 456 return fragment; 457 458 function checkboxClicked() 459 { 460 var reloadEnabled = checkboxElement.checked; 461 WebInspector.settings.cssReloadEnabled.set(reloadEnabled); 462 fieldsetElement.disabled = !reloadEnabled; 463 } 464 465 function validateReloadTimeout(value) 466 { 467 return isFinite(value) && value > 0; 468 } 469 }, 470 471 __proto__: WebInspector.SettingsTab.prototype 472} 473 474/** 475 * @constructor 476 * @extends {WebInspector.SettingsTab} 477 */ 478WebInspector.OverridesSettingsTab = function() 479{ 480 WebInspector.SettingsTab.call(this, WebInspector.UIString("Overrides"), "overrides-tab-content"); 481 this._view = new WebInspector.OverridesView(); 482 this.containerElement.parentElement.appendChild(this._view.containerElement); 483 this.containerElement.removeSelf(); 484 this.containerElement = this._view.containerElement; 485} 486 487WebInspector.OverridesSettingsTab.prototype = { 488 __proto__: WebInspector.SettingsTab.prototype 489} 490 491/** 492 * @constructor 493 * @extends {WebInspector.SettingsTab} 494 */ 495WebInspector.WorkspaceSettingsTab = function() 496{ 497 WebInspector.SettingsTab.call(this, WebInspector.UIString("Workspace"), "workspace-tab-content"); 498 this._reset(); 499} 500 501WebInspector.WorkspaceSettingsTab.prototype = { 502 wasShown: function() 503 { 504 WebInspector.SettingsTab.prototype.wasShown.call(this); 505 this._reset(); 506 }, 507 508 _reset: function() 509 { 510 this.containerElement.removeChildren(); 511 this._createFileSystemsEditor(); 512 this._createFileMappingEditor(); 513 }, 514 515 _createFileSystemsEditor: function() 516 { 517 var p = this._appendSection(WebInspector.UIString("File systems")); 518 this._fileSystemsEditor = p.createChild("p", "file-systems-editor"); 519 520 this._addFileSystemRowElement = this._fileSystemsEditor.createChild("div", "workspace-settings-row"); 521 var addFileSystemButton = this._addFileSystemRowElement.createChild("input", "file-system-add-button"); 522 addFileSystemButton.type = "button"; 523 addFileSystemButton.value = WebInspector.UIString("Add file system"); 524 addFileSystemButton.addEventListener("click", this._addFileSystemClicked.bind(this)); 525 526 var fileSystemPaths = WebInspector.isolatedFileSystemManager.mapping().fileSystemPaths(); 527 for (var i = 0; i < fileSystemPaths.length; ++i) 528 this._addFileSystemRow(fileSystemPaths[i]); 529 530 return this._fileSystemsEditor; 531 }, 532 533 /** 534 * @return {Element} 535 */ 536 _createShowTextInput: function(className, value) 537 { 538 var inputElement = document.createElement("input"); 539 inputElement.addStyleClass(className); 540 inputElement.type = "text"; 541 inputElement.value = value; 542 inputElement.title = value; 543 inputElement.disabled = true; 544 return inputElement; 545 }, 546 547 /** 548 * @return {Element} 549 */ 550 _createEditTextInput: function(className, placeHolder) 551 { 552 var inputElement = document.createElement("input"); 553 inputElement.addStyleClass(className); 554 inputElement.type = "text"; 555 inputElement.placeholder = placeHolder; 556 return inputElement; 557 }, 558 559 /** 560 * @param {function(Event)} handler 561 * @return {Element} 562 */ 563 _createRemoveButton: function(handler) 564 { 565 var removeButton = document.createElement("button"); 566 removeButton.addStyleClass("button"); 567 removeButton.addStyleClass("remove-button"); 568 removeButton.value = WebInspector.UIString("Remove"); 569 removeButton.addEventListener("click", handler, false); 570 return removeButton; 571 }, 572 573 /** 574 * @param {function(Event)} handler 575 * @return {Element} 576 */ 577 _createAddButton: function(handler) 578 { 579 var addButton = document.createElement("button"); 580 addButton.addStyleClass("button"); 581 addButton.addStyleClass("add-button"); 582 addButton.value = WebInspector.UIString("Add"); 583 addButton.addEventListener("click", handler, false); 584 return addButton; 585 }, 586 587 /** 588 * @param {string} fileSystemPath 589 */ 590 _addFileSystemRow: function(fileSystemPath) 591 { 592 var fileSystemRow = document.createElement("div"); 593 fileSystemRow.addStyleClass("workspace-settings-row"); 594 fileSystemRow.addStyleClass("file-system-row"); 595 this._fileSystemsEditor.insertBefore(fileSystemRow, this._addFileSystemRowElement); 596 597 fileSystemRow.appendChild(this._createShowTextInput("file-system-path", fileSystemPath)); 598 var removeFileSystemButton = this._createRemoveButton(removeFileSystemClicked.bind(this)); 599 fileSystemRow.appendChild(removeFileSystemButton); 600 601 function removeFileSystemClicked() 602 { 603 removeFileSystemButton.disabled = true; 604 WebInspector.isolatedFileSystemManager.removeFileSystem(fileSystemPath, fileSystemRemoved.bind(this)); 605 } 606 607 function fileSystemRemoved() 608 { 609 this._fileSystemsEditor.removeChild(fileSystemRow); 610 removeFileSystemButton.disabled = false; 611 } 612 }, 613 614 _addFileSystemClicked: function() 615 { 616 WebInspector.isolatedFileSystemManager.addFileSystem(this._fileSystemAdded.bind(this)); 617 }, 618 619 /** 620 * @param {?string} fileSystemPath 621 */ 622 _fileSystemAdded: function(fileSystemPath) 623 { 624 if (fileSystemPath) 625 this._addFileSystemRow(fileSystemPath); 626 }, 627 628 _createFileMappingEditor: function() 629 { 630 var p = this._appendSection(WebInspector.UIString("Mappings")); 631 this._fileMappingEditor = p.createChild("p", "file-mappings-editor"); 632 633 this._addMappingRowElement = this._fileMappingEditor.createChild("div", "workspace-settings-row"); 634 635 this._urlInputElement = this._createEditTextInput("file-mapping-url", WebInspector.UIString("File mapping url")); 636 this._addMappingRowElement.appendChild(this._urlInputElement); 637 this._pathInputElement = this._createEditTextInput("file-mapping-path", WebInspector.UIString("File mapping path")); 638 this._addMappingRowElement.appendChild(this._pathInputElement); 639 640 this._addMappingRowElement.appendChild(this._createAddButton(this._addFileMappingClicked.bind(this))); 641 642 var mappingEntries = WebInspector.fileMapping.mappingEntries(); 643 for (var i = 0; i < mappingEntries.length; ++i) 644 this._addMappingRow(mappingEntries[i]); 645 646 return this._fileMappingEditor; 647 }, 648 649 /** 650 * @param {WebInspector.FileMapping.Entry} mappingEntry 651 */ 652 _addMappingRow: function(mappingEntry) 653 { 654 var fileMappingRow = document.createElement("div"); 655 fileMappingRow.addStyleClass("workspace-settings-row"); 656 this._fileMappingEditor.insertBefore(fileMappingRow, this._addMappingRowElement); 657 658 fileMappingRow.appendChild(this._createShowTextInput("file-mapping-url", mappingEntry.urlPrefix)); 659 fileMappingRow.appendChild(this._createShowTextInput("file-mapping-path", mappingEntry.pathPrefix)); 660 661 fileMappingRow.appendChild(this._createRemoveButton(removeMappingClicked.bind(this))); 662 663 function removeMappingClicked() 664 { 665 var index = Array.prototype.slice.call(fileMappingRow.parentElement.childNodes).indexOf(fileMappingRow); 666 var mappingEntries = WebInspector.fileMapping.mappingEntries(); 667 mappingEntries.splice(index, 1); 668 WebInspector.fileMapping.setMappingEntries(mappingEntries); 669 this._fileMappingEditor.removeChild(fileMappingRow); 670 } 671 }, 672 673 _addFileMappingClicked: function() 674 { 675 var url = this._urlInputElement.value; 676 var path = this._pathInputElement.value; 677 if (!url || !path) 678 return; 679 var mappingEntries = WebInspector.fileMapping.mappingEntries(); 680 if (url[url.length - 1] !== "/") 681 url += "/"; 682 if (path[path.length - 1] !== "/") 683 path += "/"; 684 var mappingEntry = new WebInspector.FileMapping.Entry(url, path); 685 mappingEntries.push(mappingEntry); 686 WebInspector.fileMapping.setMappingEntries(mappingEntries); 687 this._addMappingRow(mappingEntry); 688 this._urlInputElement.value = ""; 689 this._pathInputElement.value = ""; 690 }, 691 692 __proto__: WebInspector.SettingsTab.prototype 693} 694 695/** 696 * @constructor 697 * @extends {WebInspector.SettingsTab} 698 */ 699WebInspector.ExperimentsSettingsTab = function() 700{ 701 WebInspector.SettingsTab.call(this, WebInspector.UIString("Experiments"), "experiments-tab-content"); 702 703 var experiments = WebInspector.experimentsSettings.experiments; 704 if (experiments.length) { 705 var experimentsSection = this._appendSection(); 706 experimentsSection.appendChild(this._createExperimentsWarningSubsection()); 707 for (var i = 0; i < experiments.length; ++i) 708 experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i])); 709 } 710} 711 712WebInspector.ExperimentsSettingsTab.prototype = { 713 /** 714 * @return {Element} element 715 */ 716 _createExperimentsWarningSubsection: function() 717 { 718 var subsection = document.createElement("div"); 719 var warning = subsection.createChild("span", "settings-experiments-warning-subsection-warning"); 720 warning.textContent = WebInspector.UIString("WARNING:"); 721 subsection.appendChild(document.createTextNode(" ")); 722 var message = subsection.createChild("span", "settings-experiments-warning-subsection-message"); 723 message.textContent = WebInspector.UIString("These experiments could be dangerous and may require restart."); 724 return subsection; 725 }, 726 727 _createExperimentCheckbox: function(experiment) 728 { 729 var input = document.createElement("input"); 730 input.type = "checkbox"; 731 input.name = experiment.name; 732 input.checked = experiment.isEnabled(); 733 function listener() 734 { 735 experiment.setEnabled(input.checked); 736 } 737 input.addEventListener("click", listener, false); 738 739 var p = document.createElement("p"); 740 var label = document.createElement("label"); 741 label.appendChild(input); 742 label.appendChild(document.createTextNode(WebInspector.UIString(experiment.title))); 743 p.appendChild(label); 744 return p; 745 }, 746 747 __proto__: WebInspector.SettingsTab.prototype 748} 749 750/** 751 * @constructor 752 */ 753WebInspector.SettingsController = function() 754{ 755 this._statusBarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Settings"), "settings-status-bar-item"); 756 if (WebInspector.experimentsSettings.showOverridesInDrawer.isEnabled()) 757 this._statusBarButton.element.addEventListener("mousedown", this._mouseDown.bind(this), false); 758 else 759 this._statusBarButton.element.addEventListener("mouseup", this._mouseUp.bind(this), false); 760 761 /** @type {?WebInspector.SettingsScreen} */ 762 this._settingsScreen; 763} 764 765WebInspector.SettingsController.prototype = 766{ 767 get statusBarItem() 768 { 769 return this._statusBarButton.element; 770 }, 771 772 /** 773 * @param {Event} event 774 */ 775 _mouseDown: function(event) 776 { 777 var contextMenu = new WebInspector.ContextMenu(event); 778 contextMenu.appendItem(WebInspector.UIString("Overrides"), showOverrides.bind(this)); 779 contextMenu.appendItem(WebInspector.UIString("Settings"), showSettings.bind(this)); 780 781 function showOverrides() 782 { 783 if (this._settingsScreenVisible) 784 this._hideSettingsScreen(); 785 WebInspector.OverridesView.showInDrawer(); 786 } 787 788 function showSettings() 789 { 790 if (!this._settingsScreenVisible) 791 this.showSettingsScreen(); 792 } 793 794 contextMenu.showSoftMenu(); 795 }, 796 797 /** 798 * @param {Event} event 799 */ 800 _mouseUp: function(event) 801 { 802 this.showSettingsScreen(); 803 }, 804 805 _onHideSettingsScreen: function() 806 { 807 delete this._settingsScreenVisible; 808 }, 809 810 /** 811 * @param {string=} tabId 812 */ 813 showSettingsScreen: function(tabId) 814 { 815 if (!this._settingsScreen) 816 this._settingsScreen = new WebInspector.SettingsScreen(this._onHideSettingsScreen.bind(this)); 817 818 if (tabId) 819 this._settingsScreen.selectTab(tabId); 820 821 this._settingsScreen.showModal(); 822 this._settingsScreenVisible = true; 823 }, 824 825 _hideSettingsScreen: function() 826 { 827 if (this._settingsScreen) 828 this._settingsScreen.hide(); 829 }, 830 831 resize: function() 832 { 833 if (this._settingsScreen && this._settingsScreen.isShowing()) 834 this._settingsScreen.doResize(); 835 } 836} 837