Bug 1933479 - Add tab close button on hover to vertical tabs when sidebar is collapse...
[gecko.git] / toolkit / components / antitracking / ContentBlockingNotifier.cpp
blob9a487310b68dceb270a53c61928c8a48874a4f2d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AntiTrackingLog.h"
8 #include "ContentBlockingNotifier.h"
9 #include "AntiTrackingUtils.h"
11 #include "mozilla/EventQueue.h"
12 #include "mozilla/StaticPrefs_privacy.h"
13 #include "mozilla/SourceLocation.h"
14 #include "mozilla/dom/BrowserChild.h"
15 #include "mozilla/dom/BrowsingContext.h"
16 #include "mozilla/dom/Document.h"
17 #include "mozilla/dom/ContentParent.h"
18 #include "mozilla/dom/WindowGlobalParent.h"
19 #include "nsIClassifiedChannel.h"
20 #include "nsIRunnable.h"
21 #include "nsIScriptError.h"
22 #include "nsIURI.h"
23 #include "nsIOService.h"
24 #include "nsGlobalWindowOuter.h"
25 #include "mozIThirdPartyUtil.h"
27 using namespace mozilla;
28 using namespace mozilla::dom;
29 using mozilla::dom::BrowsingContext;
30 using mozilla::dom::Document;
32 static const uint32_t kMaxConsoleOutputDelayMs = 100;
34 namespace {
36 void RunConsoleReportingRunnable(already_AddRefed<nsIRunnable>&& aRunnable) {
37 if (StaticPrefs::privacy_restrict3rdpartystorage_console_lazy()) {
38 nsresult rv = NS_DispatchToCurrentThreadQueue(std::move(aRunnable),
39 kMaxConsoleOutputDelayMs,
40 EventQueuePriority::Idle);
41 if (NS_WARN_IF(NS_FAILED(rv))) {
42 return;
44 } else {
45 nsCOMPtr<nsIRunnable> runnable(std::move(aRunnable));
46 nsresult rv = runnable->Run();
47 if (NS_WARN_IF(NS_FAILED(rv))) {
48 return;
53 void ReportUnblockingToConsole(
54 uint64_t aWindowID, nsIPrincipal* aPrincipal,
55 const nsAString& aTrackingOrigin,
56 ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason) {
57 MOZ_ASSERT(aWindowID);
58 MOZ_ASSERT(aPrincipal);
60 // Grab the calling location now since the runnable will run without a JS
61 // context on the stack.
62 auto location = JSCallingLocation::Get();
63 nsCOMPtr<nsIPrincipal> principal(aPrincipal);
64 nsAutoString trackingOrigin(aTrackingOrigin);
66 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
67 "ReportUnblockingToConsoleDelayed",
68 [aWindowID, loc = std::move(location), principal, trackingOrigin,
69 aReason]() {
70 const char* messageWithSameOrigin = nullptr;
72 switch (aReason) {
73 case ContentBlockingNotifier::eStorageAccessAPI:
74 case ContentBlockingNotifier::ePrivilegeStorageAccessForOriginAPI:
75 messageWithSameOrigin = "CookieAllowedForOriginByStorageAccessAPI";
76 break;
78 case ContentBlockingNotifier::eOpenerAfterUserInteraction:
79 [[fallthrough]];
80 case ContentBlockingNotifier::eOpener:
81 messageWithSameOrigin = "CookieAllowedForOriginByHeuristic";
82 break;
85 nsAutoCString origin;
86 nsresult rv = principal->GetOriginNoSuffix(origin);
87 if (NS_WARN_IF(NS_FAILED(rv))) {
88 return;
91 // Not adding grantedOrigin yet because we may not want it later.
92 AutoTArray<nsString, 2> params = {NS_ConvertUTF8toUTF16(origin),
93 trackingOrigin};
95 nsAutoString errorText;
96 rv = nsContentUtils::FormatLocalizedString(
97 nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, params,
98 errorText);
99 NS_ENSURE_SUCCESS_VOID(rv);
101 nsContentUtils::ReportToConsoleByWindowID(
102 errorText, nsIScriptError::warningFlag,
103 ANTITRACKING_CONSOLE_CATEGORY, aWindowID, loc);
106 RunConsoleReportingRunnable(runnable.forget());
109 void ReportBlockingToConsole(uint64_t aWindowID, nsIURI* aURI,
110 uint32_t aRejectedReason) {
111 MOZ_ASSERT(aWindowID);
112 MOZ_ASSERT(aURI);
113 MOZ_ASSERT(
114 aRejectedReason == 0 ||
115 aRejectedReason ==
116 static_cast<uint32_t>(
117 nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION) ||
118 aRejectedReason ==
119 static_cast<uint32_t>(
120 nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER) ||
121 aRejectedReason ==
122 static_cast<uint32_t>(
123 nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER) ||
124 aRejectedReason ==
125 static_cast<uint32_t>(
126 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN) ||
127 aRejectedReason ==
128 static_cast<uint32_t>(
129 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER) ||
130 aRejectedReason ==
131 static_cast<uint32_t>(
132 nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL) ||
133 aRejectedReason ==
134 static_cast<uint32_t>(
135 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN));
137 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("about")) {
138 return;
140 bool hasFlags;
141 nsresult rv = NS_URIChainHasFlags(
142 aURI, nsIProtocolHandler::URI_FORBIDS_COOKIE_ACCESS, &hasFlags);
143 if (NS_FAILED(rv) || hasFlags) {
144 // If the protocol doesn't support cookies, no need to report them blocked.
145 return;
148 auto location = JSCallingLocation::Get();
150 nsCOMPtr<nsIURI> uri(aURI);
152 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
153 "ReportBlockingToConsoleDelayed",
154 [aWindowID, loc = std::move(location), uri, aRejectedReason]() {
155 const char* message = nullptr;
156 nsAutoCString category;
157 // When changing this list, please make sure to update the corresponding
158 // code in antitracking_head.js (inside _createTask).
159 // XXX: The nsIWebProgressListener constants below are interpreted as
160 // signed integers on Windows and the compiler complains that they can't
161 // be narrowed to uint32_t. To prevent this, we cast them to uint32_t.
162 switch (aRejectedReason) {
163 case uint32_t(
164 nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION):
165 message = "CookieBlockedByPermission";
166 category = "cookieBlockedPermission"_ns;
167 break;
169 case uint32_t(nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER):
170 message = "CookieBlockedTracker";
171 category = "cookieBlockedTracker"_ns;
172 break;
174 case uint32_t(nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL):
175 message = "CookieBlockedAll";
176 category = "cookieBlockedAll"_ns;
177 break;
179 case uint32_t(nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN):
180 message = "CookieBlockedForeign";
181 category = "cookieBlockedForeign"_ns;
182 break;
184 case uint32_t(
185 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN):
186 case uint32_t(
187 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER):
188 message = "CookiePartitionedForeign2";
189 category = "cookiePartitionedForeign"_ns;
190 break;
192 default:
193 return;
196 MOZ_ASSERT(message);
198 // Strip the URL of any possible username/password and make it ready
199 // to be presented in the UI.
200 nsCOMPtr<nsIURI> exposableURI =
201 net::nsIOService::CreateExposableURI(uri);
202 AutoTArray<nsString, 1> params;
203 CopyUTF8toUTF16(exposableURI->GetSpecOrDefault(),
204 *params.AppendElement());
206 nsAutoString errorText;
207 nsresult rv = nsContentUtils::FormatLocalizedString(
208 nsContentUtils::eNECKO_PROPERTIES, message, params, errorText);
209 NS_ENSURE_SUCCESS_VOID(rv);
211 nsContentUtils::ReportToConsoleByWindowID(
212 errorText, nsIScriptError::warningFlag, category, aWindowID, loc);
215 RunConsoleReportingRunnable(runnable.forget());
218 void ReportBlockingToConsole(nsIChannel* aChannel, nsIURI* aURI,
219 uint32_t aRejectedReason) {
220 MOZ_ASSERT(aChannel && aURI);
221 uint64_t windowID = nsContentUtils::GetInnerWindowID(aChannel);
222 if (!windowID) {
223 // Get the window ID from the target BrowsingContext
224 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
226 RefPtr<dom::BrowsingContext> targetBrowsingContext;
227 loadInfo->GetTargetBrowsingContext(getter_AddRefs(targetBrowsingContext));
229 if (!targetBrowsingContext) {
230 return;
233 WindowContext* windowContext =
234 targetBrowsingContext->GetCurrentWindowContext();
235 if (!windowContext) {
236 return;
239 windowID = windowContext->InnerWindowId();
241 ReportBlockingToConsole(windowID, aURI, aRejectedReason);
244 void NotifyBlockingDecision(nsIChannel* aTrackingChannel,
245 ContentBlockingNotifier::BlockingDecision aDecision,
246 uint32_t aRejectedReason, nsIURI* aURI) {
247 MOZ_ASSERT(aTrackingChannel);
249 // This can be called in either the parent process or the child processes.
250 // When this is called in the child processes, we must have a window.
251 if (XRE_IsContentProcess()) {
252 nsCOMPtr<nsILoadContext> loadContext;
253 NS_QueryNotificationCallbacks(aTrackingChannel, loadContext);
254 if (!loadContext) {
255 return;
258 nsCOMPtr<mozIDOMWindowProxy> window;
259 loadContext->GetAssociatedWindow(getter_AddRefs(window));
260 if (!window) {
261 return;
264 nsCOMPtr<nsPIDOMWindowOuter> outer = nsPIDOMWindowOuter::From(window);
265 if (!outer) {
266 return;
269 // When this is called in the child processes with system privileges,
270 // the decision should always be ALLOW. We can stop here because both
271 // UI and content blocking log don't care this event.
272 if (nsGlobalWindowOuter::Cast(outer)->GetPrincipal() ==
273 nsContentUtils::GetSystemPrincipal()) {
274 MOZ_DIAGNOSTIC_ASSERT(aDecision ==
275 ContentBlockingNotifier::BlockingDecision::eAllow);
276 return;
280 nsAutoCString trackingOrigin;
281 if (aURI) {
282 // Using an empty OriginAttributes is OK here, as we'll only be accessing
283 // OriginNoSuffix.
284 nsCOMPtr<nsIPrincipal> principal =
285 BasePrincipal::CreateContentPrincipal(aURI, OriginAttributes{});
286 principal->GetOriginNoSuffix(trackingOrigin);
289 if (aDecision == ContentBlockingNotifier::BlockingDecision::eBlock) {
290 ContentBlockingNotifier::OnEvent(aTrackingChannel, true, aRejectedReason,
291 trackingOrigin);
293 ReportBlockingToConsole(aTrackingChannel, aURI, aRejectedReason);
296 // Now send the generic "cookies loaded" notifications, from the most generic
297 // to the most specific.
298 ContentBlockingNotifier::OnEvent(aTrackingChannel, false,
299 nsIWebProgressListener::STATE_COOKIES_LOADED,
300 trackingOrigin);
302 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
303 do_QueryInterface(aTrackingChannel);
304 if (!classifiedChannel) {
305 return;
308 if (aRejectedReason ==
309 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER) {
310 ContentBlockingNotifier::OnEvent(
311 aTrackingChannel, true,
312 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER,
313 trackingOrigin);
314 // Stop notifying the tracker cookie loaded events if they are partitioned.
315 return;
318 uint32_t classificationFlags =
319 classifiedChannel->GetThirdPartyClassificationFlags();
320 if (classificationFlags &
321 nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_TRACKING) {
322 ContentBlockingNotifier::OnEvent(
323 aTrackingChannel, false,
324 nsIWebProgressListener::STATE_COOKIES_LOADED_TRACKER, trackingOrigin);
327 if (classificationFlags &
328 nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_SOCIALTRACKING) {
329 ContentBlockingNotifier::OnEvent(
330 aTrackingChannel, false,
331 nsIWebProgressListener::STATE_COOKIES_LOADED_SOCIALTRACKER,
332 trackingOrigin);
336 // Send a message to notify OnContentBlockingEvent in the parent, which will
337 // update the ContentBlockingLog in the parent.
338 void NotifyEventInChild(
339 nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
340 const nsACString& aTrackingOrigin,
341 const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
342 aReason,
343 const Maybe<ContentBlockingNotifier::CanvasFingerprinter>
344 aCanvasFingerprinter,
345 const Maybe<bool> aCanvasFingerprinterKnownText) {
346 MOZ_ASSERT(XRE_IsContentProcess());
348 // We don't need to find the top-level window here because the
349 // parent will do that for us.
350 nsCOMPtr<nsILoadContext> loadContext;
351 NS_QueryNotificationCallbacks(aTrackingChannel, loadContext);
352 if (!loadContext) {
353 return;
356 nsCOMPtr<mozIDOMWindowProxy> window;
357 loadContext->GetAssociatedWindow(getter_AddRefs(window));
358 if (!window) {
359 return;
362 RefPtr<dom::BrowserChild> browserChild = dom::BrowserChild::GetFrom(window);
363 NS_ENSURE_TRUE_VOID(browserChild);
365 nsTArray<nsCString> trackingFullHashes;
366 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
367 do_QueryInterface(aTrackingChannel);
369 if (classifiedChannel) {
370 Unused << classifiedChannel->GetMatchedTrackingFullHashes(
371 trackingFullHashes);
374 browserChild->NotifyContentBlockingEvent(
375 aRejectedReason, aTrackingChannel, aBlocked, aTrackingOrigin,
376 trackingFullHashes, aReason, aCanvasFingerprinter,
377 aCanvasFingerprinterKnownText);
380 // Update the ContentBlockingLog of the top-level WindowGlobalParent of
381 // the tracking channel.
382 void NotifyEventInParent(
383 nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
384 const nsACString& aTrackingOrigin,
385 const Maybe<ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
386 aReason,
387 const Maybe<ContentBlockingNotifier::CanvasFingerprinter>
388 aCanvasFingerprinter,
389 const Maybe<bool> aCanvasFingerprinterKnownText) {
390 MOZ_ASSERT(XRE_IsParentProcess());
392 nsCOMPtr<nsILoadInfo> loadInfo = aTrackingChannel->LoadInfo();
393 RefPtr<dom::BrowsingContext> bc;
394 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
396 if (!bc || bc->IsDiscarded()) {
397 return;
400 bc = bc->Top();
401 RefPtr<dom::WindowGlobalParent> wgp =
402 bc->Canonical()->GetCurrentWindowGlobal();
403 NS_ENSURE_TRUE_VOID(wgp);
405 nsTArray<nsCString> trackingFullHashes;
406 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
407 do_QueryInterface(aTrackingChannel);
409 if (classifiedChannel) {
410 Unused << classifiedChannel->GetMatchedTrackingFullHashes(
411 trackingFullHashes);
414 wgp->NotifyContentBlockingEvent(aRejectedReason, aTrackingChannel, aBlocked,
415 aTrackingOrigin, trackingFullHashes, aReason,
416 aCanvasFingerprinter,
417 aCanvasFingerprinterKnownText);
420 } // namespace
422 /* static */
423 void ContentBlockingNotifier::ReportUnblockingToConsole(
424 BrowsingContext* aBrowsingContext, const nsAString& aTrackingOrigin,
425 ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason) {
426 MOZ_ASSERT(aBrowsingContext);
427 MOZ_ASSERT_IF(XRE_IsContentProcess(), aBrowsingContext->Top()->IsInProcess());
429 uint64_t windowID = aBrowsingContext->GetCurrentInnerWindowId();
431 // The storage permission is granted under the top-level origin.
432 nsCOMPtr<nsIPrincipal> principal =
433 AntiTrackingUtils::GetPrincipal(aBrowsingContext->Top());
434 if (NS_WARN_IF(!principal)) {
435 return;
438 ::ReportUnblockingToConsole(windowID, principal, aTrackingOrigin, aReason);
441 /* static */
442 void ContentBlockingNotifier::OnDecision(nsIChannel* aChannel,
443 BlockingDecision aDecision,
444 uint32_t aRejectedReason) {
445 MOZ_ASSERT(
446 aRejectedReason == 0 ||
447 aRejectedReason ==
448 static_cast<uint32_t>(
449 nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION) ||
450 aRejectedReason ==
451 static_cast<uint32_t>(
452 nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER) ||
453 aRejectedReason ==
454 static_cast<uint32_t>(
455 nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER) ||
456 aRejectedReason ==
457 static_cast<uint32_t>(
458 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN) ||
459 aRejectedReason ==
460 static_cast<uint32_t>(
461 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER) ||
462 aRejectedReason ==
463 static_cast<uint32_t>(
464 nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL) ||
465 aRejectedReason ==
466 static_cast<uint32_t>(
467 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN));
468 MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
469 aDecision == BlockingDecision::eAllow);
471 if (!aChannel) {
472 return;
475 nsCOMPtr<nsIURI> uri;
476 aChannel->GetURI(getter_AddRefs(uri));
478 // Can be called in EITHER the parent or child process.
479 NotifyBlockingDecision(aChannel, aDecision, aRejectedReason, uri);
482 /* static */
483 void ContentBlockingNotifier::OnDecision(nsPIDOMWindowInner* aWindow,
484 BlockingDecision aDecision,
485 uint32_t aRejectedReason) {
486 MOZ_ASSERT(aWindow);
487 MOZ_ASSERT(
488 aRejectedReason == 0 ||
489 aRejectedReason ==
490 static_cast<uint32_t>(
491 nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION) ||
492 aRejectedReason ==
493 static_cast<uint32_t>(
494 nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER) ||
495 aRejectedReason ==
496 static_cast<uint32_t>(
497 nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER) ||
498 aRejectedReason ==
499 static_cast<uint32_t>(
500 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN) ||
501 aRejectedReason ==
502 static_cast<uint32_t>(
503 nsIWebProgressListener::STATE_COOKIES_PARTITIONED_TRACKER) ||
504 aRejectedReason ==
505 static_cast<uint32_t>(
506 nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL) ||
507 aRejectedReason ==
508 static_cast<uint32_t>(
509 nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN));
510 MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
511 aDecision == BlockingDecision::eAllow);
513 Document* document = aWindow->GetExtantDoc();
514 if (!document) {
515 return;
518 nsIChannel* channel = document->GetChannel();
519 if (!channel) {
520 return;
523 nsIURI* uri = document->GetDocumentURI();
525 NotifyBlockingDecision(channel, aDecision, aRejectedReason, uri);
528 /* static */
529 void ContentBlockingNotifier::OnDecision(BrowsingContext* aBrowsingContext,
530 BlockingDecision aDecision,
531 uint32_t aRejectedReason) {
532 MOZ_ASSERT(aBrowsingContext);
533 MOZ_ASSERT_IF(XRE_IsContentProcess(), aBrowsingContext->IsInProcess());
535 if (aBrowsingContext->IsInProcess()) {
536 nsCOMPtr<nsPIDOMWindowOuter> outer = aBrowsingContext->GetDOMWindow();
537 if (NS_WARN_IF(!outer)) {
538 return;
541 nsCOMPtr<nsPIDOMWindowInner> inner = outer->GetCurrentInnerWindow();
542 if (NS_WARN_IF(!inner)) {
543 return;
546 ContentBlockingNotifier::OnDecision(inner, aDecision, aRejectedReason);
547 } else {
548 // we send an IPC to the content process when we don't have an in-process
549 // browsing context. This is not smart because this should be able to be
550 // done directly in the parent. The reason we are doing this is because we
551 // need the channel, which is not accessible in the parent when you only
552 // have a browsing context.
553 MOZ_ASSERT(XRE_IsParentProcess());
555 ContentParent* cp = aBrowsingContext->Canonical()->GetContentParent();
556 Unused << cp->SendOnContentBlockingDecision(aBrowsingContext, aDecision,
557 aRejectedReason);
561 /* static */
562 void ContentBlockingNotifier::OnEvent(nsIChannel* aTrackingChannel,
563 uint32_t aRejectedReason, bool aBlocked) {
564 MOZ_ASSERT(XRE_IsParentProcess() && aTrackingChannel);
566 nsCOMPtr<nsIURI> uri;
567 aTrackingChannel->GetURI(getter_AddRefs(uri));
569 nsAutoCString trackingOrigin;
570 if (uri) {
571 // Using empty OriginAttributes is OK here, as we only want to access
572 // OriginNoSuffix.
573 nsCOMPtr<nsIPrincipal> trackingPrincipal =
574 BasePrincipal::CreateContentPrincipal(uri, OriginAttributes{});
575 trackingPrincipal->GetOriginNoSuffix(trackingOrigin);
578 return ContentBlockingNotifier::OnEvent(aTrackingChannel, aBlocked,
579 aRejectedReason, trackingOrigin);
582 /* static */
583 void ContentBlockingNotifier::OnEvent(
584 nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
585 const nsACString& aTrackingOrigin,
586 const Maybe<StorageAccessPermissionGrantedReason>& aReason,
587 const Maybe<CanvasFingerprinter>& aCanvasFingerprinter,
588 const Maybe<bool> aCanvasFingerprinterKnownText) {
589 if (XRE_IsParentProcess()) {
590 NotifyEventInParent(aTrackingChannel, aBlocked, aRejectedReason,
591 aTrackingOrigin, aReason, aCanvasFingerprinter,
592 aCanvasFingerprinterKnownText);
593 } else {
594 NotifyEventInChild(aTrackingChannel, aBlocked, aRejectedReason,
595 aTrackingOrigin, aReason, aCanvasFingerprinter,
596 aCanvasFingerprinterKnownText);