mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1902319 - Separate BTP user interaction tracking from ContentBlockingUserInteraction and record user interaction for iframes. r=anti-tracking-reviewers,manuel
Differential Revision: https://phabricator.services.mozilla.com/D214622
This commit is contained in:
parent
98e9f35370
commit
2111e5b5ff
@ -46,6 +46,7 @@
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/BounceTrackingProtection.h"
|
||||
#include "mozilla/CSSEnabledState.h"
|
||||
#include "mozilla/ContentBlockingAllowList.h"
|
||||
#include "mozilla/ContentBlockingNotifier.h"
|
||||
@ -17127,6 +17128,17 @@ class UserInteractionTimer final : public Runnable,
|
||||
// the document could be already gone.
|
||||
mBlockerName.AppendPrintf("UserInteractionTimer %d for document %p",
|
||||
++userInteractionTimerId, aDocument);
|
||||
|
||||
// For ContentBlockingUserInteraction we care about user-interaction stored
|
||||
// only for top-level documents and documents with access to the Storage
|
||||
// Access API
|
||||
if (aDocument->IsTopLevelContentDocument()) {
|
||||
mShouldRecordContentBlockingUserInteraction = true;
|
||||
} else {
|
||||
bool hasSA;
|
||||
nsresult rv = aDocument->HasStorageAccessSync(hasSA);
|
||||
mShouldRecordContentBlockingUserInteraction = NS_SUCCEEDED(rv) && hasSA;
|
||||
}
|
||||
}
|
||||
|
||||
// Runnable interface
|
||||
@ -17200,7 +17212,11 @@ class UserInteractionTimer final : public Runnable,
|
||||
// If the document is not gone, let's reset its timer flag.
|
||||
nsCOMPtr<Document> document(mDocument);
|
||||
if (document) {
|
||||
ContentBlockingUserInteraction::Observe(mPrincipal);
|
||||
if (mShouldRecordContentBlockingUserInteraction) {
|
||||
ContentBlockingUserInteraction::Observe(mPrincipal);
|
||||
}
|
||||
Unused << BounceTrackingProtection::RecordUserActivation(
|
||||
mDocument->GetWindowContext());
|
||||
document->ResetUserInteractionTimer();
|
||||
}
|
||||
}
|
||||
@ -17227,6 +17243,7 @@ class UserInteractionTimer final : public Runnable,
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
WeakPtr<Document> mDocument;
|
||||
bool mShouldRecordContentBlockingUserInteraction = false;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
@ -17239,18 +17256,21 @@ NS_IMPL_ISUPPORTS_INHERITED(UserInteractionTimer, Runnable, nsITimerCallback,
|
||||
} // namespace
|
||||
|
||||
void Document::MaybeStoreUserInteractionAsPermission() {
|
||||
// We care about user-interaction stored only for top-level documents
|
||||
// and documents with access to the Storage Access API
|
||||
if (!IsTopLevelContentDocument()) {
|
||||
bool hasSA;
|
||||
nsresult rv = HasStorageAccessSync(hasSA);
|
||||
if (NS_FAILED(rv) || !hasSA) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mUserHasInteracted) {
|
||||
// First interaction, let's store this info now.
|
||||
Unused << BounceTrackingProtection::RecordUserActivation(
|
||||
GetWindowContext());
|
||||
|
||||
// For ContentBlockingUserInteraction we care about user-interaction stored
|
||||
// only for top-level documents and documents with access to the Storage
|
||||
// Access API
|
||||
if (!IsTopLevelContentDocument()) {
|
||||
bool hasSA;
|
||||
nsresult rv = HasStorageAccessSync(hasSA);
|
||||
if (NS_FAILED(rv) || !hasSA) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ContentBlockingUserInteraction::Observe(NodePrincipal());
|
||||
return;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "WebAuthnTransportIdentifiers.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/BounceTrackingProtection.h"
|
||||
#include "mozilla/glean/GleanMetrics.h"
|
||||
#include "mozilla/dom/AuthenticatorAssertionResponse.h"
|
||||
#include "mozilla/dom/AuthenticatorAttestationResponse.h"
|
||||
@ -23,7 +24,6 @@
|
||||
#include "mozilla/dom/WebAuthnManager.h"
|
||||
#include "mozilla/dom/WebAuthnTransactionChild.h"
|
||||
#include "mozilla/dom/WebAuthnUtil.h"
|
||||
#include "mozilla/dom/WindowGlobalChild.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/JSONStringWriteFuncs.h"
|
||||
@ -844,8 +844,8 @@ void WebAuthnManager::FinishGetAssertion(
|
||||
if (global) {
|
||||
nsPIDOMWindowInner* window = global->GetAsInnerWindow();
|
||||
if (window) {
|
||||
WindowGlobalChild* windowGlobalChild = window->GetWindowGlobalChild();
|
||||
windowGlobalChild->SendRecordUserActivationForBTP();
|
||||
Unused << BounceTrackingProtection::RecordUserActivation(
|
||||
window->GetWindowContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,6 @@ void ContentBlockingUserInteraction::Observe(nsIPrincipal* aPrincipal) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
LOG_PRIN(("Saving the userInteraction for %s", _spec), aPrincipal);
|
||||
|
||||
// The bounce tracking protection has its own interaction store.
|
||||
nsresult rv = BounceTrackingProtection::RecordUserActivation(aPrincipal);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("BounceTrackingProtection::RecordUserActivation failed."));
|
||||
}
|
||||
|
||||
PermissionManager* permManager = PermissionManager::GetInstance();
|
||||
if (NS_WARN_IF(!permManager)) {
|
||||
LOG(("Permission manager is null, bailing out early"));
|
||||
@ -46,7 +40,7 @@ void ContentBlockingUserInteraction::Observe(nsIPrincipal* aPrincipal) {
|
||||
int64_t when = (PR_Now() / PR_USEC_PER_MSEC) + expirationTime;
|
||||
|
||||
uint32_t privateBrowsingId = 0;
|
||||
rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
|
||||
nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
|
||||
if (!NS_WARN_IF(NS_FAILED(rv)) && privateBrowsingId > 0) {
|
||||
// If we are coming from a private window, make sure to store a
|
||||
// session-only permission which won't get persisted to disk.
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "AntiTrackingUtils.h"
|
||||
#include "TemporaryAccessGrantObserver.h"
|
||||
|
||||
#include "mozilla/BounceTrackingProtection.h"
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/ContentBlockingAllowList.h"
|
||||
#include "mozilla/ContentBlockingUserInteraction.h"
|
||||
@ -501,11 +502,14 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
||||
LOG(("Saving the permission: trackingOrigin=%s", trackingOrigin.get()));
|
||||
bool frameOnly = StaticPrefs::dom_storage_access_frame_only() &&
|
||||
aReason == ContentBlockingNotifier::eStorageAccessAPI;
|
||||
|
||||
uint64_t innerWindowId = aParentContext->GetCurrentInnerWindowId();
|
||||
|
||||
return SaveAccessForOriginOnParentProcess(aTopLevelWindowId, aParentContext,
|
||||
trackingPrincipal, aAllowMode,
|
||||
frameOnly)
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aReason, trackingPrincipal](
|
||||
[aReason, trackingPrincipal, innerWindowId](
|
||||
ParentAccessGrantPromise::ResolveOrRejectValue&& aValue) {
|
||||
if (!aValue.IsResolve()) {
|
||||
return StorageAccessPermissionGrantPromise::CreateAndReject(
|
||||
@ -518,6 +522,12 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnParentProcess(
|
||||
// occur through the clicking accept on the doorhanger.
|
||||
if (aReason == ContentBlockingNotifier::eStorageAccessAPI) {
|
||||
ContentBlockingUserInteraction::Observe(trackingPrincipal);
|
||||
RefPtr<dom::WindowContext> windowContext =
|
||||
dom::WindowContext::GetById(innerWindowId);
|
||||
if (windowContext) {
|
||||
Unused << BounceTrackingProtection::RecordUserActivation(
|
||||
windowContext);
|
||||
}
|
||||
}
|
||||
return StorageAccessPermissionGrantPromise::CreateAndResolve(
|
||||
StorageAccessAPIHelper::eAllow, __func__);
|
||||
@ -637,20 +647,29 @@ StorageAccessAPIHelper::CompleteAllowAccessForOnChildProcess(
|
||||
// sending the request of storing a permission.
|
||||
bool frameOnly = StaticPrefs::dom_storage_access_frame_only() &&
|
||||
aReason == ContentBlockingNotifier::eStorageAccessAPI;
|
||||
|
||||
uint64_t innerWindowId = aParentContext->GetCurrentInnerWindowId();
|
||||
|
||||
return cc
|
||||
->SendStorageAccessPermissionGrantedForOrigin(
|
||||
aTopLevelWindowId, aParentContext, trackingPrincipal,
|
||||
trackingOrigin, aAllowMode, reportReason, frameOnly)
|
||||
->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[aReason, trackingPrincipal](
|
||||
const ContentChild::
|
||||
StorageAccessPermissionGrantedForOriginPromise::
|
||||
ResolveOrRejectValue& aValue) {
|
||||
[aReason, trackingPrincipal,
|
||||
innerWindowId](const ContentChild::
|
||||
StorageAccessPermissionGrantedForOriginPromise::
|
||||
ResolveOrRejectValue& aValue) {
|
||||
if (aValue.IsResolve()) {
|
||||
if (aValue.ResolveValue() &&
|
||||
(aReason == ContentBlockingNotifier::eStorageAccessAPI)) {
|
||||
ContentBlockingUserInteraction::Observe(trackingPrincipal);
|
||||
RefPtr<dom::WindowContext> windowContext =
|
||||
dom::WindowContext::GetById(innerWindowId);
|
||||
if (windowContext) {
|
||||
Unused << BounceTrackingProtection::RecordUserActivation(
|
||||
windowContext);
|
||||
}
|
||||
}
|
||||
return StorageAccessPermissionGrantPromise::CreateAndResolve(
|
||||
aValue.ResolveValue(), __func__);
|
||||
|
@ -35,6 +35,9 @@
|
||||
#include "mozilla/glean/GleanMetrics.h"
|
||||
#include "mozilla/ContentBlockingLog.h"
|
||||
#include "mozilla/glean/GleanPings.h"
|
||||
#include "mozilla/dom/WindowContext.h"
|
||||
#include "mozilla/dom/WindowGlobalChild.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
|
||||
#define TEST_OBSERVER_MSG_RECORD_BOUNCES_FINISHED "test-record-bounces-finished"
|
||||
|
||||
@ -319,6 +322,26 @@ nsresult BounceTrackingProtection::RecordUserActivation(
|
||||
aActivationTime.valueOr(PR_Now()));
|
||||
}
|
||||
|
||||
nsresult BounceTrackingProtection::RecordUserActivation(
|
||||
dom::WindowContext* aWindowContext) {
|
||||
NS_ENSURE_ARG_POINTER(aWindowContext);
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
dom::WindowGlobalChild* wgc = aWindowContext->GetWindowGlobalChild();
|
||||
NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(wgc->SendRecordUserActivationForBTP(), NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
dom::WindowGlobalParent* wgp = aWindowContext->Canonical();
|
||||
MOZ_ASSERT(wgp);
|
||||
|
||||
NS_ENSURE_TRUE(wgp->RecvRecordUserActivationForBTP(), NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BounceTrackingProtection::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
|
@ -22,6 +22,10 @@ class BounceTrackingProtectionStorage;
|
||||
class ClearDataCallback;
|
||||
class OriginAttributes;
|
||||
|
||||
namespace dom {
|
||||
class WindowContext;
|
||||
}
|
||||
|
||||
using ClearDataMozPromise = MozPromise<nsCString, uint32_t, true>;
|
||||
|
||||
extern LazyLogModule gBounceTrackingProtectionLog;
|
||||
@ -46,9 +50,18 @@ class BounceTrackingProtection final : public nsIObserver,
|
||||
// Stores a user activation flag with a timestamp for the given principal. The
|
||||
// timestamp defaults to the current time, but can be overridden via
|
||||
// aActivationTime.
|
||||
// Parent process only. Prefer the WindowContext variant if possible.
|
||||
[[nodiscard]] static nsresult RecordUserActivation(
|
||||
nsIPrincipal* aPrincipal, Maybe<PRTime> aActivationTime = Nothing());
|
||||
|
||||
// Same as above but can be called from any process given a WindowContext.
|
||||
// Gecko callers should prefer this method because it takes care of IPC and
|
||||
// gets the principal user activation. IPC messages from the content to parent
|
||||
// passing a principal should be avoided for security reasons. aActivationTime
|
||||
// defaults to PR_Now().
|
||||
[[nodiscard]] static nsresult RecordUserActivation(
|
||||
dom::WindowContext* aWindowContext);
|
||||
|
||||
// Clears expired user interaction flags for the given state global. If
|
||||
// aStateGlobal == nullptr, clears expired user interaction flags for all
|
||||
// state globals.
|
||||
|
Loading…
Reference in New Issue
Block a user