Bug 1230802 - Add support for setting chrome.storage.managed via enterprise policy. r=Felipe,zombie,flod
authorMichael Kaply <mozilla@kaply.com>
Thu, 07 Mar 2019 17:31:38 +0000
changeset 463051 1a0f3a7891f481df308a373b86745e4da0277dd6
parent 463050 4a6cb39329d1e0ef14194651a6a24408fb9ccec8
child 463052 d91c333553e45cf0e9ecdf270fe4da1a84ac2dca
push id79966
push usermozilla@kaply.com
push dateThu, 07 Mar 2019 22:31:06 +0000
treeherderautoland@1a0f3a7891f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe, zombie, flod
bugs1230802
milestone67.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 1230802 - Add support for setting chrome.storage.managed via enterprise policy. r=Felipe,zombie,flod Differential Revision: https://phabricator.services.mozilla.com/D21470
browser/components/enterprisepolicies/EnterprisePolicies.js
browser/components/enterprisepolicies/Policies.jsm
browser/components/enterprisepolicies/schemas/policies-schema.json
browser/components/enterprisepolicies/tests/browser/browser.ini
browser/components/enterprisepolicies/tests/browser/browser_policy_3rdparty.js
browser/locales/en-US/browser/policies/policies-descriptions.ftl
toolkit/components/enterprisepolicies/nsIEnterprisePolicies.idl
toolkit/components/extensions/parent/ext-storage.js
toolkit/components/extensions/test/xpcshell/test_ext_storage_managed_policy.js
toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
--- a/browser/components/enterprisepolicies/EnterprisePolicies.js
+++ b/browser/components/enterprisepolicies/EnterprisePolicies.js
@@ -281,20 +281,33 @@ EnterprisePoliciesManager.prototype = {
 
   setSupportMenu(supportMenu) {
     SupportMenu = supportMenu;
   },
 
   getSupportMenu() {
     return SupportMenu;
   },
+
+  setExtensionPolicies(extensionPolicies) {
+    ExtensionPolicies = extensionPolicies;
+  },
+
+  getExtensionPolicy(extensionID) {
+    if (ExtensionPolicies &&
+        extensionID in ExtensionPolicies) {
+      return ExtensionPolicies[extensionID];
+    }
+    return null;
+  },
 };
 
 let DisallowedFeatures = {};
 let SupportMenu = null;
