Bug 1364975 - Allow WebExtensions to disable WebRTC, r?aswan draft
authorBob Silverberg <bsilverberg@mozilla.com>
Wed, 24 May 2017 09:58:43 -0400
changeset 587035 23a1943ca619d8434f268dc88252e03f38d2e9ad
parent 585921 cce4d83d2b99ffedbd67a2f40ce26e53e9ae27ab
child 631171 1293a548d871a42fd481376a1794bce7375e82a4
push id61600
push userbmo:bob.silverberg@gmail.com
push dateWed, 31 May 2017 12:24:39 +0000
reviewersaswan
bugs1364975
milestone55.0a1
Bug 1364975 - Allow WebExtensions to disable WebRTC, r?aswan Implement privacy.network.peerConnectionEnabled to allow WebExtensions to enable and disable RTCPeerConnections (aka WebRTC). MozReview-Commit-ID: 5zGotQNwsko
toolkit/components/extensions/ext-privacy.js
toolkit/components/extensions/schemas/privacy.json
toolkit/components/extensions/test/xpcshell/test_ext_privacy.js
--- a/toolkit/components/extensions/ext-privacy.js
+++ b/toolkit/components/extensions/ext-privacy.js
@@ -55,16 +55,26 @@ ExtensionPreferencesManager.addSetting("
       "network.http.speculative-parallel-limit": value ? undefined : 0,
       "network.dns.disablePrefetch": !value,
       "network.predictor.enabled": value,
       "network.prefetch-next": value,
     };
   },
 });
 
