Bug 1939881: Implement RFPTargetBits and replace appropriate uses. r=tjr

This is a huge patch, but it is only really refactoring of RFPTarget enum. We used to use RFPTarget as a bitset and now we ran out of bits, so now we need a workaround.

Differential Revision: https://phabricator.services.mozilla.com/D233182
This commit is contained in:
Fatih Kilic
2025-01-23 14:49:44 +00:00
parent 6f24b3ba80
commit 73f4f01465
39 changed files with 377 additions and 251 deletions

View File

@@ -14,7 +14,6 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/UserActivationIPCUtils.h"
#include "mozilla/PermissionDelegateIPCUtils.h"
#include "mozilla/RFPTargetIPCUtils.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ClearOnShutdown.h"
@@ -22,6 +21,7 @@
#include "nsIScriptError.h"
#include "nsIWebProgressListener.h"
#include "nsIXULRuntime.h"
#include "nsRFPTargetSetIDL.h"
#include "nsRefPtrHashtable.h"
#include "nsContentUtils.h"
@@ -78,6 +78,19 @@ bool WindowContext::IsInBFCache() {
return TopWindowContext()->GetWindowStateSaved();
}
already_AddRefed<nsIRFPTargetSetIDL>
WindowContext::GetOverriddenFingerprintingSettingsWebIDL() const {
Maybe<RFPTargetSet> overriddenFingerprintingSettings =
GetOverriddenFingerprintingSettings();
if (overriddenFingerprintingSettings.isNothing()) {
return nullptr;
}
nsCOMPtr<nsIRFPTargetSetIDL> protections =
new nsRFPTargetSetIDL(overriddenFingerprintingSettings.ref());
return protections.forget();
}
nsGlobalWindowInner* WindowContext::GetInnerWindow() const {
return mWindowGlobalChild ? mWindowGlobalChild->GetWindowGlobal() : nullptr;
}
@@ -241,7 +254,7 @@ bool WindowContext::CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
}
bool WindowContext::CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>,
const Maybe<RFPTarget>& aValue,
const Maybe<RFPTargetSet>& aValue,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}

View File

