1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et 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 #include "mozilla/BasePrincipal.h"
9 #include "nsDocShell.h"
11 #include "ExpandedPrincipal.h"
12 #include "nsNetUtil.h"
13 #include "nsContentUtils.h"
14 #include "nsIOService.h"
15 #include "nsIURIWithSpecialOrigin.h"
16 #include "nsScriptSecurityManager.h"
17 #include "nsServiceManagerUtils.h"
18 #include "nsAboutProtocolUtils.h"
19 #include "ThirdPartyUtil.h"
20 #include "mozilla/ContentPrincipal.h"
21 #include "mozilla/NullPrincipal.h"
22 #include "mozilla/dom/BlobURLProtocolHandler.h"
23 #include "mozilla/dom/ChromeUtils.h"
24 #include "mozilla/dom/ReferrerInfo.h"
25 #include "mozilla/dom/ToJSValue.h"
26 #include "mozilla/dom/nsMixedContentBlocker.h"
27 #include "mozilla/Components.h"
28 #include "mozilla/dom/StorageUtils.h"
29 #include "mozilla/dom/StorageUtils.h"
31 #include "nsEffectiveTLDService.h"
32 #include "nsIURIMutator.h"
33 #include "mozilla/StaticPrefs_permissions.h"
34 #include "nsIURIMutator.h"
36 #include "nsIURIFixup.h"
37 #include "mozilla/dom/StorageUtils.h"
38 #include "mozilla/ContentBlocking.h"
39 #include "nsPIDOMWindow.h"
40 #include "nsIURIMutator.h"
42 #include "json/json.h"
43 #include "nsSerializationHelper.h"
47 BasePrincipal::BasePrincipal(PrincipalKind aKind
)
48 : mKind(aKind
), mHasExplicitDomain(false), mInitialized(false) {}
50 BasePrincipal::~BasePrincipal() {}
53 BasePrincipal::GetOrigin(nsACString
& aOrigin
) {
54 MOZ_ASSERT(mInitialized
);
56 nsresult rv
= GetOriginNoSuffix(aOrigin
);
57 NS_ENSURE_SUCCESS(rv
, rv
);
60 rv
= GetOriginSuffix(suffix
);
61 NS_ENSURE_SUCCESS(rv
, rv
);
62 aOrigin
.Append(suffix
);
67 BasePrincipal::GetAsciiOrigin(nsACString
& aOrigin
) {
69 nsCOMPtr
<nsIURI
> prinURI
;
70 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
71 if (NS_FAILED(rv
) || !prinURI
) {
72 return NS_ERROR_NOT_AVAILABLE
;
74 return nsContentUtils::GetASCIIOrigin(prinURI
, aOrigin
);
78 BasePrincipal::GetHostPort(nsACString
& aRes
) {
80 nsCOMPtr
<nsIURI
> prinURI
;
81 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
82 if (NS_FAILED(rv
) || !prinURI
) {
85 return prinURI
->GetHostPort(aRes
);
89 BasePrincipal::GetHost(nsACString
& aRes
) {
91 nsCOMPtr
<nsIURI
> prinURI
;
92 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
93 if (NS_FAILED(rv
) || !prinURI
) {
96 return prinURI
->GetHost(aRes
);
100 BasePrincipal::GetOriginNoSuffix(nsACString
& aOrigin
) {
101 MOZ_ASSERT(mInitialized
);
102 mOriginNoSuffix
->ToUTF8String(aOrigin
);
107 BasePrincipal::GetSiteOrigin(nsACString
& aSiteOrigin
) {
108 MOZ_ASSERT(mInitialized
);
110 nsresult rv
= GetSiteOriginNoSuffix(aSiteOrigin
);
111 NS_ENSURE_SUCCESS(rv
, rv
);
113 nsAutoCString suffix
;
114 rv
= GetOriginSuffix(suffix
);
115 NS_ENSURE_SUCCESS(rv
, rv
);
116 aSiteOrigin
.Append(suffix
);
121 BasePrincipal::GetSiteOriginNoSuffix(nsACString
& aSiteOrigin
) {
122 MOZ_ASSERT(mInitialized
);
123 return GetOriginNoSuffix(aSiteOrigin
);
126 // Returns the inner Json::value of the serialized principal
127 // Example input and return values:
129 // {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
130 // {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
132 // Content principal:
133 // {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
135 // Expanded principal:
136 // {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
137 // {"0":"<base64principal1>,<base64principal2>"}
141 // The aKey passed in also returns the corresponding PrincipalKind enum
143 // Warning: The Json::Value* pointer is into the aRoot object
144 static const Json::Value
* GetPrincipalObject(const Json::Value
& aRoot
,
145 int& aOutPrincipalKind
) {
146 const Json::Value::Members members
= aRoot
.getMemberNames();
147 // We only support one top level key in the object
148 if (members
.size() != 1) {
151 // members[0] here is the "0", "1", "2", "3" principalKind
152 // that is the top level of the serialized JSON principal
153 const std::string stringPrincipalKind
= members
[0];
155 // Next we take the string value from the JSON
156 // and convert it into the int for the BasePrincipal::PrincipalKind enum
158 // Verify that the key is within the valid range
159 int principalKind
= std::stoi(stringPrincipalKind
);
160 MOZ_ASSERT(BasePrincipal::eNullPrincipal
== 0,
161 "We need to rely on 0 being a bounds check for the first "
163 if (principalKind
< 0 || principalKind
> BasePrincipal::eKindMax
) {
166 MOZ_ASSERT(principalKind
== BasePrincipal::eNullPrincipal
||
167 principalKind
== BasePrincipal::eContentPrincipal
||
168 principalKind
== BasePrincipal::eExpandedPrincipal
||
169 principalKind
== BasePrincipal::eSystemPrincipal
);
170 aOutPrincipalKind
= principalKind
;
172 if (!aRoot
[stringPrincipalKind
].isObject()) {
176 // Return the inner value of the principal object
177 return &aRoot
[stringPrincipalKind
];
180 // Accepts the JSON inner object without the wrapping principalKind
181 // (See GetPrincipalObject for the inner object response examples)
182 // Creates an array of KeyVal objects that are all defined on the principal
183 // Each principal type (null, content, expanded) has a KeyVal that stores the
184 // fields of the JSON
186 // This simplifies deserializing elsewhere as we do the checking for presence
187 // and string values here for the complete set of serializable keys that the
188 // corresponding principal supports.
190 // The KeyVal object has the following fields:
191 // - valueWasSerialized: is true if the deserialized JSON contained a string
193 // - value: The string that was serialized for this key
194 // - key: an SerializableKeys enum value specific to the principal.
195 // For example content principal is an enum of: eURI, eDomain,
199 // Given an inner content principal:
200 // {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
202 // ----------------------------- |
204 // Key ----------------------
208 // They Key "0" corresponds to ContentPrincipal::eURI
209 // They Key "1" corresponds to ContentPrincipal::eSuffix
210 template <typename T
>
211 static nsTArray
<typename
T::KeyVal
> GetJSONKeys(const Json::Value
* aInput
) {
212 int size
= T::eMax
+ 1;
213 nsTArray
<typename
T::KeyVal
> fields
;
214 for (int i
= 0; i
!= size
; i
++) {
215 typename
T::KeyVal
* field
= fields
.AppendElement();
216 // field->valueWasSerialized returns if the field was found in the
217 // deserialized code. This simplifies the consumers from having to check
219 field
->valueWasSerialized
= false;
220 field
->key
= static_cast<typename
T::SerializableKeys
>(i
);
221 const std::string key
= std::to_string(field
->key
);
222 if (aInput
->isMember(key
)) {
223 const Json::Value
& val
= (*aInput
)[key
];
224 if (val
.isString()) {
225 field
->value
.Append(nsDependentCString(val
.asCString()));
226 field
->valueWasSerialized
= true;
233 // Takes a JSON string and parses it turning it into a principal of the
234 // corresponding type
236 // Given a content principal:
240 // ---------------------------------------------------------
242 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
244 // | ----------------------------- |
246 // PrincipalKind | | |
247 // | ----------------------------
248 // SerializableKeys |
251 // The string is first deserialized with jsoncpp to get the Json::Value of the
252 // object. The inner JSON object is parsed with GetPrincipalObject which returns
253 // a KeyVal array of the inner object's fields. PrincipalKind is returned by
254 // GetPrincipalObject which is then used to decide which principal
255 // implementation of FromProperties to call. The corresponding FromProperties
256 // call takes the KeyVal fields and turns it into a principal.
257 already_AddRefed
<BasePrincipal
> BasePrincipal::FromJSON(
258 const nsACString
& aJSON
) {
260 Json::CharReaderBuilder builder
;
261 std::unique_ptr
<Json::CharReader
> const reader(builder
.newCharReader());
263 reader
->parse(aJSON
.BeginReading(), aJSON
.EndReading(), &root
, nullptr);
266 "Unable to parse string as JSON to deserialize as a principal");
270 int principalKind
= -1;
271 const Json::Value
* value
= GetPrincipalObject(root
, principalKind
);
274 fprintf(stderr
, "Unexpected JSON principal %s\n",
275 root
.toStyledString().c_str());
277 MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
281 MOZ_ASSERT(principalKind
!= -1,
282 "PrincipalKind should always be >=0 by this point");
284 if (principalKind
== eSystemPrincipal
) {
285 RefPtr
<BasePrincipal
> principal
=
286 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
287 return principal
.forget();
290 if (principalKind
== eNullPrincipal
) {
291 nsTArray
<NullPrincipal::KeyVal
> res
= GetJSONKeys
<NullPrincipal
>(value
);
292 return NullPrincipal::FromProperties(res
);
295 if (principalKind
== eContentPrincipal
) {
296 nsTArray
<ContentPrincipal::KeyVal
> res
=
297 GetJSONKeys
<ContentPrincipal
>(value
);
298 return ContentPrincipal::FromProperties(res
);
301 if (principalKind
== eExpandedPrincipal
) {
302 nsTArray
<ExpandedPrincipal::KeyVal
> res
=
303 GetJSONKeys
<ExpandedPrincipal
>(value
);
304 return ExpandedPrincipal::FromProperties(res
);
307 MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
310 nsresult
BasePrincipal::PopulateJSONObject(Json::Value
& aObject
) {
314 // Returns a JSON representation of the principal.
315 // Calling BasePrincipal::FromJSON will deserialize the JSON into
316 // the corresponding principal type.
317 nsresult
BasePrincipal::ToJSON(nsACString
& aResult
) {
318 MOZ_ASSERT(aResult
.IsEmpty(), "ToJSON only supports an empty result input");
321 Json::StreamWriterBuilder builder
;
322 builder
["indentation"] = "";
323 Json::Value innerJSONObject
= Json::objectValue
;
325 nsresult rv
= PopulateJSONObject(innerJSONObject
);
326 NS_ENSURE_SUCCESS(rv
, rv
);
328 Json::Value root
= Json::objectValue
;
329 std::string key
= std::to_string(Kind());
330 root
[key
] = innerJSONObject
;
331 std::string result
= Json::writeString(builder
, root
);
332 aResult
.Append(result
);
333 if (aResult
.Length() == 0) {
334 MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
335 return NS_ERROR_UNEXPECTED
;
340 bool BasePrincipal::FastSubsumesIgnoringFPD(
341 nsIPrincipal
* aOther
, DocumentDomainConsideration aConsideration
) {
344 if (Kind() == eContentPrincipal
&&
345 !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
346 mOriginAttributes
, Cast(aOther
)->mOriginAttributes
)) {
350 return SubsumesInternal(aOther
, aConsideration
);
353 bool BasePrincipal::Subsumes(nsIPrincipal
* aOther
,
354 DocumentDomainConsideration aConsideration
) {
356 MOZ_ASSERT_IF(Kind() == eContentPrincipal
, mOriginSuffix
);
358 // Expanded principals handle origin attributes for each of their
359 // sub-principals individually, null principals do only simple checks for
360 // pointer equality, and system principals are immune to origin attributes
361 // checks, so only do this check for content principals.
362 if (Kind() == eContentPrincipal
&&
363 mOriginSuffix
!= Cast(aOther
)->mOriginSuffix
) {
367 return SubsumesInternal(aOther
, aConsideration
);
371 BasePrincipal::Equals(nsIPrincipal
* aOther
, bool* aResult
) {
372 NS_ENSURE_ARG_POINTER(aOther
);
374 *aResult
= FastEquals(aOther
);
380 BasePrincipal::EqualsForPermission(nsIPrincipal
* aOther
, bool aExactHost
,
383 NS_ENSURE_ARG_POINTER(aOther
);
384 NS_ENSURE_ARG_POINTER(aResult
);
386 // If the principals are equal, then they match.
387 if (FastEquals(aOther
)) {
392 // If we are matching with an exact host, we're done now - the permissions
393 // don't match otherwise, we need to start comparing subdomains!
398 // Compare their OriginAttributes
399 const mozilla::OriginAttributes
& theirAttrs
= aOther
->OriginAttributesRef();
400 const mozilla::OriginAttributes
& ourAttrs
= OriginAttributesRef();
402 if (theirAttrs
!= ourAttrs
) {
406 nsCOMPtr
<nsIURI
> ourURI
;
407 nsresult rv
= GetURI(getter_AddRefs(ourURI
));
408 NS_ENSURE_SUCCESS(rv
, rv
);
409 auto* basePrin
= BasePrincipal::Cast(aOther
);
411 nsCOMPtr
<nsIURI
> otherURI
;
412 rv
= basePrin
->GetURI(getter_AddRefs(otherURI
));
413 NS_ENSURE_SUCCESS(rv
, rv
);
415 nsAutoCString otherScheme
;
416 rv
= otherURI
->GetScheme(otherScheme
);
417 NS_ENSURE_SUCCESS(rv
, rv
);
419 nsAutoCString ourScheme
;
420 rv
= ourURI
->GetScheme(ourScheme
);
421 NS_ENSURE_SUCCESS(rv
, rv
);
423 if (otherScheme
!= ourScheme
) {
429 rv
= otherURI
->GetPort(&otherPort
);
430 NS_ENSURE_SUCCESS(rv
, rv
);
433 rv
= ourURI
->GetPort(&ourPort
);
434 NS_ENSURE_SUCCESS(rv
, rv
);
436 if (otherPort
!= ourPort
) {
440 // Check if the host or any subdomain of their host matches.
441 nsAutoCString otherHost
;
442 rv
= otherURI
->GetHost(otherHost
);
443 if (NS_FAILED(rv
) || otherHost
.IsEmpty()) {
447 nsAutoCString ourHost
;
448 rv
= ourURI
->GetHost(ourHost
);
449 if (NS_FAILED(rv
) || ourHost
.IsEmpty()) {
453 nsCOMPtr
<nsIEffectiveTLDService
> tldService
=
454 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID
);
456 NS_ERROR("Should have a tld service!");
457 return NS_ERROR_FAILURE
;
460 // This loop will not loop forever, as GetNextSubDomain will eventually fail
461 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
462 while (otherHost
!= ourHost
) {
463 rv
= tldService
->GetNextSubDomain(otherHost
, otherHost
);
465 if (rv
== NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
) {
477 BasePrincipal::EqualsConsideringDomain(nsIPrincipal
* aOther
, bool* aResult
) {
478 NS_ENSURE_ARG_POINTER(aOther
);
480 *aResult
= FastEqualsConsideringDomain(aOther
);
486 BasePrincipal::EqualsURI(nsIURI
* aOtherURI
, bool* aResult
) {
488 nsCOMPtr
<nsIURI
> prinURI
;
489 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
490 if (NS_FAILED(rv
) || !prinURI
) {
493 return prinURI
->EqualsExceptRef(aOtherURI
, aResult
);
497 BasePrincipal::Subsumes(nsIPrincipal
* aOther
, bool* aResult
) {
498 NS_ENSURE_ARG_POINTER(aOther
);
500 *aResult
= FastSubsumes(aOther
);
506 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal
* aOther
, bool* aResult
) {
507 NS_ENSURE_ARG_POINTER(aOther
);
509 *aResult
= FastSubsumesConsideringDomain(aOther
);
515 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal
* aOther
,
517 NS_ENSURE_ARG_POINTER(aOther
);
519 *aResult
= FastSubsumesConsideringDomainIgnoringFPD(aOther
);
525 BasePrincipal::CheckMayLoad(nsIURI
* aURI
, bool aAllowIfInheritsPrincipal
) {
526 return CheckMayLoadHelper(aURI
, aAllowIfInheritsPrincipal
, false, 0);
530 BasePrincipal::CheckMayLoadWithReporting(nsIURI
* aURI
,
531 bool aAllowIfInheritsPrincipal
,
532 uint64_t aInnerWindowID
) {
533 return CheckMayLoadHelper(aURI
, aAllowIfInheritsPrincipal
, true,
537 nsresult
BasePrincipal::CheckMayLoadHelper(nsIURI
* aURI
,
538 bool aAllowIfInheritsPrincipal
,
540 uint64_t aInnerWindowID
) {
541 NS_ENSURE_ARG_POINTER(aURI
);
543 aReport
|| aInnerWindowID
== 0,
544 "Why do we have an inner window id if we're not supposed to report?");
546 // Check the internal method first, which allows us to quickly approve loads
547 // for the System Principal.
548 if (MayLoadInternal(aURI
)) {
553 if (aAllowIfInheritsPrincipal
) {
554 // If the caller specified to allow loads of URIs that inherit
555 // our principal, allow the load if this URI inherits its principal.
556 bool doesInheritSecurityContext
;
557 rv
= NS_URIChainHasFlags(aURI
,
558 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
559 &doesInheritSecurityContext
);
560 if (NS_SUCCEEDED(rv
) && doesInheritSecurityContext
) {
565 bool fetchableByAnyone
;
566 rv
= NS_URIChainHasFlags(aURI
, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE
,
568 if (NS_SUCCEEDED(rv
) && fetchableByAnyone
) {
573 nsCOMPtr
<nsIURI
> prinURI
;
574 rv
= GetURI(getter_AddRefs(prinURI
));
575 if (NS_SUCCEEDED(rv
) && prinURI
) {
576 nsScriptSecurityManager::ReportError(
577 "CheckSameOriginError", prinURI
, aURI
,
578 mOriginAttributes
.mPrivateBrowsingId
> 0, aInnerWindowID
);
582 return NS_ERROR_DOM_BAD_URI
;
586 BasePrincipal::IsThirdPartyURI(nsIURI
* aURI
, bool* aRes
) {
587 if (IsSystemPrincipal() || (AddonPolicy() && AddonAllowsLoad(aURI
))) {
593 // If we do not have a URI its always 3rd party.
594 nsCOMPtr
<nsIURI
> prinURI
;
595 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
596 if (NS_FAILED(rv
) || !prinURI
) {
599 ThirdPartyUtil
* thirdPartyUtil
= ThirdPartyUtil::GetInstance();
600 return thirdPartyUtil
->IsThirdPartyURI(prinURI
, aURI
, aRes
);
604 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal
* aPrin
, bool* aRes
) {
606 nsCOMPtr
<nsIURI
> prinURI
;
607 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
608 if (NS_FAILED(rv
) || !prinURI
) {
611 return aPrin
->IsThirdPartyURI(prinURI
, aRes
);
614 BasePrincipal::IsThirdPartyChannel(nsIChannel
* aChan
, bool* aRes
) {
615 if (IsSystemPrincipal()) {
616 // Nothing is 3rd party to the system principal.
621 nsCOMPtr
<nsIURI
> prinURI
;
622 GetURI(getter_AddRefs(prinURI
));
623 ThirdPartyUtil
* thirdPartyUtil
= ThirdPartyUtil::GetInstance();
624 return thirdPartyUtil
->IsThirdPartyChannel(aChan
, prinURI
, aRes
);
628 BasePrincipal::IsSameOrigin(nsIURI
* aURI
, bool aIsPrivateWin
, bool* aRes
) {
630 nsCOMPtr
<nsIURI
> prinURI
;
631 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
632 if (NS_FAILED(rv
) || !prinURI
) {
635 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
637 return NS_ERROR_UNEXPECTED
;
639 *aRes
= NS_SUCCEEDED(
640 ssm
->CheckSameOriginURI(prinURI
, aURI
, false, aIsPrivateWin
));
645 BasePrincipal::IsL10nAllowed(nsIURI
* aURI
, bool* aRes
) {
648 if (nsContentUtils::IsErrorPage(aURI
)) {
653 // The system principal is always allowed.
654 if (IsSystemPrincipal()) {
659 nsCOMPtr
<nsIURI
> uri
;
660 nsresult rv
= GetURI(getter_AddRefs(uri
));
661 NS_ENSURE_SUCCESS(rv
, NS_OK
);
665 // Allow access to uris that cannot be loaded by web content.
666 rv
= NS_URIChainHasFlags(uri
, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
,
668 NS_ENSURE_SUCCESS(rv
, NS_OK
);
674 // UI resources also get access.
675 rv
= NS_URIChainHasFlags(uri
, nsIProtocolHandler::URI_IS_UI_RESOURCE
,
677 NS_ENSURE_SUCCESS(rv
, NS_OK
);
683 auto policy
= AddonPolicy();
684 *aRes
= (policy
&& policy
->IsPrivileged());
689 BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI
* aURI
, bool* aRes
) {
691 nsCOMPtr
<nsIURI
> prinURI
;
692 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
693 if (NS_FAILED(rv
) || !prinURI
) {
696 *aRes
= NS_RelaxStrictFileOriginPolicy(aURI
, prinURI
);
701 BasePrincipal::GetPrefLightCacheKey(nsIURI
* aURI
, bool aWithCredentials
,
702 const OriginAttributes
& aOriginAttributes
,
703 nsACString
& _retval
) {
705 constexpr auto space
= " "_ns
;
707 nsCOMPtr
<nsIURI
> uri
;
708 nsresult rv
= GetURI(getter_AddRefs(uri
));
709 NS_ENSURE_SUCCESS(rv
, rv
);
711 nsAutoCString scheme
, host
, port
;
713 uri
->GetScheme(scheme
);
715 port
.AppendInt(NS_GetRealPort(uri
));
718 if (aWithCredentials
) {
719 _retval
.AssignLiteral("cred");
721 _retval
.AssignLiteral("nocred");
725 rv
= aURI
->GetSpec(spec
);
726 NS_ENSURE_SUCCESS(rv
, rv
);
728 nsAutoCString originAttributesSuffix
;
729 aOriginAttributes
.CreateSuffix(originAttributesSuffix
);
731 _retval
.Append(space
+ scheme
+ space
+ host
+ space
+ port
+ space
+ spec
+
732 space
+ originAttributesSuffix
);
738 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow
* aCheckWindow
,
739 uint32_t* aRejectedReason
,
741 *aRejectedReason
= 0;
742 *aOutAllowed
= false;
744 nsPIDOMWindowInner
* win
= nsPIDOMWindowInner::From(aCheckWindow
);
745 nsCOMPtr
<nsIURI
> uri
;
746 nsresult rv
= GetURI(getter_AddRefs(uri
));
751 ContentBlocking::ShouldAllowAccessFor(win
, uri
, aRejectedReason
);
756 BasePrincipal::GetIsNullPrincipal(bool* aResult
) {
757 *aResult
= Kind() == eNullPrincipal
;
762 BasePrincipal::GetIsContentPrincipal(bool* aResult
) {
763 *aResult
= Kind() == eContentPrincipal
;
768 BasePrincipal::GetIsExpandedPrincipal(bool* aResult
) {
769 *aResult
= Kind() == eExpandedPrincipal
;
774 BasePrincipal::GetAsciiSpec(nsACString
& aSpec
) {
776 nsCOMPtr
<nsIURI
> prinURI
;
777 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
778 if (NS_FAILED(rv
) || !prinURI
) {
781 return prinURI
->GetAsciiSpec(aSpec
);
785 BasePrincipal::GetSpec(nsACString
& aSpec
) {
787 nsCOMPtr
<nsIURI
> prinURI
;
788 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
789 if (NS_FAILED(rv
) || !prinURI
) {
792 return prinURI
->GetSpec(aSpec
);
796 BasePrincipal::GetAsciiHost(nsACString
& aHost
) {
798 nsCOMPtr
<nsIURI
> prinURI
;
799 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
800 if (NS_FAILED(rv
) || !prinURI
) {
803 return prinURI
->GetAsciiHost(aHost
);
807 BasePrincipal::GetExposablePrePath(nsACString
& aPrepath
) {
809 nsCOMPtr
<nsIURI
> prinURI
;
810 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
811 if (NS_FAILED(rv
) || !prinURI
) {
815 nsCOMPtr
<nsIURI
> exposableURI
= net::nsIOService::CreateExposableURI(prinURI
);
816 return exposableURI
->GetDisplayPrePath(aPrepath
);
820 BasePrincipal::GetExposableSpec(nsACString
& aSpec
) {
822 nsCOMPtr
<nsIURI
> prinURI
;
823 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
824 if (NS_FAILED(rv
) || !prinURI
) {
827 nsCOMPtr
<nsIURI
> clone
;
828 rv
= NS_MutateURI(prinURI
)
833 NS_ENSURE_SUCCESS(rv
, rv
);
834 return clone
->GetAsciiSpec(aSpec
);
838 BasePrincipal::GetPrepath(nsACString
& aPath
) {
840 nsCOMPtr
<nsIURI
> prinURI
;
841 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
842 if (NS_FAILED(rv
) || !prinURI
) {
845 return prinURI
->GetPrePath(aPath
);
849 BasePrincipal::GetFilePath(nsACString
& aPath
) {
851 nsCOMPtr
<nsIURI
> prinURI
;
852 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
853 if (NS_FAILED(rv
) || !prinURI
) {
856 return prinURI
->GetFilePath(aPath
);
860 BasePrincipal::GetIsSystemPrincipal(bool* aResult
) {
861 *aResult
= IsSystemPrincipal();
866 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult
) {
867 *aResult
= AddonPolicy() || ContentScriptAddonPolicy();
871 NS_IMETHODIMP
BasePrincipal::GetIsOnion(bool* aIsOnion
) {
873 nsCOMPtr
<nsIURI
> prinURI
;
874 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
875 if (NS_FAILED(rv
) || !prinURI
) {
880 rv
= prinURI
->GetHost(host
);
884 *aIsOnion
= StringEndsWith(host
, ".onion"_ns
);
888 NS_IMETHODIMP
BasePrincipal::GetIsIpAddress(bool* aIsIpAddress
) {
889 *aIsIpAddress
= false;
891 nsCOMPtr
<nsIURI
> prinURI
;
892 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
893 if (NS_FAILED(rv
) || !prinURI
) {
898 rv
= prinURI
->GetHost(host
);
904 memset(&prAddr
, 0, sizeof(prAddr
));
906 if (PR_StringToNetAddr(host
.get(), &prAddr
) == PR_SUCCESS
) {
907 *aIsIpAddress
= true;
913 NS_IMETHODIMP
BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress
) {
914 *aIsIpAddress
= false;
916 nsCOMPtr
<nsIURI
> prinURI
;
917 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
918 if (NS_FAILED(rv
) || !prinURI
) {
922 nsCOMPtr
<nsIIOService
> ioService
= do_GetIOService(&rv
);
923 if (NS_FAILED(rv
) || !ioService
) {
926 rv
= ioService
->HostnameIsLocalIPAddress(prinURI
, aIsIpAddress
);
928 *aIsIpAddress
= false;
934 BasePrincipal::GetScheme(nsACString
& aScheme
) {
937 nsCOMPtr
<nsIURI
> prinURI
;
938 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
939 if (NS_FAILED(rv
) || !prinURI
) {
943 return prinURI
->GetScheme(aScheme
);
947 BasePrincipal::SchemeIs(const char* aScheme
, bool* aResult
) {
949 nsCOMPtr
<nsIURI
> prinURI
;
950 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
951 if (NS_FAILED(rv
) || !prinURI
) {
954 *aResult
= prinURI
->SchemeIs(aScheme
);
959 BasePrincipal::IsURIInPrefList(const char* aPref
, bool* aResult
) {
961 nsCOMPtr
<nsIURI
> prinURI
;
962 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
963 if (NS_FAILED(rv
) || !prinURI
) {
966 *aResult
= nsContentUtils::IsURIInPrefList(prinURI
, aPref
);
971 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult
) {
972 MOZ_ASSERT(NS_IsMainThread());
975 nsCOMPtr
<nsIURI
> uri
;
976 nsresult rv
= GetURI(getter_AddRefs(uri
));
977 if (NS_FAILED(rv
) || !uri
) {
981 *aResult
= nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri
);
986 BasePrincipal::GetAboutModuleFlags(uint32_t* flags
) {
988 nsCOMPtr
<nsIURI
> prinURI
;
989 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
990 if (NS_FAILED(rv
) || !prinURI
) {
991 return NS_ERROR_NOT_AVAILABLE
;
993 if (!prinURI
->SchemeIs("about")) {
997 nsCOMPtr
<nsIAboutModule
> aboutModule
;
998 rv
= NS_GetAboutModule(prinURI
, getter_AddRefs(aboutModule
));
999 if (NS_FAILED(rv
) || !aboutModule
) {
1002 return aboutModule
->GetURIFlags(prinURI
, flags
);
1006 BasePrincipal::GetOriginAttributes(JSContext
* aCx
,
1007 JS::MutableHandle
<JS::Value
> aVal
) {
1008 if (NS_WARN_IF(!ToJSValue(aCx
, mOriginAttributes
, aVal
))) {
1009 return NS_ERROR_FAILURE
;
1015 BasePrincipal::GetOriginSuffix(nsACString
& aOriginAttributes
) {
1016 MOZ_ASSERT(mOriginSuffix
);
1017 mOriginSuffix
->ToUTF8String(aOriginAttributes
);
1022 BasePrincipal::GetUserContextId(uint32_t* aUserContextId
) {
1023 *aUserContextId
= UserContextId();
1028 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId
) {
1029 *aPrivateBrowsingId
= PrivateBrowsingId();
1034 BasePrincipal::GetIsInIsolatedMozBrowserElement(
1035 bool* aIsInIsolatedMozBrowserElement
) {
1036 *aIsInIsolatedMozBrowserElement
= IsInIsolatedMozBrowserElement();
1040 nsresult
BasePrincipal::GetAddonPolicy(nsISupports
** aResult
) {
1041 RefPtr
<extensions::WebExtensionPolicy
> policy(AddonPolicy());
1042 policy
.forget(aResult
);
1046 extensions::WebExtensionPolicy
* BasePrincipal::AddonPolicy() {
1047 if (Is
<ContentPrincipal
>()) {
1048 return As
<ContentPrincipal
>()->AddonPolicy();
1053 bool BasePrincipal::AddonHasPermission(const nsAtom
* aPerm
) {
1054 if (auto policy
= AddonPolicy()) {
1055 return policy
->HasPermission(aPerm
);
1060 nsIPrincipal
* BasePrincipal::PrincipalToInherit(nsIURI
* aRequestedURI
) {
1061 if (Is
<ExpandedPrincipal
>()) {
1062 return As
<ExpandedPrincipal
>()->PrincipalToInherit(aRequestedURI
);
1067 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1068 nsIURI
* aURI
, const OriginAttributes
& aAttrs
) {
1071 nsAutoCString originNoSuffix
;
1073 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI
, originNoSuffix
);
1074 if (NS_FAILED(rv
)) {
1075 // If the generation of the origin fails, we still want to have a valid
1076 // principal. Better to return a null principal here.
1077 return NullPrincipal::Create(aAttrs
);
1080 return CreateContentPrincipal(aURI
, aAttrs
, originNoSuffix
);
1083 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1084 nsIURI
* aURI
, const OriginAttributes
& aAttrs
,
1085 const nsACString
& aOriginNoSuffix
) {
1087 MOZ_ASSERT(!aOriginNoSuffix
.IsEmpty());
1089 // If the URI is supposed to inherit the security context of whoever loads it,
1090 // we shouldn't make a content principal for it.
1091 bool inheritsPrincipal
;
1092 nsresult rv
= NS_URIChainHasFlags(
1093 aURI
, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
1094 &inheritsPrincipal
);
1095 if (NS_FAILED(rv
) || inheritsPrincipal
) {
1096 return NullPrincipal::Create(aAttrs
);
1099 // Check whether the URI knows what its principal is supposed to be.
1100 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
1101 nsCOMPtr
<nsIURIWithSpecialOrigin
> uriWithSpecialOrigin
=
1102 do_QueryInterface(aURI
);
1103 if (uriWithSpecialOrigin
) {
1104 nsCOMPtr
<nsIURI
> origin
;
1105 rv
= uriWithSpecialOrigin
->GetOrigin(getter_AddRefs(origin
));
1106 if (NS_WARN_IF(NS_FAILED(rv
))) {
1110 OriginAttributes attrs
;
1111 RefPtr
<BasePrincipal
> principal
= CreateContentPrincipal(origin
, attrs
);
1112 return principal
.forget();
1116 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
1117 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
1118 aURI
, getter_AddRefs(blobPrincipal
))) {
1119 MOZ_ASSERT(blobPrincipal
);
1120 RefPtr
<BasePrincipal
> principal
= Cast(blobPrincipal
);
1121 return principal
.forget();
1124 // Mint a content principal.
1125 RefPtr
<ContentPrincipal
> principal
= new ContentPrincipal();
1126 rv
= principal
->Init(aURI
, aAttrs
, aOriginNoSuffix
);
1127 NS_ENSURE_SUCCESS(rv
, nullptr);
1128 return principal
.forget();
1131 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1132 const nsACString
& aOrigin
) {
1133 MOZ_ASSERT(!StringBeginsWith(aOrigin
, "["_ns
),
1134 "CreateContentPrincipal does not support System and Expanded "
1138 !StringBeginsWith(aOrigin
, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME
":")),
1139 "CreateContentPrincipal does not support NullPrincipal");
1141 nsAutoCString originNoSuffix
;
1142 OriginAttributes attrs
;
1143 if (!attrs
.PopulateFromOrigin(aOrigin
, originNoSuffix
)) {
1147 nsCOMPtr
<nsIURI
> uri
;
1148 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), originNoSuffix
);
1149 NS_ENSURE_SUCCESS(rv
, nullptr);
1151 return BasePrincipal::CreateContentPrincipal(uri
, attrs
);
1154 already_AddRefed
<BasePrincipal
> BasePrincipal::CloneForcingOriginAttributes(
1155 const OriginAttributes
& aOriginAttributes
) {
1156 if (NS_WARN_IF(!IsContentPrincipal())) {
1160 nsAutoCString originNoSuffix
;
1161 nsresult rv
= GetOriginNoSuffix(originNoSuffix
);
1162 NS_ENSURE_SUCCESS(rv
, nullptr);
1164 nsIURI
* uri
= static_cast<ContentPrincipal
*>(this)->mURI
;
1165 RefPtr
<ContentPrincipal
> copy
= new ContentPrincipal();
1166 rv
= copy
->Init(uri
, aOriginAttributes
, originNoSuffix
);
1167 NS_ENSURE_SUCCESS(rv
, nullptr);
1169 return copy
.forget();
1172 extensions::WebExtensionPolicy
* BasePrincipal::ContentScriptAddonPolicy() {
1173 if (!Is
<ExpandedPrincipal
>()) {
1177 auto expanded
= As
<ExpandedPrincipal
>();
1178 for (auto& prin
: expanded
->AllowList()) {
1179 if (auto policy
= BasePrincipal::Cast(prin
)->AddonPolicy()) {
1187 bool BasePrincipal::AddonAllowsLoad(nsIURI
* aURI
,
1188 bool aExplicit
/* = false */) {
1189 if (Is
<ExpandedPrincipal
>()) {
1190 return As
<ExpandedPrincipal
>()->AddonAllowsLoad(aURI
, aExplicit
);
1192 if (auto policy
= AddonPolicy()) {
1193 return policy
->CanAccessURI(aURI
, aExplicit
);
1198 void BasePrincipal::FinishInit(const nsACString
& aOriginNoSuffix
,
1199 const OriginAttributes
& aOriginAttributes
) {
1200 mInitialized
= true;
1201 mOriginAttributes
= aOriginAttributes
;
1203 // First compute the origin suffix since it's infallible.
1204 nsAutoCString originSuffix
;
1205 mOriginAttributes
.CreateSuffix(originSuffix
);
1206 mOriginSuffix
= NS_Atomize(originSuffix
);
1208 MOZ_ASSERT(!aOriginNoSuffix
.IsEmpty());
1209 mOriginNoSuffix
= NS_Atomize(aOriginNoSuffix
);
1212 void BasePrincipal::FinishInit(BasePrincipal
* aOther
,
1213 const OriginAttributes
& aOriginAttributes
) {
1214 mInitialized
= true;
1215 mOriginAttributes
= aOriginAttributes
;
1217 // First compute the origin suffix since it's infallible.
1218 nsAutoCString originSuffix
;
1219 mOriginAttributes
.CreateSuffix(originSuffix
);
1220 mOriginSuffix
= NS_Atomize(originSuffix
);
1222 mOriginNoSuffix
= aOther
->mOriginNoSuffix
;
1223 mHasExplicitDomain
= aOther
->mHasExplicitDomain
;
1227 BasePrincipal::GetLocalStorageQuotaKey(nsACString
& aKey
) {
1230 nsCOMPtr
<nsIURI
> uri
;
1231 nsresult rv
= GetURI(getter_AddRefs(uri
));
1232 NS_ENSURE_SUCCESS(rv
, rv
);
1233 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
1235 // The special handling of the file scheme should be consistent with
1236 // GetStorageOriginKey.
1238 nsAutoCString baseDomain
;
1239 rv
= uri
->GetAsciiHost(baseDomain
);
1240 NS_ENSURE_SUCCESS(rv
, rv
);
1242 if (baseDomain
.IsEmpty() && uri
->SchemeIs("file")) {
1243 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(uri
, &rv
);
1244 NS_ENSURE_SUCCESS(rv
, rv
);
1246 rv
= url
->GetDirectory(baseDomain
);
1247 NS_ENSURE_SUCCESS(rv
, rv
);
1249 nsCOMPtr
<nsIEffectiveTLDService
> eTLDService(
1250 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID
, &rv
));
1251 NS_ENSURE_SUCCESS(rv
, rv
);
1253 nsAutoCString eTLDplusOne
;
1254 rv
= eTLDService
->GetBaseDomain(uri
, 0, eTLDplusOne
);
1255 if (NS_SUCCEEDED(rv
)) {
1256 baseDomain
= eTLDplusOne
;
1257 } else if (rv
== NS_ERROR_HOST_IS_IP_ADDRESS
||
1258 rv
== NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
) {
1261 NS_ENSURE_SUCCESS(rv
, rv
);
1264 OriginAttributesRef().CreateSuffix(aKey
);
1266 nsAutoCString subdomainsDBKey
;
1267 rv
= dom::StorageUtils::CreateReversedDomain(baseDomain
, subdomainsDBKey
);
1268 NS_ENSURE_SUCCESS(rv
, rv
);
1271 aKey
.Append(subdomainsDBKey
);
1277 BasePrincipal::GetNextSubDomainPrincipal(
1278 nsIPrincipal
** aNextSubDomainPrincipal
) {
1279 nsCOMPtr
<nsIURI
> uri
;
1280 nsresult rv
= GetURI(getter_AddRefs(uri
));
1281 if (NS_FAILED(rv
) || !uri
) {
1286 rv
= uri
->GetHost(host
);
1287 if (NS_FAILED(rv
) || host
.IsEmpty()) {
1291 nsCString subDomain
;
1292 rv
= nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host
, subDomain
);
1294 if (NS_FAILED(rv
) || subDomain
.IsEmpty()) {
1298 nsCOMPtr
<nsIURI
> subDomainURI
;
1299 rv
= NS_MutateURI(uri
).SetHost(subDomain
).Finalize(subDomainURI
);
1300 if (NS_FAILED(rv
) || !subDomainURI
) {
1303 // Copy the attributes over
1304 mozilla::OriginAttributes attrs
= OriginAttributesRef();
1306 if (!StaticPrefs::permissions_isolateBy_userContext()) {
1307 // Disable userContext for permissions.
1308 attrs
.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID
);
1310 RefPtr
<nsIPrincipal
> principal
=
1311 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI
, attrs
);
1316 principal
.forget(aNextSubDomainPrincipal
);
1321 BasePrincipal::GetStorageOriginKey(nsACString
& aOriginKey
) {
1322 aOriginKey
.Truncate();
1324 nsCOMPtr
<nsIURI
> uri
;
1325 nsresult rv
= GetURI(getter_AddRefs(uri
));
1326 NS_ENSURE_SUCCESS(rv
, rv
);
1327 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
1329 // The special handling of the file scheme should be consistent with
1330 // GetLocalStorageQuotaKey.
1332 nsAutoCString domainOrigin
;
1333 rv
= uri
->GetAsciiHost(domainOrigin
);
1334 NS_ENSURE_SUCCESS(rv
, rv
);
1336 if (domainOrigin
.IsEmpty()) {
1337 // For the file:/// protocol use the exact directory as domain.
1338 if (uri
->SchemeIs("file")) {
1339 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(uri
, &rv
);
1340 NS_ENSURE_SUCCESS(rv
, rv
);
1341 rv
= url
->GetDirectory(domainOrigin
);
1342 NS_ENSURE_SUCCESS(rv
, rv
);
1346 // Append reversed domain
1347 nsAutoCString reverseDomain
;
1348 rv
= dom::StorageUtils::CreateReversedDomain(domainOrigin
, reverseDomain
);
1349 NS_ENSURE_SUCCESS(rv
, rv
);
1351 aOriginKey
.Append(reverseDomain
);
1354 nsAutoCString scheme
;
1355 rv
= uri
->GetScheme(scheme
);
1356 NS_ENSURE_SUCCESS(rv
, rv
);
1358 aOriginKey
.Append(':');
1359 aOriginKey
.Append(scheme
);
1361 // Append port if any
1362 int32_t port
= NS_GetRealPort(uri
);
1364 aOriginKey
.Append(nsPrintfCString(":%d", port
));
1371 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy
) {
1372 *aIsScriptAllowedByPolicy
= false;
1373 nsCOMPtr
<nsIURI
> prinURI
;
1374 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
1375 if (NS_FAILED(rv
) || !prinURI
) {
1378 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
1380 return NS_ERROR_UNEXPECTED
;
1382 return ssm
->PolicyAllowsScript(prinURI
, aIsScriptAllowedByPolicy
);
1385 bool SiteIdentifier::Equals(const SiteIdentifier
& aOther
) const {
1386 MOZ_ASSERT(IsInitialized());
1387 MOZ_ASSERT(aOther
.IsInitialized());
1388 return mPrincipal
->FastEquals(aOther
.mPrincipal
);
1392 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy
,
1393 nsIReferrerInfo
** _retval
) {
1394 nsCOMPtr
<nsIURI
> prinURI
;
1395 RefPtr
<dom::ReferrerInfo
> info
;
1396 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
1397 if (NS_FAILED(rv
) || !prinURI
) {
1398 info
= new dom::ReferrerInfo(nullptr);
1399 info
.forget(_retval
);
1402 info
= new dom::ReferrerInfo(prinURI
, aReferrerPolicy
);
1403 info
.forget(_retval
);
1407 } // namespace mozilla