Bug 1795172 [wpt PR 36447] - Disallow culled inlines in repeated content., a=testonly
[gecko.git] / dom / security / ReferrerInfo.h
blob79746678ac7b88e8e676b6c871d3eef5de1f3855
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_dom_ReferrerInfo_h
8 #define mozilla_dom_ReferrerInfo_h
10 #include "nsCOMPtr.h"
11 #include "nsIReferrerInfo.h"
12 #include "nsReadableUtils.h"
13 #include "mozilla/Maybe.h"
14 #include "mozilla/HashFunctions.h"
15 #include "mozilla/dom/ReferrerPolicyBinding.h"
17 #define REFERRERINFOF_CONTRACTID "@mozilla.org/referrer-info;1"
18 // 041a129f-10ce-4bda-a60d-e027a26d5ed0
19 #define REFERRERINFO_CID \
20 { \
21 0x041a129f, 0x10ce, 0x4bda, { \
22 0xa6, 0x0d, 0xe0, 0x27, 0xa2, 0x6d, 0x5e, 0xd0 \
23 } \
26 class nsIHttpChannel;
27 class nsIURI;
28 class nsIChannel;
29 class nsILoadInfo;
30 class nsINode;
31 class nsIPrincipal;
33 namespace mozilla {
34 class StyleSheet;
35 class URLAndReferrerInfo;
37 namespace net {
38 class HttpBaseChannel;
39 class nsHttpChannel;
40 } // namespace net
41 } // namespace mozilla
43 using mozilla::Maybe;
45 namespace mozilla::dom {
47 /**
48 * The ReferrerInfo class holds the raw referrer and potentially a referrer
49 * policy which allows to query the computed referrer which should be applied to
50 * a channel as the actual referrer value.
52 * The ReferrerInfo class solely contains readonly fields and represents a 1:1
53 * sync to the referrer header of the corresponding channel. In turn that means
54 * the class is immutable - so any modifications require to clone the current
55 * ReferrerInfo.
57 * For example if a request undergoes a redirect, the new channel
58 * will need a new ReferrerInfo clone with members being updated accordingly.
61 class ReferrerInfo : public nsIReferrerInfo {
62 public:
63 typedef enum ReferrerPolicy ReferrerPolicyEnum;
64 ReferrerInfo();
66 explicit ReferrerInfo(
67 nsIURI* aOriginalReferrer,
68 ReferrerPolicyEnum aPolicy = ReferrerPolicy::_empty,
69 bool aSendReferrer = true,
70 const Maybe<nsCString>& aComputedReferrer = Maybe<nsCString>());
72 // Creates already initialized ReferrerInfo from an element or a document.
73 explicit ReferrerInfo(const Element&);
74 explicit ReferrerInfo(const Document&);
76 // create an exact copy of the ReferrerInfo
77 already_AddRefed<ReferrerInfo> Clone() const;
79 // create an copy of the ReferrerInfo with new referrer policy
80 already_AddRefed<ReferrerInfo> CloneWithNewPolicy(
81 ReferrerPolicyEnum aPolicy) const;
83 // create an copy of the ReferrerInfo with new send referrer
84 already_AddRefed<ReferrerInfo> CloneWithNewSendReferrer(
85 bool aSendReferrer) const;
87 // create an copy of the ReferrerInfo with new original referrer
88 already_AddRefed<ReferrerInfo> CloneWithNewOriginalReferrer(
89 nsIURI* aOriginalReferrer) const;
91 // Record the telemetry for the referrer policy.
92 void RecordTelemetry(nsIHttpChannel* aChannel);
95 * Helper function to create a new ReferrerInfo object from other. We will not
96 * pass in any computed values and override referrer policy if needed
98 * @param aOther the other referrerInfo object to init from.
99 * @param aPolicyOverride referrer policy to override if necessary.
101 static already_AddRefed<nsIReferrerInfo> CreateFromOtherAndPolicyOverride(
102 nsIReferrerInfo* aOther, ReferrerPolicyEnum aPolicyOverride);
105 * Helper function to create a new ReferrerInfo object from a given document
106 * and override referrer policy if needed (for example, when parsing link
107 * header or speculative loading).
109 * @param aDocument the document to init referrerInfo object.
110 * @param aPolicyOverride referrer policy to override if necessary.
112 static already_AddRefed<nsIReferrerInfo> CreateFromDocumentAndPolicyOverride(
113 Document* aDoc, ReferrerPolicyEnum aPolicyOverride);
116 * Implements step 3.1 and 3.3 of the Determine request's Referrer algorithm
117 * from the Referrer Policy specification.
119 * https://w3c.github.io/webappsec/specs/referrer-policy/#determine-requests-referrer
121 static already_AddRefed<nsIReferrerInfo> CreateForFetch(
122 nsIPrincipal* aPrincipal, Document* aDoc);
125 * Helper function to create new ReferrerInfo object from a given external
126 * stylesheet. The returned nsIReferrerInfo object will be used for any
127 * requests or resources referenced by the sheet.
129 * @param aSheet the stylesheet to init referrerInfo.
130 * @param aPolicy referrer policy from header if there's any.
132 static already_AddRefed<nsIReferrerInfo> CreateForExternalCSSResources(
133 StyleSheet* aExternalSheet,
134 ReferrerPolicyEnum aPolicy = ReferrerPolicy::_empty);
137 * Helper function to create new ReferrerInfo object from a given document.
138 * The returned nsIReferrerInfo object will be used for any requests or
139 * resources referenced by internal stylesheet (for example style="" or
140 * wrapped by <style> tag).
142 * @param aDocument the document to init referrerInfo object.
144 static already_AddRefed<nsIReferrerInfo> CreateForInternalCSSResources(
145 Document* aDocument);
148 * Helper function to create new ReferrerInfo object from a given document.
149 * The returned nsIReferrerInfo object will be used for any requests or
150 * resources referenced by SVG.
152 * @param aDocument the document to init referrerInfo object.
154 static already_AddRefed<nsIReferrerInfo> CreateForSVGResources(
155 Document* aDocument);
158 * Check whether the given referrer's scheme is allowed to be computed and
159 * sent. The allowlist schemes are: http, https.
161 static bool IsReferrerSchemeAllowed(nsIURI* aReferrer);
164 * The Referrer Policy should be inherited for nested browsing contexts that
165 * are not created from responses. Such as: srcdoc, data, blob.
167 static bool ShouldResponseInheritReferrerInfo(nsIChannel* aChannel);
170 * Check whether referrer is allowed to send in secure to insecure scenario.
172 static nsresult HandleSecureToInsecureReferral(nsIURI* aOriginalURI,
173 nsIURI* aURI,
174 ReferrerPolicyEnum aPolicy,
175 bool& aAllowed);
178 * Returns true if the given channel is cross-origin request
180 * Computing whether the request is cross-origin may be expensive, so please
181 * do that in cases where we're going to use this information later on.
183 static bool IsCrossOriginRequest(nsIHttpChannel* aChannel);
186 * Returns true if the given channel is cross-site request.
188 static bool IsCrossSiteRequest(nsIHttpChannel* aChannel);
191 * Returns true if the given channel is suppressed by Referrer-Policy header
192 * and should set "null" to Origin header.
194 static bool ShouldSetNullOriginHeader(net::HttpBaseChannel* aChannel,
195 nsIURI* aOriginURI);
198 * Getter for network.http.sendRefererHeader.
200 static uint32_t GetUserReferrerSendingPolicy();
203 * Getter for network.http.referer.XOriginPolicy.
205 static uint32_t GetUserXOriginSendingPolicy();
208 * Getter for network.http.referer.trimmingPolicy.
210 static uint32_t GetUserTrimmingPolicy();
213 * Getter for network.http.referer.XOriginTrimmingPolicy.
215 static uint32_t GetUserXOriginTrimmingPolicy();
218 * Return default referrer policy which is controlled by user
219 * prefs:
220 * network.http.referer.defaultPolicy for regular mode
221 * network.http.referer.defaultPolicy.trackers for third-party trackers
222 * in regular mode
223 * network.http.referer.defaultPolicy.pbmode for private mode
224 * network.http.referer.defaultPolicy.trackers.pbmode for third-party trackers
225 * in private mode
227 static ReferrerPolicyEnum GetDefaultReferrerPolicy(
228 nsIHttpChannel* aChannel = nullptr, nsIURI* aURI = nullptr,
229 bool aPrivateBrowsing = false);
232 * Return default referrer policy for third party which is controlled by user
233 * prefs:
234 * network.http.referer.defaultPolicy.trackers for regular mode
235 * network.http.referer.defaultPolicy.trackers.pbmode for private mode
237 static ReferrerPolicyEnum GetDefaultThirdPartyReferrerPolicy(
238 bool aPrivateBrowsing = false);
241 * Helper function to parse ReferrerPolicy from meta tag referrer content.
242 * For example: <meta name="referrer" content="origin">
244 * @param aContent content string to be transformed into ReferrerPolicyEnum,
245 * e.g. "origin".
247 static ReferrerPolicyEnum ReferrerPolicyFromMetaString(
248 const nsAString& aContent);
251 * Helper function to parse ReferrerPolicy from string content of
252 * referrerpolicy attribute.
253 * For example: <a href="http://example.com" referrerpolicy="no-referrer">
255 * @param aContent content string to be transformed into ReferrerPolicyEnum,
256 * e.g. "no-referrer".
258 static ReferrerPolicyEnum ReferrerPolicyAttributeFromString(
259 const nsAString& aContent);
262 * Helper function to parse ReferrerPolicy from string content of
263 * Referrer-Policy header.
264 * For example: Referrer-Policy: origin no-referrer
265 * https://www.w3.org/tr/referrer-policy/#parse-referrer-policy-from-header
267 * @param aContent content string to be transformed into ReferrerPolicyEnum.
268 * e.g. "origin no-referrer"
270 static ReferrerPolicyEnum ReferrerPolicyFromHeaderString(
271 const nsAString& aContent);
274 * Helper function to convert ReferrerPolicy enum to string
276 * @param aPolicy referrer policy to convert.
278 static const char* ReferrerPolicyToString(ReferrerPolicyEnum aPolicy);
281 * Hash function for this object
283 HashNumber Hash() const;
285 NS_DECL_THREADSAFE_ISUPPORTS
286 NS_DECL_NSIREFERRERINFO
287 NS_DECL_NSISERIALIZABLE
289 private:
290 virtual ~ReferrerInfo() = default;
292 ReferrerInfo(const ReferrerInfo& rhs);
295 * Trimming policy when compute referrer, indicate how much information in the
296 * referrer will be sent. Order matters here.
298 enum TrimmingPolicy : uint32_t {
299 ePolicyFullURI = 0,
300 ePolicySchemeHostPortPath = 1,
301 ePolicySchemeHostPort = 2,
305 * Referrer sending policy, indicates type of action could trigger to send
306 * referrer header, not send at all, send only with user's action (click on a
307 * link) or send even with inline content request (image request).
308 * Order matters here.
310 enum ReferrerSendingPolicy : uint32_t {
311 ePolicyNotSend = 0,
312 ePolicySendWhenUserTrigger = 1,
313 ePolicySendInlineContent = 2,
317 * Sending referrer when cross origin policy, indicates when referrer should
318 * be send when compare 2 origins. Order matters here.
320 enum XOriginSendingPolicy : uint32_t {
321 ePolicyAlwaysSend = 0,
322 ePolicySendWhenSameDomain = 1,
323 ePolicySendWhenSameHost = 2,
327 * Handle user controlled pref network.http.referer.XOriginPolicy
329 nsresult HandleUserXOriginSendingPolicy(nsIURI* aURI, nsIURI* aReferrer,
330 bool& aAllowed) const;
333 * Handle user controlled pref network.http.sendRefererHeader
335 nsresult HandleUserReferrerSendingPolicy(nsIHttpChannel* aChannel,
336 bool& aAllowed) const;
339 * Compute trimming policy from user controlled prefs.
340 * This function is called when we already made sure a nonempty referrer is
341 * allowed to send.
343 TrimmingPolicy ComputeTrimmingPolicy(nsIHttpChannel* aChannel) const;
345 // HttpBaseChannel could access IsInitialized() and ComputeReferrer();
346 friend class mozilla::net::HttpBaseChannel;
349 * Compute referrer for a given channel. The computation result then will be
350 * stored in this class and then used to set the actual referrer header of
351 * the channel. The computation could be controlled by several user prefs
352 * which are defined in StaticPrefList.yaml (see StaticPrefList.yaml for more
353 * details):
354 * network.http.sendRefererHeader
355 * network.http.referer.spoofSource
356 * network.http.referer.hideOnionSource
357 * network.http.referer.XOriginPolicy
358 * network.http.referer.trimmingPolicy
359 * network.http.referer.XOriginTrimmingPolicy
361 nsresult ComputeReferrer(nsIHttpChannel* aChannel);
364 * Check whether the ReferrerInfo has been initialized or not.
366 bool IsInitialized() { return mInitialized; }
368 // nsHttpChannel, Document could access IsPolicyOverrided();
369 friend class mozilla::net::nsHttpChannel;
370 friend class mozilla::dom::Document;
372 * Check whether if unset referrer policy is overrided by default or not
374 bool IsPolicyOverrided() { return mOverridePolicyByDefault; }
377 * Get origin string from a given valid referrer URI (http, https)
379 * @aReferrer - the full referrer URI
380 * @aResult - the resulting aReferrer in string format.
382 nsresult GetOriginFromReferrerURI(nsIURI* aReferrer,
383 nsACString& aResult) const;
386 * Trim a given referrer with a given a trimming policy,
388 nsresult TrimReferrerWithPolicy(nsIURI* aReferrer,
389 TrimmingPolicy aTrimmingPolicy,
390 nsACString& aResult) const;
393 * Returns true if we should ignore less restricted referrer policies,
394 * including 'unsafe_url', 'no_referrer_when_downgrade' and
395 * 'origin_when_cross_origin', for the given channel. We only apply this
396 * restriction for cross-site requests. For the same-site request, we will
397 * still allow overriding the default referrer policy with less restricted
398 * one.
400 * Note that the channel triggered by the system and the extension will be
401 * exempt from this restriction.
403 bool ShouldIgnoreLessRestrictedPolicies(
404 nsIHttpChannel* aChannel, const ReferrerPolicyEnum aPolicy) const;
407 * Limit referrer length using the following ruleset:
408 * - If the length of referrer URL is over max length, strip down to origin.
409 * - If the origin is still over max length, remove the referrer entirely.
411 * This function comlements TrimReferrerPolicy and needs to be called right
412 * after TrimReferrerPolicy.
414 * @aChannel - used to query information needed for logging to the console.
415 * @aReferrer - the full referrer URI; needs to be identical to aReferrer
416 * passed to TrimReferrerPolicy.
417 * @aTrimmingPolicy - represents the trimming policy which was applied to the
418 * referrer; needs to be identical to aTrimmingPolicy
419 * passed to TrimReferrerPolicy.
420 * @aInAndOutTrimmedReferrer - an in and outgoing argument representing the
421 * referrer value. Please pass the result of
422 * TrimReferrerWithPolicy as
423 * aInAndOutTrimmedReferrer which will then be
424 * reduced to the origin or completely truncated
425 * in case the referrer value exceeds the length
426 * limitation.
428 nsresult LimitReferrerLength(nsIHttpChannel* aChannel, nsIURI* aReferrer,
429 TrimmingPolicy aTrimmingPolicy,
430 nsACString& aInAndOutTrimmedReferrer) const;
433 * The helper function to read the old data format before gecko 100 for
434 * deserialization.
436 nsresult ReadTailDataBeforeGecko100(const uint32_t& aData,
437 nsIObjectInputStream* aInputStream);
440 * Write message to the error console
442 void LogMessageToConsole(nsIHttpChannel* aChannel, const char* aMsg,
443 const nsTArray<nsString>& aParams) const;
445 friend class mozilla::URLAndReferrerInfo;
447 nsCOMPtr<nsIURI> mOriginalReferrer;
449 ReferrerPolicyEnum mPolicy;
451 // The referrer policy that has been set originally for the channel. Note that
452 // the policy may have been overridden by the default referrer policy, so we
453 // need to keep track of this if we need to recover the original referrer
454 // policy.
455 ReferrerPolicyEnum mOriginalPolicy;
457 // Indicates if the referrer should be sent or not even when it's available
458 // (default is true).
459 bool mSendReferrer;
461 // Since the ReferrerInfo is immutable, we use this member as a helper to
462 // ensure no one can call e.g. init() twice to modify state of the
463 // ReferrerInfo.
464 bool mInitialized;
466 // Indicates if unset referrer policy is overrided by default
467 bool mOverridePolicyByDefault;
469 // Store a computed referrer for a given channel
470 Maybe<nsCString> mComputedReferrer;
472 #ifdef DEBUG
473 // Indicates if the telemetry has been recorded. This is used to make sure the
474 // telemetry will be only recored once.
475 bool mTelemetryRecorded = false;
476 #endif // DEBUG
479 } // namespace mozilla::dom
481 #endif // mozilla_dom_ReferrerInfo_h