diff options
Diffstat (limited to 'caps/BasePrincipal.cpp')
-rw-r--r-- | caps/BasePrincipal.cpp | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp new file mode 100644 index 000000000..b768d5c1f --- /dev/null +++ b/caps/BasePrincipal.cpp @@ -0,0 +1,777 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/BasePrincipal.h" + +#include "nsDocShell.h" +#ifdef MOZ_CRASHREPORTER +#include "nsExceptionHandler.h" +#endif +#include "nsIAddonPolicyService.h" +#include "nsIContentSecurityPolicy.h" +#include "nsIEffectiveTLDService.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" + +#include "nsPrincipal.h" +#include "nsNetUtil.h" +#include "nsIURIWithPrincipal.h" +#include "nsNullPrincipal.h" +#include "nsScriptSecurityManager.h" +#include "nsServiceManagerUtils.h" + +#include "mozilla/dom/ChromeUtils.h" +#include "mozilla/dom/CSPDictionariesBinding.h" +#include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/dom/ToJSValue.h" +#include "mozilla/dom/URLSearchParams.h" + +namespace mozilla { + +using dom::URLParams; + +void +PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs, + const nsIURI* aURI) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + + // addonId is computed from the principal URI and never propagated + mUserContextId = aAttrs.mUserContextId; + + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + mFirstPartyDomain = aAttrs.mFirstPartyDomain; +} + +void +PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + + // addonId is computed from the principal URI and never propagated + mUserContextId = aAttrs.mUserContextId; + + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + mFirstPartyDomain = aAttrs.mFirstPartyDomain; +} + +void +PrincipalOriginAttributes::StripUserContextIdAndFirstPartyDomain() +{ + mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID; + mFirstPartyDomain.Truncate(); +} + +void +DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + + // addonId is computed from the principal URI and never propagated + mUserContextId = aAttrs.mUserContextId; + + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + mFirstPartyDomain = aAttrs.mFirstPartyDomain; +} + +void +NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + + // addonId is computed from the principal URI and never propagated + mUserContextId = aAttrs.mUserContextId; + + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + mFirstPartyDomain = aAttrs.mFirstPartyDomain; +} + +void +NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs, + const bool aIsTopLevelDocument, + nsIURI* aURI) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + + // addonId is computed from the principal URI and never propagated + mUserContextId = aAttrs.mUserContextId; + + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + + bool isFirstPartyEnabled = IsFirstPartyEnabled(); + + // When the pref is on, we also compute the firstPartyDomain attribute + // if this is for top-level document. + if (isFirstPartyEnabled && aIsTopLevelDocument) { + nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); + MOZ_ASSERT(tldService); + if (!tldService) { + return; + } + + nsAutoCString baseDomain; + tldService->GetBaseDomain(aURI, 0, baseDomain); + mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain); + } else { + mFirstPartyDomain = aAttrs.mFirstPartyDomain; + } +} + +void +OriginAttributes::CreateSuffix(nsACString& aStr) const +{ + UniquePtr<URLParams> params(new URLParams()); + nsAutoString value; + + // + // Important: While serializing any string-valued attributes, perform a + // release-mode assertion to make sure that they don't contain characters that + // will break the quota manager when it uses the serialization for file + // naming (see addonId below). + // + + if (mAppId != nsIScriptSecurityManager::NO_APP_ID) { + value.AppendInt(mAppId); + params->Set(NS_LITERAL_STRING("appId"), value); + } + + if (mInIsolatedMozBrowser) { + params->Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1")); + } + + if (!mAddonId.IsEmpty()) { + if (mAddonId.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) != kNotFound) { +#ifdef MOZ_CRASHREPORTER + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Crash_AddonId"), + NS_ConvertUTF16toUTF8(mAddonId)); +#endif + MOZ_CRASH(); + } + params->Set(NS_LITERAL_STRING("addonId"), mAddonId); + } + + if (mUserContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) { + value.Truncate(); + value.AppendInt(mUserContextId); + params->Set(NS_LITERAL_STRING("userContextId"), value); + } + + + if (mPrivateBrowsingId) { + value.Truncate(); + value.AppendInt(mPrivateBrowsingId); + params->Set(NS_LITERAL_STRING("privateBrowsingId"), value); + } + + if (!mFirstPartyDomain.IsEmpty()) { + MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound); + params->Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain); + } + + aStr.Truncate(); + + params->Serialize(value); + if (!value.IsEmpty()) { + aStr.AppendLiteral("^"); + aStr.Append(NS_ConvertUTF16toUTF8(value)); + } + +// In debug builds, check the whole string for illegal characters too (just in case). +#ifdef DEBUG + nsAutoCString str; + str.Assign(aStr); + MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound); +#endif +} + +void +OriginAttributes::CreateAnonymizedSuffix(nsACString& aStr) const +{ + OriginAttributes attrs = *this; + + if (!attrs.mFirstPartyDomain.IsEmpty()) { + attrs.mFirstPartyDomain.AssignLiteral("_anonymizedFirstPartyDomain_"); + } + + attrs.CreateSuffix(aStr); +} + +namespace { + +class MOZ_STACK_CLASS PopulateFromSuffixIterator final + : public URLParams::ForEachIterator +{ +public: + explicit PopulateFromSuffixIterator(OriginAttributes* aOriginAttributes) + : mOriginAttributes(aOriginAttributes) + { + MOZ_ASSERT(aOriginAttributes); + // If mPrivateBrowsingId is passed in as >0 and is not present in the suffix, + // then it will remain >0 when it should be 0 according to the suffix. Set to 0 before + // iterating to fix this. + mOriginAttributes->mPrivateBrowsingId = 0; + } + + bool URLParamsIterator(const nsString& aName, + const nsString& aValue) override + { + if (aName.EqualsLiteral("appId")) { + nsresult rv; + int64_t val = aValue.ToInteger64(&rv); + NS_ENSURE_SUCCESS(rv, false); + NS_ENSURE_TRUE(val <= UINT32_MAX, false); + mOriginAttributes->mAppId = static_cast<uint32_t>(val); + + return true; + } + + if (aName.EqualsLiteral("inBrowser")) { + if (!aValue.EqualsLiteral("1")) { + return false; + } + + mOriginAttributes->mInIsolatedMozBrowser = true; + return true; + } + + if (aName.EqualsLiteral("addonId")) { + MOZ_RELEASE_ASSERT(mOriginAttributes->mAddonId.IsEmpty()); + mOriginAttributes->mAddonId.Assign(aValue); + return true; + } + + if (aName.EqualsLiteral("userContextId")) { + nsresult rv; + int64_t val = aValue.ToInteger64(&rv); + NS_ENSURE_SUCCESS(rv, false); + NS_ENSURE_TRUE(val <= UINT32_MAX, false); + mOriginAttributes->mUserContextId = static_cast<uint32_t>(val); + + return true; + } + + if (aName.EqualsLiteral("privateBrowsingId")) { + nsresult rv; + int64_t val = aValue.ToInteger64(&rv); + NS_ENSURE_SUCCESS(rv, false); + NS_ENSURE_TRUE(val >= 0 && val <= UINT32_MAX, false); + mOriginAttributes->mPrivateBrowsingId = static_cast<uint32_t>(val); + + return true; + } + + if (aName.EqualsLiteral("firstPartyDomain")) { + MOZ_RELEASE_ASSERT(mOriginAttributes->mFirstPartyDomain.IsEmpty()); + mOriginAttributes->mFirstPartyDomain.Assign(aValue); + return true; + } + + // No other attributes are supported. + return false; + } + +private: + OriginAttributes* mOriginAttributes; +}; + +} // namespace + +bool +OriginAttributes::PopulateFromSuffix(const nsACString& aStr) +{ + if (aStr.IsEmpty()) { + return true; + } + + if (aStr[0] != '^') { + return false; + } + + UniquePtr<URLParams> params(new URLParams()); + params->ParseInput(Substring(aStr, 1, aStr.Length() - 1)); + + PopulateFromSuffixIterator iterator(this); + return params->ForEach(iterator); +} + +bool +OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin, + nsACString& aOriginNoSuffix) +{ + // RFindChar is only available on nsCString. + nsCString origin(aOrigin); + int32_t pos = origin.RFindChar('^'); + + if (pos == kNotFound) { + aOriginNoSuffix = origin; + return true; + } + + aOriginNoSuffix = Substring(origin, 0, pos); + return PopulateFromSuffix(Substring(origin, pos)); +} + +void +OriginAttributes::SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing) +{ + mPrivateBrowsingId = aInPrivateBrowsing ? 1 : 0; +} + +void +OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs) +{ + mAppId = aAttrs.mAppId; + mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser; + mAddonId = aAttrs.mAddonId; + mUserContextId = aAttrs.mUserContextId; + mPrivateBrowsingId = aAttrs.mPrivateBrowsingId; + mFirstPartyDomain = aAttrs.mFirstPartyDomain; +} + +/* static */ +bool +OriginAttributes::IsFirstPartyEnabled() +{ + // Cache the privacy.firstparty.isolate pref. + static bool sFirstPartyIsolation = false; + static bool sCachedFirstPartyPref = false; + if (!sCachedFirstPartyPref) { + sCachedFirstPartyPref = true; + Preferences::AddBoolVarCache(&sFirstPartyIsolation, "privacy.firstparty.isolate"); + } + + return sFirstPartyIsolation; +} + +BasePrincipal::BasePrincipal() +{} + +BasePrincipal::~BasePrincipal() +{} + +NS_IMETHODIMP +BasePrincipal::GetOrigin(nsACString& aOrigin) +{ + nsresult rv = GetOriginInternal(aOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString suffix; + mOriginAttributes.CreateSuffix(suffix); + aOrigin.Append(suffix); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) +{ + return GetOriginInternal(aOrigin); +} + +bool +BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) +{ + MOZ_ASSERT(aOther); + + // Expanded principals handle origin attributes for each of their + // sub-principals individually, null principals do only simple checks for + // pointer equality, and system principals are immune to origin attributes + // checks, so only do this check for codebase principals. + if (Kind() == eCodebasePrincipal && + OriginAttributesRef() != Cast(aOther)->OriginAttributesRef()) { + return false; + } + + return SubsumesInternal(aOther, aConsideration); +} + +NS_IMETHODIMP +BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult) +{ + NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); + *aResult = Subsumes(aOther, DontConsiderDocumentDomain) && + Cast(aOther)->Subsumes(this, DontConsiderDocumentDomain); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult) +{ + NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); + *aResult = Subsumes(aOther, ConsiderDocumentDomain) && + Cast(aOther)->Subsumes(this, ConsiderDocumentDomain); + return NS_OK; +} + +bool +BasePrincipal::EqualsIgnoringAddonId(nsIPrincipal *aOther) +{ + MOZ_ASSERT(aOther); + + // Note that this will not work for expanded principals, nor is it intended + // to. + if (!dom::ChromeUtils::IsOriginAttributesEqualIgnoringAddonId( + OriginAttributesRef(), Cast(aOther)->OriginAttributesRef())) { + return false; + } + + return SubsumesInternal(aOther, DontConsiderDocumentDomain) && + Cast(aOther)->SubsumesInternal(this, DontConsiderDocumentDomain); +} + +NS_IMETHODIMP +BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) +{ + NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); + *aResult = Subsumes(aOther, DontConsiderDocumentDomain); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult) +{ + NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); + *aResult = Subsumes(aOther, ConsiderDocumentDomain); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal) +{ + // Check the internal method first, which allows us to quickly approve loads + // for the System Principal. + if (MayLoadInternal(aURI)) { + return NS_OK; + } + + nsresult rv; + if (aAllowIfInheritsPrincipal) { + // If the caller specified to allow loads of URIs that inherit + // our principal, allow the load if this URI inherits its principal. + bool doesInheritSecurityContext; + rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, + &doesInheritSecurityContext); + if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) { + return NS_OK; + } + } + + bool fetchableByAnyone; + rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE, &fetchableByAnyone); + if (NS_SUCCEEDED(rv) && fetchableByAnyone) { + return NS_OK; + } + + if (aReport) { + nsCOMPtr<nsIURI> prinURI; + rv = GetURI(getter_AddRefs(prinURI)); + if (NS_SUCCEEDED(rv) && prinURI) { + nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), prinURI, aURI); + } + } + + return NS_ERROR_DOM_BAD_URI; +} + +NS_IMETHODIMP +BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) +{ + NS_IF_ADDREF(*aCsp = mCSP); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) +{ + // Never destroy an existing CSP on the principal. + // This method should only be called in rare cases. + + MOZ_ASSERT(!mCSP, "do not destroy an existing CSP"); + if (mCSP) { + return NS_ERROR_ALREADY_INITIALIZED; + } + + mCSP = aCsp; + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument, + nsIContentSecurityPolicy** aCSP) +{ + if (mCSP) { + // if there is a CSP already associated with this principal + // then just return that - do not overwrite it!!! + NS_IF_ADDREF(*aCSP = mCSP); + return NS_OK; + } + + nsresult rv = NS_OK; + mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // Store the request context for violation reports + rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr) + : mCSP->SetRequestContext(nullptr, this); + NS_ENSURE_SUCCESS(rv, rv); + NS_IF_ADDREF(*aCSP = mCSP); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) +{ + NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument, + nsIContentSecurityPolicy** aPreloadCSP) +{ + if (mPreloadCSP) { + // if there is a speculative CSP already associated with this principal + // then just return that - do not overwrite it!!! + NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); + return NS_OK; + } + + nsresult rv = NS_OK; + mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // Store the request context for violation reports + rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr) + : mPreloadCSP->SetRequestContext(nullptr, this); + NS_ENSURE_SUCCESS(rv, rv); + NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetCspJSON(nsAString& outCSPinJSON) +{ + outCSPinJSON.Truncate(); + dom::CSPPolicies jsonPolicies; + + if (!mCSP) { + jsonPolicies.ToJSON(outCSPinJSON); + return NS_OK; + } + return mCSP->ToJSON(outCSPinJSON); +} + +NS_IMETHODIMP +BasePrincipal::GetIsNullPrincipal(bool* aResult) +{ + *aResult = Kind() == eNullPrincipal; + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetIsCodebasePrincipal(bool* aResult) +{ + *aResult = Kind() == eCodebasePrincipal; + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetIsExpandedPrincipal(bool* aResult) +{ + *aResult = Kind() == eExpandedPrincipal; + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetIsSystemPrincipal(bool* aResult) +{ + *aResult = Kind() == eSystemPrincipal; + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) +{ + if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) +{ + mOriginAttributes.CreateSuffix(aOriginAttributes); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetAppStatus(uint16_t* aAppStatus) +{ + if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) { + NS_WARNING("Asking for app status on a principal with an unknown app id"); + *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; + return NS_OK; + } + + *aAppStatus = nsScriptSecurityManager::AppStatusForPrincipal(this); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetAppId(uint32_t* aAppId) +{ + if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) { + MOZ_ASSERT(false); + *aAppId = nsIScriptSecurityManager::NO_APP_ID; + return NS_OK; + } + + *aAppId = AppId(); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetAddonId(nsAString& aAddonId) +{ + aAddonId.Assign(mOriginAttributes.mAddonId); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetUserContextId(uint32_t* aUserContextId) +{ + *aUserContextId = UserContextId(); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) +{ + *aPrivateBrowsingId = PrivateBrowsingId(); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) +{ + *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement(); + return NS_OK; +} + +NS_IMETHODIMP +BasePrincipal::GetUnknownAppId(bool* aUnknownAppId) +{ + *aUnknownAppId = AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID; + return NS_OK; +} + +bool +BasePrincipal::AddonHasPermission(const nsAString& aPerm) +{ + if (mOriginAttributes.mAddonId.IsEmpty()) { + return false; + } + nsCOMPtr<nsIAddonPolicyService> aps = + do_GetService("@mozilla.org/addons/policy-service;1"); + NS_ENSURE_TRUE(aps, false); + + bool retval = false; + nsresult rv = aps->AddonHasPermission(mOriginAttributes.mAddonId, aPerm, &retval); + NS_ENSURE_SUCCESS(rv, false); + return retval; +} + +already_AddRefed<BasePrincipal> +BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs) +{ + // If the URI is supposed to inherit the security context of whoever loads it, + // we shouldn't make a codebase principal for it. + bool inheritsPrincipal; + nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, + &inheritsPrincipal); + if (NS_FAILED(rv) || inheritsPrincipal) { + return nsNullPrincipal::Create(aAttrs); + } + + // Check whether the URI knows what its principal is supposed to be. + nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); + if (uriPrinc) { + nsCOMPtr<nsIPrincipal> principal; + uriPrinc->GetPrincipal(getter_AddRefs(principal)); + if (!principal) { + return nsNullPrincipal::Create(aAttrs); + } + RefPtr<BasePrincipal> concrete = Cast(principal); + return concrete.forget(); + } + + // Mint a codebase principal. + RefPtr<nsPrincipal> codebase = new nsPrincipal(); + rv = codebase->Init(aURI, aAttrs); + NS_ENSURE_SUCCESS(rv, nullptr); + return codebase.forget(); +} + +already_AddRefed<BasePrincipal> +BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin) +{ + MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")), + "CreateCodebasePrincipal does not support System and Expanded principals"); + + MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")), + "CreateCodebasePrincipal does not support nsNullPrincipal"); + + nsAutoCString originNoSuffix; + mozilla::PrincipalOriginAttributes attrs; + if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { + return nullptr; + } + + nsCOMPtr<nsIURI> uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); + NS_ENSURE_SUCCESS(rv, nullptr); + + return BasePrincipal::CreateCodebasePrincipal(uri, attrs); +} + +already_AddRefed<BasePrincipal> +BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain() +{ + PrincipalOriginAttributes attrs = OriginAttributesRef(); + attrs.StripUserContextIdAndFirstPartyDomain(); + + nsAutoCString originNoSuffix; + nsresult rv = GetOriginNoSuffix(originNoSuffix); + NS_ENSURE_SUCCESS(rv, nullptr); + + nsCOMPtr<nsIURI> uri; + rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); + NS_ENSURE_SUCCESS(rv, nullptr); + + return BasePrincipal::CreateCodebasePrincipal(uri, attrs); +} + +bool +BasePrincipal::AddonAllowsLoad(nsIURI* aURI) +{ + if (mOriginAttributes.mAddonId.IsEmpty()) { + return false; + } + + nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1"); + NS_ENSURE_TRUE(aps, false); + + bool allowed = false; + nsresult rv = aps->AddonMayLoadURI(mOriginAttributes.mAddonId, aURI, &allowed); + return NS_SUCCEEDED(rv) && allowed; +} + +} // namespace mozilla |