+let ExtensionPolicies = null;
 
 /**
  * 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
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -61,16 +61,22 @@ var EXPORTED_SYMBOLS = ["Policies"];
  *   It will be different for each policy. It could be a boolean,
  *   a string, an array or a complex object. All parameters have
  *   been validated according to the schema, and no unknown
  *   properties will be present on them.
  *
  * The callbacks will be bound to their parent policy object.
  */
 var Policies = {
+  "3rdparty": {
+    onBeforeAddons(manager, param) {
+      manager.setExtensionPolicies(param.Extensions);
+    },
+  },
+
   "AppUpdateURL": {
     onBeforeAddons(manager, param) {
       setDefaultPref("app.update.url", param.href);
     },
   },
 
   "Authentication": {
     onBeforeAddons(manager, param) {
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -1,12 +1,27 @@
 {
   "$schema": "http://json-schema.org/draft-04/schema#",
   "type": "object",
   "properties": {
+
+    "3rdparty": {
+      "type": "object",
+      "properties": {
+        "Extensions" : {
+          "type": "object",
+          "patternProperties": {
+            "^.*$": {
+              "type": "JSON"
+            }
+          }
+        }
+      }
+    },
+
     "AppUpdateURL": {
       "type": "URL"
     },
 
     "Authentication": {
       "type": "object",
       "properties": {
         "SPNEGO" : {
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -20,16 +20,17 @@ support-files =
 skip-if = os != 'mac'
 [browser_policies_mistyped_json.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_pref_policies.js]
 [browser_policies_sorted_alphabetically.js]
+[browser_policy_3rdparty.js]
 [browser_policy_app_update.js]
 [browser_policy_app_update_URL.js]
 [browser_policy_block_about_addons.js]
 [browser_policy_block_about_config.js]
 [browser_policy_block_about_profiles.js]
 [browser_policy_block_about_support.js]
 [browser_policy_block_set_desktop_background.js]
 [browser_policy_bookmarks.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_3rdparty.js
@@ -0,0 +1,20 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_task(async function setup() {
+  await setupPolicyEngineWithJson({
+                                    "policies": {
+                                      "3rdparty": {
+                                        "Extensions": {
+                                          "3rdparty-policy@mozilla.com": {
+                                            "string": "value",
+                                          },
+                                        },
+                                      },
+                                    },
+                                  });
+
+  let extensionPolicy = Services.policies.getExtensionPolicy("3rdparty-policy@mozilla.com");
+  Assert.deepEqual(extensionPolicy, {"string": "value"});
+});
--- a/browser/locales/en-US/browser/policies/policies-descriptions.ftl
+++ b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
@@ -4,16 +4,18 @@
 
 ## The Enterprise Policies feature is aimed at system administrators
 ## who want to deploy these settings across several Firefox installations
 ## all at once. This is traditionally done through the Windows Group Policy
 ## feature, but the system also supports other forms of deployment.
 ## These are short descriptions for individual policies, to be displayed
 ## in the documentation section in about:policies.
 
+policy-3rdparty = Set policies that WebExtensions can access via chrome.storage.managed.
+
 policy-AppUpdateURL = Set custom app update URL.
 
 policy-Authentication = Configure integrated authentication for websites that support it.
 
 policy-BlockAboutAddons = Block access to the Add-ons Manager (about:addons).
 
 policy-BlockAboutConfig = Block access to the about:config page.
 
--- a/toolkit/components/enterprisepolicies/nsIEnterprisePolicies.idl
+++ b/toolkit/components/enterprisepolicies/nsIEnterprisePolicies.idl
@@ -25,9 +25,16 @@ interface nsIEnterprisePolicies : nsISup
   jsval getActivePolicies();
 
   /**
    * Get the contents of the support menu (if applicable)
    *
    * @returns A JS object that contains the url and label or null.
    */
   jsval getSupportMenu();
+
+  /**
+   * Get the policy for a given extensionID (if available)
+   *
+   * @returns A JS object that contains the storage or null if unavailable.
+   */
+  jsval getExtensionPolicy(in ACString extensionID);
 };
--- a/toolkit/components/extensions/parent/ext-storage.js
+++ b/toolkit/components/extensions/parent/ext-storage.js
@@ -21,16 +21,20 @@ const enforceNoTemporaryAddon = extensio
     throw new ExtensionError(EXCEPTION_MESSAGE);
   }
 };
 
 // WeakMap[extension -> Promise<SerializableMap?>]
 const managedStorage = new WeakMap();
 
 const lookupManagedStorage = async (extensionId, context) => {
+  let extensionPolicy = Services.policies.getExtensionPolicy(extensionId);
+  if (extensionPolicy) {
+    return ExtensionStorage._serializableMap(extensionPolicy);
+  }
   let info = await NativeManifests.lookupManifest("storage", extensionId, context);
   if (info) {
     return ExtensionStorage._serializableMap(info.manifest.data);
   }
   return null;
 };
 
 this.storage = class extends ExtensionAPI {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_storage_managed_policy.js
@@ -0,0 +1,48 @@
+"use strict";
+
+const PREF_DISABLE_SECURITY = ("security.turn_off_all_security_so_that_" +
+                               "viruses_can_take_over_this_computer");
+
+const {EnterprisePolicyTesting} = ChromeUtils.import("resource://testing-common/EnterprisePolicyTesting.jsm");
+
+// Setting PREF_DISABLE_SECURITY tells the policy engine that we are in testing
+// mode and enables restarting the policy engine without restarting the browser.
+Services.prefs.setBoolPref(PREF_DISABLE_SECURITY, true);
+registerCleanupFunction(() => {
+  Services.prefs.clearUserPref(PREF_DISABLE_SECURITY);
+});
+
+// Load policy engine
+Services.policies; // eslint-disable-line no-unused-expressions
+
+add_task(async function test_storage_managed_policy() {
+  await ExtensionTestUtils.startAddonManager();
+
+  await EnterprisePolicyTesting.setupPolicyEngineWithJson({
+    "policies": {
+      "3rdparty": {
+        "Extensions": {
+          "test-storage-managed-policy@mozilla.com": {
+            "string": "value",
+          },
+        },
+      },
+    },
+  });
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      applications: {gecko: {id: "test-storage-managed-policy@mozilla.com"}},
+      permissions: ["storage"],
+    },
+
+    async background() {
+      let str = await browser.storage.managed.get("string");
+      browser.test.sendMessage("results", str);
+    },
+  });
+
+  await extension.startup();
+  deepEqual(await extension.awaitMessage("results"), {"string": "value"});
+  await extension.unload();
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -111,16 +111,18 @@ skip-if = os == "android"
 [test_ext_storage.js]
 skip-if = os == "android" && debug
 [test_ext_storage_idb_data_migration.js]
 skip-if = os == "android" && debug
 [test_ext_storage_content.js]
 skip-if = os == "android" && debug
 [test_ext_storage_managed.js]
 skip-if = os == "android"
+[test_ext_storage_managed_policy.js]
+skip-if = os == "android"
 [test_ext_storage_sync.js]
 head = head.js head_sync.js
 skip-if = appname == "thunderbird" || os == "android"
 [test_ext_storage_sync_crypto.js]
 skip-if = appname == "thunderbird" || os == "android"
 [test_ext_storage_tab.js]
 [test_ext_storage_telemetry.js]
 skip-if = os == "android" # checking for telemetry needs to be updated: 1384923