зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1815307: Group RFP methods into logical sections r=timhuang
Differential Revision: https://phabricator.services.mozilla.com/D170888
This commit is contained in:
Родитель
4ee9882811
Коммит
ebd5b77e14
|
@ -101,47 +101,15 @@ static constexpr uint32_t kVideoDroppedRatio = 5;
|
|||
#define RFP_DEFAULT_SPOOFING_KEYBOARD_LANG KeyboardLang::EN
|
||||
#define RFP_DEFAULT_SPOOFING_KEYBOARD_REGION KeyboardRegion::US
|
||||
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// Structural Stuff & Pref Observing
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsRFPService, nsIObserver)
|
||||
|
||||
static StaticRefPtr<nsRFPService> sRFPService;
|
||||
static bool sInitialized = false;
|
||||
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() {
|
||||
|
@ -161,6 +129,211 @@ nsRFPService* nsRFPService::GetOrCreate() {
|
|||
return sRFPService;
|
||||
}
|
||||
|
||||
static const char* gCallbackPrefs[] = {
|
||||
RESIST_FINGERPRINTING_PREF, RFP_TIMER_PREF,
|
||||
RFP_TIMER_UNCONDITIONAL_PREF, RFP_TIMER_VALUE_PREF,
|
||||
RFP_JITTER_VALUE_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();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -517,6 +690,75 @@ 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);
|
||||
|
@ -575,6 +817,11 @@ 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.
|
||||
|
@ -631,136 +878,47 @@ void nsRFPService::GetSpoofedUserAgent(nsACString& userAgent,
|
|||
MOZ_ASSERT(userAgent.Length() <= preallocatedLength);
|
||||
}
|
||||
|
||||
static const char* gCallbackPrefs[] = {
|
||||
RESIST_FINGERPRINTING_PREF, RFP_TIMER_PREF,
|
||||
RFP_TIMER_UNCONDITIONAL_PREF, RFP_TIMER_VALUE_PREF,
|
||||
RFP_JITTER_VALUE_PREF, nullptr,
|
||||
};
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// Keyboard Spoofing Stuff
|
||||
|
||||
nsresult nsRFPService::Init() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsTHashMap<KeyboardHashKey, const SpoofingKeyboardCode*>*
|
||||
nsRFPService::sSpoofingKeyboardCodes = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
KeyboardHashKey::KeyboardHashKey(const KeyboardLangs aLang,
|
||||
const KeyboardRegions aRegion,
|
||||
const KeyNameIndexType aKeyIdx,
|
||||
const nsAString& aKey)
|
||||
: mLang(aLang), mRegion(aRegion), mKeyIdx(aKeyIdx), mKey(aKey) {}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
|
||||
KeyboardHashKey::KeyboardHashKey(KeyTypePointer aOther)
|
||||
: mLang(aOther->mLang),
|
||||
mRegion(aOther->mRegion),
|
||||
mKeyIdx(aOther->mKeyIdx),
|
||||
mKey(aOther->mKey) {}
|
||||
|
||||
rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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)) {}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
rv = obs->AddObserver(this, LAST_PB_SESSION_EXITED_TOPIC, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
KeyboardHashKey::~KeyboardHashKey() = default;
|
||||
|
||||
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;
|
||||
bool KeyboardHashKey::KeyEquals(KeyTypePointer aOther) const {
|
||||
return mLang == aOther->mLang && mRegion == aOther->mRegion &&
|
||||
mKeyIdx == aOther->mKeyIdx && mKey == aOther->mKey;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
KeyboardHashKey::KeyTypePointer KeyboardHashKey::KeyToPointer(KeyType aKey) {
|
||||
return &aKey;
|
||||
}
|
||||
|
||||
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);
|
||||
PLDHashNumber KeyboardHashKey::HashKey(KeyTypePointer aKey) {
|
||||
PLDHashNumber hash = mozilla::HashString(aKey->mKey);
|
||||
return mozilla::AddToHash(hash, aKey->mRegion, aKey->mKeyIdx, aKey->mLang);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -973,139 +1131,10 @@ bool nsRFPService::GetSpoofedKeyCode(const dom::Document* aDoc,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
// Randomization Stuff
|
||||
nsresult nsRFPService::EnsureSessionKey(bool aIsPrivate) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ class KeyboardHashKey : public PLDHashEntryHdr {
|
|||
|
||||
explicit KeyboardHashKey(KeyTypePointer aOther);
|
||||
|
||||
KeyboardHashKey(KeyboardHashKey&& aOther);
|
||||
KeyboardHashKey(KeyboardHashKey&& aOther) noexcept;
|
||||
|
||||
~KeyboardHashKey();
|
||||
|
||||
|
@ -124,6 +124,8 @@ class KeyboardHashKey : public PLDHashEntryHdr {
|
|||
nsString mKey;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
enum TimerPrecisionType {
|
||||
DangerouslyNone = 1,
|
||||
UnconditionalAKAHighRes = 2,
|
||||
|
@ -131,12 +133,16 @@ enum TimerPrecisionType {
|
|||
RFP = 4,
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class nsRFPService final : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static nsRFPService* GetOrCreate();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
static double TimerResolution(RTPCallerType aRTPCallerType);
|
||||
|
||||
enum TimeScale { Seconds = 1, MilliSeconds = 1000, MicroSeconds = 1000000 };
|
||||
|
@ -169,6 +175,8 @@ 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);
|
||||
|
@ -181,9 +189,13 @@ 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.
|
||||
|
@ -228,11 +240,15 @@ 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();
|
||||
|
||||
|
@ -240,12 +256,16 @@ class nsRFPService final : public nsIObserver {
|
|||
|
||||
~nsRFPService() = default;
|
||||
|
||||
nsCString mInitialTZValue;
|
||||
|
||||
void UpdateRFPPref();
|
||||
void StartShutdown();
|
||||
|
||||
void PrefChanged(const char* aPref);
|
||||
static void PrefChanged(const char* aPref, void* aSelf);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
|
||||
const KeyboardRegions aRegion);
|
||||
static void MaybeCreateSpoofingKeyCodesForEnUS();
|
||||
|
@ -260,6 +280,8 @@ class nsRFPService final : public nsIObserver {
|
|||
static nsTHashMap<KeyboardHashKey, const SpoofingKeyboardCode*>*
|
||||
sSpoofingKeyboardCodes;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
static TimerPrecisionType GetTimerPrecisionType(RTPCallerType aRTPCallerType);
|
||||
|
||||
static TimerPrecisionType GetTimerPrecisionTypeRFPOnly(
|
||||
|
@ -267,12 +289,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
|
||||
|
|
Загрузка…
Ссылка в новой задаче