diff -r 000000000000 -r 6474c204b198 caps/src/nsPrincipal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/caps/src/nsPrincipal.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,867 @@ +/* -*- 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 "nsPrincipal.h" + +#include "mozIThirdPartyUtil.h" +#include "nscore.h" +#include "nsScriptSecurityManager.h" +#include "nsString.h" +#include "nsReadableUtils.h" +#include "pratom.h" +#include "nsIURI.h" +#include "nsJSPrincipals.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" +#include "nsIClassInfoImpl.h" +#include "nsError.h" +#include "nsIContentSecurityPolicy.h" +#include "nsCxPusher.h" +#include "jswrapper.h" + +#include "mozilla/Preferences.h" +#include "mozilla/HashFunctions.h" + +#include "nsIAppsService.h" +#include "mozIApplication.h" + +using namespace mozilla; + +static bool gCodeBasePrincipalSupport = false; +static bool gIsObservingCodeBasePrincipalSupport = false; + +static bool URIIsImmutable(nsIURI* aURI) +{ + nsCOMPtr mutableObj(do_QueryInterface(aURI)); + bool isMutable; + return + mutableObj && + NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) && + !isMutable; +} + +// Static member variables +const char nsBasePrincipal::sInvalid[] = "Invalid"; + +NS_IMETHODIMP_(MozExternalRefCountType) +nsBasePrincipal::AddRef() +{ + NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt"); + // XXXcaa does this need to be threadsafe? See bug 143559. + nsrefcnt count = ++refcount; + NS_LOG_ADDREF(this, count, "nsBasePrincipal", sizeof(*this)); + return count; +} + +NS_IMETHODIMP_(MozExternalRefCountType) +nsBasePrincipal::Release() +{ + NS_PRECONDITION(0 != refcount, "dup release"); + nsrefcnt count = --refcount; + NS_LOG_RELEASE(this, count, "nsBasePrincipal"); + if (count == 0) { + delete this; + } + + return count; +} + +nsBasePrincipal::nsBasePrincipal() +{ + if (!gIsObservingCodeBasePrincipalSupport) { + nsresult rv = + Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport, + "signed.applets.codebase_principal_support", + false); + gIsObservingCodeBasePrincipalSupport = NS_SUCCEEDED(rv); + NS_WARN_IF_FALSE(gIsObservingCodeBasePrincipalSupport, + "Installing gCodeBasePrincipalSupport failed!"); + } +} + +nsBasePrincipal::~nsBasePrincipal(void) +{ +} + +NS_IMETHODIMP +nsBasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) +{ + NS_IF_ADDREF(*aCsp = mCSP); + return NS_OK; +} + +NS_IMETHODIMP +nsBasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) +{ + // If CSP was already set, it should not be destroyed! Instead, it should + // get set anew when a new principal is created. + if (mCSP) + return NS_ERROR_ALREADY_INITIALIZED; + + mCSP = aCsp; + return NS_OK; +} + +#ifdef DEBUG +void nsPrincipal::dumpImpl() +{ + nsAutoCString str; + GetScriptLocation(str); + fprintf(stderr, "nsPrincipal (%p) = %s\n", static_cast(this), str.get()); +} +#endif + +NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, + NS_PRINCIPAL_CID) +NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal, + nsIPrincipal, + nsISerializable) +NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal, + nsIPrincipal, + nsISerializable) +NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal) +NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal) + +nsPrincipal::nsPrincipal() + : mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID) + , mInMozBrowser(false) + , mCodebaseImmutable(false) + , mDomainImmutable(false) + , mInitialized(false) +{ } + +nsPrincipal::~nsPrincipal() +{ } + +nsresult +nsPrincipal::Init(nsIURI *aCodebase, + uint32_t aAppId, + bool aInMozBrowser) +{ + NS_ENSURE_STATE(!mInitialized); + NS_ENSURE_ARG(aCodebase); + + mInitialized = true; + + mCodebase = NS_TryToMakeImmutable(aCodebase); + mCodebaseImmutable = URIIsImmutable(mCodebase); + + mAppId = aAppId; + mInMozBrowser = aInMozBrowser; + + return NS_OK; +} + +void +nsPrincipal::GetScriptLocation(nsACString &aStr) +{ + mCodebase->GetSpec(aStr); +} + +/* static */ nsresult +nsPrincipal::GetOriginForURI(nsIURI* aURI, char **aOrigin) +{ + if (!aURI) { + return NS_ERROR_FAILURE; + } + + *aOrigin = nullptr; + + nsCOMPtr origin = NS_GetInnermostURI(aURI); + if (!origin) { + return NS_ERROR_FAILURE; + } + + nsAutoCString hostPort; + + // chrome: URLs don't have a meaningful origin, so make + // sure we just get the full spec for them. + // XXX this should be removed in favor of the solution in + // bug 160042. + bool isChrome; + nsresult rv = origin->SchemeIs("chrome", &isChrome); + if (NS_SUCCEEDED(rv) && !isChrome) { + rv = origin->GetAsciiHost(hostPort); + // Some implementations return an empty string, treat it as no support + // for asciiHost by that implementation. + if (hostPort.IsEmpty()) { + rv = NS_ERROR_FAILURE; + } + } + + int32_t port; + if (NS_SUCCEEDED(rv) && !isChrome) { + rv = origin->GetPort(&port); + } + + if (NS_SUCCEEDED(rv) && !isChrome) { + if (port != -1) { + hostPort.AppendLiteral(":"); + hostPort.AppendInt(port, 10); + } + + nsAutoCString scheme; + rv = origin->GetScheme(scheme); + NS_ENSURE_SUCCESS(rv, rv); + + *aOrigin = ToNewCString(scheme + NS_LITERAL_CSTRING("://") + hostPort); + } + else { + // Some URIs (e.g., nsSimpleURI) don't support asciiHost. Just + // get the full spec. + nsAutoCString spec; + // XXX nsMozIconURI and nsJARURI don't implement this correctly, they + // both fall back to GetSpec. That needs to be fixed. + rv = origin->GetAsciiSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + + *aOrigin = ToNewCString(spec); + } + + return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} + +NS_IMETHODIMP +nsPrincipal::GetOrigin(char **aOrigin) +{ + return GetOriginForURI(mCodebase, aOrigin); +} + +NS_IMETHODIMP +nsPrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult) +{ + *aResult = false; + + if (!aOther) { + NS_WARNING("Need a principal to compare this to!"); + return NS_OK; + } + + if (aOther == this) { + *aResult = true; + return NS_OK; + } + + if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) { + return NS_OK; + } + + // If either the subject or the object has changed its principal by + // explicitly setting document.domain then the other must also have + // done so in order to be considered the same origin. This prevents + // DNS spoofing based on document.domain (154930) + + nsCOMPtr thisURI; + this->GetDomain(getter_AddRefs(thisURI)); + bool thisSetDomain = !!thisURI; + if (!thisURI) { + this->GetURI(getter_AddRefs(thisURI)); + } + + nsCOMPtr otherURI; + aOther->GetDomain(getter_AddRefs(otherURI)); + bool otherSetDomain = !!otherURI; + if (!otherURI) { + aOther->GetURI(getter_AddRefs(otherURI)); + } + + *aResult = thisSetDomain == otherSetDomain && + nsScriptSecurityManager::SecurityCompareURIs(thisURI, otherURI); + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::Equals(nsIPrincipal *aOther, bool *aResult) +{ + *aResult = false; + + if (!aOther) { + NS_WARNING("Need a principal to compare this to!"); + return NS_OK; + } + + if (aOther == this) { + *aResult = true; + return NS_OK; + } + + if (!nsScriptSecurityManager::AppAttributesEqual(this, aOther)) { + return NS_OK; + } + + nsCOMPtr otherURI; + nsresult rv = aOther->GetURI(getter_AddRefs(otherURI)); + if (NS_FAILED(rv)) { + return rv; + } + + NS_ASSERTION(mCodebase, + "shouldn't be calling this on principals from preferences"); + + // Compare codebases. + *aResult = nsScriptSecurityManager::SecurityCompareURIs(mCodebase, + otherURI); + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) +{ + return Equals(aOther, aResult); +} + +NS_IMETHODIMP +nsPrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult) +{ + return EqualsConsideringDomain(aOther, aResult); +} + +NS_IMETHODIMP +nsPrincipal::GetURI(nsIURI** aURI) +{ + if (mCodebaseImmutable) { + NS_ADDREF(*aURI = mCodebase); + return NS_OK; + } + + if (!mCodebase) { + *aURI = nullptr; + return NS_OK; + } + + return NS_EnsureSafeToReturn(mCodebase, aURI); +} + +NS_IMETHODIMP +nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal) +{ + if (aAllowIfInheritsPrincipal) { + // If the caller specified to allow loads of URIs that inherit + // our principal, allow the load if this URI inherits its principal + if (nsPrincipal::IsPrincipalInherited(aURI)) { + return NS_OK; + } + } + + if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) { + return NS_OK; + } + + // If strict file origin policy is in effect, local files will always fail + // SecurityCompareURIs unless they are identical. Explicitly check file origin + // policy, in that case. + if (nsScriptSecurityManager::GetStrictFileOriginPolicy() && + NS_URIIsLocalFile(aURI) && + NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) { + return NS_OK; + } + + if (aReport) { + nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI); + } + return NS_ERROR_DOM_BAD_URI; +} + +void +nsPrincipal::SetURI(nsIURI* aURI) +{ + mCodebase = NS_TryToMakeImmutable(aURI); + mCodebaseImmutable = URIIsImmutable(mCodebase); +} + +NS_IMETHODIMP +nsPrincipal::GetHashValue(uint32_t* aValue) +{ + NS_PRECONDITION(mCodebase, "Need a codebase"); + + *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this); + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetDomain(nsIURI** aDomain) +{ + if (!mDomain) { + *aDomain = nullptr; + return NS_OK; + } + + if (mDomainImmutable) { + NS_ADDREF(*aDomain = mDomain); + return NS_OK; + } + + return NS_EnsureSafeToReturn(mDomain, aDomain); +} + +NS_IMETHODIMP +nsPrincipal::SetDomain(nsIURI* aDomain) +{ + mDomain = NS_TryToMakeImmutable(aDomain); + mDomainImmutable = URIIsImmutable(mDomain); + + // Recompute all wrappers between compartments using this principal and other + // non-chrome compartments. + AutoSafeJSContext cx; + JSPrincipals *principals = nsJSPrincipals::get(static_cast(this)); + bool success = js::RecomputeWrappers(cx, js::ContentCompartmentsOnly(), + js::CompartmentsWithPrincipals(principals)); + NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); + success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals), + js::ContentCompartmentsOnly()); + NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetJarPrefix(nsACString& aJarPrefix) +{ + MOZ_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID); + + mozilla::GetJarPrefix(mAppId, mInMozBrowser, aJarPrefix); + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetAppStatus(uint16_t* aAppStatus) +{ + *aAppStatus = GetAppStatus(); + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetAppId(uint32_t* aAppId) +{ + if (mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) { + MOZ_ASSERT(false); + *aAppId = nsIScriptSecurityManager::NO_APP_ID; + return NS_OK; + } + + *aAppId = mAppId; + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement) +{ + *aIsInBrowserElement = mInMozBrowser; + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetUnknownAppId(bool* aUnknownAppId) +{ + *aUnknownAppId = mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID; + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal) +{ + *aIsNullPrincipal = false; + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::GetBaseDomain(nsACString& aBaseDomain) +{ + // For a file URI, we return the file path. + if (NS_URIIsLocalFile(mCodebase)) { + nsCOMPtr url = do_QueryInterface(mCodebase); + + if (url) { + return url->GetFilePath(aBaseDomain); + } + } + + // For everything else, we ask the TLD service via + // the ThirdPartyUtil. + nsCOMPtr thirdPartyUtil = + do_GetService(THIRDPARTYUTIL_CONTRACTID); + if (thirdPartyUtil) { + return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::Read(nsIObjectInputStream* aStream) +{ + nsCOMPtr supports; + nsCOMPtr codebase; + nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); + if (NS_FAILED(rv)) { + return rv; + } + + codebase = do_QueryInterface(supports); + + nsCOMPtr domain; + rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); + if (NS_FAILED(rv)) { + return rv; + } + + domain = do_QueryInterface(supports); + + uint32_t appId; + rv = aStream->Read32(&appId); + NS_ENSURE_SUCCESS(rv, rv); + + bool inMozBrowser; + rv = aStream->ReadBoolean(&inMozBrowser); + NS_ENSURE_SUCCESS(rv, rv); + + rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); + NS_ENSURE_SUCCESS(rv, rv); + + // This may be null. + nsCOMPtr csp = do_QueryInterface(supports, &rv); + + rv = Init(codebase, appId, inMozBrowser); + NS_ENSURE_SUCCESS(rv, rv); + + rv = SetCsp(csp); + NS_ENSURE_SUCCESS(rv, rv); + + // need to link in the CSP context here (link in a reference to this + // nsIPrincipal and to the URI of the protected resource). + if (csp) { + csp->SetRequestContext(codebase, nullptr, this, nullptr); + } + + SetDomain(domain); + + return NS_OK; +} + +NS_IMETHODIMP +nsPrincipal::Write(nsIObjectOutputStream* aStream) +{ + NS_ENSURE_STATE(mCodebase); + + nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI), + true); + if (NS_FAILED(rv)) { + return rv; + } + + rv = NS_WriteOptionalCompoundObject(aStream, mDomain, NS_GET_IID(nsIURI), + true); + if (NS_FAILED(rv)) { + return rv; + } + + aStream->Write32(mAppId); + aStream->WriteBoolean(mInMozBrowser); + + rv = NS_WriteOptionalCompoundObject(aStream, mCSP, + NS_GET_IID(nsIContentSecurityPolicy), + true); + if (NS_FAILED(rv)) { + return rv; + } + + // mCodebaseImmutable and mDomainImmutable will be recomputed based + // on the deserialized URIs in Read(). + + return NS_OK; +} + +uint16_t +nsPrincipal::GetAppStatus() +{ + NS_WARN_IF_FALSE(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, + "Asking for app status on a principal with an unknown app id"); + // Installed apps have a valid app id (not NO_APP_ID or UNKNOWN_APP_ID) + // and they are not inside a mozbrowser. + if (mAppId == nsIScriptSecurityManager::NO_APP_ID || + mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID || mInMozBrowser) { + return nsIPrincipal::APP_STATUS_NOT_INSTALLED; + } + + nsCOMPtr appsService = do_GetService(APPS_SERVICE_CONTRACTID); + NS_ENSURE_TRUE(appsService, nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + nsCOMPtr app; + appsService->GetAppByLocalId(mAppId, getter_AddRefs(app)); + NS_ENSURE_TRUE(app, nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + uint16_t status = nsIPrincipal::APP_STATUS_INSTALLED; + NS_ENSURE_SUCCESS(app->GetAppStatus(&status), + nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + nsAutoCString origin; + NS_ENSURE_SUCCESS(GetOrigin(getter_Copies(origin)), + nsIPrincipal::APP_STATUS_NOT_INSTALLED); + nsString appOrigin; + NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin), + nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + // We go from string -> nsIURI -> origin to be sure we + // compare two punny-encoded origins. + nsCOMPtr appURI; + NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin), + nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + nsAutoCString appOriginPunned; + NS_ENSURE_SUCCESS(GetOriginForURI(appURI, getter_Copies(appOriginPunned)), + nsIPrincipal::APP_STATUS_NOT_INSTALLED); + + if (!appOriginPunned.Equals(origin)) { + return nsIPrincipal::APP_STATUS_NOT_INSTALLED; + } + + return status; +} + +/************************************************************************************************************************/ + +static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]"; + +NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, + NS_EXPANDEDPRINCIPAL_CID) +NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal, + nsIPrincipal, + nsIExpandedPrincipal) +NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal, + nsIPrincipal, + nsIExpandedPrincipal) +NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal) +NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal) + +nsExpandedPrincipal::nsExpandedPrincipal(nsTArray > &aWhiteList) +{ + mPrincipals.AppendElements(aWhiteList); +} + +nsExpandedPrincipal::~nsExpandedPrincipal() +{ } + +NS_IMETHODIMP +nsExpandedPrincipal::GetDomain(nsIURI** aDomain) +{ + *aDomain = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::SetDomain(nsIURI* aDomain) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetOrigin(char** aOrigin) +{ + *aOrigin = ToNewCString(NS_LITERAL_CSTRING(EXPANDED_PRINCIPAL_SPEC)); + return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} + +typedef nsresult (NS_STDCALL nsIPrincipal::*nsIPrincipalMemFn)(nsIPrincipal* aOther, + bool* aResult); +#define CALL_MEMBER_FUNCTION(THIS,MEM_FN) ((THIS)->*(MEM_FN)) + +// nsExpandedPrincipal::Equals and nsExpandedPrincipal::EqualsConsideringDomain +// shares the same logic. The difference only that Equals requires 'this' +// and 'aOther' to Subsume each other while EqualsConsideringDomain requires +// bidirectional SubsumesConsideringDomain. +static nsresult +Equals(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther, + bool* aResult) +{ + // If (and only if) 'aThis' and 'aOther' both Subsume/SubsumesConsideringDomain + // each other, then they are Equal. + *aResult = false; + // Calling the corresponding subsume function on this (aFn). + nsresult rv = CALL_MEMBER_FUNCTION(aThis, aFn)(aOther, aResult); + NS_ENSURE_SUCCESS(rv, rv); + if (!*aResult) + return NS_OK; + + // Calling the corresponding subsume function on aOther (aFn). + rv = CALL_MEMBER_FUNCTION(aOther, aFn)(aThis, aResult); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::Equals(nsIPrincipal* aOther, bool* aResult) +{ + return ::Equals(this, &nsIPrincipal::Subsumes, aOther, aResult); +} + +NS_IMETHODIMP +nsExpandedPrincipal::EqualsConsideringDomain(nsIPrincipal* aOther, bool* aResult) +{ + return ::Equals(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult); +} + +// nsExpandedPrincipal::Subsumes and nsExpandedPrincipal::SubsumesConsideringDomain +// shares the same logic. The difference only that Subsumes calls are replaced +//with SubsumesConsideringDomain calls in the second case. +static nsresult +Subsumes(nsExpandedPrincipal* aThis, nsIPrincipalMemFn aFn, nsIPrincipal* aOther, + bool* aResult) +{ + nsresult rv; + nsCOMPtr expanded = do_QueryInterface(aOther); + if (expanded) { + // If aOther is an ExpandedPrincipal too, check if all of its + // principals are subsumed. + nsTArray< nsCOMPtr >* otherList; + expanded->GetWhiteList(&otherList); + for (uint32_t i = 0; i < otherList->Length(); ++i){ + rv = CALL_MEMBER_FUNCTION(aThis, aFn)((*otherList)[i], aResult); + NS_ENSURE_SUCCESS(rv, rv); + if (!*aResult) { + // If we don't subsume at least one principal of aOther, return false. + return NS_OK; + } + } + } else { + // For a regular aOther, one of our principals must subsume it. + nsTArray< nsCOMPtr >* list; + aThis->GetWhiteList(&list); + for (uint32_t i = 0; i < list->Length(); ++i){ + rv = CALL_MEMBER_FUNCTION((*list)[i], aFn)(aOther, aResult); + NS_ENSURE_SUCCESS(rv, rv); + if (*aResult) { + // If one of our principal subsumes it, return true. + return NS_OK; + } + } + } + return NS_OK; +} + +#undef CALL_MEMBER_FUNCTION + +NS_IMETHODIMP +nsExpandedPrincipal::Subsumes(nsIPrincipal* aOther, bool* aResult) +{ + return ::Subsumes(this, &nsIPrincipal::Subsumes, aOther, aResult); +} + +NS_IMETHODIMP +nsExpandedPrincipal::SubsumesConsideringDomain(nsIPrincipal* aOther, bool* aResult) +{ + return ::Subsumes(this, &nsIPrincipal::SubsumesConsideringDomain, aOther, aResult); +} + +NS_IMETHODIMP +nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal) +{ + nsresult rv; + for (uint32_t i = 0; i < mPrincipals.Length(); ++i){ + rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal); + if (NS_SUCCEEDED(rv)) + return rv; + } + + return NS_ERROR_DOM_BAD_URI; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetHashValue(uint32_t* result) +{ + MOZ_CRASH("extended principal should never be used as key in a hash map"); +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetURI(nsIURI** aURI) +{ + *aURI = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetWhiteList(nsTArray >** aWhiteList) +{ + *aWhiteList = &mPrincipals; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetJarPrefix(nsACString& aJarPrefix) +{ + aJarPrefix.Truncate(); + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetAppStatus(uint16_t* aAppStatus) +{ + *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetAppId(uint32_t* aAppId) +{ + *aAppId = nsIScriptSecurityManager::NO_APP_ID; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetIsInBrowserElement(bool* aIsInBrowserElement) +{ + *aIsInBrowserElement = false; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetUnknownAppId(bool* aUnknownAppId) +{ + *aUnknownAppId = false; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetIsNullPrincipal(bool* aIsNullPrincipal) +{ + *aIsNullPrincipal = false; + return NS_OK; +} + +NS_IMETHODIMP +nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain) +{ + return NS_ERROR_NOT_AVAILABLE; +} + +void +nsExpandedPrincipal::GetScriptLocation(nsACString& aStr) +{ + // Is that a good idea to list it's principals? + aStr.Assign(EXPANDED_PRINCIPAL_SPEC); +} + +#ifdef DEBUG +void nsExpandedPrincipal::dumpImpl() +{ + fprintf(stderr, "nsExpandedPrincipal (%p)\n", static_cast(this)); +} +#endif + +////////////////////////////////////////// +// Methods implementing nsISerializable // +////////////////////////////////////////// + +NS_IMETHODIMP +nsExpandedPrincipal::Read(nsIObjectInputStream* aStream) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream) +{ + return NS_ERROR_NOT_IMPLEMENTED; +}