commit 34a426c6e35d8ea90c79fe0278dc0ae508544762
parent b0fc6031702ea1db89f523b26961f051dfd78919
Author: Tom Ritter <tom@mozilla.com>
Date: Mon, 8 Dec 2025 16:31:00 +0000
Bug 1873716: Change the plumbing to use a CanvasFingerprintingEvent r=timhuang
SKIP_BMO_CHECK
Differential Revision: https://phabricator.services.mozilla.com/D273660
Diffstat:
16 files changed, 113 insertions(+), 79 deletions(-)
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
@@ -4199,9 +4199,7 @@ void BrowserChild::NotifyContentBlockingEvent(
const Maybe<
mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
if (!IPCOpen()) {
return;
}
@@ -4210,8 +4208,7 @@ void BrowserChild::NotifyContentBlockingEvent(
if (NS_SUCCEEDED(PrepareRequestData(aChannel, requestData))) {
(void)SendNotifyContentBlockingEvent(
aEvent, requestData, aBlocked, PromiseFlatCString(aTrackingOrigin),
- aTrackingFullHashes, aReason, aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ aTrackingFullHashes, aReason, aCanvasFingerprintingEvent);
}
}
diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h
@@ -702,9 +702,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
const Maybe<
ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText);
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent);
already_AddRefed<nsIDragSession> GetDragSession();
void SetDragSession(nsIDragSession* aSession);
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
@@ -3083,9 +3083,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
const Maybe<
mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<mozilla::ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool>& aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc || bc->IsDiscarded()) {
@@ -3109,9 +3107,9 @@ mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
aRequestData.matchedList());
request->SetCanceledReason(aRequestData.canceledReason());
- wgp->NotifyContentBlockingEvent(
- aEvent, request, aBlocked, aTrackingOrigin, aTrackingFullHashes, aReason,
- aCanvasFingerprinter, aCanvasFingerprinterKnownText);
+ wgp->NotifyContentBlockingEvent(aEvent, request, aBlocked, aTrackingOrigin,
+ aTrackingFullHashes, aReason,
+ aCanvasFingerprintingEvent);
return IPC_OK();
}
diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h
@@ -306,9 +306,7 @@ class BrowserParent final : public PBrowserParent,
nsTArray<nsCString>&& aTrackingFullHashes,
const Maybe<mozilla::ContentBlockingNotifier::
StorageAccessPermissionGrantedReason>& aReason,
- const Maybe<mozilla::ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool>& aCanvasFingerprinterKnownText);
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent);
mozilla::ipc::IPCResult RecvNavigationFinished();
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
@@ -30,6 +30,7 @@ include PTabContext;
include PBackgroundSharedTypes;
include "mozilla/AntiTrackingIPCUtils.h";
+include "mozilla/nsRFPIPCUtils.h";
include "mozilla/dom/BindingIPCUtils.h";
include "mozilla/dom/CSPMessageUtils.h";
include "mozilla/dom/PolicyContainerMessageUtils.h";
@@ -103,7 +104,7 @@ using mozilla::ScrollFlags from "mozilla/PresShellForwards.h";
using struct InputFormData from "mozilla/dom/SessionStoreMessageUtils.h";
using struct CollectedInputDataValue from "mozilla/dom/SessionStoreMessageUtils.h";
using mozilla::ContentBlockingNotifier::StorageAccessPermissionGrantedReason from "mozilla/ContentBlockingNotifier.h";
-using mozilla::ContentBlockingNotifier::CanvasFingerprinter from "mozilla/ContentBlockingNotifier.h";
+using mozilla::CanvasFingerprintingEvent from "nsRFPService.h";
using mozilla::dom::CallerType from "mozilla/dom/BindingDeclarations.h";
using mozilla::dom::EmbedderElementEventType from "mozilla/dom/TabMessageTypes.h";
using mozilla::IntrinsicSize from "nsIFrame.h";
@@ -546,8 +547,7 @@ parent:
bool aBlocked, nsCString aTrackingOrigin,
nsCString[] aTrackingFullHashes,
StorageAccessPermissionGrantedReason? aReason,
- CanvasFingerprinter? aCanvasFingerprinter,
- bool? aCanvasFingerprinterKnownText);
+ CanvasFingerprintingEvent? aCanvasFingerprintingEvent);
async NavigationFinished();
diff --git a/dom/ipc/WindowGlobalParent.cpp b/dom/ipc/WindowGlobalParent.cpp
@@ -579,9 +579,7 @@ void WindowGlobalParent::NotifyContentBlockingEvent(
const nsTArray<nsCString>& aTrackingFullHashes,
const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
MOZ_ASSERT(NS_IsMainThread());
DebugOnly<bool> isCookiesBlocked =
aEvent == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
@@ -600,7 +598,7 @@ void WindowGlobalParent::NotifyContentBlockingEvent(
Maybe<uint32_t> event = GetContentBlockingLog()->RecordLogParent(
aTrackingOrigin, aEvent, aBlocked, aReason, aTrackingFullHashes,
- aCanvasFingerprinter, aCanvasFingerprinterKnownText);
+ aCanvasFingerprintingEvent);
// Notify the OnContentBlockingEvent if necessary.
if (event) {
diff --git a/dom/ipc/WindowGlobalParent.h b/dom/ipc/WindowGlobalParent.h
@@ -196,9 +196,7 @@ class WindowGlobalParent final : public WindowContext,
const Maybe<
ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText);
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent);
ContentBlockingLog* GetContentBlockingLog() { return &mContentBlockingLog; }
diff --git a/toolkit/components/antitracking/AntiTrackingIPCUtils.h b/toolkit/components/antitracking/AntiTrackingIPCUtils.h
@@ -54,14 +54,6 @@ struct ParamTraits<nsILoadInfo::StoragePermissionState>
nsILoadInfo::StoragePermissionState,
nsILoadInfo::StoragePermissionState::NoStoragePermission,
nsILoadInfo::StoragePermissionState::InactiveStoragePermission> {};
-
-// ContentBlockingNotifier::CanvasFingerprinter over IPC.
-template <>
-struct ParamTraits<mozilla::ContentBlockingNotifier::CanvasFingerprinter>
- : public ContiguousEnumSerializerInclusive<
- mozilla::ContentBlockingNotifier::CanvasFingerprinter,
- mozilla::ContentBlockingNotifier::CanvasFingerprinter::eFingerprintJS,
- mozilla::ContentBlockingNotifier::CanvasFingerprinter::eMaybe> {};
} // namespace IPC
#endif // mozilla_antitrackingipcutils_h
diff --git a/toolkit/components/antitracking/ContentBlockingLog.cpp b/toolkit/components/antitracking/ContentBlockingLog.cpp
@@ -48,9 +48,7 @@ Maybe<uint32_t> ContentBlockingLog::RecordLogParent(
const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
const nsTArray<nsCString>& aTrackingFullHashes,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
MOZ_ASSERT(XRE_IsParentProcess());
uint32_t events = GetContentBlockingEventsInLog();
@@ -135,8 +133,7 @@ Maybe<uint32_t> ContentBlockingLog::RecordLogParent(
"We don't expected to see blocked "
"STATE_ALLOWED_CANVAS_FINGERPRINTING");
entry = RecordLogInternal(aOrigin, aType, blockedValue, Nothing(), {},
- aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ aCanvasFingerprintingEvent);
// Replace the flag using the suspicious fingerprinting event so that we
// can report the event if we detect suspicious fingerprinting.
@@ -435,9 +432,7 @@ ContentBlockingLog::OriginEntry* ContentBlockingLog::RecordLogInternal(
const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
const nsTArray<nsCString>& aTrackingFullHashes,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
DebugOnly<bool> isCookiesBlockedTracker =
aType == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aType == nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER;
@@ -461,8 +456,7 @@ ContentBlockingLog::OriginEntry* ContentBlockingLog::RecordLogInternal(
if (!entry.mData->mLogs.IsEmpty()) {
auto& last = entry.mData->mLogs.LastElement();
if (last.mType == aType && last.mBlocked == aBlocked &&
- last.mCanvasFingerprinter == aCanvasFingerprinter &&
- last.mCanvasFingerprinterKnownText == aCanvasFingerprinterKnownText) {
+ last.mCanvasFingerprintingEvent == aCanvasFingerprintingEvent) {
++last.mRepeatCount;
// Don't record recorded events. This helps compress our log.
// We don't care about if the the reason is the same, just keep the
@@ -483,9 +477,9 @@ ContentBlockingLog::OriginEntry* ContentBlockingLog::RecordLogInternal(
// Cap the size at the maximum length adjustable by the pref
entry.mData->mLogs.RemoveElementAt(0);
}
- entry.mData->mLogs.AppendElement(
- LogEntry{aType, 1u, aBlocked, aReason, aTrackingFullHashes.Clone(),
- aCanvasFingerprinter, aCanvasFingerprinterKnownText});
+ entry.mData->mLogs.AppendElement(LogEntry{aType, 1u, aBlocked, aReason,
+ aTrackingFullHashes.Clone(),
+ aCanvasFingerprintingEvent});
// Check suspicious fingerprinting activities if the origin hasn't already
// been marked.
@@ -522,9 +516,9 @@ ContentBlockingLog::OriginEntry* ContentBlockingLog::RecordLogInternal(
MOZ_ASSERT(entry->mData->mHasSocialTrackerCookiesLoaded.isNothing());
entry->mData->mHasSocialTrackerCookiesLoaded.emplace(aBlocked);
} else {
- entry->mData->mLogs.AppendElement(
- LogEntry{aType, 1u, aBlocked, aReason, aTrackingFullHashes.Clone(),
- aCanvasFingerprinter, aCanvasFingerprinterKnownText});
+ entry->mData->mLogs.AppendElement(LogEntry{aType, 1u, aBlocked, aReason,
+ aTrackingFullHashes.Clone(),
+ aCanvasFingerprintingEvent});
// Check suspicious fingerprinting activities if the origin hasn't been
// marked.
diff --git a/toolkit/components/antitracking/ContentBlockingLog.h b/toolkit/components/antitracking/ContentBlockingLog.h
@@ -36,8 +36,7 @@ class ContentBlockingLog final {
Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>
mReason;
nsTArray<nsCString> mTrackingFullHashes;
- Maybe<ContentBlockingNotifier::CanvasFingerprinter> mCanvasFingerprinter;
- Maybe<bool> mCanvasFingerprinterKnownText;
+ Maybe<CanvasFingerprintingEvent> mCanvasFingerprintingEvent;
};
struct OriginDataEntry {
@@ -94,9 +93,8 @@ class ContentBlockingLog final {
ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason = Nothing(),
const nsTArray<nsCString>& aTrackingFullHashes = nsTArray<nsCString>(),
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter = Nothing(),
- const Maybe<bool> aCanvasFingerprinterKnownText = Nothing());
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent =
+ Nothing());
void RecordLog(
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
@@ -267,9 +265,8 @@ class ContentBlockingLog final {
ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason = Nothing(),
const nsTArray<nsCString>& aTrackingFullHashes = nsTArray<nsCString>(),
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>&
- aCanvasFingerprinter = Nothing(),
- const Maybe<bool> aCanvasFingerprinterKnownText = Nothing());
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent =
+ Nothing());
bool RecordLogEntryInCustomField(uint32_t aType, OriginEntry& aEntry,
bool aBlocked) {
diff --git a/toolkit/components/antitracking/ContentBlockingNotifier.cpp b/toolkit/components/antitracking/ContentBlockingNotifier.cpp
@@ -334,9 +334,7 @@ void NotifyEventInChild(
const nsACString& aTrackingOrigin,
const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
MOZ_ASSERT(XRE_IsContentProcess());
// We don't need to find the top-level window here because the
@@ -366,8 +364,7 @@ void NotifyEventInChild(
browserChild->NotifyContentBlockingEvent(
aRejectedReason, aTrackingChannel, aBlocked, aTrackingOrigin,
- trackingFullHashes, aReason, aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ trackingFullHashes, aReason, aCanvasFingerprintingEvent);
}
// Update the ContentBlockingLog of the top-level WindowGlobalParent of
@@ -377,9 +374,7 @@ void NotifyEventInParent(
const nsACString& aTrackingOrigin,
const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
aReason,
- const Maybe<ContentBlockingNotifier::CanvasFingerprinter>
- aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsILoadInfo> loadInfo = aTrackingChannel->LoadInfo();
@@ -405,8 +400,7 @@ void NotifyEventInParent(
wgp->NotifyContentBlockingEvent(aRejectedReason, aTrackingChannel, aBlocked,
aTrackingOrigin, trackingFullHashes, aReason,
- aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ aCanvasFingerprintingEvent);
}
} // namespace
@@ -576,15 +570,12 @@ void ContentBlockingNotifier::OnEvent(
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<StorageAccessPermissionGrantedReason>& aReason,
- const Maybe<CanvasFingerprinter>& aCanvasFingerprinter,
- const Maybe<bool> aCanvasFingerprinterKnownText) {
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent) {
if (XRE_IsParentProcess()) {
NotifyEventInParent(aTrackingChannel, aBlocked, aRejectedReason,
- aTrackingOrigin, aReason, aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ aTrackingOrigin, aReason, aCanvasFingerprintingEvent);
} else {
NotifyEventInChild(aTrackingChannel, aBlocked, aRejectedReason,
- aTrackingOrigin, aReason, aCanvasFingerprinter,
- aCanvasFingerprinterKnownText);
+ aTrackingOrigin, aReason, aCanvasFingerprintingEvent);
}
}
diff --git a/toolkit/components/antitracking/ContentBlockingNotifier.h b/toolkit/components/antitracking/ContentBlockingNotifier.h
@@ -9,6 +9,7 @@
#include "nsStringFwd.h"
#include "mozilla/Maybe.h"
+#include "nsRFPService.h"
#define ANTITRACKING_CONSOLE_CATEGORY "Content Blocking"_ns
@@ -85,8 +86,8 @@ class ContentBlockingNotifier final {
const nsACString& aTrackingOrigin,
const ::mozilla::Maybe<StorageAccessPermissionGrantedReason>& aReason =
Nothing(),
- const Maybe<CanvasFingerprinter>& aCanvasFingerprinter = Nothing(),
- const Maybe<bool> aCanvasFingerprinterKnownText = Nothing());
+ const Maybe<CanvasFingerprintingEvent>& aCanvasFingerprintingEvent =
+ Nothing());
static void ReportUnblockingToConsole(
dom::BrowsingContext* aBrowsingContext, const nsAString& aTrackingOrigin,
diff --git a/toolkit/components/resistfingerprinting/moz.build b/toolkit/components/resistfingerprinting/moz.build
@@ -45,6 +45,7 @@ EXPORTS += [
"RFPTargets.inc",
]
EXPORTS.mozilla += [
+ "nsRFPIPCUtils.h",
"RelativeTimeline.h",
]
EXPORTS.mozilla.gtest += ["nsUserCharacteristics.h"]
diff --git a/toolkit/components/resistfingerprinting/nsRFPIPCUtils.h b/toolkit/components/resistfingerprinting/nsRFPIPCUtils.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=80: */
+/* 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/. */
+
+#ifndef mozilla_resistfingerprinting_nsRFPIPCUtils_h
+#define mozilla_resistfingerprinting_nsRFPIPCUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+#include "ipc/EnumSerializer.h"
+#include "nsRFPService.h"
+
+namespace IPC {
+
+// CanvasFingerprintingEvent
+template <>
+struct ParamTraits<mozilla::CanvasFingerprintingEvent> {
+ typedef mozilla::CanvasFingerprintingEvent paramType;
+
+ static void Write(MessageWriter* aWriter, const paramType& aParam) {
+ WriteParam(aWriter, aParam.alias);
+ WriteParam(aWriter, aParam.knownTextBitmask);
+ WriteParam(aWriter, aParam.source);
+ }
+
+ static bool Read(MessageReader* aReader, paramType* aResult) {
+ mozilla::CanvasFingerprinterAlias alias;
+ uint32_t knownTextBitmask;
+ uint8_t source;
+
+ if (!ReadParam(aReader, &alias) || !ReadParam(aReader, &knownTextBitmask) ||
+ !ReadParam(aReader, &source)) {
+ return false;
+ }
+
+ *aResult =
+ mozilla::CanvasFingerprintingEvent(alias, knownTextBitmask, source);
+ return true;
+ }
+};
+
+} // namespace IPC
+
+#endif // mozilla_resistfingerprinting_nsRFPIPCUtils_h
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -2040,6 +2040,9 @@ static void MaybeCurrentCaller(nsACString& aFilename, uint32_t& aLineNum,
return;
}
+ auto event =
+ CanvasFingerprintingEvent(fingerprinter, knownTextBitmask, aSource);
+
if (MOZ_LOG_TEST(gFingerprinterDetection, LogLevel::Info)) {
nsAutoCString filename;
uint32_t lineNum = 0;
@@ -2061,8 +2064,7 @@ static void MaybeCurrentCaller(nsACString& aFilename, uint32_t& aLineNum,
ContentBlockingNotifier::OnEvent(
aChannel, false,
nsIWebProgressListener::STATE_ALLOWED_CANVAS_FINGERPRINTING,
- aOriginNoSuffix, Nothing(), fingerprinter,
- Some(featureUsage & CanvasFeatureUsage::KnownFingerprintText));
+ aOriginNoSuffix, Nothing(), Some(event));
}
/* static */ void nsRFPService::MaybeReportFontFingerprinter(
diff --git a/toolkit/components/resistfingerprinting/nsRFPService.h b/toolkit/components/resistfingerprinting/nsRFPService.h
@@ -185,6 +185,30 @@ class CanvasUsage {
CanvasFeatureUsage aFeatureUsage)
: mSize(aSize), mType(aType), mFeatureUsage(aFeatureUsage) {}
};
+struct CanvasFingerprintingEvent {
+ // The identity or alias of the entity doing the fingerprinting.
+ CanvasFingerprinterAlias alias;
+ // A bitmask of all of the known canvas fingerprinting texts
+ // non-zero indicates some known fingerprinting text was used, making the
+ // event highly likely to be fingerprinting.
+ uint32_t knownTextBitmask;
+ // The API source of the fingerprinting, e.g. <canvas>.toDataURL
+ uint8_t source;
+
+ CanvasFingerprintingEvent()
+ : alias(CanvasFingerprinterAlias::eNoneIdentified),
+ knownTextBitmask(0),
+ source(0) {}
+
+ CanvasFingerprintingEvent(CanvasFingerprinterAlias aAlias,
+ uint32_t aKnownTextBitmask, uint8_t aSource)
+ : alias(aAlias), knownTextBitmask(aKnownTextBitmask), source(aSource) {}
+
+ bool operator==(const CanvasFingerprintingEvent& other) const {
+ return alias == other.alias && knownTextBitmask == other.knownTextBitmask &&
+ source == other.source;
+ }
+};
// ============================================================================