Bug 1620322 - Part 2: Refactor the code for content blocking events and notifications out of AntiTrackingCommon.cpp; r=baku

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ehsan Akhgari 2020-03-09 10:16:54 +00:00
Родитель da8e27212f
Коммит 4bc71d0112
24 изменённых файлов: 730 добавлений и 618 удалений

Просмотреть файл

@ -110,7 +110,7 @@ static void ReportOriginSingleHash(OriginMetricID aId,
Maybe<uint32_t> ContentBlockingLog::RecordLogParent(
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason,
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason,
const nsTArray<nsCString>& aTrackingFullHashes) {
MOZ_ASSERT(XRE_IsParentProcess());

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef mozilla_dom_ContentBlockingLog_h
#define mozilla_dom_ContentBlockingLog_h
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/JSONWriter.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticPrefs_browser.h"
@ -18,18 +18,20 @@
#include "nsTArray.h"
#include "nsWindowSizes.h"
class nsIPrincipal;
namespace mozilla {
namespace dom {
class ContentBlockingLog final {
typedef AntiTrackingCommon::StorageAccessGrantedReason
typedef ContentBlockingNotifier::StorageAccessGrantedReason
StorageAccessGrantedReason;
struct LogEntry {
uint32_t mType;
uint32_t mRepeatCount;
bool mBlocked;
Maybe<AntiTrackingCommon::StorageAccessGrantedReason> mReason;
Maybe<ContentBlockingNotifier::StorageAccessGrantedReason> mReason;
nsTArray<nsCString> mTrackingFullHashes;
};
@ -87,12 +89,12 @@ class ContentBlockingLog final {
// ContentBlockingLog from content processes.
Maybe<uint32_t> RecordLogParent(
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason,
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason,
const nsTArray<nsCString>& aTrackingFullHashes);
void RecordLog(
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason,
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason,
const nsTArray<nsCString>& aTrackingFullHashes) {
RecordLogInternal(aOrigin, aType, aBlocked, aReason, aTrackingFullHashes);
}
@ -241,8 +243,8 @@ class ContentBlockingLog final {
private:
void RecordLogInternal(
const nsACString& aOrigin, uint32_t aType, bool aBlocked,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason =
Nothing(),
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason = Nothing(),
const nsTArray<nsCString>& aTrackingFullHashes = nsTArray<nsCString>()) {
DebugOnly<bool> isCookiesBlockedTracker =
aType == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||

Просмотреть файл

@ -15066,7 +15066,7 @@ void Document::MaybeAllowStorageForOpenerAfterUserInteraction() {
// We don't care when the asynchronous work finishes here.
Unused << AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
NodePrincipal(), openerInner,
AntiTrackingCommon::eOpenerAfterUserInteraction);
ContentBlockingNotifier::eOpenerAfterUserInteraction);
}
namespace {
@ -15721,7 +15721,7 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccess(
return std::move(p);
};
AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
NodePrincipal(), inner, AntiTrackingCommon::eStorageAccessAPI,
NodePrincipal(), inner, ContentBlockingNotifier::eStorageAccessAPI,
performFinalChecks)
->Then(
GetCurrentThreadSerialEventTarget(), __func__,

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsPluginArray.h"
#include "nsMimeTypeArray.h"
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/BodyExtractor.h"
#include "mozilla/dom/FetchBinding.h"
@ -530,10 +531,10 @@ bool Navigator::CookieEnabled() {
bool granted = AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
mWindow, contentURI, &rejectedReason);
AntiTrackingCommon::NotifyBlockingDecision(
ContentBlockingNotifier::OnDecision(
mWindow,
granted ? AntiTrackingCommon::BlockingDecision::eAllow
: AntiTrackingCommon::BlockingDecision::eBlock,
granted ? ContentBlockingNotifier::BlockingDecision::eAllow
: ContentBlockingNotifier::BlockingDecision::eBlock,
rejectedReason);
return granted;
}

Просмотреть файл

@ -500,8 +500,8 @@ ThirdPartyUtil::AnalyzeChannel(nsIChannel* aChannel, bool aNotify, nsIURI* aURI,
if (aNotify && !result.contains(
ThirdPartyAnalysis::IsFirstPartyStorageAccessGranted)) {
AntiTrackingCommon::NotifyBlockingDecision(
aChannel, AntiTrackingCommon::BlockingDecision::eBlock,
ContentBlockingNotifier::OnDecision(
aChannel, ContentBlockingNotifier::BlockingDecision::eBlock,
*aRejectedReason);
}
}

Просмотреть файл

@ -7184,7 +7184,7 @@ void nsGlobalWindowOuter::MaybeAllowStorageForOpenedWindow(nsIURI* aURI) {
// We don't care when the asynchronous work finishes here.
Unused << AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
principal, inner, AntiTrackingCommon::eOpener);
principal, inner, ContentBlockingNotifier::eOpener);
}
//*****************************************************************************

Просмотреть файл

@ -4048,7 +4048,7 @@ void BrowserChild::NotifyContentBlockingEvent(
uint32_t aEvent, nsIChannel* aChannel, bool aBlocked,
const nsACString& aTrackingOrigin,
const nsTArray<nsCString>& aTrackingFullHashes,
const Maybe<mozilla::AntiTrackingCommon::StorageAccessGrantedReason>&
const Maybe<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason) {
if (!IPCOpen()) {
return;

Просмотреть файл

@ -699,7 +699,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
uint32_t aEvent, nsIChannel* aChannel, bool aBlocked,
const nsACString& aTrackingOrigin,
const nsTArray<nsCString>& aTrackingFullHashes,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason);
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason);
protected:
virtual ~BrowserChild();

Просмотреть файл

@ -2695,7 +2695,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvNotifyContentBlockingEvent(
const uint32_t& aEvent, const RequestData& aRequestData,
const bool aBlocked, const nsACString& aTrackingOrigin,
nsTArray<nsCString>&& aTrackingFullHashes,
const Maybe<mozilla::AntiTrackingCommon::StorageAccessGrantedReason>&
const Maybe<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason) {
MOZ_ASSERT(aRequestData.elapsedLoadTimeMS().isNothing());

Просмотреть файл

@ -317,7 +317,7 @@ class BrowserParent final : public PBrowserParent,
const uint32_t& aEvent, const RequestData& aRequestData,
const bool aBlocked, const nsACString& aTrackingOrigin,
nsTArray<nsCString>&& aTrackingFullHashes,
const Maybe<mozilla::AntiTrackingCommon::StorageAccessGrantedReason>&
const Maybe<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason);
mozilla::ipc::IPCResult RecvNavigationFinished();

Просмотреть файл

@ -95,7 +95,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 refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h";
using mozilla::AntiTrackingCommon::StorageAccessGrantedReason from "mozilla/AntiTrackingCommon.h";
using mozilla::ContentBlockingNotifier::StorageAccessGrantedReason from "mozilla/ContentBlockingNotifier.h";
using CallerType from "mozilla/dom/BindingDeclarations.h";
namespace mozilla {

Просмотреть файл

@ -311,7 +311,7 @@ void WindowGlobalParent::NotifyContentBlockingEvent(
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
const nsACString& aTrackingOrigin,
const nsTArray<nsCString>& aTrackingFullHashes,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason) {
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason) {
MOZ_ASSERT(NS_IsMainThread());
DebugOnly<bool> isCookiesBlockedTracker =
aEvent == nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef mozilla_dom_WindowGlobalParent_h
#define mozilla_dom_WindowGlobalParent_h
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/PWindowGlobalParent.h"
@ -146,8 +146,8 @@ class WindowGlobalParent final : public WindowContext,
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
const nsACString& aTrackingOrigin,
const nsTArray<nsCString>& aTrackingFullHashes,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason =
Nothing());
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>&
aReason = Nothing());
ContentBlockingLog* GetContentBlockingLog() { return &mContentBlockingLog; }

Просмотреть файл

@ -4,9 +4,9 @@
* 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/. */
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/Attributes.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Likely.h"
#include "mozilla/Printf.h"
@ -2265,8 +2265,8 @@ void nsCookieService::SetCookieStringInternal(
}
void nsCookieService::NotifyAccepted(nsIChannel* aChannel) {
AntiTrackingCommon::NotifyBlockingDecision(
aChannel, AntiTrackingCommon::BlockingDecision::eAllow, 0);
ContentBlockingNotifier::OnDecision(
aChannel, ContentBlockingNotifier::BlockingDecision::eAllow, 0);
}
// notify observers that a cookie was rejected due to the users' prefs.
@ -2282,8 +2282,9 @@ void nsCookieService::NotifyRejected(nsIURI* aHostURI, nsIChannel* aChannel,
MOZ_ASSERT(aOperation == OPERATION_READ);
}
AntiTrackingCommon::NotifyBlockingDecision(
aChannel, AntiTrackingCommon::BlockingDecision::eBlock, aRejectedReason);
ContentBlockingNotifier::OnDecision(
aChannel, ContentBlockingNotifier::BlockingDecision::eBlock,
aRejectedReason);
}
// notify observers that the cookie list changed. there are five possible

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ContentBlockingAllowList.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/net/HttpBaseChannel.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
@ -211,7 +212,7 @@ nsresult UrlClassifierCommon::SetBlockedContent(nsIChannel* channel,
if (!state) {
state = nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
}
AntiTrackingCommon::NotifyContentBlockingEvent(channel, state);
ContentBlockingNotifier::OnEvent(channel, state);
return NS_OK;
}
@ -443,7 +444,7 @@ void UrlClassifierCommon::AnnotateChannel(nsIChannel* aChannel,
IsCryptominingClassificationFlag(aClassificationFlags);
if (validClassificationFlags && isThirdPartyWithTopLevelWinURI) {
AntiTrackingCommon::NotifyContentBlockingEvent(aChannel, aLoadingState);
ContentBlockingNotifier::OnEvent(aChannel, aLoadingState);
}
if (isThirdPartyWithTopLevelWinURI &&

Просмотреть файл

@ -6,6 +6,7 @@
#include "AntiTrackingLog.h"
#include "AntiTrackingCommon.h"
#include "AntiTrackingUtils.h"
#include "mozilla/ContentBlockingAllowList.h"
#include "mozilla/dom/BrowsingContext.h"
@ -48,7 +49,6 @@
#include "prtime.h"
#define ANTITRACKING_PERM_KEY "3rdPartyStorage"
#define ANTITRACKING_CONSOLE_CATEGORY NS_LITERAL_CSTRING("Content Blocking")
namespace mozilla {
@ -61,8 +61,6 @@ using mozilla::dom::BrowsingContext;
using mozilla::dom::ContentChild;
using mozilla::dom::Document;
static const uint32_t kMaxConsoleOutputDelayMs = 100;
namespace {
bool GetParentPrincipalAndTrackingOrigin(
@ -180,229 +178,6 @@ int32_t CookiesBehavior(nsIPrincipal* aPrincipal,
return aCookieJarSettings->GetCookieBehavior();
}
void RunConsoleReportingRunnable(already_AddRefed<nsIRunnable>&& aRunnable) {
if (StaticPrefs::privacy_restrict3rdpartystorage_console_lazy()) {
nsresult rv = NS_DispatchToCurrentThreadQueue(std::move(aRunnable),
kMaxConsoleOutputDelayMs,
EventQueuePriority::Idle);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
} else {
nsCOMPtr<nsIRunnable> runnable(std::move(aRunnable));
nsresult rv = runnable->Run();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
}
void ReportBlockingToConsole(uint64_t aWindowID, nsIURI* aURI,
uint32_t aRejectedReason) {
MOZ_ASSERT(aWindowID);
MOZ_ASSERT(aURI);
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
nsAutoString sourceLine;
uint32_t lineNumber = 0, columnNumber = 0;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
nsJSUtils::GetCallingLocation(cx, sourceLine, &lineNumber, &columnNumber);
}
nsCOMPtr<nsIURI> uri(aURI);
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"ReportBlockingToConsoleDelayed", [aWindowID, sourceLine, lineNumber,
columnNumber, uri, aRejectedReason]() {
const char* message = nullptr;
nsAutoCString category;
// When changing this list, please make sure to update the corresponding
// code in antitracking_head.js (inside _createTask).
switch (aRejectedReason) {
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION:
message = "CookieBlockedByPermission";
category = NS_LITERAL_CSTRING("cookieBlockedPermission");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER:
message = "CookieBlockedTracker";
category = NS_LITERAL_CSTRING("cookieBlockedTracker");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL:
message = "CookieBlockedAll";
category = NS_LITERAL_CSTRING("cookieBlockedAll");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN:
message = "CookieBlockedForeign";
category = NS_LITERAL_CSTRING("cookieBlockedForeign");
break;
default:
return;
}
MOZ_ASSERT(message);
// Strip the URL of any possible username/password and make it ready
// to be presented in the UI.
nsCOMPtr<nsIURIFixup> urifixup = services::GetURIFixup();
NS_ENSURE_TRUE_VOID(urifixup);
nsCOMPtr<nsIURI> exposableURI;
nsresult rv =
urifixup->CreateExposableURI(uri, getter_AddRefs(exposableURI));
NS_ENSURE_SUCCESS_VOID(rv);
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(exposableURI->GetSpecOrDefault(),
*params.AppendElement());
nsAutoString errorText;
rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eNECKO_PROPERTIES, message, params, errorText);
NS_ENSURE_SUCCESS_VOID(rv);
nsContentUtils::ReportToConsoleByWindowID(
errorText, nsIScriptError::warningFlag, category, aWindowID,
nullptr, sourceLine, lineNumber, columnNumber);
});
RunConsoleReportingRunnable(runnable.forget());
}
void ReportBlockingToConsole(nsIChannel* aChannel, nsIURI* aURI,
uint32_t aRejectedReason) {
MOZ_ASSERT(aChannel && aURI);
uint64_t windowID;
if (XRE_IsParentProcess()) {
// Get the top-level window ID from the top-level BrowsingContext
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
RefPtr<dom::BrowsingContext> bc;
loadInfo->GetBrowsingContext(getter_AddRefs(bc));
if (!bc || bc->IsDiscarded()) {
return;
}
bc = bc->Top();
RefPtr<dom::WindowGlobalParent> wgp =
bc->Canonical()->GetCurrentWindowGlobal();
if (!wgp) {
return;
}
windowID = wgp->InnerWindowId();
} else {
nsresult rv;
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel, &rv);
if (!httpChannel) {
return;
}
rv = httpChannel->GetTopLevelContentWindowId(&windowID);
if (NS_FAILED(rv) || !windowID) {
windowID = nsContentUtils::GetInnerWindowID(httpChannel);
}
}
ReportBlockingToConsole(windowID, aURI, aRejectedReason);
}
void ReportUnblockingToConsole(
nsPIDOMWindowInner* aWindow, const nsAString& aTrackingOrigin,
AntiTrackingCommon::StorageAccessGrantedReason aReason) {
nsCOMPtr<nsIPrincipal> principal =
nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
if (NS_WARN_IF(!principal)) {
return;
}
RefPtr<Document> doc = aWindow->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
return;
}
nsAutoString trackingOrigin(aTrackingOrigin);
nsAutoString sourceLine;
uint32_t lineNumber = 0, columnNumber = 0;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
nsJSUtils::GetCallingLocation(cx, sourceLine, &lineNumber, &columnNumber);
}
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"ReportUnblockingToConsoleDelayed",
[doc, principal, trackingOrigin, sourceLine, lineNumber, columnNumber,
aReason]() {
nsAutoString origin;
nsresult rv = nsContentUtils::GetUTFOrigin(principal, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Not adding grantedOrigin yet because we may not want it later.
AutoTArray<nsString, 3> params = {origin, trackingOrigin};
const char* messageWithSameOrigin = nullptr;
switch (aReason) {
case AntiTrackingCommon::eStorageAccessAPI:
messageWithSameOrigin = "CookieAllowedForTrackerByStorageAccessAPI";
break;
case AntiTrackingCommon::eOpenerAfterUserInteraction:
[[fallthrough]];
case AntiTrackingCommon::eOpener:
messageWithSameOrigin = "CookieAllowedForTrackerByHeuristic";
break;
}
nsContentUtils::ReportToConsole(
nsIScriptError::warningFlag, ANTITRACKING_CONSOLE_CATEGORY, doc,
nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, params,
nullptr, sourceLine, lineNumber, columnNumber);
});
RunConsoleReportingRunnable(runnable.forget());
}
already_AddRefed<nsPIDOMWindowOuter> GetTopWindow(nsPIDOMWindowInner* aWindow) {
Document* document = aWindow->GetExtantDoc();
if (!document) {
return nullptr;
}
nsIChannel* channel = document->GetChannel();
if (!channel) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowOuter> pwin =
aWindow->GetBrowsingContext()->Top()->GetDOMWindow();
if (!pwin) {
return nullptr;
}
return pwin.forget();
}
class TemporaryAccessGrantCacheKey : public PLDHashEntryHdr {
public:
typedef Pair<nsCOMPtr<nsIPrincipal>, nsCString> KeyType;
@ -636,175 +411,17 @@ bool CheckAntiTrackingPermission(nsIPrincipal* aPrincipal,
return true;
}
// This API finishes the remaining work left in NotifyBlockingDecisionInternal.
void NotifyAllowDecisionInternal(nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, nsIURI* aURI,
nsPIDOMWindowOuter* aWindow) {
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
// This can be called in either the parent process or the child processes.
// Now send the generic "cookies loaded" notifications, from the most generic
// to the most specific.
AntiTrackingCommon::NotifyContentBlockingEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED, trackingOrigin);
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (!classifiedChannel) {
return;
}
uint32_t classificationFlags =
classifiedChannel->GetThirdPartyClassificationFlags();
if (classificationFlags &
nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_TRACKING) {
AntiTrackingCommon::NotifyContentBlockingEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED_TRACKER, trackingOrigin);
}
if (classificationFlags &
nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_SOCIALTRACKING) {
AntiTrackingCommon::NotifyContentBlockingEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED_SOCIALTRACKER,
trackingOrigin);
}
}
void NotifyBlockingDecisionInternal(
nsIChannel* aReportingChannel, nsIChannel* aTrackingChannel,
AntiTrackingCommon::BlockingDecision aDecision, uint32_t aRejectedReason,
nsIURI* aURI, nsPIDOMWindowOuter* aWindow) {
MOZ_ASSERT(aWindow);
// When this is called with system priviledged, the decision should always be
// ALLOW, and we can also stop processing this event.
if (nsGlobalWindowOuter::Cast(aWindow)->GetPrincipal() ==
nsContentUtils::GetSystemPrincipal()) {
MOZ_DIAGNOSTIC_ASSERT(aDecision ==
AntiTrackingCommon::BlockingDecision::eAllow);
return;
}
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
if (aDecision == AntiTrackingCommon::BlockingDecision::eBlock) {
AntiTrackingCommon::NotifyContentBlockingEvent(
aWindow, aReportingChannel, aTrackingChannel, true, aRejectedReason,
trackingOrigin);
ReportBlockingToConsole(aReportingChannel, aURI, aRejectedReason);
}
NotifyAllowDecisionInternal(aReportingChannel, aTrackingChannel, aURI,
aWindow);
}
void NotifyBlockingDecisionInternal(
nsIChannel* aReportingChannel, nsIChannel* aTrackingChannel,
AntiTrackingCommon::BlockingDecision aDecision, uint32_t aRejectedReason,
nsIURI* aURI) {
// Can be called only in the parent process when there is no window.
MOZ_ASSERT(XRE_IsParentProcess());
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
if (aDecision == AntiTrackingCommon::BlockingDecision::eBlock) {
AntiTrackingCommon::NotifyContentBlockingEvent(
nullptr, aReportingChannel, aTrackingChannel, true, aRejectedReason,
trackingOrigin);
ReportBlockingToConsole(aReportingChannel, aURI, aRejectedReason);
}
NotifyAllowDecisionInternal(aReportingChannel, aTrackingChannel, aURI,
nullptr);
}
// Send a message to notify OnContentBlockingEvent in the parent, which will
// update the ContentBlockingLog in the parent.
void NotifyContentBlockingEventInChild(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason) {
MOZ_ASSERT(XRE_IsContentProcess());
MOZ_ASSERT(aWindow);
RefPtr<dom::BrowserChild> browserChild = dom::BrowserChild::GetFrom(aWindow);
NS_ENSURE_TRUE_VOID(browserChild);
nsTArray<nsCString> trackingFullHashes;
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (classifiedChannel) {
Unused << classifiedChannel->GetMatchedTrackingFullHashes(
trackingFullHashes);
}
browserChild->NotifyContentBlockingEvent(aRejectedReason, aReportingChannel,
aBlocked, aTrackingOrigin,
trackingFullHashes, aReason);
}
// Update the ContentBlockingLog of the top-level WindowGlobalParent of
// the reporting channel.
void NotifyContentBlockingEventInParent(
nsIChannel* aReportingChannel, nsIChannel* aTrackingChannel, bool aBlocked,
uint32_t aRejectedReason, const nsACString& aTrackingOrigin,
const Maybe<AntiTrackingCommon::StorageAccessGrantedReason>& aReason) {
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsILoadInfo> loadInfo = aReportingChannel->LoadInfo();
RefPtr<dom::BrowsingContext> bc;
loadInfo->GetBrowsingContext(getter_AddRefs(bc));
if (!bc || bc->IsDiscarded()) {
return;
}
bc = bc->Top();
RefPtr<dom::WindowGlobalParent> wgp =
bc->Canonical()->GetCurrentWindowGlobal();
NS_ENSURE_TRUE_VOID(wgp);
nsTArray<nsCString> trackingFullHashes;
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (classifiedChannel) {
Unused << classifiedChannel->GetMatchedTrackingFullHashes(
trackingFullHashes);
}
wgp->NotifyContentBlockingEvent(aRejectedReason, aReportingChannel, aBlocked,
aTrackingOrigin, trackingFullHashes, aReason);
}
} // namespace
/* static */ RefPtr<AntiTrackingCommon::StorageAccessGrantPromise>
AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aParentWindow,
StorageAccessGrantedReason aReason,
ContentBlockingNotifier::StorageAccessGrantedReason aReason,
const AntiTrackingCommon::PerformFinalChecks& aPerformFinalChecks) {
MOZ_ASSERT(aParentWindow);
switch (aReason) {
case eOpener:
case ContentBlockingNotifier::eOpener:
if (!StaticPrefs::
privacy_restrict3rdpartystorage_heuristic_window_open()) {
LOG(
@ -814,7 +431,7 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
}
break;
case eOpenerAfterUserInteraction:
case ContentBlockingNotifier::eOpenerAfterUserInteraction:
if (!StaticPrefs::
privacy_restrict3rdpartystorage_heuristic_opened_window_after_interaction()) {
LOG(
@ -976,12 +593,14 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
"refusing to add a first-party storage permission to access it",
_spec),
trackingPrincipal);
NotifyBlockingDecision(aParentWindow, BlockingDecision::eBlock,
blockReason);
ContentBlockingNotifier::OnDecision(
aParentWindow, ContentBlockingNotifier::BlockingDecision::eBlock,
blockReason);
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
}
nsCOMPtr<nsPIDOMWindowOuter> pwin = GetTopWindow(parentWindow);
nsCOMPtr<nsPIDOMWindowOuter> pwin =
AntiTrackingUtils::GetTopWindow(parentWindow);
if (!pwin) {
LOG(("Couldn't get the top window"));
return StorageAccessGrantPromise::CreateAndReject(false, __func__);
@ -1003,12 +622,12 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
nsIChannel* channel =
pwin->GetCurrentInnerWindow()->GetExtantDoc()->GetChannel();
NotifyContentBlockingEvent(
ContentBlockingNotifier::OnEvent(
pwin, channel, parentWindow->GetExtantDoc()->GetChannel(), false,
blockReason, trackingOrigin, Some(aReason));
ReportUnblockingToConsole(parentWindow,
NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
ContentBlockingNotifier::ReportUnblockingToConsole(
parentWindow, NS_ConvertUTF8toUTF16(trackingOrigin), aReason);
if (XRE_IsParentProcess()) {
LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get()));
@ -1740,111 +1359,6 @@ bool AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(
nsContentUtils::IsInPrivateBrowsing(parentDocument), nullptr, 0);
}
/* static */
void AntiTrackingCommon::NotifyBlockingDecision(nsIChannel* aChannel,
BlockingDecision aDecision,
uint32_t aRejectedReason) {
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
if (!aChannel) {
return;
}
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
// Can be called in EITHER the parent or child process.
// Window is only needed while in child processes.
if (XRE_IsParentProcess()) {
NotifyBlockingDecisionInternal(aChannel, aChannel, aDecision,
aRejectedReason, uri);
return;
}
MOZ_ASSERT(XRE_IsContentProcess());
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
if (!thirdPartyUtil) {
return;
}
nsCOMPtr<nsIURI> uriBeingLoaded = MaybeGetDocumentURIBeingLoaded(aChannel);
nsCOMPtr<mozIDOMWindowProxy> win;
nsresult rv = thirdPartyUtil->GetTopWindowForChannel(aChannel, uriBeingLoaded,
getter_AddRefs(win));
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(win);
if (!pwin) {
return;
}
NotifyBlockingDecisionInternal(aChannel, aChannel, aDecision, aRejectedReason,
uri, pwin);
}
/* static */
void AntiTrackingCommon::NotifyBlockingDecision(nsPIDOMWindowInner* aWindow,
BlockingDecision aDecision,
uint32_t aRejectedReason) {
MOZ_ASSERT(aWindow);
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
nsCOMPtr<nsPIDOMWindowOuter> pwin = GetTopWindow(aWindow);
if (!pwin) {
return;
}
nsPIDOMWindowInner* inner = pwin->GetCurrentInnerWindow();
if (!inner) {
return;
}
Document* pwinDoc = inner->GetExtantDoc();
if (!pwinDoc) {
return;
}
nsIChannel* channel = pwinDoc->GetChannel();
if (!channel) {
return;
}
Document* document = aWindow->GetExtantDoc();
if (!document) {
return;
}
nsIURI* uri = document->GetDocumentURI();
nsIChannel* trackingChannel = document->GetChannel();
NotifyBlockingDecisionInternal(channel, trackingChannel, aDecision,
aRejectedReason, uri, pwin);
}
/* static */
void AntiTrackingCommon::StoreUserInteractionFor(nsIPrincipal* aPrincipal) {
if (!aPrincipal) {
@ -1931,40 +1445,6 @@ already_AddRefed<nsIURI> AntiTrackingCommon::MaybeGetDocumentURIBeingLoaded(
return uriBeingLoaded.forget();
}
/* static */
void AntiTrackingCommon::NotifyContentBlockingEvent(nsIChannel* aChannel,
uint32_t aRejectedReason) {
MOZ_ASSERT(XRE_IsParentProcess() && aChannel);
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
nsAutoCString trackingOrigin;
if (uri) {
Unused << nsContentUtils::GetASCIIOrigin(uri, trackingOrigin);
}
return AntiTrackingCommon::NotifyContentBlockingEvent(
nullptr, aChannel, aChannel, true, aRejectedReason, trackingOrigin);
}
/* static */
void AntiTrackingCommon::NotifyContentBlockingEvent(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<StorageAccessGrantedReason>& aReason) {
if (XRE_IsParentProcess()) {
NotifyContentBlockingEventInParent(aReportingChannel, aTrackingChannel,
aBlocked, aRejectedReason,
aTrackingOrigin, aReason);
} else {
NotifyContentBlockingEventInChild(
aWindow, aReportingChannel, aTrackingChannel, aBlocked, aRejectedReason,
aTrackingOrigin, aReason);
}
}
/* static */
void AntiTrackingCommon::RedirectHeuristic(nsIChannel* aOldChannel,
nsIURI* aOldURI,

Просмотреть файл

@ -8,6 +8,7 @@
#define mozilla_antitrackingservice_h
#include "nsString.h"
#include "mozilla/ContentBlockingNotifier.h"
#include "mozilla/MozPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPrefs_privacy.h"
@ -73,11 +74,6 @@ class AntiTrackingCommon final {
static bool IsFirstPartyStorageAccessGrantedFor(
nsIPrincipal* aPrincipal, nsICookieJarSettings* aCookieJarSettings);
enum StorageAccessGrantedReason {
eStorageAccessAPI,
eOpenerAfterUserInteraction,
eOpener
};
enum StorageAccessPromptChoices { eAllow, eAllowAutoGrant };
// Grant the permission for aOrigin to have access to the first party storage.
@ -102,7 +98,7 @@ class AntiTrackingCommon final {
static MOZ_MUST_USE RefPtr<StorageAccessGrantPromise>
AddFirstPartyStorageAccessGrantedFor(
nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aParentWindow,
StorageAccessGrantedReason aReason,
ContentBlockingNotifier::StorageAccessGrantedReason aReason,
const PerformFinalChecks& aPerformFinalChecks = nullptr);
// Given a principal, returns the storage permission key that will be used for
@ -128,45 +124,10 @@ class AntiTrackingCommon final {
uint64_t aExpirationTime =
StaticPrefs::privacy_restrict3rdpartystorage_expiration());
enum class BlockingDecision {
eBlock,
eAllow,
};
// This method can be called on the parent process or on the content process.
// The notification is propagated to the child channel if aChannel is a parent
// channel proxy.
//
// aDecision can be eBlock if we have decided to block some content, or eAllow
// if we have decided to allow the content through.
//
// aRejectedReason must be one of these values:
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN
static void NotifyBlockingDecision(nsIChannel* aChannel,
BlockingDecision aDecision,
uint32_t aRejectedReason);
static void NotifyBlockingDecision(nsPIDOMWindowInner* aWindow,
BlockingDecision aDecision,
uint32_t aRejectedReason);
// Get the current document URI from a document channel as it is being loaded.
static already_AddRefed<nsIURI> MaybeGetDocumentURIBeingLoaded(
nsIChannel* aChannel);
static void NotifyContentBlockingEvent(nsIChannel* aChannel,
uint32_t aRejectedReason);
static void NotifyContentBlockingEvent(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<StorageAccessGrantedReason>& aReason = Nothing());
static void RedirectHeuristic(nsIChannel* aOldChannel, nsIURI* aOldURI,
nsIChannel* aNewChannel, nsIURI* aNewURI);
};

Просмотреть файл

@ -9,19 +9,20 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/AntiTrackingCommon.h"
#include "mozilla/ContentBlockingNotifier.h"
namespace IPC {
// For allowing passing the enum AntiTrackingCommon::StorageAccessGrantedReason
// over IPC.
// For allowing passing the enum
// ContentBlockingNotifier::StorageAccessGrantedReason over IPC.
template <>
struct ParamTraits<mozilla::AntiTrackingCommon::StorageAccessGrantedReason>
struct ParamTraits<mozilla::ContentBlockingNotifier::StorageAccessGrantedReason>
: public ContiguousEnumSerializerInclusive<
mozilla::AntiTrackingCommon::StorageAccessGrantedReason,
mozilla::AntiTrackingCommon::StorageAccessGrantedReason::
mozilla::ContentBlockingNotifier::StorageAccessGrantedReason,
mozilla::ContentBlockingNotifier::StorageAccessGrantedReason::
eStorageAccessAPI,
mozilla::AntiTrackingCommon::StorageAccessGrantedReason::eOpener> {};
mozilla::ContentBlockingNotifier::StorageAccessGrantedReason::
eOpener> {};
} // namespace IPC

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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/. */
#include "AntiTrackingUtils.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/Document.h"
#include "nsIChannel.h"
#include "nsPIDOMWindow.h"
using namespace mozilla;
using namespace mozilla::dom;
/* static */ already_AddRefed<nsPIDOMWindowOuter>
AntiTrackingUtils::GetTopWindow(nsPIDOMWindowInner* aWindow) {
Document* document = aWindow->GetExtantDoc();
if (!document) {
return nullptr;
}
nsIChannel* channel = document->GetChannel();
if (!channel) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowOuter> pwin =
aWindow->GetBrowsingContext()->Top()->GetDOMWindow();
if (!pwin) {
return nullptr;
}
return pwin.forget();
}

Просмотреть файл

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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_antitrackingutils_h
#define mozilla_antitrackingutils_h
#include "mozilla/AlreadyAddRefed.h"
class nsPIDOMWindowInner;
class nsPIDOMWindowOuter;
namespace mozilla {
class AntiTrackingUtils final {
public:
static already_AddRefed<nsPIDOMWindowOuter> GetTopWindow(
nsPIDOMWindowInner* aWindow);
};
} // namespace mozilla
#endif // mozilla_antitrackingutils_h

Просмотреть файл

@ -0,0 +1,531 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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/. */
#include "AntiTrackingLog.h"
#include "ContentBlockingNotifier.h"
#include "AntiTrackingCommon.h"
#include "AntiTrackingUtils.h"
#include "mozilla/AbstractEventQueue.h"
#include "mozilla/StaticPrefs_privacy.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "nsIClassifiedChannel.h"
#include "nsIRunnable.h"
#include "nsIScriptError.h"
#include "nsIURI.h"
#include "nsIURIFixup.h"
#include "nsGlobalWindowInner.h"
#include "nsJSUtils.h"
#include "mozIThirdPartyUtil.h"
using namespace mozilla;
using mozilla::dom::BrowsingContext;
using mozilla::dom::ContentChild;
using mozilla::dom::Document;
static const uint32_t kMaxConsoleOutputDelayMs = 100;
namespace {
void RunConsoleReportingRunnable(already_AddRefed<nsIRunnable>&& aRunnable) {
if (StaticPrefs::privacy_restrict3rdpartystorage_console_lazy()) {
nsresult rv = NS_DispatchToCurrentThreadQueue(std::move(aRunnable),
kMaxConsoleOutputDelayMs,
EventQueuePriority::Idle);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
} else {
nsCOMPtr<nsIRunnable> runnable(std::move(aRunnable));
nsresult rv = runnable->Run();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
}
void ReportBlockingToConsole(uint64_t aWindowID, nsIURI* aURI,
uint32_t aRejectedReason) {
MOZ_ASSERT(aWindowID);
MOZ_ASSERT(aURI);
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
nsAutoString sourceLine;
uint32_t lineNumber = 0, columnNumber = 0;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
nsJSUtils::GetCallingLocation(cx, sourceLine, &lineNumber, &columnNumber);
}
nsCOMPtr<nsIURI> uri(aURI);
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"ReportBlockingToConsoleDelayed", [aWindowID, sourceLine, lineNumber,
columnNumber, uri, aRejectedReason]() {
const char* message = nullptr;
nsAutoCString category;
// When changing this list, please make sure to update the corresponding
// code in antitracking_head.js (inside _createTask).
switch (aRejectedReason) {
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION:
message = "CookieBlockedByPermission";
category = NS_LITERAL_CSTRING("cookieBlockedPermission");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER:
message = "CookieBlockedTracker";
category = NS_LITERAL_CSTRING("cookieBlockedTracker");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL:
message = "CookieBlockedAll";
category = NS_LITERAL_CSTRING("cookieBlockedAll");
break;
case nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN:
message = "CookieBlockedForeign";
category = NS_LITERAL_CSTRING("cookieBlockedForeign");
break;
default:
return;
}
MOZ_ASSERT(message);
// Strip the URL of any possible username/password and make it ready
// to be presented in the UI.
nsCOMPtr<nsIURIFixup> urifixup = services::GetURIFixup();
NS_ENSURE_TRUE_VOID(urifixup);
nsCOMPtr<nsIURI> exposableURI;
nsresult rv =
urifixup->CreateExposableURI(uri, getter_AddRefs(exposableURI));
NS_ENSURE_SUCCESS_VOID(rv);
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(exposableURI->GetSpecOrDefault(),
*params.AppendElement());
nsAutoString errorText;
rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eNECKO_PROPERTIES, message, params, errorText);
NS_ENSURE_SUCCESS_VOID(rv);
nsContentUtils::ReportToConsoleByWindowID(
errorText, nsIScriptError::warningFlag, category, aWindowID,
nullptr, sourceLine, lineNumber, columnNumber);
});
RunConsoleReportingRunnable(runnable.forget());
}
void ReportBlockingToConsole(nsIChannel* aChannel, nsIURI* aURI,
uint32_t aRejectedReason) {
MOZ_ASSERT(aChannel && aURI);
uint64_t windowID;
if (XRE_IsParentProcess()) {
// Get the top-level window ID from the top-level BrowsingContext
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
RefPtr<dom::BrowsingContext> bc;
loadInfo->GetBrowsingContext(getter_AddRefs(bc));
if (!bc || bc->IsDiscarded()) {
return;
}
bc = bc->Top();
RefPtr<dom::WindowGlobalParent> wgp =
bc->Canonical()->GetCurrentWindowGlobal();
if (!wgp) {
return;
}
windowID = wgp->InnerWindowId();
} else {
nsresult rv;
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel, &rv);
if (!httpChannel) {
return;
}
rv = httpChannel->GetTopLevelContentWindowId(&windowID);
if (NS_FAILED(rv) || !windowID) {
windowID = nsContentUtils::GetInnerWindowID(httpChannel);
}
}
ReportBlockingToConsole(windowID, aURI, aRejectedReason);
}
// This API finishes the remaining work left in NotifyBlockingDecision.
void NotifyAllowDecision(nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, nsIURI* aURI,
nsPIDOMWindowOuter* aWindow) {
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
// This can be called in either the parent process or the child processes.
// Now send the generic "cookies loaded" notifications, from the most generic
// to the most specific.
ContentBlockingNotifier::OnEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED, trackingOrigin);
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (!classifiedChannel) {
return;
}
uint32_t classificationFlags =
classifiedChannel->GetThirdPartyClassificationFlags();
if (classificationFlags &
nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_TRACKING) {
ContentBlockingNotifier::OnEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED_TRACKER, trackingOrigin);
}
if (classificationFlags &
nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_SOCIALTRACKING) {
ContentBlockingNotifier::OnEvent(
aWindow, aReportingChannel, aTrackingChannel, false,
nsIWebProgressListener::STATE_COOKIES_LOADED_SOCIALTRACKER,
trackingOrigin);
}
}
void NotifyBlockingDecision(nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel,
ContentBlockingNotifier::BlockingDecision aDecision,
uint32_t aRejectedReason, nsIURI* aURI,
nsPIDOMWindowOuter* aWindow) {
MOZ_ASSERT(aWindow);
// When this is called with system priviledged, the decision should always be
// ALLOW, and we can also stop processing this event.
if (nsGlobalWindowOuter::Cast(aWindow)->GetPrincipal() ==
nsContentUtils::GetSystemPrincipal()) {
MOZ_DIAGNOSTIC_ASSERT(aDecision ==
ContentBlockingNotifier::BlockingDecision::eAllow);
return;
}
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
if (aDecision == ContentBlockingNotifier::BlockingDecision::eBlock) {
ContentBlockingNotifier::OnEvent(aWindow, aReportingChannel,
aTrackingChannel, true, aRejectedReason,
trackingOrigin);
ReportBlockingToConsole(aReportingChannel, aURI, aRejectedReason);
}
NotifyAllowDecision(aReportingChannel, aTrackingChannel, aURI, aWindow);
}
void NotifyBlockingDecision(nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel,
ContentBlockingNotifier::BlockingDecision aDecision,
uint32_t aRejectedReason, nsIURI* aURI) {
// Can be called only in the parent process when there is no window.
MOZ_ASSERT(XRE_IsParentProcess());
nsAutoCString trackingOrigin;
if (aURI) {
Unused << nsContentUtils::GetASCIIOrigin(aURI, trackingOrigin);
}
if (aDecision == ContentBlockingNotifier::BlockingDecision::eBlock) {
ContentBlockingNotifier::OnEvent(nullptr, aReportingChannel,
aTrackingChannel, true, aRejectedReason,
trackingOrigin);
ReportBlockingToConsole(aReportingChannel, aURI, aRejectedReason);
}
NotifyAllowDecision(aReportingChannel, aTrackingChannel, aURI, nullptr);
}
// Send a message to notify OnContentBlockingEvent in the parent, which will
// update the ContentBlockingLog in the parent.
void NotifyEventInChild(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason) {
MOZ_ASSERT(XRE_IsContentProcess());
MOZ_ASSERT(aWindow);
RefPtr<dom::BrowserChild> browserChild = dom::BrowserChild::GetFrom(aWindow);
NS_ENSURE_TRUE_VOID(browserChild);
nsTArray<nsCString> trackingFullHashes;
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (classifiedChannel) {
Unused << classifiedChannel->GetMatchedTrackingFullHashes(
trackingFullHashes);
}
browserChild->NotifyContentBlockingEvent(aRejectedReason, aReportingChannel,
aBlocked, aTrackingOrigin,
trackingFullHashes, aReason);
}
// Update the ContentBlockingLog of the top-level WindowGlobalParent of
// the reporting channel.
void NotifyEventInParent(
nsIChannel* aReportingChannel, nsIChannel* aTrackingChannel, bool aBlocked,
uint32_t aRejectedReason, const nsACString& aTrackingOrigin,
const Maybe<ContentBlockingNotifier::StorageAccessGrantedReason>& aReason) {
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsILoadInfo> loadInfo = aReportingChannel->LoadInfo();
RefPtr<dom::BrowsingContext> bc;
loadInfo->GetBrowsingContext(getter_AddRefs(bc));
if (!bc || bc->IsDiscarded()) {
return;
}
bc = bc->Top();
RefPtr<dom::WindowGlobalParent> wgp =
bc->Canonical()->GetCurrentWindowGlobal();
NS_ENSURE_TRUE_VOID(wgp);
nsTArray<nsCString> trackingFullHashes;
nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
do_QueryInterface(aTrackingChannel);
if (classifiedChannel) {
Unused << classifiedChannel->GetMatchedTrackingFullHashes(
trackingFullHashes);
}
wgp->NotifyContentBlockingEvent(aRejectedReason, aReportingChannel, aBlocked,
aTrackingOrigin, trackingFullHashes, aReason);
}
} // namespace
/* static */ void ContentBlockingNotifier::ReportUnblockingToConsole(
nsPIDOMWindowInner* aWindow, const nsAString& aTrackingOrigin,
ContentBlockingNotifier::StorageAccessGrantedReason aReason) {
nsCOMPtr<nsIPrincipal> principal =
nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
if (NS_WARN_IF(!principal)) {
return;
}
RefPtr<Document> doc = aWindow->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
return;
}
nsAutoString trackingOrigin(aTrackingOrigin);
nsAutoString sourceLine;
uint32_t lineNumber = 0, columnNumber = 0;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
nsJSUtils::GetCallingLocation(cx, sourceLine, &lineNumber, &columnNumber);
}
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"ReportUnblockingToConsoleDelayed",
[doc, principal, trackingOrigin, sourceLine, lineNumber, columnNumber,
aReason]() {
nsAutoString origin;
nsresult rv = nsContentUtils::GetUTFOrigin(principal, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Not adding grantedOrigin yet because we may not want it later.
AutoTArray<nsString, 3> params = {origin, trackingOrigin};
const char* messageWithSameOrigin = nullptr;
switch (aReason) {
case ContentBlockingNotifier::eStorageAccessAPI:
messageWithSameOrigin = "CookieAllowedForTrackerByStorageAccessAPI";
break;
case ContentBlockingNotifier::eOpenerAfterUserInteraction:
[[fallthrough]];
case ContentBlockingNotifier::eOpener:
messageWithSameOrigin = "CookieAllowedForTrackerByHeuristic";
break;
}
nsContentUtils::ReportToConsole(
nsIScriptError::warningFlag, ANTITRACKING_CONSOLE_CATEGORY, doc,
nsContentUtils::eNECKO_PROPERTIES, messageWithSameOrigin, params,
nullptr, sourceLine, lineNumber, columnNumber);
});
RunConsoleReportingRunnable(runnable.forget());
}
/* static */
void ContentBlockingNotifier::OnDecision(nsIChannel* aChannel,
BlockingDecision aDecision,
uint32_t aRejectedReason) {
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
if (!aChannel) {
return;
}
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
// Can be called in EITHER the parent or child process.
// Window is only needed while in child processes.
if (XRE_IsParentProcess()) {
NotifyBlockingDecision(aChannel, aChannel, aDecision, aRejectedReason, uri);
return;
}
MOZ_ASSERT(XRE_IsContentProcess());
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
if (!thirdPartyUtil) {
return;
}
nsCOMPtr<nsIURI> uriBeingLoaded =
AntiTrackingCommon::MaybeGetDocumentURIBeingLoaded(aChannel);
nsCOMPtr<mozIDOMWindowProxy> win;
nsresult rv = thirdPartyUtil->GetTopWindowForChannel(aChannel, uriBeingLoaded,
getter_AddRefs(win));
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(win);
if (!pwin) {
return;
}
NotifyBlockingDecision(aChannel, aChannel, aDecision, aRejectedReason, uri,
pwin);
}
/* static */
void ContentBlockingNotifier::OnDecision(nsPIDOMWindowInner* aWindow,
BlockingDecision aDecision,
uint32_t aRejectedReason) {
MOZ_ASSERT(aWindow);
MOZ_ASSERT(
aRejectedReason == 0 ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER ||
aRejectedReason ==
nsIWebProgressListener::STATE_COOKIES_PARTITIONED_FOREIGN ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL ||
aRejectedReason == nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN);
MOZ_ASSERT(aDecision == BlockingDecision::eBlock ||
aDecision == BlockingDecision::eAllow);
nsCOMPtr<nsPIDOMWindowOuter> pwin = AntiTrackingUtils::GetTopWindow(aWindow);
if (!pwin) {
return;
}
nsPIDOMWindowInner* inner = pwin->GetCurrentInnerWindow();
if (!inner) {
return;
}
Document* pwinDoc = inner->GetExtantDoc();
if (!pwinDoc) {
return;
}
nsIChannel* channel = pwinDoc->GetChannel();
if (!channel) {
return;
}
Document* document = aWindow->GetExtantDoc();
if (!document) {
return;
}
nsIURI* uri = document->GetDocumentURI();
nsIChannel* trackingChannel = document->GetChannel();
NotifyBlockingDecision(channel, trackingChannel, aDecision, aRejectedReason,
uri, pwin);
}
/* static */
void ContentBlockingNotifier::OnEvent(nsIChannel* aChannel,
uint32_t aRejectedReason) {
MOZ_ASSERT(XRE_IsParentProcess() && aChannel);
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
nsAutoCString trackingOrigin;
if (uri) {
Unused << nsContentUtils::GetASCIIOrigin(uri, trackingOrigin);
}
return ContentBlockingNotifier::OnEvent(nullptr, aChannel, aChannel, true,
aRejectedReason, trackingOrigin);
}
/* static */
void ContentBlockingNotifier::OnEvent(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<StorageAccessGrantedReason>& aReason) {
if (XRE_IsParentProcess()) {
NotifyEventInParent(aReportingChannel, aTrackingChannel, aBlocked,
aRejectedReason, aTrackingOrigin, aReason);
} else {
NotifyEventInChild(aWindow, aReportingChannel, aTrackingChannel, aBlocked,
aRejectedReason, aTrackingOrigin, aReason);
}
}

Просмотреть файл

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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_contentblockingnotifier_h
#define mozilla_contentblockingnotifier_h
#include "nsStringFwd.h"
#include "mozilla/Maybe.h"
#define ANTITRACKING_CONSOLE_CATEGORY NS_LITERAL_CSTRING("Content Blocking")
class nsIChannel;
class nsPIDOMWindowInner;
class nsPIDOMWindowOuter;
namespace mozilla {
class ContentBlockingNotifier final {
public:
enum class BlockingDecision {
eBlock,
eAllow,
};
enum StorageAccessGrantedReason {
eStorageAccessAPI,
eOpenerAfterUserInteraction,
eOpener
};
// This method can be called on the parent process or on the content process.
// The notification is propagated to the child channel if aChannel is a parent
// channel proxy.
//
// aDecision can be eBlock if we have decided to block some content, or eAllow
// if we have decided to allow the content through.
//
// aRejectedReason must be one of these values:
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_SOCIALTRACKER
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_ALL
// * nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN
static void OnDecision(nsIChannel* aChannel, BlockingDecision aDecision,
uint32_t aRejectedReason);
static void OnDecision(nsPIDOMWindowInner* aWindow,
BlockingDecision aDecision, uint32_t aRejectedReason);
static void OnEvent(nsIChannel* aChannel, uint32_t aRejectedReason);
static void OnEvent(
nsPIDOMWindowOuter* aWindow, nsIChannel* aReportingChannel,
nsIChannel* aTrackingChannel, bool aBlocked, uint32_t aRejectedReason,
const nsACString& aTrackingOrigin,
const Maybe<StorageAccessGrantedReason>& aReason = Nothing());
static void ReportUnblockingToConsole(nsPIDOMWindowInner* aWindow,
const nsAString& aTrackingOrigin,
StorageAccessGrantedReason aReason);
};
} // namespace mozilla
#endif // mozilla_contentblockingnotifier_h

Просмотреть файл

@ -300,16 +300,16 @@ bool StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
bool disabled = StorageDisabledByAntiTrackingInternal(
aWindow, aChannel, aPrincipal, aURI, cookieJarSettings, aRejectedReason);
if (aWindow) {
AntiTrackingCommon::NotifyBlockingDecision(
ContentBlockingNotifier::OnDecision(
aWindow,
disabled ? AntiTrackingCommon::BlockingDecision::eBlock
: AntiTrackingCommon::BlockingDecision::eAllow,
disabled ? ContentBlockingNotifier::BlockingDecision::eBlock
: ContentBlockingNotifier::BlockingDecision::eAllow,
aRejectedReason);
} else if (aChannel) {
AntiTrackingCommon::NotifyBlockingDecision(
ContentBlockingNotifier::OnDecision(
aChannel,
disabled ? AntiTrackingCommon::BlockingDecision::eBlock
: AntiTrackingCommon::BlockingDecision::eAllow,
disabled ? ContentBlockingNotifier::BlockingDecision::eBlock
: ContentBlockingNotifier::BlockingDecision::eAllow,
aRejectedReason);
}
return disabled;

Просмотреть файл

@ -34,6 +34,7 @@ EXPORTS.mozilla = [
'AntiTrackingCommon.h',
'AntiTrackingIPCUtils.h',
'ContentBlockingAllowList.h',
'ContentBlockingNotifier.h',
'StorageAccess.h',
'StoragePrincipalHelper.h',
'URLDecorationStripper.h',
@ -41,7 +42,9 @@ EXPORTS.mozilla = [
UNIFIED_SOURCES += [
'AntiTrackingCommon.cpp',
'AntiTrackingUtils.cpp',
'ContentBlockingAllowList.cpp',
'ContentBlockingNotifier.cpp',
'SettingsChangeObserver.cpp',
'StorageAccess.cpp',
'StoragePrincipalHelper.cpp',