Bug 1610860 [wpt PR 21344] - Update wpt metadata, a=testonly
[gecko.git] / caps / BasePrincipal.cpp
blob994dc0910b79fad5e600d0ad00e064043a21611b
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 "nsIURIWithSpecialOrigin.h"
15 #include "nsScriptSecurityManager.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsAboutProtocolUtils.h"
18 #include "ThirdPartyUtil.h"
19 #include "mozilla/ContentPrincipal.h"
20 #include "mozilla/NullPrincipal.h"
21 #include "mozilla/dom/BlobURLProtocolHandler.h"
22 #include "mozilla/dom/ChromeUtils.h"
23 #include "mozilla/dom/ToJSValue.h"
24 #include "mozilla/dom/nsMixedContentBlocker.h"
25 #include "mozilla/Components.h"
26 #include "nsIURIFixup.h"
28 #include "json/json.h"
29 #include "nsSerializationHelper.h"
31 namespace mozilla {
33 BasePrincipal::BasePrincipal(PrincipalKind aKind)
34 : mKind(aKind), mHasExplicitDomain(false), mInitialized(false) {}
36 BasePrincipal::~BasePrincipal() {}
38 NS_IMETHODIMP
39 BasePrincipal::GetOrigin(nsACString& aOrigin) {
40 MOZ_ASSERT(mInitialized);
42 nsresult rv = GetOriginNoSuffix(aOrigin);
43 NS_ENSURE_SUCCESS(rv, rv);
45 nsAutoCString suffix;
46 rv = GetOriginSuffix(suffix);
47 NS_ENSURE_SUCCESS(rv, rv);
48 aOrigin.Append(suffix);
49 return NS_OK;
52 NS_IMETHODIMP
53 BasePrincipal::GetAsciiOrigin(nsACString& aOrigin) {
54 aOrigin.Truncate();
55 nsCOMPtr<nsIURI> prinURI;
56 nsresult rv = GetURI(getter_AddRefs(prinURI));
57 if (NS_FAILED(rv) || !prinURI) {
58 return NS_ERROR_NOT_AVAILABLE;
60 return nsContentUtils::GetASCIIOrigin(prinURI, aOrigin);
63 NS_IMETHODIMP
64 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
65 MOZ_ASSERT(mInitialized);
66 mOriginNoSuffix->ToUTF8String(aOrigin);
67 return NS_OK;
70 NS_IMETHODIMP
71 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
72 MOZ_ASSERT(mInitialized);
73 return GetOrigin(aSiteOrigin);
76 // Returns the inner Json::value of the serialized principal
77 // Example input and return values:
78 // Null principal:
79 // {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
80 // {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
82 // Content principal:
83 // {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
85 // Expanded principal:
86 // {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
87 // {"0":"<base64principal1>,<base64principal2>"}
89 // System principal:
90 // {"3":{}} -> {}
91 // The aKey passed in also returns the corresponding PrincipalKind enum
93 // Warning: The Json::Value* pointer is into the aRoot object
94 static const Json::Value* GetPrincipalObject(const Json::Value& aRoot,
95 int& aOutPrincipalKind) {
96 const Json::Value::Members members = aRoot.getMemberNames();
97 // We only support one top level key in the object
98 if (members.size() != 1) {
99 return nullptr;
101 // members[0] here is the "0", "1", "2", "3" principalKind
102 // that is the top level of the serialized JSON principal
103 const std::string stringPrincipalKind = members[0];
105 // Next we take the string value from the JSON
106 // and convert it into the int for the BasePrincipal::PrincipalKind enum
108 // Verify that the key is within the valid range
109 int principalKind = std::stoi(stringPrincipalKind);
110 MOZ_ASSERT(BasePrincipal::eNullPrincipal == 0,
111 "We need to rely on 0 being a bounds check for the first "
112 "principal kind.");
113 if (principalKind < 0 || principalKind > BasePrincipal::eKindMax) {
114 return nullptr;
116 MOZ_ASSERT(principalKind == BasePrincipal::eNullPrincipal ||
117 principalKind == BasePrincipal::eContentPrincipal ||
118 principalKind == BasePrincipal::eExpandedPrincipal ||
119 principalKind == BasePrincipal::eSystemPrincipal);
120 aOutPrincipalKind = principalKind;
122 if (!aRoot[stringPrincipalKind].isObject()) {
123 return nullptr;
126 // Return the inner value of the principal object
127 return &aRoot[stringPrincipalKind];
130 // Accepts the JSON inner object without the wrapping principalKind
131 // (See GetPrincipalObject for the inner object response examples)
132 // Creates an array of KeyVal objects that are all defined on the principal
133 // Each principal type (null, content, expanded) has a KeyVal that stores the
134 // fields of the JSON
136 // This simplifies deserializing elsewhere as we do the checking for presence
137 // and string values here for the complete set of serializable keys that the
138 // corresponding principal supports.
140 // The KeyVal object has the following fields:
141 // - valueWasSerialized: is true if the deserialized JSON contained a string
142 // value
143 // - value: The string that was serialized for this key
144 // - key: an SerializableKeys enum value specific to the principal.
145 // For example content principal is an enum of: eURI, eDomain,
146 // eSuffix, eCSP
149 // Given an inner content principal:
150 // {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
151 // | | | |
152 // ----------------------------- |
153 // | | |
154 // Key ----------------------
155 // |
156 // Value
158 // They Key "0" corresponds to ContentPrincipal::eURI
159 // They Key "1" corresponds to ContentPrincipal::eSuffix
160 template <typename T>
161 static nsTArray<typename T::KeyVal> GetJSONKeys(const Json::Value* aInput) {
162 int size = T::eMax + 1;
163 nsTArray<typename T::KeyVal> fields;
164 for (int i = 0; i != size; i++) {
165 typename T::KeyVal* field = fields.AppendElement();
166 // field->valueWasSerialized returns if the field was found in the
167 // deserialized code. This simplifies the consumers from having to check
168 // length.
169 field->valueWasSerialized = false;
170 field->key = static_cast<typename T::SerializableKeys>(i);
171 const std::string key = std::to_string(field->key);
172 if (aInput->isMember(key)) {
173 const Json::Value& val = (*aInput)[key];
174 if (val.isString()) {
175 field->value.Append(nsDependentCString(val.asCString()));
176 field->valueWasSerialized = true;
180 return fields;
183 // Takes a JSON string and parses it turning it into a principal of the
184 // corresponding type
186 // Given a content principal:
188 // inner JSON object
189 // |
190 // ---------------------------------------------------------
191 // | |
192 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
193 // | | | | |
194 // | ----------------------------- |
195 // | | | |
196 // PrincipalKind | | |
197 // | ----------------------------
198 // SerializableKeys |
199 // Value
201 // The string is first deserialized with jsoncpp to get the Json::Value of the
202 // object. The inner JSON object is parsed with GetPrincipalObject which returns
203 // a KeyVal array of the inner object's fields. PrincipalKind is returned by
204 // GetPrincipalObject which is then used to decide which principal
205 // implementation of FromProperties to call. The corresponding FromProperties
206 // call takes the KeyVal fields and turns it into a principal.
207 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
208 const nsACString& aJSON) {
209 Json::Value root;
210 Json::CharReaderBuilder builder;
211 std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
212 bool parseSuccess =
213 reader->parse(aJSON.BeginReading(), aJSON.EndReading(), &root, nullptr);
214 if (!parseSuccess) {
215 MOZ_ASSERT(false,
216 "Unable to parse string as JSON to deserialize as a principal");
217 return nullptr;
220 int principalKind = -1;
221 const Json::Value* value = GetPrincipalObject(root, principalKind);
222 if (!value) {
223 #ifdef DEBUG
224 fprintf(stderr, "Unexpected JSON principal %s\n",
225 root.toStyledString().c_str());
226 #endif
227 MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
229 return nullptr;
231 MOZ_ASSERT(principalKind != -1,
232 "PrincipalKind should always be >=0 by this point");
234 if (principalKind == eSystemPrincipal) {
235 RefPtr<BasePrincipal> principal =
236 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
237 return principal.forget();
240 if (principalKind == eNullPrincipal) {
241 nsTArray<NullPrincipal::KeyVal> res = GetJSONKeys<NullPrincipal>(value);
242 return NullPrincipal::FromProperties(res);
245 if (principalKind == eContentPrincipal) {
246 nsTArray<ContentPrincipal::KeyVal> res =
247 GetJSONKeys<ContentPrincipal>(value);
248 return ContentPrincipal::FromProperties(res);
251 if (principalKind == eExpandedPrincipal) {
252 nsTArray<ExpandedPrincipal::KeyVal> res =
253 GetJSONKeys<ExpandedPrincipal>(value);
254 return ExpandedPrincipal::FromProperties(res);
257 MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
260 nsresult BasePrincipal::PopulateJSONObject(Json::Value& aObject) {
261 return NS_OK;
264 // Returns a JSON representation of the principal.
265 // Calling BasePrincipal::FromJSON will deserialize the JSON into
266 // the corresponding principal type.
267 nsresult BasePrincipal::ToJSON(nsACString& aResult) {
268 MOZ_ASSERT(aResult.IsEmpty(), "ToJSON only supports an empty result input");
269 aResult.Truncate();
271 Json::StreamWriterBuilder builder;
272 builder["indentation"] = "";
273 Json::Value innerJSONObject = Json::objectValue;
275 nsresult rv = PopulateJSONObject(innerJSONObject);
276 NS_ENSURE_SUCCESS(rv, rv);
278 Json::Value root = Json::objectValue;
279 std::string key = std::to_string(Kind());
280 root[key] = innerJSONObject;
281 std::string result = Json::writeString(builder, root);
282 aResult.Append(result);
283 if (aResult.Length() == 0) {
284 MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
285 return NS_ERROR_UNEXPECTED;
287 return NS_OK;
290 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
291 DocumentDomainConsideration aConsideration) {
292 MOZ_ASSERT(aOther);
293 MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
295 // Expanded principals handle origin attributes for each of their
296 // sub-principals individually, null principals do only simple checks for
297 // pointer equality, and system principals are immune to origin attributes
298 // checks, so only do this check for content principals.
299 if (Kind() == eContentPrincipal &&
300 mOriginSuffix != Cast(aOther)->mOriginSuffix) {
301 return false;
304 return SubsumesInternal(aOther, aConsideration);
307 NS_IMETHODIMP
308 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
309 NS_ENSURE_ARG_POINTER(aOther);
311 *aResult = FastEquals(aOther);
313 return NS_OK;
316 NS_IMETHODIMP
317 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
318 NS_ENSURE_ARG_POINTER(aOther);
320 *aResult = FastEqualsConsideringDomain(aOther);
322 return NS_OK;
325 NS_IMETHODIMP
326 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
327 *aResult = false;
328 nsCOMPtr<nsIURI> prinURI;
329 nsresult rv = GetURI(getter_AddRefs(prinURI));
330 if (NS_FAILED(rv) || !prinURI) {
331 return NS_OK;
333 return prinURI->EqualsExceptRef(aOtherURI, aResult);
336 NS_IMETHODIMP
337 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
338 NS_ENSURE_ARG_POINTER(aOther);
340 *aResult = FastSubsumes(aOther);
342 return NS_OK;
345 NS_IMETHODIMP
346 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
347 NS_ENSURE_ARG_POINTER(aOther);
349 *aResult = FastSubsumesConsideringDomain(aOther);
351 return NS_OK;
354 NS_IMETHODIMP
355 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
356 bool* aResult) {
357 NS_ENSURE_ARG_POINTER(aOther);
359 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
361 return NS_OK;
364 NS_IMETHODIMP
365 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
366 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
369 NS_IMETHODIMP
370 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
371 bool aAllowIfInheritsPrincipal,
372 uint64_t aInnerWindowID) {
373 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
374 aInnerWindowID);
377 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
378 bool aAllowIfInheritsPrincipal,
379 bool aReport,
380 uint64_t aInnerWindowID) {
381 NS_ENSURE_ARG_POINTER(aURI);
382 MOZ_ASSERT(
383 aReport || aInnerWindowID == 0,
384 "Why do we have an inner window id if we're not supposed to report?");
386 // Check the internal method first, which allows us to quickly approve loads
387 // for the System Principal.
388 if (MayLoadInternal(aURI)) {
389 return NS_OK;
392 nsresult rv;
393 if (aAllowIfInheritsPrincipal) {
394 // If the caller specified to allow loads of URIs that inherit
395 // our principal, allow the load if this URI inherits its principal.
396 bool doesInheritSecurityContext;
397 rv = NS_URIChainHasFlags(aURI,
398 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
399 &doesInheritSecurityContext);
400 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
401 return NS_OK;
405 bool fetchableByAnyone;
406 rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
407 &fetchableByAnyone);
408 if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
409 return NS_OK;
412 if (aReport) {
413 nsCOMPtr<nsIURI> prinURI;
414 rv = GetURI(getter_AddRefs(prinURI));
415 if (NS_SUCCEEDED(rv) && prinURI) {
416 nsScriptSecurityManager::ReportError(
417 "CheckSameOriginError", prinURI, aURI,
418 mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
422 return NS_ERROR_DOM_BAD_URI;
425 NS_IMETHODIMP
426 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
427 *aRes = true;
428 // If we do not have a URI its always 3rd party.
429 nsCOMPtr<nsIURI> prinURI;
430 nsresult rv = GetURI(getter_AddRefs(prinURI));
431 if (NS_FAILED(rv) || !prinURI) {
432 return NS_OK;
434 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
435 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
438 NS_IMETHODIMP
439 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
440 *aRes = true;
441 nsCOMPtr<nsIURI> prinURI;
442 nsresult rv = GetURI(getter_AddRefs(prinURI));
443 if (NS_FAILED(rv) || !prinURI) {
444 return NS_OK;
446 return aPrin->IsThirdPartyURI(prinURI, aRes);
449 NS_IMETHODIMP
450 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool aIsPrivateWin, bool* aRes) {
451 *aRes = false;
452 nsCOMPtr<nsIURI> prinURI;
453 nsresult rv = GetURI(getter_AddRefs(prinURI));
454 if (NS_FAILED(rv) || !prinURI) {
455 return NS_OK;
457 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
458 if (!ssm) {
459 return NS_ERROR_UNEXPECTED;
462 *aRes = NS_SUCCEEDED(
463 ssm->CheckSameOriginURI(prinURI, aURI, false, aIsPrivateWin));
464 return NS_OK;
467 NS_IMETHODIMP
468 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
469 *aResult = Kind() == eNullPrincipal;
470 return NS_OK;
473 NS_IMETHODIMP
474 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
475 *aResult = Kind() == eContentPrincipal;
476 return NS_OK;
479 NS_IMETHODIMP
480 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
481 *aResult = Kind() == eExpandedPrincipal;
482 return NS_OK;
485 NS_IMETHODIMP
486 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
487 aSpec.Truncate();
488 nsCOMPtr<nsIURI> prinURI;
489 nsresult rv = GetURI(getter_AddRefs(prinURI));
490 if (NS_FAILED(rv) || !prinURI) {
491 return NS_OK;
493 return prinURI->GetAsciiSpec(aSpec);
496 NS_IMETHODIMP
497 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
498 aPrepath.Truncate();
499 nsCOMPtr<nsIURI> prinURI;
500 nsresult rv = GetURI(getter_AddRefs(prinURI));
501 if (NS_FAILED(rv) || !prinURI) {
502 return NS_OK;
505 nsCOMPtr<nsIURIFixup> fixup(components::URIFixup::Service());
506 nsCOMPtr<nsIURIFixup> urifixup = services::GetURIFixup();
507 if (NS_WARN_IF(!urifixup)) {
508 return NS_OK;
511 nsCOMPtr<nsIURI> fixedURI;
512 rv = fixup->CreateExposableURI(prinURI, getter_AddRefs(fixedURI));
514 if (NS_FAILED(rv) || NS_WARN_IF(!fixedURI)) {
515 return NS_OK;
517 return fixedURI->GetDisplayPrePath(aPrepath);
520 NS_IMETHODIMP
521 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
522 *aResult = IsSystemPrincipal();
523 return NS_OK;
526 NS_IMETHODIMP
527 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
528 *aResult = AddonPolicy() || ContentScriptAddonPolicy();
529 return NS_OK;
532 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
533 *aIsOnion = false;
534 nsCOMPtr<nsIURI> prinURI;
535 nsresult rv = GetURI(getter_AddRefs(prinURI));
536 if (NS_FAILED(rv) || !prinURI) {
537 return NS_OK;
540 nsAutoCString host;
541 rv = prinURI->GetHost(host);
542 if (NS_FAILED(rv)) {
543 return NS_OK;
545 *aIsOnion = StringEndsWith(host, NS_LITERAL_CSTRING(".onion"));
546 return NS_OK;
549 NS_IMETHODIMP
550 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
551 *aResult = false;
552 nsCOMPtr<nsIURI> prinURI;
553 nsresult rv = GetURI(getter_AddRefs(prinURI));
554 if (NS_FAILED(rv) || !prinURI) {
555 return NS_OK;
557 *aResult = prinURI->SchemeIs(aScheme);
558 return NS_OK;
561 NS_IMETHODIMP
562 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
563 *aResult = false;
564 nsCOMPtr<nsIURI> prinURI;
565 nsresult rv = GetURI(getter_AddRefs(prinURI));
566 if (NS_FAILED(rv) || !prinURI) {
567 return NS_OK;
569 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
570 return NS_OK;
573 NS_IMETHODIMP
574 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
575 MOZ_ASSERT(NS_IsMainThread());
576 *aResult = false;
578 nsCOMPtr<nsIURI> uri;
579 nsresult rv = GetURI(getter_AddRefs(uri));
580 if (NS_FAILED(rv) || !uri) {
581 return NS_OK;
584 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
585 return NS_OK;
588 NS_IMETHODIMP
589 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
590 *flags = 0;
591 nsCOMPtr<nsIURI> prinURI;
592 nsresult rv = GetURI(getter_AddRefs(prinURI));
593 if (NS_FAILED(rv) || !prinURI) {
594 return NS_ERROR_NOT_AVAILABLE;
596 if (!prinURI->SchemeIs("about")) {
597 return NS_OK;
600 nsCOMPtr<nsIAboutModule> aboutModule;
601 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
602 if (NS_FAILED(rv) || !aboutModule) {
603 return rv;
605 return aboutModule->GetURIFlags(prinURI, flags);
608 NS_IMETHODIMP
609 BasePrincipal::GetOriginAttributes(JSContext* aCx,
610 JS::MutableHandle<JS::Value> aVal) {
611 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
612 return NS_ERROR_FAILURE;
614 return NS_OK;
617 NS_IMETHODIMP
618 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
619 MOZ_ASSERT(mOriginSuffix);
620 mOriginSuffix->ToUTF8String(aOriginAttributes);
621 return NS_OK;
624 NS_IMETHODIMP
625 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
626 *aUserContextId = UserContextId();
627 return NS_OK;
630 NS_IMETHODIMP
631 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
632 *aPrivateBrowsingId = PrivateBrowsingId();
633 return NS_OK;
636 NS_IMETHODIMP
637 BasePrincipal::GetIsInIsolatedMozBrowserElement(
638 bool* aIsInIsolatedMozBrowserElement) {
639 *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
640 return NS_OK;
643 nsresult BasePrincipal::GetAddonPolicy(nsISupports** aResult) {
644 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
645 policy.forget(aResult);
646 return NS_OK;
649 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
650 if (Is<ContentPrincipal>()) {
651 return As<ContentPrincipal>()->AddonPolicy();
653 return nullptr;
656 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
657 if (auto policy = AddonPolicy()) {
658 return policy->HasPermission(aPerm);
660 return false;
663 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
664 if (Is<ExpandedPrincipal>()) {
665 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
667 return this;
670 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
671 nsIURI* aURI, const OriginAttributes& aAttrs) {
672 MOZ_ASSERT(aURI);
674 nsAutoCString originNoSuffix;
675 nsresult rv =
676 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
677 if (NS_FAILED(rv)) {
678 // If the generation of the origin fails, we still want to have a valid
679 // principal. Better to return a null principal here.
680 return NullPrincipal::Create(aAttrs);
683 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix);
686 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
687 nsIURI* aURI, const OriginAttributes& aAttrs,
688 const nsACString& aOriginNoSuffix) {
689 MOZ_ASSERT(aURI);
690 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
692 // If the URI is supposed to inherit the security context of whoever loads it,
693 // we shouldn't make a content principal for it.
694 bool inheritsPrincipal;
695 nsresult rv = NS_URIChainHasFlags(
696 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
697 &inheritsPrincipal);
698 if (NS_FAILED(rv) || inheritsPrincipal) {
699 return NullPrincipal::Create(aAttrs);
702 // Check whether the URI knows what its principal is supposed to be.
703 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
704 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
705 do_QueryInterface(aURI);
706 if (uriWithSpecialOrigin) {
707 nsCOMPtr<nsIURI> origin;
708 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
709 if (NS_WARN_IF(NS_FAILED(rv))) {
710 return nullptr;
712 MOZ_ASSERT(origin);
713 OriginAttributes attrs;
714 RefPtr<BasePrincipal> principal = CreateContentPrincipal(origin, attrs);
715 return principal.forget();
717 #endif
719 nsCOMPtr<nsIPrincipal> blobPrincipal;
720 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
721 aURI, getter_AddRefs(blobPrincipal))) {
722 MOZ_ASSERT(blobPrincipal);
723 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
724 return principal.forget();
727 // Mint a content principal.
728 RefPtr<ContentPrincipal> principal = new ContentPrincipal();
729 rv = principal->Init(aURI, aAttrs, aOriginNoSuffix);
730 NS_ENSURE_SUCCESS(rv, nullptr);
731 return principal.forget();
734 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
735 const nsACString& aOrigin) {
736 MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
737 "CreateContentPrincipal does not support System and Expanded "
738 "principals");
740 MOZ_ASSERT(!StringBeginsWith(aOrigin,
741 NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
742 "CreateContentPrincipal does not support NullPrincipal");
744 nsAutoCString originNoSuffix;
745 OriginAttributes attrs;
746 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
747 return nullptr;
750 nsCOMPtr<nsIURI> uri;
751 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
752 NS_ENSURE_SUCCESS(rv, nullptr);
754 return BasePrincipal::CreateContentPrincipal(uri, attrs);
757 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
758 const OriginAttributes& aOriginAttributes) {
759 if (NS_WARN_IF(!IsContentPrincipal())) {
760 return nullptr;
763 nsAutoCString originNoSuffix;
764 nsresult rv = GetOriginNoSuffix(originNoSuffix);
765 NS_ENSURE_SUCCESS(rv, nullptr);
767 nsIURI* uri = static_cast<ContentPrincipal*>(this)->mURI;
768 RefPtr<ContentPrincipal> copy = new ContentPrincipal();
769 rv = copy->Init(uri, aOriginAttributes, originNoSuffix);
770 NS_ENSURE_SUCCESS(rv, nullptr);
772 return copy.forget();
775 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
776 if (!Is<ExpandedPrincipal>()) {
777 return nullptr;
780 auto expanded = As<ExpandedPrincipal>();
781 for (auto& prin : expanded->AllowList()) {
782 if (auto policy = BasePrincipal::Cast(prin)->AddonPolicy()) {
783 return policy;
787 return nullptr;
790 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
791 bool aExplicit /* = false */) {
792 if (Is<ExpandedPrincipal>()) {
793 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
795 if (auto policy = AddonPolicy()) {
796 return policy->CanAccessURI(aURI, aExplicit);
798 return false;
801 void BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
802 const OriginAttributes& aOriginAttributes) {
803 mInitialized = true;
804 mOriginAttributes = aOriginAttributes;
806 // First compute the origin suffix since it's infallible.
807 nsAutoCString originSuffix;
808 mOriginAttributes.CreateSuffix(originSuffix);
809 mOriginSuffix = NS_Atomize(originSuffix);
811 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
812 mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
815 void BasePrincipal::FinishInit(BasePrincipal* aOther,
816 const OriginAttributes& aOriginAttributes) {
817 mInitialized = true;
818 mOriginAttributes = aOriginAttributes;
820 // First compute the origin suffix since it's infallible.
821 nsAutoCString originSuffix;
822 mOriginAttributes.CreateSuffix(originSuffix);
823 mOriginSuffix = NS_Atomize(originSuffix);
825 mOriginNoSuffix = aOther->mOriginNoSuffix;
826 mHasExplicitDomain = aOther->mHasExplicitDomain;
829 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
830 MOZ_ASSERT(IsInitialized());
831 MOZ_ASSERT(aOther.IsInitialized());
832 return mPrincipal->FastEquals(aOther.mPrincipal);
835 } // namespace mozilla