Bug 1837168 - Update user activation check to be after the permission check - r=timhuang,anti-tracking-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D186981
This commit is contained in:
Benjamin VanderSloot 2023-09-19 21:03:06 +00:00
Родитель 7e8b84dd5a
Коммит 5005011998
4 изменённых файлов: 37 добавлений и 41 удалений

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

@ -17269,16 +17269,16 @@ Document::GetContentBlockingEvents() {
StorageAccessAPIHelper::PerformPermissionGrant
Document::CreatePermissionGrantPromise(
nsPIDOMWindowInner* aInnerWindow, nsIPrincipal* aPrincipal,
bool aHasUserInteraction, const Maybe<nsCString>& aTopLevelBaseDomain,
bool aFrameOnly) {
bool aHasUserInteraction, bool aRequireUserInteraction,
const Maybe<nsCString>& aTopLevelBaseDomain, bool aFrameOnly) {
MOZ_ASSERT(aInnerWindow);
MOZ_ASSERT(aPrincipal);
RefPtr<Document> self(this);
RefPtr<nsPIDOMWindowInner> inner(aInnerWindow);
RefPtr<nsIPrincipal> principal(aPrincipal);
return [inner, self, principal, aHasUserInteraction, aTopLevelBaseDomain,
aFrameOnly]() {
return [inner, self, principal, aHasUserInteraction, aRequireUserInteraction,
aTopLevelBaseDomain, aFrameOnly]() {
RefPtr<StorageAccessAPIHelper::StorageAccessPermissionGrantPromise::Private>
p = new StorageAccessAPIHelper::StorageAccessPermissionGrantPromise::
Private(__func__);
@ -17294,13 +17294,31 @@ Document::CreatePermissionGrantPromise(
MOZ_ASSERT(promise);
promise->Then(
GetCurrentSerialEventTarget(), __func__,
[self, p, inner, principal, aHasUserInteraction, aTopLevelBaseDomain,
[self, p, inner, principal, aHasUserInteraction,
aRequireUserInteraction, aTopLevelBaseDomain,
aFrameOnly](bool aGranted) {
if (aGranted) {
p->Resolve(true, __func__);
return;
}
// We require user activation before conducting a permission request
// See
// https://privacycg.github.io/storage-access/#dom-document-requeststorageaccess
// where we "If has transient activation is false: ..." immediately
// before we "Let permissionState be the result of requesting
// permission to use "storage-access"" from in parallel.
if (!aHasUserInteraction && aRequireUserInteraction) {
// Report an error to the console for this case
nsContentUtils::ReportToConsole(
nsIScriptError::errorFlag,
nsLiteralCString("requestStorageAccess"), self,
nsContentUtils::eDOM_PROPERTIES,
"RequestStorageAccessUserGesture");
p->Reject(false, __func__);
return;
}
// Create the user prompt
RefPtr<StorageAccessPermissionRequest> sapr =
StorageAccessPermissionRequest::Create(
@ -17414,20 +17432,6 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccess(
return nullptr;
}
// Step 0: Check that we have user activation before proceeding to prevent
// rapid calls to the API to leak information.
if (!HasValidTransientUserGestureActivation()) {
// Report an error to the console for this case
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
nsLiteralCString("requestStorageAccess"),
this, nsContentUtils::eDOM_PROPERTIES,
"RequestStorageAccessUserGesture");
ConsumeTransientUserGestureActivation();
promise->MaybeRejectWithNotAllowedError(
"requestStorageAccess not allowed"_ns);
return promise.forget();
}
// Get a pointer to the inner window- We need this for convenience sake
RefPtr<nsPIDOMWindowInner> inner = GetInnerWindow();
if (!inner) {
@ -17536,7 +17540,8 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccess(
// on work changing state to reflect the result of the API. If it resolves,
// the request was granted. If it rejects it was denied.
StorageAccessAPIHelper::RequestStorageAccessAsyncHelper(
this, inner, bc, NodePrincipal(), true, true,
this, inner, bc, NodePrincipal(),
self->HasValidTransientUserGestureActivation(), true, true,
ContentBlockingNotifier::eStorageAccessAPI, true)
->Then(
GetCurrentSerialEventTarget(), __func__,
@ -17665,8 +17670,8 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccessForOrigin(
GetBrowsingContext(), principal)
->Then(
GetCurrentSerialEventTarget(), __func__,
[inner, thirdPartyURI, bc, principal, hasUserActivation, self,
promise](Maybe<bool> cookieResult) {
[inner, thirdPartyURI, bc, principal, hasUserActivation,
aRequireUserActivation, self, promise](Maybe<bool> cookieResult) {
// Handle the result of the cookie permission check that took place
// in the ContentParent.
if (cookieResult.isSome()) {
@ -17697,7 +17702,8 @@ already_AddRefed<mozilla::dom::Promise> Document::RequestStorageAccessForOrigin(
// with a user-prompt. This is the part that is async in the
// typical requestStorageAccess function.
return StorageAccessAPIHelper::RequestStorageAccessAsyncHelper(
self, inner, bc, principal, hasUserActivation, false,
self, inner, bc, principal, hasUserActivation,
aRequireUserActivation, false,
ContentBlockingNotifier::ePrivilegeStorageAccessForOriginAPI,
true);
},
@ -17857,7 +17863,7 @@ already_AddRefed<Promise> Document::RequestStorageAccessUnderSite(
false, __func__);
}
return self->CreatePermissionGrantPromise(
self->GetInnerWindow(), self->NodePrincipal(), true,
self->GetInnerWindow(), self->NodePrincipal(), true, true,
Some(serializedSite), false)();
},
[](const ContentChild::TestStorageAccessPermissionPromise::
@ -18030,7 +18036,7 @@ already_AddRefed<Promise> Document::CompleteStorageAccessRequestFromSite(
// either by prompt doorhanger or autogrant takes place. We already
// gathered an equivalent grant in requestStorageAccessUnderSite.
return StorageAccessAPIHelper::RequestStorageAccessAsyncHelper(
self, inner, bc, principal, true, false,
self, inner, bc, principal, true, true, false,
ContentBlockingNotifier::eStorageAccessAPI, false);
},
// If the IPC rejects, we should reject our promise here which will

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

@ -1267,8 +1267,8 @@ class Document : public nsINode,
StorageAccessAPIHelper::PerformPermissionGrant CreatePermissionGrantPromise(
nsPIDOMWindowInner* aInnerWindow, nsIPrincipal* aPrincipal,
bool aHasUserInteraction, const Maybe<nsCString>& aTopLevelBaseDomain,
bool aFrameOnly);
bool aHasUserInteraction, bool aRequireUserInteraction,
const Maybe<nsCString>& aTopLevelBaseDomain, bool aFrameOnly);
already_AddRefed<Promise> RequestStorageAccess(ErrorResult& aRv);

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

@ -840,17 +840,6 @@ Maybe<bool> StorageAccessAPIHelper::CheckBrowserSettingsDecidesStorageAccessAPI(
Maybe<bool> StorageAccessAPIHelper::CheckCallingContextDecidesStorageAccessAPI(
Document* aDocument, bool aRequestingStorageAccess) {
MOZ_ASSERT(aDocument);
// Window doesn't have user activation and we are asking for access -> reject.
if (aRequestingStorageAccess) {
if (!aDocument->HasValidTransientUserGestureActivation()) {
// Report an error to the console for this case
nsContentUtils::ReportToConsole(
nsIScriptError::errorFlag, nsLiteralCString("requestStorageAccess"),
aDocument, nsContentUtils::eDOM_PROPERTIES,
"RequestStorageAccessUserGesture");
return Some(false);
}
}
if (aDocument->IsTopLevelContentDocument()) {
return Some(true);
@ -1006,7 +995,7 @@ RefPtr<StorageAccessAPIHelper::StorageAccessPermissionGrantPromise>
StorageAccessAPIHelper::RequestStorageAccessAsyncHelper(
dom::Document* aDocument, nsPIDOMWindowInner* aInnerWindow,
dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal,
bool aHasUserInteraction, bool aFrameOnly,
bool aHasUserInteraction, bool aRequireUserInteraction, bool aFrameOnly,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier,
bool aRequireGrant) {
MOZ_ASSERT(aDocument);
@ -1022,7 +1011,8 @@ StorageAccessAPIHelper::RequestStorageAccessAsyncHelper(
// This is a lambda function that has some variables bound to it. It will be
// called later in CompleteAllowAccessFor inside of AllowAccessFor.
auto performPermissionGrant = aDocument->CreatePermissionGrantPromise(
aInnerWindow, principal, aHasUserInteraction, Nothing(), aFrameOnly);
aInnerWindow, principal, aHasUserInteraction, aRequireUserInteraction,
Nothing(), aFrameOnly);
// Try to allow access for the given principal.
return StorageAccessAPIHelper::AllowAccessFor(

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

@ -166,7 +166,7 @@ class StorageAccessAPIHelper final {
RequestStorageAccessAsyncHelper(
dom::Document* aDocument, nsPIDOMWindowInner* aInnerWindow,
dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal,
bool aHasUserInteraction, bool aFrameOnly,
bool aHasUserInteraction, bool aRequireUserInteraction, bool aFrameOnly,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier,
bool aRequireGrant);