diff --git a/accessible/jsat/AccessFu.jsm b/accessible/jsat/AccessFu.jsm index d87962ac3d85..cba9ee07ce95 100644 --- a/accessible/jsat/AccessFu.jsm +++ b/accessible/jsat/AccessFu.jsm @@ -37,6 +37,16 @@ this.AccessFu = { // jshint ignore:line Services.obs.addObserver(this, 'Accessibility:Settings', false); } catch (x) { // Not on Android + if (aWindow.navigator.mozSettings) { + let lock = aWindow.navigator.mozSettings.createLock(); + let req = lock.get(SCREENREADER_SETTING); + req.addEventListener('success', () => { + this._systemPref = req.result[SCREENREADER_SETTING]; + this._enableOrDisable(); + }); + aWindow.navigator.mozSettings.addObserver( + SCREENREADER_SETTING, this.handleEvent); + } } this._activatePref = new PrefCache( @@ -55,6 +65,9 @@ this.AccessFu = { // jshint ignore:line } if (Utils.MozBuildApp === 'mobile/android') { Services.obs.removeObserver(this, 'Accessibility:Settings'); + } else if (Utils.win.navigator.mozSettings) { + Utils.win.navigator.mozSettings.removeObserver( + SCREENREADER_SETTING, this.handleEvent); } delete this._activatePref; Utils.uninit(); diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm index 61a68eb28b67..4e478cab0d85 100644 --- a/accessible/jsat/Utils.jsm +++ b/accessible/jsat/Utils.jsm @@ -4,7 +4,7 @@ /* global Components, XPCOMUtils, Services, PluralForm, Logger, Rect, Utils, States, Relations, Roles, dump, Events, PivotContext, PrefCache */ -/* exported Utils, Logger, PivotContext, PrefCache */ +/* exported Utils, Logger, PivotContext, PrefCache, SettingCache */ 'use strict'; @@ -26,7 +26,8 @@ XPCOMUtils.defineLazyModuleGetter(this, 'States', // jshint ignore:line XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm', // jshint ignore:line 'resource://gre/modules/PluralForm.jsm'); -this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache']; // jshint ignore:line +this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache', // jshint ignore:line + 'SettingCache']; this.Utils = { // jshint ignore:line _buildAppMap: { @@ -1073,3 +1074,41 @@ PrefCache.prototype = { QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]) }; + +this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) { // jshint ignore:line + this.value = aOptions.defaultValue; + let runCallback = () => { + if (aCallback) { + aCallback(aName, this.value); + if (aOptions.callbackOnce) { + runCallback = () => {}; + } + } + }; + + let settings = Utils.win.navigator.mozSettings; + if (!settings) { + if (aOptions.callbackNow) { + runCallback(); + } + return; + } + + + let lock = settings.createLock(); + let req = lock.get(aName); + + req.addEventListener('success', () => { + this.value = req.result[aName] === undefined ? + aOptions.defaultValue : req.result[aName]; + if (aOptions.callbackNow) { + runCallback(); + } + }); + + settings.addObserver(aName, + (evt) => { + this.value = evt.settingValue; + runCallback(); + }); +}; diff --git a/accessible/tests/mochitest/jsat/jsatcommon.js b/accessible/tests/mochitest/jsat/jsatcommon.js index 43d754afa915..aa7ee74e400b 100644 --- a/accessible/tests/mochitest/jsat/jsatcommon.js +++ b/accessible/tests/mochitest/jsat/jsatcommon.js @@ -149,7 +149,8 @@ var AccessFuTest = { Logger.logLevel = Logger.DEBUG; }; - var prefs = [['accessibility.accessfu.notify_output', 1]]; + var prefs = [['accessibility.accessfu.notify_output', 1], + ['dom.mozSettings.enabled', true]]; prefs.push.apply(prefs, aAdditionalPrefs); this.originalDwellThreshold = GestureSettings.dwellThreshold; diff --git a/addon-sdk/source/python-lib/cuddlefish/prefs.py b/addon-sdk/source/python-lib/cuddlefish/prefs.py index c7208b7d732d..bb087b7f5eaf 100644 --- a/addon-sdk/source/python-lib/cuddlefish/prefs.py +++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py @@ -216,6 +216,7 @@ DEFAULT_TEST_PREFS = { 'layout.css.report_errors': True, 'layout.css.grid.enabled': True, 'layout.spammy_warnings.enabled': False, + 'dom.mozSettings.enabled': True, # Make sure the disk cache doesn't get auto disabled 'network.http.bypass-cachelock-threshold': 200000, # Always use network provider for geolocation tests diff --git a/addon-sdk/source/test/preferences/test.json b/addon-sdk/source/test/preferences/test.json index be96488b374a..d34061fb88b4 100644 --- a/addon-sdk/source/test/preferences/test.json +++ b/addon-sdk/source/test/preferences/test.json @@ -31,6 +31,7 @@ "layout.css.report_errors": true, "layout.css.grid.enabled": true, "layout.spammy_warnings.enabled": false, + "dom.mozSettings.enabled": true, "network.http.bypass-cachelock-threshold": 200000, "geo.provider.testing": true, "browser.pagethumbnails.capturing_disabled": true, diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 375abb5c4720..ba79ad2713a1 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -278,6 +278,7 @@ pref("ui.threedlightshadow", "#ece7e2"); pref("ui.threedshadow", "#aea194"); pref("ui.windowframe", "#efebe7"); +// Themable via mozSettings pref("ui.menu", "#f97c17"); pref("ui.menutext", "#ffffff"); pref("ui.infobackground", "#343e40"); @@ -408,6 +409,9 @@ pref("dom.webapps.firstRunWithSIM", true); pref("dom.mozApps.single_variant_sourcedir", "/persist/svoperapps"); #endif +// WebSettings +pref("dom.mozSettings.enabled", true); + // controls if we want camera support pref("device.camera.enabled", true); pref("media.realtime_decoder.enabled", true); @@ -912,6 +916,27 @@ pref("dom.mapped_arraybuffer.enabled", true); // UDPSocket API pref("dom.udpsocket.enabled", true); +// Enable TV Manager API +pref("dom.tv.enabled", true); + +// Enable Inputport Manager API +pref("dom.inputport.enabled", true); + +pref("dom.mozSettings.SettingsDB.debug.enabled", true); +pref("dom.mozSettings.SettingsManager.debug.enabled", true); +pref("dom.mozSettings.SettingsRequestManager.debug.enabled", true); +pref("dom.mozSettings.SettingsService.debug.enabled", true); + +pref("dom.mozSettings.SettingsDB.verbose.enabled", false); +pref("dom.mozSettings.SettingsManager.verbose.enabled", false); +pref("dom.mozSettings.SettingsRequestManager.verbose.enabled", false); +pref("dom.mozSettings.SettingsService.verbose.enabled", false); + +// Controlling whether we want to allow forcing some Settings +// IndexedDB transactions to be opened as readonly or keep everything as +// readwrite. +pref("dom.mozSettings.allowForceReadOnly", false); + // Comma separated list of activity names that can only be provided by // the system app in dev mode. pref("dom.activities.developer_mode_only", "import-app"); diff --git a/b2g/chrome/content/desktop.js b/b2g/chrome/content/desktop.js index 83b443e21936..5a1e7ff04727 100644 --- a/b2g/chrome/content/desktop.js +++ b/b2g/chrome/content/desktop.js @@ -111,6 +111,8 @@ function checkDebuggerPort() { if (dbgport) { dump('Opening debugger server on ' + dbgport + '\n'); Services.prefs.setCharPref('devtools.debugger.unix-domain-socket', dbgport); + navigator.mozSettings.createLock().set( + {'debugger.remote-mode': 'adb-devtools'}); } } diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index ac23cceee7a4..2282de2b20bf 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -207,6 +207,7 @@ @RESPATH@/components/dom_quota.xpt @RESPATH@/components/dom_range.xpt @RESPATH@/components/dom_security.xpt +@RESPATH@/components/dom_settings.xpt @RESPATH@/components/dom_sidebar.xpt @RESPATH@/components/dom_storage.xpt @RESPATH@/components/dom_stylesheets.xpt @@ -501,6 +502,8 @@ @RESPATH@/components/XULStore.manifest @RESPATH@/components/messageWakeupService.js @RESPATH@/components/messageWakeupService.manifest +@RESPATH@/components/SettingsManager.js +@RESPATH@/components/SettingsManager.manifest @RESPATH@/components/recording-cmdline.js @RESPATH@/components/recording-cmdline.manifest @RESPATH@/components/htmlMenuBuilder.js diff --git a/devtools/client/webide/content/devicesettings.js b/devtools/client/webide/content/devicesettings.js new file mode 100644 index 000000000000..987df5995b26 --- /dev/null +++ b/devtools/client/webide/content/devicesettings.js @@ -0,0 +1,81 @@ +/* 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/. */ + +var Cu = Components.utils; +const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {}); +const {AppManager} = require("devtools/client/webide/modules/app-manager"); +const {Connection} = require("devtools/shared/client/connection-manager"); +const ConfigView = require("devtools/client/webide/modules/config-view"); + +var configView = new ConfigView(window); + +window.addEventListener("load", function onLoad() { + window.removeEventListener("load", onLoad); + AppManager.on("app-manager-update", OnAppManagerUpdate); + document.getElementById("close").onclick = CloseUI; + document.getElementById("device-fields").onchange = UpdateField; + document.getElementById("device-fields").onclick = CheckReset; + document.getElementById("search-bar").onkeyup = document.getElementById("search-bar").onclick = SearchField; + document.getElementById("custom-value").onclick = UpdateNewField; + document.getElementById("custom-value-type").onchange = ClearNewFields; + document.getElementById("add-custom-field").onkeyup = CheckNewFieldSubmit; + BuildUI(); +}, true); + +window.addEventListener("unload", function onUnload() { + window.removeEventListener("unload", onUnload); + AppManager.off("app-manager-update", OnAppManagerUpdate); +}); + +function CloseUI() { + window.parent.UI.openProject(); +} + +function OnAppManagerUpdate(event, what) { + if (what == "connection" || what == "runtime-global-actors") { + BuildUI(); + } +} + +function CheckNewFieldSubmit(event) { + configView.checkNewFieldSubmit(event); +} + +function UpdateNewField() { + configView.updateNewField(); +} + +function ClearNewFields() { + configView.clearNewFields(); +} + +function CheckReset(event) { + configView.checkReset(event); +} + +function UpdateField(event) { + configView.updateField(event); +} + +function SearchField(event) { + configView.search(event); +} + +var getAllSettings; // Used by tests +function BuildUI() { + configView.resetTable(); + + if (AppManager.connection && + AppManager.connection.status == Connection.Status.CONNECTED && + AppManager.settingsFront) { + configView.front = AppManager.settingsFront; + configView.kind = "Setting"; + configView.includeTypeName = false; + + getAllSettings = AppManager.settingsFront.getAllSettings() + .then(json => configView.generateDisplay(json)); + } else { + CloseUI(); + } +} diff --git a/devtools/client/webide/content/devicesettings.xhtml b/devtools/client/webide/content/devicesettings.xhtml new file mode 100644 index 000000000000..0406c6f076fa --- /dev/null +++ b/devtools/client/webide/content/devicesettings.xhtml @@ -0,0 +1,50 @@ + + + + + + %webideDTD; +]> + + + + + + + + + +
+
+ &deck_close; +
+

&devicesetting_title;

+ +
+ + + + + + +
+ + + + + + +
+ + diff --git a/devtools/client/webide/content/jar.mn b/devtools/client/webide/content/jar.mn index 81da906f7859..73b7b62097a2 100644 --- a/devtools/client/webide/content/jar.mn +++ b/devtools/client/webide/content/jar.mn @@ -20,6 +20,8 @@ webide.jar: content/monitor.js (monitor.js) content/devicepreferences.js (devicepreferences.js) content/devicepreferences.xhtml (devicepreferences.xhtml) + content/devicesettings.js (devicesettings.js) + content/devicesettings.xhtml (devicesettings.xhtml) content/wifi-auth.js (wifi-auth.js) content/wifi-auth.xhtml (wifi-auth.xhtml) content/logs.xhtml (logs.xhtml) diff --git a/devtools/client/webide/content/webide.js b/devtools/client/webide/content/webide.js index 384c82e60d37..5df2d09a9f30 100644 --- a/devtools/client/webide/content/webide.js +++ b/devtools/client/webide/content/webide.js @@ -1052,6 +1052,10 @@ var Cmds = { UI.selectDeckPanel("devicepreferences"); }, + showSettings: function () { + UI.selectDeckPanel("devicesettings"); + }, + showMonitor: function () { UI.selectDeckPanel("monitor"); }, diff --git a/devtools/client/webide/content/webide.xul b/devtools/client/webide/content/webide.xul index 4c6ca53b3319..8c9f5d31b10a 100644 --- a/devtools/client/webide/content/webide.xul +++ b/devtools/client/webide/content/webide.xul @@ -157,6 +157,7 @@ + +
+
+
+ + diff --git a/dom/settings/tests/test_settings_observer_killer.html b/dom/settings/tests/test_settings_observer_killer.html new file mode 100644 index 000000000000..8e7ed973c887 --- /dev/null +++ b/dom/settings/tests/test_settings_observer_killer.html @@ -0,0 +1,60 @@ + + + + + Test for Bug 1193469 Settings API + + + + + + +Mozilla Bug 1193469 +

+ +
+
+
+ + diff --git a/dom/settings/tests/test_settings_onsettingchange.html b/dom/settings/tests/test_settings_onsettingchange.html new file mode 100644 index 000000000000..974da0c636bc --- /dev/null +++ b/dom/settings/tests/test_settings_onsettingchange.html @@ -0,0 +1,306 @@ + + + + + Test for Bug 678695 Settings API + + + + + + +Mozilla Bug 678695 +

+ +
+
+
+ + diff --git a/dom/settings/tests/test_settings_permissions.html b/dom/settings/tests/test_settings_permissions.html new file mode 100644 index 000000000000..4cc02385aa51 --- /dev/null +++ b/dom/settings/tests/test_settings_permissions.html @@ -0,0 +1,184 @@ + + + + + Test for Bug {678695} Settings API + + + + + + +Mozilla Bug {900551} +

+ +
+
+
+ + diff --git a/dom/settings/tests/test_settings_service.js b/dom/settings/tests/test_settings_service.js new file mode 100644 index 000000000000..132877a5d4b1 --- /dev/null +++ b/dom/settings/tests/test_settings_service.js @@ -0,0 +1,138 @@ +"use strict"; + +var Cu = Components.utils; +var Cc = Components.classes; +var Ci = Components.interfaces; + +if (SpecialPowers.isMainProcess()) { + SpecialPowers.Cu.import("resource://gre/modules/SettingsRequestManager.jsm"); +} + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +SimpleTest.waitForExplicitFinish(); + +XPCOMUtils.defineLazyServiceGetter(this, "SettingsService", + "@mozilla.org/settingsService;1", + "nsISettingsService"); + +var tests = [ + /* Callback tests */ + function() { + let callbackCount = 10; + + let callback = { + handle: function(name, result) { + switch (callbackCount) { + case 10: + case 9: + is(result, true, "result is true"); + break; + case 8: + case 7: + is(result, false, "result is false"); + break; + case 6: + case 5: + is(result, 9, "result is 9"); + break; + case 4: + case 3: + is(result, 9.4, "result is 9.4"); + break; + case 2: + is(result, false, "result is false"); + break; + case 1: + is(result, null, "result is null"); + break; + default: + ok(false, "Unexpected call: " + callbackCount); + } + + --callbackCount; + if (callbackCount === 0) { + next(); + } + }, + + handleError: function(name) { + ok(false, "error: " + name); + } + }; + + let lock = SettingsService.createLock(); + let lock1 = SettingsService.createLock(); + + lock.set("asdf", true, callback, null); + lock1.get("asdf", callback); + lock.get("asdf", callback); + lock.set("asdf", false, callback, null); + lock.get("asdf", callback); + lock.set("int", 9, callback, null); + lock.get("int", callback); + lock.set("doub", 9.4, callback, null); + lock.get("doub", callback); + lock1.get("asdfxxx", callback); + }, + + /* Observer tests */ + function() { + const MOZSETTINGS_CHANGED = "mozsettings-changed"; + const TEST_OBSERVER_KEY = "test.observer.key"; + const TEST_OBSERVER_VALUE = true; + const TEST_OBSERVER_MESSAGE = "test.observer.message"; + + var obs = { + observe: function (subject, topic, data) { + + if (topic !== MOZSETTINGS_CHANGED) { + ok(false, "Event is not mozsettings-changed."); + return; + } + // Data is now stored in subject + if ("wrappedJSObject" in subject) { + ok(true, "JS object wrapped into subject"); + subject = subject.wrappedJSObject; + } + if (subject["key"] != TEST_OBSERVER_KEY) { + return; + } + + function checkProp(name, type, value) { + ok(name in subject, "subject." + name + " is present"); + is(typeof subject[name], type, "subject." + name + " is " + type); + is(subject[name], value, "subject." + name + " is " + value); + } + + checkProp("key", "string", TEST_OBSERVER_KEY); + checkProp("value", "boolean", TEST_OBSERVER_VALUE); + checkProp("isInternalChange", "boolean", true); + + Services.obs.removeObserver(this, MOZSETTINGS_CHANGED); + next(); + } + }; + + Services.obs.addObserver(obs, MOZSETTINGS_CHANGED, false); + + let lock = SettingsService.createLock(); + lock.set(TEST_OBSERVER_KEY, TEST_OBSERVER_VALUE, null); + } +]; + +function next() { + let step = tests.shift(); + if (step) { + try { + step(); + } catch(e) { + ok(false, "Test threw: " + e); + } + } else { + SimpleTest.finish(); + } +} + +next(); diff --git a/dom/settings/tests/test_settings_service.xul b/dom/settings/tests/test_settings_service.xul new file mode 100644 index 000000000000..58a9efad96d2 --- /dev/null +++ b/dom/settings/tests/test_settings_service.xul @@ -0,0 +1,19 @@ + + + + + + + + + + Mozilla Bug 678695 + + + + + + + Mozilla Bug 1012214 + + +