Backed out 3 changesets (bug 1531303) for causing close_window/close.py and browser_permissions_dialog.js to perma fail CLOSED TREE
authorCiure Andrei <aciure@mozilla.com>
Wed, 14 Aug 2019 13:07:55 +0300
changeset 487883 b03aef80e76a8feb6ab77cd89a6b8f901459e563
parent 487882 0cb31b4bc6f4d5a06b21441c500fe5bf31c976b7
child 487884 7d82341d122dce7610e8e550f43380e773550f9e
push id92513
push useraciure@mozilla.com
push dateWed, 14 Aug 2019 10:08:27 +0000
treeherderautoland@b03aef80e76a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1531303
milestone70.0a1
backs out87305e83174e205342c765ad4750e6e26879a3b8
0c75c3bac00be2683556c9dc5cde2e6426335c48
865c2a5d40daeeffd9c0a29782b680588299b70f
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
Backed out 3 changesets (bug 1531303) for causing close_window/close.py and browser_permissions_dialog.js to perma fail CLOSED TREE Backed out changeset 87305e83174e (bug 1531303) Backed out changeset 0c75c3bac00b (bug 1531303) Backed out changeset 865c2a5d40da (bug 1531303)
browser/base/content/test/alerts/browser_notification_close.js
browser/base/content/test/alerts/browser_notification_remove_permission.js
browser/base/content/test/alerts/browser_notification_tab_switching.js
browser/base/content/test/general/browser_bug578534.js
browser/base/content/test/general/browser_remoteTroubleshoot.js
browser/base/content/test/pageinfo/browser_pageinfo_permissions.js
browser/base/content/test/permissions/browser_autoplay_blocked.js
browser/base/content/test/permissions/browser_permissions.js
browser/base/content/test/permissions/browser_permissions_event_telemetry.js
browser/base/content/test/permissions/browser_permissions_postPrompt.js
browser/base/content/test/permissions/browser_temporary_permissions.js
browser/base/content/test/permissions/browser_temporary_permissions_expiry.js
browser/base/content/test/permissions/browser_temporary_permissions_navigation.js
browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
browser/base/content/test/permissions/head.js
browser/base/content/test/popups/browser_popup_blocker_identity_block.js
browser/base/content/test/sanitize/browser_cookiePermission_aboutURL.js
browser/base/content/test/sanitize/browser_cookiePermission_subDomains.js
browser/base/content/test/sanitize/browser_sanitize-sitepermissions.js
browser/base/content/test/sanitize/head.js
browser/base/content/test/siteIdentity/browser_geolocation_indicator.js
browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
browser/base/content/test/webextensions/browser_permissions_unsigned.js
browser/base/content/test/webextensions/head.js
browser/base/content/test/webrtc/browser_devices_get_user_media.js
browser/base/content/test/webrtc/browser_devices_get_user_media_default_permissions.js
browser/base/content/test/webrtc/browser_devices_get_user_media_in_frame.js
browser/base/content/test/webrtc/browser_devices_get_user_media_queue_request.js
browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js
browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access.js
browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_in_frame.js
browser/base/content/test/webrtc/head.js
browser/components/enterprisepolicies/tests/xpcshell/head.js
browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js
browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons_flash.js
browser/components/originattributes/test/browser/browser_permissions.js
browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
browser/components/preferences/in-content/tests/browser_permissions_dialog.js
browser/components/preferences/in-content/tests/head.js
browser/components/preferences/in-content/tests/siteData/browser_clearSiteData.js
browser/components/translation/test/browser_translation_exceptions.js
browser/components/uitour/test/browser_no_tabs.js
browser/components/uitour/test/head.js
browser/modules/test/browser/browser_PermissionUI.js
browser/modules/test/browser/browser_PermissionUI_prompts.js
browser/modules/test/unit/test_SiteDataManager.js
dom/indexedDB/test/unit/test_idle_maintenance.js
dom/indexedDB/test/unit/test_storageOption_pref.js
dom/notification/test/browser/browser_permission_dismiss.js
dom/push/test/xpcshell/head.js
dom/push/test/xpcshell/test_drop_expired.js
dom/push/test/xpcshell/test_quota_observer.js
dom/push/test/xpcshell/test_record.js
dom/serviceworkers/test/browser_storage_permission.js
extensions/permissions/moz.build
extensions/permissions/test/PermissionTestUtils.jsm
netwerk/cookie/test/browser/head.js
netwerk/test/unit/test_bug767025.js
netwerk/test/unit/test_pinned_app_cache.js
toolkit/components/antitracking/test/browser/browser_allowListSeparationInPrivateAndNormalWindows.js
toolkit/components/antitracking/test/browser/browser_allowPermissionForTracker.js
toolkit/components/antitracking/test/browser/browser_denyPermissionForTracker.js
toolkit/components/antitracking/test/browser/browser_permissionInNormalWindows.js
toolkit/components/antitracking/test/browser/browser_permissionInPrivateWindows.js
toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
toolkit/components/antitracking/test/browser/browser_userInteraction.js
toolkit/components/antitracking/test/browser/head.js
toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
toolkit/components/telemetry/tests/browser/browser_HybridContentTelemetry.js
toolkit/content/tests/browser/browser_autoplay_policy_request_permission.js
toolkit/content/tests/browser/browser_autoplay_policy_webRTC_permission.js
toolkit/content/tests/browser/browser_autoplay_policy_web_audio.js
toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
toolkit/modules/tests/xpcshell/test_web_channel.js
toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js
toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js
toolkit/mozapps/extensions/test/xpinstall/browser_auth.js
toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js
toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js
toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js
toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js
toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js
toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js
toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js
toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js
toolkit/mozapps/extensions/test/xpinstall/browser_containers.js
toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js
toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js
toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js
toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js
toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js
toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js
toolkit/mozapps/extensions/test/xpinstall/browser_doorhanger_installs.js
toolkit/mozapps/extensions/test/xpinstall/browser_empty.js
toolkit/mozapps/extensions/test/xpinstall/browser_hash.js
toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js
toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js
toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js
toolkit/mozapps/extensions/test/xpinstall/browser_newwindow.js
toolkit/mozapps/extensions/test/xpinstall/browser_offline.js
toolkit/mozapps/extensions/test/xpinstall/browser_privatebrowsing.js
toolkit/mozapps/extensions/test/xpinstall/browser_relative.js
toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js
toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js
toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js
toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js
toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js
toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js
toolkit/mozapps/extensions/test/xpinstall/head.js
--- a/browser/base/content/test/alerts/browser_notification_close.js
+++ b/browser/base/content/test/alerts/browser_notification_close.js
@@ -1,18 +1,14 @@
 "use strict";
 
 const { PlacesTestUtils } = ChromeUtils.import(
   "resource://testing-common/PlacesTestUtils.jsm"
 );
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 let notificationURL =
   "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 let oldShowFavicons;
 
 add_task(async function test_notificationClose() {
   let notificationURI = makeURI(notificationURL);
   await addNotificationPermission(notificationURL);
 
@@ -96,13 +92,13 @@ add_task(async function test_notificatio
           ", actually closed at " +
           currentTime
       );
     }
   );
 });
 
 add_task(async function cleanup() {
-  PermissionTestUtils.remove(notificationURL, "desktop-notification");
+  Services.perms.remove(makeURI(notificationURL), "desktop-notification");
   if (typeof oldShowFavicons == "boolean") {
     Services.prefs.setBoolPref("alerts.showFavicons", oldShowFavicons);
   }
 });
--- a/browser/base/content/test/alerts/browser_notification_remove_permission.js
+++ b/browser/base/content/test/alerts/browser_notification_remove_permission.js
@@ -1,14 +1,10 @@
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 var tab;
 var notificationURL =
   "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 var alertWindowClosed = false;
 var permRemoved = false;
 
 function test() {
   waitForExplicitFinish();
@@ -34,18 +30,18 @@ function onAlertShowing() {
 
   let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
   if (!alertWindow) {
     ok(true, "Notifications don't use XUL windows on all platforms.");
     closeNotification(tab.linkedBrowser).then(finish);
     return;
   }
   ok(
-    PermissionTestUtils.testExactPermission(
-      notificationURL,
+    Services.perms.testExactPermission(
+      makeURI(notificationURL),
       "desktop-notification"
     ),
     "Permission should exist prior to removal"
   );
   let disableForOriginMenuItem = alertWindow.document.getElementById(
     "disableForOriginMenuItem"
   );
   is(disableForOriginMenuItem.localName, "menuitem", "menuitem found");
--- a/browser/base/content/test/alerts/browser_notification_tab_switching.js
+++ b/browser/base/content/test/alerts/browser_notification_tab_switching.js
@@ -1,18 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 var tab;
 var notification;
 var notificationURL =
   "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 var newWindowOpenedFromTab;
 
 add_task(async function test_notificationPreventDefaultAndSwitchTabs() {
   await addNotificationPermission(notificationURL);
@@ -103,10 +99,10 @@ add_task(async function test_notificatio
       notificationClosed = promiseNotificationEvent("close");
       await closeNotification(aBrowser);
       await notificationClosed;
     }
   );
 });
 
 add_task(async function cleanup() {
-  PermissionTestUtils.remove(notificationURL, "desktop-notification");
+  Services.perms.remove(makeURI(notificationURL), "desktop-notification");
 });
--- a/browser/base/content/test/general/browser_bug578534.js
+++ b/browser/base/content/test/general/browser_bug578534.js
@@ -1,30 +1,27 @@
 /* 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/. */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 add_task(async function test() {
   let uriString = "http://example.com/";
   let cookieBehavior = "network.cookie.cookieBehavior";
+  let uriObj = Services.io.newURI(uriString);
 
   await SpecialPowers.pushPrefEnv({ set: [[cookieBehavior, 2]] });
-  PermissionTestUtils.add(uriString, "cookie", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uriObj, "cookie", Services.perms.ALLOW_ACTION);
 
   await BrowserTestUtils.withNewTab(
     { gBrowser, url: uriString },
     async function(browser) {
       await ContentTask.spawn(browser, null, function() {
         is(
           content.navigator.cookieEnabled,
           true,
           "navigator.cookieEnabled should be true"
         );
       });
     }
   );
 
-  PermissionTestUtils.add(uriString, "cookie", Services.perms.UNKNOWN_ACTION);
+  Services.perms.add(uriObj, "cookie", Services.perms.UNKNOWN_ACTION);
 });
--- a/browser/base/content/test/general/browser_remoteTroubleshoot.js
+++ b/browser/base/content/test/general/browser_remoteTroubleshoot.js
@@ -1,18 +1,15 @@
 /* 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/. */
 
 var { WebChannel } = ChromeUtils.import(
   "resource://gre/modules/WebChannel.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const TEST_URL_TAIL =
   "example.com/browser/browser/base/content/test/general/test_remoteTroubleshoot.html";
 const TEST_URI_GOOD = Services.io.newURI("https://" + TEST_URL_TAIL);
 const TEST_URI_BAD = Services.io.newURI("http://" + TEST_URL_TAIL);
 const TEST_URI_GOOD_OBJECT = Services.io.newURI(
   "https://" + TEST_URL_TAIL + "?object"
 );
@@ -52,23 +49,23 @@ add_task(async function() {
   let got = await promiseNewChannelResponse(TEST_URI_GOOD);
   // Should return an error.
   Assert.ok(
     got.message.errno === 2,
     "should have failed with errno 2, no such channel"
   );
 
   // Add a permission manager entry for our URI.
-  PermissionTestUtils.add(
+  Services.perms.add(
     TEST_URI_GOOD,
     "remote-troubleshooting",
     Services.perms.ALLOW_ACTION
   );
   registerCleanupFunction(() => {
-    PermissionTestUtils.remove(TEST_URI_GOOD, "remote-troubleshooting");
+    Services.perms.remove(TEST_URI_GOOD, "remote-troubleshooting");
   });
 
   // Try again - now we are expecting a response with the actual data.
   got = await promiseNewChannelResponse(TEST_URI_GOOD);
 
   // Check some keys we expect to always get.
   Assert.ok(got.message.extensions, "should have extensions");
   Assert.ok(got.message.graphics, "should have graphics");
--- a/browser/base/content/test/pageinfo/browser_pageinfo_permissions.js
+++ b/browser/base/content/test/pageinfo/browser_pageinfo_permissions.js
@@ -1,14 +1,11 @@
 const { SitePermissions } = ChromeUtils.import(
   "resource:///modules/SitePermissions.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const TEST_ORIGIN = "https://example.com";
 const TEST_ORIGIN_CERT_ERROR = "https://expired.example.com";
 const LOW_TLS_VERSION = "https://tls1.example.com/";
 
 async function testPermissions(defaultPermission) {
   await BrowserTestUtils.withNewTab(TEST_ORIGIN, async function(browser) {
     let pageInfo = BrowserPageInfo(TEST_ORIGIN, "permTab");
@@ -20,66 +17,64 @@ async function testPermissions(defaultPe
     let radioGroup = pageInfo.document.getElementById("geoRadioGroup");
     let defaultRadioButton = pageInfo.document.getElementById(
       "geo#" + defaultPermission
     );
     let blockRadioButton = pageInfo.document.getElementById("geo#2");
 
     ok(defaultCheckbox.checked, "The default checkbox should be checked.");
 
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "geo",
-      Services.perms.DENY_ACTION
-    );
+    SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.BLOCK);
 
     ok(!defaultCheckbox.checked, "The default checkbox should not be checked.");
 
     defaultCheckbox.checked = true;
     defaultCheckbox.dispatchEvent(new Event("command"));
 
-    ok(
-      !PermissionTestUtils.getPermissionObject(gBrowser.currentURI, "geo"),
+    is(
+      SitePermissions.get(gBrowser.currentURI, "geo").state,
+      defaultPermission,
       "Checking the default checkbox should reset the permission."
     );
 
     defaultCheckbox.checked = false;
     defaultCheckbox.dispatchEvent(new Event("command"));
 
-    ok(
-      !PermissionTestUtils.getPermissionObject(gBrowser.currentURI, "geo"),
+    is(
+      SitePermissions.get(gBrowser.currentURI, "geo").state,
+      defaultPermission,
       "Unchecking the default checkbox should pick the default permission."
     );
     is(
       radioGroup.selectedItem,
       defaultRadioButton,
       "The unknown radio button should be selected."
     );
 
     radioGroup.selectedItem = blockRadioButton;
     blockRadioButton.dispatchEvent(new Event("command"));
 
     is(
-      PermissionTestUtils.getPermissionObject(gBrowser.currentURI, "geo")
-        .capability,
-      Services.perms.DENY_ACTION,
+      SitePermissions.get(gBrowser.currentURI, "geo").state,
+      SitePermissions.BLOCK,
       "Selecting a value in the radio group should set the corresponding permission"
     );
 
     radioGroup.selectedItem = defaultRadioButton;
     defaultRadioButton.dispatchEvent(new Event("command"));
 
-    ok(
-      !PermissionTestUtils.getPermissionObject(gBrowser.currentURI, "geo"),
+    is(
+      SitePermissions.get(gBrowser.currentURI, "geo").state,
+      defaultPermission,
       "Selecting the default value should reset the permission."
     );
     ok(defaultCheckbox.checked, "The default checkbox should be checked.");
 
     pageInfo.close();
-    PermissionTestUtils.remove(gBrowser.currentURI, "geo");
+    SitePermissions.remove(gBrowser.currentURI, "geo");
   });
 }
 
 // Test displaying website permissions on certificate error pages.
 add_task(async function test_CertificateError() {
   let browser;
   let pageLoaded;
   await BrowserTestUtils.openNewForegroundTab(
@@ -178,26 +173,26 @@ add_task(async function test_NetworkErro
   );
 
   pageInfo.close();
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 // Test some standard operations in the permission tab.
 add_task(async function test_geo_permission() {
-  await testPermissions(Services.perms.UNKNOWN_ACTION);
+  await testPermissions(SitePermissions.UNKNOWN);
 });
 
 // Test some standard operations in the permission tab, falling back to a custom
 // default permission instead of UNKNOWN.
 add_task(async function test_default_geo_permission() {
   await SpecialPowers.pushPrefEnv({
     set: [["permissions.default.geo", SitePermissions.ALLOW]],
   });
-  await testPermissions(Services.perms.ALLOW_ACTION);
+  await testPermissions(SitePermissions.ALLOW);
 });
 
 // Test special behavior for cookie permissions.
 add_task(async function test_cookie_permission() {
   await BrowserTestUtils.withNewTab(TEST_ORIGIN, async function(browser) {
     let pageInfo = BrowserPageInfo(TEST_ORIGIN, "permTab");
     await BrowserTestUtils.waitForEvent(pageInfo, "load");
 
@@ -209,55 +204,55 @@ add_task(async function test_cookie_perm
     let blockRadioButton = pageInfo.document.getElementById("cookie#2");
 
     ok(defaultCheckbox.checked, "The default checkbox should be checked.");
 
     defaultCheckbox.checked = false;
     defaultCheckbox.dispatchEvent(new Event("command"));
 
     is(
-      PermissionTestUtils.testPermission(gBrowser.currentURI, "cookie"),
+      Services.perms.testPermission(gBrowser.currentURI, "cookie"),
       SitePermissions.ALLOW,
       "Unchecking the default checkbox should pick the default permission."
     );
     is(
       radioGroup.selectedItem,
       allowRadioButton,
       "The unknown radio button should be selected."
     );
 
     radioGroup.selectedItem = blockRadioButton;
     blockRadioButton.dispatchEvent(new Event("command"));
 
     is(
-      PermissionTestUtils.testPermission(gBrowser.currentURI, "cookie"),
+      Services.perms.testPermission(gBrowser.currentURI, "cookie"),
       SitePermissions.BLOCK,
       "Selecting a value in the radio group should set the corresponding permission"
     );
 
     radioGroup.selectedItem = allowRadioButton;
     allowRadioButton.dispatchEvent(new Event("command"));
 
     is(
-      PermissionTestUtils.testPermission(gBrowser.currentURI, "cookie"),
+      Services.perms.testPermission(gBrowser.currentURI, "cookie"),
       SitePermissions.ALLOW,
       "Selecting a value in the radio group should set the corresponding permission"
     );
     ok(!defaultCheckbox.checked, "The default checkbox should not be checked.");
 
     defaultCheckbox.checked = true;
     defaultCheckbox.dispatchEvent(new Event("command"));
 
     is(
-      PermissionTestUtils.testPermission(gBrowser.currentURI, "cookie"),
+      Services.perms.testPermission(gBrowser.currentURI, "cookie"),
       SitePermissions.UNKNOWN,
       "Checking the default checkbox should reset the permission."
     );
     is(
       radioGroup.selectedItem,
       null,
       "For cookies, no item should be selected when the checkbox is checked."
     );
 
     pageInfo.close();
-    PermissionTestUtils.remove(gBrowser.currentURI, "cookie");
+    SitePermissions.remove(gBrowser.currentURI, "cookie");
   });
 });
--- a/browser/base/content/test/permissions/browser_autoplay_blocked.js
+++ b/browser/base/content/test/permissions/browser_autoplay_blocked.js
@@ -1,16 +1,12 @@
 /*
  * Test that a blocked request to autoplay media is shown to the user
  */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const AUTOPLAY_PAGE =
   getRootDirectory(gTestPath).replace(
     "chrome://mochitests/content",
     "https://example.com"
   ) + "browser_autoplay_blocked.html";
 
 const SLOW_AUTOPLAY_PAGE =
   getRootDirectory(gTestPath).replace(
@@ -137,71 +133,47 @@ add_task(async function testMainViewVisi
     let menuitem = menulist.getElementsByTagName("menuitem")[0];
     Assert.equal(menuitem.getAttribute("label"), "Allow Audio and Video");
 
     menuitem.click();
     menulist.menupopup.hidePopup();
     await closeIdentityPopup();
 
     let uri = Services.io.newURI(AUTOPLAY_PAGE);
-    let state = PermissionTestUtils.getPermissionObject(uri, AUTOPLAY_PERM)
-      .capability;
-    Assert.equal(state, Services.perms.ALLOW_ACTION);
+    let state = SitePermissions.get(uri, AUTOPLAY_PERM).state;
+    Assert.equal(state, SitePermissions.ALLOW);
   });
 
   Services.perms.removeAll();
 });
 
 add_task(async function testGloballyBlockedOnNewWindow() {
   Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED);
 
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    AUTOPLAY_PAGE
-  );
+  let uri = Services.io.newURI(AUTOPLAY_PAGE);
 
-  let tab = await BrowserTestUtils.openNewForegroundTab(
-    gBrowser,
-    AUTOPLAY_PAGE
-  );
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri.spec);
   await blockedIconShown();
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(
-      principal,
-      AUTOPLAY_PERM,
-      tab.linkedBrowser
-    ),
-    {
-      state: SitePermissions.BLOCK,
-      scope: SitePermissions.SCOPE_PERSISTENT,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, AUTOPLAY_PERM, tab.linkedBrowser), {
+    state: SitePermissions.BLOCK,
+    scope: SitePermissions.SCOPE_PERSISTENT,
+  });
 
   let promiseWin = BrowserTestUtils.waitForNewWindow();
   gBrowser.replaceTabWithWindow(tab);
   let win = await promiseWin;
   tab = win.gBrowser.selectedTab;
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(
-      principal,
-      AUTOPLAY_PERM,
-      tab.linkedBrowser
-    ),
-    {
-      state: SitePermissions.BLOCK,
-      scope: SitePermissions.SCOPE_PERSISTENT,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, AUTOPLAY_PERM, tab.linkedBrowser), {
+    state: SitePermissions.BLOCK,
+    scope: SitePermissions.SCOPE_PERSISTENT,
+  });
 
-  SitePermissions.removeFromPrincipal(
-    principal,
-    AUTOPLAY_PERM,
-    tab.linkedBrowser
-  );
+  SitePermissions.remove(uri, AUTOPLAY_PERM, tab.linkedBrowser);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testBFCache() {
   Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED);
 
   await BrowserTestUtils.withNewTab("about:home", async function(browser) {
     await BrowserTestUtils.loadURI(browser, AUTOPLAY_PAGE);
--- a/browser/base/content/test/permissions/browser_permissions.js
+++ b/browser/base/content/test/permissions/browser_permissions.js
@@ -1,16 +1,12 @@
 /*
  * Test the Permissions section in the Control Center.
  */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const PERMISSIONS_PAGE =
   getRootDirectory(gTestPath).replace(
     "chrome://mochitests/content",
     "https://example.com"
   ) + "permissions.html";
 const kStrictKeyPressEvents = SpecialPowers.getBoolPref(
   "dom.keyboardevent.keypress.dispatch_non_printable_keys_only_system_group_in_content"
 );
@@ -41,21 +37,17 @@ add_task(async function testMainViewVisi
     let emptyLabel = permissionsList.nextElementSibling.nextElementSibling;
 
     await openIdentityPopup();
 
     ok(!BrowserTestUtils.is_hidden(emptyLabel), "List of permissions is empty");
 
     await closeIdentityPopup();
 
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "camera",
-      Services.perms.ALLOW_ACTION
-    );
+    SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.ALLOW);
 
     await openIdentityPopup();
 
     ok(
       BrowserTestUtils.is_hidden(emptyLabel),
       "List of permissions is not empty"
     );
 
@@ -69,91 +61,75 @@ add_task(async function testMainViewVisi
     let img = permissionsList.querySelector(
       "image.identity-popup-permission-icon"
     );
     ok(img, "There is an image for the permissions");
     ok(img.classList.contains("camera-icon"), "proper class is in image class");
 
     await closeIdentityPopup();
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "camera");
+    SitePermissions.remove(gBrowser.currentURI, "camera");
 
     await openIdentityPopup();
 
     ok(!BrowserTestUtils.is_hidden(emptyLabel), "List of permissions is empty");
 
     await closeIdentityPopup();
   });
 });
 
 add_task(async function testIdentityIcon() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, function() {
-    PermissionTestUtils.add(
+    SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
+
+    ok(
+      gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
+      "identity-box signals granted permissions"
+    );
+
+    SitePermissions.remove(gBrowser.currentURI, "geo");
+
+    ok(
+      !gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
+      "identity-box doesn't signal granted permissions"
+    );
+
+    SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.BLOCK);
+
+    ok(
+      !gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
+      "identity-box doesn't signal granted permissions"
+    );
+
+    SitePermissions.set(
       gBrowser.currentURI,
-      "geo",
-      Services.perms.ALLOW_ACTION
+      "cookie",
+      SitePermissions.ALLOW_COOKIES_FOR_SESSION
     );
 
     ok(
       gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
       "identity-box signals granted permissions"
     );
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "geo");
-
-    ok(
-      !gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
-      "identity-box doesn't signal granted permissions"
-    );
-
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "camera",
-      Services.perms.DENY_ACTION
-    );
-
-    ok(
-      !gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
-      "identity-box doesn't signal granted permissions"
-    );
-
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "cookie",
-      Ci.nsICookiePermission.ACCESS_SESSION
-    );
-
-    ok(
-      gIdentityHandler._identityBox.classList.contains("grantedPermissions"),
-      "identity-box signals granted permissions"
-    );
-
-    PermissionTestUtils.remove(gBrowser.currentURI, "geo");
-    PermissionTestUtils.remove(gBrowser.currentURI, "camera");
-    PermissionTestUtils.remove(gBrowser.currentURI, "cookie");
+    SitePermissions.remove(gBrowser.currentURI, "geo");
+    SitePermissions.remove(gBrowser.currentURI, "camera");
+    SitePermissions.remove(gBrowser.currentURI, "cookie");
   });
 });
 
 add_task(async function testCancelPermission() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function() {
     let permissionsList = document.getElementById(
       "identity-popup-permission-list"
     );
     let emptyLabel = permissionsList.nextElementSibling.nextElementSibling;
 
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "geo",
-      Services.perms.ALLOW_ACTION
-    );
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "camera",
-      Services.perms.DENY_ACTION
-    );
+    SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
+    SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.BLOCK);
 
     await openIdentityPopup();
 
     ok(
       BrowserTestUtils.is_hidden(emptyLabel),
       "List of permissions is not empty"
     );
 
@@ -197,36 +173,28 @@ add_task(async function testPermissionHi
 
     await openIdentityPopup();
 
     ok(!BrowserTestUtils.is_hidden(emptyHint), "Empty hint is visible");
     ok(BrowserTestUtils.is_hidden(reloadHint), "Reload hint is hidden");
 
     await closeIdentityPopup();
 
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "geo",
-      Services.perms.ALLOW_ACTION
-    );
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "camera",
-      Services.perms.DENY_ACTION
-    );
+    SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.ALLOW);
+    SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.BLOCK);
 
     await openIdentityPopup();
 
     ok(BrowserTestUtils.is_hidden(emptyHint), "Empty hint is hidden");
     ok(BrowserTestUtils.is_hidden(reloadHint), "Reload hint is hidden");
 
     let cancelButtons = permissionsList.querySelectorAll(
       ".identity-popup-permission-remove-button"
     );
-    PermissionTestUtils.remove(gBrowser.currentURI, "camera");
+    SitePermissions.remove(gBrowser.currentURI, "camera");
 
     cancelButtons[0].click();
     ok(BrowserTestUtils.is_hidden(emptyHint), "Empty hint is hidden");
     ok(!BrowserTestUtils.is_hidden(reloadHint), "Reload hint is visible");
 
     cancelButtons[1].click();
     ok(BrowserTestUtils.is_hidden(emptyHint), "Empty hint is hidden");
     ok(!BrowserTestUtils.is_hidden(reloadHint), "Reload hint is visible");
