tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d5ad2b2885d6fe9e92d810d92b1dc80738710809
parent 8b291d9ff1ae342d9c0215c2ae78b3ae36202cbe
Author: Tom Ritter <tom@mozilla.com>
Date:   Tue,  9 Dec 2025 16:34:59 +0000

Bug 1873716: Finally change how we report telemetry r=timhuang

SKIP_BMO_CHECK

Differential Revision: https://phabricator.services.mozilla.com/D273664

Diffstat:
Mtoolkit/components/antitracking/ContentBlockingLog.cpp | 149++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 106 insertions(+), 43 deletions(-)

diff --git a/toolkit/components/antitracking/ContentBlockingLog.cpp b/toolkit/components/antitracking/ContentBlockingLog.cpp @@ -25,6 +25,8 @@ #include "mozilla/StaticPtr.h" #include "mozilla/glean/AntitrackingMetrics.h" +static mozilla::LazyLogModule gFingerprinterDetection("FingerprinterDetection"); + namespace mozilla { namespace { @@ -213,8 +215,6 @@ void ContentBlockingLog::ReportCanvasFingerprintingLog( } bool hasCanvasFingerprinter = false; - bool canvasFingerprinterKnownText = false; - Maybe<ContentBlockingNotifier::CanvasFingerprinter> canvasFingerprinter; for (const auto& originEntry : mLog) { if (!originEntry.mData) { continue; @@ -224,55 +224,118 @@ void ContentBlockingLog::ReportCanvasFingerprintingLog( if (logEntry.mType != nsIWebProgressListener::STATE_ALLOWED_CANVAS_FINGERPRINTING) { continue; + } else if (logEntry.mCanvasFingerprintingEvent.isSome() == false) { + // Little confused about how we could get here, but I did see a crash + { + nsAutoCString firstPartyOrigin; + aFirstPartyPrincipal->GetOriginNoSuffix(firstPartyOrigin); + MOZ_LOG(gFingerprinterDetection, LogLevel::Error, + ("ContentBlockingLog::ReportCanvasFingerprintingLog: " + "logEntry has no CanvasFingerprintingEvent " + "(firstPartyOrigin=%s)", + firstPartyOrigin.get())); + } + continue; } - - // Select the log entry with the highest fingerprinting likelihood, - // that primarily means preferring those with a FingerprinterKnownText. - if (!hasCanvasFingerprinter || - (!canvasFingerprinterKnownText && - *logEntry.mCanvasFingerprinterKnownText) || - (!canvasFingerprinterKnownText && canvasFingerprinter.isNothing() && - logEntry.mCanvasFingerprinter.isSome())) { - hasCanvasFingerprinter = true; - canvasFingerprinterKnownText = *logEntry.mCanvasFingerprinterKnownText; - canvasFingerprinter = logEntry.mCanvasFingerprinter; + hasCanvasFingerprinter = true; + + auto canvasFingerprintingEvent = + logEntry.mCanvasFingerprintingEvent.value(); + + // ---------------------------------- + // This function iterates through all source bits, incrementing for each + // individually And then incrementing for the combination of all source + // bits set. It is used for both of the specific metrics we record. + auto IncrementBySources = + [](const CanvasFingerprintingEvent canvasFingerprintingEvent, + glean::impl::DualLabeledCounterMetric metric, + const nsCString& key) { + for (uint64_t b = canvasFingerprintingEvent.sourcesBitmask; b; + b &= (b - 1)) { + // Unlike knownText, we use the full number (e.g. 256) rather than + // the exponent (e.g. 8) + uint32_t singleSetBit_Source = b & (~b + 1); + + nsAutoCString category; + category.AppendInt(singleSetBit_Source); + + // Increment once for each known text bit and source bit + // combination + + metric.Get(key, category).Add(); + } + // And increment once for each known text bit and source bit + // combination. Make this an Info-level log because combinations + // MUST be added to the metric definition to be useful. + MOZ_LOG(gFingerprinterDetection, LogLevel::Info, + ("ContentBlockingLog::ReportCanvasFingerprintingLog: " + "Incrementing for combined sources bitmask %" PRIu64, + canvasFingerprintingEvent.sourcesBitmask)); + nsAutoCString category; + category.AppendInt(canvasFingerprintingEvent.sourcesBitmask); + metric.Get(key, category).Add(); + }; + + // ---------------------------------- + // First cover canvas_fingerprinting_type_text_by_source_per_tab2 + // We do this for each log entry + if (!canvasFingerprintingEvent.knownTextBitmask) { + nsAutoCString key; + key.AppendLiteral("none"); + + IncrementBySources( + canvasFingerprintingEvent, + glean::contentblocking:: + canvas_fingerprinting_type_text_by_source_per_tab2, + key); + } else { + // Iterate over each set bit in the bitmask + for (uint32_t b = canvasFingerprintingEvent.knownTextBitmask; b; + b &= (b - 1)) { + uint32_t singleSetBit_Text = b & (~b + 1); + uint32_t exponent = mozilla::CountTrailingZeroes32(singleSetBit_Text); + + nsAutoCString key; + key.AppendInt(exponent); + + IncrementBySources( + canvasFingerprintingEvent, + glean::contentblocking:: + canvas_fingerprinting_type_text_by_source_per_tab2, + key); + } } + + // ---------------------------------- + // Second, cover canvas_fingerprinting_type_alias_by_source_per_tab2 + // We also do this for each log entry + nsAutoCString key; + key.AppendInt(static_cast<uint32_t>(canvasFingerprintingEvent.alias)); + + IncrementBySources( + canvasFingerprintingEvent, + glean::contentblocking:: + canvas_fingerprinting_type_alias_by_source_per_tab2, + key); } } - auto label = - glean::contentblocking::CanvasFingerprintingPerTabLabel::eUnknown; - auto labelMatched = - glean::contentblocking::CanvasFingerprintingPerTabLabel::eUnknownMatched; - if (hasCanvasFingerprinter && canvasFingerprinterKnownText) { - label = glean::contentblocking::CanvasFingerprintingPerTabLabel::eKnownText; - labelMatched = glean::contentblocking::CanvasFingerprintingPerTabLabel:: - eKnownTextMatched; - } + // ---------------------------------- + // Finally, cover the overall 'was there any canvas fingerprinting' metric + // canvas_fingerprinting_per_tab2 if (!hasCanvasFingerprinter) { - glean::contentblocking::canvas_fingerprinting_per_tab.EnumGet(label) - .AccumulateSingleSample(0); - if (aShouldReport) { - glean::contentblocking::canvas_fingerprinting_per_tab - .EnumGet(labelMatched) - .AccumulateSingleSample(0); - } + // Increment the global 'did the page have any' metric + glean::contentblocking::canvas_fingerprinting_per_tab2 + .EnumGet( + glean::contentblocking::CanvasFingerprintingPerTab2Label::eNotFound) + .Add(); } else { - int32_t fingerprinter = - canvasFingerprinter.isSome() ? (*canvasFingerprinter + 1) : 0; - auto label = - canvasFingerprinterKnownText - ? glean::contentblocking::CanvasFingerprintingPerTabLabel:: - eKnownText - : glean::contentblocking::CanvasFingerprintingPerTabLabel::eUnknown; - glean::contentblocking::canvas_fingerprinting_per_tab.EnumGet(label) - .AccumulateSingleSample(fingerprinter); - if (aShouldReport) { - glean::contentblocking::canvas_fingerprinting_per_tab - .EnumGet(labelMatched) - .AccumulateSingleSample(fingerprinter); - } + // Increment the global 'did the page have any' metric + glean::contentblocking::canvas_fingerprinting_per_tab2 + .EnumGet( + glean::contentblocking::CanvasFingerprintingPerTab2Label::eFound) + .Add(); } }