|
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / |
|
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 "use strict;" |
|
8 |
|
9 const Cc = Components.classes; |
|
10 const Ci = Components.interfaces; |
|
11 const Cu = Components.utils; |
|
12 const Cr = Components.results; |
|
13 |
|
14 Cu.import('resource://gre/modules/XPCOMUtils.jsm'); |
|
15 Cu.import('resource://gre/modules/Services.jsm'); |
|
16 |
|
17 #ifdef MOZ_WIDGET_GONK |
|
18 XPCOMUtils.defineLazyGetter(this, "libcutils", function () { |
|
19 Cu.import("resource://gre/modules/systemlibs.js"); |
|
20 return libcutils; |
|
21 }); |
|
22 #endif |
|
23 |
|
24 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", |
|
25 "@mozilla.org/uuid-generator;1", |
|
26 "nsIUUIDGenerator"); |
|
27 |
|
28 // Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget |
|
29 // is resolved this helper could be removed. |
|
30 var SettingsListener = { |
|
31 _callbacks: {}, |
|
32 |
|
33 init: function sl_init() { |
|
34 if ('mozSettings' in navigator && navigator.mozSettings) { |
|
35 navigator.mozSettings.onsettingchange = this.onchange.bind(this); |
|
36 } |
|
37 }, |
|
38 |
|
39 onchange: function sl_onchange(evt) { |
|
40 var callback = this._callbacks[evt.settingName]; |
|
41 if (callback) { |
|
42 callback(evt.settingValue); |
|
43 } |
|
44 }, |
|
45 |
|
46 observe: function sl_observe(name, defaultValue, callback) { |
|
47 var settings = window.navigator.mozSettings; |
|
48 if (!settings) { |
|
49 window.setTimeout(function() { callback(defaultValue); }); |
|
50 return; |
|
51 } |
|
52 |
|
53 if (!callback || typeof callback !== 'function') { |
|
54 throw new Error('Callback is not a function'); |
|
55 } |
|
56 |
|
57 var req = settings.createLock().get(name); |
|
58 req.addEventListener('success', (function onsuccess() { |
|
59 callback(typeof(req.result[name]) != 'undefined' ? |
|
60 req.result[name] : defaultValue); |
|
61 })); |
|
62 |
|
63 this._callbacks[name] = callback; |
|
64 } |
|
65 }; |
|
66 |
|
67 SettingsListener.init(); |
|
68 |
|
69 // =================== Console ====================== |
|
70 |
|
71 SettingsListener.observe('debug.console.enabled', true, function(value) { |
|
72 Services.prefs.setBoolPref('consoleservice.enabled', value); |
|
73 Services.prefs.setBoolPref('layout.css.report_errors', value); |
|
74 }); |
|
75 |
|
76 // =================== Languages ==================== |
|
77 SettingsListener.observe('language.current', 'en-US', function(value) { |
|
78 Services.prefs.setCharPref('general.useragent.locale', value); |
|
79 |
|
80 let prefName = 'intl.accept_languages'; |
|
81 if (Services.prefs.prefHasUserValue(prefName)) { |
|
82 Services.prefs.clearUserPref(prefName); |
|
83 } |
|
84 |
|
85 let intl = ''; |
|
86 try { |
|
87 intl = Services.prefs.getComplexValue(prefName, |
|
88 Ci.nsIPrefLocalizedString).data; |
|
89 } catch(e) {} |
|
90 |
|
91 // Bug 830782 - Homescreen is in English instead of selected locale after |
|
92 // the first run experience. |
|
93 // In order to ensure the current intl value is reflected on the child |
|
94 // process let's always write a user value, even if this one match the |
|
95 // current localized pref value. |
|
96 if (!((new RegExp('^' + value + '[^a-z-_] *[,;]?', 'i')).test(intl))) { |
|
97 value = value + ', ' + intl; |
|
98 } else { |
|
99 value = intl; |
|
100 } |
|
101 Services.prefs.setCharPref(prefName, value); |
|
102 |
|
103 if (shell.hasStarted() == false) { |
|
104 shell.start(); |
|
105 } |
|
106 }); |
|
107 |
|
108 // =================== RIL ==================== |
|
109 (function RILSettingsToPrefs() { |
|
110 let strPrefs = ['ril.mms.mmsc', 'ril.mms.mmsproxy']; |
|
111 strPrefs.forEach(function(key) { |
|
112 SettingsListener.observe(key, "", function(value) { |
|
113 Services.prefs.setCharPref(key, value); |
|
114 }); |
|
115 }); |
|
116 |
|
117 ['ril.mms.mmsport'].forEach(function(key) { |
|
118 SettingsListener.observe(key, null, function(value) { |
|
119 if (value != null) { |
|
120 Services.prefs.setIntPref(key, value); |
|
121 } |
|
122 }); |
|
123 }); |
|
124 |
|
125 // DSDS default service IDs |
|
126 ['mms', 'sms', 'telephony', 'voicemail'].forEach(function(key) { |
|
127 SettingsListener.observe('ril.' + key + '.defaultServiceId', 0, |
|
128 function(value) { |
|
129 if (value != null) { |
|
130 Services.prefs.setIntPref('dom.' + key + '.defaultServiceId', value); |
|
131 } |
|
132 }); |
|
133 }); |
|
134 })(); |
|
135 |
|
136 //=================== DeviceInfo ==================== |
|
137 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); |
|
138 Components.utils.import('resource://gre/modules/ctypes.jsm'); |
|
139 (function DeviceInfoToSettings() { |
|
140 // MOZ_B2G_VERSION is set in b2g/confvars.sh, and is output as a #define value |
|
141 // from configure.in, defaults to 1.0.0 if this value is not exist. |
|
142 #filter attemptSubstitution |
|
143 let os_version = '@MOZ_B2G_VERSION@'; |
|
144 let os_name = '@MOZ_B2G_OS_NAME@'; |
|
145 #unfilter attemptSubstitution |
|
146 |
|
147 let appInfo = Cc["@mozilla.org/xre/app-info;1"] |
|
148 .getService(Ci.nsIXULAppInfo); |
|
149 |
|
150 // Get the hardware info and firmware revision from device properties. |
|
151 let hardware_info = null; |
|
152 let firmware_revision = null; |
|
153 let product_model = null; |
|
154 #ifdef MOZ_WIDGET_GONK |
|
155 hardware_info = libcutils.property_get('ro.hardware'); |
|
156 firmware_revision = libcutils.property_get('ro.firmware_revision'); |
|
157 product_model = libcutils.property_get('ro.product.model'); |
|
158 #endif |
|
159 |
|
160 let software = os_name + ' ' + os_version; |
|
161 let setting = { |
|
162 'deviceinfo.os': os_version, |
|
163 'deviceinfo.software': software, |
|
164 'deviceinfo.platform_version': appInfo.platformVersion, |
|
165 'deviceinfo.platform_build_id': appInfo.platformBuildID, |
|
166 'deviceinfo.hardware': hardware_info, |
|
167 'deviceinfo.firmware_revision': firmware_revision, |
|
168 'deviceinfo.product_model': product_model |
|
169 } |
|
170 window.navigator.mozSettings.createLock().set(setting); |
|
171 })(); |
|
172 |
|
173 // =================== DevTools ==================== |
|
174 |
|
175 let developerHUD; |
|
176 SettingsListener.observe('devtools.overlay', false, (value) => { |
|
177 if (value) { |
|
178 if (!developerHUD) { |
|
179 let scope = {}; |
|
180 Services.scriptloader.loadSubScript('chrome://b2g/content/devtools.js', scope); |
|
181 developerHUD = scope.developerHUD; |
|
182 } |
|
183 developerHUD.init(); |
|
184 } else { |
|
185 if (developerHUD) { |
|
186 developerHUD.uninit(); |
|
187 } |
|
188 } |
|
189 }); |
|
190 |
|
191 // =================== Debugger / ADB ==================== |
|
192 |
|
193 #ifdef MOZ_WIDGET_GONK |
|
194 let AdbController = { |
|
195 DEBUG: false, |
|
196 locked: undefined, |
|
197 remoteDebuggerEnabled: undefined, |
|
198 lockEnabled: undefined, |
|
199 disableAdbTimer: null, |
|
200 disableAdbTimeoutHours: 12, |
|
201 umsActive: false, |
|
202 |
|
203 debug: function(str) { |
|
204 dump("AdbController: " + str + "\n"); |
|
205 }, |
|
206 |
|
207 setLockscreenEnabled: function(value) { |
|
208 this.lockEnabled = value; |
|
209 if (this.DEBUG) { |
|
210 this.debug("setLockscreenEnabled = " + this.lockEnabled); |
|
211 } |
|
212 this.updateState(); |
|
213 }, |
|
214 |
|
215 setLockscreenState: function(value) { |
|
216 this.locked = value; |
|
217 if (this.DEBUG) { |
|
218 this.debug("setLockscreenState = " + this.locked); |
|
219 } |
|
220 this.updateState(); |
|
221 }, |
|
222 |
|
223 setRemoteDebuggerState: function(value) { |
|
224 this.remoteDebuggerEnabled = value; |
|
225 if (this.DEBUG) { |
|
226 this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled); |
|
227 } |
|
228 this.updateState(); |
|
229 }, |
|
230 |
|
231 startDisableAdbTimer: function() { |
|
232 if (this.disableAdbTimer) { |
|
233 this.disableAdbTimer.cancel(); |
|
234 } else { |
|
235 this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
|
236 try { |
|
237 this.disableAdbTimeoutHours = |
|
238 Services.prefs.getIntPref("b2g.adb.timeout-hours"); |
|
239 } catch (e) { |
|
240 // This happens if the pref doesn't exist, in which case |
|
241 // disableAdbTimeoutHours will still be set to the default. |
|
242 } |
|
243 } |
|
244 if (this.disableAdbTimeoutHours <= 0) { |
|
245 if (this.DEBUG) { |
|
246 this.debug("Timer to disable ADB not started due to zero timeout"); |
|
247 } |
|
248 return; |
|
249 } |
|
250 |
|
251 if (this.DEBUG) { |
|
252 this.debug("Starting timer to disable ADB in " + |
|
253 this.disableAdbTimeoutHours + " hours"); |
|
254 } |
|
255 let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000; |
|
256 this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds, |
|
257 Ci.nsITimer.TYPE_ONE_SHOT); |
|
258 }, |
|
259 |
|
260 stopDisableAdbTimer: function() { |
|
261 if (this.DEBUG) { |
|
262 this.debug("Stopping timer to disable ADB"); |
|
263 } |
|
264 if (this.disableAdbTimer) { |
|
265 this.disableAdbTimer.cancel(); |
|
266 this.disableAdbTimer = null; |
|
267 } |
|
268 }, |
|
269 |
|
270 notify: function(aTimer) { |
|
271 if (aTimer == this.disableAdbTimer) { |
|
272 this.disableAdbTimer = null; |
|
273 // The following dump will be the last thing that shows up in logcat, |
|
274 // and will at least give the user a clue about why logcat was |
|
275 // disconnected, if the user happens to be using logcat. |
|
276 dump("AdbController: ADB timer expired - disabling ADB\n"); |
|
277 navigator.mozSettings.createLock().set( |
|
278 {'devtools.debugger.remote-enabled': false}); |
|
279 } |
|
280 }, |
|
281 |
|
282 updateState: function() { |
|
283 this.umsActive = false; |
|
284 this.storages = navigator.getDeviceStorages('sdcard'); |
|
285 this.updateStorageState(0); |
|
286 }, |
|
287 |
|
288 updateStorageState: function(storageIndex) { |
|
289 if (storageIndex >= this.storages.length) { |
|
290 // We've iterated through all of the storage objects, now we can |
|
291 // really do updateStateInternal. |
|
292 this.updateStateInternal(); |
|
293 return; |
|
294 } |
|
295 let storage = this.storages[storageIndex]; |
|
296 if (this.DEBUG) { |
|
297 this.debug("Checking availability of storage: '" + |
|
298 storage.storageName); |
|
299 } |
|
300 |
|
301 let req = storage.available(); |
|
302 req.onsuccess = function(e) { |
|
303 if (this.DEBUG) { |
|
304 this.debug("Storage: '" + storage.storageName + "' is '" + |
|
305 e.target.result); |
|
306 } |
|
307 if (e.target.result == 'shared') { |
|
308 // We've found a storage area that's being shared with the PC. |
|
309 // We can stop looking now. |
|
310 this.umsActive = true; |
|
311 this.updateStateInternal(); |
|
312 return; |
|
313 } |
|
314 this.updateStorageState(storageIndex + 1); |
|
315 }.bind(this); |
|
316 req.onerror = function(e) { |
|
317 dump("AdbController: error querying storage availability for '" + |
|
318 this.storages[storageIndex].storageName + "' (ignoring)\n"); |
|
319 this.updateStorageState(storageIndex + 1); |
|
320 }.bind(this); |
|
321 }, |
|
322 |
|
323 updateStateInternal: function() { |
|
324 if (this.DEBUG) { |
|
325 this.debug("updateStateInternal: called"); |
|
326 } |
|
327 |
|
328 if (this.remoteDebuggerEnabled === undefined || |
|
329 this.lockEnabled === undefined || |
|
330 this.locked === undefined) { |
|
331 // Part of initializing the settings database will cause the observers |
|
332 // to trigger. We want to wait until both have been initialized before |
|
333 // we start changing ther adb state. Without this then we can wind up |
|
334 // toggling adb off and back on again (or on and back off again). |
|
335 // |
|
336 // For completeness, one scenario which toggles adb is using the unagi. |
|
337 // The unagi has adb enabled by default (prior to b2g starting). If you |
|
338 // have the phone lock disabled and remote debugging enabled, then we'll |
|
339 // receive an unlock event and an rde event. However at the time we |
|
340 // receive the unlock event we haven't yet received the rde event, so |
|
341 // we turn adb off momentarily, which disconnects a logcat that might |
|
342 // be running. Changing the defaults (in AdbController) just moves the |
|
343 // problem to a different phone, which has adb disabled by default and |
|
344 // we wind up turning on adb for a short period when we shouldn't. |
|
345 // |
|
346 // By waiting until both values are properly initialized, we avoid |
|
347 // turning adb on or off accidentally. |
|
348 if (this.DEBUG) { |
|
349 this.debug("updateState: Waiting for all vars to be initialized"); |
|
350 } |
|
351 return; |
|
352 } |
|
353 |
|
354 // Check if we have a remote debugging session going on. If so, we won't |
|
355 // disable adb even if the screen is locked. |
|
356 let isDebugging = RemoteDebugger.isDebugging; |
|
357 if (this.DEBUG) { |
|
358 this.debug("isDebugging=" + isDebugging); |
|
359 } |
|
360 |
|
361 // If USB Mass Storage, USB tethering, or a debug session is active, |
|
362 // then we don't want to disable adb in an automatic fashion (i.e. |
|
363 // when the screen locks or due to timeout). |
|
364 let sysUsbConfig = libcutils.property_get("sys.usb.config"); |
|
365 let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0); |
|
366 let usbFuncActive = rndisActive || this.umsActive || isDebugging; |
|
367 |
|
368 let enableAdb = this.remoteDebuggerEnabled && |
|
369 (!(this.lockEnabled && this.locked) || usbFuncActive); |
|
370 |
|
371 let useDisableAdbTimer = true; |
|
372 try { |
|
373 if (Services.prefs.getBoolPref("marionette.defaultPrefs.enabled")) { |
|
374 // Marionette is enabled. Marionette requires that adb be on (and also |
|
375 // requires that remote debugging be off). The fact that marionette |
|
376 // is enabled also implies that we're doing a non-production build, so |
|
377 // we want adb enabled all of the time. |
|
378 enableAdb = true; |
|
379 useDisableAdbTimer = false; |
|
380 } |
|
381 } catch (e) { |
|
382 // This means that the pref doesn't exist. Which is fine. We just leave |
|
383 // enableAdb alone. |
|
384 } |
|
385 if (this.DEBUG) { |
|
386 this.debug("updateState: enableAdb = " + enableAdb + |
|
387 " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled + |
|
388 " lockEnabled = " + this.lockEnabled + |
|
389 " locked = " + this.locked + |
|
390 " usbFuncActive = " + usbFuncActive); |
|
391 } |
|
392 |
|
393 // Configure adb. |
|
394 let currentConfig = libcutils.property_get("persist.sys.usb.config"); |
|
395 let configFuncs = currentConfig.split(","); |
|
396 let adbIndex = configFuncs.indexOf("adb"); |
|
397 |
|
398 if (enableAdb) { |
|
399 // Add adb to the list of functions, if not already present |
|
400 if (adbIndex < 0) { |
|
401 configFuncs.push("adb"); |
|
402 } |
|
403 } else { |
|
404 // Remove adb from the list of functions, if present |
|
405 if (adbIndex >= 0) { |
|
406 configFuncs.splice(adbIndex, 1); |
|
407 } |
|
408 } |
|
409 let newConfig = configFuncs.join(","); |
|
410 if (newConfig != currentConfig) { |
|
411 if (this.DEBUG) { |
|
412 this.debug("updateState: currentConfig = " + currentConfig); |
|
413 this.debug("updateState: newConfig = " + newConfig); |
|
414 } |
|
415 try { |
|
416 libcutils.property_set("persist.sys.usb.config", newConfig); |
|
417 } catch(e) { |
|
418 dump("Error configuring adb: " + e); |
|
419 } |
|
420 } |
|
421 if (useDisableAdbTimer) { |
|
422 if (enableAdb && !usbFuncActive) { |
|
423 this.startDisableAdbTimer(); |
|
424 } else { |
|
425 this.stopDisableAdbTimer(); |
|
426 } |
|
427 } |
|
428 } |
|
429 }; |
|
430 |
|
431 SettingsListener.observe("lockscreen.locked", false, |
|
432 AdbController.setLockscreenState.bind(AdbController)); |
|
433 SettingsListener.observe("lockscreen.enabled", false, |
|
434 AdbController.setLockscreenEnabled.bind(AdbController)); |
|
435 #endif |
|
436 |
|
437 // Keep the old setting to not break people that won't have updated |
|
438 // gaia and gecko. |
|
439 SettingsListener.observe('devtools.debugger.remote-enabled', false, function(value) { |
|
440 Services.prefs.setBoolPref('devtools.debugger.remote-enabled', value); |
|
441 // This preference is consulted during startup |
|
442 Services.prefs.savePrefFile(null); |
|
443 try { |
|
444 value ? RemoteDebugger.start() : RemoteDebugger.stop(); |
|
445 } catch(e) { |
|
446 dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n"); |
|
447 } |
|
448 |
|
449 #ifdef MOZ_WIDGET_GONK |
|
450 AdbController.setRemoteDebuggerState(value); |
|
451 #endif |
|
452 }); |
|
453 |
|
454 SettingsListener.observe('debugger.remote-mode', false, function(value) { |
|
455 if (['disabled', 'adb-only', 'adb-devtools'].indexOf(value) == -1) { |
|
456 dump('Illegal value for debugger.remote-mode: ' + value + '\n'); |
|
457 return; |
|
458 } |
|
459 |
|
460 Services.prefs.setBoolPref('devtools.debugger.remote-enabled', |
|
461 value == 'adb-devtools'); |
|
462 // This preference is consulted during startup |
|
463 Services.prefs.savePrefFile(null); |
|
464 |
|
465 try { |
|
466 (value == 'adb-devtools') ? RemoteDebugger.start() |
|
467 : RemoteDebugger.stop(); |
|
468 } catch(e) { |
|
469 dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n"); |
|
470 } |
|
471 |
|
472 #ifdef MOZ_WIDGET_GONK |
|
473 AdbController.setRemoteDebuggerState(value != 'disabled'); |
|
474 #endif |
|
475 }); |
|
476 |
|
477 // =================== Device Storage ==================== |
|
478 SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) { |
|
479 if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) { |
|
480 // We clear the pref because it used to be erroneously written as a bool |
|
481 // and we need to clear it before we can change it to have the correct type. |
|
482 Services.prefs.clearUserPref('device.storage.writable.name'); |
|
483 } |
|
484 Services.prefs.setCharPref('device.storage.writable.name', value); |
|
485 }); |
|
486 |
|
487 // =================== Privacy ==================== |
|
488 SettingsListener.observe('privacy.donottrackheader.value', 1, function(value) { |
|
489 Services.prefs.setIntPref('privacy.donottrackheader.value', value); |
|
490 // If the user specifically disallows tracking, we set the value of |
|
491 // app.update.custom (update tracking ID) to an empty string. |
|
492 if (value == 1) { |
|
493 Services.prefs.setCharPref('app.update.custom', ''); |
|
494 return; |
|
495 } |
|
496 // Otherwise, we assure that the update tracking ID exists. |
|
497 setUpdateTrackingId(); |
|
498 }); |
|
499 |
|
500 // =================== Crash Reporting ==================== |
|
501 SettingsListener.observe('app.reportCrashes', 'ask', function(value) { |
|
502 if (value == 'always') { |
|
503 Services.prefs.setBoolPref('app.reportCrashes', true); |
|
504 } else if (value == 'never') { |
|
505 Services.prefs.setBoolPref('app.reportCrashes', false); |
|
506 } else { |
|
507 Services.prefs.clearUserPref('app.reportCrashes'); |
|
508 } |
|
509 // This preference is consulted during startup. |
|
510 Services.prefs.savePrefFile(null); |
|
511 }); |
|
512 |
|
513 // ================ Updates ================ |
|
514 /** |
|
515 * For tracking purposes some partners require us to add an UUID to the |
|
516 * update URL. The update tracking ID will be an empty string if the |
|
517 * do-not-track feature specifically disallows tracking and it is reseted |
|
518 * to a different ID if the do-not-track value changes from disallow to allow. |
|
519 */ |
|
520 function setUpdateTrackingId() { |
|
521 try { |
|
522 let dntEnabled = Services.prefs.getBoolPref('privacy.donottrackheader.enabled'); |
|
523 let dntValue = Services.prefs.getIntPref('privacy.donottrackheader.value'); |
|
524 // If the user specifically decides to disallow tracking (1), we just bail out. |
|
525 if (dntEnabled && (dntValue == 1)) { |
|
526 return; |
|
527 } |
|
528 |
|
529 let trackingId = |
|
530 Services.prefs.getPrefType('app.update.custom') == |
|
531 Ci.nsIPrefBranch.PREF_STRING && |
|
532 Services.prefs.getCharPref('app.update.custom'); |
|
533 |
|
534 // If there is no previous registered tracking ID, we generate a new one. |
|
535 // This should only happen on first usage or after changing the |
|
536 // do-not-track value from disallow to allow. |
|
537 if (!trackingId) { |
|
538 trackingId = uuidgen.generateUUID().toString().replace(/[{}]/g, ""); |
|
539 Services.prefs.setCharPref('app.update.custom', trackingId); |
|
540 } |
|
541 } catch(e) { |
|
542 dump('Error getting tracking ID ' + e + '\n'); |
|
543 } |
|
544 } |
|
545 setUpdateTrackingId(); |
|
546 |
|
547 |
|
548 // ================ Debug ================ |
|
549 (function Composer2DSettingToPref() { |
|
550 //layers.composer.enabled can be enabled in three ways |
|
551 //In order of precedence they are: |
|
552 // |
|
553 //1. mozSettings "layers.composer.enabled" |
|
554 //2. a gecko pref "layers.composer.enabled" |
|
555 //3. presence of ro.display.colorfill at the Gonk level |
|
556 |
|
557 var req = navigator.mozSettings.createLock().get('layers.composer2d.enabled'); |
|
558 req.onsuccess = function() { |
|
559 if (typeof(req.result['layers.composer2d.enabled']) === 'undefined') { |
|
560 var enabled = false; |
|
561 if (Services.prefs.getPrefType('layers.composer2d.enabled') == Ci.nsIPrefBranch.PREF_BOOL) { |
|
562 enabled = Services.prefs.getBoolPref('layers.composer2d.enabled'); |
|
563 } else { |
|
564 #ifdef MOZ_WIDGET_GONK |
|
565 enabled = (libcutils.property_get('ro.display.colorfill') === '1'); |
|
566 #endif |
|
567 } |
|
568 navigator.mozSettings.createLock().set({'layers.composer2d.enabled': enabled }); |
|
569 } |
|
570 |
|
571 SettingsListener.observe("layers.composer2d.enabled", true, function(value) { |
|
572 Services.prefs.setBoolPref("layers.composer2d.enabled", value); |
|
573 }); |
|
574 }; |
|
575 req.onerror = function() { |
|
576 dump("Error configuring layers.composer2d.enabled setting"); |
|
577 }; |
|
578 |
|
579 })(); |
|
580 |
|
581 // ================ Accessibility ============ |
|
582 SettingsListener.observe("accessibility.screenreader", false, function(value) { |
|
583 if (value && !("AccessFu" in this)) { |
|
584 Cu.import('resource://gre/modules/accessibility/AccessFu.jsm'); |
|
585 AccessFu.attach(window); |
|
586 } |
|
587 }); |
|
588 |
|
589 // ================ Theming ============ |
|
590 (function themingSettingsListener() { |
|
591 let themingPrefs = ['ui.menu', 'ui.menutext', 'ui.infobackground', 'ui.infotext', |
|
592 'ui.window', 'ui.windowtext', 'ui.highlight']; |
|
593 |
|
594 themingPrefs.forEach(function(pref) { |
|
595 SettingsListener.observe('gaia.' + pref, null, function(value) { |
|
596 if (value) { |
|
597 Services.prefs.setCharPref(pref, value); |
|
598 } |
|
599 }); |
|
600 }); |
|
601 })(); |
|
602 |
|
603 // =================== AsyncPanZoom ====================== |
|
604 SettingsListener.observe('apz.displayport.heuristics', 'default', function(value) { |
|
605 // first reset everything to default |
|
606 Services.prefs.clearUserPref('apz.velocity_bias'); |
|
607 Services.prefs.clearUserPref('apz.use_paint_duration'); |
|
608 Services.prefs.clearUserPref('apz.x_skate_size_multiplier'); |
|
609 Services.prefs.clearUserPref('apz.y_skate_size_multiplier'); |
|
610 Services.prefs.clearUserPref('apz.allow-checkerboarding'); |
|
611 // and then set the things that we want to change |
|
612 switch (value) { |
|
613 case 'default': |
|
614 break; |
|
615 case 'center-displayport': |
|
616 Services.prefs.setCharPref('apz.velocity_bias', '0.0'); |
|
617 break; |
|
618 case 'perfect-paint-times': |
|
619 Services.prefs.setBoolPref('apz.use_paint_duration', false); |
|
620 Services.prefs.setCharPref('apz.velocity_bias', '0.32'); // 16/50 (assumes 16ms paint times instead of 50ms) |
|
621 break; |
|
622 case 'taller-displayport': |
|
623 Services.prefs.setCharPref('apz.y_skate_size_multiplier', '3.5'); |
|
624 break; |
|
625 case 'faster-paint': |
|
626 Services.prefs.setCharPref('apz.x_skate_size_multiplier', '1.0'); |
|
627 Services.prefs.setCharPref('apz.y_skate_size_multiplier', '1.5'); |
|
628 break; |
|
629 case 'no-checkerboard': |
|
630 Services.prefs.setBoolPref('apz.allow-checkerboarding', false); |
|
631 break; |
|
632 } |
|
633 }); |
|
634 |
|
635 // =================== Various simple mapping ====================== |
|
636 let settingsToObserve = { |
|
637 'ril.mms.retrieval_mode': { |
|
638 prefName: 'dom.mms.retrieval_mode', |
|
639 defaultValue: 'manual' |
|
640 }, |
|
641 'ril.sms.strict7BitEncoding.enabled': { |
|
642 prefName: 'dom.sms.strict7BitEncoding', |
|
643 defaultValue: false |
|
644 }, |
|
645 'ril.sms.requestStatusReport.enabled': { |
|
646 prefName: 'dom.sms.requestStatusReport', |
|
647 defaultValue: false |
|
648 }, |
|
649 'ril.mms.requestStatusReport.enabled': { |
|
650 prefName: 'dom.mms.requestStatusReport', |
|
651 defaultValue: false |
|
652 }, |
|
653 'ril.mms.requestReadReport.enabled': { |
|
654 prefName: 'dom.mms.requestReadReport', |
|
655 defaultValue: true |
|
656 }, |
|
657 'ril.cellbroadcast.disabled': false, |
|
658 'ril.radio.disabled': false, |
|
659 'wap.UAProf.url': '', |
|
660 'wap.UAProf.tagname': 'x-wap-profile', |
|
661 'devtools.eventlooplag.threshold': 100, |
|
662 'privacy.donottrackheader.enabled': false, |
|
663 'apz.force-enable': { |
|
664 prefName: 'dom.browser_frames.useAsyncPanZoom', |
|
665 defaultValue: false |
|
666 }, |
|
667 'layers.enable-tiles': true, |
|
668 'layers.simple-tiles': false, |
|
669 'layers.progressive-paint': false, |
|
670 'layers.draw-tile-borders': false, |
|
671 'layers.dump': false, |
|
672 'debug.fps.enabled': { |
|
673 prefName: 'layers.acceleration.draw-fps', |
|
674 defaultValue: false |
|
675 }, |
|
676 'debug.paint-flashing.enabled': { |
|
677 prefName: 'nglayout.debug.paint_flashing', |
|
678 defaultValue: false |
|
679 }, |
|
680 'layers.draw-borders': false, |
|
681 'app.update.interval': 86400, |
|
682 'app.update.url': { |
|
683 resetToPref: true |
|
684 }, |
|
685 'app.update.channel': { |
|
686 resetToPref: true |
|
687 }, |
|
688 'debug.log-animations.enabled': { |
|
689 prefName: 'layers.offmainthreadcomposition.log-animations', |
|
690 defaultValue: false |
|
691 } |
|
692 }; |
|
693 |
|
694 for (let key in settingsToObserve) { |
|
695 let setting = settingsToObserve[key]; |
|
696 |
|
697 // Allow setting to contain flags redefining prefName and defaultValue. |
|
698 let prefName = setting.prefName || key; |
|
699 let defaultValue = setting.defaultValue; |
|
700 if (defaultValue === undefined) { |
|
701 defaultValue = setting; |
|
702 } |
|
703 |
|
704 let prefs = Services.prefs; |
|
705 |
|
706 // If requested, reset setting value and defaultValue to the pref value. |
|
707 if (setting.resetToPref) { |
|
708 switch (prefs.getPrefType(prefName)) { |
|
709 case Ci.nsIPrefBranch.PREF_BOOL: |
|
710 defaultValue = prefs.getBoolPref(prefName); |
|
711 break; |
|
712 |
|
713 case Ci.nsIPrefBranch.PREF_INT: |
|
714 defaultValue = prefs.getIntPref(prefName); |
|
715 break; |
|
716 |
|
717 case Ci.nsIPrefBranch.PREF_STRING: |
|
718 defaultValue = prefs.getCharPref(prefName); |
|
719 break; |
|
720 } |
|
721 |
|
722 let setting = {}; |
|
723 setting[key] = defaultValue; |
|
724 window.navigator.mozSettings.createLock().set(setting); |
|
725 } |
|
726 |
|
727 // Figure out the right setter function for this type of pref. |
|
728 let setPref; |
|
729 switch (typeof defaultValue) { |
|
730 case 'boolean': |
|
731 setPref = prefs.setBoolPref.bind(prefs); |
|
732 break; |
|
733 |
|
734 case 'number': |
|
735 setPref = prefs.setIntPref.bind(prefs); |
|
736 break; |
|
737 |
|
738 case 'string': |
|
739 setPref = prefs.setCharPref.bind(prefs); |
|
740 break; |
|
741 } |
|
742 |
|
743 SettingsListener.observe(key, defaultValue, function(value) { |
|
744 setPref(prefName, value); |
|
745 }); |
|
746 }; |
|
747 |