Bug 1345158 - Implement browser.privacy.trackingProtection API, r?aswan r?francois draft
authorBob Silverberg <bsilverberg@mozilla.com>
Tue, 07 Mar 2017 15:01:20 -0500
changeset 568144 045a16d25326c4d4dedf0c6af243ad2f6a911f7f
parent 567252 62a2d3693579fc77b1c510984ae471a860d03302
child 625836 16f1d6f29886c6798802dfde7bb0f566ed593ae5
push id55776
push userbmo:bob.silverberg@gmail.com
push dateTue, 25 Apr 2017 19:59:45 +0000
reviewersaswan, francois
bugs1345158
milestone55.0a1
Bug 1345158 - Implement browser.privacy.trackingProtection API, r?aswan r?francois MozReview-Commit-ID: ENUIBZ7uhqU
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
@@ -90,16 +90,43 @@ ExtensionPreferencesManager.addSetting("
       case "disable_non_proxied_udp":
         prefs["media.peerconnection.ice.proxy_only"] = true;
         break;
     }
     return prefs;
   },
 });
 
+ExtensionPreferencesManager.addSetting("tracking.trackingProtectionEnabled", {
+  prefNames: [
+    "privacy.trackingprotection.enabled",
+    "privacy.trackingprotection.pbmode.enabled",
+  ],
+
+  setCallback(value) {
+    // Default to disabled.
+    let prefs = {
+      "privacy.trackingprotection.enabled": false,
+      "privacy.trackingprotection.pbmode.enabled": false,
+    };
+
+    switch (value) {
+      case "private_browsing_only":
+        prefs["privacy.trackingprotection.pbmode.enabled"] = true;
+        break;
+
+      case "globally":
+        prefs["privacy.trackingprotection.enabled"] = true;
+        prefs["privacy.trackingprotection.pbmode.enabled"] = true;
+        break;
+    }
+    return prefs;
+  },
+});
+
 ExtensionPreferencesManager.addSetting("websites.hyperlinkAuditingEnabled", {
   prefNames: [
     "browser.send_pings",
   ],
 
   setCallback(value) {
     return {[this.prefNames[0]]: value};
   },
@@ -133,16 +160,29 @@ this.privacy = class extends ExtensionAP
                   return "default_public_interface_only";
                 }
                 return "default_public_and_private_interfaces";
               }
 
               return "default";
             }),
         },
+        tracking: {
+          trackingProtectionEnabled: getAPI(extension,
+            "tracking.trackingProtectionEnabled",
+            () => {
+              if (!Preferences.get("privacy.trackingprotection.enabled")) {
+                if (!Preferences.get("privacy.trackingprotection.pbmode.enabled")) {
+                  return "disabled";
+                }
+                return "private_browsing_only";
+              }
+              return "globally";
+            }),
+        },
         websites: {
           hyperlinkAuditingEnabled: getAPI(extension,
             "websites.hyperlinkAuditingEnabled",
             () => {
               return Preferences.get("browser.send_pings");
             }),
         },
       },
--- a/toolkit/components/extensions/schemas/privacy.json
+++ b/toolkit/components/extensions/schemas/privacy.json
@@ -40,16 +40,35 @@
       },
       "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.tracking",
+    "description": "Use the <code>browser.privacy</code> API to control usage of tracking features in the browser.",
+    "permissions": ["privacy"],
+    "types": [
+      {
+        "id": "trackingProtectionEnabledMode",
+        "type": "string",
+        "enum": ["disabled", "globally", "private_browsing_only"],
+        "description": "The mode for tracking protection."
+      }
+    ],
+    "properties": {
+      "trackingProtectionEnabled": {
+        "$ref": "types.Setting",
+        "description": "Allow users to specify the mode for tracking protection. This setting's value is of type trackingProtectionEnabledMode, defaulting to <code>private_browsing_only</code>."
+      }
+    }
+  },
+  {
     "namespace": "privacy.websites",
     "description": "Use the <code>browser.privacy</code> API to control usage of the features in the browser that can affect a user's privacy.",
     "permissions": ["privacy"],
     "properties": {
       "thirdPartyCookiesAllowed": {
         "$ref": "types.Setting",
         "description": "If disabled, the browser blocks third-party sites from setting cookies. The value of this preference is of type boolean, and the default value is <code>true</code>.",
         "unsupported": true
--- a/toolkit/components/extensions/test/xpcshell/test_ext_privacy.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_privacy.js
@@ -244,17 +244,16 @@ add_task(async function test_privacy_web
           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"],
@@ -293,16 +292,92 @@ add_task(async function test_privacy_web
 
   await testSetting("default", []);
 
   await extension.unload();
 
   await promiseShutdownManager();
 });
 
+add_task(async function test_privacy_trackingProtectionEnabled() {
+  // Create a object to hold the default values of all the prefs.
+  const PREFS = [
+    "privacy.trackingprotection.enabled",
+    "privacy.trackingprotection.pbmode.enabled",
+  ];
+
+  do_register_cleanup(() => {
+    // Reset the prefs.
+    for (let pref in PREFS) {
+      Preferences.reset(pref);
+    }
+  });
+
+  async function background() {
+    browser.test.onMessage.addListener(async (msg, value) => {
+      let tpData;
+      switch (msg) {
+        case "set":
+          await browser.privacy.tracking.trackingProtectionEnabled.set({value});
+          tpData = await browser.privacy.tracking.trackingProtectionEnabled.get({});
+          browser.test.sendMessage("tpData", tpData);
+          break;
+
+        case "clear":
+          await browser.privacy.tracking.trackingProtectionEnabled.clear({});
+          tpData = await browser.privacy.tracking.trackingProtectionEnabled.get({});
+          browser.test.sendMessage("tpData", tpData);
+          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("tpData");
+    equal(data.value, value);
+    for (let pref of PREFS) {
+      equal(
+        Preferences.get(pref),
+        truePrefs.includes(pref),
+        `${pref} set correctly for ${value}`);
+    }
+  }
+
+  await testSetting(
+    "disabled",
+    []);
+
+  await testSetting(
+    "globally",
+    [
+      "privacy.trackingprotection.enabled",
+      "privacy.trackingprotection.pbmode.enabled",
+    ]);
+
+  await testSetting(
+    "private_browsing_only",
+    ["privacy.trackingprotection.pbmode.enabled"]);
+
+  await extension.unload();
+
+  await promiseShutdownManager();
+});
+
 add_task(async function test_exceptions() {
   async function background() {
     await browser.test.assertRejects(
       browser.privacy.network.networkPredictionEnabled.set({value: true, scope: "regular_only"}),
       "Firefox does not support the regular_only settings scope.",
       "Expected rejection calling set with invalid scope.");
 
     await browser.test.assertRejects(