commit 39accc7ebd036a744d2bf375aeda31b841685ed3
parent a59040a6b05d918cd8ed64f7fd7325a7115a6f44
Author: Tom Ritter <tom@mozilla.com>
Date: Mon, 8 Dec 2025 16:31:01 +0000
Bug 1873716: Finally change how we report telemetry r=timhuang
SKIP_BMO_CHECK
Differential Revision: https://phabricator.services.mozilla.com/D273664
Diffstat:
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();
}
}