Bug 1958090: Make PermissionManager thread-safe.r=edenchuang,permissions-reviewers,timhuang
This class is used by both parent and child processes. It's more heavily used on the parent vs the child side. With this change, even though the PermissionManager class should itself be now thread-safe, I have still kept assertions on most of it's public methods for main thread in place because I wanted to keep the regression risk minimal with this change while still satisfying my criteria about allowing some operations like adding new and reading existing permissions thread-safe such that they can be performed off-main thread. There might be some permission manager callers here which previously needed to switch to main thread in order to invoke operations; they would no longer need to do that. After gaining some confidence with this limited exposure maybe we can slowly start looking into the callers and see if they can benefit from this thread-safety now i.e. if they do not need to switch to main thread just for the sake of PermissionManager usage. Since, this is a singleton class; ofcourse, the creation, initialization, etc. are still main thread only. Also, any DB operation can also only be performed on the corresponding thread only. Differential Revision: https://phabricator.services.mozilla.com/D244608
This commit is contained in:
@@ -2460,7 +2460,7 @@ mozilla::ipc::IPCResult ContentChild::RecvAddPermission(
|
||||
// child processes don't care about modification time.
|
||||
int64_t modificationTime = 0;
|
||||
|
||||
permissionManager->AddInternal(
|
||||
permissionManager->Add(
|
||||
principal, nsCString(permission.type), permission.capability, 0,
|
||||
permission.expireType, permission.expireTime, modificationTime,
|
||||
PermissionManager::eNotify, PermissionManager::eNoDBOperation);
|
||||
|
||||
@@ -89,7 +89,7 @@ constexpr int64_t cIDPermissionIsDefault = -1;
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsChildProcess() { return XRE_IsContentProcess(); }
|
||||
inline bool IsChildProcess() { return XRE_IsContentProcess(); }
|
||||
|
||||
void LogToConsole(const nsAString& aMsg) {
|
||||
nsCOMPtr<nsIConsoleService> console(
|
||||
@@ -697,6 +697,8 @@ PermissionManager::PermissionManager()
|
||||
mLargestID(0) {}
|
||||
|
||||
PermissionManager::~PermissionManager() {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// NOTE: Make sure to reject each of the promises in mPermissionKeyPromiseMap
|
||||
// before destroying.
|
||||
for (const auto& promise : mPermissionKeyPromiseMap.Values()) {
|
||||
@@ -755,6 +757,11 @@ nsresult PermissionManager::Init() {
|
||||
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
MOZ_ASSERT(mState == eInitializing);
|
||||
|
||||
// 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);
|
||||
@@ -842,11 +849,9 @@ nsresult PermissionManager::OpenDatabase(nsIFile* aPermissionsFile) {
|
||||
|
||||
void PermissionManager::InitDB(bool aRemoveFile) {
|
||||
mState = eInitializing;
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mReadEntries.Clear();
|
||||
}
|
||||
mReadEntries.Clear();
|
||||
|
||||
auto readyIfFailed = MakeScopeExit([&]() {
|
||||
// ignore failure here, since it's non-fatal (we can run fine without
|
||||
@@ -876,15 +881,19 @@ void PermissionManager::InitDB(bool aRemoveFile) {
|
||||
RefPtr<PermissionManager> self = this;
|
||||
mThread->Dispatch(NS_NewRunnableFunction(
|
||||
"PermissionManager::InitDB", [self, aRemoveFile, defaultsInputStream] {
|
||||
nsresult rv = self->TryInitDB(aRemoveFile, defaultsInputStream);
|
||||
MonitorAutoLock lock(self->mMonitor);
|
||||
|
||||
nsresult rv = self->TryInitDB(aRemoveFile, defaultsInputStream, lock);
|
||||
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(); }));
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"PermissionManager::InitDB-MainThread", [self] {
|
||||
MonitorAutoLock lock{self->mMonitor};
|
||||
self->EnsureReadCompleted();
|
||||
}));
|
||||
|
||||
self->mMonitor.Notify();
|
||||
}));
|
||||
@@ -893,11 +902,10 @@ void PermissionManager::InitDB(bool aRemoveFile) {
|
||||
}
|
||||
|
||||
nsresult PermissionManager::TryInitDB(bool aRemoveFile,
|
||||
nsIInputStream* aDefaultsInputStream) {
|
||||
nsIInputStream* aDefaultsInputStream,
|
||||
const MonitorAutoLock& aProofOfLock) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
auto raii = MakeScopeExit([&]() {
|
||||
if (aDefaultsInputStream) {
|
||||
aDefaultsInputStream->Close();
|
||||
@@ -1571,11 +1579,11 @@ nsresult PermissionManager::TryInitDB(bool aRemoveFile,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Always import default permissions.
|
||||
ConsumeDefaultsInputStream(aDefaultsInputStream, lock);
|
||||
ConsumeDefaultsInputStream(aDefaultsInputStream, aProofOfLock);
|
||||
|
||||
// check whether to import or just read in the db
|
||||
if (tableExists) {
|
||||
rv = Read(lock);
|
||||
rv = Read(aProofOfLock);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@@ -1703,10 +1711,11 @@ PermissionManager::AddFromPrincipalAndPersistInPrivateBrowsing(
|
||||
// A modificationTime of zero will cause AddInternal to use now().
|
||||
int64_t modificationTime = 0;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
return AddInternal(aPrincipal, aType, aPermission, 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER,
|
||||
/* aExpireTime */ 0, modificationTime, eNotify, eWriteToDB,
|
||||
/* aIgnoreSessionPermissions */ false,
|
||||
/* aOriginString*/ nullptr,
|
||||
/* aAllowPersistInPrivateBrowsing */ true);
|
||||
}
|
||||
@@ -1731,11 +1740,10 @@ PermissionManager::AddDefaultFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
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
|
||||
@@ -1801,7 +1809,7 @@ PermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
|
||||
// A modificationTime of zero will cause AddInternal to use now().
|
||||
int64_t modificationTime = 0;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return AddInternal(aPrincipal, aType, aPermission, 0, aExpireType,
|
||||
aExpireTime, modificationTime, eNotify, eWriteToDB);
|
||||
}
|
||||
@@ -1823,19 +1831,36 @@ PermissionManager::TestAddFromPrincipalByTime(nsIPrincipal* aPrincipal,
|
||||
return rv;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return AddInternal(aPrincipal, aType, aPermission, 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0, aModificationTime,
|
||||
eNotify, eWriteToDB);
|
||||
}
|
||||
|
||||
nsresult PermissionManager::Add(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 nsACString* aOriginString,
|
||||
const bool aAllowPersistInPrivateBrowsing) {
|
||||
MOZ_ASSERT(IsChildProcess());
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return AddInternal(aPrincipal, aType, aPermission, aID, aExpireType,
|
||||
aExpireTime, aModificationTime, aNotifyOperation,
|
||||
aDBOperation, aOriginString,
|
||||
aAllowPersistInPrivateBrowsing);
|
||||
}
|
||||
|
||||
nsresult PermissionManager::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,
|
||||
DBOperationType aDBOperation, const nsACString* aOriginString,
|
||||
const bool aAllowPersistInPrivateBrowsing) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT_IF(!IsChildProcess(), NS_IsMainThread());
|
||||
|
||||
// If this is a default permission, no changes should not be written to disk.
|
||||
MOZ_ASSERT((aID != cIDPermissionIsDefault) || (aDBOperation != eWriteToDB));
|
||||
@@ -1907,7 +1932,7 @@ nsresult PermissionManager::AddInternal(
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, aType));
|
||||
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, aType));
|
||||
|
||||
// look up the type index
|
||||
int32_t typeIndex = GetTypeIndex(aType, true);
|
||||
@@ -1934,10 +1959,11 @@ nsresult PermissionManager::AddInternal(
|
||||
OperationType op;
|
||||
int32_t index = entry->GetPermissionIndex(typeIndex);
|
||||
if (index == -1) {
|
||||
if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
|
||||
if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
op = eOperationNone;
|
||||
else
|
||||
} else {
|
||||
op = eOperationAdding;
|
||||
}
|
||||
|
||||
} else {
|
||||
PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||
@@ -2010,7 +2036,7 @@ nsresult PermissionManager::AddInternal(
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||
aPermission, aExpireType, aExpireTime,
|
||||
aModificationTime, u"added");
|
||||
aModificationTime, u"added"_ns);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2029,17 +2055,18 @@ nsresult PermissionManager::AddInternal(
|
||||
|
||||
entry->GetPermissions().RemoveElementAt(index);
|
||||
|
||||
if (aDBOperation == eWriteToDB)
|
||||
if (aDBOperation == eWriteToDB) {
|
||||
// We care only about the id here so we pass dummy values for all other
|
||||
// parameters.
|
||||
UpdateDB(op, id, ""_ns, ""_ns, 0, nsIPermissionManager::EXPIRE_NEVER, 0,
|
||||
0);
|
||||
}
|
||||
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(
|
||||
aPrincipal, mTypeArray[typeIndex], oldPermissionEntry.mPermission,
|
||||
oldPermissionEntry.mExpireType, oldPermissionEntry.mExpireTime,
|
||||
oldPermissionEntry.mModificationTime, u"deleted");
|
||||
oldPermissionEntry.mModificationTime, u"deleted"_ns);
|
||||
}
|
||||
|
||||
// If there are no more permissions stored for that entry, clear it.
|
||||
@@ -2127,7 +2154,7 @@ nsresult PermissionManager::AddInternal(
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||
aPermission, aExpireType, aExpireTime,
|
||||
aModificationTime, u"changed");
|
||||
aModificationTime, u"changed"_ns);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2177,7 +2204,7 @@ nsresult PermissionManager::AddInternal(
|
||||
if (aNotifyOperation == eNotify) {
|
||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||
aPermission, aExpireType, aExpireTime,
|
||||
aModificationTime, u"changed");
|
||||
aModificationTime, u"changed"_ns);
|
||||
}
|
||||
|
||||
} break;
|
||||
@@ -2190,6 +2217,14 @@ NS_IMETHODIMP
|
||||
PermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return RemoveFromPrincipalInternal(aPrincipal, aType);
|
||||
}
|
||||
|
||||
nsresult PermissionManager::RemoveFromPrincipalInternal(
|
||||
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.
|
||||
@@ -2221,20 +2256,25 @@ PermissionManager::RemovePermission(nsIPermission* aPerm) {
|
||||
rv = aPerm->GetType(type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// Permissions are uniquely identified by their principal and type.
|
||||
// We remove the permission using these two pieces of data.
|
||||
return RemoveFromPrincipal(principal, type);
|
||||
return RemoveFromPrincipalInternal(principal, type);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PermissionManager::RemoveAll() {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return RemoveAllInternal(true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PermissionManager::RemoveAllSince(int64_t aSince) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return RemoveAllModifiedSince(aSince);
|
||||
}
|
||||
|
||||
@@ -2243,6 +2283,7 @@ PermissionManager::RemoveAllExceptTypes(
|
||||
const nsTArray<nsCString>& aTypeExceptions) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
// Need to make sure read is done before we get the type index. Type indexes
|
||||
// are populated from DB.
|
||||
EnsureReadCompleted();
|
||||
@@ -2251,9 +2292,10 @@ PermissionManager::RemoveAllExceptTypes(
|
||||
return RemoveAllInternal(true);
|
||||
}
|
||||
|
||||
return RemovePermissionEntries([&](const PermissionEntry& aPermEntry) {
|
||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]);
|
||||
});
|
||||
return RemovePermissionEntries(
|
||||
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]);
|
||||
});
|
||||
}
|
||||
|
||||
nsresult PermissionManager::RemovePermissionEntries(
|
||||
@@ -2298,7 +2340,7 @@ nsresult PermissionManager::RemovePermissionEntries(
|
||||
AddInternal(
|
||||
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
||||
PermissionManager::eWriteToDB, false, &std::get<2>(i));
|
||||
PermissionManager::eWriteToDB, &std::get<2>(i));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -2318,6 +2360,8 @@ NS_IMETHODIMP
|
||||
PermissionManager::RemoveByType(const nsACString& aType) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// Need to make sure read is done before we get the type index. Type indexes
|
||||
// are populated from DB.
|
||||
EnsureReadCompleted();
|
||||
@@ -2340,6 +2384,8 @@ PermissionManager::RemoveByTypeSince(const nsACString& aType,
|
||||
int64_t aModificationTime) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// Need to make sure read is done before we get the type index. Type indexes
|
||||
// are populated from DB.
|
||||
EnsureReadCompleted();
|
||||
@@ -2363,14 +2409,17 @@ PermissionManager::RemoveAllSinceWithTypeExceptions(
|
||||
int64_t aModificationTime, const nsTArray<nsCString>& aTypeExceptions) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// Need to make sure read is done before we get the type index. Type indexes
|
||||
// are populated from DB.
|
||||
EnsureReadCompleted();
|
||||
|
||||
return RemovePermissionEntries([&](const PermissionEntry& aPermEntry) {
|
||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]) &&
|
||||
aModificationTime <= aPermEntry.mModificationTime;
|
||||
});
|
||||
return RemovePermissionEntries(
|
||||
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]) &&
|
||||
aModificationTime <= aPermEntry.mModificationTime;
|
||||
});
|
||||
}
|
||||
|
||||
void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
||||
@@ -2397,7 +2446,8 @@ void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
||||
data->mDBConn = nullptr;
|
||||
|
||||
if (aNextOp == eRebuldOnSuccess) {
|
||||
self->TryInitDB(true, defaultsInputStream);
|
||||
MonitorAutoLock lock{self->mMonitor};
|
||||
self->TryInitDB(true, defaultsInputStream, lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2412,6 +2462,8 @@ void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
||||
nsresult PermissionManager::RemoveAllFromIPC() {
|
||||
MOZ_ASSERT(IsChildProcess());
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
// 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.
|
||||
@@ -2441,7 +2493,7 @@ nsresult PermissionManager::RemoveAllInternal(bool aNotifyObservers) {
|
||||
ImportLatestDefaults();
|
||||
|
||||
if (aNotifyObservers) {
|
||||
NotifyObservers(nullptr, u"cleared");
|
||||
NotifyObservers(nullptr, u"cleared"_ns);
|
||||
}
|
||||
|
||||
RefPtr<PermissionManager> self = this;
|
||||
@@ -2458,8 +2510,10 @@ nsresult PermissionManager::RemoveAllInternal(bool aNotifyObservers) {
|
||||
data->mDBConn->ExecuteSimpleSQL("DELETE FROM moz_perms"_ns);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"PermissionManager::RemoveAllInternal-Failure",
|
||||
[self] { self->CloseDB(eRebuldOnSuccess); }));
|
||||
"PermissionManager::RemoveAllInternal-Failure", [self] {
|
||||
MonitorAutoLock lock{self->mMonitor};
|
||||
self->CloseDB(eRebuldOnSuccess);
|
||||
}));
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -2470,6 +2524,7 @@ NS_IMETHODIMP
|
||||
PermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType,
|
||||
uint32_t* aPermission) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
||||
true);
|
||||
@@ -2479,6 +2534,7 @@ NS_IMETHODIMP
|
||||
PermissionManager::TestExactPermanentPermission(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType,
|
||||
uint32_t* aPermission) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
||||
false);
|
||||
@@ -2488,6 +2544,7 @@ NS_IMETHODIMP
|
||||
PermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType,
|
||||
uint32_t* aPermission) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||
nsIPermissionManager::UNKNOWN_ACTION, false,
|
||||
false, true);
|
||||
@@ -2501,6 +2558,8 @@ PermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
|
||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||
*aResult = nullptr;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
EnsureReadCompleted();
|
||||
|
||||
if (aPrincipal->IsSystemPrincipal()) {
|
||||
@@ -2512,7 +2571,7 @@ PermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, aType));
|
||||
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, aType));
|
||||
|
||||
int32_t typeIndex = GetTypeIndex(aType, false);
|
||||
// If type == -1, the type isn't known,
|
||||
@@ -2570,7 +2629,7 @@ nsresult PermissionManager::CommonTestPermissionInternal(
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(prin);
|
||||
MOZ_ASSERT(PermissionAvailable(prin, aType));
|
||||
MOZ_ASSERT(PermissionAvailableInternal(prin, aType));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2587,7 +2646,6 @@ nsresult PermissionManager::CommonTestPermissionInternal(
|
||||
*aPermission = aIncludingSession
|
||||
? entry->GetPermission(aTypeIndex).mPermission
|
||||
: entry->GetPermission(aTypeIndex).mNonSessionPermission;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -2649,6 +2707,7 @@ nsresult PermissionManager::GetPermissionEntries(
|
||||
|
||||
NS_IMETHODIMP PermissionManager::GetAll(
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return GetPermissionEntries(
|
||||
[](const PermissionEntry& aPermEntry) { return true; }, aResult);
|
||||
}
|
||||
@@ -2660,8 +2719,10 @@ NS_IMETHODIMP PermissionManager::GetAllByTypeSince(
|
||||
if (aSince > (PR_Now() / PR_USEC_PER_MSEC)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return GetPermissionEntries(
|
||||
[&](const PermissionEntry& aPermEntry) {
|
||||
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||
return mTypeArray[aPermEntry.mType].Equals(aPrefix) &&
|
||||
aSince <= aPermEntry.mModificationTime;
|
||||
},
|
||||
@@ -2670,8 +2731,9 @@ NS_IMETHODIMP PermissionManager::GetAllByTypeSince(
|
||||
|
||||
NS_IMETHODIMP PermissionManager::GetAllWithTypePrefix(
|
||||
const nsACString& aPrefix, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return GetPermissionEntries(
|
||||
[&](const PermissionEntry& aPermEntry) {
|
||||
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||
return StringBeginsWith(mTypeArray[aPermEntry.mType], aPrefix);
|
||||
},
|
||||
aResult);
|
||||
@@ -2684,8 +2746,9 @@ NS_IMETHODIMP PermissionManager::GetAllByTypes(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return GetPermissionEntries(
|
||||
[&](const PermissionEntry& aPermEntry) {
|
||||
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||
return aTypes.Contains(mTypeArray[aPermEntry.mType]);
|
||||
},
|
||||
aResult);
|
||||
@@ -2801,9 +2864,11 @@ PermissionManager::GetAllForPrincipal(
|
||||
nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
nsresult rv;
|
||||
aResult.Clear();
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
EnsureReadCompleted();
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, ""_ns));
|
||||
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, ""_ns));
|
||||
|
||||
// First, append the non-site-scoped permissions.
|
||||
rv = GetAllForPrincipalHelper(aPrincipal, false, aResult);
|
||||
@@ -2818,6 +2883,8 @@ NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject,
|
||||
const char16_t* someData) {
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
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
|
||||
@@ -2875,6 +2942,7 @@ PermissionManager::RemovePermissionsWithAttributes(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return RemovePermissionsWithAttributes(pattern, aTypeInclusions,
|
||||
aTypeExceptions);
|
||||
}
|
||||
@@ -2918,7 +2986,7 @@ nsresult PermissionManager::RemovePermissionsWithAttributes(
|
||||
AddInternal(
|
||||
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
||||
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
||||
PermissionManager::eWriteToDB, false, &std::get<2>(i));
|
||||
PermissionManager::eWriteToDB, &std::get<2>(i));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -3005,7 +3073,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
||||
nsIPrincipal* aPrincipal, uint32_t aType, bool aExactHostMatch) {
|
||||
EnsureReadCompleted();
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, mTypeArray[aType]));
|
||||
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, mTypeArray[aType]));
|
||||
|
||||
nsresult rv;
|
||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
||||
@@ -3023,7 +3091,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
||||
// if the entry is expired, remove and keep looking for others.
|
||||
if (HasExpired(permEntry.mExpireType, permEntry.mExpireTime)) {
|
||||
entry = nullptr;
|
||||
RemoveFromPrincipal(aPrincipal, mTypeArray[aType]);
|
||||
RemoveFromPrincipalInternal(aPrincipal, mTypeArray[aType]);
|
||||
} else if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
entry = nullptr;
|
||||
}
|
||||
@@ -3059,7 +3127,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
||||
rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
||||
}
|
||||
MOZ_ASSERT_IF(NS_SUCCEEDED(rv),
|
||||
PermissionAvailable(principal, mTypeArray[aType]));
|
||||
PermissionAvailableInternal(principal, mTypeArray[aType]));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3135,11 +3203,13 @@ nsresult PermissionManager::RemoveAllFromMemory() {
|
||||
void PermissionManager::NotifyObserversWithPermission(
|
||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
||||
const char16_t* aData) {
|
||||
const nsString& aData) {
|
||||
nsCOMPtr<nsIPermission> permission =
|
||||
Permission::Create(aPrincipal, aType, aPermission, aExpireType,
|
||||
aExpireTime, aModificationTime);
|
||||
if (permission) NotifyObservers(permission, aData);
|
||||
if (permission) {
|
||||
NotifyObservers(permission, aData);
|
||||
}
|
||||
}
|
||||
|
||||
// notify observers that the permission list changed. there are four possible
|
||||
@@ -3149,12 +3219,17 @@ void PermissionManager::NotifyObserversWithPermission(
|
||||
// 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) {
|
||||
void PermissionManager::NotifyObservers(
|
||||
const nsCOMPtr<nsIPermission>& aPermission, const nsString& aData) {
|
||||
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
||||
if (observerService)
|
||||
if (observerService) {
|
||||
// we need to release the monitor here because the observers for the below
|
||||
// notification can call back in to permission manager and try to lock the
|
||||
// monitor again.
|
||||
MonitorAutoUnlock unlock{mMonitor};
|
||||
observerService->NotifyObservers(aPermission, kPermissionChangeNotification,
|
||||
aData);
|
||||
aData.Data());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult PermissionManager::Read(const MonitorAutoLock& aProofOfLock) {
|
||||
@@ -3239,11 +3314,7 @@ void PermissionManager::CompleteMigrations() {
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsTArray<MigrationEntry> entries;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
entries = std::move(mMigrationEntries);
|
||||
}
|
||||
nsTArray<MigrationEntry> entries = std::move(mMigrationEntries);
|
||||
|
||||
for (const MigrationEntry& entry : entries) {
|
||||
rv = UpgradeHostToOriginAndInsert(
|
||||
@@ -3251,7 +3322,7 @@ void PermissionManager::CompleteMigrations() {
|
||||
entry.mExpireTime, entry.mModificationTime,
|
||||
[&](const nsACString& aOrigin, const nsCString& aType,
|
||||
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
||||
int64_t aModificationTime) {
|
||||
int64_t aModificationTime) MOZ_REQUIRES(mMonitor) {
|
||||
MaybeAddReadEntryFromMigration(aOrigin, aType, aPermission,
|
||||
aExpireType, aExpireTime,
|
||||
aModificationTime, entry.mId);
|
||||
@@ -3267,11 +3338,7 @@ void PermissionManager::CompleteRead() {
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsTArray<ReadEntry> entries;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
entries = std::move(mReadEntries);
|
||||
}
|
||||
nsTArray<ReadEntry> entries = std::move(mReadEntries);
|
||||
|
||||
for (const ReadEntry& entry : entries) {
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
@@ -3286,8 +3353,7 @@ void PermissionManager::CompleteRead() {
|
||||
|
||||
rv = AddInternal(principal, entry.mType, entry.mPermission, entry.mId,
|
||||
entry.mExpireType, entry.mExpireTime,
|
||||
entry.mModificationTime, eDontNotify, op, false,
|
||||
&entry.mOrigin);
|
||||
entry.mModificationTime, eDontNotify, op, &entry.mOrigin);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
}
|
||||
@@ -3296,8 +3362,6 @@ 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) {
|
||||
@@ -3418,6 +3482,8 @@ void PermissionManager::UpdateDB(OperationType aOp, int64_t aID,
|
||||
bool PermissionManager::GetPermissionsFromOriginOrKey(
|
||||
const nsACString& aOrigin, const nsACString& aKey,
|
||||
nsTArray<IPC::Permission>& aPerms) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
EnsureReadCompleted();
|
||||
|
||||
aPerms.Clear();
|
||||
@@ -3479,6 +3545,8 @@ void PermissionManager::SetPermissionsWithKey(
|
||||
return;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
RefPtr<GenericNonExclusivePromise::Private> promise;
|
||||
bool foundKey =
|
||||
mPermissionKeyPromiseMap.Get(aPermissionKey, getter_AddRefs(promise));
|
||||
@@ -3518,8 +3586,7 @@ void PermissionManager::SetPermissionsWithKey(
|
||||
// will end up as now()) is fine.
|
||||
uint64_t modificationTime = 0;
|
||||
AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
|
||||
perm.expireTime, modificationTime, eNotify, eNoDBOperation,
|
||||
true /* ignoreSessionPermissions */);
|
||||
perm.expireTime, modificationTime, eDontNotify, eNoDBOperation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3649,6 +3716,12 @@ PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
|
||||
|
||||
bool PermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType) {
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return PermissionAvailableInternal(aPrincipal, aType);
|
||||
}
|
||||
|
||||
bool PermissionManager::PermissionAvailableInternal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType) {
|
||||
EnsureReadCompleted();
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
@@ -3682,6 +3755,8 @@ void PermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
|
||||
return;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
|
||||
for (auto& pair : GetAllKeysForPrincipal(aPrincipal)) {
|
||||
RefPtr<GenericNonExclusivePromise::Private> promise;
|
||||
@@ -3721,12 +3796,9 @@ void PermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
|
||||
}
|
||||
|
||||
void PermissionManager::EnsureReadCompleted() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mState == eInitializing) {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
while (mState == eInitializing) {
|
||||
mMonitor.AssertCurrentThreadOwns();
|
||||
mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
@@ -3736,6 +3808,9 @@ void PermissionManager::EnsureReadCompleted() {
|
||||
MOZ_CRASH("This state is impossible!");
|
||||
|
||||
case eDBInitialized:
|
||||
// child processes transitions from eInitializing -> eReady
|
||||
ENSURE_NOT_CHILD_PROCESS_NORET;
|
||||
|
||||
mState = eReady;
|
||||
|
||||
CompleteMigrations();
|
||||
@@ -3748,7 +3823,7 @@ void PermissionManager::EnsureReadCompleted() {
|
||||
[[fallthrough]];
|
||||
|
||||
case eClosed:
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid state");
|
||||
@@ -3842,7 +3917,7 @@ void PermissionManager::ConsumeDefaultsInputStream(
|
||||
0,
|
||||
[&](const nsACString& aOrigin, const nsCString& aType,
|
||||
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
||||
int64_t aModificationTime) {
|
||||
int64_t aModificationTime) MOZ_REQUIRES(mMonitor) {
|
||||
AddDefaultEntryForImport(aOrigin, aType, aPermission, aProofOfLock);
|
||||
return NS_OK;
|
||||
});
|
||||
@@ -3922,8 +3997,6 @@ nsresult PermissionManager::ImportLatestDefaults() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mState == eReady);
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
for (const DefaultEntry& entry : mDefaultEntriesForImport) {
|
||||
Unused << ImportDefaultEntry(entry);
|
||||
}
|
||||
@@ -3993,8 +4066,8 @@ PermissionManager::CommonPrepareToTestPermission(
|
||||
// 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()) {
|
||||
auto* ep = basePrin->As<ExpandedPrincipal>();
|
||||
for (const auto& prin : ep->AllowList()) {
|
||||
uint32_t perm;
|
||||
nsresult rv =
|
||||
CommonTestPermission(prin, typeIndex, aType, &perm, defaultPermission,
|
||||
@@ -4081,6 +4154,7 @@ nsresult PermissionManager::TestPermissionWithoutDefaultsFromPrincipal(
|
||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t* aPermission) {
|
||||
MOZ_ASSERT(!HasDefaultPref(aType));
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||
nsIPermissionManager::UNKNOWN_ACTION, true, false,
|
||||
true);
|
||||
@@ -4117,6 +4191,9 @@ NS_IMETHODIMP PermissionManager::BlockShutdown(
|
||||
StaticMutexAutoLock lock(sCreationMutex);
|
||||
sInstanceDead = true;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock{mMonitor};
|
||||
|
||||
RemoveIdleDailyMaintenanceJob();
|
||||
RemoveAllFromMemory();
|
||||
// CloseDB does async work and will call FinishAsyncShutdown once done.
|
||||
|
||||
@@ -53,8 +53,6 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIAsyncShutdownBlocker {
|
||||
friend class dom::ContentChild;
|
||||
|
||||
public:
|
||||
class PermissionEntry {
|
||||
public:
|
||||
@@ -145,15 +143,21 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
}
|
||||
|
||||
inline int32_t GetPermissionIndex(uint32_t aType) const {
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType) return i;
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i) {
|
||||
if (mPermissions[i].mType == aType) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline PermissionEntry GetPermission(uint32_t aType) const {
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
||||
if (mPermissions[i].mType == aType) return mPermissions[i];
|
||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i) {
|
||||
if (mPermissions[i].mType == aType) {
|
||||
return mPermissions[i];
|
||||
}
|
||||
}
|
||||
|
||||
// unknown permission... return relevant data
|
||||
return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
|
||||
@@ -173,7 +177,6 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
PermissionManager();
|
||||
static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
|
||||
static already_AddRefed<PermissionManager> GetInstance();
|
||||
nsresult Init();
|
||||
|
||||
// enums for AddInternal()
|
||||
enum OperationType {
|
||||
@@ -197,7 +200,7 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
nsresult RemovePermissionsWithAttributes(
|
||||
OriginAttributesPattern& aPattern,
|
||||
const nsTArray<nsCString>& aTypeInclusions = {},
|
||||
const nsTArray<nsCString>& aTypeExceptions = {});
|
||||
const nsTArray<nsCString>& aTypeExceptions = {}) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
/**
|
||||
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
|
||||
@@ -368,8 +371,18 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
static void MaybeStripOriginAttributes(bool aForceStrip,
|
||||
OriginAttributes& aOriginAttributes);
|
||||
|
||||
nsresult Add(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 nsACString* aOriginString = nullptr,
|
||||
const bool aAllowPersistInPrivateBrowsing = false);
|
||||
|
||||
private:
|
||||
~PermissionManager();
|
||||
nsresult Init();
|
||||
|
||||
static StaticMutex sCreationMutex;
|
||||
// Holding our singleton instance until shutdown.
|
||||
static StaticRefPtr<PermissionManager> sInstanceHolder
|
||||
@@ -389,10 +402,12 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
*/
|
||||
nsresult GetStripPermsForPrincipal(nsIPrincipal* aPrincipal,
|
||||
bool aSiteScopePermissions,
|
||||
nsTArray<PermissionEntry>& aResult);
|
||||
nsTArray<PermissionEntry>& aResult)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Returns -1 on failure
|
||||
int32_t GetTypeIndex(const nsACString& aType, bool aAdd);
|
||||
int32_t GetTypeIndex(const nsACString& aType, bool aAdd = false)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Returns whether the given combination of expire type and expire time are
|
||||
// expired. Note that EXPIRE_SESSION only honors expireTime if it is nonzero.
|
||||
@@ -404,7 +419,8 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// site-scoped are used.
|
||||
nsresult GetAllForPrincipalHelper(nsIPrincipal* aPrincipal,
|
||||
bool aSiteScopePermissions,
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult);
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Returns true if the principal can be used for getting / setting
|
||||
// permissions. If the principal can not be used an error code may be
|
||||
@@ -418,7 +434,12 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// accepts host on the format "<foo>". This will perform an exact match lookup
|
||||
// as the string doesn't contain any dots.
|
||||
PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal,
|
||||
uint32_t aType, bool aExactHostMatch);
|
||||
uint32_t aType, bool aExactHostMatch)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult RemoveFromPrincipalInternal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Returns PermissionHashKey for a given { host, isInBrowserElement } tuple.
|
||||
// This is not simply using PermissionKey because we will walk-up domains in
|
||||
@@ -427,7 +448,13 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// as the string doesn't contain any dots.
|
||||
PermissionHashKey* GetPermissionHashKey(
|
||||
nsIURI* aURI, const OriginAttributes* aOriginAttributes, uint32_t aType,
|
||||
bool aExactHostMatch);
|
||||
bool aExactHostMatch) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// to be used by internal caller as a helper method; monitor lock must be
|
||||
// held.
|
||||
bool PermissionAvailableInternal(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aType)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// The int32_t is the type index, the nsresult is an early bail-out return
|
||||
// code.
|
||||
@@ -436,59 +463,62 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
|
||||
uint32_t* aPermission, uint32_t aDefaultPermission,
|
||||
bool aDefaultPermissionIsValid, bool aExactHostMatch,
|
||||
bool aIncludingSession);
|
||||
bool aIncludingSession) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// 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)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// 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)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
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);
|
||||
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) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// 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 nsACString& aType, uint32_t* aPermission, bool aExactHostMatch,
|
||||
bool aIncludingSession);
|
||||
bool aIncludingSession) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult OpenDatabase(nsIFile* permissionsFile);
|
||||
|
||||
void InitDB(bool aRemoveFile);
|
||||
nsresult TryInitDB(bool aRemoveFile, nsIInputStream* aDefaultsInputStream);
|
||||
void InitDB(bool aRemoveFile) MOZ_REQUIRES(mMonitor);
|
||||
nsresult TryInitDB(bool aRemoveFile, nsIInputStream* aDefaultsInputStream,
|
||||
const MonitorAutoLock& aProofOfLock)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
void AddIdleDailyMaintenanceJob();
|
||||
void RemoveIdleDailyMaintenanceJob();
|
||||
void PerformIdleDailyMaintenance();
|
||||
void PerformIdleDailyMaintenance() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult ImportLatestDefaults();
|
||||
nsresult ImportLatestDefaults() MOZ_REQUIRES(mMonitor);
|
||||
already_AddRefed<nsIInputStream> GetDefaultsInputStream();
|
||||
void ConsumeDefaultsInputStream(nsIInputStream* aDefaultsInputStream,
|
||||
const MonitorAutoLock& aProofOfLock);
|
||||
void ConsumeDefaultsInputStream(nsIInputStream* aInputStream,
|
||||
const MonitorAutoLock& aProofOfLock)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult CreateTable();
|
||||
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);
|
||||
void NotifyObserversWithPermission(
|
||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
||||
const nsString& aData) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
void NotifyObservers(const nsCOMPtr<nsIPermission>& aPermission,
|
||||
const nsString& aData) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Finalize all statements, close the DB and null it.
|
||||
enum CloseDBNextOp {
|
||||
@@ -496,24 +526,25 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
eRebuldOnSuccess,
|
||||
eShutdown,
|
||||
};
|
||||
void CloseDB(CloseDBNextOp aNextOp);
|
||||
void CloseDB(CloseDBNextOp aNextOp) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult RemoveAllInternal(bool aNotifyObservers);
|
||||
nsresult RemoveAllFromMemory();
|
||||
nsresult RemoveAllInternal(bool aNotifyObservers) MOZ_REQUIRES(mMonitor);
|
||||
nsresult RemoveAllFromMemory() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
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);
|
||||
int64_t aModificationTime) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
/**
|
||||
* This method removes all permissions modified after the specified time.
|
||||
*/
|
||||
nsresult RemoveAllModifiedSince(int64_t aModificationTime);
|
||||
nsresult RemoveAllModifiedSince(int64_t aModificationTime)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Removes all permissions with a private browsing principal (i.e.
|
||||
// privateBrowsingId OA != 0).
|
||||
nsresult RemoveAllForPrivateBrowsing();
|
||||
nsresult RemoveAllForPrivateBrowsing() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Helper function which removes all permissions for which aCondition
|
||||
// evaluates to true.
|
||||
@@ -521,47 +552,49 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
const std::function<bool(const PermissionEntry& aPermEntry,
|
||||
const nsCOMPtr<nsIPrincipal>& aPrincipal)>&
|
||||
aCondition,
|
||||
bool aComputePrincipalForCondition = true);
|
||||
bool aComputePrincipalForCondition = true) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Overload of RemovePermissionEntries allowing aCondition not to take
|
||||
// aPrincipal as an argument.
|
||||
nsresult RemovePermissionEntries(
|
||||
const std::function<bool(const PermissionEntry& aPermEntry)>& aCondition);
|
||||
const std::function<bool(const PermissionEntry& aPermEntry)>& aCondition)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// Helper function which returns all permissions for which aCondition
|
||||
// evaluates to true.
|
||||
nsresult GetPermissionEntries(
|
||||
const std::function<bool(const PermissionEntry& aPermEntry)>& aCondition,
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult);
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult) MOZ_REQUIRES(mMonitor);
|
||||
|
||||
// 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();
|
||||
void EnsureReadCompleted() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
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,
|
||||
const bool aAllowPersistInPrivateBrowsing = false);
|
||||
const bool aAllowPersistInPrivateBrowsing = false)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
void MaybeAddReadEntryFromMigration(const nsACString& aOrigin,
|
||||
const nsCString& aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime,
|
||||
int64_t aModificationTime, int64_t aId);
|
||||
int64_t aModificationTime, int64_t aId)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsCOMPtr<nsIAsyncShutdownClient> GetAsyncShutdownBarrier() const;
|
||||
|
||||
void FinishAsyncShutdown();
|
||||
|
||||
nsRefPtrHashtable<nsCStringHashKey, GenericNonExclusivePromise::Private>
|
||||
mPermissionKeyPromiseMap;
|
||||
mPermissionKeyPromiseMap MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
nsCOMPtr<nsIFile> mPermissionsFile;
|
||||
nsCOMPtr<nsIFile> mPermissionsFile MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
// 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
|
||||
@@ -597,7 +630,8 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
mPermission(0),
|
||||
mExpireType(0),
|
||||
mExpireTime(0),
|
||||
mModificationTime(0) {}
|
||||
mModificationTime(0),
|
||||
mFromMigration(false) {}
|
||||
|
||||
nsCString mOrigin;
|
||||
nsCString mType;
|
||||
@@ -614,7 +648,7 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// 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;
|
||||
nsTArray<ReadEntry> mReadEntries MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
// A single entry, from the database.
|
||||
struct MigrationEntry {
|
||||
@@ -638,7 +672,7 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// 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;
|
||||
nsTArray<MigrationEntry> mMigrationEntries MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
// A single entry from the defaults URL.
|
||||
struct DefaultEntry {
|
||||
@@ -649,37 +683,39 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
|
||||
// List of entries read from the default settings.
|
||||
// This array is protected by the monitor.
|
||||
nsTArray<DefaultEntry> mDefaultEntriesForImport;
|
||||
nsTArray<DefaultEntry> mDefaultEntriesForImport MOZ_GUARDED_BY(mMonitor);
|
||||
// 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);
|
||||
const MonitorAutoLock& aProofOfLock)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
// 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);
|
||||
nsresult ImportDefaultEntry(const DefaultEntry& aDefaultEntry)
|
||||
MOZ_REQUIRES(mMonitor);
|
||||
|
||||
nsresult Read(const MonitorAutoLock& aProofOfLock);
|
||||
void CompleteRead();
|
||||
nsresult Read(const MonitorAutoLock& aProofOfLock) MOZ_REQUIRES(mMonitor);
|
||||
void CompleteRead() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
void CompleteMigrations();
|
||||
void CompleteMigrations() MOZ_REQUIRES(mMonitor);
|
||||
|
||||
bool mMemoryOnlyDB;
|
||||
Atomic<bool> mMemoryOnlyDB;
|
||||
|
||||
nsTHashtable<PermissionHashKey> mPermissionTable;
|
||||
nsTHashtable<PermissionHashKey> mPermissionTable MOZ_GUARDED_BY(mMonitor);
|
||||
// a unique, monotonically increasing id used to identify each database entry
|
||||
int64_t mLargestID;
|
||||
Atomic<int64_t> mLargestID;
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> mDefaultPrefBranch;
|
||||
nsCOMPtr<nsIPrefBranch> mDefaultPrefBranch MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
// 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;
|
||||
Vector<nsCString, 512> mTypeArray MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsCOMPtr<nsIThread> mThread MOZ_GUARDED_BY(mMonitor);
|
||||
|
||||
struct ThreadBoundData {
|
||||
nsCOMPtr<mozIStorageConnection> mDBConn;
|
||||
@@ -689,9 +725,6 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
|
||||
};
|
||||
ThreadBound<ThreadBoundData> mThreadBoundData;
|
||||
|
||||
friend class DeleteFromMozHostListener;
|
||||
friend class CloseDatabaseListener;
|
||||
};
|
||||
|
||||
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}
|
||||
|
||||
Reference in New Issue
Block a user