Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / caps / BasePrincipal.cpp
bloba805b6325c1d66f437521421dac44d7bd021beff
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 AssertIsOnMainThread();
614 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
617 NS_IMETHODIMP
618 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
619 bool aAllowIfInheritsPrincipal,
620 uint64_t aInnerWindowID) {
621 AssertIsOnMainThread();
622 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
623 aInnerWindowID);
626 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
627 bool aAllowIfInheritsPrincipal,
628 bool aReport,
629 uint64_t aInnerWindowID) {
630 AssertIsOnMainThread(); // Accesses non-threadsafe URI flags and the
631 // non-threadsafe ExtensionPolicyService
632 NS_ENSURE_ARG_POINTER(aURI);
633 MOZ_ASSERT(
634 aReport || aInnerWindowID == 0,
635 "Why do we have an inner window id if we're not supposed to report?");
637 // Check the internal method first, which allows us to quickly approve loads
638 // for the System Principal.
639 if (MayLoadInternal(aURI)) {
640 return NS_OK;
643 nsresult rv;
644 if (aAllowIfInheritsPrincipal) {
645 // If the caller specified to allow loads of URIs that inherit
646 // our principal, allow the load if this URI inherits its principal.
647 bool doesInheritSecurityContext;
648 rv = NS_URIChainHasFlags(aURI,
649 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
650 &doesInheritSecurityContext);
651 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
652 return NS_OK;
656 // Web Accessible Resources in MV2 Extensions are marked with
657 // URI_FETCHABLE_BY_ANYONE
658 bool fetchableByAnyone;
659 rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
660 &fetchableByAnyone);
661 if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
662 return NS_OK;
665 // Get the principal uri for the last flag check or error.
666 nsCOMPtr<nsIURI> prinURI;
667 rv = GetURI(getter_AddRefs(prinURI));
668 if (!(NS_SUCCEEDED(rv) && prinURI)) {
669 return NS_ERROR_DOM_BAD_URI;
672 // If MV3 Extension uris are web accessible by this principal it is allowed to
673 // load.
674 bool maybeWebAccessible = false;
675 NS_URIChainHasFlags(aURI, nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
676 &maybeWebAccessible);
677 NS_ENSURE_SUCCESS(rv, rv);
678 if (maybeWebAccessible) {
679 bool isWebAccessible = false;
680 rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
681 prinURI, aURI, &isWebAccessible);
682 if (NS_SUCCEEDED(rv) && isWebAccessible) {
683 return NS_OK;
687 if (aReport) {
688 nsScriptSecurityManager::ReportError(
689 "CheckSameOriginError", prinURI, aURI,
690 mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
693 return NS_ERROR_DOM_BAD_URI;
696 NS_IMETHODIMP
697 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
698 if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) {
699 *aRes = false;
700 return NS_OK;
703 *aRes = true;
704 // If we do not have a URI its always 3rd party.
705 nsCOMPtr<nsIURI> prinURI;
706 nsresult rv = GetURI(getter_AddRefs(prinURI));
707 if (NS_FAILED(rv) || !prinURI) {
708 return NS_OK;
710 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
711 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
714 NS_IMETHODIMP
715 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
716 *aRes = true;
717 nsCOMPtr<nsIURI> prinURI;
718 nsresult rv = GetURI(getter_AddRefs(prinURI));
719 if (NS_FAILED(rv) || !prinURI) {
720 return NS_OK;
722 return aPrin->IsThirdPartyURI(prinURI, aRes);
725 NS_IMETHODIMP
726 BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) {
727 AssertIsOnMainThread();
728 if (IsSystemPrincipal()) {
729 // Nothing is 3rd party to the system principal.
730 *aRes = false;
731 return NS_OK;
734 nsCOMPtr<nsIURI> prinURI;
735 GetURI(getter_AddRefs(prinURI));
736 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
737 return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes);
740 NS_IMETHODIMP
741 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) {
742 *aRes = false;
743 nsCOMPtr<nsIURI> prinURI;
744 nsresult rv = GetURI(getter_AddRefs(prinURI));
745 if (NS_FAILED(rv) || !prinURI) {
746 // Note that expanded and system principals return here, because they have
747 // no URI.
748 return NS_OK;
750 *aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI);
751 return NS_OK;
754 NS_IMETHODIMP
755 BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
756 AssertIsOnMainThread(); // URI_DANGEROUS_TO_LOAD is not threadsafe to query.
757 *aRes = false;
759 if (nsContentUtils::IsErrorPage(aURI)) {
760 *aRes = true;
761 return NS_OK;
764 // The system principal is always allowed.
765 if (IsSystemPrincipal()) {
766 *aRes = true;
767 return NS_OK;
770 nsCOMPtr<nsIURI> uri;
771 nsresult rv = GetURI(getter_AddRefs(uri));
772 NS_ENSURE_SUCCESS(rv, NS_OK);
774 bool hasFlags;
776 // Allow access to uris that cannot be loaded by web content.
777 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
778 &hasFlags);
779 NS_ENSURE_SUCCESS(rv, NS_OK);
780 if (hasFlags) {
781 *aRes = true;
782 return NS_OK;
785 // UI resources also get access.
786 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
787 &hasFlags);
788 NS_ENSURE_SUCCESS(rv, NS_OK);
789 if (hasFlags) {
790 *aRes = true;
791 return NS_OK;
794 auto policy = AddonPolicyCore();
795 *aRes = (policy && policy->IsPrivileged());
796 return NS_OK;
799 NS_IMETHODIMP
800 BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, bool* aRes) {
801 *aRes = false;
802 nsCOMPtr<nsIURI> prinURI;
803 nsresult rv = GetURI(getter_AddRefs(prinURI));
804 if (NS_FAILED(rv) || !prinURI) {
805 return NS_OK;
807 *aRes = NS_RelaxStrictFileOriginPolicy(aURI, prinURI);
808 return NS_OK;
811 NS_IMETHODIMP
812 BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
813 const OriginAttributes& aOriginAttributes,
814 nsACString& _retval) {
815 _retval.Truncate();
816 constexpr auto space = " "_ns;
818 nsCOMPtr<nsIURI> uri;
819 nsresult rv = GetURI(getter_AddRefs(uri));
820 NS_ENSURE_SUCCESS(rv, rv);
822 nsAutoCString scheme, host, port;
823 if (uri) {
824 uri->GetScheme(scheme);
825 uri->GetHost(host);
826 port.AppendInt(NS_GetRealPort(uri));
829 if (aWithCredentials) {
830 _retval.AssignLiteral("cred");
831 } else {
832 _retval.AssignLiteral("nocred");
835 nsAutoCString spec;
836 rv = aURI->GetSpec(spec);
837 NS_ENSURE_SUCCESS(rv, rv);
839 nsAutoCString originAttributesSuffix;
840 aOriginAttributes.CreateSuffix(originAttributesSuffix);
842 _retval.Append(space + scheme + space + host + space + port + space + spec +
843 space + originAttributesSuffix);
845 return NS_OK;
848 NS_IMETHODIMP
849 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow,
850 uint32_t* aRejectedReason,
851 bool* aOutAllowed) {
852 AssertIsOnMainThread();
853 *aRejectedReason = 0;
854 *aOutAllowed = false;
856 nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow);
857 nsCOMPtr<nsIURI> uri;
858 nsresult rv = GetURI(getter_AddRefs(uri));
859 if (NS_FAILED(rv)) {
860 return rv;
862 *aOutAllowed = ShouldAllowAccessFor(win, uri, aRejectedReason);
863 return NS_OK;
866 NS_IMETHODIMP
867 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
868 *aResult = Kind() == eNullPrincipal;
869 return NS_OK;
872 NS_IMETHODIMP
873 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
874 *aResult = Kind() == eContentPrincipal;
875 return NS_OK;
878 NS_IMETHODIMP
879 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
880 *aResult = Kind() == eExpandedPrincipal;
881 return NS_OK;
884 NS_IMETHODIMP
885 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
886 aSpec.Truncate();
887 nsCOMPtr<nsIURI> prinURI;
888 nsresult rv = GetURI(getter_AddRefs(prinURI));
889 if (NS_FAILED(rv) || !prinURI) {
890 return NS_OK;
892 return prinURI->GetAsciiSpec(aSpec);
895 NS_IMETHODIMP
896 BasePrincipal::GetSpec(nsACString& aSpec) {
897 aSpec.Truncate();
898 nsCOMPtr<nsIURI> prinURI;
899 nsresult rv = GetURI(getter_AddRefs(prinURI));
900 if (NS_FAILED(rv) || !prinURI) {
901 return NS_OK;
903 return prinURI->GetSpec(aSpec);
906 NS_IMETHODIMP
907 BasePrincipal::GetAsciiHost(nsACString& aHost) {
908 aHost.Truncate();
909 nsCOMPtr<nsIURI> prinURI;
910 nsresult rv = GetURI(getter_AddRefs(prinURI));
911 if (NS_FAILED(rv) || !prinURI) {
912 return NS_OK;
914 return prinURI->GetAsciiHost(aHost);
917 NS_IMETHODIMP
918 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
919 aPrepath.Truncate();
920 nsCOMPtr<nsIURI> prinURI;
921 nsresult rv = GetURI(getter_AddRefs(prinURI));
922 if (NS_FAILED(rv) || !prinURI) {
923 return NS_OK;
926 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
927 return exposableURI->GetDisplayPrePath(aPrepath);
930 NS_IMETHODIMP
931 BasePrincipal::GetExposableSpec(nsACString& aSpec) {
932 aSpec.Truncate();
933 nsCOMPtr<nsIURI> prinURI;
934 nsresult rv = GetURI(getter_AddRefs(prinURI));
935 if (NS_FAILED(rv) || !prinURI) {
936 return NS_OK;
938 nsCOMPtr<nsIURI> clone;
939 rv = NS_MutateURI(prinURI)
940 .SetQuery(""_ns)
941 .SetRef(""_ns)
942 .SetUserPass(""_ns)
943 .Finalize(clone);
944 NS_ENSURE_SUCCESS(rv, rv);
945 return clone->GetAsciiSpec(aSpec);
948 NS_IMETHODIMP
949 BasePrincipal::GetPrePath(nsACString& aPath) {
950 aPath.Truncate();
951 nsCOMPtr<nsIURI> prinURI;
952 nsresult rv = GetURI(getter_AddRefs(prinURI));
953 if (NS_FAILED(rv) || !prinURI) {
954 return NS_OK;
956 return prinURI->GetPrePath(aPath);
959 NS_IMETHODIMP
960 BasePrincipal::GetFilePath(nsACString& aPath) {
961 aPath.Truncate();
962 nsCOMPtr<nsIURI> prinURI;
963 nsresult rv = GetURI(getter_AddRefs(prinURI));
964 if (NS_FAILED(rv) || !prinURI) {
965 return NS_OK;
967 return prinURI->GetFilePath(aPath);
970 NS_IMETHODIMP
971 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
972 *aResult = IsSystemPrincipal();
973 return NS_OK;
976 NS_IMETHODIMP
977 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
978 *aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore();
979 return NS_OK;
982 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
983 *aIsOnion = false;
984 nsCOMPtr<nsIURI> prinURI;
985 nsresult rv = GetURI(getter_AddRefs(prinURI));
986 if (NS_FAILED(rv) || !prinURI) {
987 return NS_OK;
990 nsAutoCString host;
991 rv = prinURI->GetHost(host);
992 if (NS_FAILED(rv)) {
993 return NS_OK;
995 *aIsOnion = StringEndsWith(host, ".onion"_ns);
996 return NS_OK;
999 NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
1000 *aIsIpAddress = false;
1002 nsCOMPtr<nsIURI> prinURI;
1003 nsresult rv = GetURI(getter_AddRefs(prinURI));
1004 if (NS_FAILED(rv) || !prinURI) {
1005 return NS_OK;
1008 nsAutoCString host;
1009 rv = prinURI->GetHost(host);
1010 if (NS_FAILED(rv)) {
1011 return NS_OK;
1014 PRNetAddr prAddr;
1015 memset(&prAddr, 0, sizeof(prAddr));
1017 if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
1018 *aIsIpAddress = true;
1021 return NS_OK;
1024 NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) {
1025 *aIsIpAddress = false;
1027 nsCOMPtr<nsIURI> prinURI;
1028 nsresult rv = GetURI(getter_AddRefs(prinURI));
1029 if (NS_FAILED(rv) || !prinURI) {
1030 return NS_OK;
1033 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
1034 if (NS_FAILED(rv) || !ioService) {
1035 return NS_OK;
1037 rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress);
1038 if (NS_FAILED(rv)) {
1039 *aIsIpAddress = false;
1041 return NS_OK;
1044 NS_IMETHODIMP
1045 BasePrincipal::GetScheme(nsACString& aScheme) {
1046 aScheme.Truncate();
1048 nsCOMPtr<nsIURI> prinURI;
1049 nsresult rv = GetURI(getter_AddRefs(prinURI));
1050 if (NS_FAILED(rv) || !prinURI) {
1051 return NS_OK;
1054 return prinURI->GetScheme(aScheme);
1057 NS_IMETHODIMP
1058 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
1059 *aResult = false;
1060 nsCOMPtr<nsIURI> prinURI;
1061 nsresult rv = GetURI(getter_AddRefs(prinURI));
1062 if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) {
1063 return NS_OK;
1065 *aResult = prinURI->SchemeIs(aScheme);
1066 return NS_OK;
1069 NS_IMETHODIMP
1070 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
1071 AssertIsOnMainThread();
1072 *aResult = false;
1073 nsCOMPtr<nsIURI> prinURI;
1074 nsresult rv = GetURI(getter_AddRefs(prinURI));
1075 if (NS_FAILED(rv) || !prinURI) {
1076 return NS_OK;
1078 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
1079 return NS_OK;
1082 NS_IMETHODIMP
1083 BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) {
1084 *aResult = false;
1085 nsCOMPtr<nsIURI> prinURI;
1087 nsresult rv = GetURI(getter_AddRefs(prinURI));
1088 if (NS_FAILED(rv) || !prinURI) {
1089 return NS_OK;
1092 *aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList));
1093 return NS_OK;
1096 NS_IMETHODIMP
1097 BasePrincipal::IsContentAccessibleAboutURI(bool* aResult) {
1098 *aResult = false;
1100 nsCOMPtr<nsIURI> prinURI;
1101 nsresult rv = GetURI(getter_AddRefs(prinURI));
1102 if (NS_FAILED(rv) || !prinURI) {
1103 return NS_OK;
1106 if (!prinURI->SchemeIs("about")) {
1107 return NS_OK;
1110 *aResult = NS_IsContentAccessibleAboutURI(prinURI);
1111 return NS_OK;
1114 NS_IMETHODIMP
1115 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
1116 AssertIsOnMainThread();
1117 *aResult = false;
1119 nsCOMPtr<nsIURI> uri;
1120 nsresult rv = GetURI(getter_AddRefs(uri));
1121 if (NS_FAILED(rv) || !uri) {
1122 return NS_OK;
1125 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
1126 return NS_OK;
1129 NS_IMETHODIMP
1130 BasePrincipal::GetIsLoopbackHost(bool* aRes) {
1131 AssertIsOnMainThread();
1132 *aRes = false;
1133 nsAutoCString host;
1134 nsresult rv = GetHost(host);
1135 // Swallow potential failure as this method is infallible.
1136 if (NS_FAILED(rv)) {
1137 return NS_OK;
1140 *aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host);
1141 return NS_OK;
1144 NS_IMETHODIMP
1145 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
1146 AssertIsOnMainThread();
1147 *flags = 0;
1148 nsCOMPtr<nsIURI> prinURI;
1149 nsresult rv = GetURI(getter_AddRefs(prinURI));
1150 if (NS_FAILED(rv) || !prinURI) {
1151 return NS_ERROR_NOT_AVAILABLE;
1153 if (!prinURI->SchemeIs("about")) {
1154 return NS_OK;
1157 nsCOMPtr<nsIAboutModule> aboutModule;
1158 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
1159 if (NS_FAILED(rv) || !aboutModule) {
1160 return rv;
1162 return aboutModule->GetURIFlags(prinURI, flags);
1165 NS_IMETHODIMP
1166 BasePrincipal::GetOriginAttributes(JSContext* aCx,
1167 JS::MutableHandle<JS::Value> aVal) {
1168 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
1169 return NS_ERROR_FAILURE;
1171 return NS_OK;
1174 NS_IMETHODIMP
1175 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
1176 MOZ_ASSERT(mOriginSuffix);
1177 mOriginSuffix->ToUTF8String(aOriginAttributes);
1178 return NS_OK;
1181 NS_IMETHODIMP
1182 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
1183 *aUserContextId = UserContextId();
1184 return NS_OK;
1187 NS_IMETHODIMP
1188 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
1189 *aPrivateBrowsingId = PrivateBrowsingId();
1190 return NS_OK;
1193 nsresult BasePrincipal::GetAddonPolicy(
1194 extensions::WebExtensionPolicy** aResult) {
1195 AssertIsOnMainThread();
1196 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
1197 policy.forget(aResult);
1198 return NS_OK;
1201 nsresult BasePrincipal::GetContentScriptAddonPolicy(
1202 extensions::WebExtensionPolicy** aResult) {
1203 RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy());
1204 policy.forget(aResult);
1205 return NS_OK;
1208 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
1209 AssertIsOnMainThread();
1210 RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore();
1211 return core ? core->GetMainThreadPolicy() : nullptr;
1214 RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() {
1215 if (Is<ContentPrincipal>()) {
1216 return As<ContentPrincipal>()->AddonPolicyCore();
1218 return nullptr;
1221 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
1222 if (auto policy = AddonPolicyCore()) {
1223 return policy->HasPermission(aPerm);
1225 return false;
1228 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
1229 if (Is<ExpandedPrincipal>()) {
1230 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
1232 return this;
1235 bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
1236 MOZ_ASSERT(aDocumentPrincipal);
1238 // Expanded principals override CSP if and only if they subsume the document
1239 // principal.
1240 if (mKind == eExpandedPrincipal) {
1241 return FastSubsumes(aDocumentPrincipal);
1243 // Extension principals always override the CSP of non-extension principals.
1244 // This is primarily for the sake of their stylesheets, which are usually
1245 // loaded from channels and cannot have expanded principals.
1246 return (AddonPolicyCore() &&
1247 !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore());
1250 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1251 nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) {
1252 MOZ_ASSERT(aURI);
1254 nsAutoCString originNoSuffix;
1255 nsresult rv =
1256 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
1257 if (NS_FAILED(rv)) {
1258 // If the generation of the origin fails, we still want to have a valid
1259 // principal. Better to return a null principal here.
1260 return NullPrincipal::Create(aAttrs);
1263 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain);
1266 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1267 nsIURI* aURI, const OriginAttributes& aAttrs,
1268 const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) {
1269 MOZ_ASSERT(aURI);
1270 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
1272 // If the URI is supposed to inherit the security context of whoever loads it,
1273 // we shouldn't make a content principal for it.
1274 bool inheritsPrincipal;
1275 nsresult rv = NS_URIChainHasFlags(
1276 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
1277 &inheritsPrincipal);
1278 if (NS_FAILED(rv) || inheritsPrincipal) {
1279 return NullPrincipal::Create(aAttrs);
1282 // Check whether the URI knows what its principal is supposed to be.
1283 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
1284 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
1285 do_QueryInterface(aURI);
1286 if (uriWithSpecialOrigin) {
1287 nsCOMPtr<nsIURI> origin;
1288 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
1289 if (NS_WARN_IF(NS_FAILED(rv))) {
1290 return nullptr;
1292 MOZ_ASSERT(origin);
1293 OriginAttributes attrs;
1294 RefPtr<BasePrincipal> principal =
1295 CreateContentPrincipal(origin, attrs, aInitialDomain);
1296 return principal.forget();
1298 #endif
1300 nsCOMPtr<nsIPrincipal> blobPrincipal;
1301 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
1302 aURI, getter_AddRefs(blobPrincipal))) {
1303 MOZ_ASSERT(blobPrincipal);
1304 MOZ_ASSERT(!aInitialDomain,
1305 "an initial domain for a blob URI makes no sense");
1306 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
1307 return principal.forget();
1310 // Mint a content principal.
1311 RefPtr<ContentPrincipal> principal =
1312 new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain);
1313 return principal.forget();
1316 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1317 const nsACString& aOrigin) {
1318 MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns),
1319 "CreateContentPrincipal does not support System and Expanded "
1320 "principals");
1322 MOZ_ASSERT(
1323 !StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")),
1324 "CreateContentPrincipal does not support NullPrincipal");
1326 nsAutoCString originNoSuffix;
1327 OriginAttributes attrs;
1328 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
1329 return nullptr;
1332 nsCOMPtr<nsIURI> uri;
1333 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
1334 NS_ENSURE_SUCCESS(rv, nullptr);
1336 return BasePrincipal::CreateContentPrincipal(uri, attrs);
1339 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
1340 const OriginAttributes& aOriginAttributes) {
1341 if (NS_WARN_IF(!IsContentPrincipal())) {
1342 return nullptr;
1345 nsAutoCString originNoSuffix;
1346 nsresult rv = GetOriginNoSuffix(originNoSuffix);
1347 NS_ENSURE_SUCCESS(rv, nullptr);
1349 nsCOMPtr<nsIURI> uri;
1350 MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri)));
1352 // XXX: This does not copy over the domain. Should it?
1353 RefPtr<ContentPrincipal> copy =
1354 new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr);
1355 return copy.forget();
1358 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
1359 AssertIsOnMainThread();
1360 RefPtr<extensions::WebExtensionPolicyCore> core =
1361 ContentScriptAddonPolicyCore();
1362 return core ? core->GetMainThreadPolicy() : nullptr;
1365 RefPtr<extensions::WebExtensionPolicyCore>
1366 BasePrincipal::ContentScriptAddonPolicyCore() {
1367 if (!Is<ExpandedPrincipal>()) {
1368 return nullptr;
1371 auto* expanded = As<ExpandedPrincipal>();
1372 for (const auto& prin : expanded->AllowList()) {
1373 if (RefPtr<extensions::WebExtensionPolicyCore> policy =
1374 BasePrincipal::Cast(prin)->AddonPolicyCore()) {
1375 return policy;
1379 return nullptr;
1382 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
1383 bool aExplicit /* = false */) {
1384 if (Is<ExpandedPrincipal>()) {
1385 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
1387 if (auto policy = AddonPolicyCore()) {
1388 return policy->CanAccessURI(aURI, aExplicit);
1390 return false;
1393 NS_IMETHODIMP
1394 BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
1395 aKey.Truncate();
1397 nsCOMPtr<nsIURI> uri;
1398 nsresult rv = GetURI(getter_AddRefs(uri));
1399 NS_ENSURE_SUCCESS(rv, rv);
1400 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1402 // The special handling of the file scheme should be consistent with
1403 // GetStorageOriginKey.
1405 nsAutoCString baseDomain;
1406 rv = uri->GetAsciiHost(baseDomain);
1407 NS_ENSURE_SUCCESS(rv, rv);
1409 if (baseDomain.IsEmpty() && uri->SchemeIs("file")) {
1410 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1411 NS_ENSURE_SUCCESS(rv, rv);
1413 rv = url->GetDirectory(baseDomain);
1414 NS_ENSURE_SUCCESS(rv, rv);
1415 } else {
1416 nsCOMPtr<nsIEffectiveTLDService> eTLDService(
1417 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
1418 NS_ENSURE_SUCCESS(rv, rv);
1420 nsAutoCString eTLDplusOne;
1421 rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
1422 if (NS_SUCCEEDED(rv)) {
1423 baseDomain = eTLDplusOne;
1424 } else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
1425 rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
1426 rv = NS_OK;
1428 NS_ENSURE_SUCCESS(rv, rv);
1431 OriginAttributesRef().CreateSuffix(aKey);
1433 nsAutoCString subdomainsDBKey;
1434 rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey);
1435 NS_ENSURE_SUCCESS(rv, rv);
1437 aKey.Append(':');
1438 aKey.Append(subdomainsDBKey);
1440 return NS_OK;
1443 NS_IMETHODIMP
1444 BasePrincipal::GetNextSubDomainPrincipal(
1445 nsIPrincipal** aNextSubDomainPrincipal) {
1446 nsCOMPtr<nsIURI> uri;
1447 nsresult rv = GetURI(getter_AddRefs(uri));
1448 if (NS_FAILED(rv) || !uri) {
1449 return NS_OK;
1452 nsAutoCString host;
1453 rv = uri->GetHost(host);
1454 if (NS_FAILED(rv) || host.IsEmpty()) {
1455 return NS_OK;
1458 nsCString subDomain;
1459 rv = nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host, subDomain);
1461 if (NS_FAILED(rv) || subDomain.IsEmpty()) {
1462 return NS_OK;
1465 nsCOMPtr<nsIURI> subDomainURI;
1466 rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI);
1467 if (NS_FAILED(rv) || !subDomainURI) {
1468 return NS_OK;
1470 // Copy the attributes over
1471 mozilla::OriginAttributes attrs = OriginAttributesRef();
1473 if (!StaticPrefs::permissions_isolateBy_userContext()) {
1474 // Disable userContext for permissions.
1475 attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
1477 RefPtr<nsIPrincipal> principal =
1478 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs);
1480 if (!principal) {
1481 return NS_OK;
1483 principal.forget(aNextSubDomainPrincipal);
1484 return NS_OK;
1487 NS_IMETHODIMP
1488 BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
1489 aOriginKey.Truncate();
1491 nsCOMPtr<nsIURI> uri;
1492 nsresult rv = GetURI(getter_AddRefs(uri));
1493 NS_ENSURE_SUCCESS(rv, rv);
1494 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1496 // The special handling of the file scheme should be consistent with
1497 // GetLocalStorageQuotaKey.
1499 nsAutoCString domainOrigin;
1500 rv = uri->GetAsciiHost(domainOrigin);
1501 NS_ENSURE_SUCCESS(rv, rv);
1503 if (domainOrigin.IsEmpty()) {
1504 // For the file:/// protocol use the exact directory as domain.
1505 if (uri->SchemeIs("file")) {
1506 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1507 NS_ENSURE_SUCCESS(rv, rv);
1508 rv = url->GetDirectory(domainOrigin);
1509 NS_ENSURE_SUCCESS(rv, rv);
1513 // Append reversed domain
1514 nsAutoCString reverseDomain;
1515 rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
1516 NS_ENSURE_SUCCESS(rv, rv);
1518 aOriginKey.Append(reverseDomain);
1520 // Append scheme
1521 nsAutoCString scheme;
1522 rv = uri->GetScheme(scheme);
1523 NS_ENSURE_SUCCESS(rv, rv);
1525 aOriginKey.Append(':');
1526 aOriginKey.Append(scheme);
1528 // Append port if any
1529 int32_t port = NS_GetRealPort(uri);
1530 if (port != -1) {
1531 aOriginKey.Append(nsPrintfCString(":%d", port));
1534 return NS_OK;
1537 NS_IMETHODIMP
1538 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
1539 AssertIsOnMainThread();
1540 *aIsScriptAllowedByPolicy = false;
1541 nsCOMPtr<nsIURI> prinURI;
1542 nsresult rv = GetURI(getter_AddRefs(prinURI));
1543 if (NS_FAILED(rv) || !prinURI) {
1544 return NS_OK;
1546 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1547 if (!ssm) {
1548 return NS_ERROR_UNEXPECTED;
1550 return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
1553 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
1554 MOZ_ASSERT(IsInitialized());
1555 MOZ_ASSERT(aOther.IsInitialized());
1556 return mPrincipal->FastEquals(aOther.mPrincipal);
1559 NS_IMETHODIMP
1560 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
1561 nsIReferrerInfo** _retval) {
1562 nsCOMPtr<nsIURI> prinURI;
1563 RefPtr<dom::ReferrerInfo> info;
1564 nsresult rv = GetURI(getter_AddRefs(prinURI));
1565 if (NS_FAILED(rv) || !prinURI) {
1566 info = new dom::ReferrerInfo(nullptr);
1567 info.forget(_retval);
1568 return NS_OK;
1570 info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
1571 info.forget(_retval);
1572 return NS_OK;
1575 NS_IMETHODIMP
1576 BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) {
1577 *aPrecursor = nullptr;
1578 return NS_OK;
1581 NS_IMPL_ADDREF(BasePrincipal::Deserializer)
1582 NS_IMPL_RELEASE(BasePrincipal::Deserializer)
1584 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer)
1585 NS_INTERFACE_MAP_ENTRY(nsISupports)
1586 NS_INTERFACE_MAP_ENTRY(nsISerializable)
1587 if (mPrincipal) {
1588 return mPrincipal->QueryInterface(aIID, aInstancePtr);
1589 } else
1590 NS_INTERFACE_MAP_END
1592 NS_IMETHODIMP
1593 BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) {
1594 // Read is used still for legacy principals
1595 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
1596 return NS_OK;
1599 /* static */
1600 void BasePrincipal::WriteJSONProperty(JSONWriter& aWriter,
1601 const Span<const char>& aKey,
1602 const nsCString& aValue) {
1603 aWriter.StringProperty(aKey, aValue);
1606 } // namespace mozilla