Bug 1433136 - Basic GPO Support. r?felipe
MozReview-Commit-ID: 1V1aOK3ELZC
--- 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'