Fix ASSERT when the Web Content Process crashes
[WebKit-https.git] / Source / WebCore / inspector / front-end / 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 var Preferences = {
33     maxInlineTextChildLength: 80,
34     minConsoleHeight: 75,
35     minSidebarWidth: 100,
36     minSidebarHeight: 75,
37     minElementsSidebarWidth: 200,
38     minElementsSidebarHeight: 200,
39     minScriptsSidebarWidth: 200,
40     styleRulesExpandedState: {},
41     showMissingLocalizedStrings: false,
42     useLowerCaseMenuTitlesOnWindows: false,
43     sharedWorkersDebugNote: undefined,
44     localizeUI: true,
45     exposeDisableCache: false,
46     applicationTitle: "Web Inspector - %s",
47     showDockToRight: false,
48     exposeFileSystemInspection: false,
49     experimentsEnabled: true
50 }
51
52 var Capabilities = {
53     samplingCPUProfiler: false,
54     debuggerCausesRecompilation: true,
55     separateScriptCompilationAndExecutionEnabled: false,
56     profilerCausesRecompilation: true,
57     heapProfilerPresent: false,
58     canOverrideDeviceMetrics: false,
59     timelineSupportsFrameInstrumentation: false,
60     timelineCanMonitorMainThread: false,
61     canOverrideGeolocation: false,
62     canOverrideDeviceOrientation: false,
63     canShowDebugBorders: false,
64     canShowFPSCounter: false,
65     canContinuouslyPaint: false
66 }
67
68 /**
69  * @constructor
70  */
71 WebInspector.Settings = function()
72 {
73     this._eventSupport = new WebInspector.Object();
74
75     this.colorFormat = this.createSetting("colorFormat", "original");
76     this.consoleHistory = this.createSetting("consoleHistory", []);
77     this.debuggerEnabled = this.createSetting("debuggerEnabled", false);
78     this.domWordWrap = this.createSetting("domWordWrap", true);
79     this.profilerEnabled = this.createSetting("profilerEnabled", false);
80     this.eventListenersFilter = this.createSetting("eventListenersFilter", "all");
81     this.lastActivePanel = this.createSetting("lastActivePanel", "elements");
82     this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application");
83     this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false);
84     this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false);
85     this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true);
86     this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
87     this.resourceViewTab = this.createSetting("resourceViewTab", "preview");
88     this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false);
89     this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true);
90     this.watchExpressions = this.createSetting("watchExpressions", []);
91     this.breakpoints = this.createSetting("breakpoints", []);
92     this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []);
93     this.domBreakpoints = this.createSetting("domBreakpoints", []);
94     this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []);
95     this.sourceMapsEnabled = this.createSetting("sourceMapsEnabled", false);
96     this.cacheDisabled = this.createSetting("cacheDisabled", false);
97     this.overrideUserAgent = this.createSetting("overrideUserAgent", "");
98     this.userAgent = this.createSetting("userAgent", "");
99     this.deviceMetrics = this.createSetting("deviceMetrics", "");
100     this.deviceFitWindow = this.createSetting("deviceFitWindow", false);
101     this.emulateTouchEvents = this.createSetting("emulateTouchEvents", false);
102     this.showPaintRects = this.createSetting("showPaintRects", false);
103     this.continuousPainting = this.createSetting("continuousPainting", false);
104     this.showDebugBorders = this.createSetting("showDebugBorders", false);
105     this.showFPSCounter = this.createSetting("showFPSCounter", false);
106     this.showShadowDOM = this.createSetting("showShadowDOM", false);
107     this.zoomLevel = this.createSetting("zoomLevel", 0);
108     this.savedURLs = this.createSetting("savedURLs", {});
109     this.javaScriptDisabled = this.createSetting("javaScriptDisabled", false);
110     this.geolocationOverride = this.createSetting("geolocationOverride", "");
111     this.deviceOrientationOverride = this.createSetting("deviceOrientationOverride", "");
112     this.showHeapSnapshotObjectsHiddenProperties = this.createSetting("showHeaSnapshotObjectsHiddenProperties", false);
113     this.showNativeSnapshotUninstrumentedSize = this.createSetting("showNativeSnapshotUninstrumentedSize", false);
114     this.searchInContentScripts = this.createSetting("searchInContentScripts", false);
115     this.textEditorIndent = this.createSetting("textEditorIndent", "    ");
116     this.lastDockState = this.createSetting("lastDockState", "");
117     this.cssReloadEnabled = this.createSetting("cssReloadEnabled", false);
118     this.cssReloadTimeout = this.createSetting("cssReloadTimeout", 1000);
119     this.showCpuOnTimelineRuler = this.createSetting("showCpuOnTimelineRuler", false);
120     this.showMetricsRulers = this.createSetting("showMetricsRulers", false);
121     this.emulatedCSSMedia = this.createSetting("emulatedCSSMedia", "print");
122     this.showToolbarIcons = this.createSetting("showToolbarIcons", false);
123     this.workerInspectorWidth = this.createSetting("workerInspectorWidth", 600);
124     this.workerInspectorHeight = this.createSetting("workerInspectorHeight", 600);
125     this.messageURLFilters = this.createSetting("messageURLFilters", {});
126
127     // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
128     // periodical breakpoints duplication leading to inspector slowness.
129     if (this.breakpoints.get().length > 500000)
130         this.breakpoints.set([]);
131 }
132
133 WebInspector.Settings.prototype = {
134     /**
135      * @return {WebInspector.Setting}
136      */
137     createSetting: function(key, defaultValue)
138     {
139         return new WebInspector.Setting(key, defaultValue, this._eventSupport);
140     }
141 }
142
143 /**
144  * @constructor
145  */
146 WebInspector.Setting = function(name, defaultValue, eventSupport)
147 {
148     this._name = name;
149     this._defaultValue = defaultValue;
150     this._eventSupport = eventSupport;
151 }
152
153 WebInspector.Setting.prototype = {
154     addChangeListener: function(listener, thisObject)
155     {
156         this._eventSupport.addEventListener(this._name, listener, thisObject);
157     },
158
159     removeChangeListener: function(listener, thisObject)
160     {
161         this._eventSupport.removeEventListener(this._name, listener, thisObject);
162     },
163
164     get name()
165     {
166         return this._name;
167     },
168
169     get: function()
170     {
171         if (typeof this._value !== "undefined")
172             return this._value;
173
174         this._value = this._defaultValue;
175         if (window.localStorage != null && this._name in window.localStorage) {
176             try {
177                 this._value = JSON.parse(window.localStorage[this._name]);
178             } catch(e) {
179                 window.localStorage.removeItem(this._name);
180             }
181         }
182         return this._value;
183     },
184
185     set: function(value)
186     {
187         this._value = value;
188         if (window.localStorage != null) {
189             try {
190                 window.localStorage[this._name] = JSON.stringify(value);
191             } catch(e) {
192                 console.error("Error saving setting with name:" + this._name);
193             }
194         }
195         this._eventSupport.dispatchEventToListeners(this._name, value);
196     }
197 }
198
199 /**
200  * @constructor
201  */
202 WebInspector.ExperimentsSettings = function()
203 {
204     this._setting = WebInspector.settings.createSetting("experiments", {});
205     this._experiments = [];
206     this._enabledForTest = {};
207     
208     // Add currently running experiments here.
209     this.snippetsSupport = this._createExperiment("snippetsSupport", "Snippets support");
210     this.nativeMemorySnapshots = this._createExperiment("nativeMemorySnapshots", "Native memory profiling");
211     this.liveNativeMemoryChart = this._createExperiment("liveNativeMemoryChart", "Live native memory chart");
212     this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection");
213     this.canvasInspection = this._createExperiment("canvasInspection ", "Canvas inspection");
214     this.sass = this._createExperiment("sass", "Support for Sass");
215     this.codemirror = this._createExperiment("codemirror", "Use CodeMirror editor");
216     this.cssRegions = this._createExperiment("cssRegions", "CSS Regions Support");
217     this.showOverridesInDrawer = this._createExperiment("showOverridesInDrawer", "Show Overrides in drawer");
218     this.fileSystemProject = this._createExperiment("fileSystemProject", "File system folders in Sources Panel");
219     this.horizontalPanelSplit = this._createExperiment("horizontalPanelSplit", "Allow horizontal split in Elements and Sources panels");
220
221     this._cleanUpSetting();
222 }
223
224 WebInspector.ExperimentsSettings.prototype = {
225     /**
226      * @return {Array.<WebInspector.Experiment>}
227      */
228     get experiments()
229     {
230         return this._experiments.slice();
231     },
232     
233     /**
234      * @return {boolean}
235      */
236     get experimentsEnabled()
237     {
238         return Preferences.experimentsEnabled || ("experiments" in WebInspector.queryParamsObject);
239     },
240     
241     /**
242      * @param {string} experimentName
243      * @param {string} experimentTitle
244      * @return {WebInspector.Experiment}
245      */
246     _createExperiment: function(experimentName, experimentTitle)
247     {
248         var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle);
249         this._experiments.push(experiment);
250         return experiment;
251     },
252     
253     /**
254      * @param {string} experimentName
255      * @return {boolean}
256      */
257     isEnabled: function(experimentName)
258     {
259         if (this._enabledForTest[experimentName])
260             return true;
261
262         if (!this.experimentsEnabled)
263             return false;
264         
265         var experimentsSetting = this._setting.get();
266         return experimentsSetting[experimentName];
267     },
268     
269     /**
270      * @param {string} experimentName
271      * @param {boolean} enabled
272      */
273     setEnabled: function(experimentName, enabled)
274     {
275         var experimentsSetting = this._setting.get();
276         experimentsSetting[experimentName] = enabled;
277         this._setting.set(experimentsSetting);
278     },
279
280     /**
281      * @param {string} experimentName
282      */
283     _enableForTest: function(experimentName)
284     {
285         this._enabledForTest[experimentName] = true;
286     },
287
288     _cleanUpSetting: function()
289     {
290         var experimentsSetting = this._setting.get();
291         var cleanedUpExperimentSetting = {};
292         for (var i = 0; i < this._experiments.length; ++i) {
293             var experimentName = this._experiments[i].name;
294             if (experimentsSetting[experimentName])
295                 cleanedUpExperimentSetting[experimentName] = true;
296         }
297         this._setting.set(cleanedUpExperimentSetting);
298     }
299 }
300
301 /**
302  * @constructor
303  * @param {WebInspector.ExperimentsSettings} experimentsSettings
304  * @param {string} name
305  * @param {string} title
306  */
307 WebInspector.Experiment = function(experimentsSettings, name, title)
308 {
309     this._name = name;
310     this._title = title;
311     this._experimentsSettings = experimentsSettings;
312 }
313
314 WebInspector.Experiment.prototype = {
315     /**
316      * @return {string}
317      */
318     get name()
319     {
320         return this._name;
321     },
322     
323     /**
324      * @return {string}
325      */
326     get title()
327     {
328         return this._title;
329     },
330     
331     /**
332      * @return {boolean}
333      */
334     isEnabled: function()
335     {
336         return this._experimentsSettings.isEnabled(this._name);
337     },
338     
339     /**
340      * @param {boolean} enabled
341      */
342     setEnabled: function(enabled)
343     {
344         return this._experimentsSettings.setEnabled(this._name, enabled);
345     },
346
347     enableForTest: function()
348     {
349         this._experimentsSettings._enableForTest(this._name);
350     }
351 }
352
353 WebInspector.settings = new WebInspector.Settings();
354 WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings();