From 8c75b7c054a49d63ff27c91c824092f1802608b4 Mon Sep 17 00:00:00 2001 From: Sandor Molnar Date: Wed, 13 Nov 2024 18:22:41 +0200 Subject: [PATCH] Backed out 8 changesets (bug 1919558, bug 1816449) for causing mochitest failures @ test_refresh_firefox.py Backed out changeset a194f41588e9 (bug 1816449) Backed out changeset 10643d7c7a78 (bug 1919558) Backed out changeset b346a2a2bfdc (bug 1919558) Backed out changeset 507f18e7103d (bug 1919558) Backed out changeset 4d0d9f72bc2a (bug 1919558) Backed out changeset 65d9270f0991 (bug 1919558) Backed out changeset fe95b9e6ff13 (bug 1919558) Backed out changeset ea6ffcb0e334 (bug 1919558) --- extensions/permissions/PermissionManager.cpp | 340 +++++-------- extensions/permissions/PermissionManager.h | 31 +- .../RemotePermissionService.sys.mjs | 191 ------- extensions/permissions/components.conf | 8 - extensions/permissions/moz.build | 10 - .../nsIRemotePermissionService.idl | 41 -- .../test/unit/test_permmanager_remote.js | 480 ------------------ .../permissions/test/unit/xpcshell.toml | 2 - modules/libpref/init/StaticPrefList.yaml | 7 - netwerk/base/nsIPermissionManager.idl | 14 - .../dumps/main/remote-permissions.json | 4 - 11 files changed, 139 insertions(+), 989 deletions(-) delete mode 100644 extensions/permissions/RemotePermissionService.sys.mjs delete mode 100644 extensions/permissions/nsIRemotePermissionService.idl delete mode 100644 extensions/permissions/test/unit/test_permmanager_remote.js delete mode 100644 services/settings/dumps/main/remote-permissions.json diff --git a/extensions/permissions/PermissionManager.cpp b/extensions/permissions/PermissionManager.cpp index 5a38bb50e88c..80c7fefbffbe 100644 --- a/extensions/permissions/PermissionManager.cpp +++ b/extensions/permissions/PermissionManager.cpp @@ -6,9 +6,6 @@ #include "mozilla/AbstractThread.h" #include "mozilla/AppShutdown.h" -#ifdef MOZ_BACKGROUNDTASKS -# include "mozilla/BackgroundTasks.h" -#endif #include "mozilla/BasePrincipal.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/ContentPrincipal.h" @@ -406,10 +403,8 @@ nsresult UpgradeHostToOriginAndInsert( // subdomain of this host), and try to add it as a principal. bool foundHistory = false; - nsCOMPtr histSrv = nullptr; - if (NS_IsMainThread()) { - histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); - } + nsCOMPtr histSrv = + do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); if (histSrv) { nsCOMPtr histQuery; @@ -1709,68 +1704,6 @@ PermissionManager::AddFromPrincipalAndPersistInPrivateBrowsing( /* aAllowPersistInPrivateBrowsing */ true); } -NS_IMETHODIMP -PermissionManager::AddDefaultFromPrincipal(nsIPrincipal* aPrincipal, - const nsACString& aType, - uint32_t aPermission) { - ENSURE_NOT_CHILD_PROCESS; - MOZ_ASSERT(mState == eReady); - - bool isValidPermissionPrincipal = false; - nsresult rv = ShouldHandlePrincipalForPermission(aPrincipal, - isValidPermissionPrincipal); - NS_ENSURE_SUCCESS(rv, rv); - if (!isValidPermissionPrincipal) { - // return early if the principal is invalid for permissions - return rv; - } - - nsCString origin; - rv = GetOriginFromPrincipal(aPrincipal, IsOAForceStripPermission(aType), - origin); - NS_ENSURE_SUCCESS(rv, rv); - - DefaultEntry entry; - { - // Lock for mDefaultEntriesForImport - MonitorAutoLock lock(mMonitor); - - // Try to update existing entry in mDefaultEntriesForImport, which will - // later be used to restore the default permissions when permissions are - // cleared - bool updatedExistingEntry = false; - nsTArray::iterator defaultEntry = - mDefaultEntriesForImport.begin(); - while (defaultEntry != mDefaultEntriesForImport.end()) { - if (defaultEntry->mType == aType && defaultEntry->mOrigin == origin) { - defaultEntry->mPermission = aPermission; - entry = *defaultEntry; - if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) { - mDefaultEntriesForImport.RemoveElementAt(defaultEntry); - } - updatedExistingEntry = true; - break; - } - ++defaultEntry; - } - - // Or add a new entry if there wasn't already one and we aren't deleting the - // default permission - if (!updatedExistingEntry) { - entry.mOrigin = origin; - entry.mPermission = aPermission; - entry.mType = aType; - if (aPermission != nsIPermissionManager::UNKNOWN_ACTION) { - mDefaultEntriesForImport.AppendElement(entry); - } - } - } - - // So far, we have only updated mDefaultEntriesForImport for later recovery. - // Now, we actually need to import this change into the permission manager. - return ImportDefaultEntry(entry); -} - NS_IMETHODIMP PermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal, const nsACString& aType, @@ -1836,9 +1769,6 @@ nsresult PermissionManager::AddInternal( const bool aAllowPersistInPrivateBrowsing) { MOZ_ASSERT(NS_IsMainThread()); - // If this is a default permission, no changes should not be written to disk. - MOZ_ASSERT((aID != cIDPermissionIsDefault) || (aDBOperation != eWriteToDB)); - EnsureReadCompleted(); nsresult rv = NS_OK; @@ -1949,26 +1879,23 @@ nsresult PermissionManager::AddInternal( if (aPermission == oldPermissionEntry.mPermission && aExpireType == oldPermissionEntry.mExpireType && (aExpireType == nsIPermissionManager::EXPIRE_NEVER || - aExpireTime == oldPermissionEntry.mExpireTime)) { + aExpireTime == oldPermissionEntry.mExpireTime)) op = eOperationNone; - } else if (oldPermissionEntry.mID == cIDPermissionIsDefault && - aID != cIDPermissionIsDefault) { - // An existing default permission already exists, but the new permission - // isn't a default permission. This case requires some special handing. + else if (oldPermissionEntry.mID == cIDPermissionIsDefault) + // The existing permission is one added as a default and the new + // permission doesn't exactly match so we are replacing the default. This + // is true even if the new permission is UNKNOWN_ACTION (which means a + // "logical remove" of the default) op = eOperationReplacingDefault; - } else if (oldPermissionEntry.mID != cIDPermissionIsDefault && - aID == cIDPermissionIsDefault) { + else if (aID == cIDPermissionIsDefault) // We are adding a default permission but a "real" permission already - // exists. This means we don't have to do anything here. + // exists. This almost-certainly means we just did a removeAllSince and + // are re-importing defaults - so we can ignore this. op = eOperationNone; - } else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) { - // At this point, both the old and new permission are either both default - // permissions, or both not default permissions. Now we only need to check - // wether to change or remove the old permission. + else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) op = eOperationRemoving; - } else { + else op = eOperationChanging; - } } // child processes should *always* be passed a modificationTime of zero. @@ -2046,20 +1973,6 @@ nsresult PermissionManager::AddInternal( mPermissionTable.RemoveEntry(entry); } - // If the entry we are removing is not a default, restore the potential - // default entry in-memory - if (oldPermissionEntry.mID != cIDPermissionIsDefault) { - for (const DefaultEntry& defaultEntry : mDefaultEntriesForImport) { - if (defaultEntry.mType == aType && defaultEntry.mOrigin == origin && - defaultEntry.mPermission != - nsIPermissionManager::UNKNOWN_ACTION) { - rv = ImportDefaultEntry(defaultEntry); - NS_ENSURE_SUCCESS(rv, rv); - break; - } - } - } - break; } @@ -2290,6 +2203,9 @@ nsresult PermissionManager::RemovePermissionEntries(T aCondition) { PermissionManager::eWriteToDB, false, &std::get<2>(i)); } + // now re-import any defaults as they may now be required if we just deleted + // an override. + ImportLatestDefaults(); return NS_OK; } @@ -2798,13 +2714,10 @@ NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject, const char16_t* someData) { ENSURE_NOT_CHILD_PROCESS; - if (!nsCRT::strcmp(aTopic, "profile-do-change")) { - if (!mPermissionsFile) { - // profile startup is complete, and we didn't have the permissions file - // before; init the db from the new location - InitDB(false); - } - InitRemotePermissionService(); + if (!nsCRT::strcmp(aTopic, "profile-do-change") && !mPermissionsFile) { + // profile startup is complete, and we didn't have the permissions file + // before; 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 @@ -2816,7 +2729,6 @@ NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject, RemoveAllFromMemory(); CloseDB(eNone); InitDB(false); - InitRemotePermissionService(); } else if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY)) { PerformIdleDailyMaintenance(); } @@ -3263,33 +3175,6 @@ void PermissionManager::CompleteRead() { } } -void PermissionManager::InitRemotePermissionService() { - // Check if this service is disabled by pref, and abort if it is. - if (!StaticPrefs::permissions_manager_remote_enabled()) { - return; - } - - // Also abort if we are in a background task. We do not want to call remote - // settings there, because we do not want to pollute the background task - // profile, and because we don't need the remote permissions there anyways. -#ifdef MOZ_BACKGROUNDTASKS - if (BackgroundTasks::IsBackgroundTaskMode()) { - return; - } -#endif - - NS_DispatchToCurrentThreadQueue( - NS_NewRunnableFunction( - "RemotePermissionService::Init", - [&] { - nsCOMPtr remotePermissionService = - do_GetService(NS_REMOTEPERMISSIONSERVICE_CONTRACTID); - NS_ENSURE_TRUE_VOID(remotePermissionService); - remotePermissionService->Init(); - }), - EventQueuePriority::Idle); -} - void PermissionManager::MaybeAddReadEntryFromMigration( const nsACString& aOrigin, const nsCString& aType, uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime, @@ -3785,7 +3670,7 @@ void PermissionManager::ConsumeDefaultsInputStream( constexpr char kMatchTypeHost[] = "host"; constexpr char kMatchTypeOrigin[] = "origin"; - mDefaultEntriesForImport.Clear(); + mDefaultEntries.Clear(); if (!aInputStream) { return; @@ -3829,99 +3714,128 @@ void PermissionManager::ConsumeDefaultsInputStream( continue; } - const nsCString& hostOrOrigin = lineArray[3]; - const nsCString& type = lineArray[1]; + DefaultEntry::Op op; if (lineArray[0].EqualsLiteral(kMatchTypeHost)) { - UpgradeHostToOriginAndInsert( - hostOrOrigin, type, permission, nsIPermissionManager::EXPIRE_NEVER, 0, - 0, - [&](const nsACString& aOrigin, const nsCString& aType, - uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, - int64_t aModificationTime) { - AddDefaultEntryForImport(aOrigin, aType, aPermission, aProofOfLock); - return NS_OK; - }); + op = DefaultEntry::eImportMatchTypeHost; } else if (lineArray[0].EqualsLiteral(kMatchTypeOrigin)) { - AddDefaultEntryForImport(hostOrOrigin, type, permission, aProofOfLock); + 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); } -void PermissionManager::AddDefaultEntryForImport( - const nsACString& aOrigin, const nsCString& aType, uint32_t aPermission, - const MonitorAutoLock& aProofOfLock) { - DefaultEntry* entry = mDefaultEntriesForImport.AppendElement(); - MOZ_ASSERT(entry); - - entry->mPermission = aPermission; - entry->mOrigin = aOrigin; - entry->mType = aType; -} - -nsresult PermissionManager::ImportDefaultEntry( - const DefaultEntry& aDefaultEntry) { - nsCOMPtr principal; - nsresult rv = GetPrincipalFromOrigin( - aDefaultEntry.mOrigin, IsOAForceStripPermission(aDefaultEntry.mType), - getter_AddRefs(principal)); - if (NS_FAILED(rv)) { - NS_WARNING("Couldn't import an origin permission - malformed origin"); - return rv; - } - - // 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, aDefaultEntry.mType, aDefaultEntry.mPermission, - cIDPermissionIsDefault, nsIPermissionManager::EXPIRE_NEVER, - 0, modificationTime, eDontNotify, eNoDBOperation); - if (NS_FAILED(rv)) { - NS_WARNING("There was a problem importing an origin permission"); - return rv; - } - - if (StaticPrefs::permissions_isolateBy_privateBrowsing() && - !IsOAForceStripPermission(aDefaultEntry.mType)) { - // Also import the permission for private browsing. - OriginAttributes attrs = OriginAttributes(principal->OriginAttributesRef()); - attrs.mPrivateBrowsingId = 1; - nsCOMPtr pbPrincipal = - BasePrincipal::Cast(principal)->CloneForcingOriginAttributes(attrs); - // May return nullptr if clone fails. - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = - AddInternal(pbPrincipal, aDefaultEntry.mType, aDefaultEntry.mPermission, - cIDPermissionIsDefault, nsIPermissionManager::EXPIRE_NEVER, - 0, modificationTime, eDontNotify, eNoDBOperation); - if (NS_FAILED(rv)) { - NS_WARNING( - "There was a problem importing an origin permission for private " - "browsing"); - return rv; - } - } - - return NS_OK; -} - -// ImportLatestDefaults will import the latest default permissions read during -// the last DB initialization. +// 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 : mDefaultEntriesForImport) { - Unused << ImportDefaultEntry(entry); + 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, + [&](const nsACString& aOrigin, const nsCString& aType, + uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, + int64_t aModificationTime) { + nsCOMPtr principal; + nsresult rv = + GetPrincipalFromOrigin(aOrigin, IsOAForceStripPermission(aType), + getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + rv = + AddInternal(principal, aType, aPermission, + cIDPermissionIsDefault, aExpireType, aExpireTime, + aModificationTime, PermissionManager::eDontNotify, + PermissionManager::eNoDBOperation, false, &aOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + if (StaticPrefs::permissions_isolateBy_privateBrowsing()) { + // Also import the permission for private browsing. + OriginAttributes attrs = + OriginAttributes(principal->OriginAttributesRef()); + attrs.mPrivateBrowsingId = 1; + nsCOMPtr pbPrincipal = + BasePrincipal::Cast(principal)->CloneForcingOriginAttributes( + attrs); + + rv = AddInternal( + pbPrincipal, aType, aPermission, cIDPermissionIsDefault, + aExpireType, aExpireTime, aModificationTime, + PermissionManager::eDontNotify, + PermissionManager::eNoDBOperation, false, &aOrigin); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; + }); + + if (NS_FAILED(rv)) { + NS_WARNING("There was a problem importing a host permission"); + } + continue; + } + + MOZ_ASSERT(entry.mOp == DefaultEntry::eImportMatchTypeOrigin); + + nsCOMPtr 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"); + } + + if (StaticPrefs::permissions_isolateBy_privateBrowsing()) { + // Also import the permission for private browsing. + OriginAttributes attrs = + OriginAttributes(principal->OriginAttributesRef()); + attrs.mPrivateBrowsingId = 1; + nsCOMPtr pbPrincipal = + BasePrincipal::Cast(principal)->CloneForcingOriginAttributes(attrs); + // May return nullptr if clone fails. + NS_ENSURE_TRUE(pbPrincipal, NS_ERROR_FAILURE); + + rv = AddInternal(pbPrincipal, 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 for private " + "browsing"); + } + } } return NS_OK; diff --git a/extensions/permissions/PermissionManager.h b/extensions/permissions/PermissionManager.h index aad994ae2c80..97011167e0be 100644 --- a/extensions/permissions/PermissionManager.h +++ b/extensions/permissions/PermissionManager.h @@ -10,7 +10,6 @@ #include "nsIPermissionManager.h" #include "nsIAsyncShutdown.h" #include "nsIObserver.h" -#include "nsIRemotePermissionService.h" #include "nsWeakReference.h" #include "nsCOMPtr.h" #include "nsIURI.h" @@ -621,35 +620,29 @@ class PermissionManager final : public nsIPermissionManager, // A single entry from the defaults URL. struct DefaultEntry { - nsCString mOrigin; + DefaultEntry() : mOp(eImportMatchTypeHost), mPermission(0) {} + + enum Op { + eImportMatchTypeHost, + eImportMatchTypeOrigin, + }; + + Op mOp; + + nsCString mHostOrOrigin; nsCString mType; - uint32_t mPermission = 0; + uint32_t mPermission; }; // List of entries read from the default settings. // This array is protected by the monitor. - nsTArray mDefaultEntriesForImport; - // Adds a default permission entry to AddDefaultEntryForImport for given - // origin, type and value - void AddDefaultEntryForImport(const nsACString& aOrigin, - const nsCString& aType, uint32_t aPermission, - const MonitorAutoLock& aProofOfLock); - // Given a default entry, import it as a default permission (id = -1) into the - // permission manager without storing it to disk. If permission isolation for - // private browsing is enabled (which is the default), and the permission type - // is not exempt from it, this will also create a separate default permission - // for private browsing - nsresult ImportDefaultEntry(const DefaultEntry& aDefaultEntry); + nsTArray mDefaultEntries; nsresult Read(const MonitorAutoLock& aProofOfLock); void CompleteRead(); void CompleteMigrations(); - // Initialize service used for importing default permissions from remote - // settings - void InitRemotePermissionService(); - bool mMemoryOnlyDB; nsTHashtable mPermissionTable; diff --git a/extensions/permissions/RemotePermissionService.sys.mjs b/extensions/permissions/RemotePermissionService.sys.mjs deleted file mode 100644 index b1cd015cf449..000000000000 --- a/extensions/permissions/RemotePermissionService.sys.mjs +++ /dev/null @@ -1,191 +0,0 @@ -/* 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/. */ - -import { RemoteSettings } from "resource://services-settings/remote-settings.sys.mjs"; - -const COLLECTION_NAME = "remote-permissions"; - -/** - * Allowlist of permission types and values allowed to be set through remote - * settings. In this map, the key is the permission type, while the value is an - * array of allowed permission values/capabilities allowed to be set. Possible - * values for most permissions are: - * - * - Ci.nsIPermissionManager.ALLOW_ACTION - * - Ci.nsIPermissionManager.DENY_ACTION - * - Ci.nsIPermissionManager.PROMPT_ACTION - * - "*" (Allows all values) - * - * Permission types with custom permission values (like - * https-only-load-insecure) may include different values. Only change this - * value with a review from #permissions-reviewers. - */ -const ALLOWED_PERMISSION_VALUES = { - "https-only-load-insecure": [ - Ci.nsIHttpsOnlyModePermission.HTTPSFIRST_LOAD_INSECURE_ALLOW, - ], -}; - -/** - * See nsIRemotePermissionService.idl - */ -export class RemotePermissionService { - classId = Components.ID("{a4b1b3b1-b68a-4129-aa2f-eb086162a8c7}"); - QueryInterface = ChromeUtils.generateQI(["nsIRemotePermissionService"]); - - #rs = RemoteSettings(COLLECTION_NAME); - #onSyncCallback = null; - #initialized = Promise.withResolvers(); - #allowedPermissionValues = ALLOWED_PERMISSION_VALUES; - - /** - * Asynchonously import all default permissions from remote settings into the - * permission manager. Also, if not already done, set up remote settings event - * listener to keep remote permissions in sync. - */ - async init() { - try { - if (Services.startup.shuttingDown) { - return; - } - - if ( - !Services.prefs.getBoolPref("permissions.manager.remote.enabled", false) - ) { - throw Error( - "Tried to initialize remote permission service despite being disabled by pref" - ); - } - - let remotePermissions = await this.#rs.get(); - for (const permission of remotePermissions) { - this.#addDefaultPermission(permission); - } - - // Init could be called multiple times if the permission manager is - // reinitializing itself due to "testonly-reload-permissions-from-disk" - // being emitted. In that case, we don't shouldn't set up the RS listener - // again. We may also land in that situtation when "profile-do-change" is - // emitted. - if (!this.#onSyncCallback) { - this.#onSyncCallback = this.#onSync.bind(this); - this.#rs.on("sync", this.#onSyncCallback); - } - - this.#initialized.resolve(); - } catch (e) { - this.#initialized.reject(e); - throw e; - } - } - - get isInitialized() { - return this.#initialized.promise; - } - - get testAllowedPermissionValues() { - return this.#allowedPermissionValues; - } - - set testAllowedPermissionValues(allowedPermissionValues) { - Cu.crashIfNotInAutomation(); - this.#allowedPermissionValues = allowedPermissionValues; - } - - // eslint-disable-next-line jsdoc/require-param - /** - * Callback for the "sync" event from remote settings. This function will - * receive the created, updated and deleted permissions from remote settings, - * and will update the permission manager accordingly. - */ - #onSync({ data: { created = [], updated = [], deleted = [] } }) { - const toBeDeletedPermissions = [ - // Delete permissions that got deleted in remote settings. - ...deleted, - // If an existing entry got updated in remote settings, but the origin or - // type changed, we can not just update it, as permissions are identified - // by origin and type in the permission manager. Instead, we need to - // remove the old permission and add a new one. - ...updated - .filter( - ({ - old: { origin: oldOrigin, type: oldType }, - new: { origin: newOrigin, type: newType }, - }) => oldOrigin != newOrigin || oldType != newType - ) - .map(({ old }) => old), - ]; - - const toBeAddedPermissions = [ - // Add newly created permissions. - ...created, - // "Add" permissions updated in remote settings (the permission manager - // will automatically update the existing default permission instead of - // creating a new one if the permission origin and type match). - ...updated.map(({ new: newPermission }) => newPermission), - // Delete permissions by "adding" them with value UNKNOWN_ACTION. - ...toBeDeletedPermissions.map(({ origin, type }) => ({ - origin, - type, - capability: Ci.nsIPermissionManager.UNKNOWN_ACTION, - })), - ]; - - for (const permission of toBeAddedPermissions) { - this.#addDefaultPermission(permission); - } - } - - /** - * Check if a permission type and value is allowed to be set through remote - * settings, based on the ALLOWED_PERMISSION_VALUES allowlist. - * - * @param {string} type Permission type to check - * @param {string} capability Permission capability to check - * @returns {boolean} - */ - #isAllowed(type, capability) { - if (!this.#allowedPermissionValues[type]) { - if (this.#allowedPermissionValues["*"]) { - this.#allowedPermissionValues[type] = - this.#allowedPermissionValues["*"]; - } else { - return false; - } - } - - return ( - this.#allowedPermissionValues[type].includes("*") || - this.#allowedPermissionValues[type].includes(capability) || - capability === Ci.nsIPermissionManager.UNKNOWN_ACTION - ); - } - - /** - * Add a default permission to the permission manager. - * - * @param {object} permission The permission to add - * @param {string} permission.origin Origin string of the permission - * @param {string} permission.type Type of the permission - * @param {number} permission.capability Capability of the permission - */ - #addDefaultPermission({ origin, type, capability }) { - if (!this.#isAllowed(type, capability)) { - console.error( - `Remote Settings contain default permission of disallowed type '${type}' with value '${capability}' for origin '${origin}', skipping import` - ); - return; - } - - try { - let principal = Services.scriptSecurityManager.createContentPrincipal( - Services.io.newURI(origin), - {} - ); - Services.perms.addDefaultFromPrincipal(principal, type, capability); - } catch (e) { - console.error(e); - } - } -} diff --git a/extensions/permissions/components.conf b/extensions/permissions/components.conf index 759686c0c84b..62f4f7ba1c56 100644 --- a/extensions/permissions/components.conf +++ b/extensions/permissions/components.conf @@ -22,12 +22,4 @@ Classes = [ 'type': 'PermissionDelegateHandler', 'headers': ['/extensions/permissions/PermissionDelegateHandler.h'], }, - { - 'cid': '{a4b1b3b1-b68a-4129-aa2f-eb086162a8c7}', - 'contract_ids': ['@mozilla.org/remote-permission-service;1'], - 'esModule': 'resource://gre/modules/RemotePermissionService.sys.mjs', - 'constructor': 'RemotePermissionService', - 'singleton': True, - 'processes': ProcessSelector.MAIN_PROCESS_ONLY, - }, ] diff --git a/extensions/permissions/moz.build b/extensions/permissions/moz.build index a8565b90fec2..6cdac6092644 100644 --- a/extensions/permissions/moz.build +++ b/extensions/permissions/moz.build @@ -27,16 +27,6 @@ XPCOM_MANIFESTS += [ "components.conf", ] -XPIDL_MODULE = "permissions" - -XPIDL_SOURCES += [ - "nsIRemotePermissionService.idl", -] - -EXTRA_JS_MODULES += [ - "RemotePermissionService.sys.mjs", -] - LOCAL_INCLUDES += [ "/caps", ] diff --git a/extensions/permissions/nsIRemotePermissionService.idl b/extensions/permissions/nsIRemotePermissionService.idl deleted file mode 100644 index 0c0d9cd65374..000000000000 --- a/extensions/permissions/nsIRemotePermissionService.idl +++ /dev/null @@ -1,41 +0,0 @@ -/* 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 "nsISupports.idl" - -interface nsIPrincipal; - -/** - * Service to import default permissions from Remote Settings. Will be - * initialized by permission manager after it itself has completed its - * initialization, and will then import default permissions from Remote Settings - * asynchronously. This also means default permissions aren't guranteed to be - * available directly after startup. - */ -[scriptable, uuid(a4b1b3b1-b68a-4129-aa2f-eb086162a8c7)] -interface nsIRemotePermissionService : nsISupports { - /** - * Asynchonously import all default permissions from remote settings into - * the permission manager. Also, if not already done, set up remote settings - * event listener to keep remote permissions in sync. - */ - void init(); - /** - * Promise that is resolved when the remote permission service has been - * fully initialized, meaning all intial permissions have been imported and - * the remote settings sync event listener has been set up. If any errors - * are encountered during inizialization, this promise will be rejected. - */ - readonly attribute Promise isInitialized; - /** - * Allowed permission types and values to be set through remote settings. - * See RemotePermissionService.sys.mjs for further documentation. Exposed - * only for testing purposes. - */ - attribute jsval testAllowedPermissionValues; -}; - -%{C++ -#define NS_REMOTEPERMISSIONSERVICE_CONTRACTID "@mozilla.org/remote-permission-service;1" -%} diff --git a/extensions/permissions/test/unit/test_permmanager_remote.js b/extensions/permissions/test/unit/test_permmanager_remote.js deleted file mode 100644 index 2131114a92b4..000000000000 --- a/extensions/permissions/test/unit/test_permmanager_remote.js +++ /dev/null @@ -1,480 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. -https://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -ChromeUtils.defineESModuleGetters(this, { - RemoteSettings: "resource://services-settings/remote-settings.sys.mjs", -}); - -const COLLECTION_NAME = "remote-permissions"; -const ORIGIN_1 = "https://example.com"; -const PRINCIPAL_1 = Services.scriptSecurityManager.createContentPrincipal( - Services.io.newURI(ORIGIN_1), - {} -); -const PRINCIPAL_1_PB = Services.scriptSecurityManager.createContentPrincipal( - Services.io.newURI(ORIGIN_1), - { privateBrowsingId: 1 } -); -const ORIGIN_2 = "https://example.org"; -const PRINCIPAL_2 = Services.scriptSecurityManager.createContentPrincipal( - Services.io.newURI(ORIGIN_2), - {} -); -const PRINCIPAL_2_PB = Services.scriptSecurityManager.createContentPrincipal( - Services.io.newURI(ORIGIN_2), - { privateBrowsingId: 1 } -); -const ORIGIN_INVALID = "not a valid origin"; -const TEST_PERMISSION_1 = "test-permission-1"; -const TEST_PERMISSION_2 = "test-permission-2"; - -let rs = RemoteSettings(COLLECTION_NAME); -let pm = Services.perms; -let rps = Cc["@mozilla.org/remote-permission-service;1"].getService( - Ci.nsIRemotePermissionService -); - -async function remoteSettingsSync({ created, updated, deleted }) { - await rs.emit("sync", { - data: { - created, - updated, - deleted, - }, - }); -} - -function expectPermissions(perms) { - Assert.deepEqual( - pm.all - .map(({ principal, type, capability }) => ({ - principal: principal.siteOrigin, - type, - capability, - })) - .sort((a, b) => a.principal.localeCompare(b.principal)), - perms - .map(({ principal, type, capability }) => ({ - principal: principal.siteOrigin, - type, - capability, - })) - .sort((a, b) => a.principal.localeCompare(b.principal)), - "Permission manager should have expected permissions" - ); -} - -add_setup(async function () { - do_get_profile(); - - // This needs to be restored on cleanup - let originalPermissionValues = structuredClone( - rps.testAllowedPermissionValues - ); - - // Initialize remote permission service - let permObserver = Services.perms.QueryInterface(Ci.nsIObserver); - permObserver.observe(null, "profile-do-change", ""); - await rps.isInitialized; - - registerCleanupFunction(async () => { - info("Cleaning up"); - rps.testAllowedPermissionValues = originalPermissionValues; - Services.prefs.clearUserPref("permissions.manager.defaultsUrl"); - Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); - Services.perms.removeAll(); - }); - - // Allow setting everything - rps.testAllowedPermissionValues = { - "*": ["*"], - }; -}); - -add_task(async function test_create_permission() { - info("Creating permission"); - - await remoteSettingsSync({ - created: [ - { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ], - }); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ]); -}); - -add_task(async function test_update_permission_value() { - info("Updating permission value"); - - await remoteSettingsSync({ - updated: [ - { - old: { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - new: { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - }, - ], - }); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); -}); - -add_task(async function test_update_permission_origin() { - info("Updating permission origin"); - - await remoteSettingsSync({ - updated: [ - { - old: { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - new: { - origin: ORIGIN_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - }, - ], - }); - - expectPermissions([ - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); -}); - -add_task(async function test_user_permission_restoration() { - info("Overriding with user permission"); - - pm.addFromPrincipal( - PRINCIPAL_2, - TEST_PERMISSION_1, - Ci.nsIPermissionManager.ALLOW_ACTION - ); - - expectPermissions([ - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); - - info("Removing user permission"); - - pm.removeFromPrincipal(PRINCIPAL_2, TEST_PERMISSION_1); - - expectPermissions([ - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); -}); - -add_task(async function test_remove_all_restoration() { - info("Overriding with user permission and adding new user permission"); - - pm.addFromPrincipal( - PRINCIPAL_1, - TEST_PERMISSION_1, - Ci.nsIPermissionManager.ALLOW_ACTION - ); - pm.addFromPrincipal( - PRINCIPAL_2, - TEST_PERMISSION_1, - Ci.nsIPermissionManager.ALLOW_ACTION - ); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); - - info("Removing all permissions"); - - pm.removeAll(); - - expectPermissions([ - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); -}); - -add_task(async function test_delete_permission() { - info("Deleting permission"); - - await remoteSettingsSync({ - deleted: [ - { - origin: ORIGIN_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ], - }); - - expectPermissions([]); -}); - -add_task(async function test_allowlist() { - info("Only allowing TEST_PERMISSION_1 with value ALLOW_ACTION"); - - rps.testAllowedPermissionValues = { - [TEST_PERMISSION_1]: [Ci.nsIPermissionManager.ALLOW_ACTION], - }; - - info("Trying to add all sorts of default permissions"); - - await remoteSettingsSync({ - created: [ORIGIN_1, ORIGIN_2].flatMap(origin => - [TEST_PERMISSION_1, TEST_PERMISSION_2].flatMap(type => - [ - Ci.nsIPermissionManager.ALLOW_ACTION, - Ci.nsIPermissionManager.DENY_ACTION, - Ci.nsIPermissionManager.PROMPT_ACTION, - ].flatMap(capability => ({ origin, type, capability })) - ) - ), - }); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_2, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_2_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ]); - - rps.testAllowedPermissionValues = { - "*": ["*"], - }; -}); - -add_task(async function test_defaults_url() { - info("Testing interaction with permissions.manager.defaultsUrl"); - - info("Setting up permissions.manager.defaultsUrl"); - - let file = do_get_tempdir(); - file.append("test_default_permissions"); - let ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( - Ci.nsIFileOutputStream - ); - ostream.init(file, -1, 0o666, 0); - let conv = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance( - Ci.nsIConverterOutputStream - ); - conv.init(ostream, "UTF-8"); - conv.writeString( - [ - "host", - TEST_PERMISSION_1, - Ci.nsIPermissionManager.ALLOW_ACTION, - ORIGIN_1, - ].join("\t") + "\n" - ); - conv.writeString( - [ - "host", - TEST_PERMISSION_2, - Ci.nsIPermissionManager.ALLOW_ACTION, - ORIGIN_1, - ].join("\t") + "\n" - ); - ostream.close(); - - Services.prefs.setCharPref( - "permissions.manager.defaultsUrl", - "file://" + file.path - ); - - info("Re-initializing permission manager"); - - // Start from a clean slate with our new default permissions from - // permissions.manager.defaultsUrl - Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk"); - Services.perms.removeAll(); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_2, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_2, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ]); - - info("Overriding permissions from permissions.manager.defaultsUrl"); - - await remoteSettingsSync({ - created: [ - { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - origin: ORIGIN_1, - type: TEST_PERMISSION_2, - capability: Ci.nsIPermissionManager.UNKNOWN_ACTION, - }, - ], - }); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.DENY_ACTION, - }, - ]); -}); - -add_task(async function test_malformed_origin() { - info( - "Testing that import will continue after encountering a malformed origin" - ); - - await remoteSettingsSync({ - created: [ - { - origin: ORIGIN_INVALID, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - // TEST_PERMISSION_1 still exists for ORIGIN_1 from the previous step, but - // for simplicity we act like it is new here. We will see if the value has - // changed from deny to allow. - { - origin: ORIGIN_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ], - }); - - expectPermissions([ - { - principal: PRINCIPAL_1, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - { - principal: PRINCIPAL_1_PB, - type: TEST_PERMISSION_1, - capability: Ci.nsIPermissionManager.ALLOW_ACTION, - }, - ]); -}); diff --git a/extensions/permissions/test/unit/xpcshell.toml b/extensions/permissions/test/unit/xpcshell.toml index 5f3f3c918fac..93eb51d98c6c 100644 --- a/extensions/permissions/test/unit/xpcshell.toml +++ b/extensions/permissions/test/unit/xpcshell.toml @@ -77,8 +77,6 @@ skip-if = ["os == 'android'"] # Android doesn't use places ["test_permmanager_oa_strip.js"] -["test_permmanager_remote.js"] - ["test_permmanager_removeAllExceptTypes.js"] ["test_permmanager_removeAllSinceWithTypeExceptions.js"] diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index bf6b911cf9f4..5d4d11ea97f6 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -14565,13 +14565,6 @@ value: true mirror: always -# Whether default permissions should be imported from remote settings in -# addition to importing them from browser/app/permissions. -- name: permissions.manager.remote.enabled - type: bool - value: @IS_EARLY_BETA_OR_EARLIER@ - mirror: always - #--------------------------------------------------------------------------- # Prefs starting with "places." #--------------------------------------------------------------------------- diff --git a/netwerk/base/nsIPermissionManager.idl b/netwerk/base/nsIPermissionManager.idl index bc8f2104da74..db680b9d0d46 100644 --- a/netwerk/base/nsIPermissionManager.idl +++ b/netwerk/base/nsIPermissionManager.idl @@ -155,20 +155,6 @@ interface nsIPermissionManager : nsISupports in ACString type, in uint32_t permission); - /** - * Add temporary default permission information for a given principal. - * This permission will be cleared at the end of the session, will not be - * stored on disk, and will not be set if a conflicting (non-default) - * permission already exists. - * - * This function shouldn't be used by regular permission manager consumers and - * is only expected to be called by the RemotePermissionService.sys.mjs for - * the purpose of importing default permissions from remote settings. - */ - void addDefaultFromPrincipal(in nsIPrincipal principal, - in ACString type, - in uint32_t permission); - /** * Remove permission information for a given principal. * This is internally calling remove() with the host from the principal's URI. diff --git a/services/settings/dumps/main/remote-permissions.json b/services/settings/dumps/main/remote-permissions.json deleted file mode 100644 index 8c65f467207c..000000000000 --- a/services/settings/dumps/main/remote-permissions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "data": [], - "timestamp": 1730278443662 -}