Backed out 6 changesets (bug 1363541) for perma failures. CLOSED TREE
authorRazvan Maries <rmaries@mozilla.com>
Fri, 10 Apr 2020 11:31:20 +0300
changeset 523362 397af4c4b102f8cae9e471449e74fa3bb5f6c655
parent 523361 91d5c60ddc69aff6ef25d4bbee6f76bcc1c8872d
child 523363 bbef701c7a1aad1def411071ccc4bf47322bbfa1
push id37301
push useraiakab@mozilla.com
push dateFri, 10 Apr 2020 21:37:00 +0000
treeherdermozilla-central@82d84da94d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1363541
milestone77.0a1
backs outa775f6e9eb41a272c375cdb2f1af798c2340cf9e
9212bfd89eca2fbae1669f215e56f425f4c81c8e
bf41b0c139f6b558c08c8e6c1b1842a420eb5818
aa7c6668b249f4e555ea29774f749e6db1804d04
9f413a8a47bbe149eb945018e54fc2e96566b459
827a9a2866bd8900bf82d0e520dfaeec09cde629
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 6 changesets (bug 1363541) for perma failures. CLOSED TREE Backed out changeset a775f6e9eb41 (bug 1363541) Backed out changeset 9212bfd89eca (bug 1363541) Backed out changeset bf41b0c139f6 (bug 1363541) Backed out changeset aa7c6668b249 (bug 1363541) Backed out changeset 9f413a8a47bb (bug 1363541) Backed out changeset 827a9a2866bd (bug 1363541)
browser/app/permissions
browser/base/content/test/performance/browser_startup_mainthreadio.js
build/clang-plugin/ThreadAllows.txt
dom/base/Document.cpp
dom/base/Document.h
dom/base/Navigator.cpp
dom/base/moz.build
dom/base/nsContentPermissionHelper.h
dom/base/nsIContentPolicy.idl
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/moz.build
dom/media/MediaManager.cpp
dom/permission/PermissionStatus.cpp
dom/permission/moz.build
dom/serviceworkers/ServiceWorkerManager.cpp
dom/serviceworkers/moz.build
dom/workers/remoteworkers/RemoteWorkerChild.cpp
dom/workers/remoteworkers/moz.build
extensions/permissions/Permission.cpp
extensions/permissions/Permission.h
extensions/permissions/PermissionDelegateHandler.cpp
extensions/permissions/PermissionDelegateHandler.h
extensions/permissions/PermissionManager.cpp
extensions/permissions/PermissionManager.h
extensions/permissions/components.conf
extensions/permissions/moz.build
extensions/permissions/nsPermission.cpp
extensions/permissions/nsPermission.h
extensions/permissions/nsPermissionManager.cpp
extensions/permissions/nsPermissionManager.h
extensions/permissions/test/browser.ini
extensions/permissions/test/gtest/PermissionManagerTest.cpp
extensions/permissions/test/gtest/moz.build
extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
extensions/permissions/test/unit/test_permmanager_migrate_10-11.js
extensions/permissions/test/unit/test_permmanager_migrate_4-7.js
extensions/permissions/test/unit/test_permmanager_migrate_4-7_no_history.js
extensions/permissions/test/unit/test_permmanager_migrate_5-7a.js
extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
extensions/permissions/test/unit/test_permmanager_migrate_6-7a.js
extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
extensions/permissions/test/unit/test_permmanager_migrate_7-8.js
extensions/permissions/test/unit/test_permmanager_migrate_9-10.js
extensions/permissions/test/unit/test_permmanager_oa_strip.js
extensions/permissions/test/unit/test_permmanager_removeall.js
extensions/permissions/test/unit/test_permmanager_removebytypesince.js
extensions/permissions/test/unit/test_permmanager_removesince.js
layout/build/moz.build
layout/build/nsLayoutStatics.cpp
layout/tools/reftest/selftest/files/leaks.log
modules/libpref/init/StaticPrefList.yaml
netwerk/base/moz.build
netwerk/cookie/CookieJarSettings.cpp
netwerk/cookie/CookiePermission.cpp
netwerk/cookie/CookiePermission.h
netwerk/cookie/moz.build
testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
testing/mozbase/mozprofile/mozprofile/permissions.py
testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
toolkit/components/antitracking/AntiTrackingUtils.cpp
toolkit/components/antitracking/ContentBlocking.cpp
toolkit/components/antitracking/ContentBlockingAllowList.cpp
toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
toolkit/components/antitracking/TemporaryAccessGrantObserver.h
toolkit/components/antitracking/moz.build
--- a/browser/app/permissions
+++ b/browser/app/permissions
@@ -1,15 +1,15 @@
 # This file has default permissions for the permission manager.
 # The file-format is strict:
 # * matchtype \t type \t permission \t host
 # * "origin" should be used for matchtype, "host" is supported for legacy reasons
 # * type is a string that identifies the type of permission (e.g. "cookie")
 # * permission is an integer between 1 and 15
-# See PermissionManager.cpp for more...
+# See nsPermissionManager.cpp for more...
 
 # UITour
 # Bug 1557153: www.mozilla.org gets a special workaround in UITourChild.jsm
 origin	uitour	1	https://www.mozilla.org
 origin	uitour	1	https://monitor.firefox.com
 origin	uitour	1	https://screenshots.firefox.com
 origin	uitour	1	https://support.mozilla.org
 origin	uitour	1	about:home
