Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (C) 2009 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  */
     34 WebInspector.Settings = function()
     35 {
     36     this._eventSupport = new WebInspector.Object();
     37     this._registry = /** @type {!Object.<string, !WebInspector.Setting>} */ ({});
     38 
     39     this.colorFormat = this.createSetting("colorFormat", "original");
     40     this.consoleHistory = this.createSetting("consoleHistory", []);
     41     this.domWordWrap = this.createSetting("domWordWrap", true);
     42     this.eventListenersFilter = this.createSetting("eventListenersFilter", "all");
     43     this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application");
     44     this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false);
     45     this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false);
     46     this.consoleTimestampsEnabled = this.createSetting("consoleTimestampsEnabled", false);
     47     this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true);
     48     this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
     49     this.resourceViewTab = this.createSetting("resourceViewTab", "preview");
     50     this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false);
     51     this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true);
     52     this.watchExpressions = this.createSetting("watchExpressions", []);
     53     this.breakpoints = this.createSetting("breakpoints", []);
     54     this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []);
     55     this.domBreakpoints = this.createSetting("domBreakpoints", []);
     56     this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []);
     57     this.jsSourceMapsEnabled = this.createSetting("sourceMapsEnabled", true);
     58     this.cssSourceMapsEnabled = this.createSetting("cssSourceMapsEnabled", true);
     59     this.cacheDisabled = this.createSetting("cacheDisabled", false);
     60     this.showUAShadowDOM = this.createSetting("showUAShadowDOM", false);
     61     this.savedURLs = this.createSetting("savedURLs", {});
     62     this.javaScriptDisabled = this.createSetting("javaScriptDisabled", false);
     63     this.showAdvancedHeapSnapshotProperties = this.createSetting("showAdvancedHeapSnapshotProperties", false);
     64     this.recordAllocationStacks = this.createSetting("recordAllocationStacks", false);
     65     this.highResolutionCpuProfiling = this.createSetting("highResolutionCpuProfiling", false);
     66     this.searchInContentScripts = this.createSetting("searchInContentScripts", false);
     67     this.textEditorIndent = this.createSetting("textEditorIndent", "    ");
     68     this.textEditorAutoDetectIndent = this.createSetting("textEditorAutoIndentIndent", true);
     69     this.textEditorAutocompletion = this.createSetting("textEditorAutocompletion", true);
     70     this.textEditorBracketMatching = this.createSetting("textEditorBracketMatching", true);
     71     this.cssReloadEnabled = this.createSetting("cssReloadEnabled", false);
     72     this.timelineLiveUpdate = this.createSetting("timelineLiveUpdate", true);
     73     this.showMetricsRulers = this.createSetting("showMetricsRulers", false);
     74     this.workerInspectorWidth = this.createSetting("workerInspectorWidth", 600);
     75     this.workerInspectorHeight = this.createSetting("workerInspectorHeight", 600);
     76     this.messageURLFilters = this.createSetting("messageURLFilters", {});
     77     this.networkHideDataURL = this.createSetting("networkHideDataURL", false);
     78     this.networkResourceTypeFilters = this.createSetting("networkResourceTypeFilters", {});
     79     this.messageLevelFilters = this.createSetting("messageLevelFilters", {});
     80     this.splitVerticallyWhenDockedToRight = this.createSetting("splitVerticallyWhenDockedToRight", true);
     81     this.visiblePanels = this.createSetting("visiblePanels", {});
     82     this.shortcutPanelSwitch = this.createSetting("shortcutPanelSwitch", false);
     83     this.showWhitespacesInEditor = this.createSetting("showWhitespacesInEditor", false);
     84     this.skipStackFramesPattern = this.createRegExpSetting("skipStackFramesPattern", "");
     85     this.skipContentScripts = this.createSetting("skipContentScripts", false);
     86     this.pauseOnExceptionEnabled = this.createSetting("pauseOnExceptionEnabled", false);
     87     this.pauseOnCaughtException = this.createSetting("pauseOnCaughtException", false);
     88     this.enableAsyncStackTraces = this.createSetting("enableAsyncStackTraces", false);
     89     this.showMediaQueryInspector = this.createSetting("showMediaQueryInspector", false);
     90     this.disableOverridesWarning = this.createSetting("disableOverridesWarning", false);
     91 
     92     // Rendering options
     93     this.showPaintRects = this.createSetting("showPaintRects", false);
     94     this.showDebugBorders = this.createSetting("showDebugBorders", false);
     95     this.showFPSCounter = this.createSetting("showFPSCounter", false);
     96     this.continuousPainting = this.createSetting("continuousPainting", false);
     97     this.showScrollBottleneckRects = this.createSetting("showScrollBottleneckRects", false);
     98 }
     99 
    100 WebInspector.Settings.prototype = {
    101     /**
    102      * @param {string} key
    103      * @param {*} defaultValue
    104      * @return {!WebInspector.Setting}
    105      */
    106     createSetting: function(key, defaultValue)
    107     {
    108         if (!this._registry[key])
    109             this._registry[key] = new WebInspector.Setting(key, defaultValue, this._eventSupport, window.localStorage);
    110         return this._registry[key];
    111     },
    112 
    113     /**
    114      * @param {string} key
    115      * @param {string} defaultValue
    116      * @param {string=} regexFlags
    117      * @return {!WebInspector.Setting}
    118      */
    119     createRegExpSetting: function(key, defaultValue, regexFlags)
    120     {
    121         if (!this._registry[key])
    122             this._registry[key] = new WebInspector.RegExpSetting(key, defaultValue, this._eventSupport, window.localStorage, regexFlags);
    123         return this._registry[key];
    124     }
    125 }
    126 
    127 /**
    128  * @constructor
    129  * @param {string} name
    130  * @param {V} defaultValue
    131  * @param {!WebInspector.Object} eventSupport
    132  * @param {?Storage} storage
    133  * @template V
    134  */
    135 WebInspector.Setting = function(name, defaultValue, eventSupport, storage)
    136 {
    137     this._name = name;
    138     this._defaultValue = defaultValue;
    139     this._eventSupport = eventSupport;
    140     this._storage = storage;
    141 }
    142 
    143 WebInspector.Setting.prototype = {
    144     /**
    145      * @param {function(!WebInspector.Event)} listener
    146      * @param {!Object=} thisObject
    147      */
    148     addChangeListener: function(listener, thisObject)
    149     {
    150         this._eventSupport.addEventListener(this._name, listener, thisObject);
    151     },
    152 
    153     /**
    154      * @param {function(!WebInspector.Event)} listener
    155      * @param {!Object=} thisObject
    156      */
    157     removeChangeListener: function(listener, thisObject)
    158     {
    159         this._eventSupport.removeEventListener(this._name, listener, thisObject);
    160     },
    161 
    162     get name()
    163     {
    164         return this._name;
    165     },
    166 
    167     /**
    168      * @return {V}
    169      */
    170     get: function()
    171     {
    172         if (typeof this._value !== "undefined")
    173             return this._value;
    174 
    175         this._value = this._defaultValue;
    176         if (this._storage && this._name in this._storage) {
    177             try {
    178                 this._value = JSON.parse(this._storage[this._name]);
    179             } catch(e) {
    180                 delete this._storage[this._name];
    181             }
    182         }
    183         return this._value;
    184     },
    185 
    186     /**
    187      * @param {V} value
    188      */
    189     set: function(value)
    190     {
    191         this._value = value;
    192         if (this._storage) {
    193             try {
    194                 var settingString = JSON.stringify(value);
    195                 try {
    196                     this._storage[this._name] = settingString;
    197                 } catch(e) {
    198                     this._printSettingsSavingError(e.message, this._name, settingString);
    199                 }
    200             } catch(e) {
    201                 WebInspector.console.error("Cannot stringify setting with name: " + this._name + ", error: " + e.message);
    202             }
    203         }
    204         this._eventSupport.dispatchEventToListeners(this._name, value);
    205     },
    206 
    207     /**
    208      * @param {string} message
    209      * @param {string} name
    210      * @param {string} value
    211      */
    212     _printSettingsSavingError: function(message, name, value)
    213     {
    214         var errorMessage = "Error saving setting with name: " + this._name + ", value length: " + value.length + ". Error: " + message;
    215         console.error(errorMessage);
    216         WebInspector.console.error(errorMessage);
    217         WebInspector.console.log("Ten largest settings: ");
    218 
    219         var sizes = { __proto__: null };
    220         for (var key in this._storage)
    221             sizes[key] = this._storage.getItem(key).length;
    222         var keys = Object.keys(sizes);
    223 
    224         function comparator(key1, key2)
    225         {
    226             return sizes[key2] - sizes[key1];
    227         }
    228 
    229         keys.sort(comparator);
    230 
    231         for (var i = 0; i < 10 && i < keys.length; ++i)
    232             WebInspector.console.log("Setting: '" + keys[i] + "', size: " + sizes[keys[i]]);
    233     },
    234 }
    235 
    236 /**
    237  * @constructor
    238  * @extends {WebInspector.Setting}
    239  * @param {string} name
    240  * @param {string} defaultValue
    241  * @param {!WebInspector.Object} eventSupport
    242  * @param {?Storage} storage
    243  * @param {string=} regexFlags
    244  */
    245 WebInspector.RegExpSetting = function(name, defaultValue, eventSupport, storage, regexFlags)
    246 {
    247     WebInspector.Setting.call(this, name, defaultValue ? [{ pattern: defaultValue }] : [], eventSupport, storage);
    248     this._regexFlags = regexFlags;
    249 }
    250 
    251 WebInspector.RegExpSetting.prototype = {
    252     /**
    253      * @override
    254      * @return {string}
    255      */
    256     get: function()
    257     {
    258         var result = [];
    259         var items = this.getAsArray();
    260         for (var i = 0; i < items.length; ++i) {
    261             var item = items[i];
    262             if (item.pattern && !item.disabled)
    263                 result.push(item.pattern);
    264         }
    265         return result.join("|");
    266     },
    267 
    268     /**
    269      * @return {!Array.<{pattern: string, disabled: (boolean|undefined)}>}
    270      */
    271     getAsArray: function()
    272     {
    273         return WebInspector.Setting.prototype.get.call(this);
    274     },
    275 
    276     /**
    277      * @override
    278      * @param {string} value
    279      */
    280     set: function(value)
    281     {
    282         this.setAsArray([{ pattern: value }]);
    283     },
    284 
    285     /**
    286      * @param {!Array.<{pattern: string, disabled: (boolean|undefined)}>} value
    287      */
    288     setAsArray: function(value)
    289     {
    290         delete this._regex;
    291         WebInspector.Setting.prototype.set.call(this, value);
    292     },
    293 
    294     /**
    295      * @return {?RegExp}
    296      */
    297     asRegExp: function()
    298     {
    299         if (typeof this._regex !== "undefined")
    300             return this._regex;
    301         this._regex = null;
    302         try {
    303             var pattern = this.get();
    304             if (pattern)
    305                 this._regex = new RegExp(pattern, this._regexFlags || "");
    306         } catch (e) {
    307         }
    308         return this._regex;
    309     },
    310 
    311     __proto__: WebInspector.Setting.prototype
    312 }
    313 
    314 /**
    315  * @constructor
    316  */
    317 WebInspector.VersionController = function()
    318 {
    319 }
    320 
    321 WebInspector.VersionController.currentVersion = 10;
    322 
    323 WebInspector.VersionController.prototype = {
    324     updateVersion: function()
    325     {
    326         var versionSetting = WebInspector.settings.createSetting("inspectorVersion", 0);
    327         var currentVersion = WebInspector.VersionController.currentVersion;
    328         var oldVersion = versionSetting.get();
    329         var methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion);
    330         for (var i = 0; i < methodsToRun.length; ++i)
    331             this[methodsToRun[i]].call(this);
    332         versionSetting.set(currentVersion);
    333     },
    334 
    335     /**
    336      * @param {number} oldVersion
    337      * @param {number} currentVersion
    338      */
    339     _methodsToRunToUpdateVersion: function(oldVersion, currentVersion)
    340     {
    341         var result = [];
    342         for (var i = oldVersion; i < currentVersion; ++i)
    343             result.push("_updateVersionFrom" + i + "To" + (i + 1));
    344         return result;
    345     },
    346 
    347     _updateVersionFrom0To1: function()
    348     {
    349         this._clearBreakpointsWhenTooMany(WebInspector.settings.breakpoints, 500000);
    350     },
    351 
    352     _updateVersionFrom1To2: function()
    353     {
    354         var versionSetting = WebInspector.settings.createSetting("previouslyViewedFiles", []);
    355         versionSetting.set([]);
    356     },
    357 
    358     _updateVersionFrom2To3: function()
    359     {
    360         var fileSystemMappingSetting = WebInspector.settings.createSetting("fileSystemMapping", {});
    361         fileSystemMappingSetting.set({});
    362         if (window.localStorage)
    363             delete window.localStorage["fileMappingEntries"];
    364     },
    365 
    366     _updateVersionFrom3To4: function()
    367     {
    368         var advancedMode = WebInspector.settings.createSetting("showHeaSnapshotObjectsHiddenProperties", false).get();
    369         WebInspector.settings.showAdvancedHeapSnapshotProperties.set(advancedMode);
    370     },
    371 
    372     _updateVersionFrom4To5: function()
    373     {
    374         if (!window.localStorage)
    375             return;
    376         var settingNames = {
    377             "FileSystemViewSidebarWidth": "fileSystemViewSplitViewState",
    378             "canvasProfileViewReplaySplitLocation": "canvasProfileViewReplaySplitViewState",
    379             "canvasProfileViewSplitLocation": "canvasProfileViewSplitViewState",
    380             "elementsSidebarWidth": "elementsPanelSplitViewState",
    381             "StylesPaneSplitRatio": "stylesPaneSplitViewState",
    382             "heapSnapshotRetainersViewSize": "heapSnapshotSplitViewState",
    383             "InspectorView.splitView": "InspectorView.splitViewState",
    384             "InspectorView.screencastSplitView": "InspectorView.screencastSplitViewState",
    385             "Inspector.drawerSplitView": "Inspector.drawerSplitViewState",
    386             "layerDetailsSplitView": "layerDetailsSplitViewState",
    387             "networkSidebarWidth": "networkPanelSplitViewState",
    388             "sourcesSidebarWidth": "sourcesPanelSplitViewState",
    389             "scriptsPanelNavigatorSidebarWidth": "sourcesPanelNavigatorSplitViewState",
    390             "sourcesPanelSplitSidebarRatio": "sourcesPanelDebuggerSidebarSplitViewState",
    391             "timeline-details": "timelinePanelDetailsSplitViewState",
    392             "timeline-split": "timelinePanelRecorsSplitViewState",
    393             "timeline-view": "timelinePanelTimelineStackSplitViewState",
    394             "auditsSidebarWidth": "auditsPanelSplitViewState",
    395             "layersSidebarWidth": "layersPanelSplitViewState",
    396             "profilesSidebarWidth": "profilesPanelSplitViewState",
    397             "resourcesSidebarWidth": "resourcesPanelSplitViewState"
    398         };
    399         for (var oldName in settingNames) {
    400             var newName = settingNames[oldName];
    401             var oldNameH = oldName + "H";
    402 
    403             var newValue = null;
    404             var oldSetting = WebInspector.settings.createSetting(oldName, undefined).get();
    405             if (oldSetting) {
    406                 newValue = newValue || {};
    407                 newValue.vertical = {};
    408                 newValue.vertical.size = oldSetting;
    409                 delete window.localStorage[oldName];
    410             }
    411             var oldSettingH = WebInspector.settings.createSetting(oldNameH, undefined).get();
    412             if (oldSettingH) {
    413                 newValue = newValue || {};
    414                 newValue.horizontal = {};
    415                 newValue.horizontal.size = oldSettingH;
    416                 delete window.localStorage[oldNameH];
    417             }
    418             var newSetting = WebInspector.settings.createSetting(newName, {});
    419             if (newValue)
    420                 newSetting.set(newValue);
    421         }
    422     },
    423 
    424     _updateVersionFrom5To6: function()
    425     {
    426         if (!window.localStorage)
    427             return;
    428 
    429         var settingNames = {
    430             "debuggerSidebarHidden": "sourcesPanelSplitViewState",
    431             "navigatorHidden": "sourcesPanelNavigatorSplitViewState",
    432             "WebInspector.Drawer.showOnLoad": "Inspector.drawerSplitViewState"
    433         };
    434 
    435         for (var oldName in settingNames) {
    436             var newName = settingNames[oldName];
    437 
    438             var oldSetting = WebInspector.settings.createSetting(oldName, undefined).get();
    439             var invert = "WebInspector.Drawer.showOnLoad" === oldName;
    440             var hidden = !!oldSetting !== invert;
    441             delete window.localStorage[oldName];
    442             var showMode = hidden ? "OnlyMain" : "Both";
    443 
    444             var newSetting = WebInspector.settings.createSetting(newName, null);
    445             var newValue = newSetting.get() || {};
    446             newValue.vertical = newValue.vertical || {};
    447             newValue.vertical.showMode = showMode;
    448             newValue.horizontal = newValue.horizontal || {};
    449             newValue.horizontal.showMode = showMode;
    450             newSetting.set(newValue);
    451         }
    452     },
    453 
    454     _updateVersionFrom6To7: function()
    455     {
    456         if (!window.localStorage)
    457             return;
    458 
    459         var settingNames = {
    460             "sourcesPanelNavigatorSplitViewState": "sourcesPanelNavigatorSplitViewState",
    461             "elementsPanelSplitViewState": "elementsPanelSplitViewState",
    462             "canvasProfileViewReplaySplitViewState": "canvasProfileViewReplaySplitViewState",
    463             "stylesPaneSplitViewState": "stylesPaneSplitViewState",
    464             "sourcesPanelDebuggerSidebarSplitViewState": "sourcesPanelDebuggerSidebarSplitViewState"
    465         };
    466 
    467         for (var name in settingNames) {
    468             if (!(name in window.localStorage))
    469                 continue;
    470             var setting = WebInspector.settings.createSetting(name, undefined);
    471             var value = setting.get();
    472             if (!value)
    473                 continue;
    474             // Zero out saved percentage sizes, and they will be restored to defaults.
    475             if (value.vertical && value.vertical.size && value.vertical.size < 1)
    476                 value.vertical.size = 0;
    477             if (value.horizontal && value.horizontal.size && value.horizontal.size < 1)
    478                 value.horizontal.size = 0;
    479             setting.set(value);
    480         }
    481     },
    482 
    483     _updateVersionFrom7To8: function()
    484     {
    485         var settingName = "deviceMetrics";
    486         if (!window.localStorage || !(settingName in window.localStorage))
    487             return;
    488         var setting = WebInspector.settings.createSetting(settingName, undefined);
    489         var value = setting.get();
    490         if (!value)
    491             return;
    492 
    493         var components = value.split("x");
    494         if (components.length >= 3) {
    495             var width = parseInt(components[0], 10);
    496             var height = parseInt(components[1], 10);
    497             var deviceScaleFactor = parseFloat(components[2]);
    498             if (deviceScaleFactor) {
    499                 components[0] = "" + Math.round(width / deviceScaleFactor);
    500                 components[1] = "" + Math.round(height / deviceScaleFactor);
    501             }
    502         }
    503         value = components.join("x");
    504         setting.set(value);
    505     },
    506 
    507     _updateVersionFrom8To9: function()
    508     {
    509         if (!window.localStorage)
    510             return;
    511 
    512         var settingNames = [
    513             "skipStackFramesPattern",
    514             "workspaceFolderExcludePattern"
    515         ];
    516 
    517         for (var i = 0; i < settingNames.length; ++i) {
    518             var settingName = settingNames[i];
    519             if (!(settingName in window.localStorage))
    520                 continue;
    521             try {
    522                 var value = JSON.parse(window.localStorage[settingName]);
    523                 if (!value)
    524                     continue;
    525                 if (typeof value === "string")
    526                     value = [value];
    527                 for (var j = 0; j < value.length; ++j) {
    528                     if (typeof value[j] === "string")
    529                         value[j] = { pattern: value[j] };
    530                 }
    531                 window.localStorage[settingName] = JSON.stringify(value);
    532             } catch(e) {
    533             }
    534         }
    535     },
    536 
    537     _updateVersionFrom9To10: function()
    538     {
    539         if (!window.localStorage)
    540             return;
    541 
    542         for (var key in window.localStorage) {
    543             if (key.startsWith("revision-history"))
    544                 window.localStorage.removeItem(key);
    545         }
    546     },
    547 
    548     /**
    549      * @param {!WebInspector.Setting} breakpointsSetting
    550      * @param {number} maxBreakpointsCount
    551      */
    552     _clearBreakpointsWhenTooMany: function(breakpointsSetting, maxBreakpointsCount)
    553     {
    554         // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
    555         // periodical breakpoints duplication leading to inspector slowness.
    556         if (breakpointsSetting.get().length > maxBreakpointsCount)
    557             breakpointsSetting.set([]);
    558     }
    559 }
    560 
    561 /**
    562  * @type {!WebInspector.Settings}
    563  */
    564 WebInspector.settings;
    565 
    566 // These methods are added for backwards compatibility with Devtools CodeSchool extension.
    567 // DO NOT REMOVE
    568 
    569 /**
    570  * @constructor
    571  */
    572 WebInspector.PauseOnExceptionStateSetting = function()
    573 {
    574     WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._enabledChanged, this);
    575     WebInspector.settings.pauseOnCaughtException.addChangeListener(this._pauseOnCaughtChanged, this);
    576     this._name = "pauseOnExceptionStateString";
    577     this._eventSupport = new WebInspector.Object();
    578     this._value = this._calculateValue();
    579 }
    580 
    581 WebInspector.PauseOnExceptionStateSetting.prototype = {
    582     /**
    583      * @param {function(!WebInspector.Event)} listener
    584      * @param {!Object=} thisObject
    585      */
    586     addChangeListener: function(listener, thisObject)
    587     {
    588         this._eventSupport.addEventListener(this._name, listener, thisObject);
    589     },
    590 
    591     /**
    592      * @param {function(!WebInspector.Event)} listener
    593      * @param {!Object=} thisObject
    594      */
    595     removeChangeListener: function(listener, thisObject)
    596     {
    597         this._eventSupport.removeEventListener(this._name, listener, thisObject);
    598     },
    599 
    600     /**
    601      * @return {string}
    602      */
    603     get: function()
    604     {
    605         return this._value;
    606     },
    607 
    608     /**
    609      * @return {string}
    610      */
    611     _calculateValue: function()
    612     {
    613         if (!WebInspector.settings.pauseOnExceptionEnabled.get())
    614             return "none";
    615         // The correct code here would be
    616         //     return WebInspector.settings.pauseOnCaughtException.get() ? "all" : "uncaught";
    617         // But the CodeSchool DevTools relies on the fact that we used to enable pausing on ALL extensions by default, so we trick it here.
    618         return "all";
    619     },
    620 
    621     _enabledChanged: function(event)
    622     {
    623         this._fireChangedIfNeeded();
    624     },
    625 
    626     _pauseOnCaughtChanged: function(event)
    627     {
    628         this._fireChangedIfNeeded();
    629     },
    630 
    631     _fireChangedIfNeeded: function()
    632     {
    633         var newValue = this._calculateValue();
    634         if (newValue === this._value)
    635             return;
    636         this._value = newValue;
    637         this._eventSupport.dispatchEventToListeners(this._name, this._value);
    638     }
    639 }
    640