Bug 1364936 - Allow WebExtensions to disable the browser cache, r?aswan draft
authorBob Silverberg <bsilverberg@mozilla.com>
Wed, 24 May 2017 13:17:42 -0400
changeset 596607 0be6a46e8e6169f2f826afca159cfc6f804a1b4c
parent 596561 d39cd452b52bf82fa4a717172a62d62ab9e5366f
child 634012 9e7cae835d0cd574371cfd52d77e062efc551a38
push id64696
push userbmo:bob.silverberg@gmail.com
push dateMon, 19 Jun 2017 14:53:23 +0000
reviewersaswan
bugs1364936
milestone56.0a1
Bug 1364936 - Allow WebExtensions to disable the browser cache, r?aswan MozReview-Commit-ID: KhupGnBT5mZ
browser/locales/en-US/chrome/browser/browser.properties
toolkit/components/extensions/ext-browserSettings.js
toolkit/components/extensions/ext-toolkit.js
toolkit/components/extensions/jar.mn
toolkit/components/extensions/schemas/browser_settings.json
toolkit/components/extensions/schemas/jar.mn
toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
toolkit/components/extensions/test/xpcshell/xpcshell.ini
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -91,16 +91,17 @@ webextPerms.updateAccept.accessKey=U
 webextPerms.optionalPermsHeader=%S requests additional permissions.
 webextPerms.optionalPermsListIntro=It wants to:
 webextPerms.optionalPermsAllow.label=Allow
 webextPerms.optionalPermsAllow.accessKey=A
 webextPerms.optionalPermsDeny.label=Deny
 webextPerms.optionalPermsDeny.accessKey=D
 
 webextPerms.description.bookmarks=Read and modify bookmarks
+webextPerms.description.browserSettings=Read and modify browser settings
 webextPerms.description.clipboardRead=Get data from the clipboard
 webextPerms.description.clipboardWrite=Input data to the clipboard
 webextPerms.description.downloads=Download files and read and modify the browser’s download history
 webextPerms.description.geolocation=Access your location
 webextPerms.description.history=Access browsing history
 webextPerms.description.management=Monitor extension usage and manage themes
 # LOCALIZATION NOTE (webextPerms.description.nativeMessaging)
 # %S will be replaced with the name of the application
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/ext-browserSettings.js
@@ -0,0 +1,61 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+                                  "resource://gre/modules/Preferences.jsm");
+
+Cu.import("resource://gre/modules/ExtensionPreferencesManager.jsm");
+
+function getAPI(extension, name, callback) {
+  return {
+    async get(details) {
+      return {
+        levelOfControl: details.incognito ?
+          "not_controllable" :
+          await ExtensionPreferencesManager.getLevelOfControl(
+            extension, name),
+        value: await callback(),
+      };
+    },
+    set(details) {
+      return ExtensionPreferencesManager.setSetting(
+        extension, name, details.value);
+    },
+    clear(details) {
+      return ExtensionPreferencesManager.removeSetting(extension, name);
+    },
+  };
+}
+
+// Add settings objects for supported APIs to the preferences manager.
+ExtensionPreferencesManager.addSetting("cacheEnabled", {
+  prefNames: [
+    "browser.cache.disk.enable",
+    "browser.cache.memory.enable",
+  ],
+
+  setCallback(value) {
+    let returnObj = {};
+    for (let pref of this.prefNames) {
+      returnObj[pref] = value;
+    }
+    return returnObj;
+  },
+});
+
+this.browserSettings = class extends ExtensionAPI {
+  getAPI(context) {
+    let {extension} = context;
+    return {
+      browserSettings: {
+        cacheEnabled: getAPI(extension,
+          "cacheEnabled",
+          () => {
+            return Preferences.get("browser.cache.disk.enable") &&
+              Preferences.get("browser.cache.memory.enable");
+          }),
+      },
+    };
+  }
+};
--- a/toolkit/components/extensions/ext-toolkit.js
+++ b/toolkit/components/extensions/ext-toolkit.js
@@ -85,16 +85,24 @@ extensions.registerModules({
       ["alarms"],
     ],
   },
   backgroundPage: {
     url: "chrome://extensions/content/ext-backgroundPage.js",
     scopes: ["addon_parent"],
     manifest: ["background"],
   },
+  browserSettings: {
+    url: "chrome://extensions/content/ext-browserSettings.js",
+    schema: "chrome://extensions/content/schemas/browser_settings.json",
+    scopes: ["addon_parent"],
+    paths: [
+      ["browserSettings"],
+    ],
+  },
   contextualIdentities: {
     url: "chrome://extensions/content/ext-contextualIdentities.js",
     schema: "chrome://extensions/content/schemas/contextual_identities.json",
     scopes: ["addon_parent"],
     paths: [
       ["contextualIdentities"],
     ],
   },
--- a/toolkit/components/extensions/jar.mn
+++ b/toolkit/components/extensions/jar.mn
@@ -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/.
 
 toolkit.jar:
 % content extensions %content/extensions/
     content/extensions/ext-alarms.js
     content/extensions/ext-backgroundPage.js
     content/extensions/ext-browser-content.js
