michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: 'use strict'; michael@0: michael@0: this.EXPORTED_SYMBOLS = []; michael@0: michael@0: #ifdef XP_WIN michael@0: #ifdef MOZ_METRO michael@0: michael@0: const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = michael@0: Components; michael@0: const PREF_BASE_KEY = "Software\\Mozilla\\Firefox\\Metro\\Prefs\\"; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: this.EXPORTED_SYMBOLS = [ "WindowsPrefSync" ]; michael@0: michael@0: /** michael@0: * Manages preferences that need to be pulled and pushed between Metro michael@0: * and desktop. michael@0: */ michael@0: this.WindowsPrefSync = { michael@0: init: function() { michael@0: this.pullSharedPrefs(); michael@0: this.prefListToPush.forEach(function(prefName) { michael@0: this.pushSharedPref(prefName); michael@0: Services.prefs.addObserver(prefName, this, false); michael@0: }, this); michael@0: }, michael@0: michael@0: uninit: function() { michael@0: this.prefListToPush.forEach(function(prefName) { michael@0: Services.prefs.removeObserver(prefName, this); michael@0: }, this); michael@0: }, michael@0: michael@0: /** michael@0: * Returns the list of prefs that should be pushed for the current michael@0: * environment. michael@0: */ michael@0: get prefListToPush() { michael@0: return !Services.metro.immersive ? this.desktopControlledPrefs : michael@0: this.metroControlledPrefs; michael@0: }, michael@0: michael@0: /** michael@0: * Returns the list of prefs that should be pulled for the current michael@0: * environment. michael@0: */ michael@0: get prefListToPull() { michael@0: return Services.metro.immersive ? this.desktopControlledPrefs : michael@0: this.metroControlledPrefs; michael@0: }, michael@0: michael@0: /** michael@0: * The following preferences will be pushed to registry from Desktop michael@0: * Firefox and pulled in from Metro Firefox. michael@0: * michael@0: * app.update.* prefs are because Metro shares an installation directory with michael@0: * Firefox, and the options for these are only present in the Desktop options. michael@0: * michael@0: * browser.sessionstore.resume_session_once is mainly for the switch to Metro michael@0: * and switch to Desktop feature. michael@0: * michael@0: * browser.startup.page - if a desktop Firefox user wants her/his sessions michael@0: * to always restore, we need to honor that in metro Firefox as well. michael@0: */ michael@0: desktopControlledPrefs: ["app.update.auto", michael@0: "app.update.enabled", michael@0: "app.update.service.enabled", michael@0: "app.update.metro.enabled", michael@0: "browser.sessionstore.resume_session_once", michael@0: "browser.startup.page"], michael@0: michael@0: /** michael@0: * Returns the base path where registry sync prefs are stored. michael@0: */ michael@0: get prefRegistryPath() { michael@0: let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]. michael@0: createInstance(Ci.nsIToolkitProfileService); michael@0: return PREF_BASE_KEY + profileService.selectedProfile.name + "\\"; michael@0: }, michael@0: michael@0: /** michael@0: * The following preferences will be pushed to registry from Metro michael@0: * Firefox and pulled in from Desktop Firefox. michael@0: * michael@0: * browser.sessionstore.resume_session_once is mainly for the switch to Metro michael@0: * and switch to Desktop feature. michael@0: */ michael@0: metroControlledPrefs: ["browser.sessionstore.resume_session_once"], michael@0: michael@0: /** michael@0: * Observes preference changes and writes them to the registry, only michael@0: * the list of preferences initialized will be observed michael@0: */ michael@0: observe: function (aSubject, aTopic, aPrefName) { michael@0: if (aTopic != "nsPref:changed") michael@0: return; michael@0: michael@0: this.pushSharedPref(aPrefName); michael@0: }, michael@0: michael@0: /** michael@0: * Writes the pref to HKCU in the registry and adds a pref-observer to keep michael@0: * the registry in sync with changes to the value. michael@0: */ michael@0: pushSharedPref : function(aPrefName) { michael@0: let registry = Cc["@mozilla.org/windows-registry-key;1"]. michael@0: createInstance(Ci.nsIWindowsRegKey); michael@0: try { michael@0: var prefType = Services.prefs.getPrefType(aPrefName); michael@0: let prefFunc; michael@0: if (prefType == Ci.nsIPrefBranch.PREF_INT) michael@0: prefFunc = "getIntPref"; michael@0: else if (prefType == Ci.nsIPrefBranch.PREF_BOOL) michael@0: prefFunc = "getBoolPref"; michael@0: else if (prefType == Ci.nsIPrefBranch.PREF_STRING) michael@0: prefFunc = "getCharPref"; michael@0: else michael@0: throw "Unsupported pref type"; michael@0: michael@0: let prefValue = Services.prefs[prefFunc](aPrefName); michael@0: registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, michael@0: this.prefRegistryPath + prefType, Ci.nsIWindowsRegKey.ACCESS_WRITE); michael@0: // Always write as string, but the registry subfolder will determine michael@0: // how Metro interprets that string value. michael@0: registry.writeStringValue(aPrefName, prefValue); michael@0: } catch (ex) { michael@0: Cu.reportError("Couldn't push pref " + aPrefName + ": " + ex); michael@0: } finally { michael@0: registry.close(); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Pulls in all shared prefs from the registry michael@0: */ michael@0: pullSharedPrefs: function() { michael@0: function pullSharedPrefType(prefType, prefFunc) { michael@0: try { michael@0: registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, michael@0: self.prefRegistryPath + prefType, michael@0: Ci.nsIWindowsRegKey.ACCESS_ALL); michael@0: for (let i = 0; i < registry.valueCount; i++) { michael@0: let prefName = registry.getValueName(i); michael@0: let prefValue = registry.readStringValue(prefName); michael@0: if (prefType == Ci.nsIPrefBranch.PREF_BOOL) { michael@0: prefValue = prefValue == "true"; michael@0: } michael@0: if (self.prefListToPull.indexOf(prefName) != -1) { michael@0: Services.prefs[prefFunc](prefName, prefValue); michael@0: } michael@0: } michael@0: } catch (ex) { michael@0: dump("Could not pull for prefType " + prefType + ": " + ex + "\n"); michael@0: } finally { michael@0: registry.close(); michael@0: } michael@0: } michael@0: let self = this; michael@0: let registry = Cc["@mozilla.org/windows-registry-key;1"]. michael@0: createInstance(Ci.nsIWindowsRegKey); michael@0: pullSharedPrefType(Ci.nsIPrefBranch.PREF_INT, "setIntPref"); michael@0: pullSharedPrefType(Ci.nsIPrefBranch.PREF_BOOL, "setBoolPref"); michael@0: pullSharedPrefType(Ci.nsIPrefBranch.PREF_STRING, "setCharPref"); michael@0: } michael@0: }; michael@0: #endif michael@0: #endif