@@ -23,6 +23,7 @@ class nsGlobalWindowInner;
namespace mozilla {
class LogModule;
class nsRFPTargetSetIDL;
namespace dom {
@@ -55,7 +56,7 @@ class BrowsingContextGroup;
* the Storage Access API */ \
FIELD(UsingStorageAccess, bool) \
FIELD(ShouldResistFingerprinting, bool) \
FIELD(OverriddenFingerprintingSettings, Maybe<RFPTarget>) \
FIELD(OverriddenFingerprintingSettings, Maybe<RFPTargetSet>) \
FIELD(IsSecureContext, bool) \
FIELD(IsOriginalFrameSource, bool) \
/* Mixed-Content: If the corresponding documentURI is https, \
@@ -139,15 +140,8 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool UsingStorageAccess() const { return GetUsingStorageAccess(); }
Nullable<uint64_t> GetOverriddenFingerprintingSettingsWebIDL() const {
Maybe<RFPTarget> overriddenFingerprintingSettings =
GetOverriddenFingerprintingSettings();
return overriddenFingerprintingSettings.isSome()
? Nullable<uint64_t>(
uint64_t(overriddenFingerprintingSettings.ref()))
: Nullable<uint64_t>();
}
already_AddRefed<nsIRFPTargetSetIDL>
GetOverriddenFingerprintingSettingsWebIDL() const;
nsGlobalWindowInner* GetInnerWindow() const;
Document* GetDocument() const;
@@ -305,7 +299,7 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_ShouldResistFingerprinting>,
const bool& aShouldResistFingerprinting, ContentParent* aSource);
bool CanSet(FieldIndex<IDX_OverriddenFingerprintingSettings>,
const Maybe<RFPTarget>& aValue, ContentParent* aSource);
const Maybe<RFPTargetSet>& aValue, ContentParent* aSource);
bool CanSet(FieldIndex<IDX_IsSecureContext>, const bool& aIsSecureContext,
ContentParent* aSource);
bool CanSet(FieldIndex<IDX_IsOriginalFrameSource>,

View File

@@ -60,6 +60,7 @@
#include "mozilla/RemoteDecoderManagerChild.h"
#include "mozilla/KeySystemConfig.h"
#include "mozilla/WheelHandlingHelper.h"
#include "nsIRFPTargetSetIDL.h"
#include "nsContentSecurityUtils.h"
#include "nsString.h"
#include "nsNativeTheme.h"
@@ -2317,7 +2318,7 @@ void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject& aGlobal,
/* static */
bool ChromeUtils::ShouldResistFingerprinting(
GlobalObject& aGlobal, JSRFPTarget aTarget,
const Nullable<uint64_t>& aOverriddenFingerprintingSettings,
nsIRFPTargetSetIDL* aOverriddenFingerprintingSettings,
const Optional<bool>& aIsPBM) {
RFPTarget target;
switch (aTarget) {
@@ -2351,10 +2352,16 @@ bool ChromeUtils::ShouldResistFingerprinting(
}
}
Maybe<RFPTarget> overriddenFingerprintingSettings;
if (!aOverriddenFingerprintingSettings.IsNull()) {
overriddenFingerprintingSettings.emplace(
RFPTarget(aOverriddenFingerprintingSettings.Value()));
Maybe<RFPTargetSet> overriddenFingerprintingSettings;
if (aOverriddenFingerprintingSettings) {
uint64_t low, hi;
aOverriddenFingerprintingSettings->GetLow(&low);
aOverriddenFingerprintingSettings->GetHigh(&hi);
std::bitset<128> bitset;
bitset |= hi;
bitset <<= 64;
bitset |= low;
overriddenFingerprintingSettings.emplace(RFPTargetSet(bitset));
}
// This global object appears to be the global window, not for individual

View File

@@ -16,6 +16,8 @@
#include "nsIDOMProcessChild.h"
#include "nsIDOMProcessParent.h"
class nsIRFPTargetSetIDL;
namespace mozilla {
class ErrorResult;
@@ -326,7 +328,7 @@ class ChromeUtils {
static bool ShouldResistFingerprinting(
GlobalObject& aGlobal, JSRFPTarget aTarget,
const Nullable<uint64_t>& aOverriddenFingerprintingSettings,
nsIRFPTargetSetIDL* aOverriddenFingerprintingSettings,
const Optional<bool>& aIsPBM);
static void SanitizeTelemetryFileURL(GlobalObject& aGlobal,

View File

@@ -4200,7 +4200,7 @@ class Document : public nsINode,
bool ShouldResistFingerprinting(RFPTarget aTarget) const;
bool IsInPrivateBrowsing() const;
const Maybe<RFPTarget>& GetOverriddenFingerprintingSettings() const {
const Maybe<RFPTargetSet>& GetOverriddenFingerprintingSettings() const {
return mOverriddenFingerprintingSettings;
}
@@ -4986,7 +4986,7 @@ class Document : public nsINode,
// This will only get populated if these is one that comes from the local
// fingerprinting protection override pref or WebCompat. Otherwise, a value of
// Nothing() indicates no overrides are present for this document.
Maybe<RFPTarget> mOverriddenFingerprintingSettings;
Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
uint8_t mXMLDeclarationBits;

View File

@@ -2013,6 +2013,7 @@ addExternalIface('nsIScreen', nativeType='nsIScreen',
headerFile='nsIScreen.h', notflattened=True)
addExternalIface('InputStream',
nativeType='nsIInputStream', notflattened=True)
addExternalIface('nsIRFPTargetSetIDL', nativeType='nsIRFPTargetSetIDL')
# The TemplatedAttributes dictionary has the interface name where the template
# should be generated as the key. The values are lists of dictionaries, where

View File

@@ -7,6 +7,7 @@
interface nsIDOMProcessChild;
interface nsIDOMProcessParent;
interface Principal;
interface nsIRFPTargetSetIDL;
/**
* An optimized QueryInterface method, generated by generateQI.
@@ -749,7 +750,7 @@ partial namespace ChromeUtils {
sequence<UTF8String> getAllPossibleUtilityActorNames();
boolean shouldResistFingerprinting(JSRFPTarget target,
unsigned long long? overriddenFingerprintingSettings,
nsIRFPTargetSetIDL? overriddenFingerprintingSettings,
optional boolean isPBM);
FileNameTypeDetails sanitizeTelemetryFileURL(UTF8String url);

View File

@@ -8,6 +8,7 @@ interface URI;
interface nsIDocShell;
interface RemoteTab;
interface nsIDOMProcessParent;
interface nsIRFPTargetSetIDL;
[Exposed=Window, ChromeOnly]
interface WindowContext {
@@ -43,7 +44,7 @@ interface WindowContext {
// null, which means we are using default fingerprinting protection in the
// context.
[BinaryName="OverriddenFingerprintingSettingsWebIDL"]
readonly attribute unsigned long long? overriddenFingerprintingSettings;
readonly attribute nsIRFPTargetSetIDL? overriddenFingerprintingSettings;
/**
* Partially determines whether script execution is allowed in this

View File

@@ -4647,7 +4647,7 @@ void ContentChild::ConfigureThreadPerformanceHints(
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
for (size_t i = 0; i < cpuInfo->mTotalNumCpus; i++) {
if (cpus.Test(i)) {
if (cpus.test(i)) {
CPU_SET(i, &cpuset);
}
}

View File

@@ -553,8 +553,8 @@ nsresult ServiceWorkerPrivate::Initialize() {
// it's a third-party service worker. So, the cookieJarSettings can directly
// use the partitionKey from it. For first-party case, we can populate the
// partitionKey from the principal URI.
Maybe<uint64_t> overriddenFingerprintingSettingsArg;
Maybe<RFPTarget> overriddenFingerprintingSettings;
Maybe<RFPTargetSet> overriddenFingerprintingSettingsArg;
Maybe<RFPTargetSet> overriddenFingerprintingSettings;
nsCOMPtr<nsIURI> firstPartyURI;
bool foreignByAncestorContext = false;
bool isOn3PCBExceptionList = false;
@@ -583,7 +583,7 @@ nsresult ServiceWorkerPrivate::Initialize() {
firstPartyURI, uri);
if (overriddenFingerprintingSettings.isSome()) {
overriddenFingerprintingSettingsArg.emplace(
uint64_t(overriddenFingerprintingSettings.ref()));
overriddenFingerprintingSettings.ref());
}
RefPtr<net::CookieService> csSingleton =
@@ -626,7 +626,7 @@ nsresult ServiceWorkerPrivate::Initialize() {
if (overriddenFingerprintingSettings.isSome()) {
overriddenFingerprintingSettingsArg.emplace(
uint64_t(overriddenFingerprintingSettings.ref()));
overriddenFingerprintingSettings.ref());
}
}
} else {
@@ -642,7 +642,7 @@ nsresult ServiceWorkerPrivate::Initialize() {
if (overriddenFingerprintingSettings.isSome()) {
overriddenFingerprintingSettingsArg.emplace(
uint64_t(overriddenFingerprintingSettings.ref()));
overriddenFingerprintingSettings.ref());
}
}

View File

@@ -146,7 +146,7 @@ struct WorkerLoadInfoData {
bool mUsingStorageAccess;
bool mServiceWorkersTestingInWindow;
bool mShouldResistFingerprinting;
Maybe<RFPTarget> mOverriddenFingerprintingSettings;
Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
OriginAttributes mOriginAttributes;
bool mIsThirdPartyContext;
bool mIsOn3PCBExceptionList;

View File

@@ -1028,7 +1028,7 @@ class WorkerPrivate final
bool ShouldResistFingerprinting(RFPTarget aTarget) const;
const Maybe<RFPTarget>& GetOverriddenFingerprintingSettings() const {
const Maybe<RFPTargetSet>& GetOverriddenFingerprintingSettings() const {
return mLoadInfo.mOverriddenFingerprintingSettings;
}

View File

@@ -280,10 +280,10 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(
info.mOriginAttributes =
BasePrincipal::Cast(principal)->OriginAttributesRef();
info.mShouldResistFingerprinting = aData.shouldResistFingerprinting();
Maybe<RFPTarget> overriddenFingerprintingSettings;
Maybe<RFPTargetSet> overriddenFingerprintingSettings;
if (aData.overriddenFingerprintingSettings().isSome()) {
overriddenFingerprintingSettings.emplace(
RFPTarget(aData.overriddenFingerprintingSettings().ref()));
aData.overriddenFingerprintingSettings().ref());
}
info.mOverriddenFingerprintingSettings = overriddenFingerprintingSettings;
net::CookieJarSettings::Deserialize(aData.cookieJarSettings(),

View File

@@ -19,6 +19,7 @@ using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
using mozilla::dom::WorkerOptions from "mozilla/dom/WorkerBinding.h";
using mozilla::StorageAccess from "mozilla/StorageAccess.h";
using mozilla::OriginTrials from "mozilla/OriginTrialsIPCUtils.h";
using mozilla::RFPTargetSet from "nsRFPService.h";
namespace mozilla {
namespace dom {
@@ -85,7 +86,7 @@ struct RemoteWorkerData
bool shouldResistFingerprinting;
uint64_t? overriddenFingerprintingSettings;
RFPTargetSet? overriddenFingerprintingSettings;
bool isOn3PCBExceptionList;

View File

@@ -253,10 +253,10 @@ already_AddRefed<SharedWorker> SharedWorker::Constructor(
return nullptr;
}
Maybe<uint64_t> overriddenFingerprintingSettingsArg;
Maybe<RFPTargetSet> overriddenFingerprintingSettingsArg;
if (loadInfo.mOverriddenFingerprintingSettings.isSome()) {
overriddenFingerprintingSettingsArg.emplace(
uint64_t(loadInfo.mOverriddenFingerprintingSettings.ref()));
loadInfo.mOverriddenFingerprintingSettings.ref());
}
RemoteWorkerData remoteWorkerData(

View File

@@ -128,7 +128,7 @@ class WorkletImpl {
// This will only get populated if these is one that comes from the local
// granular override pref or WebCompat. Otherwise, a value of Nothing()
// indicates no granular overrides are present for this workerlet.
Maybe<RFPTarget> mOverriddenFingerprintingSettings;
Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
const OriginTrials mTrials;
};

View File

@@ -545,13 +545,13 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
redirectChain, interceptionInfo->FromThirdParty()));
}
Maybe<uint64_t> overriddenFingerprintingSettingsArg;
Maybe<RFPTarget> overriddenFingerprintingSettings =
Maybe<RFPTargetSet> overriddenFingerprintingSettingsArg;
Maybe<RFPTargetSet> overriddenFingerprintingSettings =
aLoadInfo->GetOverriddenFingerprintingSettings();
if (overriddenFingerprintingSettings) {
overriddenFingerprintingSettingsArg =
Some(uint64_t(overriddenFingerprintingSettings.ref()));
Some(overriddenFingerprintingSettings.ref());
}
*outLoadInfoArgs = LoadInfoArgs(
@@ -790,10 +790,10 @@ nsresult LoadInfoArgsToLoadInfo(const LoadInfoArgs& loadInfoArgs,
CookieJarSettings::Deserialize(loadInfoArgs.cookieJarSettings(),
getter_AddRefs(cookieJarSettings));
Maybe<RFPTarget> overriddenFingerprintingSettings;
Maybe<RFPTargetSet> overriddenFingerprintingSettings;
if (loadInfoArgs.overriddenFingerprintingSettings().isSome()) {
overriddenFingerprintingSettings.emplace(
RFPTarget(loadInfoArgs.overriddenFingerprintingSettings().ref()));
loadInfoArgs.overriddenFingerprintingSettings().ref());
}
nsCOMPtr<nsIContentSecurityPolicy> cspToInherit;
@@ -955,13 +955,13 @@ void LoadInfoToParentLoadInfoForwarder(
aLoadInfo->GetIsThirdPartyContextToTopWindow());
}
Maybe<uint64_t> overriddenFingerprintingSettingsArg;
Maybe<RFPTarget> overriddenFingerprintingSettings =
Maybe<RFPTargetSet> overriddenFingerprintingSettingsArg;
Maybe<RFPTargetSet> overriddenFingerprintingSettings =
aLoadInfo->GetOverriddenFingerprintingSettings();
if (overriddenFingerprintingSettings) {
overriddenFingerprintingSettingsArg =
Some(uint64_t(overriddenFingerprintingSettings.ref()));
Some(overriddenFingerprintingSettings.ref());
}
*aForwarderArgsOut = ParentLoadInfoForwarderArgs(
@@ -1081,11 +1081,11 @@ nsresult MergeParentLoadInfoForwarder(
rv = aLoadInfo->SetIsMetaRefresh(aForwarderArgs.isMetaRefresh());
NS_ENSURE_SUCCESS(rv, rv);
const Maybe<uint64_t> overriddenFingerprintingSettings =
const Maybe<RFPTargetSet> overriddenFingerprintingSettings =
aForwarderArgs.overriddenFingerprintingSettings();
if (overriddenFingerprintingSettings.isSome()) {
aLoadInfo->SetOverriddenFingerprintingSettings(
RFPTarget(overriddenFingerprintingSettings.ref()));
overriddenFingerprintingSettings.ref());
}
static_cast<LoadInfo*>(aLoadInfo)->ClearIsThirdPartyContextToTopWindow();

View File

@@ -56,7 +56,7 @@ class BitSet {
return *this;
}
MOZ_IMPLICIT operator bool() const { return mBitSet.Test(mPos); }
MOZ_IMPLICIT operator bool() const { return mBitSet.test(mPos); }
private:
BitSet<N, Word>& mBitSet;
@@ -76,9 +76,9 @@ class BitSet {
PodCopy(mStorage.begin(), aStorage.Elements(), kNumWords);
}
static constexpr size_t Size() { return N; }
static constexpr size_t size() { return N; }
constexpr bool Test(size_t aPos) const {
constexpr bool test(size_t aPos) const {
MOZ_ASSERT(aPos < N);
return mStorage[aPos / kBitsPerWord] & (Word(1) << (aPos % kBitsPerWord));
}
@@ -94,7 +94,7 @@ class BitSet {
explicit constexpr operator bool() { return !IsEmpty(); }
constexpr bool operator[](size_t aPos) const { return Test(aPos); }
constexpr bool operator[](size_t aPos) const { return test(aPos); }
Reference operator[](size_t aPos) {
MOZ_ASSERT(aPos < N);
@@ -193,7 +193,7 @@ class BitSet {
return wordIndex * kBitsPerWord + pos;
}
size_t FindLast() const { return FindPrev(Size() - 1); }
size_t FindLast() const { return FindPrev(size() - 1); }
// Return the position of the previous bit set starting from |aFromPos|
// inclusive, or SIZE_MAX if none.

View File

@@ -52,6 +52,8 @@ class EnumSet {
}
}
constexpr explicit EnumSet(Serialized aValue) : mBitField(aValue) {}
#ifdef DEBUG
constexpr EnumSet(const EnumSet& aEnumSet) : mBitField(aEnumSet.mBitField) {}
@@ -321,7 +323,12 @@ class EnumSet {
}
constexpr bool HasBitAt(size_t aPos) const {
return static_cast<bool>(mBitField & BitAt(aPos));
if constexpr (std::is_unsigned_v<Serialized>) {
return mBitField & BitAt(aPos);
} else {
// for std::bitset and mozilla::BitSet
return mBitField.test(aPos);
}
}
constexpr void IncVersion() {
@@ -334,7 +341,7 @@ class EnumSet {
if constexpr (std::is_unsigned_v<Serialized>) {
return sizeof(Serialized) * 8;
} else {
return Serialized::Size();
return Serialized().size();
}
}

View File

@@ -67,28 +67,28 @@ class BitSetSuite {
void testSetBit() {
TestBitSet<kBitsPerWord + 2> bitset;
MOZ_RELEASE_ASSERT(!bitset.Test(3));
MOZ_RELEASE_ASSERT(!bitset.test(3));
MOZ_RELEASE_ASSERT(!bitset[3]);
MOZ_RELEASE_ASSERT(!bitset.Test(kBitsPerWord + 1));
MOZ_RELEASE_ASSERT(!bitset.test(kBitsPerWord + 1));
MOZ_RELEASE_ASSERT(!bitset[kBitsPerWord + 1]);
bitset[3] = true;
MOZ_RELEASE_ASSERT(bitset.Test(3));
MOZ_RELEASE_ASSERT(bitset.test(3));
MOZ_RELEASE_ASSERT(bitset[3]);
bitset[kBitsPerWord + 1] = true;
MOZ_RELEASE_ASSERT(bitset.Test(3));
MOZ_RELEASE_ASSERT(bitset.test(3));
MOZ_RELEASE_ASSERT(bitset[3]);
MOZ_RELEASE_ASSERT(bitset.Test(kBitsPerWord + 1));
MOZ_RELEASE_ASSERT(bitset.test(kBitsPerWord + 1));
MOZ_RELEASE_ASSERT(bitset[kBitsPerWord + 1]);
bitset.ResetAll();
for (size_t i = 0; i < decltype(bitset)::Size(); i++) {
for (size_t i = 0; i < decltype(bitset)::size(); i++) {
MOZ_RELEASE_ASSERT(!bitset[i]);
}
bitset.SetAll();
for (size_t i = 0; i < decltype(bitset)::Size(); i++) {
for (size_t i = 0; i < decltype(bitset)::size(); i++) {
MOZ_RELEASE_ASSERT(bitset[i]);
}
@@ -96,14 +96,14 @@ class BitSetSuite {
MOZ_RELEASE_ASSERT(bitset.Storage()[1] == 3);
bitset.ResetAll();
for (size_t i = 0; i < decltype(bitset)::Size(); i++) {
for (size_t i = 0; i < decltype(bitset)::size(); i++) {
MOZ_RELEASE_ASSERT(!bitset[i]);
}
}
void testFindBits() {
TestBitSet<kBitsPerWord * 5 + 2> bitset;
size_t size = bitset.Size();
size_t size = bitset.size();
MOZ_RELEASE_ASSERT(bitset.IsEmpty());
MOZ_RELEASE_ASSERT(bitset.FindFirst() == SIZE_MAX);
MOZ_RELEASE_ASSERT(bitset.FindLast() == SIZE_MAX);

View File

@@ -739,7 +739,7 @@ LoadInfo::LoadInfo(
bool aIsSameDocumentNavigation, bool aAllowDeprecatedSystemRequests,
bool aIsInDevToolsContext, bool aParserCreatedScript,
nsILoadInfo::StoragePermissionState aStoragePermission,
const Maybe<RFPTarget>& aOverriddenFingerprintingSettings,
const Maybe<RFPTargetSet>& aOverriddenFingerprintingSettings,
bool aIsMetaRefresh, uint32_t aRequestBlockingReason,
nsINode* aLoadingContext,
nsILoadInfo::CrossOriginEmbedderPolicy aLoadingEmbedderPolicy,
@@ -1227,7 +1227,7 @@ LoadInfo::SetStoragePermission(
return NS_OK;
}
const Maybe<RFPTarget>& LoadInfo::GetOverriddenFingerprintingSettings() {
const Maybe<RFPTargetSet>& LoadInfo::GetOverriddenFingerprintingSettings() {
#ifdef DEBUG
RefPtr<BrowsingContext> browsingContext;
GetTargetBrowsingContext(getter_AddRefs(browsingContext));
@@ -1241,7 +1241,7 @@ const Maybe<RFPTarget>& LoadInfo::GetOverriddenFingerprintingSettings() {
return mOverriddenFingerprintingSettings;
}
void LoadInfo::SetOverriddenFingerprintingSettings(RFPTarget aTargets) {
void LoadInfo::SetOverriddenFingerprintingSettings(RFPTargetSet aTargets) {
mOverriddenFingerprintingSettings.reset();
mOverriddenFingerprintingSettings.emplace(aTargets);
}

View File

@@ -253,7 +253,7 @@ class LoadInfo final : public nsILoadInfo {
bool aIsSameDocumentNavigation, bool aAllowDeprecatedSystemRequests,
bool aIsInDevToolsContext, bool aParserCreatedScript,
nsILoadInfo::StoragePermissionState aStoragePermission,
const Maybe<RFPTarget>& aOverriddenFingerprintingSettings,
const Maybe<RFPTargetSet>& aOverriddenFingerprintingSettings,
bool aIsMetaRefresh, uint32_t aRequestBlockingReason,
nsINode* aLoadingContext,
nsILoadInfo::CrossOriginEmbedderPolicy aLoadingEmbedderPolicy,
@@ -381,7 +381,7 @@ class LoadInfo final : public nsILoadInfo {
bool mParserCreatedScript = false;
nsILoadInfo::StoragePermissionState mStoragePermission =
nsILoadInfo::NoStoragePermission;
Maybe<RFPTarget> mOverriddenFingerprintingSettings;
Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
#ifdef DEBUG
// A boolean used to ensure the mOverriddenFingerprintingSettings is set
// before use it.

View File

@@ -208,11 +208,11 @@ TRRLoadInfo::SetStoragePermission(
return NS_ERROR_NOT_IMPLEMENTED;
}
const Maybe<RFPTarget>& TRRLoadInfo::GetOverriddenFingerprintingSettings() {
const Maybe<RFPTargetSet>& TRRLoadInfo::GetOverriddenFingerprintingSettings() {
return mOverriddenFingerprintingSettings;
}
void TRRLoadInfo::SetOverriddenFingerprintingSettings(RFPTarget aTargets) {}
void TRRLoadInfo::SetOverriddenFingerprintingSettings(RFPTargetSet aTargets) {}
NS_IMETHODIMP
TRRLoadInfo::GetIsMetaRefresh(bool* aResult) {

View File

@@ -45,7 +45,7 @@ class TRRLoadInfo final : public nsILoadInfo {
Maybe<mozilla::dom::ClientInfo> mReservedClientInfo;
Maybe<mozilla::dom::ClientInfo> mInitialClientInfo;
Maybe<mozilla::dom::ServiceWorkerDescriptor> mController;
Maybe<RFPTarget> mOverriddenFingerprintingSettings;
Maybe<RFPTargetSet> mOverriddenFingerprintingSettings;
};
} // namespace net

View File

@@ -53,8 +53,8 @@ native OriginAttributes(mozilla::OriginAttributes);
[ref] native const_MaybeClientInfoRef(const mozilla::Maybe<mozilla::dom::ClientInfo>);
[ref] native const_ServiceWorkerDescriptorRef(const mozilla::dom::ServiceWorkerDescriptor);
[ref] native const_MaybeServiceWorkerDescriptorRef(const mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>);
[ref] native const_MaybeRFPTarget(const mozilla::Maybe<mozilla::RFPTarget>);
native RFPTarget(mozilla::RFPTarget);
[ref] native const_MaybeRFPTargetSet(const mozilla::Maybe<mozilla::RFPTargetSet>);
native RFPTargetSet(mozilla::RFPTargetSet);
[ptr] native PerformanceStoragePtr(mozilla::dom::PerformanceStorage);
native LoadTainting(mozilla::LoadTainting);
native CSPRef(already_AddRefed<nsIContentSecurityPolicy>);
@@ -651,13 +651,13 @@ interface nsILoadInfo : nsISupports
* The RFPTarget defined in the RFPTargets.inc.
*/
[noscript, nostdcall, notxpcom]
const_MaybeRFPTarget GetOverriddenFingerprintingSettings();
const_MaybeRFPTargetSet GetOverriddenFingerprintingSettings();
/**
* Set the granular overrides of fingerprinting protections for the channel.
*/
[noscript, nostdcall, notxpcom]
void SetOverriddenFingerprintingSettings(in RFPTarget aTargets);
void SetOverriddenFingerprintingSettings(in RFPTargetSet aTargets);
/**
* True if the load was triggered by a meta refresh.

View File

@@ -44,6 +44,7 @@ using mozilla::dom::FeaturePolicyInfo from "mozilla/dom/FeaturePolicy.h";
using nsILoadInfo::HTTPSUpgradeTelemetryType from "nsILoadInfo.h";
using nsILoadInfo::SchemelessInputType from "nsILoadInfo.h";
using mozilla::dom::UserNavigationInvolvement from "mozilla/dom/UserNavigationInvolvement.h";
using mozilla::RFPTargetSet from "nsRFPService.h";
namespace mozilla {
namespace net {
@@ -195,7 +196,7 @@ struct LoadInfoArgs
uint32_t requestBlockingReason;
CSPInfo? cspToInheritInfo;
StoragePermissionState storagePermission;
uint64_t? overriddenFingerprintingSettings;
RFPTargetSet? overriddenFingerprintingSettings;
bool isMetaRefresh;
CrossOriginEmbedderPolicy loadingEmbedderPolicy;
bool originTrialCoepCredentiallessEnabledForTopLevel;
@@ -286,7 +287,7 @@ struct ParentLoadInfoForwarderArgs
StoragePermissionState storagePermission;
uint64_t? overriddenFingerprintingSettings;
RFPTargetSet? overriddenFingerprintingSettings;
bool isMetaRefresh;

View File

@@ -1111,7 +1111,7 @@ void AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(nsIChannel* aChannel) {
// Note that we need to put this after computing the IsThirdPartyToTopWindow
// flag because it will be used when getting the granular fingerprinting
// protections.
Maybe<RFPTarget> overriddenFingerprintingSettings =
Maybe<RFPTargetSet> overriddenFingerprintingSettings =
nsRFPService::GetOverriddenFingerprintingSettingsForChannel(aChannel);
if (overriddenFingerprintingSettings) {

View File

@@ -1,23 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef __RFPTargetIPCUtils_h__
#define __RFPTargetIPCUtils_h__
#include "ipc/EnumSerializer.h"
#include "nsRFPService.h"
namespace IPC {
template <>
struct ParamTraits<mozilla::RFPTarget>
: BitFlagsEnumSerializer<mozilla::RFPTarget,
mozilla::RFPTarget::AllTargets> {};
} // namespace IPC
#endif // __RFPTargetIPCUtils_h__

View File

@@ -5,95 +5,95 @@
// Names should not be re-used.
ITEM_VALUE(TouchEvents, 1llu << 0)
ITEM_VALUE(PointerEvents, 1llu << 1)
ITEM_VALUE(KeyboardEvents, 1llu << 2)
ITEM_VALUE(ScreenOrientation, 1llu << 3)
ITEM_VALUE(TouchEvents, 1)
ITEM_VALUE(PointerEvents, 2)
ITEM_VALUE(KeyboardEvents, 3)
ITEM_VALUE(ScreenOrientation, 4)
// SpeechSynthesis part of the Web Speech API
ITEM_VALUE(SpeechSynthesis, 1llu << 4)
ITEM_VALUE(SpeechSynthesis, 5)
// `prefers-color-scheme` CSS media feature
ITEM_VALUE(CSSPrefersColorScheme, 1llu << 5)
ITEM_VALUE(CSSPrefersColorScheme, 6)
// `prefers-reduced-motion` CSS media feature
ITEM_VALUE(CSSPrefersReducedMotion, 1llu << 6)
ITEM_VALUE(CSSPrefersReducedMotion, 7)
// `prefers-contrast` CSS media feature
ITEM_VALUE(CSSPrefersContrast, 1llu << 7)
ITEM_VALUE(CSSPrefersContrast, 8)
// Add random noises to image data extracted from canvas.
ITEM_VALUE(CanvasRandomization, 1llu << 8)
ITEM_VALUE(CanvasRandomization, 9)
// Canvas targets: For unusual combinations of these, see comments
// in IsImageExtractionAllowed
ITEM_VALUE(CanvasImageExtractionPrompt, 1llu << 9)
ITEM_VALUE(CanvasExtractionFromThirdPartiesIsBlocked, 1llu << 10)
ITEM_VALUE(CanvasExtractionBeforeUserInputIsBlocked, 1llu << 11)
ITEM_VALUE(CanvasImageExtractionPrompt, 10)
ITEM_VALUE(CanvasExtractionFromThirdPartiesIsBlocked, 11)
ITEM_VALUE(CanvasExtractionBeforeUserInputIsBlocked, 12)
ITEM_VALUE(JSLocale, 1llu << 12)
ITEM_VALUE(JSLocale, 13)
// Various "client identification" values of the navigator object
ITEM_VALUE(NavigatorAppVersion, 1llu << 13)
ITEM_VALUE(NavigatorBuildID, 1llu << 14)
ITEM_VALUE(NavigatorHWConcurrency, 1llu << 15)
ITEM_VALUE(NavigatorOscpu, 1llu << 16)
ITEM_VALUE(NavigatorPlatform, 1llu << 17)
ITEM_VALUE(NavigatorUserAgent, 1llu << 18)
ITEM_VALUE(PointerId, 1llu << 19)
ITEM_VALUE(StreamVideoFacingMode, 1llu << 20)
ITEM_VALUE(JSDateTimeUTC, 1llu << 21)
ITEM_VALUE(JSMathFdlibm, 1llu << 22)
ITEM_VALUE(Gamepad, 1llu << 23)
ITEM_VALUE(HttpUserAgent, 1llu << 24)
ITEM_VALUE(WindowOuterSize, 1llu << 25)
ITEM_VALUE(WindowScreenXY, 1llu << 26)
ITEM_VALUE(WindowInnerScreenXY, 1llu << 27)
ITEM_VALUE(ScreenPixelDepth, 1llu << 28)
ITEM_VALUE(ScreenRect, 1llu << 29)
ITEM_VALUE(ScreenAvailRect, 1llu << 30)
ITEM_VALUE(NavigatorAppVersion, 14)
ITEM_VALUE(NavigatorBuildID, 15)
ITEM_VALUE(NavigatorHWConcurrency, 16)
ITEM_VALUE(NavigatorOscpu, 17)
ITEM_VALUE(NavigatorPlatform, 18)
ITEM_VALUE(NavigatorUserAgent, 19)
ITEM_VALUE(PointerId, 20)
ITEM_VALUE(StreamVideoFacingMode, 21)
ITEM_VALUE(JSDateTimeUTC, 22)
ITEM_VALUE(JSMathFdlibm, 23)
ITEM_VALUE(Gamepad, 24)
ITEM_VALUE(HttpUserAgent, 25)
ITEM_VALUE(WindowOuterSize, 26)
ITEM_VALUE(WindowScreenXY, 27)
ITEM_VALUE(WindowInnerScreenXY, 28)
ITEM_VALUE(ScreenPixelDepth, 29)
ITEM_VALUE(ScreenRect, 30)
ITEM_VALUE(ScreenAvailRect, 31)
// HTMLVideoElement
// mozParsedFrames, mozDecodedFrames, mozPresentedFrames, mozPaintedFrames
ITEM_VALUE(VideoElementMozFrames, 1llu << 31)
ITEM_VALUE(VideoElementMozFrames, 32)
// mozFrameDelay
ITEM_VALUE(VideoElementMozFrameDelay, 1llu << 32)
ITEM_VALUE(VideoElementMozFrameDelay, 33)
// getVideoPlaybackQuality()
ITEM_VALUE(VideoElementPlaybackQuality, 1llu << 33)
ITEM_VALUE(VideoElementPlaybackQuality, 34)
// See also Reduce Timer Precision (RTP) Caller Type
ITEM_VALUE(ReduceTimerPrecision, 1llu << 34)
ITEM_VALUE(ReduceTimerPrecision, 35)
// Hide keyboard and pointer WidgetEvents
ITEM_VALUE(WidgetEvents, 1llu << 35)
ITEM_VALUE(MediaDevices, 1llu << 36)
ITEM_VALUE(MediaCapabilities, 1llu << 37)
ITEM_VALUE(AudioSampleRate, 1llu << 38)
ITEM_VALUE(NavigatorConnection, 1llu << 39)
ITEM_VALUE(WindowDevicePixelRatio, 1llu << 40)
ITEM_VALUE(MouseEventScreenPoint, 1llu << 41)
ITEM_VALUE(WidgetEvents, 36)
ITEM_VALUE(MediaDevices, 37)
ITEM_VALUE(MediaCapabilities, 38)
ITEM_VALUE(AudioSampleRate, 39)
ITEM_VALUE(NavigatorConnection, 40)
ITEM_VALUE(WindowDevicePixelRatio, 41)
ITEM_VALUE(MouseEventScreenPoint, 42)
// Visibility level of font families available to CSS font-matching
ITEM_VALUE(FontVisibilityBaseSystem, 1llu << 42)
ITEM_VALUE(FontVisibilityLangPack, 1llu << 43)
ITEM_VALUE(DeviceSensors, 1llu << 44)
ITEM_VALUE(FrameRate, 1llu << 45)
ITEM_VALUE(RoundWindowSize, 1llu << 46)
ITEM_VALUE(UseStandinsForNativeColors, 1llu << 47)
ITEM_VALUE(AudioContext, 1llu << 48)
ITEM_VALUE(MediaError, 1llu << 49)
ITEM_VALUE(DOMStyleOsxFontSmoothing, 1llu << 50)
ITEM_VALUE(FontVisibilityBaseSystem, 43)
ITEM_VALUE(FontVisibilityLangPack, 44)
ITEM_VALUE(DeviceSensors, 45)
ITEM_VALUE(FrameRate, 46)
ITEM_VALUE(RoundWindowSize, 47)
ITEM_VALUE(UseStandinsForNativeColors, 48)
ITEM_VALUE(AudioContext, 49)
ITEM_VALUE(MediaError, 50)
ITEM_VALUE(DOMStyleOsxFontSmoothing, 51)
// `device-height`/`device-width` CSS media features
ITEM_VALUE(CSSDeviceSize, 1llu << 51)
ITEM_VALUE(CSSDeviceSize, 52)
// `color`/`color-gamut` CSS media features
ITEM_VALUE(CSSColorInfo, 1llu << 52)
ITEM_VALUE(CSSColorInfo, 53)
// `resolution` CSS media feature
ITEM_VALUE(CSSResolution, 1llu << 53)
ITEM_VALUE(CSSResolution, 54)
// `prefers-reduced-transparency` CSS media feature
ITEM_VALUE(CSSPrefersReducedTransparency, 1llu << 54)
ITEM_VALUE(CSSPrefersReducedTransparency, 55)
// `inverted-colors` CSS media feature
ITEM_VALUE(CSSInvertedColors, 1llu << 55)
ITEM_VALUE(CSSInvertedColors, 56)
// `video-dynamic-range` CSS media feature
ITEM_VALUE(CSSVideoDynamicRange, 1llu << 56)
ITEM_VALUE(CSSPointerCapabilities, 1llu << 57)
ITEM_VALUE(CSSVideoDynamicRange, 57)
ITEM_VALUE(CSSPointerCapabilities, 58)
// WebGL
ITEM_VALUE(WebGLRenderCapability, 1llu << 58)
ITEM_VALUE(WebGLRenderInfo, 1llu << 59)
ITEM_VALUE(SiteSpecificZoom, 1llu << 60)
ITEM_VALUE(WebGLRenderCapability, 59)
ITEM_VALUE(WebGLRenderInfo, 60)
ITEM_VALUE(SiteSpecificZoom, 61)
// Are font visibility restrictions applied when resolving a CSS <generic-family>?
// (This may block the fonts selected in Preferences from actually being used.)
ITEM_VALUE(FontVisibilityRestrictGenerics, 1llu << 61)
ITEM_VALUE(WebVTT, 1llu << 62)
ITEM_VALUE(FontVisibilityRestrictGenerics, 62)
ITEM_VALUE(WebVTT, 63)
// !!! Don't forget to update kDefaultFingerprintingProtections in nsRFPService.cpp
// if necessary.
@@ -103,7 +103,7 @@ ITEM_VALUE(WebVTT, 1llu << 62)
* (This saves us more computation and casting later.) This document will still
* need to check whether an individual target is allowed, but the initial
* question of "Does this document have any RFP applied to it ever?" can still
* be precomputed. This enum value will always be included in RFPLite, so when a
* be precomputed. This enum value will always be included in FPP, so when a
* document asks if they might have RFP enabled, it will return true. (Putting
* this value in the overrides pref is undefined behavior and may do anything.)
*/
@@ -119,4 +119,4 @@ ITEM_VALUE(IsAlwaysEnabledForPrecompute, 0)
* +AllTargets,-CSSPrefersColorScheme
* -AllTargets,+Gamepad
*/
ITEM_VALUE(AllTargets, 0xFFFFFFFF'FFFFFFFF)
ITEM_VALUE(AllTargets, 127)

View File

@@ -41,4 +41,10 @@ Classes = [
'constructor': 'UserCharacteristicsPageService',
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
},
{
'cid': '{6c072f47-f25c-484f-add8-051b07789593}',
'type': 'mozilla::nsRFPTargetSetIDL',
'interfaces': ['nsIRFPTargetSetIDL'],
'headers': ['/toolkit/components/resistfingerprinting/nsRFPTargetSetIDL.h'],
},
]

View File

@@ -38,8 +38,7 @@ def parse_targets(path):
targets = {}
for match in pattern.finditer(contents):
target = match.group(1)
value = match.group(2).replace("llu", "").replace("'", "")
value = value.split(" << ")
value = match.group(2)
targets[target] = value
return targets
@@ -49,15 +48,7 @@ def write_targets(output, targets):
output.write("export const Targets = {\n")
for target, value in targets.items():
target_w_padding = f'\t"{target}":'.ljust(45)
if len(value) == 2:
# value is in the format 1 << n = ["1", "n"]
output.write(
f"{target_w_padding} BigInt({value[0]}) << BigInt({value[1]}),\n"
)
else:
# value is in the format 0xFFFF... = ["0xffff"]
output.write(f'{target_w_padding} BigInt("{value[0]}"),\n')
output.write(f"{target_w_padding} {value},\n")
output.write("}\n")

View File

@@ -13,6 +13,7 @@ JAR_MANIFESTS += ["jar.mn"]
UNIFIED_SOURCES += [
"nsRFPService.cpp",
"nsRFPTargetSetIDL.cpp",
"RelativeTimeline.cpp",
]
# Because nsUserCharacteristics doesn't `use namespace mozilla` (because we're going to wind
@@ -31,10 +32,14 @@ SPHINX_TREES["resistfingerprinting"] = "docs"
FINAL_LIBRARY = "xul"
EXPORTS += ["nsRFPService.h", "nsUserCharacteristics.h", "RFPTargets.inc"]
EXPORTS += [
"nsRFPService.h",
"nsRFPTargetSetIDL.h",
"nsUserCharacteristics.h",
"RFPTargets.inc",
]
EXPORTS.mozilla += [
"RelativeTimeline.h",
"RFPTargetIPCUtils.h",
]
EXPORTS.mozilla.gtest += ["nsUserCharacteristics.h"]
@@ -54,6 +59,7 @@ XPCOM_MANIFESTS += [
XPIDL_SOURCES += [
"nsIFingerprintingWebCompatService.idl",
"nsIRFPService.idl",
"nsIRFPTargetSetIDL.idl",
"nsIUserCharacteristicsPageService.idl",
]

View File

@@ -4,6 +4,7 @@
#include "nsISupports.idl"
#include "nsIFingerprintingWebCompatService.idl"
#include "nsIRFPTargetSetIDL.idl"
interface nsIPrincipal;
interface nsIChannel;
@@ -32,7 +33,7 @@ interface nsIRFPService : nsISupports
* scope. 0 if the overridden scope doesn't exist.
*
*/
uint64_t getFingerprintingOverrides(in ACString aDomainKey);
nsIRFPTargetSetIDL getFingerprintingOverrides(in ACString aDomainKey);
/**
* Clean all overrides. This is for testing purpose.
@@ -42,7 +43,7 @@ interface nsIRFPService : nsISupports
/**
* The bitfield of the default enabled RFP Targets.
*/
readonly attribute uint64_t enabledFingerprintingProtections;
readonly attribute nsIRFPTargetSetIDL enabledFingerprintingProtections;
/**
* Clean all fingerprinting randomization keys.

View File

@@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* Used to represent active RFPTargets.
* We used to use uint64_t, but we ran out of bits.
*/
[scriptable, uuid(6c072f47-f25c-484f-add8-051b07789593)]
interface nsIRFPTargetSetIDL : nsISupports {
attribute uint64_t low;
attribute uint64_t high;
};

View File

@@ -77,6 +77,7 @@
#include "nsTStringRepr.h"
#include "nsUserCharacteristics.h"
#include "nsXPCOM.h"
#include "nsRFPTargetSetIDL.h"
#include "nsICookieJarSettings.h"
#include "nsICryptoHash.h"
@@ -128,22 +129,22 @@ static constexpr uint32_t kVideoDroppedRatio = 1;
// Fingerprinting protections that are enabled by default. This can be
// overridden using the privacy.fingerprintingProtection.overrides pref.
// NOLINTBEGIN(bugprone-macro-parentheses)
#if defined(MOZ_WIDGET_ANDROID)
// NOLINTNEXTLINE(bugprone-macro-parentheses)
# define ANDROID_DEFAULT(name) RFPTarget::name |
# define ANDROID_DEFAULT(name) RFPTarget::name,
# define DESKTOP_DEFAULT(name)
#else
# define ANDROID_DEFAULT(name)
// NOLINTNEXTLINE(bugprone-macro-parentheses)
# define DESKTOP_DEFAULT(name) RFPTarget::name |
# define DESKTOP_DEFAULT(name) RFPTarget::name,
#endif
const RFPTarget kDefaultFingerprintingProtections =
MOZ_RUNINIT const RFPTargetSet kDefaultFingerprintingProtections = {
#include "RFPTargetsDefault.inc"
static_cast<RFPTarget>(0);
};
#undef ANDROID_DEFAULT
#undef DESKTOP_DEFAULT
// NOLINTEND(bugprone-macro-parentheses)
static constexpr uint32_t kSuspiciousFingerprintingActivityThreshold = 1;
@@ -158,7 +159,9 @@ static StaticRefPtr<nsRFPService> sRFPService;
static bool sInitialized = false;
// Actually enabled fingerprinting protections.
static Atomic<RFPTarget> sEnabledFingerprintingProtections;
static StaticMutex sEnabledFingerprintingProtectionsMutex;
MOZ_CONSTINIT static RFPTargetSet sEnabledFingerprintingProtections
MOZ_GUARDED_BY(sEnabledFingerprintingProtectionsMutex);
/* static */
already_AddRefed<nsRFPService> nsRFPService::GetOrCreate() {
@@ -299,7 +302,7 @@ bool IsJSContextCurrentlyChromePrivileged() {
/* static */
bool nsRFPService::IsRFPEnabledFor(
bool aIsPrivateMode, RFPTarget aTarget,
const Maybe<RFPTarget>& aOverriddenFingerprintingSettings,
const Maybe<RFPTargetSet>& aOverriddenFingerprintingSettings,
bool aSkipChromePrincipalCheck /* = false */) {
MOZ_ASSERT(aTarget != RFPTarget::AllTargets);
@@ -331,10 +334,11 @@ bool nsRFPService::IsRFPEnabledFor(
}
if (aOverriddenFingerprintingSettings) {
return bool(aOverriddenFingerprintingSettings.ref() & aTarget);
return aOverriddenFingerprintingSettings.ref().contains(aTarget);
}
return bool(sEnabledFingerprintingProtections & aTarget);
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
return sEnabledFingerprintingProtections.contains(aTarget);
}
return false;
@@ -350,9 +354,10 @@ void nsRFPService::UpdateFPPOverrideList() {
return;
}
RFPTarget enabled = CreateOverridesFromText(
RFPTargetSet enabled = CreateOverridesFromText(
targetOverrides, kDefaultFingerprintingProtections);
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
sEnabledFingerprintingProtections = enabled;
}
@@ -2080,44 +2085,51 @@ nsresult nsRFPService::CreateOverrideDomainKey(
}
/* static */
RFPTarget nsRFPService::CreateOverridesFromText(const nsString& aOverridesText,
RFPTarget aBaseOverrides) {
RFPTarget result = aBaseOverrides;
RFPTargetSet nsRFPService::CreateOverridesFromText(
const nsString& aOverridesText, RFPTargetSet aBaseOverrides) {
RFPTargetSet result = aBaseOverrides;
for (const nsAString& each : aOverridesText.Split(',')) {
Maybe<RFPTarget> mappedValue =
nsRFPService::TextToRFPTarget(Substring(each, 1, each.Length() - 1));
if (mappedValue.isSome()) {
if (mappedValue.isNothing()) {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Could not map the value %s to an RFPTarget Enum",
NS_ConvertUTF16toUTF8(each).get()));
continue;
}
RFPTarget target = mappedValue.value();
RFPTargetSet targetSet = RFPTargetSet(target);
if (target == RFPTarget::AllTargets) {
std::bitset<128> allTargets;
allTargets.set();
targetSet = RFPTargetSet(allTargets);
}
if (target == RFPTarget::IsAlwaysEnabledForPrecompute) {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("RFPTarget::%s is not a valid value",
NS_ConvertUTF16toUTF8(each).get()));
} else if (each[0] == '+') {
result |= target;
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (0x%" PRIx64
"), to an addition, now we have 0x%" PRIx64,
NS_ConvertUTF16toUTF8(each).get(), uint64_t(target),
uint64_t(result)));
result += targetSet;
MOZ_LOG(
gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (0x%" PRIx64 "), to an addition, now we have %s",
NS_ConvertUTF16toUTF8(each).get(), static_cast<uint64_t>(target),
result.serialize().to_string().c_str()));
} else if (each[0] == '-') {
result &= ~target;
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (0x%" PRIx64
") to a subtraction, now we have 0x%" PRIx64,
NS_ConvertUTF16toUTF8(each).get(), uint64_t(target),
uint64_t(result)));
result -= targetSet;
MOZ_LOG(
gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (0x%" PRIx64 ") to a subtraction, now we have %s",
NS_ConvertUTF16toUTF8(each).get(), static_cast<uint64_t>(target),
result.serialize().to_string().c_str()));
} else {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
MOZ_LOG(
gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (0x%" PRIx64
") to an RFPTarget Enum, but the first "
"character wasn't + or -",
NS_ConvertUTF16toUTF8(each).get(), uint64_t(target)));
}
} else {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Could not map the value %s to an RFPTarget Enum",
NS_ConvertUTF16toUTF8(each).get()));
NS_ConvertUTF16toUTF8(each).get(), static_cast<uint64_t>(target)));
}
}
@@ -2144,7 +2156,8 @@ nsRFPService::SetFingerprintingOverrides(
rv = fpOverride->GetOverrides(overridesText);
NS_ENSURE_SUCCESS(rv, rv);
RFPTarget targets = nsRFPService::CreateOverridesFromText(
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
RFPTargetSet targets = nsRFPService::CreateOverridesFromText(
NS_ConvertUTF8toUTF16(overridesText),
mFingerprintingOverrides.Contains(domainKey)
? mFingerprintingOverrides.Get(domainKey)
@@ -2167,25 +2180,32 @@ nsRFPService::SetFingerprintingOverrides(
}
NS_IMETHODIMP
nsRFPService::GetEnabledFingerprintingProtections(uint64_t* aProtections) {
RFPTarget enabled = sEnabledFingerprintingProtections;
nsRFPService::GetEnabledFingerprintingProtections(
nsIRFPTargetSetIDL** aProtections) {
StaticMutexAutoLock lock(sEnabledFingerprintingProtectionsMutex);
RFPTargetSet enabled = sEnabledFingerprintingProtections;
nsCOMPtr<nsIRFPTargetSetIDL> protections = new nsRFPTargetSetIDL(enabled);
protections.forget(aProtections);
*aProtections = uint64_t(enabled);
return NS_OK;
}
NS_IMETHODIMP
nsRFPService::GetFingerprintingOverrides(const nsACString& aDomainKey,
uint64_t* aOverrides) {
nsIRFPTargetSetIDL** aOverrides) {
MOZ_ASSERT(XRE_IsParentProcess());
Maybe<RFPTarget> overrides = mFingerprintingOverrides.MaybeGet(aDomainKey);
Maybe<RFPTargetSet> overrides = mFingerprintingOverrides.MaybeGet(aDomainKey);
if (!overrides) {
return NS_ERROR_FAILURE;
}
*aOverrides = uint64_t(overrides.ref());
nsCOMPtr<nsIRFPTargetSetIDL> protections =
new nsRFPTargetSetIDL(overrides.ref());
protections.forget(aOverrides);
return NS_OK;
}
@@ -2197,7 +2217,7 @@ nsRFPService::CleanAllOverrides() {
}
/* static */
Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
nsIChannel* aChannel) {
MOZ_ASSERT(aChannel);
MOZ_ASSERT(XRE_IsParentProcess());
@@ -2329,7 +2349,7 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel(
}
/* static */
Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
Maybe<RFPTargetSet> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI) {
MOZ_ASSERT(aFirstPartyURI);
MOZ_ASSERT(XRE_IsParentProcess());
@@ -2345,7 +2365,8 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
// scope.
// First, we get the overrides that applies to every context.
Maybe<RFPTarget> result = service->mFingerprintingOverrides.MaybeGet("*"_ns);
Maybe<RFPTargetSet> result =
service->mFingerprintingOverrides.MaybeGet("*"_ns);
RefPtr<nsEffectiveTLDService> eTLDService =
nsEffectiveTLDService::GetInstance();
@@ -2373,7 +2394,7 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
key.Append("*");
Maybe<RFPTarget> fpOverrides =
Maybe<RFPTargetSet> fpOverrides =
service->mFingerprintingOverrides.MaybeGet(key);
if (fpOverrides) {
result = fpOverrides;
@@ -2408,7 +2429,7 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForURI(
key.Assign(firstPartyDomain);
key.Append(FP_OVERRIDES_DOMAIN_KEY_DELIMITER);
key.Append("*");
Maybe<RFPTarget> fpOverrides =
Maybe<RFPTargetSet> fpOverrides =
service->mFingerprintingOverrides.MaybeGet(key);
if (fpOverrides) {
result = fpOverrides;

View File

@@ -8,6 +8,7 @@
#include <cstdint>
#include <tuple>
#include <bitset>
#include "ErrorList.h"
#include "PLDHashTable.h"
#include "mozilla/BasicEvents.h"
@@ -202,7 +203,12 @@ enum class RFPTarget : uint64_t {
#undef ITEM_VALUE
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(RFPTarget);
using RFPTargetSet = EnumSet<RFPTarget, std::bitset<128>>;
template <>
struct MaxEnumValue<RFPTarget> {
static constexpr unsigned int value = 127;
};
// ============================================================================
@@ -221,7 +227,7 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
static bool IsRFPEnabledFor(
bool aIsPrivateMode, RFPTarget aTarget,
const Maybe<RFPTarget>& aOverriddenFingerprintingSettings,
const Maybe<RFPTargetSet>& aOverriddenFingerprintingSettings,
bool aSkipChromePrincipalCheck = false);
static bool IsSystemPrincipalOrAboutFingerprintingProtection(JSContext*,
@@ -349,7 +355,7 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
// overrides to replace default enabled RFPTargets for the context of the
// channel. The method will return Nothing() to indicate using the default
// RFPTargets
static Maybe<RFPTarget> GetOverriddenFingerprintingSettingsForChannel(
static Maybe<RFPTargetSet> GetOverriddenFingerprintingSettingsForChannel(
nsIChannel* aChannel);
// The method for getting the granular fingerprinting protection override of
@@ -357,7 +363,7 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
// overrides if there is one defined for the context of the first-party URI
// and third-party URI. Otherwise, it will return Nothing() to indicate using
// the default RFPTargets.
static Maybe<RFPTarget> GetOverriddenFingerprintingSettingsForURI(
static Maybe<RFPTargetSet> GetOverriddenFingerprintingSettingsForURI(
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI);
// --------------------------------------------------------------------------
@@ -474,7 +480,7 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
nsTHashMap<nsCStringHashKey, nsID> mBrowsingSessionKeys;
nsCOMPtr<nsIFingerprintingWebCompatService> mWebCompatService;
nsTHashMap<nsCStringHashKey, RFPTarget> mFingerprintingOverrides;
nsTHashMap<nsCStringHashKey, RFPTargetSet> mFingerprintingOverrides;
// A helper function to create the domain key for the fingerprinting
// overrides. The key can be in the following five formats.
@@ -493,8 +499,9 @@ class nsRFPService final : public nsIObserver, public nsIRFPService {
// overrides text and the based overrides bitfield. The function will parse
// the text and update the based overrides bitfield accordingly. Then, it will
// return the updated bitfield.
static RFPTarget CreateOverridesFromText(
const nsString& aOverridesText, RFPTarget aBaseOverrides = RFPTarget(0));
static RFPTargetSet CreateOverridesFromText(
const nsString& aOverridesText,
RFPTargetSet aBaseOverrides = RFPTargetSet());
};
} // namespace mozilla

View File

@@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsRFPTargetSetIDL.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(nsRFPTargetSetIDL, nsIRFPTargetSetIDL)
NS_IMETHODIMP
nsRFPTargetSetIDL::GetLow(uint64_t* aLow) {
std::bitset<128> bitset = mBits.serialize();
std::bitset<128> mask = std::bitset<128>(0xFFFFFFFFFFFFFFFF);
*aLow = (bitset & mask).to_ullong();
return NS_OK;
}
NS_IMETHODIMP
nsRFPTargetSetIDL::GetHigh(uint64_t* aHigh) {
std::bitset<128> bitset = mBits.serialize();
std::bitset<128> mask = std::bitset<128>(0xFFFFFFFFFFFFFFFF);
*aHigh = ((bitset >> 64) & mask).to_ullong();
return NS_OK;
}
NS_IMETHODIMP
nsRFPTargetSetIDL::SetLow(uint64_t aLow) {
std::bitset<128> bitset = mBits.serialize();
bitset |= aLow;
mBits.deserialize(bitset);
return NS_OK;
}
NS_IMETHODIMP
nsRFPTargetSetIDL::SetHigh(uint64_t aHigh) {
std::bitset<128> bitset = mBits.serialize();
std::bitset<128> mask = std::bitset<128>(0xFFFFFFFFFFFFFFFF);
uint64_t low = (bitset & mask).to_ullong();
bitset = aHigh;
bitset <<= 64;
bitset |= low;
return NS_OK;
}
} // namespace mozilla

View File

@@ -0,0 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef mozilla_RFPTargetSetIDL_h__
#define mozilla_RFPTargetSetIDL_h__
#include "nsIRFPTargetSetIDL.h"
#include "nsRFPService.h"
namespace mozilla {
class nsRFPTargetSetIDL final : public nsIRFPTargetSetIDL {
NS_DECL_ISUPPORTS
NS_DECL_NSIRFPTARGETSETIDL
public:
nsRFPTargetSetIDL() = default;
explicit nsRFPTargetSetIDL(RFPTargetSet& aBits) : mBits(aBits) {};
private:
~nsRFPTargetSetIDL() = default;
RFPTargetSet mBits;
};
} // namespace mozilla
#endif // mozilla_RFPTargetSetIDL_h__

View File

@@ -13,12 +13,12 @@ const COLLECTION_NAME = "fingerprinting-protection-overrides";
// The javascript bitwise operator only support 32bits. So, we only test
// RFPTargets that is under low 32 bits.
const TARGET_DEFAULT = extractLow32Bits(
Services.rfp.enabledFingerprintingProtections
Services.rfp.enabledFingerprintingProtections.low
);
const TARGET_PointerEvents = 0x00000002;
const TARGET_CanvasRandomization = 0x000000100;
const TARGET_WindowOuterSize = 0x002000000;
const TARGET_Gamepad = 0x00800000;
const TARGET_PointerEvents = 1 << 2;
const TARGET_CanvasRandomization = 1 << 9;
const TARGET_WindowOuterSize = 1 << 26;
const TARGET_Gamepad = 1 << 24;
const TEST_PAGE =
getRootDirectory(gTestPath).replace(
@@ -309,7 +309,7 @@ add_task(async function test_remote_settings() {
// Get the addition and subtraction flags for the domain.
try {
let overrides = extractLow32Bits(
Services.rfp.getFingerprintingOverrides(expect.domain)
Services.rfp.getFingerprintingOverrides(expect.domain).low
);
// Verify if the flags are matching to expected values.
@@ -354,7 +354,7 @@ add_task(async function test_remote_settings_pref() {
for (let expect of test.expects) {
try {
// Check for the existance of RFP overrides
Services.rfp.getFingerprintingOverrides(expect.domain);
Services.rfp.getFingerprintingOverrides(expect.domain).low;
ok(
false,
"This line should never run as the override should not exist and the previous line would throw an exception"
@@ -392,7 +392,7 @@ add_task(async function test_pref() {
try {
// Get the addition and subtraction flags for the domain.
let overrides = extractLow32Bits(
Services.rfp.getFingerprintingOverrides(expect.domain)
Services.rfp.getFingerprintingOverrides(expect.domain).low
);
// Verify if the flags are matching to expected values.
@@ -447,7 +447,7 @@ add_task(async function test_pref_override_remote_settings() {
// Get the addition and subtraction flags for the domain.
let overrides = extractLow32Bits(
Services.rfp.getFingerprintingOverrides("example.org")
Services.rfp.getFingerprintingOverrides("example.org").low
);
// Verify if the flags are matching to the pref settings.