Bug 1954188: bFPP Part 2 - Implement granular overrides. r=tjr
Differential Revision: https://phabricator.services.mozilla.com/D241852
This commit is contained in:
@@ -570,6 +570,10 @@ nsresult ServiceWorkerPrivate::Initialize() {
|
||||
nsCOMPtr<nsIURI> firstPartyURI;
|
||||
bool foreignByAncestorContext = false;
|
||||
bool isOn3PCBExceptionList = false;
|
||||
// Firefox doesn't support service workers in PBM,
|
||||
// but we add this just so that when we do,
|
||||
// we can handle it correctly.
|
||||
bool isPBM = principal->GetIsInPrivateBrowsing();
|
||||
if (!principal->OriginAttributesRef().mPartitionKey.IsEmpty()) {
|
||||
net::CookieJarSettings::Cast(cookieJarSettings)
|
||||
->SetPartitionKey(principal->OriginAttributesRef().mPartitionKey);
|
||||
@@ -592,7 +596,7 @@ nsresult ServiceWorkerPrivate::Initialize() {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
overriddenFingerprintingSettings =
|
||||
nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
firstPartyURI, uri);
|
||||
firstPartyURI, uri, isPBM);
|
||||
if (overriddenFingerprintingSettings.isSome()) {
|
||||
overriddenFingerprintingSettingsArg.emplace(
|
||||
overriddenFingerprintingSettings.ref());
|
||||
@@ -625,9 +629,9 @@ nsresult ServiceWorkerPrivate::Initialize() {
|
||||
overriddenFingerprintingSettings =
|
||||
isThirdParty
|
||||
? nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
firstPartyURI, uri)
|
||||
firstPartyURI, uri, isPBM)
|
||||
: nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
uri, nullptr);
|
||||
uri, nullptr, isPBM);
|
||||
|
||||
RefPtr<net::CookieService> csSingleton =
|
||||
net::CookieService::GetSingleton();
|
||||
@@ -650,7 +654,8 @@ nsresult ServiceWorkerPrivate::Initialize() {
|
||||
// the service worker as the first-party domain to get the fingerprinting
|
||||
// protection overrides.
|
||||
overriddenFingerprintingSettings =
|
||||
nsRFPService::GetOverriddenFingerprintingSettingsForURI(uri, nullptr);
|
||||
nsRFPService::GetOverriddenFingerprintingSettingsForURI(uri, nullptr,
|
||||
isPBM);
|
||||
|
||||
if (overriddenFingerprintingSettings.isSome()) {
|
||||
overriddenFingerprintingSettingsArg.emplace(
|
||||
@@ -658,7 +663,6 @@ nsresult ServiceWorkerPrivate::Initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
bool isPBM = principal->GetIsInPrivateBrowsing();
|
||||
if (ContentBlockingAllowList::Check(principal, isPBM)) {
|
||||
net::CookieJarSettings::Cast(cookieJarSettings)
|
||||
->SetIsOnContentBlockingAllowList(true);
|
||||
|
||||
@@ -49,6 +49,8 @@ const SCHEMA = `{
|
||||
const COLLECTION_NAME = "fingerprinting-protection-overrides";
|
||||
const PREF_GRANULAR_OVERRIDES =
|
||||
"privacy.fingerprintingProtection.granularOverrides";
|
||||
const PREF_GRANULAR_OVERRIDES_BASELINE =
|
||||
"privacy.baselineFingerprintingProtection.granularOverrides";
|
||||
const PREF_REMOTE_OVERRIDES_ENABLED =
|
||||
"privacy.fingerprintingProtection.remoteOverrides.enabled";
|
||||
|
||||
@@ -58,6 +60,12 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
PREF_GRANULAR_OVERRIDES
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"baselineGranularOverridesPref",
|
||||
PREF_GRANULAR_OVERRIDES_BASELINE
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"remoteOverridesEnabled",
|
||||
@@ -71,10 +79,11 @@ export class FingerprintingOverride {
|
||||
classID = Components.ID("{07f45442-1806-44be-9230-12eb79de9bac}");
|
||||
QueryInterface = ChromeUtils.generateQI(["nsIFingerprintingOverride"]);
|
||||
|
||||
constructor(firstPartyDomain, thirdPartyDomain, overrides) {
|
||||
constructor(firstPartyDomain, thirdPartyDomain, overrides, isBaseline) {
|
||||
this.firstPartyDomain = firstPartyDomain;
|
||||
this.thirdPartyDomain = thirdPartyDomain;
|
||||
this.overrides = overrides;
|
||||
this.isBaseline = isBaseline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +134,7 @@ export class FingerprintingWebCompatService {
|
||||
|
||||
// Register listener to import overrides when the overrides pref changes.
|
||||
Services.prefs.addObserver(PREF_GRANULAR_OVERRIDES, this);
|
||||
Services.prefs.addObserver(PREF_GRANULAR_OVERRIDES_BASELINE, this);
|
||||
|
||||
// Register the sync event for the remote settings updates.
|
||||
this.#rs.on("sync", event => {
|
||||
@@ -155,9 +165,13 @@ export class FingerprintingWebCompatService {
|
||||
// Clear overrides before we update.
|
||||
this.#granularOverrides.clear();
|
||||
|
||||
for (const [pref, isBaseline] of [
|
||||
[lazy.baselineGranularOverridesPref, true],
|
||||
[lazy.granularOverridesPref, false],
|
||||
]) {
|
||||
let overrides;
|
||||
try {
|
||||
overrides = JSON.parse(lazy.granularOverridesPref || "[]");
|
||||
overrides = JSON.parse(pref || "[]");
|
||||
} catch (error) {
|
||||
lazy.logConsole.error(
|
||||
`Failed to parse granular override JSON string: Not a valid JSON.`,
|
||||
@@ -184,10 +198,11 @@ export class FingerprintingWebCompatService {
|
||||
}
|
||||
|
||||
this.#granularOverrides.add(
|
||||
this.#createFingerprintingOverrideFrom(override)
|
||||
this.#createFingerprintingOverrideFrom(override, isBaseline)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import fingerprinting overrides from the remote settings.
|
||||
async #importRemoteSettingsOverrides() {
|
||||
@@ -217,11 +232,18 @@ export class FingerprintingWebCompatService {
|
||||
}
|
||||
}
|
||||
|
||||
#createFingerprintingOverrideFrom(entry) {
|
||||
#createFingerprintingOverrideFrom(entry, isBaselineOverride = null) {
|
||||
// If the isBaselineOverride is not provided, we will use the value from the
|
||||
// entry. If the entry doesn't have the isBaseline field, we will default to
|
||||
// false.
|
||||
// We default to false because we didn't have the baseline mode in the past,
|
||||
// and the existing entries don't have the isBaseline field.
|
||||
const isBaseline = isBaselineOverride ?? entry.isBaseline ?? false;
|
||||
return new FingerprintingOverride(
|
||||
entry.firstPartyDomain,
|
||||
entry.thirdPartyDomain,
|
||||
entry.overrides
|
||||
entry.overrides,
|
||||
isBaseline
|
||||
);
|
||||
}
|
||||
|
||||
@@ -240,7 +262,10 @@ export class FingerprintingWebCompatService {
|
||||
}
|
||||
|
||||
observe(subject, topic, prefName) {
|
||||
if (prefName != PREF_GRANULAR_OVERRIDES) {
|
||||
if (
|
||||
prefName != PREF_GRANULAR_OVERRIDES &&
|
||||
prefName != PREF_GRANULAR_OVERRIDES_BASELINE
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,5 +277,6 @@ export class FingerprintingWebCompatService {
|
||||
lazy.logConsole.debug("shutdown");
|
||||
|
||||
Services.prefs.removeObserver(PREF_GRANULAR_OVERRIDES, this);
|
||||
Services.prefs.removeObserver(PREF_GRANULAR_OVERRIDES_BASELINE, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ interface nsIFingerprintingOverride : nsISupports
|
||||
* fingerprinting override pref "privacy.fingerprintingProtection.overrides".
|
||||
*/
|
||||
readonly attribute ACString overrides;
|
||||
|
||||
/**
|
||||
* Whether the override is baseline or FPP.
|
||||
*/
|
||||
readonly attribute boolean isBaseline;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2072,6 +2072,10 @@ nsresult nsRFPService::CreateOverrideDomainKey(
|
||||
nsresult rv = aOverride->GetFirstPartyDomain(firstPartyDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isBaseline = false;
|
||||
rv = aOverride->GetIsBaseline(&isBaseline);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The first party domain shouldn't be empty. And it shouldn't contain a comma
|
||||
// because we use a comma as a delimiter.
|
||||
if (firstPartyDomain.IsEmpty() ||
|
||||
@@ -2102,6 +2106,9 @@ nsresult nsRFPService::CreateOverrideDomainKey(
|
||||
aDomainKey.Append(thirdPartyDomain);
|
||||
}
|
||||
|
||||
aDomainKey.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
aDomainKey.Append(isBaseline ? "1" : "0");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -2162,8 +2169,9 @@ nsRFPService::SetFingerprintingOverrides(
|
||||
const nsTArray<RefPtr<nsIFingerprintingOverride>>& aOverrides) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Clear all overrides before importing.
|
||||
mFingerprintingOverrides.Clear();
|
||||
CleanAllOverrides();
|
||||
|
||||
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
|
||||
for (const auto& fpOverride : aOverrides) {
|
||||
nsAutoCString domainKey;
|
||||
|
||||
@@ -2177,14 +2185,18 @@ nsRFPService::SetFingerprintingOverrides(
|
||||
rv = fpOverride->GetOverrides(overridesText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
|
||||
bool isBaseline = false;
|
||||
rv = fpOverride->GetIsBaseline(&isBaseline);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
RFPTargetSet baseOverrides = isBaseline
|
||||
? sEnabledFingerprintingProtectionsBase
|
||||
: sEnabledFingerprintingProtections;
|
||||
RFPTargetSet targets = nsRFPService::CreateOverridesFromText(
|
||||
NS_ConvertUTF8toUTF16(overridesText),
|
||||
mFingerprintingOverrides.Contains(domainKey)
|
||||
? mFingerprintingOverrides.Get(domainKey)
|
||||
// TODO(fkilic): We will handle granular overrides in the following
|
||||
// patches.
|
||||
: sEnabledFingerprintingProtections);
|
||||
: baseOverrides);
|
||||
|
||||
// The newly added one will replace the existing one for the given domain
|
||||
// key.
|
||||
@@ -2273,9 +2285,11 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool isPrivate = loadInfo->GetOriginAttributes().IsPrivateBrowsing();
|
||||
|
||||
// The channel is for the first-party load.
|
||||
if (!AntiTrackingUtils::IsThirdPartyChannel(aChannel)) {
|
||||
return GetOverriddenFingerprintingSettingsForURI(uri, nullptr);
|
||||
return GetOverriddenFingerprintingSettingsForURI(uri, nullptr, isPrivate);
|
||||
}
|
||||
|
||||
// The channel is for the third-party load. We get the first-party URI from
|
||||
@@ -2328,7 +2342,7 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
|
||||
rv = NS_NewURI(getter_AddRefs(topURI), scheme + u"://"_ns + domain);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
return GetOverriddenFingerprintingSettingsForURI(topURI, uri);
|
||||
return GetOverriddenFingerprintingSettingsForURI(topURI, uri, isPrivate);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> topPrincipal = topWGP->DocumentPrincipal();
|
||||
@@ -2380,12 +2394,12 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
|
||||
attrsForeignByAncestor.mPartitionKey.Equals(partitionKey));
|
||||
#endif
|
||||
|
||||
return GetOverriddenFingerprintingSettingsForURI(topURI, uri);
|
||||
return GetOverriddenFingerprintingSettingsForURI(topURI, uri, isPrivate);
|
||||
}
|
||||
|
||||
/* static */
|
||||
Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI) {
|
||||
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI, bool aIsPrivate) {
|
||||
MOZ_ASSERT(aFirstPartyURI);
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
@@ -2399,9 +2413,17 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
// will take over {first-party domain, *} because the latter one has a smaller
|
||||
// scope.
|
||||
|
||||
bool isBaseline = !IsFPPEnabled(aIsPrivate);
|
||||
auto addIsBaseline = [](nsAutoCString& aKey, bool aIsBaseline) {
|
||||
aKey.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
aKey.Append(aIsBaseline ? "1" : "0");
|
||||
};
|
||||
|
||||
// First, we get the overrides that applies to every context.
|
||||
Maybe<RFPTargetSet> result =
|
||||
service->mFingerprintingOverrides.MaybeGet("*"_ns);
|
||||
nsAutoCString key;
|
||||
key.Assign("*"_ns);
|
||||
addIsBaseline(key, isBaseline);
|
||||
Maybe<RFPTargetSet> result = service->mFingerprintingOverrides.MaybeGet(key);
|
||||
|
||||
nsCOMPtr<nsIEffectiveTLDService> eTLDService =
|
||||
mozilla::components::EffectiveTLD::Service();
|
||||
@@ -2424,11 +2446,10 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
// first-party domain.
|
||||
if (!aThirdPartyURI) {
|
||||
// Test the {first-party domain, *} scope.
|
||||
nsAutoCString key;
|
||||
key.Assign(firstPartyDomain);
|
||||
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
key.Append("*");
|
||||
|
||||
key.Append("*"_ns);
|
||||
addIsBaseline(key, isBaseline);
|
||||
Maybe<RFPTargetSet> fpOverrides =
|
||||
service->mFingerprintingOverrides.MaybeGet(key);
|
||||
if (fpOverrides) {
|
||||
@@ -2436,7 +2457,9 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
}
|
||||
|
||||
// Test the {first-party domain} scope.
|
||||
fpOverrides = service->mFingerprintingOverrides.MaybeGet(firstPartyDomain);
|
||||
key.Assign(firstPartyDomain);
|
||||
addIsBaseline(key, isBaseline);
|
||||
fpOverrides = service->mFingerprintingOverrides.MaybeGet(key);
|
||||
if (fpOverrides) {
|
||||
result = fpOverrides;
|
||||
}
|
||||
@@ -2460,10 +2483,10 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
}
|
||||
|
||||
// Test {first-party domain, *} scope.
|
||||
nsAutoCString key;
|
||||
key.Assign(firstPartyDomain);
|
||||
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
key.Append("*");
|
||||
key.Append("*"_ns);
|
||||
addIsBaseline(key, isBaseline);
|
||||
Maybe<RFPTargetSet> fpOverrides =
|
||||
service->mFingerprintingOverrides.MaybeGet(key);
|
||||
if (fpOverrides) {
|
||||
@@ -2474,6 +2497,7 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
key.Assign("*");
|
||||
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
key.Append(thirdPartyDomain);
|
||||
addIsBaseline(key, isBaseline);
|
||||
fpOverrides = service->mFingerprintingOverrides.MaybeGet(key);
|
||||
if (fpOverrides) {
|
||||
result = fpOverrides;
|
||||
@@ -2483,6 +2507,7 @@ Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
|
||||
key.Assign(firstPartyDomain);
|
||||
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
|
||||
key.Append(thirdPartyDomain);
|
||||
addIsBaseline(key, isBaseline);
|
||||
fpOverrides = service->mFingerprintingOverrides.MaybeGet(key);
|
||||
if (fpOverrides) {
|
||||
result = fpOverrides;
|
||||
|
||||
@@ -355,7 +355,7 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
|
||||
// and third-party URI. Otherwise, it will return Nothing() to indicate using
|
||||
// the default RFPTargets.
|
||||
static Maybe<RFPTargetSet> GetOverriddenFingerprintingSettingsForURI(
|
||||
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI);
|
||||
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI, bool aIsPrivate);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user