Bug 1433136 - Basic GPO Support. r=Felipe
authorMichael Kaply <mozilla@kaply.com>
Wed, 21 Feb 2018 19:49:09 -0600
changeset 404981 946a3f94fc70a7f1ba31467c21a24710a7958921
parent 404980 d2a26faa304293e281cf1745e468ebf3026ca3ba
child 404982 d3363d47276bf078c00d6d3bd9d231ebbce4c4b4
push id33498
push userccoroiu@mozilla.com
push dateFri, 23 Feb 2018 17:42:25 +0000
treeherdermozilla-central@41492f00c669 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe
bugs1433136
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1433136 - Basic GPO Support. r=Felipe MozReview-Commit-ID: 1V1aOK3ELZC
browser/components/enterprisepolicies/EnterprisePolicies.js
browser/components/enterprisepolicies/WindowsGPOParser.jsm
browser/components/enterprisepolicies/moz.build
--- a/browser/components/enterprisepolicies/EnterprisePolicies.js
+++ b/browser/components/enterprisepolicies/EnterprisePolicies.js
@@ -2,16 +2,17 @@
  * 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  WindowsGPOParser: "resource:///modules/policies/WindowsGPOParser.jsm",
   NetUtil: "resource://gre/modules/NetUtil.jsm",
   Policies: "resource:///modules/policies/Policies.jsm",
   PoliciesValidator: "resource:///modules/policies/PoliciesValidator.jsm",
 });
 
 // This is the file that will be searched for in the
 // ${InstallDir}/distribution folder.
 const POLICIES_FILENAME = "policies.json";
@@ -95,17 +96,22 @@ EnterprisePoliciesManager.prototype = {
       return;
     }
 
     this.status = Ci.nsIEnterprisePolicies.ACTIVE;
     this._activatePolicies(provider.policies);
   },
 
   _chooseProvider() {
-    // TODO: Bug 1433136 - Add GPO provider with higher precendence here
+    if (AppConstants.platform == "win") {
+      let gpoProvider = new GPOPoliciesProvider();
+      if (gpoProvider.hasPolicies) {
+        return gpoProvider;
+      }
+    }
 
     let jsonProvider = new JSONPoliciesProvider();
     if (jsonProvider.hasPolicies) {
       return jsonProvider;
     }
 
     return null;
   },
@@ -361,11 +367,51 @@ class JSONPoliciesProvider {
       } else {
         log.error("Error reading file");
         this._failed = true;
       }
     }
   }
 }
 
+class GPOPoliciesProvider {
+  constructor() {
+    this._policies = null;
+
+    let wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(Ci.nsIWindowsRegKey);
+    // Machine policies override user policies, so we read
+    // user policies first and then replace them if necessary.
+    wrk.open(wrk.ROOT_KEY_CURRENT_USER,
+             "SOFTWARE\\Policies",
+             wrk.ACCESS_READ);
+    if (wrk.hasChild("Mozilla\\Firefox")) {
+      this._readData(wrk);
+    }
+    wrk.close();
+
+    wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
+             "SOFTWARE\\Policies",
+             wrk.ACCESS_READ);
+    if (wrk.hasChild("Mozilla\\Firefox")) {
+      this._readData(wrk);
+    }
+    wrk.close();
+  }
+
+  get hasPolicies() {
+    return this._policies !== null;
+  }
+
+  get policies() {
+    return this._policies;
+  }
+
+  get failed() {
+    return this._failed;
+  }
+
+  _readData(wrk) {
+    this._policies = WindowsGPOParser.readPolicies(wrk, this._policies);
+  }
+}
 
 var components = [EnterprisePoliciesManager];
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/WindowsGPOParser.jsm
@@ -0,0 +1,97 @@
+/* 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/. */
+
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const PREF_LOGLEVEL = "browser.policies.loglevel";
+
+XPCOMUtils.defineLazyGetter(this, "log", () => {
+  let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
+  return new ConsoleAPI({
+    prefix: "GPOParser.jsm",
+    // tip: set maxLogLevel to "debug" and use log.debug() to create detailed
+    // messages during development. See LOG_LEVELS in Console.jsm for details.
+    maxLogLevel: "error",
+    maxLogLevelPref: PREF_LOGLEVEL,
+  });
+});
+
+this.EXPORTED_SYMBOLS = ["WindowsGPOParser"];
+
+this.WindowsGPOParser = {
+  readPolicies(wrk, policies) {
+    let childWrk = wrk.openChild("Mozilla\\Firefox", wrk.ACCESS_READ);
+    if (!policies) {
+      policies = {};
+    }
+    try {
+      policies = registryToObject(childWrk, policies);
+    } catch (e) {
+      log.error(e);
+    } finally {
+      childWrk.close();
+    }
+    return policies;
+  }
+};
+
+function registryToObject(wrk, policies) {
+  if (!policies) {
+    policies = {};
+  }
+  if (wrk.valueCount > 0) {
+    if (wrk.getValueName(0) == "1") {
+      // If the first item is 1, just assume it is an array
+      let array = [];
+      for (let i = 0; i < wrk.valueCount; i++) {
+        array.push(readRegistryValue(wrk, wrk.getValueName(i)));
+      }
+      // If it's an array, it shouldn't have any children
+      return array;
+    }
+    for (let i = 0; i < wrk.valueCount; i++) {
+      let name = wrk.getValueName(i);
+      let value = readRegistryValue(wrk, name);
+      policies[name] = value;
+    }
+  }
+  if (wrk.childCount > 0) {
+    if (wrk.getChildName(0) == "1") {
+      // If the first item is 1, it's an array of objects
+      let array = [];
+      for (let i = 0; i < wrk.childCount; i++) {
+        let name = wrk.getChildName(i);
+        let childWrk = wrk.openChild(name, wrk.ACCESS_READ);
+        array.push(registryToObject(childWrk));
+        childWrk.close();
+      }
+      // If it's an array, it shouldn't have any children
+      return array;
+    }
+    for (let i = 0; i < wrk.childCount; i++) {
+      let name = wrk.getChildName(i);
+      let childWrk = wrk.openChild(name, wrk.ACCESS_READ);
+      policies[name] = registryToObject(childWrk);
+      childWrk.close();
+    }
+  }
+  return policies;
+}
+
+function readRegistryValue(wrk, value) {
+  switch (wrk.getValueType(value)) {
+    case wrk.TYPE_STRING:
+     return wrk.readStringValue(value);
+    case wrk.TYPE_BINARY:
+      return wrk.readBinaryValue(value);
+    case wrk.TYPE_INT:
+      return wrk.readIntValue(value);
+    case wrk.TYPE_INT64:
+      return wrk.readInt64Value(value);
+  }
+  // unknown type
+  return null;
+}
--- a/browser/components/enterprisepolicies/moz.build
+++ b/browser/components/enterprisepolicies/moz.build
@@ -22,9 +22,14 @@ EXTRA_COMPONENTS += [
     'EnterprisePoliciesContent.js',
 ]
 
 EXTRA_JS_MODULES.policies += [
     'Policies.jsm',
     'PoliciesValidator.jsm',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    EXTRA_JS_MODULES.policies += [
+        'WindowsGPOParser.jsm',
+]
+
 FINAL_LIBRARY = 'browsercomps'