@@ -247,48 +215,40 @@ add_task(async function testPermissionHi
     );
 
     await closeIdentityPopup();
   });
 });
 
 add_task(async function testPermissionIcons() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, function() {
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "camera",
-      Services.perms.ALLOW_ACTION
-    );
-    PermissionTestUtils.add(
-      gBrowser.currentURI,
-      "geo",
-      Services.perms.DENY_ACTION
-    );
+    SitePermissions.set(gBrowser.currentURI, "camera", SitePermissions.ALLOW);
+    SitePermissions.set(gBrowser.currentURI, "geo", SitePermissions.BLOCK);
 
     let geoIcon = gIdentityHandler._identityBox.querySelector(
       ".blocked-permission-icon[data-permission-id='geo']"
     );
     ok(geoIcon.hasAttribute("showing"), "blocked permission icon is shown");
 
     let cameraIcon = gIdentityHandler._identityBox.querySelector(
       ".blocked-permission-icon[data-permission-id='camera']"
     );
     ok(
       !cameraIcon.hasAttribute("showing"),
       "allowed permission icon is not shown"
     );
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "geo");
+    SitePermissions.remove(gBrowser.currentURI, "geo");
 
     ok(
       !geoIcon.hasAttribute("showing"),
       "blocked permission icon is not shown after reset"
     );
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "camera");
+    SitePermissions.remove(gBrowser.currentURI, "camera");
   });
 });
 
 add_task(async function testPermissionShortcuts() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(browser) {
     browser.focus();
 
     await new Promise(r => {
@@ -323,72 +283,72 @@ add_task(async function testPermissionSh
           expectedValue,
           "keypress event should be fired even for shortcut key, " + desc
         );
       }
     }
 
     await tryKey("pressed with default permissions", 1);
 
-    PermissionTestUtils.add(
+    SitePermissions.set(
       gBrowser.currentURI,
       "shortcuts",
-      Services.perms.DENY_ACTION
+      SitePermissions.BLOCK
     );
     await tryKey("pressed when site blocked", 1);
 
-    PermissionTestUtils.add(
+    SitePermissions.set(
       gBrowser.currentURI,
       "shortcuts",
-      PermissionTestUtils.ALLOW
+      SitePermissions.ALLOW
     );
     await tryKey("pressed when site allowed", 2);
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "shortcuts");
+    SitePermissions.remove(gBrowser.currentURI, "shortcuts");
     await new Promise(r => {
       SpecialPowers.pushPrefEnv(
         { set: [["permissions.default.shortcuts", 2]] },
         r
       );
     });
 
     await tryKey("pressed when globally blocked", 2);
-    PermissionTestUtils.add(
+    SitePermissions.set(
       gBrowser.currentURI,
       "shortcuts",
-      Services.perms.ALLOW_ACTION
+      SitePermissions.ALLOW
     );
     await tryKey("pressed when globally blocked but site allowed", 3);
 
-    PermissionTestUtils.add(
+    SitePermissions.set(
       gBrowser.currentURI,
       "shortcuts",
-      Services.perms.DENY_ACTION
+      SitePermissions.BLOCK
     );
     await tryKey("pressed when globally blocked and site blocked", 3);
 
-    PermissionTestUtils.remove(gBrowser.currentURI, "shortcuts");
+    SitePermissions.remove(gBrowser.currentURI, "shortcuts");
   });
 });
 
 // Test the control center UI when policy permissions are set.
 add_task(async function testPolicyPermission() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function() {
     await SpecialPowers.pushPrefEnv({
       set: [["dom.disable_open_during_load", true]],
     });
 
     let permissionsList = document.getElementById(
       "identity-popup-permission-list"
     );
-    PermissionTestUtils.add(
+    SitePermissions.set(
       gBrowser.currentURI,
       "popup",
-      Services.perms.ALLOW_ACTION,
-      Services.perms.EXPIRE_POLICY
+      SitePermissions.ALLOW,
+      SitePermissions.SCOPE_POLICY
     );
 
     await openIdentityPopup();
 
     // Check if the icon, nameLabel and stateLabel are visible.
     let img, labelText, labels;
 
     img = permissionsList.querySelector("image.identity-popup-permission-icon");
--- a/browser/base/content/test/permissions/browser_permissions_event_telemetry.js
+++ b/browser/base/content/test/permissions/browser_permissions_event_telemetry.js
@@ -100,25 +100,21 @@ add_task(async function setup() {
   Services.telemetry.canRecordExtended = true;
 
   Services.prefs.setBoolPref("permissions.eventTelemetry.enabled", true);
 
   // Add some example permissions.
   let uri = Services.io.newURI(PERMISSIONS_PAGE);
   let uri2 = Services.io.newURI("https://example.org");
   let uri3 = Services.io.newURI("http://sub.example.org");
-  PermissionTestUtils.add(uri, "geo", Services.perms.ALLOW_ACTION);
-  PermissionTestUtils.add(
-    uri3,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
-  PermissionTestUtils.add(uri2, "microphone", Services.perms.DENY_ACTION);
-  PermissionTestUtils.add(uri, "camera", Services.perms.DENY_ACTION);
-  PermissionTestUtils.add(uri2, "geo", Services.perms.DENY_ACTION);
+  Services.perms.add(uri, "geo", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uri3, "desktop-notification", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uri2, "microphone", Services.perms.DENY_ACTION);
+  Services.perms.add(uri, "camera", Services.perms.DENY_ACTION);
+  Services.perms.add(uri2, "geo", Services.perms.DENY_ACTION);
 
   registerCleanupFunction(() => {
     Services.perms.removeAll();
     Services.prefs.clearUserPref("permissions.eventTelemetry.enabled");
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 
   Services.telemetry.clearEvents();
@@ -131,33 +127,39 @@ add_task(async function testAccept() {
     checkEventTelemetry("show");
 
     let notification = PopupNotifications.panel.firstElementChild;
     EventUtils.synthesizeMouseAtCenter(notification.button, {});
 
     checkEventTelemetry("accept");
 
     Services.telemetry.clearEvents();
-    PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
+    Services.perms.remove(
+      Services.io.newURI(PERMISSIONS_PAGE),
+      "desktop-notification"
+    );
   });
 });
 
 add_task(async function testDeny() {
   await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(browser) {
     await showPermissionPrompt(browser);
 
     checkEventTelemetry("show");
 
     let notification = PopupNotifications.panel.firstElementChild;
     EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
 
     checkEventTelemetry("deny");
 
     Services.telemetry.clearEvents();
-    PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
+    Services.perms.remove(
+      Services.io.newURI(PERMISSIONS_PAGE),
+      "desktop-notification"
+    );
   });
 });
 
 add_task(async function testLeave() {
   let tab = await BrowserTestUtils.openNewForegroundTab(
     gBrowser,
     PERMISSIONS_PAGE
   );
@@ -167,10 +169,13 @@ add_task(async function testLeave() {
 
   let tabClosed = BrowserTestUtils.waitForTabClosing(tab);
   await BrowserTestUtils.removeTab(tab);
   await tabClosed;
 
   checkEventTelemetry("leave");
 
   Services.telemetry.clearEvents();
-  PermissionTestUtils.remove(PERMISSIONS_PAGE, "desktop-notification");
+  Services.perms.remove(
+    Services.io.newURI(PERMISSIONS_PAGE),
+    "desktop-notification"
+  );
 });
--- a/browser/base/content/test/permissions/browser_permissions_postPrompt.js
+++ b/browser/base/content/test/permissions/browser_permissions_postPrompt.js
@@ -36,22 +36,22 @@ function testPostPrompt(task) {
     await popupshown;
 
     ok(true, "Notification permission prompt was shown");
 
     let notification = PopupNotifications.panel.firstElementChild;
     EventUtils.synthesizeMouseAtCenter(notification.button, {});
 
     is(
-      PermissionTestUtils.testPermission(uri, "desktop-notification"),
+      Services.perms.testPermission(uri, "desktop-notification"),
       Ci.nsIPermissionManager.ALLOW_ACTION,
       "User can override the default deny by using the prompt"
     );
 
-    PermissionTestUtils.remove(uri, "desktop-notification");
+    Services.perms.remove(uri, "desktop-notification");
   });
 }
 
 add_task(async function testNotificationPermission() {
   Services.prefs.setBoolPref(
     "dom.webnotifications.requireuserinteraction",
     true
   );
--- a/browser/base/content/test/permissions/browser_temporary_permissions.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions.js
@@ -12,62 +12,56 @@ const PERMISSIONS_PAGE =
   getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
   "permissions.html";
 const SUBFRAME_PAGE =
   getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
   "temporary_permissions_subframe.html";
 
 // Test that setting temp permissions triggers a change in the identity block.
 add_task(async function testTempPermissionChangeEvents() {
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    ORIGIN
-  );
+  let uri = NetUtil.newURI(ORIGIN);
   let id = "geo";
 
-  await BrowserTestUtils.withNewTab(ORIGIN, function(browser) {
-    SitePermissions.setForPrincipal(
-      principal,
+  await BrowserTestUtils.withNewTab(uri.spec, function(browser) {
+    SitePermissions.set(
+      uri,
       id,
       SitePermissions.BLOCK,
       SitePermissions.SCOPE_TEMPORARY,
       browser
     );
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
     let geoIcon = document.querySelector(
       ".blocked-permission-icon[data-permission-id=geo]"
     );
 
     Assert.notEqual(
       geoIcon.getBoundingClientRect().width,
       0,
       "geo anchor should be visible"
     );
 
-    SitePermissions.removeFromPrincipal(principal, id, browser);
+    SitePermissions.remove(uri, id, browser);
 
     Assert.equal(
       geoIcon.getBoundingClientRect().width,
       0,
       "geo anchor should not be visible"
     );
   });
 });
 
 // Test that temp blocked permissions requested by subframes (with a different URI) affect the whole page.
 add_task(async function testTempPermissionSubframes() {
   let uri = NetUtil.newURI(ORIGIN);
-  let principal = Services.scriptSecurityManager.createContentPrincipal(
-    uri,
-    {}
-  );
   let id = "geo";
 
   await BrowserTestUtils.withNewTab(SUBFRAME_PAGE, async function(browser) {
     let popupshown = BrowserTestUtils.waitForEvent(
       PopupNotifications.panel,
       "popupshown"
     );
 
@@ -91,14 +85,14 @@ add_task(async function testTempPermissi
       "popuphidden"
     );
 
     let notification = PopupNotifications.panel.firstElementChild;
     EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
 
     await popuphidden;
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
   });
 });
--- a/browser/base/content/test/permissions/browser_temporary_permissions_expiry.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions_expiry.js
@@ -23,59 +23,51 @@ const TIMEOUT_MS = 500;
 add_task(async function testTempPermissionRequestAfterExpiry() {
   await SpecialPowers.pushPrefEnv({
     set: [
       ["privacy.temporary_permission_expire_time_ms", EXPIRE_TIME_MS],
       ["media.navigator.permission.fake", true],
     ],
   });
 
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    ORIGIN
-  );
+  let uri = NetUtil.newURI(ORIGIN);
   let ids = ["geo", "camera"];
 
   for (let id of ids) {
     await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(
       browser
     ) {
       let blockedIcon = gIdentityHandler._identityBox.querySelector(
         `.blocked-permission-icon[data-permission-id='${id}']`
       );
 
-      SitePermissions.setForPrincipal(
-        principal,
+      SitePermissions.set(
+        uri,
         id,
         SitePermissions.BLOCK,
         SitePermissions.SCOPE_TEMPORARY,
         browser
       );
 
-      Assert.deepEqual(
-        SitePermissions.getForPrincipal(principal, id, browser),
-        {
-          state: SitePermissions.BLOCK,
-          scope: SitePermissions.SCOPE_TEMPORARY,
-        }
-      );
+      Assert.deepEqual(SitePermissions.get(uri, id, browser), {
+        state: SitePermissions.BLOCK,
+        scope: SitePermissions.SCOPE_TEMPORARY,
+      });
 
       ok(
         blockedIcon.hasAttribute("showing"),
         "blocked permission icon is shown"
       );
 
       await new Promise(c => setTimeout(c, TIMEOUT_MS));
 
-      Assert.deepEqual(
-        SitePermissions.getForPrincipal(principal, id, browser),
-        {
-          state: SitePermissions.UNKNOWN,
-          scope: SitePermissions.SCOPE_PERSISTENT,
-        }
-      );
+      Assert.deepEqual(SitePermissions.get(uri, id, browser), {
+        state: SitePermissions.UNKNOWN,
+        scope: SitePermissions.SCOPE_PERSISTENT,
+      });
 
       let popupshown = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
 
       // Request a permission;
       await BrowserTestUtils.synthesizeMouseAtCenter(`#${id}`, {}, browser);
@@ -92,12 +84,12 @@ add_task(async function testTempPermissi
         "popuphidden"
       );
 
       let notification = PopupNotifications.panel.firstElementChild;
       EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
 
       await popuphidden;
 
-      SitePermissions.removeFromPrincipal(principal, id, browser);
+      SitePermissions.remove(uri, id, browser);
     });
   }
 });
--- a/browser/base/content/test/permissions/browser_temporary_permissions_navigation.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions_navigation.js
@@ -1,69 +1,66 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that temporary permissions are removed on user initiated reload only.
 add_task(async function testTempPermissionOnReload() {
-  let origin = "https://example.com/";
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
+  let uri = NetUtil.newURI("https://example.com");
   let id = "geo";
 
-  await BrowserTestUtils.withNewTab(origin, async function(browser) {
+  await BrowserTestUtils.withNewTab(uri.spec, async function(browser) {
     let reloadButton = document.getElementById("reload-button");
 
-    SitePermissions.setForPrincipal(
-      principal,
+    SitePermissions.set(
+      uri,
       id,
       SitePermissions.BLOCK,
       SitePermissions.SCOPE_TEMPORARY,
       browser
     );
 
-    let reloaded = BrowserTestUtils.browserLoaded(browser, false, origin);
+    let reloaded = BrowserTestUtils.browserLoaded(browser, false, uri.spec);
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
     // Reload through the page (should not remove the temp permission).
     await ContentTask.spawn(browser, {}, () =>
       content.document.location.reload()
     );
 
     await reloaded;
     await BrowserTestUtils.waitForCondition(() => {
       return !reloadButton.disabled;
     });
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
-    reloaded = BrowserTestUtils.browserLoaded(browser, false, origin);
+    reloaded = BrowserTestUtils.browserLoaded(browser, false, uri.spec);
 
     // Reload as a user (should remove the temp permission).
     EventUtils.synthesizeMouseAtCenter(reloadButton, {});
 
     await reloaded;
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.UNKNOWN,
       scope: SitePermissions.SCOPE_PERSISTENT,
     });
 
     // Set the permission again.
-    SitePermissions.setForPrincipal(
-      principal,
+    SitePermissions.set(
+      uri,
       id,
       SitePermissions.BLOCK,
       SitePermissions.SCOPE_TEMPORARY,
       browser
     );
 
     // Open the tab context menu.
     let contextMenu = document.getElementById("tabContextMenu");
@@ -77,43 +74,40 @@ add_task(async function testTempPermissi
     EventUtils.synthesizeMouseAtCenter(gBrowser.selectedTab, {
       type: "contextmenu",
       button: 2,
     });
     await popupShownPromise;
 
     let reloadMenuItem = document.getElementById("context_reloadTab");
 
-    reloaded = BrowserTestUtils.browserLoaded(browser, false, origin);
+    reloaded = BrowserTestUtils.browserLoaded(browser, false, uri.spec);
 
     // Reload as a user through the context menu (should remove the temp permission).
     EventUtils.synthesizeMouseAtCenter(reloadMenuItem, {});
 
     await reloaded;
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.UNKNOWN,
       scope: SitePermissions.SCOPE_PERSISTENT,
     });
 
-    SitePermissions.removeFromPrincipal(principal, id, browser);
+    SitePermissions.remove(uri, id, browser);
   });
 });
 
 // Test that temporary permissions are not removed when reloading all tabs.
 add_task(async function testTempPermissionOnReloadAllTabs() {
-  let origin = "https://example.com/";
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
+  let uri = NetUtil.newURI("https://example.com");
   let id = "geo";
 
-  await BrowserTestUtils.withNewTab(origin, async function(browser) {
-    SitePermissions.setForPrincipal(
-      principal,
+  await BrowserTestUtils.withNewTab(uri.spec, async function(browser) {
+    SitePermissions.set(
+      uri,
       id,
       SitePermissions.BLOCK,
       SitePermissions.SCOPE_TEMPORARY,
       browser
     );
 
     // Select all tabs before opening the context menu.
     gBrowser.selectAllTabs();
@@ -138,43 +132,40 @@ add_task(async function testTempPermissi
     let reloaded = Promise.all(
       gBrowser.visibleTabs.map(tab =>
         BrowserTestUtils.browserLoaded(gBrowser.getBrowserForTab(tab))
       )
     );
     EventUtils.synthesizeMouseAtCenter(reloadMenuItem, {});
     await reloaded;
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
-    SitePermissions.removeFromPrincipal(principal, id, browser);
+    SitePermissions.remove(uri, id, browser);
   });
 });
 
 // Test that temporary permissions are persisted through navigation in a tab.
 add_task(async function testTempPermissionOnNavigation() {
-  let origin = "https://example.com/";
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
+  let uri = NetUtil.newURI("https://example.com/");
   let id = "geo";
 
-  await BrowserTestUtils.withNewTab(origin, async function(browser) {
-    SitePermissions.setForPrincipal(
-      principal,
+  await BrowserTestUtils.withNewTab(uri.spec, async function(browser) {
+    SitePermissions.set(
+      uri,
       id,
       SitePermissions.BLOCK,
       SitePermissions.SCOPE_TEMPORARY,
       browser
     );
 
-    Assert.deepEqual(SitePermissions.getForPrincipal(principal, id, browser), {
+    Assert.deepEqual(SitePermissions.get(uri, id, browser), {
       state: SitePermissions.BLOCK,
       scope: SitePermissions.SCOPE_TEMPORARY,
     });
 
     let loaded = BrowserTestUtils.browserLoaded(
       browser,
       false,
       "https://example.org/"
@@ -185,39 +176,33 @@ add_task(async function testTempPermissi
       browser,
       {},
       () => (content.document.location = "https://example.org/")
     );
 
     await loaded;
 
     // The temporary permissions for the current URI should be reset.
-    Assert.deepEqual(
-      SitePermissions.getForPrincipal(browser.contentPrincipal, id, browser),
-      {
-        state: SitePermissions.UNKNOWN,
-        scope: SitePermissions.SCOPE_PERSISTENT,
-      }
-    );
+    Assert.deepEqual(SitePermissions.get(browser.currentURI, id, browser), {
+      state: SitePermissions.UNKNOWN,
+      scope: SitePermissions.SCOPE_PERSISTENT,
+    });
 
-    loaded = BrowserTestUtils.browserLoaded(browser, false, origin);
+    loaded = BrowserTestUtils.browserLoaded(browser, false, uri.spec);
 
     // Navigate to the original domain.
     await ContentTask.spawn(
       browser,
       {},
       () => (content.document.location = "https://example.com/")
     );
 
     await loaded;
 
     // The temporary permissions for the original URI should still exist.
-    Assert.deepEqual(
-      SitePermissions.getForPrincipal(browser.contentPrincipal, id, browser),
-      {
-        state: SitePermissions.BLOCK,
-        scope: SitePermissions.SCOPE_TEMPORARY,
-      }
-    );
+    Assert.deepEqual(SitePermissions.get(browser.currentURI, id, browser), {
+      state: SitePermissions.BLOCK,
+      scope: SitePermissions.SCOPE_TEMPORARY,
+    });
 
-    SitePermissions.removeFromPrincipal(browser.contentPrincipal, id, browser);
+    SitePermissions.remove(uri, id, browser);
   });
 });
--- a/browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
+++ b/browser/base/content/test/permissions/browser_temporary_permissions_tabs.js
@@ -1,90 +1,72 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that temp permissions are persisted through moving tabs to new windows.
 add_task(async function testTempPermissionOnTabMove() {
-  let origin = "https://example.com/";
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
+  let uri = NetUtil.newURI("https://example.com");
   let id = "geo";
 
-  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, origin);
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri.spec);
 
-  SitePermissions.setForPrincipal(
-    principal,
+  SitePermissions.set(
+    uri,
     id,
     SitePermissions.BLOCK,
     SitePermissions.SCOPE_TEMPORARY,
     tab.linkedBrowser
   );
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(principal, id, tab.linkedBrowser),
-    {
-      state: SitePermissions.BLOCK,
-      scope: SitePermissions.SCOPE_TEMPORARY,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, id, tab.linkedBrowser), {
+    state: SitePermissions.BLOCK,
+    scope: SitePermissions.SCOPE_TEMPORARY,
+  });
 
   let promiseWin = BrowserTestUtils.waitForNewWindow();
   gBrowser.replaceTabWithWindow(tab);
   let win = await promiseWin;
   tab = win.gBrowser.selectedTab;
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(principal, id, tab.linkedBrowser),
-    {
-      state: SitePermissions.BLOCK,
-      scope: SitePermissions.SCOPE_TEMPORARY,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, id, tab.linkedBrowser), {
+    state: SitePermissions.BLOCK,
+    scope: SitePermissions.SCOPE_TEMPORARY,
+  });
 
-  SitePermissions.removeFromPrincipal(principal, id, tab.linkedBrowser);
+  SitePermissions.remove(uri, id, tab.linkedBrowser);
   await BrowserTestUtils.closeWindow(win);
 });
 
 // Test that temp permissions don't affect other tabs of the same URI.
 add_task(async function testTempPermissionMultipleTabs() {
-  let origin = "https://example.com/";
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
+  let uri = NetUtil.newURI("https://example.com");
   let id = "geo";
 
-  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, origin);
-  let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, origin);
+  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri.spec);
+  let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, uri.spec);
 
-  SitePermissions.setForPrincipal(
-    principal,
+  SitePermissions.set(
+    uri,
     id,
     SitePermissions.BLOCK,
     SitePermissions.SCOPE_TEMPORARY,
     tab2.linkedBrowser
   );
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(principal, id, tab2.linkedBrowser),
-    {
-      state: SitePermissions.BLOCK,
-      scope: SitePermissions.SCOPE_TEMPORARY,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, id, tab2.linkedBrowser), {
+    state: SitePermissions.BLOCK,
+    scope: SitePermissions.SCOPE_TEMPORARY,
+  });
 
-  Assert.deepEqual(
-    SitePermissions.getForPrincipal(principal, id, tab1.linkedBrowser),
-    {
-      state: SitePermissions.UNKNOWN,
-      scope: SitePermissions.SCOPE_PERSISTENT,
-    }
-  );
+  Assert.deepEqual(SitePermissions.get(uri, id, tab1.linkedBrowser), {
+    state: SitePermissions.UNKNOWN,
+    scope: SitePermissions.SCOPE_PERSISTENT,
+  });
 
   let geoIcon = document.querySelector(
     ".blocked-permission-icon[data-permission-id=geo]"
   );
 
   Assert.notEqual(
     geoIcon.getBoundingClientRect().width,
     0,
@@ -94,12 +76,12 @@ add_task(async function testTempPermissi
   await BrowserTestUtils.switchTab(gBrowser, tab1);
 
   Assert.equal(
     geoIcon.getBoundingClientRect().width,
     0,
     "geo anchor should not be visible"
   );
 
-  SitePermissions.removeFromPrincipal(principal, id, tab2.linkedBrowser);
+  SitePermissions.remove(uri, id, tab2.linkedBrowser);
   BrowserTestUtils.removeTab(tab1);
   BrowserTestUtils.removeTab(tab2);
 });
--- a/browser/base/content/test/permissions/head.js
+++ b/browser/base/content/test/permissions/head.js
@@ -1,4 +1,1 @@
 ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
--- a/browser/base/content/test/popups/browser_popup_blocker_identity_block.js
+++ b/browser/base/content/test/popups/browser_popup_blocker_identity_block.js
@@ -2,30 +2,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/. */
 
 const { SitePermissions } = ChromeUtils.import(
   "resource:///modules/SitePermissions.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const baseURL = getRootDirectory(gTestPath).replace(
   "chrome://mochitests/content",
   "http://example.com"
 );
 const URL = baseURL + "popup_blocker2.html";
 const URI = Services.io.newURI(URL);
-const PRINCIPAL = Services.scriptSecurityManager.createContentPrincipal(
-  URI,
-  {}
-);
 
 function openIdentityPopup() {
   let promise = BrowserTestUtils.waitForEvent(
     gIdentityHandler._identityPopup,
     "popupshown"
   );
   gIdentityHandler._identityBox.click();
   return promise;
@@ -137,18 +130,17 @@ add_task(async function check_popup_show
   gBrowser.removeTab(tab);
 });
 
 // Test if changing menulist values of blocked popup indicator changes permission state and popup behavior.
 add_task(async function check_permission_state_change() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
 
   // Initially the permission state is BLOCK for popups (set by the prefs).
-  let state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser)
-    .state;
+  let state = SitePermissions.get(URI, "popup", gBrowser).state;
   Assert.equal(state, SitePermissions.BLOCK);
 
   await ContentTask.spawn(gBrowser.selectedBrowser, null, async () => {
     let open = content.document.getElementById("pop");
     open.click();
   });
 
   // Wait for popup block.
@@ -159,17 +151,17 @@ add_task(async function check_permission
   // Open identity popup and change permission state to allow.
   await openIdentityPopup();
   let menulist = document.getElementById("identity-popup-popup-menulist");
   menulist.menupopup.openPopup(); // Open the allow/block menu
   let menuitem = menulist.getElementsByTagName("menuitem")[0];
   menuitem.click();
   await closeIdentityPopup();
 
-  state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser).state;
+  state = SitePermissions.get(URI, "popup", gBrowser).state;
   Assert.equal(state, SitePermissions.ALLOW);
 
   // Store the popup that opens in this array.
   let popup;
   function onTabOpen(event) {
     popup = event.target;
   }
   gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen);
@@ -199,40 +191,40 @@ add_task(async function check_permission
   menulist = document.getElementById("identity-popup-popup-menulist");
   menulist.menupopup.openPopup(); // Open the allow/block menu
   menuitem = menulist.getElementsByTagName("menuitem")[1];
   menuitem.click();
   await closeIdentityPopup();
 
   // Clicking on the "Block" menuitem should remove the permission object(same behavior as UNKNOWN state).
   // We have already confirmed that popups are blocked when the permission state is BLOCK.
-  state = SitePermissions.getForPrincipal(PRINCIPAL, "popup", gBrowser).state;
+  state = SitePermissions.get(URI, "popup", gBrowser).state;
   Assert.equal(state, SitePermissions.BLOCK);
 
   gBrowser.removeTab(tab);
 });
 
 // Explicitly set the permission to the otherwise default state and check that
 // the label still displays correctly.
 add_task(async function check_explicit_default_permission() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
 
   // DENY only works if triggered through Services.perms (it's very edge-casey),
   // since SitePermissions.jsm considers setting default permissions to be removal.
-  PermissionTestUtils.add(URI, "popup", Ci.nsIPermissionManager.DENY_ACTION);
+  Services.perms.add(URI, "popup", Ci.nsIPermissionManager.DENY_ACTION);
 
   await openIdentityPopup();
   let menulist = document.getElementById("identity-popup-popup-menulist");
   Assert.equal(menulist.value, "0");
   Assert.equal(menulist.label, "Block");
   await closeIdentityPopup();
 
-  PermissionTestUtils.add(URI, "popup", Services.perms.ALLOW_ACTION);
+  SitePermissions.set(URI, "popup", SitePermissions.ALLOW);
 
   await openIdentityPopup();
   menulist = document.getElementById("identity-popup-popup-menulist");
   Assert.equal(menulist.value, "1");
   Assert.equal(menulist.label, "Allow");
   await closeIdentityPopup();
 
-  PermissionTestUtils.remove(URI, "popup");
+  SitePermissions.remove(URI, "popup");
   gBrowser.removeTab(tab);
 });
--- a/browser/base/content/test/sanitize/browser_cookiePermission_aboutURL.js
+++ b/browser/base/content/test/sanitize/browser_cookiePermission_aboutURL.js
@@ -1,15 +1,12 @@
 const { Sanitizer } = ChromeUtils.import("resource:///modules/Sanitizer.jsm");
 const { SiteDataTestUtils } = ChromeUtils.import(
   "resource://testing-common/SiteDataTestUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 function checkDataForAboutURL() {
   return new Promise(resolve => {
     let data = true;
     let uri = Services.io.newURI("about:newtab");
     let principal = Services.scriptSecurityManager.createContentPrincipal(
       uri,
       {}
@@ -75,17 +72,17 @@ add_task(async function deleteStorageOnl
     set: [
       ["network.cookie.lifetimePolicy", Ci.nsICookieService.ACCEPT_NORMALLY],
       ["browser.sanitizer.loglevel", "All"],
     ],
   });
 
   // Custom permission without considering OriginAttributes
   let uri = Services.io.newURI("about:newtab");
-  PermissionTestUtils.add(uri, "cookie", Ci.nsICookiePermission.ACCESS_SESSION);
+  Services.perms.add(uri, "cookie", Ci.nsICookiePermission.ACCESS_SESSION);
 
   // Let's create a tab with some data.
   await SiteDataTestUtils.addToIndexedDB("about:newtab", "foo", "bar", {});
 
   ok(await checkDataForAboutURL(), "We have data for about:newtab");
 
   // Cleaning up.
   await Sanitizer.runSanitizeOnShutdown();
@@ -100,10 +97,10 @@ add_task(async function deleteStorageOnl
   );
   await new Promise(aResolve => {
     let req = Services.qms.clearStoragesForPrincipal(principal);
     req.callback = () => {
       aResolve();
     };
   });
 
-  PermissionTestUtils.remove(uri, "cookie");
+  Services.perms.remove(uri, "cookie");
 });
--- a/browser/base/content/test/sanitize/browser_cookiePermission_subDomains.js
+++ b/browser/base/content/test/sanitize/browser_cookiePermission_subDomains.js
@@ -17,21 +17,17 @@ add_task(async function subDomains() {
     set: [
       ["network.cookie.lifetimePolicy", Ci.nsICookieService.ACCEPT_NORMALLY],
       ["browser.sanitizer.loglevel", "All"],
     ],
   });
 
   // Domains and data
   let uriA = Services.io.newURI("https://www.mozilla.org");
-  PermissionTestUtils.add(
-    uriA,
-    "cookie",
-    Ci.nsICookiePermission.ACCESS_SESSION
-  );
+  Services.perms.add(uriA, "cookie", Ci.nsICookiePermission.ACCESS_SESSION);
 
   Services.cookies.add(
     uriA.host,
     "/test",
     "a",
     "b",
     false,
     false,
@@ -39,17 +35,17 @@ add_task(async function subDomains() {
     Date.now() + 24000 * 60 * 60,
     {},
     Ci.nsICookie.SAMESITE_NONE
   );
 
   await createIndexedDB(uriA.host, {});
 
   let uriB = Services.io.newURI("https://mozilla.org");
-  PermissionTestUtils.add(uriB, "cookie", Ci.nsICookiePermission.ACCESS_ALLOW);
+  Services.perms.add(uriB, "cookie", Ci.nsICookiePermission.ACCESS_ALLOW);
 
   Services.cookies.add(
     uriB.host,
     "/test",
     "c",
     "d",
     false,
     false,
@@ -84,18 +80,18 @@ add_task(async function subDomains() {
     "We should have cookies for URI: " + uriB.host
   );
   ok(
     await checkIndexedDB(uriB.host, {}),
     "We should have IDB for URI: " + uriB.host
   );
 
   // Cleaning up permissions
-  PermissionTestUtils.remove(uriA, "cookie");
-  PermissionTestUtils.remove(uriB, "cookie");
+  Services.perms.remove(uriA, "cookie");
+  Services.perms.remove(uriB, "cookie");
 });
 
 // session only cookie life-time, 2 domains (mozilla.org, www.mozilla.org),
 // only the latter has a cookie permission.
 add_task(async function subDomains() {
   info("Test subdomains and custom setting with cookieBehavior == 2");
 
   // Let's clean up all the data.
@@ -107,17 +103,17 @@ add_task(async function subDomains() {
     set: [
       ["network.cookie.lifetimePolicy", Ci.nsICookieService.ACCEPT_SESSION],
       ["browser.sanitizer.loglevel", "All"],
     ],
   });
 
   // Domains and data
   let uriA = Services.io.newURI("https://sub.mozilla.org");
-  PermissionTestUtils.add(uriA, "cookie", Ci.nsICookiePermission.ACCESS_ALLOW);
+  Services.perms.add(uriA, "cookie", Ci.nsICookiePermission.ACCESS_ALLOW);
 
   Services.cookies.add(
     uriA.host,
     "/test",
     "a",
     "b",
     false,
     false,
@@ -169,10 +165,10 @@ add_task(async function subDomains() {
     "We should not have cookies for URI: " + uriB.host
   );
   ok(
     !(await checkIndexedDB(uriB.host, {})),
     "We should not have IDB for URI: " + uriB.host
   );
 
   // Cleaning up permissions
-  PermissionTestUtils.remove(uriA, "cookie");
+  Services.perms.remove(uriA, "cookie");
 });
--- a/browser/base/content/test/sanitize/browser_sanitize-sitepermissions.js
+++ b/browser/base/content/test/sanitize/browser_sanitize-sitepermissions.js
@@ -14,25 +14,22 @@ add_task(async function test() {
   // sanitize before we start so we have a good baseline.
   await Sanitizer.sanitize(["siteSettings"], { ignoreTimespan: false });
 
   // Count how many permissions we start with - some are defaults that
   // will not be sanitized.
   let numAtStart = countPermissions();
 
   // Add a permission entry
-  PermissionTestUtils.add(
-    "http://example.com",
-    "testing",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(Services.io.newURI("http://example.com"), "testing", pm.ALLOW_ACTION);
 
   // Sanity check
   ok(
-    Services.perms.enumerator.hasMoreElements(),
+    pm.enumerator.hasMoreElements(),
     "Permission manager should have elements, since we just added one"
   );
 
   // Clear it
   await Sanitizer.sanitize(["siteSettings"], { ignoreTimespan: false });
 
   // Make sure it's gone
   is(
--- a/browser/base/content/test/sanitize/head.js
+++ b/browser/base/content/test/sanitize/head.js
@@ -3,17 +3,16 @@ var { XPCOMUtils } = ChromeUtils.import(
 );
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   Downloads: "resource://gre/modules/Downloads.jsm",
   FormHistory: "resource://gre/modules/FormHistory.jsm",
   PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SiteDataTestUtils: "resource://testing-common/SiteDataTestUtils.jsm",
-  PermissionTestUtils: "resource://testing-common/PermissionTestUtils.jsm",
 });
 
 function createIndexedDB(host, originAttributes) {
   let uri = Services.io.newURI("https://" + host);
   let principal = Services.scriptSecurityManager.createContentPrincipal(
     uri,
     originAttributes
   );
@@ -94,17 +93,17 @@ async function deleteOnShutdown(opt) {
       ["network.cookie.lifetimePolicy", opt.lifetimePolicy],
       ["browser.sanitizer.loglevel", "All"],
     ],
   });
 
   // Custom permission without considering OriginAttributes
   if (opt.cookiePermission !== undefined) {
     let uri = Services.io.newURI("https://www.example.com");
-    PermissionTestUtils.add(uri, "cookie", opt.cookiePermission);
+    Services.perms.add(uri, "cookie", opt.cookiePermission);
   }
 
   // Let's create a tab with some data.
   await opt.createData(
     (opt.fullHost ? "www." : "") + "example.org",
     opt.originAttributes
   );
   ok(
@@ -147,17 +146,17 @@ async function deleteOnShutdown(opt) {
     "Do we have data for www.example.com?"
   );
 
   // Clean up.
   await Sanitizer.sanitize(["cookies", "offlineApps"]);
 
   if (opt.cookiePermission !== undefined) {
     let uri = Services.io.newURI("https://www.example.com");
-    PermissionTestUtils.remove(uri, "cookie");
+    Services.perms.remove(uri, "cookie");
   }
 }
 
 function runAllCookiePermissionTests(originAttributes) {
   let tests = [
     { name: "IDB", createData: createIndexedDB, checkData: checkIndexedDB },
     {
       name: "Host Cookie",
--- a/browser/base/content/test/siteIdentity/browser_geolocation_indicator.js
+++ b/browser/base/content/test/siteIdentity/browser_geolocation_indicator.js
@@ -1,29 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 ChromeUtils.import("resource:///modules/PermissionUI.jsm", this);
 ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const CP = Cc["@mozilla.org/content-pref/service;1"].getService(
   Ci.nsIContentPrefService2
 );
 
 const EXAMPLE_PAGE_URL = "https://example.com";
 const EXAMPLE_PAGE_URI = Services.io.newURI(EXAMPLE_PAGE_URL);
-const EXAMPLE_PAGE_PRINCIPAL = Services.scriptSecurityManager.createContentPrincipal(
-  EXAMPLE_PAGE_URI,
-  {}
-);
 const GEO_CONTENT_PREF_KEY = "permissions.geoLocation.lastAccess";
 const POLL_INTERVAL_FALSE_STATE = 50;
 
 async function testGeoSharingIconVisible(state = true) {
   let sharingIcon = document.getElementById("geo-sharing-icon");
   ok(sharingIcon, "Geo sharing icon exists");
 
   try {
@@ -230,21 +223,21 @@ add_task(function test_indicator_and_tim
   return testIndicatorExplicitAllow(false);
 });
 add_task(function test_indicator_and_timestamp_after_explicit_allow_remember() {
   return testIndicatorExplicitAllow(true);
 });
 
 // Indicator and identity popup entry shown after auto PermissionUI geolocation allow
 add_task(async function test_indicator_and_timestamp_after_implicit_allow() {
-  PermissionTestUtils.add(
+  SitePermissions.set(
     EXAMPLE_PAGE_URI,
     "geo",
-    Services.perms.ALLOW_ACTION,
-    Services.perms.EXPIRE_NEVER
+    SitePermissions.ALLOW,
+    SitePermissions.SCOPE_PERSISTENT
   );
   let tab = await openExamplePage();
   let result = await requestGeoLocation(tab.linkedBrowser);
   ok(result, "Request should be allowed");
 
   await Promise.all([
     testGeoSharingIconVisible(true),
     testIdentityPopupGeoContainer(true, true),
@@ -261,21 +254,21 @@ add_task(function test_indicator_sharing
 
 // Indicator not shown when manually setting sharing state to false
 add_task(function test_indicator_sharing_state_inactive() {
   return testIndicatorGeoSharingState(false);
 });
 
 // Identity popup shows permission if geo permission is set to persistent allow
 add_task(async function test_identity_popup_permission_scope_permanent() {
-  PermissionTestUtils.add(
+  SitePermissions.set(
     EXAMPLE_PAGE_URI,
     "geo",
-    Services.perms.ALLOW_ACTION,
-    Services.perms.EXPIRE_NEVER
+    SitePermissions.ALLOW,
+    SitePermissions.SCOPE_PERSISTENT
   );
   let tab = await openExamplePage();
 
   await testIdentityPopupGeoContainer(true, false); // Expect permission to be visible, but not lastAccess indicator
 
   await cleanup(tab);
 });
 
@@ -298,21 +291,21 @@ add_task(
     await testIdentityPopupGeoContainer(true, true);
 
     await cleanup(tab);
   }
 );
 
 // Clicking permission clear button clears permission and resets geo sharing state
 add_task(async function test_identity_popup_permission_clear() {
-  PermissionTestUtils.add(
+  SitePermissions.set(
     EXAMPLE_PAGE_URI,
     "geo",
-    Services.perms.ALLOW_ACTION,
-    Services.perms.EXPIRE_NEVER
+    SitePermissions.ALLOW,
+    SitePermissions.SCOPE_PERSISTENT
   );
   let tab = await openExamplePage();
   gBrowser.updateBrowserSharing(tab.linkedBrowser, { geo: true });
 
   await openIdentityPopup();
 
   let clearButton = document.querySelector(
     "#identity-popup-geo-container button"
--- a/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
+++ b/browser/base/content/test/tabPrompts/browser_openPromptInBackgroundTab.js
@@ -1,14 +1,10 @@
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const ROOT = getRootDirectory(gTestPath).replace(
   "chrome://mochitests/content/",
   "http://example.com/"
 );
 let pageWithAlert = ROOT + "openPromptOffTimeout.html";
 
 registerCleanupFunction(function() {
   Services.perms.removeAll();
@@ -65,19 +61,20 @@ add_task(async function() {
     ourPromptElement
   );
   ourPrompt.onButtonClick(0);
   // Wait for that click to actually be handled completely.
   await new Promise(function(resolve) {
     Services.tm.dispatchToMainThread(resolve);
   });
   // check permission is set
+  let ps = Services.perms;
   is(
-    Services.perms.ALLOW_ACTION,
-    PermissionTestUtils.testPermission(pageWithAlert, "focus-tab-by-prompt"),
+    ps.ALLOW_ACTION,
+    ps.testPermission(makeURI(pageWithAlert), "focus-tab-by-prompt"),
     "Tab switching should now be allowed"
   );
 
   // Check if the control center shows the correct permission.
   let shown = BrowserTestUtils.waitForEvent(
     gIdentityHandler._identityPopup,
     "popupshown"
   );
--- a/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_trackers_subview.js
@@ -1,18 +1,14 @@
 /* eslint-disable mozilla/no-arbitrary-setTimeout */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const TRACKING_PAGE =
   "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
 
 const TP_PREF = "privacy.trackingprotection.enabled";
 
 add_task(async function setup() {
   await UrlClassifierTestUtils.addTestTrackers();
 
@@ -112,20 +108,16 @@ add_task(async function testTrackersSubV
   info("Testing trackers subview with TP disabled.");
   Services.prefs.setBoolPref(TP_PREF, false);
   await assertSitesListed(false);
   info("Testing trackers subview with TP enabled.");
   Services.prefs.setBoolPref(TP_PREF, true);
   await assertSitesListed(true);
   info("Testing trackers subview with TP enabled and a CB exception.");
   let uri = Services.io.newURI("https://tracking.example.org");
-  PermissionTestUtils.add(
-    uri,
-    "trackingprotection",
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(uri, "trackingprotection", Services.perms.ALLOW_ACTION);
   await assertSitesListed(false);
   info("Testing trackers subview with TP enabled and a CB exception removed.");
-  PermissionTestUtils.remove(uri, "trackingprotection");
+  Services.perms.remove(uri, "trackingprotection");
   await assertSitesListed(true);
 
   Services.prefs.clearUserPref(TP_PREF);
 });
--- a/browser/base/content/test/webextensions/browser_permissions_unsigned.js
+++ b/browser/base/content/test/webextensions/browser_permissions_unsigned.js
@@ -7,18 +7,18 @@ add_task(async function test_unsigned() 
   await SpecialPowers.pushPrefEnv({
     set: [
       ["extensions.webapi.testing", true],
       ["extensions.install.requireBuiltInCerts", false],
     ],
   });
 
   let testURI = makeURI("https://example.com/");
-  PermissionTestUtils.add(testURI, "install", Services.perms.ALLOW_ACTION);
-  registerCleanupFunction(() => PermissionTestUtils.remove(testURI, "install"));
+  Services.perms.add(testURI, "install", Services.perms.ALLOW_ACTION);
+  registerCleanupFunction(() => Services.perms.remove(testURI, "install"));
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
 
   BrowserTestUtils.loadURI(
     gBrowser.selectedBrowser,
     `${BASE}/file_install_extensions.html`
   );
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
--- a/browser/base/content/test/webextensions/head.js
+++ b/browser/base/content/test/webextensions/head.js
@@ -22,20 +22,16 @@ XPCOMUtils.defineLazyGetter(this, "Manag
 });
 
 ChromeUtils.import(
   "resource://testing-common/CustomizableUITestUtils.jsm",
   this
 );
 let gCUITestUtils = new CustomizableUITestUtils(window);
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 /**
  * Wait for the given PopupNotification to display
  *
  * @param {string} name
  *        The name of the notification to wait for.
  *
  * @returns {Promise}
  *          Resolves with the notification window.
@@ -308,18 +304,18 @@ async function testInstallMethod(install
     ],
   });
 
   if (telemetryBase !== undefined) {
     hookExtensionsTelemetry();
   }
 
   let testURI = makeURI("https://example.com/");
-  PermissionTestUtils.add(testURI, "install", Services.perms.ALLOW_ACTION);
-  registerCleanupFunction(() => PermissionTestUtils.remove(testURI, "install"));
+  Services.perms.add(testURI, "install", Services.perms.ALLOW_ACTION);
+  registerCleanupFunction(() => Services.perms.remove(testURI, "install"));
 
   async function runOnce(filename, cancel) {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
 
     let installPromise = new Promise(resolve => {
       let listener = {
         onDownloadCancelled() {
           AddonManager.removeInstallListener(listener);
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media.js
@@ -138,35 +138,27 @@ var gTests = [
       await checkNotSharing();
 
       // Verify that we set 'Temporarily blocked' permissions.
       let browser = gBrowser.selectedBrowser;
       let blockedPerms = document.getElementById(
         "blocked-permissions-container"
       );
 
-      let { state, scope } = SitePermissions.getForPrincipal(
-        null,
-        "camera",
-        browser
-      );
+      let { state, scope } = SitePermissions.get(null, "camera", browser);
       Assert.equal(state, SitePermissions.BLOCK);
       Assert.equal(scope, SitePermissions.SCOPE_TEMPORARY);
       ok(
         blockedPerms.querySelector(
           ".blocked-permission-icon.camera-icon[showing=true]"
         ),
         "the blocked camera icon is shown"
       );
 
-      ({ state, scope } = SitePermissions.getForPrincipal(
-        null,
-        "microphone",
-        browser
-      ));
+      ({ state, scope } = SitePermissions.get(null, "microphone", browser));
       Assert.equal(state, SitePermissions.BLOCK);
       Assert.equal(scope, SitePermissions.SCOPE_TEMPORARY);
       ok(
         blockedPerms.querySelector(
           ".blocked-permission-icon.microphone-icon[showing=true]"
         ),
         "the blocked microphone icon is shown"
       );
@@ -175,26 +167,18 @@ var gTests = [
       promise = promiseMessage(permissionError);
       await promiseRequestDevice(true, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
 
-      SitePermissions.removeFromPrincipal(
-        browser.contentPrincipal,
-        "camera",
-        browser
-      );
-      SitePermissions.removeFromPrincipal(
-        browser.contentPrincipal,
-        "microphone",
-        browser
-      );
+      SitePermissions.remove(browser.currentURI, "camera", browser);
+      SitePermissions.remove(browser.currentURI, "microphone", browser);
     },
   },
 
   {
     desc: "getUserMedia audio+video: stop sharing",
     run: async function checkStopSharing() {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
@@ -231,31 +215,19 @@ var gTests = [
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia audio+video: reloading the page removes all gUM UI",
     run: async function checkReloading() {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
@@ -289,31 +261,19 @@ var gTests = [
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia prompt: Always/Never Share",
     run: async function checkRememberCheckbox() {
       let elt = id => document.getElementById(id);
 
@@ -363,48 +323,44 @@ var gTests = [
         }
         Assert.deepEqual(
           await getMediaCaptureState(),
           expected,
           "expected " + Object.keys(expected).join(" and ") + " to be shared"
         );
 
         function checkDevicePermissions(aDevice, aExpected) {
+          let Perms = Services.perms;
           let uri = gBrowser.selectedBrowser.documentURI;
-          let devicePerms = PermissionTestUtils.testExactPermission(
-            uri,
-            aDevice
-          );
+          let devicePerms = Perms.testExactPermission(uri, aDevice);
           if (aExpected === undefined) {
             is(
               devicePerms,
-              Services.perms.UNKNOWN_ACTION,
+              Perms.UNKNOWN_ACTION,
               "no " + aDevice + " persistent permissions"
             );
           } else {
             is(
               devicePerms,
-              aExpected
-                ? Services.perms.ALLOW_ACTION
-                : Services.perms.DENY_ACTION,
+              aExpected ? Perms.ALLOW_ACTION : Perms.DENY_ACTION,
               aDevice + " persistently " + (aExpected ? "allowed" : "denied")
             );
           }
-          PermissionTestUtils.remove(uri, aDevice);
+          Perms.remove(uri, aDevice);
         }
         checkDevicePermissions("microphone", aExpectedAudioPerm);
         checkDevicePermissions("camera", aExpectedVideoPerm);
 
         if (expectedMessage == "ok") {
           await closeStream();
         }
       }
 
       // 3 cases where the user accepts the device prompt.
-      info("audio+video, user grants, expect both Services.perms set to allow");
+      info("audio+video, user grants, expect both perms set to allow");
       await checkPerm(true, true, true, true);
       info(
         "audio only, user grants, check audio perm set to allow, video perm not set"
       );
       await checkPerm(true, false, true, undefined);
       info(
         "video only, user grants, check video perm set to allow, audio perm not set"
       );
@@ -414,49 +370,46 @@ var gTests = [
       info(
         "audio only, user denies, expect audio perm set to deny, video not set"
       );
       await checkPerm(true, false, false, undefined, true);
       info(
         "video only, user denies, expect video perm set to deny, audio perm not set"
       );
       await checkPerm(false, true, undefined, false, true);
-      info("audio+video, user denies, expect both Services.perms set to deny");
+      info("audio+video, user denies, expect both perms set to deny");
       await checkPerm(true, true, false, false, true);
     },
   },
 
   {
     desc: "getUserMedia without prompt: use persistent permissions",
     run: async function checkUsePersistentPermissions() {
       async function usePerm(
         aAllowAudio,
         aAllowVideo,
         aRequestAudio,
         aRequestVideo,
         aExpectStream
       ) {
+        let Perms = Services.perms;
         let uri = gBrowser.selectedBrowser.documentURI;
 
         if (aAllowAudio !== undefined) {
-          PermissionTestUtils.add(
+          Perms.add(
             uri,
             "microphone",
-            aAllowAudio
-              ? Services.perms.ALLOW_ACTION
-              : Services.perms.DENY_ACTION
+            aAllowAudio ? Perms.ALLOW_ACTION : Perms.DENY_ACTION
           );
         }
         if (aAllowVideo !== undefined) {
-          PermissionTestUtils.add(
+          Perms.add(
             uri,
             "camera",
-            aAllowVideo
-              ? Services.perms.ALLOW_ACTION
-              : Services.perms.DENY_ACTION
+            aAllowVideo ? Perms.ALLOW_ACTION : Perms.DENY_ACTION
           );
         }
 
         if (aExpectStream === undefined) {
           // Check that we get a prompt.
           let promise = promisePopupNotificationShown("webRTC-shareDevices");
           await promiseRequestDevice(aRequestAudio, aRequestVideo);
           await promise;
@@ -464,18 +417,18 @@ var gTests = [
 
           // Deny the request to cleanup...
           await promiseMessage(permissionError, () => {
             activateSecondaryAction(kActionDeny);
           });
           await expectObserverCalled("getUserMedia:response:deny");
           await expectObserverCalled("recording-window-ended");
           let browser = gBrowser.selectedBrowser;
-          SitePermissions.removeFromPrincipal(null, "camera", browser);
-          SitePermissions.removeFromPrincipal(null, "microphone", browser);
+          SitePermissions.remove(null, "camera", browser);
+          SitePermissions.remove(null, "microphone", browser);
         } else {
           let expectedMessage = aExpectStream ? "ok" : permissionError;
           let promise = promiseMessage(expectedMessage);
           await promiseRequestDevice(aRequestAudio, aRequestVideo);
           await promise;
 
           if (expectedMessage == "ok") {
             await expectObserverCalled("getUserMedia:request");
@@ -500,18 +453,18 @@ var gTests = [
             );
 
             await closeStream();
           } else {
             await expectObserverCalled("recording-window-ended");
           }
         }
 
-        PermissionTestUtils.remove(uri, "camera");
-        PermissionTestUtils.remove(uri, "microphone");
+        Perms.remove(uri, "camera");
+        Perms.remove(uri, "microphone");
       }
 
       // Set both permissions identically
       info("allow audio+video, request audio+video, expect ok (audio+video)");
       await usePerm(true, true, true, true, true);
       info("deny audio+video, request audio+video, expect denied");
       await usePerm(false, false, true, true, false);
 
@@ -564,75 +517,57 @@ var gTests = [
       await usePerm(undefined, false, false, true, false);
     },
   },
 
   {
     desc: "Stop Sharing removes persistent permissions",
     run: async function checkStopSharingRemovesPersistentPermissions() {
       async function stopAndCheckPerm(aRequestAudio, aRequestVideo) {
+        let Perms = Services.perms;
         let uri = gBrowser.selectedBrowser.documentURI;
 
         // Initially set both permissions to 'allow'.
-        PermissionTestUtils.add(uri, "microphone", Services.perms.ALLOW_ACTION);
-        PermissionTestUtils.add(uri, "camera", Services.perms.ALLOW_ACTION);
+        Perms.add(uri, "microphone", Perms.ALLOW_ACTION);
+        Perms.add(uri, "camera", Perms.ALLOW_ACTION);
 
         let indicator = promiseIndicatorWindow();
         // Start sharing what's been requested.
         let promise = promiseMessage("ok");
         await promiseRequestDevice(aRequestAudio, aRequestVideo);
         await promise;
 
         await expectObserverCalled("getUserMedia:request");
         await expectObserverCalled("getUserMedia:response:allow");
         await expectObserverCalled("recording-device-events");
         await indicator;
         await checkSharingUI({ video: aRequestVideo, audio: aRequestAudio });
 
         await stopSharing(aRequestVideo ? "camera" : "microphone");
 
         // Check that permissions have been removed as expected.
-        let audioPerm = PermissionTestUtils.testExactPermission(
-          uri,
-          "microphone"
-        );
+        let audioPerm = Perms.testExactPermission(uri, "microphone");
         if (aRequestAudio) {
-          is(
-            audioPerm,
-            Services.perms.UNKNOWN_ACTION,
-            "microphone permissions removed"
-          );
+          is(audioPerm, Perms.UNKNOWN_ACTION, "microphone permissions removed");
         } else {
-          is(
-            audioPerm,
-            Services.perms.ALLOW_ACTION,
-            "microphone permissions untouched"
-          );
+          is(audioPerm, Perms.ALLOW_ACTION, "microphone permissions untouched");
         }
 
-        let videoPerm = PermissionTestUtils.testExactPermission(uri, "camera");
+        let videoPerm = Perms.testExactPermission(uri, "camera");
         if (aRequestVideo) {
-          is(
-            videoPerm,
-            Services.perms.UNKNOWN_ACTION,
-            "camera permissions removed"
-          );
+          is(videoPerm, Perms.UNKNOWN_ACTION, "camera permissions removed");
         } else {
-          is(
-            videoPerm,
-            Services.perms.ALLOW_ACTION,
-            "camera permissions untouched"
-          );
+          is(videoPerm, Perms.ALLOW_ACTION, "camera permissions untouched");
         }
 
         // Cleanup.
         await closeStream(true);
 
-        PermissionTestUtils.remove(uri, "camera");
-        PermissionTestUtils.remove(uri, "microphone");
+        Perms.remove(uri, "camera");
+        Perms.remove(uri, "microphone");
       }
 
       info("request audio+video, stop sharing resets both");
       await stopAndCheckPerm(true, true);
       info("request audio, stop sharing resets audio only");
       await stopAndCheckPerm(true, false);
       info("request video, stop sharing resets video only");
       await stopAndCheckPerm(false, true);
@@ -705,19 +640,20 @@ var gTests = [
       let browser = gBrowser.selectedBrowser;
       BrowserTestUtils.loadURI(
         browser,
         browser.documentURI.spec.replace("https://", "http://")
       );
       await BrowserTestUtils.browserLoaded(browser);
 
       // Initially set both permissions to 'allow'.
+      let Perms = Services.perms;
       let uri = browser.documentURI;
-      PermissionTestUtils.add(uri, "microphone", Services.perms.ALLOW_ACTION);
-      PermissionTestUtils.add(uri, "camera", Services.perms.ALLOW_ACTION);
+      Perms.add(uri, "microphone", Perms.ALLOW_ACTION);
+      Perms.add(uri, "camera", Perms.ALLOW_ACTION);
 
       // Request devices and expect a prompt despite the saved 'Allow' permission,
       // because the connection isn't secure.
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
 
@@ -732,17 +668,17 @@ var gTests = [
       ok(notification.button.disabled, "Allow button is disabled");
       ok(
         !notification.hasAttribute("warninghidden"),
         "warning message is shown"
       );
 
       // Cleanup.
       await closeStream(true);
-      PermissionTestUtils.remove(uri, "camera");
-      PermissionTestUtils.remove(uri, "microphone");
+      Perms.remove(uri, "camera");
+      Perms.remove(uri, "microphone");
     },
   },
 ];
 
 add_task(async function test() {
   await runTests(gTests);
 });
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_default_permissions.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_default_permissions.js
@@ -1,16 +1,12 @@
 /* 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/. */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const permissionError =
   "error: NotAllowedError: The request is not allowed " +
   "by the user agent or the platform in the current context.";
 
 const CAMERA_PREF = "permissions.default.camera";
 const MICROPHONE_PREF = "permissions.default.microphone";
 
 var gTests = [
@@ -70,36 +66,32 @@ var gTests = [
   },
 
   {
     desc: "getUserMedia video: globally blocking camera + local exception",
     run: async function checkAudioVideo() {
       let browser = gBrowser.selectedBrowser;
       Services.prefs.setIntPref(CAMERA_PREF, SitePermissions.BLOCK);
       // Overwrite the permission for that URI, requesting video should work again.
-      PermissionTestUtils.add(
-        browser.currentURI,
-        "camera",
-        Services.perms.ALLOW_ACTION
-      );
+      SitePermissions.set(browser.currentURI, "camera", SitePermissions.ALLOW);
 
       // Requesting video should work.
       let indicator = promiseIndicatorWindow();
       let promise = promiseMessage("ok");
       await promiseRequestDevice(false, true);
       await promise;
 
       await expectObserverCalled("getUserMedia:request");
       await expectObserverCalled("getUserMedia:response:allow");
       await expectObserverCalled("recording-device-events");
       await indicator;
       await checkSharingUI({ video: true });
       await closeStream();
 
-      PermissionTestUtils.remove(browser.currentURI, "camera");
+      SitePermissions.remove(browser.currentURI, "camera");
       Services.prefs.clearUserPref(CAMERA_PREF);
     },
   },
 
   {
     desc: "getUserMedia audio+video: globally blocking microphone",
     run: async function checkAudioVideo() {
       Services.prefs.setIntPref(MICROPHONE_PREF, SitePermissions.BLOCK);
@@ -155,35 +147,35 @@ var gTests = [
   },
 
   {
     desc: "getUserMedia audio: globally blocking microphone + local exception",
     run: async function checkAudioVideo() {
       let browser = gBrowser.selectedBrowser;
       Services.prefs.setIntPref(MICROPHONE_PREF, SitePermissions.BLOCK);
       // Overwrite the permission for that URI, requesting video should work again.
-      PermissionTestUtils.add(
+      SitePermissions.set(
         browser.currentURI,
         "microphone",
-        Services.perms.ALLOW_ACTION
+        SitePermissions.ALLOW
       );
 
       // Requesting audio should work.
       let indicator = promiseIndicatorWindow();
       let promise = promiseMessage("ok");
       await promiseRequestDevice(true);
       await promise;
 
       await expectObserverCalled("getUserMedia:request");
       await expectObserverCalled("getUserMedia:response:allow");
       await expectObserverCalled("recording-device-events");
       await indicator;
       await checkSharingUI({ audio: true });
       await closeStream();
 
-      PermissionTestUtils.remove(browser.currentURI, "microphone");
+      SitePermissions.remove(browser.currentURI, "microphone");
       Services.prefs.clearUserPref(MICROPHONE_PREF);
     },
   },
 ];
 add_task(async function test() {
   await runTests(gTests);
 });
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_in_frame.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_in_frame.js
@@ -60,39 +60,40 @@ var gTests = [
         await getMediaCaptureState(),
         { audio: true, video: true },
         "expected camera and microphone to be shared"
       );
 
       await indicator;
       await checkSharingUI({ video: true, audio: true });
 
+      let Perms = Services.perms;
       let uri = Services.io.newURI("https://example.com/");
       is(
-        PermissionTestUtils.testExactPermission(uri, "microphone"),
-        Services.perms.ALLOW_ACTION,
+        Perms.testExactPermission(uri, "microphone"),
+        Perms.ALLOW_ACTION,
         "microphone persistently allowed"
       );
       is(
-        PermissionTestUtils.testExactPermission(uri, "camera"),
-        Services.perms.ALLOW_ACTION,
+        Perms.testExactPermission(uri, "camera"),
+        Perms.ALLOW_ACTION,
         "camera persistently allowed"
       );
 
       await stopSharing();
 
       // The persistent permissions for the frame should have been removed.
       is(
-        PermissionTestUtils.testExactPermission(uri, "microphone"),
-        Services.perms.UNKNOWN_ACTION,
+        Perms.testExactPermission(uri, "microphone"),
+        Perms.UNKNOWN_ACTION,
         "microphone not persistently allowed"
       );
       is(
-        PermissionTestUtils.testExactPermission(uri, "camera"),
-        Services.perms.UNKNOWN_ACTION,
+        Perms.testExactPermission(uri, "camera"),
+        Perms.UNKNOWN_ACTION,
         "camera not persistently allowed"
       );
 
       // the stream is already closed, but this will do some cleanup anyway
       await closeStream(true, "frame1");
     },
   },
 
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_queue_request.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_queue_request.js
@@ -39,21 +39,17 @@ var gTests = [
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(true, false);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // close all streams
       await closeStream();
     },
   },
 
   {
     desc: "test queueing allow video behind deny audio",
@@ -87,21 +83,17 @@ var gTests = [
       Assert.deepEqual(
         await getMediaCaptureState(),
         { video: true },
         "expected camera to be shared"
       );
       await indicator;
       await checkSharingUI({ audio: false, video: true });
 
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // close all streams
       await closeStream();
     },
   },
 
   {
     desc: "test queueing allow audio behind allow video with error",
@@ -166,20 +158,16 @@ var gTests = [
       promise = promiseSpecificMessageReceived(permissionError, 2);
       activateSecondaryAction(kActionDeny);
       await promise;
 
       await expectObserverCalled("getUserMedia:request");
       await expectObserverCalled("getUserMedia:response:deny", 2);
       await expectObserverCalled("recording-window-ended");
 
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 ];
 
 add_task(async function test() {
   await runTests(gTests);
 });
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js
@@ -173,21 +173,17 @@ var gTests = [
       );
       checkDeviceSelectors(false, false, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
       await closeStream();
     },
   },
 
   {
     desc: "getUserMedia window/screen picking window",
     run: async function checkWindowOrScreen() {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
@@ -461,26 +457,18 @@ var gTests = [
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia audio + window/screen: stop sharing",
     run: async function checkStopSharing() {
       if (AppConstants.platform == "macosx") {
         todo(
@@ -643,21 +631,18 @@ var gTests = [
       await closeStream();
     },
   },
 
   {
     desc: "Only persistent block is possible for screen sharing",
     run: async function checkPersistentPermissions() {
       let browser = gBrowser.selectedBrowser;
-      let devicePerms = SitePermissions.getForPrincipal(
-        browser.contentPrincipal,
-        "screen",
-        browser
-      );
+      let uri = browser.documentURI;
+      let devicePerms = SitePermissions.get(uri, "screen", browser);
       is(
         devicePerms.state,
         SitePermissions.UNKNOWN,
         "starting without screen persistent permissions"
       );
 
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(false, true, null, "screen");
@@ -690,40 +675,32 @@ var gTests = [
       // Click "Don't Allow" to save a persistent block permission.
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
 
-      let permission = SitePermissions.getForPrincipal(
-        browser.contentPrincipal,
-        "screen",
-        browser
-      );
+      let permission = SitePermissions.get(uri, "screen", browser);
       is(permission.state, SitePermissions.BLOCK, "screen sharing is blocked");
       is(
         permission.scope,
         SitePermissions.SCOPE_PERSISTENT,
         "screen sharing is persistently blocked"
       );
 
       // Request screensharing again, expect an immediate failure.
       promise = promiseMessage(permissionError);
       await promiseRequestDevice(false, true, null, "screen");
       await promise;
       await expectObserverCalled("recording-window-ended");
 
       // Now set the permission to allow and expect a prompt.
-      SitePermissions.setForPrincipal(
-        browser.contentPrincipal,
-        "screen",
-        SitePermissions.ALLOW
-      );
+      SitePermissions.set(uri, "screen", SitePermissions.ALLOW);
 
       // Request devices and expect a prompt despite the saved 'Allow' permission.
       promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(false, true, null, "screen");
       await promise;
       await expectObserverCalled("getUserMedia:request");
 
       // The 'remember' checkbox shouldn't be checked anymore.
@@ -737,21 +714,17 @@ var gTests = [
       ok(!checkbox.checked, "checkbox is not checked");
 
       // Deny the request to cleanup...
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
-      SitePermissions.removeFromPrincipal(
-        browser.contentPrincipal,
-        "screen",
-        browser
-      );
+      SitePermissions.remove(uri, "screen", browser);
     },
   },
 
   {
     desc:
       "Switching between menu options maintains correct main action state while window sharing",
     run: async function checkDoorhangerState() {
       let win = await BrowserTestUtils.openNewBrowserWindow();
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access.js
@@ -61,62 +61,38 @@ var gTests = [
       );
       checkDeviceSelectors(false, false, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // After closing all streams, gUM(audio+camera) causes a prompt.
       await closeStream();
       promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(true, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
       await checkNotSharing();
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia camera",
     run: async function checkAudioVideoWhileLiveTracksExist_camera() {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(false, true);
@@ -146,59 +122,35 @@ var gTests = [
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(true, false);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // gUM(audio+camera) causes a prompt;
       promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(true, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // gUM(screen) causes a prompt;
       promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(false, true, null, "screen");
       await promise;
       await expectObserverCalled("getUserMedia:request");
 
       is(
@@ -208,31 +160,19 @@ var gTests = [
       );
       checkDeviceSelectors(false, false, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // gUM(camera) returns a stream without prompting.
       promise = promiseMessage("ok");
       await promiseRequestDevice(false, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       await promiseNoPopupNotification("webRTC-shareDevices");
       await expectObserverCalled("getUserMedia:response:allow");
@@ -282,59 +222,35 @@ var gTests = [
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(false, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // gUM(audio+camera) causes a prompt;
       promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       checkDeviceSelectors(true, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // gUM(audio) returns a stream without prompting.
       promise = promiseMessage("ok");
       await promiseRequestDevice(true, false);
       await promise;
       await expectObserverCalled("getUserMedia:request");
       await promiseNoPopupNotification("webRTC-shareDevices");
       await expectObserverCalled("getUserMedia:response:allow");
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_in_frame.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_unprompted_access_in_frame.js
@@ -40,31 +40,19 @@ var gTests = [
       checkDeviceSelectors(true, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
 
       // If there's an active audio+camera stream in frame 1,
       // gUM(audio+camera) in frame 1 returns a stream without prompting;
       promise = promiseMessage("ok");
       await promiseRequestDevice(true, true, "frame1");
       await promise;
       await expectObserverCalled("getUserMedia:request");
       await promiseNoPopupNotification("webRTC-shareDevices");
@@ -113,31 +101,19 @@ var gTests = [
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
 
       // close the stream
       await closeStream(false, "frame1");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia audio+camera in frame 1 - reload",
     run: async function checkAudioVideoWhileLiveTracksExist_frame_reload() {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       await promiseRequestDevice(true, true, "frame1");
@@ -180,31 +156,19 @@ var gTests = [
       checkDeviceSelectors(true, true);
 
       await promiseMessage(permissionError, () => {
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 
   {
     desc: "getUserMedia audio+camera at the top level window",
     run: async function checkAudioVideoWhileLiveTracksExist_topLevel() {
       // create an active audio+camera stream at the top level window
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
@@ -241,30 +205,18 @@ var gTests = [
         activateSecondaryAction(kActionDeny);
       });
 
       await expectObserverCalled("getUserMedia:response:deny");
       await expectObserverCalled("recording-window-ended");
 
       // close the stream
       await closeStream();
-      SitePermissions.removeFromPrincipal(
-        null,
-        "screen",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "camera",
-        gBrowser.selectedBrowser
-      );
-      SitePermissions.removeFromPrincipal(
-        null,
-        "microphone",
-        gBrowser.selectedBrowser
-      );
+      SitePermissions.remove(null, "screen", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "camera", gBrowser.selectedBrowser);
+      SitePermissions.remove(null, "microphone", gBrowser.selectedBrowser);
     },
   },
 ];
 
 add_task(async function test() {
   await runTests(gTests, { relativeURI: "get_user_media_in_frame.html" });
 });
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -1,17 +1,14 @@
 var { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 var { SitePermissions } = ChromeUtils.import(
   "resource:///modules/SitePermissions.jsm"
 );
-var { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const PREF_PERMISSION_FAKE = "media.navigator.permission.fake";
 const PREF_AUDIO_LOOPBACK = "media.audio_loopback_dev";
 const PREF_VIDEO_LOOPBACK = "media.video_loopback_dev";
 const PREF_FAKE_STREAMS = "media.navigator.streams.fake";
 const PREF_FOCUS_SOURCE = "media.getusermedia.window.focus_source.enabled";
 const CONTENT_SCRIPT_HELPER =
   getRootDirectory(gTestPath) + "get_user_media_content_script.js";
--- a/browser/components/enterprisepolicies/tests/xpcshell/head.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/head.js
@@ -10,19 +10,16 @@ const { Preferences } = ChromeUtils.impo
   "resource://gre/modules/Preferences.jsm"
 );
 const { updateAppInfo, getAppInfo } = ChromeUtils.import(
   "resource://testing-common/AppInfo.jsm"
 );
 const { FileTestUtils } = ChromeUtils.import(
   "resource://testing-common/FileTestUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 updateAppInfo({
   name: "XPCShell",
   ID: "xpcshell@tests.mozilla.org",
   version: "48",
   platformVersion: "48",
 });
 
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js
@@ -9,64 +9,64 @@ function URI(str) {
 
 add_task(async function test_setup_preexisting_permissions() {
   // Pre-existing ALLOW permissions that should be overriden
   // with DENY.
 
   // No ALLOW -> DENY override for popup and install permissions,
   // because their policies only supports the Allow parameter.
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "camera",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "microphone",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "geo",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "desktop-notification",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
   // Pre-existing DENY permissions that should be overriden
   // with ALLOW.
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "camera",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "microphone",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "geo",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "desktop-notification",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 });
 
 add_task(async function test_setup_activate_policies() {
   await setupPolicyEngineWithJson({
@@ -98,23 +98,23 @@ add_task(async function test_setup_activ
   );
 });
 
 function checkPermission(url, expected, permissionName) {
   let expectedValue = Ci.nsIPermissionManager[`${expected}_ACTION`];
   let uri = Services.io.newURI(`https://www.${url}`);
 
   equal(
-    PermissionTestUtils.testPermission(uri, permissionName),
+    Services.perms.testPermission(uri, permissionName),
     expectedValue,
     `Correct (${permissionName}=${expected}) for URL ${url}`
   );
 
   if (expected != "UNKNOWN") {
-    let permission = PermissionTestUtils.getPermissionObject(
+    let permission = Services.perms.getPermissionObjectForURI(
       uri,
       permissionName,
       true
     );
     ok(permission, "Permission object exists");
     equal(
       permission.expireType,
       Ci.nsIPermissionManager.EXPIRE_POLICY,
@@ -148,65 +148,65 @@ add_task(async function test_location_po
 
 add_task(async function test_notifications_policy() {
   checkAllPermissionsForType("desktop-notification");
 });
 
 add_task(async function test_change_permission() {
   // Checks that changing a permission will still retain the
   // value set through the engine.
-  PermissionTestUtils.add(
-    "https://www.allow.com",
+  Services.perms.add(
+    URI("https://www.allow.com"),
     "camera",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.allow.com",
+  Services.perms.add(
+    URI("https://www.allow.com"),
     "microphone",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.allow.com",
+  Services.perms.add(
+    URI("https://www.allow.com"),
     "geo",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.allow.com",
+  Services.perms.add(
+    URI("https://www.allow.com"),
     "desktop-notification",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
   checkPermission("allow.com", "ALLOW", "camera");
   checkPermission("allow.com", "ALLOW", "microphone");
   checkPermission("allow.com", "ALLOW", "geo");
   checkPermission("allow.com", "ALLOW", "desktop-notification");
 
   // Also change one un-managed permission to make sure it doesn't
   // cause any problems to the policy engine or the permission manager.
-  PermissionTestUtils.add(
-    "https://www.unmanaged.com",
+  Services.perms.add(
+    URI("https://www.unmanaged.com"),
     "camera",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.unmanaged.com",
+  Services.perms.add(
+    URI("https://www.unmanaged.com"),
     "microphone",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.unmanaged.com",
+  Services.perms.add(
+    URI("https://www.unmanaged.com"),
     "geo",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
-  PermissionTestUtils.add(
-    "https://www.unmanaged.com",
+  Services.perms.add(
+    URI("https://www.unmanaged.com"),
     "desktop-notification",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 });
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons_flash.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons_flash.js
@@ -9,55 +9,55 @@ function URI(str) {
 
 add_task(async function test_setup_preexisting_permissions() {
   // Pre-existing ALLOW permissions that should be overriden
   // with DENY.
 
   // No ALLOW -> DENY override for popup and install permissions,
   // because their policies only supports the Allow parameter.
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "cookie",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-allow.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-allow.com"),
     "plugin:flash",
     Ci.nsIPermissionManager.ALLOW_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
   // Pre-existing DENY permissions that should be overriden
   // with ALLOW.
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "popup",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "install",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "cookie",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
-  PermissionTestUtils.add(
-    "https://www.pre-existing-deny.com",
+  Services.perms.add(
+    URI("https://www.pre-existing-deny.com"),
     "plugin:flash",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 });
 
 add_task(async function test_setup_activate_policies() {
   await setupPolicyEngineWithJson("config_popups_cookies_addons_flash.json");
@@ -68,23 +68,23 @@ add_task(async function test_setup_activ
   );
 });
 
 function checkPermission(url, expected, permissionName) {
   let expectedValue = Ci.nsIPermissionManager[`${expected}_ACTION`];
   let uri = Services.io.newURI(`https://www.${url}`);
 
   equal(
-    PermissionTestUtils.testPermission(uri, permissionName),
+    Services.perms.testPermission(uri, permissionName),
     expectedValue,
     `Correct (${permissionName}=${expected}) for URL ${url}`
   );
 
   if (expected != "UNKNOWN") {
-    let permission = PermissionTestUtils.getPermissionObject(
+    let permission = Services.perms.getPermissionObjectForURI(
       uri,
       permissionName,
       true
     );
     ok(permission, "Permission object exists");
     equal(
       permission.expireType,
       Ci.nsIPermissionManager.EXPIRE_POLICY,
@@ -118,26 +118,26 @@ add_task(async function test_cookies_pol
 
 add_task(async function test_flash_policy() {
   checkAllPermissionsForType("plugin:flash");
 });
 
 add_task(async function test_change_permission() {
   // Checks that changing a permission will still retain the
   // value set through the engine.
-  PermissionTestUtils.add(
-    "https://www.allow.com",
+  Services.perms.add(
+    URI("https://www.allow.com"),
     "cookie",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 
   checkPermission("allow.com", "ALLOW", "cookie");
 
   // Also change one un-managed permission to make sure it doesn't
   // cause any problems to the policy engine or the permission manager.
-  PermissionTestUtils.add(
-    "https://www.unmanaged.com",
+  Services.perms.add(
+    URI("https://www.unmanaged.com"),
     "cookie",
     Ci.nsIPermissionManager.DENY_ACTION,
     Ci.nsIPermissionManager.EXPIRE_SESSION
   );
 });
--- a/browser/components/originattributes/test/browser/browser_permissions.js
+++ b/browser/components/originattributes/test/browser/browser_permissions.js
@@ -1,24 +1,20 @@
 /**
  * Bug 1282655 - Test if site permissions are universal across origin attributes.
  *
  * This test is testing the cookie "permission" for a specific URI.
  */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const TEST_PAGE = "http://example.net";
 const uri = Services.io.newURI(TEST_PAGE);
 
 function disableCookies() {
   Services.cookies.removeAll();
-  PermissionTestUtils.add(uri, "cookie", Services.perms.DENY_ACTION);
+  Services.perms.add(uri, "cookie", Services.perms.DENY_ACTION);
 }
 
 function ensureCookieNotSet(aBrowser) {
   ContentTask.spawn(aBrowser, null, async function() {
     content.document.cookie = "key=value";
     is(
       content.document.cookie,
       "",
@@ -32,17 +28,17 @@ IsolationTestTools.runTests(
   TEST_PAGE,
   ensureCookieNotSet,
   () => true,
   disableCookies
 );
 
 function enableCookies() {
   Services.cookies.removeAll();
-  PermissionTestUtils.add(uri, "cookie", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uri, "cookie", Services.perms.ALLOW_ACTION);
 }
 
 function ensureCookieSet(aBrowser) {
   ContentTask.spawn(aBrowser, null, function() {
     content.document.cookie = "key=value";
     is(
       content.document.cookie,
       "key=value",
--- a/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
+++ b/browser/components/preferences/in-content/tests/browser_cookies_exceptions.js
@@ -133,29 +133,25 @@ add_task(async function testRemove() {
     }
   );
 });
 
 add_task(async function testAdd() {
   await runTest(
     async (params, observeAllPromise, apply) => {
       let uri = Services.io.newURI("http://test.com");
-      PermissionTestUtils.add(
-        uri,
-        "popup",
-        Ci.nsIPermissionManager.DENY_ACTION
-      );
+      Services.perms.add(uri, "popup", Ci.nsIPermissionManager.DENY_ACTION);
 
       info("Adding unrelated permission should not change display.");
       assertListContents(params, []);
 
       apply();
       await observeAllPromise;
 
-      PermissionTestUtils.remove(uri, "popup");
+      Services.perms.remove(uri, "popup");
     },
     params => {
       return [
         {
           type: "popup",
           origin: "http://test.com",
           data: "added",
           capability: Ci.nsIPermissionManager.DENY_ACTION,
@@ -411,21 +407,17 @@ add_task(async function testSort() {
       EventUtils.synthesizeMouseAtCenter(
         params.doc.getElementById("siteCol"),
         {},
         params.doc.defaultView
       );
 
       for (let URL of ["http://a", "http://z", "http://b"]) {
         let URI = Services.io.newURI(URL);
-        PermissionTestUtils.add(
-          URI,
-          "cookie",
-          Ci.nsIPermissionManager.ALLOW_ACTION
-        );
+        Services.perms.add(URI, "cookie", Ci.nsIPermissionManager.ALLOW_ACTION);
       }
 
       assertListContents(params, [
         ["http://a", params.allowL10nId],
         ["http://b", params.allowL10nId],
         ["http://z", params.allowL10nId],
       ]);
 
@@ -442,17 +434,17 @@ add_task(async function testSort() {
         ["http://a", params.allowL10nId],
       ]);
 
       apply();
       await observeAllPromise;
 
       for (let URL of ["http://a", "http://z", "http://b"]) {
         let uri = Services.io.newURI(URL);
-        PermissionTestUtils.remove(uri, "cookie");
+        Services.perms.remove(uri, "cookie");
       }
     },
     params => {
       return [
         {
           type: "cookie",
           origin: "http://a",
           data: "added",
--- a/browser/components/preferences/in-content/tests/browser_permissions_dialog.js
+++ b/browser/components/preferences/in-content/tests/browser_permissions_dialog.js
@@ -2,19 +2,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/. */
 
 var { SitePermissions } = ChromeUtils.import(
   "resource:///modules/SitePermissions.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const PERMISSIONS_URL =
   "chrome://browser/content/preferences/sitePermissions.xul";
 const URL = "http://www.example.com";
 const URI = Services.io.newURI(URL);
 var sitePermissionsDialog;
 
@@ -53,305 +50,240 @@ add_task(async function addPermission() 
   // First item in the richlistbox contains column headers.
   Assert.equal(
     richlistbox.itemCount,
     0,
     "Number of permission items is 0 initially"
   );
 
   // Add notification permission for a website.
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Observe the added permission changes in the dialog UI.
   Assert.equal(richlistbox.itemCount, 1);
   checkPermissionItem(URL, Services.perms.ALLOW_ACTION);
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 });
 
 add_task(async function observePermissionChange() {
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Change the permission.
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.DENY_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.BLOCK);
 
   checkPermissionItem(URL, Services.perms.DENY_ACTION);
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 });
 
 add_task(async function observePermissionDelete() {
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   Assert.equal(
     richlistbox.itemCount,
     1,
     "The box contains one permission item initially"
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 
   Assert.equal(richlistbox.itemCount, 0);
 });
 
 add_task(async function onPermissionChange() {
   let doc = sitePermissionsDialog.document;
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Change the permission state in the UI.
   doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click();
 
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION,
+    SitePermissions.get(URI, "desktop-notification").state,
+    SitePermissions.ALLOW,
     "Permission state does not change before saving changes"
   );
 
   doc.getElementById("btnApplyChanges").click();
 
   await TestUtils.waitForCondition(
     () =>
-      PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-        .capability == Services.perms.DENY_ACTION
+      SitePermissions.get(URI, "desktop-notification").state ==
+      SitePermissions.BLOCK
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 });
 
 add_task(async function onPermissionDelete() {
   await openPermissionsDialog();
 
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   richlistbox.selectItem(richlistbox.getItemAtIndex(0));
   doc.getElementById("removePermission").click();
 
   await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
 
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION,
+    SitePermissions.get(URI, "desktop-notification").state,
+    SitePermissions.ALLOW,
     "Permission is not deleted before saving changes"
   );
 
   doc.getElementById("btnApplyChanges").click();
 
   await TestUtils.waitForCondition(
     () =>
-      PermissionTestUtils.getPermissionObject(URI, "desktop-notification") ==
-      null
+      SitePermissions.get(URI, "desktop-notification").state ==
+      SitePermissions.UNKNOWN
   );
 });
 
 add_task(async function onAllPermissionsDelete() {
   await openPermissionsDialog();
 
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
   let u = Services.io.newURI("http://www.test.com");
-  PermissionTestUtils.add(
-    u,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(u, "desktop-notification", SitePermissions.ALLOW);
 
   doc.getElementById("removeAllPermissions").click();
   await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
 
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION
+    SitePermissions.get(URI, "desktop-notification").state,
+    SitePermissions.ALLOW
   );
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(u, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION,
+    SitePermissions.get(u, "desktop-notification").state,
+    SitePermissions.ALLOW,
     "Permissions are not deleted before saving changes"
   );
 
   doc.getElementById("btnApplyChanges").click();
 
   await TestUtils.waitForCondition(
     () =>
-      PermissionTestUtils.getPermissionObject(URI, "desktop-notification") ==
-        null &&
-      PermissionTestUtils.getPermissionObject(u, "desktop-notification") == null
+      SitePermissions.get(URI, "desktop-notification").state ==
+        SitePermissions.UNKNOWN &&
+      SitePermissions.get(u, "desktop-notification").state ==
+        SitePermissions.UNKNOWN
   );
 });
 
 add_task(async function onPermissionChangeAndDelete() {
   await openPermissionsDialog();
 
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Change the permission state in the UI.
   doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click();
 
   // Remove that permission by clicking the "Remove" button.
   richlistbox.selectItem(richlistbox.getItemAtIndex(0));
   doc.getElementById("removePermission").click();
 
   await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
 
   doc.getElementById("btnApplyChanges").click();
 
   await TestUtils.waitForCondition(
     () =>
-      PermissionTestUtils.getPermissionObject(URI, "desktop-notification") ==
-      null
+      SitePermissions.get(URI, "desktop-notification").state ==
+      SitePermissions.UNKNOWN
   );
 });
 
 add_task(async function onPermissionChangeCancel() {
   await openPermissionsDialog();
 
   let doc = sitePermissionsDialog.document;
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Change the permission state in the UI.
   doc.getElementsByAttribute("value", SitePermissions.BLOCK)[0].click();
 
   doc.getElementById("cancel").click();
 
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION,
+    SitePermissions.get(URI, "desktop-notification").state,
+    SitePermissions.ALLOW,
     "Permission state does not change on clicking cancel"
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 });
 
 add_task(async function onPermissionDeleteCancel() {
   await openPermissionsDialog();
 
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
 
   // Remove that permission by clicking the "Remove" button.
   richlistbox.selectItem(richlistbox.getItemAtIndex(0));
   doc.getElementById("removePermission").click();
 
   await TestUtils.waitForCondition(() => richlistbox.itemCount == 0);
 
   doc.getElementById("cancel").click();
 
   Assert.equal(
-    PermissionTestUtils.getPermissionObject(URI, "desktop-notification")
-      .capability,
-    Services.perms.ALLOW_ACTION,
+    SitePermissions.get(URI, "desktop-notification").state,
+    SitePermissions.ALLOW,
     "Permission state does not change on clicking cancel"
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
 });
 
 add_task(async function onSearch() {
   await openPermissionsDialog();
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
   let searchBox = doc.getElementById("searchBox");
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
   searchBox.value = "www.example.com";
 
   let u = Services.io.newURI("http://www.test.com");
-  PermissionTestUtils.add(
-    u,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(u, "desktop-notification", SitePermissions.ALLOW);
 
   Assert.equal(
     doc.getElementsByAttribute("origin", "http://www.test.com")[0],
     null
   );
   Assert.equal(
     doc.getElementsByAttribute("origin", "http://www.example.com")[0],
     richlistbox.getItemAtIndex(0)
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
-  PermissionTestUtils.remove(u, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
+  SitePermissions.remove(u, "desktop-notification");
 
   doc.getElementById("cancel").click();
 });
 
 add_task(async function onPermissionsSort() {
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
   let u = Services.io.newURI("http://www.test.com");
-  PermissionTestUtils.add(
-    u,
-    "desktop-notification",
-    Services.perms.DENY_ACTION
-  );
+  SitePermissions.set(u, "desktop-notification", SitePermissions.BLOCK);
 
   await openPermissionsDialog();
   let doc = sitePermissionsDialog.document;
   let richlistbox = doc.getElementById("permissionsBox");
 
   // Test default arrangement(Allow followed by Block).
   Assert.equal(
     richlistbox.getItemAtIndex(0).getAttribute("origin"),
@@ -393,18 +325,18 @@ add_task(async function onPermissionsSor
     richlistbox.getItemAtIndex(0).getAttribute("origin"),
     "http://www.test.com"
   );
   Assert.equal(
     richlistbox.getItemAtIndex(1).getAttribute("origin"),
     "http://www.example.com"
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
-  PermissionTestUtils.remove(u, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
+  SitePermissions.remove(u, "desktop-notification");
 
   doc.getElementById("cancel").click();
 });
 
 add_task(async function onPermissionDisable() {
   // Enable desktop-notification permission prompts.
   Services.prefs.setIntPref(
     "permissions.default.desktop-notification",
@@ -491,27 +423,19 @@ add_task(async function checkDefaultPerm
 
 add_task(async function testTabBehaviour() {
   // Test tab behaviour inside the permissions setting dialog when site permissions are selected.
   // Only selected items in the richlistbox should be tabable for accessibility reasons.
 
   // Force tabfocus for all elements on OSX.
   SpecialPowers.pushPrefEnv({ set: [["accessibility.tabfocus", 7]] });
 
-  PermissionTestUtils.add(
-    URI,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(URI, "desktop-notification", SitePermissions.ALLOW);
   let u = Services.io.newURI("http://www.test.com");
-  PermissionTestUtils.add(
-    u,
-    "desktop-notification",
-    Services.perms.ALLOW_ACTION
-  );
+  SitePermissions.set(u, "desktop-notification", SitePermissions.ALLOW);
 
   await openPermissionsDialog();
   let doc = sitePermissionsDialog.document;
 
   EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog);
   let richlistbox = doc.getElementById("permissionsBox");
   is(
     richlistbox,
@@ -533,17 +457,17 @@ add_task(async function testTabBehaviour
   EventUtils.synthesizeKey("KEY_Tab", {}, sitePermissionsDialog);
   let removeButton = doc.getElementById("removePermission");
   is(
     removeButton,
     doc.activeElement,
     "The focus moves outside the richlistbox and onto the remove button"
   );
 
-  PermissionTestUtils.remove(URI, "desktop-notification");
-  PermissionTestUtils.remove(u, "desktop-notification");
+  SitePermissions.remove(URI, "desktop-notification");
+  SitePermissions.remove(u, "desktop-notification");
 
   doc.getElementById("cancel").click();
 });
 
 add_task(async function removeTab() {
   gBrowser.removeCurrentTab();
 });
--- a/browser/components/preferences/in-content/tests/head.js
+++ b/browser/components/preferences/in-content/tests/head.js
@@ -1,15 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 ChromeUtils.import("resource://gre/modules/Promise.jsm", this);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const kDefaultWait = 2000;
 
 function is_element_visible(aElement, aMsg) {
   isnot(aElement, null, "Element should not be null, when checking visibility");
   ok(!BrowserTestUtils.is_hidden(aElement), aMsg);
 }
 
--- a/browser/components/preferences/in-content/tests/siteData/browser_clearSiteData.js
+++ b/browser/components/preferences/in-content/tests/siteData/browser_clearSiteData.js
@@ -1,26 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 var { SitePermissions } = ChromeUtils.import(
   "resource:///modules/SitePermissions.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 async function testClearData(clearSiteData, clearCache) {
-  PermissionTestUtils.add(
-    TEST_QUOTA_USAGE_ORIGIN,
-    "persistent-storage",
-    Services.perms.ALLOW_ACTION
-  );
+  let quotaURI = Services.io.newURI(TEST_QUOTA_USAGE_ORIGIN);
+  SitePermissions.set(quotaURI, "persistent-storage", SitePermissions.ALLOW);
 
   // Open a test site which saves into appcache.
   await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_OFFLINE_URL);
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
   // Fill indexedDB with test data.
   // Don't wait for the page to load, to register the content event handler as quickly as possible.
   // If this test goes intermittent, we might have to tell the page to wait longer before
@@ -179,23 +173,23 @@ async function testClearData(clearSiteDa
         await ContentTaskUtils.waitForCondition(
           () => sizeLabel.textContent != opts.initialSizeLabelValue,
           "Site data size label should have updated."
         );
       }
     );
   }
 
-  let permission = PermissionTestUtils.getPermissionObject(
-    TEST_QUOTA_USAGE_ORIGIN,
-    "persistent-storage"
-  );
+  let desiredPermissionState = clearSiteData
+    ? SitePermissions.UNKNOWN
+    : SitePermissions.ALLOW;
+  let permission = SitePermissions.get(quotaURI, "persistent-storage");
   is(
-    clearSiteData ? permission : permission.capability,
-    clearSiteData ? null : Services.perms.ALLOW_ACTION,
+    permission.state,
+    desiredPermissionState,
     "Should have the correct permission state."
   );
 
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
   await SiteDataManager.removeAll();
 }
 
 // Test opening the "Clear All Data" dialog and cancelling.
--- a/browser/components/translation/test/browser_translation_exceptions.js
+++ b/browser/components/translation/test/browser_translation_exceptions.js
@@ -1,19 +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/. */
 
 // tests the translation infobar, using a fake 'Translation' implementation.
 
 var tmp = {};
 ChromeUtils.import("resource:///modules/translation/Translation.jsm", tmp);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 var { Translation } = tmp;
 
 const kLanguagesPref = "browser.translation.neverForLanguages";
 const kShowUIPref = "browser.translation.ui.show";
 
 function test() {
   waitForExplicitFinish();
 
@@ -238,17 +235,17 @@ var gTests = [
       // Open the "options" drop down.
       await openPopup(notif._getAnonElt("options"));
       ok(
         notif._getAnonElt("neverForSite").disabled,
         "The 'Never translate French' item is disabled"
       );
 
       // Cleanup.
-      PermissionTestUtils.remove("http://example.com", "translate");
+      Services.perms.remove(makeURI("http://example.com"), "translate");
       notif.close();
     },
   },
 
   {
     desc: "language exception list",
     run: async function checkLanguageExceptions() {
       // Put 2 languages in the pref before opening the window to check
@@ -305,26 +302,19 @@ var gTests = [
     },
   },
 
   {
     desc: "domains exception list",
     run: async function checkDomainExceptions() {
       // Put 2 exceptions before opening the window to check the list is
       // displayed on load.
-      PermissionTestUtils.add(
-        "http://example.org",
-        "translate",
-        Services.perms.DENY_ACTION
-      );
-      PermissionTestUtils.add(
-        "http://example.com",
-        "translate",
-        Services.perms.DENY_ACTION
-      );
+      let perms = Services.perms;
+      perms.add(makeURI("http://example.org"), "translate", perms.DENY_ACTION);
+      perms.add(makeURI("http://example.com"), "translate", perms.DENY_ACTION);
 
       // Open the translation exceptions dialog.
       let win = openDialog(
         "chrome://browser/content/preferences/translation.xul",
         "Browser:TranslationExceptions",
         "",
         null
       );
@@ -344,28 +334,24 @@ var gTests = [
       ok(!remove.disabled, "The 'Remove Site' button is enabled");
 
       // Click the 'Remove' button.
       remove.click();
       is(tree.view.rowCount, 1, "The site exceptions now contains 1 item");
       is(getDomainExceptions().length, 1, "One exception in the permissions");
 
       // Clear the permissions, and check the last item is removed from the display.
-      PermissionTestUtils.remove("http://example.org", "translate");
-      PermissionTestUtils.remove("http://example.com", "translate");
+      perms.remove(makeURI("http://example.org"), "translate");
+      perms.remove(makeURI("http://example.com"), "translate");
       is(tree.view.rowCount, 0, "The site exceptions list is empty");
       ok(remove.disabled, "The 'Remove Site' button is disabled");
       ok(removeAll.disabled, "The 'Remove All Site' button is disabled");
 
       // Add an item and check it appears.
-      PermissionTestUtils.add(
-        "http://example.com",
-        "translate",
-        Services.perms.DENY_ACTION
-      );
+      perms.add(makeURI("http://example.com"), "translate", perms.DENY_ACTION);
       is(tree.view.rowCount, 1, "The site exceptions list has 1 item");
       ok(remove.disabled, "The 'Remove Site' button is disabled");
       ok(!removeAll.disabled, "The 'Remove All Sites' button is enabled");
 
       // Click the 'Remove All' button.
       removeAll.click();
       is(tree.view.rowCount, 0, "The site exceptions list is empty");
       ok(remove.disabled, "The 'Remove Site' button is disabled");
--- a/browser/components/uitour/test/browser_no_tabs.js
+++ b/browser/components/uitour/test/browser_no_tabs.js
@@ -55,17 +55,18 @@ function destroyHiddenBrowser(aFrame, aB
  * browsers).
  */
 add_task(async function test_windowless_UITour() {
   // Get the URL for the test page.
   let pageURL = getRootDirectory(gTestPath) + "uitour.html";
 
   // Allow the URL to use the UITour.
   info("Adding UITour permission to the test page.");
-  PermissionTestUtils.add(pageURL, "uitour", Services.perms.ALLOW_ACTION);
+  let pageURI = Services.io.newURI(pageURL);
+  Services.perms.add(pageURI, "uitour", Services.perms.ALLOW_ACTION);
 
   // UITour's ping will resolve this promise.
   await new Promise(resolve => {
     // Create a windowless browser and test that UITour works in it.
     let browserPromise = createHiddenBrowser(pageURL);
     browserPromise.then(frameInfo => {
       isnot(frameInfo.browser, null, "The browser must exist and not be null.");
 
--- a/browser/components/uitour/test/head.js
+++ b/browser/components/uitour/test/head.js
@@ -4,20 +4,16 @@
 /* global gTestTab:true, gContentAPI:true, gContentWindow:true, tests:false */
 
 ChromeUtils.defineModuleGetter(
   this,
   "UITour",
   "resource:///modules/UITour.jsm"
 );
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const SINGLE_TRY_TIMEOUT = 100;
 const NUMBER_OF_TRIES = 30;
 
 function waitForConditionPromise(
   condition,
   timeoutMsg,
   tryCount = NUMBER_OF_TRIES
 ) {
@@ -445,45 +441,37 @@ function loadUITourTestPage(callback, ho
 // Wrapper for UITourTest to be used by add_task tests.
 function setup_UITourTest() {
   return UITourTest(true);
 }
 
 // Use `add_task(setup_UITourTest);` instead as we will fold this into `setup_UITourTest` once all tests are using `add_UITour_task`.
 function UITourTest(usingAddTask = false) {
   Services.prefs.setBoolPref("browser.uitour.enabled", true);
-  let testHttpsOrigin = "https://example.org";
-  let testHttpOrigin = "http://example.org";
-  PermissionTestUtils.add(
-    testHttpsOrigin,
-    "uitour",
-    Services.perms.ALLOW_ACTION
-  );
-  PermissionTestUtils.add(
-    testHttpOrigin,
-    "uitour",
-    Services.perms.ALLOW_ACTION
-  );
+  let testHttpsUri = Services.io.newURI("https://example.org");
+  let testHttpUri = Services.io.newURI("http://example.org");
+  Services.perms.add(testHttpsUri, "uitour", Services.perms.ALLOW_ACTION);
+  Services.perms.add(testHttpUri, "uitour", Services.perms.ALLOW_ACTION);
 
   // If a test file is using add_task, we don't need to have a test function or
   // call `waitForExplicitFinish`.
   if (!usingAddTask) {
     waitForExplicitFinish();
   }
 
   registerCleanupFunction(function() {
     delete window.gContentWindow;
     delete window.gContentAPI;
     if (gTestTab) {
       gBrowser.removeTab(gTestTab);
     }
     delete window.gTestTab;
     Services.prefs.clearUserPref("browser.uitour.enabled");
-    PermissionTestUtils.remove(testHttpsOrigin, "uitour");
-    PermissionTestUtils.remove(testHttpOrigin, "uitour");
+    Services.perms.remove(testHttpsUri, "uitour");
+    Services.perms.remove(testHttpUri, "uitour");
   });
 
   // When using tasks, the harness will call the next added task for us.
   if (!usingAddTask) {
     nextTest();
   }
 }
 
--- a/browser/modules/test/browser/browser_PermissionUI.js
+++ b/browser/modules/test/browser/browser_PermissionUI.js
@@ -4,19 +4,16 @@
  * add-ons can introduce their own permission prompts.
  */
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/Integration.jsm", this);
 ChromeUtils.import("resource:///modules/PermissionUI.jsm", this);
 ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 /**
  * Tests the PermissionPromptForRequest prototype to ensure that a prompt
  * can be displayed. Does not test permission handling.
  */
 add_task(async function test_permission_prompt_for_request() {
   await BrowserTestUtils.withNewTab(
     {
@@ -195,17 +192,17 @@ add_task(async function test_with_permis
         callback() {
           denied = true;
         },
       };
 
       let mockRequest = makeMockPermissionRequest(browser);
       let principal = mockRequest.principal;
       registerCleanupFunction(function() {
-        PermissionTestUtils.remove(principal.URI, kTestPermissionKey);
+        SitePermissions.remove(principal.URI, kTestPermissionKey);
       });
 
       let TestPrompt = {
         __proto__: PermissionUI.PermissionPromptForRequestPrototype,
         request: mockRequest,
         notificationID: kTestNotificationID,
         permissionKey: kTestPermissionKey,
         message: kTestMessage,
@@ -226,18 +223,18 @@ add_task(async function test_with_permis
       TestPrompt.prompt();
       await shownPromise;
       let notification = PopupNotifications.getNotification(
         kTestNotificationID,
         browser
       );
       Assert.ok(notification, "Should have gotten the notification");
 
-      let curPerm = SitePermissions.getForPrincipal(
-        principal,
+      let curPerm = SitePermissions.get(
+        principal.URI,
         kTestPermissionKey,
         browser
       );
       Assert.equal(
         curPerm.state,
         SitePermissions.UNKNOWN,
         "Should be no permission set to begin with."
       );
@@ -247,56 +244,48 @@ add_task(async function test_with_permis
       popupNotification.checkbox.checked = false;
 
       Assert.equal(
         notification.secondaryActions.length,
         1,
         "There should only be 1 secondary action"
       );
       await clickSecondaryAction();
-      curPerm = SitePermissions.getForPrincipal(
-        principal,
-        kTestPermissionKey,
-        browser
-      );
+      curPerm = SitePermissions.get(principal.URI, kTestPermissionKey, browser);
       Assert.deepEqual(
         curPerm,
         {
           state: SitePermissions.BLOCK,
           scope: SitePermissions.SCOPE_TEMPORARY,
         },
         "Should have denied the action temporarily"
       );
       // Try getting the permission without passing the browser object (should fail).
-      curPerm = PermissionTestUtils.getPermissionObject(
-        principal.URI,
-        kTestPermissionKey
-      );
-      Assert.equal(
+      curPerm = SitePermissions.get(principal.URI, kTestPermissionKey);
+      Assert.deepEqual(
         curPerm,
-        null,
+        {
+          state: SitePermissions.UNKNOWN,
+          scope: SitePermissions.SCOPE_PERSISTENT,
+        },
         "Should have made no permanent permission entry"
       );
       Assert.ok(denied, "The secondaryAction callback should have fired");
       Assert.ok(!allowed, "The mainAction callback should not have fired");
       Assert.ok(
         mockRequest._cancelled,
         "The request should have been cancelled"
       );
       Assert.ok(
         !mockRequest._allowed,
         "The request should not have been allowed"
       );
 
       // Clear the permission and pretend we never denied
-      SitePermissions.removeFromPrincipal(
-        principal,
-        kTestPermissionKey,
-        browser
-      );
+      SitePermissions.remove(principal.URI, kTestPermissionKey, browser);
       denied = false;
       mockRequest._cancelled = false;
 
       // Bring the PopupNotification back up now...
       shownPromise = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
@@ -305,62 +294,60 @@ add_task(async function test_with_permis
 
       // Test denying the permission request.
       Assert.equal(
         notification.secondaryActions.length,
         1,
         "There should only be 1 secondary action"
       );
       await clickSecondaryAction();
-      curPerm = PermissionTestUtils.getPermissionObject(
-        principal.URI,
-        kTestPermissionKey
-      );
-      Assert.equal(
-        curPerm.capability,
-        Services.perms.DENY_ACTION,
+      curPerm = SitePermissions.get(principal.URI, kTestPermissionKey);
+      Assert.deepEqual(
+        curPerm,
+        {
+          state: SitePermissions.BLOCK,
+          scope: SitePermissions.SCOPE_PERSISTENT,
+        },
         "Should have denied the action"
       );
-      Assert.equal(curPerm.expireTime, 0, "Deny should be permanent");
       Assert.ok(denied, "The secondaryAction callback should have fired");
       Assert.ok(!allowed, "The mainAction callback should not have fired");
       Assert.ok(
         mockRequest._cancelled,
         "The request should have been cancelled"
       );
       Assert.ok(
         !mockRequest._allowed,
         "The request should not have been allowed"
       );
 
       // Clear the permission and pretend we never denied
-      PermissionTestUtils.remove(principal.URI, kTestPermissionKey);
+      SitePermissions.remove(principal.URI, kTestPermissionKey);
       denied = false;
       mockRequest._cancelled = false;
 
       // Bring the PopupNotification back up now...
       shownPromise = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
       TestPrompt.prompt();
       await shownPromise;
 
       // Test allowing the permission request.
       await clickMainAction();
-      curPerm = PermissionTestUtils.getPermissionObject(
-        principal.URI,
-        kTestPermissionKey
-      );
-      Assert.equal(
-        curPerm.capability,
-        Services.perms.ALLOW_ACTION,
+      curPerm = SitePermissions.get(principal.URI, kTestPermissionKey);
+      Assert.deepEqual(
+        curPerm,
+        {
+          state: SitePermissions.ALLOW,
+          scope: SitePermissions.SCOPE_PERSISTENT,
+        },
         "Should have allowed the action"
       );
-      Assert.equal(curPerm.expireTime, 0, "Allow should be permanent");
       Assert.ok(!denied, "The secondaryAction callback should not have fired");
       Assert.ok(allowed, "The mainAction callback should have fired");
       Assert.ok(
         !mockRequest._cancelled,
         "The request should not have been cancelled"
       );
       Assert.ok(mockRequest._allowed, "The request should have been allowed");
     }
--- a/browser/modules/test/browser/browser_PermissionUI_prompts.js
+++ b/browser/modules/test/browser/browser_PermissionUI_prompts.js
@@ -4,19 +4,16 @@
  * add-ons can introduce their own permission prompts.
  */
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/Integration.jsm", this);
 ChromeUtils.import("resource:///modules/PermissionUI.jsm", this);
 ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 // Tests that GeolocationPermissionPrompt works as expected
 add_task(async function test_geo_permission_prompt() {
   await testPrompt(PermissionUI.GeolocationPermissionPrompt);
 });
 
 // Tests that DesktopNotificationPermissionPrompt works as expected
 add_task(async function test_desktop_notification_permission_prompt() {
@@ -55,17 +52,17 @@ async function testPrompt(Prompt) {
       let mockRequest = makeMockPermissionRequest(browser);
       let principal = mockRequest.principal;
       let TestPrompt = new Prompt(mockRequest);
       let permissionKey =
         TestPrompt.usePermissionManager && TestPrompt.permissionKey;
 
       registerCleanupFunction(function() {
         if (permissionKey) {
-          PermissionTestUtils.remove(principal.URI, permissionKey);
+          SitePermissions.remove(principal.URI, permissionKey);
         }
       });
 
       let shownPromise = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
       TestPrompt.prompt();
@@ -73,21 +70,17 @@ async function testPrompt(Prompt) {
       let notification = PopupNotifications.getNotification(
         TestPrompt.notificationID,
         browser
       );
       Assert.ok(notification, "Should have gotten the notification");
 
       let curPerm;
       if (permissionKey) {
-        curPerm = SitePermissions.getForPrincipal(
-          principal,
-          permissionKey,
-          browser
-        );
+        curPerm = SitePermissions.get(principal.URI, permissionKey, browser);
         Assert.equal(
           curPerm.state,
           SitePermissions.UNKNOWN,
           "Should be no permission set to begin with."
         );
       }
 
       // First test denying the permission request without the checkbox checked.
@@ -111,21 +104,17 @@ async function testPrompt(Prompt) {
         notification.secondaryActions.length,
         expectedSecondaryActionsCount,
         "There should only be " +
           expectedSecondaryActionsCount +
           " secondary action(s)"
       );
       await clickSecondaryAction();
       if (permissionKey) {
-        curPerm = SitePermissions.getForPrincipal(
-          principal,
-          permissionKey,
-          browser
-        );
+        curPerm = SitePermissions.get(principal.URI, permissionKey, browser);
         Assert.deepEqual(
           curPerm,
           {
             state: SitePermissions.BLOCK,
             scope: SitePermissions.SCOPE_TEMPORARY,
           },
           "Should have denied the action temporarily"
         );
@@ -134,17 +123,17 @@ async function testPrompt(Prompt) {
           mockRequest._cancelled,
           "The request should have been cancelled"
         );
         Assert.ok(
           !mockRequest._allowed,
           "The request should not have been allowed"
         );
 
-        SitePermissions.removeFromPrincipal(principal, permissionKey, browser);
+        SitePermissions.remove(principal.URI, permissionKey, browser);
         mockRequest._cancelled = false;
       }
 
       // Bring the PopupNotification back up now...
       shownPromise = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
@@ -165,38 +154,37 @@ async function testPrompt(Prompt) {
         notification.secondaryActions.length,
         expectedSecondaryActionsCount,
         "There should only be " +
           expectedSecondaryActionsCount +
           " secondary action(s)"
       );
       await clickSecondaryAction(secondaryActionToClickIndex);
       if (permissionKey) {
-        curPerm = PermissionTestUtils.getPermissionObject(
-          principal.URI,
-          permissionKey
+        curPerm = SitePermissions.get(principal.URI, permissionKey);
+        Assert.deepEqual(
+          curPerm,
+          {
+            state: SitePermissions.BLOCK,
+            scope: SitePermissions.SCOPE_PERSISTENT,
+          },
+          "Should have denied the action permanently"
         );
-        Assert.equal(
-          curPerm.capability,
-          Services.perms.DENY_ACTION,
-          "Should have denied the action"
-        );
-        Assert.equal(curPerm.expireTime, 0, "Deny should be permanent");
         Assert.ok(
           mockRequest._cancelled,
           "The request should have been cancelled"
         );
         Assert.ok(
           !mockRequest._allowed,
           "The request should not have been allowed"
         );
       }
 
       if (permissionKey) {
-        PermissionTestUtils.remove(principal.URI, permissionKey);
+        SitePermissions.remove(principal.URI, permissionKey);
         mockRequest._cancelled = false;
       }
 
       // Bring the PopupNotification back up now...
       shownPromise = BrowserTestUtils.waitForEvent(
         PopupNotifications.panel,
         "popupshown"
       );
@@ -204,26 +192,25 @@ async function testPrompt(Prompt) {
       await shownPromise;
 
       // Test allowing the permission request with the checkbox checked.
       popupNotification = getPopupNotificationNode();
       popupNotification.checkbox.checked = true;
 
       await clickMainAction();
       if (permissionKey) {
-        curPerm = PermissionTestUtils.getPermissionObject(
-          principal.URI,
-          permissionKey
+        curPerm = SitePermissions.get(principal.URI, permissionKey);
+        Assert.deepEqual(
+          curPerm,
+          {
+            state: SitePermissions.ALLOW,
+            scope: SitePermissions.SCOPE_PERSISTENT,
+          },
+          "Should have allowed the action permanently"
         );
-        Assert.equal(
-          curPerm.capability,
-          Services.perms.ALLOW_ACTION,
-          "Should have allowed the action"
-        );
-        Assert.equal(curPerm.expireTime, 0, "Allow should be permanent");
         Assert.ok(
           !mockRequest._cancelled,
           "The request should not have been cancelled"
         );
         Assert.ok(mockRequest._allowed, "The request should have been allowed");
       }
     }
   );
--- a/browser/modules/test/unit/test_SiteDataManager.js
+++ b/browser/modules/test/unit/test_SiteDataManager.js
@@ -8,19 +8,16 @@ const EXAMPLE_ORIGIN_2 = "https://exampl
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { SiteDataManager } = ChromeUtils.import(
   "resource:///modules/SiteDataManager.jsm"
 );
 const { SiteDataTestUtils } = ChromeUtils.import(
   "resource://testing-common/SiteDataTestUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 ChromeUtils.defineModuleGetter(
   this,
   "setTimeout",
   "resource://gre/modules/Timer.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "TestUtils",
@@ -117,17 +114,17 @@ add_task(async function testGetTotalUsag
 
   await SiteDataTestUtils.clear();
 });
 
 add_task(async function testRemove() {
   await SiteDataManager.updateSites();
 
   let uri = Services.io.newURI(EXAMPLE_ORIGIN);
-  PermissionTestUtils.add(uri, "camera", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
 
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
   await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
   await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
   await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
 
@@ -149,35 +146,35 @@ add_task(async function testRemove() {
   );
 
   let usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN);
   Assert.equal(usage, 0, "Has cleared quota usage for example.com");
 
   let cookies = Services.cookies.countCookiesFromHost("example.com");
   Assert.equal(cookies, 0, "Has cleared cookies for example.com");
 
-  let perm = PermissionTestUtils.testPermission(uri, "persistent-storage");
+  let perm = Services.perms.testPermission(uri, "persistent-storage");
   Assert.equal(
     perm,
     Services.perms.UNKNOWN_ACTION,
     "Cleared the persistent-storage permission."
   );
-  perm = PermissionTestUtils.testPermission(uri, "camera");
+  perm = Services.perms.testPermission(uri, "camera");
   Assert.equal(
     perm,
     Services.perms.ALLOW_ACTION,
     "Did not clear other permissions."
   );
 
-  PermissionTestUtils.remove(uri, "camera");
+  Services.perms.remove(uri, "camera");
 });
 
 add_task(async function testRemoveSiteData() {
   let uri = Services.io.newURI(EXAMPLE_ORIGIN);
-  PermissionTestUtils.add(uri, "camera", Services.perms.ALLOW_ACTION);
+  Services.perms.add(uri, "camera", Services.perms.ALLOW_ACTION);
 
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo1", "bar1");
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN, "foo2", "bar2");
   await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN, 4096);
   SiteDataTestUtils.addToCookies(EXAMPLE_ORIGIN_2, "foo", "bar");
   await SiteDataTestUtils.addToIndexedDB(EXAMPLE_ORIGIN_2, 2048);
   await SiteDataTestUtils.persist(EXAMPLE_ORIGIN_2);
 
@@ -197,23 +194,23 @@ add_task(async function testRemoveSiteDa
   Assert.equal(usage, 0, "Has cleared quota usage for example.com");
 
   usage = await SiteDataTestUtils.getQuotaUsage(EXAMPLE_ORIGIN_2);
   Assert.equal(usage, 0, "Has cleared quota usage for example.org");
 
   let cookies = Services.cookies.countCookiesFromHost("example.org");
   Assert.equal(cookies, 0, "Has cleared cookies for example.org");
 
-  let perm = PermissionTestUtils.testPermission(uri, "persistent-storage");
+  let perm = Services.perms.testPermission(uri, "persistent-storage");
   Assert.equal(
     perm,
     Services.perms.UNKNOWN_ACTION,
     "Cleared the persistent-storage permission."
   );
-  perm = PermissionTestUtils.testPermission(uri, "camera");
+  perm = Services.perms.testPermission(uri, "camera");
   Assert.equal(
     perm,
     Services.perms.ALLOW_ACTION,
     "Did not clear other permissions."
   );
 
-  PermissionTestUtils.remove(uri, "camera");
+  Services.perms.remove(uri, "camera");
 });
--- a/dom/indexedDB/test/unit/test_idle_maintenance.js
+++ b/dom/indexedDB/test/unit/test_idle_maintenance.js
@@ -10,21 +10,17 @@ function* testSteps() {
   let uri = Services.io.newURI("https://www.example.com");
   let principal = Services.scriptSecurityManager.createContentPrincipal(
     uri,
     {}
   );
 
   info("Setting permissions");
 
-  Services.perms.addFromPrincipal(
-    principal,
-    "indexedDB",
-    Ci.nsIPermissionManager.ALLOW_ACTION
-  );
+  Services.perms.add(uri, "indexedDB", Ci.nsIPermissionManager.ALLOW_ACTION);
 
   // The idle-daily notification is disabled in xpchsell tests, so we don't
   // need to do anything special to disable it for this test.
 
   info("Activating real idle service");
 
   do_get_idle();
 
--- a/dom/indexedDB/test/unit/test_storageOption_pref.js
+++ b/dom/indexedDB/test/unit/test_storageOption_pref.js
@@ -15,32 +15,27 @@ function* testSteps() {
     Services.prefs.clearUserPref("dom.indexedDB.storageOption.enabled");
   });
 
   const name = "Splendid Test";
   const version = 1;
   const origin = "https://example.com";
 
   // Avoid trying to show permission prompts on a window.
-  let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-    origin
-  );
-  Services.perms.addFromPrincipal(
-    principal,
-    "indexedDB",
-    Ci.nsIPermissionManager.ALLOW_ACTION
-  );
+  let uri = Services.io.newURI(origin);
+  Services.perms.add(uri, "indexedDB", Ci.nsIPermissionManager.ALLOW_ACTION);
 
   const objectStoreName = "Foo";
   const data = { key: 1, value: "bar" };
 
   // Turn the storage option off, content databases should be "default".
   Services.prefs.setBoolPref("dom.indexedDB.storageOption.enabled", false);
 
   // Open a database with content privileges.
+  let principal = getPrincipal(origin);
   let request = indexedDB.openForPrincipal(principal, name, {
     version,
     storage: "persistent",
   });
 
   request.onerror = errorHandler;
   request.onupgradeneeded = grabEventAndContinueHandler;
   request.onsuccess = grabEventAndContinueHandler;
--- a/dom/notification/test/browser/browser_permission_dismiss.js
+++ b/dom/notification/test/browser/browser_permission_dismiss.js
@@ -1,14 +1,10 @@
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const ORIGIN_URI = Services.io.newURI("https://example.com");
 const PERMISSION_NAME = "desktop-notification";
 const PROMPT_ALLOW_BUTTON = -1;
 const PROMPT_NOT_NOW_BUTTON = 0;
 const PROMPT_NEVER_BUTTON = 1;
 const TEST_URL =
   "https://example.com/browser/dom/notification/test/browser/notification.html";
 
@@ -44,17 +40,17 @@ function clickDoorhangerButton(aButtonIn
  * and verifies that the expected permission is set.
  *
  * @param {Function} task Task function to run to interact with the prompt.
  * @param {String} permission Expected permission value.
  * @return {Promise} resolving when the task function is done and the tab
  *                   closes.
  */
 function tabWithRequest(task, permission) {
-  PermissionTestUtils.remove(ORIGIN_URI, PERMISSION_NAME);
+  Services.perms.remove(ORIGIN_URI, PERMISSION_NAME);
 
   return BrowserTestUtils.withNewTab(
     {
       gBrowser,
       url: TEST_URL,
     },
     async function(browser) {
       let requestPromise = ContentTask.spawn(
@@ -93,62 +89,62 @@ function tabWithRequest(task, permission
 
 add_task(async function setup() {
   Services.prefs.setBoolPref(
     "dom.webnotifications.requireuserinteraction",
     false
   );
   SimpleTest.registerCleanupFunction(() => {
     Services.prefs.clearUserPref("dom.webnotifications.requireuserinteraction");
-    PermissionTestUtils.remove(ORIGIN_URI, PERMISSION_NAME);
+    Services.perms.remove(ORIGIN_URI, PERMISSION_NAME);
   });
 });
 
 add_task(async function test_requestPermission_granted() {
   await tabWithRequest(function() {
     clickDoorhangerButton(PROMPT_ALLOW_BUTTON);
   }, "granted");
 
   ok(
     !PopupNotifications.getNotification("web-notifications"),
     "Should remove the doorhanger notification icon if granted"
   );
 
   is(
-    PermissionTestUtils.testPermission(ORIGIN_URI, PERMISSION_NAME),
+    Services.perms.testPermission(ORIGIN_URI, PERMISSION_NAME),
     Services.perms.ALLOW_ACTION,
     "Check permission in perm. manager"
   );
 });
 
 add_task(async function test_requestPermission_denied_temporarily() {
   await tabWithRequest(function() {
     clickDoorhangerButton(PROMPT_NOT_NOW_BUTTON);
   }, "default");
 
   ok(
     !PopupNotifications.getNotification("web-notifications"),
     "Should remove the doorhanger notification icon if denied"
   );
 
   is(
-    PermissionTestUtils.testPermission(ORIGIN_URI, PERMISSION_NAME),
+    Services.perms.testPermission(ORIGIN_URI, PERMISSION_NAME),
     Services.perms.UNKNOWN_ACTION,
     "Check permission in perm. manager"
   );
 });
 
 add_task(async function test_requestPermission_denied_permanently() {
   await tabWithRequest(async function() {
     await clickDoorhangerButton(PROMPT_NEVER_BUTTON);
   }, "denied");
 
   ok(
     !PopupNotifications.getNotification("web-notifications"),
     "Should remove the doorhanger notification icon if denied"
   );
 
   is(
-    PermissionTestUtils.testPermission(ORIGIN_URI, PERMISSION_NAME),
+    Services.perms.testPermission(ORIGIN_URI, PERMISSION_NAME),
     Services.perms.DENY_ACTION,
     "Check permission in perm. manager"
   );
 });
--- a/dom/push/test/xpcshell/head.js
+++ b/dom/push/test/xpcshell/head.js
@@ -19,19 +19,16 @@ var { Preferences } = ChromeUtils.import
   "resource://gre/modules/Preferences.jsm"
 );
 var { PlacesUtils } = ChromeUtils.import(
   "resource://gre/modules/PlacesUtils.jsm"
 );
 var { ObjectUtils } = ChromeUtils.import(
   "resource://gre/modules/ObjectUtils.jsm"
 );
-var { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 ChromeUtils.defineModuleGetter(
   this,
   "PlacesTestUtils",
   "resource://testing-common/PlacesTestUtils.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
--- a/dom/push/test/xpcshell/test_drop_expired.js
+++ b/dom/push/test/xpcshell/test_drop_expired.js
@@ -18,23 +18,23 @@ function visitURI(uri, timestamp) {
     visitDate: timestamp * 1000,
     transition: Ci.nsINavHistoryService.TRANSITION_LINK,
   });
 }
 
 var putRecord = async function({ scope, perm, quota, lastPush, lastVisit }) {
   let uri = Services.io.newURI(scope);
 
-  PermissionTestUtils.add(
+  Services.perms.add(
     uri,
     "desktop-notification",
     Ci.nsIPermissionManager[perm]
   );
   registerCleanupFunction(() => {
-    PermissionTestUtils.remove(uri, "desktop-notification");
+    Services.perms.remove(uri, "desktop-notification");
   });
 
   await visitURI(uri, lastVisit);
 
   await db.put({
     channelID: uri.pathQueryRef,
     pushEndpoint: "https://example.org/push" + uri.pathQueryRef,
     scope: uri.spec,
@@ -151,16 +151,16 @@ add_task(async function test_site_visite
 });
 
 add_task(async function test_perm_restored() {
   let subChangePromise = promiseObserverNotification(
     PushServiceComponent.subscriptionChangeTopic,
     (subject, data) => data == "https://example.info/expired-perm-revoked"
   );
 
-  PermissionTestUtils.add(
+  Services.perms.add(
     permURI,
     "desktop-notification",
     Ci.nsIPermissionManager.ALLOW_ACTION
   );
 
   await subChangePromise;
 });
--- a/dom/push/test/xpcshell/test_quota_observer.js
+++ b/dom/push/test/xpcshell/test_quota_observer.js
@@ -15,23 +15,23 @@ function run_test() {
     userAgentID,
   });
   run_next_test();
 }
 
 let putRecord = async function(perm, record) {
   let uri = Services.io.newURI(record.scope);
 
-  PermissionTestUtils.add(
+  Services.perms.add(
     uri,
     "desktop-notification",
     Ci.nsIPermissionManager[perm]
   );
   registerCleanupFunction(() => {
-    PermissionTestUtils.remove(uri, "desktop-notification");
+    Services.perms.remove(uri, "desktop-notification");
   });
 
   await db.put(record);
 };
 
 add_task(async function test_expiration_history_observer() {
   db = PushServiceWebSocket.newPushDB();
   registerCleanupFunction(() => db.drop().then(_ => db.close()));
--- a/dom/push/test/xpcshell/test_record.js
+++ b/dom/push/test/xpcshell/test_record.js
@@ -85,28 +85,28 @@ function testPermissionCheck(props) {
       `Origin suffixes should match for ${JSON.stringify(props)}`
     );
   }
   ok(
     !record.hasPermission(),
     `Record ${JSON.stringify(props)} should not have permission yet`
   );
   let permURI = Services.io.newURI(props.scope);
-  PermissionTestUtils.add(
+  Services.perms.add(
     permURI,
     "desktop-notification",
     Ci.nsIPermissionManager.ALLOW_ACTION
   );
   try {
     ok(
       record.hasPermission(),
       `Record ${JSON.stringify(props)} should have permission`
     );
   } finally {
-    PermissionTestUtils.remove(permURI, "desktop-notification");
+    Services.perms.remove(permURI, "desktop-notification");
   }
 }
 
 add_task(async function test_principal_permissions() {
   let testProps = [
     {
       scope: "https://example.com/",
     },
--- a/dom/serviceworkers/test/browser_storage_permission.js
+++ b/dom/serviceworkers/test/browser_storage_permission.js
@@ -1,14 +1,10 @@
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const BASE_URI = "http://mochi.test:8888/browser/dom/serviceworkers/test/";
 const PAGE_URI = BASE_URI + "empty.html";
 const SCOPE = PAGE_URI + "?storage_permission";
 const SW_SCRIPT = BASE_URI + "empty.js";
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({
     set: [
@@ -46,18 +42,18 @@ add_task(async function setup() {
       });
     }
   );
 
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_allow_permission() {
-  PermissionTestUtils.add(
-    PAGE_URI,
+  Services.perms.add(
+    Services.io.newURI(PAGE_URI),
     "cookie",
     Ci.nsICookiePermission.ACCESS_ALLOW
   );
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
@@ -66,62 +62,62 @@ add_task(async function test_allow_permi
   });
 
   ok(!!controller, "page should be controlled with storage allowed");
 
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_deny_permission() {
-  PermissionTestUtils.add(
-    PAGE_URI,
+  Services.perms.add(
+    Services.io.newURI(PAGE_URI),
     "cookie",
     Ci.nsICookiePermission.ACCESS_DENY
   );
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let controller = await ContentTask.spawn(browser, null, async function() {
     return content.navigator.serviceWorker.controller;
   });
 
   is(controller, null, "page should be not controlled with storage denied");
 
   BrowserTestUtils.removeTab(tab);
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 });
 
 add_task(async function test_session_permission() {
-  PermissionTestUtils.add(
-    PAGE_URI,
+  Services.perms.add(
+    Services.io.newURI(PAGE_URI),
     "cookie",
     Ci.nsICookiePermission.ACCESS_SESSION
   );
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let controller = await ContentTask.spawn(browser, null, async function() {
     return content.navigator.serviceWorker.controller;
   });
 
   is(controller, null, "page should be not controlled with session storage");
 
   BrowserTestUtils.removeTab(tab);
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 });
 
 // Test to verify an about:blank iframe successfully inherits the
 // parent's controller when storage is blocked between opening the
 // parent page and creating the iframe.
 add_task(async function test_block_storage_before_blank_iframe() {
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let controller = await ContentTask.spawn(browser, null, async function() {
     return content.navigator.serviceWorker.controller;
   });
@@ -155,17 +151,17 @@ add_task(async function test_block_stora
   await SpecialPowers.popPrefEnv();
   BrowserTestUtils.removeTab(tab);
 });
 
 // Test to verify a blob URL iframe successfully inherits the
 // parent's controller when storage is blocked between opening the
 // parent page and creating the iframe.
 add_task(async function test_block_storage_before_blob_iframe() {
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let controller = await ContentTask.spawn(browser, null, async function() {
     return content.navigator.serviceWorker.controller;
   });
@@ -211,17 +207,17 @@ add_task(async function test_block_stora
 });
 
 // Test to verify a blob worker script does not hit our service
 // worker storage assertions when storage is blocked between opening
 // the parent page and creating the worker.  Note, we cannot
 // explicitly check if the worker is controlled since we don't expose
 // WorkerNavigator.serviceWorkers.controller yet.
 add_task(async function test_block_storage_before_blob_worker() {
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 
   let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let controller = await ContentTask.spawn(browser, null, async function() {
     return content.navigator.serviceWorker.controller;
   });
@@ -264,17 +260,17 @@ add_task(async function test_block_stora
 
   ok(scriptURL2.startsWith("blob:"), "blob URL worker should run");
 
   await SpecialPowers.popPrefEnv();
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function cleanup() {
-  PermissionTestUtils.remove(PAGE_URI, "cookie");
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 
   let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   await ContentTask.spawn(browser, SCOPE, async function(uri) {
     let reg = await content.navigator.serviceWorker.getRegistration(uri);
     let worker = reg.active;
--- a/extensions/permissions/moz.build
+++ b/extensions/permissions/moz.build
@@ -1,20 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 TEST_DIRS += ['test']
 
-TESTING_JS_MODULES += [
-    'test/PermissionTestUtils.jsm',
-]
-
 UNIFIED_SOURCES += [
     'nsContentBlocker.cpp',
     'nsPermission.cpp',
     'nsPermissionManager.cpp',
 ]
 
 XPCOM_MANIFESTS += [
     'components.conf',
deleted file mode 100644
--- a/extensions/permissions/test/PermissionTestUtils.jsm
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * Utility module for tests to access the PermissionManager
- * with uri or origin string parameters.
- */
-
-"use strict";
-
-let pm = Cc["@mozilla.org/permissionmanager;1"].getService(
-  Ci.nsIPermissionManager
-);
-
-let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(
-  Ci.nsIScriptSecurityManager
-);
-
-const EXPORTED_SYMBOLS = ["PermissionTestUtils"];
-
-/**
- * Convert origin string or uri to principal.
- * If passed an nsIPrincipal it will be returned without conversion.
- * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject - Subject to convert to principal
- * @returns {Ci.nsIPrincipal} Principal created from subject
- */
-function convertToPrincipal(subject) {
-  if (subject instanceof Ci.nsIPrincipal) {
-    return subject;
-  }
-  if (typeof subject === "string") {
-    return secMan.createContentPrincipalFromOrigin(subject);
-  }
-  if (subject == null || subject instanceof Ci.nsIURI) {
-    return secMan.createContentPrincipal(subject, {});
-  }
-  throw new Error(
-    "subject parameter must be an nsIURI an origin string or a principal."
-  );
-}
-
-let PermissionTestUtils = {
-  /**
-   * Add permission information for a given subject.
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  add(subject, ...args) {
-    return pm.addFromPrincipal(convertToPrincipal(subject), ...args);
-  },
-  /**
-   * Get all custom permissions for a given subject.
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  getAll(subject, ...args) {
-    return pm.getAllForPrincipal(convertToPrincipal(subject), ...args);
-  },
-  /**
-   * Remove permission information for a given subject and permission type
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  remove(subject, ...args) {
-    return pm.removeFromPrincipal(convertToPrincipal(subject), ...args);
-  },
-  /**
-   * Test whether a website has permission to perform the given action.
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  testPermission(subject, ...args) {
-    return pm.testPermissionFromPrincipal(convertToPrincipal(subject), ...args);
-  },
-  /**
-   * Test whether a website has permission to perform the given action.
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  testExactPermission(subject, ...args) {
-    return pm.testExactPermissionFromPrincipal(
-      convertToPrincipal(subject),
-      ...args
-    );
-  },
-  /**
-   * Get the permission object associated with the given subject and action.
-   * Subject can be a principal, uri or origin string.
-   * @see nsIPermissionManager for documentation
-   *
-   * @param {Ci.nsIPrincipal|Ci.nsIURI|string} subject
-   * @param {*} args
-   */
-  getPermissionObject(subject, type, exactHost = false) {
-    return pm.getPermissionObject(convertToPrincipal(subject), type, exactHost);
-  },
-};
--- a/netwerk/cookie/test/browser/head.js
+++ b/netwerk/cookie/test/browser/head.js
@@ -1,12 +1,8 @@
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const BEHAVIOR_ACCEPT = Ci.nsICookieService.BEHAVIOR_ACCEPT;
 const BEHAVIOR_REJECT = Ci.nsICookieService.BEHAVIOR_REJECT;
 
 const PERM_DEFAULT = Ci.nsICookiePermission.ACCESS_DEFAULT;
 const PERM_ALLOW = Ci.nsICookiePermission.ACCESS_ALLOW;
 const PERM_DENY = Ci.nsICookiePermission.ACCESS_DENY;
 
 const TEST_DOMAIN = "https://example.com/";
@@ -85,18 +81,20 @@ this.CookiePolicyHelper = {
       info("Starting " + testName + ": " + config.toSource());
 
       await SpecialPowers.flushPrefEnv();
 
       if (prefs) {
         await SpecialPowers.pushPrefEnv({ set: prefs });
       }
 
+      let uri = Services.io.newURI(TEST_DOMAIN);
+
       // Let's set the first cookie pref.
-      PermissionTestUtils.add(TEST_DOMAIN, "cookie", config.fromPermission);
+      Services.perms.add(uri, "cookie", config.fromPermission);
       await SpecialPowers.pushPrefEnv({
         set: [["network.cookie.cookieBehavior", config.fromBehavior]],
       });
 
       // Let's open a tab and load content.
       let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
       gBrowser.selectedTab = tab;
 
@@ -130,17 +128,17 @@ this.CookiePolicyHelper = {
           await runnable(content);
 
           let ifr = content.document.getElementById("iframe");
           await runnable(ifr.contentWindow);
         }
       );
 
       // Now, let's change the cookie settings
-      PermissionTestUtils.add(TEST_DOMAIN, "cookie", config.toPermission);
+      Services.perms.add(uri, "cookie", config.toPermission);
       await SpecialPowers.pushPrefEnv({
         set: [["network.cookie.cookieBehavior", config.toBehavior]],
       });
 
       // We still want the good callback to succeed.
       info(
         "Executing the test after setting the cookie behavior to " +
           config.toBehavior +
--- a/netwerk/test/unit/test_bug767025.js
+++ b/netwerk/test/unit/test_bug767025.js
@@ -1,14 +1,11 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 
 const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 /**
  * This is testcase do following steps to make sure bug767025 removing
  * files as expection.
  *
  * STEPS:
  *  - Schedule a offline cache update for app.manifest.
  *    - pages/foo1, pages/foo2, pages/foo3, and pages/foo4 are cached.
@@ -105,17 +102,17 @@ function clean_app_cache() {
   storage.asyncEvictStorage(null);
 }
 
 function do_app_cache(manifestURL, pageURL) {
   let update_service = Cc[kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID].getService(
     Ci.nsIOfflineCacheUpdateService
   );
 
-  PermissionTestUtils.add(
+  Services.perms.add(
     manifestURL,
     "offline-app",
     Ci.nsIPermissionManager.ALLOW_ACTION
   );
 
   let update = update_service.scheduleUpdate(
     manifestURL,
     pageURL,
--- a/netwerk/test/unit/test_pinned_app_cache.js
+++ b/netwerk/test/unit/test_pinned_app_cache.js
@@ -26,19 +26,16 @@
  *     - The offline cache storage has only enough space for one
  *       additional page.  But, this is a pinned request,
  *       nsOfflineCacheService will make more space for this request
  *       by discarding app1 (non-pinned)
  *
  */
 
 const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 // const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 const kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID =
   "@mozilla.org/offlinecacheupdate-service;1";
 
 const kManifest1 =
   "CACHE MANIFEST\n" +
@@ -139,17 +136,17 @@ function clean_app_cache() {
   evict_cache_entries("appcache");
 }
 
 function do_app_cache(manifestURL, pageURL, pinned) {
   let update_service = Cc[kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID].getService(
     Ci.nsIOfflineCacheUpdateService
   );
 
-  PermissionTestUtils.add(
+  Services.perms.add(
     manifestURL,
     "pin-app",
     pinned
       ? Ci.nsIPermissionManager.ALLOW_ACTION
       : Ci.nsIPermissionManager.DENY_ACTION
   );
 
   let update = update_service.scheduleUpdate(
--- a/toolkit/components/antitracking/test/browser/browser_allowListSeparationInPrivateAndNormalWindows.js
+++ b/toolkit/components/antitracking/test/browser/browser_allowListSeparationInPrivateAndNormalWindows.js
@@ -10,21 +10,17 @@
 // private windows wouldn't send any blocking notifications as they don't have
 // storage access in the first place.
 
 /* import-globals-from antitracking_head.js */
 
 "use strict";
 add_task(async _ => {
   let uri = Services.io.newURI("https://example.net");
-  PermissionTestUtils.add(
-    uri,
-    "trackingprotection-pb",
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(uri, "trackingprotection-pb", Services.perms.ALLOW_ACTION);
 
   registerCleanupFunction(_ => {
     Services.perms.removeAll();
   });
 });
 
 AntiTracking.runTest(
   "Test that we don't honour a private allow list exception in a normal window",
--- a/toolkit/components/antitracking/test/browser/browser_allowPermissionForTracker.js
+++ b/toolkit/components/antitracking/test/browser/browser_allowPermissionForTracker.js
@@ -1,21 +1,21 @@
 // This test works by setting up an exception for the tracker domain, which
 // disables all the anti-tracking tests.
 
 /* import-globals-from antitracking_head.js */
 
 add_task(async _ => {
-  PermissionTestUtils.add(
-    "https://tracking.example.org",
+  Services.perms.add(
+    Services.io.newURI("https://tracking.example.org"),
     "cookie",
     Services.perms.ALLOW_ACTION
   );
-  PermissionTestUtils.add(
-    "https://tracking.example.com",
+  Services.perms.add(
+    Services.io.newURI("https://tracking.example.com"),
     "cookie",
     Services.perms.ALLOW_ACTION
   );
 
   registerCleanupFunction(_ => {
     Services.perms.removeAll();
   });
 });
--- a/toolkit/components/antitracking/test/browser/browser_denyPermissionForTracker.js
+++ b/toolkit/components/antitracking/test/browser/browser_denyPermissionForTracker.js
@@ -1,21 +1,21 @@
 // This test works by setting up an exception for the tracker domain, which
 // disables all the anti-tracking tests.
 
 /* import-globals-from antitracking_head.js */
 
 add_task(async _ => {
-  PermissionTestUtils.add(
-    "https://tracking.example.org",
+  Services.perms.add(
+    Services.io.newURI("https://tracking.example.org"),
     "cookie",
     Services.perms.DENY_ACTION
   );
-  PermissionTestUtils.add(
-    "https://tracking.example.com",
+  Services.perms.add(
+    Services.io.newURI("https://tracking.example.com"),
     "cookie",
     Services.perms.DENY_ACTION
   );
 
   registerCleanupFunction(_ => {
     Services.perms.removeAll();
   });
 });
--- a/toolkit/components/antitracking/test/browser/browser_permissionInNormalWindows.js
+++ b/toolkit/components/antitracking/test/browser/browser_permissionInNormalWindows.js
@@ -8,20 +8,18 @@ AntiTracking.runTest(
   },
 
   // Non blocking callback
   async _ => {
     try {
       let Services = SpecialPowers.Services;
       // We would use TEST_3RD_PARTY_DOMAIN here, except that the variable isn't
       // accessible in the context of the web page...
-      let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-        "https://tracking.example.org/"
-      );
-      for (let perm of Services.perms.getAllForPrincipal(principal)) {
+      let uri = Services.io.newURI("https://tracking.example.org/");
+      for (let perm of Services.perms.getAllForURI(uri)) {
         // Ignore permissions other than storage access
         if (!perm.type.startsWith("3rdPartyStorage^")) {
           continue;
         }
         is(
           perm.expireType,
           Services.perms.EXPIRE_TIME,
           "Permission must expire at a specific time"
--- a/toolkit/components/antitracking/test/browser/browser_permissionInPrivateWindows.js
+++ b/toolkit/components/antitracking/test/browser/browser_permissionInPrivateWindows.js
@@ -8,20 +8,18 @@ AntiTracking.runTest(
   },
 
   // Non blocking callback
   async _ => {
     try {
       let Services = SpecialPowers.Services;
       // We would use TEST_3RD_PARTY_DOMAIN here, except that the variable isn't
       // accessible in the context of the web page...
-      let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
-        "https://tracking.example.org/"
-      );
-      for (let perm of Services.perms.getAllForPrincipal(principal)) {
+      let uri = Services.io.newURI("https://tracking.example.org/");
+      for (let perm of Services.perms.getAllForURI(uri)) {
         // Ignore permissions other than storage access
         if (!perm.type.startsWith("3rdPartyStorage^")) {
           continue;
         }
         is(
           perm.expireType,
           Services.perms.EXPIRE_SESSION,
           "Permission must expire at the end of session"
--- a/toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessDoorHanger.js
@@ -237,39 +237,129 @@ async function preparePermissionsFromOth
   info("Faking permissions from other sites");
   let type = "3rdPartyStorage^https://tracking.example.org";
   let permission = Services.perms.ALLOW_ACTION;
   let expireType = Services.perms.EXPIRE_SESSION;
   if (topPage == TEST_TOP_PAGE) {
     // For the first page, don't do anything
   } else if (topPage == TEST_TOP_PAGE_2) {
     // For the second page, only add the permission from the first page
-    PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0);
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN),
+      type,
+      permission,
+      expireType,
+      0
+    );
   } else if (topPage == TEST_TOP_PAGE_3) {
     // For the third page, add the permissions from the first two pages
-    PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_2, type, permission, expireType, 0);
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_2),
+      type,
+      permission,
+      expireType,
+      0
+    );
   } else if (topPage == TEST_TOP_PAGE_4) {
     // For the fourth page, add the permissions from the first three pages
-    PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_2, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_3, type, permission, expireType, 0);
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_2),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_3),
+      type,
+      permission,
+      expireType,
+      0
+    );
   } else if (topPage == TEST_TOP_PAGE_5) {
     // For the fifth page, add the permissions from the first four pages
-    PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_2, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_3, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_4, type, permission, expireType, 0);
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_2),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_3),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_4),
+      type,
+      permission,
+      expireType,
+      0
+    );
   } else if (topPage == TEST_TOP_PAGE_6) {
     // For the sixth page, add the permissions from the first five pages
-    PermissionTestUtils.add(TEST_DOMAIN, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_2, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_3, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_4, type, permission, expireType, 0);
-    PermissionTestUtils.add(TEST_DOMAIN_5, type, permission, expireType, 0);
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_2),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_3),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_4),
+      type,
+      permission,
+      expireType,
+      0
+    );
+    Services.perms.add(
+      Services.io.newURI(TEST_DOMAIN_5),
+      type,
+      permission,
+      expireType,
+      0
+    );
   } else {
     ok(false, "Unexpected top page: " + topPage);
   }
 }
 
 async function cleanUp() {
   info("Cleaning up.");
   await new Promise(resolve => {
--- a/toolkit/components/antitracking/test/browser/browser_userInteraction.js
+++ b/toolkit/components/antitracking/test/browser/browser_userInteraction.js
@@ -26,17 +26,17 @@ add_task(async function() {
   let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
   gBrowser.selectedTab = tab;
 
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   let uri = Services.io.newURI(TEST_DOMAIN);
   is(
-    PermissionTestUtils.testPermission(uri, "storageAccessAPI"),
+    Services.perms.testPermission(uri, "storageAccessAPI"),
     Services.perms.UNKNOWN_ACTION,
     "Before user-interaction we don't have a permission"
   );
 
   let promise = TestUtils.topicObserved("perm-changed", (aSubject, aData) => {
     let permission = aSubject.QueryInterface(Ci.nsIPermission);
     return (
       permission.type == "storageAccessAPI" &&
--- a/toolkit/components/antitracking/test/browser/head.js
+++ b/toolkit/components/antitracking/test/browser/head.js
@@ -51,20 +51,16 @@ const BEHAVIOR_REJECT_FOREIGN = Ci.nsICo
 const BEHAVIOR_REJECT_TRACKER = Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER;
 
 requestLongerTimeout(3);
 
 const { UrlClassifierTestUtils } = ChromeUtils.import(
   "resource://testing-common/UrlClassifierTestUtils.jsm"
 );
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/antitracking_head.js",
   this
 );
 
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/partitionedstorage_head.js",
   this
--- a/toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
+++ b/toolkit/components/antitracking/test/browser/storageAccessAPIHelpers.js
@@ -142,23 +142,18 @@ async function callRequestStorageAccess(
   return [threw, rejected];
 }
 
 async function waitUntilPermission(url, name) {
   await new Promise(resolve => {
     let id = setInterval(_ => {
       let Services = SpecialPowers.Services;
       let uri = Services.io.newURI(url);
-      let principal = Services.scriptSecurityManager.createContentPrincipal(
-        uri,
-        {}
-      );
       if (
-        Services.perms.testPermissionFromPrincipal(principal, name) ==
-        Services.perms.ALLOW_ACTION
+        Services.perms.testPermission(uri, name) == Services.perms.ALLOW_ACTION
       ) {
         clearInterval(id);
         resolve();
       }
     }, 0);
   });
 }
 
@@ -174,22 +169,16 @@ async function interactWithTracker() {
 
   // Wait until the user interaction permission becomes visible in our process
   await waitUntilPermission(window.origin, "storageAccessAPI");
 }
 
 function isOnContentBlockingAllowList() {
   let url = new URL(SpecialPowers.wrap(top).location.href);
   let origin = SpecialPowers.Services.io.newURI("https://" + url.host);
-  let principal = SpecialPowers.Services.scriptSecurityManager.createContentPrincipal(
-    origin,
-    {}
-  );
   let types = ["trackingprotection", "trackingprotection-pb"];
   return types.some(type => {
     return (
-      SpecialPowers.Services.perms.testPermissionFromPrincipal(
-        principal,
-        type
-      ) == SpecialPowers.Services.perms.ALLOW_ACTION
+      SpecialPowers.Services.perms.testPermission(origin, type) ==
+      SpecialPowers.Services.perms.ALLOW_ACTION
     );
   });
 }
--- a/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
+++ b/toolkit/components/passwordmgr/test/unit/test_storage_mozStorage.js
@@ -1,19 +1,15 @@
 /**
  * This test interfaces directly with the mozStorage password storage module,
  * bypassing the normal password manager usage.
  */
 
 /* eslint-disable no-var */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const ENCTYPE_BASE64 = 0;
 const ENCTYPE_SDR = 1;
 const PERMISSION_SAVE_LOGINS = "login-saving";
 
 // Current schema version used by storage-mozStorage.js. This will need to be
 // kept in sync with the version there (or else the tests fail).
 const CURRENT_SCHEMA = 6;
 
@@ -82,24 +78,22 @@ function getAllDisabledHostsFromPermissi
       disabledHosts.push(perm.principal.URI.prePath);
     }
   }
 
   return disabledHosts;
 }
 
 function setLoginSavingEnabled(origin, enabled) {
+  let uri = Services.io.newURI(origin);
+
   if (enabled) {
-    PermissionTestUtils.remove(origin, PERMISSION_SAVE_LOGINS);
+    Services.perms.remove(uri, PERMISSION_SAVE_LOGINS);
   } else {
-    PermissionTestUtils.add(
-      origin,
-      PERMISSION_SAVE_LOGINS,
-      Services.perms.DENY_ACTION
-    );
+    Services.perms.add(uri, PERMISSION_SAVE_LOGINS, Services.perms.DENY_ACTION);
   }
 }
 
 add_task(async function test_execute() {
   const OUTDIR = OS.Constants.Path.profileDir;
   let testnum = 0;
   let testdesc = "Setup of nsLoginInfo test-users";
 
--- a/toolkit/components/telemetry/tests/browser/browser_HybridContentTelemetry.js
+++ b/toolkit/components/telemetry/tests/browser/browser_HybridContentTelemetry.js
@@ -8,19 +8,16 @@ const { ContentTaskUtils } = ChromeUtils
   "resource://testing-common/ContentTaskUtils.jsm"
 );
 const { TelemetryUtils } = ChromeUtils.import(
   "resource://gre/modules/TelemetryUtils.jsm"
 );
 const { ObjectUtils } = ChromeUtils.import(
   "resource://gre/modules/ObjectUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const HC_PERMISSION = "hc_telemetry";
 
 async function waitForProcessesEvents(
   aProcesses,
   aAdditionalCondition = data => true
 ) {
   await ContentTaskUtils.waitForCondition(() => {
@@ -93,21 +90,17 @@ add_task(async function test_untrusted_h
   // and makes the test fail. We don't expect any message from non secure contexts.
   const messageName = "HybridContentTelemetry:onTelemetryMessage";
   let makeTestFail = () => ok(false, `Received an unexpected ${messageName}.`);
   Services.mm.addMessageListener(messageName, makeTestFail);
 
   // Try to use the API on a non-secure host.
   const testHost = "http://example.org";
   let testHttpUri = Services.io.newURI(testHost);
-  PermissionTestUtils.add(
-    testHttpUri,
-    HC_PERMISSION,
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(testHttpUri, HC_PERMISSION, Services.perms.ALLOW_ACTION);
   let url = getRootDirectory(gTestPath) + "hybrid_content.html";
   url = url.replace("chrome://mochitests/content", testHost);
   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
   // Try to use the API. Also record a content event from outside HCT: we'll
   // use this event to know when we can stop waiting for the hybrid content data.
   const TEST_CONTENT_EVENT = ["telemetry.test", "main_and_content", "object1"];
   Services.telemetry.setEventRecordingEnabled("telemetry.test", true);
@@ -129,17 +122,17 @@ add_task(async function test_untrusted_h
     : "parent";
   await waitForEvent(processName, TEST_CONTENT_EVENT);
 
   // This is needed otherwise the test will fail due to missing test passes.
   ok(true, "The untrusted HTTP page was not able to use the API.");
 
   // Finally clean up the listener.
   BrowserTestUtils.removeTab(newTab);
-  PermissionTestUtils.remove(testHttpUri, HC_PERMISSION);
+  Services.perms.remove(testHttpUri, HC_PERMISSION);
   Services.mm.removeMessageListener(messageName, makeTestFail);
   Services.telemetry.setEventRecordingEnabled("telemetry.test", false);
 });
 
 add_task(async function test_secure_non_whitelisted_origin() {
   Services.telemetry.clearEvents();
 
   // Install a custom handler that intercepts hybrid content telemetry messages
@@ -197,21 +190,17 @@ add_task(async function test_trusted_dis
   // and makes the test fail. We don't expect any message when the API is disabled.
   const messageName = "HybridContentTelemetry:onTelemetryMessage";
   let makeTestFail = () => ok(false, `Received an unexpected ${messageName}.`);
   Services.mm.addMessageListener(messageName, makeTestFail);
 
   // Try to use the API on a secure host.
   const testHost = "https://example.org";
   let testHttpsUri = Services.io.newURI(testHost);
-  PermissionTestUtils.add(
-    testHttpsUri,
-    HC_PERMISSION,
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(testHttpsUri, HC_PERMISSION, Services.perms.ALLOW_ACTION);
   let url = getRootDirectory(gTestPath) + "hybrid_content.html";
   url = url.replace("chrome://mochitests/content", testHost);
   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
   // Try to use the API. Also record a content event from outside HCT: we'll
   // use this event to know when we can stop waiting for the hybrid content data.
   const TEST_CONTENT_EVENT = ["telemetry.test", "main_and_content", "object1"];
   Services.telemetry.setEventRecordingEnabled("telemetry.test", true);
@@ -234,32 +223,28 @@ add_task(async function test_trusted_dis
   await waitForEvent(processName, TEST_CONTENT_EVENT);
 
   // This is needed otherwise the test will fail due to missing test passes.
   ok(true, "There were no unintended hybrid content API usages.");
 
   // Finally clean up the listener.
   await SpecialPowers.popPrefEnv();
   BrowserTestUtils.removeTab(newTab);
-  PermissionTestUtils.remove(testHttpsUri, HC_PERMISSION);
+  Services.perms.remove(testHttpsUri, HC_PERMISSION);
   Services.mm.removeMessageListener(messageName, makeTestFail);
   Services.telemetry.setEventRecordingEnabled("telemetry.test", false);
 });
 
 add_task(async function test_hybrid_content_with_iframe() {
   Services.telemetry.clearEvents();
 
   // Open a trusted page that can use in the HCT in a new tab.
   const testOuterPageHost = "https://example.com";
   let testHttpsUri = Services.io.newURI(testOuterPageHost);
-  PermissionTestUtils.add(
-    testHttpsUri,
-    HC_PERMISSION,
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(testHttpsUri, HC_PERMISSION, Services.perms.ALLOW_ACTION);
   let url = getRootDirectory(gTestPath) + "hybrid_content.html";
   let outerUrl = url.replace("chrome://mochitests/content", testOuterPageHost);
   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, outerUrl);
 
   // Install a custom handler that intercepts hybrid content telemetry messages
   // and makes the test fail. This needs to be done after the tab is opened.
   const messageName = "HybridContentTelemetry:onTelemetryMessage";
   let makeTestFail = () => ok(false, `Received an unexpected ${messageName}.`);
@@ -307,17 +292,17 @@ add_task(async function test_hybrid_cont
   ok(
     true,
     "There were no unintended hybrid content API usages from the iframe."
   );
 
   // Cleanup permissions and remove the tab.
   BrowserTestUtils.removeTab(newTab);
   Services.mm.removeMessageListener(messageName, makeTestFail);
-  PermissionTestUtils.remove(testHttpsUri, HC_PERMISSION);
+  Services.perms.remove(testHttpsUri, HC_PERMISSION);
   Services.telemetry.setEventRecordingEnabled("telemetry.test", false);
 });
 
 add_task(async function test_hybrid_content_recording() {
   const testHost = "https://example.org";
   const TEST_EVENT_CATEGORY = "telemetry.test.hct";
   const RECORDED_TEST_EVENTS = [
     [TEST_EVENT_CATEGORY, "test1", "object1"],
@@ -335,21 +320,17 @@ add_task(async function test_hybrid_cont
   const NON_RECORDED_TEST_EVENTS = [
     [TEST_EVENT_CATEGORY, "unknown", "unknown"],
   ];
 
   Services.telemetry.clearEvents();
 
   // Give the test host enough privileges to use the API and open the test page.
   let testHttpsUri = Services.io.newURI(testHost);
-  PermissionTestUtils.add(
-    testHttpsUri,
-    HC_PERMISSION,
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(testHttpsUri, HC_PERMISSION, Services.perms.ALLOW_ACTION);
   let url = getRootDirectory(gTestPath) + "hybrid_content.html";
   url = url.replace("chrome://mochitests/content", testHost);
   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
   // Register some events and record them in Telemetry.
   await ContentTask.spawn(
     newTab.linkedBrowser,
     [TEST_EVENT_CATEGORY, RECORDED_TEST_EVENTS, NON_RECORDED_TEST_EVENTS],
@@ -412,33 +393,29 @@ add_task(async function test_hybrid_cont
       dynamicEvents[i],
       removeTrailingInvalidEntry(RECORDED_TEST_EVENTS[i]),
       "Should have recorded the expected event."
     );
   }
 
   // Cleanup permissions and remove the tab.
   BrowserTestUtils.removeTab(newTab);
-  PermissionTestUtils.remove(testHttpsUri, HC_PERMISSION);
+  Services.perms.remove(testHttpsUri, HC_PERMISSION);
 });
 
 add_task(async function test_can_upload() {
   const testHost = "https://example.org";
 
   await SpecialPowers.pushPrefEnv({
     set: [[TelemetryUtils.Preferences.FhrUploadEnabled, true]],
   });
 
   // Give the test host enough privileges to use the API and open the test page.
   let testHttpsUri = Services.io.newURI(testHost);
-  PermissionTestUtils.add(
-    testHttpsUri,
-    HC_PERMISSION,
-    Services.perms.ALLOW_ACTION
-  );
+  Services.perms.add(testHttpsUri, HC_PERMISSION, Services.perms.ALLOW_ACTION);
   let url = getRootDirectory(gTestPath) + "hybrid_content.html";
   url = url.replace("chrome://mochitests/content", testHost);
   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
   // Check that CanUpload reports the correct value.
   await ContentTask.spawn(newTab.linkedBrowser, {}, async function() {
     let contentWin = Cu.waiveXrays(content);
 
@@ -463,27 +440,24 @@ add_task(async function test_can_upload(
     ok(
       !canUpload,
       "CanUpload must report 'false' if the preference has that value."
     );
   });
 
   // Cleanup permissions and remove the tab.
   BrowserTestUtils.removeTab(newTab);
-  PermissionTestUtils.remove(testHttpsUri, HC_PERMISSION);
+  Services.perms.remove(testHttpsUri, HC_PERMISSION);
 });
 
 add_task(async function test_hct_for_discopane() {
   const discoHost = "https://discovery.addons.mozilla.org";
 
   let discoHttpsUri = Services.io.newURI(discoHost);
-  let permission = PermissionTestUtils.testPermission(
-    discoHttpsUri,
-    HC_PERMISSION
-  );
+  let permission = Services.perms.testPermission(discoHttpsUri, HC_PERMISSION);
 
   ok(
     permission == Services.perms.ALLOW_ACTION,
     "Disco Pane needs Hybrid Content Permission for Telemetry data upload"
   );
 });
 
 add_task(async function test_init_rejects() {
@@ -517,17 +491,17 @@ add_task(async function test_init_reject
       let canUpload = contentWin.Mozilla.ContentTelemetry.canUpload();
       ok(!canUpload, "CanUpload must report 'false' if init failed.");
     }
   );
 
   // Give the test host HCT privileges and test that init doesn't throw.
   const testHostPrivileges = "https://example.com";
   let testUrlPrivileges = Services.io.newURI(testHostPrivileges);
-  PermissionTestUtils.add(
+  Services.perms.add(
     testUrlPrivileges,
     HC_PERMISSION,
     Services.perms.ALLOW_ACTION
   );
   let urlWithPrivs = getRootDirectory(gTestPath) + "hybrid_content.html";
   urlWithPrivs = urlWithPrivs.replace(
     "chrome://mochitests/content",
     testHostPrivileges
@@ -555,10 +529,10 @@ add_task(async function test_init_reject
     }
   );
 
   await Promise.all([page1Promise, page2Promise]);
 
   // Cleanup permissions and remove the tab.
   BrowserTestUtils.removeTab(newTab);
   BrowserTestUtils.removeTab(otherTab);
-  PermissionTestUtils.remove(testUrlPrivileges, HC_PERMISSION);
+  Services.perms.remove(testUrlPrivileges, HC_PERMISSION);
 });
--- a/toolkit/content/tests/browser/browser_autoplay_policy_request_permission.js
+++ b/toolkit/content/tests/browser/browser_autoplay_policy_request_permission.js
@@ -1,17 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
+ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
 
 const VIDEO_PAGE =
   "https://example.com/browser/toolkit/content/tests/browser/file_empty.html";
 
 function setTestingPreferences(defaultSetting) {
   info(`set default autoplay setting to '${defaultSetting}'`);
   let defaultValue =
     defaultSetting == "blocked"
@@ -32,28 +30,28 @@ async function testAutoplayExistingPermi
     {
       gBrowser,
       url: VIDEO_PAGE,
     },
     async browser => {
       let promptShowing = () =>
         PopupNotifications.getNotification("autoplay-media", browser);
 
-      PermissionTestUtils.add(
+      SitePermissions.set(
         browser.currentURI,
         "autoplay-media",
         args.permission
       );
       ok(!promptShowing(), "Should not be showing permission prompt yet");
 
       await loadAutoplayVideo(browser, args);
       await checkVideoDidPlay(browser, args);
 
       // Reset permission.
-      PermissionTestUtils.remove(browser.currentURI, "autoplay-media");
+      SitePermissions.remove(browser.currentURI, "autoplay-media");
 
       info("- Finished '" + args.name + "' -");
     }
   );
 }
 
 async function testAutoplayExistingPermissionAgainstDefaultSetting(args) {
   await setTestingPreferences(args.defaultSetting);
@@ -62,54 +60,54 @@ async function testAutoplayExistingPermi
 
 // Test the simple ALLOW/BLOCK cases; when permission is already set to ALLOW,
 // we shoud be able to autoplay via calling play(), or via the autoplay attribute,
 // and when it's set to BLOCK, we should not.
 add_task(async () => {
   await setTestingPreferences("blocked" /* default setting */);
   await testAutoplayExistingPermission({
     name: "Prexisting allow permission autoplay attribute",
-    permission: Services.perms.ALLOW_ACTION,
+    permission: SitePermissions.ALLOW,
     shouldPlay: true,
     mode: "autoplay attribute",
   });
   await testAutoplayExistingPermission({
     name: "Prexisting allow permission call play",
-    permission: Services.perms.ALLOW_ACTION,
+    permission: SitePermissions.ALLOW,
     shouldPlay: true,
     mode: "call play",
   });
   await testAutoplayExistingPermission({
     name: "Prexisting block permission autoplay attribute",
-    permission: Services.perms.DENY_ACTION,
+    permission: SitePermissions.BLOCK,
     shouldPlay: false,
     mode: "autoplay attribute",
   });
   await testAutoplayExistingPermission({
     name: "Prexisting block permission call play",
-    permission: Services.perms.DENY_ACTION,
+    permission: SitePermissions.BLOCK,
     shouldPlay: false,
     mode: "call play",
   });
 });
 
 /**
  * These tests are used to ensure the autoplay setting for specific site can
  * always override the default autoplay setting.
  */
 add_task(async () => {
   await testAutoplayExistingPermissionAgainstDefaultSetting({
     name:
       "Site has prexisting allow permission but default setting is 'blocked'",
-    permission: Services.perms.ALLOW_ACTION,
+    permission: SitePermissions.ALLOW,
     defaultSetting: "blocked",
     shouldPlay: true,
     mode: "autoplay attribute",
   });
   await testAutoplayExistingPermissionAgainstDefaultSetting({
     name:
       "Site has prexisting block permission but default setting is 'allowed'",
-    permission: Services.perms.DENY_ACTION,
+    permission: SitePermissions.BLOCK,
     defaultSetting: "allowed",
     shouldPlay: false,
     mode: "autoplay attribute",
   });
 });
--- a/toolkit/content/tests/browser/browser_autoplay_policy_webRTC_permission.js
+++ b/toolkit/content/tests/browser/browser_autoplay_policy_webRTC_permission.js
@@ -1,18 +1,15 @@
 /**
  * This test is used to ensure site which has granted 'camera' or 'microphone'
  * or 'screen' permission could be allowed to autoplay.
  */
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
+ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
 const VIDEO_PAGE =
   "https://example.com/browser/toolkit/content/tests/browser/file_empty.html";
 
 add_task(() => {
   return SpecialPowers.pushPrefEnv({
     set: [
       ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
       ["media.autoplay.enabled.user-gestures-needed", true],
@@ -24,27 +21,27 @@ add_task(() => {
 async function testAutoplayWebRTCPermission(args) {
   info(`- Starting ${args.name} -`);
   await BrowserTestUtils.withNewTab(
     {
       gBrowser,
       url: VIDEO_PAGE,
     },
     async browser => {
-      PermissionTestUtils.add(
+      SitePermissions.set(
         browser.currentURI,
         args.permission,
-        Services.perms.ALLOW_ACTION
+        SitePermissions.ALLOW
       );
 
       await loadAutoplayVideo(browser, args);
       await checkVideoDidPlay(browser, args);
 
       // Reset permission.
-      PermissionTestUtils.remove(browser.currentURI, args.permission);
+      SitePermissions.remove(browser.currentURI, args.permission);
 
       info(`- Finished ${args.name} -`);
     }
   );
 }
 
 add_task(async function start_test() {
   await testAutoplayWebRTCPermission({
--- a/toolkit/content/tests/browser/browser_autoplay_policy_web_audio.js
+++ b/toolkit/content/tests/browser/browser_autoplay_policy_web_audio.js
@@ -3,20 +3,17 @@
  * different scenarios, such as
  * 1) site has existing 'autoplay-media' permission for allowing autoplay
  * 2) site has existing 'autoplay-media' permission for blocking autoplay
  * 3) site doesn't have permission, start audio context by calling resume() or
  *    AudioScheduledNode.start() after granting user activation.
  */
 "use strict";
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
+ChromeUtils.import("resource:///modules/SitePermissions.jsm", this);
 const PAGE =
   "https://example.com/browser/toolkit/content/tests/browser/file_empty.html";
 
 function setup_test_preference() {
   return SpecialPowers.pushPrefEnv({
     set: [
       ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
       ["media.autoplay.enabled.user-gestures-needed", true],
@@ -119,51 +116,51 @@ async function testAutoplayExistingPermi
     window.gBrowser,
     PAGE
   );
   const browser = tab.linkedBrowser;
 
   info(`- set the 'autoplay-media' permission -`);
   const promptShow = () =>
     PopupNotifications.getNotification("autoplay-media", browser);
-  PermissionTestUtils.add(browser.currentURI, "autoplay-media", permission);
+  SitePermissions.set(browser.currentURI, "autoplay-media", permission);
   ok(!promptShow(), `should not be showing permission prompt yet`);
 
   info(`- create audio context -`);
   loadFrameScript(browser, createAudioContext);
 
   info(`- check AudioContext status -`);
-  const isAllowedToStart = permission === Services.perms.ALLOW_ACTION;
+  const isAllowedToStart = permission === SitePermissions.ALLOW;
   await ContentTask.spawn(
     browser,
     isAllowedToStart,
     checkIfAudioContextIsAllowedToStart
   );
   await ContentTask.spawn(browser, isAllowedToStart, resumeAudioContext);
 
   info(`- remove tab -`);
-  PermissionTestUtils.remove(browser.currentURI, "autoplay-media");
+  SitePermissions.remove(browser.currentURI, "autoplay-media");
   await BrowserTestUtils.removeTab(tab);
 }
 
 async function testAutoplayUnknownPermission({ name, method }) {
   info(`- starting \"${name}\" -`);
   const tab = await BrowserTestUtils.openNewForegroundTab(
     window.gBrowser,
     PAGE
   );
   const browser = tab.linkedBrowser;
 
   info(`- set the 'autoplay-media' permission to UNKNOWN -`);
   const promptShow = () =>
     PopupNotifications.getNotification("autoplay-media", browser);
-  PermissionTestUtils.add(
+  SitePermissions.set(
     browser.currentURI,
     "autoplay-media",
-    Services.perms.UNKNOWN_ACTION
+    SitePermissions.UNKNOWN
   );
   ok(!promptShow(), `should not be showing permission prompt yet`);
 
   info(`- create AudioContext which should not start -`);
   loadFrameScript(browser, createAudioContext);
   await ContentTask.spawn(browser, false, checkIfAudioContextIsAllowedToStart);
 
   info(`- simulate user activate the page -`);
@@ -182,31 +179,31 @@ async function testAutoplayUnknownPermis
   );
   await ContentTask.spawn(
     browser,
     true /* allow to start */,
     resumeAudioContext
   );
 
   info(`- remove tab -`);
-  PermissionTestUtils.remove(browser.currentURI, "autoplay-media");
+  SitePermissions.remove(browser.currentURI, "autoplay-media");
   await BrowserTestUtils.removeTab(tab);
 }
 
 add_task(async function start_tests() {
   info("- setup test preference -");
   await setup_test_preference();
 
   await testAutoplayExistingPermission({
     name: "Prexisting allow permission",
-    permission: Services.perms.ALLOW_ACTION,
+    permission: SitePermissions.ALLOW,
   });
   await testAutoplayExistingPermission({
     name: "Prexisting block permission",
-    permission: Services.perms.DENY_ACTION,
+    permission: SitePermissions.BLOCK,
   });
   const startMethods = [
     "AudioContext",
     "AudioBufferSourceNode",
     "ConstantSourceNode",
     "OscillatorNode",
   ];
   for (let method of startMethods) {
--- a/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
+++ b/toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
@@ -8,19 +8,16 @@
 //       converted into permissions on startup.
 
 const PREF_ROOT = "testpermissions.";
 const TEST_PERM = "test-permission";
 
 const { PermissionsUtils } = ChromeUtils.import(
   "resource://gre/modules/PermissionsUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 function run_test() {
   test_importfromPrefs();
 }
 
 function test_importfromPrefs() {
   // Create own preferences to test
   Services.prefs.setCharPref(PREF_ROOT + "whitelist.add.EMPTY", "");
@@ -77,17 +74,17 @@ function test_importfromPrefs() {
     "http://blacklist2-1.example.com",
     "https://whitelist2-2.example.com:8080",
     "https://blacklist2-2.example.com:8080",
   ];
   let unknown = whitelisted.concat(blacklisted).concat(untouched);
   for (let url of unknown) {
     let uri = Services.io.newURI(url);
     Assert.equal(
-      PermissionTestUtils.testPermission(uri, TEST_PERM),
+      Services.perms.testPermission(uri, TEST_PERM),
       Services.perms.UNKNOWN_ACTION
     );
   }
 
   // Import them
   PermissionsUtils.importFromPrefs(PREF_ROOT, TEST_PERM);
 
   // Get list of preferences to check
@@ -97,27 +94,27 @@ function test_importfromPrefs() {
   for (let pref of preferences) {
     Assert.equal(Services.prefs.getCharPref(pref), "");
   }
 
   // Check they were imported into the permissions manager
   for (let url of whitelisted) {
     let uri = Services.io.newURI(url);
     Assert.equal(
-      PermissionTestUtils.testPermission(uri, TEST_PERM),
+      Services.perms.testPermission(uri, TEST_PERM),
       Services.perms.ALLOW_ACTION
     );
   }
   for (let url of blacklisted) {
     let uri = Services.io.newURI(url);
     Assert.equal(
-      PermissionTestUtils.testPermission(uri, TEST_PERM),
+      Services.perms.testPermission(uri, TEST_PERM),
       Services.perms.DENY_ACTION
     );
   }
   for (let url of untouched) {
     let uri = Services.io.newURI(url);
     Assert.equal(
-      PermissionTestUtils.testPermission(uri, TEST_PERM),
+      Services.perms.testPermission(uri, TEST_PERM),
       Services.perms.UNKNOWN_ACTION
     );
   }
 }
--- a/toolkit/modules/tests/xpcshell/test_web_channel.js
+++ b/toolkit/modules/tests/xpcshell/test_web_channel.js
@@ -1,19 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const { WebChannel } = ChromeUtils.import(
   "resource://gre/modules/WebChannel.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const ERROR_ID_ORIGIN_REQUIRED =
   "WebChannel id and originOrPermission are required.";
 const VALID_WEB_CHANNEL_ID = "id";
 const URL_STRING = "http://example.com";
 const VALID_WEB_CHANNEL_ORIGIN = Services.io.newURI(URL_STRING);
 const TEST_PERMISSION_NAME = "test-webchannel-permissions";
 
@@ -91,23 +88,23 @@ add_task(function test_web_channel_liste
 });
 
 /**
  * Test channel listening with originOrPermission being a permission string.
  */
 add_task(function test_web_channel_listen_permission() {
   return new Promise((resolve, reject) => {
     // add a new permission
-    PermissionTestUtils.add(
+    Services.perms.add(
       VALID_WEB_CHANNEL_ORIGIN,
       TEST_PERMISSION_NAME,
       Services.perms.ALLOW_ACTION
     );
     registerCleanupFunction(() =>
-      PermissionTestUtils.remove(VALID_WEB_CHANNEL_ORIGIN, TEST_PERMISSION_NAME)
+      Services.perms.remove(VALID_WEB_CHANNEL_ORIGIN, TEST_PERMISSION_NAME)
     );
     let channel = new WebChannel(VALID_WEB_CHANNEL_ID, TEST_PERMISSION_NAME, {
       broker: MockWebChannelBroker,
     });
     let delivered = 0;
     Assert.equal(channel.id, VALID_WEB_CHANNEL_ID);
     Assert.equal(channel._originOrPermission, TEST_PERMISSION_NAME);
     Assert.equal(channel._deliverCallback, null);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
@@ -1,19 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Checks that permissions set in preferences are correctly imported but can
 // be removed by the user.
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const XPI_MIMETYPE = "application/x-xpinstall";
 
 function newPrincipal(uri) {
   return Services.scriptSecurityManager.createContentPrincipal(
     NetUtil.newURI(uri),
     {}
   );
 }
@@ -29,18 +25,18 @@ add_task(async function setup() {
     "xpinstall.whitelist.add.36",
     "https://test3.com,https://www.test4.com"
   );
   Services.prefs.setCharPref(
     "xpinstall.whitelist.add.test5",
     "https://test5.com"
   );
 
-  PermissionTestUtils.add(
-    "https://www.test9.com",
+  Services.perms.add(
+    NetUtil.newURI("https://www.test9.com"),
     "install",
     Ci.nsIPermissionManager.ALLOW_ACTION
   );
 
   await promiseStartupManager();
 
   Assert.ok(
     !AddonManager.isInstallAllowed(
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger.js
@@ -3,21 +3,18 @@
 // content.
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         IconURL: TESTROOT + "icon.png",
         toString() {
           return this.URL;
@@ -44,17 +41,17 @@ function install_ended(install, addon) {
     "Got the expected install.installTelemetryInfo"
   );
   install.cancel();
 }
 
 const finish_test = async function(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_amosigned_trigger_iframe.js
@@ -4,21 +4,18 @@
 
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var inner_url = encodeURIComponent(
     TESTROOT +
       "installtrigger.html?" +
       encodeURIComponent(
         JSON.stringify({
           "Unsigned XPI": {
             URL: TESTROOT + "amosigned.xpi",
@@ -44,17 +41,17 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 const finish_test = async function(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.frames[0].document.getElementById("return").textContent,
         status: content.frames[0].document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth.js
@@ -11,21 +11,18 @@ function test() {
   Harness.authenticationCallback = get_auth_info;
   Harness.downloadFailedCallback = download_failed;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
   Services.prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI":
         TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
@@ -49,17 +46,17 @@ function install_ended(install, addon) {
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
   var authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].getService(
     Ci.nsIHttpAuthManager
   );
   authMgr.clearAll();
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   Services.prefs.clearUserPref(
     "network.auth.non-web-content-triggered-resources-http-auth-allow"
   );
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth2.js
@@ -11,21 +11,18 @@ function test() {
 
   requestLongerTimeout(2);
   Harness.authenticationCallback = get_auth_info;
   Harness.downloadFailedCallback = download_failed;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI":
         TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
@@ -54,17 +51,17 @@ function install_ended(install, addon) {
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
   var authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].getService(
     Ci.nsIHttpAuthManager
   );
   authMgr.clearAll();
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   Services.prefs.clearUserPref(
     "network.auth.non-web-content-triggered-resources-http-auth-allow"
   );
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth3.js
@@ -10,21 +10,18 @@ function test() {
   );
 
   Harness.authenticationCallback = get_auth_info;
   Harness.downloadFailedCallback = download_failed;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI":
         TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
@@ -53,17 +50,17 @@ function install_ended(install, addon) {
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
   var authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].getService(
     Ci.nsIHttpAuthManager
   );
   authMgr.clearAll();
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   Services.prefs.clearUserPref(
     "network.auth.non-web-content-triggered-resources-http-auth-allow"
   );
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_auth4.js
@@ -9,21 +9,18 @@ function test() {
   );
 
   Harness.authenticationCallback = get_auth_info;
   Harness.downloadFailedCallback = download_failed;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI":
         TESTROOT + "authRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gNewTab = BrowserTestUtils.addTab(gBrowser);
@@ -52,17 +49,17 @@ function install_ended(install, addon) {
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
   var authMgr = Cc["@mozilla.org/network/http-auth-manager;1"].getService(
     Ci.nsIHttpAuthManager
   );
   authMgr.clearAll();
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   Services.prefs.clearUserPref(
     "network.auth.non-web-content-triggered-resources-http-auth-allow"
   );
 
   gBrowser.removeTab(gNewTab);
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhash.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test whether an install fails when an invalid hash is included
 // This verifies bug 302284
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         Hash: "sha1:643b08418599ddbd1ea8a511c90696578fb844b9",
         toString() {
           return this.URL;
@@ -31,13 +28,13 @@ function test() {
 }
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail");
 }
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com/", "install");
+  Services.perms.remove(makeURI("http://example.com/"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_badhashtype.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test whether an install fails when an unknown hash type is included
 // This verifies bug 302284
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         Hash: "foo:3d0dc22e1f394e159b08aaf5f0f97de4d5c65f4f",
         toString() {
           return this.URL;
@@ -31,13 +28,13 @@ function test() {
 }
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Install should fail");
 }
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com/", "install");
+  Services.perms.remove(makeURI("http://example.com/"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug540558.js
@@ -1,28 +1,25 @@
 // ----------------------------------------------------------------------------
 // Tests that calling InstallTrigger.installChrome works
 function test() {
   Harness.installEndedCallback = check_xpi_install;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(gBrowser, TESTROOT + "bug540558.html");
 }
 
 function check_xpi_install(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js
@@ -3,21 +3,18 @@
 // content. This should be blocked by the whitelist check.
 // This verifies bug 645699
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installBlockedCallback = allow_blocked;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.org/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(gBrowser, TESTROOT + "bug645699.html");
 }
 
 function allow_blocked(installInfo) {
   is(
     installInfo.browser,
@@ -34,14 +31,14 @@ function allow_blocked(installInfo) {
 
 function confirm_install(panel) {
   ok(false, "Should not see the install dialog");
   return false;
 }
 
 function finish_test(count) {
   is(count, 0, "0 Add-ons should have been successfully installed");
-  PermissionTestUtils.remove("http://addons.mozilla.org", "install");
+  Services.perms.remove(makeURI("http://addons.mozilla.org"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
 // ----------------------------------------------------------------------------
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug672485.js
@@ -10,21 +10,18 @@ function test() {
   Harness.installEndedCallback = complete_install;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
   gWindowWatcher = Services.ww;
   delete Services.ww;
   is(Services.ww, undefined, "Services.ww should now be undefined");
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
@@ -49,12 +46,12 @@ function complete_install() {
 
 function finish_test(count) {
   is(count, 0, "0 Add-ons should have been successfully installed");
 
   gBrowser.removeCurrentTab();
 
   Services.ww = gWindowWatcher;
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_containers.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_containers.js
@@ -24,21 +24,18 @@ function check_channel(subject) {
 // Tests we send the right cookies when installing through an InstallTrigger call
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         IconURL: TESTROOT + "icon.png",
         toString() {
           return this.URL;
@@ -74,17 +71,17 @@ const finish_test = async function(count
   ok(
     gDidSeeChannel,
     "Should have seen the request for the XPI and verified it was sent the right way."
   );
   is(count, 1, "1 Add-on should have been successfully installed");
 
   Services.obs.removeObserver(check_channel, "http-on-before-connect");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies.js
@@ -2,21 +2,18 @@
 // Test that an install that requires cookies to be sent fails when no cookies
 // are set
 // This verifies bug 462739
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Cookie check":
         TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
@@ -27,13 +24,13 @@ function test() {
 }
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_NETWORK_FAILURE, "Install should fail");
 }
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies2.js
@@ -15,21 +15,18 @@ function test() {
     false,
     false,
     true,
     Date.now() / 1000 + 60,
     {},
     Ci.nsICookie.SAMESITE_NONE
   );
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Cookie check":
         TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
@@ -49,13 +46,13 @@ function finish_test(count) {
   Services.cookies.remove(
     "example.com",
     "xpinstall",
     "/browser/" + RELATIVE_DIR,
     false,
     {}
   );
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies3.js
@@ -15,21 +15,18 @@ function test() {
     false,
     false,
     true,
     Date.now() / 1000 + 60,
     {},
     Ci.nsICookie.SAMESITE_NONE
   );
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Cookie check":
         TESTROOT + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
@@ -53,13 +50,13 @@ function finish_test(count) {
     "xpinstall",
     "/browser/" + RELATIVE_DIR,
     false,
     {}
   );
 
   Services.prefs.clearUserPref("network.cookie.cookieBehavior");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_cookies4.js
@@ -16,21 +16,18 @@ function test() {
     false,
     false,
     true,
     Date.now() / 1000 + 60,
     {},
     Ci.nsICookie.SAMESITE_NONE
   );
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Cookie check":
         TESTROOT2 + "cookieRedirect.sjs?" + TESTROOT + "amosigned.xpi",
     })
@@ -53,13 +50,13 @@ function finish_test(count) {
     "example.org",
     "xpinstall",
     "/browser/" + RELATIVE_DIR,
     false,
     {}
   );
 
   Services.prefs.clearUserPref("network.cookie.cookieBehavior");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_corrupt.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test whether an install fails when the xpi is corrupt.
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Corrupt XPI": TESTROOT + "corrupt.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
@@ -25,17 +22,17 @@ function test() {
 }
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail");
 }
 
 const finish_test = async function(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_datauri.js
@@ -48,14 +48,14 @@ function install_blocked(installInfo) {
     installInfo.installs[0].installTelemetryInfo,
     { source: "unknown", method: "link" },
     "Got the expected install.installTelemetryInfo"
   );
 }
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
   finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_doorhanger_installs.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_doorhanger_installs.js
@@ -1,18 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 const { AddonTestUtils } = ChromeUtils.import(
   "resource://testing-common/AddonTestUtils.jsm"
 );
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
 
 const SECUREROOT =
   "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
 const PROGRESS_NOTIFICATION = "addon-progress";
 
 const CHROMEROOT = extractChromeRoot(gTestPath);
 
 AddonTestUtils.initMochitest(this);
@@ -420,40 +417,44 @@ var TESTS = [
     await TestUtils.waitForCondition(
       () => !PopupNotifications.isPanelOpen,
       "Waiting for notification to close"
     );
 
     let installs = await AddonManager.getAllInstalls();
     is(installs.length, 0, "Should be no pending installs");
 
-    let installPerm = PermissionTestUtils.testPermission(
+    let installPerm = Services.perms.testPermission(
       gBrowser.currentURI,
       "install"
     );
     is(
       installPerm,
       Ci.nsIPermissionManager.DENY_ACTION,
       "Addon installation should be blocked for site"
     );
 
     await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
-    PermissionTestUtils.remove(target, "install");
+    SitePermissions.remove(NetUtil.newURI(target), "install");
   },
 
   async function test_permaBlockedInstallNoPrompt() {
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "amosigned.xpi",
       })
     );
     let target = TESTROOT + "installtrigger.html?" + triggers;
 
-    PermissionTestUtils.add(target, "install", Services.perms.DENY_ACTION);
+    SitePermissions.set(
+      NetUtil.newURI(target),
+      "install",
+      SitePermissions.BLOCK
+    );
     await BrowserTestUtils.openNewForegroundTab(gBrowser, target);
 
     let panelOpened;
     try {
       panelOpened = await TestUtils.waitForCondition(
         () => PopupNotifications.isPanelOpen,
         100,
         10
@@ -463,32 +464,29 @@ var TESTS = [
     }
     is(panelOpened, false, "Addon prompt should not open");
 
     let installs = await AddonManager.getAllInstalls();
     is(installs.length, 0, "Should be no pending installs");
 
     await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
-    PermissionTestUtils.remove(target, "install");
+    SitePermissions.remove(NetUtil.newURI(target), "install");
   },
 
   async function test_whitelistedInstall() {
     Services.prefs.setBoolPref(
       "extensions.allowPrivateBrowsingByDefault",
       false
     );
     let originalTab = gBrowser.selectedTab;
     let tab;
     gBrowser.selectedTab = originalTab;
-    PermissionTestUtils.add(
-      "http://example.com/",
-      "install",
-      Services.perms.ALLOW_ACTION
-    );
+    let pm = Services.perms;
+    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
     let progressPromise = waitForProgressNotification();
     let dialogPromise = waitForInstallDialog();
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "amosigned.xpi",
       })
     );
@@ -529,28 +527,25 @@ var TESTS = [
     let policy = WebExtensionPolicy.getByID(addon.id);
     ok(
       !policy.privateBrowsingAllowed,
       "private browsing permission was not granted"
     );
 
     addon.uninstall();
 
-    PermissionTestUtils.remove("http://example.com/", "install");
+    Services.perms.remove(makeURI("http://example.com/"), "install");
 
     Services.prefs.clearUserPref("extensions.allowPrivateBrowsingByDefault");
     await removeTabAndWaitForNotificationClose();
   },
 
   async function test_failedDownload() {
-    PermissionTestUtils.add(
-      "http://example.com/",
-      "install",
-      Services.perms.ALLOW_ACTION
-    );
+    let pm = Services.perms;
+    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
     let progressPromise = waitForProgressNotification();
     let failPromise = waitForNotification("addon-install-failed");
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "missing.xpi",
       })
     );
@@ -563,26 +558,23 @@ var TESTS = [
 
     let notification = panel.childNodes[0];
     is(
       notification.getAttribute("label"),
       "The add-on could not be downloaded because of a connection failure.",
       "Should have seen the right message"
     );
 
-    PermissionTestUtils.remove("http://example.com/", "install");
+    Services.perms.remove(makeURI("http://example.com/"), "install");
     await removeTabAndWaitForNotificationClose();
   },
 
   async function test_corruptFile() {
-    PermissionTestUtils.add(
-      "http://example.com/",
-      "install",
-      Services.perms.ALLOW_ACTION
-    );
+    let pm = Services.perms;
+    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
     let progressPromise = waitForProgressNotification();
     let failPromise = waitForNotification("addon-install-failed");
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "corrupt.xpi",
       })
     );
@@ -596,26 +588,23 @@ var TESTS = [
     let notification = panel.childNodes[0];
     is(
       notification.getAttribute("label"),
       "The add-on downloaded from this site could not be installed " +
         "because it appears to be corrupt.",
       "Should have seen the right message"
     );
 
-    PermissionTestUtils.remove("http://example.com/", "install");
+    Services.perms.remove(makeURI("http://example.com/"), "install");
     await removeTabAndWaitForNotificationClose();
   },
 
   async function test_incompatible() {
-    PermissionTestUtils.add(
-      "http://example.com/",
-      "install",
-      Services.perms.ALLOW_ACTION
-    );
+    let pm = Services.perms;
+    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
     let progressPromise = waitForProgressNotification();
     let failPromise = waitForNotification("addon-install-failed");
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "incompatible.xpi",
       })
     );
@@ -635,17 +624,17 @@ var TESTS = [
       Services.appinfo.version
     }.`;
     is(
       notification.getAttribute("label"),
       message,
       "Should have seen the right message"
     );
 
-    PermissionTestUtils.remove("http://example.com/", "install");
+    Services.perms.remove(makeURI("http://example.com/"), "install");
     await removeTabAndWaitForNotificationClose();
   },
 
   async function test_localFile() {
     let cr = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(
       Ci.nsIChromeRegistry
     );
     let path;
@@ -813,21 +802,18 @@ var TESTS = [
 
     await removeTabAndWaitForNotificationClose(gBrowser.selectedTab);
 
     installs = await AddonManager.getAllInstalls();
     is(installs.length, 0, "Should have cancelled the installs");
   },
 
   async function test_cancel() {
-    PermissionTestUtils.add(
-      "http://example.com/",
-      "install",
-      Services.perms.ALLOW_ACTION
-    );
+    let pm = Services.perms;
+    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
     let notificationPromise = waitForNotification(PROGRESS_NOTIFICATION);
     let triggers = encodeURIComponent(
       JSON.stringify({
         XPI: "slowinstall.sjs?file=amosigned.xpi",
       })
     );
     BrowserTestUtils.openNewForegroundTab(
@@ -871,17 +857,17 @@ var TESTS = [
 
     await new Promise(resolve => executeSoon(resolve));
 
     ok(!PopupNotifications.isPanelOpen, "Notification should be closed");
 
     let installs = await AddonManager.getAllInstalls();
     is(installs.length, 0, "Should be no pending install");
 
-    PermissionTestUtils.remove("http://example.com/", "install");
+    Services.perms.remove(makeURI("http://example.com/"), "install");
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   },
 
   async function test_failedSecurity() {
     Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
     setupRedirect({
       Location: TESTROOT + "amosigned.xpi",
     });
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_empty.js
@@ -1,20 +1,17 @@
 // ----------------------------------------------------------------------------
 // Test whether an install fails when there is no install script present.
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Empty XPI": TESTROOT + "empty.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
@@ -24,13 +21,13 @@ function test() {
 }
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_CORRUPT_FILE, "Install should fail");
 }
 
 function finish_test(count) {
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test whether an install succeeds when a valid hash is included
 // This verifies bug 302284
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         Hash: "sha1:ee95834ad862245a9ef99ccecc2a857cadc16404",
         toString() {
           return this.URL;
@@ -32,13 +29,13 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_hash2.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test whether an install succeeds using case-insensitive hashes
 // This verifies bug 603021
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         Hash: "sha1:EE95834AD862245A9EF99CCECC2A857CADC16404",
         toString() {
           return this.URL;
@@ -32,13 +29,13 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash.js
@@ -2,21 +2,18 @@
 // Test whether an install succeeds when a valid hash is included in the HTTPS
 // request
 // This verifies bug 591070
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url +=
     "?sha1:ee95834ad862245a9ef99ccecc2a857cadc16404|" +
     TESTROOT +
     "amosigned.xpi";
 
@@ -39,14 +36,14 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
   Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS);
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash2.js
@@ -2,21 +2,18 @@
 // Test whether an install fails when a invalid hash is included in the HTTPS
 // request
 // This verifies bug 591070
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi";
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
@@ -36,14 +33,14 @@ function test() {
 
 function download_failed(install) {
   is(install.error, AddonManager.ERROR_INCORRECT_HASH, "Download should fail");
 }
 
 function finish_test(count) {
   is(count, 0, "0 Add-ons should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
   Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS);
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash3.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Tests that the HTTPS hash is ignored when InstallTrigger is passed a hash.
 // This verifies bug 591070
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi";
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
@@ -36,14 +33,14 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
   Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS);
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash4.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test that hashes are ignored in the headers of HTTP requests
 // This verifies bug 591070
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var url = "http://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi";
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: url,
@@ -34,13 +31,13 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash5.js
@@ -1,21 +1,18 @@
 // ----------------------------------------------------------------------------
 // Test that only the first HTTPS hash is used
 // This verifies bug 591070
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   var url = "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url += "?sha1:ee95834ad862245a9ef99ccecc2a857cadc16404|";
   url += "https://example.com/browser/" + RELATIVE_DIR + "hashRedirect.sjs";
   url += "?sha1:foobar|" + TESTROOT + "amosigned.xpi";
 
   var triggers = encodeURIComponent(
@@ -37,14 +34,14 @@ function test() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
   Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS);
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js
@@ -15,21 +15,18 @@ function setup_redirect(aSettings) {
 
 var gInstall = null;
 
 function test() {
   Harness.downloadFailedCallback = download_failed;
   Harness.installsCompletedCallback = finish_failed_download;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   // Set up the redirect to give a bad hash
   setup_redirect({
     "X-Target-Digest": "sha1:foo",
     Location: "http://example.com/browser/" + RELATIVE_DIR + "amosigned.xpi",
   });
 
@@ -91,14 +88,14 @@ function finish_failed_download() {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
   Services.prefs.clearUserPref(PREF_INSTALL_REQUIREBUILTINCERTS);
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_installchrome.js
@@ -1,33 +1,30 @@
 // ----------------------------------------------------------------------------
 // Tests that calling InstallTrigger.installChrome works
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
     gBrowser,
     TESTROOT +
       "installchrome.html? " +
       encodeURIComponent(TESTROOT + "amosigned.xpi")
   );
 }
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_newwindow.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_newwindow.js
@@ -12,17 +12,18 @@ async function test() {
   Harness.installEndedCallback = install => {
     install.cancel();
   };
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   win = await BrowserTestUtils.openNewBrowserWindow();
   Harness.setup(win);
 
-  PermissionTestUtils.add(exampleURI, "install", Services.perms.ALLOW_ACTION);
+  const pm = Services.perms;
+  pm.add(exampleURI, "install", pm.ALLOW_ACTION);
 
   const triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         IconURL: TESTROOT + "icon.png",
       },
     })
@@ -39,17 +40,17 @@ async function test() {
 function confirm_install(panel) {
   is(panel.getAttribute("name"), "XPI Test", "Should have seen the name");
   return true;
 }
 
 async function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove(exampleURI, "install");
+  Services.perms.remove(exampleURI, "install");
 
   const results = await ContentTask.spawn(
     win.gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_offline.js
@@ -2,21 +2,18 @@ var proxyPrefValue;
 
 // ----------------------------------------------------------------------------
 // Tests that going offline cancels an in progress download.
 function test() {
   Harness.downloadProgressCallback = download_progress;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
@@ -57,12 +54,12 @@ function finish_test(count) {
   }
 
   is(count, 0, "No add-ons should have been installed");
   try {
     Services.prefs.setIntPref("network.proxy.type", proxyPrefValue);
     Services.io.offline = false;
   } catch (ex) {}
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   wait_for_online();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_privatebrowsing.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_privatebrowsing.js
@@ -27,21 +27,18 @@ async function test() {
   waitForExplicitFinish(); // have to call this ourselves because we're async.
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   gPrivateWin = await BrowserTestUtils.openNewBrowserWindow({ private: true });
   Harness.setup(gPrivateWin);
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "amosigned.xpi",
         IconURL: TESTROOT + "icon.png",
         toString() {
           return this.URL;
@@ -81,17 +78,17 @@ const finish_test = async function(count
   ok(
     gDidSeeChannel,
     "Should have seen the request for the XPI and verified it was sent the right way."
   );
   is(count, 1, "1 Add-on should have been successfully installed");
 
   Services.obs.removeObserver(check_channel, "http-on-before-connect");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gPrivateWin.gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_relative.js
@@ -2,21 +2,18 @@
 // Tests that InstallTrigger deals with relative urls correctly.
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: "amosigned.xpi",
         IconURL: "icon.png",
         toString() {
           return this.URL;
@@ -38,17 +35,17 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 const finish_test = async function(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_signed_trigger.js
@@ -2,21 +2,18 @@
 // Tests installing an signed add-on through an InstallTrigger call in web
 // content.
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Signed XPI": TESTROOT + "amosigned.xpi",
     })
   );
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
@@ -32,13 +29,13 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_softwareupdate.js
@@ -1,33 +1,30 @@
 // ----------------------------------------------------------------------------
 // Tests that calling InstallTrigger.startSoftwareUpdate works
 function test() {
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(
     gBrowser,
     TESTROOT +
       "startsoftwareupdate.html? " +
       encodeURIComponent(TESTROOT + "amosigned.xpi")
   );
 }
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_trigger_redirect.js
@@ -2,21 +2,18 @@
 // Tests that the InstallTrigger callback can redirect to a relative url.
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   BrowserTestUtils.loadURI(gBrowser, TESTROOT + "triggerredirect.html");
 }
 
 function confirm_install(panel) {
   is(panel.getAttribute("name"), "XPI Test", "Should have seen the name");
   return true;
@@ -24,17 +21,17 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 function finish_test(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   is(
     gBrowser.currentURI.spec,
     TESTROOT + "triggerredirect.html#foo",
     "Should have redirected"
   );
 
   gBrowser.removeCurrentTab();
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger.js
@@ -3,21 +3,18 @@
 // content.
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(
     JSON.stringify({
       "Unsigned XPI": {
         URL: TESTROOT + "unsigned.xpi",
         IconURL: TESTROOT + "icon.png",
         toString() {
           return this.URL;
@@ -39,17 +36,17 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 const finish_test = async function(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.document.getElementById("return").textContent,
         status: content.document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_iframe.js
@@ -4,21 +4,18 @@
 
 function test() {
   Harness.installConfirmCallback = confirm_install;
   Harness.installEndedCallback = install_ended;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var inner_url = encodeURIComponent(
     TESTROOT +
       "installtrigger.html?" +
       encodeURIComponent(
         JSON.stringify({
           "Unsigned XPI": {
             URL: TESTROOT + "unsigned.xpi",
@@ -44,17 +41,17 @@ function confirm_install(panel) {
 
 function install_ended(install, addon) {
   install.cancel();
 }
 
 const finish_test = async function(count) {
   is(count, 1, "1 Add-on should have been successfully installed");
 
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   const results = await ContentTask.spawn(
     gBrowser.selectedBrowser,
     null,
     () => {
       return {
         return: content.frames[0].document.getElementById("return").textContent,
         status: content.frames[0].document.getElementById("status").textContent,
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_unsigned_trigger_xorigin.js
@@ -4,21 +4,18 @@
 var wasOriginBlocked = false;
 
 function test() {
   Harness.installOriginBlockedCallback = install_blocked;
   Harness.installsCompletedCallback = finish_test;
   Harness.finalContentEvent = "InstallComplete";
   Harness.setup();
 
-  PermissionTestUtils.add(
-    "http://example.com/",
-    "install",
-    Services.perms.ALLOW_ACTION
-  );
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var inner_url = encodeURIComponent(
     TESTROOT +
       "installtrigger.html?" +
       encodeURIComponent(
         JSON.stringify({
           "Unsigned XPI": {
             URL: TESTROOT + "amosigned.xpi",
@@ -43,13 +40,13 @@ function install_blocked(installInfo) {
 
 function finish_test(count) {
   ok(
     wasOriginBlocked,
     "Should have been blocked due to the cross origin request."
   );
 
   is(count, 0, "No add-ons should have been installed");
-  PermissionTestUtils.remove("http://example.com", "install");
+  Services.perms.remove(makeURI("http://example.com"), "install");
 
   gBrowser.removeCurrentTab();
   Harness.finish();
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/head.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/head.js
@@ -1,14 +1,10 @@
 /* eslint no-unused-vars: ["error", {vars: "local", args: "none"}] */
 
-const { PermissionTestUtils } = ChromeUtils.import(
-  "resource://testing-common/PermissionTestUtils.jsm"
-);
-
 const RELATIVE_DIR = "toolkit/mozapps/extensions/test/xpinstall/";
 
 const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
 const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR;
 const PROMPT_URL = "chrome://global/content/commonDialog.xul";
 const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xul";
 const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
 const PREF_INSTALL_REQUIREBUILTINCERTS =