+ExtensionPreferencesManager.addSetting("network.peerConnectionEnabled", {
+  prefNames: [
+    "media.peerconnection.enabled",
+  ],
+
+  setCallback(value) {
+    return {[this.prefNames[0]]: value};
+  },
+});
+
 ExtensionPreferencesManager.addSetting("network.webRTCIPHandlingPolicy", {
   prefNames: [
     "media.peerconnection.ice.default_address_only",
     "media.peerconnection.ice.no_host",
     "media.peerconnection.ice.proxy_only",
   ],
 
   setCallback(value) {
@@ -114,16 +124,21 @@ this.privacy = class extends ExtensionAP
           networkPredictionEnabled: getAPI(extension,
             "network.networkPredictionEnabled",
             () => {
               return Preferences.get("network.predictor.enabled") &&
                 Preferences.get("network.prefetch-next") &&
                 Preferences.get("network.http.speculative-parallel-limit") > 0 &&
                 !Preferences.get("network.dns.disablePrefetch");
             }),
+          peerConnectionEnabled: getAPI(extension,
+            "network.peerConnectionEnabled",
+            () => {
+              return Preferences.get("media.peerconnection.enabled");
+            }),
           webRTCIPHandlingPolicy: getAPI(extension,
             "network.webRTCIPHandlingPolicy",
             () => {
               if (Preferences.get("media.peerconnection.ice.proxy_only")) {
                 return "disable_non_proxied_udp";
               }
 
               let default_address_only =
--- a/toolkit/components/extensions/schemas/privacy.json
+++ b/toolkit/components/extensions/schemas/privacy.json
@@ -33,16 +33,20 @@
         "description": "The IP handling policy of WebRTC."
       }
     ],
     "properties": {
       "networkPredictionEnabled": {
         "$ref": "types.Setting",
         "description": "If enabled, the browser attempts to speed up your web browsing experience by pre-resolving DNS entries, prerendering sites (<code>&lt;link rel='prefetch' ...&gt;</code>), and preemptively opening TCP and SSL connections to servers.  This preference's value is a boolean, defaulting to <code>true</code>."
       },
+      "peerConnectionEnabled": {
+        "$ref": "types.Setting",
+        "description": "Allow users to enable and disable RTCPeerConnections (aka WebRTC)."
+      },
       "webRTCIPHandlingPolicy": {
         "$ref": "types.Setting",
         "description": "Allow users to specify the media performance/privacy tradeoffs which impacts how WebRTC traffic will be routed and how much local address information is exposed. This preference's value is of type IPHandlingPolicy, defaulting to <code>default</code>."
       }
     }
   },
   {
     "namespace": "privacy.websites",
--- a/toolkit/components/extensions/test/xpcshell/test_ext_privacy.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_privacy.js
@@ -209,94 +209,110 @@ add_task(async function test_privacy() {
 
   for (let extension of testExtensions) {
     await extension.unload();
   }
 
   await promiseShutdownManager();
 });
 
-add_task(async function test_privacy_webRTCIPHandlingPolicy() {
-  // Create a object to hold the default values of all the prefs.
-  const PREF_DEFAULTS = {
-    "media.peerconnection.ice.default_address_only": null,
-    "media.peerconnection.ice.no_host": null,
-    "media.peerconnection.ice.proxy_only": null,
+// This test can be used for any settings that are added which utilize only
+// boolean prefs.
+add_task(async function test_privacy_boolean_prefs() {
+  // Create an object to hold the values to which we will initialize the prefs.
+  const SETTINGS = {
+    "network.webRTCIPHandlingPolicy": {
+      "media.peerconnection.ice.default_address_only": false,
+      "media.peerconnection.ice.no_host": false,
+      "media.peerconnection.ice.proxy_only": false,
+    },
+    "network.peerConnectionEnabled": {
+      "media.peerconnection.enabled": true,
+    },
   };
 
-  // Store the default values of each pref.
-  for (let pref in PREF_DEFAULTS) {
-    PREF_DEFAULTS[pref] = ExtensionPreferencesManager.getDefaultValue(pref);
+  async function background() {
+    browser.test.onMessage.addListener(async (msg, ...args) => {
+      let data = args[0];
+      // The second argument is the end of the api name,
+      // e.g., "network.webRTCIPHandlingPolicy".
+      let apiObj = args[1].split(".").reduce((o, i) => o[i], browser.privacy);
+      let settingData;
+      switch (msg) {
+        case "set":
+          await apiObj.set(data);
+          settingData = await apiObj.get({});
+          browser.test.sendMessage("settingData", settingData);
+          break;
+
+        case "clear":
+          await apiObj.clear(data);
+          settingData = await apiObj.get({});
+          browser.test.sendMessage("settingData", settingData);
+          break;
+      }
+    });
+  }
+
+  // Set prefs to our initial values.
+  for (let setting in SETTINGS) {
+    for (let pref in SETTINGS[setting]) {
+      Preferences.set(pref, SETTINGS[setting][pref]);
+    }
   }
 
   do_register_cleanup(() => {
     // Reset the prefs.
-    for (let pref in PREF_DEFAULTS) {
-      Preferences.reset(pref);
+    for (let setting in SETTINGS) {
+      for (let pref in SETTINGS[setting]) {
+        Preferences.reset(pref);
+      }
     }
   });
 
-  async function background() {
-    browser.test.onMessage.addListener(async (msg, value) => {
-      let rtcData;
-      switch (msg) {
-        case "set":
-          await browser.privacy.network.webRTCIPHandlingPolicy.set({value});
-          rtcData = await browser.privacy.network.webRTCIPHandlingPolicy.get({});
-          browser.test.sendMessage("rtcData", rtcData);
-          break;
-
-        case "clear":
-          await browser.privacy.network.webRTCIPHandlingPolicy.clear({});
-          rtcData = await browser.privacy.network.webRTCIPHandlingPolicy.get({});
-          browser.test.sendMessage("rtcData", rtcData);
-          break;
-
-      }
-    });
-  }
-
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       permissions: ["privacy"],
     },
     useAddonManager: "temporary",
   });
 
   await promiseStartupManager();
   await extension.startup();
 
-  async function testSetting(value, truePrefs) {
-    extension.sendMessage("set", value);
-    let data = await extension.awaitMessage("rtcData");
+  async function testSetting(setting, value, truePrefs) {
+    extension.sendMessage("set", {value: value}, setting);
+    let data = await extension.awaitMessage("settingData");
     equal(data.value, value);
-    for (let pref in PREF_DEFAULTS) {
+    for (let pref in SETTINGS[setting]) {
       let prefValue = Preferences.get(pref);
-      if (truePrefs.includes(pref)) {
-        ok(prefValue, `${pref} set correctly for ${value}`);
-      } else {
-        equal(prefValue, PREF_DEFAULTS[pref], `${pref} contains default value for ${value}`);
-      }
+      equal(prefValue, truePrefs.includes(pref), `${pref} set correctly for ${value}`);
     }
   }
 
   await testSetting(
+    "network.webRTCIPHandlingPolicy",
     "default_public_and_private_interfaces",
     ["media.peerconnection.ice.default_address_only"]);
 
   await testSetting(
+    "network.webRTCIPHandlingPolicy",
     "default_public_interface_only",
     ["media.peerconnection.ice.default_address_only", "media.peerconnection.ice.no_host"]);
 
   await testSetting(
+    "network.webRTCIPHandlingPolicy",
     "disable_non_proxied_udp",
     ["media.peerconnection.ice.proxy_only"]);
 
-  await testSetting("default", []);
+  await testSetting("network.webRTCIPHandlingPolicy", "default", []);
+
+  await testSetting("network.peerConnectionEnabled", false, []);
+  await testSetting("network.peerConnectionEnabled", true, ["media.peerconnection.enabled"]);
 
   await extension.unload();
 
   await promiseShutdownManager();
 });
 
 add_task(async function test_exceptions() {
   async function background() {