mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1603969 - Part 1: Remove the concept of granted origins from the anti-tracking backend; r=baku
Granted origins cause a third-party tracker browsing context to not get full first-party storage access after successfully calling the storage access API or a heuristic granting ephemeral access. For example, after https://tracker.example calls the storage access API successfully in the third-party context, they embed https://other-tracker.example, and that load fails because of ETP restrictions. Here what happens is that https://other-tracker.example is mistakenly considered the granted origin, and because such a permission doesn't exist, access is denied. Differential Revision: https://phabricator.services.mozilla.com/D57493 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
066888a1e5
commit
1ca91dd7ab
@ -779,10 +779,7 @@ var ThirdPartyCookies = {
|
||||
for (let perm of Services.perms.getAllForPrincipal(
|
||||
gBrowser.contentPrincipal
|
||||
)) {
|
||||
if (
|
||||
perm.type == "3rdPartyStorage^" + origin ||
|
||||
perm.type.startsWith("3rdPartyStorage^" + origin + "^")
|
||||
) {
|
||||
if (perm.type == "3rdPartyStorage^" + origin) {
|
||||
return perm.capability;
|
||||
}
|
||||
}
|
||||
@ -799,10 +796,7 @@ var ThirdPartyCookies = {
|
||||
for (let perm of Services.perms.getAllForPrincipal(
|
||||
gBrowser.contentPrincipal
|
||||
)) {
|
||||
if (
|
||||
perm.type == "3rdPartyStorage^" + origin ||
|
||||
perm.type.startsWith("3rdPartyStorage^" + origin + "^")
|
||||
) {
|
||||
if (perm.type == "3rdPartyStorage^" + origin) {
|
||||
Services.perms.removePermission(perm);
|
||||
}
|
||||
}
|
||||
|
@ -5787,13 +5787,11 @@ mozilla::ipc::IPCResult ContentParent::RecvAutomaticStorageAccessCanBeGranted(
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvFirstPartyStorageAccessGrantedForOrigin(
|
||||
const Principal& aParentPrincipal, const Principal& aTrackingPrincipal,
|
||||
const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin,
|
||||
const int& aAllowMode,
|
||||
const nsCString& aTrackingOrigin, const int& aAllowMode,
|
||||
FirstPartyStorageAccessGrantedForOriginResolver&& aResolver) {
|
||||
AntiTrackingCommon::
|
||||
SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
aParentPrincipal, aTrackingPrincipal, aTrackingOrigin, aGrantedOrigin,
|
||||
aAllowMode)
|
||||
aParentPrincipal, aTrackingPrincipal, aTrackingOrigin, aAllowMode)
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
AntiTrackingCommon::FirstPartyStorageAccessGrantPromise::
|
||||
|
@ -1198,8 +1198,7 @@ class ContentParent final
|
||||
|
||||
mozilla::ipc::IPCResult RecvFirstPartyStorageAccessGrantedForOrigin(
|
||||
const Principal& aParentPrincipal, const Principal& aTrackingPrincipal,
|
||||
const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin,
|
||||
const int& aAllowMode,
|
||||
const nsCString& aTrackingOrigin, const int& aAllowMode,
|
||||
FirstPartyStorageAccessGrantedForOriginResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvStoreUserInteractionAsPermission(
|
||||
|
@ -1490,7 +1490,6 @@ parent:
|
||||
async FirstPartyStorageAccessGrantedForOrigin(Principal aParentPrincipal,
|
||||
Principal aTrackingPrincipal,
|
||||
nsCString aTrackingOrigin,
|
||||
nsCString aGrantedOrigin,
|
||||
int aAllowMode)
|
||||
returns (bool unused);
|
||||
|
||||
|
@ -44,11 +44,7 @@ CookieBlockedTracker=Request to access cookie or storage on “%1$S” was block
|
||||
CookieBlockedAll=Request to access cookie or storage on “%1$S” was blocked because we are blocking all storage access requests.
|
||||
CookieBlockedForeign=Request to access cookie or storage on “%1$S” was blocked because we are blocking all third-party storage access requests and content blocking is enabled.
|
||||
|
||||
# LOCALIZATION NOTE (CookieAllowedForOriginOnTrackerByStorageAccessAPI): %3$S, %2$S and %1$S are URLs.
|
||||
CookieAllowedForOriginOnTrackerByStorageAccessAPI=Storage access granted for “%3$S” opened by tracker “%2$S” on “%1$S”.
|
||||
# LOCALIZATION NOTE (CookieAllowedForTrackerByStorageAccessAPI): %2$S and %1$S are URLs.
|
||||
CookieAllowedForTrackerByStorageAccessAPI=Storage access granted for tracker “%2$S” on “%1$S”.
|
||||
# LOCALIZATION NOTE (CookieAllowedForOriginOnTrackerByHeuristic): %3$S, %2$S and %1$S are URLs.
|
||||
CookieAllowedForOriginOnTrackerByHeuristic=Storage access automatically granted for “%3$S” opened by tracker “%2$S” on “%1$S”.
|
||||
# LOCALIZATION NOTE (CookieAllowedForTrackerByHeuristic): %2$S and %1$S are URLs.
|
||||
CookieAllowedForTrackerByHeuristic=Storage access automatically granted for tracker “%2$S” on “%1$S”.
|
||||
|
@ -128,27 +128,6 @@ void CreatePermissionKey(const nsCString& aTrackingOrigin,
|
||||
aPermissionKey.Append(aTrackingOrigin);
|
||||
}
|
||||
|
||||
void CreatePermissionKey(const nsCString& aTrackingOrigin,
|
||||
const nsCString& aGrantedOrigin,
|
||||
nsACString& aPermissionKey) {
|
||||
MOZ_ASSERT(aPermissionKey.IsEmpty());
|
||||
|
||||
if (aTrackingOrigin == aGrantedOrigin) {
|
||||
CreatePermissionKey(aTrackingOrigin, aPermissionKey);
|
||||
return;
|
||||
}
|
||||
|
||||
static const nsLiteralCString prefix =
|
||||
NS_LITERAL_CSTRING(ANTITRACKING_PERM_KEY "^");
|
||||
|
||||
aPermissionKey.SetCapacity(prefix.Length() + 1 + aTrackingOrigin.Length() +
|
||||
aGrantedOrigin.Length());
|
||||
aPermissionKey.Append(prefix);
|
||||
aPermissionKey.Append(aTrackingOrigin);
|
||||
aPermissionKey.AppendLiteral("^");
|
||||
aPermissionKey.Append(aGrantedOrigin);
|
||||
}
|
||||
|
||||
// This internal method returns ACCESS_DENY if the access is denied,
|
||||
// ACCESS_DEFAULT if unknown, some other access code if granted.
|
||||
uint32_t CheckCookiePermissionForPrincipal(nsICookieSettings* aCookieSettings,
|
||||
@ -464,7 +443,6 @@ void ReportBlockingToConsole(nsPIDOMWindowOuter* aWindow, nsIURI* aURI,
|
||||
|
||||
void ReportUnblockingToConsole(
|
||||
nsPIDOMWindowInner* aWindow, const nsAString& aTrackingOrigin,
|
||||
const nsAString& aGrantedOrigin,
|
||||
AntiTrackingCommon::StorageAccessGrantedReason aReason) {
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
|
||||
@ -478,7 +456,6 @@ void ReportUnblockingToConsole(
|
||||
}
|
||||
|
||||
nsAutoString trackingOrigin(aTrackingOrigin);
|
||||
nsAutoString grantedOrigin(aGrantedOrigin);
|
||||
|
||||
nsAutoString sourceLine;
|
||||
uint32_t lineNumber = 0, columnNumber = 0;
|
||||
@ -489,8 +466,8 @@ void ReportUnblockingToConsole(
|
||||
|
||||
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
|
||||
"ReportUnblockingToConsoleDelayed",
|
||||
[doc, principal, trackingOrigin, grantedOrigin, sourceLine, lineNumber,
|
||||
columnNumber, aReason]() {
|
||||
[doc, principal, trackingOrigin, sourceLine, lineNumber, columnNumber,
|
||||
aReason]() {
|
||||
nsAutoString origin;
|
||||
nsresult rv = nsContentUtils::GetUTFOrigin(principal, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -499,39 +476,24 @@ void ReportUnblockingToConsole(
|
||||
|
||||
// Not adding grantedOrigin yet because we may not want it later.
|
||||
AutoTArray<nsString, 3> params = {origin, trackingOrigin};
|
||||
const char* messageWithDifferentOrigin = nullptr;
|
||||
const char* messageWithSameOrigin = nullptr;
|
||||
|
||||
switch (aReason) {
|
||||
case AntiTrackingCommon::eStorageAccessAPI:
|
||||
messageWithDifferentOrigin =
|
||||
"CookieAllowedForOriginOnTrackerByStorageAccessAPI";
|
||||
messageWithSameOrigin = "CookieAllowedForTrackerByStorageAccessAPI";
|
||||
break;
|
||||
|
||||
case AntiTrackingCommon::eOpenerAfterUserInteraction:
|
||||
MOZ_FALLTHROUGH;
|
||||
case AntiTrackingCommon::eOpener:
|
||||
messageWithDifferentOrigin =
|
||||
"CookieAllowedForOriginOnTrackerByHeuristic";
|
||||
messageWithSameOrigin = "CookieAllowedForTrackerByHeuristic";
|
||||
break;
|
||||
}
|
||||
|
||||
if (trackingOrigin == grantedOrigin) {
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Content Blocking"), doc,
|
||||
nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, params,
|
||||
nullptr, sourceLine, lineNumber, columnNumber);
|
||||
} else {
|
||||
params.AppendElement(grantedOrigin);
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Content Blocking"), doc,
|
||||
nsContentUtils::eNECKO_PROPERTIES, messageWithDifferentOrigin,
|
||||
params, nullptr, sourceLine, lineNumber, columnNumber);
|
||||
}
|
||||
nsContentUtils::ReportToConsole(
|
||||
nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Content Blocking"),
|
||||
doc, nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin,
|
||||
params, nullptr, sourceLine, lineNumber, columnNumber);
|
||||
});
|
||||
|
||||
RunConsoleReportingRunnable(runnable.forget());
|
||||
@ -943,16 +905,13 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
|
||||
}
|
||||
|
||||
nsAutoCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(uri, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("Can't get the origin from the URI"));
|
||||
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
|
||||
if (MOZ_LOG_TEST(gAntiTrackingLog, mozilla::LogLevel::Debug)) {
|
||||
nsAutoCString origin;
|
||||
Unused << nsContentUtils::GetASCIIOrigin(uri, origin);
|
||||
LOG(("Adding a first-party storage exception for %s...",
|
||||
PromiseFlatCString(origin).get()));
|
||||
}
|
||||
|
||||
LOG(("Adding a first-party storage exception for %s...",
|
||||
PromiseFlatCString(origin).get()));
|
||||
|
||||
Document* parentDoc = aParentWindow->GetExtantDoc();
|
||||
if (!parentDoc) {
|
||||
LOG(("Parent window has no doc"));
|
||||
@ -996,6 +955,13 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
|
||||
// We are a first party resource.
|
||||
if (outerParentWindow->IsTopLevelWindow()) {
|
||||
nsAutoCString origin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(uri, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("Can't get the origin from the URI"));
|
||||
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
|
||||
}
|
||||
|
||||
trackingOrigin = origin;
|
||||
trackingPrincipal = aPrincipal;
|
||||
rv = trackingPrincipal->GetURI(getter_AddRefs(trackingURI));
|
||||
@ -1098,11 +1064,11 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
}
|
||||
|
||||
auto storePermission =
|
||||
[pwin, parentWindow, origin, trackingOrigin, trackingPrincipal,
|
||||
trackingURI, topInnerWindow, topLevelStoragePrincipal,
|
||||
[pwin, parentWindow, trackingOrigin, trackingPrincipal, trackingURI,
|
||||
topInnerWindow, topLevelStoragePrincipal,
|
||||
aReason](int aAllowMode) -> RefPtr<StorageAccessGrantPromise> {
|
||||
nsAutoCString permissionKey;
|
||||
CreatePermissionKey(trackingOrigin, origin, permissionKey);
|
||||
CreatePermissionKey(trackingOrigin, permissionKey);
|
||||
|
||||
// Let's store the permission in the current parent window.
|
||||
topInnerWindow->SaveStorageAccessGranted(permissionKey);
|
||||
@ -1118,16 +1084,14 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
Some(aReason));
|
||||
|
||||
ReportUnblockingToConsole(parentWindow,
|
||||
NS_ConvertUTF8toUTF16(trackingOrigin),
|
||||
NS_ConvertUTF8toUTF16(origin), aReason);
|
||||
NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
LOG(("Saving the permission: trackingOrigin=%s, grantedOrigin=%s",
|
||||
trackingOrigin.get(), origin.get()));
|
||||
LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get()));
|
||||
|
||||
return SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
topLevelStoragePrincipal, trackingPrincipal, trackingOrigin,
|
||||
origin, aAllowMode)
|
||||
aAllowMode)
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[](FirstPartyStorageAccessGrantPromise::ResolveOrRejectValue&&
|
||||
aValue) {
|
||||
@ -1145,16 +1109,15 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
|
||||
LOG(
|
||||
("Asking the parent process to save the permission for us: "
|
||||
"trackingOrigin=%s, grantedOrigin=%s",
|
||||
trackingOrigin.get(), origin.get()));
|
||||
"trackingOrigin=%s",
|
||||
trackingOrigin.get()));
|
||||
|
||||
// This is not really secure, because here we have the content process
|
||||
// sending the request of storing a permission.
|
||||
return cc
|
||||
->SendFirstPartyStorageAccessGrantedForOrigin(
|
||||
IPC::Principal(topLevelStoragePrincipal),
|
||||
IPC::Principal(trackingPrincipal), trackingOrigin, origin,
|
||||
aAllowMode)
|
||||
IPC::Principal(trackingPrincipal), trackingOrigin, aAllowMode)
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[](const ContentChild::
|
||||
FirstPartyStorageAccessGrantedForOriginPromise::
|
||||
@ -1186,8 +1149,7 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
|
||||
RefPtr<mozilla::AntiTrackingCommon::FirstPartyStorageAccessGrantPromise>
|
||||
AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
nsIPrincipal* aParentPrincipal, nsIPrincipal* aTrackingPrincipal,
|
||||
const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin,
|
||||
int aAllowMode) {
|
||||
const nsCString& aTrackingOrigin, int aAllowMode) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(aAllowMode == eAllow || aAllowMode == eAllowAutoGrant);
|
||||
|
||||
@ -1200,8 +1162,8 @@ AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
nsCOMPtr<nsIURI> parentPrincipalURI;
|
||||
Unused << aParentPrincipal->GetURI(getter_AddRefs(parentPrincipalURI));
|
||||
LOG_SPEC(("Saving a first-party storage permission on %s for "
|
||||
"trackingOrigin=%s grantedOrigin=%s",
|
||||
_spec, aTrackingOrigin.get(), aGrantedOrigin.get()),
|
||||
"trackingOrigin=%s",
|
||||
_spec, aTrackingOrigin.get()),
|
||||
parentPrincipalURI);
|
||||
|
||||
if (NS_WARN_IF(!aParentPrincipal)) {
|
||||
@ -1236,7 +1198,7 @@ AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
}
|
||||
|
||||
nsAutoCString type;
|
||||
CreatePermissionKey(aTrackingOrigin, aGrantedOrigin, type);
|
||||
CreatePermissionKey(aTrackingOrigin, type);
|
||||
|
||||
LOG(
|
||||
("Computed permission key: %s, expiry: %u, proceeding to save in the "
|
||||
@ -1499,15 +1461,8 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
|
||||
}
|
||||
Unused << parentPrincipal->GetURI(getter_AddRefs(parentPrincipalURI));
|
||||
|
||||
nsAutoCString grantedOrigin;
|
||||
nsresult rv = nsContentUtils::GetASCIIOrigin(aURI, grantedOrigin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG_SPEC(("Failed to compute the origin from %s", _spec), aURI);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString type;
|
||||
CreatePermissionKey(trackingOrigin, grantedOrigin, type);
|
||||
CreatePermissionKey(trackingOrigin, type);
|
||||
|
||||
if (topInnerWindow->HasStorageAccessGranted(type)) {
|
||||
LOG(("Permission stored in the window. All good."));
|
||||
@ -1773,15 +1728,8 @@ bool AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString origin;
|
||||
rv = nsContentUtils::GetASCIIOrigin(aURI, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG_SPEC(("Failed to compute the origin from %s", _spec), aURI);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString type;
|
||||
CreatePermissionKey(trackingOrigin, origin, type);
|
||||
CreatePermissionKey(trackingOrigin, type);
|
||||
|
||||
uint32_t privateBrowsingId = 0;
|
||||
rv = channelPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
|
||||
|
@ -130,8 +130,7 @@ class AntiTrackingCommon final {
|
||||
static RefPtr<FirstPartyStorageAccessGrantPromise>
|
||||
SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aTrackingPrinciapl,
|
||||
const nsCString& aParentOrigin, const nsCString& aGrantedOrigin,
|
||||
int aAllowMode);
|
||||
const nsCString& aTrackingOrigin, int aAllowMode);
|
||||
|
||||
// Check whether a top window principal is on the content blocking allow list.
|
||||
static nsresult IsOnContentBlockingAllowList(nsIPrincipal* aTopWinPrincipal,
|
||||
|
@ -879,19 +879,14 @@ const PermissionsCleaner = {
|
||||
|
||||
if (!toBeRemoved && perm.type.startsWith("3rdPartyStorage^")) {
|
||||
let parts = perm.type.split("^");
|
||||
for (let i = 1; i < parts.length; ++i) {
|
||||
let uri;
|
||||
try {
|
||||
uri = Services.io.newURI(parts[i]);
|
||||
} catch (ex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
toBeRemoved = Services.eTLD.hasRootDomain(uri.host, aHost);
|
||||
if (toBeRemoved) {
|
||||
break;
|
||||
}
|
||||
let uri;
|
||||
try {
|
||||
uri = Services.io.newURI(parts[1]);
|
||||
} catch (ex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
toBeRemoved = Services.eTLD.hasRootDomain(uri.host, aHost);
|
||||
}
|
||||
|
||||
if (!toBeRemoved) {
|
||||
|
@ -133,16 +133,6 @@ add_task(async function test_3rdpartystorage_permissions() {
|
||||
"cookie",
|
||||
Services.perms.ALLOW_ACTION
|
||||
);
|
||||
Services.perms.addFromPrincipal(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.net^https://example.org",
|
||||
Services.perms.ALLOW_ACTION
|
||||
);
|
||||
Services.perms.addFromPrincipal(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.org^https://example.net",
|
||||
Services.perms.ALLOW_ACTION
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(principal, "cookie", true) != null
|
||||
@ -160,20 +150,6 @@ add_task(async function test_3rdpartystorage_permissions() {
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(oneMorePrincipal, "cookie", true) != null
|
||||
);
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.net^https://example.org",
|
||||
true
|
||||
) != null
|
||||
);
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.org^https://example.net",
|
||||
true
|
||||
) != null
|
||||
);
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataFromPrincipal(
|
||||
@ -203,20 +179,6 @@ add_task(async function test_3rdpartystorage_permissions() {
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(oneMorePrincipal, "cookie", true) != null
|
||||
);
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.net^https://example.org",
|
||||
true
|
||||
) == null
|
||||
);
|
||||
Assert.ok(
|
||||
Services.perms.getPermissionObject(
|
||||
oneMorePrincipal,
|
||||
"3rdPartyStorage^https://example.org^https://example.net",
|
||||
true
|
||||
) == null
|
||||
);
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteData(
|
||||
|
Loading…
Reference in New Issue
Block a user