Backed out changeset 8aaffdf63d09 (bug 1920575) for causing bc failures on browser_si...
[gecko.git] / caps / BasePrincipal.cpp
blob1cd6e4ae3d5090b073268e68a1be08ae555c2bfe
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/ExtensionPolicyService.h"
22 #include "mozilla/NullPrincipal.h"
23 #include "mozilla/dom/BlobURLProtocolHandler.h"
24 #include "mozilla/dom/ChromeUtils.h"
25 #include "mozilla/dom/ReferrerInfo.h"
26 #include "mozilla/dom/ToJSValue.h"
27 #include "mozilla/dom/nsMixedContentBlocker.h"
28 #include "mozilla/Components.h"
29 #include "mozilla/dom/StorageUtils.h"
30 #include "mozilla/dom/StorageUtils.h"
31 #include "mozilla/JSONStringWriteFuncs.h"
32 #include "mozilla/JSONWriter.h"
33 #include "nsIURL.h"
34 #include "nsEffectiveTLDService.h"
35 #include "nsIURIMutator.h"
36 #include "mozilla/StaticPrefs_permissions.h"
37 #include "nsIURIMutator.h"
38 #include "nsMixedContentBlocker.h"
39 #include "prnetdb.h"
40 #include "nsIURIFixup.h"
41 #include "mozilla/dom/StorageUtils.h"
42 #include "mozilla/StorageAccess.h"
43 #include "nsPIDOMWindow.h"
44 #include "nsIURIMutator.h"
45 #include "mozilla/PermissionManager.h"
47 #include "nsSerializationHelper.h"
49 #include "js/JSON.h"
50 #include "ContentPrincipalJSONHandler.h"
51 #include "ExpandedPrincipalJSONHandler.h"
52 #include "NullPrincipalJSONHandler.h"
53 #include "PrincipalJSONHandler.h"
54 #include "SubsumedPrincipalJSONHandler.h"
56 namespace mozilla {
58 BasePrincipal::BasePrincipal(PrincipalKind aKind,
59 const nsACString& aOriginNoSuffix,
60 const OriginAttributes& aOriginAttributes)
61 : mOriginNoSuffix(NS_Atomize(aOriginNoSuffix)),
62 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
63 mOriginAttributes(aOriginAttributes),
64 mKind(aKind),
65 mHasExplicitDomain(false) {}
67 BasePrincipal::BasePrincipal(BasePrincipal* aOther,
68 const OriginAttributes& aOriginAttributes)
69 : mOriginNoSuffix(aOther->mOriginNoSuffix),
70 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
71 mOriginAttributes(aOriginAttributes),
72 mKind(aOther->mKind),
73 mHasExplicitDomain(aOther->mHasExplicitDomain.load()) {}
75 BasePrincipal::~BasePrincipal() = default;
77 NS_IMETHODIMP
78 BasePrincipal::GetOrigin(nsACString& aOrigin) {
79 nsresult rv = GetOriginNoSuffix(aOrigin);
80 NS_ENSURE_SUCCESS(rv, rv);
82 nsAutoCString suffix;
83 rv = GetOriginSuffix(suffix);
84 NS_ENSURE_SUCCESS(rv, rv);
85 aOrigin.Append(suffix);
86 return NS_OK;
89 NS_IMETHODIMP
90 BasePrincipal::GetWebExposedOriginSerialization(nsACString& aOrigin) {
91 aOrigin.Truncate();
92 nsCOMPtr<nsIURI> prinURI;
93 nsresult rv = GetURI(getter_AddRefs(prinURI));
94 if (NS_FAILED(rv) || !prinURI) {
95 return NS_ERROR_NOT_AVAILABLE;
97 return nsContentUtils::GetWebExposedOriginSerialization(prinURI, aOrigin);
100 NS_IMETHODIMP
101 BasePrincipal::GetHostPort(nsACString& aRes) {
102 aRes.Truncate();
103 nsCOMPtr<nsIURI> prinURI;
104 nsresult rv = GetURI(getter_AddRefs(prinURI));
105 if (NS_FAILED(rv) || !prinURI) {
106 return NS_OK;
108 return prinURI->GetHostPort(aRes);
111 NS_IMETHODIMP
112 BasePrincipal::GetHost(nsACString& aRes) {
113 aRes.Truncate();
114 nsCOMPtr<nsIURI> prinURI;
115 nsresult rv = GetURI(getter_AddRefs(prinURI));
116 if (NS_FAILED(rv) || !prinURI) {
117 return NS_OK;
119 return prinURI->GetHost(aRes);
122 NS_IMETHODIMP
123 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
124 mOriginNoSuffix->ToUTF8String(aOrigin);
125 return NS_OK;
128 NS_IMETHODIMP
129 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
130 nsresult rv = GetSiteOriginNoSuffix(aSiteOrigin);
131 NS_ENSURE_SUCCESS(rv, rv);
133 nsAutoCString suffix;
134 rv = GetOriginSuffix(suffix);
135 NS_ENSURE_SUCCESS(rv, rv);
136 aSiteOrigin.Append(suffix);
137 return NS_OK;
140 NS_IMETHODIMP
141 BasePrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) {
142 return GetOriginNoSuffix(aSiteOrigin);
145 template <typename HandlerTypesT>
146 bool ContainerPrincipalJSONHandler<HandlerTypesT>::ProcessInnerResult(
147 bool aResult) {
148 if (!aResult) {
149 NS_WARNING("Failed to parse inner object");
150 mState = State::Error;
151 return false;
153 return true;
156 template <typename HandlerTypesT>
157 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startObject() {
158 if (mInnerHandler.isSome()) {
159 return CallOnInner([&](auto& aInner) { return aInner.startObject(); });
162 switch (mState) {
163 case State::Init:
164 mState = State::StartObject;
165 break;
166 case State::SystemPrincipal_Key:
167 mState = State::SystemPrincipal_StartObject;
168 break;
169 default:
170 NS_WARNING("Unexpected object value");
171 mState = State::Error;
172 return false;
175 return true;
178 template <typename HandlerTypesT>
179 bool ContainerPrincipalJSONHandler<HandlerTypesT>::propertyName(
180 const JS::Latin1Char* name, size_t length) {
181 if (mInnerHandler.isSome()) {
182 return CallOnInner(
183 [&](auto& aInner) { return aInner.propertyName(name, length); });
186 switch (mState) {
187 case State::StartObject: {
188 if (length != 1) {
189 NS_WARNING(
190 nsPrintfCString("Unexpected property name length: %zu", length)
191 .get());
192 mState = State::Error;
193 return false;
196 char key = char(name[0]);
197 switch (key) {
198 case BasePrincipal::NullPrincipalKey:
199 mState = State::NullPrincipal_Inner;
200 mInnerHandler.emplace(VariantType<NullPrincipalJSONHandler>());
201 break;
202 case BasePrincipal::ContentPrincipalKey:
203 mState = State::ContentPrincipal_Inner;
204 mInnerHandler.emplace(VariantType<ContentPrincipalJSONHandler>());
205 break;
206 case BasePrincipal::SystemPrincipalKey:
207 mState = State::SystemPrincipal_Key;
208 break;
209 default:
210 if constexpr (CanContainExpandedPrincipal) {
211 if (key == BasePrincipal::ExpandedPrincipalKey) {
212 mState = State::ExpandedPrincipal_Inner;
213 mInnerHandler.emplace(
214 VariantType<ExpandedPrincipalJSONHandler>());
215 break;
218 NS_WARNING(
219 nsPrintfCString("Unexpected property name: '%c'", key).get());
220 mState = State::Error;
221 return false;
223 break;
225 default:
226 NS_WARNING("Unexpected property name");
227 mState = State::Error;
228 return false;
231 return true;
234 template <typename HandlerTypesT>
235 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endObject() {
236 if (mInnerHandler.isSome()) {
237 return CallOnInner([&](auto& aInner) {
238 if (!aInner.endObject()) {
239 return false;
241 if (aInner.HasAccepted()) {
242 this->mPrincipal = aInner.mPrincipal.forget();
243 MOZ_ASSERT(this->mPrincipal);
244 mInnerHandler.reset();
246 return true;
250 switch (mState) {
251 case State::SystemPrincipal_StartObject:
252 mState = State::SystemPrincipal_EndObject;
253 break;
254 case State::SystemPrincipal_EndObject:
255 this->mPrincipal =
256 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
257 mState = State::EndObject;
258 break;
259 case State::NullPrincipal_Inner:
260 mState = State::EndObject;
261 break;
262 case State::ContentPrincipal_Inner:
263 mState = State::EndObject;
264 break;
265 default:
266 if constexpr (CanContainExpandedPrincipal) {
267 if (mState == State::ExpandedPrincipal_Inner) {
268 mState = State::EndObject;
269 break;
272 NS_WARNING("Unexpected end of object");
273 mState = State::Error;
274 return false;
277 return true;
280 template <typename HandlerTypesT>
281 bool ContainerPrincipalJSONHandler<HandlerTypesT>::startArray() {
282 if constexpr (CanContainExpandedPrincipal) {
283 if (mInnerHandler.isSome()) {
284 return CallOnInner([&](auto& aInner) { return aInner.startArray(); });
288 NS_WARNING("Unexpected array value");
289 mState = State::Error;
290 return false;
293 template <typename HandlerTypesT>
294 bool ContainerPrincipalJSONHandler<HandlerTypesT>::endArray() {
295 if constexpr (CanContainExpandedPrincipal) {
296 if (mInnerHandler.isSome()) {
297 return CallOnInner([&](auto& aInner) { return aInner.endArray(); });
301 NS_WARNING("Unexpected array value");
302 mState = State::Error;
303 return false;
306 template <typename HandlerTypesT>
307 bool ContainerPrincipalJSONHandler<HandlerTypesT>::stringValue(
308 const JS::Latin1Char* str, size_t length) {
309 if (mInnerHandler.isSome()) {
310 return CallOnInner(
311 [&](auto& aInner) { return aInner.stringValue(str, length); });
314 NS_WARNING("Unexpected string value");
315 mState = State::Error;
316 return false;
319 template class ContainerPrincipalJSONHandler<PrincipalJSONHandlerTypes>;
320 template class ContainerPrincipalJSONHandler<SubsumedPrincipalJSONHandlerTypes>;
322 // Takes a JSON string and parses it turning it into a principal of the
323 // corresponding type
325 // Given a content principal:
327 // inner JSON object
328 // |
329 // ---------------------------------------------------------
330 // | |
331 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
332 // | | | | |
333 // | ----------------------------- |
334 // | | | |
335 // PrincipalKind | | |
336 // | ----------------------------
337 // SerializableKeys |
338 // Value
340 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
341 const nsACString& aJSON) {
342 PrincipalJSONHandler handler;
344 if (!JS::ParseJSONWithHandler(
345 reinterpret_cast<const JS::Latin1Char*>(aJSON.BeginReading()),
346 aJSON.Length(), &handler)) {
347 NS_WARNING(
348 nsPrintfCString("Unable to parse: %s", aJSON.BeginReading()).get());
349 MOZ_ASSERT(false,
350 "Unable to parse string as JSON to deserialize as a principal");
351 return nullptr;
354 return handler.Get();
357 // Returns a JSON representation of the principal.
358 // Calling BasePrincipal::FromJSON will deserialize the JSON into
359 // the corresponding principal type.
360 nsresult BasePrincipal::ToJSON(nsACString& aJSON) {
361 MOZ_ASSERT(aJSON.IsEmpty(), "ToJSON only supports an empty result input");
362 aJSON.Truncate();
364 // NOTE: JSONWriter emits raw UTF-8 code units for non-ASCII range.
365 JSONStringRefWriteFunc func(aJSON);
366 JSONWriter writer(func, JSONWriter::CollectionStyle::SingleLineStyle);
368 nsresult rv = ToJSON(writer);
369 NS_ENSURE_SUCCESS(rv, rv);
371 return NS_OK;
374 nsresult BasePrincipal::ToJSON(JSONWriter& aWriter) {
375 static_assert(eKindMax < ArrayLength(JSONEnumKeyStrings));
377 aWriter.Start(JSONWriter::CollectionStyle::SingleLineStyle);
379 nsresult rv = WriteJSONProperties(aWriter);
380 NS_ENSURE_SUCCESS(rv, rv);
382 aWriter.End();
384 return NS_OK;
387 nsresult BasePrincipal::WriteJSONProperties(JSONWriter& aWriter) {
388 aWriter.StartObjectProperty(JSONEnumKeyStrings[Kind()],
389 JSONWriter::CollectionStyle::SingleLineStyle);
391 nsresult rv = WriteJSONInnerProperties(aWriter);
392 NS_ENSURE_SUCCESS(rv, rv);
394 aWriter.EndObject();
396 return NS_OK;
399 nsresult BasePrincipal::WriteJSONInnerProperties(JSONWriter& aWriter) {
400 return NS_OK;
403 bool BasePrincipal::FastSubsumesIgnoringFPD(
404 nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) {
405 MOZ_ASSERT(aOther);
407 if (Kind() == eContentPrincipal &&
408 !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
409 mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
410 return false;
413 return SubsumesInternal(aOther, aConsideration);
416 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
417 DocumentDomainConsideration aConsideration) {
418 MOZ_ASSERT(aOther);
419 MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
421 // Expanded principals handle origin attributes for each of their
422 // sub-principals individually, null principals do only simple checks for
423 // pointer equality, and system principals are immune to origin attributes
424 // checks, so only do this check for content principals.
425 if (Kind() == eContentPrincipal &&
426 mOriginSuffix != Cast(aOther)->mOriginSuffix) {
427 return false;
430 return SubsumesInternal(aOther, aConsideration);
433 NS_IMETHODIMP
434 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
435 NS_ENSURE_ARG_POINTER(aOther);
437 *aResult = FastEquals(aOther);
439 return NS_OK;
442 NS_IMETHODIMP
443 BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
444 bool* aResult) {
445 *aResult = false;
446 NS_ENSURE_ARG_POINTER(aOther);
447 NS_ENSURE_ARG_POINTER(aResult);
449 auto* other = Cast(aOther);
450 if (Kind() != other->Kind()) {
451 // Principals of different kinds can't be equal.
452 return NS_OK;
455 if (Kind() == eSystemPrincipal) {
456 *aResult = this == other;
457 return NS_OK;
460 if (Kind() == eNullPrincipal) {
461 // We don't store permissions for NullPrincipals.
462 return NS_OK;
465 MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal);
467 // Certain origin attributes should not be used to isolate permissions.
468 // Create a stripped copy of both OA sets to compare.
469 mozilla::OriginAttributes ourAttrs = mOriginAttributes;
470 PermissionManager::MaybeStripOriginAttributes(false, ourAttrs);
471 mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef();
472 PermissionManager::MaybeStripOriginAttributes(false, theirAttrs);
474 if (ourAttrs != theirAttrs) {
475 return NS_OK;
478 if (mOriginNoSuffix == other->mOriginNoSuffix) {
479 *aResult = true;
480 return NS_OK;
483 // If we are matching with an exact host, we're done now - the permissions
484 // don't match otherwise, we need to start comparing subdomains!
485 if (aExactHost) {
486 return NS_OK;
489 nsCOMPtr<nsIURI> ourURI;
490 nsresult rv = GetURI(getter_AddRefs(ourURI));
491 NS_ENSURE_SUCCESS(rv, rv);
492 // Some principal types may indicate success, but still return nullptr for
493 // URI.
494 NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE);
496 nsCOMPtr<nsIURI> otherURI;
497 rv = other->GetURI(getter_AddRefs(otherURI));
498 NS_ENSURE_SUCCESS(rv, rv);
499 NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE);
501 // Compare schemes
502 nsAutoCString otherScheme;
503 rv = otherURI->GetScheme(otherScheme);
504 NS_ENSURE_SUCCESS(rv, rv);
506 nsAutoCString ourScheme;
507 rv = ourURI->GetScheme(ourScheme);
508 NS_ENSURE_SUCCESS(rv, rv);
510 if (otherScheme != ourScheme) {
511 return NS_OK;
514 // Compare ports
515 int32_t otherPort;
516 rv = otherURI->GetPort(&otherPort);
517 NS_ENSURE_SUCCESS(rv, rv);
519 int32_t ourPort;
520 rv = ourURI->GetPort(&ourPort);
521 NS_ENSURE_SUCCESS(rv, rv);
523 if (otherPort != ourPort) {
524 return NS_OK;
527 // Check if the host or any subdomain of their host matches.
528 nsAutoCString otherHost;
529 rv = otherURI->GetHost(otherHost);
530 if (NS_FAILED(rv) || otherHost.IsEmpty()) {
531 return NS_OK;
534 nsAutoCString ourHost;
535 rv = ourURI->GetHost(ourHost);
536 if (NS_FAILED(rv) || ourHost.IsEmpty()) {
537 return NS_OK;
540 nsCOMPtr<nsIEffectiveTLDService> tldService =
541 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
542 if (!tldService) {
543 NS_ERROR("Should have a tld service!");
544 return NS_ERROR_FAILURE;
547 // This loop will not loop forever, as GetNextSubDomain will eventually fail
548 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
549 while (otherHost != ourHost) {
550 rv = tldService->GetNextSubDomain(otherHost, otherHost);
551 if (NS_FAILED(rv)) {
552 if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
553 return NS_OK;
555 return rv;
559 *aResult = true;
560 return NS_OK;
563 NS_IMETHODIMP
564 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
565 NS_ENSURE_ARG_POINTER(aOther);
567 *aResult = FastEqualsConsideringDomain(aOther);
569 return NS_OK;
572 NS_IMETHODIMP
573 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
574 *aResult = false;
575 nsCOMPtr<nsIURI> prinURI;
576 nsresult rv = GetURI(getter_AddRefs(prinURI));
577 if (NS_FAILED(rv) || !prinURI) {
578 return NS_OK;
580 return prinURI->EqualsExceptRef(aOtherURI, aResult);
583 NS_IMETHODIMP
584 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
585 NS_ENSURE_ARG_POINTER(aOther);
587 *aResult = FastSubsumes(aOther);
589 return NS_OK;
592 NS_IMETHODIMP
593 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
594 NS_ENSURE_ARG_POINTER(aOther);
596 *aResult = FastSubsumesConsideringDomain(aOther);
598 return NS_OK;
601 NS_IMETHODIMP
602 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
603 bool* aResult) {
604 NS_ENSURE_ARG_POINTER(aOther);
606 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
608 return NS_OK;
611 NS_IMETHODIMP
612 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
613 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
616 NS_IMETHODIMP
617 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
618 bool aAllowIfInheritsPrincipal,
619 uint64_t aInnerWindowID) {
620 AssertIsOnMainThread();
621 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
622 aInnerWindowID);
625 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
626 bool aAllowIfInheritsPrincipal,
627 bool aReport,
628 uint64_t aInnerWindowID) {
629 NS_ENSURE_ARG_POINTER(aURI);
630 MOZ_ASSERT(
631 aReport || aInnerWindowID == 0,
632 "Why do we have an inner window id if we're not supposed to report?");
633 MOZ_ASSERT(!aReport || NS_IsMainThread(), "Must be on main thread to report");
635 // Check the internal method first, which allows us to quickly approve loads
636 // for the System Principal.
637 if (MayLoadInternal(aURI)) {
638 return NS_OK;
641 nsresult rv;
642 if (aAllowIfInheritsPrincipal) {
643 // If the caller specified to allow loads of URIs that inherit
644 // our principal, allow the load if this URI inherits its principal.
645 bool doesInheritSecurityContext;
646 rv = NS_URIChainHasFlags(aURI,
647 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
648 &doesInheritSecurityContext);
649 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
650 return NS_OK;
654 // Get the principal uri for the WebExtension access check or error.
655 nsCOMPtr<nsIURI> prinURI;
656 rv = GetURI(getter_AddRefs(prinURI));
657 if (!(NS_SUCCEEDED(rv) && prinURI)) {
658 return NS_ERROR_DOM_BAD_URI;
661 // If the URL being loaded corresponds to a WebExtension URL, ask the policy
662 // if the path should be accessible.
663 bool isWebExtensionResource;
664 rv = NS_URIChainHasFlags(aURI,
665 nsIProtocolHandler::URI_IS_WEBEXTENSION_RESOURCE,
666 &isWebExtensionResource);
667 if (NS_SUCCEEDED(rv) && isWebExtensionResource) {
668 extensions::URLInfo urlInfo(aURI);
669 if (RefPtr<extensions::WebExtensionPolicyCore> urlPolicyCore =
670 ExtensionPolicyService::GetCoreByURL(urlInfo)) {
671 extensions::URLInfo prinUrlInfo(prinURI);
672 if (urlPolicyCore->SourceMayAccessPath(prinUrlInfo, urlInfo.FilePath())) {
673 return NS_OK;
678 if (aReport) {
679 // FIXME: Once bug 1900706 is complete, reporting can be updated to work
680 // off-main-thread.
681 nsScriptSecurityManager::ReportError("CheckSameOriginError", prinURI, aURI,
682 mOriginAttributes.IsPrivateBrowsing(),
683 aInnerWindowID);
686 return NS_ERROR_DOM_BAD_URI;
689 NS_IMETHODIMP
690 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
691 if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) {
692 *aRes = false;
693 return NS_OK;
696 *aRes = true;
697 // If we do not have a URI its always 3rd party.
698 nsCOMPtr<nsIURI> prinURI;
699 nsresult rv = GetURI(getter_AddRefs(prinURI));
700 if (NS_FAILED(rv) || !prinURI) {
701 return NS_OK;
703 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
704 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
707 NS_IMETHODIMP
708 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
709 *aRes = true;
710 nsCOMPtr<nsIURI> prinURI;
711 nsresult rv = GetURI(getter_AddRefs(prinURI));
712 if (NS_FAILED(rv) || !prinURI) {
713 return NS_OK;
715 return aPrin->IsThirdPartyURI(prinURI, aRes);
718 NS_IMETHODIMP
719 BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) {
720 AssertIsOnMainThread();
721 if (IsSystemPrincipal()) {
722 // Nothing is 3rd party to the system principal.
723 *aRes = false;
724 return NS_OK;
727 nsCOMPtr<nsIURI> prinURI;
728 GetURI(getter_AddRefs(prinURI));
729 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
730 return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes);
733 NS_IMETHODIMP
734 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) {
735 *aRes = false;
736 nsCOMPtr<nsIURI> prinURI;
737 nsresult rv = GetURI(getter_AddRefs(prinURI));
738 if (NS_FAILED(rv) || !prinURI) {
739 // Note that expanded and system principals return here, because they have
740 // no URI.
741 return NS_OK;
743 *aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI);
744 return NS_OK;
747 NS_IMETHODIMP
748 BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
749 AssertIsOnMainThread(); // URI_DANGEROUS_TO_LOAD is not threadsafe to query.
750 *aRes = false;
752 if (nsContentUtils::IsErrorPage(aURI)) {
753 *aRes = true;
754 return NS_OK;
757 // The system principal is always allowed.
758 if (IsSystemPrincipal()) {
759 *aRes = true;
760 return NS_OK;
763 nsCOMPtr<nsIURI> uri;
764 nsresult rv = GetURI(getter_AddRefs(uri));
765 NS_ENSURE_SUCCESS(rv, NS_OK);
767 if (!uri) {
768 return NS_OK;
771 bool hasFlags;
773 // Allow access to uris that cannot be loaded by web content.
774 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
775 &hasFlags);
776 NS_ENSURE_SUCCESS(rv, NS_OK);
777 if (hasFlags) {
778 *aRes = true;
779 return NS_OK;
782 // UI resources also get access.
783 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
784 &hasFlags);
785 NS_ENSURE_SUCCESS(rv, NS_OK);
786 if (hasFlags) {
787 *aRes = true;
788 return NS_OK;
791 auto policy = AddonPolicyCore();
792 *aRes = (policy && policy->IsPrivileged());
793 return NS_OK;
796 NS_IMETHODIMP
797 BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
798 const OriginAttributes& aOriginAttributes,
799 nsACString& _retval) {
800 _retval.Truncate();
801 constexpr auto space = " "_ns;
803 nsCOMPtr<nsIURI> uri;
804 nsresult rv = GetURI(getter_AddRefs(uri));
805 NS_ENSURE_SUCCESS(rv, rv);
807 nsAutoCString scheme, host, port;
808 if (uri) {
809 uri->GetScheme(scheme);
810 uri->GetHost(host);
811 port.AppendInt(NS_GetRealPort(uri));
814 if (aWithCredentials) {
815 _retval.AssignLiteral("cred");
816 } else {
817 _retval.AssignLiteral("nocred");
820 nsAutoCString spec;
821 rv = aURI->GetSpec(spec);
822 NS_ENSURE_SUCCESS(rv, rv);
824 nsAutoCString originAttributesSuffix;
825 aOriginAttributes.CreateSuffix(originAttributesSuffix);
827 _retval.Append(space + scheme + space + host + space + port + space + spec +
828 space + originAttributesSuffix);
830 return NS_OK;
833 NS_IMETHODIMP
834 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow,
835 uint32_t* aRejectedReason,
836 bool* aOutAllowed) {
837 AssertIsOnMainThread();
838 *aRejectedReason = 0;
839 *aOutAllowed = false;
841 if (IsSystemPrincipal()) {
842 // System principal is always considered to have first-party storage access.
843 *aOutAllowed = true;
844 return NS_OK;
847 nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow);
848 nsCOMPtr<nsIURI> uri;
849 nsresult rv = GetURI(getter_AddRefs(uri));
850 if (NS_FAILED(rv)) {
851 return rv;
854 // The uri could be null if the principal is an expanded principal.
855 if (!uri) {
856 return NS_ERROR_UNEXPECTED;
859 *aOutAllowed = ShouldAllowAccessFor(win, uri, aRejectedReason);
860 return NS_OK;
863 NS_IMETHODIMP
864 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
865 *aResult = Kind() == eNullPrincipal;
866 return NS_OK;
869 NS_IMETHODIMP
870 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
871 *aResult = Kind() == eContentPrincipal;
872 return NS_OK;
875 NS_IMETHODIMP
876 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
877 *aResult = Kind() == eExpandedPrincipal;
878 return NS_OK;
881 NS_IMETHODIMP
882 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
883 aSpec.Truncate();
884 nsCOMPtr<nsIURI> prinURI;
885 nsresult rv = GetURI(getter_AddRefs(prinURI));
886 if (NS_FAILED(rv) || !prinURI) {
887 return NS_OK;
889 return prinURI->GetAsciiSpec(aSpec);
892 NS_IMETHODIMP
893 BasePrincipal::GetSpec(nsACString& aSpec) {
894 aSpec.Truncate();
895 nsCOMPtr<nsIURI> prinURI;
896 nsresult rv = GetURI(getter_AddRefs(prinURI));
897 if (NS_FAILED(rv) || !prinURI) {
898 return NS_OK;
900 return prinURI->GetSpec(aSpec);
903 NS_IMETHODIMP
904 BasePrincipal::GetAsciiHost(nsACString& aHost) {
905 aHost.Truncate();
906 nsCOMPtr<nsIURI> prinURI;
907 nsresult rv = GetURI(getter_AddRefs(prinURI));
908 if (NS_FAILED(rv) || !prinURI) {
909 return NS_OK;
911 return prinURI->GetAsciiHost(aHost);
914 NS_IMETHODIMP
915 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
916 aPrepath.Truncate();
917 nsCOMPtr<nsIURI> prinURI;
918 nsresult rv = GetURI(getter_AddRefs(prinURI));
919 if (NS_FAILED(rv) || !prinURI) {
920 return NS_OK;
923 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
924 return exposableURI->GetDisplayPrePath(aPrepath);
927 NS_IMETHODIMP
928 BasePrincipal::GetExposableSpec(nsACString& aSpec) {
929 aSpec.Truncate();
930 nsCOMPtr<nsIURI> prinURI;
931 nsresult rv = GetURI(getter_AddRefs(prinURI));
932 if (NS_FAILED(rv) || !prinURI) {
933 return NS_OK;
935 nsCOMPtr<nsIURI> clone;
936 rv = NS_MutateURI(prinURI)
937 .SetQuery(""_ns)
938 .SetRef(""_ns)
939 .SetUserPass(""_ns)
940 .Finalize(clone);
941 NS_ENSURE_SUCCESS(rv, rv);
942 return clone->GetAsciiSpec(aSpec);
945 NS_IMETHODIMP
946 BasePrincipal::GetPrePath(nsACString& aPath) {
947 aPath.Truncate();
948 nsCOMPtr<nsIURI> prinURI;
949 nsresult rv = GetURI(getter_AddRefs(prinURI));
950 if (NS_FAILED(rv) || !prinURI) {
951 return NS_OK;
953 return prinURI->GetPrePath(aPath);
956 NS_IMETHODIMP
957 BasePrincipal::GetFilePath(nsACString& aPath) {
958 aPath.Truncate();
959 nsCOMPtr<nsIURI> prinURI;
960 nsresult rv = GetURI(getter_AddRefs(prinURI));
961 if (NS_FAILED(rv) || !prinURI) {
962 return NS_OK;
964 return prinURI->GetFilePath(aPath);
967 NS_IMETHODIMP
968 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
969 *aResult = IsSystemPrincipal();
970 return NS_OK;
973 NS_IMETHODIMP
974 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
975 *aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore();
976 return NS_OK;
979 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
980 *aIsOnion = false;
981 nsCOMPtr<nsIURI> prinURI;
982 nsresult rv = GetURI(getter_AddRefs(prinURI));
983 if (NS_FAILED(rv) || !prinURI) {
984 return NS_OK;
987 nsAutoCString host;
988 rv = prinURI->GetHost(host);
989 if (NS_FAILED(rv)) {
990 return NS_OK;
992 *aIsOnion = StringEndsWith(host, ".onion"_ns);
993 return NS_OK;
996 NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
997 *aIsIpAddress = false;
999 nsCOMPtr<nsIURI> prinURI;
1000 nsresult rv = GetURI(getter_AddRefs(prinURI));
1001 if (NS_FAILED(rv) || !prinURI) {
1002 return NS_OK;
1005 nsAutoCString host;
1006 rv = prinURI->GetHost(host);
1007 if (NS_FAILED(rv)) {
1008 return NS_OK;
1011 PRNetAddr prAddr;
1012 memset(&prAddr, 0, sizeof(prAddr));
1014 if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
1015 *aIsIpAddress = true;
1018 return NS_OK;
1021 NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) {
1022 *aIsIpAddress = false;
1024 nsCOMPtr<nsIURI> prinURI;
1025 nsresult rv = GetURI(getter_AddRefs(prinURI));
1026 if (NS_FAILED(rv) || !prinURI) {
1027 return NS_OK;
1030 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
1031 if (NS_FAILED(rv) || !ioService) {
1032 return NS_OK;
1034 rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress);
1035 if (NS_FAILED(rv)) {
1036 *aIsIpAddress = false;
1038 return NS_OK;
1041 NS_IMETHODIMP
1042 BasePrincipal::GetScheme(nsACString& aScheme) {
1043 aScheme.Truncate();
1045 nsCOMPtr<nsIURI> prinURI;
1046 nsresult rv = GetURI(getter_AddRefs(prinURI));
1047 if (NS_FAILED(rv) || !prinURI) {
1048 return NS_OK;
1051 return prinURI->GetScheme(aScheme);
1054 NS_IMETHODIMP
1055 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
1056 *aResult = false;
1057 nsCOMPtr<nsIURI> prinURI;
1058 nsresult rv = GetURI(getter_AddRefs(prinURI));
1059 if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) {
1060 return NS_OK;
1062 *aResult = prinURI->SchemeIs(aScheme);
1063 return NS_OK;
1066 NS_IMETHODIMP
1067 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
1068 AssertIsOnMainThread();
1069 *aResult = false;
1070 nsCOMPtr<nsIURI> prinURI;
1071 nsresult rv = GetURI(getter_AddRefs(prinURI));
1072 if (NS_FAILED(rv) || !prinURI) {
1073 return NS_OK;
1075 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
1076 return NS_OK;
1079 NS_IMETHODIMP
1080 BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) {
1081 *aResult = false;
1082 nsCOMPtr<nsIURI> prinURI;
1084 nsresult rv = GetURI(getter_AddRefs(prinURI));
1085 if (NS_FAILED(rv) || !prinURI) {
1086 return NS_OK;
1089 *aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList));
1090 return NS_OK;
1093 NS_IMETHODIMP
1094 BasePrincipal::IsContentAccessibleAboutURI(bool* aResult) {
1095 *aResult = false;
1097 nsCOMPtr<nsIURI> prinURI;
1098 nsresult rv = GetURI(getter_AddRefs(prinURI));
1099 if (NS_FAILED(rv) || !prinURI) {
1100 return NS_OK;
1103 if (!prinURI->SchemeIs("about")) {
1104 return NS_OK;
1107 *aResult = NS_IsContentAccessibleAboutURI(prinURI);
1108 return NS_OK;
1111 NS_IMETHODIMP
1112 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
1113 AssertIsOnMainThread();
1114 *aResult = false;
1116 nsCOMPtr<nsIURI> uri;
1117 nsresult rv = GetURI(getter_AddRefs(uri));
1118 if (NS_FAILED(rv) || !uri) {
1119 return NS_OK;
1122 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
1123 return NS_OK;
1126 NS_IMETHODIMP
1127 BasePrincipal::GetIsLoopbackHost(bool* aRes) {
1128 AssertIsOnMainThread();
1129 *aRes = false;
1130 nsAutoCString host;
1131 nsresult rv = GetHost(host);
1132 // Swallow potential failure as this method is infallible.
1133 if (NS_FAILED(rv)) {
1134 return NS_OK;
1137 *aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host);
1138 return NS_OK;
1141 NS_IMETHODIMP
1142 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
1143 AssertIsOnMainThread();
1144 *flags = 0;
1145 nsCOMPtr<nsIURI> prinURI;
1146 nsresult rv = GetURI(getter_AddRefs(prinURI));
1147 if (NS_FAILED(rv) || !prinURI) {
1148 return NS_ERROR_NOT_AVAILABLE;
1150 if (!prinURI->SchemeIs("about")) {
1151 return NS_OK;
1154 nsCOMPtr<nsIAboutModule> aboutModule;
1155 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
1156 if (NS_FAILED(rv) || !aboutModule) {
1157 return rv;
1159 return aboutModule->GetURIFlags(prinURI, flags);
1162 NS_IMETHODIMP
1163 BasePrincipal::GetOriginAttributes(JSContext* aCx,
1164 JS::MutableHandle<JS::Value> aVal) {
1165 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
1166 return NS_ERROR_FAILURE;
1168 return NS_OK;
1171 NS_IMETHODIMP
1172 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
1173 MOZ_ASSERT(mOriginSuffix);
1174 mOriginSuffix->ToUTF8String(aOriginAttributes);
1175 return NS_OK;
1178 NS_IMETHODIMP
1179 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
1180 *aUserContextId = UserContextId();
1181 return NS_OK;
1184 NS_IMETHODIMP
1185 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
1186 *aPrivateBrowsingId = PrivateBrowsingId();
1187 return NS_OK;
1190 NS_IMETHODIMP
1191 BasePrincipal::GetIsInPrivateBrowsing(bool* aIsInPrivateBrowsing) {
1192 *aIsInPrivateBrowsing = mOriginAttributes.IsPrivateBrowsing();
1193 return NS_OK;
1196 nsresult BasePrincipal::GetAddonPolicy(
1197 extensions::WebExtensionPolicy** aResult) {
1198 AssertIsOnMainThread();
1199 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
1200 policy.forget(aResult);
1201 return NS_OK;
1204 nsresult BasePrincipal::GetContentScriptAddonPolicy(
1205 extensions::WebExtensionPolicy** aResult) {
1206 RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy());
1207 policy.forget(aResult);
1208 return NS_OK;
1211 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
1212 AssertIsOnMainThread();
1213 RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore();
1214 return core ? core->GetMainThreadPolicy() : nullptr;
1217 RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() {
1218 if (Is<ContentPrincipal>()) {
1219 return As<ContentPrincipal>()->AddonPolicyCore();
1221 return nullptr;
1224 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
1225 if (auto policy = AddonPolicyCore()) {
1226 return policy->HasPermission(aPerm);
1228 return false;
1231 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
1232 if (Is<ExpandedPrincipal>()) {
1233 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
1235 return this;
1238 bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
1239 MOZ_ASSERT(aDocumentPrincipal);
1241 // Expanded principals override CSP if and only if they subsume the document
1242 // principal.
1243 if (mKind == eExpandedPrincipal) {
1244 return FastSubsumes(aDocumentPrincipal);
1246 // Extension principals always override the CSP of non-extension principals.
1247 // This is primarily for the sake of their stylesheets, which are usually
1248 // loaded from channels and cannot have expanded principals.
1249 return (AddonPolicyCore() &&
1250 !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore());
1253 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1254 nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) {
1255 MOZ_ASSERT(aURI);
1257 nsAutoCString originNoSuffix;
1258 nsresult rv =
1259 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
1260 if (NS_FAILED(rv)) {
1261 // If the generation of the origin fails, we still want to have a valid
1262 // principal. Better to return a null principal here.
1263 return NullPrincipal::Create(aAttrs);
1266 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain);
1269 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1270 nsIURI* aURI, const OriginAttributes& aAttrs,
1271 const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) {
1272 MOZ_ASSERT(aURI);
1273 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
1275 // If the URI is supposed to inherit the security context of whoever loads it,
1276 // we shouldn't make a content principal for it.
1277 bool inheritsPrincipal;
1278 nsresult rv = NS_URIChainHasFlags(
1279 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
1280 &inheritsPrincipal);
1281 if (NS_FAILED(rv) || inheritsPrincipal) {
1282 return NullPrincipal::Create(aAttrs);
1285 // Check whether the URI knows what its principal is supposed to be.
1286 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
1287 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
1288 do_QueryInterface(aURI);
1289 if (uriWithSpecialOrigin) {
1290 nsCOMPtr<nsIURI> origin;
1291 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
1292 if (NS_WARN_IF(NS_FAILED(rv))) {
1293 return nullptr;
1295 MOZ_ASSERT(origin);
1296 OriginAttributes attrs;
1297 RefPtr<BasePrincipal> principal =
1298 CreateContentPrincipal(origin, attrs, aInitialDomain);
1299 return principal.forget();
1301 #endif
1303 nsCOMPtr<nsIPrincipal> blobPrincipal;
1304 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
1305 aURI, getter_AddRefs(blobPrincipal))) {
1306 MOZ_ASSERT(blobPrincipal);
1307 MOZ_ASSERT(!aInitialDomain,
1308 "an initial domain for a blob URI makes no sense");
1309 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
1310 return principal.forget();
1313 // Mint a content principal.
1314 RefPtr<ContentPrincipal> principal =
1315 new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain);
1316 return principal.forget();
1319 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1320 const nsACString& aOrigin) {
1321 MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns),
1322 "CreateContentPrincipal does not support System and Expanded "
1323 "principals");
1325 MOZ_ASSERT(
1326 !StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")),
1327 "CreateContentPrincipal does not support NullPrincipal");
1329 nsAutoCString originNoSuffix;
1330 OriginAttributes attrs;
1331 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
1332 return nullptr;
1335 nsCOMPtr<nsIURI> uri;
1336 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
1337 NS_ENSURE_SUCCESS(rv, nullptr);
1339 return BasePrincipal::CreateContentPrincipal(uri, attrs);
1342 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
1343 const OriginAttributes& aOriginAttributes) {
1344 if (NS_WARN_IF(!IsContentPrincipal())) {
1345 return nullptr;
1348 nsAutoCString originNoSuffix;
1349 nsresult rv = GetOriginNoSuffix(originNoSuffix);
1350 NS_ENSURE_SUCCESS(rv, nullptr);
1352 nsCOMPtr<nsIURI> uri;
1353 MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri)));
1355 // XXX: This does not copy over the domain. Should it?
1356 RefPtr<ContentPrincipal> copy =
1357 new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr);
1358 return copy.forget();
1361 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
1362 AssertIsOnMainThread();
1363 RefPtr<extensions::WebExtensionPolicyCore> core =
1364 ContentScriptAddonPolicyCore();
1365 return core ? core->GetMainThreadPolicy() : nullptr;
1368 RefPtr<extensions::WebExtensionPolicyCore>
1369 BasePrincipal::ContentScriptAddonPolicyCore() {
1370 if (!Is<ExpandedPrincipal>()) {
1371 return nullptr;
1374 auto* expanded = As<ExpandedPrincipal>();
1375 for (const auto& prin : expanded->AllowList()) {
1376 if (RefPtr<extensions::WebExtensionPolicyCore> policy =
1377 BasePrincipal::Cast(prin)->AddonPolicyCore()) {
1378 return policy;
1382 return nullptr;
1385 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
1386 bool aExplicit /* = false */) {
1387 if (Is<ExpandedPrincipal>()) {
1388 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
1390 if (auto policy = AddonPolicyCore()) {
1391 return policy->CanAccessURI(aURI, aExplicit);
1393 return false;
1396 NS_IMETHODIMP
1397 BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
1398 aKey.Truncate();
1400 nsCOMPtr<nsIURI> uri;
1401 nsresult rv = GetURI(getter_AddRefs(uri));
1402 NS_ENSURE_SUCCESS(rv, rv);
1403 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1405 // The special handling of the file scheme should be consistent with
1406 // GetStorageOriginKey.
1408 nsAutoCString baseDomain;
1409 rv = uri->GetAsciiHost(baseDomain);
1410 NS_ENSURE_SUCCESS(rv, rv);
1412 if (baseDomain.IsEmpty() && uri->SchemeIs("file")) {
1413 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1414 NS_ENSURE_SUCCESS(rv, rv);
1416 rv = url->GetDirectory(baseDomain);
1417 NS_ENSURE_SUCCESS(rv, rv);
1418 } else {
1419 nsCOMPtr<nsIEffectiveTLDService> eTLDService(
1420 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
1421 NS_ENSURE_SUCCESS(rv, rv);
1423 nsAutoCString eTLDplusOne;
1424 rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
1425 if (NS_SUCCEEDED(rv)) {
1426 baseDomain = eTLDplusOne;
1427 } else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
1428 rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
1429 rv = NS_OK;
1431 NS_ENSURE_SUCCESS(rv, rv);
1434 OriginAttributesRef().CreateSuffix(aKey);
1436 nsAutoCString subdomainsDBKey;
1437 rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey);
1438 NS_ENSURE_SUCCESS(rv, rv);
1440 aKey.Append(':');
1441 aKey.Append(subdomainsDBKey);
1443 return NS_OK;
1446 NS_IMETHODIMP
1447 BasePrincipal::GetNextSubDomainPrincipal(
1448 nsIPrincipal** aNextSubDomainPrincipal) {
1449 nsCOMPtr<nsIURI> uri;
1450 nsresult rv = GetURI(getter_AddRefs(uri));
1451 if (NS_FAILED(rv) || !uri) {
1452 return NS_OK;
1455 nsAutoCString host;
1456 rv = uri->GetHost(host);
1457 if (NS_FAILED(rv) || host.IsEmpty()) {
1458 return NS_OK;
1461 nsCString subDomain;
1462 rv = nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host, subDomain);
1464 if (NS_FAILED(rv) || subDomain.IsEmpty()) {
1465 return NS_OK;
1468 nsCOMPtr<nsIURI> subDomainURI;
1469 rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI);
1470 if (NS_FAILED(rv) || !subDomainURI) {
1471 return NS_OK;
1473 // Copy the attributes over
1474 mozilla::OriginAttributes attrs = OriginAttributesRef();
1476 if (!StaticPrefs::permissions_isolateBy_userContext()) {
1477 // Disable userContext for permissions.
1478 attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
1480 RefPtr<nsIPrincipal> principal =
1481 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs);
1483 if (!principal) {
1484 return NS_OK;
1486 principal.forget(aNextSubDomainPrincipal);
1487 return NS_OK;
1490 NS_IMETHODIMP
1491 BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
1492 aOriginKey.Truncate();
1494 nsCOMPtr<nsIURI> uri;
1495 nsresult rv = GetURI(getter_AddRefs(uri));
1496 NS_ENSURE_SUCCESS(rv, rv);
1497 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1499 // The special handling of the file scheme should be consistent with
1500 // GetLocalStorageQuotaKey.
1502 nsAutoCString domainOrigin;
1503 rv = uri->GetAsciiHost(domainOrigin);
1504 NS_ENSURE_SUCCESS(rv, rv);
1506 if (domainOrigin.IsEmpty()) {
1507 // For the file:/// protocol use the exact directory as domain.
1508 if (uri->SchemeIs("file")) {
1509 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1510 NS_ENSURE_SUCCESS(rv, rv);
1511 rv = url->GetDirectory(domainOrigin);
1512 NS_ENSURE_SUCCESS(rv, rv);
1516 // Append reversed domain
1517 nsAutoCString reverseDomain;
1518 rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
1519 NS_ENSURE_SUCCESS(rv, rv);
1521 aOriginKey.Append(reverseDomain);
1523 // Append scheme
1524 nsAutoCString scheme;
1525 rv = uri->GetScheme(scheme);
1526 NS_ENSURE_SUCCESS(rv, rv);
1528 aOriginKey.Append(':');
1529 aOriginKey.Append(scheme);
1531 // Append port if any
1532 int32_t port = NS_GetRealPort(uri);
1533 if (port != -1) {
1534 aOriginKey.Append(nsPrintfCString(":%d", port));
1537 return NS_OK;
1540 NS_IMETHODIMP
1541 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
1542 AssertIsOnMainThread();
1543 *aIsScriptAllowedByPolicy = false;
1544 nsCOMPtr<nsIURI> prinURI;
1545 nsresult rv = GetURI(getter_AddRefs(prinURI));
1546 if (NS_FAILED(rv) || !prinURI) {
1547 return NS_OK;
1549 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1550 if (!ssm) {
1551 return NS_ERROR_UNEXPECTED;
1553 return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
1556 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
1557 MOZ_ASSERT(IsInitialized());
1558 MOZ_ASSERT(aOther.IsInitialized());
1559 return mPrincipal->FastEquals(aOther.mPrincipal);
1562 NS_IMETHODIMP
1563 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
1564 nsIReferrerInfo** _retval) {
1565 nsCOMPtr<nsIURI> prinURI;
1566 RefPtr<dom::ReferrerInfo> info;
1567 nsresult rv = GetURI(getter_AddRefs(prinURI));
1568 if (NS_FAILED(rv) || !prinURI) {
1569 info = new dom::ReferrerInfo(nullptr);
1570 info.forget(_retval);
1571 return NS_OK;
1573 info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
1574 info.forget(_retval);
1575 return NS_OK;
1578 NS_IMETHODIMP
1579 BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) {
1580 *aPrecursor = nullptr;
1581 return NS_OK;
1584 NS_IMPL_ADDREF(BasePrincipal::Deserializer)
1585 NS_IMPL_RELEASE(BasePrincipal::Deserializer)
1587 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer)
1588 NS_INTERFACE_MAP_ENTRY(nsISupports)
1589 NS_INTERFACE_MAP_ENTRY(nsISerializable)
1590 if (mPrincipal) {
1591 return mPrincipal->QueryInterface(aIID, aInstancePtr);
1592 } else
1593 NS_INTERFACE_MAP_END
1595 NS_IMETHODIMP
1596 BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) {
1597 // Read is used still for legacy principals
1598 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
1599 return NS_OK;
1602 /* static */
1603 void BasePrincipal::WriteJSONProperty(JSONWriter& aWriter,
1604 const Span<const char>& aKey,
1605 const nsCString& aValue) {
1606 aWriter.StringProperty(aKey, aValue);
1609 } // namespace mozilla