diff options
Diffstat (limited to 'toolkit/components/antitracking/StorageAccessAPIHelper.h')
-rw-r--r-- | toolkit/components/antitracking/StorageAccessAPIHelper.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/toolkit/components/antitracking/StorageAccessAPIHelper.h b/toolkit/components/antitracking/StorageAccessAPIHelper.h new file mode 100644 index 0000000000..9be39df1c5 --- /dev/null +++ b/toolkit/components/antitracking/StorageAccessAPIHelper.h @@ -0,0 +1,195 @@ +/* -*- 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_antitrackingservice_h +#define mozilla_antitrackingservice_h + +#include "nsString.h" +#include "mozilla/ContentBlockingNotifier.h" +#include "mozilla/MozPromise.h" +#include "mozilla/RefPtr.h" +#include "mozilla/StaticPrefs_privacy.h" + +#include "nsIUrlClassifierFeature.h" + +class nsIChannel; +class nsICookieJarSettings; +class nsIPermission; +class nsIPrincipal; +class nsIURI; +class nsPIDOMWindowInner; +class nsPIDOMWindowOuter; + +namespace mozilla { + +class OriginAttributes; + +namespace dom { +class BrowsingContext; +class ContentParent; +class Document; +} // namespace dom + +class StorageAccessAPIHelper final { + public: + enum StorageAccessPromptChoices { eAllow, eAllowAutoGrant }; + + // Grant the permission for aOrigin to have access to the first party storage. + // This method can handle 2 different scenarios: + // - aParentContext is a 3rd party context, it opens an aOrigin window and the + // user interacts with it. We want to grant the permission at the + // combination: top-level + aParentWindow + aOrigin. + // Ex: example.net loads an iframe tracker.com, which opens a popup + // tracker.prg and the user interacts with it. tracker.org is allowed if + // loaded by tracker.com when loaded by example.net. + // - aParentContext is a first party context and a 3rd party resource + // (probably + // becuase of a script) opens a popup and the user interacts with it. We + // want to grant the permission for the 3rd party context to have access to + // the first party stoage when loaded in aParentWindow. + // Ex: example.net import tracker.com/script.js which does opens a popup and + // the user interacts with it. tracker.com is allowed when loaded by + // example.net. + typedef MozPromise<int, bool, true> StorageAccessPermissionGrantPromise; + typedef std::function<RefPtr<StorageAccessPermissionGrantPromise>()> + PerformPermissionGrant; + [[nodiscard]] static RefPtr<StorageAccessPermissionGrantPromise> + AllowAccessFor( + nsIPrincipal* aPrincipal, dom::BrowsingContext* aParentContext, + ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason, + const PerformPermissionGrant& aPerformFinalChecks = nullptr); + + // This function handles tasks that have to be done in the process + // of the window that we just grant permission for. + static void OnAllowAccessFor( + dom::BrowsingContext* aParentContext, const nsACString& aTrackingOrigin, + uint32_t aCookieBehavior, + ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason); + + // For IPC only. + typedef MozPromise<nsresult, bool, true> ParentAccessGrantPromise; + static RefPtr<ParentAccessGrantPromise> SaveAccessForOriginOnParentProcess( + nsIPrincipal* aParentPrincipal, nsIPrincipal* aTrackingPrincipal, + int aAllowMode, + uint64_t aExpirationTime = + StaticPrefs::privacy_restrict3rdpartystorage_expiration()); + + static RefPtr<ParentAccessGrantPromise> SaveAccessForOriginOnParentProcess( + uint64_t aTopLevelWindowId, dom::BrowsingContext* aParentContext, + nsIPrincipal* aTrackingPrincipal, int aAllowMode, + uint64_t aExpirationTime = + StaticPrefs::privacy_restrict3rdpartystorage_expiration()); + + // This function checks if the document has explicit permission either to + // allow or deny access to cookies. This may be because of the "cookie" + // permission or because the domain is on the ContentBlockingAllowList + // e.g. because the user flipped the sheild. + // This returns: + // Some(true) if unpartitioned cookies will be permitted + // Some(false) if unpartitioned cookies will be blocked + // None if it is not clear from permission alone what to do + static Maybe<bool> CheckCookiesPermittedDecidesStorageAccessAPI( + nsICookieJarSettings* aCookieJarSettings, + nsIPrincipal* aRequestingPrincipal); + + // Calls CheckCookiesPermittedDecidesStorageAccessAPI in the Content Parent + // using aBrowsingContext's Top's Window Global's CookieJarSettings. + static RefPtr<MozPromise<Maybe<bool>, nsresult, true>> + AsyncCheckCookiesPermittedDecidesStorageAccessAPI( + dom::BrowsingContext* aBrowsingContext, + nsIPrincipal* aRequestingPrincipal); + + // This function checks if the browser settings give explicit permission + // either to allow or deny access to cookies. This only checks the + // cookieBehavior setting. This requires an additional bool to indicate + // whether or not the context considered is third-party. This returns: + // Some(true) if unpartitioned cookies will be permitted + // Some(false) if unpartitioned cookies will be blocked + // None if it is not clear from settings alone what to do + static Maybe<bool> CheckBrowserSettingsDecidesStorageAccessAPI( + nsICookieJarSettings* aCookieJarSettings, bool aThirdParty, + bool aOnRejectForeignAllowlist, bool aIsOnThirdPartySkipList, + bool aIsThirdPartyTracker); + + // This function checks if the document's context (like if it is third-party + // or an iframe) gives an answer of how a the StorageAccessAPI call, that is + // meant to be called by an embedded third party, should return. + // This requires an argument that allows some checks to be run only if the + // caller of this function is performing a request for storage access. + // This returns: + // Some(true) if the calling context has access to cookies if it is not + // disallowed by the browser settings and cookie permissions + // Some(false) if the calling context should not have access to cookies if + // it is not expressly allowed by the browser settings and + // cookie permissions + // None if the calling context does not determine the document's access to + // unpartitioned cookies + static Maybe<bool> CheckCallingContextDecidesStorageAccessAPI( + dom::Document* aDocument, bool aRequestingStorageAccess); + + // This function checks if the document's context (like if it is third-party + // or an iframe) gives an answer of how a the StorageAccessAPI call that is + // meant to be called in a top-level context, should return. + // This returns: + // Some(true) if the calling context indicates calls to the top-level + // API must resolve if it is not + // disallowed by the browser settings and cookie permissions + // Some(false) if the calling context must reject when calling top level + // portions of the API if it is not expressly allowed by the + // browser settings and cookie permissions + // None if the calling context does not determine the outcome of the + // document's use of the top-level portions of the Storage Access API. + static Maybe<bool> CheckSameSiteCallingContextDecidesStorageAccessAPI( + dom::Document* aDocument, bool aRequireUserActivation); + + // This function checks if the document has already been granted or denied + // access to its unpartitioned cookies by the StorageAccessAPI + // This returns: + // Some(true) if the document has been granted access by the Storage Access + // API before + // Some(false) if the document has been denied access by the Storage Access + // API before + // None if the document has not been granted or denied access by the Storage + // Access API before + static Maybe<bool> CheckExistingPermissionDecidesStorageAccessAPI( + dom::Document* aDocument, bool aRequestingStorageAccess); + + // This function performs the asynchronous portion of checking if requests + // for storage access will be successful or not. This includes calling + // Document member functions that creating a permission prompt request and + // trying to perform an "autogrant" if aRequireGrant is true. + // This will return a promise whose values correspond to those of a + // ContentBlocking::AllowAccessFor call that ends the function. + static RefPtr<StorageAccessPermissionGrantPromise> + RequestStorageAccessAsyncHelper( + dom::Document* aDocument, nsPIDOMWindowInner* aInnerWindow, + dom::BrowsingContext* aBrowsingContext, nsIPrincipal* aPrincipal, + bool aHasUserInteraction, + ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier, + bool aRequireGrant); + + private: + friend class dom::ContentParent; + // This should be running either in the parent process or in the child + // processes with an in-process browsing context. + [[nodiscard]] static RefPtr<StorageAccessPermissionGrantPromise> + CompleteAllowAccessFor( + dom::BrowsingContext* aParentContext, uint64_t aTopLevelWindowId, + nsIPrincipal* aTrackingPrincipal, const nsACString& aTrackingOrigin, + uint32_t aCookieBehavior, + ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason, + const PerformPermissionGrant& aPerformFinalChecks = nullptr); + + static void UpdateAllowAccessOnCurrentProcess( + dom::BrowsingContext* aParentContext, const nsACString& aTrackingOrigin); + + static void UpdateAllowAccessOnParentProcess( + dom::BrowsingContext* aParentContext, const nsACString& aTrackingOrigin); +}; + +} // namespace mozilla + +#endif // mozilla_antitrackingservice_h |