1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/* -*- 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 methods 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.org 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>
AllowAccessForOnParentProcess(
nsIPrincipal* aPrincipal, dom::BrowsingContext* aParentContext,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason,
const PerformPermissionGrant& aPerformFinalChecks = nullptr);
[[nodiscard]] static RefPtr<StorageAccessPermissionGrantPromise>
AllowAccessForOnChildProcess(
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, bool aFrameOnly,
uint64_t aExpirationTime =
StaticPrefs::privacy_restrict3rdpartystorage_expiration());
static RefPtr<ParentAccessGrantPromise> SaveAccessForOriginOnParentProcess(
uint64_t aTopLevelWindowId, dom::BrowsingContext* aParentContext,
nsIPrincipal* aTrackingPrincipal, int aAllowMode, bool aFrameOnly,
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>>
AsyncCheckCookiesPermittedDecidesStorageAccessAPIOnChildProcess(
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 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, bool aRequireUserInteraction, bool aFrameOnly,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aNotifier,
bool aRequireGrant);
private:
friend class dom::ContentParent;
// This function performs browser setting, cookie behavior and requesting
// context checks that might grant/reject storage access immediately using
// information provided by the inputs aPrincipal and aParentContext. To reduce
// redundancy the following out parameters with information also required in
// AllowAccessFor() are set in the function: aTrackingPrinciple,
// aTrackingOrigin, aTopLevelWindowId, aBehavior. If storage access can be
// granted/rejected due to settings/behavior returns a promise, else returns
// nullptr.
[[nodiscard]] static RefPtr<
StorageAccessAPIHelper::StorageAccessPermissionGrantPromise>
AllowAccessForHelper(
nsIPrincipal* aPrincipal, dom::BrowsingContext* aParentContext,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason,
nsCOMPtr<nsIPrincipal>* aTrackingPrincipal, nsACString& aTrackingOrigin,
uint64_t* aTopLevelWindowId, uint32_t* aBehavior);
[[nodiscard]] static RefPtr<StorageAccessPermissionGrantPromise>
CompleteAllowAccessForOnParentProcess(
dom::BrowsingContext* aParentContext, uint64_t aTopLevelWindowId,
nsIPrincipal* aTrackingPrincipal, const nsACString& aTrackingOrigin,
uint32_t aCookieBehavior,
ContentBlockingNotifier::StorageAccessPermissionGrantedReason aReason,
const PerformPermissionGrant& aPerformFinalChecks = nullptr);
[[nodiscard]] static RefPtr<StorageAccessPermissionGrantPromise>
CompleteAllowAccessForOnChildProcess(
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
|