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 const nsACString
& aOriginNoSuffix
,
49 const OriginAttributes
& aOriginAttributes
)
50 : mOriginNoSuffix(NS_Atomize(aOriginNoSuffix
)),
51 mOriginSuffix(aOriginAttributes
.CreateSuffixAtom()),
52 mOriginAttributes(aOriginAttributes
),
54 mHasExplicitDomain(false) {}
56 BasePrincipal::BasePrincipal(BasePrincipal
* aOther
,
57 const OriginAttributes
& aOriginAttributes
)
58 : mOriginNoSuffix(aOther
->mOriginNoSuffix
),
59 mOriginSuffix(aOriginAttributes
.CreateSuffixAtom()),
60 mOriginAttributes(aOriginAttributes
),
62 mHasExplicitDomain(aOther
->mHasExplicitDomain
) {}
64 BasePrincipal::~BasePrincipal() = default;
67 BasePrincipal::GetOrigin(nsACString
& aOrigin
) {
68 nsresult rv
= GetOriginNoSuffix(aOrigin
);
69 NS_ENSURE_SUCCESS(rv
, rv
);
72 rv
= GetOriginSuffix(suffix
);
73 NS_ENSURE_SUCCESS(rv
, rv
);
74 aOrigin
.Append(suffix
);
79 BasePrincipal::GetAsciiOrigin(nsACString
& aOrigin
) {
81 nsCOMPtr
<nsIURI
> prinURI
;
82 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
83 if (NS_FAILED(rv
) || !prinURI
) {
84 return NS_ERROR_NOT_AVAILABLE
;
86 return nsContentUtils::GetASCIIOrigin(prinURI
, aOrigin
);
90 BasePrincipal::GetHostPort(nsACString
& aRes
) {
92 nsCOMPtr
<nsIURI
> prinURI
;
93 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
94 if (NS_FAILED(rv
) || !prinURI
) {
97 return prinURI
->GetHostPort(aRes
);
101 BasePrincipal::GetHost(nsACString
& aRes
) {
103 nsCOMPtr
<nsIURI
> prinURI
;
104 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
105 if (NS_FAILED(rv
) || !prinURI
) {
108 return prinURI
->GetHost(aRes
);
112 BasePrincipal::GetOriginNoSuffix(nsACString
& aOrigin
) {
113 mOriginNoSuffix
->ToUTF8String(aOrigin
);
118 BasePrincipal::GetSiteOrigin(nsACString
& aSiteOrigin
) {
119 nsresult rv
= GetSiteOriginNoSuffix(aSiteOrigin
);
120 NS_ENSURE_SUCCESS(rv
, rv
);
122 nsAutoCString suffix
;
123 rv
= GetOriginSuffix(suffix
);
124 NS_ENSURE_SUCCESS(rv
, rv
);
125 aSiteOrigin
.Append(suffix
);
130 BasePrincipal::GetSiteOriginNoSuffix(nsACString
& aSiteOrigin
) {
131 return GetOriginNoSuffix(aSiteOrigin
);
134 // Returns the inner Json::value of the serialized principal
135 // Example input and return values:
137 // {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
138 // {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
140 // Content principal:
141 // {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
143 // Expanded principal:
144 // {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
145 // {"0":"<base64principal1>,<base64principal2>"}
149 // The aKey passed in also returns the corresponding PrincipalKind enum
151 // Warning: The Json::Value* pointer is into the aRoot object
152 static const Json::Value
* GetPrincipalObject(const Json::Value
& aRoot
,
153 int& aOutPrincipalKind
) {
154 const Json::Value::Members members
= aRoot
.getMemberNames();
155 // We only support one top level key in the object
156 if (members
.size() != 1) {
159 // members[0] here is the "0", "1", "2", "3" principalKind
160 // that is the top level of the serialized JSON principal
161 const std::string stringPrincipalKind
= members
[0];
163 // Next we take the string value from the JSON
164 // and convert it into the int for the BasePrincipal::PrincipalKind enum
166 // Verify that the key is within the valid range
167 int principalKind
= std::stoi(stringPrincipalKind
);
168 MOZ_ASSERT(BasePrincipal::eNullPrincipal
== 0,
169 "We need to rely on 0 being a bounds check for the first "
171 if (principalKind
< 0 || principalKind
> BasePrincipal::eKindMax
) {
174 MOZ_ASSERT(principalKind
== BasePrincipal::eNullPrincipal
||
175 principalKind
== BasePrincipal::eContentPrincipal
||
176 principalKind
== BasePrincipal::eExpandedPrincipal
||
177 principalKind
== BasePrincipal::eSystemPrincipal
);
178 aOutPrincipalKind
= principalKind
;
180 if (!aRoot
[stringPrincipalKind
].isObject()) {
184 // Return the inner value of the principal object
185 return &aRoot
[stringPrincipalKind
];
188 // Accepts the JSON inner object without the wrapping principalKind
189 // (See GetPrincipalObject for the inner object response examples)
190 // Creates an array of KeyVal objects that are all defined on the principal
191 // Each principal type (null, content, expanded) has a KeyVal that stores the
192 // fields of the JSON
194 // This simplifies deserializing elsewhere as we do the checking for presence
195 // and string values here for the complete set of serializable keys that the
196 // corresponding principal supports.
198 // The KeyVal object has the following fields:
199 // - valueWasSerialized: is true if the deserialized JSON contained a string
201 // - value: The string that was serialized for this key
202 // - key: an SerializableKeys enum value specific to the principal.
203 // For example content principal is an enum of: eURI, eDomain,
207 // Given an inner content principal:
208 // {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
210 // ----------------------------- |
212 // Key ----------------------
216 // They Key "0" corresponds to ContentPrincipal::eURI
217 // They Key "1" corresponds to ContentPrincipal::eSuffix
218 template <typename T
>
219 static nsTArray
<typename
T::KeyVal
> GetJSONKeys(const Json::Value
* aInput
) {
220 int size
= T::eMax
+ 1;
221 nsTArray
<typename
T::KeyVal
> fields
;
222 for (int i
= 0; i
!= size
; i
++) {
223 typename
T::KeyVal
* field
= fields
.AppendElement();
224 // field->valueWasSerialized returns if the field was found in the
225 // deserialized code. This simplifies the consumers from having to check
227 field
->valueWasSerialized
= false;
228 field
->key
= static_cast<typename
T::SerializableKeys
>(i
);
229 const std::string key
= std::to_string(field
->key
);
230 if (aInput
->isMember(key
)) {
231 const Json::Value
& val
= (*aInput
)[key
];
232 if (val
.isString()) {
233 field
->value
.Append(nsDependentCString(val
.asCString()));
234 field
->valueWasSerialized
= true;
241 // Takes a JSON string and parses it turning it into a principal of the
242 // corresponding type
244 // Given a content principal:
248 // ---------------------------------------------------------
250 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
252 // | ----------------------------- |
254 // PrincipalKind | | |
255 // | ----------------------------
256 // SerializableKeys |
259 // The string is first deserialized with jsoncpp to get the Json::Value of the
260 // object. The inner JSON object is parsed with GetPrincipalObject which returns
261 // a KeyVal array of the inner object's fields. PrincipalKind is returned by
262 // GetPrincipalObject which is then used to decide which principal
263 // implementation of FromProperties to call. The corresponding FromProperties
264 // call takes the KeyVal fields and turns it into a principal.
265 already_AddRefed
<BasePrincipal
> BasePrincipal::FromJSON(
266 const nsACString
& aJSON
) {
268 Json::CharReaderBuilder builder
;
269 std::unique_ptr
<Json::CharReader
> const reader(builder
.newCharReader());
271 reader
->parse(aJSON
.BeginReading(), aJSON
.EndReading(), &root
, nullptr);
274 "Unable to parse string as JSON to deserialize as a principal");
278 int principalKind
= -1;
279 const Json::Value
* value
= GetPrincipalObject(root
, principalKind
);
282 fprintf(stderr
, "Unexpected JSON principal %s\n",
283 root
.toStyledString().c_str());
285 MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
289 MOZ_ASSERT(principalKind
!= -1,
290 "PrincipalKind should always be >=0 by this point");
292 if (principalKind
== eSystemPrincipal
) {
293 RefPtr
<BasePrincipal
> principal
=
294 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
295 return principal
.forget();
298 if (principalKind
== eNullPrincipal
) {
299 nsTArray
<NullPrincipal::KeyVal
> res
= GetJSONKeys
<NullPrincipal
>(value
);
300 return NullPrincipal::FromProperties(res
);
303 if (principalKind
== eContentPrincipal
) {
304 nsTArray
<ContentPrincipal::KeyVal
> res
=
305 GetJSONKeys
<ContentPrincipal
>(value
);
306 return ContentPrincipal::FromProperties(res
);
309 if (principalKind
== eExpandedPrincipal
) {
310 nsTArray
<ExpandedPrincipal::KeyVal
> res
=
311 GetJSONKeys
<ExpandedPrincipal
>(value
);
312 return ExpandedPrincipal::FromProperties(res
);
315 MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
318 nsresult
BasePrincipal::PopulateJSONObject(Json::Value
& aObject
) {
322 // Returns a JSON representation of the principal.
323 // Calling BasePrincipal::FromJSON will deserialize the JSON into
324 // the corresponding principal type.
325 nsresult
BasePrincipal::ToJSON(nsACString
& aResult
) {
326 MOZ_ASSERT(aResult
.IsEmpty(), "ToJSON only supports an empty result input");
329 Json::StreamWriterBuilder builder
;
330 builder
["indentation"] = "";
331 Json::Value innerJSONObject
= Json::objectValue
;
333 nsresult rv
= PopulateJSONObject(innerJSONObject
);
334 NS_ENSURE_SUCCESS(rv
, rv
);
336 Json::Value root
= Json::objectValue
;
337 std::string key
= std::to_string(Kind());
338 root
[key
] = innerJSONObject
;
339 std::string result
= Json::writeString(builder
, root
);
340 aResult
.Append(result
);
341 if (aResult
.Length() == 0) {
342 MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
343 return NS_ERROR_UNEXPECTED
;
348 bool BasePrincipal::FastSubsumesIgnoringFPD(
349 nsIPrincipal
* aOther
, DocumentDomainConsideration aConsideration
) {
352 if (Kind() == eContentPrincipal
&&
353 !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
354 mOriginAttributes
, Cast(aOther
)->mOriginAttributes
)) {
358 return SubsumesInternal(aOther
, aConsideration
);
361 bool BasePrincipal::Subsumes(nsIPrincipal
* aOther
,
362 DocumentDomainConsideration aConsideration
) {
364 MOZ_ASSERT_IF(Kind() == eContentPrincipal
, mOriginSuffix
);
366 // Expanded principals handle origin attributes for each of their
367 // sub-principals individually, null principals do only simple checks for
368 // pointer equality, and system principals are immune to origin attributes
369 // checks, so only do this check for content principals.
370 if (Kind() == eContentPrincipal
&&
371 mOriginSuffix
!= Cast(aOther
)->mOriginSuffix
) {
375 return SubsumesInternal(aOther
, aConsideration
);
379 BasePrincipal::Equals(nsIPrincipal
* aOther
, bool* aResult
) {
380 NS_ENSURE_ARG_POINTER(aOther
);
382 *aResult
= FastEquals(aOther
);
388 BasePrincipal::EqualsForPermission(nsIPrincipal
* aOther
, bool aExactHost
,
391 NS_ENSURE_ARG_POINTER(aOther
);
392 NS_ENSURE_ARG_POINTER(aResult
);
394 // If the principals are equal, then they match.
395 if (FastEquals(aOther
)) {
400 // If we are matching with an exact host, we're done now - the permissions
401 // don't match otherwise, we need to start comparing subdomains!
406 // Compare their OriginAttributes
407 const mozilla::OriginAttributes
& theirAttrs
= aOther
->OriginAttributesRef();
408 const mozilla::OriginAttributes
& ourAttrs
= OriginAttributesRef();
410 if (theirAttrs
!= ourAttrs
) {
414 nsCOMPtr
<nsIURI
> ourURI
;
415 nsresult rv
= GetURI(getter_AddRefs(ourURI
));
416 NS_ENSURE_SUCCESS(rv
, rv
);
417 auto* basePrin
= BasePrincipal::Cast(aOther
);
419 nsCOMPtr
<nsIURI
> otherURI
;
420 rv
= basePrin
->GetURI(getter_AddRefs(otherURI
));
421 NS_ENSURE_SUCCESS(rv
, rv
);
423 nsAutoCString otherScheme
;
424 rv
= otherURI
->GetScheme(otherScheme
);
425 NS_ENSURE_SUCCESS(rv
, rv
);
427 nsAutoCString ourScheme
;
428 rv
= ourURI
->GetScheme(ourScheme
);
429 NS_ENSURE_SUCCESS(rv
, rv
);
431 if (otherScheme
!= ourScheme
) {
437 rv
= otherURI
->GetPort(&otherPort
);
438 NS_ENSURE_SUCCESS(rv
, rv
);
441 rv
= ourURI
->GetPort(&ourPort
);
442 NS_ENSURE_SUCCESS(rv
, rv
);
444 if (otherPort
!= ourPort
) {
448 // Check if the host or any subdomain of their host matches.
449 nsAutoCString otherHost
;
450 rv
= otherURI
->GetHost(otherHost
);
451 if (NS_FAILED(rv
) || otherHost
.IsEmpty()) {
455 nsAutoCString ourHost
;
456 rv
= ourURI
->GetHost(ourHost
);
457 if (NS_FAILED(rv
) || ourHost
.IsEmpty()) {
461 nsCOMPtr
<nsIEffectiveTLDService
> tldService
=
462 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID
);
464 NS_ERROR("Should have a tld service!");
465 return NS_ERROR_FAILURE
;
468 // This loop will not loop forever, as GetNextSubDomain will eventually fail
469 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
470 while (otherHost
!= ourHost
) {
471 rv
= tldService
->GetNextSubDomain(otherHost
, otherHost
);
473 if (rv
== NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
) {
485 BasePrincipal::EqualsConsideringDomain(nsIPrincipal
* aOther
, bool* aResult
) {
486 NS_ENSURE_ARG_POINTER(aOther
);
488 *aResult
= FastEqualsConsideringDomain(aOther
);
494 BasePrincipal::EqualsURI(nsIURI
* aOtherURI
, bool* aResult
) {
496 nsCOMPtr
<nsIURI
> prinURI
;
497 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
498 if (NS_FAILED(rv
) || !prinURI
) {
501 return prinURI
->EqualsExceptRef(aOtherURI
, aResult
);
505 BasePrincipal::Subsumes(nsIPrincipal
* aOther
, bool* aResult
) {
506 NS_ENSURE_ARG_POINTER(aOther
);
508 *aResult
= FastSubsumes(aOther
);
514 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal
* aOther
, bool* aResult
) {
515 NS_ENSURE_ARG_POINTER(aOther
);
517 *aResult
= FastSubsumesConsideringDomain(aOther
);
523 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal
* aOther
,
525 NS_ENSURE_ARG_POINTER(aOther
);
527 *aResult
= FastSubsumesConsideringDomainIgnoringFPD(aOther
);
533 BasePrincipal::CheckMayLoad(nsIURI
* aURI
, bool aAllowIfInheritsPrincipal
) {
534 return CheckMayLoadHelper(aURI
, aAllowIfInheritsPrincipal
, false, 0);
538 BasePrincipal::CheckMayLoadWithReporting(nsIURI
* aURI
,
539 bool aAllowIfInheritsPrincipal
,
540 uint64_t aInnerWindowID
) {
541 return CheckMayLoadHelper(aURI
, aAllowIfInheritsPrincipal
, true,
545 nsresult
BasePrincipal::CheckMayLoadHelper(nsIURI
* aURI
,
546 bool aAllowIfInheritsPrincipal
,
548 uint64_t aInnerWindowID
) {
549 NS_ENSURE_ARG_POINTER(aURI
);
551 aReport
|| aInnerWindowID
== 0,
552 "Why do we have an inner window id if we're not supposed to report?");
554 // Check the internal method first, which allows us to quickly approve loads
555 // for the System Principal.
556 if (MayLoadInternal(aURI
)) {
561 if (aAllowIfInheritsPrincipal
) {
562 // If the caller specified to allow loads of URIs that inherit
563 // our principal, allow the load if this URI inherits its principal.
564 bool doesInheritSecurityContext
;
565 rv
= NS_URIChainHasFlags(aURI
,
566 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
567 &doesInheritSecurityContext
);
568 if (NS_SUCCEEDED(rv
) && doesInheritSecurityContext
) {
573 bool fetchableByAnyone
;
574 rv
= NS_URIChainHasFlags(aURI
, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE
,
576 if (NS_SUCCEEDED(rv
) && fetchableByAnyone
) {
581 nsCOMPtr
<nsIURI
> prinURI
;
582 rv
= GetURI(getter_AddRefs(prinURI
));
583 if (NS_SUCCEEDED(rv
) && prinURI
) {
584 nsScriptSecurityManager::ReportError(
585 "CheckSameOriginError", prinURI
, aURI
,
586 mOriginAttributes
.mPrivateBrowsingId
> 0, aInnerWindowID
);
590 return NS_ERROR_DOM_BAD_URI
;
594 BasePrincipal::IsThirdPartyURI(nsIURI
* aURI
, bool* aRes
) {
595 if (IsSystemPrincipal() || (AddonPolicy() && AddonAllowsLoad(aURI
))) {
601 // If we do not have a URI its always 3rd party.
602 nsCOMPtr
<nsIURI
> prinURI
;
603 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
604 if (NS_FAILED(rv
) || !prinURI
) {
607 ThirdPartyUtil
* thirdPartyUtil
= ThirdPartyUtil::GetInstance();
608 return thirdPartyUtil
->IsThirdPartyURI(prinURI
, aURI
, aRes
);
612 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal
* aPrin
, bool* aRes
) {
614 nsCOMPtr
<nsIURI
> prinURI
;
615 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
616 if (NS_FAILED(rv
) || !prinURI
) {
619 return aPrin
->IsThirdPartyURI(prinURI
, aRes
);
622 BasePrincipal::IsThirdPartyChannel(nsIChannel
* aChan
, bool* aRes
) {
623 if (IsSystemPrincipal()) {
624 // Nothing is 3rd party to the system principal.
629 nsCOMPtr
<nsIURI
> prinURI
;
630 GetURI(getter_AddRefs(prinURI
));
631 ThirdPartyUtil
* thirdPartyUtil
= ThirdPartyUtil::GetInstance();
632 return thirdPartyUtil
->IsThirdPartyChannel(aChan
, prinURI
, aRes
);
636 BasePrincipal::IsSameOrigin(nsIURI
* aURI
, bool aIsPrivateWin
, bool* aRes
) {
638 nsCOMPtr
<nsIURI
> prinURI
;
639 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
640 if (NS_FAILED(rv
) || !prinURI
) {
643 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
645 return NS_ERROR_UNEXPECTED
;
647 *aRes
= NS_SUCCEEDED(
648 ssm
->CheckSameOriginURI(prinURI
, aURI
, false, aIsPrivateWin
));
653 BasePrincipal::IsL10nAllowed(nsIURI
* aURI
, bool* aRes
) {
656 if (nsContentUtils::IsErrorPage(aURI
)) {
661 // The system principal is always allowed.
662 if (IsSystemPrincipal()) {
667 nsCOMPtr
<nsIURI
> uri
;
668 nsresult rv
= GetURI(getter_AddRefs(uri
));
669 NS_ENSURE_SUCCESS(rv
, NS_OK
);
673 // Allow access to uris that cannot be loaded by web content.
674 rv
= NS_URIChainHasFlags(uri
, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD
,
676 NS_ENSURE_SUCCESS(rv
, NS_OK
);
682 // UI resources also get access.
683 rv
= NS_URIChainHasFlags(uri
, nsIProtocolHandler::URI_IS_UI_RESOURCE
,
685 NS_ENSURE_SUCCESS(rv
, NS_OK
);
691 auto policy
= AddonPolicy();
692 *aRes
= (policy
&& policy
->IsPrivileged());
697 BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI
* aURI
, bool* aRes
) {
699 nsCOMPtr
<nsIURI
> prinURI
;
700 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
701 if (NS_FAILED(rv
) || !prinURI
) {
704 *aRes
= NS_RelaxStrictFileOriginPolicy(aURI
, prinURI
);
709 BasePrincipal::GetPrefLightCacheKey(nsIURI
* aURI
, bool aWithCredentials
,
710 const OriginAttributes
& aOriginAttributes
,
711 nsACString
& _retval
) {
713 constexpr auto space
= " "_ns
;
715 nsCOMPtr
<nsIURI
> uri
;
716 nsresult rv
= GetURI(getter_AddRefs(uri
));
717 NS_ENSURE_SUCCESS(rv
, rv
);
719 nsAutoCString scheme
, host
, port
;
721 uri
->GetScheme(scheme
);
723 port
.AppendInt(NS_GetRealPort(uri
));
726 if (aWithCredentials
) {
727 _retval
.AssignLiteral("cred");
729 _retval
.AssignLiteral("nocred");
733 rv
= aURI
->GetSpec(spec
);
734 NS_ENSURE_SUCCESS(rv
, rv
);
736 nsAutoCString originAttributesSuffix
;
737 aOriginAttributes
.CreateSuffix(originAttributesSuffix
);
739 _retval
.Append(space
+ scheme
+ space
+ host
+ space
+ port
+ space
+ spec
+
740 space
+ originAttributesSuffix
);
746 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow
* aCheckWindow
,
747 uint32_t* aRejectedReason
,
749 *aRejectedReason
= 0;
750 *aOutAllowed
= false;
752 nsPIDOMWindowInner
* win
= nsPIDOMWindowInner::From(aCheckWindow
);
753 nsCOMPtr
<nsIURI
> uri
;
754 nsresult rv
= GetURI(getter_AddRefs(uri
));
759 ContentBlocking::ShouldAllowAccessFor(win
, uri
, aRejectedReason
);
764 BasePrincipal::GetIsNullPrincipal(bool* aResult
) {
765 *aResult
= Kind() == eNullPrincipal
;
770 BasePrincipal::GetIsContentPrincipal(bool* aResult
) {
771 *aResult
= Kind() == eContentPrincipal
;
776 BasePrincipal::GetIsExpandedPrincipal(bool* aResult
) {
777 *aResult
= Kind() == eExpandedPrincipal
;
782 BasePrincipal::GetAsciiSpec(nsACString
& aSpec
) {
784 nsCOMPtr
<nsIURI
> prinURI
;
785 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
786 if (NS_FAILED(rv
) || !prinURI
) {
789 return prinURI
->GetAsciiSpec(aSpec
);
793 BasePrincipal::GetSpec(nsACString
& aSpec
) {
795 nsCOMPtr
<nsIURI
> prinURI
;
796 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
797 if (NS_FAILED(rv
) || !prinURI
) {
800 return prinURI
->GetSpec(aSpec
);
804 BasePrincipal::GetAsciiHost(nsACString
& aHost
) {
806 nsCOMPtr
<nsIURI
> prinURI
;
807 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
808 if (NS_FAILED(rv
) || !prinURI
) {
811 return prinURI
->GetAsciiHost(aHost
);
815 BasePrincipal::GetExposablePrePath(nsACString
& aPrepath
) {
817 nsCOMPtr
<nsIURI
> prinURI
;
818 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
819 if (NS_FAILED(rv
) || !prinURI
) {
823 nsCOMPtr
<nsIURI
> exposableURI
= net::nsIOService::CreateExposableURI(prinURI
);
824 return exposableURI
->GetDisplayPrePath(aPrepath
);
828 BasePrincipal::GetExposableSpec(nsACString
& aSpec
) {
830 nsCOMPtr
<nsIURI
> prinURI
;
831 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
832 if (NS_FAILED(rv
) || !prinURI
) {
835 nsCOMPtr
<nsIURI
> clone
;
836 rv
= NS_MutateURI(prinURI
)
841 NS_ENSURE_SUCCESS(rv
, rv
);
842 return clone
->GetAsciiSpec(aSpec
);
846 BasePrincipal::GetPrePath(nsACString
& aPath
) {
848 nsCOMPtr
<nsIURI
> prinURI
;
849 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
850 if (NS_FAILED(rv
) || !prinURI
) {
853 return prinURI
->GetPrePath(aPath
);
857 BasePrincipal::GetFilePath(nsACString
& aPath
) {
859 nsCOMPtr
<nsIURI
> prinURI
;
860 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
861 if (NS_FAILED(rv
) || !prinURI
) {
864 return prinURI
->GetFilePath(aPath
);
868 BasePrincipal::GetIsSystemPrincipal(bool* aResult
) {
869 *aResult
= IsSystemPrincipal();
874 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult
) {
875 *aResult
= AddonPolicy() || ContentScriptAddonPolicy();
879 NS_IMETHODIMP
BasePrincipal::GetIsOnion(bool* aIsOnion
) {
881 nsCOMPtr
<nsIURI
> prinURI
;
882 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
883 if (NS_FAILED(rv
) || !prinURI
) {
888 rv
= prinURI
->GetHost(host
);
892 *aIsOnion
= StringEndsWith(host
, ".onion"_ns
);
896 NS_IMETHODIMP
BasePrincipal::GetIsIpAddress(bool* aIsIpAddress
) {
897 *aIsIpAddress
= false;
899 nsCOMPtr
<nsIURI
> prinURI
;
900 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
901 if (NS_FAILED(rv
) || !prinURI
) {
906 rv
= prinURI
->GetHost(host
);
912 memset(&prAddr
, 0, sizeof(prAddr
));
914 if (PR_StringToNetAddr(host
.get(), &prAddr
) == PR_SUCCESS
) {
915 *aIsIpAddress
= true;
921 NS_IMETHODIMP
BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress
) {
922 *aIsIpAddress
= false;
924 nsCOMPtr
<nsIURI
> prinURI
;
925 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
926 if (NS_FAILED(rv
) || !prinURI
) {
930 nsCOMPtr
<nsIIOService
> ioService
= do_GetIOService(&rv
);
931 if (NS_FAILED(rv
) || !ioService
) {
934 rv
= ioService
->HostnameIsLocalIPAddress(prinURI
, aIsIpAddress
);
936 *aIsIpAddress
= false;
942 BasePrincipal::GetScheme(nsACString
& aScheme
) {
945 nsCOMPtr
<nsIURI
> prinURI
;
946 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
947 if (NS_FAILED(rv
) || !prinURI
) {
951 return prinURI
->GetScheme(aScheme
);
955 BasePrincipal::SchemeIs(const char* aScheme
, bool* aResult
) {
957 nsCOMPtr
<nsIURI
> prinURI
;
958 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
959 if (NS_FAILED(rv
) || !prinURI
) {
962 *aResult
= prinURI
->SchemeIs(aScheme
);
967 BasePrincipal::IsURIInPrefList(const char* aPref
, bool* aResult
) {
969 nsCOMPtr
<nsIURI
> prinURI
;
970 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
971 if (NS_FAILED(rv
) || !prinURI
) {
974 *aResult
= nsContentUtils::IsURIInPrefList(prinURI
, aPref
);
979 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult
) {
980 MOZ_ASSERT(NS_IsMainThread());
983 nsCOMPtr
<nsIURI
> uri
;
984 nsresult rv
= GetURI(getter_AddRefs(uri
));
985 if (NS_FAILED(rv
) || !uri
) {
989 *aResult
= nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri
);
994 BasePrincipal::GetAboutModuleFlags(uint32_t* flags
) {
996 nsCOMPtr
<nsIURI
> prinURI
;
997 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
998 if (NS_FAILED(rv
) || !prinURI
) {
999 return NS_ERROR_NOT_AVAILABLE
;
1001 if (!prinURI
->SchemeIs("about")) {
1005 nsCOMPtr
<nsIAboutModule
> aboutModule
;
1006 rv
= NS_GetAboutModule(prinURI
, getter_AddRefs(aboutModule
));
1007 if (NS_FAILED(rv
) || !aboutModule
) {
1010 return aboutModule
->GetURIFlags(prinURI
, flags
);
1014 BasePrincipal::GetOriginAttributes(JSContext
* aCx
,
1015 JS::MutableHandle
<JS::Value
> aVal
) {
1016 if (NS_WARN_IF(!ToJSValue(aCx
, mOriginAttributes
, aVal
))) {
1017 return NS_ERROR_FAILURE
;
1023 BasePrincipal::GetOriginSuffix(nsACString
& aOriginAttributes
) {
1024 MOZ_ASSERT(mOriginSuffix
);
1025 mOriginSuffix
->ToUTF8String(aOriginAttributes
);
1030 BasePrincipal::GetUserContextId(uint32_t* aUserContextId
) {
1031 *aUserContextId
= UserContextId();
1036 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId
) {
1037 *aPrivateBrowsingId
= PrivateBrowsingId();
1042 BasePrincipal::GetIsInIsolatedMozBrowserElement(
1043 bool* aIsInIsolatedMozBrowserElement
) {
1044 *aIsInIsolatedMozBrowserElement
= IsInIsolatedMozBrowserElement();
1048 nsresult
BasePrincipal::GetAddonPolicy(nsISupports
** aResult
) {
1049 RefPtr
<extensions::WebExtensionPolicy
> policy(AddonPolicy());
1050 policy
.forget(aResult
);
1054 extensions::WebExtensionPolicy
* BasePrincipal::AddonPolicy() {
1055 if (Is
<ContentPrincipal
>()) {
1056 return As
<ContentPrincipal
>()->AddonPolicy();
1061 bool BasePrincipal::AddonHasPermission(const nsAtom
* aPerm
) {
1062 if (auto policy
= AddonPolicy()) {
1063 return policy
->HasPermission(aPerm
);
1068 nsIPrincipal
* BasePrincipal::PrincipalToInherit(nsIURI
* aRequestedURI
) {
1069 if (Is
<ExpandedPrincipal
>()) {
1070 return As
<ExpandedPrincipal
>()->PrincipalToInherit(aRequestedURI
);
1075 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1076 nsIURI
* aURI
, const OriginAttributes
& aAttrs
) {
1079 nsAutoCString originNoSuffix
;
1081 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI
, originNoSuffix
);
1082 if (NS_FAILED(rv
)) {
1083 // If the generation of the origin fails, we still want to have a valid
1084 // principal. Better to return a null principal here.
1085 return NullPrincipal::Create(aAttrs
);
1088 return CreateContentPrincipal(aURI
, aAttrs
, originNoSuffix
);
1091 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1092 nsIURI
* aURI
, const OriginAttributes
& aAttrs
,
1093 const nsACString
& aOriginNoSuffix
) {
1095 MOZ_ASSERT(!aOriginNoSuffix
.IsEmpty());
1097 // If the URI is supposed to inherit the security context of whoever loads it,
1098 // we shouldn't make a content principal for it.
1099 bool inheritsPrincipal
;
1100 nsresult rv
= NS_URIChainHasFlags(
1101 aURI
, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT
,
1102 &inheritsPrincipal
);
1103 if (NS_FAILED(rv
) || inheritsPrincipal
) {
1104 return NullPrincipal::Create(aAttrs
);
1107 // Check whether the URI knows what its principal is supposed to be.
1108 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
1109 nsCOMPtr
<nsIURIWithSpecialOrigin
> uriWithSpecialOrigin
=
1110 do_QueryInterface(aURI
);
1111 if (uriWithSpecialOrigin
) {
1112 nsCOMPtr
<nsIURI
> origin
;
1113 rv
= uriWithSpecialOrigin
->GetOrigin(getter_AddRefs(origin
));
1114 if (NS_WARN_IF(NS_FAILED(rv
))) {
1118 OriginAttributes attrs
;
1119 RefPtr
<BasePrincipal
> principal
= CreateContentPrincipal(origin
, attrs
);
1120 return principal
.forget();
1124 nsCOMPtr
<nsIPrincipal
> blobPrincipal
;
1125 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
1126 aURI
, getter_AddRefs(blobPrincipal
))) {
1127 MOZ_ASSERT(blobPrincipal
);
1128 RefPtr
<BasePrincipal
> principal
= Cast(blobPrincipal
);
1129 return principal
.forget();
1132 // Mint a content principal.
1133 RefPtr
<ContentPrincipal
> principal
=
1134 new ContentPrincipal(aURI
, aAttrs
, aOriginNoSuffix
);
1135 return principal
.forget();
1138 already_AddRefed
<BasePrincipal
> BasePrincipal::CreateContentPrincipal(
1139 const nsACString
& aOrigin
) {
1140 MOZ_ASSERT(!StringBeginsWith(aOrigin
, "["_ns
),
1141 "CreateContentPrincipal does not support System and Expanded "
1145 !StringBeginsWith(aOrigin
, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME
":")),
1146 "CreateContentPrincipal does not support NullPrincipal");
1148 nsAutoCString originNoSuffix
;
1149 OriginAttributes attrs
;
1150 if (!attrs
.PopulateFromOrigin(aOrigin
, originNoSuffix
)) {
1154 nsCOMPtr
<nsIURI
> uri
;
1155 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), originNoSuffix
);
1156 NS_ENSURE_SUCCESS(rv
, nullptr);
1158 return BasePrincipal::CreateContentPrincipal(uri
, attrs
);
1161 already_AddRefed
<BasePrincipal
> BasePrincipal::CloneForcingOriginAttributes(
1162 const OriginAttributes
& aOriginAttributes
) {
1163 if (NS_WARN_IF(!IsContentPrincipal())) {
1167 nsAutoCString originNoSuffix
;
1168 nsresult rv
= GetOriginNoSuffix(originNoSuffix
);
1169 NS_ENSURE_SUCCESS(rv
, nullptr);
1171 nsCOMPtr
<nsIURI
> uri
;
1172 MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri
)));
1174 RefPtr
<ContentPrincipal
> copy
=
1175 new ContentPrincipal(uri
, aOriginAttributes
, originNoSuffix
);
1176 return copy
.forget();
1179 extensions::WebExtensionPolicy
* BasePrincipal::ContentScriptAddonPolicy() {
1180 if (!Is
<ExpandedPrincipal
>()) {
1184 auto expanded
= As
<ExpandedPrincipal
>();
1185 for (auto& prin
: expanded
->AllowList()) {
1186 if (auto policy
= BasePrincipal::Cast(prin
)->AddonPolicy()) {
1194 bool BasePrincipal::AddonAllowsLoad(nsIURI
* aURI
,
1195 bool aExplicit
/* = false */) {
1196 if (Is
<ExpandedPrincipal
>()) {
1197 return As
<ExpandedPrincipal
>()->AddonAllowsLoad(aURI
, aExplicit
);
1199 if (auto policy
= AddonPolicy()) {
1200 return policy
->CanAccessURI(aURI
, aExplicit
);
1206 BasePrincipal::GetLocalStorageQuotaKey(nsACString
& aKey
) {
1209 nsCOMPtr
<nsIURI
> uri
;
1210 nsresult rv
= GetURI(getter_AddRefs(uri
));
1211 NS_ENSURE_SUCCESS(rv
, rv
);
1212 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
1214 // The special handling of the file scheme should be consistent with
1215 // GetStorageOriginKey.
1217 nsAutoCString baseDomain
;
1218 rv
= uri
->GetAsciiHost(baseDomain
);
1219 NS_ENSURE_SUCCESS(rv
, rv
);
1221 if (baseDomain
.IsEmpty() && uri
->SchemeIs("file")) {
1222 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(uri
, &rv
);
1223 NS_ENSURE_SUCCESS(rv
, rv
);
1225 rv
= url
->GetDirectory(baseDomain
);
1226 NS_ENSURE_SUCCESS(rv
, rv
);
1228 nsCOMPtr
<nsIEffectiveTLDService
> eTLDService(
1229 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID
, &rv
));
1230 NS_ENSURE_SUCCESS(rv
, rv
);
1232 nsAutoCString eTLDplusOne
;
1233 rv
= eTLDService
->GetBaseDomain(uri
, 0, eTLDplusOne
);
1234 if (NS_SUCCEEDED(rv
)) {
1235 baseDomain
= eTLDplusOne
;
1236 } else if (rv
== NS_ERROR_HOST_IS_IP_ADDRESS
||
1237 rv
== NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
) {
1240 NS_ENSURE_SUCCESS(rv
, rv
);
1243 OriginAttributesRef().CreateSuffix(aKey
);
1245 nsAutoCString subdomainsDBKey
;
1246 rv
= dom::StorageUtils::CreateReversedDomain(baseDomain
, subdomainsDBKey
);
1247 NS_ENSURE_SUCCESS(rv
, rv
);
1250 aKey
.Append(subdomainsDBKey
);
1256 BasePrincipal::GetNextSubDomainPrincipal(
1257 nsIPrincipal
** aNextSubDomainPrincipal
) {
1258 nsCOMPtr
<nsIURI
> uri
;
1259 nsresult rv
= GetURI(getter_AddRefs(uri
));
1260 if (NS_FAILED(rv
) || !uri
) {
1265 rv
= uri
->GetHost(host
);
1266 if (NS_FAILED(rv
) || host
.IsEmpty()) {
1270 nsCString subDomain
;
1271 rv
= nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host
, subDomain
);
1273 if (NS_FAILED(rv
) || subDomain
.IsEmpty()) {
1277 nsCOMPtr
<nsIURI
> subDomainURI
;
1278 rv
= NS_MutateURI(uri
).SetHost(subDomain
).Finalize(subDomainURI
);
1279 if (NS_FAILED(rv
) || !subDomainURI
) {
1282 // Copy the attributes over
1283 mozilla::OriginAttributes attrs
= OriginAttributesRef();
1285 if (!StaticPrefs::permissions_isolateBy_userContext()) {
1286 // Disable userContext for permissions.
1287 attrs
.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID
);
1289 RefPtr
<nsIPrincipal
> principal
=
1290 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI
, attrs
);
1295 principal
.forget(aNextSubDomainPrincipal
);
1300 BasePrincipal::GetStorageOriginKey(nsACString
& aOriginKey
) {
1301 aOriginKey
.Truncate();
1303 nsCOMPtr
<nsIURI
> uri
;
1304 nsresult rv
= GetURI(getter_AddRefs(uri
));
1305 NS_ENSURE_SUCCESS(rv
, rv
);
1306 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
1308 // The special handling of the file scheme should be consistent with
1309 // GetLocalStorageQuotaKey.
1311 nsAutoCString domainOrigin
;
1312 rv
= uri
->GetAsciiHost(domainOrigin
);
1313 NS_ENSURE_SUCCESS(rv
, rv
);
1315 if (domainOrigin
.IsEmpty()) {
1316 // For the file:/// protocol use the exact directory as domain.
1317 if (uri
->SchemeIs("file")) {
1318 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(uri
, &rv
);
1319 NS_ENSURE_SUCCESS(rv
, rv
);
1320 rv
= url
->GetDirectory(domainOrigin
);
1321 NS_ENSURE_SUCCESS(rv
, rv
);
1325 // Append reversed domain
1326 nsAutoCString reverseDomain
;
1327 rv
= dom::StorageUtils::CreateReversedDomain(domainOrigin
, reverseDomain
);
1328 NS_ENSURE_SUCCESS(rv
, rv
);
1330 aOriginKey
.Append(reverseDomain
);
1333 nsAutoCString scheme
;
1334 rv
= uri
->GetScheme(scheme
);
1335 NS_ENSURE_SUCCESS(rv
, rv
);
1337 aOriginKey
.Append(':');
1338 aOriginKey
.Append(scheme
);
1340 // Append port if any
1341 int32_t port
= NS_GetRealPort(uri
);
1343 aOriginKey
.Append(nsPrintfCString(":%d", port
));
1350 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy
) {
1351 *aIsScriptAllowedByPolicy
= false;
1352 nsCOMPtr
<nsIURI
> prinURI
;
1353 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
1354 if (NS_FAILED(rv
) || !prinURI
) {
1357 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
1359 return NS_ERROR_UNEXPECTED
;
1361 return ssm
->PolicyAllowsScript(prinURI
, aIsScriptAllowedByPolicy
);
1364 bool SiteIdentifier::Equals(const SiteIdentifier
& aOther
) const {
1365 MOZ_ASSERT(IsInitialized());
1366 MOZ_ASSERT(aOther
.IsInitialized());
1367 return mPrincipal
->FastEquals(aOther
.mPrincipal
);
1371 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy
,
1372 nsIReferrerInfo
** _retval
) {
1373 nsCOMPtr
<nsIURI
> prinURI
;
1374 RefPtr
<dom::ReferrerInfo
> info
;
1375 nsresult rv
= GetURI(getter_AddRefs(prinURI
));
1376 if (NS_FAILED(rv
) || !prinURI
) {
1377 info
= new dom::ReferrerInfo(nullptr);
1378 info
.forget(_retval
);
1381 info
= new dom::ReferrerInfo(prinURI
, aReferrerPolicy
);
1382 info
.forget(_retval
);
1386 NS_IMPL_ADDREF(BasePrincipal::Deserializer
)
1387 NS_IMPL_RELEASE(BasePrincipal::Deserializer
)
1389 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer
)
1390 NS_INTERFACE_MAP_ENTRY(nsISupports
)
1391 NS_INTERFACE_MAP_ENTRY(nsISerializable
)
1393 return mPrincipal
->QueryInterface(aIID
, aInstancePtr
);
1395 NS_INTERFACE_MAP_END
1398 BasePrincipal::Deserializer::Write(nsIObjectOutputStream
* aStream
) {
1399 // Read is used still for legacy principals
1400 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
1404 } // namespace mozilla