Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / common / Settings.js
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.pauseOnExceptionEnabled = this.createSetting("pauseOnExceptionEnabled", false);
86     this.pauseOnCaughtException = this.createSetting("pauseOnCaughtException", false);
87     this.enableAsyncStackTraces = this.createSetting("enableAsyncStackTraces", false);
88     this.showMediaQueryInspector = this.createSetting("showMediaQueryInspector", false);
89     this.disableOverridesWarning = this.createSetting("disableOverridesWarning", false);
90
91     // Rendering options
92     this.showPaintRects = this.createSetting("showPaintRects", false);
93     this.showDebugBorders = this.createSetting("showDebugBorders", false);
94     this.showFPSCounter = this.createSetting("showFPSCounter", false);
95     this.continuousPainting = this.createSetting("continuousPainting", false);
96     this.showScrollBottleneckRects = this.createSetting("showScrollBottleneckRects", false);
97 }
98
99 WebInspector.Settings.prototype = {
100     /**
101      * @param {string} key
102      * @param {*} defaultValue
103      * @return {!WebInspector.Setting}
104      */
105     createSetting: function(key, defaultValue)
106     {
107         if (!this._registry[key])
108             this._registry[key] = new WebInspector.Setting(key, defaultValue, this._eventSupport, window.localStorage);
109         return this._registry[key];
110     },
111
112     /**
113      * @param {string} key
114      * @param {string} defaultValue
115      * @param {string=} regexFlags
116      * @return {!WebInspector.Setting}
117      */
118     createRegExpSetting: function(key, defaultValue, regexFlags)
119     {
120         if (!this._registry[key])
121             this._registry[key] = new WebInspector.RegExpSetting(key, defaultValue, this._eventSupport, window.localStorage, regexFlags);
122         return this._registry[key];
123     }
124 }
125
126 /**
127  * @constructor
128  * @param {string} name
129  * @param {V} defaultValue
130  * @param {!WebInspector.Object} eventSupport
131  * @param {?Storage} storage
132  * @template V
133  */
134 WebInspector.Setting = function(name, defaultValue, eventSupport, storage)
135 {
136     this._name = name;
137     this._defaultValue = defaultValue;
138     this._eventSupport = eventSupport;
139     this._storage = storage;
140 }
141
142 WebInspector.Setting.prototype = {
143     /**
144      * @param {function(!WebInspector.Event)} listener
145      * @param {!Object=} thisObject
146      */
147     addChangeListener: function(listener, thisObject)
148     {
149         this._eventSupport.addEventListener(this._name, listener, thisObject);
150     },
151
152     /**
153      * @param {function(!WebInspector.Event)} listener
154      * @param {!Object=} thisObject
155      */
156     removeChangeListener: function(listener, thisObject)
157     {
158         this._eventSupport.removeEventListener(this._name, listener, thisObject);
159     },
160
161     get name()
162     {
163         return this._name;
164     },
165
166     /**
167      * @return {V}
168      */
169     get: function()
170     {
171         if (typeof this._value !== "undefined")
172             return this._value;
173
174         this._value = this._defaultValue;
175         if (this._storage && this._name in this._storage) {
176             try {
177                 this._value = JSON.parse(this._storage[this._name]);
178             } catch(e) {
179                 delete this._storage[this._name];
180             }
181         }
182         return this._value;
183     },
184
185     /**
186      * @param {V} value
187      */
188     set: function(value)
189     {
190         this._value = value;
191         if (this._storage) {
192             try {
193                 this._storage[this._name] = JSON.stringify(value);
194             } catch(e) {
195                 console.error("Error saving setting with name:" + this._name);
196             }
197         }
198         this._eventSupport.dispatchEventToListeners(this._name, value);
199     }
200 }
201
202 /**
203  * @constructor
204  * @extends {WebInspector.Setting}
205  * @param {string} name
206  * @param {string} defaultValue
207  * @param {!WebInspector.Object} eventSupport
208  * @param {?Storage} storage
209  * @param {string=} regexFlags
210  */
211 WebInspector.RegExpSetting = function(name, defaultValue, eventSupport, storage, regexFlags)
212 {
213     WebInspector.Setting.call(this, name, defaultValue ? [{ pattern: defaultValue }] : [], eventSupport, storage);
214     this._regexFlags = regexFlags;
215 }
216
217 WebInspector.RegExpSetting.prototype = {
218     /**
219      * @override
220      * @return {string}
221      */
222     get: function()
223     {
224         var result = [];
225         var items = this.getAsArray();
226         for (var i = 0; i < items.length; ++i) {
227             var item = items[i];
228             if (item.pattern && !item.disabled)
229                 result.push(item.pattern);
230         }
231         return result.join("|");
232     },
233
234     /**
235      * @return {!Array.<{pattern: string, disabled: (boolean|undefined)}>}
236      */
237     getAsArray: function()
238     {
239         return WebInspector.Setting.prototype.get.call(this);
240     },
241
242     /**
243      * @override
244      * @param {string} value
245      */
246     set: function(value)
247     {
248         this.setAsArray([{ pattern: value }]);
249     },
250
251     /**
252      * @param {!Array.<{pattern: string, disabled: (boolean|undefined)}>} value
253      */
254     setAsArray: function(value)
255     {
256         delete this._regex;
257         WebInspector.Setting.prototype.set.call(this, value);
258     },
259
260     /**
261      * @return {?RegExp}
262      */
263     asRegExp: function()
264     {
265         if (typeof this._regex !== "undefined")
266             return this._regex;
267         this._regex = null;
268         try {
269             var pattern = this.get();
270             if (pattern)
271                 this._regex = new RegExp(pattern, this._regexFlags || "");
272         } catch (e) {
273         }
274         return this._regex;
275     },
276
277     __proto__: WebInspector.Setting.prototype
278 }
279
280 /**
281  * @constructor
282  * @param {boolean} experimentsEnabled
283  */
284 WebInspector.ExperimentsSettings = function(experimentsEnabled)
285 {
286     this._experimentsEnabled = experimentsEnabled;
287     this._setting = WebInspector.settings.createSetting("experiments", {});
288     this._experiments = [];
289     this._enabledForTest = {};
290
291     // Add currently running experiments here.
292     this.applyCustomStylesheet = this._createExperiment("applyCustomStylesheet", "Allow custom UI themes");
293     this.canvasInspection = this._createExperiment("canvasInspection ", "Canvas inspection");
294     this.devicesPanel = this._createExperiment("devicesPanel", "Devices panel");
295     this.disableAgentsWhenProfile = this._createExperiment("disableAgentsWhenProfile", "Disable other agents and UI when profiler is active", true);
296     this.dockToLeft = this._createExperiment("dockToLeft", "Dock to left", true);
297     this.documentation = this._createExperiment("documentation", "Documentation for JS and CSS", true);
298     this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection");
299     this.gpuTimeline = this._createExperiment("gpuTimeline", "GPU data on timeline", true);
300     this.layersPanel = this._createExperiment("layersPanel", "Layers panel");
301     this.timelineOnTraceEvents = this._createExperiment("timelineOnTraceEvents", "Timeline on trace events");
302     this.paintProfiler = this._createExperiment("paintProfiler", "Paint profiler");
303     this.timelinePowerProfiler = this._createExperiment("timelinePowerProfiler", "Timeline power profiler");
304     this.timelineJSCPUProfile = this._createExperiment("timelineJSCPUProfile", "Timeline with JS sampling");
305
306     this._cleanUpSetting();
307 }
308
309 WebInspector.ExperimentsSettings.prototype = {
310     /**
311      * @return {!Array.<!WebInspector.Experiment>}
312      */
313     get experiments()
314     {
315         return this._experiments.slice();
316     },
317
318     /**
319      * @return {boolean}
320      */
321     get experimentsEnabled()
322     {
323         return this._experimentsEnabled;
324     },
325
326     /**
327      * @param {string} experimentName
328      * @param {string} experimentTitle
329      * @param {boolean=} hidden
330      * @return {!WebInspector.Experiment}
331      */
332     _createExperiment: function(experimentName, experimentTitle, hidden)
333     {
334         var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle, !!hidden);
335         this._experiments.push(experiment);
336         return experiment;
337     },
338
339     /**
340      * @param {string} experimentName
341      * @return {boolean}
342      */
343     isEnabled: function(experimentName)
344     {
345         if (this._enabledForTest[experimentName])
346             return true;
347
348         if (!this.experimentsEnabled)
349             return false;
350
351         var experimentsSetting = this._setting.get();
352         return experimentsSetting[experimentName];
353     },
354
355     /**
356      * @param {string} experimentName
357      * @param {boolean} enabled
358      */
359     setEnabled: function(experimentName, enabled)
360     {
361         var experimentsSetting = this._setting.get();
362         experimentsSetting[experimentName] = enabled;
363         this._setting.set(experimentsSetting);
364     },
365
366     /**
367      * @param {string} experimentName
368      */
369     _enableForTest: function(experimentName)
370     {
371         this._enabledForTest[experimentName] = true;
372     },
373
374     _cleanUpSetting: function()
375     {
376         var experimentsSetting = this._setting.get();
377         var cleanedUpExperimentSetting = {};
378         for (var i = 0; i < this._experiments.length; ++i) {
379             var experimentName = this._experiments[i].name;
380             if (experimentsSetting[experimentName])
381                 cleanedUpExperimentSetting[experimentName] = true;
382         }
383         this._setting.set(cleanedUpExperimentSetting);
384     }
385 }
386
387 /**
388  * @constructor
389  * @param {!WebInspector.ExperimentsSettings} experimentsSettings
390  * @param {string} name
391  * @param {string} title
392  * @param {boolean} hidden
393  */
394 WebInspector.Experiment = function(experimentsSettings, name, title, hidden)
395 {
396     this._name = name;
397     this._title = title;
398     this._hidden = hidden;
399     this._experimentsSettings = experimentsSettings;
400 }
401
402 WebInspector.Experiment.prototype = {
403     /**
404      * @return {string}
405      */
406     get name()
407     {
408         return this._name;
409     },
410
411     /**
412      * @return {string}
413      */
414     get title()
415     {
416         return this._title;
417     },
418
419     /**
420      * @return {boolean}
421      */
422     get hidden()
423     {
424         return this._hidden;
425     },
426
427     /**
428      * @return {boolean}
429      */
430     isEnabled: function()
431     {
432         return this._experimentsSettings.isEnabled(this._name);
433     },
434
435     /**
436      * @param {boolean} enabled
437      */
438     setEnabled: function(enabled)
439     {
440         this._experimentsSettings.setEnabled(this._name, enabled);
441     },
442
443     enableForTest: function()
444     {
445         this._experimentsSettings._enableForTest(this._name);
446     }
447 }
448
449 /**
450  * @constructor
451  */
452 WebInspector.VersionController = function()
453 {
454 }
455
456 WebInspector.VersionController.currentVersion = 9;
457
458 WebInspector.VersionController.prototype = {
459     updateVersion: function()
460     {
461         var versionSetting = WebInspector.settings.createSetting("inspectorVersion", 0);
462         var currentVersion = WebInspector.VersionController.currentVersion;
463         var oldVersion = versionSetting.get();
464         var methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion);
465         for (var i = 0; i < methodsToRun.length; ++i)
466             this[methodsToRun[i]].call(this);
467         versionSetting.set(currentVersion);
468     },
469
470     /**
471      * @param {number} oldVersion
472      * @param {number} currentVersion
473      */
474     _methodsToRunToUpdateVersion: function(oldVersion, currentVersion)
475     {
476         var result = [];
477         for (var i = oldVersion; i < currentVersion; ++i)
478             result.push("_updateVersionFrom" + i + "To" + (i + 1));
479         return result;
480     },
481
482     _updateVersionFrom0To1: function()
483     {
484         this._clearBreakpointsWhenTooMany(WebInspector.settings.breakpoints, 500000);
485     },
486
487     _updateVersionFrom1To2: function()
488     {
489         var versionSetting = WebInspector.settings.createSetting("previouslyViewedFiles", []);
490         versionSetting.set([]);
491     },
492
493     _updateVersionFrom2To3: function()
494     {
495         var fileSystemMappingSetting = WebInspector.settings.createSetting("fileSystemMapping", {});
496         fileSystemMappingSetting.set({});
497         if (window.localStorage)
498             delete window.localStorage["fileMappingEntries"];
499     },
500
501     _updateVersionFrom3To4: function()
502     {
503         var advancedMode = WebInspector.settings.createSetting("showHeaSnapshotObjectsHiddenProperties", false).get();
504         WebInspector.settings.showAdvancedHeapSnapshotProperties.set(advancedMode);
505     },
506
507     _updateVersionFrom4To5: function()
508     {
509         if (!window.localStorage)
510             return;
511         var settingNames = {
512             "FileSystemViewSidebarWidth": "fileSystemViewSplitViewState",
513             "canvasProfileViewReplaySplitLocation": "canvasProfileViewReplaySplitViewState",
514             "canvasProfileViewSplitLocation": "canvasProfileViewSplitViewState",
515             "elementsSidebarWidth": "elementsPanelSplitViewState",
516             "StylesPaneSplitRatio": "stylesPaneSplitViewState",
517             "heapSnapshotRetainersViewSize": "heapSnapshotSplitViewState",
518             "InspectorView.splitView": "InspectorView.splitViewState",
519             "InspectorView.screencastSplitView": "InspectorView.screencastSplitViewState",
520             "Inspector.drawerSplitView": "Inspector.drawerSplitViewState",
521             "layerDetailsSplitView": "layerDetailsSplitViewState",
522             "networkSidebarWidth": "networkPanelSplitViewState",
523             "sourcesSidebarWidth": "sourcesPanelSplitViewState",
524             "scriptsPanelNavigatorSidebarWidth": "sourcesPanelNavigatorSplitViewState",
525             "sourcesPanelSplitSidebarRatio": "sourcesPanelDebuggerSidebarSplitViewState",
526             "timeline-details": "timelinePanelDetailsSplitViewState",
527             "timeline-split": "timelinePanelRecorsSplitViewState",
528             "timeline-view": "timelinePanelTimelineStackSplitViewState",
529             "auditsSidebarWidth": "auditsPanelSplitViewState",
530             "layersSidebarWidth": "layersPanelSplitViewState",
531             "profilesSidebarWidth": "profilesPanelSplitViewState",
532             "resourcesSidebarWidth": "resourcesPanelSplitViewState"
533         };
534         for (var oldName in settingNames) {
535             var newName = settingNames[oldName];
536             var oldNameH = oldName + "H";
537
538             var newValue = null;
539             var oldSetting = WebInspector.settings.createSetting(oldName, undefined).get();
540             if (oldSetting) {
541                 newValue = newValue || {};
542                 newValue.vertical = {};
543                 newValue.vertical.size = oldSetting;
544                 delete window.localStorage[oldName];
545             }
546             var oldSettingH = WebInspector.settings.createSetting(oldNameH, undefined).get();
547             if (oldSettingH) {
548                 newValue = newValue || {};
549                 newValue.horizontal = {};
550                 newValue.horizontal.size = oldSettingH;
551                 delete window.localStorage[oldNameH];
552             }
553             var newSetting = WebInspector.settings.createSetting(newName, {});
554             if (newValue)
555                 newSetting.set(newValue);
556         }
557     },
558
559     _updateVersionFrom5To6: function()
560     {
561         if (!window.localStorage)
562             return;
563
564         var settingNames = {
565             "debuggerSidebarHidden": "sourcesPanelSplitViewState",
566             "navigatorHidden": "sourcesPanelNavigatorSplitViewState",
567             "WebInspector.Drawer.showOnLoad": "Inspector.drawerSplitViewState"
568         };
569
570         for (var oldName in settingNames) {
571             var newName = settingNames[oldName];
572
573             var oldSetting = WebInspector.settings.createSetting(oldName, undefined).get();
574             var invert = "WebInspector.Drawer.showOnLoad" === oldName;
575             var hidden = !!oldSetting !== invert;
576             delete window.localStorage[oldName];
577             var showMode = hidden ? "OnlyMain" : "Both";
578
579             var newSetting = WebInspector.settings.createSetting(newName, null);
580             var newValue = newSetting.get() || {};
581             newValue.vertical = newValue.vertical || {};
582             newValue.vertical.showMode = showMode;
583             newValue.horizontal = newValue.horizontal || {};
584             newValue.horizontal.showMode = showMode;
585             newSetting.set(newValue);
586         }
587     },
588
589     _updateVersionFrom6To7: function()
590     {
591         if (!window.localStorage)
592             return;
593
594         var settingNames = {
595             "sourcesPanelNavigatorSplitViewState": "sourcesPanelNavigatorSplitViewState",
596             "elementsPanelSplitViewState": "elementsPanelSplitViewState",
597             "canvasProfileViewReplaySplitViewState": "canvasProfileViewReplaySplitViewState",
598             "stylesPaneSplitViewState": "stylesPaneSplitViewState",
599             "sourcesPanelDebuggerSidebarSplitViewState": "sourcesPanelDebuggerSidebarSplitViewState"
600         };
601
602         for (var name in settingNames) {
603             if (!(name in window.localStorage))
604                 continue;
605             var setting = WebInspector.settings.createSetting(name, undefined);
606             var value = setting.get();
607             if (!value)
608                 continue;
609             // Zero out saved percentage sizes, and they will be restored to defaults.
610             if (value.vertical && value.vertical.size && value.vertical.size < 1)
611                 value.vertical.size = 0;
612             if (value.horizontal && value.horizontal.size && value.horizontal.size < 1)
613                 value.horizontal.size = 0;
614             setting.set(value);
615         }
616     },
617
618     _updateVersionFrom7To8: function()
619     {
620         var settingName = "deviceMetrics";
621         if (!window.localStorage || !(settingName in window.localStorage))
622             return;
623         var setting = WebInspector.settings.createSetting(settingName, undefined);
624         var value = setting.get();
625         if (!value)
626             return;
627
628         var components = value.split("x");
629         if (components.length >= 3) {
630             var width = parseInt(components[0], 10);
631             var height = parseInt(components[1], 10);
632             var deviceScaleFactor = parseFloat(components[2]);
633             if (deviceScaleFactor) {
634                 components[0] = "" + Math.round(width / deviceScaleFactor);
635                 components[1] = "" + Math.round(height / deviceScaleFactor);
636             }
637         }
638         value = components.join("x");
639         setting.set(value);
640     },
641
642     _updateVersionFrom8To9: function()
643     {
644         if (!window.localStorage)
645             return;
646
647         var settingNames = [
648             "skipStackFramesPattern",
649             "workspaceFolderExcludePattern"
650         ];
651
652         for (var i = 0; i < settingNames.length; ++i) {
653             var settingName = settingNames[i];
654             if (!(settingName in window.localStorage))
655                 continue;
656             try {
657                 var value = JSON.parse(window.localStorage[settingName]);
658                 if (!value)
659                     continue;
660                 if (typeof value === "string")
661                     value = [value];
662                 for (var j = 0; j < value.length; ++j) {
663                     if (typeof value[j] === "string")
664                         value[j] = { pattern: value[j] };
665                 }
666                 window.localStorage[settingName] = JSON.stringify(value);
667             } catch(e) {
668             }
669         }
670     },
671
672     /**
673      * @param {!WebInspector.Setting} breakpointsSetting
674      * @param {number} maxBreakpointsCount
675      */
676     _clearBreakpointsWhenTooMany: function(breakpointsSetting, maxBreakpointsCount)
677     {
678         // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
679         // periodical breakpoints duplication leading to inspector slowness.
680         if (breakpointsSetting.get().length > maxBreakpointsCount)
681             breakpointsSetting.set([]);
682     }
683 }
684
685 /**
686  * @type {!WebInspector.Settings}
687  */
688 WebInspector.settings;
689
690 /**
691  * @type {!WebInspector.ExperimentsSettings}
692  */
693 WebInspector.experimentsSettings;
694
695 // These methods are added for backwards compatibility with Devtools CodeSchool extension.
696 // DO NOT REMOVE
697
698 /**
699  * @constructor
700  */
701 WebInspector.PauseOnExceptionStateSetting = function()
702 {
703     WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._enabledChanged, this);
704     WebInspector.settings.pauseOnCaughtException.addChangeListener(this._pauseOnCaughtChanged, this);
705     this._name = "pauseOnExceptionStateString";
706     this._eventSupport = new WebInspector.Object();
707     this._value = this._calculateValue();
708 }
709
710 WebInspector.PauseOnExceptionStateSetting.prototype = {
711     /**
712      * @param {function(!WebInspector.Event)} listener
713      * @param {!Object=} thisObject
714      */
715     addChangeListener: function(listener, thisObject)
716     {
717         this._eventSupport.addEventListener(this._name, listener, thisObject);
718     },
719
720     /**
721      * @param {function(!WebInspector.Event)} listener
722      * @param {!Object=} thisObject
723      */
724     removeChangeListener: function(listener, thisObject)
725     {
726         this._eventSupport.removeEventListener(this._name, listener, thisObject);
727     },
728
729     /**
730      * @return {string}
731      */
732     get: function()
733     {
734         return this._value;
735     },
736
737     /**
738      * @return {string}
739      */
740     _calculateValue: function()
741     {
742         if (!WebInspector.settings.pauseOnExceptionEnabled.get())
743             return "none";
744         // The correct code here would be
745         //     return WebInspector.settings.pauseOnCaughtException.get() ? "all" : "uncaught";
746         // But the CodeSchool DevTools relies on the fact that we used to enable pausing on ALL extensions by default, so we trick it here.
747         return "all";
748     },
749
750     _enabledChanged: function(event)
751     {
752         this._fireChangedIfNeeded();
753     },
754
755     _pauseOnCaughtChanged: function(event)
756     {
757         this._fireChangedIfNeeded();
758     },
759
760     _fireChangedIfNeeded: function()
761     {
762         var newValue = this._calculateValue();
763         if (newValue === this._value)
764             return;
765         this._value = newValue;
766         this._eventSupport.dispatchEventToListeners(this._name, this._value);
767     }
768 }