Bug 1646181 - Put rkv under a pref in ExtensionPermissions. r=robwu
authorAgi Sferro <agi@sferro.dev>
Thu, 18 Jun 2020 17:46:18 +0000
changeset 536363 0073554a8bed3dae59ffc04cb5e5cfc84c2cf866
parent 536362 ef8485a16d099e24f4832178664c5a93a28396ec
child 536364 5de39c68950ab402e55d573b54ebebacdb3418e4
push id37520
push userdluca@mozilla.com
push dateFri, 19 Jun 2020 04:04:08 +0000
treeherdermozilla-central@d1a4f9157858 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrobwu
bugs1646181
milestone79.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 1646181 - Put rkv under a pref in ExtensionPermissions. r=robwu Differential Revision: https://phabricator.services.mozilla.com/D79910
toolkit/components/extensions/ExtensionPermissions.jsm
toolkit/components/extensions/moz.build
toolkit/components/extensions/test/xpcshell/head_legacy_ep.js
toolkit/components/extensions/test/xpcshell/xpcshell-legacy-ep.ini
--- a/toolkit/components/extensions/ExtensionPermissions.jsm
+++ b/toolkit/components/extensions/ExtensionPermissions.jsm
@@ -3,19 +3,23 @@
 /* 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/. */
 "use strict";
 
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
+const { AppConstants } = ChromeUtils.import(
+  "resource://gre/modules/AppConstants.jsm"
+);
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   ExtensionParent: "resource://gre/modules/ExtensionParent.jsm",
+  JSONFile: "resource://gre/modules/JSONFile.jsm",
   OS: "resource://gre/modules/osfile.jsm",
 });
 
 XPCOMUtils.defineLazyGetter(
   this,
   "StartupCache",
   () => ExtensionParent.StartupCache
 );
