--- a/devtools/client/framework/devtools.js
+++ b/devtools/client/framework/devtools.js
@@ -313,24 +313,16 @@ DevTools.prototype = {
// Reset the theme if an extension theme that's currently applied
// is being removed.
// Ignore shutdown since addons get disabled during that time.
if (!Services.startup.shuttingDown &&
!isCoreTheme &&
theme.id == currTheme) {
Services.prefs.setCharPref("devtools.theme", "light");
- let data = {
- pref: "devtools.theme",
- newValue: "light",
- oldValue: currTheme
- };
-
- this.emit("pref-changed", data);
-
this.emit("theme-unregistered", theme);
}
this._themes.delete(themeId);
},
/**
* Get a theme definition if it exists.
--- a/devtools/client/framework/test/browser_toolbox_options.js
+++ b/devtools/client/framework/test/browser_toolbox_options.js
@@ -7,16 +7,17 @@
"use strict";
// Tests that changing preferences in the options panel updates the prefs
// and toggles appropriate things in the toolbox.
var doc = null, toolbox = null, panelWin = null, modifiedPrefs = [];
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
+const {PrefObserver} = require("devtools/client/shared/prefs");
add_task(function* () {
const URL = "data:text/html;charset=utf8,test for dynamically registering " +
"and unregistering tools";
registerNewTool();
let tab = yield addTab(URL);
let target = TargetFactory.forTab(tab);
toolbox = yield gDevTools.showToolbox(target);
@@ -146,60 +147,63 @@ function* testSelect(select) {
is(select.options[select.selectedIndex].value, GetPref(pref),
"select starts out selected");
for (let option of options) {
if (options.indexOf(option) === select.selectedIndex) {
continue;
}
+ let observer = new PrefObserver("devtools.");
+
let deferred = defer();
- gDevTools.once("pref-changed", (event, data) => {
- if (data.pref == pref) {
- ok(true, "Correct pref was changed");
- is(GetPref(pref), option.value, "Preference been switched for " + pref);
- } else {
- ok(false, "Pref " + pref + " was not changed correctly");
- }
+ let changeSeen = false;
+ observer.once(pref, () => {
+ changeSeen = true;
+ is(GetPref(pref), option.value, "Preference been switched for " + pref);
deferred.resolve();
});
select.selectedIndex = options.indexOf(option);
let changeEvent = new Event("change");
select.dispatchEvent(changeEvent);
yield deferred.promise;
+
+ ok(changeSeen, "Correct pref was changed");
+ observer.destroy();
}
}
function* testMouseClick(node, prefValue) {
let deferred = defer();
+ let observer = new PrefObserver("devtools.");
+
let pref = node.getAttribute("data-pref");
- gDevTools.once("pref-changed", (event, data) => {
- if (data.pref == pref) {
- ok(true, "Correct pref was changed");
- is(data.oldValue, prefValue, "Previous value is correct for " + pref);
- is(data.newValue, !prefValue, "New value is correct for " + pref);
- } else {
- ok(false, "Pref " + pref + " was not changed correctly");
- }
+ let changeSeen = false;
+ observer.once(pref, () => {
+ changeSeen = true;
+ is(GetPref(pref), !prefValue, "New value is correct for " + pref);
deferred.resolve();
});
node.scrollIntoView();
// We use executeSoon here to ensure that the element is in view and
// clickable.
executeSoon(function () {
info("Click event synthesized for pref " + pref);
EventUtils.synthesizeMouseAtCenter(node, {}, panelWin);
});
yield deferred.promise;
+
+ ok(changeSeen, "Correct pref was changed");
+ observer.destroy();
}
function* testToggleTools() {
let toolNodes = panelWin.document.querySelectorAll(
"#default-tools-box input[type=checkbox]:not([data-unsupported])," +
"#additional-tools-box input[type=checkbox]:not([data-unsupported])");
let enabledTools = [...toolNodes].filter(node => node.checked);
--- a/devtools/client/framework/toolbox-options.js
+++ b/devtools/client/framework/toolbox-options.js
@@ -270,17 +270,17 @@ OptionsPanel.prototype = {
let createThemeOption = theme => {
let inputLabel = this.panelDoc.createElement("label");
let inputRadio = this.panelDoc.createElement("input");
inputRadio.setAttribute("type", "radio");
inputRadio.setAttribute("value", theme.id);
inputRadio.setAttribute("name", "devtools-theme-item");
inputRadio.addEventListener("change", function (e) {
- setPrefAndEmit(themeBox.getAttribute("data-pref"),
+ SetPref(themeBox.getAttribute("data-pref"),
e.target.value);
});
let inputSpanLabel = this.panelDoc.createElement("span");
inputSpanLabel.textContent = theme.label;
inputLabel.appendChild(inputRadio);
inputLabel.appendChild(inputSpanLabel);
@@ -300,32 +300,32 @@ OptionsPanel.prototype = {
let prefCheckboxes = this.panelDoc.querySelectorAll(
"input[type=checkbox][data-pref]");
for (let prefCheckbox of prefCheckboxes) {
if (GetPref(prefCheckbox.getAttribute("data-pref"))) {
prefCheckbox.setAttribute("checked", true);
}
prefCheckbox.addEventListener("change", function (e) {
let checkbox = e.target;
- setPrefAndEmit(checkbox.getAttribute("data-pref"), checkbox.checked);
+ SetPref(checkbox.getAttribute("data-pref"), checkbox.checked);
});
}
// Themes radio inputs are handled in setupThemeList
let prefRadiogroups = this.panelDoc.querySelectorAll(
".radiogroup[data-pref]:not(#devtools-theme-box)");
for (let radioGroup of prefRadiogroups) {
let selectedValue = GetPref(radioGroup.getAttribute("data-pref"));
for (let radioInput of radioGroup.querySelectorAll("input[type=radio]")) {
if (radioInput.getAttribute("value") == selectedValue) {
radioInput.setAttribute("checked", true);
}
radioInput.addEventListener("change", function (e) {
- setPrefAndEmit(radioGroup.getAttribute("data-pref"),
+ SetPref(radioGroup.getAttribute("data-pref"),
e.target.value);
});
}
}
let prefSelects = this.panelDoc.querySelectorAll("select[data-pref]");
for (let prefSelect of prefSelects) {
let pref = GetPref(prefSelect.getAttribute("data-pref"));
let options = [...prefSelect.options];
@@ -335,17 +335,17 @@ OptionsPanel.prototype = {
if (value == pref) {
prefSelect.selectedIndex = options.indexOf(option);
return true;
}
});
prefSelect.addEventListener("change", function (e) {
let select = e.target;
- setPrefAndEmit(select.getAttribute("data-pref"),
+ SetPref(select.getAttribute("data-pref"),
select.options[select.selectedIndex].value);
});
}
if (this.target.activeTab) {
return this.target.client.attachTab(this.target.activeTab._actor)
.then(([response, client]) => {
this._origJavascriptEnabled = !response.javascriptEnabled;
@@ -417,22 +417,8 @@ OptionsPanel.prototype = {
deferred.resolve();
}
this.panelWin = this.panelDoc = this.disableJSNode = this.toolbox = null;
return this.destroyPromise;
}
};
-
-/* Set a pref and emit the pref-changed event if needed. */
-function setPrefAndEmit(prefName, newValue) {
- let data = {
- pref: prefName,
- newValue: newValue
- };
- data.oldValue = GetPref(data.pref);
- SetPref(data.pref, data.newValue);
-
- if (data.newValue != data.oldValue) {
- gDevTools.emit("pref-changed", data);
- }
-}
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -108,17 +108,19 @@ function Toolbox(target, selectedTool, h
this._toggleAutohide = this._toggleAutohide.bind(this);
this.showFramesMenu = this.showFramesMenu.bind(this);
this._updateFrames = this._updateFrames.bind(this);
this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this);
this.destroy = this.destroy.bind(this);
this.highlighterUtils = getHighlighterUtils(this);
this._highlighterReady = this._highlighterReady.bind(this);
this._highlighterHidden = this._highlighterHidden.bind(this);
- this._prefChanged = this._prefChanged.bind(this);
+ this._applyCacheSettings = this._applyCacheSettings.bind(this);
+ this._applyServiceWorkersTestingSettings =
+ this._applyServiceWorkersTestingSettings.bind(this);
this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
this._onFocus = this._onFocus.bind(this);
this._onBrowserMessage = this._onBrowserMessage.bind(this);
this._showDevEditionPromo = this._showDevEditionPromo.bind(this);
this._updateTextBoxMenuItems = this._updateTextBoxMenuItems.bind(this);
this._onBottomHostMinimized = this._onBottomHostMinimized.bind(this);
this._onBottomHostMaximized = this._onBottomHostMaximized.bind(this);
this._onToolSelectWhileMinimized = this._onToolSelectWhileMinimized.bind(this);
@@ -362,17 +364,20 @@ Toolbox.prototype = {
yield domReady.promise;
this.isReady = true;
let framesPromise = this._listFrames();
this.closeButton = this.doc.getElementById("toolbox-close");
this.closeButton.addEventListener("click", this.destroy, true);
- gDevTools.on("pref-changed", this._prefChanged);
+ Services.prefs.addObserver("devtools.cache.disabled", this._applyCacheSettings,
+ false);
+ Services.prefs.addObserver("devtools.serviceWorkers.testing.enabled",
+ this._applyServiceWorkersTestingSettings, false);
let framesMenu = this.doc.getElementById("command-button-frames");
framesMenu.addEventListener("click", this.showFramesMenu, false);
let noautohideMenu = this.doc.getElementById("command-button-noautohide");
noautohideMenu.addEventListener("click", this._toggleAutohide, true);
this.textBoxContextMenuPopup =
@@ -480,39 +485,16 @@ Toolbox.prototype = {
this._telemetry.logOncePerBrowserVersion(OS_HISTOGRAM, system.getOSCPU());
this._telemetry.logOncePerBrowserVersion(OS_IS_64_BITS,
Services.appinfo.is64Bit ? 1 : 0);
this._telemetry.logOncePerBrowserVersion(SCREENSIZE_HISTOGRAM,
system.getScreenDimensions());
this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
},
- /**
- * Because our panels are lazy loaded this is a good place to watch for
- * "pref-changed" events.
- * @param {String} event
- * The event type, "pref-changed".
- * @param {Object} data
- * {
- * newValue: The new value
- * oldValue: The old value
- * pref: The name of the preference that has changed
- * }
- */
- _prefChanged: function (event, data) {
- switch (data.pref) {
- case "devtools.cache.disabled":
- this._applyCacheSettings();
- break;
- case "devtools.serviceWorkers.testing.enabled":
- this._applyServiceWorkersTestingSettings();
- break;
- }
- },
-
_buildOptions: function () {
let selectOptions = (name, event) => {
// Flip back to the last used panel if we are already
// on the options panel.
if (this.currentToolId === "options" &&
gDevTools.getToolDefinition(this.lastUsedToolId)) {
this.selectTool(this.lastUsedToolId);
} else {
@@ -2209,17 +2191,19 @@ Toolbox.prototype = {
this._target.off("frame-update", this._updateFrames);
this.off("select", this._refreshHostTitle);
this.off("host-changed", this._refreshHostTitle);
this.off("ready", this._showDevEditionPromo);
gDevTools.off("tool-registered", this._toolRegistered);
gDevTools.off("tool-unregistered", this._toolUnregistered);
- gDevTools.off("pref-changed", this._prefChanged);
+ Services.prefs.removeObserver("devtools.cache.disabled", this._applyCacheSettings);
+ Services.prefs.removeObserver("devtools.serviceWorkers.testing.enabled",
+ this._applyServiceWorkersTestingSettings);
this._lastFocusedElement = null;
if (this._sourceMapService) {
this._sourceMapService.destroy();
this._sourceMapService = null;
}
if (this.webconsolePanel) {
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -193,24 +193,23 @@ function CssComputedView(inspector, docu
this.includeBrowserStylesCheckbox.addEventListener("input",
this._onIncludeBrowserStyles);
this.searchClearButton.hidden = true;
// No results text.
this.noResults = this.styleDocument.getElementById("computedview-no-results");
- // Refresh panel when color unit changed.
+ // Refresh panel when color unit changed or pref for showing
+ // original sources changes.
this._handlePrefChange = this._handlePrefChange.bind(this);
- gDevTools.on("pref-changed", this._handlePrefChange);
-
- // Refresh panel when pref for showing original sources changes
this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
this._prefObserver = new PrefObserver("devtools.");
this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
+ this._prefObserver.on("devtools.defaultColorUnit", this._handlePrefChange);
// The element that we're inspecting, and the document that it comes from.
this._viewedElement = null;
this.createStyleViews();
this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
@@ -257,18 +256,17 @@ CssComputedView.prototype = {
this.pageStyle = pageStyle;
},
get includeBrowserStyles() {
return this.includeBrowserStylesCheckbox.checked;
},
_handlePrefChange: function (event, data) {
- if (this._computed && (data.pref === "devtools.defaultColorUnit" ||
- data.pref === PREF_ORIG_SOURCES)) {
+ if (this._computed) {
this.refreshPanel();
}
},
/**
* Update the view with a new selected element. The CssComputedView panel
* will show the style information for the given element.
*
@@ -595,16 +593,17 @@ CssComputedView.prototype = {
refreshSourceFilter: function () {
this._matchedProperties = null;
this._sourceFilter = this.includeBrowserStyles ?
CssLogic.FILTER.UA :
CssLogic.FILTER.USER;
},
_onSourcePrefChanged: function () {
+ this._handlePrefChange();
for (let propView of this.propertyViews) {
propView.updateSourceLinks();
}
this.inspector.emit("computed-view-sourcelinks-updated");
},
/**
* The CSS as displayed by the UI.
@@ -729,19 +728,18 @@ CssComputedView.prototype = {
/**
* Destructor for CssComputedView.
*/
destroy: function () {
this._viewedElement = null;
this._outputParser = null;
- gDevTools.off("pref-changed", this._handlePrefChange);
-
this._prefObserver.off(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
+ this._prefObserver.off("devtools.defaultColorUnit", this._handlePrefChange);
this._prefObserver.destroy();
// Cancel tree construction
if (this._createViewsProcess) {
this._createViewsProcess.cancel();
}
if (this._refreshProcess) {
this._refreshProcess.cancel();
--- a/devtools/client/performance/performance-controller.js
+++ b/devtools/client/performance/performance-controller.js
@@ -11,17 +11,17 @@ var BrowserLoaderModule = {};
Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
var { loader, require } = BrowserLoaderModule.BrowserLoader({
baseURI: "resource://devtools/client/performance/",
window
});
var { Task } = require("devtools/shared/task");
/* exported Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout */
var { Heritage, ViewHelpers, WidgetMethods, setNamedTimeout, clearNamedTimeout } = require("devtools/client/shared/widgets/view-helpers");
-var { gDevTools } = require("devtools/client/framework/devtools");
+var { PrefObserver } = require("devtools/client/shared/prefs");
// Events emitted by various objects in the panel.
var EVENTS = require("devtools/client/performance/events");
Object.defineProperty(this, "EVENTS", {
value: EVENTS,
enumerable: true,
writable: false
});
@@ -138,17 +138,18 @@ var PerformanceController = {
PerformanceView.on(EVENTS.UI_START_RECORDING, this.startRecording);
PerformanceView.on(EVENTS.UI_STOP_RECORDING, this.stopRecording);
PerformanceView.on(EVENTS.UI_IMPORT_RECORDING, this.importRecording);
PerformanceView.on(EVENTS.UI_CLEAR_RECORDINGS, this.clearRecordings);
RecordingsView.on(EVENTS.UI_EXPORT_RECORDING, this.exportRecording);
RecordingsView.on(EVENTS.UI_RECORDING_SELECTED, this._onRecordingSelectFromView);
DetailsView.on(EVENTS.UI_DETAILS_VIEW_SELECTED, this._pipe);
- gDevTools.on("pref-changed", this._onThemeChanged);
+ this._prefObserver = new PrefObserver("devtools.");
+ this._prefObserver.on("devtools.theme", this._onThemeChanged);
}),
/**
* Remove events handled by the PerformanceController
*/
destroy: function () {
this._telemetry.destroy();
this._prefs.off("pref-changed", this._onPrefChanged);
@@ -158,17 +159,18 @@ var PerformanceController = {
PerformanceView.off(EVENTS.UI_START_RECORDING, this.startRecording);
PerformanceView.off(EVENTS.UI_STOP_RECORDING, this.stopRecording);
PerformanceView.off(EVENTS.UI_IMPORT_RECORDING, this.importRecording);
PerformanceView.off(EVENTS.UI_CLEAR_RECORDINGS, this.clearRecordings);
RecordingsView.off(EVENTS.UI_EXPORT_RECORDING, this.exportRecording);
RecordingsView.off(EVENTS.UI_RECORDING_SELECTED, this._onRecordingSelectFromView);
DetailsView.off(EVENTS.UI_DETAILS_VIEW_SELECTED, this._pipe);
- gDevTools.off("pref-changed", this._onThemeChanged);
+ this._prefObserver.off("devtools.theme", this._onThemeChanged);
+ this._prefObserver.destroy();
},
/**
* Enables front event listeners.
*
* The rationale behind this is given by the async intialization of all the
* frontend components. Even though the panel is considered "open" only after
* both the controller and the view are created, and even though their
@@ -397,24 +399,19 @@ var PerformanceController = {
*/
_onPrefChanged: function (_, prefName, prefValue) {
this.emit(EVENTS.PREF_CHANGED, prefName, prefValue);
},
/*
* Called when the developer tools theme changes.
*/
- _onThemeChanged: function (_, data) {
- // Right now, gDevTools only emits `pref-changed` for the theme,
- // but this could change in the future.
- if (data.pref !== "devtools.theme") {
- return;
- }
-
- this.emit(EVENTS.THEME_CHANGED, data.newValue);
+ _onThemeChanged: function () {
+ let newValue = Services.prefs.getCharPref("devtools.theme");
+ this.emit(EVENTS.THEME_CHANGED, newValue);
},
/**
* Fired from the front on any event. Propagates to other handlers from here.
*/
_onFrontEvent: function (eventName, ...data) {
switch (eventName) {
case "profiler-status":
--- a/devtools/client/shared/autocomplete-popup.js
+++ b/devtools/client/shared/autocomplete-popup.js
@@ -2,19 +2,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const Services = require("Services");
-const {gDevTools} = require("devtools/client/framework/devtools");
const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const EventEmitter = require("devtools/shared/event-emitter");
+const {PrefObserver} = require("devtools/client/shared/prefs");
let itemIdCounter = 0;
/**
* Autocomplete popup UI implementation.
*
* @constructor
* @param {Document} toolboxDoc
* The toolbox document to attach the autocomplete popup panel.
@@ -42,17 +42,19 @@ function AutocompletePopup(toolboxDoc, o
this.onClickCallback = options.onClick;
// If theme is auto, use the devtools.theme pref
if (theme === "auto") {
theme = Services.prefs.getCharPref("devtools.theme");
this.autoThemeEnabled = true;
// Setup theme change listener.
this._handleThemeChange = this._handleThemeChange.bind(this);
- gDevTools.on("pref-changed", this._handleThemeChange);
+ this._prefObserver = new PrefObserver("devtools.");
+ this._prefObserver.on("devtools.theme", this._handleThemeChange);
+ this._currentTheme = theme;
}
// Create HTMLTooltip instance
this._tooltip = new HTMLTooltip(this._document);
this._tooltip.panel.classList.add(
"devtools-autocomplete-popup",
"devtools-monospace",
theme + "-theme");
@@ -189,17 +191,18 @@ AutocompletePopup.prototype = {
destroy: function () {
if (this.isOpen) {
this.hidePopup();
}
this._list.removeEventListener("click", this.onClick, false);
if (this.autoThemeEnabled) {
- gDevTools.off("pref-changed", this._handleThemeChange);
+ this._prefObserver.off("devtools.theme", this._handleThemeChange);
+ this._prefObserver.destroy();
}
this._list.remove();
this._listClone.remove();
this._tooltip.destroy();
this._document = null;
this._list = null;
this._tooltip = null;
@@ -557,35 +560,27 @@ AutocompletePopup.prototype = {
selectPreviousPageItem: function () {
let prevPageIndex = this.selectedIndex - this._itemsPerPane - 1;
this.selectedIndex = Math.max(prevPageIndex, 0);
return this.selectedItem;
},
/**
* Manages theme switching for the popup based on the devtools.theme pref.
- *
- * @private
- *
- * @param {String} event
- * The name of the event. In this case, "pref-changed".
- * @param {Object} data
- * An object passed by the emitter of the event. In this case, the
- * object consists of three properties:
- * - pref {String} The name of the preference that was modified.
- * - newValue {Object} The new value of the preference.
- * - oldValue {Object} The old value of the preference.
*/
- _handleThemeChange: function (event, data) {
- if (data.pref === "devtools.theme") {
- this._tooltip.panel.classList.toggle(data.oldValue + "-theme", false);
- this._tooltip.panel.classList.toggle(data.newValue + "-theme", true);
- this._list.classList.toggle(data.oldValue + "-theme", false);
- this._list.classList.toggle(data.newValue + "-theme", true);
- }
+ _handleThemeChange: function () {
+ const oldValue = this._currentTheme;
+ const newValue = Services.prefs.getCharPref("devtools.theme");
+
+ this._tooltip.panel.classList.toggle(oldValue + "-theme", false);
+ this._tooltip.panel.classList.toggle(newValue + "-theme", true);
+ this._list.classList.toggle(oldValue + "-theme", false);
+ this._list.classList.toggle(newValue + "-theme", true);
+
+ this._currentTheme = newValue;
},
/**
* Used by tests.
*/
get _panel() {
return this._tooltip.panel;
},
--- a/devtools/client/shared/test/browser_theme.js
+++ b/devtools/client/shared/test/browser_theme.js
@@ -2,16 +2,17 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that theme utilities work
const {getColor, getTheme, setTheme} = require("devtools/client/shared/theme");
+const {PrefObserver} = require("devtools/client/shared/prefs");
add_task(function* () {
testGetTheme();
testSetTheme();
testGetColor();
testColorExistence();
});
@@ -26,37 +27,40 @@ function testGetTheme() {
is(getTheme(), "firebug", "getTheme() correctly returns firebug theme");
Services.prefs.setCharPref("devtools.theme", "unknown");
is(getTheme(), "unknown", "getTheme() correctly returns an unknown theme");
Services.prefs.setCharPref("devtools.theme", originalTheme);
}
function testSetTheme() {
let originalTheme = getTheme();
- gDevTools.once("pref-changed", (_, { pref, oldValue, newValue }) => {
+
+ let prefObserver = new PrefObserver("devtools.");
+ prefObserver.once("devtools.theme", pref => {
is(pref, "devtools.theme",
- "The 'pref-changed' event triggered by setTheme has correct pref.");
- is(oldValue, originalTheme,
- "The 'pref-changed' event triggered by setTheme has correct oldValue.");
+ "A preference event triggered by setTheme has correct pref.");
+ let newValue = Services.prefs.getCharPref("devtools.theme");
is(newValue, "dark",
- "The 'pref-changed' event triggered by setTheme has correct newValue.");
+ "A preference event triggered by setTheme comes after the value is set.");
});
setTheme("dark");
is(Services.prefs.getCharPref("devtools.theme"), "dark",
"setTheme() correctly sets dark theme.");
setTheme("light");
is(Services.prefs.getCharPref("devtools.theme"), "light",
"setTheme() correctly sets light theme.");
setTheme("firebug");
is(Services.prefs.getCharPref("devtools.theme"), "firebug",
"setTheme() correctly sets firebug theme.");
setTheme("unknown");
is(Services.prefs.getCharPref("devtools.theme"), "unknown",
"setTheme() correctly sets an unknown theme.");
Services.prefs.setCharPref("devtools.theme", originalTheme);
+
+ prefObserver.destroy();
}
function testGetColor() {
let BLUE_DARK = "#46afe3";
let BLUE_LIGHT = "#0088cc";
let BLUE_FIREBUG = "#3455db";
let originalTheme = getTheme();
--- a/devtools/client/shared/theme.js
+++ b/devtools/client/shared/theme.js
@@ -5,17 +5,16 @@
"use strict";
/**
* Colors for themes taken from:
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
*/
const Services = require("Services");
-const { gDevTools } = require("devtools/client/framework/devtools");
const variableFileContents = require("raw!devtools/client/themes/variables.css");
const THEME_SELECTOR_STRINGS = {
light: ":root.theme-light {",
dark: ":root.theme-dark {",
firebug: ":root.theme-firebug {"
};
@@ -62,23 +61,14 @@ const getColor = exports.getColor = (typ
let themeFile = getThemeFile(themeName);
let match = themeFile.match(new RegExp("--theme-" + type + ": (.*);"));
// Return the appropriate variable in the theme, or otherwise, null.
return match ? match[1] : null;
};
/**
- * Mimics selecting the theme selector in the toolbox;
- * sets the preference and emits an event on gDevTools to trigger
- * the themeing.
+ * Set the theme preference.
*/
const setTheme = exports.setTheme = (newTheme) => {
- let oldTheme = getTheme();
-
Services.prefs.setCharPref("devtools.theme", newTheme);
- gDevTools.emit("pref-changed", {
- pref: "devtools.theme",
- newValue: newTheme,
- oldValue: oldTheme
- });
};
/* eslint-enable */
--- a/devtools/client/webaudioeditor/controller.js
+++ b/devtools/client/webaudioeditor/controller.js
@@ -1,12 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
+const {PrefObserver} = require("devtools/client/shared/prefs");
+
/**
* A collection of `AudioNodeModel`s used throughout the editor
* to keep track of audio nodes within the audio context.
*/
var gAudioNodes = new AudioNodesCollection();
/**
* Initializes the web audio editor views
@@ -53,17 +55,19 @@ var WebAudioEditorController = {
gFront.on("connect-param", this._onConnectParam);
gFront.on("disconnect-node", this._onDisconnectNode);
gFront.on("change-param", this._onChangeParam);
gFront.on("destroy-node", this._onDestroyNode);
// Hook into theme change so we can change
// the graph's marker styling, since we can't do this
// with CSS
- gDevTools.on("pref-changed", this._onThemeChange);
+
+ this._prefObserver = new PrefObserver("");
+ this._prefObserver.on("devtools.theme", this._onThemeChange);
// Store the AudioNode definitions from the WebAudioFront, if the method exists.
// If not, get the JSON directly. Using the actor method is preferable so the client
// knows exactly what methods are supported on the server.
let actorHasDefinition = yield gTarget.actorHasMethod("webaudio", "getDefinition");
if (actorHasDefinition) {
AUDIO_NODE_DEFINITION = yield gFront.getDefinition();
} else {
@@ -85,17 +89,18 @@ var WebAudioEditorController = {
gTarget.off("navigate", this._onTabNavigated);
gFront.off("start-context", this._onStartContext);
gFront.off("create-node", this._onCreateNode);
gFront.off("connect-node", this._onConnectNode);
gFront.off("connect-param", this._onConnectParam);
gFront.off("disconnect-node", this._onDisconnectNode);
gFront.off("change-param", this._onChangeParam);
gFront.off("destroy-node", this._onDestroyNode);
- gDevTools.off("pref-changed", this._onThemeChange);
+ this._prefObserver.off("devtools.theme", this._onThemeChange);
+ this._prefObserver.destroy();
},
/**
* Called when page is reloaded to show the reload notice and waiting
* for an audio context notice.
*/
reset: function () {
$("#content").hidden = true;
@@ -124,18 +129,19 @@ var WebAudioEditorController = {
return node;
},
/**
* Fired when the devtools theme changes (light, dark, etc.)
* so that the graph can update marker styling, as that
* cannot currently be done with CSS.
*/
- _onThemeChange: function (event, data) {
- window.emit(EVENTS.THEME_CHANGE, data.newValue);
+ _onThemeChange: function () {
+ let newValue = Services.prefs.getCharPref("devtools.theme");
+ window.emit(EVENTS.THEME_CHANGE, newValue);
},
/**
* Called for each location change in the debugged tab.
*/
_onTabNavigated: Task.async(function* (event, {isFrameSwitching}) {
switch (event) {
case "will-navigate": {
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_timestamps.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_timestamps.js
@@ -3,50 +3,52 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test for the message timestamps option: check if the preference toggles the
// display of messages in the console output. See bug 722267.
"use strict";
+const {PrefObserver} = require("devtools/client/shared/prefs");
+
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
"bug 1307871 - preference for toggling timestamps in messages";
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
add_task(function* () {
let hud = yield openNewTabAndConsole(TEST_URI);
let outputNode = hud.ui.experimentalOutputNode;
let outputEl = outputNode.querySelector(".webconsole-output");
testPrefDefaults(outputEl);
+ let observer = new PrefObserver("");
let toolbox = gDevTools.getToolbox(hud.target);
let optionsPanel = yield toolbox.selectTool("options");
- yield togglePref(optionsPanel);
+ yield togglePref(optionsPanel, observer);
+ observer.destroy();
yield testChangedPref(outputEl);
Services.prefs.clearUserPref(PREF_MESSAGE_TIMESTAMP);
});
function testPrefDefaults(outputEl) {
let prefValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
ok(!prefValue, "Messages should have no timestamp by default (pref check)");
ok(outputEl.classList.contains("hideTimestamps"),
"Messages should have no timestamp (class name check)");
}
-function* togglePref(panel) {
+function* togglePref(panel, observer) {
info("Options panel opened");
info("Changing pref");
- let prefChanged = new Promise(resolve => {
- gDevTools.once("pref-changed", resolve);
- });
+ let prefChanged = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
let checkbox = panel.panelDoc.getElementById("webconsole-timestamp-messages");
checkbox.click();
yield prefChanged;
}
function* testChangedPref(outputEl) {
let prefValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
--- a/devtools/client/webconsole/test/browser_webconsole_expandable_timestamps.js
+++ b/devtools/client/webconsole/test/browser_webconsole_expandable_timestamps.js
@@ -3,49 +3,53 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test for the message timestamps option: check if the preference toggles the
// display of messages in the console output. See bug 722267.
"use strict";
+const {PrefObserver} = require("devtools/client/shared/prefs");
+
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
"bug 722267 - preference for toggling timestamps in messages";
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
var hud;
add_task(function* () {
yield loadTab(TEST_URI);
hud = yield openConsole();
let panel = yield consoleOpened();
- yield onOptionsPanelSelected(panel);
+ let observer = new PrefObserver("");
+ yield onOptionsPanelSelected(panel, observer);
onPrefChanged();
+ observer.destroy();
Services.prefs.clearUserPref(PREF_MESSAGE_TIMESTAMP);
hud = null;
});
function consoleOpened() {
info("console opened");
let prefValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
ok(!prefValue, "messages have no timestamp by default (pref check)");
ok(hud.outputNode.classList.contains("hideTimestamps"),
"messages have no timestamp (class name check)");
let toolbox = gDevTools.getToolbox(hud.target);
return toolbox.selectTool("options");
}
-function onOptionsPanelSelected(panel) {
+function onOptionsPanelSelected(panel, observer) {
info("options panel opened");
- let prefChanged = gDevTools.once("pref-changed", onPrefChanged);
+ let prefChanged = observer.once(PREF_MESSAGE_TIMESTAMP, () => {});
let checkbox = panel.panelDoc.getElementById("webconsole-timestamp-messages");
checkbox.click();
return prefChanged;
}
function onPrefChanged() {
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -12,16 +12,17 @@ const {Utils: WebConsoleUtils, CONSOLE_W
require("devtools/client/webconsole/utils");
const { getSourceNames } = require("devtools/client/shared/source-utils");
const BrowserLoaderModule = {};
Cu.import("resource://devtools/client/shared/browser-loader.js", BrowserLoaderModule);
const promise = require("promise");
const Services = require("Services");
const Telemetry = require("devtools/client/shared/telemetry");
+const {PrefObserver} = require("devtools/client/shared/prefs");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper");
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "ConsoleOutput", "devtools/client/webconsole/console-output", true);
loader.lazyRequireGetter(this, "Messages", "devtools/client/webconsole/console-output", true);
loader.lazyRequireGetter(this, "EnvironmentClient", "devtools/shared/client/main", true);
@@ -631,21 +632,19 @@ WebConsoleFrame.prototype = {
event.target.getAttribute("type").toLowerCase() === "search") {
return;
}
this.jsterm.focus();
});
// Toggle the timestamp on preference change
- gDevTools.on("pref-changed", this._onToolboxPrefChanged);
- this._onToolboxPrefChanged("pref-changed", {
- pref: PREF_MESSAGE_TIMESTAMP,
- newValue: Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP),
- });
+ this._prefObserver = new PrefObserver("");
+ this._prefObserver.on(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
+ this._onToolboxPrefChanged();
this._initShortcuts();
// focus input node
this.jsterm.focus();
},
/**
@@ -2686,35 +2685,26 @@ WebConsoleFrame.prototype = {
this._startX = this._startY = undefined;
callback.call(this, event);
}, false);
},
/**
- * Handler for the pref-changed event coming from the toolbox.
- * Currently this function only handles the timestamps preferences.
- *
- * @private
- * @param object event
- * This parameter is a string that holds the event name
- * pref-changed in this case.
- * @param object data
- * This is the pref-changed data object.
- */
- _onToolboxPrefChanged: function (event, data) {
- if (data.pref == PREF_MESSAGE_TIMESTAMP) {
- if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
- this.newConsoleOutput.dispatchTimestampsToggle(data.newValue);
- } else if (data.newValue) {
- this.outputNode.classList.remove("hideTimestamps");
- } else {
- this.outputNode.classList.add("hideTimestamps");
- }
+ * Called when the message timestamp pref changes.
+ */
+ _onToolboxPrefChanged: function () {
+ let newValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
+ if (this.NEW_CONSOLE_OUTPUT_ENABLED) {
+ this.newConsoleOutput.dispatchTimestampsToggle(newValue);
+ } else if (newValue) {
+ this.outputNode.classList.remove("hideTimestamps");
+ } else {
+ this.outputNode.classList.add("hideTimestamps");
}
},
/**
* Copies the selected items to the system clipboard.
*
* @param object options
* - linkOnly:
@@ -2813,17 +2803,18 @@ WebConsoleFrame.prototype = {
this._destroyer = promise.defer();
let toolbox = gDevTools.getToolbox(this.owner.target);
if (toolbox) {
toolbox.off("webconsole-selected", this._onPanelSelected);
}
- gDevTools.off("pref-changed", this._onToolboxPrefChanged);
+ this._prefObserver.off(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
+ this._prefObserver.destroy();
this.window.removeEventListener("resize", this.resize, true);
this._repeatNodes = {};
this._outputQueue.forEach(this._destroyItem, this);
this._outputQueue = [];
this._itemDestroyQueue.forEach(this._destroyItem, this);
this._itemDestroyQueue = [];
this._pruneCategoriesQueue = {};