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.
|
// child processes don't care about modification time.
|
||||||
int64_t modificationTime = 0;
|
int64_t modificationTime = 0;
|
||||||
|
|
||||||
permissionManager->AddInternal(
|
permissionManager->Add(
|
||||||
principal, nsCString(permission.type), permission.capability, 0,
|
principal, nsCString(permission.type), permission.capability, 0,
|
||||||
permission.expireType, permission.expireTime, modificationTime,
|
permission.expireType, permission.expireTime, modificationTime,
|
||||||
PermissionManager::eNotify, PermissionManager::eNoDBOperation);
|
PermissionManager::eNotify, PermissionManager::eNoDBOperation);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ constexpr int64_t cIDPermissionIsDefault = -1;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool IsChildProcess() { return XRE_IsContentProcess(); }
|
inline bool IsChildProcess() { return XRE_IsContentProcess(); }
|
||||||
|
|
||||||
void LogToConsole(const nsAString& aMsg) {
|
void LogToConsole(const nsAString& aMsg) {
|
||||||
nsCOMPtr<nsIConsoleService> console(
|
nsCOMPtr<nsIConsoleService> console(
|
||||||
@@ -697,6 +697,8 @@ PermissionManager::PermissionManager()
|
|||||||
mLargestID(0) {}
|
mLargestID(0) {}
|
||||||
|
|
||||||
PermissionManager::~PermissionManager() {
|
PermissionManager::~PermissionManager() {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// NOTE: Make sure to reject each of the promises in mPermissionKeyPromiseMap
|
// NOTE: Make sure to reject each of the promises in mPermissionKeyPromiseMap
|
||||||
// before destroying.
|
// before destroying.
|
||||||
for (const auto& promise : mPermissionKeyPromiseMap.Values()) {
|
for (const auto& promise : mPermissionKeyPromiseMap.Values()) {
|
||||||
@@ -755,6 +757,11 @@ nsresult PermissionManager::Init() {
|
|||||||
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
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
|
// 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.
|
// permission settings to disk, but keep them in a memory-only database.
|
||||||
mMemoryOnlyDB = Preferences::GetBool("permissions.memory_only", false);
|
mMemoryOnlyDB = Preferences::GetBool("permissions.memory_only", false);
|
||||||
@@ -842,11 +849,9 @@ nsresult PermissionManager::OpenDatabase(nsIFile* aPermissionsFile) {
|
|||||||
|
|
||||||
void PermissionManager::InitDB(bool aRemoveFile) {
|
void PermissionManager::InitDB(bool aRemoveFile) {
|
||||||
mState = eInitializing;
|
mState = eInitializing;
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
{
|
mReadEntries.Clear();
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
mReadEntries.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto readyIfFailed = MakeScopeExit([&]() {
|
auto readyIfFailed = MakeScopeExit([&]() {
|
||||||
// ignore failure here, since it's non-fatal (we can run fine without
|
// 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;
|
RefPtr<PermissionManager> self = this;
|
||||||
mThread->Dispatch(NS_NewRunnableFunction(
|
mThread->Dispatch(NS_NewRunnableFunction(
|
||||||
"PermissionManager::InitDB", [self, aRemoveFile, defaultsInputStream] {
|
"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));
|
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||||
|
|
||||||
// This extra runnable calls EnsureReadCompleted to finialize the
|
// This extra runnable calls EnsureReadCompleted to finialize the
|
||||||
// initialization. If there is something blocked by the monitor, it will
|
// initialization. If there is something blocked by the monitor, it will
|
||||||
// be NOP.
|
// be NOP.
|
||||||
NS_DispatchToMainThread(
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
NS_NewRunnableFunction("PermissionManager::InitDB-MainThread",
|
"PermissionManager::InitDB-MainThread", [self] {
|
||||||
[self] { self->EnsureReadCompleted(); }));
|
MonitorAutoLock lock{self->mMonitor};
|
||||||
|
self->EnsureReadCompleted();
|
||||||
|
}));
|
||||||
|
|
||||||
self->mMonitor.Notify();
|
self->mMonitor.Notify();
|
||||||
}));
|
}));
|
||||||
@@ -893,11 +902,10 @@ void PermissionManager::InitDB(bool aRemoveFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult PermissionManager::TryInitDB(bool aRemoveFile,
|
nsresult PermissionManager::TryInitDB(bool aRemoveFile,
|
||||||
nsIInputStream* aDefaultsInputStream) {
|
nsIInputStream* aDefaultsInputStream,
|
||||||
|
const MonitorAutoLock& aProofOfLock) {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
|
|
||||||
auto raii = MakeScopeExit([&]() {
|
auto raii = MakeScopeExit([&]() {
|
||||||
if (aDefaultsInputStream) {
|
if (aDefaultsInputStream) {
|
||||||
aDefaultsInputStream->Close();
|
aDefaultsInputStream->Close();
|
||||||
@@ -1571,11 +1579,11 @@ nsresult PermissionManager::TryInitDB(bool aRemoveFile,
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Always import default permissions.
|
// Always import default permissions.
|
||||||
ConsumeDefaultsInputStream(aDefaultsInputStream, lock);
|
ConsumeDefaultsInputStream(aDefaultsInputStream, aProofOfLock);
|
||||||
|
|
||||||
// check whether to import or just read in the db
|
// check whether to import or just read in the db
|
||||||
if (tableExists) {
|
if (tableExists) {
|
||||||
rv = Read(lock);
|
rv = Read(aProofOfLock);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1703,10 +1711,11 @@ PermissionManager::AddFromPrincipalAndPersistInPrivateBrowsing(
|
|||||||
// A modificationTime of zero will cause AddInternal to use now().
|
// A modificationTime of zero will cause AddInternal to use now().
|
||||||
int64_t modificationTime = 0;
|
int64_t modificationTime = 0;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
return AddInternal(aPrincipal, aType, aPermission, 0,
|
return AddInternal(aPrincipal, aType, aPermission, 0,
|
||||||
nsIPermissionManager::EXPIRE_NEVER,
|
nsIPermissionManager::EXPIRE_NEVER,
|
||||||
/* aExpireTime */ 0, modificationTime, eNotify, eWriteToDB,
|
/* aExpireTime */ 0, modificationTime, eNotify, eWriteToDB,
|
||||||
/* aIgnoreSessionPermissions */ false,
|
|
||||||
/* aOriginString*/ nullptr,
|
/* aOriginString*/ nullptr,
|
||||||
/* aAllowPersistInPrivateBrowsing */ true);
|
/* aAllowPersistInPrivateBrowsing */ true);
|
||||||
}
|
}
|
||||||
@@ -1731,11 +1740,10 @@ PermissionManager::AddDefaultFromPrincipal(nsIPrincipal* aPrincipal,
|
|||||||
origin);
|
origin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
DefaultEntry entry;
|
DefaultEntry entry;
|
||||||
{
|
{
|
||||||
// Lock for mDefaultEntriesForImport
|
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
|
|
||||||
// Try to update existing entry in mDefaultEntriesForImport, which will
|
// Try to update existing entry in mDefaultEntriesForImport, which will
|
||||||
// later be used to restore the default permissions when permissions are
|
// later be used to restore the default permissions when permissions are
|
||||||
// cleared
|
// cleared
|
||||||
@@ -1801,7 +1809,7 @@ PermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
|
|||||||
|
|
||||||
// A modificationTime of zero will cause AddInternal to use now().
|
// A modificationTime of zero will cause AddInternal to use now().
|
||||||
int64_t modificationTime = 0;
|
int64_t modificationTime = 0;
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return AddInternal(aPrincipal, aType, aPermission, 0, aExpireType,
|
return AddInternal(aPrincipal, aType, aPermission, 0, aExpireType,
|
||||||
aExpireTime, modificationTime, eNotify, eWriteToDB);
|
aExpireTime, modificationTime, eNotify, eWriteToDB);
|
||||||
}
|
}
|
||||||
@@ -1823,19 +1831,36 @@ PermissionManager::TestAddFromPrincipalByTime(nsIPrincipal* aPrincipal,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return AddInternal(aPrincipal, aType, aPermission, 0,
|
return AddInternal(aPrincipal, aType, aPermission, 0,
|
||||||
nsIPermissionManager::EXPIRE_NEVER, 0, aModificationTime,
|
nsIPermissionManager::EXPIRE_NEVER, 0, aModificationTime,
|
||||||
eNotify, eWriteToDB);
|
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(
|
nsresult PermissionManager::AddInternal(
|
||||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
||||||
int64_t aID, uint32_t aExpireType, int64_t aExpireTime,
|
int64_t aID, uint32_t aExpireType, int64_t aExpireTime,
|
||||||
int64_t aModificationTime, NotifyOperationType aNotifyOperation,
|
int64_t aModificationTime, NotifyOperationType aNotifyOperation,
|
||||||
DBOperationType aDBOperation, const bool aIgnoreSessionPermissions,
|
DBOperationType aDBOperation, const nsACString* aOriginString,
|
||||||
const nsACString* aOriginString,
|
|
||||||
const bool aAllowPersistInPrivateBrowsing) {
|
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.
|
// If this is a default permission, no changes should not be written to disk.
|
||||||
MOZ_ASSERT((aID != cIDPermissionIsDefault) || (aDBOperation != eWriteToDB));
|
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
|
// look up the type index
|
||||||
int32_t typeIndex = GetTypeIndex(aType, true);
|
int32_t typeIndex = GetTypeIndex(aType, true);
|
||||||
@@ -1934,10 +1959,11 @@ nsresult PermissionManager::AddInternal(
|
|||||||
OperationType op;
|
OperationType op;
|
||||||
int32_t index = entry->GetPermissionIndex(typeIndex);
|
int32_t index = entry->GetPermissionIndex(typeIndex);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
|
if (aPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||||
op = eOperationNone;
|
op = eOperationNone;
|
||||||
else
|
} else {
|
||||||
op = eOperationAdding;
|
op = eOperationAdding;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
|
||||||
@@ -2010,7 +2036,7 @@ nsresult PermissionManager::AddInternal(
|
|||||||
if (aNotifyOperation == eNotify) {
|
if (aNotifyOperation == eNotify) {
|
||||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||||
aPermission, aExpireType, aExpireTime,
|
aPermission, aExpireType, aExpireTime,
|
||||||
aModificationTime, u"added");
|
aModificationTime, u"added"_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -2029,17 +2055,18 @@ nsresult PermissionManager::AddInternal(
|
|||||||
|
|
||||||
entry->GetPermissions().RemoveElementAt(index);
|
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
|
// We care only about the id here so we pass dummy values for all other
|
||||||
// parameters.
|
// parameters.
|
||||||
UpdateDB(op, id, ""_ns, ""_ns, 0, nsIPermissionManager::EXPIRE_NEVER, 0,
|
UpdateDB(op, id, ""_ns, ""_ns, 0, nsIPermissionManager::EXPIRE_NEVER, 0,
|
||||||
0);
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
if (aNotifyOperation == eNotify) {
|
if (aNotifyOperation == eNotify) {
|
||||||
NotifyObserversWithPermission(
|
NotifyObserversWithPermission(
|
||||||
aPrincipal, mTypeArray[typeIndex], oldPermissionEntry.mPermission,
|
aPrincipal, mTypeArray[typeIndex], oldPermissionEntry.mPermission,
|
||||||
oldPermissionEntry.mExpireType, oldPermissionEntry.mExpireTime,
|
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.
|
// If there are no more permissions stored for that entry, clear it.
|
||||||
@@ -2127,7 +2154,7 @@ nsresult PermissionManager::AddInternal(
|
|||||||
if (aNotifyOperation == eNotify) {
|
if (aNotifyOperation == eNotify) {
|
||||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||||
aPermission, aExpireType, aExpireTime,
|
aPermission, aExpireType, aExpireTime,
|
||||||
aModificationTime, u"changed");
|
aModificationTime, u"changed"_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -2177,7 +2204,7 @@ nsresult PermissionManager::AddInternal(
|
|||||||
if (aNotifyOperation == eNotify) {
|
if (aNotifyOperation == eNotify) {
|
||||||
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex],
|
||||||
aPermission, aExpireType, aExpireTime,
|
aPermission, aExpireType, aExpireTime,
|
||||||
aModificationTime, u"changed");
|
aModificationTime, u"changed"_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@@ -2190,6 +2217,14 @@ NS_IMETHODIMP
|
|||||||
PermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
|
PermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
|
||||||
const nsACString& aType) {
|
const nsACString& aType) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
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);
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||||
|
|
||||||
// System principals are never added to the database, no need to remove them.
|
// 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);
|
rv = aPerm->GetType(type);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// Permissions are uniquely identified by their principal and type.
|
// Permissions are uniquely identified by their principal and type.
|
||||||
// We remove the permission using these two pieces of data.
|
// We remove the permission using these two pieces of data.
|
||||||
return RemoveFromPrincipal(principal, type);
|
return RemoveFromPrincipalInternal(principal, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PermissionManager::RemoveAll() {
|
PermissionManager::RemoveAll() {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return RemoveAllInternal(true);
|
return RemoveAllInternal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PermissionManager::RemoveAllSince(int64_t aSince) {
|
PermissionManager::RemoveAllSince(int64_t aSince) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return RemoveAllModifiedSince(aSince);
|
return RemoveAllModifiedSince(aSince);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2243,6 +2283,7 @@ PermissionManager::RemoveAllExceptTypes(
|
|||||||
const nsTArray<nsCString>& aTypeExceptions) {
|
const nsTArray<nsCString>& aTypeExceptions) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
// Need to make sure read is done before we get the type index. Type indexes
|
// Need to make sure read is done before we get the type index. Type indexes
|
||||||
// are populated from DB.
|
// are populated from DB.
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
@@ -2251,9 +2292,10 @@ PermissionManager::RemoveAllExceptTypes(
|
|||||||
return RemoveAllInternal(true);
|
return RemoveAllInternal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RemovePermissionEntries([&](const PermissionEntry& aPermEntry) {
|
return RemovePermissionEntries(
|
||||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]);
|
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||||
});
|
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult PermissionManager::RemovePermissionEntries(
|
nsresult PermissionManager::RemovePermissionEntries(
|
||||||
@@ -2298,7 +2340,7 @@ nsresult PermissionManager::RemovePermissionEntries(
|
|||||||
AddInternal(
|
AddInternal(
|
||||||
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
||||||
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
||||||
PermissionManager::eWriteToDB, false, &std::get<2>(i));
|
PermissionManager::eWriteToDB, &std::get<2>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -2318,6 +2360,8 @@ NS_IMETHODIMP
|
|||||||
PermissionManager::RemoveByType(const nsACString& aType) {
|
PermissionManager::RemoveByType(const nsACString& aType) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// Need to make sure read is done before we get the type index. Type indexes
|
// Need to make sure read is done before we get the type index. Type indexes
|
||||||
// are populated from DB.
|
// are populated from DB.
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
@@ -2340,6 +2384,8 @@ PermissionManager::RemoveByTypeSince(const nsACString& aType,
|
|||||||
int64_t aModificationTime) {
|
int64_t aModificationTime) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// Need to make sure read is done before we get the type index. Type indexes
|
// Need to make sure read is done before we get the type index. Type indexes
|
||||||
// are populated from DB.
|
// are populated from DB.
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
@@ -2363,14 +2409,17 @@ PermissionManager::RemoveAllSinceWithTypeExceptions(
|
|||||||
int64_t aModificationTime, const nsTArray<nsCString>& aTypeExceptions) {
|
int64_t aModificationTime, const nsTArray<nsCString>& aTypeExceptions) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// Need to make sure read is done before we get the type index. Type indexes
|
// Need to make sure read is done before we get the type index. Type indexes
|
||||||
// are populated from DB.
|
// are populated from DB.
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
return RemovePermissionEntries([&](const PermissionEntry& aPermEntry) {
|
return RemovePermissionEntries(
|
||||||
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]) &&
|
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||||
aModificationTime <= aPermEntry.mModificationTime;
|
return !aTypeExceptions.Contains(mTypeArray[aPermEntry.mType]) &&
|
||||||
});
|
aModificationTime <= aPermEntry.mModificationTime;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
||||||
@@ -2397,7 +2446,8 @@ void PermissionManager::CloseDB(CloseDBNextOp aNextOp) {
|
|||||||
data->mDBConn = nullptr;
|
data->mDBConn = nullptr;
|
||||||
|
|
||||||
if (aNextOp == eRebuldOnSuccess) {
|
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() {
|
nsresult PermissionManager::RemoveAllFromIPC() {
|
||||||
MOZ_ASSERT(IsChildProcess());
|
MOZ_ASSERT(IsChildProcess());
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
// Remove from memory and notify immediately. Since the in-memory
|
// Remove from memory and notify immediately. Since the in-memory
|
||||||
// database is authoritative, we do not need confirmation from the
|
// database is authoritative, we do not need confirmation from the
|
||||||
// on-disk database to notify observers.
|
// on-disk database to notify observers.
|
||||||
@@ -2441,7 +2493,7 @@ nsresult PermissionManager::RemoveAllInternal(bool aNotifyObservers) {
|
|||||||
ImportLatestDefaults();
|
ImportLatestDefaults();
|
||||||
|
|
||||||
if (aNotifyObservers) {
|
if (aNotifyObservers) {
|
||||||
NotifyObservers(nullptr, u"cleared");
|
NotifyObservers(nullptr, u"cleared"_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<PermissionManager> self = this;
|
RefPtr<PermissionManager> self = this;
|
||||||
@@ -2458,8 +2510,10 @@ nsresult PermissionManager::RemoveAllInternal(bool aNotifyObservers) {
|
|||||||
data->mDBConn->ExecuteSimpleSQL("DELETE FROM moz_perms"_ns);
|
data->mDBConn->ExecuteSimpleSQL("DELETE FROM moz_perms"_ns);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
"PermissionManager::RemoveAllInternal-Failure",
|
"PermissionManager::RemoveAllInternal-Failure", [self] {
|
||||||
[self] { self->CloseDB(eRebuldOnSuccess); }));
|
MonitorAutoLock lock{self->mMonitor};
|
||||||
|
self->CloseDB(eRebuldOnSuccess);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -2470,6 +2524,7 @@ NS_IMETHODIMP
|
|||||||
PermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
PermissionManager::TestExactPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||||
const nsACString& aType,
|
const nsACString& aType,
|
||||||
uint32_t* aPermission) {
|
uint32_t* aPermission) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||||
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
||||||
true);
|
true);
|
||||||
@@ -2479,6 +2534,7 @@ NS_IMETHODIMP
|
|||||||
PermissionManager::TestExactPermanentPermission(nsIPrincipal* aPrincipal,
|
PermissionManager::TestExactPermanentPermission(nsIPrincipal* aPrincipal,
|
||||||
const nsACString& aType,
|
const nsACString& aType,
|
||||||
uint32_t* aPermission) {
|
uint32_t* aPermission) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||||
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
nsIPermissionManager::UNKNOWN_ACTION, false, true,
|
||||||
false);
|
false);
|
||||||
@@ -2488,6 +2544,7 @@ NS_IMETHODIMP
|
|||||||
PermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
PermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
|
||||||
const nsACString& aType,
|
const nsACString& aType,
|
||||||
uint32_t* aPermission) {
|
uint32_t* aPermission) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||||
nsIPermissionManager::UNKNOWN_ACTION, false,
|
nsIPermissionManager::UNKNOWN_ACTION, false,
|
||||||
false, true);
|
false, true);
|
||||||
@@ -2501,6 +2558,8 @@ PermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
|
|||||||
NS_ENSURE_ARG_POINTER(aPrincipal);
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
||||||
*aResult = nullptr;
|
*aResult = nullptr;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
if (aPrincipal->IsSystemPrincipal()) {
|
if (aPrincipal->IsSystemPrincipal()) {
|
||||||
@@ -2512,7 +2571,7 @@ PermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal,
|
|||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, aType));
|
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, aType));
|
||||||
|
|
||||||
int32_t typeIndex = GetTypeIndex(aType, false);
|
int32_t typeIndex = GetTypeIndex(aType, false);
|
||||||
// If type == -1, the type isn't known,
|
// If type == -1, the type isn't known,
|
||||||
@@ -2570,7 +2629,7 @@ nsresult PermissionManager::CommonTestPermissionInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(prin);
|
MOZ_ASSERT(prin);
|
||||||
MOZ_ASSERT(PermissionAvailable(prin, aType));
|
MOZ_ASSERT(PermissionAvailableInternal(prin, aType));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2587,7 +2646,6 @@ nsresult PermissionManager::CommonTestPermissionInternal(
|
|||||||
*aPermission = aIncludingSession
|
*aPermission = aIncludingSession
|
||||||
? entry->GetPermission(aTypeIndex).mPermission
|
? entry->GetPermission(aTypeIndex).mPermission
|
||||||
: entry->GetPermission(aTypeIndex).mNonSessionPermission;
|
: entry->GetPermission(aTypeIndex).mNonSessionPermission;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2649,6 +2707,7 @@ nsresult PermissionManager::GetPermissionEntries(
|
|||||||
|
|
||||||
NS_IMETHODIMP PermissionManager::GetAll(
|
NS_IMETHODIMP PermissionManager::GetAll(
|
||||||
nsTArray<RefPtr<nsIPermission>>& aResult) {
|
nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return GetPermissionEntries(
|
return GetPermissionEntries(
|
||||||
[](const PermissionEntry& aPermEntry) { return true; }, aResult);
|
[](const PermissionEntry& aPermEntry) { return true; }, aResult);
|
||||||
}
|
}
|
||||||
@@ -2660,8 +2719,10 @@ NS_IMETHODIMP PermissionManager::GetAllByTypeSince(
|
|||||||
if (aSince > (PR_Now() / PR_USEC_PER_MSEC)) {
|
if (aSince > (PR_Now() / PR_USEC_PER_MSEC)) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return GetPermissionEntries(
|
return GetPermissionEntries(
|
||||||
[&](const PermissionEntry& aPermEntry) {
|
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||||
return mTypeArray[aPermEntry.mType].Equals(aPrefix) &&
|
return mTypeArray[aPermEntry.mType].Equals(aPrefix) &&
|
||||||
aSince <= aPermEntry.mModificationTime;
|
aSince <= aPermEntry.mModificationTime;
|
||||||
},
|
},
|
||||||
@@ -2670,8 +2731,9 @@ NS_IMETHODIMP PermissionManager::GetAllByTypeSince(
|
|||||||
|
|
||||||
NS_IMETHODIMP PermissionManager::GetAllWithTypePrefix(
|
NS_IMETHODIMP PermissionManager::GetAllWithTypePrefix(
|
||||||
const nsACString& aPrefix, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
const nsACString& aPrefix, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return GetPermissionEntries(
|
return GetPermissionEntries(
|
||||||
[&](const PermissionEntry& aPermEntry) {
|
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||||
return StringBeginsWith(mTypeArray[aPermEntry.mType], aPrefix);
|
return StringBeginsWith(mTypeArray[aPermEntry.mType], aPrefix);
|
||||||
},
|
},
|
||||||
aResult);
|
aResult);
|
||||||
@@ -2684,8 +2746,9 @@ NS_IMETHODIMP PermissionManager::GetAllByTypes(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return GetPermissionEntries(
|
return GetPermissionEntries(
|
||||||
[&](const PermissionEntry& aPermEntry) {
|
[&](const PermissionEntry& aPermEntry) MOZ_REQUIRES(mMonitor) {
|
||||||
return aTypes.Contains(mTypeArray[aPermEntry.mType]);
|
return aTypes.Contains(mTypeArray[aPermEntry.mType]);
|
||||||
},
|
},
|
||||||
aResult);
|
aResult);
|
||||||
@@ -2801,9 +2864,11 @@ PermissionManager::GetAllForPrincipal(
|
|||||||
nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
aResult.Clear();
|
aResult.Clear();
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, ""_ns));
|
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, ""_ns));
|
||||||
|
|
||||||
// First, append the non-site-scoped permissions.
|
// First, append the non-site-scoped permissions.
|
||||||
rv = GetAllForPrincipalHelper(aPrincipal, false, aResult);
|
rv = GetAllForPrincipalHelper(aPrincipal, false, aResult);
|
||||||
@@ -2818,6 +2883,8 @@ NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject,
|
|||||||
const char16_t* someData) {
|
const char16_t* someData) {
|
||||||
ENSURE_NOT_CHILD_PROCESS;
|
ENSURE_NOT_CHILD_PROCESS;
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
if (!nsCRT::strcmp(aTopic, "profile-do-change") && !mPermissionsFile) {
|
if (!nsCRT::strcmp(aTopic, "profile-do-change") && !mPermissionsFile) {
|
||||||
// profile startup is complete, and we didn't have the permissions file
|
// profile startup is complete, and we didn't have the permissions file
|
||||||
// before; init the db from the new location
|
// before; init the db from the new location
|
||||||
@@ -2875,6 +2942,7 @@ PermissionManager::RemovePermissionsWithAttributes(
|
|||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return RemovePermissionsWithAttributes(pattern, aTypeInclusions,
|
return RemovePermissionsWithAttributes(pattern, aTypeInclusions,
|
||||||
aTypeExceptions);
|
aTypeExceptions);
|
||||||
}
|
}
|
||||||
@@ -2918,7 +2986,7 @@ nsresult PermissionManager::RemovePermissionsWithAttributes(
|
|||||||
AddInternal(
|
AddInternal(
|
||||||
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
std::get<0>(i), std::get<1>(i), nsIPermissionManager::UNKNOWN_ACTION, 0,
|
||||||
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
nsIPermissionManager::EXPIRE_NEVER, 0, 0, PermissionManager::eNotify,
|
||||||
PermissionManager::eWriteToDB, false, &std::get<2>(i));
|
PermissionManager::eWriteToDB, &std::get<2>(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -3005,7 +3073,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
|||||||
nsIPrincipal* aPrincipal, uint32_t aType, bool aExactHostMatch) {
|
nsIPrincipal* aPrincipal, uint32_t aType, bool aExactHostMatch) {
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, mTypeArray[aType]));
|
MOZ_ASSERT(PermissionAvailableInternal(aPrincipal, mTypeArray[aType]));
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
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 the entry is expired, remove and keep looking for others.
|
||||||
if (HasExpired(permEntry.mExpireType, permEntry.mExpireTime)) {
|
if (HasExpired(permEntry.mExpireType, permEntry.mExpireTime)) {
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
RemoveFromPrincipal(aPrincipal, mTypeArray[aType]);
|
RemoveFromPrincipalInternal(aPrincipal, mTypeArray[aType]);
|
||||||
} else if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
} else if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
}
|
}
|
||||||
@@ -3059,7 +3127,7 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
|||||||
rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
rv = GetPrincipal(aURI, getter_AddRefs(principal));
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(NS_SUCCEEDED(rv),
|
MOZ_ASSERT_IF(NS_SUCCEEDED(rv),
|
||||||
PermissionAvailable(principal, mTypeArray[aType]));
|
PermissionAvailableInternal(principal, mTypeArray[aType]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3135,11 +3203,13 @@ nsresult PermissionManager::RemoveAllFromMemory() {
|
|||||||
void PermissionManager::NotifyObserversWithPermission(
|
void PermissionManager::NotifyObserversWithPermission(
|
||||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
||||||
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
||||||
const char16_t* aData) {
|
const nsString& aData) {
|
||||||
nsCOMPtr<nsIPermission> permission =
|
nsCOMPtr<nsIPermission> permission =
|
||||||
Permission::Create(aPrincipal, aType, aPermission, aExpireType,
|
Permission::Create(aPrincipal, aType, aPermission, aExpireType,
|
||||||
aExpireTime, aModificationTime);
|
aExpireTime, aModificationTime);
|
||||||
if (permission) NotifyObservers(permission, aData);
|
if (permission) {
|
||||||
|
NotifyObservers(permission, aData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify observers that the permission list changed. there are four possible
|
// 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. "changed" means a permission was altered. aPermission is the new
|
||||||
// permission. "cleared" means the entire permission list was cleared.
|
// permission. "cleared" means the entire permission list was cleared.
|
||||||
// aPermission is null.
|
// aPermission is null.
|
||||||
void PermissionManager::NotifyObservers(nsIPermission* aPermission,
|
void PermissionManager::NotifyObservers(
|
||||||
const char16_t* aData) {
|
const nsCOMPtr<nsIPermission>& aPermission, const nsString& aData) {
|
||||||
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
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,
|
observerService->NotifyObservers(aPermission, kPermissionChangeNotification,
|
||||||
aData);
|
aData.Data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult PermissionManager::Read(const MonitorAutoLock& aProofOfLock) {
|
nsresult PermissionManager::Read(const MonitorAutoLock& aProofOfLock) {
|
||||||
@@ -3239,11 +3314,7 @@ void PermissionManager::CompleteMigrations() {
|
|||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
nsTArray<MigrationEntry> entries;
|
nsTArray<MigrationEntry> entries = std::move(mMigrationEntries);
|
||||||
{
|
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
entries = std::move(mMigrationEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const MigrationEntry& entry : entries) {
|
for (const MigrationEntry& entry : entries) {
|
||||||
rv = UpgradeHostToOriginAndInsert(
|
rv = UpgradeHostToOriginAndInsert(
|
||||||
@@ -3251,7 +3322,7 @@ void PermissionManager::CompleteMigrations() {
|
|||||||
entry.mExpireTime, entry.mModificationTime,
|
entry.mExpireTime, entry.mModificationTime,
|
||||||
[&](const nsACString& aOrigin, const nsCString& aType,
|
[&](const nsACString& aOrigin, const nsCString& aType,
|
||||||
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
||||||
int64_t aModificationTime) {
|
int64_t aModificationTime) MOZ_REQUIRES(mMonitor) {
|
||||||
MaybeAddReadEntryFromMigration(aOrigin, aType, aPermission,
|
MaybeAddReadEntryFromMigration(aOrigin, aType, aPermission,
|
||||||
aExpireType, aExpireTime,
|
aExpireType, aExpireTime,
|
||||||
aModificationTime, entry.mId);
|
aModificationTime, entry.mId);
|
||||||
@@ -3267,11 +3338,7 @@ void PermissionManager::CompleteRead() {
|
|||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
nsTArray<ReadEntry> entries;
|
nsTArray<ReadEntry> entries = std::move(mReadEntries);
|
||||||
{
|
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
entries = std::move(mReadEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ReadEntry& entry : entries) {
|
for (const ReadEntry& entry : entries) {
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
@@ -3286,8 +3353,7 @@ void PermissionManager::CompleteRead() {
|
|||||||
|
|
||||||
rv = AddInternal(principal, entry.mType, entry.mPermission, entry.mId,
|
rv = AddInternal(principal, entry.mType, entry.mPermission, entry.mId,
|
||||||
entry.mExpireType, entry.mExpireTime,
|
entry.mExpireType, entry.mExpireTime,
|
||||||
entry.mModificationTime, eDontNotify, op, false,
|
entry.mModificationTime, eDontNotify, op, &entry.mOrigin);
|
||||||
&entry.mOrigin);
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3296,8 +3362,6 @@ void PermissionManager::MaybeAddReadEntryFromMigration(
|
|||||||
const nsACString& aOrigin, const nsCString& aType, uint32_t aPermission,
|
const nsACString& aOrigin, const nsCString& aType, uint32_t aPermission,
|
||||||
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
||||||
int64_t aId) {
|
int64_t aId) {
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
|
|
||||||
// We convert a migration to a ReadEntry only if we don't have an existing
|
// We convert a migration to a ReadEntry only if we don't have an existing
|
||||||
// ReadEntry for the same origin + type.
|
// ReadEntry for the same origin + type.
|
||||||
for (const ReadEntry& entry : mReadEntries) {
|
for (const ReadEntry& entry : mReadEntries) {
|
||||||
@@ -3418,6 +3482,8 @@ void PermissionManager::UpdateDB(OperationType aOp, int64_t aID,
|
|||||||
bool PermissionManager::GetPermissionsFromOriginOrKey(
|
bool PermissionManager::GetPermissionsFromOriginOrKey(
|
||||||
const nsACString& aOrigin, const nsACString& aKey,
|
const nsACString& aOrigin, const nsACString& aKey,
|
||||||
nsTArray<IPC::Permission>& aPerms) {
|
nsTArray<IPC::Permission>& aPerms) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
aPerms.Clear();
|
aPerms.Clear();
|
||||||
@@ -3479,6 +3545,8 @@ void PermissionManager::SetPermissionsWithKey(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
RefPtr<GenericNonExclusivePromise::Private> promise;
|
RefPtr<GenericNonExclusivePromise::Private> promise;
|
||||||
bool foundKey =
|
bool foundKey =
|
||||||
mPermissionKeyPromiseMap.Get(aPermissionKey, getter_AddRefs(promise));
|
mPermissionKeyPromiseMap.Get(aPermissionKey, getter_AddRefs(promise));
|
||||||
@@ -3518,8 +3586,7 @@ void PermissionManager::SetPermissionsWithKey(
|
|||||||
// will end up as now()) is fine.
|
// will end up as now()) is fine.
|
||||||
uint64_t modificationTime = 0;
|
uint64_t modificationTime = 0;
|
||||||
AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
|
AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
|
||||||
perm.expireTime, modificationTime, eNotify, eNoDBOperation,
|
perm.expireTime, modificationTime, eDontNotify, eNoDBOperation);
|
||||||
true /* ignoreSessionPermissions */);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3649,6 +3716,12 @@ PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
|
|||||||
|
|
||||||
bool PermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
|
bool PermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
|
||||||
const nsACString& aType) {
|
const nsACString& aType) {
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
return PermissionAvailableInternal(aPrincipal, aType);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PermissionManager::PermissionAvailableInternal(nsIPrincipal* aPrincipal,
|
||||||
|
const nsACString& aType) {
|
||||||
EnsureReadCompleted();
|
EnsureReadCompleted();
|
||||||
|
|
||||||
if (XRE_IsContentProcess()) {
|
if (XRE_IsContentProcess()) {
|
||||||
@@ -3682,6 +3755,8 @@ void PermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
|
nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
|
||||||
for (auto& pair : GetAllKeysForPrincipal(aPrincipal)) {
|
for (auto& pair : GetAllKeysForPrincipal(aPrincipal)) {
|
||||||
RefPtr<GenericNonExclusivePromise::Private> promise;
|
RefPtr<GenericNonExclusivePromise::Private> promise;
|
||||||
@@ -3721,12 +3796,9 @@ void PermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PermissionManager::EnsureReadCompleted() {
|
void PermissionManager::EnsureReadCompleted() {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (mState == eInitializing) {
|
if (mState == eInitializing) {
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
|
|
||||||
while (mState == eInitializing) {
|
while (mState == eInitializing) {
|
||||||
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
mMonitor.Wait();
|
mMonitor.Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3736,6 +3808,9 @@ void PermissionManager::EnsureReadCompleted() {
|
|||||||
MOZ_CRASH("This state is impossible!");
|
MOZ_CRASH("This state is impossible!");
|
||||||
|
|
||||||
case eDBInitialized:
|
case eDBInitialized:
|
||||||
|
// child processes transitions from eInitializing -> eReady
|
||||||
|
ENSURE_NOT_CHILD_PROCESS_NORET;
|
||||||
|
|
||||||
mState = eReady;
|
mState = eReady;
|
||||||
|
|
||||||
CompleteMigrations();
|
CompleteMigrations();
|
||||||
@@ -3748,7 +3823,7 @@ void PermissionManager::EnsureReadCompleted() {
|
|||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
case eClosed:
|
case eClosed:
|
||||||
return;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Invalid state");
|
MOZ_CRASH("Invalid state");
|
||||||
@@ -3842,7 +3917,7 @@ void PermissionManager::ConsumeDefaultsInputStream(
|
|||||||
0,
|
0,
|
||||||
[&](const nsACString& aOrigin, const nsCString& aType,
|
[&](const nsACString& aOrigin, const nsCString& aType,
|
||||||
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
|
||||||
int64_t aModificationTime) {
|
int64_t aModificationTime) MOZ_REQUIRES(mMonitor) {
|
||||||
AddDefaultEntryForImport(aOrigin, aType, aPermission, aProofOfLock);
|
AddDefaultEntryForImport(aOrigin, aType, aPermission, aProofOfLock);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
});
|
});
|
||||||
@@ -3922,8 +3997,6 @@ nsresult PermissionManager::ImportLatestDefaults() {
|
|||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(mState == eReady);
|
MOZ_ASSERT(mState == eReady);
|
||||||
|
|
||||||
MonitorAutoLock lock(mMonitor);
|
|
||||||
|
|
||||||
for (const DefaultEntry& entry : mDefaultEntriesForImport) {
|
for (const DefaultEntry& entry : mDefaultEntriesForImport) {
|
||||||
Unused << ImportDefaultEntry(entry);
|
Unused << ImportDefaultEntry(entry);
|
||||||
}
|
}
|
||||||
@@ -3993,8 +4066,8 @@ PermissionManager::CommonPrepareToTestPermission(
|
|||||||
// For expanded principals, we want to iterate over the allowlist and see
|
// For expanded principals, we want to iterate over the allowlist and see
|
||||||
// if the permission is granted for any of them.
|
// if the permission is granted for any of them.
|
||||||
if (basePrin && basePrin->Is<ExpandedPrincipal>()) {
|
if (basePrin && basePrin->Is<ExpandedPrincipal>()) {
|
||||||
auto ep = basePrin->As<ExpandedPrincipal>();
|
auto* ep = basePrin->As<ExpandedPrincipal>();
|
||||||
for (auto& prin : ep->AllowList()) {
|
for (const auto& prin : ep->AllowList()) {
|
||||||
uint32_t perm;
|
uint32_t perm;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
CommonTestPermission(prin, typeIndex, aType, &perm, defaultPermission,
|
CommonTestPermission(prin, typeIndex, aType, &perm, defaultPermission,
|
||||||
@@ -4081,6 +4154,7 @@ nsresult PermissionManager::TestPermissionWithoutDefaultsFromPrincipal(
|
|||||||
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t* aPermission) {
|
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t* aPermission) {
|
||||||
MOZ_ASSERT(!HasDefaultPref(aType));
|
MOZ_ASSERT(!HasDefaultPref(aType));
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
return CommonTestPermission(aPrincipal, -1, aType, aPermission,
|
||||||
nsIPermissionManager::UNKNOWN_ACTION, true, false,
|
nsIPermissionManager::UNKNOWN_ACTION, true, false,
|
||||||
true);
|
true);
|
||||||
@@ -4117,6 +4191,9 @@ NS_IMETHODIMP PermissionManager::BlockShutdown(
|
|||||||
StaticMutexAutoLock lock(sCreationMutex);
|
StaticMutexAutoLock lock(sCreationMutex);
|
||||||
sInstanceDead = true;
|
sInstanceDead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MonitorAutoLock lock{mMonitor};
|
||||||
|
|
||||||
RemoveIdleDailyMaintenanceJob();
|
RemoveIdleDailyMaintenanceJob();
|
||||||
RemoveAllFromMemory();
|
RemoveAllFromMemory();
|
||||||
// CloseDB does async work and will call FinishAsyncShutdown once done.
|
// CloseDB does async work and will call FinishAsyncShutdown once done.
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
public nsIObserver,
|
public nsIObserver,
|
||||||
public nsSupportsWeakReference,
|
public nsSupportsWeakReference,
|
||||||
public nsIAsyncShutdownBlocker {
|
public nsIAsyncShutdownBlocker {
|
||||||
friend class dom::ContentChild;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class PermissionEntry {
|
class PermissionEntry {
|
||||||
public:
|
public:
|
||||||
@@ -145,15 +143,21 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t GetPermissionIndex(uint32_t aType) const {
|
inline int32_t GetPermissionIndex(uint32_t aType) const {
|
||||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
for (uint32_t i = 0; i < mPermissions.Length(); ++i) {
|
||||||
if (mPermissions[i].mType == aType) return i;
|
if (mPermissions[i].mType == aType) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PermissionEntry GetPermission(uint32_t aType) const {
|
inline PermissionEntry GetPermission(uint32_t aType) const {
|
||||||
for (uint32_t i = 0; i < mPermissions.Length(); ++i)
|
for (uint32_t i = 0; i < mPermissions.Length(); ++i) {
|
||||||
if (mPermissions[i].mType == aType) return mPermissions[i];
|
if (mPermissions[i].mType == aType) {
|
||||||
|
return mPermissions[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unknown permission... return relevant data
|
// unknown permission... return relevant data
|
||||||
return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
|
return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
|
||||||
@@ -173,7 +177,6 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
PermissionManager();
|
PermissionManager();
|
||||||
static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
|
static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
|
||||||
static already_AddRefed<PermissionManager> GetInstance();
|
static already_AddRefed<PermissionManager> GetInstance();
|
||||||
nsresult Init();
|
|
||||||
|
|
||||||
// enums for AddInternal()
|
// enums for AddInternal()
|
||||||
enum OperationType {
|
enum OperationType {
|
||||||
@@ -197,7 +200,7 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
nsresult RemovePermissionsWithAttributes(
|
nsresult RemovePermissionsWithAttributes(
|
||||||
OriginAttributesPattern& aPattern,
|
OriginAttributesPattern& aPattern,
|
||||||
const nsTArray<nsCString>& aTypeInclusions = {},
|
const nsTArray<nsCString>& aTypeInclusions = {},
|
||||||
const nsTArray<nsCString>& aTypeExceptions = {});
|
const nsTArray<nsCString>& aTypeExceptions = {}) MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
|
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
|
||||||
@@ -368,8 +371,18 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
static void MaybeStripOriginAttributes(bool aForceStrip,
|
static void MaybeStripOriginAttributes(bool aForceStrip,
|
||||||
OriginAttributes& aOriginAttributes);
|
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:
|
private:
|
||||||
~PermissionManager();
|
~PermissionManager();
|
||||||
|
nsresult Init();
|
||||||
|
|
||||||
static StaticMutex sCreationMutex;
|
static StaticMutex sCreationMutex;
|
||||||
// Holding our singleton instance until shutdown.
|
// Holding our singleton instance until shutdown.
|
||||||
static StaticRefPtr<PermissionManager> sInstanceHolder
|
static StaticRefPtr<PermissionManager> sInstanceHolder
|
||||||
@@ -389,10 +402,12 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
*/
|
*/
|
||||||
nsresult GetStripPermsForPrincipal(nsIPrincipal* aPrincipal,
|
nsresult GetStripPermsForPrincipal(nsIPrincipal* aPrincipal,
|
||||||
bool aSiteScopePermissions,
|
bool aSiteScopePermissions,
|
||||||
nsTArray<PermissionEntry>& aResult);
|
nsTArray<PermissionEntry>& aResult)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
// Returns -1 on failure
|
// 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
|
// Returns whether the given combination of expire type and expire time are
|
||||||
// expired. Note that EXPIRE_SESSION only honors expireTime if it is nonzero.
|
// 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.
|
// site-scoped are used.
|
||||||
nsresult GetAllForPrincipalHelper(nsIPrincipal* aPrincipal,
|
nsresult GetAllForPrincipalHelper(nsIPrincipal* aPrincipal,
|
||||||
bool aSiteScopePermissions,
|
bool aSiteScopePermissions,
|
||||||
nsTArray<RefPtr<nsIPermission>>& aResult);
|
nsTArray<RefPtr<nsIPermission>>& aResult)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
// Returns true if the principal can be used for getting / setting
|
// Returns true if the principal can be used for getting / setting
|
||||||
// permissions. If the principal can not be used an error code may be
|
// 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
|
// accepts host on the format "<foo>". This will perform an exact match lookup
|
||||||
// as the string doesn't contain any dots.
|
// as the string doesn't contain any dots.
|
||||||
PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal,
|
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.
|
// Returns PermissionHashKey for a given { host, isInBrowserElement } tuple.
|
||||||
// This is not simply using PermissionKey because we will walk-up domains in
|
// 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.
|
// as the string doesn't contain any dots.
|
||||||
PermissionHashKey* GetPermissionHashKey(
|
PermissionHashKey* GetPermissionHashKey(
|
||||||
nsIURI* aURI, const OriginAttributes* aOriginAttributes, uint32_t aType,
|
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
|
// The int32_t is the type index, the nsresult is an early bail-out return
|
||||||
// code.
|
// code.
|
||||||
@@ -436,59 +463,62 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
|
nsIPrincipal* aPrincipal, int32_t aTypeIndex, const nsACString& aType,
|
||||||
uint32_t* aPermission, uint32_t aDefaultPermission,
|
uint32_t* aPermission, uint32_t aDefaultPermission,
|
||||||
bool aDefaultPermissionIsValid, bool aExactHostMatch,
|
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.
|
// If aTypeIndex is passed -1, we try to inder the type index from aType.
|
||||||
nsresult CommonTestPermission(nsIPrincipal* aPrincipal, int32_t aTypeIndex,
|
nsresult CommonTestPermission(nsIPrincipal* aPrincipal, int32_t aTypeIndex,
|
||||||
const nsACString& aType, uint32_t* aPermission,
|
const nsACString& aType, uint32_t* aPermission,
|
||||||
uint32_t aDefaultPermission,
|
uint32_t aDefaultPermission,
|
||||||
bool aDefaultPermissionIsValid,
|
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.
|
// If aTypeIndex is passed -1, we try to inder the type index from aType.
|
||||||
nsresult CommonTestPermission(nsIURI* aURI, int32_t aTypeIndex,
|
nsresult CommonTestPermission(nsIURI* aURI, int32_t aTypeIndex,
|
||||||
const nsACString& aType, uint32_t* aPermission,
|
const nsACString& aType, uint32_t* aPermission,
|
||||||
uint32_t aDefaultPermission,
|
uint32_t aDefaultPermission,
|
||||||
bool aDefaultPermissionIsValid,
|
bool aDefaultPermissionIsValid,
|
||||||
bool aExactHostMatch, bool aIncludingSession);
|
bool aExactHostMatch, bool aIncludingSession)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult CommonTestPermission(nsIURI* aURI,
|
nsresult CommonTestPermission(
|
||||||
const OriginAttributes* aOriginAttributes,
|
nsIURI* aURI, const OriginAttributes* aOriginAttributes,
|
||||||
int32_t aTypeIndex, const nsACString& aType,
|
int32_t aTypeIndex, const nsACString& aType, uint32_t* aPermission,
|
||||||
uint32_t* aPermission,
|
uint32_t aDefaultPermission, bool aDefaultPermissionIsValid,
|
||||||
uint32_t aDefaultPermission,
|
bool aExactHostMatch, bool aIncludingSession) MOZ_REQUIRES(mMonitor);
|
||||||
bool aDefaultPermissionIsValid,
|
|
||||||
bool aExactHostMatch, bool aIncludingSession);
|
|
||||||
|
|
||||||
// Only one of aPrincipal or aURI is allowed to be passed in.
|
// Only one of aPrincipal or aURI is allowed to be passed in.
|
||||||
nsresult CommonTestPermissionInternal(
|
nsresult CommonTestPermissionInternal(
|
||||||
nsIPrincipal* aPrincipal, nsIURI* aURI,
|
nsIPrincipal* aPrincipal, nsIURI* aURI,
|
||||||
const OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
|
const OriginAttributes* aOriginAttributes, int32_t aTypeIndex,
|
||||||
const nsACString& aType, uint32_t* aPermission, bool aExactHostMatch,
|
const nsACString& aType, uint32_t* aPermission, bool aExactHostMatch,
|
||||||
bool aIncludingSession);
|
bool aIncludingSession) MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult OpenDatabase(nsIFile* permissionsFile);
|
nsresult OpenDatabase(nsIFile* permissionsFile);
|
||||||
|
|
||||||
void InitDB(bool aRemoveFile);
|
void InitDB(bool aRemoveFile) MOZ_REQUIRES(mMonitor);
|
||||||
nsresult TryInitDB(bool aRemoveFile, nsIInputStream* aDefaultsInputStream);
|
nsresult TryInitDB(bool aRemoveFile, nsIInputStream* aDefaultsInputStream,
|
||||||
|
const MonitorAutoLock& aProofOfLock)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
void AddIdleDailyMaintenanceJob();
|
void AddIdleDailyMaintenanceJob();
|
||||||
void RemoveIdleDailyMaintenanceJob();
|
void RemoveIdleDailyMaintenanceJob();
|
||||||
void PerformIdleDailyMaintenance();
|
void PerformIdleDailyMaintenance() MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult ImportLatestDefaults();
|
nsresult ImportLatestDefaults() MOZ_REQUIRES(mMonitor);
|
||||||
already_AddRefed<nsIInputStream> GetDefaultsInputStream();
|
already_AddRefed<nsIInputStream> GetDefaultsInputStream();
|
||||||
void ConsumeDefaultsInputStream(nsIInputStream* aDefaultsInputStream,
|
void ConsumeDefaultsInputStream(nsIInputStream* aInputStream,
|
||||||
const MonitorAutoLock& aProofOfLock);
|
const MonitorAutoLock& aProofOfLock)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult CreateTable();
|
nsresult CreateTable();
|
||||||
void NotifyObserversWithPermission(nsIPrincipal* aPrincipal,
|
void NotifyObserversWithPermission(
|
||||||
const nsACString& aType,
|
nsIPrincipal* aPrincipal, const nsACString& aType, uint32_t aPermission,
|
||||||
uint32_t aPermission, uint32_t aExpireType,
|
uint32_t aExpireType, int64_t aExpireTime, int64_t aModificationTime,
|
||||||
int64_t aExpireTime,
|
const nsString& aData) MOZ_REQUIRES(mMonitor);
|
||||||
int64_t aModificationTime,
|
|
||||||
const char16_t* aData);
|
void NotifyObservers(const nsCOMPtr<nsIPermission>& aPermission,
|
||||||
void NotifyObservers(nsIPermission* aPermission, const char16_t* aData);
|
const nsString& aData) MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
// Finalize all statements, close the DB and null it.
|
// Finalize all statements, close the DB and null it.
|
||||||
enum CloseDBNextOp {
|
enum CloseDBNextOp {
|
||||||
@@ -496,24 +526,25 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
eRebuldOnSuccess,
|
eRebuldOnSuccess,
|
||||||
eShutdown,
|
eShutdown,
|
||||||
};
|
};
|
||||||
void CloseDB(CloseDBNextOp aNextOp);
|
void CloseDB(CloseDBNextOp aNextOp) MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult RemoveAllInternal(bool aNotifyObservers);
|
nsresult RemoveAllInternal(bool aNotifyObservers) MOZ_REQUIRES(mMonitor);
|
||||||
nsresult RemoveAllFromMemory();
|
nsresult RemoveAllFromMemory() MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
void UpdateDB(OperationType aOp, int64_t aID, const nsACString& aOrigin,
|
void UpdateDB(OperationType aOp, int64_t aID, const nsACString& aOrigin,
|
||||||
const nsACString& aType, uint32_t aPermission,
|
const nsACString& aType, uint32_t aPermission,
|
||||||
uint32_t aExpireType, int64_t aExpireTime,
|
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.
|
* 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.
|
// Removes all permissions with a private browsing principal (i.e.
|
||||||
// privateBrowsingId OA != 0).
|
// privateBrowsingId OA != 0).
|
||||||
nsresult RemoveAllForPrivateBrowsing();
|
nsresult RemoveAllForPrivateBrowsing() MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
// Helper function which removes all permissions for which aCondition
|
// Helper function which removes all permissions for which aCondition
|
||||||
// evaluates to true.
|
// evaluates to true.
|
||||||
@@ -521,47 +552,49 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
const std::function<bool(const PermissionEntry& aPermEntry,
|
const std::function<bool(const PermissionEntry& aPermEntry,
|
||||||
const nsCOMPtr<nsIPrincipal>& aPrincipal)>&
|
const nsCOMPtr<nsIPrincipal>& aPrincipal)>&
|
||||||
aCondition,
|
aCondition,
|
||||||
bool aComputePrincipalForCondition = true);
|
bool aComputePrincipalForCondition = true) MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
// Overload of RemovePermissionEntries allowing aCondition not to take
|
// Overload of RemovePermissionEntries allowing aCondition not to take
|
||||||
// aPrincipal as an argument.
|
// aPrincipal as an argument.
|
||||||
nsresult RemovePermissionEntries(
|
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
|
// Helper function which returns all permissions for which aCondition
|
||||||
// evaluates to true.
|
// evaluates to true.
|
||||||
nsresult GetPermissionEntries(
|
nsresult GetPermissionEntries(
|
||||||
const std::function<bool(const PermissionEntry& aPermEntry)>& aCondition,
|
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
|
// 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
|
// DB reading has been completed. This method is also in charge to complete
|
||||||
// the migrations if needed.
|
// the migrations if needed.
|
||||||
void EnsureReadCompleted();
|
void EnsureReadCompleted() MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult AddInternal(nsIPrincipal* aPrincipal, const nsACString& aType,
|
nsresult AddInternal(nsIPrincipal* aPrincipal, const nsACString& aType,
|
||||||
uint32_t aPermission, int64_t aID, uint32_t aExpireType,
|
uint32_t aPermission, int64_t aID, uint32_t aExpireType,
|
||||||
int64_t aExpireTime, int64_t aModificationTime,
|
int64_t aExpireTime, int64_t aModificationTime,
|
||||||
NotifyOperationType aNotifyOperation,
|
NotifyOperationType aNotifyOperation,
|
||||||
DBOperationType aDBOperation,
|
DBOperationType aDBOperation,
|
||||||
const bool aIgnoreSessionPermissions = false,
|
|
||||||
const nsACString* aOriginString = nullptr,
|
const nsACString* aOriginString = nullptr,
|
||||||
const bool aAllowPersistInPrivateBrowsing = false);
|
const bool aAllowPersistInPrivateBrowsing = false)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
void MaybeAddReadEntryFromMigration(const nsACString& aOrigin,
|
void MaybeAddReadEntryFromMigration(const nsACString& aOrigin,
|
||||||
const nsCString& aType,
|
const nsCString& aType,
|
||||||
uint32_t aPermission,
|
uint32_t aPermission,
|
||||||
uint32_t aExpireType, int64_t aExpireTime,
|
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;
|
nsCOMPtr<nsIAsyncShutdownClient> GetAsyncShutdownBarrier() const;
|
||||||
|
|
||||||
void FinishAsyncShutdown();
|
void FinishAsyncShutdown();
|
||||||
|
|
||||||
nsRefPtrHashtable<nsCStringHashKey, GenericNonExclusivePromise::Private>
|
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
|
// 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
|
// operation. The reading of the database happens OMT. See |State| to know the
|
||||||
@@ -597,7 +630,8 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
mPermission(0),
|
mPermission(0),
|
||||||
mExpireType(0),
|
mExpireType(0),
|
||||||
mExpireTime(0),
|
mExpireTime(0),
|
||||||
mModificationTime(0) {}
|
mModificationTime(0),
|
||||||
|
mFromMigration(false) {}
|
||||||
|
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
nsCString mType;
|
nsCString mType;
|
||||||
@@ -614,7 +648,7 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
// List of entries read from the database. It will be populated OMT and
|
// List of entries read from the database. It will be populated OMT and
|
||||||
// consumed on the main-thread.
|
// consumed on the main-thread.
|
||||||
// This array is protected by the monitor.
|
// This array is protected by the monitor.
|
||||||
nsTArray<ReadEntry> mReadEntries;
|
nsTArray<ReadEntry> mReadEntries MOZ_GUARDED_BY(mMonitor);
|
||||||
|
|
||||||
// A single entry, from the database.
|
// A single entry, from the database.
|
||||||
struct MigrationEntry {
|
struct MigrationEntry {
|
||||||
@@ -638,7 +672,7 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
// consumed on the main-thread. The migration entries will be converted to
|
// consumed on the main-thread. The migration entries will be converted to
|
||||||
// ReadEntry in |CompleteMigrations|.
|
// ReadEntry in |CompleteMigrations|.
|
||||||
// This array is protected by the monitor.
|
// This array is protected by the monitor.
|
||||||
nsTArray<MigrationEntry> mMigrationEntries;
|
nsTArray<MigrationEntry> mMigrationEntries MOZ_GUARDED_BY(mMonitor);
|
||||||
|
|
||||||
// A single entry from the defaults URL.
|
// A single entry from the defaults URL.
|
||||||
struct DefaultEntry {
|
struct DefaultEntry {
|
||||||
@@ -649,37 +683,39 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
|
|
||||||
// List of entries read from the default settings.
|
// List of entries read from the default settings.
|
||||||
// This array is protected by the monitor.
|
// 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
|
// Adds a default permission entry to AddDefaultEntryForImport for given
|
||||||
// origin, type and value
|
// origin, type and value
|
||||||
void AddDefaultEntryForImport(const nsACString& aOrigin,
|
void AddDefaultEntryForImport(const nsACString& aOrigin,
|
||||||
const nsCString& aType, uint32_t aPermission,
|
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
|
// 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
|
// permission manager without storing it to disk. If permission isolation for
|
||||||
// private browsing is enabled (which is the default), and the permission type
|
// 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
|
// is not exempt from it, this will also create a separate default permission
|
||||||
// for private browsing
|
// for private browsing
|
||||||
nsresult ImportDefaultEntry(const DefaultEntry& aDefaultEntry);
|
nsresult ImportDefaultEntry(const DefaultEntry& aDefaultEntry)
|
||||||
|
MOZ_REQUIRES(mMonitor);
|
||||||
|
|
||||||
nsresult Read(const MonitorAutoLock& aProofOfLock);
|
nsresult Read(const MonitorAutoLock& aProofOfLock) MOZ_REQUIRES(mMonitor);
|
||||||
void CompleteRead();
|
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
|
// 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.
|
// NOTE: Ensure this is the last member since it has a large inline buffer.
|
||||||
// An array to store the strings identifying the different types.
|
// 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 {
|
struct ThreadBoundData {
|
||||||
nsCOMPtr<mozIStorageConnection> mDBConn;
|
nsCOMPtr<mozIStorageConnection> mDBConn;
|
||||||
@@ -689,9 +725,6 @@ class PermissionManager final : public nsIPermissionManager,
|
|||||||
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
|
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
|
||||||
};
|
};
|
||||||
ThreadBound<ThreadBoundData> mThreadBoundData;
|
ThreadBound<ThreadBoundData> mThreadBoundData;
|
||||||
|
|
||||||
friend class DeleteFromMozHostListener;
|
|
||||||
friend class CloseDatabaseListener;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}
|
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}
|
||||||
|
|||||||
Reference in New Issue
Block a user