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
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 \
21 0x041a129f, 0x10ce, 0x4bda, { \
22 0xa6, 0x0d, 0xe0, 0x27, 0xa2, 0x6d, 0x5e, 0xd0 \
35 class URLAndReferrerInfo
;
38 class HttpBaseChannel
;
41 } // namespace mozilla
43 namespace mozilla::dom
{
46 * The ReferrerInfo class holds the raw referrer and potentially a referrer
47 * policy which allows to query the computed referrer which should be applied to
48 * a channel as the actual referrer value.
50 * The ReferrerInfo class solely contains readonly fields and represents a 1:1
51 * sync to the referrer header of the corresponding channel. In turn that means
52 * the class is immutable - so any modifications require to clone the current
55 * For example if a request undergoes a redirect, the new channel
56 * will need a new ReferrerInfo clone with members being updated accordingly.
59 class ReferrerInfo
: public nsIReferrerInfo
{
61 typedef enum ReferrerPolicy ReferrerPolicyEnum
;
64 explicit ReferrerInfo(
65 nsIURI
* aOriginalReferrer
,
66 ReferrerPolicyEnum aPolicy
= ReferrerPolicy::_empty
,
67 bool aSendReferrer
= true,
68 const Maybe
<nsCString
>& aComputedReferrer
= Maybe
<nsCString
>());
70 // Creates already initialized ReferrerInfo from an element or a document.
71 explicit ReferrerInfo(const Element
&);
72 explicit ReferrerInfo(const Document
&);
74 // create an exact copy of the ReferrerInfo
75 already_AddRefed
<ReferrerInfo
> Clone() const;
77 // create an copy of the ReferrerInfo with new referrer policy
78 already_AddRefed
<ReferrerInfo
> CloneWithNewPolicy(
79 ReferrerPolicyEnum aPolicy
) const;
81 // create an copy of the ReferrerInfo with new send referrer
82 already_AddRefed
<ReferrerInfo
> CloneWithNewSendReferrer(
83 bool aSendReferrer
) const;
85 // create an copy of the ReferrerInfo with new original referrer
86 already_AddRefed
<ReferrerInfo
> CloneWithNewOriginalReferrer(
87 nsIURI
* aOriginalReferrer
) const;
89 // Record the telemetry for the referrer policy.
90 void RecordTelemetry(nsIHttpChannel
* aChannel
);
93 * Helper function to create a new ReferrerInfo object from other. We will not
94 * pass in any computed values and override referrer policy if needed
96 * @param aOther the other referrerInfo object to init from.
97 * @param aPolicyOverride referrer policy to override if necessary.
99 static already_AddRefed
<nsIReferrerInfo
> CreateFromOtherAndPolicyOverride(
100 nsIReferrerInfo
* aOther
, ReferrerPolicyEnum aPolicyOverride
);
103 * Helper function to create a new ReferrerInfo object from a given document
104 * and override referrer policy if needed (for example, when parsing link
105 * header or speculative loading).
107 * @param aDocument the document to init referrerInfo object.
108 * @param aPolicyOverride referrer policy to override if necessary.
110 static already_AddRefed
<nsIReferrerInfo
> CreateFromDocumentAndPolicyOverride(
111 Document
* aDoc
, ReferrerPolicyEnum aPolicyOverride
);
114 * Implements step 3.1 and 3.3 of the Determine request's Referrer algorithm
115 * from the Referrer Policy specification.
117 * https://w3c.github.io/webappsec/specs/referrer-policy/#determine-requests-referrer
119 static already_AddRefed
<nsIReferrerInfo
> CreateForFetch(
120 nsIPrincipal
* aPrincipal
, Document
* aDoc
);
123 * Helper function to create new ReferrerInfo object from a given external
124 * stylesheet. The returned nsIReferrerInfo object will be used for any
125 * requests or resources referenced by the sheet.
127 * @param aSheet the stylesheet to init referrerInfo.
128 * @param aPolicy referrer policy from header if there's any.
130 static already_AddRefed
<nsIReferrerInfo
> CreateForExternalCSSResources(
131 StyleSheet
* aExternalSheet
,
132 ReferrerPolicyEnum aPolicy
= ReferrerPolicy::_empty
);
135 * Helper function to create new ReferrerInfo object from a given document.
136 * The returned nsIReferrerInfo object will be used for any requests or
137 * resources referenced by internal stylesheet (for example style="" or
138 * wrapped by <style> tag), as well as SVG resources.
140 * @param aDocument the document to init referrerInfo object.
142 static already_AddRefed
<nsIReferrerInfo
> CreateForInternalCSSAndSVGResources(
143 Document
* aDocument
);
146 * Check whether the given referrer's scheme is allowed to be computed and
147 * sent. The allowlist schemes are: http, https.
149 static bool IsReferrerSchemeAllowed(nsIURI
* aReferrer
);
152 * The Referrer Policy should be inherited for nested browsing contexts that
153 * are not created from responses. Such as: srcdoc, data, blob.
155 static bool ShouldResponseInheritReferrerInfo(nsIChannel
* aChannel
);
158 * Check whether referrer is allowed to send in secure to insecure scenario.
160 static nsresult
HandleSecureToInsecureReferral(nsIURI
* aOriginalURI
,
162 ReferrerPolicyEnum aPolicy
,
166 * Returns true if the given channel is cross-origin request
168 * Computing whether the request is cross-origin may be expensive, so please
169 * do that in cases where we're going to use this information later on.
171 static bool IsCrossOriginRequest(nsIHttpChannel
* aChannel
);
174 * Returns true if aReferrer's origin and aChannel's URI are cross-origin.
176 static bool IsReferrerCrossOrigin(nsIHttpChannel
* aChannel
,
180 * Returns true if the given channel is cross-site request.
182 static bool IsCrossSiteRequest(nsIHttpChannel
* aChannel
);
185 * Returns true if the given channel is suppressed by Referrer-Policy header
186 * and should set "null" to Origin header.
188 static bool ShouldSetNullOriginHeader(net::HttpBaseChannel
* aChannel
,
192 * Getter for network.http.sendRefererHeader.
194 static uint32_t GetUserReferrerSendingPolicy();
197 * Getter for network.http.referer.XOriginPolicy.
199 static uint32_t GetUserXOriginSendingPolicy();
202 * Getter for network.http.referer.trimmingPolicy.
204 static uint32_t GetUserTrimmingPolicy();
207 * Getter for network.http.referer.XOriginTrimmingPolicy.
209 static uint32_t GetUserXOriginTrimmingPolicy();
212 * Return default referrer policy which is controlled by user
214 * network.http.referer.defaultPolicy for regular mode
215 * network.http.referer.defaultPolicy.trackers for third-party trackers
217 * network.http.referer.defaultPolicy.pbmode for private mode
218 * network.http.referer.defaultPolicy.trackers.pbmode for third-party trackers
221 static ReferrerPolicyEnum
GetDefaultReferrerPolicy(
222 nsIHttpChannel
* aChannel
= nullptr, nsIURI
* aURI
= nullptr,
223 bool aPrivateBrowsing
= false);
226 * Return default referrer policy for third party which is controlled by user
228 * network.http.referer.defaultPolicy.trackers for regular mode
229 * network.http.referer.defaultPolicy.trackers.pbmode for private mode
231 static ReferrerPolicyEnum
GetDefaultThirdPartyReferrerPolicy(
232 bool aPrivateBrowsing
= false);
235 * Helper function to parse ReferrerPolicy from meta tag referrer content.
236 * For example: <meta name="referrer" content="origin">
238 * @param aContent content string to be transformed into ReferrerPolicyEnum,
241 static ReferrerPolicyEnum
ReferrerPolicyFromMetaString(
242 const nsAString
& aContent
);
245 * Helper function to parse ReferrerPolicy from string content of
246 * referrerpolicy attribute.
247 * For example: <a href="http://example.com" referrerpolicy="no-referrer">
249 * @param aContent content string to be transformed into ReferrerPolicyEnum,
250 * e.g. "no-referrer".
252 static ReferrerPolicyEnum
ReferrerPolicyAttributeFromString(
253 const nsAString
& aContent
);
256 * Helper function to parse ReferrerPolicy from string content of
257 * Referrer-Policy header.
258 * For example: Referrer-Policy: origin no-referrer
259 * https://www.w3.org/tr/referrer-policy/#parse-referrer-policy-from-header
261 * @param aContent content string to be transformed into ReferrerPolicyEnum.
262 * e.g. "origin no-referrer"
264 static ReferrerPolicyEnum
ReferrerPolicyFromHeaderString(
265 const nsAString
& aContent
);
268 * Helper function to convert ReferrerPolicy enum to string
270 * @param aPolicy referrer policy to convert.
272 static const char* ReferrerPolicyToString(ReferrerPolicyEnum aPolicy
);
275 * Hash function for this object
277 HashNumber
Hash() const;
279 NS_DECL_THREADSAFE_ISUPPORTS
280 NS_DECL_NSIREFERRERINFO
281 NS_DECL_NSISERIALIZABLE
284 virtual ~ReferrerInfo() = default;
286 ReferrerInfo(const ReferrerInfo
& rhs
);
289 * Trimming policy when compute referrer, indicate how much information in the
290 * referrer will be sent. Order matters here.
292 enum TrimmingPolicy
: uint32_t {
294 ePolicySchemeHostPortPath
= 1,
295 ePolicySchemeHostPort
= 2,
299 * Referrer sending policy, indicates type of action could trigger to send
300 * referrer header, not send at all, send only with user's action (click on a
301 * link) or send even with inline content request (image request).
302 * Order matters here.
304 enum ReferrerSendingPolicy
: uint32_t {
306 ePolicySendWhenUserTrigger
= 1,
307 ePolicySendInlineContent
= 2,
311 * Sending referrer when cross origin policy, indicates when referrer should
312 * be send when compare 2 origins. Order matters here.
314 enum XOriginSendingPolicy
: uint32_t {
315 ePolicyAlwaysSend
= 0,
316 ePolicySendWhenSameDomain
= 1,
317 ePolicySendWhenSameHost
= 2,
321 * Handle user controlled pref network.http.referer.XOriginPolicy
323 nsresult
HandleUserXOriginSendingPolicy(nsIURI
* aURI
, nsIURI
* aReferrer
,
324 bool& aAllowed
) const;
327 * Handle user controlled pref network.http.sendRefererHeader
329 nsresult
HandleUserReferrerSendingPolicy(nsIHttpChannel
* aChannel
,
330 bool& aAllowed
) const;
333 * Compute trimming policy from user controlled prefs.
334 * This function is called when we already made sure a nonempty referrer is
337 TrimmingPolicy
ComputeTrimmingPolicy(nsIHttpChannel
* aChannel
,
338 nsIURI
* aReferrer
) const;
340 // HttpBaseChannel could access IsInitialized() and ComputeReferrer();
341 friend class mozilla::net::HttpBaseChannel
;
344 * Compute referrer for a given channel. The computation result then will be
345 * stored in this class and then used to set the actual referrer header of
346 * the channel. The computation could be controlled by several user prefs
347 * which are defined in StaticPrefList.yaml (see StaticPrefList.yaml for more
349 * network.http.sendRefererHeader
350 * network.http.referer.spoofSource
351 * network.http.referer.hideOnionSource
352 * network.http.referer.XOriginPolicy
353 * network.http.referer.trimmingPolicy
354 * network.http.referer.XOriginTrimmingPolicy
356 nsresult
ComputeReferrer(nsIHttpChannel
* aChannel
);
359 * Check whether the ReferrerInfo has been initialized or not.
361 bool IsInitialized() { return mInitialized
; }
363 // nsHttpChannel, Document could access IsPolicyOverrided();
364 friend class mozilla::net::nsHttpChannel
;
365 friend class mozilla::dom::Document
;
367 * Check whether if unset referrer policy is overrided by default or not
369 bool IsPolicyOverrided() { return mOverridePolicyByDefault
; }
372 * Get origin string from a given valid referrer URI (http, https)
374 * @aReferrer - the full referrer URI
375 * @aResult - the resulting aReferrer in string format.
377 nsresult
GetOriginFromReferrerURI(nsIURI
* aReferrer
,
378 nsACString
& aResult
) const;
381 * Trim a given referrer with a given a trimming policy,
383 nsresult
TrimReferrerWithPolicy(nsIURI
* aReferrer
,
384 TrimmingPolicy aTrimmingPolicy
,
385 nsACString
& aResult
) const;
388 * Returns true if we should ignore less restricted referrer policies,
389 * including 'unsafe_url', 'no_referrer_when_downgrade' and
390 * 'origin_when_cross_origin', for the given channel. We only apply this
391 * restriction for cross-site requests. For the same-site request, we will
392 * still allow overriding the default referrer policy with less restricted
395 * Note that the channel triggered by the system and the extension will be
396 * exempt from this restriction.
398 bool ShouldIgnoreLessRestrictedPolicies(
399 nsIHttpChannel
* aChannel
, const ReferrerPolicyEnum aPolicy
) const;
402 * Limit referrer length using the following ruleset:
403 * - If the length of referrer URL is over max length, strip down to origin.
404 * - If the origin is still over max length, remove the referrer entirely.
406 * This function comlements TrimReferrerPolicy and needs to be called right
407 * after TrimReferrerPolicy.
409 * @aChannel - used to query information needed for logging to the console.
410 * @aReferrer - the full referrer URI; needs to be identical to aReferrer
411 * passed to TrimReferrerPolicy.
412 * @aTrimmingPolicy - represents the trimming policy which was applied to the
413 * referrer; needs to be identical to aTrimmingPolicy
414 * passed to TrimReferrerPolicy.
415 * @aInAndOutTrimmedReferrer - an in and outgoing argument representing the
416 * referrer value. Please pass the result of
417 * TrimReferrerWithPolicy as
418 * aInAndOutTrimmedReferrer which will then be
419 * reduced to the origin or completely truncated
420 * in case the referrer value exceeds the length
423 nsresult
LimitReferrerLength(nsIHttpChannel
* aChannel
, nsIURI
* aReferrer
,
424 TrimmingPolicy aTrimmingPolicy
,
425 nsACString
& aInAndOutTrimmedReferrer
) const;
428 * The helper function to read the old data format before gecko 100 for
431 nsresult
ReadTailDataBeforeGecko100(const uint32_t& aData
,
432 nsIObjectInputStream
* aInputStream
);
435 * Write message to the error console
437 void LogMessageToConsole(nsIHttpChannel
* aChannel
, const char* aMsg
,
438 const nsTArray
<nsString
>& aParams
) const;
440 friend class mozilla::URLAndReferrerInfo
;
442 nsCOMPtr
<nsIURI
> mOriginalReferrer
;
444 ReferrerPolicyEnum mPolicy
;
446 // The referrer policy that has been set originally for the channel. Note that
447 // the policy may have been overridden by the default referrer policy, so we
448 // need to keep track of this if we need to recover the original referrer
450 ReferrerPolicyEnum mOriginalPolicy
;
452 // Indicates if the referrer should be sent or not even when it's available
453 // (default is true).
456 // Since the ReferrerInfo is immutable, we use this member as a helper to
457 // ensure no one can call e.g. init() twice to modify state of the
461 // Indicates if unset referrer policy is overrided by default
462 bool mOverridePolicyByDefault
;
464 // Store a computed referrer for a given channel
465 Maybe
<nsCString
> mComputedReferrer
;
468 // Indicates if the telemetry has been recorded. This is used to make sure the
469 // telemetry will be only recored once.
470 bool mTelemetryRecorded
= false;
474 } // namespace mozilla::dom
476 #endif // mozilla_dom_ReferrerInfo_h