/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 sts=2 ts=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/. */
/** * This is the principal that has no rights and can't be accessed by * anything other than itself and chrome; null principals are not * same-origin with anything but themselves.
*/
void NullPrincipal::EscapePrecursorQuery(nsACString& aPrecursorQuery) { // origins should not contain existing escape sequences, so set `esc_Forced` // to force any `%` in the input to be escaped in addition to non-ascii, // control characters and DEL.
nsCString modified; if (NS_EscapeURLSpan(aPrecursorQuery, esc_Query | esc_Forced, modified)) {
aPrecursorQuery.Assign(std::move(modified));
}
}
// If there's a precursor URI, encode it in the null principal URI's query. if (aPrecursor) {
nsAutoCString precursorOrigin; switch (BasePrincipal::Cast(aPrecursor)->Kind()) { case eNullPrincipal: { // If the precursor null principal has a precursor, inherit it. if (nsCOMPtr<nsIURI> nullPrecursorURI = aPrecursor->GetURI()) {
MOZ_ALWAYS_SUCCEEDS(nullPrecursorURI->GetQuery(precursorOrigin));
} break;
} case eContentPrincipal: {
MOZ_ALWAYS_SUCCEEDS(aPrecursor->GetOriginNoSuffix(precursorOrigin)); #ifdef DEBUG
nsAutoCString original(precursorOrigin); #endif
EscapePrecursorQuery(precursorOrigin); #ifdef DEBUG
nsAutoCString unescaped(precursorOrigin);
UnescapePrecursorQuery(unescaped);
MOZ_ASSERT(unescaped == original, "cannot recover original precursor origin after escape"); #endif break;
}
// For now, we won't track expanded or system principal precursors. We may // want to track expanded principal precursors in the future, but it's // unlikely we'll want to track system principal precursors. case eExpandedPrincipal: case eSystemPrincipal: break;
} if (!precursorOrigin.IsEmpty()) {
mutator.SetQuery(precursorOrigin);
}
}
NS_IMETHODIMP
NullPrincipal::SetDomain(nsIURI* aDomain) { // I think the right thing to do here is to just throw... Silently failing // seems counterproductive. return NS_ERROR_NOT_AVAILABLE;
}
bool NullPrincipal::MayLoadInternal(nsIURI* aURI) { // Also allow the load if we are the principal of the URI being checked.
nsCOMPtr<nsIPrincipal> blobPrincipal; if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(
aURI, getter_AddRefs(blobPrincipal))) {
MOZ_ASSERT(blobPrincipal); return SubsumesInternal(blobPrincipal,
BasePrincipal::ConsiderDocumentDomain);
}
returnfalse;
}
NS_IMETHODIMP
NullPrincipal::GetBaseDomain(nsACString& aBaseDomain) { // For a null principal, we use our unique uuid as the base domain. return mURI->GetPathQueryRef(aBaseDomain);
}
nsCOMPtr<nsIURI> precursorURI; if (NS_FAILED(NS_NewURI(getter_AddRefs(precursorURI), query))) {
MOZ_ASSERT_UNREACHABLE( "Failed to parse precursor from nullprincipal query"); return NS_OK;
}
// If our precursor is another null principal, re-construct it. This can // happen if a null principal without a precursor causes another principal to // be created. if (precursorURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME)) { #ifdef DEBUG
nsAutoCString precursorQuery;
precursorURI->GetQuery(precursorQuery);
MOZ_ASSERT(precursorQuery.IsEmpty(), "Null principal with nested precursors?"); #endif
*aPrincipal =
NullPrincipal::Create(OriginAttributesRef(), precursorURI).take(); return NS_OK;
}
RefPtr<BasePrincipal> contentPrincipal =
BasePrincipal::CreateContentPrincipal(precursorURI,
OriginAttributesRef()); // If `CreateContentPrincipal` failed, it will create a new NullPrincipal and // return that instead. We only want to return real content principals here. if (!contentPrincipal || !contentPrincipal->Is<ContentPrincipal>()) { return NS_OK;
}
contentPrincipal.forget(aPrincipal); return NS_OK;
}