Backed out 7 changesets (bug 1815307) for causing mochitest failures at test_bug1729861.html CLOSED TREE

Backed out changeset 18c8ae091952 (bug 1815307)
Backed out changeset df49c162e4ad (bug 1815307)
Backed out changeset a22d49909ffa (bug 1815307)
Backed out changeset 371d1d626984 (bug 1815307)
Backed out changeset 7f4b594cf468 (bug 1815307)
Backed out changeset 83d79fcbded5 (bug 1815307)
Backed out changeset 337dfbf6a1f9 (bug 1815307)
This commit is contained in:
Cristina Horotan 2023-03-16 17:51:56 +02:00
Родитель e2bfc76403
Коммит d376603a21
28 изменённых файлов: 407 добавлений и 677 удалений

Просмотреть файл

@ -6,7 +6,7 @@
let errorMessageMap = {};
let testPromise = (resistFingerprinting, src, allowlist) => new Promise(resolve => {
let testPromise = (resistFingerprinting, src, whitelist) => new Promise(resolve => {
let video = document.createElement("video");
video.src = src;
video.controls = "true";
@ -16,8 +16,8 @@ let testPromise = (resistFingerprinting, src, allowlist) => new Promise(resolve
SimpleTest.isnot(message, "", "Message should not be blank");
SimpleTest.info(src + ": " + message);
errorMessageMap[src] = message;
} else if (allowlist) {
SimpleTest.is(message, allowlist, "Error message in allowlist: " + allowlist);
} else if (whitelist) {
SimpleTest.is(message, whitelist, "Error message in whitelist: " + whitelist);
} else {
SimpleTest.is(message, "", "Blank error message: " + errorMessageMap[src]);
}
@ -35,12 +35,12 @@ async function testBody(resistFingerprinting) {
await testPromise(
resistFingerprinting,
"load_error.mp4",
"404: Not Found" // allowlist
"404: Not Found" // whitelist
);
await testPromise(
resistFingerprinting,
"decode_error.mp4",
false // allowlist
false // whitelist
);
}

Просмотреть файл

@ -25,32 +25,12 @@ document.addEventListener("DOMContentLoaded", async () => {
const target0 = document.getElementById("target0");
const touchParams = {force: 1.0, angle: 1.0, rx: 2, ry: 3};
await SpecialPowers.pushPrefEnv({set: [["dom.w3c_touch_events.enabled", 1]]});
for (let seq of [0, 1, 2, 3]) {
let resist = false;
if (seq == 0) {
resist = true;
await SpecialPowers.pushPrefEnv({set: [["privacy.resistFingerprinting", true]]});
} else if (seq == 1) {
await SpecialPowers.pushPrefEnv({set: [["privacy.resistFingerprinting", false]]});
} else if (seq == 2) {
resist = true;
await SpecialPowers.pushPrefEnv({set: [
["privacy.resistFingerprintingLite", true],
["privacy.resistFingerprintingLite.overrides", "+TouchEvents"]
]});
} else {
await SpecialPowers.pushPrefEnv({set: [
["privacy.resistFingerprintingLite", true],
["privacy.resistFingerprintingLite.overrides", "-TouchEvents"]
]});
}
info("starting test with fingerprinting resistance " + (resist ? "on" : "off") + " sequence number " + seq);
for (let resist of [false, true]) {
await SpecialPowers.pushPrefEnv({set: [["privacy.resistFingerprinting", resist]]});
info("starting test with fingerprinting resistance " + (resist ? "on" : "off"));
let touchEvent = await promiseTouchEvent(target0, "touchstart", 5, 5, touchParams);
info("touch event received");
let touch = touchEvent.touches[0];
if (resist) {
is(touch.screenX, touch.clientX, "touch.screenX should be the same as touch.clientX");
is(touch.screenY, touch.clientY, "touch.screenY should be the same as touch.clientY");
@ -61,9 +41,7 @@ document.addEventListener("DOMContentLoaded", async () => {
}
is(touch.force, resist ? 0.0 : touchParams.force, "touch.force");
is(touch.rotationAngle, resist ? 0 : touchParams.angle, "touch.rotationAngle");
await SpecialPowers.popPrefEnv();
}
SimpleTest.finish();
});
</script>

Просмотреть файл

@ -15864,14 +15864,9 @@ void Document::SendPageUseCounters() {
}
void Document::RecomputeResistFingerprinting() {
mShouldResistFingerprinting = !nsContentUtils::IsChromeDoc(this) &&
nsContentUtils::ShouldResistFingerprinting(
mChannel, RFPTarget::PrecomputeIsEnabled);
}
bool Document::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
return mShouldResistFingerprinting && nsRFPService::IsRFPEnabledFor(aTarget);
mShouldResistFingerprinting =
!nsContentUtils::IsChromeDoc(this) &&
nsContentUtils::ShouldResistFingerprinting(mChannel);
}
WindowContext* Document::GetWindowContextForPageUseCounters() const {

Просмотреть файл

@ -4148,7 +4148,9 @@ class Document : public nsINode,
*/
class HighlightRegistry& HighlightRegistry();
bool ShouldResistFingerprinting(RFPTarget aTarget = RFPTarget::Unknown) const;
bool ShouldResistFingerprinting() const {
return mShouldResistFingerprinting;
}
void RecomputeResistFingerprinting();

Просмотреть файл

@ -357,6 +357,7 @@
#include "nsPresContext.h"
#include "nsQueryFrame.h"
#include "nsQueryObject.h"
#include "nsRFPService.h"
#include "nsRange.h"
#include "nsRefPtrHashtable.h"
#include "nsSandboxFlags.h"
@ -738,8 +739,6 @@ class nsContentUtils::UserInteractionObserver final
static constexpr nsLiteralCString kRfpPrefs[] = {
"privacy.resistFingerprinting"_ns,
"privacy.resistFingerprintingLite"_ns,
"privacy.resistFingerprintingLite.overrides"_ns,
"privacy.resistFingerprinting.testGranularityMask"_ns,
};
@ -751,11 +750,9 @@ static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
bcGroup->GetDocGroups(docGroups);
for (auto* docGroup : docGroups) {
for (Document* doc : *docGroup) {
const bool old =
doc->ShouldResistFingerprinting(RFPTarget::PrecomputeIsEnabled);
const bool old = doc->ShouldResistFingerprinting();
doc->RecomputeResistFingerprinting();
if (old !=
doc->ShouldResistFingerprinting(RFPTarget::PrecomputeIsEnabled)) {
if (old != doc->ShouldResistFingerprinting()) {
if (auto* pc = doc->GetPresContext()) {
pc->MediaFeatureValuesChanged(
{MediaFeatureChangeReason::PreferenceChange},
@ -2149,19 +2146,17 @@ bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
// Older Should RFP Functions ----------------------------------
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) {
return nsRFPService::IsRFPEnabledFor(aTarget);
bool nsContentUtils::ShouldResistFingerprinting() {
return StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly();
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
nsIGlobalObject* aGlobalObject,
RFPTarget aTarget /* = RFPTarget::Unknown */) {
nsIGlobalObject* aGlobalObject) {
if (!aGlobalObject) {
return ShouldResistFingerprinting(aTarget);
return ShouldResistFingerprinting();
}
return aGlobalObject->ShouldResistFingerprinting(aTarget);
return aGlobalObject->ShouldResistFingerprinting();
}
// Newer Should RFP Functions ----------------------------------
@ -2201,44 +2196,40 @@ const char* kExemptedDomainsPrefName =
"privacy.resistFingerprinting.exemptedDomains";
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
const char* aJustification, RFPTarget aTarget /* = RFPTarget::Unknown */) {
bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification) {
// See comment in header file for information about usage
return ShouldResistFingerprinting(aTarget);
return ShouldResistFingerprinting();
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
CallerType aCallerType, nsIGlobalObject* aGlobalObject,
RFPTarget aTarget /* = RFPTarget::Unknown */) {
CallerType aCallerType, nsIGlobalObject* aGlobalObject) {
if (aCallerType == CallerType::System) {
return false;
}
return ShouldResistFingerprinting(aGlobalObject, aTarget);
return ShouldResistFingerprinting(aGlobalObject);
}
bool nsContentUtils::ShouldResistFingerprinting(
nsIDocShell* aDocShell, RFPTarget aTarget /* = RFPTarget::Unknown */) {
bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell) {
if (!aDocShell) {
MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,
("Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "
"with NULL docshell"));
return ShouldResistFingerprinting(aTarget);
return ShouldResistFingerprinting();
}
Document* doc = aDocShell->GetDocument();
if (!doc) {
MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,
("Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "
"with NULL doc"));
return ShouldResistFingerprinting(aTarget);
return ShouldResistFingerprinting();
}
return doc->ShouldResistFingerprinting(aTarget);
return doc->ShouldResistFingerprinting();
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
nsIChannel* aChannel, RFPTarget aTarget /* = RFPTarget::Unknown */) {
if (!ShouldResistFingerprinting("Legacy quick-check", aTarget)) {
bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel) {
if (!ShouldResistFingerprinting("Legacy quick-check")) {
return false;
}
@ -2307,18 +2298,18 @@ bool nsContentUtils::ShouldResistFingerprinting(
#endif
return ShouldResistFingerprinting_dangerous(
channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
channelURI, loadInfo->GetOriginAttributes(), "Internal Call");
}
// Case 2: Subresource Load
return ShouldResistFingerprinting(loadInfo, aTarget);
return ShouldResistFingerprinting(loadInfo);
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting_dangerous(
nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
const char* aJustification, RFPTarget aTarget /* = RFPTarget::Unknown */) {
if (!ShouldResistFingerprinting("Legacy quick-check", aTarget)) {
const char* aJustification) {
if (!ShouldResistFingerprinting("Legacy quick-check")) {
return false;
}
@ -2363,14 +2354,13 @@ bool nsContentUtils::ShouldResistFingerprinting_dangerous(
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting(
nsILoadInfo* aLoadInfo, RFPTarget aTarget /* = RFPTarget::Unknown */) {
bool nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* aLoadInfo) {
MOZ_ASSERT(aLoadInfo->GetExternalContentPolicyType() !=
ExtContentPolicy::TYPE_DOCUMENT &&
aLoadInfo->GetExternalContentPolicyType() !=
ExtContentPolicy::TYPE_SUBDOCUMENT);
if (!ShouldResistFingerprinting("Legacy quick-check", aTarget)) {
if (!ShouldResistFingerprinting("Legacy quick-check")) {
return false;
}
@ -2388,15 +2378,13 @@ bool nsContentUtils::ShouldResistFingerprinting(
MOZ_ASSERT(BasePrincipal::Cast(principal)->OriginAttributesRef() ==
aLoadInfo->GetOriginAttributes());
return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
aTarget);
return ShouldResistFingerprinting_dangerous(principal, "Internal Call");
}
/* static */
bool nsContentUtils::ShouldResistFingerprinting_dangerous(
nsIPrincipal* aPrincipal, const char* aJustification,
RFPTarget aTarget /* = RFPTarget::Unknown */) {
if (!ShouldResistFingerprinting("Legacy quick-check", aTarget)) {
nsIPrincipal* aPrincipal, const char* aJustification) {
if (!ShouldResistFingerprinting("Legacy quick-check")) {
return false;
}

Просмотреть файл

@ -50,7 +50,6 @@
#include "nsLiteralString.h"
#include "nsMargin.h"
#include "nsPIDOMWindow.h"
#include "nsRFPService.h"
#include "nsStringFwd.h"
#include "nsTArray.h"
#include "nsTLiteralString.h"
@ -262,7 +261,6 @@ class nsContentUtils {
using TimeDuration = mozilla::TimeDuration;
using Trusted = mozilla::Trusted;
using JSONBehavior = mozilla::dom::JSONBehavior;
using RFPTarget = mozilla::RFPTarget;
public:
static nsresult Init();
@ -353,22 +351,16 @@ class nsContentUtils {
// Check whether we should avoid leaking distinguishing information to JS/CSS.
// This function can be called both in the main thread and worker threads.
static bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(
nsIGlobalObject* aGlobalObject, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting();
static bool ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject);
// Similar to the function above, but always allows CallerType::System
// callers.
static bool ShouldResistFingerprinting(
mozilla::dom::CallerType aCallerType, nsIGlobalObject* aGlobalObject,
RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(
nsIDocShell* aDocShell, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(mozilla::dom::CallerType aCallerType,
nsIGlobalObject* aGlobalObject);
static bool ShouldResistFingerprinting(nsIDocShell* aDocShell);
// These functions are the new, nuanced functions
static bool ShouldResistFingerprinting(
nsIChannel* aChannel, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(
nsILoadInfo* aLoadInfo, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(nsIChannel* aChannel);
static bool ShouldResistFingerprinting(nsILoadInfo* aPrincipal);
// These functions are labeled as dangerous because they will do the wrong
// thing in _most_ cases. They should only be used if you don't have a fully
// constructed LoadInfo or Document.
@ -378,10 +370,9 @@ class nsContentUtils {
// (see below for more on justification strings.)
static bool ShouldResistFingerprinting_dangerous(
nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
const char* aJustification, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting_dangerous(
nsIPrincipal* aPrincipal, const char* aJustification,
RFPTarget aTarget = RFPTarget::Unknown);
const char* aJustification);
static bool ShouldResistFingerprinting_dangerous(nsIPrincipal* aPrincipal,
const char* aJustification);
/**
* Implement a RFP function that only checks the pref, and does not take
@ -393,8 +384,7 @@ class nsContentUtils {
* require a legacy function. (Additionally, we sometimes use the coarse
* check first, to avoid running additional code to support a nuanced check.)
*/
static bool ShouldResistFingerprinting(
const char* aJustification, RFPTarget aTarget = RFPTarget::Unknown);
static bool ShouldResistFingerprinting(const char* aJustification);
// A helper function to calculate the rounded window size for fingerprinting
// resistance. The rounded size is based on the chrome UI size and available

Просмотреть файл

@ -1628,15 +1628,13 @@ bool nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded) {
// nsGlobalWindowInner::nsIScriptGlobalObject
//*****************************************************************************
bool nsGlobalWindowInner::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
bool nsGlobalWindowInner::ShouldResistFingerprinting() const {
if (mDoc) {
return mDoc->ShouldResistFingerprinting(aTarget);
return mDoc->ShouldResistFingerprinting();
}
return nsContentUtils::ShouldResistFingerprinting(
"If we do not have a document then we do not have any context"
"to make an informed RFP choice, so we fall back to the global pref",
aTarget);
"to make an informed RFP choice, so we fall back to the global pref");
}
OriginTrials nsGlobalWindowInner::Trials() const {

Просмотреть файл

@ -247,8 +247,7 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
}
// nsIGlobalObject
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const final;
bool ShouldResistFingerprinting() const final;
mozilla::OriginTrials Trials() const final;
mozilla::dom::FontFaceSet* Fonts() final;

Просмотреть файл

@ -1664,15 +1664,13 @@ bool nsGlobalWindowOuter::IsBlackForCC(bool aTracingNeeded) {
// nsGlobalWindowOuter::nsIScriptGlobalObject
//*****************************************************************************
bool nsGlobalWindowOuter::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
bool nsGlobalWindowOuter::ShouldResistFingerprinting() const {
if (mDoc) {
return mDoc->ShouldResistFingerprinting(aTarget);
return mDoc->ShouldResistFingerprinting();
}
return nsContentUtils::ShouldResistFingerprinting(
"If we do not have a document then we do not have any context"
"to make an informed RFP choice, so we fall back to the global pref",
aTarget);
"to make an informed RFP choice, so we fall back to the global pref");
}
OriginTrials nsGlobalWindowOuter::Trials() const {

Просмотреть файл

@ -233,8 +233,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
}
// nsIGlobalObject
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const final;
bool ShouldResistFingerprinting() const final;
mozilla::OriginTrials Trials() const final;
mozilla::dom::FontFaceSet* Fonts() final;

Просмотреть файл

@ -392,7 +392,7 @@ mozilla::Result<bool, nsresult> nsIGlobalObject::HasEqualStorageKey(
return mozilla::ipc::StorageKeysEqual(storageKey, aStorageKey);
}
mozilla::RTPCallerType nsIGlobalObject::GetRTPCallerType() const {
RTPCallerType nsIGlobalObject::GetRTPCallerType() const {
if (PrincipalOrNull() && PrincipalOrNull()->IsSystemPrincipal()) {
return RTPCallerType::SystemPrincipal;
}
@ -408,9 +408,6 @@ mozilla::RTPCallerType nsIGlobalObject::GetRTPCallerType() const {
return RTPCallerType::Normal;
}
bool nsIGlobalObject::ShouldResistFingerprinting(
CallerType aCallerType,
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
return aCallerType != CallerType::System &&
ShouldResistFingerprinting(aTarget);
bool nsIGlobalObject::ShouldResistFingerprinting(CallerType aCallerType) const {
return aCallerType != CallerType::System && ShouldResistFingerprinting();
}

Просмотреть файл

@ -16,7 +16,6 @@
#include "nsContentUtils.h"
#include "nsHashKeys.h"
#include "nsISupports.h"
#include "nsRFPService.h"
#include "nsStringFwd.h"
#include "nsTArray.h"
#include "nsTHashtable.h"
@ -62,12 +61,21 @@ namespace JS::loader {
class ModuleLoaderBase;
} // namespace JS::loader
// Reduce Timer Precision (RTP) Caller Type
// This lives here because anything dealing with RTPCallerType determines it
// through this object.
enum class RTPCallerType : uint8_t {
Normal = 0,
SystemPrincipal = (1 << 0),
ResistFingerprinting = (1 << 1),
CrossOriginIsolated = (1 << 2)
};
/**
* See <https://developer.mozilla.org/en-US/docs/Glossary/Global_object>.
*/
class nsIGlobalObject : public nsISupports,
public mozilla::dom::DispatcherTrait {
private:
nsTArray<nsCString> mHostObjectURIs;
// Raw pointers to bound DETH objects. These are added by
@ -83,8 +91,6 @@ class nsIGlobalObject : public nsISupports,
nsIGlobalObject();
public:
using RTPCallerType = mozilla::RTPCallerType;
using RFPTarget = mozilla::RFPTarget;
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
/**
@ -249,12 +255,10 @@ class nsIGlobalObject : public nsISupports,
* Check whether we should avoid leaking distinguishing information to JS/CSS.
* https://w3c.github.io/fingerprinting-guidance/
*/
virtual bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const = 0;
virtual bool ShouldResistFingerprinting() const = 0;
// CallerType::System callers never have to resist fingerprinting.
bool ShouldResistFingerprinting(mozilla::dom::CallerType aCallerType,
RFPTarget aTarget = RFPTarget::Unknown) const;
bool ShouldResistFingerprinting(mozilla::dom::CallerType aCallerType) const;
RTPCallerType GetRTPCallerType() const;

Просмотреть файл

@ -73,12 +73,10 @@ class SimpleGlobalObject : public nsIGlobalObject, public nsWrapperCache {
MOZ_CRASH("SimpleGlobalObject doesn't use DOM bindings!");
}
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const override {
bool ShouldResistFingerprinting() const override {
return nsContentUtils::ShouldResistFingerprinting(
"Presently we don't have enough context to make an informed decision"
"on JS Sandboxes. See 1782853",
aTarget);
"on JS Sandboxes. See 1782853");
}
private:

Просмотреть файл

@ -131,8 +131,8 @@ EventTarget* Touch::GetOriginalTarget() const {
}
int32_t Touch::ScreenX(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return ClientX();
}
@ -140,8 +140,8 @@ int32_t Touch::ScreenX(CallerType aCallerType) const {
}
int32_t Touch::ScreenY(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return ClientY();
}
@ -149,8 +149,8 @@ int32_t Touch::ScreenY(CallerType aCallerType) const {
}
int32_t Touch::RadiusX(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return 0;
}
@ -158,8 +158,8 @@ int32_t Touch::RadiusX(CallerType aCallerType) const {
}
int32_t Touch::RadiusY(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return 0;
}
@ -167,8 +167,8 @@ int32_t Touch::RadiusY(CallerType aCallerType) const {
}
float Touch::RotationAngle(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return 0.0f;
}
@ -176,8 +176,8 @@ float Touch::RotationAngle(CallerType aCallerType) const {
}
float Touch::Force(CallerType aCallerType) const {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType, GetParentObject(),
RFPTarget::TouchEvents)) {
if (nsContentUtils::ShouldResistFingerprinting(aCallerType,
GetParentObject())) {
return 0.0f;
}

Просмотреть файл

@ -55,12 +55,10 @@ class ShadowRealmGlobalScope : public nsIGlobalObject, public nsWrapperCache {
JS::loader::ModuleLoaderBase* GetModuleLoader(JSContext* aCx) override;
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const override {
bool ShouldResistFingerprinting() const override {
return nsContentUtils::ShouldResistFingerprinting(
"Presently we don't have enough context to make an informed decision"
"on JS Sandboxes. See 1782853",
aTarget);
"on JS Sandboxes. See 1782853");
}
private:

Просмотреть файл

@ -272,10 +272,9 @@ bool WorkerGlobalScopeBase::IsSharedMemoryAllowed() const {
return mWorkerPrivate->IsSharedMemoryAllowed();
}
bool WorkerGlobalScopeBase::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
bool WorkerGlobalScopeBase::ShouldResistFingerprinting() const {
AssertIsOnWorkerThread();
return mShouldResistFingerprinting && nsRFPService::IsRFPEnabledFor(aTarget);
return mShouldResistFingerprinting;
}
OriginTrials WorkerGlobalScopeBase::Trials() const {

Просмотреть файл

@ -119,8 +119,7 @@ class WorkerGlobalScopeBase : public DOMEventTargetHelper,
bool IsSharedMemoryAllowed() const final;
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const final;
bool ShouldResistFingerprinting() const final;
OriginTrials Trials() const final;

Просмотреть файл

@ -87,9 +87,8 @@ bool WorkletGlobalScope::IsSharedMemoryAllowed() const {
return mImpl->IsSharedMemoryAllowed();
}
bool WorkletGlobalScope::ShouldResistFingerprinting(
RFPTarget aTarget /* = RFPTarget::Unknown */) const {
return mImpl->ShouldResistFingerprinting(aTarget);
bool WorkletGlobalScope::ShouldResistFingerprinting() const {
return mImpl->ShouldResistFingerprinting();
}
void WorkletGlobalScope::Dump(const Optional<nsAString>& aString) const {

Просмотреть файл

@ -81,8 +81,7 @@ class WorkletGlobalScope : public nsIGlobalObject, public nsWrapperCache {
OriginTrials Trials() const override;
Maybe<nsID> GetAgentClusterId() const override;
bool IsSharedMemoryAllowed() const override;
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const override;
bool ShouldResistFingerprinting() const override;
protected:
~WorkletGlobalScope();

Просмотреть файл

@ -13,7 +13,6 @@
#include "mozilla/OriginAttributes.h"
#include "mozilla/OriginTrials.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsRFPService.h"
class nsPIDOMWindowInner;
class nsIPrincipal;
@ -50,8 +49,6 @@ class WorkletLoadInfo {
* collected.
*/
class WorkletImpl {
using RFPTarget = mozilla::RFPTarget;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkletImpl);
@ -83,10 +80,8 @@ class WorkletImpl {
bool IsSharedMemoryAllowed() const { return mSharedMemoryAllowed; }
bool IsSystemPrincipal() const { return mPrincipal->IsSystemPrincipal(); }
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const {
return mShouldResistFingerprinting &&
nsRFPService::IsRFPEnabledFor(aTarget);
bool ShouldResistFingerprinting() const {
return mShouldResistFingerprinting;
}
virtual void OnAddModuleStarted() const {

Просмотреть файл

@ -68,8 +68,7 @@ class BackstagePass final : public nsIGlobalObject,
mModuleLoader = aModuleLoader;
}
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const override {
bool ShouldResistFingerprinting() const override {
// BackstagePass is always the System Principal
MOZ_RELEASE_ASSERT(mPrincipal->IsSystemPrincipal());
return false;

Просмотреть файл

@ -97,12 +97,10 @@ class SandboxPrivate : public nsIGlobalObject,
return 0;
}
bool ShouldResistFingerprinting(
RFPTarget aTarget = RFPTarget::Unknown) const override {
bool ShouldResistFingerprinting() const override {
return nsContentUtils::ShouldResistFingerprinting(
"Presently we don't have enough context to make an informed decision"
"on JS Sandboxes. See 1782853",
aTarget);
"on JS Sandboxes. See 1782853");
}
private:

Просмотреть файл

@ -12905,13 +12905,8 @@
#
# The variables will, however, be read often (specifically .microseconds on
# each timer rounding) so performance is important.
- name: privacy.resistFingerprinting
type: RelaxedAtomicBool
value: false
mirror: always
do_not_use_directly: true
- name: privacy.resistFingerprintingLite
- name: privacy.resistFingerprinting
type: RelaxedAtomicBool
value: false
mirror: always

Просмотреть файл

@ -925,10 +925,6 @@ pref("privacy.popups.disable_from_plugins", 3);
// domains exempted from RFP.
pref("privacy.resistFingerprinting.exemptedDomains", "*.example.invalid");
// If privacy.resistFingerprintingLite is enabled, this pref can be used to add
// or remove features from its effects
pref("privacy.resistFingerprintingLite.overrides", "");
// Fix cookie blocking breakage by providing ephemeral Paritioned LocalStorage
// for a list of hosts when detected as trackers.
// (See nsICookieService::BEHAVIOR_REJECT_TRACKER cookie behavior)

Просмотреть файл

@ -1,25 +0,0 @@
/*
* Once allocated, a string or value cannot ever be changed or re-used
*/
ITEM_VALUE(TouchEvents, 0x0001)
/*
* In certain cases, we precompute the vaqlue of ShouldRFP for e.g. a Document.
* (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 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.)
*/
ITEM_VALUE(PrecomputeIsEnabled, 0xFFFE)
/*
* This value is the default argument value, to allow all callsites to ShouldRFP
* continue working. We will eventually remove the default argument, and comment
* out this enum value.
*/
ITEM_VALUE(Unknown, 0xFFFF)

Просмотреть файл

@ -16,7 +16,7 @@ UNIFIED_SOURCES += [
FINAL_LIBRARY = "xul"
EXPORTS += ["nsRFPService.h", "RFPTargets.inc"]
EXPORTS += ["nsRFPService.h"]
EXPORTS.mozilla += [
"RelativeTimeline.h",
]

Просмотреть файл

@ -84,10 +84,14 @@ static mozilla::LazyLogModule gResistFingerprintingLog(
"nsResistFingerprinting");
#define RESIST_FINGERPRINTING_PREF "privacy.resistFingerprinting"
#define RESIST_FINGERPRINTINGLITE_PREF "privacy.resistFingerprintingLite"
#define RESIST_FINGERPRINTINGLITE_OVERRIDE_PREF \
"privacy.resistFingerprintingLite.overrides"
#define RFP_TIMER_PREF "privacy.reduceTimerPrecision"
#define RFP_TIMER_UNCONDITIONAL_PREF \
"privacy.reduceTimerPrecision.unconditional"
#define RFP_TIMER_UNCONDITIONAL_VALUE 20
#define RFP_TIMER_VALUE_PREF \
"privacy.resistFingerprinting.reduceTimerPrecision.microseconds"
#define RFP_JITTER_VALUE_PREF \
"privacy.resistFingerprinting.reduceTimerPrecision.jitter"
#define PROFILE_INITIALIZED_TOPIC "profile-initial-state"
#define LAST_PB_SESSION_EXITED_TOPIC "last-pb-context-exited"
@ -97,20 +101,47 @@ static constexpr uint32_t kVideoDroppedRatio = 5;
#define RFP_DEFAULT_SPOOFING_KEYBOARD_LANG KeyboardLang::EN
#define RFP_DEFAULT_SPOOFING_KEYBOARD_REGION KeyboardRegion::US
static nsTArray<mozilla::RFPTarget> sRFPLiteTargets = {
RFPTarget::PrecomputeIsEnabled, RFPTarget::Unknown};
// ============================================================================
// ============================================================================
// ============================================================================
// Structural Stuff & Pref Observing
NS_IMPL_ISUPPORTS(nsRFPService, nsIObserver)
static StaticRefPtr<nsRFPService> sRFPService;
static bool sInitialized = false;
static nsTArray<mozilla::RFPTarget> sTargetOverrideAdditions;
static nsTArray<mozilla::RFPTarget> sTargetOverrideSubtractions;
nsTHashMap<KeyboardHashKey, const SpoofingKeyboardCode*>*
nsRFPService::sSpoofingKeyboardCodes = nullptr;
KeyboardHashKey::KeyboardHashKey(const KeyboardLangs aLang,
const KeyboardRegions aRegion,
const KeyNameIndexType aKeyIdx,
const nsAString& aKey)
: mLang(aLang), mRegion(aRegion), mKeyIdx(aKeyIdx), mKey(aKey) {}
KeyboardHashKey::KeyboardHashKey(KeyTypePointer aOther)
: mLang(aOther->mLang),
mRegion(aOther->mRegion),
mKeyIdx(aOther->mKeyIdx),
mKey(aOther->mKey) {}
KeyboardHashKey::KeyboardHashKey(KeyboardHashKey&& aOther)
: PLDHashEntryHdr(std::move(aOther)),
mLang(std::move(aOther.mLang)),
mRegion(std::move(aOther.mRegion)),
mKeyIdx(std::move(aOther.mKeyIdx)),
mKey(std::move(aOther.mKey)) {}
KeyboardHashKey::~KeyboardHashKey() = default;
bool KeyboardHashKey::KeyEquals(KeyTypePointer aOther) const {
return mLang == aOther->mLang && mRegion == aOther->mRegion &&
mKeyIdx == aOther->mKeyIdx && mKey == aOther->mKey;
}
KeyboardHashKey::KeyTypePointer KeyboardHashKey::KeyToPointer(KeyType aKey) {
return &aKey;
}
PLDHashNumber KeyboardHashKey::HashKey(KeyTypePointer aKey) {
PLDHashNumber hash = mozilla::HashString(aKey->mKey);
return mozilla::AddToHash(hash, aKey->mRegion, aKey->mKeyIdx, aKey->mLang);
}
/* static */
nsRFPService* nsRFPService::GetOrCreate() {
@ -130,306 +161,6 @@ nsRFPService* nsRFPService::GetOrCreate() {
return sRFPService;
}
static const char* gCallbackPrefs[] = {
RESIST_FINGERPRINTING_PREF,
RESIST_FINGERPRINTINGLITE_PREF,
RESIST_FINGERPRINTINGLITE_OVERRIDE_PREF,
nullptr,
};
nsresult nsRFPService::Init() {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
NS_ENSURE_SUCCESS(rv, rv);
if (XRE_IsParentProcess()) {
rv = obs->AddObserver(this, LAST_PB_SESSION_EXITED_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = obs->AddObserver(this, OBSERVER_TOPIC_IDLE_DAILY, false);
NS_ENSURE_SUCCESS(rv, rv);
}
#if defined(XP_WIN)
rv = obs->AddObserver(this, PROFILE_INITIALIZED_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
#endif
Preferences::RegisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
this);
// We backup the original TZ value here.
const char* tzValue = PR_GetEnv("TZ");
if (tzValue != nullptr) {
mInitialTZValue = nsCString(tzValue);
}
// Call Update here to cache the values of the prefs and set the timezone.
UpdateRFPPref();
UpdateRFPLiteOverrideList();
return rv;
}
/* static */
bool nsRFPService::IsRFPEnabledFor(RFPTarget aTarget) {
if (StaticPrefs::privacy_resistFingerprinting_DoNotUseDirectly()) {
return true;
}
if (StaticPrefs::privacy_resistFingerprintingLite_DoNotUseDirectly()) {
if (sTargetOverrideAdditions.Contains(aTarget)) {
return true;
}
if (sTargetOverrideSubtractions.Contains(aTarget)) {
return false;
}
if (sRFPLiteTargets.Contains(aTarget)) {
return true;
}
return false;
}
return false;
}
// This function updates every fingerprinting item necessary except
// timing-related
void nsRFPService::UpdateRFPPref() {
MOZ_ASSERT(NS_IsMainThread());
bool resistFingerprinting = nsContentUtils::ShouldResistFingerprinting();
JS::SetReduceMicrosecondTimePrecisionCallback(
nsRFPService::ReduceTimePrecisionAsUSecsWrapper);
// set fdlibm pref
JS::SetUseFdlibmForSinCosTan(
StaticPrefs::javascript_options_use_fdlibm_for_sin_cos_tan() ||
resistFingerprinting);
// The JavaScript engine can already set the timezone per realm/global,
// but we think there are still other users of libc that rely
// on the TZ environment variable.
if (!StaticPrefs::privacy_resistFingerprinting_testing_setTZtoUTC()) {
return;
}
if (resistFingerprinting) {
PR_SetEnv("TZ=UTC");
} else if (sInitialized) {
// We will not touch the TZ value if 'privacy.resistFingerprinting' is false
// during the time of initialization.
if (!mInitialTZValue.IsEmpty()) {
nsAutoCString tzValue = "TZ="_ns + mInitialTZValue;
static char* tz = nullptr;
// If the tz has been set before, we free it first since it will be
// allocated a new value later.
if (tz != nullptr) {
free(tz);
}
// PR_SetEnv() needs the input string been leaked intentionally, so
// we copy it here.
tz = ToNewCString(tzValue, mozilla::fallible);
if (tz != nullptr) {
PR_SetEnv(tz);
}
} else {
#if defined(XP_WIN)
// For Windows, we reset the TZ to an empty string. This will make Windows
// to use its system timezone.
PR_SetEnv("TZ=");
#else
// For POSIX like system, we reset the TZ to the /etc/localtime, which is
// the system timezone.
PR_SetEnv("TZ=:/etc/localtime");
#endif
}
}
// If and only if the time zone was changed above, propagate the change to the
// <time.h> functions and the JS runtime.
if (resistFingerprinting || sInitialized) {
// localtime_r (and other functions) may not call tzset, so do this here
// after changing TZ to ensure all <time.h> functions use the new time zone.
#if defined(XP_WIN)
_tzset();
#else
tzset();
#endif
nsJSUtils::ResetTimeZone();
}
// If and only if the time zone was changed above, propagate the change to the
// <time.h> functions and the JS runtime.
if (resistFingerprinting || sInitialized) {
// localtime_r (and other functions) may not call tzset, so do this here
// after changing TZ to ensure all <time.h> functions use the new time zone.
#if defined(XP_WIN)
_tzset();
#else
tzset();
#endif
nsJSUtils::ResetTimeZone();
}
}
void nsRFPService::UpdateRFPLiteOverrideList() {
nsAutoString targetOverrides;
nsresult rv = Preferences::GetString(RESIST_FINGERPRINTINGLITE_OVERRIDE_PREF,
targetOverrides);
if (!NS_SUCCEEDED(rv) || targetOverrides.IsEmpty()) {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Could not map any values"));
return;
}
sTargetOverrideAdditions.Clear();
sTargetOverrideSubtractions.Clear();
for (const nsAString& each : targetOverrides.Split(',')) {
Maybe<RFPTarget> mappedValue =
nsRFPService::TextToRFPTarget(Substring(each, 1, each.Length() - 1));
if (mappedValue.isSome()) {
if (each[0] == '+') {
sTargetOverrideAdditions.AppendElement(mappedValue.value());
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (%X), to an addition, now we have %zu",
NS_ConvertUTF16toUTF8(each).get(), mappedValue.value(),
sTargetOverrideAdditions.Length()));
} else if (each[0] == '-') {
sTargetOverrideSubtractions.AppendElement(mappedValue.value());
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (%X) to a subtraction, now we have %zu",
NS_ConvertUTF16toUTF8(each).get(), mappedValue.value(),
sTargetOverrideSubtractions.Length()));
} else {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Mapped value %s (%X) to an RFPTarget Enum, but the first "
"character wasn't + or -",
NS_ConvertUTF16toUTF8(each).get(), mappedValue.value()));
}
} else {
MOZ_LOG(gResistFingerprintingLog, LogLevel::Warning,
("Could not map the value %s to an RFPTarget Enum",
NS_ConvertUTF16toUTF8(each).get()));
}
}
}
/* static */
Maybe<RFPTarget> nsRFPService::TextToRFPTarget(const nsAString& aText) {
#define ITEM_VALUE(name, value) \
if (aText.EqualsLiteral(#name)) { \
return Some(RFPTarget::name); \
}
#include "RFPTargets.inc"
#undef ITEM_VALUE
return Nothing();
}
void nsRFPService::StartShutdown() {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
if (XRE_IsParentProcess()) {
obs->RemoveObserver(this, LAST_PB_SESSION_EXITED_TOPIC);
obs->RemoveObserver(this, OBSERVER_TOPIC_IDLE_DAILY);
}
}
Preferences::UnregisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
this);
}
// static
void nsRFPService::PrefChanged(const char* aPref, void* aSelf) {
static_cast<nsRFPService*>(aSelf)->PrefChanged(aPref);
}
void nsRFPService::PrefChanged(const char* aPref) {
nsDependentCString pref(aPref);
if (pref.EqualsLiteral(RESIST_FINGERPRINTING_PREF)) {
UpdateRFPPref();
#if defined(XP_WIN)
if (!XRE_IsE10sParentProcess()) {
// Windows does not follow POSIX. Updates to the TZ environment variable
// are not reflected immediately on that platform as they are on UNIX
// systems without this call.
_tzset();
}
#endif
} else if (pref.EqualsLiteral(RESIST_FINGERPRINTINGLITE_OVERRIDE_PREF)) {
UpdateRFPLiteOverrideList();
}
}
NS_IMETHODIMP
nsRFPService::Observe(nsISupports* aObject, const char* aTopic,
const char16_t* aMessage) {
if (strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic) == 0) {
StartShutdown();
}
#if defined(XP_WIN)
else if (!strcmp(PROFILE_INITIALIZED_TOPIC, aTopic)) {
// If we're e10s, then we don't need to run this, since the child process
// will simply inherit the environment variable from the parent process, in
// which case it's unnecessary to call _tzset().
if (XRE_IsParentProcess() && !XRE_IsE10sParentProcess()) {
// Windows does not follow POSIX. Updates to the TZ environment variable
// are not reflected immediately on that platform as they are on UNIX
// systems without this call.
_tzset();
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
nsresult rv = obs->RemoveObserver(this, PROFILE_INITIALIZED_TOPIC);
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
if (strcmp(LAST_PB_SESSION_EXITED_TOPIC, aTopic) == 0) {
// Clear the private session key when the private session ends so that we
// can generate a new key for the new private session.
ClearSessionKey(true);
}
if (!strcmp(OBSERVER_TOPIC_IDLE_DAILY, aTopic)) {
if (StaticPrefs::
privacy_resistFingerprinting_randomization_daily_reset_enabled()) {
ClearSessionKey(false);
}
if (StaticPrefs::
privacy_resistFingerprinting_randomization_daily_reset_private_enabled()) {
ClearSessionKey(true);
}
}
return NS_OK;
}
// ============================================================================
// ============================================================================
// ============================================================================
// Reduce Timer Precision Stuff
constexpr double RFP_TIME_ATOM_MS = 16.667; // 60Hz, 1000/60 but rounded.
/*
In RFP RAF always runs at 60Hz, so we're ~0.02% off of 1000/60 here.
@ -786,75 +517,6 @@ double nsRFPService::ReduceTimePrecisionAsUSecsWrapper(
GetTimerPrecisionType(callerType));
}
/* static */
TimerPrecisionType nsRFPService::GetTimerPrecisionType(
RTPCallerType aRTPCallerType) {
if (aRTPCallerType == RTPCallerType::SystemPrincipal) {
return DangerouslyNone;
}
if (aRTPCallerType == RTPCallerType::ResistFingerprinting) {
return RFP;
}
if (StaticPrefs::privacy_reduceTimerPrecision() &&
aRTPCallerType == RTPCallerType::CrossOriginIsolated) {
return UnconditionalAKAHighRes;
}
if (StaticPrefs::privacy_reduceTimerPrecision()) {
return Normal;
}
if (StaticPrefs::privacy_reduceTimerPrecision_unconditional()) {
return UnconditionalAKAHighRes;
}
return DangerouslyNone;
}
/* static */
TimerPrecisionType nsRFPService::GetTimerPrecisionTypeRFPOnly(
RTPCallerType aRTPCallerType) {
if (aRTPCallerType == RTPCallerType::ResistFingerprinting) {
return RFP;
}
if (StaticPrefs::privacy_reduceTimerPrecision_unconditional() &&
aRTPCallerType != RTPCallerType::SystemPrincipal) {
return UnconditionalAKAHighRes;
}
return DangerouslyNone;
}
/* static */
void nsRFPService::TypeToText(TimerPrecisionType aType, nsACString& aText) {
switch (aType) {
case TimerPrecisionType::DangerouslyNone:
aText.AssignLiteral("DangerouslyNone");
return;
case TimerPrecisionType::Normal:
aText.AssignLiteral("Normal");
return;
case TimerPrecisionType::RFP:
aText.AssignLiteral("RFP");
return;
case TimerPrecisionType::UnconditionalAKAHighRes:
aText.AssignLiteral("UnconditionalAKAHighRes");
return;
default:
MOZ_ASSERT(false, "Shouldn't go here");
aText.AssignLiteral("Unknown Enum Value");
return;
}
}
// ============================================================================
// ============================================================================
// ============================================================================
// Video Statistics Spoofing
/* static */
uint32_t nsRFPService::CalculateTargetVideoResolution(uint32_t aVideoQuality) {
return aVideoQuality * NSToIntCeil(aVideoQuality * 16 / 9.0);
@ -913,11 +575,6 @@ uint32_t nsRFPService::GetSpoofedPresentedFrames(double aTime, uint32_t aWidth,
((100 - boundedDroppedRatio) / 100.0));
}
// ============================================================================
// ============================================================================
// ============================================================================
// User-Agent/Version Stuff
static const char* GetSpoofedVersion() {
#ifdef ANDROID
// Return Desktop's ESR version.
@ -974,47 +631,136 @@ void nsRFPService::GetSpoofedUserAgent(nsACString& userAgent,
MOZ_ASSERT(userAgent.Length() <= preallocatedLength);
}
// ============================================================================
// ============================================================================
// ============================================================================
// Keyboard Spoofing Stuff
static const char* gCallbackPrefs[] = {
RESIST_FINGERPRINTING_PREF, RFP_TIMER_PREF,
RFP_TIMER_UNCONDITIONAL_PREF, RFP_TIMER_VALUE_PREF,
RFP_JITTER_VALUE_PREF, nullptr,
};
nsTHashMap<KeyboardHashKey, const SpoofingKeyboardCode*>*
nsRFPService::sSpoofingKeyboardCodes = nullptr;
nsresult nsRFPService::Init() {
MOZ_ASSERT(NS_IsMainThread());
KeyboardHashKey::KeyboardHashKey(const KeyboardLangs aLang,
const KeyboardRegions aRegion,
const KeyNameIndexType aKeyIdx,
const nsAString& aKey)
: mLang(aLang), mRegion(aRegion), mKeyIdx(aKeyIdx), mKey(aKey) {}
nsresult rv;
KeyboardHashKey::KeyboardHashKey(KeyTypePointer aOther)
: mLang(aOther->mLang),
mRegion(aOther->mRegion),
mKeyIdx(aOther->mKeyIdx),
mKey(aOther->mKey) {}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
KeyboardHashKey::KeyboardHashKey(KeyboardHashKey&& aOther) noexcept
: PLDHashEntryHdr(std::move(aOther)),
mLang(std::move(aOther.mLang)),
mRegion(std::move(aOther.mRegion)),
mKeyIdx(std::move(aOther.mKeyIdx)),
mKey(std::move(aOther.mKey)) {}
rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
NS_ENSURE_SUCCESS(rv, rv);
KeyboardHashKey::~KeyboardHashKey() = default;
if (XRE_IsParentProcess()) {
rv = obs->AddObserver(this, LAST_PB_SESSION_EXITED_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
bool KeyboardHashKey::KeyEquals(KeyTypePointer aOther) const {
return mLang == aOther->mLang && mRegion == aOther->mRegion &&
mKeyIdx == aOther->mKeyIdx && mKey == aOther->mKey;
rv = obs->AddObserver(this, OBSERVER_TOPIC_IDLE_DAILY, false);
NS_ENSURE_SUCCESS(rv, rv);
}
#if defined(XP_WIN)
rv = obs->AddObserver(this, PROFILE_INITIALIZED_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
#endif
Preferences::RegisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
this);
// We backup the original TZ value here.
const char* tzValue = PR_GetEnv("TZ");
if (tzValue != nullptr) {
mInitialTZValue = nsCString(tzValue);
}
// Call Update here to cache the values of the prefs and set the timezone.
UpdateRFPPref();
return rv;
}
KeyboardHashKey::KeyTypePointer KeyboardHashKey::KeyToPointer(KeyType aKey) {
return &aKey;
// This function updates every fingerprinting item necessary except
// timing-related
void nsRFPService::UpdateRFPPref() {
MOZ_ASSERT(NS_IsMainThread());
bool resistFingerprinting = nsContentUtils::ShouldResistFingerprinting();
JS::SetReduceMicrosecondTimePrecisionCallback(
nsRFPService::ReduceTimePrecisionAsUSecsWrapper);
// set fdlibm pref
JS::SetUseFdlibmForSinCosTan(
StaticPrefs::javascript_options_use_fdlibm_for_sin_cos_tan() ||
resistFingerprinting);
// The JavaScript engine can already set the timezone per realm/global,
// but we think there are still other users of libc that rely
// on the TZ environment variable.
if (!StaticPrefs::privacy_resistFingerprinting_testing_setTZtoUTC()) {
return;
}
if (resistFingerprinting) {
PR_SetEnv("TZ=UTC");
} else if (sInitialized) {
// We will not touch the TZ value if 'privacy.resistFingerprinting' is false
// during the time of initialization.
if (!mInitialTZValue.IsEmpty()) {
nsAutoCString tzValue = "TZ="_ns + mInitialTZValue;
static char* tz = nullptr;
// If the tz has been set before, we free it first since it will be
// allocated a new value later.
if (tz != nullptr) {
free(tz);
}
// PR_SetEnv() needs the input string been leaked intentionally, so
// we copy it here.
tz = ToNewCString(tzValue, mozilla::fallible);
if (tz != nullptr) {
PR_SetEnv(tz);
}
} else {
#if defined(XP_WIN)
// For Windows, we reset the TZ to an empty string. This will make Windows
// to use its system timezone.
PR_SetEnv("TZ=");
#else
// For POSIX like system, we reset the TZ to the /etc/localtime, which is
// the system timezone.
PR_SetEnv("TZ=:/etc/localtime");
#endif
}
}
// If and only if the time zone was changed above, propagate the change to the
// <time.h> functions and the JS runtime.
if (resistFingerprinting || sInitialized) {
// localtime_r (and other functions) may not call tzset, so do this here
// after changing TZ to ensure all <time.h> functions use the new time zone.
#if defined(XP_WIN)
_tzset();
#else
tzset();
#endif
nsJSUtils::ResetTimeZone();
}
}
PLDHashNumber KeyboardHashKey::HashKey(KeyTypePointer aKey) {
PLDHashNumber hash = mozilla::HashString(aKey->mKey);
return mozilla::AddToHash(hash, aKey->mRegion, aKey->mKeyIdx, aKey->mLang);
void nsRFPService::StartShutdown() {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
if (XRE_IsParentProcess()) {
obs->RemoveObserver(this, LAST_PB_SESSION_EXITED_TOPIC);
obs->RemoveObserver(this, OBSERVER_TOPIC_IDLE_DAILY);
}
}
Preferences::UnregisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs,
this);
}
/* static */
@ -1227,10 +973,139 @@ bool nsRFPService::GetSpoofedKeyCode(const dom::Document* aDoc,
return false;
}
// ============================================================================
// ============================================================================
// ============================================================================
// Randomization Stuff
/* static */
TimerPrecisionType nsRFPService::GetTimerPrecisionType(
RTPCallerType aRTPCallerType) {
if (aRTPCallerType == RTPCallerType::SystemPrincipal) {
return DangerouslyNone;
}
if (aRTPCallerType == RTPCallerType::ResistFingerprinting) {
return RFP;
}
if (StaticPrefs::privacy_reduceTimerPrecision() &&
aRTPCallerType == RTPCallerType::CrossOriginIsolated) {
return UnconditionalAKAHighRes;
}
if (StaticPrefs::privacy_reduceTimerPrecision()) {
return Normal;
}
if (StaticPrefs::privacy_reduceTimerPrecision_unconditional()) {
return UnconditionalAKAHighRes;
}
return DangerouslyNone;
}
/* static */
TimerPrecisionType nsRFPService::GetTimerPrecisionTypeRFPOnly(
RTPCallerType aRTPCallerType) {
if (aRTPCallerType == RTPCallerType::ResistFingerprinting) {
return RFP;
}
if (StaticPrefs::privacy_reduceTimerPrecision_unconditional() &&
aRTPCallerType != RTPCallerType::SystemPrincipal) {
return UnconditionalAKAHighRes;
}
return DangerouslyNone;
}
/* static */
void nsRFPService::TypeToText(TimerPrecisionType aType, nsACString& aText) {
switch (aType) {
case TimerPrecisionType::DangerouslyNone:
aText.AssignLiteral("DangerouslyNone");
return;
case TimerPrecisionType::Normal:
aText.AssignLiteral("Normal");
return;
case TimerPrecisionType::RFP:
aText.AssignLiteral("RFP");
return;
case TimerPrecisionType::UnconditionalAKAHighRes:
aText.AssignLiteral("UnconditionalAKAHighRes");
return;
default:
MOZ_ASSERT(false, "Shouldn't go here");
aText.AssignLiteral("Unknown Enum Value");
return;
}
}
// static
void nsRFPService::PrefChanged(const char* aPref, void* aSelf) {
static_cast<nsRFPService*>(aSelf)->PrefChanged(aPref);
}
void nsRFPService::PrefChanged(const char* aPref) {
nsDependentCString pref(aPref);
if (pref.EqualsLiteral(RESIST_FINGERPRINTING_PREF)) {
UpdateRFPPref();
#if defined(XP_WIN)
if (!XRE_IsE10sParentProcess()) {
// Windows does not follow POSIX. Updates to the TZ environment variable
// are not reflected immediately on that platform as they are on UNIX
// systems without this call.
_tzset();
}
#endif
}
}
NS_IMETHODIMP
nsRFPService::Observe(nsISupports* aObject, const char* aTopic,
const char16_t* aMessage) {
if (strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic) == 0) {
StartShutdown();
}
#if defined(XP_WIN)
else if (!strcmp(PROFILE_INITIALIZED_TOPIC, aTopic)) {
// If we're e10s, then we don't need to run this, since the child process
// will simply inherit the environment variable from the parent process, in
// which case it's unnecessary to call _tzset().
if (XRE_IsParentProcess() && !XRE_IsE10sParentProcess()) {
// Windows does not follow POSIX. Updates to the TZ environment variable
// are not reflected immediately on that platform as they are on UNIX
// systems without this call.
_tzset();
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
nsresult rv = obs->RemoveObserver(this, PROFILE_INITIALIZED_TOPIC);
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
if (strcmp(LAST_PB_SESSION_EXITED_TOPIC, aTopic) == 0) {
// Clear the private session key when the private session ends so that we
// can generate a new key for the new private session.
ClearSessionKey(true);
}
if (!strcmp(OBSERVER_TOPIC_IDLE_DAILY, aTopic)) {
if (StaticPrefs::
privacy_resistFingerprinting_randomization_daily_reset_enabled()) {
ClearSessionKey(false);
}
if (StaticPrefs::
privacy_resistFingerprinting_randomization_daily_reset_private_enabled()) {
ClearSessionKey(true);
}
}
return NS_OK;
}
nsresult nsRFPService::EnsureSessionKey(bool aIsPrivate) {
MOZ_ASSERT(XRE_IsParentProcess());

Просмотреть файл

@ -10,7 +10,10 @@
#include "ErrorList.h"
#include "PLDHashTable.h"
#include "mozilla/BasicEvents.h"
#include "nsContentUtils.h"
#include "nsHashtablesFwd.h"
#include "nsID.h"
#include "nsIGlobalObject.h"
#include "nsIObserver.h"
#include "nsISupports.h"
#include "nsStringFwd.h"
@ -103,7 +106,7 @@ class KeyboardHashKey : public PLDHashEntryHdr {
explicit KeyboardHashKey(KeyTypePointer aOther);
KeyboardHashKey(KeyboardHashKey&& aOther) noexcept;
KeyboardHashKey(KeyboardHashKey&& aOther);
~KeyboardHashKey();
@ -121,16 +124,6 @@ class KeyboardHashKey : public PLDHashEntryHdr {
nsString mKey;
};
// ============================================================================
// Reduce Timer Precision (RTP) Caller Type
enum class RTPCallerType : uint8_t {
Normal = 0,
SystemPrincipal = (1 << 0),
ResistFingerprinting = (1 << 1),
CrossOriginIsolated = (1 << 2)
};
enum TimerPrecisionType {
DangerouslyNone = 1,
UnconditionalAKAHighRes = 2,
@ -138,29 +131,12 @@ enum TimerPrecisionType {
RFP = 4,
};
// ============================================================================
// NOLINTNEXTLINE(bugprone-macro-parentheses)
#define ITEM_VALUE(name, val) name = val,
enum RFPTarget {
#include "RFPTargets.inc"
};
#undef ITEM_VALUE
// ============================================================================
class nsRFPService final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static nsRFPService* GetOrCreate();
static bool IsRFPEnabledFor(RFPTarget aTarget);
// --------------------------------------------------------------------------
static double TimerResolution(RTPCallerType aRTPCallerType);
enum TimeScale { Seconds = 1, MilliSeconds = 1000, MicroSeconds = 1000000 };
@ -193,8 +169,6 @@ class nsRFPService final : public nsIObserver {
int64_t aContextMixin, long long* aMidpointOut,
uint8_t* aSecretSeed = nullptr);
// --------------------------------------------------------------------------
// This method calculates the video resolution (i.e. height x width) based
// on the video quality (480p, 720p, etc).
static uint32_t CalculateTargetVideoResolution(uint32_t aVideoQuality);
@ -207,13 +181,9 @@ class nsRFPService final : public nsIObserver {
static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth,
uint32_t aHeight);
// --------------------------------------------------------------------------
// This method generates the spoofed value of User Agent.
static void GetSpoofedUserAgent(nsACString& userAgent, bool isForHTTPHeader);
// --------------------------------------------------------------------------
/**
* This method for getting spoofed modifier states for the given keyboard
* event.
@ -258,15 +228,11 @@ class nsRFPService final : public nsIObserver {
const WidgetKeyboardEvent* aKeyboardEvent,
uint32_t& aOut);
// --------------------------------------------------------------------------
// The method to generate the key for randomization. It can return nothing if
// the session key is not available due to the randomization is disabled.
static Maybe<nsTArray<uint8_t>> GenerateKey(nsIURI* aTopLevelURI,
bool aIsPrivate);
// --------------------------------------------------------------------------
private:
nsresult Init();
@ -274,19 +240,12 @@ class nsRFPService final : public nsIObserver {
~nsRFPService() = default;
nsCString mInitialTZValue;
void UpdateRFPPref();
void UpdateRFPLiteOverrideList();
void StartShutdown();
void PrefChanged(const char* aPref);
static void PrefChanged(const char* aPref, void* aSelf);
static Maybe<RFPTarget> TextToRFPTarget(const nsAString& aText);
// --------------------------------------------------------------------------
static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
const KeyboardRegions aRegion);
static void MaybeCreateSpoofingKeyCodesForEnUS();
@ -301,8 +260,6 @@ class nsRFPService final : public nsIObserver {
static nsTHashMap<KeyboardHashKey, const SpoofingKeyboardCode*>*
sSpoofingKeyboardCodes;
// --------------------------------------------------------------------------
static TimerPrecisionType GetTimerPrecisionType(RTPCallerType aRTPCallerType);
static TimerPrecisionType GetTimerPrecisionTypeRFPOnly(
@ -310,12 +267,12 @@ class nsRFPService final : public nsIObserver {
static void TypeToText(TimerPrecisionType aType, nsACString& aText);
// --------------------------------------------------------------------------
// Generate the session key if it hasn't been generated.
nsresult EnsureSessionKey(bool aIsPrivate);
void ClearSessionKey(bool aIsPrivate);
nsCString mInitialTZValue;
// The keys that represent the browsing session. The lifetime of the key ties
// to the browsing session. For normal windows, the key is generated when
// loading the first http channel after the browser startup and persists until