forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			141 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 | |
| /* 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/. */
 | |
| 
 | |
| /**
 | |
|  * The installer prefs component provides a way to get a specific set of prefs
 | |
|  * from a profile into a place where the installer can read them. The primary
 | |
|  * reason for wanting to do this is so we can run things like Shield studies
 | |
|  * on installer features; normally those are enabled by setting a pref, but
 | |
|  * the installer runs outside of any profile and so has no access to prefs.
 | |
|  * So we need to do something else to allow it to read these prefs.
 | |
|  *
 | |
|  * The mechanism we use here is to reflect the values of a list of relevant
 | |
|  * prefs into registry values. One registry value is created for each pref
 | |
|  * that is set. Each installation of the product gets its own registry key
 | |
|  * (based on the path hash). This is obviously a somewhat wider scope than a
 | |
|  * single profile, but it should be close enough in enough cases to suit our
 | |
|  * purposes here.
 | |
|  *
 | |
|  * Currently this module only supports bool prefs. Other types could likely
 | |
|  * be added if needed, but it doesn't seem necessary for the primary use case.
 | |
|  */
 | |
| 
 | |
| // All prefs processed through this component must be in this branch.
 | |
| const INSTALLER_PREFS_BRANCH = "installer.";
 | |
| 
 | |
| // This is the list of prefs that will be reflected to the registry. It should
 | |
| // be kept up to date so that it reflects the list of prefs that are in
 | |
| // current use (e.g., currently active experiments).
 | |
| // Only add prefs to this list which are in INSTALLER_PREFS_BRANCH;
 | |
| // any others will be ignored.
 | |
| const INSTALLER_PREFS_LIST = ["installer.taskbarpin.win10.enabled"];
 | |
| 
 | |
| import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
 | |
| 
 | |
| // This constructor can take a list of prefs to override the default one,
 | |
| // but this is really only intended for tests to use. Normal usage should be
 | |
| // to leave the parameter omitted/undefined.
 | |
| export function InstallerPrefs(prefsList) {
 | |
|   this.prefsList = prefsList || INSTALLER_PREFS_LIST;
 | |
| 
 | |
|   // Each pref to be reflected will get a value created under this key, in HKCU.
 | |
|   // The path will look something like:
 | |
|   // "Software\Mozilla\Firefox\Installer\71AE18FE3142402B\".
 | |
|   ChromeUtils.defineLazyGetter(this, "_registryKeyPath", function () {
 | |
|     const app = AppConstants.MOZ_APP_NAME;
 | |
|     const vendor = Services.appinfo.vendor || "Mozilla";
 | |
|     const xreDirProvider = Cc[
 | |
|       "@mozilla.org/xre/directory-provider;1"
 | |
|     ].getService(Ci.nsIXREDirProvider);
 | |
|     const installHash = xreDirProvider.getInstallHash();
 | |
|     return `Software\\${vendor}\\${app}\\Installer\\${installHash}`;
 | |
|   });
 | |
| }
 | |
| 
 | |
| InstallerPrefs.prototype = {
 | |
|   classID: Components.ID("{cd8a6995-1f19-4cdd-9ed1-d6263302f594}"),
 | |
|   contractID: "@mozilla.org/installerprefs;1",
 | |
| 
 | |
|   QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
 | |
| 
 | |
|   observe(subject, topic, data) {
 | |
|     switch (topic) {
 | |
|       case "profile-after-change": {
 | |
|         if (
 | |
|           AppConstants.platform != "win" ||
 | |
|           !this.prefsList ||
 | |
|           !this.prefsList.length
 | |
|         ) {
 | |
|           // This module has no work to do.
 | |
|           break;
 | |
|         }
 | |
|         const regKey = this._openRegKey();
 | |
|         this._reflectPrefsToRegistry(regKey);
 | |
|         this._registerPrefListeners();
 | |
|         regKey.close();
 | |
|         break;
 | |
|       }
 | |
|       case "nsPref:changed": {
 | |
|         const regKey = this._openRegKey();
 | |
|         if (this.prefsList.includes(data)) {
 | |
|           this._reflectOnePrefToRegistry(regKey, data);
 | |
|         }
 | |
|         regKey.close();
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   _registerPrefListeners() {
 | |
|     Services.prefs.addObserver(INSTALLER_PREFS_BRANCH, this);
 | |
|   },
 | |
| 
 | |
|   _cleanRegistryKey(regKey) {
 | |
|     for (let i = regKey.valueCount - 1; i >= 0; --i) {
 | |
|       const name = regKey.getValueName(i);
 | |
|       if (name.startsWith(INSTALLER_PREFS_BRANCH)) {
 | |
|         regKey.removeValue(name);
 | |
|       }
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   _reflectPrefsToRegistry(regKey) {
 | |
|     this._cleanRegistryKey(regKey);
 | |
|     this.prefsList.forEach(pref =>
 | |
|       this._reflectOnePrefToRegistry(regKey, pref)
 | |
|     );
 | |
|   },
 | |
| 
 | |
|   _reflectOnePrefToRegistry(regKey, pref) {
 | |
|     if (!pref.startsWith(INSTALLER_PREFS_BRANCH)) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     const value = Services.prefs.getBoolPref(pref, false);
 | |
|     if (value) {
 | |
|       regKey.writeIntValue(pref, 1);
 | |
|     } else {
 | |
|       try {
 | |
|         regKey.removeValue(pref);
 | |
|       } catch (ex) {
 | |
|         // This removeValue call is prone to failing because the value we
 | |
|         // tried to remove didn't exist. Obviously that isn't really an error
 | |
|         // that we need to handle.
 | |
|       }
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   _openRegKey() {
 | |
|     const key = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
 | |
|       Ci.nsIWindowsRegKey
 | |
|     );
 | |
|     key.create(
 | |
|       key.ROOT_KEY_CURRENT_USER,
 | |
|       this._registryKeyPath,
 | |
|       key.ACCESS_READ | key.ACCESS_WRITE | key.WOW64_64
 | |
|     );
 | |
|     return key;
 | |
|   },
 | |
| };
 | 
