Settings.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. var Preferences = {
  31. maxInlineTextChildLength: 80,
  32. minConsoleHeight: 75,
  33. minSidebarWidth: 100,
  34. minSidebarHeight: 75,
  35. minElementsSidebarWidth: 200,
  36. minElementsSidebarHeight: 200,
  37. minScriptsSidebarWidth: 200,
  38. applicationTitle: "Developer Tools - %s",
  39. experimentsEnabled: false
  40. }
  41. var Capabilities = {
  42. canInspectWorkers: false
  43. }
  44. /**
  45. * @constructor
  46. */
  47. WebInspector.Settings = function()
  48. {
  49. this._eventSupport = new WebInspector.Object();
  50. this._registry = /** @type {!Object.<string, !WebInspector.Setting>} */ ({});
  51. this.colorFormat = this.createSetting("colorFormat", "original");
  52. this.consoleHistory = this.createSetting("consoleHistory", []);
  53. this.domWordWrap = this.createSetting("domWordWrap", true);
  54. this.eventListenersFilter = this.createSetting("eventListenersFilter", "all");
  55. this.lastActivePanel = this.createSetting("lastActivePanel", "elements");
  56. this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application");
  57. this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false);
  58. this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false);
  59. this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true);
  60. this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
  61. this.resourceViewTab = this.createSetting("resourceViewTab", "preview");
  62. this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false);
  63. this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true);
  64. this.watchExpressions = this.createSetting("watchExpressions", []);
  65. this.breakpoints = this.createSetting("breakpoints", []);
  66. this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []);
  67. this.domBreakpoints = this.createSetting("domBreakpoints", []);
  68. this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []);
  69. this.jsSourceMapsEnabled = this.createSetting("sourceMapsEnabled", true);
  70. this.cssSourceMapsEnabled = this.createSetting("cssSourceMapsEnabled", true);
  71. this.cacheDisabled = this.createSetting("cacheDisabled", false);
  72. this.enableOverridesOnStartup = this.createSetting("enableOverridesOnStartup", false);
  73. this.overrideUserAgent = this.createSetting("overrideUserAgent", false);
  74. this.userAgent = this.createSetting("userAgent", "");
  75. this.overrideDeviceMetrics = this.createSetting("overrideDeviceMetrics", false);
  76. this.deviceMetrics = this.createSetting("deviceMetrics", "");
  77. this.deviceFitWindow = this.createSetting("deviceFitWindow", false);
  78. this.emulateTouchEvents = this.createSetting("emulateTouchEvents", false);
  79. this.showShadowDOM = this.createSetting("showShadowDOM", false);
  80. this.zoomLevel = this.createSetting("zoomLevel", 0);
  81. this.savedURLs = this.createSetting("savedURLs", {});
  82. this.javaScriptDisabled = this.createSetting("javaScriptDisabled", false);
  83. this.overrideGeolocation = this.createSetting("overrideGeolocation", false);
  84. this.geolocationOverride = this.createSetting("geolocationOverride", "");
  85. this.overrideDeviceOrientation = this.createSetting("overrideDeviceOrientation", false);
  86. this.deviceOrientationOverride = this.createSetting("deviceOrientationOverride", "");
  87. this.showAdvancedHeapSnapshotProperties = this.createSetting("showAdvancedHeapSnapshotProperties", false);
  88. this.searchInContentScripts = this.createSetting("searchInContentScripts", false);
  89. this.textEditorIndent = this.createSetting("textEditorIndent", " ");
  90. this.textEditorAutoDetectIndent = this.createSetting("textEditorAutoIndentIndent", true);
  91. this.lastDockState = this.createSetting("lastDockState", "");
  92. this.cssReloadEnabled = this.createSetting("cssReloadEnabled", false);
  93. this.showCpuOnTimelineRuler = this.createSetting("showCpuOnTimelineRuler", false);
  94. this.timelineStackFramesToCapture = this.createSetting("timelineStackFramesToCapture", 30);
  95. this.timelineLimitStackFramesFlag = this.createSetting("timelineLimitStackFramesFlag", false);
  96. this.showMetricsRulers = this.createSetting("showMetricsRulers", false);
  97. this.overrideCSSMedia = this.createSetting("overrideCSSMedia", false);
  98. this.emulatedCSSMedia = this.createSetting("emulatedCSSMedia", "print");
  99. this.workerInspectorWidth = this.createSetting("workerInspectorWidth", 600);
  100. this.workerInspectorHeight = this.createSetting("workerInspectorHeight", 600);
  101. this.messageURLFilters = this.createSetting("messageURLFilters", {});
  102. this.messageSourceFilters = this.createSetting("messageSourceFilters", {"CSS": true});
  103. this.messageLevelFilters = this.createSetting("messageLevelFilters", {});
  104. this.splitVerticallyWhenDockedToRight = this.createSetting("splitVerticallyWhenDockedToRight", true);
  105. this.visiblePanels = this.createSetting("visiblePanels", {});
  106. this.shortcutPanelSwitch = this.createSetting("shortcutPanelSwitch", false);
  107. this.showWhitespacesInEditor = this.createSetting("showWhitespacesInEditor", false);
  108. this.skipStackFramesSwitch = this.createSetting("skipStackFramesSwitch", false);
  109. this.skipStackFramesPattern = this.createSetting("skipStackFramesPattern", "");
  110. }
  111. WebInspector.Settings.prototype = {
  112. /**
  113. * @param {string} key
  114. * @param {*} defaultValue
  115. * @return {!WebInspector.Setting}
  116. */
  117. createSetting: function(key, defaultValue)
  118. {
  119. if (!this._registry[key])
  120. this._registry[key] = new WebInspector.Setting(key, defaultValue, this._eventSupport, window.localStorage);
  121. return this._registry[key];
  122. },
  123. /**
  124. * @param {string} key
  125. * @param {*} defaultValue
  126. * @param {function(*, function(string, ...))} setterCallback
  127. * @return {!WebInspector.Setting}
  128. */
  129. createBackendSetting: function(key, defaultValue, setterCallback)
  130. {
  131. if (!this._registry[key])
  132. this._registry[key] = new WebInspector.BackendSetting(key, defaultValue, this._eventSupport, window.localStorage, setterCallback);
  133. return this._registry[key];
  134. }
  135. }
  136. /**
  137. * @constructor
  138. * @param {string} name
  139. * @param {*} defaultValue
  140. * @param {!WebInspector.Object} eventSupport
  141. * @param {?Storage} storage
  142. */
  143. WebInspector.Setting = function(name, defaultValue, eventSupport, storage)
  144. {
  145. this._name = name;
  146. this._defaultValue = defaultValue;
  147. this._eventSupport = eventSupport;
  148. this._storage = storage;
  149. }
  150. WebInspector.Setting.prototype = {
  151. /**
  152. * @param {function(WebInspector.Event)} listener
  153. * @param {Object=} thisObject
  154. */
  155. addChangeListener: function(listener, thisObject)
  156. {
  157. this._eventSupport.addEventListener(this._name, listener, thisObject);
  158. },
  159. /**
  160. * @param {function(WebInspector.Event)} listener
  161. * @param {Object=} thisObject
  162. */
  163. removeChangeListener: function(listener, thisObject)
  164. {
  165. this._eventSupport.removeEventListener(this._name, listener, thisObject);
  166. },
  167. get name()
  168. {
  169. return this._name;
  170. },
  171. get: function()
  172. {
  173. if (typeof this._value !== "undefined")
  174. return this._value;
  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. set: function(value)
  186. {
  187. this._value = value;
  188. if (this._storage) {
  189. try {
  190. this._storage[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. * @constructor
  200. * @extends {WebInspector.Setting}
  201. * @param {string} name
  202. * @param {*} defaultValue
  203. * @param {!WebInspector.Object} eventSupport
  204. * @param {?Storage} storage
  205. * @param {function(*,function(string, ...))} setterCallback
  206. */
  207. WebInspector.BackendSetting = function(name, defaultValue, eventSupport, storage, setterCallback)
  208. {
  209. WebInspector.Setting.call(this, name, defaultValue, eventSupport, storage);
  210. this._setterCallback = setterCallback;
  211. var currentValue = this.get();
  212. if (currentValue !== defaultValue) {
  213. this._value = defaultValue; // Make sure we're in sync with backend, in case setting fails.
  214. this.set(currentValue);
  215. }
  216. }
  217. WebInspector.BackendSetting.prototype = {
  218. set: function(value)
  219. {
  220. function callback(error)
  221. {
  222. if (error) {
  223. WebInspector.log("Error applying setting " + this._name + ": " + error);
  224. this._eventSupport.dispatchEventToListeners(this._name, this._value);
  225. return;
  226. }
  227. WebInspector.Setting.prototype.set.call(this, value);
  228. }
  229. this._setterCallback(value, callback.bind(this));
  230. },
  231. __proto__: WebInspector.Setting.prototype
  232. };
  233. /**
  234. * @constructor
  235. */
  236. WebInspector.ExperimentsSettings = function()
  237. {
  238. this._setting = WebInspector.settings.createSetting("experiments", {});
  239. this._experiments = [];
  240. this._enabledForTest = {};
  241. // Add currently running experiments here.
  242. this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection");
  243. this.canvasInspection = this._createExperiment("canvasInspection ", "Canvas inspection");
  244. this.cssRegions = this._createExperiment("cssRegions", "CSS Regions Support");
  245. this.showOverridesInDrawer = this._createExperiment("showOverridesInDrawer", "Show Overrides in drawer");
  246. this.customizableToolbar = this._createExperiment("customizableToolbar", "Enable toolbar customization");
  247. this.drawerOverlay = this._createExperiment("drawerOverlay", "Open console as overlay");
  248. this.frameworksDebuggingSupport = this._createExperiment("frameworksDebuggingSupport", "Enable frameworks debugging support");
  249. this.layersPanel = this._createExperiment("layersPanel", "Show Layers panel");
  250. this.screencast = this._createExperiment("screencast", "Enable screencast");
  251. this.stepIntoSelection = this._createExperiment("stepIntoSelection", "Show step-in candidates while debugging.");
  252. this.openConsoleWithCtrlTilde = this._createExperiment("openConsoleWithCtrlTilde", "Open console with Ctrl/Cmd+Tilde, not Esc");
  253. this._cleanUpSetting();
  254. }
  255. WebInspector.ExperimentsSettings.prototype = {
  256. /**
  257. * @return {Array.<WebInspector.Experiment>}
  258. */
  259. get experiments()
  260. {
  261. return this._experiments.slice();
  262. },
  263. /**
  264. * @return {boolean}
  265. */
  266. get experimentsEnabled()
  267. {
  268. return Preferences.experimentsEnabled || ("experiments" in WebInspector.queryParamsObject);
  269. },
  270. /**
  271. * @param {string} experimentName
  272. * @param {string} experimentTitle
  273. * @return {WebInspector.Experiment}
  274. */
  275. _createExperiment: function(experimentName, experimentTitle)
  276. {
  277. var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle);
  278. this._experiments.push(experiment);
  279. return experiment;
  280. },
  281. /**
  282. * @param {string} experimentName
  283. * @return {boolean}
  284. */
  285. isEnabled: function(experimentName)
  286. {
  287. if (this._enabledForTest[experimentName])
  288. return true;
  289. if (!this.experimentsEnabled)
  290. return false;
  291. var experimentsSetting = this._setting.get();
  292. return experimentsSetting[experimentName];
  293. },
  294. /**
  295. * @param {string} experimentName
  296. * @param {boolean} enabled
  297. */
  298. setEnabled: function(experimentName, enabled)
  299. {
  300. var experimentsSetting = this._setting.get();
  301. experimentsSetting[experimentName] = enabled;
  302. this._setting.set(experimentsSetting);
  303. },
  304. /**
  305. * @param {string} experimentName
  306. */
  307. _enableForTest: function(experimentName)
  308. {
  309. this._enabledForTest[experimentName] = true;
  310. },
  311. _cleanUpSetting: function()
  312. {
  313. var experimentsSetting = this._setting.get();
  314. var cleanedUpExperimentSetting = {};
  315. for (var i = 0; i < this._experiments.length; ++i) {
  316. var experimentName = this._experiments[i].name;
  317. if (experimentsSetting[experimentName])
  318. cleanedUpExperimentSetting[experimentName] = true;
  319. }
  320. this._setting.set(cleanedUpExperimentSetting);
  321. }
  322. }
  323. /**
  324. * @constructor
  325. * @param {WebInspector.ExperimentsSettings} experimentsSettings
  326. * @param {string} name
  327. * @param {string} title
  328. */
  329. WebInspector.Experiment = function(experimentsSettings, name, title)
  330. {
  331. this._name = name;
  332. this._title = title;
  333. this._experimentsSettings = experimentsSettings;
  334. }
  335. WebInspector.Experiment.prototype = {
  336. /**
  337. * @return {string}
  338. */
  339. get name()
  340. {
  341. return this._name;
  342. },
  343. /**
  344. * @return {string}
  345. */
  346. get title()
  347. {
  348. return this._title;
  349. },
  350. /**
  351. * @return {boolean}
  352. */
  353. isEnabled: function()
  354. {
  355. return this._experimentsSettings.isEnabled(this._name);
  356. },
  357. /**
  358. * @param {boolean} enabled
  359. */
  360. setEnabled: function(enabled)
  361. {
  362. return this._experimentsSettings.setEnabled(this._name, enabled);
  363. },
  364. enableForTest: function()
  365. {
  366. this._experimentsSettings._enableForTest(this._name);
  367. }
  368. }
  369. /**
  370. * @constructor
  371. */
  372. WebInspector.VersionController = function()
  373. {
  374. }
  375. WebInspector.VersionController.currentVersion = 4;
  376. WebInspector.VersionController.prototype = {
  377. updateVersion: function()
  378. {
  379. var versionSetting = WebInspector.settings.createSetting("inspectorVersion", 0);
  380. var currentVersion = WebInspector.VersionController.currentVersion;
  381. var oldVersion = versionSetting.get();
  382. var methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion);
  383. for (var i = 0; i < methodsToRun.length; ++i)
  384. this[methodsToRun[i]].call(this);
  385. versionSetting.set(currentVersion);
  386. },
  387. /**
  388. * @param {number} oldVersion
  389. * @param {number} currentVersion
  390. */
  391. _methodsToRunToUpdateVersion: function(oldVersion, currentVersion)
  392. {
  393. var result = [];
  394. for (var i = oldVersion; i < currentVersion; ++i)
  395. result.push("_updateVersionFrom" + i + "To" + (i + 1));
  396. return result;
  397. },
  398. _updateVersionFrom0To1: function()
  399. {
  400. this._clearBreakpointsWhenTooMany(WebInspector.settings.breakpoints, 500000);
  401. },
  402. _updateVersionFrom1To2: function()
  403. {
  404. var versionSetting = WebInspector.settings.createSetting("previouslyViewedFiles", []);
  405. versionSetting.set([]);
  406. },
  407. _updateVersionFrom2To3: function()
  408. {
  409. var fileSystemMappingSetting = WebInspector.settings.createSetting("fileSystemMapping", {});
  410. fileSystemMappingSetting.set({});
  411. delete window.localStorage["fileMappingEntries"];
  412. },
  413. _updateVersionFrom3To4: function()
  414. {
  415. var advancedMode = WebInspector.settings.createSetting("showHeaSnapshotObjectsHiddenProperties", false).get();
  416. WebInspector.settings.showAdvancedHeapSnapshotProperties.set(advancedMode);
  417. },
  418. /**
  419. * @param {WebInspector.Setting} breakpointsSetting
  420. * @param {number} maxBreakpointsCount
  421. */
  422. _clearBreakpointsWhenTooMany: function(breakpointsSetting, maxBreakpointsCount)
  423. {
  424. // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
  425. // periodical breakpoints duplication leading to inspector slowness.
  426. if (breakpointsSetting.get().length > maxBreakpointsCount)
  427. breakpointsSetting.set([]);
  428. }
  429. }
  430. WebInspector.settings = new WebInspector.Settings();
  431. WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings();