1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/modules/WindowsPrefSync.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,173 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +'use strict'; 1.9 + 1.10 +this.EXPORTED_SYMBOLS = []; 1.11 + 1.12 +#ifdef XP_WIN 1.13 +#ifdef MOZ_METRO 1.14 + 1.15 +const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = 1.16 + Components; 1.17 +const PREF_BASE_KEY = "Software\\Mozilla\\Firefox\\Metro\\Prefs\\"; 1.18 + 1.19 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.20 +Cu.import("resource://gre/modules/Services.jsm"); 1.21 + 1.22 +this.EXPORTED_SYMBOLS = [ "WindowsPrefSync" ]; 1.23 + 1.24 +/** 1.25 + * Manages preferences that need to be pulled and pushed between Metro 1.26 + * and desktop. 1.27 + */ 1.28 +this.WindowsPrefSync = { 1.29 + init: function() { 1.30 + this.pullSharedPrefs(); 1.31 + this.prefListToPush.forEach(function(prefName) { 1.32 + this.pushSharedPref(prefName); 1.33 + Services.prefs.addObserver(prefName, this, false); 1.34 + }, this); 1.35 + }, 1.36 + 1.37 + uninit: function() { 1.38 + this.prefListToPush.forEach(function(prefName) { 1.39 + Services.prefs.removeObserver(prefName, this); 1.40 + }, this); 1.41 + }, 1.42 + 1.43 + /** 1.44 + * Returns the list of prefs that should be pushed for the current 1.45 + * environment. 1.46 + */ 1.47 + get prefListToPush() { 1.48 + return !Services.metro.immersive ? this.desktopControlledPrefs : 1.49 + this.metroControlledPrefs; 1.50 + }, 1.51 + 1.52 + /** 1.53 + * Returns the list of prefs that should be pulled for the current 1.54 + * environment. 1.55 + */ 1.56 + get prefListToPull() { 1.57 + return Services.metro.immersive ? this.desktopControlledPrefs : 1.58 + this.metroControlledPrefs; 1.59 + }, 1.60 + 1.61 + /** 1.62 + * The following preferences will be pushed to registry from Desktop 1.63 + * Firefox and pulled in from Metro Firefox. 1.64 + * 1.65 + * app.update.* prefs are because Metro shares an installation directory with 1.66 + * Firefox, and the options for these are only present in the Desktop options. 1.67 + * 1.68 + * browser.sessionstore.resume_session_once is mainly for the switch to Metro 1.69 + * and switch to Desktop feature. 1.70 + * 1.71 + * browser.startup.page - if a desktop Firefox user wants her/his sessions 1.72 + * to always restore, we need to honor that in metro Firefox as well. 1.73 + */ 1.74 + desktopControlledPrefs: ["app.update.auto", 1.75 + "app.update.enabled", 1.76 + "app.update.service.enabled", 1.77 + "app.update.metro.enabled", 1.78 + "browser.sessionstore.resume_session_once", 1.79 + "browser.startup.page"], 1.80 + 1.81 + /** 1.82 + * Returns the base path where registry sync prefs are stored. 1.83 + */ 1.84 + get prefRegistryPath() { 1.85 + let profileService = Cc["@mozilla.org/toolkit/profile-service;1"]. 1.86 + createInstance(Ci.nsIToolkitProfileService); 1.87 + return PREF_BASE_KEY + profileService.selectedProfile.name + "\\"; 1.88 + }, 1.89 + 1.90 + /** 1.91 + * The following preferences will be pushed to registry from Metro 1.92 + * Firefox and pulled in from Desktop Firefox. 1.93 + * 1.94 + * browser.sessionstore.resume_session_once is mainly for the switch to Metro 1.95 + * and switch to Desktop feature. 1.96 + */ 1.97 + metroControlledPrefs: ["browser.sessionstore.resume_session_once"], 1.98 + 1.99 + /** 1.100 + * Observes preference changes and writes them to the registry, only 1.101 + * the list of preferences initialized will be observed 1.102 + */ 1.103 + observe: function (aSubject, aTopic, aPrefName) { 1.104 + if (aTopic != "nsPref:changed") 1.105 + return; 1.106 + 1.107 + this.pushSharedPref(aPrefName); 1.108 + }, 1.109 + 1.110 + /** 1.111 + * Writes the pref to HKCU in the registry and adds a pref-observer to keep 1.112 + * the registry in sync with changes to the value. 1.113 + */ 1.114 + pushSharedPref : function(aPrefName) { 1.115 + let registry = Cc["@mozilla.org/windows-registry-key;1"]. 1.116 + createInstance(Ci.nsIWindowsRegKey); 1.117 + try { 1.118 + var prefType = Services.prefs.getPrefType(aPrefName); 1.119 + let prefFunc; 1.120 + if (prefType == Ci.nsIPrefBranch.PREF_INT) 1.121 + prefFunc = "getIntPref"; 1.122 + else if (prefType == Ci.nsIPrefBranch.PREF_BOOL) 1.123 + prefFunc = "getBoolPref"; 1.124 + else if (prefType == Ci.nsIPrefBranch.PREF_STRING) 1.125 + prefFunc = "getCharPref"; 1.126 + else 1.127 + throw "Unsupported pref type"; 1.128 + 1.129 + let prefValue = Services.prefs[prefFunc](aPrefName); 1.130 + registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, 1.131 + this.prefRegistryPath + prefType, Ci.nsIWindowsRegKey.ACCESS_WRITE); 1.132 + // Always write as string, but the registry subfolder will determine 1.133 + // how Metro interprets that string value. 1.134 + registry.writeStringValue(aPrefName, prefValue); 1.135 + } catch (ex) { 1.136 + Cu.reportError("Couldn't push pref " + aPrefName + ": " + ex); 1.137 + } finally { 1.138 + registry.close(); 1.139 + } 1.140 + }, 1.141 + 1.142 + /** 1.143 + * Pulls in all shared prefs from the registry 1.144 + */ 1.145 + pullSharedPrefs: function() { 1.146 + function pullSharedPrefType(prefType, prefFunc) { 1.147 + try { 1.148 + registry.create(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, 1.149 + self.prefRegistryPath + prefType, 1.150 + Ci.nsIWindowsRegKey.ACCESS_ALL); 1.151 + for (let i = 0; i < registry.valueCount; i++) { 1.152 + let prefName = registry.getValueName(i); 1.153 + let prefValue = registry.readStringValue(prefName); 1.154 + if (prefType == Ci.nsIPrefBranch.PREF_BOOL) { 1.155 + prefValue = prefValue == "true"; 1.156 + } 1.157 + if (self.prefListToPull.indexOf(prefName) != -1) { 1.158 + Services.prefs[prefFunc](prefName, prefValue); 1.159 + } 1.160 + } 1.161 + } catch (ex) { 1.162 + dump("Could not pull for prefType " + prefType + ": " + ex + "\n"); 1.163 + } finally { 1.164 + registry.close(); 1.165 + } 1.166 + } 1.167 + let self = this; 1.168 + let registry = Cc["@mozilla.org/windows-registry-key;1"]. 1.169 + createInstance(Ci.nsIWindowsRegKey); 1.170 + pullSharedPrefType(Ci.nsIPrefBranch.PREF_INT, "setIntPref"); 1.171 + pullSharedPrefType(Ci.nsIPrefBranch.PREF_BOOL, "setBoolPref"); 1.172 + pullSharedPrefType(Ci.nsIPrefBranch.PREF_STRING, "setCharPref"); 1.173 + } 1.174 +}; 1.175 +#endif 1.176 +#endif