Bug 1613876 [wpt PR 21654] - Reland "Move SMIL events tests to WPT", a=testonly
[gecko.git] / caps / BasePrincipal.cpp
blob39f3a48663d71e4bbfa8d6be446d1e70fdb9f159
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::GetHostPort(nsACString& aRes) {
65 aRes.Truncate();
66 nsCOMPtr<nsIURI> prinURI;
67 nsresult rv = GetURI(getter_AddRefs(prinURI));
68 if (NS_FAILED(rv) || !prinURI) {
69 return NS_OK;
71 return prinURI->GetHostPort(aRes);
74 NS_IMETHODIMP
75 BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) {
76 MOZ_ASSERT(mInitialized);
77 mOriginNoSuffix->ToUTF8String(aOrigin);
78 return NS_OK;
81 NS_IMETHODIMP
82 BasePrincipal::GetSiteOrigin(nsACString& aSiteOrigin) {
83 MOZ_ASSERT(mInitialized);
84 return GetOrigin(aSiteOrigin);
87 // Returns the inner Json::value of the serialized principal
88 // Example input and return values:
89 // Null principal:
90 // {"0":{"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}} ->
91 // {"0":"moz-nullprincipal:{56cac540-864d-47e7-8e25-1614eab5155e}"}
93 // Content principal:
94 // {"1":{"0":"https://mozilla.com"}} -> {"0":"https://mozilla.com"}
96 // Expanded principal:
97 // {"2":{"0":"<base64principal1>,<base64principal2>"}} ->
98 // {"0":"<base64principal1>,<base64principal2>"}
100 // System principal:
101 // {"3":{}} -> {}
102 // The aKey passed in also returns the corresponding PrincipalKind enum
104 // Warning: The Json::Value* pointer is into the aRoot object
105 static const Json::Value* GetPrincipalObject(const Json::Value& aRoot,
106 int& aOutPrincipalKind) {
107 const Json::Value::Members members = aRoot.getMemberNames();
108 // We only support one top level key in the object
109 if (members.size() != 1) {
110 return nullptr;
112 // members[0] here is the "0", "1", "2", "3" principalKind
113 // that is the top level of the serialized JSON principal
114 const std::string stringPrincipalKind = members[0];
116 // Next we take the string value from the JSON
117 // and convert it into the int for the BasePrincipal::PrincipalKind enum
119 // Verify that the key is within the valid range
120 int principalKind = std::stoi(stringPrincipalKind);
121 MOZ_ASSERT(BasePrincipal::eNullPrincipal == 0,
122 "We need to rely on 0 being a bounds check for the first "
123 "principal kind.");
124 if (principalKind < 0 || principalKind > BasePrincipal::eKindMax) {
125 return nullptr;
127 MOZ_ASSERT(principalKind == BasePrincipal::eNullPrincipal ||
128 principalKind == BasePrincipal::eContentPrincipal ||
129 principalKind == BasePrincipal::eExpandedPrincipal ||
130 principalKind == BasePrincipal::eSystemPrincipal);
131 aOutPrincipalKind = principalKind;
133 if (!aRoot[stringPrincipalKind].isObject()) {
134 return nullptr;
137 // Return the inner value of the principal object
138 return &aRoot[stringPrincipalKind];
141 // Accepts the JSON inner object without the wrapping principalKind
142 // (See GetPrincipalObject for the inner object response examples)
143 // Creates an array of KeyVal objects that are all defined on the principal
144 // Each principal type (null, content, expanded) has a KeyVal that stores the
145 // fields of the JSON
147 // This simplifies deserializing elsewhere as we do the checking for presence
148 // and string values here for the complete set of serializable keys that the
149 // corresponding principal supports.
151 // The KeyVal object has the following fields:
152 // - valueWasSerialized: is true if the deserialized JSON contained a string
153 // value
154 // - value: The string that was serialized for this key
155 // - key: an SerializableKeys enum value specific to the principal.
156 // For example content principal is an enum of: eURI, eDomain,
157 // eSuffix, eCSP
160 // Given an inner content principal:
161 // {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}
162 // | | | |
163 // ----------------------------- |
164 // | | |
165 // Key ----------------------
166 // |
167 // Value
169 // They Key "0" corresponds to ContentPrincipal::eURI
170 // They Key "1" corresponds to ContentPrincipal::eSuffix
171 template <typename T>
172 static nsTArray<typename T::KeyVal> GetJSONKeys(const Json::Value* aInput) {
173 int size = T::eMax + 1;
174 nsTArray<typename T::KeyVal> fields;
175 for (int i = 0; i != size; i++) {
176 typename T::KeyVal* field = fields.AppendElement();
177 // field->valueWasSerialized returns if the field was found in the
178 // deserialized code. This simplifies the consumers from having to check
179 // length.
180 field->valueWasSerialized = false;
181 field->key = static_cast<typename T::SerializableKeys>(i);
182 const std::string key = std::to_string(field->key);
183 if (aInput->isMember(key)) {
184 const Json::Value& val = (*aInput)[key];
185 if (val.isString()) {
186 field->value.Append(nsDependentCString(val.asCString()));
187 field->valueWasSerialized = true;
191 return fields;
194 // Takes a JSON string and parses it turning it into a principal of the
195 // corresponding type
197 // Given a content principal:
199 // inner JSON object
200 // |
201 // ---------------------------------------------------------
202 // | |
203 // {"1": {"0": "https://mozilla.com", "2": "^privateBrowsingId=1"}}
204 // | | | | |
205 // | ----------------------------- |
206 // | | | |
207 // PrincipalKind | | |
208 // | ----------------------------
209 // SerializableKeys |
210 // Value
212 // The string is first deserialized with jsoncpp to get the Json::Value of the
213 // object. The inner JSON object is parsed with GetPrincipalObject which returns
214 // a KeyVal array of the inner object's fields. PrincipalKind is returned by
215 // GetPrincipalObject which is then used to decide which principal
216 // implementation of FromProperties to call. The corresponding FromProperties
217 // call takes the KeyVal fields and turns it into a principal.
218 already_AddRefed<BasePrincipal> BasePrincipal::FromJSON(
219 const nsACString& aJSON) {
220 Json::Value root;
221 Json::CharReaderBuilder builder;
222 std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
223 bool parseSuccess =
224 reader->parse(aJSON.BeginReading(), aJSON.EndReading(), &root, nullptr);
225 if (!parseSuccess) {
226 MOZ_ASSERT(false,
227 "Unable to parse string as JSON to deserialize as a principal");
228 return nullptr;
231 int principalKind = -1;
232 const Json::Value* value = GetPrincipalObject(root, principalKind);
233 if (!value) {
234 #ifdef DEBUG
235 fprintf(stderr, "Unexpected JSON principal %s\n",
236 root.toStyledString().c_str());
237 #endif
238 MOZ_ASSERT(false, "Unexpected JSON to deserialize as a principal");
240 return nullptr;
242 MOZ_ASSERT(principalKind != -1,
243 "PrincipalKind should always be >=0 by this point");
245 if (principalKind == eSystemPrincipal) {
246 RefPtr<BasePrincipal> principal =
247 BasePrincipal::Cast(nsContentUtils::GetSystemPrincipal());
248 return principal.forget();
251 if (principalKind == eNullPrincipal) {
252 nsTArray<NullPrincipal::KeyVal> res = GetJSONKeys<NullPrincipal>(value);
253 return NullPrincipal::FromProperties(res);
256 if (principalKind == eContentPrincipal) {
257 nsTArray<ContentPrincipal::KeyVal> res =
258 GetJSONKeys<ContentPrincipal>(value);
259 return ContentPrincipal::FromProperties(res);
262 if (principalKind == eExpandedPrincipal) {
263 nsTArray<ExpandedPrincipal::KeyVal> res =
264 GetJSONKeys<ExpandedPrincipal>(value);
265 return ExpandedPrincipal::FromProperties(res);
268 MOZ_RELEASE_ASSERT(false, "Unexpected enum to deserialize as a principal");
271 nsresult BasePrincipal::PopulateJSONObject(Json::Value& aObject) {
272 return NS_OK;
275 // Returns a JSON representation of the principal.
276 // Calling BasePrincipal::FromJSON will deserialize the JSON into
277 // the corresponding principal type.
278 nsresult BasePrincipal::ToJSON(nsACString& aResult) {
279 MOZ_ASSERT(aResult.IsEmpty(), "ToJSON only supports an empty result input");
280 aResult.Truncate();
282 Json::StreamWriterBuilder builder;
283 builder["indentation"] = "";
284 Json::Value innerJSONObject = Json::objectValue;
286 nsresult rv = PopulateJSONObject(innerJSONObject);
287 NS_ENSURE_SUCCESS(rv, rv);
289 Json::Value root = Json::objectValue;
290 std::string key = std::to_string(Kind());
291 root[key] = innerJSONObject;
292 std::string result = Json::writeString(builder, root);
293 aResult.Append(result);
294 if (aResult.Length() == 0) {
295 MOZ_ASSERT(false, "JSON writer failed to output a principal serialization");
296 return NS_ERROR_UNEXPECTED;
298 return NS_OK;
301 bool BasePrincipal::Subsumes(nsIPrincipal* aOther,
302 DocumentDomainConsideration aConsideration) {
303 MOZ_ASSERT(aOther);
304 MOZ_ASSERT_IF(Kind() == eContentPrincipal, mOriginSuffix);
306 // Expanded principals handle origin attributes for each of their
307 // sub-principals individually, null principals do only simple checks for
308 // pointer equality, and system principals are immune to origin attributes
309 // checks, so only do this check for content principals.
310 if (Kind() == eContentPrincipal &&
311 mOriginSuffix != Cast(aOther)->mOriginSuffix) {
312 return false;
315 return SubsumesInternal(aOther, aConsideration);
318 NS_IMETHODIMP
319 BasePrincipal::Equals(nsIPrincipal* aOther, bool* aResult) {
320 NS_ENSURE_ARG_POINTER(aOther);
322 *aResult = FastEquals(aOther);
324 return NS_OK;
327 NS_IMETHODIMP
328 BasePrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
329 NS_ENSURE_ARG_POINTER(aOther);
331 *aResult = FastEqualsConsideringDomain(aOther);
333 return NS_OK;
336 NS_IMETHODIMP
337 BasePrincipal::EqualsURI(nsIURI* aOtherURI, bool* aResult) {
338 *aResult = false;
339 nsCOMPtr<nsIURI> prinURI;
340 nsresult rv = GetURI(getter_AddRefs(prinURI));
341 if (NS_FAILED(rv) || !prinURI) {
342 return NS_OK;
344 return prinURI->EqualsExceptRef(aOtherURI, aResult);
347 NS_IMETHODIMP
348 BasePrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) {
349 NS_ENSURE_ARG_POINTER(aOther);
351 *aResult = FastSubsumes(aOther);
353 return NS_OK;
356 NS_IMETHODIMP
357 BasePrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) {
358 NS_ENSURE_ARG_POINTER(aOther);
360 *aResult = FastSubsumesConsideringDomain(aOther);
362 return NS_OK;
365 NS_IMETHODIMP
366 BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther,
367 bool* aResult) {
368 NS_ENSURE_ARG_POINTER(aOther);
370 *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
372 return NS_OK;
375 NS_IMETHODIMP
376 BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aAllowIfInheritsPrincipal) {
377 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, false, 0);
380 NS_IMETHODIMP
381 BasePrincipal::CheckMayLoadWithReporting(nsIURI* aURI,
382 bool aAllowIfInheritsPrincipal,
383 uint64_t aInnerWindowID) {
384 return CheckMayLoadHelper(aURI, aAllowIfInheritsPrincipal, true,
385 aInnerWindowID);
388 nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
389 bool aAllowIfInheritsPrincipal,
390 bool aReport,
391 uint64_t aInnerWindowID) {
392 NS_ENSURE_ARG_POINTER(aURI);
393 MOZ_ASSERT(
394 aReport || aInnerWindowID == 0,
395 "Why do we have an inner window id if we're not supposed to report?");
397 // Check the internal method first, which allows us to quickly approve loads
398 // for the System Principal.
399 if (MayLoadInternal(aURI)) {
400 return NS_OK;
403 nsresult rv;
404 if (aAllowIfInheritsPrincipal) {
405 // If the caller specified to allow loads of URIs that inherit
406 // our principal, allow the load if this URI inherits its principal.
407 bool doesInheritSecurityContext;
408 rv = NS_URIChainHasFlags(aURI,
409 nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
410 &doesInheritSecurityContext);
411 if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
412 return NS_OK;
416 bool fetchableByAnyone;
417 rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
418 &fetchableByAnyone);
419 if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
420 return NS_OK;
423 if (aReport) {
424 nsCOMPtr<nsIURI> prinURI;
425 rv = GetURI(getter_AddRefs(prinURI));
426 if (NS_SUCCEEDED(rv) && prinURI) {
427 nsScriptSecurityManager::ReportError(
428 "CheckSameOriginError", prinURI, aURI,
429 mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
433 return NS_ERROR_DOM_BAD_URI;
436 NS_IMETHODIMP
437 BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) {
438 *aRes = true;
439 // If we do not have a URI its always 3rd party.
440 nsCOMPtr<nsIURI> prinURI;
441 nsresult rv = GetURI(getter_AddRefs(prinURI));
442 if (NS_FAILED(rv) || !prinURI) {
443 return NS_OK;
445 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
446 return thirdPartyUtil->IsThirdPartyURI(prinURI, aURI, aRes);
449 NS_IMETHODIMP
450 BasePrincipal::IsThirdPartyPrincipal(nsIPrincipal* aPrin, bool* aRes) {
451 *aRes = true;
452 nsCOMPtr<nsIURI> prinURI;
453 nsresult rv = GetURI(getter_AddRefs(prinURI));
454 if (NS_FAILED(rv) || !prinURI) {
455 return NS_OK;
457 return aPrin->IsThirdPartyURI(prinURI, aRes);
460 NS_IMETHODIMP
461 BasePrincipal::IsSameOrigin(nsIURI* aURI, bool aIsPrivateWin, bool* aRes) {
462 *aRes = false;
463 nsCOMPtr<nsIURI> prinURI;
464 nsresult rv = GetURI(getter_AddRefs(prinURI));
465 if (NS_FAILED(rv) || !prinURI) {
466 return NS_OK;
468 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
469 if (!ssm) {
470 return NS_ERROR_UNEXPECTED;
473 *aRes = NS_SUCCEEDED(
474 ssm->CheckSameOriginURI(prinURI, aURI, false, aIsPrivateWin));
475 return NS_OK;
478 NS_IMETHODIMP
479 BasePrincipal::GetIsNullPrincipal(bool* aResult) {
480 *aResult = Kind() == eNullPrincipal;
481 return NS_OK;
484 NS_IMETHODIMP
485 BasePrincipal::GetIsContentPrincipal(bool* aResult) {
486 *aResult = Kind() == eContentPrincipal;
487 return NS_OK;
490 NS_IMETHODIMP
491 BasePrincipal::GetIsExpandedPrincipal(bool* aResult) {
492 *aResult = Kind() == eExpandedPrincipal;
493 return NS_OK;
496 NS_IMETHODIMP
497 BasePrincipal::GetAsciiSpec(nsACString& aSpec) {
498 aSpec.Truncate();
499 nsCOMPtr<nsIURI> prinURI;
500 nsresult rv = GetURI(getter_AddRefs(prinURI));
501 if (NS_FAILED(rv) || !prinURI) {
502 return NS_OK;
504 return prinURI->GetAsciiSpec(aSpec);
507 NS_IMETHODIMP
508 BasePrincipal::GetExposablePrePath(nsACString& aPrepath) {
509 aPrepath.Truncate();
510 nsCOMPtr<nsIURI> prinURI;
511 nsresult rv = GetURI(getter_AddRefs(prinURI));
512 if (NS_FAILED(rv) || !prinURI) {
513 return NS_OK;
516 nsCOMPtr<nsIURIFixup> fixup(components::URIFixup::Service());
517 nsCOMPtr<nsIURIFixup> urifixup = services::GetURIFixup();
518 if (NS_WARN_IF(!urifixup)) {
519 return NS_OK;
522 nsCOMPtr<nsIURI> fixedURI;
523 rv = fixup->CreateExposableURI(prinURI, getter_AddRefs(fixedURI));
525 if (NS_FAILED(rv) || NS_WARN_IF(!fixedURI)) {
526 return NS_OK;
528 return fixedURI->GetDisplayPrePath(aPrepath);
530 NS_IMETHODIMP
531 BasePrincipal::GetPrepath(nsACString& aPath) {
532 aPath.Truncate();
533 nsCOMPtr<nsIURI> prinURI;
534 nsresult rv = GetURI(getter_AddRefs(prinURI));
535 if (NS_FAILED(rv) || !prinURI) {
536 return NS_OK;
538 return prinURI->GetPrePath(aPath);
541 NS_IMETHODIMP
542 BasePrincipal::GetIsSystemPrincipal(bool* aResult) {
543 *aResult = IsSystemPrincipal();
544 return NS_OK;
547 NS_IMETHODIMP
548 BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult) {
549 *aResult = AddonPolicy() || ContentScriptAddonPolicy();
550 return NS_OK;
553 NS_IMETHODIMP BasePrincipal::GetIsOnion(bool* aIsOnion) {
554 *aIsOnion = false;
555 nsCOMPtr<nsIURI> prinURI;
556 nsresult rv = GetURI(getter_AddRefs(prinURI));
557 if (NS_FAILED(rv) || !prinURI) {
558 return NS_OK;
561 nsAutoCString host;
562 rv = prinURI->GetHost(host);
563 if (NS_FAILED(rv)) {
564 return NS_OK;
566 *aIsOnion = StringEndsWith(host, NS_LITERAL_CSTRING(".onion"));
567 return NS_OK;
570 NS_IMETHODIMP
571 BasePrincipal::SchemeIs(const char* aScheme, bool* aResult) {
572 *aResult = false;
573 nsCOMPtr<nsIURI> prinURI;
574 nsresult rv = GetURI(getter_AddRefs(prinURI));
575 if (NS_FAILED(rv) || !prinURI) {
576 return NS_OK;
578 *aResult = prinURI->SchemeIs(aScheme);
579 return NS_OK;
582 NS_IMETHODIMP
583 BasePrincipal::IsURIInPrefList(const char* aPref, bool* aResult) {
584 *aResult = false;
585 nsCOMPtr<nsIURI> prinURI;
586 nsresult rv = GetURI(getter_AddRefs(prinURI));
587 if (NS_FAILED(rv) || !prinURI) {
588 return NS_OK;
590 *aResult = nsContentUtils::IsURIInPrefList(prinURI, aPref);
591 return NS_OK;
594 NS_IMETHODIMP
595 BasePrincipal::GetIsOriginPotentiallyTrustworthy(bool* aResult) {
596 MOZ_ASSERT(NS_IsMainThread());
597 *aResult = false;
599 nsCOMPtr<nsIURI> uri;
600 nsresult rv = GetURI(getter_AddRefs(uri));
601 if (NS_FAILED(rv) || !uri) {
602 return NS_OK;
605 *aResult = nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(uri);
606 return NS_OK;
609 NS_IMETHODIMP
610 BasePrincipal::GetAboutModuleFlags(uint32_t* flags) {
611 *flags = 0;
612 nsCOMPtr<nsIURI> prinURI;
613 nsresult rv = GetURI(getter_AddRefs(prinURI));
614 if (NS_FAILED(rv) || !prinURI) {
615 return NS_ERROR_NOT_AVAILABLE;
617 if (!prinURI->SchemeIs("about")) {
618 return NS_OK;
621 nsCOMPtr<nsIAboutModule> aboutModule;
622 rv = NS_GetAboutModule(prinURI, getter_AddRefs(aboutModule));
623 if (NS_FAILED(rv) || !aboutModule) {
624 return rv;
626 return aboutModule->GetURIFlags(prinURI, flags);
629 NS_IMETHODIMP
630 BasePrincipal::GetOriginAttributes(JSContext* aCx,
631 JS::MutableHandle<JS::Value> aVal) {
632 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
633 return NS_ERROR_FAILURE;
635 return NS_OK;
638 NS_IMETHODIMP
639 BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) {
640 MOZ_ASSERT(mOriginSuffix);
641 mOriginSuffix->ToUTF8String(aOriginAttributes);
642 return NS_OK;
645 NS_IMETHODIMP
646 BasePrincipal::GetUserContextId(uint32_t* aUserContextId) {
647 *aUserContextId = UserContextId();
648 return NS_OK;
651 NS_IMETHODIMP
652 BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) {
653 *aPrivateBrowsingId = PrivateBrowsingId();
654 return NS_OK;
657 NS_IMETHODIMP
658 BasePrincipal::GetIsInIsolatedMozBrowserElement(
659 bool* aIsInIsolatedMozBrowserElement) {
660 *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
661 return NS_OK;
664 nsresult BasePrincipal::GetAddonPolicy(nsISupports** aResult) {
665 RefPtr<extensions::WebExtensionPolicy> policy(AddonPolicy());
666 policy.forget(aResult);
667 return NS_OK;
670 extensions::WebExtensionPolicy* BasePrincipal::AddonPolicy() {
671 if (Is<ContentPrincipal>()) {
672 return As<ContentPrincipal>()->AddonPolicy();
674 return nullptr;
677 bool BasePrincipal::AddonHasPermission(const nsAtom* aPerm) {
678 if (auto policy = AddonPolicy()) {
679 return policy->HasPermission(aPerm);
681 return false;
684 nsIPrincipal* BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI) {
685 if (Is<ExpandedPrincipal>()) {
686 return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
688 return this;
691 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
692 nsIURI* aURI, const OriginAttributes& aAttrs) {
693 MOZ_ASSERT(aURI);
695 nsAutoCString originNoSuffix;
696 nsresult rv =
697 ContentPrincipal::GenerateOriginNoSuffixFromURI(aURI, originNoSuffix);
698 if (NS_FAILED(rv)) {
699 // If the generation of the origin fails, we still want to have a valid
700 // principal. Better to return a null principal here.
701 return NullPrincipal::Create(aAttrs);
704 return CreateContentPrincipal(aURI, aAttrs, originNoSuffix);
707 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
708 nsIURI* aURI, const OriginAttributes& aAttrs,
709 const nsACString& aOriginNoSuffix) {
710 MOZ_ASSERT(aURI);
711 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
713 // If the URI is supposed to inherit the security context of whoever loads it,
714 // we shouldn't make a content principal for it.
715 bool inheritsPrincipal;
716 nsresult rv = NS_URIChainHasFlags(
717 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
718 &inheritsPrincipal);
719 if (NS_FAILED(rv) || inheritsPrincipal) {
720 return NullPrincipal::Create(aAttrs);
723 // Check whether the URI knows what its principal is supposed to be.
724 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
725 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
726 do_QueryInterface(aURI);
727 if (uriWithSpecialOrigin) {
728 nsCOMPtr<nsIURI> origin;
729 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
730 if (NS_WARN_IF(NS_FAILED(rv))) {
731 return nullptr;
733 MOZ_ASSERT(origin);
734 OriginAttributes attrs;
735 RefPtr<BasePrincipal> principal = CreateContentPrincipal(origin, attrs);
736 return principal.forget();
738 #endif
740 nsCOMPtr<nsIPrincipal> blobPrincipal;
741 if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
742 aURI, getter_AddRefs(blobPrincipal))) {
743 MOZ_ASSERT(blobPrincipal);
744 RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
745 return principal.forget();
748 // Mint a content principal.
749 RefPtr<ContentPrincipal> principal = new ContentPrincipal();
750 rv = principal->Init(aURI, aAttrs, aOriginNoSuffix);
751 NS_ENSURE_SUCCESS(rv, nullptr);
752 return principal.forget();
755 already_AddRefed<BasePrincipal> BasePrincipal::CreateContentPrincipal(
756 const nsACString& aOrigin) {
757 MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
758 "CreateContentPrincipal does not support System and Expanded "
759 "principals");
761 MOZ_ASSERT(!StringBeginsWith(aOrigin,
762 NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
763 "CreateContentPrincipal does not support NullPrincipal");
765 nsAutoCString originNoSuffix;
766 OriginAttributes attrs;
767 if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
768 return nullptr;
771 nsCOMPtr<nsIURI> uri;
772 nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
773 NS_ENSURE_SUCCESS(rv, nullptr);
775 return BasePrincipal::CreateContentPrincipal(uri, attrs);
778 already_AddRefed<BasePrincipal> BasePrincipal::CloneForcingOriginAttributes(
779 const OriginAttributes& aOriginAttributes) {
780 if (NS_WARN_IF(!IsContentPrincipal())) {
781 return nullptr;
784 nsAutoCString originNoSuffix;
785 nsresult rv = GetOriginNoSuffix(originNoSuffix);
786 NS_ENSURE_SUCCESS(rv, nullptr);
788 nsIURI* uri = static_cast<ContentPrincipal*>(this)->mURI;
789 RefPtr<ContentPrincipal> copy = new ContentPrincipal();
790 rv = copy->Init(uri, aOriginAttributes, originNoSuffix);
791 NS_ENSURE_SUCCESS(rv, nullptr);
793 return copy.forget();
796 extensions::WebExtensionPolicy* BasePrincipal::ContentScriptAddonPolicy() {
797 if (!Is<ExpandedPrincipal>()) {
798 return nullptr;
801 auto expanded = As<ExpandedPrincipal>();
802 for (auto& prin : expanded->AllowList()) {
803 if (auto policy = BasePrincipal::Cast(prin)->AddonPolicy()) {
804 return policy;
808 return nullptr;
811 bool BasePrincipal::AddonAllowsLoad(nsIURI* aURI,
812 bool aExplicit /* = false */) {
813 if (Is<ExpandedPrincipal>()) {
814 return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
816 if (auto policy = AddonPolicy()) {
817 return policy->CanAccessURI(aURI, aExplicit);
819 return false;
822 void BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
823 const OriginAttributes& aOriginAttributes) {
824 mInitialized = true;
825 mOriginAttributes = aOriginAttributes;
827 // First compute the origin suffix since it's infallible.
828 nsAutoCString originSuffix;
829 mOriginAttributes.CreateSuffix(originSuffix);
830 mOriginSuffix = NS_Atomize(originSuffix);
832 MOZ_ASSERT(!aOriginNoSuffix.IsEmpty());
833 mOriginNoSuffix = NS_Atomize(aOriginNoSuffix);
836 void BasePrincipal::FinishInit(BasePrincipal* aOther,
837 const OriginAttributes& aOriginAttributes) {
838 mInitialized = true;
839 mOriginAttributes = aOriginAttributes;
841 // First compute the origin suffix since it's infallible.
842 nsAutoCString originSuffix;
843 mOriginAttributes.CreateSuffix(originSuffix);
844 mOriginSuffix = NS_Atomize(originSuffix);
846 mOriginNoSuffix = aOther->mOriginNoSuffix;
847 mHasExplicitDomain = aOther->mHasExplicitDomain;
850 bool SiteIdentifier::Equals(const SiteIdentifier& aOther) const {
851 MOZ_ASSERT(IsInitialized());
852 MOZ_ASSERT(aOther.IsInitialized());
853 return mPrincipal->FastEquals(aOther.mPrincipal);
856 } // namespace mozilla