mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1731739 part 2 - Use site as key for 3rdPartyStorage permissions, rather than origin r=anti-tracking-reviewers,pbz,timhuang
- Adding browser tests to verify correct behavior in integration - New test that fails on previous version: toolkit/components/antitracking/test/browser/browser_storageAccessScopeSameSiteWrite.js - Add the ability to store permission by site, use 3rdPartyStorage for this - No change is made to permission reads. These already proceed recursively, which eventually reach the site. - When fetching all permissions for a principal, also look for site-scoped permissions on its site's principal Differential Revision: https://phabricator.services.mozilla.com/D130675
This commit is contained in:
parent
8a550db0b7
commit
83bac9db86
@ -783,12 +783,13 @@ let ThirdPartyCookies = new (class ThirdPartyCookies extends ProtectionCategory
|
||||
}
|
||||
|
||||
_getExceptionState(origin) {
|
||||
for (let perm of Services.perms.getAllForPrincipal(
|
||||
gBrowser.contentPrincipal
|
||||
)) {
|
||||
if (perm.type == "3rdPartyStorage^" + origin) {
|
||||
return perm.capability;
|
||||
}
|
||||
let thirdPartyStorage = Services.perms.testPermissionFromPrincipal(
|
||||
gBrowser.contentPrincipal,
|
||||
"3rdPartyStorage^" + origin
|
||||
);
|
||||
|
||||
if (thirdPartyStorage != Services.perms.UNKNOWN_ACTION) {
|
||||
return thirdPartyStorage;
|
||||
}
|
||||
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
|
@ -32,3 +32,4 @@ skip-if = true # Bug 1538602
|
||||
[browser_temporary_permissions_expiry.js]
|
||||
[browser_temporary_permissions_navigation.js]
|
||||
[browser_temporary_permissions_tabs.js]
|
||||
[browser_site_scoped_permissions.js]
|
||||
|
@ -29,26 +29,6 @@ const EMPTY_PAGE =
|
||||
const AUTOPLAY_PREF = "media.autoplay.default";
|
||||
const AUTOPLAY_PERM = "autoplay-media";
|
||||
|
||||
function openPermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
gBrowser.ownerGlobal,
|
||||
"popupshown",
|
||||
true,
|
||||
event => event.target == gPermissionPanel._permissionPopup
|
||||
);
|
||||
gPermissionPanel._identityPermissionBox.click();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function closePermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
gPermissionPanel._permissionPopup,
|
||||
"popuphidden"
|
||||
);
|
||||
gPermissionPanel._permissionPopup.hidePopup();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function autoplayBlockedIcon() {
|
||||
return document.querySelector(
|
||||
"#blocked-permissions-container " +
|
||||
|
@ -8,26 +8,6 @@ const PERMISSIONS_PAGE =
|
||||
"https://example.com"
|
||||
) + "permissions.html";
|
||||
|
||||
function openPermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"popupshown",
|
||||
true,
|
||||
event => event.target == gPermissionPanel._permissionPopup
|
||||
);
|
||||
gPermissionPanel._identityPermissionBox.click();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function closePermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
gPermissionPanel._permissionPopup,
|
||||
"popuphidden"
|
||||
);
|
||||
gPermissionPanel._permissionPopup.hidePopup();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testPermListHasEntries(expectEntries) {
|
||||
let permissionsList = document.getElementById(
|
||||
"permission-popup-permission-list"
|
||||
|
@ -0,0 +1,105 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const EMPTY_PAGE =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://example.com"
|
||||
) + "empty.html";
|
||||
|
||||
const SUBDOMAIN_EMPTY_PAGE =
|
||||
getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"https://www.example.com"
|
||||
) + "empty.html";
|
||||
|
||||
add_task(async function testSiteScopedPermissionSubdomainAffectsBaseDomain() {
|
||||
let subdomainOrigin = "https://www.example.com";
|
||||
let subdomainPrincipal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
subdomainOrigin
|
||||
);
|
||||
let id = "3rdPartyStorage^https://example.org";
|
||||
|
||||
await BrowserTestUtils.withNewTab(EMPTY_PAGE, async function(browser) {
|
||||
Services.perms.addFromPrincipal(
|
||||
subdomainPrincipal,
|
||||
id,
|
||||
SitePermissions.ALLOW
|
||||
);
|
||||
|
||||
await openPermissionPopup();
|
||||
|
||||
let permissionsList = document.getElementById(
|
||||
"permission-popup-permission-list"
|
||||
);
|
||||
let listEntryCount = permissionsList.querySelectorAll(
|
||||
".permission-popup-permission-item"
|
||||
).length;
|
||||
is(
|
||||
listEntryCount,
|
||||
1,
|
||||
"Permission exists on base domain when set on subdomain"
|
||||
);
|
||||
|
||||
closePermissionPopup();
|
||||
|
||||
Services.perms.removeFromPrincipal(subdomainPrincipal, id);
|
||||
|
||||
await openPermissionPopup();
|
||||
|
||||
listEntryCount = permissionsList.querySelectorAll(
|
||||
".permission-popup-permission-item-3rdPartyStorage"
|
||||
).length;
|
||||
is(
|
||||
listEntryCount,
|
||||
0,
|
||||
"Permission removed on base domain when removed on subdomain"
|
||||
);
|
||||
|
||||
await closePermissionPopup();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testSiteScopedPermissionBaseDomainAffectsSubdomain() {
|
||||
let origin = "https://example.com";
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
origin
|
||||
);
|
||||
let id = "3rdPartyStorage^https://example.org";
|
||||
|
||||
await BrowserTestUtils.withNewTab(SUBDOMAIN_EMPTY_PAGE, async function(
|
||||
browser
|
||||
) {
|
||||
Services.perms.addFromPrincipal(principal, id, SitePermissions.ALLOW);
|
||||
await openPermissionPopup();
|
||||
|
||||
let permissionsList = document.getElementById(
|
||||
"permission-popup-permission-list"
|
||||
);
|
||||
let listEntryCount = permissionsList.querySelectorAll(
|
||||
".permission-popup-permission-item"
|
||||
).length;
|
||||
is(
|
||||
listEntryCount,
|
||||
1,
|
||||
"Permission exists on base domain when set on subdomain"
|
||||
);
|
||||
|
||||
closePermissionPopup();
|
||||
|
||||
Services.perms.removeFromPrincipal(principal, id);
|
||||
|
||||
await openPermissionPopup();
|
||||
|
||||
listEntryCount = permissionsList.querySelectorAll(
|
||||
".permission-popup-permission-item-3rdPartyStorage"
|
||||
).length;
|
||||
is(
|
||||
listEntryCount,
|
||||
0,
|
||||
"Permission removed on base domain when removed on subdomain"
|
||||
);
|
||||
|
||||
await closePermissionPopup();
|
||||
});
|
||||
});
|
@ -9,3 +9,23 @@ SpecialPowers.addTaskImport(
|
||||
"E10SUtils",
|
||||
"resource://gre/modules/E10SUtils.jsm"
|
||||
);
|
||||
|
||||
function openPermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
gBrowser.ownerGlobal,
|
||||
"popupshown",
|
||||
true,
|
||||
event => event.target == gPermissionPanel._permissionPopup
|
||||
);
|
||||
gPermissionPanel._identityPermissionBox.click();
|
||||
return promise;
|
||||
}
|
||||
|
||||
function closePermissionPopup() {
|
||||
let promise = BrowserTestUtils.waitForEvent(
|
||||
gPermissionPanel._permissionPopup,
|
||||
"popuphidden"
|
||||
);
|
||||
gPermissionPanel._permissionPopup.hidePopup();
|
||||
return promise;
|
||||
}
|
||||
|
@ -164,6 +164,25 @@ bool IsOAForceStripPermission(const nsACString& aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Array of permission prefixes which should be isolated only by site.
|
||||
// These site-scoped permissions are stored under their site's principal.
|
||||
// GetAllForPrincipal also needs to look for these especially.
|
||||
static constexpr std::array<nsLiteralCString, 1> kSiteScopedPermissions = {
|
||||
{"3rdPartyStorage^"_ns}};
|
||||
|
||||
bool IsSiteScopedPermission(const nsACString& aType) {
|
||||
if (aType.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& perm : kSiteScopedPermissions) {
|
||||
if (aType.Length() >= perm.Length() &&
|
||||
Substring(aType, 0, perm.Length()) == perm) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OriginAppendOASuffix(OriginAttributes aOriginAttributes,
|
||||
bool aForceStripOA, nsACString& aOrigin) {
|
||||
PermissionManager::MaybeStripOriginAttributes(aForceStripOA,
|
||||
@ -188,15 +207,33 @@ nsresult GetOriginFromPrincipal(nsIPrincipal* aPrincipal, bool aForceStripOA,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OriginAttributes attrs;
|
||||
if (!attrs.PopulateFromSuffix(suffix)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ENSURE_TRUE(attrs.PopulateFromSuffix(suffix), NS_ERROR_FAILURE);
|
||||
|
||||
OriginAppendOASuffix(attrs, aForceStripOA, aOrigin);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Returns the site of the principal, including OA, given a principal.
|
||||
nsresult GetSiteFromPrincipal(nsIPrincipal* aPrincipal, bool aForceStripOA,
|
||||
nsACString& aSite) {
|
||||
nsresult rv = aPrincipal->GetSiteOriginNoSuffix(aSite);
|
||||
// The principal may belong to the about:blank content viewer, so this can be
|
||||
// expected to fail.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString suffix;
|
||||
rv = aPrincipal->GetOriginSuffix(suffix);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OriginAttributes attrs;
|
||||
NS_ENSURE_TRUE(attrs.PopulateFromSuffix(suffix), NS_ERROR_FAILURE);
|
||||
|
||||
OriginAppendOASuffix(attrs, aForceStripOA, aSite);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetOriginFromURIAndOA(nsIURI* aURI,
|
||||
const OriginAttributes* aOriginAttributes,
|
||||
bool aForceStripOA, nsACString& aOrigin) {
|
||||
@ -533,14 +570,19 @@ bool IsPersistentExpire(uint32_t aExpire, const nsACString& aType) {
|
||||
PermissionManager::PermissionKey*
|
||||
PermissionManager::PermissionKey::CreateFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
bool aForceStripOA,
|
||||
bool scopeToSite,
|
||||
nsresult& aResult) {
|
||||
nsAutoCString origin;
|
||||
aResult = GetOriginFromPrincipal(aPrincipal, aForceStripOA, origin);
|
||||
nsAutoCString keyString;
|
||||
if (scopeToSite) {
|
||||
aResult = GetSiteFromPrincipal(aPrincipal, aForceStripOA, keyString);
|
||||
} else {
|
||||
aResult = GetOriginFromPrincipal(aPrincipal, aForceStripOA, keyString);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(aResult))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new PermissionKey(origin);
|
||||
return new PermissionKey(keyString);
|
||||
}
|
||||
|
||||
PermissionManager::PermissionKey*
|
||||
@ -1589,9 +1631,14 @@ nsresult PermissionManager::AddInternal(
|
||||
// Use the origin string provided by the caller.
|
||||
origin = *aOriginString;
|
||||
} else {
|
||||
// Compute it from the principal provided.
|
||||
rv = GetOriginFromPrincipal(aPrincipal, IsOAForceStripPermission(aType),
|
||||
if (IsSiteScopedPermission(aType)) {
|
||||
rv = GetSiteFromPrincipal(aPrincipal, IsOAForceStripPermission(aType),
|
||||
origin);
|
||||
} else {
|
||||
// Compute it from the principal provided.
|
||||
rv = GetOriginFromPrincipal(aPrincipal, IsOAForceStripPermission(aType),
|
||||
origin);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
@ -1640,7 +1687,8 @@ nsresult PermissionManager::AddInternal(
|
||||
// When an entry already exists, PutEntry will return that, instead
|
||||
// of adding a new one
|
||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
||||
aPrincipal, IsOAForceStripPermission(aType), rv);
|
||||
aPrincipal, IsOAForceStripPermission(aType),
|
||||
IsSiteScopedPermission(aType), rv);
|
||||
if (!key) {
|
||||
MOZ_ASSERT(NS_FAILED(rv));
|
||||
return rv;
|
||||
@ -2330,17 +2378,12 @@ NS_IMETHODIMP PermissionManager::GetAllWithTypePrefix(
|
||||
aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PermissionManager::GetAllForPrincipal(
|
||||
nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
aResult.Clear();
|
||||
EnsureReadCompleted();
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, ""_ns));
|
||||
|
||||
nsresult PermissionManager::GetAllForPrincipalHelper(
|
||||
nsIPrincipal* aPrincipal, bool aSiteScopePermissions,
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
nsresult rv;
|
||||
RefPtr<PermissionKey> key =
|
||||
PermissionKey::CreateFromPrincipal(aPrincipal, false, rv);
|
||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
||||
aPrincipal, false, aSiteScopePermissions, rv);
|
||||
if (!key) {
|
||||
MOZ_ASSERT(NS_FAILED(rv));
|
||||
return rv;
|
||||
@ -2348,7 +2391,8 @@ PermissionManager::GetAllForPrincipal(
|
||||
PermissionHashKey* entry = mPermissionTable.GetEntry(key);
|
||||
|
||||
nsTArray<PermissionEntry> strippedPerms;
|
||||
rv = GetStripPermsForPrincipal(aPrincipal, strippedPerms);
|
||||
rv = GetStripPermsForPrincipal(aPrincipal, aSiteScopePermissions,
|
||||
strippedPerms);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -2367,6 +2411,13 @@ PermissionManager::GetAllForPrincipal(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure that we only get site scoped permissions if this
|
||||
// helper is being invoked for that purpose.
|
||||
if (aSiteScopePermissions !=
|
||||
IsSiteScopedPermission(mTypeArray[permEntry.mType])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stripped principal permissions overwrite regular ones
|
||||
// For each permission check if there is a stripped permission we should
|
||||
// use instead
|
||||
@ -2404,6 +2455,23 @@ PermissionManager::GetAllForPrincipal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PermissionManager::GetAllForPrincipal(
|
||||
nsIPrincipal* aPrincipal, nsTArray<RefPtr<nsIPermission>>& aResult) {
|
||||
nsresult rv;
|
||||
aResult.Clear();
|
||||
EnsureReadCompleted();
|
||||
|
||||
MOZ_ASSERT(PermissionAvailable(aPrincipal, ""_ns));
|
||||
|
||||
// First, append the non-site-scoped permissions.
|
||||
rv = GetAllForPrincipalHelper(aPrincipal, false, aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Second, append the site-scoped permissions.
|
||||
return GetAllForPrincipalHelper(aPrincipal, true, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* someData) {
|
||||
@ -2494,7 +2562,8 @@ nsresult PermissionManager::RemovePermissionsWithAttributes(
|
||||
}
|
||||
|
||||
nsresult PermissionManager::GetStripPermsForPrincipal(
|
||||
nsIPrincipal* aPrincipal, nsTArray<PermissionEntry>& aResult) {
|
||||
nsIPrincipal* aPrincipal, bool aSiteScopePermissions,
|
||||
nsTArray<PermissionEntry>& aResult) {
|
||||
aResult.Clear();
|
||||
aResult.SetCapacity(kStripOAPermissions.size());
|
||||
|
||||
@ -2511,9 +2580,10 @@ nsresult PermissionManager::GetStripPermsForPrincipal(
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
// Create a key for the principal, but strip any origin attributes
|
||||
RefPtr<PermissionKey> key =
|
||||
PermissionKey::CreateFromPrincipal(aPrincipal, true, rv);
|
||||
// Create a key for the principal, but strip any origin attributes.
|
||||
// The key must be created aware of whether or not we are scoping to site.
|
||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
||||
aPrincipal, true, aSiteScopePermissions, rv);
|
||||
if (!key) {
|
||||
MOZ_ASSERT(NS_FAILED(rv));
|
||||
return rv;
|
||||
@ -2525,6 +2595,14 @@ nsresult PermissionManager::GetStripPermsForPrincipal(
|
||||
}
|
||||
|
||||
for (const auto& permType : kStripOAPermissions) {
|
||||
// if the permission type's site scoping does not match this function call,
|
||||
// we don't care about it, so continue.
|
||||
// As of time of writing, this never happens when aSiteScopePermissions
|
||||
// is true because there is no common permission between kStripOAPermissions
|
||||
// and kSiteScopedPermissions
|
||||
if (aSiteScopePermissions != IsSiteScopedPermission(permType)) {
|
||||
continue;
|
||||
}
|
||||
int32_t index = GetTypeIndex(permType, false);
|
||||
if (index == -1) {
|
||||
continue;
|
||||
@ -2568,7 +2646,8 @@ PermissionManager::PermissionHashKey* PermissionManager::GetPermissionHashKey(
|
||||
|
||||
nsresult rv;
|
||||
RefPtr<PermissionKey> key = PermissionKey::CreateFromPrincipal(
|
||||
aPrincipal, IsOAForceStripPermission(mTypeArray[aType]), rv);
|
||||
aPrincipal, IsOAForceStripPermission(mTypeArray[aType]),
|
||||
IsSiteScopedPermission(mTypeArray[aType]), rv);
|
||||
if (!key) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2988,7 +3067,7 @@ bool PermissionManager::GetPermissionsFromOriginOrKey(
|
||||
if (aOrigin.IsEmpty()) {
|
||||
// We can't check for individual OA strip perms here.
|
||||
// Don't force strip origin attributes.
|
||||
GetKeyForOrigin(entry.GetKey()->mOrigin, false, permissionKey);
|
||||
GetKeyForOrigin(entry.GetKey()->mOrigin, false, false, permissionKey);
|
||||
|
||||
// If the keys don't match, and we aren't getting the default "" key, then
|
||||
// we can exit early. We have to keep looking if we're getting the default
|
||||
@ -3083,7 +3162,9 @@ void PermissionManager::SetPermissionsWithKey(
|
||||
|
||||
/* static */
|
||||
void PermissionManager::GetKeyForOrigin(const nsACString& aOrigin,
|
||||
bool aForceStripOA, nsACString& aKey) {
|
||||
bool aForceStripOA,
|
||||
bool aSiteScopePermissions,
|
||||
nsACString& aKey) {
|
||||
aKey.Truncate();
|
||||
|
||||
// We only key origins for http, https, and ftp URIs. All origins begin with
|
||||
@ -3119,6 +3200,19 @@ void PermissionManager::GetKeyForOrigin(const nsACString& aOrigin,
|
||||
MOZ_ASSERT(dbgPrincipal->OriginAttributesRef() == attrs);
|
||||
#endif
|
||||
|
||||
// If it is needed, turn the origin into its site-origin
|
||||
if (aSiteScopePermissions) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aKey);
|
||||
if (!NS_WARN_IF(NS_FAILED(rv))) {
|
||||
nsCString site;
|
||||
rv = nsEffectiveTLDService::GetInstance()->GetSite(uri, site);
|
||||
if (!NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aKey = site;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append the stripped suffix to the output origin key.
|
||||
nsAutoCString suffix;
|
||||
attrs.CreateSuffix(suffix);
|
||||
@ -3128,6 +3222,7 @@ void PermissionManager::GetKeyForOrigin(const nsACString& aOrigin,
|
||||
/* static */
|
||||
void PermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal,
|
||||
bool aForceStripOA,
|
||||
bool aSiteScopePermissions,
|
||||
nsACString& aKey) {
|
||||
nsAutoCString origin;
|
||||
nsresult rv = aPrincipal->GetOrigin(origin);
|
||||
@ -3135,7 +3230,7 @@ void PermissionManager::GetKeyForPrincipal(nsIPrincipal* aPrincipal,
|
||||
aKey.Truncate();
|
||||
return;
|
||||
}
|
||||
GetKeyForOrigin(origin, aForceStripOA, aKey);
|
||||
GetKeyForOrigin(origin, aForceStripOA, aSiteScopePermissions, aKey);
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -3148,7 +3243,8 @@ void PermissionManager::GetKeyForPermission(nsIPrincipal* aPrincipal,
|
||||
return;
|
||||
}
|
||||
|
||||
GetKeyForPrincipal(aPrincipal, IsOAForceStripPermission(aType), aKey);
|
||||
GetKeyForPrincipal(aPrincipal, IsOAForceStripPermission(aType),
|
||||
IsSiteScopedPermission(aType), aKey);
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -3164,7 +3260,7 @@ PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
|
||||
pairs.AppendElement(std::make_pair(""_ns, ""_ns));
|
||||
// We can't check for individual OA strip perms here.
|
||||
// Don't force strip origin attributes.
|
||||
GetKeyForPrincipal(prin, false, pair->first);
|
||||
GetKeyForPrincipal(prin, false, false, pair->first);
|
||||
|
||||
// On origins with a derived key set to an empty string
|
||||
// (basically any non-web URI scheme), we want to make sure
|
||||
|
@ -85,6 +85,7 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
public:
|
||||
static PermissionKey* CreateFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
bool aForceStripOA,
|
||||
bool aScopeToSite,
|
||||
nsresult& aResult);
|
||||
static PermissionKey* CreateFromURI(nsIURI* aURI, nsresult& aResult);
|
||||
static PermissionKey* CreateFromURIAndOriginAttributes(
|
||||
@ -216,11 +217,15 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
* @param aPrincipal The Principal which the key is to be extracted from.
|
||||
* @param aForceStripOA Whether to force stripping the principals origin
|
||||
* attributes prior to generating the key.
|
||||
* @param aSiteScopePermissions Whether to prepare the key for permissions
|
||||
* scoped to the Principal's site, rather than origin. These are looked
|
||||
* up independently. Scoping of a permission is fully determined by its
|
||||
* type and determined by calls to the function IsSiteScopedPermission.
|
||||
* @param aKey A string which will be filled with the permission
|
||||
* key.
|
||||
*/
|
||||
static void GetKeyForPrincipal(nsIPrincipal* aPrincipal, bool aForceStripOA,
|
||||
nsACString& aKey);
|
||||
bool aSiteScopePermissions, nsACString& aKey);
|
||||
|
||||
/**
|
||||
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
|
||||
@ -236,11 +241,15 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
* @param aOrigin The origin which the key is to be extracted from.
|
||||
* @param aForceStripOA Whether to force stripping the origins attributes
|
||||
* prior to generating the key.
|
||||
* @param aSiteScopePermissions Whether to prepare the key for permissions
|
||||
* scoped to the Principal's site, rather than origin. These are looked
|
||||
* up independently. Scoping of a permission is fully determined by its
|
||||
* type and determined by calls to the function IsSiteScopedPermission.
|
||||
* @param aKey A string which will be filled with the permission
|
||||
* key.
|
||||
*/
|
||||
static void GetKeyForOrigin(const nsACString& aOrigin, bool aForceStripOA,
|
||||
nsACString& aKey);
|
||||
bool aSiteScopePermissions, nsACString& aKey);
|
||||
|
||||
/**
|
||||
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
|
||||
@ -371,8 +380,12 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
* attributes stripped before perm db lookup. This is currently only affects
|
||||
* the "cookie" permission.
|
||||
* @param aPrincipal Used for creating the permission key.
|
||||
* @param aSiteScopePermissions Used to specify whether to get strip perms for
|
||||
* site scoped permissions (defined in IsSiteScopedPermission) or all other
|
||||
* permissions. Also used to create the permission key.
|
||||
*/
|
||||
nsresult GetStripPermsForPrincipal(nsIPrincipal* aPrincipal,
|
||||
bool aSiteScopePermissions,
|
||||
nsTArray<PermissionEntry>& aResult);
|
||||
|
||||
// Returns -1 on failure
|
||||
@ -382,6 +395,14 @@ class PermissionManager final : public nsIPermissionManager,
|
||||
// expired. Note that EXPIRE_SESSION only honors expireTime if it is nonzero.
|
||||
bool HasExpired(uint32_t aExpireType, int64_t aExpireTime);
|
||||
|
||||
// Appends the permissions associated with this principal to aResult.
|
||||
// If the onlySiteScopePermissions argument is true, the permissions searched
|
||||
// are those for the site of the principal and only the permissions that are
|
||||
// site-scoped are used.
|
||||
nsresult GetAllForPrincipalHelper(nsIPrincipal* aPrincipal,
|
||||
bool aSiteScopePermissions,
|
||||
nsTArray<RefPtr<nsIPermission>>& aResult);
|
||||
|
||||
// Returns PermissionHashKey for a given { host, isInBrowserElement } tuple.
|
||||
// This is not simply using PermissionKey because we will walk-up domains in
|
||||
// case of |host| contains sub-domains. Returns null if nothing found. Also
|
||||
|
120
extensions/permissions/test/unit/test_permmanager_site_scope.js
Normal file
120
extensions/permissions/test/unit/test_permmanager_site_scope.js
Normal file
@ -0,0 +1,120 @@
|
||||
const TEST_SITE_URI = Services.io.newURI("http://example.com");
|
||||
const TEST_FQDN_1_URI = Services.io.newURI("http://test1.example.com");
|
||||
const TEST_FQDN_2_URI = Services.io.newURI("http://test2.example.com");
|
||||
const TEST_OTHER_URI = Services.io.newURI("http://example.net");
|
||||
const TEST_PERMISSION = "3rdPartyStorage^https://example.org";
|
||||
|
||||
add_task(async function do_test() {
|
||||
let pm = Services.perms;
|
||||
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
TEST_SITE_URI,
|
||||
{}
|
||||
);
|
||||
|
||||
let subdomain1Principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
TEST_FQDN_1_URI,
|
||||
{}
|
||||
);
|
||||
|
||||
let subdomain2Principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
TEST_FQDN_2_URI,
|
||||
{}
|
||||
);
|
||||
|
||||
let otherPrincipal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
TEST_OTHER_URI,
|
||||
{}
|
||||
);
|
||||
|
||||
// Set test permission for site
|
||||
pm.addFromPrincipal(principal, TEST_PERMISSION, pm.ALLOW_ACTION);
|
||||
|
||||
// Check normal site permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check subdomain permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
pm.testPermissionFromPrincipal(subdomain1Principal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check other site permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION,
|
||||
pm.testPermissionFromPrincipal(otherPrincipal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Remove the permission from the site
|
||||
pm.removeFromPrincipal(principal, TEST_PERMISSION);
|
||||
Assert.equal(
|
||||
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
);
|
||||
Assert.equal(
|
||||
pm.testPermissionFromPrincipal(subdomain1Principal, TEST_PERMISSION),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
);
|
||||
|
||||
// Set test permission for subdomain
|
||||
pm.addFromPrincipal(subdomain1Principal, TEST_PERMISSION, pm.ALLOW_ACTION);
|
||||
|
||||
// Check normal site permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check subdomain permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
pm.testPermissionFromPrincipal(subdomain1Principal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check other subdomain permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
pm.testPermissionFromPrincipal(subdomain2Principal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check other site permission
|
||||
Assert.equal(
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION,
|
||||
pm.testPermissionFromPrincipal(otherPrincipal, TEST_PERMISSION)
|
||||
);
|
||||
|
||||
// Check that subdomains include the site-scoped in the getAllForPrincipal
|
||||
let sitePerms = pm.getAllForPrincipal(principal, TEST_PERMISSION);
|
||||
let subdomain1Perms = pm.getAllForPrincipal(
|
||||
subdomain1Principal,
|
||||
TEST_PERMISSION
|
||||
);
|
||||
let subdomain2Perms = pm.getAllForPrincipal(
|
||||
subdomain2Principal,
|
||||
TEST_PERMISSION
|
||||
);
|
||||
let otherSitePerms = pm.getAllForPrincipal(otherPrincipal, TEST_PERMISSION);
|
||||
|
||||
Assert.equal(sitePerms.length, 1);
|
||||
Assert.equal(subdomain1Perms.length, 1);
|
||||
Assert.equal(subdomain2Perms.length, 1);
|
||||
Assert.equal(otherSitePerms.length, 0);
|
||||
|
||||
// Remove the permission from the subdomain
|
||||
pm.removeFromPrincipal(subdomain1Principal, TEST_PERMISSION);
|
||||
Assert.equal(
|
||||
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
);
|
||||
Assert.equal(
|
||||
pm.testPermissionFromPrincipal(subdomain1Principal, TEST_PERMISSION),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
);
|
||||
Assert.equal(
|
||||
pm.testPermissionFromPrincipal(subdomain2Principal, TEST_PERMISSION),
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION
|
||||
);
|
||||
});
|
@ -44,6 +44,7 @@ skip-if = toolkit == 'android' # Android doesn't use places
|
||||
[test_permmanager_migrate_10-11.js]
|
||||
skip-if = toolkit == 'android' # Android doesn't use places
|
||||
[test_permmanager_oa_strip.js]
|
||||
[test_permmanager_site_scope.js]
|
||||
[test_permmanager_remove_add_update.js]
|
||||
skip-if = win10_2004 && bits == 64 # Bug 1718292
|
||||
[test_permmanager_ipc.js]
|
||||
|
@ -829,7 +829,7 @@ void ContentBlocking::UpdateAllowAccessOnParentProcess(
|
||||
nsAutoCString topKey;
|
||||
nsCOMPtr<nsIPrincipal> topPrincipal =
|
||||
AntiTrackingUtils::GetPrincipal(aParentContext->Top());
|
||||
PermissionManager::GetKeyForPrincipal(topPrincipal, false, topKey);
|
||||
PermissionManager::GetKeyForPrincipal(topPrincipal, false, true, topKey);
|
||||
|
||||
// Propagate the storage permission to same-origin frames in the same
|
||||
// agent-cluster.
|
||||
@ -857,7 +857,7 @@ void ContentBlocking::UpdateAllowAccessOnParentProcess(
|
||||
}
|
||||
|
||||
nsAutoCString key;
|
||||
PermissionManager::GetKeyForPrincipal(principal, false, key);
|
||||
PermissionManager::GetKeyForPrincipal(principal, false, true, key);
|
||||
// Make sure we only apply to frames that have the same top-level.
|
||||
if (topKey != key) {
|
||||
continue;
|
||||
|
@ -22,6 +22,7 @@ support-files =
|
||||
antitracking_head.js
|
||||
dynamicfpi_head.js
|
||||
partitionedstorage_head.js
|
||||
storage_access_head.js
|
||||
cookiesCORS.sjs
|
||||
iframe.html
|
||||
image.sjs
|
||||
@ -99,6 +100,10 @@ skip-if = debug # Bug 1700551
|
||||
[browser_storageAccessRemovalNavigateSubframe.js]
|
||||
[browser_storageAccessRemovalNavigateTopframe.js]
|
||||
[browser_storageAccessSandboxed.js]
|
||||
[browser_storageAccessScopeDifferentSite.js]
|
||||
[browser_storageAccessScopeSameOrigin.js]
|
||||
[browser_storageAccessScopeSameSiteRead.js]
|
||||
[browser_storageAccessScopeSameSiteWrite.js]
|
||||
[browser_storageAccessThirdPartyChecks.js]
|
||||
[browser_storageAccessWithDynamicFpi.js]
|
||||
[browser_storageAccessWithHeuristics.js]
|
||||
|
@ -0,0 +1,46 @@
|
||||
/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
|
||||
/* import-globals-from head.js */
|
||||
/* import-globals-from storage_access_head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/browser/modules/test/browser/head.js",
|
||||
this
|
||||
);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/storage_access_head.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_task(async function testInitialBlock() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("reject"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectFailure
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testDifferentSitePermission() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("accept"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE,
|
||||
getExpectPopupAndClick("reject"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectFailure
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
@ -0,0 +1,46 @@
|
||||
/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
|
||||
/* import-globals-from head.js */
|
||||
/* import-globals-from storage_access_head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/browser/modules/test/browser/head.js",
|
||||
this
|
||||
);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/storage_access_head.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_task(async function testInitialBlock() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("reject"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectFailure
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testSameOriginPermission() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("accept"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
expectNoPopup,
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
@ -0,0 +1,46 @@
|
||||
/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
|
||||
/* import-globals-from head.js */
|
||||
/* import-globals-from storage_access_head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/browser/modules/test/browser/head.js",
|
||||
this
|
||||
);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/storage_access_head.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_task(async function testInitialBlock() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("reject"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectFailure
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testSameSitePermission() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("accept"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_8,
|
||||
expectNoPopup,
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
@ -0,0 +1,46 @@
|
||||
/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
|
||||
/* import-globals-from head.js */
|
||||
/* import-globals-from storage_access_head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/browser/modules/test/browser/head.js",
|
||||
this
|
||||
);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/toolkit/components/antitracking/test/browser/storage_access_head.js",
|
||||
this
|
||||
);
|
||||
|
||||
add_task(async function testInitialBlock() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
getExpectPopupAndClick("reject"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectFailure
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testSameSitePermissionReversed() {
|
||||
await setPreferences();
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_8,
|
||||
getExpectPopupAndClick("accept"),
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await openPageAndRunCode(
|
||||
TEST_TOP_PAGE_7,
|
||||
expectNoPopup,
|
||||
TEST_3RD_PARTY_PAGE,
|
||||
requestStorageAccessAndExpectSuccess
|
||||
);
|
||||
|
||||
await cleanUpData();
|
||||
await SpecialPowers.flushPrefEnv();
|
||||
});
|
@ -11,6 +11,8 @@ const TEST_DOMAIN_3 = "https://xn--hxajbheg2az3al.xn--jxalpdlp/";
|
||||
const TEST_DOMAIN_4 = "http://prefixexample.com/";
|
||||
const TEST_DOMAIN_5 = "http://test/";
|
||||
const TEST_DOMAIN_6 = "http://mochi.test:8888/";
|
||||
const TEST_DOMAIN_7 = "http://example.com/";
|
||||
const TEST_DOMAIN_8 = "http://www.example.com/";
|
||||
const TEST_3RD_PARTY_DOMAIN = "https://tracking.example.org/";
|
||||
const TEST_3RD_PARTY_DOMAIN_HTTP = "http://tracking.example.org/";
|
||||
const TEST_3RD_PARTY_DOMAIN_TP = "https://tracking.example.com/";
|
||||
@ -32,6 +34,8 @@ const TEST_TOP_PAGE_3 = TEST_DOMAIN_3 + TEST_PATH + "page.html";
|
||||
const TEST_TOP_PAGE_4 = TEST_DOMAIN_4 + TEST_PATH + "page.html";
|
||||
const TEST_TOP_PAGE_5 = TEST_DOMAIN_5 + TEST_PATH + "page.html";
|
||||
const TEST_TOP_PAGE_6 = TEST_DOMAIN_6 + TEST_PATH + "page.html";
|
||||
const TEST_TOP_PAGE_7 = TEST_DOMAIN_7 + TEST_PATH + "page.html";
|
||||
const TEST_TOP_PAGE_8 = TEST_DOMAIN_8 + TEST_PATH + "page.html";
|
||||
const TEST_EMBEDDER_PAGE = TEST_DOMAIN + TEST_PATH + "embedder.html";
|
||||
const TEST_POPUP_PAGE = TEST_DOMAIN + TEST_PATH + "popup.html";
|
||||
const TEST_IFRAME_PAGE = TEST_DOMAIN + TEST_PATH + "iframe.html";
|
||||
|
@ -0,0 +1,175 @@
|
||||
/* import-globals-from ../../../../../browser/modules/test/browser/head.js */
|
||||
/* import-globals-from antitracking_head.js */
|
||||
|
||||
async function openPageAndRunCode(
|
||||
topPage,
|
||||
topPageCallback,
|
||||
embeddedPage,
|
||||
embeddedPageCallback
|
||||
) {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab({
|
||||
gBrowser,
|
||||
url: topPage,
|
||||
waitForLoad: true,
|
||||
});
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
|
||||
await topPageCallback();
|
||||
await SpecialPowers.spawn(
|
||||
browser,
|
||||
[{ page: embeddedPage, callback: embeddedPageCallback.toString() }],
|
||||
async function(obj) {
|
||||
await new content.Promise(resolve => {
|
||||
let ifr = content.document.createElement("iframe");
|
||||
ifr.onload = function() {
|
||||
ifr.contentWindow.postMessage(obj.callback, "*");
|
||||
};
|
||||
|
||||
content.addEventListener("message", function msg(event) {
|
||||
if (event.data.type == "finish") {
|
||||
content.removeEventListener("message", msg);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "ok") {
|
||||
ok(event.data.what, event.data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "info") {
|
||||
info(event.data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ok(false, "Unknown message");
|
||||
});
|
||||
|
||||
content.document.body.appendChild(ifr);
|
||||
ifr.src = obj.page;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
// This function returns a function that spawns an asynchronous task to handle
|
||||
// the popup and click on the appropriate values. If that task is never executed
|
||||
// the catch case is reached and we fail the test. If for some reason that catch
|
||||
// case isn't reached, having an extra event listener at the end of the test
|
||||
// will cause the test to fail anyway.
|
||||
// Note: this means that tests that use this callback should probably be in
|
||||
// their own test file.
|
||||
function getExpectPopupAndClick(accept) {
|
||||
return function() {
|
||||
let shownPromise = BrowserTestUtils.waitForEvent(
|
||||
PopupNotifications.panel,
|
||||
"popupshown"
|
||||
);
|
||||
shownPromise
|
||||
.then(async _ => {
|
||||
// This occurs when the promise resolves on the test finishing
|
||||
let popupNotifications = PopupNotifications.panel.childNodes;
|
||||
if (!popupNotifications.length) {
|
||||
ok(false, "Prompt did not show up");
|
||||
} else if (accept == "accept") {
|
||||
ok(true, "Prompt shows up, clicking accept.");
|
||||
await clickMainAction();
|
||||
} else if (accept == "reject") {
|
||||
ok(true, "Prompt shows up, clicking reject.");
|
||||
await clickSecondaryAction();
|
||||
} else {
|
||||
ok(false, "Unknown accept value for test: " + accept);
|
||||
info("Clicking accept so that the test can finish.");
|
||||
await clickMainAction();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
ok(false, "Prompt did not show up");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// This function spawns an asynchronous task that fails the test if a popup
|
||||
// appears. If that never happens, the catch case is executed on the test
|
||||
// cleanup.
|
||||
// Note: this means that tests that use this callback should probably be in
|
||||
// their own test file.
|
||||
function expectNoPopup() {
|
||||
let shownPromise = BrowserTestUtils.waitForEvent(
|
||||
PopupNotifications.panel,
|
||||
"popupshown"
|
||||
);
|
||||
shownPromise
|
||||
.then(async _ => {
|
||||
// This occurs when the promise resolves on the test finishing
|
||||
let popupNotifications = PopupNotifications.panel.childNodes;
|
||||
if (!popupNotifications.length) {
|
||||
ok(true, "Prompt did not show up");
|
||||
} else {
|
||||
ok(false, "Prompt shows up");
|
||||
info(PopupNotifications.panel);
|
||||
await clickSecondaryAction();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
ok(true, "Prompt did not show up");
|
||||
});
|
||||
}
|
||||
|
||||
async function requestStorageAccessAndExpectSuccess() {
|
||||
SpecialPowers.wrap(document).notifyUserGestureActivation();
|
||||
let p = document.requestStorageAccess();
|
||||
try {
|
||||
await p;
|
||||
ok(true, "gain storage access.");
|
||||
} catch {
|
||||
ok(false, "denied storage access.");
|
||||
}
|
||||
SpecialPowers.wrap(document).clearUserGestureActivation();
|
||||
}
|
||||
|
||||
async function requestStorageAccessAndExpectFailure() {
|
||||
SpecialPowers.wrap(document).notifyUserGestureActivation();
|
||||
let p = document.requestStorageAccess();
|
||||
try {
|
||||
await p;
|
||||
ok(false, "gain storage access.");
|
||||
} catch {
|
||||
ok(true, "denied storage access.");
|
||||
}
|
||||
SpecialPowers.wrap(document).clearUserGestureActivation();
|
||||
}
|
||||
|
||||
async function cleanUpData() {
|
||||
await new Promise(resolve => {
|
||||
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value =>
|
||||
resolve()
|
||||
);
|
||||
});
|
||||
ok(true, "Deleted all data.");
|
||||
}
|
||||
|
||||
async function setPreferences() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["dom.storage_access.auto_grants", true],
|
||||
["dom.storage_access.auto_grants.delayed", false],
|
||||
["dom.storage_access.enabled", true],
|
||||
["dom.storage_access.max_concurrent_auto_grants", 0],
|
||||
["dom.storage_access.prompt.testing", false],
|
||||
[
|
||||
"network.cookie.cookieBehavior",
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
|
||||
],
|
||||
[
|
||||
"network.cookie.cookieBehavior.pbmode",
|
||||
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
|
||||
],
|
||||
["privacy.trackingprotection.enabled", false],
|
||||
["privacy.trackingprotection.pbmode.enabled", false],
|
||||
["privacy.trackingprotection.annotate_channels", true],
|
||||
],
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user