@@ -49,16 +53,90 @@ function emptyPermissions() {
 
 const DEFAULT_VALUE = JSON.stringify(emptyPermissions());
 
 const VERSION_KEY = "_version";
 const VERSION_VALUE = 1;
 
 const KEY_PREFIX = "id-";
 
+// Bug 1646182: remove once we fully migrate to rkv
+let prefs;
+
+// Bug 1646182: remove once we fully migrate to rkv
+class LegacyPermissionStore {
+  async lazyInit() {
+    if (!this._initPromise) {
+      this._initPromise = this._init();
+    }
+    return this._initPromise;
+  }
+
+  async _init() {
+    let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_NAME);
+
+    prefs = new JSONFile({ path });
+    prefs.data = {};
+
+    try {
+      let { buffer } = await OS.File.read(path);
+      prefs.data = JSON.parse(new TextDecoder().decode(buffer));
+    } catch (e) {
+      if (!e.becauseNoSuchFile) {
+        Cu.reportError(e);
+      }
+    }
+  }
+
+  async has(extensionId) {
+    await this.lazyInit();
+    return !!prefs.data[extensionId];
+  }
+
+  async get(extensionId) {
+    await this.lazyInit();
+
+    let perms = prefs.data[extensionId];
+    if (!perms) {
+      perms = emptyPermissions();
+    }
+
+    return perms;
+  }
+
+  async put(extensionId, permissions) {
+    await this.lazyInit();
+    prefs.data[extensionId] = permissions;
+    prefs.saveSoon();
+  }
+
+  async delete(extensionId) {
+    await this.lazyInit();
+    if (prefs.data[extensionId]) {
+      delete prefs.data[extensionId];
+      prefs.saveSoon();
+    }
+  }
+
+  async uninitForTest() {
+    if (!this._initPromise) {
+      return;
+    }
+
+    await this._initPromise;
+    await prefs.finalize();
+    prefs = null;
+    this._initPromise = null;
+  }
+
+  async resetVersionForTest() {
+    throw new Error("Not supported");
+  }
+}
+
 class PermissionStore {
   async _init() {
     const dir = FileUtils.getDir("ProfD", ["extension-store"], true);
     this._store = await KeyValueService.getOrCreate(dir.path, "permissions");
     if (!(await this._store.has(VERSION_KEY))) {
       await this.maybeMigrateData();
     }
   }
@@ -156,22 +234,32 @@ class PermissionStore {
     return this._store.delete(this.makeKey(extensionId));
   }
 
   async resetVersionForTest() {
     await this.lazyInit();
     return this._store.delete(VERSION_KEY);
   }
 
-  get initPromiseForTest() {
+  async uninitForTest() {
+    // Nothing special to do to unitialize, let's just
+    // make sure we're not in the middle of initialization
     return this._initPromise;
   }
 }
 
-let store = new PermissionStore();
+// Bug 1646182: turn on rkv on all channels
+function createStore(useRkv = AppConstants.NIGHTLY_BUILD) {
+  if (useRkv) {
+    return new PermissionStore();
+  }
+  return new LegacyPermissionStore();
+}
+
+let store = createStore();
 
 var ExtensionPermissions = {
   async _update(extensionId, perms) {
     await store.put(extensionId, perms);
     return StartupCache.permissions.set(extensionId, perms);
   },
 
   async _get(extensionId) {
@@ -292,14 +380,16 @@ var ExtensionPermissions = {
   },
 
   // This is meant for tests only
   async _resetVersion() {
     await store.resetVersionForTest();
   },
 
   // This is meant for tests only
+  _useLegacyStorageBackend: false,
+
+  // This is meant for tests only
   async _uninit() {
-    // Make sure the store is not in the middle of initializing itself
-    await store.initPromiseForTest;
-    store = new PermissionStore();
+    await store.uninitForTest();
+    store = createStore(!this._useLegacyStorageBackend);
   },
 };
--- a/toolkit/components/extensions/moz.build
+++ b/toolkit/components/extensions/moz.build
@@ -105,16 +105,17 @@ BROWSER_CHROME_MANIFESTS += [
 MOCHITEST_MANIFESTS += [
     'test/mochitest/mochitest-remote.ini',
     'test/mochitest/mochitest.ini'
 ]
 MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
 XPCSHELL_TESTS_MANIFESTS += [
     'test/xpcshell/native_messaging.ini',
     'test/xpcshell/xpcshell-e10s.ini',
+    'test/xpcshell/xpcshell-legacy-ep.ini',
     'test/xpcshell/xpcshell-remote.ini',
     'test/xpcshell/xpcshell.ini',
 ]
 
 SPHINX_TREES['webextensions'] = 'docs'
 
 with Files('docs/**'):
     SCHEDULES.exclusive = ['docs']
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/head_legacy_ep.js
@@ -0,0 +1,13 @@
+"use strict";
+
+// Bug 1646182: Test the legacy ExtensionPermission backend until we fully
+// migrate to rkv
+
+{
+  const { ExtensionPermissions } = ChromeUtils.import(
+    "resource://gre/modules/ExtensionPermissions.jsm"
+  );
+
+  ExtensionPermissions._useLegacyStorageBackend = true;
+  ExtensionPermissions._uninit();
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-legacy-ep.ini
@@ -0,0 +1,23 @@
+[DEFAULT]
+head = head.js head_remote.js head_e10s.js head_legacy_ep.js
+tail =
+firefox-appdir = browser
+skip-if = appname == "thunderbird" || os == "android"
+dupe-manifest =
+
+# services.settings.server/default_bucket:
+# Make sure that loading the default settings for url-classifier-skip-urls
+# doesn't interfere with running our tests while IDB operations are in
+# flight by overriding the default remote settings bucket pref name to
+# ensure that the IDB database isn't created in the first place.
+prefs =
+  services.settings.server=http://localhost:7777/remote-settings-dummy/v1
+  services.settings.default_bucket=nonexistent-bucket-foo
+
+# Bug 1646182: Test the legacy ExtensionPermission backend until we fully
+# migrate to rkv
+[test_ext_permissions.js]
+[test_ext_permissions_api.js]
+[test_ext_permissions_migrate.js]
+[test_ext_permissions_uninstall.js]
+[test_ext_proxy_config.js]