--- a/browser/base/content/test/performance/browser_startup_mainthreadio.js
+++ b/browser/base/content/test/performance/browser_startup_mainthreadio.js
@@ -248,16 +248,39 @@ const startupPhases = {
     },
     {
       // bug 1534745
       path: "ProfD:cookies.sqlite-wal",
       condition: WIN,
       stat: 2,
     },
     {
+      // bug 975996
+      path: "ProfD:permissions.sqlite",
+      condition: WIN || MAC,
+      fsync: 8,
+      read: 2,
+      stat: 1,
+      write: 10,
+    },
+    {
+      // bug 975996
+      path: "ProfD:permissions.sqlite-journal",
+      condition: WIN || MAC,
+      fsync: 8,
+      stat: 28,
+      write: 40,
+    },
+    {
+      // bug 975996
+      path: "ProfD:permissions.sqlite-wal",
+      condition: WIN,
+      stat: 20,
+    },
+    {
       // Seems done by OS X and outside of our control.
       path: "*.savedState/restorecount.plist",
       condition: MAC,
       ignoreIfUnused: true,
       write: 1,
     },
     {
       path: "*ld.so.conf*",
--- a/build/clang-plugin/ThreadAllows.txt
+++ b/build/clang-plugin/ThreadAllows.txt
@@ -50,17 +50,16 @@ MediaTelemetry
 MediaTrackGrph
 mtransport
 NamedPipeSrv
 NetPredictClean
 Netlink Monitor
 OSKeyStore
 OutputDrain
 PaintThread
-Permission
 PlayEventSound
 ProcessHangMon
 ProfSymbolTable
 ProfilerChild
 ProxyResolution
 RWLockTester
 RacingServMan
 RemVidChild
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -86,17 +86,17 @@
 #include "nsSerializationHelper.h"
 #include "nsICertOverrideService.h"
 #include "nsIX509Cert.h"
 #include "nsIX509CertValidity.h"
 #include "nsITransportSecurityInfo.h"
 #include "nsINSSErrorsService.h"
 #include "nsISocketProvider.h"
 #include "nsISiteSecurityService.h"
-#include "mozilla/PermissionDelegateHandler.h"
+#include "PermissionDelegateHandler.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/FullscreenChange.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "mozilla/intl/LocaleService.h"
@@ -169,19 +169,19 @@
 #include "nsIRequestContext.h"
 #include "nsStyleSheetService.h"
 
 #include "nsNetUtil.h"  // for NS_NewURI
 #include "nsIInputStreamChannel.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 
-#include "mozilla/PermissionManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPermission.h"
+#include "nsPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIPrivateBrowsingChannel.h"
 #include "ExpandedPrincipal.h"
 #include "mozilla/NullPrincipal.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "nsICookieService.h"
@@ -6818,18 +6818,17 @@ void Document::SetScopeObject(nsIGlobalO
   mScopeObject = do_GetWeakReference(aGlobal);
   if (aGlobal) {
     mHasHadScriptHandlingObject = true;
 
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
     if (!window) {
       return;
     }
-    BrowsingContextGroup* browsingContextGroup =
-        window->GetBrowsingContextGroup();
+    BrowsingContextGroup* browsingContextGroup = window->GetBrowsingContextGroup();
 
     // We should already have the principal, and now that we have been added
     // to a window, we should be able to join a DocGroup!
     nsAutoCString docGroupKey;
     nsresult rv = mozilla::dom::DocGroup::GetKey(NodePrincipal(), docGroupKey);
     if (mDocGroup) {
       if (NS_SUCCEEDED(rv)) {
         MOZ_RELEASE_ASSERT(mDocGroup->MatchesKey(docGroupKey));
@@ -15888,17 +15887,17 @@ Document::AutomaticStorageAccessCanBeGra
 
   return AutomaticStorageAccessGrantPromise::CreateAndReject(false, __func__);
 }
 
 bool Document::AutomaticStorageAccessCanBeGranted(nsIPrincipal* aPrincipal) {
   nsAutoCString prefix;
   AntiTrackingUtils::CreateStoragePermissionKey(aPrincipal, prefix);
 
-  PermissionManager* permManager = PermissionManager::GetInstance();
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!permManager)) {
     return false;
   }
 
   typedef nsTArray<RefPtr<nsIPermission>> Permissions;
   Permissions perms;
   nsresult rv = permManager->GetAllWithTypePrefix(prefix, perms);
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -123,33 +123,33 @@ class nsSimpleContentList;
 class nsTextNode;
 class nsWindowSizes;
 class nsDOMCaretPosition;
 class nsViewportInfo;
 class nsIGlobalObject;
 class nsIAppWindow;
 class nsXULPrototypeDocument;
 class nsXULPrototypeElement;
+class PermissionDelegateHandler;
 class nsIPermissionDelegateHandler;
 struct nsFont;
 struct StyleUseCounters;
 
 namespace mozilla {
 class AbstractThread;
 class StyleSheet;
 class EditorCommand;
 class Encoding;
 class ErrorResult;
 class EventStates;
 class EventListenerManager;
 class FullscreenExit;
 class FullscreenRequest;
 struct LangGroupFontPrefs;
 class PendingAnimationTracker;
-class PermissionDelegateHandler;
 class PresShell;
 class ServoStyleSet;
 enum class StyleOrigin : uint8_t;
 class SMILAnimationController;
 enum class StyleCursorKind : uint8_t;
 enum class StylePrefersColorScheme : uint8_t;
 template <typename>
 class OwningNonNull;
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -68,17 +68,17 @@
 #include "nsStringStream.h"
 #include "nsComponentManagerUtils.h"
 #include "nsICookieService.h"
 #include "nsIHttpChannel.h"
 #include "nsStreamUtils.h"
 #include "WidgetUtils.h"
 #include "nsIScriptError.h"
 #include "ReferrerInfo.h"
-#include "mozilla/PermissionDelegateHandler.h"
+#include "PermissionDelegateHandler.h"
 
 #include "nsIExternalProtocolHandler.h"
 #include "BrowserChild.h"
 #include "URIUtils.h"
 
 #include "mozilla/dom/MediaDevices.h"
 #include "MediaManager.h"
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -505,16 +505,17 @@ LOCAL_INCLUDES += [
     '/dom/html',
     '/dom/ipc',
     '/dom/storage',
     '/dom/svg',
     '/dom/u2f',
     '/dom/xml',
     '/dom/xslt/xpath',
     '/dom/xul',
+    '/extensions/permissions',
     '/gfx/2d',
     '/image',
     '/js/xpconnect/loader',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/base',
     '/layout/forms',
     '/layout/generic',
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -7,17 +7,17 @@
 #ifndef nsContentPermissionHelper_h
 #define nsContentPermissionHelper_h
 
 #include "nsIContentPermissionPrompt.h"
 #include "nsTArray.h"
 #include "nsIMutableArray.h"
 #include "mozilla/dom/PContentPermissionRequestChild.h"
 #include "mozilla/dom/ipc/IdType.h"
-#include "mozilla/PermissionDelegateHandler.h"
+#include "PermissionDelegateHandler.h"
 
 // Microsoft's API Name hackery sucks
 // XXXbz Doing this in a header is a gigantic footgun. See
 // https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why.
 #undef LoadImage
 
 class nsPIDOMWindowInner;
 class nsContentPermissionRequestProxy;
--- a/dom/base/nsIContentPolicy.idl
+++ b/dom/base/nsIContentPolicy.idl
@@ -393,17 +393,17 @@ interface nsIContentPolicy : nsISupports
    * implementations.
    */
   const nsContentPolicyType TYPE_INTERNAL_PAINTWORKLET = 50;
 
   /* When adding new content types, please update
    * NS_CP_ContentTypeName, nsCSPContext, CSP_ContentTypeToDirective,
    * DoContentSecurityChecks, all nsIContentPolicy implementations, the
    * static_assert in dom/cache/DBSchema.cpp, ChannelWrapper.webidl,
-   * ChannelWrapper.cpp, PermissionManager.cpp, and other things that are not
+   * ChannelWrapper.cpp, nsPermissionManager.cpp, and other things that are not
    * listed here that are related to nsIContentPolicy. */
 
   //////////////////////////////////////////////////////////////////////
 
   /**
    * Returned from shouldLoad or shouldProcess if the load or process request
    * is rejected based on details of the request.
    */
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -204,18 +204,18 @@
 
 #include "nsIScriptSecurityManager.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 
 #ifdef MOZ_WEBRTC
 #  include "signaling/src/peerconnection/WebrtcGlobalChild.h"
 #endif
 
-#include "mozilla/Permission.h"
-#include "mozilla/PermissionManager.h"
+#include "nsPermission.h"
+#include "nsPermissionManager.h"
 
 #include "PermissionMessageUtils.h"
 
 #if defined(MOZ_WIDGET_ANDROID)
 #  include "APKOpen.h"
 #endif
 
 #ifdef XP_WIN
@@ -2464,18 +2464,18 @@ mozilla::ipc::IPCResult ContentChild::Re
   LocaleService::GetInstance()->AssignRequestedLocales(aRequestedLocales);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvAddPermission(
     const IPC::Permission& permission) {
   nsCOMPtr<nsIPermissionManager> permissionManagerIface =
       services::GetPermissionManager();
-  PermissionManager* permissionManager =
-      static_cast<PermissionManager*>(permissionManagerIface.get());
+  nsPermissionManager* permissionManager =
+      static_cast<nsPermissionManager*>(permissionManagerIface.get());
   MOZ_ASSERT(permissionManager,
              "We have no permissionManager in the Content process !");
 
   // note we do not need to force mUserContextId to the default here because
   // the permission manager does that internally.
   nsAutoCString originNoSuffix;
   OriginAttributes attrs;
   bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
@@ -2489,26 +2489,26 @@ mozilla::ipc::IPCResult ContentChild::Re
       mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
 
   // child processes don't care about modification time.
   int64_t modificationTime = 0;
 
   permissionManager->AddInternal(
       principal, nsCString(permission.type), permission.capability, 0,
       permission.expireType, permission.expireTime, modificationTime,
-      PermissionManager::eNotify, PermissionManager::eNoDBOperation);
+      nsPermissionManager::eNotify, nsPermissionManager::eNoDBOperation);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvRemoveAllPermissions() {
   nsCOMPtr<nsIPermissionManager> permissionManagerIface =
       services::GetPermissionManager();
-  PermissionManager* permissionManager =
-      static_cast<PermissionManager*>(permissionManagerIface.get());
+  nsPermissionManager* permissionManager =
+      static_cast<nsPermissionManager*>(permissionManagerIface.get());
   MOZ_ASSERT(permissionManager,
              "We have no permissionManager in the Content process !");
 
   permissionManager->RemoveAllFromIPC();
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvFlushMemory(const nsString& reason) {
@@ -3341,17 +3341,17 @@ nsresult ContentChild::AsyncOpenAnonymou
   // Remember the association with the callback.
   MOZ_ASSERT(!mPendingAnonymousTemporaryFiles.Get(newID));
   mPendingAnonymousTemporaryFiles.LookupOrAdd(newID, aCallback);
   return NS_OK;
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey(
     const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) {
-  RefPtr<PermissionManager> permManager = PermissionManager::GetInstance();
+  RefPtr<nsPermissionManager> permManager = nsPermissionManager::GetInstance();
   if (permManager) {
     permManager->SetPermissionsWithKey(aPermissionKey, aPerms);
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens(
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -246,17 +246,17 @@
 #if defined(XP_LINUX)
 #  include "mozilla/Hal.h"
 #endif
 
 #ifdef ANDROID
 #  include "gfxAndroidPlatform.h"
 #endif
 
-#include "mozilla/PermissionManager.h"
+#include "nsPermissionManager.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #  include "AndroidBridge.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #  include <gdk/gdk.h>
 #endif
@@ -5451,17 +5451,17 @@ nsresult ContentParent::AboutToLoadHttpF
 
   return NS_OK;
 }
 
 nsresult ContentParent::TransmitPermissionsForPrincipal(
     nsIPrincipal* aPrincipal) {
   // Create the key, and send it down to the content process.
   nsTArray<std::pair<nsCString, nsCString>> pairs =
-      PermissionManager::GetAllKeysForPrincipal(aPrincipal);
+      nsPermissionManager::GetAllKeysForPrincipal(aPrincipal);
   MOZ_ASSERT(pairs.Length() >= 1);
   for (auto& pair : pairs) {
     EnsurePermissionsByKey(pair.first, pair.second);
   }
 
   return NS_OK;
 }
 
@@ -5501,17 +5501,17 @@ void ContentParent::TransmitBlobURLsForP
 
 void ContentParent::EnsurePermissionsByKey(const nsCString& aKey,
                                            const nsCString& aOrigin) {
   // NOTE: Make sure to initialize the permission manager before updating the
   // mActivePermissionKeys list. If the permission manager is being initialized
   // by this call to GetPermissionManager, and we've added the key to
   // mActivePermissionKeys, then the permission manager will send down a
   // SendAddPermission before receiving the SendSetPermissionsWithKey message.
-  RefPtr<PermissionManager> permManager = PermissionManager::GetInstance();
+  RefPtr<nsPermissionManager> permManager = nsPermissionManager::GetInstance();
   if (!permManager) {
     return;
   }
 
   if (mActivePermissionKeys.Contains(aKey)) {
     return;
   }
   mActivePermissionKeys.PutEntry(aKey);
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -184,16 +184,17 @@ LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/bindings',
     '/dom/events',
     '/dom/filesystem',
     '/dom/geolocation',
     '/dom/media/webspeech/synth/ipc',
     '/dom/security',
     '/dom/storage',
+    '/extensions/permissions',
     '/extensions/spellcheck/src',
     '/gfx/2d',
     '/hal/sandbox',
     '/js/xpconnect/loader',
     '/js/xpconnect/src',
     '/layout/base',
     '/media/webrtc',
     '/netwerk/base',
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -27,17 +27,16 @@
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/UserActivation.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/media/MediaTaskUtils.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/PeerIdentity.h"
-#include "mozilla/PermissionDelegateHandler.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StaticPrefs_media.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Types.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsArray.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
@@ -51,16 +50,17 @@
 #include "nsJSUtils.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "nspr.h"
 #include "nsProxyRelease.h"
 #include "nss.h"
 #include "nsVariant.h"
+#include "PermissionDelegateHandler.h"
 #include "pk11pub.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 #include "VideoStreamTrack.h"
 #include "VideoUtils.h"
 #include "CubebDeviceEnumerator.h"
 
 /* Using WebRTC backend on Desktops (Mac, Windows, Linux), otherwise default */
 #include "MediaEngineDefault.h"
--- a/dom/permission/PermissionStatus.cpp
+++ b/dom/permission/PermissionStatus.cpp
@@ -1,23 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/dom/PermissionStatus.h"
-#include "mozilla/PermissionDelegateHandler.h"
 
 #include "mozilla/AsyncEventDispatcher.h"
-#include "mozilla/Permission.h"
 #include "mozilla/Services.h"
 #include "nsIPermissionManager.h"
 #include "PermissionObserver.h"
 #include "PermissionUtils.h"
+#include "nsPermission.h"
+#include "PermissionDelegateHandler.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */
 already_AddRefed<PermissionStatus> PermissionStatus::Create(
     nsPIDOMWindowInner* aWindow, PermissionName aName, ErrorResult& aRv) {
   RefPtr<PermissionStatus> status = new PermissionStatus(aWindow, aName);
@@ -100,17 +100,17 @@ already_AddRefed<nsIPrincipal> Permissio
   }
 
   Document* doc = window->GetExtantDoc();
   if (NS_WARN_IF(!doc)) {
     return nullptr;
   }
 
   nsCOMPtr<nsIPrincipal> principal =
-      Permission::ClonePrincipalForPermission(doc->NodePrincipal());
+      nsPermission::ClonePrincipalForPermission(doc->NodePrincipal());
   NS_ENSURE_TRUE(principal, nullptr);
 
   return principal.forget();
 }
 
 void PermissionStatus::PermissionChanged() {
   auto oldState = mState;
   UpdateState();
--- a/dom/permission/moz.build
+++ b/dom/permission/moz.build
@@ -14,13 +14,17 @@ EXPORTS.mozilla.dom += [
 
 UNIFIED_SOURCES += [
     'PermissionObserver.cpp',
     'Permissions.cpp',
     'PermissionStatus.cpp',
     'PermissionUtils.cpp',
 ]
 
+LOCAL_INCLUDES += [
+    '/extensions/permissions',
+]
+
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/serviceworkers/ServiceWorkerManager.cpp
+++ b/dom/serviceworkers/ServiceWorkerManager.cpp
@@ -48,22 +48,22 @@
 #include "mozilla/dom/SharedWorker.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/dom/ScriptLoader.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/Unused.h"
 #include "mozilla/EnumSet.h"
 
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
+#include "nsPermissionManager.h"
 #include "nsProxyRelease.h"
 #include "nsQueryObject.h"
 #include "nsTArray.h"
 
 #include "ServiceWorker.h"
 #include "ServiceWorkerContainer.h"
 #include "ServiceWorkerInfo.h"
 #include "ServiceWorkerJobQueue.h"
@@ -2282,17 +2282,18 @@ void ServiceWorkerManager::DispatchFetch
       new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(),
                                              aChannel, loadGroup);
 
   // When this service worker was registered, we also sent down the permissions
   // for the runnable. They should have arrived by now, but we still need to
   // wait for them if they have not.
   nsCOMPtr<nsIRunnable> permissionsRunnable = NS_NewRunnableFunction(
       "dom::ServiceWorkerManager::DispatchFetchEvent", [=]() {
-        RefPtr<PermissionManager> permMgr = PermissionManager::GetInstance();
+        RefPtr<nsPermissionManager> permMgr =
+            nsPermissionManager::GetInstance();
         if (permMgr) {
           permMgr->WhenPermissionsAvailable(serviceWorker->Principal(),
                                             continueRunnable);
         } else {
           continueRunnable->HandleError();
         }
       });
 
--- a/dom/serviceworkers/moz.build
+++ b/dom/serviceworkers/moz.build
@@ -102,16 +102,17 @@ IPDL_SOURCES += [
     'ServiceWorkerRegistrarTypes.ipdlh',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
+    '/extensions/permissions',
     '/js/xpconnect/loader',
 ]
 
 MOCHITEST_MANIFESTS += [
     'test/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += [
--- a/dom/workers/remoteworkers/RemoteWorkerChild.cpp
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp
@@ -10,16 +10,17 @@
 
 #include "MainThreadUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsIConsoleReportCollector.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIPrincipal.h"
 #include "nsNetUtil.h"
+#include "nsPermissionManager.h"
 #include "nsProxyRelease.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 #include "RemoteWorkerService.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/BasePrincipal.h"
@@ -41,17 +42,16 @@
 #include "mozilla/dom/workerinternals/ScriptLoader.h"
 #include "mozilla/dom/WorkerError.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/net/CookieJarSettings.h"
-#include "mozilla/PermissionManager.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
 using workerinternals::ChannelFromScriptURLMainThread;
@@ -460,18 +460,18 @@ nsresult RemoteWorkerChild::ExecWorkerOn
             isPending = lock->is<Pending>();
           }
           if (NS_WARN_IF(!isPending || !initializeWorkerRunnable->Dispatch())) {
             self->TransitionStateToTerminated();
             self->CreationFailedOnAnyThread();
           }
         });
 
-    RefPtr<PermissionManager> permissionManager =
-        PermissionManager::GetInstance();
+    RefPtr<nsPermissionManager> permissionManager =
+        nsPermissionManager::GetInstance();
     if (!permissionManager) {
       return NS_ERROR_FAILURE;
     }
     permissionManager->WhenPermissionsAvailable(principal, r);
   } else {
     if (NS_WARN_IF(!runnable->Dispatch())) {
       rv = NS_ERROR_FAILURE;
       return rv;
--- a/dom/workers/remoteworkers/moz.build
+++ b/dom/workers/remoteworkers/moz.build
@@ -24,16 +24,17 @@ UNIFIED_SOURCES += [
     'RemoteWorkerParent.cpp',
     'RemoteWorkerService.cpp',
     'RemoteWorkerServiceChild.cpp',
     'RemoteWorkerServiceParent.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/serviceworkers',
+    '/extensions/permissions',
     '/xpcom/build',
 ]
 
 IPDL_SOURCES += [
     'PRemoteWorker.ipdl',
     'PRemoteWorkerController.ipdl',
     'PRemoteWorkerService.ipdl',
     'RemoteWorkerTypes.ipdlh',
--- a/extensions/permissions/PermissionDelegateHandler.cpp
+++ b/extensions/permissions/PermissionDelegateHandler.cpp
@@ -1,31 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
-#include "mozilla/PermissionDelegateHandler.h"
-
 #include "nsGlobalWindowInner.h"
+#include "PermissionDelegateHandler.h"
 #include "nsPIDOMWindow.h"
+#include "nsPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsContentPermissionHelper.h"
 
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/StaticPrefs_permissions.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
-#include "mozilla/PermissionManager.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
-
-namespace mozilla {
-
 typedef PermissionDelegateHandler::PermissionDelegatePolicy DelegatePolicy;
 typedef PermissionDelegateHandler::PermissionDelegateInfo DelegateInfo;
 
 // Particular type of permissions to care about. We decide cases by case and
 // give various types of controls over each of these.
 static const DelegateInfo sPermissionsMap[] = {
     // Permissions API map
     {"geo", u"geolocation", DelegatePolicy::eDelegateUseFeaturePolicy},
@@ -130,17 +127,17 @@ nsresult PermissionDelegateHandler::GetD
   }
 
   return aRequest->GetPrincipal(aResult);
 }
 
 bool PermissionDelegateHandler::Initialize() {
   MOZ_ASSERT(mDocument);
 
-  mPermissionManager = PermissionManager::GetInstance();
+  mPermissionManager = nsPermissionManager::GetInstance();
   if (!mPermissionManager) {
     return false;
   }
 
   mPrincipal = mDocument->NodePrincipal();
   nsPIDOMWindowInner* window = mDocument->GetInnerWindow();
   nsGlobalWindowInner* innerWindow = nsGlobalWindowInner::Cast(window);
   if (innerWindow) {
@@ -240,10 +237,8 @@ nsresult PermissionDelegateHandler::GetP
 
   return (mPermissionManager->*testPermission)(principal, aType, aPermission);
 }
 
 nsresult PermissionDelegateHandler::GetPermissionForPermissionsAPI(
     const nsACString& aType, uint32_t* aPermission) {
   return GetPermission(aType, aPermission, false);
 }
-
-}  // namespace mozilla
--- a/extensions/permissions/PermissionDelegateHandler.h
+++ b/extensions/permissions/PermissionDelegateHandler.h
@@ -18,32 +18,30 @@
  * denied. if the top-level origin already has access to geolocation and the
  * iframe has been granted access to geolocation by Feature Policy, the iframe
  * will also have access to geolocation. If the top-level frame did not have
  * access to geolocation, and the iframe has been granted access to geolocation
  * by Feature Policy, a request from the cross-origin iframe would trigger a
  * prompt using of the top-level origin.
  */
 
-#ifndef mozilla_PermissionDelegateHandler_h
-#define mozilla_PermissionDelegateHandler_h
+#ifndef PermissionDelegateHandler_h__
+#define PermissionDelegateHandler_h__
 
-#include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsIPermissionDelegateHandler.h"
-#include "nsCOMPtr.h"
 
-class nsIPermissionManager;
 class nsIPrincipal;
 class nsIContentPermissionRequest;
 
 namespace mozilla {
 namespace dom {
 class Document;
 }
+}  // namespace mozilla
 
 class PermissionDelegateHandler final : public nsIPermissionDelegateHandler {
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(PermissionDelegateHandler)
 
   NS_DECL_NSIPERMISSIONDELEGATEHANDLER
 
@@ -159,11 +157,9 @@ class PermissionDelegateHandler final : 
   // A weak pointer to our document. Nulled out by DropDocumentReference.
   mozilla::dom::Document* mDocument;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIPrincipal> mTopLevelPrincipal;
   RefPtr<nsIPermissionManager> mPermissionManager;
 };
 
-}  // namespace mozilla
-
-#endif  // mozilla_PermissionDelegateHandler_h
+#endif  // PermissionDelegateHandler_h__
--- a/extensions/permissions/components.conf
+++ b/extensions/permissions/components.conf
@@ -5,18 +5,18 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 Classes = [
     {
         'cid': '{4f6b5e00-0c36-11d5-a535-0010a401eb10}',
         'contract_ids': ['@mozilla.org/permissionmanager;1'],
         'singleton': True,
         'type': 'nsIPermissionManager',
-        'constructor': 'mozilla::PermissionManager::GetXPCOMSingleton',
-        'headers': ['/extensions/permissions/PermissionManager.h'],
+        'constructor': 'nsPermissionManager::GetXPCOMSingleton',
+        'headers': ['/extensions/permissions/nsPermissionManager.h'],
     },
     {
         'cid': '{07611dc6-bf4d-4d8a-a64b-f3a5904dddc7}',
         'contract_ids': ['@mozilla.org/permissiondelegatehandler;1'],
         'type': 'PermissionDelegateHandler',
         'headers': ['/extensions/permissions/PermissionDelegateHandler.h'],
     },
 ]
--- a/extensions/permissions/moz.build
+++ b/extensions/permissions/moz.build
@@ -5,26 +5,24 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['test']
 
 TESTING_JS_MODULES += [
     'test/PermissionTestUtils.jsm',
 ]
 
-EXPORTS.mozilla += [
-    'Permission.h',
+EXPORTS += [
     'PermissionDelegateHandler.h',
-    'PermissionManager.h',
 ]
 
 UNIFIED_SOURCES += [
-    'Permission.cpp',
+    'nsPermission.cpp',
+    'nsPermissionManager.cpp',
     'PermissionDelegateHandler.cpp',
-    'PermissionManager.cpp',
 ]
 
 XPCOM_MANIFESTS += [
     'components.conf',
 ]
 
 LOCAL_INCLUDES += [
     '/caps',
rename from extensions/permissions/Permission.cpp
rename to extensions/permissions/nsPermission.cpp
--- a/extensions/permissions/Permission.cpp
+++ b/extensions/permissions/nsPermission.cpp
@@ -1,39 +1,38 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-#include "mozilla/Permission.h"
+#include "nsPermission.h"
+#include "nsContentUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/StaticPrefs_permissions.h"
 
-namespace mozilla {
-
-// Permission Implementation
+// nsPermission Implementation
 
-NS_IMPL_CLASSINFO(Permission, nullptr, 0, {0})
-NS_IMPL_ISUPPORTS_CI(Permission, nsIPermission)
+NS_IMPL_CLASSINFO(nsPermission, nullptr, 0, {0})
+NS_IMPL_ISUPPORTS_CI(nsPermission, nsIPermission)
 
-Permission::Permission(nsIPrincipal* aPrincipal, const nsACString& aType,
-                       uint32_t aCapability, uint32_t aExpireType,
-                       int64_t aExpireTime, int64_t aModificationTime)
+nsPermission::nsPermission(nsIPrincipal* aPrincipal, const nsACString& aType,
+                           uint32_t aCapability, uint32_t aExpireType,
+                           int64_t aExpireTime, int64_t aModificationTime)
     : mPrincipal(aPrincipal),
       mType(aType),
       mCapability(aCapability),
       mExpireType(aExpireType),
       mExpireTime(aExpireTime),
       mModificationTime(aModificationTime) {}
 
-already_AddRefed<nsIPrincipal> Permission::ClonePrincipalForPermission(
+already_AddRefed<nsIPrincipal> nsPermission::ClonePrincipalForPermission(
     nsIPrincipal* aPrincipal) {
   MOZ_ASSERT(aPrincipal);
 
   mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef();
   if (!StaticPrefs::permissions_isolateBy_userContext()) {
     attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
   }
 
@@ -43,88 +42,89 @@ already_AddRefed<nsIPrincipal> Permissio
 
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
 }
 
-already_AddRefed<Permission> Permission::Create(
+already_AddRefed<nsPermission> nsPermission::Create(
     nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aCapability,
     uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime) {
   NS_ENSURE_TRUE(aPrincipal, nullptr);
 
   nsCOMPtr<nsIPrincipal> principal =
-      Permission::ClonePrincipalForPermission(aPrincipal);
+      nsPermission::ClonePrincipalForPermission(aPrincipal);
   NS_ENSURE_TRUE(principal, nullptr);
 
-  RefPtr<Permission> permission =
-      new Permission(principal, aType, aCapability, aExpireType, aExpireTime,
-                     aModificationTime);
+  RefPtr<nsPermission> permission =
+      new nsPermission(principal, aType, aCapability, aExpireType, aExpireTime,
+                       aModificationTime);
   return permission.forget();
 }
 
 NS_IMETHODIMP
-Permission::GetPrincipal(nsIPrincipal** aPrincipal) {
+nsPermission::GetPrincipal(nsIPrincipal** aPrincipal) {
   nsCOMPtr<nsIPrincipal> copy = mPrincipal;
   copy.forget(aPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::GetType(nsACString& aType) {
+nsPermission::GetType(nsACString& aType) {
   aType = mType;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::GetCapability(uint32_t* aCapability) {
+nsPermission::GetCapability(uint32_t* aCapability) {
   *aCapability = mCapability;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::GetExpireType(uint32_t* aExpireType) {
+nsPermission::GetExpireType(uint32_t* aExpireType) {
   *aExpireType = mExpireType;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::GetExpireTime(int64_t* aExpireTime) {
+nsPermission::GetExpireTime(int64_t* aExpireTime) {
   *aExpireTime = mExpireTime;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::GetModificationTime(int64_t* aModificationTime) {
+nsPermission::GetModificationTime(int64_t* aModificationTime) {
   *aModificationTime = mModificationTime;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches) {
+nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost,
+                      bool* aMatches) {
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aMatches);
 
   *aMatches = false;
 
   nsCOMPtr<nsIPrincipal> principal =
-      Permission::ClonePrincipalForPermission(aPrincipal);
+      nsPermission::ClonePrincipalForPermission(aPrincipal);
   if (!principal) {
     *aMatches = false;
     return NS_OK;
   }
 
   return MatchesPrincipalForPermission(principal, aExactHost, aMatches);
 }
 
 NS_IMETHODIMP
-Permission::MatchesPrincipalForPermission(nsIPrincipal* aPrincipal,
-                                          bool aExactHost, bool* aMatches) {
+nsPermission::MatchesPrincipalForPermission(nsIPrincipal* aPrincipal,
+                                            bool aExactHost, bool* aMatches) {
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aMatches);
 
   *aMatches = false;
 
   // If the principals are equal, then they match.
   if (mPrincipal->Equals(aPrincipal)) {
     *aMatches = true;
@@ -202,30 +202,29 @@ Permission::MatchesPrincipalForPermissio
 
   // This loop will not loop forever, as GetNextSubDomain will eventually fail
   // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
   while (theirHost != ourHost) {
     rv = tldService->GetNextSubDomain(theirHost, theirHost);
     if (NS_FAILED(rv)) {
       if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
         return NS_OK;
+      } else {
+        return rv;
       }
-      return rv;
     }
   }
 
   *aMatches = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Permission::MatchesURI(nsIURI* aURI, bool aExactHost, bool* aMatches) {
+nsPermission::MatchesURI(nsIURI* aURI, bool aExactHost, bool* aMatches) {
   NS_ENSURE_ARG_POINTER(aURI);
 
   mozilla::OriginAttributes attrs;
   nsCOMPtr<nsIPrincipal> principal =
       mozilla::BasePrincipal::CreateContentPrincipal(aURI, attrs);
   NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
 
   return Matches(principal, aExactHost, aMatches);
 }
-
-}  // namespace mozilla
rename from extensions/permissions/Permission.h
rename to extensions/permissions/nsPermission.h
--- a/extensions/permissions/Permission.h
+++ b/extensions/permissions/nsPermission.h
@@ -1,49 +1,45 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
-#ifndef mozilla_Permission_h
-#define mozilla_Permission_h
+#ifndef nsPermission_h__
+#define nsPermission_h__
 
 #include "nsIPermission.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
-namespace mozilla {
-
 ////////////////////////////////////////////////////////////////////////////////
 
-class Permission : public nsIPermission {
+class nsPermission : public nsIPermission {
  public:
   // nsISupports
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPERMISSION
 
-  static already_AddRefed<Permission> Create(
+  static already_AddRefed<nsPermission> Create(
       nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aCapability,
       uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime);
 
   // This method creates a new nsIPrincipal with a stripped OriginAttributes (no
   // userContextId) and a content principal equal to the origin of 'aPrincipal'.
   static already_AddRefed<nsIPrincipal> ClonePrincipalForPermission(
       nsIPrincipal* aPrincipal);
 
  protected:
-  Permission(nsIPrincipal* aPrincipal, const nsACString& aType,
-             uint32_t aCapability, uint32_t aExpireType, int64_t aExpireTime,
-             int64_t aModificationTime);
+  nsPermission(nsIPrincipal* aPrincipal, const nsACString& aType,
+               uint32_t aCapability, uint32_t aExpireType, int64_t aExpireTime,
+               int64_t aModificationTime);
 
-  virtual ~Permission() = default;
+  virtual ~nsPermission(){};
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCString mType;
   uint32_t mCapability;
   uint32_t mExpireType;
   int64_t mExpireTime;
   int64_t mModificationTime;
 };
 
-}  // namespace mozilla
-
-#endif  // mozilla_Permission_h
+#endif  // nsPermission_h__
rename from extensions/permissions/PermissionManager.cpp
rename to extensions/permissions/nsPermissionManager.cpp
--- a/extensions/permissions/PermissionManager.cpp
+++ b/extensions/permissions/nsPermissionManager.cpp
@@ -1,67 +1,78 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
-#include "mozilla/AbstractThread.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/BasePrincipal.h"
-#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/ContentPrincipal.h"
 #include "mozilla/DebugOnly.h"
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/ExpandedPrincipal.h"
+#include "mozilla/Services.h"
+#include "nsPermissionManager.h"
+#include "nsPermission.h"
+#include "nsCRT.h"
+#include "nsNetUtil.h"
+#include "nsTArray.h"
+#include "nsReadableUtils.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceDefs.h"
+#include "mozIStorageCompletionCallback.h"
+#include "mozIStorageService.h"
+#include "mozIStorageStatementCallback.h"
+#include "mozilla/storage.h"
+#include "mozilla/Attributes.h"
+#include "nsXULAppAPI.h"
+#include "nsIIdleService.h"
+#include "nsIPrincipal.h"
+#include "nsIURIMutator.h"
+#include "nsContentUtils.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/Document.h"
 #include "mozilla/net/NeckoMessageUtils.h"
-#include "mozilla/Permission.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs_permissions.h"
+#include "nsReadLine.h"
 #include "mozilla/Telemetry.h"
-
-#include "mozIStorageService.h"
-#include "mozIStorageConnection.h"
-#include "mozIStorageStatement.h"
-#include "mozStorageCID.h"
-
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsContentUtils.h"
-#include "nsEffectiveTLDService.h"
 #include "nsIConsoleService.h"
-#include "nsIIdleService.h"
-#include "nsIInputStream.h"
 #include "nsINavHistoryService.h"
-#include "nsIObserverService.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrincipal.h"
-#include "nsIURIMutator.h"
-#include "nsReadLine.h"
 #include "nsToolkitCompsCID.h"
-
+#include "nsIObserverService.h"
+#include "nsPrintfCString.h"
+#include "mozilla/AbstractThread.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "nsEffectiveTLDService.h"
+
+static mozilla::StaticRefPtr<nsPermissionManager> gPermissionManager;
+
+// Initially, |false|. Set to |true| once shutdown has started, to avoid
+// reopening the database.
+static bool gIsShuttingDown = false;
+
+using namespace mozilla;
 using namespace mozilla::dom;
 
-namespace mozilla {
-
-#define PERMISSIONS_FILE_NAME "permissions.sqlite"
-#define HOSTS_SCHEMA_VERSION 11
-
-// Default permissions are read from a URL - this is the preference we read
-// to find that URL. If not set, don't use any default permissions.
-constexpr char kDefaultsUrlPrefName[] = "permissions.manager.defaultsUrl";
-
-constexpr char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION;
-
-// A special value for a permission ID that indicates the ID was loaded as
-// a default value.  These will never be written to the database, but may
-// be overridden with an explicit permission (including UNKNOWN_ACTION)
-constexpr int64_t cIDPermissionIsDefault = -1;
-
-static StaticRefPtr<PermissionManager> gPermissionManager;
+static bool IsChildProcess() { return XRE_IsContentProcess(); }
+
+static void LogToConsole(const nsAString& aMsg) {
+  nsCOMPtr<nsIConsoleService> console(
+      do_GetService("@mozilla.org/consoleservice;1"));
+  if (!console) {
+    NS_WARNING("Failed to log message to console.");
+    return;
+  }
+
+  nsAutoString msg(aMsg);
+  console->LogStringMessage(msg.get());
+}
 
 #define ENSURE_NOT_CHILD_PROCESS_(onError)                 \
   PR_BEGIN_MACRO                                           \
   if (IsChildProcess()) {                                  \
     NS_ERROR("Cannot perform action in content process!"); \
     onError                                                \
   }                                                        \
   PR_END_MACRO
@@ -72,51 +83,16 @@ static StaticRefPtr<PermissionManager> g
 #define ENSURE_NOT_CHILD_PROCESS_NORET ENSURE_NOT_CHILD_PROCESS_(;)
 
 #define EXPIRY_NOW PR_Now() / 1000
 
 ////////////////////////////////////////////////////////////////////////////////
 
 namespace {
 
-bool IsChildProcess() { return XRE_IsContentProcess(); }
-
-void LogToConsole(const nsAString& aMsg) {
-  nsCOMPtr<nsIConsoleService> console(
-      do_GetService("@mozilla.org/consoleservice;1"));
-  if (!console) {
-    NS_WARNING("Failed to log message to console.");
-    return;
-  }
-
-  nsAutoString msg(aMsg);
-  console->LogStringMessage(msg.get());
-}
-
-// NOTE: an empty string can be passed as aType - if it is this function will
-// return "false" unconditionally.
-bool HasDefaultPref(const nsACString& aType) {
-  // A list of permissions that can have a fallback default permission
-  // set under the permissions.default.* pref.
-  static const nsLiteralCString kPermissionsWithDefaults[] = {
-      NS_LITERAL_CSTRING("camera"), NS_LITERAL_CSTRING("microphone"),
-      NS_LITERAL_CSTRING("geo"), NS_LITERAL_CSTRING("desktop-notification"),
-      NS_LITERAL_CSTRING("shortcuts")};
-
-  if (!aType.IsEmpty()) {
-    for (const auto& perm : kPermissionsWithDefaults) {
-      if (perm.Equals(aType)) {
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
 // These permissions are special permissions which must be transmitted to the
 // content process before documents with their principals have loaded within
 // that process.
 //
 // Permissions which are in this list are considered to have a "" permission
 // key, even if their principal would not normally have that key.
 static const nsLiteralCString kPreloadPermissions[] = {
     // This permission is preloaded to support properly blocking service worker
@@ -216,17 +192,17 @@ nsresult GetOriginFromPrincipal(nsIPrinc
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsAutoCString suffix;
   rv = aPrincipal->GetOriginSuffix(suffix);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  OriginAttributes attrs;
+  mozilla::OriginAttributes attrs;
   if (!attrs.PopulateFromSuffix(suffix)) {
     return NS_ERROR_FAILURE;
   }
 
   OriginAppendOASuffix(attrs, aForceStripOA, aOrigin);
 
   return NS_OK;
 }
@@ -243,48 +219,48 @@ nsresult GetOriginFromURIAndOA(nsIURI* a
   aOrigin = origin;
 
   return NS_OK;
 }
 
 nsresult GetPrincipalFromOrigin(const nsACString& aOrigin, bool aForceStripOA,
                                 nsIPrincipal** aPrincipal) {
   nsAutoCString originNoSuffix;
-  OriginAttributes attrs;
+  mozilla::OriginAttributes attrs;
   if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
     return NS_ERROR_FAILURE;
   }
 
   MaybeStripOAs(aForceStripOA, attrs);
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrincipal> principal =
-      BasePrincipal::CreateContentPrincipal(uri, attrs);
+      mozilla::BasePrincipal::CreateContentPrincipal(uri, attrs);
   principal.forget(aPrincipal);
   return NS_OK;
 }
 
 nsresult GetPrincipal(nsIURI* aURI, bool aIsInIsolatedMozBrowserElement,
                       nsIPrincipal** aPrincipal) {
-  OriginAttributes attrs(aIsInIsolatedMozBrowserElement);
+  mozilla::OriginAttributes attrs(aIsInIsolatedMozBrowserElement);
   nsCOMPtr<nsIPrincipal> principal =
-      BasePrincipal::CreateContentPrincipal(aURI, attrs);
+      mozilla::BasePrincipal::CreateContentPrincipal(aURI, attrs);
   NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
 
   principal.forget(aPrincipal);
   return NS_OK;
 }
 
 nsresult GetPrincipal(nsIURI* aURI, nsIPrincipal** aPrincipal) {
-  OriginAttributes attrs;
+  mozilla::OriginAttributes attrs;
   nsCOMPtr<nsIPrincipal> principal =
-      BasePrincipal::CreateContentPrincipal(aURI, attrs);
+      mozilla::BasePrincipal::CreateContentPrincipal(aURI, attrs);
   NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
 
   principal.forget(aPrincipal);
   return NS_OK;
 }
 
 nsCString GetNextSubDomainForHost(const nsACString& aHost) {
   nsCString subDomain;
@@ -337,37 +313,208 @@ already_AddRefed<nsIPrincipal> GetNextSu
   // Create a new principal which is identical to the current one, but with the
   // new host
   nsCOMPtr<nsIURI> newURI = GetNextSubDomainURI(uri);
   if (!newURI) {
     return nullptr;
   }
 
   // Copy the attributes over
-  OriginAttributes attrs = aPrincipal->OriginAttributesRef();
+  mozilla::OriginAttributes attrs = aPrincipal->OriginAttributesRef();
 
   if (!StaticPrefs::permissions_isolateBy_userContext()) {
     // Disable userContext for permissions.
-    attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID);
+    attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
   }
 
   nsCOMPtr<nsIPrincipal> principal =
-      BasePrincipal::CreateContentPrincipal(newURI, attrs);
+      mozilla::BasePrincipal::CreateContentPrincipal(newURI, attrs);
 
   return principal.forget();
 }
 
+class MOZ_STACK_CLASS UpgradeHostToOriginHelper {
+ public:
+  virtual nsresult Insert(const nsACString& aOrigin, const nsCString& aType,
+                          uint32_t aPermission, uint32_t aExpireType,
+                          int64_t aExpireTime, int64_t aModificationTime) = 0;
+};
+
+class MOZ_STACK_CLASS UpgradeHostToOriginDBMigration final
+    : public UpgradeHostToOriginHelper {
+ public:
+  UpgradeHostToOriginDBMigration(mozIStorageConnection* aDBConn, int64_t* aID)
+      : mDBConn(aDBConn), mID(aID) {
+    mDBConn->CreateStatement(
+        NS_LITERAL_CSTRING("INSERT INTO moz_hosts_new "
+                           "(id, origin, type, permission, expireType, "
+                           "expireTime, modificationTime) "
+                           "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"),
+        getter_AddRefs(mStmt));
+  }
+
+  nsresult Insert(const nsACString& aOrigin, const nsCString& aType,
+                  uint32_t aPermission, uint32_t aExpireType,
+                  int64_t aExpireTime, int64_t aModificationTime) final {
+    nsresult rv = mStmt->BindInt64ByIndex(0, *mID);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindUTF8StringByIndex(1, aOrigin);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindUTF8StringByIndex(2, aType);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt32ByIndex(3, aPermission);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt32ByIndex(4, aExpireType);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt64ByIndex(5, aExpireTime);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt64ByIndex(6, aModificationTime);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Increment the working identifier, as we are about to use this one
+    (*mID)++;
+
+    rv = mStmt->Execute();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
+
+ private:
+  nsCOMPtr<mozIStorageStatement> mStmt;
+  nsCOMPtr<mozIStorageConnection> mDBConn;
+  int64_t* mID;
+};
+
+class MOZ_STACK_CLASS UpgradeHostToOriginHostfileImport final
+    : public UpgradeHostToOriginHelper {
+ public:
+  UpgradeHostToOriginHostfileImport(
+      nsPermissionManager* aPm, nsPermissionManager::DBOperationType aOperation,
+      int64_t aID)
+      : mPm(aPm), mOperation(aOperation), mID(aID) {}
+
+  nsresult Insert(const nsACString& aOrigin, const nsCString& aType,
+                  uint32_t aPermission, uint32_t aExpireType,
+                  int64_t aExpireTime, int64_t aModificationTime) final {
+    nsCOMPtr<nsIPrincipal> principal;
+    nsresult rv = GetPrincipalFromOrigin(
+        aOrigin, IsOAForceStripPermission(aType), getter_AddRefs(principal));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return mPm->AddInternal(principal, aType, aPermission, mID, aExpireType,
+                            aExpireTime, aModificationTime,
+                            nsPermissionManager::eDontNotify, mOperation, false,
+                            &aOrigin);
+  }
+
+ private:
+  RefPtr<nsPermissionManager> mPm;
+  nsPermissionManager::DBOperationType mOperation;
+  int64_t mID;
+};
+
+class MOZ_STACK_CLASS UpgradeIPHostToOriginDB final
+    : public UpgradeHostToOriginHelper {
+ public:
+  UpgradeIPHostToOriginDB(mozIStorageConnection* aDBConn, int64_t* aID)
+      : mDBConn(aDBConn), mID(aID) {
+    mDBConn->CreateStatement(
+        NS_LITERAL_CSTRING("INSERT INTO moz_perms"
+                           "(id, origin, type, permission, expireType, "
+                           "expireTime, modificationTime) "
+                           "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"),
+        getter_AddRefs(mStmt));
+
+    mDBConn->CreateStatement(
+        NS_LITERAL_CSTRING(
+            "SELECT id FROM moz_perms WHERE origin = ?1 AND type = ?2"),
+        getter_AddRefs(mLookupStmt));
+  }
+
+  nsresult Insert(const nsACString& aOrigin, const nsCString& aType,
+                  uint32_t aPermission, uint32_t aExpireType,
+                  int64_t aExpireTime, int64_t aModificationTime) final {
+    // Every time the migration code wants to insert an origin into
+    // the database we need to check to see if someone has already
+    // created a permissions entry for that permission. If they have,
+    // we don't want to insert a duplicate row.
+    //
+    // We can afford to do this lookup unconditionally and not perform
+    // caching, as a origin type pair should only be attempted to be
+    // inserted once.
+
+    nsresult rv = mLookupStmt->Reset();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mLookupStmt->BindUTF8StringByIndex(0, aOrigin);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mLookupStmt->BindUTF8StringByIndex(1, aType);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Check if we already have the row in the database, if we do, then
+    // we don't want to be inserting it again.
+    bool moreStmts = false;
+    if (NS_FAILED(mLookupStmt->ExecuteStep(&moreStmts)) || moreStmts) {
+      mLookupStmt->Reset();
+      NS_WARNING(
+          "A permissions entry was going to be re-migrated, "
+          "but was already found in the permissions database.");
+      return NS_OK;
+    }
+
+    // Actually insert the statement into the database.
+    rv = mStmt->BindInt64ByIndex(0, *mID);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindUTF8StringByIndex(1, aOrigin);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindUTF8StringByIndex(2, aType);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt32ByIndex(3, aPermission);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt32ByIndex(4, aExpireType);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt64ByIndex(5, aExpireTime);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = mStmt->BindInt64ByIndex(6, aModificationTime);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Increment the working identifier, as we are about to use this one
+    (*mID)++;
+
+    rv = mStmt->Execute();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
+
+ private:
+  nsCOMPtr<mozIStorageStatement> mStmt;
+  nsCOMPtr<mozIStorageStatement> mLookupStmt;
+  nsCOMPtr<mozIStorageConnection> mDBConn;
+  int64_t* mID;
+};
+
 nsresult UpgradeHostToOriginAndInsert(
     const nsACString& aHost, const nsCString& aType, uint32_t aPermission,
     uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
-    bool aIsInIsolatedMozBrowserElement,
-    std::function<nsresult(const nsACString& aOrigin, const nsCString& aType,
-                           uint32_t aPermission, uint32_t aExpireType,
-                           int64_t aExpireTime, int64_t aModificationTime)>&&
-        aCallback) {
+    bool aIsInIsolatedMozBrowserElement, UpgradeHostToOriginHelper* aHelper) {
   if (aHost.EqualsLiteral("<file>")) {
     // We no longer support the magic host <file>
     NS_WARNING(
         "The magic host <file> is no longer supported. "
         "It is being removed from the permissions database.");
     return NS_OK;
   }
 
@@ -389,18 +536,18 @@ nsresult UpgradeHostToOriginAndInsert(
                       getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString origin;
     rv = GetOriginFromPrincipal(principal, IsOAForceStripPermission(aType),
                                 origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    aCallback(origin, aType, aPermission, aExpireType, aExpireTime,
-              aModificationTime);
+    return aHelper->Insert(origin, aType, aPermission, aExpireType, aExpireTime,
+                           aModificationTime);
     return NS_OK;
   }
 
   // The user may use this host at non-standard ports or protocols, we can use
   // their history to guess what ports and protocols we want to add permissions
   // for. We find every URI which they have visited with this host (or a
   // subdomain of this host), and try to add it as a principal.
   bool foundHistory = false;
@@ -511,18 +658,18 @@ nsresult UpgradeHostToOriginAndInsert(
       if (NS_WARN_IF(NS_FAILED(rv))) continue;
 
       // Ensure that we don't insert the same origin repeatedly
       if (insertedOrigins.Contains(origin)) {
         continue;
       }
 
       foundHistory = true;
-      rv = aCallback(origin, aType, aPermission, aExpireType, aExpireTime,
-                     aModificationTime);
+      rv = aHelper->Insert(origin, aType, aPermission, aExpireType, aExpireTime,
+                           aModificationTime);
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Insert failed");
       insertedOrigins.PutEntry(origin);
     }
 
     rv = histResultContainer->SetContainerOpen(false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -553,666 +700,703 @@ nsresult UpgradeHostToOriginAndInsert(
     rv = GetPrincipal(uri, aIsInIsolatedMozBrowserElement,
                       getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = GetOriginFromPrincipal(principal, IsOAForceStripPermission(aType),
                                 origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    aCallback(origin, aType, aPermission, aExpireType, aExpireTime,
-              aModificationTime);
+    aHelper->Insert(origin, aType, aPermission, aExpireType, aExpireTime,
+                    aModificationTime);
 
     // https:// URI default
     rv = NS_NewURI(getter_AddRefs(uri),
                    NS_LITERAL_CSTRING("https://") + hostSegment);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = GetPrincipal(uri, aIsInIsolatedMozBrowserElement,
                       getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = GetOriginFromPrincipal(principal, IsOAForceStripPermission(aType),
                                 origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    aCallback(origin, aType, aPermission, aExpireType, aExpireTime,
-              aModificationTime);
+    aHelper->Insert(origin, aType, aPermission, aExpireType, aExpireTime,
+                    aModificationTime);
   }
 
   return NS_OK;
 }
 
-bool IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
+static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
   nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
   return !!ep;
 }
 
 // We only want to persist permissions which don't have session or policy
 // expiration.
-bool IsPersistentExpire(uint32_t aExpire, const nsACString& aType) {
+static bool IsPersistentExpire(uint32_t aExpire, const nsACString& aType) {
   bool res = (aExpire != nsIPermissionManager::EXPIRE_SESSION &&
               aExpire != nsIPermissionManager::EXPIRE_POLICY);
 #ifdef ANDROID
   for (const auto& perm : kGeckoViewRestrictedPermissions) {
     res = res && !perm.Equals(aType);
   }
 #endif
   return res;
 }
 
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 
-PermissionManager::PermissionKey*
-PermissionManager::PermissionKey::CreateFromPrincipal(nsIPrincipal* aPrincipal,
-                                                      bool aForceStripOA,
-                                                      nsresult& aResult) {
+nsPermissionManager::PermissionKey*
+nsPermissionManager::PermissionKey::CreateFromPrincipal(
+    nsIPrincipal* aPrincipal, bool aForceStripOA, nsresult& aResult) {
   nsAutoCString origin;
   aResult = GetOriginFromPrincipal(aPrincipal, aForceStripOA, origin);
   if (NS_WARN_IF(NS_FAILED(aResult))) {
     return nullptr;
   }
 
   return new PermissionKey(origin);
 }
 
-PermissionManager::PermissionKey*
-PermissionManager::PermissionKey::CreateFromURIAndOriginAttributes(
+nsPermissionManager::PermissionKey*
+nsPermissionManager::PermissionKey::CreateFromURIAndOriginAttributes(
     nsIURI* aURI, const OriginAttributes* aOriginAttributes, bool aForceStripOA,
     nsresult& aResult) {
   nsAutoCString origin;
   aResult =
       GetOriginFromURIAndOA(aURI, aOriginAttributes, aForceStripOA, origin);
   if (NS_WARN_IF(NS_FAILED(aResult))) {
     return nullptr;
   }
 
   return new PermissionKey(origin);
 }
 
-PermissionManager::PermissionKey*
-PermissionManager::PermissionKey::CreateFromURI(nsIURI* aURI,
-                                                nsresult& aResult) {
+nsPermissionManager::PermissionKey*
+nsPermissionManager::PermissionKey::CreateFromURI(nsIURI* aURI,
+                                                  nsresult& aResult) {
   nsAutoCString origin;
   aResult = ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, origin);
   if (NS_WARN_IF(NS_FAILED(aResult))) {
     return nullptr;
   }
 
   return new PermissionKey(origin);
 }
 
+/**
+ * Simple callback used by |AsyncClose| to trigger a treatment once
+ * the database is closed.
+ *
+ * Note: Beware that, if you hold onto a |CloseDatabaseListener| from a
+ * |nsPermissionManager|, this will create a cycle.
+ *
+ * Note: Once the callback has been called this DeleteFromMozHostListener cannot
+ * be reused.
+ */
+class CloseDatabaseListener final : public mozIStorageCompletionCallback {
+  ~CloseDatabaseListener() {}
+
+ public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
+  /**
+   * @param aManager The owning manager.
+   * @param aRebuildOnSuccess If |true|, reinitialize the database once
+   * it has been closed. Otherwise, do nothing such.
+   */
+  CloseDatabaseListener(nsPermissionManager* aManager, bool aRebuildOnSuccess);
+
+ protected:
+  RefPtr<nsPermissionManager> mManager;
+  bool mRebuildOnSuccess;
+};
+
+NS_IMPL_ISUPPORTS(CloseDatabaseListener, mozIStorageCompletionCallback)
+
+CloseDatabaseListener::CloseDatabaseListener(nsPermissionManager* aManager,
+                                             bool aRebuildOnSuccess)
+    : mManager(aManager), mRebuildOnSuccess(aRebuildOnSuccess) {}
+
+NS_IMETHODIMP
+CloseDatabaseListener::Complete(nsresult, nsISupports*) {
+  // Help breaking cycles
+  RefPtr<nsPermissionManager> manager = std::move(mManager);
+  if (mRebuildOnSuccess && !gIsShuttingDown) {
+    return manager->InitDB(true);
+  }
+  return NS_OK;
+}
+
+/**
+ * Simple callback used by |RemoveAllInternal| to trigger closing
+ * the database and reinitializing it.
+ *
+ * Note: Beware that, if you hold onto a |DeleteFromMozHostListener| from a
+ * |nsPermissionManager|, this will create a cycle.
+ *
+ * Note: Once the callback has been called this DeleteFromMozHostListener cannot
+ * be reused.
+ */
+class DeleteFromMozHostListener final : public mozIStorageStatementCallback {
+  ~DeleteFromMozHostListener() {}
+
+ public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGESTATEMENTCALLBACK
+
+  /**
+   * @param aManager The owning manager.
+   */
+  explicit DeleteFromMozHostListener(nsPermissionManager* aManager);
+
+ protected:
+  RefPtr<nsPermissionManager> mManager;
+};
+
+NS_IMPL_ISUPPORTS(DeleteFromMozHostListener, mozIStorageStatementCallback)
+
+DeleteFromMozHostListener::DeleteFromMozHostListener(
+    nsPermissionManager* aManager)
+    : mManager(aManager) {}
+
+NS_IMETHODIMP DeleteFromMozHostListener::HandleResult(mozIStorageResultSet*) {
+  MOZ_CRASH("Should not get any results");
+}
+
+NS_IMETHODIMP DeleteFromMozHostListener::HandleError(mozIStorageError*) {
+  // Errors are handled in |HandleCompletion|
+  return NS_OK;
+}
+
+NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(uint16_t aReason) {
+  // Help breaking cycles
+  RefPtr<nsPermissionManager> manager = std::move(mManager);
+
+  if (aReason == REASON_ERROR) {
+    manager->CloseDB(true);
+  }
+
+  return NS_OK;
+}
+
 /* static */
-void PermissionManager::Startup() {
+void nsPermissionManager::Startup() {
   nsCOMPtr<nsIPermissionManager> permManager =
       do_GetService("@mozilla.org/permissionmanager;1");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// PermissionManager Implementation
-
-NS_IMPL_ISUPPORTS(PermissionManager, nsIPermissionManager, nsIObserver,
+// nsPermissionManager Implementation
+
+#define PERMISSIONS_FILE_NAME "permissions.sqlite"
+#define HOSTS_SCHEMA_VERSION 11
+
+// Default permissions are read from a URL - this is the preference we read
+// to find that URL. If not set, don't use any default permissions.
+static const char kDefaultsUrlPrefName[] = "permissions.manager.defaultsUrl";
+
+static const char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION;
+
+NS_IMPL_ISUPPORTS(nsPermissionManager, nsIPermissionManager, nsIObserver,
                   nsISupportsWeakReference)
 
-PermissionManager::PermissionManager()
-    : mMonitor("PermissionManager::mMonitor"),
-      mState(eInitializing),
-      mMemoryOnlyDB(false),
-      mLargestID(0) {}
-
-PermissionManager::~PermissionManager() {
+nsPermissionManager::nsPermissionManager()
+    : mMemoryOnlyDB(false), mLargestID(0) {}
+
+nsPermissionManager::~nsPermissionManager() {
   // NOTE: Make sure to reject each of the promises in mPermissionKeyPromiseMap
   // before destroying.
   for (auto iter = mPermissionKeyPromiseMap.Iter(); !iter.Done(); iter.Next()) {
     if (iter.Data()) {
       iter.Data()->Reject(NS_ERROR_FAILURE, __func__);
     }
   }
   mPermissionKeyPromiseMap.Clear();
 
   RemoveAllFromMemory();
   if (gPermissionManager) {
     MOZ_ASSERT(gPermissionManager == this);
     gPermissionManager = nullptr;
   }
-
-  if (mThread) {
-    mThread->Shutdown();
-    mThread = nullptr;
-  }
 }
 
 // static
-already_AddRefed<nsIPermissionManager> PermissionManager::GetXPCOMSingleton() {
+already_AddRefed<nsIPermissionManager>
+nsPermissionManager::GetXPCOMSingleton() {
   if (gPermissionManager) {
     return do_AddRef(gPermissionManager);
   }
 
-  // Create a new singleton PermissionManager.
+  if (gIsShuttingDown) {
+    return nullptr;
+  }
+
+  // Create a new singleton nsPermissionManager.
   // We AddRef only once since XPCOM has rules about the ordering of module
   // teardowns - by the time our module destructor is called, it's too late to
   // Release our members, since GC cycles have already been completed and
   // would result in serious leaks.
   // See bug 209571.
-  auto permManager = MakeRefPtr<PermissionManager>();
+  auto permManager = MakeRefPtr<nsPermissionManager>();
   if (NS_SUCCEEDED(permManager->Init())) {
-    // Note: This is cleared in the PermissionManager destructor.
+    // Note: This is cleared in the nsPermissionManager destructor.
     gPermissionManager = permManager.get();
     ClearOnShutdown(&gPermissionManager);
     return permManager.forget();
   }
 
   return nullptr;
 }
 
 // static
-PermissionManager* PermissionManager::GetInstance() {
+nsPermissionManager* nsPermissionManager::GetInstance() {
   if (!gPermissionManager) {
     // Hand off the creation of the permission manager to GetXPCOMSingleton.
     nsCOMPtr<nsIPermissionManager> permManager = GetXPCOMSingleton();
   }
 
   return gPermissionManager;
 }
 
-nsresult PermissionManager::Init() {
+nsresult nsPermissionManager::Init() {
   // If the 'permissions.memory_only' pref is set to true, then don't write any
   // permission settings to disk, but keep them in a memory-only database.
-  mMemoryOnlyDB = Preferences::GetBool("permissions.memory_only", false);
+  mMemoryOnlyDB =
+      mozilla::Preferences::GetBool("permissions.memory_only", false);
 
   nsresult rv;
   nsCOMPtr<nsIPrefService> prefService =
       do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = prefService->GetBranch("permissions.default.",
                               getter_AddRefs(mDefaultPrefBranch));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (IsChildProcess()) {
     // Stop here; we don't need the DB in the child process. Instead we will be
     // sent permissions as we need them by our parent process.
-    mState = eReady;
     return NS_OK;
   }
 
-  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+  nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
   if (observerService) {
     observerService->AddObserver(this, "profile-before-change", true);
     observerService->AddObserver(this, "profile-do-change", true);
     observerService->AddObserver(this, "testonly-reload-permissions-from-disk",
                                  true);
   }
 
-  AddIdleDailyMaintenanceJob();
-
-  MOZ_ASSERT(!mThread);
-  NS_ENSURE_SUCCESS(NS_NewNamedThread("Permission", getter_AddRefs(mThread)),
-                    NS_ERROR_FAILURE);
-
-  PRThread* prThread;
-  MOZ_ALWAYS_SUCCEEDS(mThread->GetPRThread(&prThread));
-  MOZ_ASSERT(prThread);
-
-  mThreadBoundData.Transfer(prThread);
-
+  // ignore failure here, since it's non-fatal (we can run fine without
+  // persistent storage - e.g. if there's no profile).
+  // XXX should we tell the user about this?
   InitDB(false);
 
   return NS_OK;
 }
 
-nsresult PermissionManager::OpenDatabase(nsIFile* aPermissionsFile) {
-  MOZ_ASSERT(!NS_IsMainThread());
-  MOZ_ACCESS_THREAD_BOUND(mThreadBoundData, data);
-
+nsresult nsPermissionManager::OpenDatabase(nsIFile* aPermissionsFile) {
   nsresult rv;
   nsCOMPtr<mozIStorageService> storage =
       do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   if (!storage) {
     return NS_ERROR_UNEXPECTED;
   }
   // cache a connection to the hosts database
   if (mMemoryOnlyDB) {
-    rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(data->mDBConn));
+    rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
   } else {
-    rv = storage->OpenDatabase(aPermissionsFile, getter_AddRefs(data->mDBConn));
+    rv = storage->OpenDatabase(aPermissionsFile, getter_AddRefs(mDBConn));
   }
   return rv;
 }
 
-void PermissionManager::InitDB(bool aRemoveFile) {
-  mState = eInitializing;
-
-  {
-    MonitorAutoLock lock(mMonitor);
-    mReadEntries.Clear();
-  }
-
-  auto readyIfFailed = MakeScopeExit([&]() {
-    // ignore failure here, since it's non-fatal (we can run fine without
-    // persistent storage - e.g. if there's no profile).
-    // XXX should we tell the user about this?
-    mState = eReady;
-  });
-
-  if (!mPermissionsFile) {
-    nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR,
-                                         getter_AddRefs(mPermissionsFile));
+nsresult nsPermissionManager::InitDB(bool aRemoveFile) {
+  nsCOMPtr<nsIFile> permissionsFile;
+  nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR,
+                                       getter_AddRefs(permissionsFile));
+  if (NS_FAILED(rv)) {
+    rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
+                                getter_AddRefs(permissionsFile));
     if (NS_FAILED(rv)) {
-      rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
-                                  getter_AddRefs(mPermissionsFile));
-      if (NS_FAILED(rv)) {
-        return;
-      }
+      return NS_ERROR_UNEXPECTED;
     }
-
-    rv = mPermissionsFile->AppendNative(
-        NS_LITERAL_CSTRING(PERMISSIONS_FILE_NAME));
-    NS_ENSURE_SUCCESS_VOID(rv);
   }
 
-  nsCOMPtr<nsIInputStream> defaultsInputStream = GetDefaultsInputStream();
-
-  RefPtr<PermissionManager> self = this;
-  mThread->Dispatch(NS_NewRunnableFunction(
-      "PermissionManager::InitDB", [self, aRemoveFile, defaultsInputStream] {
-        nsresult rv = self->TryInitDB(aRemoveFile, defaultsInputStream);
-        Unused << NS_WARN_IF(NS_FAILED(rv));
-
-        // This extra runnable calls EnsureReadCompleted to finialize the
-        // initialization. If there is something blocked by the monitor, it will
-        // be NOP.
-        NS_DispatchToMainThread(
-            NS_NewRunnableFunction("PermissionManager::InitDB-MainThread",
-                                   [self] { self->EnsureReadCompleted(); }));
-
-        self->mMonitor.Notify();
-      }));
-
-  readyIfFailed.release();
-}
-
-nsresult PermissionManager::TryInitDB(bool aRemoveFile,
-                                      nsIInputStream* aDefaultsInputStream) {
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  MonitorAutoLock lock(mMonitor);
-
-  auto raii = MakeScopeExit([&]() {
-    if (aDefaultsInputStream) {
-      aDefaultsInputStream->Close();
-    }
-
-    mState = eDBInitialized;
-  });
-
-  nsresult rv;
+  rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(PERMISSIONS_FILE_NAME));
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (aRemoveFile) {
     bool exists = false;
-    rv = mPermissionsFile->Exists(&exists);
+    rv = permissionsFile->Exists(&exists);
     NS_ENSURE_SUCCESS(rv, rv);
     if (exists) {
-      rv = mPermissionsFile->Remove(false);
+      rv = permissionsFile->Remove(false);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
-  rv = OpenDatabase(mPermissionsFile);
+  rv = OpenDatabase(permissionsFile);
   if (rv == NS_ERROR_FILE_CORRUPTED) {
     LogToConsole(
         NS_LITERAL_STRING("permissions.sqlite is corrupted! Try again!"));
 
     // Add telemetry probe
-    Telemetry::Accumulate(Telemetry::PERMISSIONS_SQL_CORRUPTED, 1);
+    mozilla::Telemetry::Accumulate(
+        mozilla::Telemetry::PERMISSIONS_SQL_CORRUPTED, 1);
 
     // delete corrupted permissions.sqlite and try again
-    rv = mPermissionsFile->Remove(false);
+    rv = permissionsFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, rv);
     LogToConsole(
         NS_LITERAL_STRING("Corrupted permissions.sqlite has been removed."));
 
-    rv = OpenDatabase(mPermissionsFile);
+    rv = OpenDatabase(permissionsFile);
     NS_ENSURE_SUCCESS(rv, rv);
     LogToConsole(
         NS_LITERAL_STRING("OpenDatabase to permissions.sqlite is successful!"));
-  }
-
-  if (NS_WARN_IF(NS_FAILED(rv))) {
+  } else if (NS_FAILED(rv)) {
     return rv;
   }
 
-  MOZ_ACCESS_THREAD_BOUND(mThreadBoundData, data);
-
   bool ready;
-  data->mDBConn->GetConnectionReady(&ready);
+  mDBConn->GetConnectionReady(&ready);
   if (!ready) {
     LogToConsole(NS_LITERAL_STRING(
         "Fail to get connection to permissions.sqlite! Try again!"));
 
     // delete and try again
-    rv = mPermissionsFile->Remove(false);
+    rv = permissionsFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, rv);
     LogToConsole(
         NS_LITERAL_STRING("Defective permissions.sqlite has been removed."));
 
     // Add telemetry probe
-    Telemetry::Accumulate(Telemetry::DEFECTIVE_PERMISSIONS_SQL_REMOVED, 1);
-
-    rv = OpenDatabase(mPermissionsFile);
+    mozilla::Telemetry::Accumulate(
+        mozilla::Telemetry::DEFECTIVE_PERMISSIONS_SQL_REMOVED, 1);
+
+    rv = OpenDatabase(permissionsFile);
     NS_ENSURE_SUCCESS(rv, rv);
     LogToConsole(
         NS_LITERAL_STRING("OpenDatabase to permissions.sqlite is successful!"));
 
-    data->mDBConn->GetConnectionReady(&ready);
+    mDBConn->GetConnectionReady(&ready);
     if (!ready) return NS_ERROR_UNEXPECTED;
   }
 
   bool tableExists = false;
-  data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"), &tableExists);
+  mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"), &tableExists);
   if (!tableExists) {
-    data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &tableExists);
+    mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &tableExists);
   }
   if (!tableExists) {
     rv = CreateTable();
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     // table already exists; check the schema version before reading
     int32_t dbSchemaVersion;
-    rv = data->mDBConn->GetSchemaVersion(&dbSchemaVersion);
+    rv = mDBConn->GetSchemaVersion(&dbSchemaVersion);
     NS_ENSURE_SUCCESS(rv, rv);
 
     switch (dbSchemaVersion) {
         // upgrading.
-        // every time you increment the database schema, you need to
-        // implement the upgrading code from the previous version to the
-        // new one. fall through to current version
+        // every time you increment the database schema, you need to implement
+        // the upgrading code from the previous version to the new one.
+        // fall through to current version
 
       case 1: {
-        // previous non-expiry version of database.  Upgrade it by adding
-        // the expiration columns
-        rv = data->mDBConn->ExecuteSimpleSQL(
+        // previous non-expiry version of database.  Upgrade it by adding the
+        // expiration columns
+        rv = mDBConn->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("ALTER TABLE moz_hosts ADD expireType INTEGER"));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = data->mDBConn->ExecuteSimpleSQL(
+        rv = mDBConn->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("ALTER TABLE moz_hosts ADD expireTime INTEGER"));
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
-      // TODO: we want to make default version as version 2 in order to
-      // fix bug 784875.
+      // TODO: we want to make default version as version 2 in order to fix bug
+      // 784875.
       case 0:
       case 2: {
         // Add appId/isInBrowserElement fields.
-        rv = data->mDBConn->ExecuteSimpleSQL(
+        rv = mDBConn->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("ALTER TABLE moz_hosts ADD appId INTEGER"));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
             "ALTER TABLE moz_hosts ADD isInBrowserElement INTEGER"));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = data->mDBConn->SetSchemaVersion(3);
+        rv = mDBConn->SetSchemaVersion(3);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
       // Version 3->4 is the creation of the modificationTime field.
       case 3: {
-        rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
             "ALTER TABLE moz_hosts ADD modificationTime INTEGER"));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        // We leave the modificationTime at zero for all existing records;
-        // using now() would mean, eg, that doing "remove all from the
-        // last hour" within the first hour after migration would remove
-        // all permissions.
-
-        rv = data->mDBConn->SetSchemaVersion(4);
+        // We leave the modificationTime at zero for all existing records; using
+        // now() would mean, eg, that doing "remove all from the last hour"
+        // within the first hour after migration would remove all permissions.
+
+        rv = mDBConn->SetSchemaVersion(4);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
-      // In version 5, host appId, and isInBrowserElement were merged into
-      // a single origin entry
+      // In version 5, host appId, and isInBrowserElement were merged into a
+      // single origin entry
       //
       // In version 6, the tables were renamed for backwards compatability
       // reasons with version 4 and earlier.
       //
       // In version 7, a bug in the migration used for version 4->5 was
-      // discovered which could have triggered data-loss. Because of that,
-      // all users with a version 4, 5, or 6 database will be re-migrated
-      // from the backup database. (bug 1186034). This migration bug is
-      // not present after bug 1185340, and the re-migration ensures that
-      // all users have the fix.
+      // discovered which could have triggered data-loss. Because of that, all
+      // users with a version 4, 5, or 6 database will be re-migrated from the
+      // backup database. (bug 1186034). This migration bug is not present after
+      // bug 1185340, and the re-migration ensures that all users have the fix.
       case 5:
-        // This branch could also be reached via dbSchemaVersion == 3, in
-        // which case we want to fall through to the dbSchemaVersion == 4
-        // case. The easiest way to do that is to perform this extra check
-        // here to make sure that we didn't get here via a fallthrough
-        // from v3
+        // This branch could also be reached via dbSchemaVersion == 3, in which
+        // case we want to fall through to the dbSchemaVersion == 4 case. The
+        // easiest way to do that is to perform this extra check here to make
+        // sure that we didn't get here via a fallthrough from v3
         if (dbSchemaVersion == 5) {
-          // In version 5, the backup database is named moz_hosts_v4. We
-          // perform the version 5->6 migration to get the tables to have
-          // consistent naming conventions.
+          // In version 5, the backup database is named moz_hosts_v4. We perform
+          // the version 5->6 migration to get the tables to have consistent
+          // naming conventions.
 
           // Version 5->6 is the renaming of moz_hosts to moz_perms, and
           // moz_hosts_v4 to moz_hosts (bug 1185343)
           //
-          // In version 5, we performed the modifications to the
-          // permissions database in place, this meant that if you
-          // upgraded to a version which used V5, and then downgraded to a
-          // version which used v4 or earlier, the fallback path would
-          // drop the table, and your permissions data would be lost. This
-          // migration undoes that mistake, by restoring the old moz_hosts
-          // table (if it was present), and instead using the new table
-          // moz_perms for the new permissions schema.
+          // In version 5, we performed the modifications to the permissions
+          // database in place, this meant that if you upgraded to a version
+          // which used V5, and then downgraded to a version which used v4 or
+          // earlier, the fallback path would drop the table, and your
+          // permissions data would be lost. This migration undoes that mistake,
+          // by restoring the old moz_hosts table (if it was present), and
+          // instead using the new table moz_perms for the new permissions
+          // schema.
           //
-          // NOTE: If you downgrade, store new permissions, and then
-          // upgrade again, these new permissions won't be migrated or
-          // reflected in the updated database. This migration only occurs
-          // once, as if moz_perms exists, it will skip creating it. In
-          // addition, permissions added after the migration will not be
-          // visible in previous versions of firefox.
+          // NOTE: If you downgrade, store new permissions, and then upgrade
+          // again, these new permissions won't be migrated or reflected in the
+          // updated database. This migration only occurs once, as if moz_perms
+          // exists, it will skip creating it. In addition, permissions added
+          // after the migration will not be visible in previous versions of
+          // firefox.
 
           bool permsTableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
-                                     &permsTableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
+                               &permsTableExists);
           if (!permsTableExists) {
             // Move the upgraded database to moz_perms
-            rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+            rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
                 "ALTER TABLE moz_hosts RENAME TO moz_perms"));
             NS_ENSURE_SUCCESS(rv, rv);
           } else {
             NS_WARNING(
                 "moz_hosts was not renamed to moz_perms, "
                 "as a moz_perms table already exists");
 
-            // In the situation where a moz_perms table already exists,
-            // but the schema is lower than 6, a migration has already
-            // previously occured to V6, but a downgrade has caused the
-            // moz_hosts table to be dropped. This should only occur in
-            // the case of a downgrade to a V5 database, which was only
-            // present in a few day's nightlies. As that version was
-            // likely used only on a temporary basis, we assume that the
-            // database from the previous V6 has the permissions which the
-            // user actually wants to use. We have to get rid of moz_hosts
-            // such that moz_hosts_v4 can be moved into its place if it
-            // exists.
-            rv = data->mDBConn->ExecuteSimpleSQL(
+            // In the situation where a moz_perms table already exists, but the
+            // schema is lower than 6, a migration has already previously
+            // occured to V6, but a downgrade has caused the moz_hosts table to
+            // be dropped. This should only occur in the case of a downgrade to
+            // a V5 database, which was only present in a few day's nightlies.
+            // As that version was likely used only on a temporary basis, we
+            // assume that the database from the previous V6 has the permissions
+            // which the user actually wants to use. We have to get rid of
+            // moz_hosts such that moz_hosts_v4 can be moved into its place if
+            // it exists.
+            rv = mDBConn->ExecuteSimpleSQL(
                 NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
 #ifdef DEBUG
           // The moz_hosts table shouldn't exist anymore
           bool hostsTableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
-                                     &hostsTableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
+                               &hostsTableExists);
           MOZ_ASSERT(!hostsTableExists);
 #endif
 
-          // Rename moz_hosts_v4 back to it's original location, if it
-          // exists
+          // Rename moz_hosts_v4 back to it's original location, if it exists
           bool v4TableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_v4"),
-                                     &v4TableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_v4"),
+                               &v4TableExists);
           if (v4TableExists) {
-            rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+            rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
                 "ALTER TABLE moz_hosts_v4 RENAME TO moz_hosts"));
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
-          rv = data->mDBConn->SetSchemaVersion(6);
+          rv = mDBConn->SetSchemaVersion(6);
           NS_ENSURE_SUCCESS(rv, rv);
         }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
-      // At this point, the version 5 table has been migrated to a version
-      // 6 table We are guaranteed to have at least one of moz_hosts and
+      // At this point, the version 5 table has been migrated to a version 6
+      // table We are guaranteed to have at least one of moz_hosts and
       // moz_perms. If we have moz_hosts, we will migrate moz_hosts into
       // moz_perms (even if we already have a moz_perms, as we need a
       // re-migration due to bug 1186034).
       //
-      // After this migration, we are guaranteed to have both a moz_hosts
-      // (for backwards compatability), and a moz_perms table. The
-      // moz_hosts table will have a v4 schema, and the moz_perms table
-      // will have a v6 schema.
+      // After this migration, we are guaranteed to have both a moz_hosts (for
+      // backwards compatability), and a moz_perms table. The moz_hosts table
+      // will have a v4 schema, and the moz_perms table will have a v6 schema.
       case 4:
       case 6: {
         bool hostsTableExists = false;
-        data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
-                                   &hostsTableExists);
+        mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
+                             &hostsTableExists);
         if (hostsTableExists) {
-          // Both versions 4 and 6 have a version 4 formatted hosts table
-          // named moz_hosts. We can migrate this table to our version 7
-          // table moz_perms. If moz_perms is present, then we can use it
-          // as a basis for comparison.
-
-          rv = data->mDBConn->BeginTransaction();
+          // Both versions 4 and 6 have a version 4 formatted hosts table named
+          // moz_hosts. We can migrate this table to our version 7 table
+          // moz_perms. If moz_perms is present, then we can use it as a basis
+          // for comparison.
+
+          rv = mDBConn->BeginTransaction();
           NS_ENSURE_SUCCESS(rv, rv);
 
           bool tableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"),
-                                     &tableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"),
+                               &tableExists);
           if (tableExists) {
             NS_WARNING(
-                "The temporary database moz_hosts_new already exists, "
-                "dropping "
+                "The temporary database moz_hosts_new already exists, dropping "
                 "it.");
-            rv = data->mDBConn->ExecuteSimpleSQL(
+            rv = mDBConn->ExecuteSimpleSQL(
                 NS_LITERAL_CSTRING("DROP TABLE moz_hosts_new"));
             NS_ENSURE_SUCCESS(rv, rv);
           }
-          rv = data->mDBConn->ExecuteSimpleSQL(
+          rv = mDBConn->ExecuteSimpleSQL(
               NS_LITERAL_CSTRING("CREATE TABLE moz_hosts_new ("
                                  " id INTEGER PRIMARY KEY"
                                  ",origin TEXT"
                                  ",type TEXT"
                                  ",permission INTEGER"
                                  ",expireType INTEGER"
                                  ",expireTime INTEGER"
                                  ",modificationTime INTEGER"
                                  ")"));
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCOMPtr<mozIStorageStatement> stmt;
-          rv = data->mDBConn->CreateStatement(
+          rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING(
-                  "SELECT host, type, permission, expireType, "
-                  "expireTime, "
+                  "SELECT host, type, permission, expireType, expireTime, "
                   "modificationTime, isInBrowserElement FROM moz_hosts"),
               getter_AddRefs(stmt));
           NS_ENSURE_SUCCESS(rv, rv);
 
           int64_t id = 0;
+          nsAutoCString host, type;
+          uint32_t permission;
+          uint32_t expireType;
+          int64_t expireTime;
+          int64_t modificationTime;
+          bool isInBrowserElement;
           bool hasResult;
 
           while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
-            MigrationEntry entry;
-
             // Read in the old row
-            rv = stmt->GetUTF8String(0, entry.mHost);
+            rv = stmt->GetUTF8String(0, host);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
-            rv = stmt->GetUTF8String(1, entry.mType);
+            rv = stmt->GetUTF8String(1, type);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
-
-            entry.mId = id++;
-            entry.mPermission = stmt->AsInt32(2);
-            entry.mExpireType = stmt->AsInt32(3);
-            entry.mExpireTime = stmt->AsInt64(4);
-            entry.mModificationTime = stmt->AsInt64(5);
-            entry.mIsInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
-
-            mMigrationEntries.AppendElement(entry);
+            permission = stmt->AsInt32(2);
+            expireType = stmt->AsInt32(3);
+            expireTime = stmt->AsInt64(4);
+            modificationTime = stmt->AsInt64(5);
+            isInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
+
+            // Perform the meat of the migration by deferring to the
+            // UpgradeHostToOriginAndInsert function.
+            UpgradeHostToOriginDBMigration upHelper(mDBConn, &id);
+            rv = UpgradeHostToOriginAndInsert(
+                host, type, permission, expireType, expireTime,
+                modificationTime, isInBrowserElement, &upHelper);
+            if (NS_FAILED(rv)) {
+              NS_WARNING(
+                  "Unexpected failure when upgrading migrating permission "
+                  "from host to origin");
+            }
           }
 
-          // We don't drop the moz_hosts table such that it is available
-          // for backwards-compatability and for future migrations in case
-          // of migration errors in the current code. Create a marker
-          // empty table which will indicate that the moz_hosts table is
-          // intended to act as a backup. If this table is not present,
+          // We don't drop the moz_hosts table such that it is available for
+          // backwards-compatability and for future migrations in case of
+          // migration errors in the current code.
+          // Create a marker empty table which will indicate that the moz_hosts
+          // table is intended to act as a backup. If this table is not present,
           // then the moz_hosts table was created as a random empty table.
-          rv = data->mDBConn->ExecuteSimpleSQL(
-              NS_LITERAL_CSTRING("CREATE TABLE moz_hosts_is_backup (dummy "
-                                 "INTEGER PRIMARY KEY)"));
+          rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+              "CREATE TABLE moz_hosts_is_backup (dummy INTEGER PRIMARY KEY)"));
           NS_ENSURE_SUCCESS(rv, rv);
 
           bool permsTableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
-                                     &permsTableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
+                               &permsTableExists);
           if (permsTableExists) {
-            // The user already had a moz_perms table, and we are
-            // performing a re-migration. We count the rows in the old
-            // table for telemetry, and then back up their old database as
-            // moz_perms_v6
+            // The user already had a moz_perms table, and we are performing a
+            // re-migration. We count the rows in the old table for telemetry,
+            // and then back up their old database as moz_perms_v6
 
             nsCOMPtr<mozIStorageStatement> countStmt;
-            rv = data->mDBConn->CreateStatement(
+            rv = mDBConn->CreateStatement(
                 NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_perms"),
                 getter_AddRefs(countStmt));
             bool hasResult = false;
             if (NS_FAILED(rv) ||
                 NS_FAILED(countStmt->ExecuteStep(&hasResult)) || !hasResult) {
               NS_WARNING("Could not count the rows in moz_perms");
             }
 
-            // Back up the old moz_perms database as moz_perms_v6 before
-            // we move the new table into its position
-            rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+            // Back up the old moz_perms database as moz_perms_v6 before we
+            // move the new table into its position
+            rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
                 "ALTER TABLE moz_perms RENAME TO moz_perms_v6"));
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
-          rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
               "ALTER TABLE moz_hosts_new RENAME TO moz_perms"));
           NS_ENSURE_SUCCESS(rv, rv);
 
-          rv = data->mDBConn->CommitTransaction();
+          rv = mDBConn->CommitTransaction();
           NS_ENSURE_SUCCESS(rv, rv);
         } else {
-          // We don't have a moz_hosts table, so we create one for
-          // downgrading purposes. This table is empty.
-          rv = data->mDBConn->ExecuteSimpleSQL(
+          // We don't have a moz_hosts table, so we create one for downgrading
+          // purposes. This table is empty.
+          rv = mDBConn->ExecuteSimpleSQL(
               NS_LITERAL_CSTRING("CREATE TABLE moz_hosts ("
                                  " id INTEGER PRIMARY KEY"
                                  ",host TEXT"
                                  ",type TEXT"
                                  ",permission INTEGER"
                                  ",expireType INTEGER"
                                  ",expireTime INTEGER"
                                  ",modificationTime INTEGER"
@@ -1221,342 +1405,334 @@ nsresult PermissionManager::TryInitDB(bo
                                  ")"));
           NS_ENSURE_SUCCESS(rv, rv);
 
           // We are guaranteed to have a moz_perms table at this point.
         }
 
 #ifdef DEBUG
         {
-          // At this point, both the moz_hosts and moz_perms tables should
-          // exist
+          // At this point, both the moz_hosts and moz_perms tables should exist
           bool hostsTableExists = false;
           bool permsTableExists = false;
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
-                                     &hostsTableExists);
-          data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
-                                     &permsTableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"),
+                               &hostsTableExists);
+          mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"),
+                               &permsTableExists);
           MOZ_ASSERT(hostsTableExists && permsTableExists);
         }
 #endif
 
-        rv = data->mDBConn->SetSchemaVersion(7);
+        rv = mDBConn->SetSchemaVersion(7);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
       // The version 7-8 migration is the re-migration of localhost and
-      // ip-address entries due to errors in the previous version 7
-      // migration which caused localhost and ip-address entries to be
-      // incorrectly discarded. The version 7 migration logic has been
-      // corrected, and thus this logic only needs to execute if the user
-      // is currently on version 7.
+      // ip-address entries due to errors in the previous version 7 migration
+      // which caused localhost and ip-address entries to be incorrectly
+      // discarded. The version 7 migration logic has been corrected, and thus
+      // this logic only needs to execute if the user is currently on version 7.
       case 7: {
-        // This migration will be relatively expensive as we need to
-        // perform database lookups for each origin which we want to
-        // insert. Fortunately, it shouldn't be too expensive as we only
-        // want to insert a small number of entries created for localhost
-        // or IP addresses.
-
-        // We only want to perform the re-migration if moz_hosts is a
-        // backup
+        // This migration will be relatively expensive as we need to perform
+        // database lookups for each origin which we want to insert.
+        // Fortunately, it shouldn't be too expensive as we only want to insert
+        // a small number of entries created for localhost or IP addresses.
+
+        // We only want to perform the re-migration if moz_hosts is a backup
         bool hostsIsBackupExists = false;
-        data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_is_backup"),
-                                   &hostsIsBackupExists);
-
-        // Only perform this migration if the original schema version was
-        // 7, and the moz_hosts table is a backup.
+        mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_is_backup"),
+                             &hostsIsBackupExists);
+
+        // Only perform this migration if the original schema version was 7, and
+        // the moz_hosts table is a backup.
         if (dbSchemaVersion == 7 && hostsIsBackupExists) {
           nsCOMPtr<mozIStorageStatement> stmt;
-          rv = data->mDBConn->CreateStatement(
+          rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING(
-                  "SELECT host, type, permission, expireType, "
-                  "expireTime, "
+                  "SELECT host, type, permission, expireType, expireTime, "
                   "modificationTime, isInBrowserElement FROM moz_hosts"),
               getter_AddRefs(stmt));
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCOMPtr<mozIStorageStatement> idStmt;
-          rv = data->mDBConn->CreateStatement(
+          rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING("SELECT MAX(id) FROM moz_hosts"),
               getter_AddRefs(idStmt));
-
           int64_t id = 0;
           bool hasResult = false;
           if (NS_SUCCEEDED(rv) &&
               NS_SUCCEEDED(idStmt->ExecuteStep(&hasResult)) && hasResult) {
             id = idStmt->AsInt32(0) + 1;
           }
 
+          nsAutoCString host, type;
+          uint32_t permission;
+          uint32_t expireType;
+          int64_t expireTime;
+          int64_t modificationTime;
+          bool isInBrowserElement;
+
           while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
-            MigrationEntry entry;
-
             // Read in the old row
-            rv = stmt->GetUTF8String(0, entry.mHost);
+            rv = stmt->GetUTF8String(0, host);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
 
             nsAutoCString eTLD1;
             rv = nsEffectiveTLDService::GetInstance()->GetBaseDomainFromHost(
-                entry.mHost, 0, eTLD1);
+                host, 0, eTLD1);
             if (NS_SUCCEEDED(rv)) {
-              // We only care about entries which the tldService can't
-              // handle
+              // We only care about entries which the tldService can't handle
               continue;
             }
 
-            rv = stmt->GetUTF8String(1, entry.mType);
+            rv = stmt->GetUTF8String(1, type);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
-
-            entry.mId = id++;
-            entry.mPermission = stmt->AsInt32(2);
-            entry.mExpireType = stmt->AsInt32(3);
-            entry.mExpireTime = stmt->AsInt64(4);
-            entry.mModificationTime = stmt->AsInt64(5);
-            entry.mIsInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
-
-            mMigrationEntries.AppendElement(entry);
+            permission = stmt->AsInt32(2);
+            expireType = stmt->AsInt32(3);
+            expireTime = stmt->AsInt64(4);
+            modificationTime = stmt->AsInt64(5);
+            isInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
+
+            // Perform the meat of the migration by deferring to the
+            // UpgradeHostToOriginAndInsert function.
+            UpgradeIPHostToOriginDB upHelper(mDBConn, &id);
+            rv = UpgradeHostToOriginAndInsert(
+                host, type, permission, expireType, expireTime,
+                modificationTime, isInBrowserElement, &upHelper);
+            if (NS_FAILED(rv)) {
+              NS_WARNING(
+                  "Unexpected failure when upgrading migrating permission "
+                  "from host to origin");
+            }
           }
         }
 
-        // Even if we didn't perform the migration, we want to bump the
-        // schema version to 8.
-        rv = data->mDBConn->SetSchemaVersion(8);
+        // Even if we didn't perform the migration, we want to bump the schema
+        // version to 8.
+        rv = mDBConn->SetSchemaVersion(8);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
-      // The version 8-9 migration removes the unnecessary backup
-      // moz-hosts database contents. as the data no longer needs to be
-      // migrated
+      // The version 8-9 migration removes the unnecessary backup moz-hosts
+      // database contents. as the data no longer needs to be migrated
       case 8: {
-        // We only want to clear out the old table if it is a backup. If
-        // it isn't a backup, we don't need to touch it.
+        // We only want to clear out the old table if it is a backup. If it
+        // isn't a backup, we don't need to touch it.
         bool hostsIsBackupExists = false;
-        data->mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_is_backup"),
-                                   &hostsIsBackupExists);
+        mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_is_backup"),
+                             &hostsIsBackupExists);
         if (hostsIsBackupExists) {
-          // Delete everything from the backup, we want to keep around the
-          // table so that you can still downgrade and not break things,
-          // but we don't need to keep the rows around.
-          rv = data->mDBConn->ExecuteSimpleSQL(
+          // Delete everything from the backup, we want to keep around the table
+          // so that you can still downgrade and not break things, but we don't
+          // need to keep the rows around.
+          rv = mDBConn->ExecuteSimpleSQL(
               NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
           NS_ENSURE_SUCCESS(rv, rv);
 
           // The table is no longer a backup, so get rid of it.
-          rv = data->mDBConn->ExecuteSimpleSQL(
+          rv = mDBConn->ExecuteSimpleSQL(
               NS_LITERAL_CSTRING("DROP TABLE moz_hosts_is_backup"));
           NS_ENSURE_SUCCESS(rv, rv);
         }
 
-        rv = data->mDBConn->SetSchemaVersion(9);
+        rv = mDBConn->SetSchemaVersion(9);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
       case 9: {
-        rv = data->mDBConn->SetSchemaVersion(10);
+        rv = mDBConn->SetSchemaVersion(10);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
       case 10: {
         // Filter out the rows with storage access API permissions with a
         // granted origin, and remove the granted origin part from the
         // permission type.
-        rv = data->mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
             "UPDATE moz_perms "
-            "SET type=SUBSTR(type, 0, INSTR(SUBSTR(type, INSTR(type, "
-            "'^') + "
+            "SET type=SUBSTR(type, 0, INSTR(SUBSTR(type, INSTR(type, '^') + "
             "1), '^') + INSTR(type, '^')) "
             "WHERE INSTR(SUBSTR(type, INSTR(type, '^') + 1), '^') AND "
             "SUBSTR(type, 0, 18) == \"storageAccessAPI^\";"));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        rv = data->mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
+        rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         [[fallthrough]];
 
       // current version.
       case HOSTS_SCHEMA_VERSION:
         break;
 
       // downgrading.
-      // if columns have been added to the table, we can still use the
-      // ones we understand safely. if columns have been deleted or
-      // altered, just blow away the table and start from scratch! if you
-      // change the way a column is interpreted, make sure you also change
-      // its name so this check will catch it.
+      // if columns have been added to the table, we can still use the ones we
+      // understand safely. if columns have been deleted or altered, just
+      // blow away the table and start from scratch! if you change the way
+      // a column is interpreted, make sure you also change its name so this
+      // check will catch it.
       default: {
         // check if all the expected columns exist
         nsCOMPtr<mozIStorageStatement> stmt;
-        rv = data->mDBConn->CreateStatement(
-            NS_LITERAL_CSTRING("SELECT origin, type, permission, "
-                               "expireType, expireTime, "
-                               "modificationTime FROM moz_perms"),
+        rv = mDBConn->CreateStatement(
+            NS_LITERAL_CSTRING(
+                "SELECT origin, type, permission, expireType, expireTime, "
+                "modificationTime FROM moz_perms"),
             getter_AddRefs(stmt));
         if (NS_SUCCEEDED(rv)) break;
 
         // our columns aren't there - drop the table!
-        rv = data->mDBConn->ExecuteSimpleSQL(
+        rv = mDBConn->ExecuteSimpleSQL(
             NS_LITERAL_CSTRING("DROP TABLE moz_perms"));
         NS_ENSURE_SUCCESS(rv, rv);
 
         rv = CreateTable();
         NS_ENSURE_SUCCESS(rv, rv);
       } break;
     }
   }
 
-  // cache frequently used statements (for insertion, deletion, and
-  // updating)
-  rv = data->mDBConn->CreateStatement(
+  // cache frequently used statements (for insertion, deletion, and updating)
+  rv = mDBConn->CreateAsyncStatement(
       NS_LITERAL_CSTRING("INSERT INTO moz_perms "
                          "(id, origin, type, permission, expireType, "
                          "expireTime, modificationTime) "
                          "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"),
-      getter_AddRefs(data->mStmtInsert));
+      getter_AddRefs(mStmtInsert));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv =
-      data->mDBConn->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_perms "
+  rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING("DELETE FROM moz_perms "
                                                         "WHERE id = ?1"),
-                                     getter_AddRefs(data->mStmtDelete));
+                                     getter_AddRefs(mStmtDelete));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = data->mDBConn->CreateStatement(
+  rv = mDBConn->CreateAsyncStatement(
       NS_LITERAL_CSTRING("UPDATE moz_perms "
                          "SET permission = ?2, expireType= ?3, expireTime = "
                          "?4, modificationTime = ?5 WHERE id = ?1"),
-      getter_AddRefs(data->mStmtUpdate));
+      getter_AddRefs(mStmtUpdate));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Always import default permissions.
-  ConsumeDefaultsInputStream(aDefaultsInputStream, lock);
-
+  ImportDefaults();
   // check whether to import or just read in the db
   if (tableExists) {
-    rv = Read(lock);
+    rv = Read();
     NS_ENSURE_SUCCESS(rv, rv);
+
+    AddIdleDailyMaintenanceJob();
   }
 
   return NS_OK;
 }
 
-void PermissionManager::AddIdleDailyMaintenanceJob() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+void nsPermissionManager::AddIdleDailyMaintenanceJob() {
+  nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
   NS_ENSURE_TRUE_VOID(observerService);
 
   nsresult rv =
       observerService->AddObserver(this, OBSERVER_TOPIC_IDLE_DAILY, false);
   NS_ENSURE_SUCCESS_VOID(rv);
 }
 
-void PermissionManager::RemoveIdleDailyMaintenanceJob() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+void nsPermissionManager::RemoveIdleDailyMaintenanceJob() {
+  nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
   NS_ENSURE_TRUE_VOID(observerService);
 
   nsresult rv =
       observerService->RemoveObserver(this, OBSERVER_TOPIC_IDLE_DAILY);
   NS_ENSURE_SUCCESS_VOID(rv);
 }
 
-void PermissionManager::PerformIdleDailyMaintenance() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  RefPtr<PermissionManager> self = this;
-  mThread->Dispatch(NS_NewRunnableFunction(
-      "PermissionManager::PerformIdleDailyMaintenance", [self] {
-        MOZ_ACCESS_THREAD_BOUND(self->mThreadBoundData, data);
-
-        if (self->mState == eClosed || !data->mDBConn) {
-          return;
-        }
-
-        nsCOMPtr<mozIStorageStatement> stmtDeleteExpired;
-        nsresult rv = data->mDBConn->CreateStatement(
-            NS_LITERAL_CSTRING("DELETE FROM moz_perms WHERE expireType = "
-                               "?1 AND expireTime <= ?2"),
-            getter_AddRefs(stmtDeleteExpired));
-        NS_ENSURE_SUCCESS_VOID(rv);
-
-        rv = stmtDeleteExpired->BindInt32ByIndex(
-            0, nsIPermissionManager::EXPIRE_TIME);
-        NS_ENSURE_SUCCESS_VOID(rv);
-
-        rv = stmtDeleteExpired->BindInt64ByIndex(1, EXPIRY_NOW);
-        NS_ENSURE_SUCCESS_VOID(rv);
-
-        rv = stmtDeleteExpired->Execute();
-        NS_ENSURE_SUCCESS_VOID(rv);
-      }));
+void nsPermissionManager::PerformIdleDailyMaintenance() {
+  if (!mDBConn) {
+    return;
+  }
+
+  nsCOMPtr<mozIStorageAsyncStatement> stmtDeleteExpired;
+  nsresult rv = mDBConn->CreateAsyncStatement(
+      NS_LITERAL_CSTRING("DELETE FROM moz_perms WHERE expireType = "
+                         "?1 AND expireTime <= ?2"),
+      getter_AddRefs(stmtDeleteExpired));
+  NS_ENSURE_SUCCESS_VOID(rv);
+
+  rv =
+      stmtDeleteExpired->BindInt32ByIndex(0, nsIPermissionManager::EXPIRE_TIME);
+  NS_ENSURE_SUCCESS_VOID(rv);
+
+  rv = stmtDeleteExpired->BindInt64ByIndex(1, EXPIRY_NOW);
+  NS_ENSURE_SUCCESS_VOID(rv);
+
+  nsCOMPtr<mozIStoragePendingStatement> pending;
+  rv = stmtDeleteExpired->ExecuteAsync(nullptr, getter_AddRefs(pending));
+  NS_ENSURE_SUCCESS_VOID(rv);
 }
 
 // sets the schema version and creates the moz_perms table.
-nsresult PermissionManager::CreateTable() {
-  MOZ_ASSERT(!NS_IsMainThread());
-  MOZ_ACCESS_THREAD_BOUND(mThreadBoundData, data);
-
+nsresult nsPermissionManager::CreateTable() {
   // set the schema version, before creating the table
-  nsresult rv = data->mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
+  nsresult rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
   if (NS_FAILED(rv)) return rv;
 
   // create the table
   // SQL also lives in automation.py.in. If you change this SQL change that
   // one too
-  rv = data->mDBConn->ExecuteSimpleSQL(
-      NS_LITERAL_CSTRING("CREATE TABLE moz_perms ("
-                         " id INTEGER PRIMARY KEY"
-                         ",origin TEXT"
-                         ",type TEXT"
-                         ",permission INTEGER"
-                         ",expireType INTEGER"
-                         ",expireTime INTEGER"
-                         ",modificationTime INTEGER"
-                         ")"));
+  rv =
+      mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_perms ("
+                                                   " id INTEGER PRIMARY KEY"
+                                                   ",origin TEXT"
+                                                   ",type TEXT"
+                                                   ",permission INTEGER"
+                                                   ",expireType INTEGER"
+                                                   ",expireTime INTEGER"
+                                                   ",modificationTime INTEGER"
+                                                   ")"));
   if (NS_FAILED(rv)) return rv;
 
   // We also create a legacy V4 table, for backwards compatability,
   // and to ensure that downgrades don't trigger a schema version change.
-  return data->mDBConn->ExecuteSimpleSQL(
+  return mDBConn->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE TABLE moz_hosts ("
                          " id INTEGER PRIMARY KEY"
                          ",host TEXT"
                          ",type TEXT"
                          ",permission INTEGER"
                          ",expireType INTEGER"
                          ",expireTime INTEGER"
                          ",modificationTime INTEGER"
                          ",isInBrowserElement INTEGER"
                          ")"));
 }
 
 NS_IMETHODIMP
-PermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
-                                    const nsACString& aType,
-                                    uint32_t aPermission, uint32_t aExpireType,
-                                    int64_t aExpireTime) {
+nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
+                                      const nsACString& aType,
+                                      uint32_t aPermission,
+                                      uint32_t aExpireType,
+                                      int64_t aExpireTime) {
   ENSURE_NOT_CHILD_PROCESS;
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_TRUE(aExpireType == nsIPermissionManager::EXPIRE_NEVER ||
                      aExpireType == nsIPermissionManager::EXPIRE_TIME ||
                      aExpireType == nsIPermissionManager::EXPIRE_SESSION ||
                      aExpireType == nsIPermissionManager::EXPIRE_POLICY,
                  NS_ERROR_INVALID_ARG);
 
@@ -1588,26 +1764,22 @@ PermissionManager::AddFromPrincipal(nsIP
 
   // A modificationTime of zero will cause AddInternal to use now().
   int64_t modificationTime = 0;
 
   return AddInternal(aPrincipal, aType, aPermission, 0, aExpireType,
                      aExpireTime, modificationTime, eNotify, eWriteToDB);
 }
 
-nsresult PermissionManager::AddInternal(
+nsresult nsPermissionManager::AddInternal(
     nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
     int64_t aID, uint32_t aExpireType, int64_t aExpireTime,
     int64_t aModificationTime, NotifyOperationType aNotifyOperation,
     DBOperationType aDBOperation, const bool aIgnoreSessionPermissions,
     const nsACString* aOriginString) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  EnsureReadCompleted();
-
   nsresult rv = NS_OK;
   nsAutoCString origin;
   // Only attempt to compute the origin string when it is going to be needed
   // later on in the function.
   if (!IsChildProcess() ||
       (aDBOperation == eWriteToDB && IsPersistentExpire(aExpireType, aType))) {
     if (aOriginString) {
       // Use the origin string provided by the caller.
@@ -1735,18 +1907,18 @@ nsresult PermissionManager::AddInternal(
       }
 
       entry->GetPermissions().AppendElement(
           PermissionEntry(id, typeIndex, aPermission, aExpireType, aExpireTime,
                           aModificationTime));
 
       if (aDBOperation == eWriteToDB &&
           IsPersistentExpire(aExpireType, aType)) {
-        UpdateDB(op, id, origin, aType, aPermission, aExpireType, aExpireTime,
-                 aModificationTime);
+        UpdateDB(op, mStmtInsert, id, origin, aType, aPermission, aExpireType,
+                 aExpireTime, aModificationTime);
       }
 
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
                                       aPermission, aExpireType, aExpireTime,
                                       aModificationTime, u"added");
       }
 
@@ -1764,17 +1936,17 @@ nsresult PermissionManager::AddInternal(
         break;
       }
 
       entry->GetPermissions().RemoveElementAt(index);
 
       if (aDBOperation == eWriteToDB)
         // We care only about the id here so we pass dummy values for all other
         // parameters.
-        UpdateDB(op, id, EmptyCString(), EmptyCString(), 0,
+        UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0,
                  nsIPermissionManager::EXPIRE_NEVER, 0, 0);
 
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(
             aPrincipal, mTypeArray[typeIndex], oldPermissionEntry.mPermission,
             oldPermissionEntry.mExpireType, oldPermissionEntry.mExpireTime,
             oldPermissionEntry.mModificationTime, u"deleted");
       }
@@ -1820,18 +1992,18 @@ nsresult PermissionManager::AddInternal(
       entry->GetPermissions()[index].mExpireTime = aExpireTime;
       entry->GetPermissions()[index].mModificationTime = aModificationTime;
 
       if (aDBOperation == eWriteToDB &&
           IsPersistentExpire(aExpireType, aType)) {
         // We care only about the id, the permission and
         // expireType/expireTime/modificationTime here. We pass dummy values for
         // all other parameters.
-        UpdateDB(op, id, EmptyCString(), EmptyCString(), aPermission,
-                 aExpireType, aExpireTime, aModificationTime);
+        UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(),
+                 aPermission, aExpireType, aExpireTime, aModificationTime);
       }
 
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
                                       aPermission, aExpireType, aExpireTime,
                                       aModificationTime, u"changed");
       }
 
@@ -1870,35 +2042,35 @@ nsresult PermissionManager::AddInternal(
       entry->GetPermissions()[index].mPermission = aPermission;
       entry->GetPermissions()[index].mExpireType = aExpireType;
       entry->GetPermissions()[index].mExpireTime = aExpireTime;
       entry->GetPermissions()[index].mModificationTime = aModificationTime;
 
       // If requested, create the entry in the DB.
       if (aDBOperation == eWriteToDB &&
           IsPersistentExpire(aExpireType, aType)) {
-        UpdateDB(eOperationAdding, id, origin, aType, aPermission, aExpireType,
-                 aExpireTime, aModificationTime);
+        UpdateDB(eOperationAdding, mStmtInsert, id, origin, aType, aPermission,
+                 aExpireType, aExpireTime, aModificationTime);
       }
 
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
                                       aPermission, aExpireType, aExpireTime,
                                       aModificationTime, u"changed");
       }
 
     } break;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
-                                       const nsACString& aType) {
+nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
+                                         const nsACString& aType) {
   ENSURE_NOT_CHILD_PROCESS;
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
   // System principals are never added to the database, no need to remove them.
   if (aPrincipal->IsSystemPrincipal()) {
     return NS_OK;
   }
 
@@ -1909,17 +2081,17 @@ PermissionManager::RemoveFromPrincipal(n
 
   // AddInternal() handles removal, just let it do the work
   return AddInternal(aPrincipal, aType, nsIPermissionManager::UNKNOWN_ACTION, 0,
                      nsIPermissionManager::EXPIRE_NEVER, 0, 0, eNotify,
                      eWriteToDB);
 }
 
 NS_IMETHODIMP
-PermissionManager::RemovePermission(nsIPermission* aPerm) {
+nsPermissionManager::RemovePermission(nsIPermission* aPerm) {
   if (!aPerm) {
     return NS_OK;
   }
   nsCOMPtr<nsIPrincipal> principal;
   nsresult rv = aPerm->GetPrincipal(getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString type;
@@ -1927,29 +2099,29 @@ PermissionManager::RemovePermission(nsIP
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Permissions are uniquely identified by their principal and type.
   // We remove the permission using these two pieces of data.
   return RemoveFromPrincipal(principal, type);
 }
 
 NS_IMETHODIMP
-PermissionManager::RemoveAll() {
+nsPermissionManager::RemoveAll() {
   ENSURE_NOT_CHILD_PROCESS;
   return RemoveAllInternal(true);
 }
 
 NS_IMETHODIMP
-PermissionManager::RemoveAllSince(int64_t aSince) {
+nsPermissionManager::RemoveAllSince(int64_t aSince) {
   ENSURE_NOT_CHILD_PROCESS;
   return RemoveAllModifiedSince(aSince);
 }
 
 template <class T>
-nsresult PermissionManager::RemovePermissionEntries(T aCondition) {
+nsresult nsPermissionManager::RemovePermissionEntries(T aCondition) {
   Vector<Tuple<nsCOMPtr<nsIPrincipal>, nsCString, nsCString>, 10> array;
   for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
     PermissionHashKey* entry = iter.Get();
     for (const auto& permEntry : entry->GetPermissions()) {
       if (!aCondition(permEntry)) {
         continue;
       }
 
@@ -1968,195 +2140,173 @@ nsresult PermissionManager::RemovePermis
       }
     }
   }
 
   for (auto& i : array) {
     // AddInternal handles removal, so let it do the work...
     AddInternal(Get<0>(i), Get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
                 nsIPermissionManager::EXPIRE_NEVER, 0, 0,
-                PermissionManager::eNotify, PermissionManager::eWriteToDB,
+                nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB,
                 false, &Get<2>(i));
   }
-
   // now re-import any defaults as they may now be required if we just deleted
   // an override.
-  ImportLatestDefaults();
+  ImportDefaults();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PermissionManager::RemoveByType(const nsACString& aType) {
+nsPermissionManager::RemoveByType(const nsACString& aType) {
   ENSURE_NOT_CHILD_PROCESS;
 
   int32_t typeIndex = GetTypeIndex(aType, false);
   // If type == -1, the type isn't known,
   // so just return NS_OK
   if (typeIndex == -1) {
     return NS_OK;
   }
 
   return RemovePermissionEntries(
       [typeIndex](const PermissionEntry& aPermEntry) {
         return static_cast<uint32_t>(typeIndex) == aPermEntry.mType;
       });
 }
 
 NS_IMETHODIMP
-PermissionManager::RemoveByTypeSince(const nsACString& aType,
-                                     int64_t aModificationTime) {
+nsPermissionManager::RemoveByTypeSince(const nsACString& aType,
+                                       int64_t aModificationTime) {
   ENSURE_NOT_CHILD_PROCESS;
 
   int32_t typeIndex = GetTypeIndex(aType, false);
   // If type == -1, the type isn't known,
   // so just return NS_OK
   if (typeIndex == -1) {
     return NS_OK;
   }
 
   return RemovePermissionEntries(
       [typeIndex, aModificationTime](const PermissionEntry& aPermEntry) {
         return uint32_t(typeIndex) == aPermEntry.mType &&
                aModificationTime <= aPermEntry.mModificationTime;
       });
 }
 
-void PermissionManager::CloseDB(bool aRebuildOnSuccess) {
-  EnsureReadCompleted();
-
-  mState = eClosed;
-
-  nsCOMPtr<nsIInputStream> defaultsInputStream;
-  if (aRebuildOnSuccess) {
-    defaultsInputStream = GetDefaultsInputStream();
+void nsPermissionManager::CloseDB(bool aRebuildOnSuccess) {
+  // Null the statements, this will finalize them.
+  mStmtInsert = nullptr;
+  mStmtDelete = nullptr;
+  mStmtUpdate = nullptr;
+  if (mDBConn) {
+    mozIStorageCompletionCallback* cb =
+        new CloseDatabaseListener(this, aRebuildOnSuccess);
+    mozilla::DebugOnly<nsresult> rv = mDBConn->AsyncClose(cb);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    mDBConn = nullptr;  // Avoid race conditions
   }
-
-  RefPtr<PermissionManager> self = this;
-  mThread->Dispatch(NS_NewRunnableFunction(
-      "PermissionManager::CloseDB",
-      [self, aRebuildOnSuccess, defaultsInputStream] {
-        MOZ_ACCESS_THREAD_BOUND(self->mThreadBoundData, data);
-        // Null the statements, this will finalize them.
-        data->mStmtInsert = nullptr;
-        data->mStmtDelete = nullptr;
-        data->mStmtUpdate = nullptr;
-        if (data->mDBConn) {
-          DebugOnly<nsresult> rv = data->mDBConn->Close();
-          MOZ_ASSERT(NS_SUCCEEDED(rv));
-          data->mDBConn = nullptr;
-
-          if (aRebuildOnSuccess) {
-            self->TryInitDB(true, defaultsInputStream);
-          }
-        }
-      }));
 }
 
-nsresult PermissionManager::RemoveAllFromIPC() {
+nsresult nsPermissionManager::RemoveAllFromIPC() {
   MOZ_ASSERT(IsChildProcess());
 
   // Remove from memory and notify immediately. Since the in-memory
   // database is authoritative, we do not need confirmation from the
   // on-disk database to notify observers.
   RemoveAllFromMemory();
 
   return NS_OK;
 }
 
-nsresult PermissionManager::RemoveAllInternal(bool aNotifyObservers) {
+nsresult nsPermissionManager::RemoveAllInternal(bool aNotifyObservers) {
   ENSURE_NOT_CHILD_PROCESS;
 
-  EnsureReadCompleted();
-
   // Let's broadcast the removeAll() to any content process.
   nsTArray<ContentParent*> parents;
   ContentParent::GetAll(parents);
   for (ContentParent* parent : parents) {
     Unused << parent->SendRemoveAllPermissions();
   }
 
   // Remove from memory and notify immediately. Since the in-memory
   // database is authoritative, we do not need confirmation from the
   // on-disk database to notify observers.
   RemoveAllFromMemory();
 
   // Re-import the defaults
-  ImportLatestDefaults();
+  ImportDefaults();
 
   if (aNotifyObservers) {
     NotifyObservers(nullptr, u"cleared");
   }
 
-  RefPtr<PermissionManager> self = this;
-  mThread->Dispatch(
-      NS_NewRunnableFunction("PermissionManager::RemoveAllInternal", [self] {
-        MOZ_ACCESS_THREAD_BOUND(self->mThreadBoundData, data);
-
-        if (self->mState == eClosed || !data->mDBConn) {
-          return;
-        }
-
-        // clear the db
-        nsresult rv = data->mDBConn->ExecuteSimpleSQL(
-            NS_LITERAL_CSTRING("DELETE FROM moz_perms"));
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          NS_DispatchToMainThread(NS_NewRunnableFunction(
-              "PermissionManager::RemoveAllInternal-Failure",
-              [self] { self->CloseDB(true); }));
-        }
-      }));
+  // clear the db
+  if (mDBConn) {
+    nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
+    nsresult rv = mDBConn->CreateAsyncStatement(
+        NS_LITERAL_CSTRING("DELETE FROM moz_perms"),
+        getter_AddRefs(removeStmt));
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    if (!removeStmt) {
+      return NS_ERROR_UNEXPECTED;
+    }
+    nsCOMPtr<mozIStoragePendingStatement> pending;
+    mozIStorageStatementCallback* cb = new DeleteFromMozHostListener(this);
+    rv = removeStmt->ExecuteAsync(cb, getter_AddRefs(pending));
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+    return rv;
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
-                                                    const nsACString& aType,
-                                                    uint32_t* aPermission) {
+nsPermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
+                                                      const nsACString& aType,
+                                                      uint32_t* aPermission) {
   return CommonTestPermission(aPrincipal, -1, aType, aPermission,
                               nsIPermissionManager::UNKNOWN_ACTION, false, true,
                               true);
 }
 
 NS_IMETHODIMP
-PermissionManager::TestExactPermanentPermission(nsIPrincipal* aPrincipal,
-                                                const nsACString& aType,
-                                                uint32_t* aPermission) {
+nsPermissionManager::TestExactPermanentPermission(nsIPrincipal* aPrincipal,
+                                                  const nsACString& aType,
+                                                  uint32_t* aPermission) {
   return CommonTestPermission(aPrincipal, -1, aType, aPermission,
                               nsIPermissionManager::UNKNOWN_ACTION, false, true,
                               false);
 }
 
-nsresult PermissionManager::LegacyTestPermissionFromURI(
-    nsIURI* aURI, const OriginAttributes* aOriginAttributes,
+nsresult nsPermissionManager::LegacyTestPermissionFromURI(
+    nsIURI* aURI, const mozilla::OriginAttributes* aOriginAttributes,
     const nsACString& aType, uint32_t* aPermission) {
   return CommonTestPermission(aURI, aOriginAttributes, -1, aType, aPermission,
                               nsIPermissionManager::UNKNOWN_ACTION, false,
                               false, true);
 }
 
 NS_IMETHODIMP
-PermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
-                                               const nsACString& aType,
-                                               uint32_t* aPermission) {
+nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
+                                                 const nsACString& aType,
+                                                 uint32_t* aPermission) {
   return CommonTestPermission(aPrincipal, -1, aType, aPermission,
                               nsIPermissionManager::UNKNOWN_ACTION, false,
                               false, true);
 }
 
 NS_IMETHODIMP
-PermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
-                                       const nsACString& aType,
-                                       bool aExactHostMatch,
-                                       nsIPermission** aResult) {
+nsPermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
+                                         const nsACString& aType,
+                                         bool aExactHostMatch,
+                                         nsIPermission** aResult) {
   NS_ENSURE_ARG_POINTER(aPrincipal);
+
   *aResult = nullptr;
 
-  EnsureReadCompleted();
-
   if (aPrincipal->IsSystemPrincipal()) {
     return NS_OK;
   }
 
   // Querying the permission object of an nsEP is non-sensical.
   if (IsExpandedPrincipal(aPrincipal)) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -2183,44 +2333,43 @@ PermissionManager::GetPermissionObject(n
 
   nsCOMPtr<nsIPrincipal> principal;
   nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
                                        IsOAForceStripPermission(aType),
                                        getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PermissionEntry& perm = entry->GetPermissions()[idx];
-  nsCOMPtr<nsIPermission> r = Permission::Create(
+  nsCOMPtr<nsIPermission> r = nsPermission::Create(
       principal, mTypeArray[perm.mType], perm.mPermission, perm.mExpireType,
       perm.mExpireTime, perm.mModificationTime);
   if (NS_WARN_IF(!r)) {
     return NS_ERROR_FAILURE;
   }
   r.forget(aResult);
   return NS_OK;
 }
 
-nsresult PermissionManager::CommonTestPermissionInternal(
+nsresult nsPermissionManager::CommonTestPermissionInternal(
     nsIPrincipal* aPrincipal, nsIURI* aURI,
     const OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
     const nsACString& aType, uint32_t* aPermission, bool aExactHostMatch,
     bool aIncludingSession) {
   MOZ_ASSERT(aPrincipal || aURI);
   NS_ENSURE_ARG_POINTER(aPrincipal || aURI);
   MOZ_ASSERT_IF(aPrincipal, !aURI && !aOriginAttributes);
   MOZ_ASSERT_IF(aURI || aOriginAttributes, !aPrincipal);
 
-  EnsureReadCompleted();
-
 #ifdef DEBUG
   {
     nsCOMPtr<nsIPrincipal> prin = aPrincipal;
     if (!prin) {
       if (aURI) {
-        prin = BasePrincipal::CreateContentPrincipal(aURI, OriginAttributes());
+        prin = mozilla::BasePrincipal::CreateContentPrincipal(
+            aURI, OriginAttributes());
       }
     }
     MOZ_ASSERT(prin);
     MOZ_ASSERT(PermissionAvailable(prin, aType));
   }
 #endif
 
   PermissionHashKey* entry =
@@ -2235,288 +2384,25 @@ nsresult PermissionManager::CommonTestPe
 
   *aPermission = aIncludingSession
                      ? entry->GetPermission(aTypeIndex).mPermission
                      : entry->GetPermission(aTypeIndex).mNonSessionPermission;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP PermissionManager::GetAll(
-    nsTArray<RefPtr<nsIPermission>>& aResult) {
-  return GetAllWithTypePrefix(NS_LITERAL_CSTRING(""), aResult);
-}
-
-NS_IMETHODIMP PermissionManager::GetAllWithTypePrefix(
-    const nsACString& aPrefix, nsTArray<RefPtr<nsIPermission>>& aResult) {
-  aResult.Clear();
-  if (XRE_IsContentProcess()) {
-    NS_WARNING(
-        "PermissionManager's getAllWithTypePrefix is not available in the "
-        "content process, as not all permissions may be available.");
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  EnsureReadCompleted();
-
-  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
-    PermissionHashKey* entry = iter.Get();
-    for (const auto& permEntry : entry->GetPermissions()) {
-      // Given how "default" permissions work and the possibility of them being
-      // overridden with UNKNOWN_ACTION, we might see this value here - but we
-      // do *not* want to return them via the enumerator.
-      if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
-        continue;
-      }
-
-      if (!aPrefix.IsEmpty() &&
-          !StringBeginsWith(mTypeArray[permEntry.mType], aPrefix)) {
-        continue;
-      }
-
-      nsCOMPtr<nsIPrincipal> principal;
-      nsresult rv = GetPrincipalFromOrigin(
-          entry->GetKey()->mOrigin,
-          IsOAForceStripPermission(mTypeArray[permEntry.mType]),
-          getter_AddRefs(principal));
-      if (NS_FAILED(rv)) {
-        continue;
-      }
-
-      RefPtr<nsIPermission> permission = Permission::Create(
-          principal, mTypeArray[permEntry.mType], permEntry.mPermission,
-          permEntry.mExpireType, permEntry.mExpireTime,
-          permEntry.mModificationTime);
-      if (NS_WARN_IF(!permission)) {
-        continue;
-      }
-      aResult.AppendElement(std::move(permission));
-    }
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-PermissionManager::GetAllForPrincipal(
-    nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
-  aResult.Clear();
-
-  MOZ_ASSERT(PermissionAvailable(aPrincipal, EmptyCString()));
-
-  nsresult rv;
-  RefPtr<PermissionKey> key =
-      PermissionKey::CreateFromPrincipal(aPrincipal, false, rv);
-  if (!key) {
-    MOZ_ASSERT(NS_FAILED(rv));
-    return rv;
-  }
-  PermissionHashKey* entry = mPermissionTable.GetEntry(key);
-
-  nsTArray<PermissionEntry> strippedPerms;
-  rv = GetStripPermsForPrincipal(aPrincipal, strippedPerms);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  if (entry) {
-    for (const auto& permEntry : entry->GetPermissions()) {
-      // Only return custom permissions
-      if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
-        continue;
-      }
-
-      // Stripped principal permissions overwrite regular ones
-      // For each permission check if there is a stripped permission we should
-      // use instead
-      PermissionEntry perm = permEntry;
-      nsTArray<PermissionEntry>::index_type index = 0;
-      for (const auto& strippedPerm : strippedPerms) {
-        if (strippedPerm.mType == permEntry.mType) {
-          perm = strippedPerm;
-          strippedPerms.RemoveElementAt(index);
-          break;
-        }
-        index++;
-      }
-
-      RefPtr<nsIPermission> permission = Permission::Create(
-          aPrincipal, mTypeArray[perm.mType], perm.mPermission,
-          perm.mExpireType, perm.mExpireTime, perm.mModificationTime);
-      if (NS_WARN_IF(!permission)) {
-        continue;
-      }
-      aResult.AppendElement(permission);
-    }
-  }
-
-  for (const auto& perm : strippedPerms) {
-    RefPtr<nsIPermission> permission = Permission::Create(
-        aPrincipal, mTypeArray[perm.mType], perm.mPermission, perm.mExpireType,
-        perm.mExpireTime, perm.mModificationTime);
-    if (NS_WARN_IF(!permission)) {
-      continue;
-    }
-    aResult.AppendElement(permission);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject,
-                                         const char* aTopic,
-                                         const char16_t* someData) {
-  ENSURE_NOT_CHILD_PROCESS;
-
-  if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
-    // The profile is about to change,
-    // or is going away because the application is shutting down.
-    RemoveIdleDailyMaintenanceJob();
-    RemoveAllFromMemory();
-    CloseDB(false);
-  } else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
-    // the profile has already changed; init the db from the new location
-    InitDB(false);
-  } else if (!nsCRT::strcmp(aTopic, "testonly-reload-permissions-from-disk")) {
-    // Testing mechanism to reload all permissions from disk. Because the
-    // permission manager automatically initializes itself at startup, tests
-    // that directly manipulate the permissions database need some way to reload
-    // the database for their changes to have any effect. This mechanism was
-    // introduced when moving the permissions manager from on-demand startup to
-    // always being initialized. This is not guarded by a pref because it's not
-    // dangerous to reload permissions from disk, just bad for performance.
-    RemoveAllFromMemory();
-    CloseDB(false);
-    InitDB(false);
-  } else if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) {
-    PerformIdleDailyMaintenance();
-  }
-
-  return NS_OK;
-}
-
-nsresult PermissionManager::RemoveAllModifiedSince(int64_t aModificationTime) {
-  ENSURE_NOT_CHILD_PROCESS;
-
-  return RemovePermissionEntries(
-      [aModificationTime](const PermissionEntry& aPermEntry) {
-        return aModificationTime <= aPermEntry.mModificationTime;
-      });
-}
-
-NS_IMETHODIMP
-PermissionManager::RemovePermissionsWithAttributes(const nsAString& aPattern) {
-  ENSURE_NOT_CHILD_PROCESS;
-  OriginAttributesPattern pattern;
-  if (!pattern.Init(aPattern)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  return RemovePermissionsWithAttributes(pattern);
-}
-
-nsresult PermissionManager::RemovePermissionsWithAttributes(
-    OriginAttributesPattern& aPattern) {
-  Vector<Tuple<nsCOMPtr<nsIPrincipal>, nsCString, nsCString>, 10> permissions;
-  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
-    PermissionHashKey* entry = iter.Get();
-
-    nsCOMPtr<nsIPrincipal> principal;
-    nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, false,
-                                         getter_AddRefs(principal));
-    if (NS_FAILED(rv)) {
-      continue;
-    }
-
-    if (!aPattern.Matches(principal->OriginAttributesRef())) {
-      continue;
-    }
-
-    for (const auto& permEntry : entry->GetPermissions()) {
-      if (!permissions.emplaceBack(principal, mTypeArray[permEntry.mType],
-                                   entry->GetKey()->mOrigin)) {
-        continue;
-      }
-    }
-  }
-
-  for (auto& i : permissions) {
-    AddInternal(Get<0>(i), Get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
-                nsIPermissionManager::EXPIRE_NEVER, 0, 0,
-                PermissionManager::eNotify, PermissionManager::eWriteToDB,
-                false, &Get<2>(i));
-  }
-
-  return NS_OK;
-}
-
-nsresult PermissionManager::GetStripPermsForPrincipal(
-    nsIPrincipal* aPrincipal, nsTArray<PermissionEntry>& aResult) {
-  aResult.Clear();
-  aResult.SetCapacity(kStripOAPermissions.size());
-
-  // No special strip permissions
-  if (kStripOAPermissions.empty()) {
-    return NS_OK;
-  }
-
-  nsresult rv;
-  // Create a key for the principal, but strip any origin attributes
-  RefPtr<PermissionKey> key =
-      PermissionKey::CreateFromPrincipal(aPrincipal, true, rv);
-  if (!key) {
-    MOZ_ASSERT(NS_FAILED(rv));
-    return rv;
-  }
-
-  PermissionHashKey* hashKey = mPermissionTable.GetEntry(key);
-  if (!hashKey) {
-    return NS_OK;
-  }
-
-  for (const auto& permType : kStripOAPermissions) {
-    int32_t index = GetTypeIndex(permType, false);
-    if (index == -1) {
-      continue;
-    }
-    PermissionEntry perm = hashKey->GetPermission(index);
-    if (perm.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
-      continue;
-    }
-    aResult.AppendElement(perm);
-  }
-
-  return NS_OK;
-}
-
-int32_t PermissionManager::GetTypeIndex(const nsACString& aType, bool aAdd) {
-  for (uint32_t i = 0; i < mTypeArray.length(); ++i) {
-    if (mTypeArray[i].Equals(aType)) {
-      return i;
-    }
-  }
-
-  if (!aAdd) {
-    // Not found, but that is ok - we were just looking.
-    return -1;
-  }
-
-  // This type was not registered before.
-  // append it to the array, without copy-constructing the string
-  if (!mTypeArray.emplaceBack(aType)) {
-    return -1;
-  }
-
-  return mTypeArray.length() - 1;
-}
-
-PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
-    nsIPrincipal* aPrincipal, uint32_t aType, bool aExactHostMatch) {
-  EnsureReadCompleted();
-
+// Returns PermissionHashKey for a given { host, isInBrowserElement }
+// tuple. This is not simply using PermissionKey because we will walk-up domains
+// in case of |host| contains sub-domains. Returns null if nothing found. Also
+// accepts host on the format "<foo>". This will perform an exact match lookup
+// as the string doesn't contain any dots.
+nsPermissionManager::PermissionHashKey*
+nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal,
+                                          uint32_t aType,
+                                          bool aExactHostMatch) {
   MOZ_ASSERT(PermissionAvailable(aPrincipal, mTypeArray[aType]));
 
   nsresult rv;
   RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
       aPrincipal, IsOAForceStripPermission(mTypeArray[aType]), rv);
   if (!key) {
     return nullptr;
   }
@@ -2551,17 +2437,23 @@ PermissionManager::PermissionHashKey* Pe
       return GetPermissionHashKey(principal, aType, aExactHostMatch);
     }
   }
 
   // No entry, really...
   return nullptr;
 }
 
-PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
+// Returns PermissionHashKey for a given { host, isInBrowserElement }
+// tuple. This is not simply using PermissionKey because we will walk-up domains
+// in case of |host| contains sub-domains. Returns null if nothing found. Also
+// accepts host on the format "<foo>". This will perform an exact match lookup
+// as the string doesn't contain any dots.
+nsPermissionManager::PermissionHashKey*
+nsPermissionManager::GetPermissionHashKey(
     nsIURI* aURI, const OriginAttributes* aOriginAttributes, uint32_t aType,
     bool aExactHostMatch) {
   MOZ_ASSERT(aURI);
 
 #ifdef DEBUG
   {
     nsCOMPtr<nsIPrincipal> principal;
     nsresult rv = NS_OK;
@@ -2631,304 +2523,587 @@ PermissionManager::PermissionHashKey* Pe
                                   aExactHostMatch);
     }
   }
 
   // No entry, really...
   return nullptr;
 }
 
-nsresult PermissionManager::RemoveAllFromMemory() {
+NS_IMETHODIMP nsPermissionManager::GetAll(
+    nsTArray<RefPtr<nsIPermission>>& aResult) {
+  return GetAllWithTypePrefix(NS_LITERAL_CSTRING(""), aResult);
+}
+
+NS_IMETHODIMP nsPermissionManager::GetAllWithTypePrefix(
+    const nsACString& aPrefix, nsTArray<RefPtr<nsIPermission>>& aResult) {
+  aResult.Clear();
+  if (XRE_IsContentProcess()) {
+    NS_WARNING(
+        "nsPermissionManager's getAllWithTypePrefix is not available in the "
+        "content process, as not all permissions may be available.");
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
+    PermissionHashKey* entry = iter.Get();
+    for (const auto& permEntry : entry->GetPermissions()) {
+      // Given how "default" permissions work and the possibility of them being
+      // overridden with UNKNOWN_ACTION, we might see this value here - but we
+      // do *not* want to return them via the enumerator.
+      if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
+        continue;
+      }
+
+      if (!aPrefix.IsEmpty() &&
+          !StringBeginsWith(mTypeArray[permEntry.mType], aPrefix)) {
+        continue;
+      }
+
+      nsCOMPtr<nsIPrincipal> principal;
+      nsresult rv = GetPrincipalFromOrigin(
+          entry->GetKey()->mOrigin,
+          IsOAForceStripPermission(mTypeArray[permEntry.mType]),
+          getter_AddRefs(principal));
+      if (NS_FAILED(rv)) {
+        continue;
+      }
+
+      RefPtr<nsIPermission> permission = nsPermission::Create(
+          principal, mTypeArray[permEntry.mType], permEntry.mPermission,
+          permEntry.mExpireType, permEntry.mExpireTime,
+          permEntry.mModificationTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      aResult.AppendElement(std::move(permission));
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult nsPermissionManager::GetStripPermsForPrincipal(
+    nsIPrincipal* aPrincipal, nsTArray<PermissionEntry>& aResult) {
+  aResult.Clear();
+  aResult.SetCapacity(kStripOAPermissions.size());
+
+  // No special strip permissions
+  if (kStripOAPermissions.empty()) {
+    return NS_OK;
+  }
+
+  nsresult rv;
+  // Create a key for the principal, but strip any origin attributes
+  RefPtr<PermissionKey> key =
+      PermissionKey::CreateFromPrincipal(aPrincipal, true, rv);
+  if (!key) {
+    MOZ_ASSERT(NS_FAILED(rv));
+    return rv;
+  }
+
+  PermissionHashKey* hashKey = mPermissionTable.GetEntry(key);
+  if (!hashKey) {
+    return NS_OK;
+  }
+
+  for (const auto& permType : kStripOAPermissions) {
+    int32_t index = GetTypeIndex(permType, false);
+    if (index == -1) {
+      continue;
+    }
+    PermissionEntry perm = hashKey->GetPermission(index);
+    if (perm.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
+      continue;
+    }
+    aResult.AppendElement(perm);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPermissionManager::GetAllForPrincipal(
+    nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
+  aResult.Clear();
+
+  MOZ_ASSERT(PermissionAvailable(aPrincipal, EmptyCString()));
+
+  nsresult rv;
+  RefPtr<PermissionKey> key =
+      PermissionKey::CreateFromPrincipal(aPrincipal, false, rv);
+  if (!key) {
+    MOZ_ASSERT(NS_FAILED(rv));
+    return rv;
+  }
+  PermissionHashKey* entry = mPermissionTable.GetEntry(key);
+
+  nsTArray<PermissionEntry> strippedPerms;
+  rv = GetStripPermsForPrincipal(aPrincipal, strippedPerms);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  if (entry) {
+    for (const auto& permEntry : entry->GetPermissions()) {
+      // Only return custom permissions
+      if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
+        continue;
+      }
+
+      // Stripped principal permissions overwrite regular ones
+      // For each permission check if there is a stripped permission we should
+      // use instead
+      PermissionEntry perm = permEntry;
+      nsTArray<PermissionEntry>::index_type index = 0;
+      for (const auto& strippedPerm : strippedPerms) {
+        if (strippedPerm.mType == permEntry.mType) {
+          perm = strippedPerm;
+          strippedPerms.RemoveElementAt(index);
+          break;
+        }
+        index++;
+      }
+
+      RefPtr<nsIPermission> permission = nsPermission::Create(
+          aPrincipal, mTypeArray[perm.mType], perm.mPermission,
+          perm.mExpireType, perm.mExpireTime, perm.mModificationTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      aResult.AppendElement(permission);
+    }
+  }
+
+  for (const auto& perm : strippedPerms) {
+    RefPtr<nsIPermission> permission = nsPermission::Create(
+        aPrincipal, mTypeArray[perm.mType], perm.mPermission, perm.mExpireType,
+        perm.mExpireTime, perm.mModificationTime);
+    if (NS_WARN_IF(!permission)) {
+      continue;
+    }
+    aResult.AppendElement(permission);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsPermissionManager::Observe(nsISupports* aSubject,
+                                           const char* aTopic,
+                                           const char16_t* someData) {
+  ENSURE_NOT_CHILD_PROCESS;
+
+  if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
+    // The profile is about to change,
+    // or is going away because the application is shutting down.
+    RemoveIdleDailyMaintenanceJob();
+    gIsShuttingDown = true;
+    RemoveAllFromMemory();
+    CloseDB(false);
+  } else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
+    // the profile has already changed; init the db from the new location
+    InitDB(false);
+  } else if (!nsCRT::strcmp(aTopic, "testonly-reload-permissions-from-disk")) {
+    // Testing mechanism to reload all permissions from disk. Because the
+    // permission manager automatically initializes itself at startup, tests
+    // that directly manipulate the permissions database need some way to reload
+    // the database for their changes to have any effect. This mechanism was
+    // introduced when moving the permissions manager from on-demand startup to
+    // always being initialized. This is not guarded by a pref because it's not
+    // dangerous to reload permissions from disk, just bad for performance.
+    RemoveAllFromMemory();
+    CloseDB(false);
+    InitDB(false);
+  } else if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) {
+    PerformIdleDailyMaintenance();
+  }
+
+  return NS_OK;
+}
+
+nsresult nsPermissionManager::RemoveAllModifiedSince(
+    int64_t aModificationTime) {
+  ENSURE_NOT_CHILD_PROCESS;
+
+  return RemovePermissionEntries(
+      [aModificationTime](const PermissionEntry& aPermEntry) {
+        return aModificationTime <= aPermEntry.mModificationTime;
+      });
+}
+
+NS_IMETHODIMP
+nsPermissionManager::RemovePermissionsWithAttributes(
+    const nsAString& aPattern) {
+  ENSURE_NOT_CHILD_PROCESS;
+  mozilla::OriginAttributesPattern pattern;
+  if (!pattern.Init(aPattern)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return RemovePermissionsWithAttributes(pattern);
+}
+
+nsresult nsPermissionManager::RemovePermissionsWithAttributes(
+    mozilla::OriginAttributesPattern& aPattern) {
+  Vector<Tuple<nsCOMPtr<nsIPrincipal>, nsCString, nsCString>, 10> permissions;
+  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
+    PermissionHashKey* entry = iter.Get();
+
+    nsCOMPtr<nsIPrincipal> principal;
+    nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, false,
+                                         getter_AddRefs(principal));
+    if (NS_FAILED(rv)) {
+      continue;
+    }
+
+    if (!aPattern.Matches(principal->OriginAttributesRef())) {
+      continue;
+    }
+
+    for (const auto& permEntry : entry->GetPermissions()) {
+      if (!permissions.emplaceBack(principal, mTypeArray[permEntry.mType],
+                                   entry->GetKey()->mOrigin)) {
+        continue;
+      }
+    }
+  }
+
+  for (auto& i : permissions) {
+    AddInternal(Get<0>(i), Get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
+                nsIPermissionManager::EXPIRE_NEVER, 0, 0,
+                nsPermissionManager::eNotify, nsPermissionManager::eWriteToDB,
+                false, &Get<2>(i));
+  }
+
+  return NS_OK;
+}
+
+//*****************************************************************************
+//*** nsPermissionManager private methods
+//*****************************************************************************
+
+nsresult nsPermissionManager::RemoveAllFromMemory() {
   mLargestID = 0;
   mTypeArray.clear();
   mPermissionTable.Clear();
 
   return NS_OK;
 }
 
 // wrapper function for mangling (host,type,perm,expireType,expireTime)
 // set into an nsIPermission.
-void PermissionManager::NotifyObserversWithPermission(
+void nsPermissionManager::NotifyObserversWithPermission(
     nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
     uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
     const char16_t* aData) {
   nsCOMPtr<nsIPermission> permission =
-      Permission::Create(aPrincipal, aType, aPermission, aExpireType,
-                         aExpireTime, aModificationTime);
+      nsPermission::Create(aPrincipal, aType, aPermission, aExpireType,
+                           aExpireTime, aModificationTime);
   if (permission) NotifyObservers(permission, aData);
 }
 
 // notify observers that the permission list changed. there are four possible
 // values for aData:
 // "deleted" means a permission was deleted. aPermission is the deleted
 // permission. "added"   means a permission was added. aPermission is the added
 // permission. "changed" means a permission was altered. aPermission is the new
 // permission. "cleared" means the entire permission list was cleared.
 // aPermission is null.
-void PermissionManager::NotifyObservers(nsIPermission* aPermission,
-                                        const char16_t* aData) {
-  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+void nsPermissionManager::NotifyObservers(nsIPermission* aPermission,
+                                          const char16_t* aData) {
+  nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
   if (observerService)
     observerService->NotifyObservers(aPermission, kPermissionChangeNotification,
                                      aData);
 }
 
-nsresult PermissionManager::Read(const MonitorAutoLock& aProofOfLock) {
+nsresult nsPermissionManager::Read() {
   ENSURE_NOT_CHILD_PROCESS;
 
-  MOZ_ASSERT(!NS_IsMainThread());
-  MOZ_ACCESS_THREAD_BOUND(mThreadBoundData, data);
-
   nsresult rv;
 
   nsCOMPtr<mozIStorageStatement> stmt;
-  rv = data->mDBConn->CreateStatement(
+  rv = mDBConn->CreateStatement(
       NS_LITERAL_CSTRING(
           "SELECT id, origin, type, permission, expireType, "
           "expireTime, modificationTime "
           "FROM moz_perms WHERE expireType != ?1 OR expireTime > ?2"),
       getter_AddRefs(stmt));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = stmt->BindInt32ByIndex(0, nsIPermissionManager::EXPIRE_TIME);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = stmt->BindInt64ByIndex(1, EXPIRY_NOW);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  int64_t id;
+  nsAutoCString origin, type;
+  uint32_t permission;
+  uint32_t expireType;
+  int64_t expireTime;
+  int64_t modificationTime;
   bool hasResult;
   bool readError = false;
 
   while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
-    ReadEntry entry;
-
     // explicitly set our entry id counter for use in AddInternal(),
     // and keep track of the largest id so we know where to pick up.
-    entry.mId = stmt->AsInt64(0);
-    if (entry.mId > mLargestID) mLargestID = entry.mId;
-
-    rv = stmt->GetUTF8String(1, entry.mOrigin);
+    id = stmt->AsInt64(0);
+    if (id > mLargestID) mLargestID = id;
+
+    rv = stmt->GetUTF8String(1, origin);
     if (NS_FAILED(rv)) {
       readError = true;
       continue;
     }
 
-    rv = stmt->GetUTF8String(2, entry.mType);
+    rv = stmt->GetUTF8String(2, type);
     if (NS_FAILED(rv)) {
       readError = true;
       continue;
     }
 
-    entry.mPermission = stmt->AsInt32(3);
-    entry.mExpireType = stmt->AsInt32(4);
+    permission = stmt->AsInt32(3);
+    expireType = stmt->AsInt32(4);
 
     // convert into int64_t values (milliseconds)
-    entry.mExpireTime = stmt->AsInt64(5);
-    entry.mModificationTime = stmt->AsInt64(6);
-
-    entry.mFromMigration = false;
-
-    mReadEntries.AppendElement(entry);
+    expireTime = stmt->AsInt64(5);
+    modificationTime = stmt->AsInt64(6);
+
+    nsCOMPtr<nsIPrincipal> principal;
+    nsresult rv = GetPrincipalFromOrigin(origin, IsOAForceStripPermission(type),
+                                         getter_AddRefs(principal));
+    if (NS_FAILED(rv)) {
+      readError = true;
+      continue;
+    }
+
+    rv = AddInternal(principal, type, permission, id, expireType, expireTime,
+                     modificationTime, eDontNotify, eNoDBOperation, false,
+                     &origin);
+    if (NS_FAILED(rv)) {
+      readError = true;
+      continue;
+    }
   }
 
   if (readError) {
     NS_ERROR("Error occured while reading the permissions database!");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
-void PermissionManager::CompleteMigrations() {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mState == eReady);
-
-  nsresult rv;
-
-  nsTArray<MigrationEntry> entries;
-  {
-    MonitorAutoLock lock(mMonitor);
-    entries.SwapElements(mMigrationEntries);
+static const char kMatchTypeHost[] = "host";
+static const char kMatchTypeOrigin[] = "origin";
+
+// ImportDefaults will read a URL with default permissions and add them to the
+// in-memory copy of permissions.  The database is *not* written to.
+nsresult nsPermissionManager::ImportDefaults() {
+  nsAutoCString defaultsURL;
+  mozilla::Preferences::GetCString(kDefaultsUrlPrefName, defaultsURL);
+  if (defaultsURL.IsEmpty()) {  // == Don't use built-in permissions.
+    return NS_OK;
   }
 
-  for (const MigrationEntry& entry : entries) {
-    rv = UpgradeHostToOriginAndInsert(
-        entry.mHost, entry.mType, entry.mPermission, entry.mExpireType,
-        entry.mExpireTime, entry.mModificationTime, entry.mIsInBrowserElement,
-        [&](const nsACString& aOrigin, const nsCString& aType,
-            uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-            int64_t aModificationTime) {
-          MaybeAddReadEntryFromMigration(aOrigin, aType, aPermission,
-                                         aExpireType, aExpireTime,
-                                         aModificationTime, entry.mId);
-          return NS_OK;
-        });
-    Unused << NS_WARN_IF(NS_FAILED(rv));
-  }
+  nsCOMPtr<nsIURI> defaultsURI;
+  nsresult rv = NS_NewURI(getter_AddRefs(defaultsURI), defaultsURL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIChannel> channel;
+  rv = NS_NewChannel(getter_AddRefs(channel), defaultsURI,
+                     nsContentUtils::GetSystemPrincipal(),
+                     nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+                     nsIContentPolicy::TYPE_OTHER);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIInputStream> inputStream;
+  rv = channel->Open(getter_AddRefs(inputStream));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = _DoImport(inputStream, nullptr);
+  inputStream->Close();
+  return rv;
 }
 
-void PermissionManager::CompleteRead() {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mState == eReady);
+// _DoImport reads the specified stream and adds the parsed elements.  If
+// |conn| is passed, the imported data will be written to the database, but if
+// |conn| is null the data will be added only to the in-memory copy of the
+// database.
+nsresult nsPermissionManager::_DoImport(nsIInputStream* inputStream,
+                                        mozIStorageConnection* conn) {
+  ENSURE_NOT_CHILD_PROCESS;
 
   nsresult rv;
-
-  nsTArray<ReadEntry> entries;
-  {
-    MonitorAutoLock lock(mMonitor);
-    entries.SwapElements(mReadEntries);
-  }
-
-  for (const ReadEntry& entry : entries) {
-    nsCOMPtr<nsIPrincipal> principal;
-    rv = GetPrincipalFromOrigin(entry.mOrigin,
-                                IsOAForceStripPermission(entry.mType),
-                                getter_AddRefs(principal));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
+  // start a transaction on the storage db, to optimize insertions.
+  // transaction will automically commit on completion
+  // (note the transaction is a no-op if a null connection is passed)
+  mozStorageTransaction transaction(conn, true);
+
+  // The DB operation - we only try and write if a connection was passed.
+  DBOperationType operation = conn ? eWriteToDB : eNoDBOperation;
+  // and if no DB connection was passed we assume this is a "default"
+  // permission, so use the special ID which indicates this.
+  int64_t id = conn ? 0 : cIDPermissionIsDefault;
+
+  /* format is:
+   * matchtype \t type \t permission \t host
+   * Only "host" is supported for matchtype
+   * type is a string that identifies the type of permission (e.g. "cookie")
+   * permission is an integer between 1 and 15
+   */
+
+  // Ideally we'd do this with nsILineInputString, but this is called with an
+  // nsIInputStream that comes from a resource:// URI, which doesn't support
+  // that interface.  So NS_ReadLine to the rescue...
+  nsLineBuffer<char> lineBuffer;
+  nsCString line;
+  bool isMore = true;
+  do {
+    rv = NS_ReadLine(inputStream, &lineBuffer, line, &isMore);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (line.IsEmpty() || line.First() == '#') {
       continue;
     }
 
-    DBOperationType op = entry.mFromMigration ? eWriteToDB : eNoDBOperation;
-
-    rv = AddInternal(principal, entry.mType, entry.mPermission, entry.mId,
-                     entry.mExpireType, entry.mExpireTime,
-                     entry.mModificationTime, eDontNotify, op, false,
-                     &entry.mOrigin);
-    Unused << NS_WARN_IF(NS_FAILED(rv));
-  }
+    nsTArray<nsCString> lineArray;
+
+    // Split the line at tabs
+    ParseString(line, '\t', lineArray);
+
+    if (lineArray[0].EqualsLiteral(kMatchTypeHost) && lineArray.Length() == 4) {
+      nsresult error = NS_OK;
+      uint32_t permission = lineArray[2].ToInteger(&error);
+      if (NS_FAILED(error)) continue;
+
+      // the import file format doesn't handle modification times, so we use
+      // 0, which AddInternal will convert to now()
+      int64_t modificationTime = 0;
+
+      UpgradeHostToOriginHostfileImport upHelper(this, operation, id);
+      error =
+          UpgradeHostToOriginAndInsert(lineArray[3], lineArray[1], permission,
+                                       nsIPermissionManager::EXPIRE_NEVER, 0,
+                                       modificationTime, false, &upHelper);
+      if (NS_FAILED(error)) {
+        NS_WARNING("There was a problem importing a host permission");
+      }
+    } else if (lineArray[0].EqualsLiteral(kMatchTypeOrigin) &&
+               lineArray.Length() == 4) {
+      nsresult error = NS_OK;
+      uint32_t permission = lineArray[2].ToInteger(&error);
+      if (NS_FAILED(error)) continue;
+
+      nsCOMPtr<nsIPrincipal> principal;
+      error = GetPrincipalFromOrigin(lineArray[3],
+                                     IsOAForceStripPermission(lineArray[1]),
+                                     getter_AddRefs(principal));
+      if (NS_FAILED(error)) {
+        NS_WARNING("Couldn't import an origin permission - malformed origin");
+        continue;
+      }
+
+      // the import file format doesn't handle modification times, so we use
+      // 0, which AddInternal will convert to now()
+      int64_t modificationTime = 0;
+
+      error = AddInternal(principal, lineArray[1], permission, id,
+                          nsIPermissionManager::EXPIRE_NEVER, 0,
+                          modificationTime, eDontNotify, operation);
+      if (NS_FAILED(error)) {
+        NS_WARNING("There was a problem importing an origin permission");
+      }
+    }
+
+  } while (isMore);
+
+  return NS_OK;
 }
 
-void PermissionManager::MaybeAddReadEntryFromMigration(
-    const nsACString& aOrigin, const nsCString& aType, uint32_t aPermission,
-    uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
-    int64_t aId) {
-  MonitorAutoLock lock(mMonitor);
-
-  // We convert a migration to a ReadEntry only if we don't have an existing
-  // ReadEntry for the same origin + type.
-  for (const ReadEntry& entry : mReadEntries) {
-    if (entry.mOrigin == aOrigin && entry.mType == aType) {
-      return;
+void nsPermissionManager::UpdateDB(
+    OperationType aOp, mozIStorageAsyncStatement* aStmt, int64_t aID,
+    const nsACString& aOrigin, const nsACString& aType, uint32_t aPermission,
+    uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime) {
+  ENSURE_NOT_CHILD_PROCESS_NORET;
+
+  nsresult rv;
+
+  // no statement is ok - just means we don't have a profile
+  if (!aStmt) return;
+
+  switch (aOp) {
+    case eOperationAdding: {
+      rv = aStmt->BindInt64ByIndex(0, aID);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindUTF8StringByIndex(1, aOrigin);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindUTF8StringByIndex(2, aType);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt32ByIndex(3, aPermission);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt32ByIndex(4, aExpireType);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(5, aExpireTime);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(6, aModificationTime);
+      break;
+    }
+
+    case eOperationRemoving: {
+      rv = aStmt->BindInt64ByIndex(0, aID);
+      break;
+    }
+
+    case eOperationChanging: {
+      rv = aStmt->BindInt64ByIndex(0, aID);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt32ByIndex(1, aPermission);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt32ByIndex(2, aExpireType);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(3, aExpireTime);
+      if (NS_FAILED(rv)) break;
+
+      rv = aStmt->BindInt64ByIndex(4, aModificationTime);
+      break;
+    }
+
+    default: {
+      MOZ_ASSERT_UNREACHABLE("need a valid operation in UpdateDB()!");
+      rv = NS_ERROR_UNEXPECTED;
+      break;
     }
   }
 
-  ReadEntry entry;
-  entry.mId = aId;
-  entry.mOrigin = aOrigin;
-  entry.mType = aType;
-  entry.mPermission = aPermission;
-  entry.mExpireType = aExpireType;
-  entry.mExpireTime = aExpireTime;
-  entry.mModificationTime = aModificationTime;
-  entry.mFromMigration = true;
-
-  mReadEntries.AppendElement(entry);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("db change failed!");
+    return;
+  }
+
+  nsCOMPtr<mozIStoragePendingStatement> pending;
+  rv = aStmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
-void PermissionManager::UpdateDB(OperationType aOp, int64_t aID,
-                                 const nsACString& aOrigin,
-                                 const nsACString& aType, uint32_t aPermission,
-                                 uint32_t aExpireType, int64_t aExpireTime,
-                                 int64_t aModificationTime) {
-  ENSURE_NOT_CHILD_PROCESS_NORET;
-
-  MOZ_ASSERT(NS_IsMainThread());
-  EnsureReadCompleted();
-
-  nsCString origin(aOrigin);
-  nsCString type(aType);
-
-  RefPtr<PermissionManager> self = this;
-  mThread->Dispatch(NS_NewRunnableFunction(
-      "PermissionManager::UpdateDB",
-      [self, aOp, aID, origin, type, aPermission, aExpireType, aExpireTime,
-       aModificationTime] {
-        nsresult rv;
-
-        MOZ_ACCESS_THREAD_BOUND(self->mThreadBoundData, data);
-
-        if (self->mState == eClosed || !data->mDBConn) {
-          // no statement is ok - just means we don't have a profile
-          return;
-        }
-
-        mozIStorageStatement* stmt = nullptr;
-        switch (aOp) {
-          case eOperationAdding: {
-            stmt = data->mStmtInsert;
-
-            rv = stmt->BindInt64ByIndex(0, aID);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindUTF8StringByIndex(1, origin);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindUTF8StringByIndex(2, type);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt32ByIndex(3, aPermission);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt32ByIndex(4, aExpireType);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt64ByIndex(5, aExpireTime);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt64ByIndex(6, aModificationTime);
-            break;
-          }
-
-          case eOperationRemoving: {
-            stmt = data->mStmtDelete;
-            rv = stmt->BindInt64ByIndex(0, aID);
-            break;
-          }
-
-          case eOperationChanging: {
-            stmt = data->mStmtUpdate;
-
-            rv = stmt->BindInt64ByIndex(0, aID);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt32ByIndex(1, aPermission);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt32ByIndex(2, aExpireType);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt64ByIndex(3, aExpireTime);
-            if (NS_FAILED(rv)) break;
-
-            rv = stmt->BindInt64ByIndex(4, aModificationTime);
-            break;
-          }
-
-          default: {
-            MOZ_ASSERT_UNREACHABLE("need a valid operation in UpdateDB()!");
-            rv = NS_ERROR_UNEXPECTED;
-            break;
-          }
-        }
-
-        if (NS_FAILED(rv)) {
-          NS_WARNING("db change failed!");
-          return;
-        }
-
-        rv = stmt->Execute();
-        MOZ_ASSERT(NS_SUCCEEDED(rv));
-      }));
-}
-
-bool PermissionManager::GetPermissionsFromOriginOrKey(
+bool nsPermissionManager::GetPermissionsFromOriginOrKey(
     const nsACString& aOrigin, const nsACString& aKey,
     nsTArray<IPC::Permission>& aPerms) {
-  EnsureReadCompleted();
-
   aPerms.Clear();
   if (NS_WARN_IF(XRE_IsContentProcess())) {
     return false;
   }
 
   for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
     PermissionHashKey* entry = iter.Get();
 
@@ -2974,17 +3149,17 @@ bool PermissionManager::GetPermissionsFr
                             permEntry.mExpireType, permEntry.mExpireTime));
       }
     }
   }
 
   return true;
 }
 
-void PermissionManager::SetPermissionsWithKey(
+void nsPermissionManager::SetPermissionsWithKey(
     const nsACString& aPermissionKey, nsTArray<IPC::Permission>& aPerms) {
   if (NS_WARN_IF(XRE_IsParentProcess())) {
     return;
   }
 
   RefPtr<GenericNonExclusivePromise::Private> promise;
   bool foundKey =
       mPermissionKeyPromiseMap.Get(aPermissionKey, getter_AddRefs(promise));
@@ -3025,18 +3200,19 @@ void PermissionManager::SetPermissionsWi
     uint64_t modificationTime = 0;
     AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
                 perm.expireTime, modificationTime, eNotify, eNoDBOperation,
                 true /* ignoreSessionPermissions */);
   }
 }
 
 /* static */
-void PermissionManager::GetKeyForOrigin(const nsACString& aOrigin,
-                                        bool aForceStripOA, nsACString& aKey) {
+void nsPermissionManager::GetKeyForOrigin(const nsACString& aOrigin,
+                                          bool aForceStripOA,
+                                          nsACString& aKey) {
   aKey.Truncate();
 
   // We only key origins for http, https, and ftp URIs. All origins begin with
   // the URL which they apply to, which means that they should begin with their
   // scheme in the case where they are one of these interesting URIs. We don't
   // want to actually parse the URL here however, because this can be called on
   // hot paths.
   if (!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("http:")) &&
@@ -3069,44 +3245,44 @@ void PermissionManager::GetKeyForOrigin(
 
   // Append the stripped suffix to the output origin key.
   nsAutoCString suffix;
   attrs.CreateSuffix(suffix);
   aKey.Append(suffix);
 }
 
 /* static */
-void PermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal,
-                                           bool aForceStripOA,
-                                           nsACString& aKey) {
+void nsPermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal,
+                                             bool aForceStripOA,
+                                             nsACString& aKey) {
   nsAutoCString origin;
   nsresult rv = aPrincipal->GetOrigin(origin);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aKey.Truncate();
     return;
   }
   GetKeyForOrigin(origin, aForceStripOA, aKey);
 }
 
 /* static */
-void PermissionManager::GetKeyForPermission(nsIPrincipal* aPrincipal,
-                                            const nsACString& aType,
-                                            nsACString& aKey) {
+void nsPermissionManager::GetKeyForPermission(nsIPrincipal* aPrincipal,
+                                              const nsACString& aType,
+                                              nsACString& aKey) {
   // Preload permissions have the "" key.
   if (IsPreloadPermission(aType)) {
     aKey.Truncate();
     return;
   }
 
   GetKeyForPrincipal(aPrincipal, IsOAForceStripPermission(aType), aKey);
 }
 
 /* static */
 nsTArray<std::pair<nsCString, nsCString>>
-PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
+nsPermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
   MOZ_ASSERT(aPrincipal);
 
   nsTArray<std::pair<nsCString, nsCString>> pairs;
   nsCOMPtr<nsIPrincipal> prin = aPrincipal;
   while (prin) {
     // Add the pair to the list
     std::pair<nsCString, nsCString>* pair =
         pairs.AppendElement(std::make_pair(EmptyCString(), EmptyCString()));
@@ -3121,32 +3297,30 @@ PermissionManager::GetAllKeysForPrincipa
   }
 
   MOZ_ASSERT(pairs.Length() >= 1,
              "Every principal should have at least one pair item.");
   return pairs;
 }
 
 NS_IMETHODIMP
-PermissionManager::BroadcastPermissionsForPrincipalToAllContentProcesses(
+nsPermissionManager::BroadcastPermissionsForPrincipalToAllContentProcesses(
     nsIPrincipal* aPrincipal) {
   nsTArray<ContentParent*> cps;
   ContentParent::GetAll(cps);
   for (ContentParent* cp : cps) {
     nsresult rv = cp->TransmitPermissionsForPrincipal(aPrincipal);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
-bool PermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
-                                            const nsACString& aType) {
-  EnsureReadCompleted();
-
+bool nsPermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
+                                              const nsACString& aType) {
   if (XRE_IsContentProcess()) {
     nsAutoCString permissionKey;
     // NOTE: GetKeyForPermission accepts a null aType.
     GetKeyForPermission(aPrincipal, aType, permissionKey);
 
     // If we have a pending promise for the permission key in question, we don't
     // have the permission available, so report a warning and return false.
     RefPtr<GenericNonExclusivePromise::Private> promise;
@@ -3159,18 +3333,18 @@ bool PermissionManager::PermissionAvaila
                                  permissionKey.get())
                      .get());
       return false;
     }
   }
   return true;
 }
 
-void PermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
-                                                 nsIRunnable* aRunnable) {
+void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
+                                                   nsIRunnable* aRunnable) {
   MOZ_ASSERT(aRunnable);
 
   if (!XRE_IsContentProcess()) {
     aRunnable->Run();
     return;
   }
 
   nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
@@ -3201,365 +3375,12 @@ void PermissionManager::WhenPermissionsA
   auto* thread = AbstractThread::MainThread();
 
   RefPtr<nsIRunnable> runnable = aRunnable;
   GenericNonExclusivePromise::All(thread, promises)
       ->Then(
           thread, __func__, [runnable]() { runnable->Run(); },
           []() {
             NS_WARNING(
-                "PermissionManager permission promise rejected. We're "
+                "nsPermissionManager permission promise rejected. We're "
                 "probably shutting down.");
           });
 }
-
-void PermissionManager::EnsureReadCompleted() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mState == eInitializing) {
-    MonitorAutoLock lock(mMonitor);
-
-    while (mState == eInitializing) {
-      mMonitor.Wait();
-    }
-  }
-
-  switch (mState) {
-    case eInitializing:
-      MOZ_CRASH("This state is impossible!");
-
-    case eDBInitialized:
-      mState = eReady;
-
-      CompleteMigrations();
-      ImportLatestDefaults();
-      CompleteRead();
-
-      [[fallthrough]];
-
-    case eReady:
-      [[fallthrough]];
-
-    case eClosed:
-      return;
-
-    default:
-      MOZ_CRASH("Invalid state");
-  }
-}
-
-already_AddRefed<nsIInputStream> PermissionManager::GetDefaultsInputStream() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsAutoCString defaultsURL;
-  Preferences::GetCString(kDefaultsUrlPrefName, defaultsURL);
-  if (defaultsURL.IsEmpty()) {  // == Don't use built-in permissions.
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIURI> defaultsURI;
-  nsresult rv = NS_NewURI(getter_AddRefs(defaultsURI), defaultsURL);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewChannel(getter_AddRefs(channel), defaultsURI,
-                     nsContentUtils::GetSystemPrincipal(),
-                     nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                     nsIContentPolicy::TYPE_OTHER);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  nsCOMPtr<nsIInputStream> inputStream;
-  rv = channel->Open(getter_AddRefs(inputStream));
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  return inputStream.forget();
-}
-
-void PermissionManager::ConsumeDefaultsInputStream(
-    nsIInputStream* aInputStream, const MonitorAutoLock& aProofOfLock) {
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  constexpr char kMatchTypeHost[] = "host";
-  constexpr char kMatchTypeOrigin[] = "origin";
-
-  mDefaultEntries.Clear();
-
-  if (!aInputStream) {
-    return;
-  }
-
-  nsresult rv;
-
-  /* format is:
-   * matchtype \t type \t permission \t host
-   * Only "host" is supported for matchtype
-   * type is a string that identifies the type of permission (e.g. "cookie")
-   * permission is an integer between 1 and 15
-   */
-
-  // Ideally we'd do this with nsILineInputString, but this is called with an
-  // nsIInputStream that comes from a resource:// URI, which doesn't support
-  // that interface.  So NS_ReadLine to the rescue...
-  nsLineBuffer<char> lineBuffer;
-  nsCString line;
-  bool isMore = true;
-  do {
-    rv = NS_ReadLine(aInputStream, &lineBuffer, line, &isMore);
-    NS_ENSURE_SUCCESS_VOID(rv);
-
-    if (line.IsEmpty() || line.First() == '#') {
-      continue;
-    }
-
-    nsTArray<nsCString> lineArray;
-
-    // Split the line at tabs
-    ParseString(line, '\t', lineArray);
-
-    if (lineArray.Length() != 4) {
-      continue;
-    }
-
-    nsresult error = NS_OK;
-    uint32_t permission = lineArray[2].ToInteger(&error);
-    if (NS_FAILED(error)) {
-      continue;
-    }
-
-    DefaultEntry::Op op;
-
-    if (lineArray[0].EqualsLiteral(kMatchTypeHost)) {
-      op = DefaultEntry::eImportMatchTypeHost;
-    } else if (lineArray[0].EqualsLiteral(kMatchTypeOrigin)) {
-      op = DefaultEntry::eImportMatchTypeOrigin;
-    } else {
-      continue;
-    }
-
-    DefaultEntry* entry = mDefaultEntries.AppendElement();
-    MOZ_ASSERT(entry);
-
-    entry->mOp = op;
-    entry->mPermission = permission;
-    entry->mHostOrOrigin = lineArray[3];
-    entry->mType = lineArray[1];
-  } while (isMore);
-}
-
-// ImportLatestDefaults will import the latest default cookies read during the
-// last DB initialization.
-nsresult PermissionManager::ImportLatestDefaults() {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mState == eReady);
-
-  nsresult rv;
-
-  MonitorAutoLock lock(mMonitor);
-
-  for (const DefaultEntry& entry : mDefaultEntries) {
-    if (entry.mOp == DefaultEntry::eImportMatchTypeHost) {
-      // the import file format doesn't handle modification times, so we use
-      // 0, which AddInternal will convert to now()
-      int64_t modificationTime = 0;
-
-      rv = UpgradeHostToOriginAndInsert(
-          entry.mHostOrOrigin, entry.mType, entry.mPermission,
-          nsIPermissionManager::EXPIRE_NEVER, 0, modificationTime, false,
-          [&](const nsACString& aOrigin, const nsCString& aType,
-              uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
-              int64_t aModificationTime) {
-            nsCOMPtr<nsIPrincipal> principal;
-            nsresult rv =
-                GetPrincipalFromOrigin(aOrigin, IsOAForceStripPermission(aType),
-                                       getter_AddRefs(principal));
-            NS_ENSURE_SUCCESS(rv, rv);
-
-            return AddInternal(
-                principal, aType, aPermission, cIDPermissionIsDefault,
-                aExpireType, aExpireTime, aModificationTime,
-                PermissionManager::eDontNotify,
-                PermissionManager::eNoDBOperation, false, &aOrigin);
-          });
-
-      if (NS_FAILED(rv)) {
-        NS_WARNING("There was a problem importing a host permission");
-      }
-      continue;
-    }
-
-    MOZ_ASSERT(entry.mOp == DefaultEntry::eImportMatchTypeOrigin);
-
-    nsCOMPtr<nsIPrincipal> principal;
-    rv = GetPrincipalFromOrigin(entry.mHostOrOrigin,
-                                IsOAForceStripPermission(entry.mType),
-                                getter_AddRefs(principal));
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Couldn't import an origin permission - malformed origin");
-      continue;
-    }
-
-    // the import file format doesn't handle modification times, so we use
-    // 0, which AddInternal will convert to now()
-    int64_t modificationTime = 0;
-
-    rv = AddInternal(principal, entry.mType, entry.mPermission,
-                     cIDPermissionIsDefault, nsIPermissionManager::EXPIRE_NEVER,
-                     0, modificationTime, eDontNotify, eNoDBOperation);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("There was a problem importing an origin permission");
-    }
-  }
-
-  return NS_OK;
-}
-
-/**
- * Perform the early steps of a permission check and determine whether we need
- * to call CommonTestPermissionInternal() for the actual permission check.
- *
- * @param aPrincipal optional principal argument to check the permission for,
- *                   can be nullptr if we aren't performing a principal-based
- *                   check.
- * @param aTypeIndex if the caller isn't sure what the index of the permission
- *                   type to check for is in the mTypeArray member variable,
- *                   it should pass -1, otherwise this would be the index of
- *                   the type inside mTypeArray.  This would only be something
- *                   other than -1 in recursive invocations of this function.
- * @param aType      the permission type to test.
- * @param aPermission out argument which will be a permission type that we
- *                    will return from this function once the function is
- *                    done.
- * @param aDefaultPermission the default permission to be used if we can't
- *                           determine the result of the permission check.
- * @param aDefaultPermissionIsValid whether the previous argument contains a
- *                                  valid value.
- * @param aExactHostMatch whether to look for the exact host name or also for
- *                        subdomains that can have the same permission.
- * @param aIncludingSession whether to include session permissions when
- *                          testing for the permission.
- */
-PermissionManager::TestPreparationResult
-PermissionManager::CommonPrepareToTestPermission(
-    nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
-    uint32_t* aPermission, uint32_t aDefaultPermission,
-    bool aDefaultPermissionIsValid, bool aExactHostMatch,
-    bool aIncludingSession) {
-  auto* basePrin = BasePrincipal::Cast(aPrincipal);
-  if (basePrin && basePrin->IsSystemPrincipal()) {
-    *aPermission = ALLOW_ACTION;
-    return AsVariant(NS_OK);
-  }
-
-  EnsureReadCompleted();
-
-  // For some permissions, query the default from a pref. We want to avoid
-  // doing this for all permissions so that permissions can opt into having
-  // the pref lookup overhead on each call.
-  int32_t defaultPermission =
-      aDefaultPermissionIsValid ? aDefaultPermission : UNKNOWN_ACTION;
-  if (!aDefaultPermissionIsValid && HasDefaultPref(aType)) {
-    Unused << mDefaultPrefBranch->GetIntPref(PromiseFlatCString(aType).get(),
-                                             &defaultPermission);
-  }
-
-  // Set the default.
-  *aPermission = defaultPermission;
-
-  int32_t typeIndex =
-      aTypeIndex == -1 ? GetTypeIndex(aType, false) : aTypeIndex;
-
-  // For expanded principals, we want to iterate over the allowlist and see
-  // if the permission is granted for any of them.
-  if (basePrin && basePrin->Is<ExpandedPrincipal>()) {
-    auto ep = basePrin->As<ExpandedPrincipal>();
-    for (auto& prin : ep->AllowList()) {
-      uint32_t perm;
-      nsresult rv =
-          CommonTestPermission(prin, typeIndex, aType, &perm, defaultPermission,
-                               true, aExactHostMatch, aIncludingSession);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return AsVariant(rv);
-      }
-
-      if (perm == nsIPermissionManager::ALLOW_ACTION) {
-        *aPermission = perm;
-        return AsVariant(NS_OK);
-      }
-      if (perm == nsIPermissionManager::PROMPT_ACTION) {
-        // Store it, but keep going to see if we can do better.
-        *aPermission = perm;
-      }
-    }
-
-    return AsVariant(NS_OK);
-  }
-
-  // If type == -1, the type isn't known, just signal that we are done.
-  if (typeIndex == -1) {
-    return AsVariant(NS_OK);
-  }
-
-  return AsVariant(typeIndex);
-}
-
-// If aTypeIndex is passed -1, we try to inder the type index from aType.
-nsresult PermissionManager::CommonTestPermission(
-    nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
-    uint32_t* aPermission, uint32_t aDefaultPermission,
-    bool aDefaultPermissionIsValid, bool aExactHostMatch,
-    bool aIncludingSession) {
-  auto preparationResult = CommonPrepareToTestPermission(
-      aPrincipal, aTypeIndex, aType, aPermission, aDefaultPermission,
-      aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
-  if (preparationResult.is<nsresult>()) {
-    return preparationResult.as<nsresult>();
-  }
-
-  return CommonTestPermissionInternal(
-      aPrincipal, nullptr, nullptr, preparationResult.as<int32_t>(), aType,
-      aPermission, aExactHostMatch, aIncludingSession);
-}
-
-// If aTypeIndex is passed -1, we try to inder the type index from aType.
-nsresult PermissionManager::CommonTestPermission(
-    nsIURI* aURI, int32_t aTypeIndex, const nsACString& aType,
-    uint32_t* aPermission, uint32_t aDefaultPermission,
-    bool aDefaultPermissionIsValid, bool aExactHostMatch,
-    bool aIncludingSession) {
-  auto preparationResult = CommonPrepareToTestPermission(
-      nullptr, aTypeIndex, aType, aPermission, aDefaultPermission,
-      aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
-  if (preparationResult.is<nsresult>()) {
-    return preparationResult.as<nsresult>();
-  }
-
-  return CommonTestPermissionInternal(
-      nullptr, aURI, nullptr, preparationResult.as<int32_t>(), aType,
-      aPermission, aExactHostMatch, aIncludingSession);
-}
-
-nsresult PermissionManager::CommonTestPermission(
-    nsIURI* aURI, const OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
-    const nsACString& aType, uint32_t* aPermission, uint32_t aDefaultPermission,
-    bool aDefaultPermissionIsValid, bool aExactHostMatch,
-    bool aIncludingSession) {
-  auto preparationResult = CommonPrepareToTestPermission(
-      nullptr, aTypeIndex, aType, aPermission, aDefaultPermission,
-      aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
-  if (preparationResult.is<nsresult>()) {
-    return preparationResult.as<nsresult>();
-  }
-
-  return CommonTestPermissionInternal(
-      nullptr, aURI, aOriginAttributes, preparationResult.as<int32_t>(), aType,
-      aPermission, aExactHostMatch, aIncludingSession);
-}
-
-nsresult PermissionManager::TestPermissionWithoutDefaultsFromPrincipal(
-    nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t* aPermission) {
-  MOZ_ASSERT(!HasDefaultPref(aType));
-
-  return CommonTestPermission(aPrincipal, -1, aType, aPermission,
-                              nsIPermissionManager::UNKNOWN_ACTION, true, false,
-                              true);
-}
-
-}  // namespace mozilla
rename from extensions/permissions/PermissionManager.h
rename to extensions/permissions/nsPermissionManager.h
--- a/extensions/permissions/PermissionManager.h
+++ b/extensions/permissions/nsPermissionManager.h
@@ -1,59 +1,57 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
-#ifndef mozilla_PermissionManager_h
-#define mozilla_PermissionManager_h
+#ifndef nsPermissionManager_h__
+#define nsPermissionManager_h__
 
 #include "nsIPermissionManager.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
+#include "nsIInputStream.h"
 #include "nsTHashtable.h"
 #include "nsTArray.h"
 #include "nsString.h"
+#include "nsPermission.h"
+#include "nsIPrefBranch.h"
 #include "nsHashKeys.h"
+#include "nsCOMArray.h"
+#include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
-#include "mozilla/Atomics.h"
-#include "mozilla/Monitor.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/ExpandedPrincipal.h"
 #include "mozilla/MozPromise.h"
-#include "mozilla/ThreadBound.h"
+#include "mozilla/Unused.h"
 #include "mozilla/Variant.h"
 #include "mozilla/Vector.h"
 
 #include <utility>
 
-class mozIStorageConnection;
-class mozIStorageStatement;
-class nsIInputStream;
-class nsIPermission;
-class nsIPrefBranch;
-
 namespace IPC {
 struct Permission;
 }
 
 namespace mozilla {
 class OriginAttributesPattern;
+}
 
-namespace dom {
-class ContentChild;
-}  // namespace dom
+class nsIPermission;
+class mozIStorageConnection;
+class mozIStorageAsyncStatement;
 
 ////////////////////////////////////////////////////////////////////////////////
 
-class PermissionManager final : public nsIPermissionManager,
-                                public nsIObserver,
-                                public nsSupportsWeakReference {
-  friend class dom::ContentChild;
-
+class nsPermissionManager final : public nsIPermissionManager,
+                                  public nsIObserver,
+                                  public nsSupportsWeakReference {
  public:
   class PermissionEntry {
    public:
     PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission,
                     uint32_t aExpireType, int64_t aExpireTime,
                     int64_t aModificationTime)
         : mID(aID),
           mExpireTime(aExpireTime),
@@ -81,21 +79,21 @@ class PermissionManager final : public n
    */
   class PermissionKey {
    public:
     static PermissionKey* CreateFromPrincipal(nsIPrincipal* aPrincipal,
                                               bool aForceStripOA,
                                               nsresult& aResult);
     static PermissionKey* CreateFromURI(nsIURI* aURI, nsresult& aResult);
     static PermissionKey* CreateFromURIAndOriginAttributes(
-        nsIURI* aURI, const OriginAttributes* aOriginAttributes,
+        nsIURI* aURI, const mozilla::OriginAttributes* aOriginAttributes,
         bool aForceStripOA, nsresult& aResult);
 
     explicit PermissionKey(const nsACString& aOrigin)
-        : mOrigin(aOrigin), mHashCode(HashString(aOrigin)) {}
+        : mOrigin(aOrigin), mHashCode(mozilla::HashString(aOrigin)) {}
 
     bool operator==(const PermissionKey& aKey) const {
       return mOrigin.Equals(aKey.mOrigin);
     }
 
     PLDHashNumber GetHashCode() const { return mHashCode; }
 
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey)
@@ -150,58 +148,78 @@ class PermissionManager final : public n
                              nsIPermissionManager::EXPIRE_NEVER, 0, 0);
     }
 
    private:
     AutoTArray<PermissionEntry, 1> mPermissions;
   };
 
   // nsISupports
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS
   NS_DECL_NSIPERMISSIONMANAGER
   NS_DECL_NSIOBSERVER
 
-  PermissionManager();
+  nsPermissionManager();
   static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
-  static PermissionManager* GetInstance();
+  static nsPermissionManager* GetInstance();
   nsresult Init();
 
   // enums for AddInternal()
   enum OperationType {
     eOperationNone,
     eOperationAdding,
     eOperationRemoving,
     eOperationChanging,
     eOperationReplacingDefault
   };
 
   enum DBOperationType { eNoDBOperation, eWriteToDB };
 
   enum NotifyOperationType { eDontNotify, eNotify };
 
+  // A special value for a permission ID that indicates the ID was loaded as
+  // a default value.  These will never be written to the database, but may
+  // be overridden with an explicit permission (including UNKNOWN_ACTION)
+  static const int64_t cIDPermissionIsDefault = -1;
+
+  nsresult AddInternal(nsIPrincipal* aPrincipal, const nsACString& aType,
+                       uint32_t aPermission, int64_t aID, uint32_t aExpireType,
+                       int64_t aExpireTime, int64_t aModificationTime,
+                       NotifyOperationType aNotifyOperation,
+                       DBOperationType aDBOperation,
+                       const bool aIgnoreSessionPermissions = false,
+                       const nsACString* aOriginString = nullptr);
+
   // Similar to TestPermissionFromPrincipal, except that it is used only for
   // permissions which can never have default values.
   nsresult TestPermissionWithoutDefaultsFromPrincipal(nsIPrincipal* aPrincipal,
                                                       const nsACString& aType,
-                                                      uint32_t* aPermission);
+                                                      uint32_t* aPermission) {
+    MOZ_ASSERT(!HasDefaultPref(aType));
+
+    return CommonTestPermission(aPrincipal, -1, aType, aPermission,
+                                nsIPermissionManager::UNKNOWN_ACTION, true,
+                                false, true);
+  }
 
   nsresult LegacyTestPermissionFromURI(
-      nsIURI* aURI, const OriginAttributes* aOriginAttributes,
+      nsIURI* aURI, const mozilla::OriginAttributes* aOriginAttributes,
       const nsACString& aType, uint32_t* aPermission);
 
   /**
    * Initialize the permission-manager service.
    * The permission manager is always initialized at startup because when it
    * was lazy-initialized on demand, it was possible for it to be created
    * once shutdown had begun, resulting in the manager failing to correctly
    * shutdown because it missed its shutdown observer notification.
    */
   static void Startup();
 
-  nsresult RemovePermissionsWithAttributes(OriginAttributesPattern& aAttrs);
+  nsresult RemovePermissionsWithAttributes(
+      mozilla::OriginAttributesPattern& aAttrs);
 
   /**
    * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
    * permission keys.
    *
    * Get the permission key corresponding to the given Principal. This method is
    * intentionally infallible, as we want to provide an permission key to every
    * principal. Principals which don't have meaningful URIs with http://,
@@ -291,34 +309,34 @@ class PermissionManager final : public n
   /**
    * The content process doesn't have access to every permission. Instead, when
    * LOAD_DOCUMENT_URI channels for http://, https://, and ftp:// URIs are
    * opened, the permissions for those channels are sent down to the content
    * process before the OnStartRequest message. Permissions for principals with
    * other schemes are sent down at process startup.
    *
    * Permissions are keyed and grouped by "Permission Key"s.
-   * `PermissionManager::GetKeyForPrincipal` provides the mechanism for
+   * `nsPermissionManager::GetKeyForPrincipal` provides the mechanism for
    * determining the permission key for a given principal.
    *
    * This method may only be called in the parent process. It fills the nsTArray
    * argument with the IPC::Permission objects which have a matching origin.
    *
    * @param origin The origin to use to find the permissions of interest.
    * @param key The key to use to find the permissions of interest. Only used
    *            when the origin argument is empty.
    * @param perms  An array which will be filled with the permissions which
    *               match the given origin.
    */
   bool GetPermissionsFromOriginOrKey(const nsACString& aOrigin,
                                      const nsACString& aKey,
                                      nsTArray<IPC::Permission>& aPerms);
 
   /**
-   * See `PermissionManager::GetPermissionsWithKey` for more info on
+   * See `nsPermissionManager::GetPermissionsWithKey` for more info on
    * Permission keys.
    *
    * `SetPermissionsWithKey` may only be called in the Child process, and
    * initializes the permission manager with the permissions for a given
    * Permission key. marking permissions with that key as available.
    *
    * @param permissionKey  The key for the permissions which have been sent
    * over.
@@ -342,289 +360,289 @@ class PermissionManager final : public n
    * for.
    * @param aRunnable  The runnable to run when permissions are available for
    * the given principal.
    */
   void WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
                                 nsIRunnable* aRunnable);
 
  private:
-  ~PermissionManager();
+  virtual ~nsPermissionManager();
 
   /**
    * Get all permissions for a given principal, which should not be isolated
    * by user context or private browsing. The principal has its origin
    * attributes stripped before perm db lookup. This is currently only affects
    * the "cookie" permission.
    * @param aPrincipal Used for creating the permission key.
    */
   nsresult GetStripPermsForPrincipal(nsIPrincipal* aPrincipal,
                                      nsTArray<PermissionEntry>& aResult);
 
-  // Returns -1 on failure
-  int32_t GetTypeIndex(const nsACString& aType, bool aAdd);
+  // NOTE: nullptr can be passed as aType - if it is this function will return
+  // "false" unconditionally.
+  static bool HasDefaultPref(const nsACString& aType) {
+    // A list of permissions that can have a fallback default permission
+    // set under the permissions.default.* pref.
+    static const nsLiteralCString kPermissionsWithDefaults[] = {
+        NS_LITERAL_CSTRING("camera"), NS_LITERAL_CSTRING("microphone"),
+        NS_LITERAL_CSTRING("geo"), NS_LITERAL_CSTRING("desktop-notification"),
+        NS_LITERAL_CSTRING("shortcuts")};
+
+    if (!aType.IsEmpty()) {
+      for (const auto& perm : kPermissionsWithDefaults) {
+        if (perm.Equals(aType)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
 
-  // Returns PermissionHashKey for a given { host, isInBrowserElement } tuple.
-  // This is not simply using PermissionKey because we will walk-up domains in
-  // case of |host| contains sub-domains. Returns null if nothing found. Also
-  // accepts host on the format "<foo>". This will perform an exact match lookup
-  // as the string doesn't contain any dots.
+  // Returns -1 on failure
+  int32_t GetTypeIndex(const nsACString& aType, bool aAdd) {
+    for (uint32_t i = 0; i < mTypeArray.length(); ++i) {
+      if (mTypeArray[i].Equals(aType)) {
+        return i;
+      }
+    }
+
+    if (!aAdd) {
+      // Not found, but that is ok - we were just looking.
+      return -1;
+    }
+
+    // This type was not registered before.
+    // append it to the array, without copy-constructing the string
+    if (!mTypeArray.emplaceBack(aType)) {
+      return -1;
+    }
+
+    return mTypeArray.length() - 1;
+  }
+
   PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal,
                                           uint32_t aType, bool aExactHostMatch);
-
-  // Returns PermissionHashKey for a given { host, isInBrowserElement } tuple.
-  // This is not simply using PermissionKey because we will walk-up domains in
-  // case of |host| contains sub-domains. Returns null if nothing found. Also
-  // accepts host on the format "<foo>". This will perform an exact match lookup
-  // as the string doesn't contain any dots.
   PermissionHashKey* GetPermissionHashKey(
-      nsIURI* aURI, const OriginAttributes* aOriginAttributes, uint32_t aType,
-      bool aExactHostMatch);
+      nsIURI* aURI, const mozilla::OriginAttributes* aOriginAttributes,
+      uint32_t aType, bool aExactHostMatch);
 
   // The int32_t is the type index, the nsresult is an early bail-out return
   // code.
-  typedef Variant<int32_t, nsresult> TestPreparationResult;
+  typedef mozilla::Variant<int32_t, nsresult> TestPreparationResult;
+  /**
+   * Perform the early steps of a permission check and determine whether we need
+   * to call CommonTestPermissionInternal() for the actual permission check.
+   *
+   * @param aPrincipal optional principal argument to check the permission for,
+   *                   can be nullptr if we aren't performing a principal-based
+   *                   check.
+   * @param aTypeIndex if the caller isn't sure what the index of the permission
+   *                   type to check for is in the mTypeArray member variable,
+   *                   it should pass -1, otherwise this would be the index of
+   *                   the type inside mTypeArray.  This would only be something
+   *                   other than -1 in recursive invocations of this function.
+   * @param aType      the permission type to test.
+   * @param aPermission out argument which will be a permission type that we
+   *                    will return from this function once the function is
+   *                    done.
+   * @param aDefaultPermission the default permission to be used if we can't
+   *                           determine the result of the permission check.
+   * @param aDefaultPermissionIsValid whether the previous argument contains a
+   *                                  valid value.
+   * @param aExactHostMatch whether to look for the exact host name or also for
+   *                        subdomains that can have the same permission.
+   * @param aIncludingSession whether to include session permissions when
+   *                          testing for the permission.
+   */
   TestPreparationResult CommonPrepareToTestPermission(
       nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
       uint32_t* aPermission, uint32_t aDefaultPermission,
       bool aDefaultPermissionIsValid, bool aExactHostMatch,
-      bool aIncludingSession);
+      bool aIncludingSession) {
+    using mozilla::AsVariant;
+
+    auto* basePrin = mozilla::BasePrincipal::Cast(aPrincipal);
+    if (basePrin && basePrin->IsSystemPrincipal()) {
+      *aPermission = ALLOW_ACTION;
+      return AsVariant(NS_OK);
+    }
+
+    // For some permissions, query the default from a pref. We want to avoid
+    // doing this for all permissions so that permissions can opt into having
+    // the pref lookup overhead on each call.
+    int32_t defaultPermission =
+        aDefaultPermissionIsValid ? aDefaultPermission : UNKNOWN_ACTION;
+    if (!aDefaultPermissionIsValid && HasDefaultPref(aType)) {
+      mozilla::Unused << mDefaultPrefBranch->GetIntPref(
+          PromiseFlatCString(aType).get(), &defaultPermission);
+    }
+
+    // Set the default.
+    *aPermission = defaultPermission;
+
+    int32_t typeIndex =
+        aTypeIndex == -1 ? GetTypeIndex(aType, false) : aTypeIndex;
+
+    // For expanded principals, we want to iterate over the allowlist and see
+    // if the permission is granted for any of them.
+    if (basePrin && basePrin->Is<ExpandedPrincipal>()) {
+      auto ep = basePrin->As<ExpandedPrincipal>();
+      for (auto& prin : ep->AllowList()) {
+        uint32_t perm;
+        nsresult rv = CommonTestPermission(prin, typeIndex, aType, &perm,
+                                           defaultPermission, true,
+                                           aExactHostMatch, aIncludingSession);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return AsVariant(rv);
+        }
+
+        if (perm == nsIPermissionManager::ALLOW_ACTION) {
+          *aPermission = perm;
+          return AsVariant(NS_OK);
+        }
+        if (perm == nsIPermissionManager::PROMPT_ACTION) {
+          // Store it, but keep going to see if we can do better.
+          *aPermission = perm;
+        }
+      }
+
+      return AsVariant(NS_OK);
+    }
+
+    // If type == -1, the type isn't known, just signal that we are done.
+    if (typeIndex == -1) {
+      return AsVariant(NS_OK);
+    }
+
+    return AsVariant(typeIndex);
+  }
 
   // If aTypeIndex is passed -1, we try to inder the type index from aType.
   nsresult CommonTestPermission(nsIPrincipal* aPrincipal, int32_t aTypeIndex,
                                 const nsACString& aType, uint32_t* aPermission,
                                 uint32_t aDefaultPermission,
                                 bool aDefaultPermissionIsValid,
-                                bool aExactHostMatch, bool aIncludingSession);
+                                bool aExactHostMatch, bool aIncludingSession) {
+    auto preparationResult = CommonPrepareToTestPermission(
+        aPrincipal, aTypeIndex, aType, aPermission, aDefaultPermission,
+        aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
+    if (preparationResult.is<nsresult>()) {
+      return preparationResult.as<nsresult>();
+    }
 
+    return CommonTestPermissionInternal(
+        aPrincipal, nullptr, nullptr, preparationResult.as<int32_t>(), aType,
+        aPermission, aExactHostMatch, aIncludingSession);
+  }
   // If aTypeIndex is passed -1, we try to inder the type index from aType.
   nsresult CommonTestPermission(nsIURI* aURI, int32_t aTypeIndex,
                                 const nsACString& aType, uint32_t* aPermission,
                                 uint32_t aDefaultPermission,
                                 bool aDefaultPermissionIsValid,
-                                bool aExactHostMatch, bool aIncludingSession);
+                                bool aExactHostMatch, bool aIncludingSession) {
+    auto preparationResult = CommonPrepareToTestPermission(
+        nullptr, aTypeIndex, aType, aPermission, aDefaultPermission,
+        aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
+    if (preparationResult.is<nsresult>()) {
+      return preparationResult.as<nsresult>();
+    }
 
-  nsresult CommonTestPermission(nsIURI* aURI,
-                                const OriginAttributes* aOriginAttributes,
-                                int32_t aTypeIndex, const nsACString& aType,
-                                uint32_t* aPermission,
-                                uint32_t aDefaultPermission,
-                                bool aDefaultPermissionIsValid,
-                                bool aExactHostMatch, bool aIncludingSession);
+    return CommonTestPermissionInternal(
+        nullptr, aURI, nullptr, preparationResult.as<int32_t>(), aType,
+        aPermission, aExactHostMatch, aIncludingSession);
+  }
+  nsresult CommonTestPermission(
+      nsIURI* aURI, const mozilla::OriginAttributes* aOriginAttributes,
+      int32_t aTypeIndex, const nsACString& aType, uint32_t* aPermission,
+      uint32_t aDefaultPermission, bool aDefaultPermissionIsValid,
+      bool aExactHostMatch, bool aIncludingSession) {
+    auto preparationResult = CommonPrepareToTestPermission(
+        nullptr, aTypeIndex, aType, aPermission, aDefaultPermission,
+        aDefaultPermissionIsValid, aExactHostMatch, aIncludingSession);
+    if (preparationResult.is<nsresult>()) {
+      return preparationResult.as<nsresult>();
+    }
 
+    return CommonTestPermissionInternal(
+        nullptr, aURI, aOriginAttributes, preparationResult.as<int32_t>(),
+        aType, aPermission, aExactHostMatch, aIncludingSession);
+  }
   // Only one of aPrincipal or aURI is allowed to be passed in.
   nsresult CommonTestPermissionInternal(
       nsIPrincipal* aPrincipal, nsIURI* aURI,
-      const OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
+      const mozilla::OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
       const nsACString& aType, uint32_t* aPermission, bool aExactHostMatch,
       bool aIncludingSession);
 
   nsresult OpenDatabase(nsIFile* permissionsFile);
-
-  void InitDB(bool aRemoveFile);
-  nsresult TryInitDB(bool aRemoveFile, nsIInputStream* aDefaultsInputStream);
-
+  nsresult InitDB(bool aRemoveFile);
   void AddIdleDailyMaintenanceJob();
   void RemoveIdleDailyMaintenanceJob();
   void PerformIdleDailyMaintenance();
 
-  nsresult ImportLatestDefaults();
-  already_AddRefed<nsIInputStream> GetDefaultsInputStream();
-  void ConsumeDefaultsInputStream(nsIInputStream* aDefaultsInputStream,
-                                  const MonitorAutoLock& aProofOfLock);
-
   nsresult CreateTable();
+  nsresult ImportDefaults();
+  nsresult _DoImport(nsIInputStream* inputStream, mozIStorageConnection* aConn);
+  nsresult Read();
   void NotifyObserversWithPermission(nsIPrincipal* aPrincipal,
                                      const nsACString& aType,
                                      uint32_t aPermission, uint32_t aExpireType,
                                      int64_t aExpireTime,
                                      int64_t aModificationTime,
                                      const char16_t* aData);
   void NotifyObservers(nsIPermission* aPermission, const char16_t* aData);
 
   // Finalize all statements, close the DB and null it.
   // if aRebuildOnSuccess, reinitialize database
   void CloseDB(bool aRebuildOnSuccess = false);
 
   nsresult RemoveAllInternal(bool aNotifyObservers);
   nsresult RemoveAllFromMemory();
-
-  void UpdateDB(OperationType aOp, int64_t aID, const nsACString& aOrigin,
-                const nsACString& aType, uint32_t aPermission,
-                uint32_t aExpireType, int64_t aExpireTime,
-                int64_t aModificationTime);
+  static void UpdateDB(OperationType aOp, mozIStorageAsyncStatement* aStmt,
+                       int64_t aID, const nsACString& aOrigin,
+                       const nsACString& aType, uint32_t aPermission,
+                       uint32_t aExpireType, int64_t aExpireTime,
+                       int64_t aModificationTime);
 
   /**
    * This method removes all permissions modified after the specified time.
    */
   nsresult RemoveAllModifiedSince(int64_t aModificationTime);
 
   template <class T>
   nsresult RemovePermissionEntries(T aCondition);
 
-  // This method must be called before doing any operation to be sure that the
-  // DB reading has been completed. This method is also in charge to complete
-  // the migrations if needed.
-  void EnsureReadCompleted();
-
-  nsresult AddInternal(nsIPrincipal* aPrincipal, const nsACString& aType,
-                       uint32_t aPermission, int64_t aID, uint32_t aExpireType,
-                       int64_t aExpireTime, int64_t aModificationTime,
-                       NotifyOperationType aNotifyOperation,
-                       DBOperationType aDBOperation,
-                       const bool aIgnoreSessionPermissions = false,
-                       const nsACString* aOriginString = nullptr);
-
-  void MaybeAddReadEntryFromMigration(const nsACString& aOrigin,
-                                      const nsCString& aType,
-                                      uint32_t aPermission,
-                                      uint32_t aExpireType, int64_t aExpireTime,
-                                      int64_t aModificationTime, int64_t aId);
-
-  nsRefPtrHashtable<nsCStringHashKey, GenericNonExclusivePromise::Private>
+  nsRefPtrHashtable<nsCStringHashKey,
+                    mozilla::GenericNonExclusivePromise::Private>
       mPermissionKeyPromiseMap;
 
-  nsCOMPtr<nsIFile> mPermissionsFile;
-
-  // This monitor is used to ensure the database reading before any other
-  // operation. The reading of the database happens OMT. See |State| to know the
-  // steps of the database reading.
-  Monitor mMonitor;
-
-  enum State {
-    // Initial state. The database has not been read yet.
-    // |TryInitDB| is called at startup time to read the database OMT.
-    // During the reading, |mReadEntries| will be populated with all the
-    // existing permissions.
-    eInitializing,
-
-    // At the end of the database reading, we are in this state. A runnable is
-    // executed to call |EnsureReadCompleted| on the main thread.
-    // |EnsureReadCompleted| processes |mReadEntries| and goes to the next
-    // state.
-    eDBInitialized,
-
-    // The permissions are fully read and any pending operation can proceed.
-    eReady,
-
-    // The permission manager has been terminated. No extra database operations
-    // will be allowed.
-    eClosed,
-  };
-  Atomic<State> mState;
-
-  // A single entry, from the database.
-  struct ReadEntry {
-    ReadEntry()
-        : mId(0),
-          mPermission(0),
-          mExpireType(0),
-          mExpireTime(0),
-          mModificationTime(0) {}
-
-    nsCString mOrigin;
-    nsCString mType;
-    int64_t mId;
-    uint32_t mPermission;
-    uint32_t mExpireType;
-    int64_t mExpireTime;
-    int64_t mModificationTime;
-
-    // true if this entry is the result of a migration.
-    bool mFromMigration;
-  };
-
-  // List of entries read from the database. It will be populated OMT and
-  // consumed on the main-thread.
-  // This array is protected by the monitor.
-  nsTArray<ReadEntry> mReadEntries;
-
-  // A single entry, from the database.
-  struct MigrationEntry {
-    MigrationEntry()
-        : mId(0),
-          mPermission(0),
-          mExpireType(0),
-          mExpireTime(0),
-          mModificationTime(0),
-          mIsInBrowserElement(false) {}
-
-    nsCString mHost;
-    nsCString mType;
-    int64_t mId;
-    uint32_t mPermission;
-    uint32_t mExpireType;
-    int64_t mExpireTime;
-    int64_t mModificationTime;
-
-    // Legacy, for migration.
-    bool mIsInBrowserElement;
-  };
-
-  // List of entries read from the database. It will be populated OMT and
-  // consumed on the main-thread. The migration entries will be converted to
-  // ReadEntry in |CompleteMigrations|.
-  // This array is protected by the monitor.
-  nsTArray<MigrationEntry> mMigrationEntries;
-
-  // A single entry from the defaults URL.
-  struct DefaultEntry {
-    DefaultEntry() : mOp(eImportMatchTypeHost), mPermission(0) {}
-
-    enum Op {
-      eImportMatchTypeHost,
-      eImportMatchTypeOrigin,
-    };
-
-    Op mOp;
-
-    nsCString mHostOrOrigin;
-    nsCString mType;
-    uint32_t mPermission;
-  };
-
-  // List of entries read from the default settings.
-  // This array is protected by the monitor.
-  nsTArray<DefaultEntry> mDefaultEntries;
-
-  nsresult Read(const MonitorAutoLock& aProofOfLock);
-  void CompleteRead();
-
-  void CompleteMigrations();
+  nsCOMPtr<mozIStorageConnection> mDBConn;
+  nsCOMPtr<mozIStorageAsyncStatement> mStmtInsert;
+  nsCOMPtr<mozIStorageAsyncStatement> mStmtDelete;
+  nsCOMPtr<mozIStorageAsyncStatement> mStmtUpdate;
 
   bool mMemoryOnlyDB;
 
   nsTHashtable<PermissionHashKey> mPermissionTable;
   // a unique, monotonically increasing id used to identify each database entry
   int64_t mLargestID;
 
   nsCOMPtr<nsIPrefBranch> mDefaultPrefBranch;
 
   // NOTE: Ensure this is the last member since it has a large inline buffer.
   // An array to store the strings identifying the different types.
-  Vector<nsCString, 512> mTypeArray;
-
-  nsCOMPtr<nsIThread> mThread;
-
-  struct ThreadBoundData {
-    nsCOMPtr<mozIStorageConnection> mDBConn;
-
-    nsCOMPtr<mozIStorageStatement> mStmtInsert;
-    nsCOMPtr<mozIStorageStatement> mStmtDelete;
-    nsCOMPtr<mozIStorageStatement> mStmtUpdate;
-  };
-  ThreadBound<ThreadBoundData> mThreadBoundData;
+  mozilla::Vector<nsCString, 512> mTypeArray;
 
   friend class DeleteFromMozHostListener;
   friend class CloseDatabaseListener;
 };
 
 // {4F6B5E00-0C36-11d5-A535-0010A401EB10}
 #define NS_PERMISSIONMANAGER_CID                   \
   {                                                \
     0x4f6b5e00, 0xc36, 0x11d5, {                   \
       0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 \
     }                                              \
   }
 
-}  // namespace mozilla
-
-#endif  // mozilla_PermissionManager_h
+#endif /* nsPermissionManager_h__ */
--- a/extensions/permissions/test/browser.ini
+++ b/extensions/permissions/test/browser.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
 
 [browser_permmgr_sync.js]
 fail-if = fission
 # The browser_permmgr_sync test tests e10s specific behavior, and runs code
 # paths which would hit the debug only assertion in
-# PermissionManager::PermissionKey::CreateFromPrincipal. Because of this, it
+# nsPermissionManager::PermissionKey::CreateFromPrincipal. Because of this, it
 # is only run in e10s opt builds.
 skip-if = debug || !e10s
 [browser_permmgr_viewsrc.js]
--- a/extensions/permissions/test/gtest/PermissionManagerTest.cpp
+++ b/extensions/permissions/test/gtest/PermissionManagerTest.cpp
@@ -1,31 +1,31 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "nsNetUtil.h"
+#include "nsPermissionManager.h"
 #include "mozilla/OriginAttributes.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Unused.h"
 #include "gtest/gtest.h"
 #include "gtest/MozGTestBench.h"
 
 using namespace mozilla;
 
-class PermissionManagerTester : public ::testing::Test {
+class PermissionManager : public ::testing::Test {
  protected:
-  PermissionManagerTester()
+  PermissionManager()
       : mNonExistentType(
             NS_LITERAL_CSTRING("permissionTypeThatIsGuaranteedToNeverExist")) {}
   void SetUp() override {
-    mPermissionManager = PermissionManager::GetInstance();
+    mPermissionManager = nsPermissionManager::GetInstance();
     nsCOMPtr<nsIURI> uri;
     nsresult rv = NS_NewURI(
         getter_AddRefs(uri),
         NS_LITERAL_CSTRING("https://test.origin.with.subdomains.example.com"));
     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
     mPrincipal =
         mozilla::BasePrincipal::CreateContentPrincipal(uri, OriginAttributes());
   }
@@ -33,20 +33,20 @@ class PermissionManagerTester : public :
   void TearDown() override {
     mPermissionManager = nullptr;
     mPrincipal = nullptr;
   }
 
   static const unsigned kNumIterations = 100000;
 
   nsLiteralCString mNonExistentType;
-  RefPtr<PermissionManager> mPermissionManager;
+  RefPtr<nsPermissionManager> mPermissionManager;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
-MOZ_GTEST_BENCH_F(PermissionManagerTester,
-                  TestNonExistentPermissionFromPrincipal, [this] {
+MOZ_GTEST_BENCH_F(PermissionManager, TestNonExistentPermissionFromPrincipal,
+                  [this] {
                     for (unsigned i = 0; i < kNumIterations; ++i) {
                       uint32_t result = 0;
                       Unused << mPermissionManager->TestPermissionFromPrincipal(
                           mPrincipal, mNonExistentType, &result);
                     }
                   });
--- a/extensions/permissions/test/gtest/moz.build
+++ b/extensions/permissions/test/gtest/moz.build
@@ -3,10 +3,14 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'PermissionManagerTest.cpp',
 ]
 
+LOCAL_INCLUDES += [
+    '/extensions/permissions',
+]
+
 FINAL_LIBRARY = 'xul-gtest'
 
--- a/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
+++ b/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
@@ -218,33 +218,27 @@ function run_test() {
   }
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
   // Initialize the permission manager service
   var pm = Services.perms;
 
-  // Let's do something in order to be sure the DB is read.
-  Assert.greater(pm.all.length, 0);
-
   // The schema should be upgraded to 11, and a 'modificationTime' column should
   // exist with all records having a value of 0.
   Assert.equal(connection.schemaVersion, 11);
 
   let select = connection.createStatement(
     "SELECT modificationTime FROM moz_perms"
   );
   let numMigrated = 0;
   while (select.executeStep()) {
     let thisModTime = select.getInt64(0);
-    Assert.ok(
-      thisModTime > 0,
-      "new modifiedTime field is correct (but it's not 0!)"
-    );
+    Assert.ok(thisModTime == 0, "new modifiedTime field is correct");
     numMigrated += 1;
   }
   // check we found at least 1 record that was migrated.
   Assert.greater(
     numMigrated,
     0,
     "we found at least 1 record that was migrated"
   );
--- a/extensions/permissions/test/unit/test_permmanager_migrate_10-11.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_10-11.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 10;
 
   let stmt6Insert = db.createStatement(
     "INSERT INTO moz_perms (" +
       "id, origin, type, permission, expireType, expireTime, modificationTime" +
       ") VALUES (" +
       ":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
@@ -121,17 +116,17 @@ add_task(async function test() {
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
   await PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080"));
   await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080"));
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_4-7.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_4-7.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 4;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   db.executeSimpleSQL(
     "CREATE TABLE moz_hosts (" +
       " id INTEGER PRIMARY KEY" +
@@ -195,17 +190,17 @@ add_task(async function test() {
   );
   await PlacesTestUtils.addVisits(
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_4-7_no_history.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_4-7_no_history.js
@@ -207,17 +207,17 @@ add_task(function test() {
     ["https://263.123.555.676", "A", 1, 0, 0],
   ];
 
   let found = expected.map(it => 0);
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_5-7a.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_5-7a.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 5;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   /*
    * V5 table
    */
@@ -262,17 +257,17 @@ add_task(async function test() {
   );
   await PlacesTestUtils.addVisits(
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
@@ -15,19 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 5;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   /*
    * V5 table
    */
@@ -114,17 +111,17 @@ add_task(function test() {
     ["http://localhost", "B", 2, 0, 0, 0],
   ];
 
   let found = expected.map(it => 0);
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_6-7a.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_6-7a.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 6;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   /*
    * V5 table
    */
@@ -263,17 +258,17 @@ add_task(async function test() {
   );
   await PlacesTestUtils.addVisits(
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 6;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   /*
    * V5 table
    */
@@ -110,17 +105,17 @@ add_task(function test() {
     ["http://foo.com^inBrowser=1", "A", 2, 0, 0, 0],
   ];
 
   let found = expected.map(it => 0);
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_7-8.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_7-8.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 7;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE moz_hosts");
 
   /*
    * V5 table
    */
@@ -250,17 +245,17 @@ add_task(async function test() {
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
   await PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080"));
   await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080"));
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_migrate_9-10.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_9-10.js
@@ -15,21 +15,16 @@ function GetPermissionsFile(profile) {
   return file;
 }
 
 add_task(async function test() {
   /* Create and set up the permissions database */
   let profile = do_get_profile();
   Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
-  var pm = Services.perms;
-  pm.removeAll();
-
   let db = Services.storage.openDatabase(GetPermissionsFile(profile));
   db.schemaVersion = 9;
   db.executeSimpleSQL("DROP TABLE moz_perms");
   db.executeSimpleSQL("DROP TABLE IF EXISTS moz_hosts");
 
   db.executeSimpleSQL(
     "CREATE TABLE moz_perms (" +
       " id INTEGER PRIMARY KEY" +
@@ -187,17 +182,17 @@ add_task(async function test() {
     Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory")
   );
   await PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080"));
   await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080"));
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
-  // Force initialization of the PermissionManager
+  // Force initialization of the nsPermissionManager
   for (let permission of Services.perms.all) {
     let isExpected = false;
 
     expected.forEach((it, i) => {
       if (
         permission.principal.origin == it[0] &&
         permission.type == it[1] &&
         permission.capability == it[2] &&
--- a/extensions/permissions/test/unit/test_permmanager_oa_strip.js
+++ b/extensions/permissions/test/unit/test_permmanager_oa_strip.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_URI = Services.io.newURI("http://example.com");
 const TEST_PERMISSION = "test/oastrip";
 const TEST_PERMISSION2 = "test/oastrip2";
 const TEST_PERMISSION3 = "test/oastrip3";
 
 // List of permissions which are not isolated by private browsing or user context
-// as per array kStripOAPermissions in PermissionManager.cpp
+// as per array kStripOAPermissions in nsPermissionManager.cpp
 const STRIPPED_PERMS = ["cookie"];
 
 let principal = Services.scriptSecurityManager.createContentPrincipal(
   TEST_URI,
   {}
 );
 let principalPrivateBrowsing = Services.scriptSecurityManager.createContentPrincipal(
   TEST_URI,
--- a/extensions/permissions/test/unit/test_permmanager_removeall.js
+++ b/extensions/permissions/test/unit/test_permmanager_removeall.js
@@ -1,26 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-add_task(async function test() {
+function run_test() {
   // setup a profile directory
   var dir = do_get_profile();
 
-  // We need to execute a pm method to be sure that the DB is fully
-  // initialized.
+  // initialize the permission manager service
   var pm = Services.perms;
-  Assert.ok(pm.all.length === 0);
-
-  Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk");
 
   // get the db file
   var file = dir.clone();
   file.append("permissions.sqlite");
-
   Assert.ok(file.exists());
 
   // corrupt the file
   var ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
     Ci.nsIFileOutputStream
   );
   ostream.init(file, 0x02, 0o666, 0);
   var conv = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(
@@ -35,9 +30,9 @@ add_task(async function test() {
   // prepare an empty hostperm.1 file so that it can be used for importing
   var hostperm = dir.clone();
   hostperm.append("hostperm.1");
   ostream.init(hostperm, 0x02 | 0x08, 0o666, 0);
   ostream.close();
 
   // remove all should not throw
   pm.removeAll();
-});
+}
--- a/extensions/permissions/test/unit/test_permmanager_removebytypesince.js
+++ b/extensions/permissions/test/unit/test_permmanager_removebytypesince.js
@@ -24,17 +24,17 @@ add_task(async function test() {
   pm.addFromPrincipal(principal, "pear", 1);
   pm.addFromPrincipal(principal, "cucumber", 1);
 
   // sleep briefly, then record the time - we'll remove some permissions since then.
   await new Promise(resolve => do_timeout(20, resolve));
 
   let since = Date.now();
 
-  // *sob* - on Windows at least, the now recorded by PermissionManager.cpp
+  // *sob* - on Windows at least, the now recorded by nsPermissionManager.cpp
   // might be a couple of ms *earlier* than what JS sees.  So another sleep
   // to ensure our |since| is greater than the time of the permissions we
   // are now adding.  Sadly this means we'll never be able to test when since
   // exactly equals the modTime, but there you go...
   await new Promise(resolve => do_timeout(20, resolve));
 
   pm.addFromPrincipal(principal2, "apple", 2);
   pm.addFromPrincipal(principal2, "pear", 2);
--- a/extensions/permissions/test/unit/test_permmanager_removesince.js
+++ b/extensions/permissions/test/unit/test_permmanager_removesince.js
@@ -35,17 +35,17 @@ function* do_run_test() {
   pm.addFromPrincipal(principal1, "test/remove-since", 1);
 
   // sleep briefly, then record the time - we'll remove all since then.
   do_timeout(20, continue_test);
   yield;
 
   let since = Number(Date.now());
 
-  // *sob* - on Windows at least, the now recorded by PermissionManager.cpp
+  // *sob* - on Windows at least, the now recorded by nsPermissionManager.cpp
   // might be a couple of ms *earlier* than what JS sees.  So another sleep
   // to ensure our |since| is greater than the time of the permissions we
   // are now adding.  Sadly this means we'll never be able to test when since
   // exactly equals the modTime, but there you go...
   do_timeout(20, continue_test);
   yield;
 
   // add another item - this second one should get nuked.
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -43,16 +43,17 @@ LOCAL_INCLUDES += [
     '/dom/storage',
     '/dom/svg',
     '/dom/xslt/base',
     '/dom/xslt/xml',
     '/dom/xslt/xpath',
     '/dom/xslt/xslt',
     '/dom/xul',
     '/editor/composer',
+    '/extensions/permissions',
     '/js/xpconnect/loader',
     '/js/xpconnect/src',
     '/netwerk/base',
     '/netwerk/cookie',
     '/view',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -87,17 +87,17 @@
 #include "nsJSEnvironment.h"
 #include "nsContentSink.h"
 #include "nsFrameMessageManager.h"
 #include "nsDOMMutationObserver.h"
 #include "nsHyphenationManager.h"
 #include "nsWindowMemoryReporter.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ProcessPriorityManager.h"
-#include "mozilla/PermissionManager.h"
+#include "nsPermissionManager.h"
 #include "nsApplicationCacheService.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "ThirdPartyUtil.h"
 #include "TouchManager.h"
 #include "DecoderDoctorLogger.h"
@@ -241,17 +241,17 @@ nsresult nsLayoutStatics::Initialize() {
   TouchManager::InitializeStatics();
 
   nsWindowMemoryReporter::Init();
 
   SVGElementFactory::Init();
 
   ProcessPriorityManager::Init();
 
-  PermissionManager::Startup();
+  nsPermissionManager::Startup();
 
   UIDirectionManager::Initialize();
 
   CacheObserver::Init();
 
   IMEStateManager::Init();
 
   ServiceWorkerRegistrar::Initialize();
--- a/layout/tools/reftest/selftest/files/leaks.log
+++ b/layout/tools/reftest/selftest/files/leaks.log
@@ -53,17 +53,17 @@ 1141 |nsHttpHandler                     
 1142 |nsHttpRequestHead                     |       92       92|    1190        1|
 1145 |nsIDNService                          |       56       56|       1        1|
 1146 |nsIOService                           |      176      176|       1        1|
 1176 |nsJSPrincipals                        |       16       64|   12583        4|
 1186 |nsLocalFile                           |       88      264|   13423        3|
 1192 |nsMainThreadPtrHolder<T>              |       20       80|    2253        4|
 1222 |nsNodeWeakReference                   |       16       16|     919        1|
 1223 |nsNotifyAddrListener                  |      112      112|       1        1|
-1241 |PermissionManager                     |      136      136|       1        1|
+1241 |nsPermissionManager                   |      136      136|       1        1|
 1248 |nsPrefBranch                          |       76       76|      63        1|
 1257 |nsProxyInfo                           |       72       72|    1098        1|
 1265 |nsRedirectHistoryEntry                |       32       32|      69        1|
 1307 |nsSiteSecurityService                 |       56       56|       1        1|
 1311 |nsSocketTransportService              |      208      208|       1        1|
 1313 |nsStandardURL                         |      196     1372|   59651        7|
 1319 |nsStreamConverterService              |       48       48|       1        1|
 1324 |nsStringBuffer                        |        8     1688|  722245      211|
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -7702,22 +7702,22 @@
   mirror: always
 
 - name: permissions.delegation.enabled
   type: bool
   value: true
   mirror: always
 
 - name: permissions.isolateBy.userContext
-  type: RelaxedAtomicBool
+  type: bool
   value: false
   mirror: always
 
 - name: permissions.isolateBy.privateBrowsing
-  type: RelaxedAtomicBool
+  type: bool
   value: @IS_EARLY_BETA_OR_EARLIER@
   mirror: always
 
 #---------------------------------------------------------------------------
 # Prefs starting with "plain_text."
 #---------------------------------------------------------------------------
 
 # When false, text in plaintext documents does not wrap long lines.
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -317,16 +317,17 @@ DIRS += [ 'mozurl', 'rust-helper' ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
+    '/extensions/permissions',
     '/netwerk/protocol/http',
     '/netwerk/socket',
     '/netwerk/url-classifier',
     '/security/manager/ssl',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     LOCAL_INCLUDES += [
--- a/netwerk/cookie/CookieJarSettings.cpp
+++ b/netwerk/cookie/CookieJarSettings.cpp
@@ -5,27 +5,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/AntiTrackingUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/ContentBlockingAllowList.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/net/CookieJarSettings.h"
 #include "mozilla/net/NeckoChannelParams.h"
-#include "mozilla/Permission.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/SchedulerGroup.h"
 #include "mozilla/StaticPrefs_network.h"
 #include "mozilla/Unused.h"
 #include "nsGlobalWindowInner.h"
 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
 #  include "nsIProtocolHandler.h"
 #endif
+#include "nsPermission.h"
+#include "nsPermissionManager.h"
 #include "nsICookieService.h"
-#include "nsNetUtil.h"
 
 namespace mozilla {
 namespace net {
 
 static StaticRefPtr<CookieJarSettings> sBlockinAll;
 
 namespace {
 
@@ -181,17 +180,17 @@ CookieJarSettings::CookiePermission(nsIP
 
   *aCookiePermission = nsIPermissionManager::UNKNOWN_ACTION;
 
   nsresult rv;
 
   // Let's see if we know this permission.
   if (!mCookiePermissions.IsEmpty()) {
     nsCOMPtr<nsIPrincipal> principal =
-        Permission::ClonePrincipalForPermission(aPrincipal);
+        nsPermission::ClonePrincipalForPermission(aPrincipal);
     if (NS_WARN_IF(!principal)) {
       return NS_ERROR_FAILURE;
     }
 
     for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
       bool match = false;
       rv = permission->MatchesPrincipalForPermission(principal, false, &match);
       if (NS_WARN_IF(NS_FAILED(rv)) || !match) {
@@ -203,44 +202,44 @@ CookieJarSettings::CookiePermission(nsIP
         return rv;
       }
 
       return NS_OK;
     }
   }
 
   // Let's ask the permission manager.
-  PermissionManager* pm = PermissionManager::GetInstance();
+  nsPermissionManager* pm = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!pm)) {
     return NS_ERROR_FAILURE;
   }
 
 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
   // Check if this protocol doesn't allow cookies.
   bool hasFlags;
   nsCOMPtr<nsIURI> uri;
   aPrincipal->GetURI(getter_AddRefs(uri));
   rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_FORBIDS_COOKIE_ACCESS,
                            &hasFlags);
   if (NS_FAILED(rv) || hasFlags) {
-    *aCookiePermission = PermissionManager::DENY_ACTION;
+    *aCookiePermission = nsPermissionManager::DENY_ACTION;
     rv = NS_OK;  // Reset, so it's not caught as a bad status after the `else`.
   } else         // Note the tricky `else` which controls the call below.
 #endif
 
     rv = pm->TestPermissionFromPrincipal(
         aPrincipal, NS_LITERAL_CSTRING("cookie"), aCookiePermission);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Let's store the permission, also if the result is UNKNOWN in order to avoid
   // race conditions.
 
-  nsCOMPtr<nsIPermission> permission = Permission::Create(
+  nsCOMPtr<nsIPermission> permission = nsPermission::Create(
       aPrincipal, NS_LITERAL_CSTRING("cookie"), *aCookiePermission, 0, 0, 0);
   if (permission) {
     mCookiePermissions.AppendElement(permission);
   }
 
   mToBeMerged = true;
   return NS_OK;
 }
@@ -288,18 +287,18 @@ void CookieJarSettings::Serialize(Cookie
   for (const CookiePermissionData& data : aData.cookiePermissions()) {
     nsCOMPtr<nsIPrincipal> principal =
         PrincipalInfoToPrincipal(data.principalInfo());
     if (NS_WARN_IF(!principal)) {
       continue;
     }
 
     nsCOMPtr<nsIPermission> permission =
-        Permission::Create(principal, NS_LITERAL_CSTRING("cookie"),
-                           data.cookiePermission(), 0, 0, 0);
+        nsPermission::Create(principal, NS_LITERAL_CSTRING("cookie"),
+                             data.cookiePermission(), 0, 0, 0);
     if (NS_WARN_IF(!permission)) {
       continue;
     }
 
     list.AppendElement(permission);
   }
 
   RefPtr<CookieJarSettings> cookieJarSettings = new CookieJarSettings(
@@ -349,18 +348,18 @@ void CookieJarSettings::Merge(const Cook
   for (const CookiePermissionData& data : aData.cookiePermissions()) {
     nsCOMPtr<nsIPrincipal> principal =
         PrincipalInfoToPrincipal(data.principalInfo());
     if (NS_WARN_IF(!principal)) {
       continue;
     }
 
     nsCOMPtr<nsIPermission> permission =
-        Permission::Create(principal, NS_LITERAL_CSTRING("cookie"),
-                           data.cookiePermission(), 0, 0, 0);
+        nsPermission::Create(principal, NS_LITERAL_CSTRING("cookie"),
+                             data.cookiePermission(), 0, 0, 0);
     if (NS_WARN_IF(!permission)) {
       continue;
     }
 
     if (!mCookiePermissions.Contains(permission, comparator)) {
       mCookiePermissions.AppendElement(permission);
     }
   }
--- a/netwerk/cookie/CookiePermission.cpp
+++ b/netwerk/cookie/CookiePermission.cpp
@@ -43,21 +43,21 @@ already_AddRefed<nsICookiePermission> Co
   if (!gSingleton) {
     gSingleton = new CookiePermission();
     ClearOnShutdown(&gSingleton);
   }
   return do_AddRef(gSingleton);
 }
 
 bool CookiePermission::Init() {
-  // Initialize PermissionManager and fetch relevant prefs. This is only
+  // Initialize nsPermissionManager and fetch relevant prefs. This is only
   // required for some methods on nsICookiePermission, so it should be done
   // lazily.
 
-  mPermMgr = PermissionManager::GetInstance();
+  mPermMgr = nsPermissionManager::GetInstance();
   return mPermMgr != nullptr;
 }
 
 NS_IMETHODIMP
 CookiePermission::CanSetCookie(nsIURI* aURI, nsIChannel* /*aChannel*/,
                                nsICookie* aCookie, bool* aIsSession,
                                int64_t* aExpiry, bool* aResult) {
   NS_ASSERTION(aURI, "null uri");
--- a/netwerk/cookie/CookiePermission.h
+++ b/netwerk/cookie/CookiePermission.h
@@ -1,17 +1,17 @@
 /* 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/. */
 
 #ifndef mozilla_net_CookiePermission_h
 #define mozilla_net_CookiePermission_h
 
 #include "nsICookiePermission.h"
-#include "mozilla/PermissionManager.h"
+#include "nsPermissionManager.h"
 
 namespace mozilla {
 namespace net {
 
 class CookiePermission final : public nsICookiePermission {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOOKIEPERMISSION
@@ -21,15 +21,15 @@ class CookiePermission final : public ns
 
   bool Init();
 
  private:
   ~CookiePermission() = default;
 
   bool EnsureInitialized() { return (mPermMgr != nullptr) || Init(); };
 
-  RefPtr<mozilla::PermissionManager> mPermMgr;
+  RefPtr<nsPermissionManager> mPermMgr;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif
--- a/netwerk/cookie/moz.build
+++ b/netwerk/cookie/moz.build
@@ -56,16 +56,17 @@ MOCHITEST_MANIFESTS += [
 ]
 
 IPDL_SOURCES = [
     'PCookieService.ipdl',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
+    '/extensions/permissions',
     '/intl/uconv',
     '/netwerk/base',
     '/netwerk/protocol/http',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
@@ -17,17 +17,17 @@ const ACCESS_SESSION = SpecialPowers.Ci.
 
 const EXPIRE_TIME = SpecialPowers.Ci.nsIPermissionManager.EXPIRE_TIME;
 // expire Setting:
 //     start                 expire time point
 //   ----|------------------------|-----------
 //       <------------------------>
 //                 PERIOD
 var start;
-// PR_Now() that called in PermissionManager to get the system time
+// PR_Now() that called in nsPermissionManager to get the system time
 // is sometimes 100ms~600s more than Date.now() on Android 4.3 API11.
 // Thus, the PERIOD should be larger than 600ms in this test.
 const PERIOD = 900;
 var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('specialPowers_framescript.js'));
 SimpleTest.requestFlakyTimeout("untriaged");
 
 function starttest(){
   SpecialPowers.addPermission("pPROMPT", PROMPT_ACTION, document);
@@ -205,17 +205,17 @@ async function permissionPollingCheck() 
     errorHandler('expired permission should be removed!');
   }
 }
 
 function getPlatformInfo() {
   var version = SpecialPowers.Services.sysinfo.getProperty('version');
   version = parseFloat(version);
 
-  // PR_Now() that called in PermissionManager to get the system time and
+  // PR_Now() that called in nsPermissionManager to get the system time and
   // Date.now() are out of sync on win32 platform(XP/win7). The PR_Now() is
   // 15~20ms less than Date.now(). Unfortunately, this time skew can't be
   // avoided, so it needs to add a time buffer to compensate.
   // Version 5.1 is win XP, 6.1 is win7
   if (navigator.platform.startsWith('Win32') && (version <= 6.1)) {
     return { platform: "Win32", timeCompensation: -100 };
   }
 
--- a/testing/mozbase/mozprofile/mozprofile/permissions.py
+++ b/testing/mozbase/mozprofile/mozprofile/permissions.py
@@ -232,17 +232,17 @@ class Permissions(object):
     def write_db(self, locations):
         """write permissions to the sqlite database"""
 
         # Open database and create table
         permDB = sqlite3.connect(os.path.join(self._profileDir, "permissions.sqlite"))
         cursor = permDB.cursor()
 
         # SQL copied from
-        # http://dxr.mozilla.org/mozilla-central/source/extensions/permissions/PermissionManager.cpp
+        # http://dxr.mozilla.org/mozilla-central/source/extensions/cookie/nsPermissionManager.cpp
         cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
               id INTEGER PRIMARY KEY
              ,origin TEXT
              ,type TEXT
              ,permission INTEGER
              ,expireType INTEGER
              ,expireTime INTEGER
              ,modificationTime INTEGER
--- a/testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
+++ b/testing/web-platform/meta/fetch/metadata/redirect/__dir__.ini
@@ -1,3 +1,3 @@
 prefs: [dom.security.secFetch.enabled:true]
-lsan-allowed: [Alloc, Create, Malloc, Realloc, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::ContentPrincipal::Init, mozilla::dom::DocGroup::Create, mozilla::WeakPtr, mozilla::dom::HTMLLinkElement::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender, mozilla::net::CookieSettings::Create, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, mozilla::Permission::Create, nsPrefetchService::Preload]
+lsan-allowed: [Alloc, Create, Malloc, Realloc, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::ContentPrincipal::Init, mozilla::dom::DocGroup::Create, mozilla::WeakPtr, mozilla::dom::HTMLLinkElement::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender, mozilla::net::CookieSettings::Create, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsPermission::Create, nsPrefetchService::Preload]
 leak-threshold: [tab:51200]
--- a/toolkit/components/antitracking/AntiTrackingUtils.cpp
+++ b/toolkit/components/antitracking/AntiTrackingUtils.cpp
@@ -8,21 +8,21 @@
 
 #include "AntiTrackingLog.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/net/CookieJarSettings.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/dom/WindowContext.h"
 #include "mozilla/net/NeckoChannelParams.h"
-#include "mozilla/PermissionManager.h"
 #include "nsIChannel.h"
 #include "nsIPermission.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
+#include "nsPermissionManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsSandboxFlags.h"
 #include "nsScriptSecurityManager.h"
 
 #define ANTITRACKING_PERM_KEY "3rdPartyStorage"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -133,17 +133,17 @@ bool AntiTrackingUtils::IsStorageAccessP
 }
 
 // static
 bool AntiTrackingUtils::CheckStoragePermission(nsIPrincipal* aPrincipal,
                                                const nsAutoCString& aType,
                                                bool aIsInPrivateBrowsing,
                                                uint32_t* aRejectedReason,
                                                uint32_t aBlockedReason) {
-  PermissionManager* permManager = PermissionManager::GetInstance();
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!permManager)) {
     LOG(("Failed to obtain the permission manager"));
     return false;
   }
 
   uint32_t result = 0;
   if (aIsInPrivateBrowsing) {
     LOG_PRIN(("Querying the permissions for private modei looking for a "
--- a/toolkit/components/antitracking/ContentBlocking.cpp
+++ b/toolkit/components/antitracking/ContentBlocking.cpp
@@ -11,29 +11,29 @@
 
 #include "mozilla/ContentBlockingAllowList.h"
 #include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/WindowContext.h"
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/net/CookieJarSettings.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/StaticPrefs_privacy.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindowInner.h"
 #include "nsIClassifiedChannel.h"
 #include "nsICookiePermission.h"
 #include "nsICookieService.h"
 #include "nsIPermission.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsIOService.h"
 #include "nsIWebProgressListener.h"
+#include "nsPermissionManager.h"
 #include "nsScriptSecurityManager.h"
 
 namespace mozilla {
 
 LazyLogModule gAntiTrackingLog("AntiTracking");
 
 }
 
@@ -495,17 +495,17 @@ ContentBlocking::SaveAccessForOriginOnPa
            aParentPrincipal);
 
   if (NS_WARN_IF(!aParentPrincipal)) {
     // The child process is sending something wrong. Let's ignore it.
     LOG(("aParentPrincipal is null, bailing out early"));
     return ParentAccessGrantPromise::CreateAndReject(false, __func__);
   }
 
-  PermissionManager* permManager = PermissionManager::GetInstance();
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!permManager)) {
     LOG(("Permission manager is null, bailing out early"));
     return ParentAccessGrantPromise::CreateAndReject(false, __func__);
   }
 
   // Remember that this pref is stored in seconds!
   uint32_t expirationType = nsIPermissionManager::EXPIRE_TIME;
   uint32_t expirationTime = aExpirationTime * 1000;
@@ -1023,17 +1023,17 @@ bool ContentBlocking::ShouldAllowAccessF
 
 bool ContentBlocking::ShouldAllowAccessFor(
     nsIPrincipal* aPrincipal, nsICookieJarSettings* aCookieJarSettings) {
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aCookieJarSettings);
 
   uint32_t access = nsICookiePermission::ACCESS_DEFAULT;
   if (aPrincipal->GetIsContentPrincipal()) {
-    PermissionManager* permManager = PermissionManager::GetInstance();
+    nsPermissionManager* permManager = nsPermissionManager::GetInstance();
     if (permManager) {
       Unused << NS_WARN_IF(NS_FAILED(permManager->TestPermissionFromPrincipal(
           aPrincipal, NS_LITERAL_CSTRING("cookie"), &access)));
     }
   }
 
   if (access != nsICookiePermission::ACCESS_DEFAULT) {
     return access != nsICookiePermission::ACCESS_DENY;
--- a/toolkit/components/antitracking/ContentBlockingAllowList.cpp
+++ b/toolkit/components/antitracking/ContentBlockingAllowList.cpp
@@ -4,20 +4,20 @@
  * 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/. */
 
 #include "AntiTrackingLog.h"
 #include "ContentBlockingAllowList.h"
 
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/Document.h"
-#include "mozilla/PermissionManager.h"
 #include "mozilla/ScopeExit.h"
 #include "nsContentUtils.h"
 #include "nsIHttpChannelInternal.h"
+#include "nsPermissionManager.h"
 
 using namespace mozilla;
 
 /* static */ bool ContentBlockingAllowList::Check(
     nsIPrincipal* aTopWinPrincipal, bool aIsPrivateBrowsing) {
   bool isAllowed = false;
   nsresult rv = Check(aTopWinPrincipal, aIsPrivateBrowsing, isAllowed);
   if (NS_SUCCEEDED(rv) && isAllowed) {
@@ -92,17 +92,17 @@ nsresult ContentBlockingAllowList::Check
     // Nothing to do!
     return NS_OK;
   }
 
   LOG_PRIN(("Deciding whether the user has overridden content blocking for %s",
             _spec),
            aContentBlockingAllowListPrincipal);
 
-  PermissionManager* permManager = PermissionManager::GetInstance();
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   NS_ENSURE_TRUE(permManager, NS_ERROR_FAILURE);
 
   // Check both the normal mode and private browsing mode user override
   // permissions.
   std::pair<const nsLiteralCString, bool> types[] = {
       {NS_LITERAL_CSTRING("trackingprotection"), false},
       {NS_LITERAL_CSTRING("trackingprotection-pb"), true}};
 
--- a/toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
+++ b/toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
@@ -4,34 +4,34 @@
  * 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/. */
 
 #include "AntiTrackingLog.h"
 #include "ContentBlockingUserInteraction.h"
 #include "AntiTrackingUtils.h"
 
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/PermissionManager.h"
 #include "nsIPrincipal.h"
+#include "nsPermissionManager.h"
 #include "nsXULAppAPI.h"
 #include "prtime.h"
 
 namespace mozilla {
 
 /* static */
 void ContentBlockingUserInteraction::Observe(nsIPrincipal* aPrincipal) {
   if (!aPrincipal) {
     // The content process may have sent us garbage data.
     return;
   }
 
   if (XRE_IsParentProcess()) {
     LOG_PRIN(("Saving the userInteraction for %s", _spec), aPrincipal);
 
-    PermissionManager* permManager = PermissionManager::GetInstance();
+    nsPermissionManager* permManager = nsPermissionManager::GetInstance();
     if (NS_WARN_IF(!permManager)) {
       LOG(("Permission manager is null, bailing out early"));
       return;
     }
 
     // Remember that this pref is stored in seconds!
     uint32_t expirationType = nsIPermissionManager::EXPIRE_TIME;
     uint32_t expirationTime =
@@ -60,17 +60,17 @@ void ContentBlockingUserInteraction::Obs
   LOG_PRIN(("Asking the parent process to save the user-interaction for us: %s",
             _spec),
            aPrincipal);
   cc->SendStoreUserInteractionAsPermission(IPC::Principal(aPrincipal));
 }
 
 /* static */
 bool ContentBlockingUserInteraction::Exists(nsIPrincipal* aPrincipal) {
-  PermissionManager* permManager = PermissionManager::GetInstance();
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!permManager)) {
     return false;
   }
 
   uint32_t result = 0;
   nsresult rv = permManager->TestPermissionWithoutDefaultsFromPrincipal(
       aPrincipal, USER_INTERACTION_PERM, &result);
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
+++ b/toolkit/components/antitracking/TemporaryAccessGrantObserver.cpp
@@ -1,38 +1,38 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "TemporaryAccessGrantObserver.h"
 
-#include "mozilla/PermissionManager.h"
 #include "nsIObserverService.h"
+#include "nsPermissionManager.h"
 #include "nsTHashtable.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
 
 UniquePtr<TemporaryAccessGrantObserver::ObserversTable>
     TemporaryAccessGrantObserver::sObservers;
 
 TemporaryAccessGrantObserver::TemporaryAccessGrantObserver(
-    PermissionManager* aPM, nsIPrincipal* aPrincipal, const nsACString& aType)
+    nsPermissionManager* aPM, nsIPrincipal* aPrincipal, const nsACString& aType)
     : mPM(aPM), mPrincipal(aPrincipal), mType(aType) {
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Enforcing temporary access grant lifetimes can only be done in "
              "the parent process");
 }
 
 NS_IMPL_ISUPPORTS(TemporaryAccessGrantObserver, nsIObserver)
 
 // static
-void TemporaryAccessGrantObserver::Create(PermissionManager* aPM,
+void TemporaryAccessGrantObserver::Create(nsPermissionManager* aPM,
                                           nsIPrincipal* aPrincipal,
                                           const nsACString& aType) {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (!sObservers) {
     sObservers = MakeUnique<ObserversTable>();
   }
   Unused << sObservers
--- a/toolkit/components/antitracking/TemporaryAccessGrantObserver.h
+++ b/toolkit/components/antitracking/TemporaryAccessGrantObserver.h
@@ -12,22 +12,21 @@
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 #include "PLDHashTable.h"
 
 template <class, class>
 class nsDataHashtable;
 class nsITimer;
+class nsPermissionManager;
 class TemporaryAccessGrantCacheKey;
 
 namespace mozilla {
 
-class PermissionManager;
-
 class TemporaryAccessGrantCacheKey : public PLDHashEntryHdr {
  public:
   typedef std::pair<nsCOMPtr<nsIPrincipal>, nsCString> KeyType;
   typedef const KeyType* KeyTypePointer;
 
   explicit TemporaryAccessGrantCacheKey(KeyTypePointer aKey)
       : mPrincipal(aKey->first), mType(aKey->second) {}
   TemporaryAccessGrantCacheKey(TemporaryAccessGrantCacheKey&& aOther) = default;
@@ -58,31 +57,32 @@ class TemporaryAccessGrantCacheKey : pub
   nsCString mType;
 };
 
 class TemporaryAccessGrantObserver final : public nsIObserver {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
-  static void Create(PermissionManager* aPM, nsIPrincipal* aPrincipal,
+  static void Create(nsPermissionManager* aPM, nsIPrincipal* aPrincipal,
                      const nsACString& aType);
 
   void SetTimer(nsITimer* aTimer);
 
  private:
-  TemporaryAccessGrantObserver(PermissionManager* aPM, nsIPrincipal* aPrincipal,
+  TemporaryAccessGrantObserver(nsPermissionManager* aPM,
+                               nsIPrincipal* aPrincipal,
                                const nsACString& aType);
   ~TemporaryAccessGrantObserver() = default;
 
  private:
   typedef nsDataHashtable<TemporaryAccessGrantCacheKey, nsCOMPtr<nsITimer>>
       ObserversTable;
   static UniquePtr<ObserversTable> sObservers;
   nsCOMPtr<nsITimer> mTimer;
-  RefPtr<PermissionManager> mPM;
+  RefPtr<nsPermissionManager> mPM;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCString mType;
 };
 
 }  // namespace mozilla
 
 #endif  // mozilla_temporaryaccessgrantobserver_h
--- a/toolkit/components/antitracking/moz.build
+++ b/toolkit/components/antitracking/moz.build
@@ -57,16 +57,17 @@ UNIFIED_SOURCES += [
     'SettingsChangeObserver.cpp',
     'StorageAccess.cpp',
     'StoragePrincipalHelper.cpp',
     'TemporaryAccessGrantObserver.cpp',
     'URLDecorationStripper.cpp',
 ]
 
 LOCAL_INCLUDES += [
+    '/extensions/permissions',
     '/netwerk/base',
     '/netwerk/protocol/http',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'