Bug 1436840 - Policy engine: Add support for enterprise-only policies. r=mkaply
authorFelipe Gomes <felipc@gmail.com>
Mon, 05 Mar 2018 20:46:54 -0300
changeset 763624 28a1060ab28344af513fa9169ad9f6f8a06f49d6
parent 763623 e0a165295ef81483c10ae295769d6a5980b52225
child 763625 142d7e0ffe7eb71729c904353d04a76c30ff90eb
push id101496
push usergsquelart@mozilla.com
push dateTue, 06 Mar 2018 10:10:48 +0000
reviewersmkaply
bugs1436840
milestone60.0a1
Bug 1436840 - Policy engine: Add support for enterprise-only policies. r=mkaply Policies annotated with enterprise_only in the schema will only be allowed to run on ESR or on pre-release channels (for testing) MozReview-Commit-ID: 4tF8t1ozyVp
browser/components/enterprisepolicies/EnterprisePolicies.js
browser/components/enterprisepolicies/tests/browser/browser.ini
browser/components/enterprisepolicies/tests/browser/browser_policies_enterprise_only.js
--- a/browser/components/enterprisepolicies/EnterprisePolicies.js
+++ b/browser/components/enterprisepolicies/EnterprisePolicies.js
@@ -28,16 +28,19 @@ const MAGIC_TEST_ROOT_PREFIX  = "<test-r
 const PREF_TEST_ROOT          = "mochitest.testRoot";
 
 // This pref is meant to be temporary: it will only be used while we're
 // testing this feature without rolling it out officially. When the
 // policy engine is released, this pref should be removed.
 const PREF_ENABLED            = "browser.policies.enabled";
 const PREF_LOGLEVEL           = "browser.policies.loglevel";
 
+// To force disallowing enterprise-only policies during tests
+const PREF_DISALLOW_ENTERPRISE = "browser.policies.testing.disallowEnterprise";
+
 XPCOMUtils.defineLazyGetter(this, "log", () => {
   let { ConsoleAPI } = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
   return new ConsoleAPI({
     prefix: "Enterprise Policies",
     // 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,
@@ -122,16 +125,21 @@ EnterprisePoliciesManager.prototype = {
       let policySchema = schema.properties[policyName];
       let policyParameters = unparsedPolicies[policyName];
 
       if (!policySchema) {
         log.error(`Unknown policy: ${policyName}`);
         continue;
       }
 
+      if (policySchema.enterprise_only && !areEnterpriseOnlyPoliciesAllowed()) {
+        log.error(`Policy ${policyName} is only allowed on ESR`);
+        continue;
+      }
+
       let [parametersAreValid, parsedParameters] =
         PoliciesValidator.validateAndParseParameters(policyParameters,
                                                      policySchema);
 
       if (!parametersAreValid) {
         log.error(`Invalid parameters specified for ${policyName}.`);
         continue;
       }
@@ -300,16 +308,43 @@ EnterprisePoliciesManager.prototype = {
 
   isAllowed: function BG_sanitize(feature) {
     return !(feature in DisallowedFeatures);
   },
 };
 
 let DisallowedFeatures = {};
 
+/**
+ * areEnterpriseOnlyPoliciesAllowed
+ *
+ * Checks whether the policies marked as enterprise_only in the
+ * schema are allowed to run on this browser.
+ *
+ * This is meant to only allow policies to run on ESR, but in practice
+ * we allow it to run on channels different than release, to allow
+ * these policies to be tested on pre-release channels.
+ *
+ * @returns {Bool} Whether the policy can run.
+ */
+function areEnterpriseOnlyPoliciesAllowed() {
+  if (Services.prefs.getBoolPref(PREF_DISALLOW_ENTERPRISE, false)) {
+    // This is used as an override to test the "enterprise_only"
+    // functionality itself on tests, which would always return
+    // true due to the Cu.isInAutomation check below.
+    return false;
+  }
+
+  if (AppConstants.MOZ_UPDATE_CHANNEL != "release" ||
+      Cu.isInAutomation) {
+    return true;
+  }
+
+  return false;
+}
 
 /*
  * JSON PROVIDER OF POLICIES
  *
  * This is a platform-agnostic provider which looks for
  * policies specified through a policies.json file stored
  * in the installation's distribution folder.
  */
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -2,16 +2,17 @@
 prefs =
   browser.policies.enabled=true
 support-files =
   head.js
   config_popups_cookies_addons_flash.json
   config_broken_json.json
 
 [browser_policies_broken_json.js]
+[browser_policies_enterprise_only.js]
 [browser_policies_notice_in_aboutpreferences.js]
 [browser_policies_popups_cookies_addons_flash.js]
 [browser_policies_runOnce_helper.js]
 [browser_policies_setAndLockPref_API.js]
 [browser_policies_simple_policies.js]
 [browser_policies_sorted_alphabetically.js]
 [browser_policies_validate_and_parse_API.js]
 [browser_policy_app_update.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policies_enterprise_only.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PREF_DISALLOW_ENTERPRISE = "browser.policies.testing.disallowEnterprise";
+
+add_task(async function test_enterprise_only_policies() {
+  let { Policies } = ChromeUtils.import("resource:///modules/policies/Policies.jsm", {});
+
+  let normalPolicyRan = false, enterprisePolicyRan = false;
+
+  Policies.NormalPolicy = {
+    onProfileAfterChange(manager, param) {
+      normalPolicyRan = true;
+    }
+  };
+
+  Policies.EnterpriseOnlyPolicy = {
+    onProfileAfterChange(manager, param) {
+      enterprisePolicyRan = true;
+    }
+  };
+
+  Services.prefs.setBoolPref(PREF_DISALLOW_ENTERPRISE, true);
+
+  await setupPolicyEngineWithJson(
+    // policies.json
+    {
+      "policies": {
+        "NormalPolicy": true,
+        "EnterpriseOnlyPolicy": true
+      }
+    },
+
+    // custom schema
+    {
+      properties: {
+        "NormalPolicy": {
+          "type": "boolean"
+        },
+
+        "EnterpriseOnlyPolicy": {
+          "type": "boolean",
+          "enterprise_only": true
+        },
+      }
+    }
+  );
+
+  is(Services.policies.status, Ci.nsIEnterprisePolicies.ACTIVE, "Engine is active");
+  is(normalPolicyRan, true, "Normal policy ran as expected");
+  is(enterprisePolicyRan, false, "Enterprise-only policy was prevented from running");
+
+  // Clean-up
+  delete Policies.NormalPolicy;
+  delete Policies.EnterpriseOnlyPolicy;
+  Services.prefs.clearUserPref(PREF_DISALLOW_ENTERPRISE);
+});