+    content/extensions/ext-browserSettings.js
     content/extensions/ext-contextualIdentities.js
     content/extensions/ext-cookies.js
     content/extensions/ext-downloads.js
     content/extensions/ext-extension.js
     content/extensions/ext-geolocation.js
     content/extensions/ext-i18n.js
     content/extensions/ext-idle.js
     content/extensions/ext-management.js
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/schemas/browser_settings.json
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+  {
+    "namespace": "manifest",
+    "types": [
+      {
+        "$extend": "Permission",
+        "choices": [{
+          "type": "string",
+          "enum": [
+            "browserSettings"
+          ]
+        }]
+      }
+    ]
+  },
+  {
+    "namespace": "browserSettings",
+    "description": "Use the <code>browser.browserSettings</code> API to control global settings of the browser.",
+    "permissions": ["browserSettings"],
+    "properties": {
+      "cacheEnabled": {
+        "$ref": "types.Setting",
+        "description": "Enables or disables the browser cache."
+      }
+    }
+  }
+]
--- a/toolkit/components/extensions/schemas/jar.mn
+++ b/toolkit/components/extensions/schemas/jar.mn
@@ -1,15 +1,16 @@
 # 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/.
 
 toolkit.jar:
 % content extensions %content/extensions/
     content/extensions/schemas/alarms.json
+    content/extensions/schemas/browser_settings.json
     content/extensions/schemas/contextual_identities.json
     content/extensions/schemas/cookies.json
     content/extensions/schemas/downloads.json
     content/extensions/schemas/events.json
     content/extensions/schemas/experiments.json
     content/extensions/schemas/extension.json
     content/extensions/schemas/extension_types.json
     content/extensions/schemas/extension_protocol_handlers.json
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js
@@ -0,0 +1,86 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPreferencesManager",
+                                  "resource://gre/modules/ExtensionPreferencesManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
+                                  "resource://gre/modules/Preferences.jsm");
+
+const {
+  createAppInfo,
+  promiseShutdownManager,
+  promiseStartupManager,
+} = AddonTestUtils;
+
+AddonTestUtils.init(this);
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
+
+add_task(async function test_browser_settings() {
+  // Create an object to hold the values to which we will initialize the prefs.
+  const PREFS = {
+    "browser.cache.disk.enable": true,
+    "browser.cache.memory.enable": true,
+  };
+
+  async function background() {
+    browser.test.onMessage.addListener(async (msg, apiName, value) => {
+      let apiObj = browser.browserSettings[apiName];
+      await apiObj.set({value});
+      browser.test.sendMessage("settingData", await apiObj.get({}));
+    });
+  }
+
+  // Set prefs to our initial values.
+  for (let pref in PREFS) {
+    Preferences.set(pref, PREFS[pref]);
+  }
+
+  do_register_cleanup(() => {
+    // Reset the prefs.
+    for (let pref in PREFS) {
+      Preferences.reset(pref);
+    }
+  });
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      permissions: ["browserSettings"],
+    },
+    useAddonManager: "temporary",
+  });
+
+  await promiseStartupManager();
+  await extension.startup();
+
+  async function testSetting(setting, value, expected) {
+    extension.sendMessage("set", setting, value);
+    let data = await extension.awaitMessage("settingData");
+    equal(data.value, value,
+          `The ${setting} setting has the expected value.`);
+    equal(data.levelOfControl, "controlled_by_this_extension",
+          `The ${setting} setting has the expected levelOfControl.`);
+    for (let pref in expected) {
+      equal(Preferences.get(pref), expected[pref], `${pref} set correctly for ${value}`);
+    }
+  }
+
+  await testSetting(
+    "cacheEnabled", false,
+    {
+      "browser.cache.disk.enable": false,
+      "browser.cache.memory.enable": false,
+    });
+  await testSetting(
+    "cacheEnabled", true,
+    {
+      "browser.cache.disk.enable": true,
+      "browser.cache.memory.enable": true,
+    });
+
+  await extension.unload();
+
+  await promiseShutdownManager();
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini
@@ -24,16 +24,17 @@ tags = webextensions
 [test_ext_background_generated_reload.js]
 [test_ext_background_global_history.js]
 skip-if = os == "android" # Android does not use Places for history.
 [test_ext_background_private_browsing.js]
 [test_ext_background_runtime_connect_params.js]
 [test_ext_background_sub_windows.js]
 [test_ext_background_window_properties.js]
 skip-if = os == "android"
+[test_ext_browserSettings.js]
 [test_ext_contexts.js]
 [test_ext_contextual_identities.js]
 skip-if = os == "android" # Containers are not exposed to android.
 [test_ext_debugging_utils.js]
 [test_ext_downloads.js]
 [test_ext_downloads_download.js]
 skip-if = os == "android"
 [test_ext_downloads_misc.js]