diff options
Diffstat (limited to 'toolkit/components/resistfingerprinting/nsRFPService.cpp')
-rw-r--r-- | toolkit/components/resistfingerprinting/nsRFPService.cpp | 126 |
1 files changed, 111 insertions, 15 deletions
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp index 643cc2cb7a..f39deb3283 100644 --- a/toolkit/components/resistfingerprinting/nsRFPService.cpp +++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp @@ -1,7 +1,7 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "nsRFPService.h" @@ -19,6 +19,7 @@ #include "MainThreadUtils.h" #include "ScopedNSSTypes.h" +#include "mozilla/AntiTrackingUtils.h" #include "mozilla/ArrayIterator.h" #include "mozilla/Assertions.h" #include "mozilla/Atomics.h" @@ -109,6 +110,8 @@ static mozilla::LazyLogModule gFingerprinterDetection("FingerprinterDetection"); #define LAST_PB_SESSION_EXITED_TOPIC "last-pb-context-exited" #define IDLE_TOPIC "browser-idle-startup-tasks-finished" #define GFX_FEATURES "gfx-features-ready" +#define USER_CHARACTERISTICS_TEST_REQUEST \ + "user-characteristics-testing-please-populate-data" static constexpr uint32_t kVideoFramesPerSec = 30; static constexpr uint32_t kVideoDroppedRatio = 5; @@ -190,6 +193,9 @@ nsresult nsRFPService::Init() { rv = obs->AddObserver(this, GFX_FEATURES, false); NS_ENSURE_SUCCESS(rv, rv); + + rv = obs->AddObserver(this, USER_CHARACTERISTICS_TEST_REQUEST, false); + NS_ENSURE_SUCCESS(rv, rv); } Preferences::RegisterCallbacks(nsRFPService::PrefChanged, gCallbackPrefs, @@ -289,6 +295,7 @@ void nsRFPService::StartShutdown() { obs->RemoveObserver(this, OBSERVER_TOPIC_IDLE_DAILY); obs->RemoveObserver(this, IDLE_TOPIC); obs->RemoveObserver(this, GFX_FEATURES); + obs->RemoveObserver(this, USER_CHARACTERISTICS_TEST_REQUEST); } } @@ -350,6 +357,12 @@ nsRFPService::Observe(nsISupports* aObject, const char* aTopic, } } + if (!strcmp(USER_CHARACTERISTICS_TEST_REQUEST, aTopic) && + xpc::IsInAutomation()) { + nsUserCharacteristics::PopulateDataAndEventuallySubmit( + /* aUpdatePref = */ false, /* aTesting = */ true); + } + if (!strcmp(OBSERVER_TOPIC_IDLE_DAILY, aTopic)) { if (StaticPrefs:: privacy_resistFingerprinting_randomization_daily_reset_enabled()) { @@ -1267,7 +1280,10 @@ Maybe<nsTArray<uint8_t>> nsRFPService::GenerateKey(nsIChannel* aChannel) { // Set the partitionKey using the top level URI to ensure that the key is // specific to the top level site. - attrs.SetPartitionKey(topLevelURI); + bool foreignByAncestorContext = + AntiTrackingUtils::IsThirdPartyChannel(aChannel) && + loadInfo->GetIsThirdPartyContextToTopWindow(); + attrs.SetPartitionKey(topLevelURI, foreignByAncestorContext); nsAutoCString oaSuffix; attrs.CreateSuffix(oaSuffix); @@ -1337,8 +1353,14 @@ nsRFPService::CleanRandomKeyByPrincipal(nsIPrincipal* aPrincipal) { OriginAttributes attrs = aPrincipal->OriginAttributesRef(); nsCOMPtr<nsIURI> uri = aPrincipal->GetURI(); - attrs.SetPartitionKey(uri); + attrs.SetPartitionKey(uri, false); + ClearBrowsingSessionKey(attrs); + + // We must also include the cross-site embeds of this principal that end up + // re-embedded back into the same principal's top level, otherwise state will + // persist for this target + attrs.SetPartitionKey(uri, true); ClearBrowsingSessionKey(attrs); return NS_OK; } @@ -1354,14 +1376,21 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) { // Use the originAttributes to get the partitionKey. OriginAttributes attrs; - attrs.SetPartitionKey(httpURI); + attrs.SetPartitionKey(httpURI, false); // Create a originAttributesPattern and set the http partitionKey to the // pattern. OriginAttributesPattern pattern; pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Construct(attrs.mPartitionKey); + ClearBrowsingSessionKey(pattern); + // We must also include the cross-site embeds of this principal that end up + // re-embedded back into the same principal's top level, otherwise state will + // persist for this target + attrs.SetPartitionKey(httpURI, true); + pattern.mPartitionKey.Reset(); + pattern.mPartitionKey.Construct(attrs.mPartitionKey); ClearBrowsingSessionKey(pattern); // Get https URI from the domain. @@ -1370,10 +1399,17 @@ nsRFPService::CleanRandomKeyByDomain(const nsACString& aDomain) { NS_ENSURE_SUCCESS(rv, rv); // Use the originAttributes to get the partitionKey and set to the pattern. - attrs.SetPartitionKey(httpsURI); + attrs.SetPartitionKey(httpsURI, false); pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Construct(attrs.mPartitionKey); + ClearBrowsingSessionKey(pattern); + // We must also include the cross-site embeds of this principal that end up + // re-embedded back into the same principal's top level, otherwise state will + // persist for this target + attrs.SetPartitionKey(httpsURI, true); + pattern.mPartitionKey.Reset(); + pattern.mPartitionKey.Construct(attrs.mPartitionKey); ClearBrowsingSessionKey(pattern); return NS_OK; } @@ -1395,7 +1431,7 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost, // Use the originAttributes to get the partitionKey. OriginAttributes attrs; - attrs.SetPartitionKey(httpURI); + attrs.SetPartitionKey(httpURI, false); // Set the partitionKey to the pattern. pattern.mPartitionKey.Reset(); @@ -1403,16 +1439,31 @@ nsRFPService::CleanRandomKeyByHost(const nsACString& aHost, ClearBrowsingSessionKey(pattern); + // We must also include the cross-site embeds of this principal that end up + // re-embedded back into the same principal's top level, otherwise state will + // persist for this target + attrs.SetPartitionKey(httpURI, true); + pattern.mPartitionKey.Reset(); + pattern.mPartitionKey.Construct(attrs.mPartitionKey); + ClearBrowsingSessionKey(pattern); + // Get https URI from the host. nsCOMPtr<nsIURI> httpsURI; rv = NS_NewURI(getter_AddRefs(httpsURI), "https://"_ns + aHost); NS_ENSURE_SUCCESS(rv, rv); // Use the originAttributes to get the partitionKey and set to the pattern. - attrs.SetPartitionKey(httpsURI); + attrs.SetPartitionKey(httpsURI, false); pattern.mPartitionKey.Reset(); pattern.mPartitionKey.Construct(attrs.mPartitionKey); + ClearBrowsingSessionKey(pattern); + // We must also include the cross-site embeds of this principal that end up + // re-embedded back into the same principal's top level, otherwise state will + // persist for this target + attrs.SetPartitionKey(httpsURI, true); + pattern.mPartitionKey.Reset(); + pattern.mPartitionKey.Construct(attrs.mPartitionKey); ClearBrowsingSessionKey(pattern); return NS_OK; } @@ -2011,19 +2062,63 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel( } // The channel is for the first-party load. - if (!loadInfo->GetIsThirdPartyContextToTopWindow()) { + if (!AntiTrackingUtils::IsThirdPartyChannel(aChannel)) { return GetOverriddenFingerprintingSettingsForURI(uri, nullptr); } // The channel is for the third-party load. We get the first-party URI from // the top-level window global parent. - RefPtr<dom::WindowGlobalParent> topWGP = - bc->Top()->Canonical()->GetCurrentWindowGlobal(); + RefPtr<dom::CanonicalBrowsingContext> topBC = bc->Top()->Canonical(); + RefPtr<dom::WindowGlobalParent> topWGP = topBC->GetCurrentWindowGlobal(); if (NS_WARN_IF(!topWGP)) { return Nothing(); } + nsCOMPtr<nsICookieJarSettings> cookieJarSettings; + DebugOnly<nsresult> rv = + loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + MOZ_ASSERT(cookieJarSettings); + + uint64_t topWindowContextIdFromCJS = + net::CookieJarSettings::Cast(cookieJarSettings) + ->GetTopLevelWindowContextId(); + + // The top-level window could be navigated away when we get the fingerprinting + // override here. For example, the beacon requests. In this case, the + // top-level windowContext id won't match the inner window id of the top-level + // windowGlobalParent. So, we cannot rely on the URI from the top-level + // windowGlobalParent because it could be different from the one that creates + // the channel. Instead, we fallback to use the partitionKey in the + // cookieJarSettings to get the top-level URI. + if (topWGP->InnerWindowId() != topWindowContextIdFromCJS) { + nsAutoString partitionKey; + rv = cookieJarSettings->GetPartitionKey(partitionKey); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + // Bail out early if the partitionKey is empty. + if (partitionKey.IsEmpty()) { + return Nothing(); + } + + nsAutoString scheme; + nsAutoString domain; + int32_t unused; + bool unused2; + if (!OriginAttributes::ParsePartitionKey(partitionKey, scheme, domain, + unused, unused2)) { + MOZ_ASSERT(false); + return Nothing(); + } + + nsCOMPtr<nsIURI> topURI; + rv = NS_NewURI(getter_AddRefs(topURI), scheme + u"://"_ns + domain); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + + return GetOverriddenFingerprintingSettingsForURI(topURI, uri); + } + nsCOMPtr<nsIPrincipal> topPrincipal = topWGP->DocumentPrincipal(); if (NS_WARN_IF(!topPrincipal)) { return Nothing(); @@ -2049,19 +2144,20 @@ Maybe<RFPTarget> nsRFPService::GetOverriddenFingerprintingSettingsForChannel( #ifdef DEBUG // Verify if the top URI matches the partitionKey of the channel. - nsCOMPtr<nsICookieJarSettings> cookieJarSettings; - Unused << loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)); - nsAutoString partitionKey; cookieJarSettings->GetPartitionKey(partitionKey); OriginAttributes attrs; - attrs.SetPartitionKey(topURI); + attrs.SetPartitionKey(topURI, false); + + OriginAttributes attrsForeignByAncestor; + attrsForeignByAncestor.SetPartitionKey(topURI, true); // The partitionKey of the channel could haven't been set here if the loading // channel is top-level. MOZ_ASSERT_IF(!partitionKey.IsEmpty(), - attrs.mPartitionKey.Equals(partitionKey)); + attrs.mPartitionKey.Equals(partitionKey) || + attrsForeignByAncestor.mPartitionKey.Equals(partitionKey)); #endif return GetOverriddenFingerprintingSettingsForURI(topURI, uri); |