Bug 1869043 assert that graph set access is main thread only r=padenot
[gecko.git] / netwerk / cookie / CookieJarSettings.h
blob97f8528a5540d15c4f06ee3396878a60069e4676
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_net_CookieJarSettings_h
8 #define mozilla_net_CookieJarSettings_h
10 #include "mozilla/Maybe.h"
12 #include "nsICookieJarSettings.h"
13 #include "nsTArray.h"
15 #define COOKIEJARSETTINGS_CONTRACTID "@mozilla.org/cookieJarSettings;1"
16 // 4ce234f1-52e8-47a9-8c8d-b02f815733c7
17 #define COOKIEJARSETTINGS_CID \
18 { \
19 0x4ce234f1, 0x52e8, 0x47a9, { \
20 0x8c, 0x8d, 0xb0, 0x2f, 0x81, 0x57, 0x33, 0xc7 \
21 } \
24 class nsIPermission;
26 namespace mozilla {
27 namespace net {
29 class CookieJarSettingsArgs;
31 /**
32 * CookieJarSettings
33 * ~~~~~~~~~~~~~~
35 * CookieJarSettings is a snapshot of the cookie jar's configurations in a
36 * precise moment of time, such as the cookie policy and cookie permissions.
37 * This object is used by top-level documents to have a consistent cookie jar
38 * configuration also in case the user changes it. New configurations will apply
39 * only to new top-level documents.
41 * CookieJarSettings creation
42 * ~~~~~~~~~~~~~~~~~~~~~~~
44 * CookieJarSettings is created when the top-level document's nsIChannel's
45 * nsILoadInfo is constructed. Any sub-resource and any sub-document inherits it
46 * from that nsILoadInfo. Also dedicated workers and their resources inherit it
47 * from the parent document.
49 * SharedWorkers and ServiceWorkers have their own CookieJarSettings because
50 * they don't have a single parent document (SharedWorkers could have more than
51 * one, ServiceWorkers have none).
53 * In Chrome code, we have a new CookieJarSettings when we download resources
54 * via 'Save-as...' and we also have a new CookieJarSettings for favicon
55 * downloading.
57 * Content-scripts WebExtensions also have their own CookieJarSettings because
58 * they don't have a direct access to the document they are running into.
60 * Anything else will have a special CookieJarSettings which blocks everything
61 * (CookieJarSettings::GetBlockingAll()) by forcing BEHAVIOR_REJECT as policy.
62 * When this happens, that context will not have access to the cookie jar and no
63 * cookies are sent or received.
65 * Propagation of CookieJarSettings
66 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68 * CookieJarSettings are shared inside the same top-level document via its
69 * nsIChannel's nsILoadInfo. This is done automatically if you pass a nsINode
70 * to NS_NewChannel(), and it must be done manually if you use a different
71 * channel constructor. For instance, this happens for any worker networking
72 * operation.
74 * We use the same CookieJarSettings for any resource belonging to the top-level
75 * document even if cross-origin. This makes the browser behave consistently a
76 * scenario where A loads B which loads A again, and cookie policy/permission
77 * changes in the meantime.
79 * Cookie Permissions propagation
80 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82 * CookieJarSettings populates the known cookie permissions only when required.
83 * Initially the list is empty, but when CookieJarSettings::CookiePermission()
84 * is called, the requested permission is stored in the internal list if it
85 * doesn't exist yet.
87 * This is actually nice because it relies on the permission propagation from
88 * parent to content process. No extra IPC is required.
90 * Note that we store permissions with UNKNOWN_ACTION values too because they
91 * can be set after the loading of the top-level document and we don't want to
92 * return a different value when this happens.
94 * Use of CookieJarSettings
95 * ~~~~~~~~~~~~~~~~~~~~~
97 * In theory, there should not be direct access to cookie permissions or
98 * cookieBehavior pref. Everything should pass through CookieJarSettings.
100 * A reference to CookieJarSettings can be obtained from
101 * nsILoadInfo::GetCookieJarSettings(), from Document::CookieJarSettings() and
102 * from the WorkerPrivate::CookieJarSettings().
104 * CookieJarSettings is thread-safe, but the permission list must be touched
105 * only on the main-thread.
107 * Testing
108 * ~~~~~~~
110 * If you need to test the changing of cookie policy or a cookie permission, you
111 * need to workaround CookieJarSettings. This can be done opening a new window
112 * and running the test into that new global.
116 * Class that provides an nsICookieJarSettings implementation.
118 class CookieJarSettings final : public nsICookieJarSettings {
119 public:
120 typedef nsTArray<RefPtr<nsIPermission>> CookiePermissionList;
122 NS_DECL_THREADSAFE_ISUPPORTS
123 NS_DECL_NSICOOKIEJARSETTINGS
124 NS_DECL_NSISERIALIZABLE
126 static already_AddRefed<nsICookieJarSettings> GetBlockingAll(
127 bool aShouldResistFingerprinting);
129 enum CreateMode { eRegular, ePrivate };
131 static already_AddRefed<nsICookieJarSettings> Create(
132 CreateMode aMode, bool aShouldResistFingerprinting);
134 static already_AddRefed<nsICookieJarSettings> Create(
135 nsIPrincipal* aPrincipal);
137 // This function should be only called for XPCOM. You should never use this
138 // for other purposes.
139 static already_AddRefed<nsICookieJarSettings> CreateForXPCOM();
141 static already_AddRefed<nsICookieJarSettings> Create(
142 uint32_t aCookieBehavior, const nsAString& aPartitionKey,
143 bool aIsFirstPartyIsolated, bool aIsOnContentBlockingAllowList,
144 bool aShouldResistFingerprinting);
146 static CookieJarSettings* Cast(nsICookieJarSettings* aCS) {
147 return static_cast<CookieJarSettings*>(aCS);
150 void Serialize(CookieJarSettingsArgs& aData);
152 static void Deserialize(const CookieJarSettingsArgs& aData,
153 nsICookieJarSettings** aCookieJarSettings);
155 void Merge(const CookieJarSettingsArgs& aData);
157 // We don't want to send this object from parent to child process if there are
158 // no reasons. HasBeenChanged() returns true if the object has changed its
159 // internal state and it must be sent beck to the content process.
160 bool HasBeenChanged() const { return mToBeMerged; }
162 void UpdateIsOnContentBlockingAllowList(nsIChannel* aChannel);
164 void SetPartitionKey(nsIURI* aURI);
165 void SetPartitionKey(const nsAString& aPartitionKey) {
166 mPartitionKey = aPartitionKey;
168 const nsAString& GetPartitionKey() { return mPartitionKey; };
170 void SetFingerprintingRandomizationKey(const nsTArray<uint8_t>& aKey) {
171 mFingerprintingRandomKey.reset();
173 mFingerprintingRandomKey.emplace(aKey.Clone());
176 // Utility function to test if the passed cookiebahvior is
177 // BEHAVIOR_REJECT_TRACKER, BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN or
178 // BEHAVIOR_REJECT_FOREIGN when
179 // network.cookie.rejectForeignWithExceptions.enabled pref is set to true.
180 static bool IsRejectThirdPartyContexts(uint32_t aCookieBehavior);
182 private:
183 enum State {
184 // No cookie permissions are allowed to be stored in this object.
185 eFixed,
187 // Cookie permissions can be stored in case they are unknown when they are
188 // asked or when they are sent from the parent process.
189 eProgressive,
192 CookieJarSettings(uint32_t aCookieBehavior, bool aIsFirstPartyIsolated,
193 bool aShouldResistFingerprinting, State aState);
194 ~CookieJarSettings();
196 uint32_t mCookieBehavior;
197 bool mIsFirstPartyIsolated;
198 CookiePermissionList mCookiePermissions;
199 bool mIsOnContentBlockingAllowList;
200 bool mIsOnContentBlockingAllowListUpdated;
201 nsString mPartitionKey;
203 State mState;
205 bool mToBeMerged;
207 // DO NOT USE THIS MEMBER TO CHECK IF YOU SHOULD RESIST FINGERPRINTING.
208 // USE THE nsContentUtils::ShouldResistFingerprinting() METHODS ONLY.
210 // As we move to fine-grained RFP control, we want to support per-domain
211 // exemptions from ResistFingerprinting. Specifically the behavior should be
212 // as such:
214 // Top-Level Document is on an Exempted Domain
215 // - RFP is disabled.
217 // Top-Level Document on an Exempted Domain embedding a non-exempted
218 // cross-origin iframe
219 // - RFP in the iframe is enabled (NOT exempted). (**)
221 // Top-Level Document on an Exempted Domain embedding an exempted cross-origin
222 // iframe
223 // - RFP in the iframe is disabled (exempted).
225 // Top-Level Document on a Non-Exempted Domain
226 // - RFP is enabled (NOT exempted).
228 // Top-Level Document on a Non-Exempted Domain embeds an exempted cross-origin
229 // iframe
230 // - RFP in the iframe is enabled (NOT exempted). (*)
232 // Exempted Document (top-level or iframe) contacts any cross-origin domain
233 // (exempted or non-exempted)
234 // - RFP is disabled (exempted) for the request
236 // Non-Exempted Document (top-level or iframe) contacts any cross-origin
237 // domain
238 // (exempted or non-exempted)
239 // - RFP is enabled (NOT exempted) for the request
241 // This boolean on CookieJarSettings will enable us to apply the most
242 // difficult rule, marked in (*). (It is difficult because the
243 // subdocument's loadinfo will look like it should be exempted.)
244 // However if we trusted this member blindly, it would not correctly apply
245 // the one marked with (**). (Because it would inherit an exemption into
246 // a subdocument that should not be exempted.)
247 // To handle this case, we only trust a CookieJar's ShouldRFP value if it
248 // says we should resist fingerprinting. If it says that we _should not_,
249 // we continue and check the channel's URI or LoadInfo and if
250 // the domain specified there is not an exempted domain, enforce RFP anyway.
251 // This all occurrs in the nscontentUtils::ShouldResistFingerprinting
252 // functions which you should be using.
253 bool mShouldResistFingerprinting;
255 // The key used to generate the random noise for randomizing the browser
256 // fingerprint. The key is decided by the session key and the top-level site.
257 // So, the browse fingerprint will look different to the same tracker
258 // under different top-level sites. Also, the fingerprint will change as
259 // browsing session changes. This can prevent trackers to identify individuals
260 // by using browser fingerprints.
261 Maybe<nsTArray<uint8_t>> mFingerprintingRandomKey;
264 } // namespace net
265 } // namespace mozilla
267 #endif // mozilla_net_CookieJarSettings_h