From 39c14444b712c244f5f6ab52c5027f36fdd2d16e Mon Sep 17 00:00:00 2001 From: Cosmin Sabou Date: Wed, 20 Sep 2023 04:41:18 +0300 Subject: [PATCH] Backed out 9 changesets (bug 1837168, bug 1835920, bug 1848783) for causing storage-access-api wpt failures. CLOSED TREE Backed out changeset 3fd66f8f5d65 (bug 1848783) Backed out changeset a96afb6d05d6 (bug 1848783) Backed out changeset 117132b000ac (bug 1848783) Backed out changeset 3a14281b7d72 (bug 1848783) Backed out changeset 7dc5f794364d (bug 1848783) Backed out changeset 84ca25a557a6 (bug 1848783) Backed out changeset 8bb89cf9587e (bug 1848783) Backed out changeset 15a005bef445 (bug 1837168) Backed out changeset a97bc1fd6637 (bug 1835920) --- docshell/base/WindowContext.cpp | 6 -- docshell/base/WindowContext.h | 5 -- dom/base/Document.cpp | 72 ++++++++------------ dom/base/Document.h | 4 +- dom/base/nsGlobalWindowInner.cpp | 28 ++------ dom/base/nsGlobalWindowInner.h | 4 +- dom/base/nsPIDOMWindow.h | 5 +- dom/ipc/ContentParent.cpp | 15 ----- dom/ipc/ContentParent.h | 7 -- dom/ipc/PWindowGlobal.ipdl | 2 +- dom/ipc/WindowGlobalActor.cpp | 2 - dom/ipc/WindowGlobalChild.cpp | 13 +--- dom/ipc/WindowGlobalChild.h | 3 +- extensions/permissions/PermissionManager.cpp | 13 ++-- remote/marionette/driver.sys.mjs | 8 +-- remote/marionette/permissions.sys.mjs | 69 +++----------------- .../meta/storage-access-api/__dir__.ini | 1 - ...ageAccess-ABA.tentative.sub.https.window.js.ini | 2 + .../hasStorageAccess-insecure.sub.window.js.ini | 31 +++++++++ .../hasStorageAccess.sub.https.window.js.ini | 24 +++++++ .../storage-access-api/idlharness.window.js.ini | 3 + ...ageAccess-ABA.tentative.sub.https.window.js.ini | 15 +++++ ...rigin-iframe-navigation.sub.https.window.js.ini | 12 +++- ...ccess-cross-site-iframe.sub.https.window.js.ini | 16 +++++ ...ss-site-sibling-iframes.sub.https.window.js.ini | 6 +- ...requestStorageAccess-insecure.sub.window.js.ini | 10 +++ ...ted-cross-origin-iframe.sub.https.window.js.ini | 23 +++---- ...ested-cross-site-iframe.sub.https.window.js.ini | 16 +++++ ...sted-same-origin-iframe.sub.https.window.js.ini | 32 +++++---- ...Access-non-fully-active.sub.https.window.js.ini | 7 ++ ...Access-same-site-iframe.sub.https.window.js.ini | 15 +++++ .../requestStorageAccess.sub.https.window.js.ini | 18 +++++ ...orage-access-permission.sub.https.window.js.ini | 10 +++ .../storageAccess.testdriver.sub.html.ini | 11 ++++ .../components/antitracking/AntiTrackingUtils.cpp | 26 ++++---- .../antitracking/StorageAccessAPIHelper.cpp | 76 ++++++++++++++-------- .../antitracking/StorageAccessAPIHelper.h | 2 +- .../test/browser/browser_permissionPropagation.js | 21 +++--- 38 files changed, 358 insertions(+), 275 deletions(-) delete mode 100644 testing/web-platform/meta/storage-access-api/__dir__.ini create mode 100644 testing/web-platform/meta/storage-access-api/hasStorageAccess-insecure.sub.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/hasStorageAccess.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/idlharness.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-iframe.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-insecure.sub.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-site-iframe.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-non-fully-active.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/requestStorageAccess.sub.https.window.js.ini create mode 100644 testing/web-platform/meta/storage-access-api/storage-access-permission.sub.https.window.js.ini diff --git a/docshell/base/WindowContext.cpp b/docshell/base/WindowContext.cpp index a1299ec87045..c773a561d442 100644 --- a/docshell/base/WindowContext.cpp +++ b/docshell/base/WindowContext.cpp @@ -228,12 +228,6 @@ bool WindowContext::CanSet(FieldIndex, return CheckOnlyOwningProcessCanSet(aSource); } -bool WindowContext::CanSet(FieldIndex, - const bool& aUsingStorageAccess, - ContentParent* aSource) { - return CheckOnlyOwningProcessCanSet(aSource); -} - bool WindowContext::CanSet(FieldIndex, const bool& aShouldResistFingerprinting, ContentParent* aSource) { diff --git a/docshell/base/WindowContext.h b/docshell/base/WindowContext.h index c38187679b7d..9396ad9ed107 100644 --- a/docshell/base/WindowContext.h +++ b/docshell/base/WindowContext.h @@ -51,9 +51,6 @@ class BrowsingContextGroup; /* Whether this window's channel has been marked as a third-party \ * tracking resource */ \ FIELD(IsThirdPartyTrackingResourceWindow, bool) \ - /* Whether this window is using its unpartitioned cookies due to \ - * the Storage Access API */ \ - FIELD(UsingStorageAccess, bool) \ FIELD(ShouldResistFingerprinting, bool) \ FIELD(IsSecureContext, bool) \ FIELD(IsOriginalFrameSource, bool) \ @@ -269,8 +266,6 @@ class WindowContext : public nsISupports, public nsWrapperCache { bool CanSet(FieldIndex, const bool& aIsThirdPartyTrackingResourceWindow, ContentParent* aSource); - bool CanSet(FieldIndex, - const bool& aUsingStorageAccess, ContentParent* aSource); bool CanSet(FieldIndex, const bool& aShouldResistFingerprinting, ContentParent* aSource); bool CanSet(FieldIndex, const bool& aIsSecureContext, diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 1e3fbc072010..a2f440dfadb1 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -17234,12 +17234,6 @@ already_AddRefed Document::HasStorageAccess( return nullptr; } - if (!IsCurrentActiveDocument()) { - promise->MaybeRejectWithInvalidStateError( - "hasStorageAccess requires an active document"); - return promise.forget(); - } - bool hasStorageAccess; nsresult rv = HasStorageAccessSync(hasStorageAccess); if (NS_FAILED(rv)) { @@ -17275,16 +17269,16 @@ Document::GetContentBlockingEvents() { StorageAccessAPIHelper::PerformPermissionGrant Document::CreatePermissionGrantPromise( nsPIDOMWindowInner* aInnerWindow, nsIPrincipal* aPrincipal, - bool aHasUserInteraction, bool aRequireUserInteraction, - const Maybe& aTopLevelBaseDomain, bool aFrameOnly) { + bool aHasUserInteraction, const Maybe& aTopLevelBaseDomain, + bool aFrameOnly) { MOZ_ASSERT(aInnerWindow); MOZ_ASSERT(aPrincipal); RefPtr self(this); RefPtr inner(aInnerWindow); RefPtr principal(aPrincipal); - return [inner, self, principal, aHasUserInteraction, aRequireUserInteraction, - aTopLevelBaseDomain, aFrameOnly]() { + return [inner, self, principal, aHasUserInteraction, aTopLevelBaseDomain, + aFrameOnly]() { RefPtr p = new StorageAccessAPIHelper::StorageAccessPermissionGrantPromise:: Private(__func__); @@ -17300,31 +17294,13 @@ Document::CreatePermissionGrantPromise( MOZ_ASSERT(promise); promise->Then( GetCurrentSerialEventTarget(), __func__, - [self, p, inner, principal, aHasUserInteraction, - aRequireUserInteraction, aTopLevelBaseDomain, + [self, p, inner, principal, aHasUserInteraction, 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 sapr = StorageAccessPermissionRequest::Create( @@ -17438,9 +17414,17 @@ already_AddRefed Document::RequestStorageAccess( return nullptr; } - if (!IsCurrentActiveDocument()) { - promise->MaybeRejectWithInvalidStateError( - "requestStorageAccess requires an active document"); + // 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(); } @@ -17552,8 +17536,7 @@ already_AddRefed 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(), - self->HasValidTransientUserGestureActivation(), true, true, + this, inner, bc, NodePrincipal(), true, true, ContentBlockingNotifier::eStorageAccessAPI, true) ->Then( GetCurrentSerialEventTarget(), __func__, @@ -17682,8 +17665,8 @@ already_AddRefed Document::RequestStorageAccessForOrigin( GetBrowsingContext(), principal) ->Then( GetCurrentSerialEventTarget(), __func__, - [inner, thirdPartyURI, bc, principal, hasUserActivation, - aRequireUserActivation, self, promise](Maybe cookieResult) { + [inner, thirdPartyURI, bc, principal, hasUserActivation, self, + promise](Maybe cookieResult) { // Handle the result of the cookie permission check that took place // in the ContentParent. if (cookieResult.isSome()) { @@ -17714,8 +17697,7 @@ already_AddRefed 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, - aRequireUserActivation, false, + self, inner, bc, principal, hasUserActivation, false, ContentBlockingNotifier::ePrivilegeStorageAccessForOriginAPI, true); }, @@ -17875,7 +17857,7 @@ already_AddRefed Document::RequestStorageAccessUnderSite( false, __func__); } return self->CreatePermissionGrantPromise( - self->GetInnerWindow(), self->NodePrincipal(), true, true, + self->GetInnerWindow(), self->NodePrincipal(), true, Some(serializedSite), false)(); }, [](const ContentChild::TestStorageAccessPermissionPromise:: @@ -18048,7 +18030,7 @@ already_AddRefed 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, true, false, + self, inner, bc, principal, true, false, ContentBlockingNotifier::eStorageAccessAPI, false); }, // If the IPC rejects, we should reject our promise here which will @@ -18361,12 +18343,14 @@ nsICookieJarSettings* Document::CookieJarSettings() { } bool Document::UsingStorageAccess() { - if (WindowContext* wc = GetWindowContext()) { - return wc->GetUsingStorageAccess(); + // The HasStoragePermission flag in LoadInfo remains fixed when + // it is set in the parent process, so we need to check the cache + // to see if the permission is granted afterwards. + nsPIDOMWindowInner* inner = GetInnerWindow(); + if (inner && inner->UsingStorageAccess()) { + return true; } - // If we don't yet have a window context, we have to use the decision - // from the Document's Channel's LoadInfo directly. if (!mChannel) { return false; } diff --git a/dom/base/Document.h b/dom/base/Document.h index 5f0a382e8fc2..10e25e69b83b 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -1267,8 +1267,8 @@ class Document : public nsINode, StorageAccessAPIHelper::PerformPermissionGrant CreatePermissionGrantPromise( nsPIDOMWindowInner* aInnerWindow, nsIPrincipal* aPrincipal, - bool aHasUserInteraction, bool aRequireUserInteraction, - const Maybe& aTopLevelBaseDomain, bool aFrameOnly); + bool aHasUserInteraction, const Maybe& aTopLevelBaseDomain, + bool aFrameOnly); already_AddRefed RequestStorageAccess(ErrorResult& aRv); diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp index 0d183d3d4aa0..53984ee4f0be 100644 --- a/dom/base/nsGlobalWindowInner.cpp +++ b/dom/base/nsGlobalWindowInner.cpp @@ -7461,7 +7461,7 @@ void nsGlobalWindowInner::ForgetSharedWorker(SharedWorker* aSharedWorker) { mSharedWorkers.RemoveElement(aSharedWorker); } -void nsGlobalWindowInner::StorageAccessPermissionChanged() { +void nsGlobalWindowInner::StorageAccessPermissionGranted() { // Invalidate cached StorageAllowed field so that calls to GetLocalStorage // give us the updated localStorage object. ClearStorageAllowedCache(); @@ -7644,31 +7644,12 @@ const nsIGlobalObject* nsPIDOMWindowInner::AsGlobal() const { } void nsPIDOMWindowInner::SaveStorageAccessPermissionGranted() { - WindowContext* wc = GetWindowContext(); - if (wc) { - Unused << wc->SetUsingStorageAccess(true); - } - - nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(); -} - -void nsPIDOMWindowInner::SaveStorageAccessPermissionRevoked() { - WindowContext* wc = GetWindowContext(); - if (wc) { - Unused << wc->SetUsingStorageAccess(false); - } + mUsingStorageAccess = true; - nsGlobalWindowInner::Cast(this)->StorageAccessPermissionChanged(); + nsGlobalWindowInner::Cast(this)->StorageAccessPermissionGranted(); } -bool nsPIDOMWindowInner::UsingStorageAccess() { - WindowContext* wc = GetWindowContext(); - if (!wc) { - return false; - } - - return wc->GetUsingStorageAccess(); -} +bool nsPIDOMWindowInner::UsingStorageAccess() { return mUsingStorageAccess; } nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow, WindowGlobalChild* aActor) @@ -7693,6 +7674,7 @@ nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow, mNumOfIndexedDBDatabases(0), mNumOfOpenWebSockets(0), mEvent(nullptr), + mUsingStorageAccess(false), mWindowGlobalChild(aActor), mWasSuspendedByGroup(false) { MOZ_ASSERT(aOuterWindow); diff --git a/dom/base/nsGlobalWindowInner.h b/dom/base/nsGlobalWindowInner.h index ccbccdf0e4b9..48b4ba6e3064 100644 --- a/dom/base/nsGlobalWindowInner.h +++ b/dom/base/nsGlobalWindowInner.h @@ -1097,9 +1097,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget, nsIPrincipal* GetClientPrincipal(); // This method is called if this window loads a 3rd party tracking resource - // and the storage is just been changed. The window can reset the partitioned + // and the storage is just been granted. The window can reset the partitioned // storage objects and switch to the first party cookie jar. - void StorageAccessPermissionChanged(); + void StorageAccessPermissionGranted(); protected: static void NotifyDOMWindowDestroyed(nsGlobalWindowInner* aWindow); diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 2b78eb42210f..3a25a12869c6 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -639,7 +639,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow { mozilla::TaskCategory aCategory) const = 0; void SaveStorageAccessPermissionGranted(); - void SaveStorageAccessPermissionRevoked(); bool UsingStorageAccess(); @@ -761,6 +760,10 @@ class nsPIDOMWindowInner : public mozIDOMWindow { // the event object alive. mozilla::dom::Event* mEvent; + // A boolean flag indicating whether storage access is granted for the + // current window and that it is currently being used by this window. + bool mUsingStorageAccess; + // The WindowGlobalChild actor for this window. // // This will be non-null during the full lifetime of the window, initialized diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 1f0034c60a50..d33bd8187888 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -6461,16 +6461,6 @@ nsresult ContentParent::TransmitPermissionsForPrincipal( EnsurePermissionsByKey(pair.first, pair.second); } - // We need to add the Site to the secondary keys of interest here. - // This allows site-scoped permission updates to propogate when the - // port is non-standard. - nsAutoCString siteKey; - nsresult rv = - PermissionManager::GetKeyForPrincipal(aPrincipal, false, true, siteKey); - if (NS_SUCCEEDED(rv) && !siteKey.IsEmpty()) { - mActiveSecondaryPermissionKeys.EnsureInserted(siteKey); - } - return NS_OK; } @@ -6565,11 +6555,6 @@ bool ContentParent::NeedsPermissionsUpdate( return mActivePermissionKeys.Contains(aPermissionKey); } -bool ContentParent::NeedsSecondaryKeyPermissionsUpdate( - const nsACString& aPermissionKey) const { - return mActiveSecondaryPermissionKeys.Contains(aPermissionKey); -} - mozilla::ipc::IPCResult ContentParent::RecvAccumulateChildHistograms( nsTArray&& aAccumulations) { TelemetryIPC::AccumulateChildHistograms(GetTelemetryProcessID(mRemoteType), diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 8c7176d57621..d17ed3a6d8e4 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -404,12 +404,6 @@ class ContentParent final : public PContentParent, bool NeedsPermissionsUpdate(const nsACString& aPermissionKey) const; - // Getter for which permission keys should signal that a content - // process needs to know about the change of a permission with this as the - // secondary key, like for 3rdPartyFrameStorage^https://secondary.com - bool NeedsSecondaryKeyPermissionsUpdate( - const nsACString& aPermissionKey) const; - // Manage pending load states which have been sent to this process, and are // expected to be used to start a load imminently. already_AddRefed TakePendingLoadStateForId( @@ -1598,7 +1592,6 @@ class ContentParent final : public PContentParent, nsRefPtrHashtable mGetFilesPendingRequests; nsTHashSet mActivePermissionKeys; - nsTHashSet mActiveSecondaryPermissionKeys; nsTArray mBlobURLs; diff --git a/dom/ipc/PWindowGlobal.ipdl b/dom/ipc/PWindowGlobal.ipdl index 0d3f0a09a08d..ecb4b3d718c7 100644 --- a/dom/ipc/PWindowGlobal.ipdl +++ b/dom/ipc/PWindowGlobal.ipdl @@ -220,7 +220,7 @@ parent: CookieStruct[] cookies); child: - async NotifyPermissionChange(nsCString type, uint32_t permission); + async NotifyPermissionChange(nsCString type); }; } // namespace dom diff --git a/dom/ipc/WindowGlobalActor.cpp b/dom/ipc/WindowGlobalActor.cpp index 95d224a7b086..ce5fa3eaf484 100644 --- a/dom/ipc/WindowGlobalActor.cpp +++ b/dom/ipc/WindowGlobalActor.cpp @@ -150,8 +150,6 @@ WindowGlobalInit WindowGlobalActor::WindowInitializer( nsCOMPtr loadInfo(channel->LoadInfo()); fields.Get() = loadInfo->GetOriginalFrameSrcLoad(); - fields.Get() = - loadInfo->GetStoragePermission() != nsILoadInfo::NoStoragePermission; channel->GetSecurityInfo(getter_AddRefs(securityInfo)); } diff --git a/dom/ipc/WindowGlobalChild.cpp b/dom/ipc/WindowGlobalChild.cpp index a31e95137437..7270e664a47d 100644 --- a/dom/ipc/WindowGlobalChild.cpp +++ b/dom/ipc/WindowGlobalChild.cpp @@ -219,8 +219,6 @@ void WindowGlobalChild::OnNewDocument(Document* aDocument) { if (nsCOMPtr channel = aDocument->GetChannel()) { nsCOMPtr loadInfo(channel->LoadInfo()); txn.SetIsOriginalFrameSource(loadInfo->GetOriginalFrameSrcLoad()); - txn.SetUsingStorageAccess(loadInfo->GetStoragePermission() != - nsILoadInfo::NoStoragePermission); } else { txn.SetIsOriginalFrameSource(false); } @@ -549,8 +547,8 @@ IPCResult WindowGlobalChild::RecvRawMessage( return IPC_OK(); } -IPCResult WindowGlobalChild::RecvNotifyPermissionChange(const nsCString& aType, - uint32_t aPermission) { +IPCResult WindowGlobalChild::RecvNotifyPermissionChange( + const nsCString& aType) { nsCOMPtr observerService = services::GetObserverService(); NS_ENSURE_TRUE(observerService, IPC_FAIL(this, "Failed to get observer service")); @@ -558,13 +556,6 @@ IPCResult WindowGlobalChild::RecvNotifyPermissionChange(const nsCString& aType, static_cast(this->GetWindowGlobal()); observerService->NotifyObservers(notifyTarget, "perm-changed-notify-only", NS_ConvertUTF8toUTF16(aType).get()); - // We only need to handle the revoked permission case here. The permission - // grant case is handled via the Storage Access API code. - if (this->GetWindowGlobal() && - this->GetWindowGlobal()->UsingStorageAccess() && - aPermission != nsIPermissionManager::ALLOW_ACTION) { - this->GetWindowGlobal()->SaveStorageAccessPermissionRevoked(); - } return IPC_OK(); } diff --git a/dom/ipc/WindowGlobalChild.h b/dom/ipc/WindowGlobalChild.h index 107b3f471d2d..53279f79c4e6 100644 --- a/dom/ipc/WindowGlobalChild.h +++ b/dom/ipc/WindowGlobalChild.h @@ -201,8 +201,7 @@ class WindowGlobalChild final : public WindowGlobalActor, dom::SessionStoreRestoreData* aData, RestoreTabContentResolver&& aResolve); - mozilla::ipc::IPCResult RecvNotifyPermissionChange(const nsCString& aType, - uint32_t aPermission); + mozilla::ipc::IPCResult RecvNotifyPermissionChange(const nsCString& aType); virtual void ActorDestroy(ActorDestroyReason aWhy) override; diff --git a/extensions/permissions/PermissionManager.cpp b/extensions/permissions/PermissionManager.cpp index 9905104baffd..88f671e9c56e 100644 --- a/extensions/permissions/PermissionManager.cpp +++ b/extensions/permissions/PermissionManager.cpp @@ -604,8 +604,8 @@ bool IsPersistentExpire(uint32_t aExpire, const nsACString& aType) { } nsresult NotifySecondaryKeyPermissionUpdateInContentProcess( - const nsACString& aType, uint32_t aPermission, - const nsACString& aSecondaryKey, nsIPrincipal* aTopPrincipal) { + const nsACString& aType, const nsACString& aSecondaryKey, + nsIPrincipal* aTopPrincipal) { NS_ENSURE_ARG_POINTER(aTopPrincipal); MOZ_ASSERT(XRE_IsParentProcess()); AutoTArray, 5> bcGroups; @@ -631,12 +631,12 @@ nsresult NotifySecondaryKeyPermissionUpdateInContentProcess( if (!cp) { continue; } - if (cp->NeedsSecondaryKeyPermissionsUpdate(aSecondaryKey)) { + if (cp->NeedsPermissionsUpdate(aSecondaryKey)) { WindowGlobalParent* wgp = cbc->GetCurrentWindowGlobal(); if (!wgp) { continue; } - bool success = wgp->SendNotifyPermissionChange(aType, aPermission); + bool success = wgp->SendNotifyPermissionChange(aType); Unused << NS_WARN_IF(!success); } } @@ -1833,8 +1833,8 @@ nsresult PermissionManager::AddInternal( nsAutoCString secondaryKey; isSecondaryKeyed = GetSecondaryKey(aType, secondaryKey); if (isSecondaryKeyed) { - NotifySecondaryKeyPermissionUpdateInContentProcess( - aType, aPermission, secondaryKey, aPrincipal); + NotifySecondaryKeyPermissionUpdateInContentProcess(aType, secondaryKey, + aPrincipal); } nsTArray cplist; @@ -3439,7 +3439,6 @@ PermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) { nsTArray> pairs; nsCOMPtr prin = aPrincipal; - while (prin) { // Add the pair to the list std::pair* pair = diff --git a/remote/marionette/driver.sys.mjs b/remote/marionette/driver.sys.mjs index a33985fccce6..125bfa89d47c 100644 --- a/remote/marionette/driver.sys.mjs +++ b/remote/marionette/driver.sys.mjs @@ -3350,13 +3350,7 @@ GeckoDriver.prototype.setPermission = async function (cmd) { `state is ${state}, expected "granted", "denied", or "prompt"` )(state); - lazy.permissions.set( - descriptor, - state, - oneRealm, - this.getBrowsingContext(), - this.getBrowsingContext({ top: true }) - ); + lazy.permissions.set(descriptor, state, oneRealm); }; /** diff --git a/remote/marionette/permissions.sys.mjs b/remote/marionette/permissions.sys.mjs index 681bbd192a3b..d67e2c46b7ce 100644 --- a/remote/marionette/permissions.sys.mjs +++ b/remote/marionette/permissions.sys.mjs @@ -5,7 +5,6 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { - assert: "chrome://remote/content/shared/webdriver/Assert.sys.mjs", error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs", MarionettePrefs: "chrome://remote/content/marionette/prefs.sys.mjs", }); @@ -23,38 +22,29 @@ export const permissions = {}; * State of the permission. It can be `granted`, `denied` or `prompt`. * @param {boolean} oneRealm * Currently ignored - * @param {browsingContext=} thirdPartyBrowsingContext - * 3rd party browsing context object - * @param {browsingContext=} topLevelBrowsingContext - * Top level browsing context object + * * @throws {UnsupportedOperationError} * If `marionette.setpermission.enabled` is not set or * an unsupported permission is used. */ -permissions.set = function ( - descriptor, - state, - oneRealm, - thirdPartyBrowsingContext, - topLevelBrowsingContext -) { +permissions.set = function (descriptor, state, oneRealm) { if (!lazy.MarionettePrefs.setPermissionEnabled) { throw new lazy.error.UnsupportedOperationError( "'Set Permission' is not available" ); } + if (state === "prompt") { + throw new lazy.error.UnsupportedOperationError( + "'Set Permission' doesn't support prompt" + ); + } + // This is not a real implementation of the permissions API. // Instead the purpose of this implementation is to have web-platform-tests // that use `set_permission()` not fail. // Each test needs the corresponding testing pref to make it actually work. const { name } = descriptor; - - if (state === "prompt" && name !== "storage-access") { - throw new lazy.error.UnsupportedOperationError( - "'Set Permission' doesn't support prompt" - ); - } if (["clipboard-write", "clipboard-read"].includes(name)) { if ( Services.prefs.getBoolPref("dom.events.testing.asyncClipboard", false) @@ -71,49 +61,6 @@ permissions.set = function ( throw new lazy.error.UnsupportedOperationError( "'Set Permission' expected notification.prompt.testing to be set" ); - } else if (name === "storage-access") { - // Check if browsing context has a window global object - lazy.assert.open(thirdPartyBrowsingContext); - lazy.assert.open(topLevelBrowsingContext); - - const thirdPartyURI = - thirdPartyBrowsingContext.currentWindowGlobal.documentURI; - const topLevelURI = topLevelBrowsingContext.currentWindowGlobal.documentURI; - - const thirdPartyPrincipalSite = Services.eTLD.getSite(thirdPartyURI); - - const topLevelPrincipal = - Services.scriptSecurityManager.createContentPrincipal(topLevelURI, {}); - - switch (state) { - case "granted": { - Services.perms.addFromPrincipal( - topLevelPrincipal, - "3rdPartyFrameStorage^" + thirdPartyPrincipalSite, - Services.perms.ALLOW_ACTION - ); - return; - } - case "denied": { - Services.perms.addFromPrincipal( - topLevelPrincipal, - "3rdPartyFrameStorage^" + thirdPartyPrincipalSite, - Services.perms.DENY_ACTION - ); - return; - } - case "prompt": { - Services.perms.removeFromPrincipal( - topLevelPrincipal, - "3rdPartyFrameStorage^" + thirdPartyPrincipalSite - ); - return; - } - default: - throw new lazy.error.UnsupportedOperationError( - `'Set Permission' did not work for storage-access'` - ); - } } throw new lazy.error.UnsupportedOperationError( diff --git a/testing/web-platform/meta/storage-access-api/__dir__.ini b/testing/web-platform/meta/storage-access-api/__dir__.ini deleted file mode 100644 index ebaddb8d4438..000000000000 --- a/testing/web-platform/meta/storage-access-api/__dir__.ini +++ /dev/null @@ -1 +0,0 @@ -prefs: [marionette.setpermission.enabled:true, dom.storage_access.auto_grants:false, dom.storage_access.prompt.testing:true, dom.storage_access.prompt.testing.allow:false] diff --git a/testing/web-platform/meta/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window.js.ini index 368fffe672f6..73b3a8cdfa83 100644 --- a/testing/web-platform/meta/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window.js.ini +++ b/testing/web-platform/meta/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window.js.ini @@ -2,3 +2,5 @@ [[ABA\] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.] expected: FAIL + [[ABA\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/hasStorageAccess-insecure.sub.window.js.ini b/testing/web-platform/meta/storage-access-api/hasStorageAccess-insecure.sub.window.js.ini new file mode 100644 index 000000000000..a31d80a0ce1a --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/hasStorageAccess-insecure.sub.window.js.ini @@ -0,0 +1,31 @@ +[hasStorageAccess-insecure.sub.window.html] + expected: [OK, TIMEOUT] + [[top-level-context\] document.hasStorageAccess() should be disallowed in insecure contexts] + expected: FAIL + + [[same-origin-frame\] document.hasStorageAccess() should be disallowed in insecure contexts] + expected: FAIL + + [[cross-origin-frame\] document.hasStorageAccess() should be disallowed in insecure contexts] + expected: FAIL + + [[nested-same-origin-frame\] document.hasStorageAccess() should be disallowed in insecure contexts] + expected: FAIL + + [[nested-cross-origin-frame\] document.hasStorageAccess() should be disallowed in insecure contexts] + expected: FAIL + + [[top-level-context\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[same-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[cross-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[nested-same-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[nested-cross-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/hasStorageAccess.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/hasStorageAccess.sub.https.window.js.ini new file mode 100644 index 000000000000..7769b8247c88 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/hasStorageAccess.sub.https.window.js.ini @@ -0,0 +1,24 @@ +[hasStorageAccess.sub.https.window.html] + expected: [OK, TIMEOUT] + [[top-level-context\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[same-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[nested-same-origin-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[cross-site-frame\] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.] + expected: + if os == "android": FAIL + + [[cross-site-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL + + [[nested-cross-site-frame\] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.] + expected: + if os == "android": FAIL + + [[nested-cross-site-frame\] document.hasStorageAccess() should reject in a document that isn't fully active.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/idlharness.window.js.ini b/testing/web-platform/meta/storage-access-api/idlharness.window.js.ini new file mode 100644 index 000000000000..d32879d3caca --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/idlharness.window.js.ini @@ -0,0 +1,3 @@ +[idlharness.window.html] + expected: + if (os == "android") and fission: [TIMEOUT, OK] diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini new file mode 100644 index 000000000000..6bfbf0bfa832 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window.js.ini @@ -0,0 +1,15 @@ +[requestStorageAccess-ABA.tentative.sub.https.window.html] + expected: + if (os == "android") and swgl: [OK, TIMEOUT] + if (os == "android") and not swgl: [OK, TIMEOUT] + [[ABA\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL + + [[ABA\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL + + [[ABA\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: FAIL + + [[ABA\] document.requestStorageAccess() should resolve with denied permission] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js.ini index 7f002e420ec1..f55a572ed169 100644 --- a/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js.ini +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js.ini @@ -1,3 +1,13 @@ [requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.html] + expected: TIMEOUT + [Self-initiated same-origin navigations preserve storage access] + expected: NOTRUN + [Self-initiated reloads preserve storage access] - expected: FAIL + expected: TIMEOUT + + [Non-self-initiated same-origin navigations do not preserve storage access] + expected: NOTRUN + + [Self-initiated cross-origin navigations do not preserve storage access] + expected: NOTRUN diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-iframe.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-iframe.sub.https.window.js.ini new file mode 100644 index 000000000000..11ac29206c4e --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-iframe.sub.https.window.js.ini @@ -0,0 +1,16 @@ +[requestStorageAccess-cross-site-iframe.sub.https.window.html] + expected: + if (os == "android") and debug and swgl: [TIMEOUT, OK] + if (os == "android") and debug and not swgl: [OK, TIMEOUT] + if (os == "android") and not debug: [OK, TIMEOUT] + [[cross-site-frame\] document.requestStorageAccess() should be rejected with a NotAllowedError without permission grant] + expected: FAIL + + [[cross-site-frame\] document.requestStorageAccess() should be rejected with a NotAllowedError with denied permission] + expected: FAIL + + [[cross-site-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL + + [[cross-site-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js.ini index 7d702fdf4989..bd564fdab926 100644 --- a/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js.ini +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window.js.ini @@ -1,3 +1,7 @@ [requestStorageAccess-cross-site-sibling-iframes.sub.https.window.html] + expected: TIMEOUT + [Grants have per-frame scope] + expected: TIMEOUT + [Cross-site sibling iframes should not be able to take advantage of the existing permission grant requested by others.] - expected: FAIL + expected: NOTRUN diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-insecure.sub.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-insecure.sub.window.js.ini new file mode 100644 index 000000000000..fa987125e578 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-insecure.sub.window.js.ini @@ -0,0 +1,10 @@ +[requestStorageAccess-insecure.sub.window.html] + expected: TIMEOUT + [[non-fully-active\] document.requestStorageAccess() should reject when run in a detached frame] + expected: TIMEOUT + + [[non-fully-active\] document.requestStorageAccess() should reject when run in a detached DOMParser document] + expected: NOTRUN + + [[top-level-context\] document.requestStorageAccess() should be rejected when called with a user gesture in insecure context] + expected: NOTRUN diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini index b195996478fb..07285108d1ed 100644 --- a/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-origin-iframe.sub.https.window.js.ini @@ -1,17 +1,18 @@ [requestStorageAccess-nested-cross-origin-iframe.sub.https.window.html] - expected: [OK, TIMEOUT] - - [[nested-cross-origin-frame\] document.requestStorageAccess() should exist on the document interface] - expected: PASS + expected: + if (os == "android") and not swgl and not debug: [OK, TIMEOUT, ERROR] + if (os == "mac") and not debug: [OK, TIMEOUT] + if (os == "android") and swgl: [OK, TIMEOUT, ERROR] + if (os == "win") and not debug: [TIMEOUT, OK] + [OK, ERROR, TIMEOUT] + [[nested-cross-origin-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL [[nested-cross-origin-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] - expected: PASS - - [[nested-cross-origin-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] - expected: PASS + expected: FAIL - [[nested-cross-origin-frame\] document.requestStorageAccess() should resolve without permission grant or user gesture ] - expected: PASS + [[nested-cross-origin-frame\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: FAIL [[nested-cross-origin-frame\] document.requestStorageAccess() should resolve with denied permission] - expected: PASS + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-site-iframe.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-site-iframe.sub.https.window.js.ini new file mode 100644 index 000000000000..ef562c30b158 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-cross-site-iframe.sub.https.window.js.ini @@ -0,0 +1,16 @@ +[requestStorageAccess-nested-cross-site-iframe.sub.https.window.html] + expected: + if os == "mac": OK + if os == "win": OK + [OK, TIMEOUT] + [[nested-cross-site-frame\] document.requestStorageAccess() should be rejected with a NotAllowedError without permission grant] + expected: FAIL + + [[nested-cross-site-frame\] document.requestStorageAccess() should be rejected with a NotAllowedError with denied permission] + expected: FAIL + + [[nested-cross-site-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL + + [[nested-cross-site-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini index b1171b80731c..6a9dc44eced3 100644 --- a/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window.js.ini @@ -1,18 +1,24 @@ [requestStorageAccess-nested-same-origin-iframe.sub.https.window.html] - expected: [OK, TIMEOUT] + expected: + if (os == "win") and debug and (processor == "x86_64") and not swgl: [TIMEOUT, OK, ERROR] + if (os == "win") and debug and (processor == "x86_64") and swgl: [TIMEOUT, OK, ERROR] + if (os == "linux") and debug and not fission and swgl: OK + if (os == "android") and not swgl and not debug: [OK, TIMEOUT, ERROR] + if (os == "win") and not debug and (processor == "x86"): [TIMEOUT, OK] + if (os == "win") and not debug and (processor == "x86_64"): [OK, TIMEOUT] + if (os == "linux") and debug and fission: OK + if (os == "mac") and debug: [TIMEOUT, OK, ERROR] + if (os == "mac") and not debug: [TIMEOUT, OK] + if (os == "android") and swgl: [TIMEOUT, OK] + [OK, ERROR, TIMEOUT] + [[nested-same-origin-frame\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: FAIL - [[nested-same-origin-frame\] document.requestStorageAccess() should exist on the document interface] - expected: PASS - - [[nested-same-origin-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] - expected: PASS + [[nested-same-origin-frame\] document.requestStorageAccess() should resolve with denied permission] + expected: FAIL [[nested-same-origin-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] - expected: PASS - - [[nested-same-origin-frame\] document.requestStorageAccess() should resolve without permission grant or user gesture ] - expected: PASS - - [[nested-same-origin-frame\] document.requestStorageAccess() should resolve with denied permission] - expected: PASS + expected: FAIL + [[nested-same-origin-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-non-fully-active.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-non-fully-active.sub.https.window.js.ini new file mode 100644 index 000000000000..b44e36118e49 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-non-fully-active.sub.https.window.js.ini @@ -0,0 +1,7 @@ +[requestStorageAccess-non-fully-active.sub.https.window.html] + expected: TIMEOUT + [[non-fully-active\] document.requestStorageAccess() should not resolve when run in a detached frame] + expected: TIMEOUT + + [[non-fully-active\] document.requestStorageAccess() should not resolve when run in a detached DOMParser document] + expected: NOTRUN diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini new file mode 100644 index 000000000000..58e7c6e8ab93 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window.js.ini @@ -0,0 +1,15 @@ +[requestStorageAccess-same-site-iframe.sub.https.window.html] + expected: + if (os == "mac") and debug: [TIMEOUT, OK] + [OK, TIMEOUT] + [[same-site-frame\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL + + [[same-site-frame\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL + + [[same-site-frame\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: FAIL + + [[same-site-frame\] document.requestStorageAccess() should resolve with denied permission] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/requestStorageAccess.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/requestStorageAccess.sub.https.window.js.ini new file mode 100644 index 000000000000..6935961b6da6 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/requestStorageAccess.sub.https.window.js.ini @@ -0,0 +1,18 @@ +[requestStorageAccess.sub.https.window.html] + [[top-level-context\] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access] + expected: FAIL + + [[top-level-context\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: NOTRUN + + [[top-level-context\] document.requestStorageAccess() should resolve with denied permission] + expected: NOTRUN + + [[top-level-context\] document.requestStorageAccess() should resolve without permission grant or user gesture] + expected: FAIL + + [[top-level-context\] document.requestStorageAccess() should resolve with denied permission] + expected: FAIL + + [[top-level-context\] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.] + expected: FAIL diff --git a/testing/web-platform/meta/storage-access-api/storage-access-permission.sub.https.window.js.ini b/testing/web-platform/meta/storage-access-api/storage-access-permission.sub.https.window.js.ini new file mode 100644 index 000000000000..f5f3e0a44db8 --- /dev/null +++ b/testing/web-platform/meta/storage-access-api/storage-access-permission.sub.https.window.js.ini @@ -0,0 +1,10 @@ +[storage-access-permission.sub.https.window.html] + expected: TIMEOUT + [Permissions grants are observable across same-origin iframes] + expected: TIMEOUT + + [IFrame tests] + expected: NOTRUN + + [Permissions grants are observable across same-site iframes] + expected: NOTRUN diff --git a/testing/web-platform/meta/storage-access-api/storageAccess.testdriver.sub.html.ini b/testing/web-platform/meta/storage-access-api/storageAccess.testdriver.sub.html.ini index d68424fba6c1..ac235bcfb13d 100644 --- a/testing/web-platform/meta/storage-access-api/storageAccess.testdriver.sub.html.ini +++ b/testing/web-platform/meta/storage-access-api/storageAccess.testdriver.sub.html.ini @@ -1,3 +1,14 @@ [storageAccess.testdriver.sub.html] + expected: + if (os == "win") and debug: OK + if os == "android": OK + [OK, TIMEOUT] [TestDriver - Set Storage Access Command Tests] expected: FAIL + + [TestDriver - Set Storage Access Command Tests] + expected: + if not debug and (os == "linux") and fission: [FAIL, PASS] + if not debug and (os == "linux") and not fission: [FAIL, PASS] + if not debug and (os == "win"): [FAIL, PASS] + FAIL diff --git a/toolkit/components/antitracking/AntiTrackingUtils.cpp b/toolkit/components/antitracking/AntiTrackingUtils.cpp index c80a6b869ca2..59e2573d53fe 100644 --- a/toolkit/components/antitracking/AntiTrackingUtils.cpp +++ b/toolkit/components/antitracking/AntiTrackingUtils.cpp @@ -557,23 +557,23 @@ AntiTrackingUtils::GetStoragePermissionStateInParent(nsIChannel* aChannel) { return nsILoadInfo::HasStoragePermission; } } else if (!bc->IsTop()) { - // For subframe resources, check if the document has storage access - // and that the resource being loaded is same-site to the page. - WindowContext* wc = bc->GetCurrentWindowContext(); - if (!wc) { + // Only check the frame only permission if the channel is not in the top + // browsing context. + RefPtr etld = nsEffectiveTLDService::GetInstance(); + if (!etld) { return nsILoadInfo::NoStoragePermission; } - WindowGlobalParent* wgp = wc->Canonical(); - if (!wgp) { - return nsILoadInfo::NoStoragePermission; - } - nsIPrincipal* framePrincipal = wgp->DocumentPrincipal(); - if (!framePrincipal) { + nsCString trackingSite; + rv = etld->GetSite(trackingURI, trackingSite); + if (NS_WARN_IF(NS_FAILED(rv))) { return nsILoadInfo::NoStoragePermission; } - bool isThirdParty = true; - nsresult rv = framePrincipal->IsThirdPartyURI(trackingURI, &isThirdParty); - if (NS_SUCCEEDED(rv) && wc->GetUsingStorageAccess() && !isThirdParty) { + nsAutoCString type; + AntiTrackingUtils::CreateStorageFramePermissionKey(trackingSite, type); + + if (AntiTrackingUtils::CheckStoragePermission( + targetPrincipal, type, NS_UsePrivateBrowsing(aChannel), + &unusedReason, unusedReason)) { return nsILoadInfo::HasStoragePermission; } } diff --git a/toolkit/components/antitracking/StorageAccessAPIHelper.cpp b/toolkit/components/antitracking/StorageAccessAPIHelper.cpp index 85c178874c75..9499cdbf24b7 100644 --- a/toolkit/components/antitracking/StorageAccessAPIHelper.cpp +++ b/toolkit/components/antitracking/StorageAccessAPIHelper.cpp @@ -558,14 +558,9 @@ StorageAccessAPIHelper::CompleteAllowAccessFor( MOZ_ASSERT(aParentContext->IsInProcess()); // Let's inform the parent window and the other windows having the - // same tracking origin about the storage permission is granted - // if it is not a frame-only permission grant which does not propogate. - if (aReason != ContentBlockingNotifier::StorageAccessPermissionGrantedReason:: - eStorageAccessAPI || - !StaticPrefs::dom_storage_access_frame_only()) { - StorageAccessAPIHelper::UpdateAllowAccessOnCurrentProcess(aParentContext, - aTrackingOrigin); - } + // same tracking origin about the storage permission is granted. + StorageAccessAPIHelper::UpdateAllowAccessOnCurrentProcess(aParentContext, + aTrackingOrigin); // Let's inform the parent window. nsCOMPtr parentInner = @@ -646,12 +641,9 @@ StorageAccessAPIHelper::SaveAccessForOriginOnParentProcess( // If the permission is granted on a first-party window, also have to update // the permission to all the other windows with the same tracking origin (in - // the same tab), if any, only it is not a frame-only permission grant which - // does not propogate. - if (!aFrameOnly) { - StorageAccessAPIHelper::UpdateAllowAccessOnParentProcess(aParentContext, - trackingOrigin); - } + // the same tab), if any. + StorageAccessAPIHelper::UpdateAllowAccessOnParentProcess(aParentContext, + trackingOrigin); return StorageAccessAPIHelper::SaveAccessForOriginOnParentProcess( wgp->DocumentPrincipal(), aTrackingPrincipal, aAllowMode, aFrameOnly, @@ -830,6 +822,9 @@ Maybe StorageAccessAPIHelper::CheckBrowserSettingsDecidesStorageAccessAPI( } return Nothing(); case nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN: + if (!aThirdParty) { + return Some(true); + } if (aIsOnThirdPartySkipList) { return Some(true); } @@ -845,9 +840,20 @@ Maybe StorageAccessAPIHelper::CheckBrowserSettingsDecidesStorageAccessAPI( Maybe 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->IsCurrentActiveDocument()) { - return Some(false); + if (aDocument->IsTopLevelContentDocument()) { + return Some(true); } if (aRequestingStorageAccess) { @@ -870,6 +876,31 @@ Maybe StorageAccessAPIHelper::CheckCallingContextDecidesStorageAccessAPI( return Some(false); } + // We check if the document is a first-party document here by testing if the + // top-level window is same-origin. In non-Fission mode, we can directly get + // the top-level window through the top browsing context since it should be + // in-process. And test their principals. + // + // In fission, if the sub frame's origin differs from the main frame's + // origin, they will be in different processes. We use IsInProcess() + // check here to deterimine whether they have the same origin. In + // non-fission mode, it is always in-process so we need to compare their + // principals. + if (bc->Top()->IsInProcess()) { + nsCOMPtr topOuter = bc->Top()->GetDOMWindow(); + if (!topOuter) { + return Some(false); + } + nsCOMPtr topLevelDoc = topOuter->GetExtantDoc(); + if (!topLevelDoc) { + return Some(false); + } + + if (topLevelDoc->NodePrincipal()->Equals(aDocument->NodePrincipal())) { + return Some(true); + } + } + // Check if NodePrincipal is not null if (!aDocument->NodePrincipal()) { return Some(false); @@ -901,14 +932,6 @@ Maybe StorageAccessAPIHelper::CheckCallingContextDecidesStorageAccessAPI( return Some(false); } - if (!AntiTrackingUtils::IsThirdPartyDocument(aDocument)) { - return Some(true); - } - - if (aDocument->IsTopLevelContentDocument()) { - return Some(true); - } - if (aRequestingStorageAccess) { if (aDocument->StorageAccessSandboxed()) { nsContentUtils::ReportToConsole( @@ -983,7 +1006,7 @@ RefPtr StorageAccessAPIHelper::RequestStorageAccessAsyncHelper( dom::Document* aDocument, nsPIDOMWindowInner* aInnerWindow, dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal, - bool aHasUserInteraction, bool aRequireUserInteraction, bool aFrameOnly, + bool aHasUserInteraction, bool aFrameOnly, ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier, bool aRequireGrant) { MOZ_ASSERT(aDocument); @@ -999,8 +1022,7 @@ 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, aRequireUserInteraction, - Nothing(), aFrameOnly); + aInnerWindow, principal, aHasUserInteraction, Nothing(), aFrameOnly); // Try to allow access for the given principal. return StorageAccessAPIHelper::AllowAccessFor( diff --git a/toolkit/components/antitracking/StorageAccessAPIHelper.h b/toolkit/components/antitracking/StorageAccessAPIHelper.h index a8c059b1cb9a..505f5bdcf7cf 100644 --- a/toolkit/components/antitracking/StorageAccessAPIHelper.h +++ b/toolkit/components/antitracking/StorageAccessAPIHelper.h @@ -166,7 +166,7 @@ class StorageAccessAPIHelper final { RequestStorageAccessAsyncHelper( dom::Document* aDocument, nsPIDOMWindowInner* aInnerWindow, dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal, - bool aHasUserInteraction, bool aRequireUserInteraction, bool aFrameOnly, + bool aHasUserInteraction, bool aFrameOnly, ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier, bool aRequireGrant); diff --git a/toolkit/components/antitracking/test/browser/browser_permissionPropagation.js b/toolkit/components/antitracking/test/browser/browser_permissionPropagation.js index 73dc9e7145fa..35fd83bd316f 100644 --- a/toolkit/components/antitracking/test/browser/browser_permissionPropagation.js +++ b/toolkit/components/antitracking/test/browser/browser_permissionPropagation.js @@ -81,14 +81,14 @@ async function createTrackerFrame(params, count, callback) { } } -async function testPermission(browser, block, params, frameNumber) { +async function testPermission(browser, block, params) { await SpecialPowers.spawn( browser, - [block, params, frameNumber], - async function (block, params, frameNumber) { + [block, params], + async function (block, params) { for (let i = 0; ; i++) { let ifr = content.document.getElementById("ifr" + i); - if (!ifr || (frameNumber !== undefined && i != frameNumber)) { + if (!ifr) { break; } @@ -209,8 +209,8 @@ add_task(async function testPermissionGrantedOn3rdParty() { // 4. The fourth tab is opened by the first tab but with a different top-level url). // The tab has one tracker iframe, said E. // - // This test grants permission on iframe A, which then should not propagate storage - // permission to iframe B, C, D, E + // This test grants permission on iframe A, which then should propagate storage + // permission to iframe B & C, but not D, E info("Creating the first tab"); let tab1 = await createTab(top, 2, null, params); @@ -264,12 +264,11 @@ add_task(async function testPermissionGrantedOn3rdParty() { }); }); - info("Second iframe of the first tab should not have stroage permission"); - await testPermission(browser1, false /* block */, params, 0); - await testPermission(browser1, true /* block */, params, 1); + info("Both iframs of the first tab should have stroage permission"); + await testPermission(browser1, false /* block */, params); - info("The iframe of the second tab should not have storage permission"); - await testPermission(browser2, true /* block */, params); + info("The iframe of the second tab should have storage permission"); + await testPermission(browser2, false /* block */, params); info("The iframe of the third tab should not have storage permission"); await testPermission(browser3, true /* block */, params); -- 2.11.4.GIT