Bug 1874373 - Part 1: Mark StringIterator.p.next as inlinable. r=jandem
[gecko.git] / caps / BasePrincipal.cpp
blobca611b13f8232ef64ace43cd0fcdc56b3ec75f21
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 "nsIURL.h"
32 #include "nsEffectiveTLDService.h"
33 #include "nsIURIMutator.h"
34 #include "mozilla/StaticPrefs_permissions.h"
35 #include "nsIURIMutator.h"
36 #include "nsMixedContentBlocker.h"
37 #include "prnetdb.h"
38 #include "nsIURIFixup.h"
39 #include "mozilla/dom/StorageUtils.h"
40 #include "mozilla/StorageAccess.h"
41 #include "nsPIDOMWindow.h"
42 #include "nsIURIMutator.h"
43 #include "mozilla/PermissionManager.h"
45 #include "json/json.h"
46 #include "nsSerializationHelper.h"
48 namespace mozilla {
50 const char* BasePrincipal::JSONEnumKeyStrings[4] = {
51 "0",
52 "1",
53 "2",
54 "3",
57 BasePrincipal::BasePrincipal(PrincipalKind aKind,
58 const nsACString& aOriginNoSuffix,
59 const OriginAttributes& aOriginAttributes)
60 : mOriginNoSuffix(NS_Atomize(aOriginNoSuffix)),
61 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
62 mOriginAttributes(aOriginAttributes),
63 mKind(aKind),
64 mHasExplicitDomain(false) {}
66 BasePrincipal::BasePrincipal(BasePrincipal* aOther,
67 const OriginAttributes& aOriginAttributes)
68 : mOriginNoSuffix(aOther->mOriginNoSuffix),
69 mOriginSuffix(aOriginAttributes.CreateSuffixAtom()),
70 mOriginAttributes(aOriginAttributes),
71 mKind(aOther->mKind),
72 mHasExplicitDomain(aOther->mHasExplicitDomain.load()) {}
74 BasePrincipal::~BasePrincipal() = default;
76 NS_IMETHODIMP
77 BasePrincipal::GetOrigin(nsACString& aOrigin) {
78 nsresult rv = GetOriginNoSuffix(aOrigin);
79 NS_ENSURE_SUCCESS(rv, rv);
81 nsAutoCString suffix;
82 rv = GetOriginSuffix(suffix);
83 NS_ENSURE_SUCCESS(rv, rv);
84 aOrigin.Append(suffix);
85 return NS_OK;
88 NS_IMETHODIMP
89 BasePrincipal::GetWebExposedOriginSerialization(nsACString& aOrigin) {
90 aOrigin.Truncate();
91 nsCOMPtr<nsIURI> prinURI;
92 nsresult rv = GetURI(getter_AddRefs(prinURI));
93 if (NS_FAILED(rv) || !prinURI) {
94 return NS_ERROR_NOT_AVAILABLE;
96 return nsContentUtils::GetWebExposedOriginSerialization(prinURI, aOrigin);
99 NS_IMETHODIMP
100 BasePrincipal::GetHostPort(nsACString& aRes) {
101 aRes.Truncate();
102 nsCOMPtr<nsIURI> prinURI;
103 nsresult rv = GetURI(getter_AddRefs(prinURI));
104 if (NS_FAILED(rv) || !prinURI) {
105 return NS_OK;
107 return prinURI->GetHostPort(aRes);
110 NS_IMETHODIMP
111 BasePrincipal::GetHost(nsACString& aRes) {
112 aRes.Truncate();
113 nsCOMPtr<nsIURI> prinURI;
114 nsresult rv = GetURI(getter_AddRefs(prinURI));
115 if (NS_FAILED(rv) || !prinURI) {
116 return NS_OK;
118 return prinURI->GetHost(aRes);
121 NS_IMETHODIMP
122 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
123 mOriginNoSuffix->ToUTF8String(aOrigin);
124 return NS_OK;
127 NS_IMETHODIMP
128 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
129 nsresult rv = GetSiteOriginNoSuffix(aSiteOrigin);
130 NS_ENSURE_SUCCESS(rv, rv);
132 nsAutoCString suffix;
133 rv = GetOriginSuffix(suffix);
134 NS_ENSURE_SUCCESS(rv, rv);
135 aSiteOrigin.Append(suffix);
136 return NS_OK;
139 NS_IMETHODIMP
140 BasePrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) {
141 return GetOriginNoSuffix(aSiteOrigin);
144 // Returns the inner Json::value of the serialized principal
145 // Example input and return values:
146 // Null principal:
147 // {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
148 // {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
150 // Content principal:
151 // {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
153 // Expanded principal:
154 // {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
155 // {"0":"<base64principal1>,<base64principal2>"}
157 // System principal:
158 // {"3":{}} -> {}
159 // The aKey passed in also returns the corresponding PrincipalKind enum
161 // Warning: The Json::Value* pointer is into the aRoot object
162 static const Json::Value* GetPrincipalObject(const Json::Value& aRoot,
163 int& aOutPrincipalKind) {
164 const Json::Value::Members members = aRoot.getMemberNames();
165 // We only support one top level key in the object
166 if (members.size() != 1) {
167 return nullptr;
169 // members[0] here is the "0", "1", "2", "3" principalKind
170 // that is the top level of the serialized JSON principal
171 const std::string stringPrincipalKind = members[0];
173 // Next we take the string value from the JSON
174 // and convert it into the int for the BasePrincipal::PrincipalKind enum
176 // Verify that the key is within the valid range
177 int principalKind = std::stoi(stringPrincipalKind);
178 MOZ_ASSERT(BasePrincipal::eNullPrincipal == 0,
179 "We need to rely on 0 being a bounds check for the first "
180 "principal kind.");
181 if (principalKind < 0 || principalKind > BasePrincipal::eKindMax) {
182 return nullptr;
184 MOZ_ASSERT(principalKind == BasePrincipal::eNullPrincipal ||
185 principalKind == BasePrincipal::eContentPrincipal ||
186 principalKind == BasePrincipal::eExpandedPrincipal ||
187 principalKind == BasePrincipal::eSystemPrincipal);
188 aOutPrincipalKind = principalKind;
190 if (!aRoot[stringPrincipalKind].isObject()) {
191 return nullptr;
194 // Return the inner value of the principal object
195 return &aRoot[stringPrincipalKind];
198 // Accepts the JSON inner object without the wrapping principalKind
199 // (See GetPrincipalObject for the inner object response examples)
200 // Creates an array of KeyVal objects that are all defined on the principal
201 // Each principal type (null, content, expanded) has a KeyVal that stores the
202 // fields of the JSON
204 // This simplifies deserializing elsewhere as we do the checking for presence
205 // and string values here for the complete set of serializable keys that the
206 // corresponding principal supports.
208 // The KeyVal object has the following fields:
209 // - valueWasSerialized: is true if the deserialized JSON contained a string
210 // value
211 // - value: The string that was serialized for this key
212 // - key: an SerializableKeys enum value specific to the principal.
213 // For example content principal is an enum of: eURI, eDomain,
214 // eSuffix, eCSP
217 // Given an inner content principal:
218 // {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
219 // | | | |
220 // ----------------------------- |
221 // | | |
222 // Key ----------------------
223 // |
224 // Value
226 // They Key "0" corresponds to ContentPrincipal::eURI
227 // They Key "1" corresponds to ContentPrincipal::eSuffix
228 template <typename T>
229 static nsTArray<typename T::KeyVal> GetJSONKeys(const Json::Value* aInput) {
230 int size = T::eMax + 1;
231 nsTArray<typename T::KeyVal> fields;
232 for (int i = 0; i != size; i++) {
233 typename T::KeyVal* field = fields.AppendElement();
234 // field->valueWasSerialized returns if the field was found in the
235 // deserialized code. This simplifies the consumers from having to check
236 // length.
237 field->valueWasSerialized = false;
238 field->key = static_cast<typename T::SerializableKeys>(i);
239 const std::string key = std::to_string(field->key);
240 if (aInput->isMember(key)) {
241 const Json::Value& val = (*aInput)[key];
242 if (val.isString()) {
243 field->value.Append(nsDependentCString(val.asCString()));
244 field->valueWasSerialized = true;
248 return fields;
251 // Takes a JSON string and parses it turning it into a principal of the
252 // corresponding type
254 // Given a content principal:
256 // inner JSON object
257 // |
258 // ---------------------------------------------------------
259 // | |
260 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
261 // | | | | |
262 // | ----------------------------- |
263 // | | | |
264 // PrincipalKind | | |
265 // | ----------------------------
266 // SerializableKeys |
267 // Value
269 // The string is first deserialized with jsoncpp to get the Json::Value of the
270 // object. The inner JSON object is parsed with GetPrincipalObject which returns
271 // a KeyVal array of the inner object's fields. PrincipalKind is returned by
272 // GetPrincipalObject which is then used to decide which principal
273 // implementation of FromProperties to call. The corresponding FromProperties
274 // call takes the KeyVal fields and turns it into a principal.
275 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
276 const nsACString& aJSON) {
277 Json::Value root;
278 Json::CharReaderBuilder builder;
279 std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
280 bool parseSuccess =
281 reader->parse(aJSON.BeginReading(), aJSON.EndReading(), &root, nullptr);
282 if (!parseSuccess) {
283 MOZ_ASSERT(false,
284 "Unable to parse string as JSON to deserialize as a principal");
285 return nullptr;
288 return FromJSON(root);
291 // Checks if an ExpandedPrincipal is using the legacy format, where
292 // sub-principals are Base64 encoded.
294 // Given a legacy expanded principal:
296 // *
297 // {"2": {"0": "eyIxIjp7IjAiOiJodHRwczovL2EuY29tLyJ9fQ=="}}
298 // | | |
299 // | ---------- Value
300 // | |
301 // PrincipalKind |
302 // |
303 // SerializableKeys
305 // The value is a CSV list of Base64 encoded prinipcals. The new format for this
306 // principal is:
308 // Subsumed principals
309 // |
310 // ------------------------------------
311 // * | |
312 // {"2": {"0": [{"1": {"0": https://mozilla.com"}}]}}
313 // | | |
314 // -------------- Value
315 // |
316 // PrincipalKind
318 // It is possible to tell these apart by checking the type of the property noted
319 // in both diagrams with an asterisk. In the legacy format the type will be a
320 // string and in the new format it will be an array.
321 static bool IsLegacyFormat(const Json::Value& aValue) {
322 const auto& specs = std::to_string(ExpandedPrincipal::eSpecs);
323 return aValue.isMember(specs) && aValue[specs].isString();
326 /* static */
327 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
328 const Json::Value& aJSON) {
329 int principalKind = -1;
330 const Json::Value* value = GetPrincipalObject(aJSON, principalKind);
331 if (!value) {
332 #ifdef DEBUG
333 fprintf(stderr, "Unexpected JSON principal %s\n",
334 aJSON.toStyledString().c_str());
335 #endif
336 MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
338 return nullptr;
340 MOZ_ASSERT(principalKind != -1,
341 "PrincipalKind should always be >=0 by this point");
343 if (principalKind == eSystemPrincipal) {
344 RefPtr<BasePrincipal> principal =
345 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
346 return principal.forget();
349 if (principalKind == eNullPrincipal) {
350 nsTArray<NullPrincipal::KeyVal> res = GetJSONKeys<NullPrincipal>(value);
351 return NullPrincipal::FromProperties(res);
354 if (principalKind == eContentPrincipal) {
355 nsTArray<ContentPrincipal::KeyVal> res =
356 GetJSONKeys<ContentPrincipal>(value);
357 return ContentPrincipal::FromProperties(res);
360 if (principalKind == eExpandedPrincipal) {
361 // Check if expanded principals is stored in the new or the old format. See
362 // comment for `IsLegacyFormat`.
363 if (IsLegacyFormat(*value)) {
364 nsTArray<ExpandedPrincipal::KeyVal> res =
365 GetJSONKeys<ExpandedPrincipal>(value);
366 return ExpandedPrincipal::FromProperties(res);
369 return ExpandedPrincipal::FromProperties(*value);
372 MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
375 nsresult BasePrincipal::PopulateJSONObject(Json::Value& aObject) {
376 return NS_OK;
379 // Returns a JSON representation of the principal.
380 // Calling BasePrincipal::FromJSON will deserialize the JSON into
381 // the corresponding principal type.
382 nsresult BasePrincipal::ToJSON(nsACString& aJSON) {
383 MOZ_ASSERT(aJSON.IsEmpty(), "ToJSON only supports an empty result input");
384 aJSON.Truncate();
386 Json::Value root = Json::objectValue;
387 nsresult rv = ToJSON(root);
388 NS_ENSURE_SUCCESS(rv, rv);
390 static StaticAutoPtr<Json::StreamWriterBuilder> sJSONBuilderForPrincipals;
391 if (!sJSONBuilderForPrincipals) {
392 sJSONBuilderForPrincipals = new Json::StreamWriterBuilder();
393 (*sJSONBuilderForPrincipals)["indentation"] = "";
394 (*sJSONBuilderForPrincipals)["emitUTF8"] = true;
395 ClearOnShutdown(&sJSONBuilderForPrincipals);
397 std::string result = Json::writeString(*sJSONBuilderForPrincipals, root);
398 aJSON.Append(result);
399 if (aJSON.Length() == 0) {
400 MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
401 return NS_ERROR_UNEXPECTED;
404 return NS_OK;
407 nsresult BasePrincipal::ToJSON(Json::Value& aObject) {
408 static_assert(eKindMax < ArrayLength(JSONEnumKeyStrings));
409 nsresult rv = PopulateJSONObject(
410 (aObject[Json::StaticString(JSONEnumKeyStrings[Kind()])] =
411 Json::objectValue));
412 NS_ENSURE_SUCCESS(rv, rv);
414 return NS_OK;
417 bool BasePrincipal::FastSubsumesIgnoringFPD(
418 nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) {
419 MOZ_ASSERT(aOther);
421 if (Kind() == eContentPrincipal &&
422 !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
423 mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
424 return false;
427 return SubsumesInternal(aOther, aConsideration);
430 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
431 DocumentDomainConsideration aConsideration) {
432 MOZ_ASSERT(aOther);
433 MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
435 // Expanded principals handle origin attributes for each of their
436 // sub-principals individually, null principals do only simple checks for
437 // pointer equality, and system principals are immune to origin attributes
438 // checks, so only do this check for content principals.
439 if (Kind() == eContentPrincipal &&
440 mOriginSuffix != Cast(aOther)->mOriginSuffix) {
441 return false;
444 return SubsumesInternal(aOther, aConsideration);
447 NS_IMETHODIMP
448 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
449 NS_ENSURE_ARG_POINTER(aOther);
451 *aResult = FastEquals(aOther);
453 return NS_OK;
456 NS_IMETHODIMP
457 BasePrincipal::EqualsForPermission(nsIPrincipal* aOther, bool aExactHost,
458 bool* aResult) {
459 *aResult = false;
460 NS_ENSURE_ARG_POINTER(aOther);
461 NS_ENSURE_ARG_POINTER(aResult);
463 auto* other = Cast(aOther);
464 if (Kind() != other->Kind()) {
465 // Principals of different kinds can't be equal.
466 return NS_OK;
469 if (Kind() == eSystemPrincipal) {
470 *aResult = this == other;
471 return NS_OK;
474 if (Kind() == eNullPrincipal) {
475 // We don't store permissions for NullPrincipals.
476 return NS_OK;
479 MOZ_ASSERT(Kind() == eExpandedPrincipal || Kind() == eContentPrincipal);
481 // Certain origin attributes should not be used to isolate permissions.
482 // Create a stripped copy of both OA sets to compare.
483 mozilla::OriginAttributes ourAttrs = mOriginAttributes;
484 PermissionManager::MaybeStripOriginAttributes(false, ourAttrs);
485 mozilla::OriginAttributes theirAttrs = aOther->OriginAttributesRef();
486 PermissionManager::MaybeStripOriginAttributes(false, theirAttrs);
488 if (ourAttrs != theirAttrs) {
489 return NS_OK;
492 if (mOriginNoSuffix == other->mOriginNoSuffix) {
493 *aResult = true;
494 return NS_OK;
497 // If we are matching with an exact host, we're done now - the permissions
498 // don't match otherwise, we need to start comparing subdomains!
499 if (aExactHost) {
500 return NS_OK;
503 nsCOMPtr<nsIURI> ourURI;
504 nsresult rv = GetURI(getter_AddRefs(ourURI));
505 NS_ENSURE_SUCCESS(rv, rv);
506 // Some principal types may indicate success, but still return nullptr for
507 // URI.
508 NS_ENSURE_TRUE(ourURI, NS_ERROR_FAILURE);
510 nsCOMPtr<nsIURI> otherURI;
511 rv = other->GetURI(getter_AddRefs(otherURI));
512 NS_ENSURE_SUCCESS(rv, rv);
513 NS_ENSURE_TRUE(otherURI, NS_ERROR_FAILURE);
515 // Compare schemes
516 nsAutoCString otherScheme;
517 rv = otherURI->GetScheme(otherScheme);
518 NS_ENSURE_SUCCESS(rv, rv);
520 nsAutoCString ourScheme;
521 rv = ourURI->GetScheme(ourScheme);
522 NS_ENSURE_SUCCESS(rv, rv);
524 if (otherScheme != ourScheme) {
525 return NS_OK;
528 // Compare ports
529 int32_t otherPort;
530 rv = otherURI->GetPort(&otherPort);
531 NS_ENSURE_SUCCESS(rv, rv);
533 int32_t ourPort;
534 rv = ourURI->GetPort(&ourPort);
535 NS_ENSURE_SUCCESS(rv, rv);
537 if (otherPort != ourPort) {
538 return NS_OK;
541 // Check if the host or any subdomain of their host matches.
542 nsAutoCString otherHost;
543 rv = otherURI->GetHost(otherHost);
544 if (NS_FAILED(rv) || otherHost.IsEmpty()) {
545 return NS_OK;
548 nsAutoCString ourHost;
549 rv = ourURI->GetHost(ourHost);
550 if (NS_FAILED(rv) || ourHost.IsEmpty()) {
551 return NS_OK;
554 nsCOMPtr<nsIEffectiveTLDService> tldService =
555 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
556 if (!tldService) {
557 NS_ERROR("Should have a tld service!");
558 return NS_ERROR_FAILURE;
561 // This loop will not loop forever, as GetNextSubDomain will eventually fail
562 // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
563 while (otherHost != ourHost) {
564 rv = tldService->GetNextSubDomain(otherHost, otherHost);
565 if (NS_FAILED(rv)) {
566 if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
567 return NS_OK;
569 return rv;
573 *aResult = true;
574 return NS_OK;
577 NS_IMETHODIMP
578 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
579 NS_ENSURE_ARG_POINTER(aOther);
581 *aResult = FastEqualsConsideringDomain(aOther);
583 return NS_OK;
586 NS_IMETHODIMP
587 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
588 *aResult = false;
589 nsCOMPtr<nsIURI> prinURI;
590 nsresult rv = GetURI(getter_AddRefs(prinURI));
591 if (NS_FAILED(rv) || !prinURI) {
592 return NS_OK;
594 return prinURI->EqualsExceptRef(aOtherURI, aResult);
597 NS_IMETHODIMP
598 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
599 NS_ENSURE_ARG_POINTER(aOther);
601 *aResult = FastSubsumes(aOther);
603 return NS_OK;
606 NS_IMETHODIMP
607 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
608 NS_ENSURE_ARG_POINTER(aOther);
610 *aResult = FastSubsumesConsideringDomain(aOther);
612 return NS_OK;
615 NS_IMETHODIMP
616 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
617 bool* aResult) {
618 NS_ENSURE_ARG_POINTER(aOther);
620 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
622 return NS_OK;
625 NS_IMETHODIMP
626 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
627 AssertIsOnMainThread();
628 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
631 NS_IMETHODIMP
632 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
633 bool aAllowIfInheritsPrincipal,
634 uint64_t aInnerWindowID) {
635 AssertIsOnMainThread();
636 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
637 aInnerWindowID);
640 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
641 bool aAllowIfInheritsPrincipal,
642 bool aReport,
643 uint64_t aInnerWindowID) {
644 AssertIsOnMainThread(); // Accesses non-threadsafe URI flags and the
645 // non-threadsafe ExtensionPolicyService
646 NS_ENSURE_ARG_POINTER(aURI);
647 MOZ_ASSERT(
648 aReport || aInnerWindowID == 0,
649 "Why do we have an inner window id if we're not supposed to report?");
651 // Check the internal method first, which allows us to quickly approve loads
652 // for the System Principal.
653 if (MayLoadInternal(aURI)) {
654 return NS_OK;
657 nsresult rv;
658 if (aAllowIfInheritsPrincipal) {
659 // If the caller specified to allow loads of URIs that inherit
660 // our principal, allow the load if this URI inherits its principal.
661 bool doesInheritSecurityContext;
662 rv = NS_URIChainHasFlags(aURI,
663 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
664 &doesInheritSecurityContext);
665 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
666 return NS_OK;
670 // Web Accessible Resources in MV2 Extensions are marked with
671 // URI_FETCHABLE_BY_ANYONE
672 bool fetchableByAnyone;
673 rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
674 &fetchableByAnyone);
675 if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
676 return NS_OK;
679 // Get the principal uri for the last flag check or error.
680 nsCOMPtr<nsIURI> prinURI;
681 rv = GetURI(getter_AddRefs(prinURI));
682 if (!(NS_SUCCEEDED(rv) && prinURI)) {
683 return NS_ERROR_DOM_BAD_URI;
686 // If MV3 Extension uris are web accessible by this principal it is allowed to
687 // load.
688 bool maybeWebAccessible = false;
689 NS_URIChainHasFlags(aURI, nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
690 &maybeWebAccessible);
691 NS_ENSURE_SUCCESS(rv, rv);
692 if (maybeWebAccessible) {
693 bool isWebAccessible = false;
694 rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
695 prinURI, aURI, &isWebAccessible);
696 if (NS_SUCCEEDED(rv) && isWebAccessible) {
697 return NS_OK;
701 if (aReport) {
702 nsScriptSecurityManager::ReportError(
703 "CheckSameOriginError", prinURI, aURI,
704 mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
707 return NS_ERROR_DOM_BAD_URI;
710 NS_IMETHODIMP
711 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
712 if (IsSystemPrincipal() || (AddonPolicyCore() && AddonAllowsLoad(aURI))) {
713 *aRes = false;
714 return NS_OK;
717 *aRes = true;
718 // If we do not have a URI its always 3rd party.
719 nsCOMPtr<nsIURI> prinURI;
720 nsresult rv = GetURI(getter_AddRefs(prinURI));
721 if (NS_FAILED(rv) || !prinURI) {
722 return NS_OK;
724 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
725 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
728 NS_IMETHODIMP
729 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
730 *aRes = true;
731 nsCOMPtr<nsIURI> prinURI;
732 nsresult rv = GetURI(getter_AddRefs(prinURI));
733 if (NS_FAILED(rv) || !prinURI) {
734 return NS_OK;
736 return aPrin->IsThirdPartyURI(prinURI, aRes);
739 NS_IMETHODIMP
740 BasePrincipal::IsThirdPartyChannel(nsIChannel* aChan, bool* aRes) {
741 AssertIsOnMainThread();
742 if (IsSystemPrincipal()) {
743 // Nothing is 3rd party to the system principal.
744 *aRes = false;
745 return NS_OK;
748 nsCOMPtr<nsIURI> prinURI;
749 GetURI(getter_AddRefs(prinURI));
750 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
751 return thirdPartyUtil->IsThirdPartyChannel(aChan, prinURI, aRes);
754 NS_IMETHODIMP
755 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool* aRes) {
756 *aRes = false;
757 nsCOMPtr<nsIURI> prinURI;
758 nsresult rv = GetURI(getter_AddRefs(prinURI));
759 if (NS_FAILED(rv) || !prinURI) {
760 // Note that expanded and system principals return here, because they have
761 // no URI.
762 return NS_OK;
764 *aRes = nsScriptSecurityManager::SecurityCompareURIs(prinURI, aURI);
765 return NS_OK;
768 NS_IMETHODIMP
769 BasePrincipal::IsL10nAllowed(nsIURI* aURI, bool* aRes) {
770 AssertIsOnMainThread(); // URI_DANGEROUS_TO_LOAD is not threadsafe to query.
771 *aRes = false;
773 if (nsContentUtils::IsErrorPage(aURI)) {
774 *aRes = true;
775 return NS_OK;
778 // The system principal is always allowed.
779 if (IsSystemPrincipal()) {
780 *aRes = true;
781 return NS_OK;
784 nsCOMPtr<nsIURI> uri;
785 nsresult rv = GetURI(getter_AddRefs(uri));
786 NS_ENSURE_SUCCESS(rv, NS_OK);
788 bool hasFlags;
790 // Allow access to uris that cannot be loaded by web content.
791 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DANGEROUS_TO_LOAD,
792 &hasFlags);
793 NS_ENSURE_SUCCESS(rv, NS_OK);
794 if (hasFlags) {
795 *aRes = true;
796 return NS_OK;
799 // UI resources also get access.
800 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
801 &hasFlags);
802 NS_ENSURE_SUCCESS(rv, NS_OK);
803 if (hasFlags) {
804 *aRes = true;
805 return NS_OK;
808 auto policy = AddonPolicyCore();
809 *aRes = (policy && policy->IsPrivileged());
810 return NS_OK;
813 NS_IMETHODIMP
814 BasePrincipal::AllowsRelaxStrictFileOriginPolicy(nsIURI* aURI, bool* aRes) {
815 *aRes = false;
816 nsCOMPtr<nsIURI> prinURI;
817 nsresult rv = GetURI(getter_AddRefs(prinURI));
818 if (NS_FAILED(rv) || !prinURI) {
819 return NS_OK;
821 *aRes = NS_RelaxStrictFileOriginPolicy(aURI, prinURI);
822 return NS_OK;
825 NS_IMETHODIMP
826 BasePrincipal::GetPrefLightCacheKey(nsIURI* aURI, bool aWithCredentials,
827 const OriginAttributes& aOriginAttributes,
828 nsACString& _retval) {
829 _retval.Truncate();
830 constexpr auto space = " "_ns;
832 nsCOMPtr<nsIURI> uri;
833 nsresult rv = GetURI(getter_AddRefs(uri));
834 NS_ENSURE_SUCCESS(rv, rv);
836 nsAutoCString scheme, host, port;
837 if (uri) {
838 uri->GetScheme(scheme);
839 uri->GetHost(host);
840 port.AppendInt(NS_GetRealPort(uri));
843 if (aWithCredentials) {
844 _retval.AssignLiteral("cred");
845 } else {
846 _retval.AssignLiteral("nocred");
849 nsAutoCString spec;
850 rv = aURI->GetSpec(spec);
851 NS_ENSURE_SUCCESS(rv, rv);
853 nsAutoCString originAttributesSuffix;
854 aOriginAttributes.CreateSuffix(originAttributesSuffix);
856 _retval.Append(space + scheme + space + host + space + port + space + spec +
857 space + originAttributesSuffix);
859 return NS_OK;
862 NS_IMETHODIMP
863 BasePrincipal::HasFirstpartyStorageAccess(mozIDOMWindow* aCheckWindow,
864 uint32_t* aRejectedReason,
865 bool* aOutAllowed) {
866 AssertIsOnMainThread();
867 *aRejectedReason = 0;
868 *aOutAllowed = false;
870 nsPIDOMWindowInner* win = nsPIDOMWindowInner::From(aCheckWindow);
871 nsCOMPtr<nsIURI> uri;
872 nsresult rv = GetURI(getter_AddRefs(uri));
873 if (NS_FAILED(rv)) {
874 return rv;
876 *aOutAllowed = ShouldAllowAccessFor(win, uri, aRejectedReason);
877 return NS_OK;
880 NS_IMETHODIMP
881 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
882 *aResult = Kind() == eNullPrincipal;
883 return NS_OK;
886 NS_IMETHODIMP
887 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
888 *aResult = Kind() == eContentPrincipal;
889 return NS_OK;
892 NS_IMETHODIMP
893 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
894 *aResult = Kind() == eExpandedPrincipal;
895 return NS_OK;
898 NS_IMETHODIMP
899 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
900 aSpec.Truncate();
901 nsCOMPtr<nsIURI> prinURI;
902 nsresult rv = GetURI(getter_AddRefs(prinURI));
903 if (NS_FAILED(rv) || !prinURI) {
904 return NS_OK;
906 return prinURI->GetAsciiSpec(aSpec);
909 NS_IMETHODIMP
910 BasePrincipal::GetSpec(nsACString& aSpec) {
911 aSpec.Truncate();
912 nsCOMPtr<nsIURI> prinURI;
913 nsresult rv = GetURI(getter_AddRefs(prinURI));
914 if (NS_FAILED(rv) || !prinURI) {
915 return NS_OK;
917 return prinURI->GetSpec(aSpec);
920 NS_IMETHODIMP
921 BasePrincipal::GetAsciiHost(nsACString& aHost) {
922 aHost.Truncate();
923 nsCOMPtr<nsIURI> prinURI;
924 nsresult rv = GetURI(getter_AddRefs(prinURI));
925 if (NS_FAILED(rv) || !prinURI) {
926 return NS_OK;
928 return prinURI->GetAsciiHost(aHost);
931 NS_IMETHODIMP
932 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
933 aPrepath.Truncate();
934 nsCOMPtr<nsIURI> prinURI;
935 nsresult rv = GetURI(getter_AddRefs(prinURI));
936 if (NS_FAILED(rv) || !prinURI) {
937 return NS_OK;
940 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(prinURI);
941 return exposableURI->GetDisplayPrePath(aPrepath);
944 NS_IMETHODIMP
945 BasePrincipal::GetExposableSpec(nsACString& aSpec) {
946 aSpec.Truncate();
947 nsCOMPtr<nsIURI> prinURI;
948 nsresult rv = GetURI(getter_AddRefs(prinURI));
949 if (NS_FAILED(rv) || !prinURI) {
950 return NS_OK;
952 nsCOMPtr<nsIURI> clone;
953 rv = NS_MutateURI(prinURI)
954 .SetQuery(""_ns)
955 .SetRef(""_ns)
956 .SetUserPass(""_ns)
957 .Finalize(clone);
958 NS_ENSURE_SUCCESS(rv, rv);
959 return clone->GetAsciiSpec(aSpec);
962 NS_IMETHODIMP
963 BasePrincipal::GetPrePath(nsACString& aPath) {
964 aPath.Truncate();
965 nsCOMPtr<nsIURI> prinURI;
966 nsresult rv = GetURI(getter_AddRefs(prinURI));
967 if (NS_FAILED(rv) || !prinURI) {
968 return NS_OK;
970 return prinURI->GetPrePath(aPath);
973 NS_IMETHODIMP
974 BasePrincipal::GetFilePath(nsACString& aPath) {
975 aPath.Truncate();
976 nsCOMPtr<nsIURI> prinURI;
977 nsresult rv = GetURI(getter_AddRefs(prinURI));
978 if (NS_FAILED(rv) || !prinURI) {
979 return NS_OK;
981 return prinURI->GetFilePath(aPath);
984 NS_IMETHODIMP
985 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
986 *aResult = IsSystemPrincipal();
987 return NS_OK;
990 NS_IMETHODIMP
991 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
992 *aResult = AddonPolicyCore() || ContentScriptAddonPolicyCore();
993 return NS_OK;
996 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
997 *aIsOnion = false;
998 nsCOMPtr<nsIURI> prinURI;
999 nsresult rv = GetURI(getter_AddRefs(prinURI));
1000 if (NS_FAILED(rv) || !prinURI) {
1001 return NS_OK;
1004 nsAutoCString host;
1005 rv = prinURI->GetHost(host);
1006 if (NS_FAILED(rv)) {
1007 return NS_OK;
1009 *aIsOnion = StringEndsWith(host, ".onion"_ns);
1010 return NS_OK;
1013 NS_IMETHODIMP BasePrincipal::GetIsIpAddress(bool* aIsIpAddress) {
1014 *aIsIpAddress = false;
1016 nsCOMPtr<nsIURI> prinURI;
1017 nsresult rv = GetURI(getter_AddRefs(prinURI));
1018 if (NS_FAILED(rv) || !prinURI) {
1019 return NS_OK;
1022 nsAutoCString host;
1023 rv = prinURI->GetHost(host);
1024 if (NS_FAILED(rv)) {
1025 return NS_OK;
1028 PRNetAddr prAddr;
1029 memset(&prAddr, 0, sizeof(prAddr));
1031 if (PR_StringToNetAddr(host.get(), &prAddr) == PR_SUCCESS) {
1032 *aIsIpAddress = true;
1035 return NS_OK;
1038 NS_IMETHODIMP BasePrincipal::GetIsLocalIpAddress(bool* aIsIpAddress) {
1039 *aIsIpAddress = false;
1041 nsCOMPtr<nsIURI> prinURI;
1042 nsresult rv = GetURI(getter_AddRefs(prinURI));
1043 if (NS_FAILED(rv) || !prinURI) {
1044 return NS_OK;
1047 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
1048 if (NS_FAILED(rv) || !ioService) {
1049 return NS_OK;
1051 rv = ioService->HostnameIsLocalIPAddress(prinURI, aIsIpAddress);
1052 if (NS_FAILED(rv)) {
1053 *aIsIpAddress = false;
1055 return NS_OK;
1058 NS_IMETHODIMP
1059 BasePrincipal::GetScheme(nsACString& aScheme) {
1060 aScheme.Truncate();
1062 nsCOMPtr<nsIURI> prinURI;
1063 nsresult rv = GetURI(getter_AddRefs(prinURI));
1064 if (NS_FAILED(rv) || !prinURI) {
1065 return NS_OK;
1068 return prinURI->GetScheme(aScheme);
1071 NS_IMETHODIMP
1072 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
1073 *aResult = false;
1074 nsCOMPtr<nsIURI> prinURI;
1075 nsresult rv = GetURI(getter_AddRefs(prinURI));
1076 if (NS_WARN_IF(NS_FAILED(rv)) || !prinURI) {
1077 return NS_OK;
1079 *aResult = prinURI->SchemeIs(aScheme);
1080 return NS_OK;
1083 NS_IMETHODIMP
1084 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
1085 AssertIsOnMainThread();
1086 *aResult = false;
1087 nsCOMPtr<nsIURI> prinURI;
1088 nsresult rv = GetURI(getter_AddRefs(prinURI));
1089 if (NS_FAILED(rv) || !prinURI) {
1090 return NS_OK;
1092 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
1093 return NS_OK;
1096 NS_IMETHODIMP
1097 BasePrincipal::IsURIInList(const nsACString& aList, bool* aResult) {
1098 *aResult = false;
1099 nsCOMPtr<nsIURI> prinURI;
1101 nsresult rv = GetURI(getter_AddRefs(prinURI));
1102 if (NS_FAILED(rv) || !prinURI) {
1103 return NS_OK;
1106 *aResult = nsContentUtils::IsURIInList(prinURI, nsCString(aList));
1107 return NS_OK;
1110 NS_IMETHODIMP
1111 BasePrincipal::IsContentAccessibleAboutURI(bool* aResult) {
1112 *aResult = false;
1114 nsCOMPtr<nsIURI> prinURI;
1115 nsresult rv = GetURI(getter_AddRefs(prinURI));
1116 if (NS_FAILED(rv) || !prinURI) {
1117 return NS_OK;
1120 if (!prinURI->SchemeIs("about")) {
1121 return NS_OK;
1124 *aResult = NS_IsContentAccessibleAboutURI(prinURI);
1125 return NS_OK;
1128 NS_IMETHODIMP
1129 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
1130 AssertIsOnMainThread();
1131 *aResult = false;
1133 nsCOMPtr<nsIURI> uri;
1134 nsresult rv = GetURI(getter_AddRefs(uri));
1135 if (NS_FAILED(rv) || !uri) {
1136 return NS_OK;
1139 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
1140 return NS_OK;
1143 NS_IMETHODIMP
1144 BasePrincipal::GetIsLoopbackHost(bool* aRes) {
1145 AssertIsOnMainThread();
1146 *aRes = false;
1147 nsAutoCString host;
1148 nsresult rv = GetHost(host);
1149 // Swallow potential failure as this method is infallible.
1150 if (NS_FAILED(rv)) {
1151 return NS_OK;
1154 *aRes = nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(host);
1155 return NS_OK;
1158 NS_IMETHODIMP
1159 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
1160 AssertIsOnMainThread();
1161 *flags = 0;
1162 nsCOMPtr<nsIURI> prinURI;
1163 nsresult rv = GetURI(getter_AddRefs(prinURI));
1164 if (NS_FAILED(rv) || !prinURI) {
1165 return NS_ERROR_NOT_AVAILABLE;
1167 if (!prinURI->SchemeIs("about")) {
1168 return NS_OK;
1171 nsCOMPtr<nsIAboutModule> aboutModule;
1172 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
1173 if (NS_FAILED(rv) || !aboutModule) {
1174 return rv;
1176 return aboutModule->GetURIFlags(prinURI, flags);
1179 NS_IMETHODIMP
1180 BasePrincipal::GetOriginAttributes(JSContext* aCx,
1181 JS::MutableHandle<JS::Value> aVal) {
1182 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
1183 return NS_ERROR_FAILURE;
1185 return NS_OK;
1188 NS_IMETHODIMP
1189 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
1190 MOZ_ASSERT(mOriginSuffix);
1191 mOriginSuffix->ToUTF8String(aOriginAttributes);
1192 return NS_OK;
1195 NS_IMETHODIMP
1196 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
1197 *aUserContextId = UserContextId();
1198 return NS_OK;
1201 NS_IMETHODIMP
1202 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
1203 *aPrivateBrowsingId = PrivateBrowsingId();
1204 return NS_OK;
1207 NS_IMETHODIMP
1208 BasePrincipal::GetIsInIsolatedMozBrowserElement(
1209 bool* aIsInIsolatedMozBrowserElement) {
1210 *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
1211 return NS_OK;
1214 nsresult BasePrincipal::GetAddonPolicy(
1215 extensions::WebExtensionPolicy** aResult) {
1216 AssertIsOnMainThread();
1217 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
1218 policy.forget(aResult);
1219 return NS_OK;
1222 nsresult BasePrincipal::GetContentScriptAddonPolicy(
1223 extensions::WebExtensionPolicy** aResult) {
1224 RefPtr<extensions::WebExtensionPolicy> policy(ContentScriptAddonPolicy());
1225 policy.forget(aResult);
1226 return NS_OK;
1229 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
1230 AssertIsOnMainThread();
1231 RefPtr<extensions::WebExtensionPolicyCore> core = AddonPolicyCore();
1232 return core ? core->GetMainThreadPolicy() : nullptr;
1235 RefPtr<extensions::WebExtensionPolicyCore> BasePrincipal::AddonPolicyCore() {
1236 if (Is<ContentPrincipal>()) {
1237 return As<ContentPrincipal>()->AddonPolicyCore();
1239 return nullptr;
1242 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
1243 if (auto policy = AddonPolicyCore()) {
1244 return policy->HasPermission(aPerm);
1246 return false;
1249 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
1250 if (Is<ExpandedPrincipal>()) {
1251 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
1253 return this;
1256 bool BasePrincipal::OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
1257 MOZ_ASSERT(aDocumentPrincipal);
1259 // Expanded principals override CSP if and only if they subsume the document
1260 // principal.
1261 if (mKind == eExpandedPrincipal) {
1262 return FastSubsumes(aDocumentPrincipal);
1264 // Extension principals always override the CSP of non-extension principals.
1265 // This is primarily for the sake of their stylesheets, which are usually
1266 // loaded from channels and cannot have expanded principals.
1267 return (AddonPolicyCore() &&
1268 !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicyCore());
1271 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1272 nsIURI* aURI, const OriginAttributes& aAttrs, nsIURI* aInitialDomain) {
1273 MOZ_ASSERT(aURI);
1275 nsAutoCString originNoSuffix;
1276 nsresult rv =
1277 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
1278 if (NS_FAILED(rv)) {
1279 // If the generation of the origin fails, we still want to have a valid
1280 // principal. Better to return a null principal here.
1281 return NullPrincipal::Create(aAttrs);
1284 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix, aInitialDomain);
1287 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1288 nsIURI* aURI, const OriginAttributes& aAttrs,
1289 const nsACString& aOriginNoSuffix, nsIURI* aInitialDomain) {
1290 MOZ_ASSERT(aURI);
1291 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
1293 // If the URI is supposed to inherit the security context of whoever loads it,
1294 // we shouldn't make a content principal for it.
1295 bool inheritsPrincipal;
1296 nsresult rv = NS_URIChainHasFlags(
1297 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
1298 &inheritsPrincipal);
1299 if (NS_FAILED(rv) || inheritsPrincipal) {
1300 return NullPrincipal::Create(aAttrs);
1303 // Check whether the URI knows what its principal is supposed to be.
1304 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
1305 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
1306 do_QueryInterface(aURI);
1307 if (uriWithSpecialOrigin) {
1308 nsCOMPtr<nsIURI> origin;
1309 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
1310 if (NS_WARN_IF(NS_FAILED(rv))) {
1311 return nullptr;
1313 MOZ_ASSERT(origin);
1314 OriginAttributes attrs;
1315 RefPtr<BasePrincipal> principal =
1316 CreateContentPrincipal(origin, attrs, aInitialDomain);
1317 return principal.forget();
1319 #endif
1321 nsCOMPtr<nsIPrincipal> blobPrincipal;
1322 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
1323 aURI, getter_AddRefs(blobPrincipal))) {
1324 MOZ_ASSERT(blobPrincipal);
1325 MOZ_ASSERT(!aInitialDomain,
1326 "an initial domain for a blob URI makes no sense");
1327 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
1328 return principal.forget();
1331 // Mint a content principal.
1332 RefPtr<ContentPrincipal> principal =
1333 new ContentPrincipal(aURI, aAttrs, aOriginNoSuffix, aInitialDomain);
1334 return principal.forget();
1337 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
1338 const nsACString& aOrigin) {
1339 MOZ_ASSERT(!StringBeginsWith(aOrigin, "["_ns),
1340 "CreateContentPrincipal does not support System and Expanded "
1341 "principals");
1343 MOZ_ASSERT(
1344 !StringBeginsWith(aOrigin, nsLiteralCString(NS_NULLPRINCIPAL_SCHEME ":")),
1345 "CreateContentPrincipal does not support NullPrincipal");
1347 nsAutoCString originNoSuffix;
1348 OriginAttributes attrs;
1349 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
1350 return nullptr;
1353 nsCOMPtr<nsIURI> uri;
1354 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
1355 NS_ENSURE_SUCCESS(rv, nullptr);
1357 return BasePrincipal::CreateContentPrincipal(uri, attrs);
1360 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
1361 const OriginAttributes& aOriginAttributes) {
1362 if (NS_WARN_IF(!IsContentPrincipal())) {
1363 return nullptr;
1366 nsAutoCString originNoSuffix;
1367 nsresult rv = GetOriginNoSuffix(originNoSuffix);
1368 NS_ENSURE_SUCCESS(rv, nullptr);
1370 nsCOMPtr<nsIURI> uri;
1371 MOZ_ALWAYS_SUCCEEDS(GetURI(getter_AddRefs(uri)));
1373 // XXX: This does not copy over the domain. Should it?
1374 RefPtr<ContentPrincipal> copy =
1375 new ContentPrincipal(uri, aOriginAttributes, originNoSuffix, nullptr);
1376 return copy.forget();
1379 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
1380 AssertIsOnMainThread();
1381 RefPtr<extensions::WebExtensionPolicyCore> core =
1382 ContentScriptAddonPolicyCore();
1383 return core ? core->GetMainThreadPolicy() : nullptr;
1386 RefPtr<extensions::WebExtensionPolicyCore>
1387 BasePrincipal::ContentScriptAddonPolicyCore() {
1388 if (!Is<ExpandedPrincipal>()) {
1389 return nullptr;
1392 auto* expanded = As<ExpandedPrincipal>();
1393 for (const auto& prin : expanded->AllowList()) {
1394 if (RefPtr<extensions::WebExtensionPolicyCore> policy =
1395 BasePrincipal::Cast(prin)->AddonPolicyCore()) {
1396 return policy;
1400 return nullptr;
1403 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
1404 bool aExplicit /* = false */) {
1405 if (Is<ExpandedPrincipal>()) {
1406 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
1408 if (auto policy = AddonPolicyCore()) {
1409 return policy->CanAccessURI(aURI, aExplicit);
1411 return false;
1414 NS_IMETHODIMP
1415 BasePrincipal::GetLocalStorageQuotaKey(nsACString& aKey) {
1416 aKey.Truncate();
1418 nsCOMPtr<nsIURI> uri;
1419 nsresult rv = GetURI(getter_AddRefs(uri));
1420 NS_ENSURE_SUCCESS(rv, rv);
1421 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1423 // The special handling of the file scheme should be consistent with
1424 // GetStorageOriginKey.
1426 nsAutoCString baseDomain;
1427 rv = uri->GetAsciiHost(baseDomain);
1428 NS_ENSURE_SUCCESS(rv, rv);
1430 if (baseDomain.IsEmpty() && uri->SchemeIs("file")) {
1431 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1432 NS_ENSURE_SUCCESS(rv, rv);
1434 rv = url->GetDirectory(baseDomain);
1435 NS_ENSURE_SUCCESS(rv, rv);
1436 } else {
1437 nsCOMPtr<nsIEffectiveTLDService> eTLDService(
1438 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv));
1439 NS_ENSURE_SUCCESS(rv, rv);
1441 nsAutoCString eTLDplusOne;
1442 rv = eTLDService->GetBaseDomain(uri, 0, eTLDplusOne);
1443 if (NS_SUCCEEDED(rv)) {
1444 baseDomain = eTLDplusOne;
1445 } else if (rv == NS_ERROR_HOST_IS_IP_ADDRESS ||
1446 rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
1447 rv = NS_OK;
1449 NS_ENSURE_SUCCESS(rv, rv);
1452 OriginAttributesRef().CreateSuffix(aKey);
1454 nsAutoCString subdomainsDBKey;
1455 rv = dom::StorageUtils::CreateReversedDomain(baseDomain, subdomainsDBKey);
1456 NS_ENSURE_SUCCESS(rv, rv);
1458 aKey.Append(':');
1459 aKey.Append(subdomainsDBKey);
1461 return NS_OK;
1464 NS_IMETHODIMP
1465 BasePrincipal::GetNextSubDomainPrincipal(
1466 nsIPrincipal** aNextSubDomainPrincipal) {
1467 nsCOMPtr<nsIURI> uri;
1468 nsresult rv = GetURI(getter_AddRefs(uri));
1469 if (NS_FAILED(rv) || !uri) {
1470 return NS_OK;
1473 nsAutoCString host;
1474 rv = uri->GetHost(host);
1475 if (NS_FAILED(rv) || host.IsEmpty()) {
1476 return NS_OK;
1479 nsCString subDomain;
1480 rv = nsEffectiveTLDService::GetInstance()->GetNextSubDomain(host, subDomain);
1482 if (NS_FAILED(rv) || subDomain.IsEmpty()) {
1483 return NS_OK;
1486 nsCOMPtr<nsIURI> subDomainURI;
1487 rv = NS_MutateURI(uri).SetHost(subDomain).Finalize(subDomainURI);
1488 if (NS_FAILED(rv) || !subDomainURI) {
1489 return NS_OK;
1491 // Copy the attributes over
1492 mozilla::OriginAttributes attrs = OriginAttributesRef();
1494 if (!StaticPrefs::permissions_isolateBy_userContext()) {
1495 // Disable userContext for permissions.
1496 attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID);
1498 RefPtr<nsIPrincipal> principal =
1499 mozilla::BasePrincipal::CreateContentPrincipal(subDomainURI, attrs);
1501 if (!principal) {
1502 return NS_OK;
1504 principal.forget(aNextSubDomainPrincipal);
1505 return NS_OK;
1508 NS_IMETHODIMP
1509 BasePrincipal::GetStorageOriginKey(nsACString& aOriginKey) {
1510 aOriginKey.Truncate();
1512 nsCOMPtr<nsIURI> uri;
1513 nsresult rv = GetURI(getter_AddRefs(uri));
1514 NS_ENSURE_SUCCESS(rv, rv);
1515 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
1517 // The special handling of the file scheme should be consistent with
1518 // GetLocalStorageQuotaKey.
1520 nsAutoCString domainOrigin;
1521 rv = uri->GetAsciiHost(domainOrigin);
1522 NS_ENSURE_SUCCESS(rv, rv);
1524 if (domainOrigin.IsEmpty()) {
1525 // For the file:/// protocol use the exact directory as domain.
1526 if (uri->SchemeIs("file")) {
1527 nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1528 NS_ENSURE_SUCCESS(rv, rv);
1529 rv = url->GetDirectory(domainOrigin);
1530 NS_ENSURE_SUCCESS(rv, rv);
1534 // Append reversed domain
1535 nsAutoCString reverseDomain;
1536 rv = dom::StorageUtils::CreateReversedDomain(domainOrigin, reverseDomain);
1537 NS_ENSURE_SUCCESS(rv, rv);
1539 aOriginKey.Append(reverseDomain);
1541 // Append scheme
1542 nsAutoCString scheme;
1543 rv = uri->GetScheme(scheme);
1544 NS_ENSURE_SUCCESS(rv, rv);
1546 aOriginKey.Append(':');
1547 aOriginKey.Append(scheme);
1549 // Append port if any
1550 int32_t port = NS_GetRealPort(uri);
1551 if (port != -1) {
1552 aOriginKey.Append(nsPrintfCString(":%d", port));
1555 return NS_OK;
1558 NS_IMETHODIMP
1559 BasePrincipal::GetIsScriptAllowedByPolicy(bool* aIsScriptAllowedByPolicy) {
1560 AssertIsOnMainThread();
1561 *aIsScriptAllowedByPolicy = false;
1562 nsCOMPtr<nsIURI> prinURI;
1563 nsresult rv = GetURI(getter_AddRefs(prinURI));
1564 if (NS_FAILED(rv) || !prinURI) {
1565 return NS_OK;
1567 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1568 if (!ssm) {
1569 return NS_ERROR_UNEXPECTED;
1571 return ssm->PolicyAllowsScript(prinURI, aIsScriptAllowedByPolicy);
1574 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
1575 MOZ_ASSERT(IsInitialized());
1576 MOZ_ASSERT(aOther.IsInitialized());
1577 return mPrincipal->FastEquals(aOther.mPrincipal);
1580 NS_IMETHODIMP
1581 BasePrincipal::CreateReferrerInfo(mozilla::dom::ReferrerPolicy aReferrerPolicy,
1582 nsIReferrerInfo** _retval) {
1583 nsCOMPtr<nsIURI> prinURI;
1584 RefPtr<dom::ReferrerInfo> info;
1585 nsresult rv = GetURI(getter_AddRefs(prinURI));
1586 if (NS_FAILED(rv) || !prinURI) {
1587 info = new dom::ReferrerInfo(nullptr);
1588 info.forget(_retval);
1589 return NS_OK;
1591 info = new dom::ReferrerInfo(prinURI, aReferrerPolicy);
1592 info.forget(_retval);
1593 return NS_OK;
1596 NS_IMETHODIMP
1597 BasePrincipal::GetPrecursorPrincipal(nsIPrincipal** aPrecursor) {
1598 *aPrecursor = nullptr;
1599 return NS_OK;
1602 NS_IMPL_ADDREF(BasePrincipal::Deserializer)
1603 NS_IMPL_RELEASE(BasePrincipal::Deserializer)
1605 NS_INTERFACE_MAP_BEGIN(BasePrincipal::Deserializer)
1606 NS_INTERFACE_MAP_ENTRY(nsISupports)
1607 NS_INTERFACE_MAP_ENTRY(nsISerializable)
1608 if (mPrincipal) {
1609 return mPrincipal->QueryInterface(aIID, aInstancePtr);
1610 } else
1611 NS_INTERFACE_MAP_END
1613 NS_IMETHODIMP
1614 BasePrincipal::Deserializer::Write(nsIObjectOutputStream* aStream) {
1615 // Read is used still for legacy principals
1616 MOZ_RELEASE_ASSERT(false, "Old style serialization is removed");
1617 return NS_OK;
1620 /* static */
1621 void BasePrincipal::SetJSONValue(Json::Value& aObject, const char* aKey,
1622 const nsCString& aValue) {
1623 aObject[Json::StaticString(aKey)] =
1624 Json::Value(aValue.BeginReading(), aValue.EndReading());
1627 } // namespace mozilla