Bug 1228139 - Remove nsIURIWithPrincipal - part 3 - main part, r=bz

nsIURIWithPrincipal is currently used to retrieve the nsIPrincipal from a
BlobURL object.  BlobURLProtocolHandler has a hashtable containing, for each
blobURL, a BlobImpl and its nsIPrincipal. This patch introduces
BlobURLProtocolHandler::GetBlobURLPrincipal() that retrieves the nsIPrincipal
from this hashtable.

This patch fixes also a bug in how the revocation of blobURLs is broadcasted to
other processes. This should be done immediately because each process creates
its own timer to revoke them after 5 seconds.

An important change is related to NS_SecurityCompareURIs() where, if 1 (or
both) of the 2 URIs to compare, is a revoked BlobURL, we will QI its URL to
nsIStandardURL and fail out at that point.
This commit is contained in:
Andrea Marchesini 2018-07-24 22:15:57 +02:00
Родитель 8c37ca27d9
Коммит f6768a8ff6
13 изменённых файлов: 190 добавлений и 268 удалений

Просмотреть файл

@ -14,12 +14,12 @@
#include "ExpandedPrincipal.h"
#include "nsNetUtil.h"
#include "nsIURIWithPrincipal.h"
#include "nsScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/ContentPrincipal.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/CSPDictionariesBinding.h"
#include "mozilla/dom/ToJSValue.h"
@ -411,15 +411,12 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI,
}
// 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 NullPrincipal::Create(aAttrs);
}
RefPtr<BasePrincipal> concrete = Cast(principal);
return concrete.forget();
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
getter_AddRefs(blobPrincipal))) {
MOZ_ASSERT(blobPrincipal);
RefPtr<BasePrincipal> principal = Cast(blobPrincipal);
return principal.forget();
}
// Mint a codebase principal.
@ -439,7 +436,7 @@ BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
"CreateCodebasePrincipal does not support NullPrincipal");
nsAutoCString originNoSuffix;
mozilla::OriginAttributes attrs;
OriginAttributes attrs;
if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
return nullptr;
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "ContentPrincipal.h"
#include "mozIThirdPartyUtil.h"
#include "nsContentUtils.h"
#include "nscore.h"
#include "nsScriptSecurityManager.h"
#include "nsString.h"
@ -15,7 +16,6 @@
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsIStandardURL.h"
#include "nsIURIWithPrincipal.h"
#include "nsJSPrincipals.h"
#include "nsIEffectiveTLDService.h"
#include "nsIClassInfoImpl.h"
@ -27,11 +27,11 @@
#include "nsNetCID.h"
#include "js/Wrapper.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/nsCSPContext.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Preferences.h"
#include "mozilla/HashFunctions.h"
@ -165,20 +165,11 @@ ContentPrincipal::GenerateOriginNoSuffixFromURI(nsIURI* aURI,
// This URL can be a blobURL. In this case, we should use the 'parent'
// principal instead.
nsCOMPtr<nsIURIWithPrincipal> uriWithPrincipal = do_QueryInterface(origin);
if (uriWithPrincipal) {
nsCOMPtr<nsIPrincipal> uriPrincipal;
rv = uriWithPrincipal->GetPrincipal(getter_AddRefs(uriPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
// If there is not a principal for this blobURL, it means that the blobURL
// has been revoked. Let's use a nullPrincipal instead.
if (!uriPrincipal) {
uriPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
MOZ_ASSERT(uriPrincipal);
}
return uriPrincipal->GetOriginNoSuffix(aOriginNoSuffix);
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(origin,
getter_AddRefs(blobPrincipal))) {
MOZ_ASSERT(blobPrincipal);
return blobPrincipal->GetOriginNoSuffix(aOriginNoSuffix);
}
// If we reached this branch, we can only create an origin if we have a
@ -277,18 +268,13 @@ ContentPrincipal::GetURI(nsIURI** aURI)
bool
ContentPrincipal::MayLoadInternal(nsIURI* aURI)
{
// See if aURI is something like a Blob URI that is actually associated with
// a principal.
nsCOMPtr<nsIURIWithPrincipal> uriWithPrin = do_QueryInterface(aURI);
if (uriWithPrin) {
nsCOMPtr<nsIPrincipal> uriPrin;
nsresult rv = uriWithPrin->GetPrincipal(getter_AddRefs(uriPrin));
if (NS_WARN_IF(NS_FAILED(rv)) || !uriPrin) {
// BlobURL has been revoked.
return false;
}
MOZ_ASSERT(aURI);
return nsIPrincipal::Subsumes(uriPrin);
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
getter_AddRefs(blobPrincipal))) {
MOZ_ASSERT(blobPrincipal);
return nsIPrincipal::Subsumes(blobPrincipal);
}
// If this principal is associated with an addon, check whether that addon

Просмотреть файл

@ -16,7 +16,6 @@
#include "NullPrincipal.h"
#include "NullPrincipalURI.h"
#include "nsMemory.h"
#include "nsIURIWithPrincipal.h"
#include "nsIClassInfoImpl.h"
#include "nsNetCID.h"
#include "nsError.h"
@ -185,14 +184,10 @@ bool
NullPrincipal::MayLoadInternal(nsIURI* aURI)
{
// Also allow the load if we are the principal of the URI being checked.
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (principal == this) {
return true;
}
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
getter_AddRefs(blobPrincipal))) {
return blobPrincipal == this;
}
return false;

Просмотреть файл

@ -6,11 +6,11 @@
#include "mozilla/OriginAttributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "nsIEffectiveTLDService.h"
#include "nsIURI.h"
#include "nsIURIWithPrincipal.h"
#include "nsURLHelper.h"
namespace mozilla {
@ -86,18 +86,15 @@ OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
NS_ENSURE_SUCCESS_VOID(rv);
if (scheme.EqualsLiteral("about")) {
mFirstPartyDomain.AssignLiteral(ABOUT_URI_FIRST_PARTY_DOMAIN);
} else if (scheme.EqualsLiteral("blob")) {
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
rv = uriPrinc->GetPrincipal(getter_AddRefs(principal));
NS_ENSURE_SUCCESS_VOID(rv);
return;
}
// a revoked blobURL doesn't expose a principal.
if (principal) {
mFirstPartyDomain = principal->OriginAttributesRef().mFirstPartyDomain;
}
}
nsCOMPtr<nsIPrincipal> blobPrincipal;
if (dom::BlobURLProtocolHandler::GetBlobURLPrincipal(aURI,
getter_AddRefs(blobPrincipal))) {
MOZ_ASSERT(blobPrincipal);
mFirstPartyDomain = blobPrincipal->OriginAttributesRef().mFirstPartyDomain;
return;
}
}

Просмотреть файл

@ -23,7 +23,6 @@ NS_IMPL_ADDREF_INHERITED(BlobURL, mozilla::net::nsSimpleURI)
NS_IMPL_RELEASE_INHERITED(BlobURL, mozilla::net::nsSimpleURI)
NS_INTERFACE_MAP_BEGIN(BlobURL)
NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
if (aIID.Equals(kHOSTOBJECTURICID))
foundInterface = static_cast<nsIURI*>(this);
else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
@ -36,30 +35,9 @@ NS_INTERFACE_MAP_BEGIN(BlobURL)
else
NS_INTERFACE_MAP_END_INHERITING(mozilla::net::nsSimpleURI)
// nsIURIWithPrincipal methods:
NS_IMETHODIMP
BlobURL::GetPrincipal(nsIPrincipal** aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIPrincipal> principal = mPrincipal.get();
principal.forget(aPrincipal);
return NS_OK;
}
NS_IMETHODIMP
BlobURL::GetPrincipalUri(nsIURI** aUri)
{
if (mPrincipal) {
mPrincipal->GetURI(aUri);
}
else {
*aUri = nullptr;
}
return NS_OK;
}
BlobURL::BlobURL()
: mRevoked(false)
{}
// nsISerializable methods:
@ -76,13 +54,10 @@ BlobURL::ReadPrivate(nsIObjectInputStream *aStream)
nsresult rv = mozilla::net::nsSimpleURI::ReadPrivate(aStream);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> supports;
rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
rv = aStream->ReadBoolean(&mRevoked);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(supports, &rv);
mPrincipal = new nsMainThreadPtrHolder<nsIPrincipal>("nsIPrincipal", principal, false);
return rv;
return NS_OK;
}
NS_IMETHODIMP
@ -91,10 +66,10 @@ BlobURL::Write(nsIObjectOutputStream* aStream)
nsresult rv = mozilla::net::nsSimpleURI::Write(aStream);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal = mPrincipal.get();
return NS_WriteOptionalCompoundObject(aStream, principal,
NS_GET_IID(nsIPrincipal),
true);
rv = aStream->WriteBoolean(mRevoked);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// nsIIPCSerializableURI methods:
@ -109,18 +84,7 @@ BlobURL::Serialize(mozilla::ipc::URIParams& aParams)
mozilla::net::nsSimpleURI::Serialize(simpleParams);
hostParams.simpleParams() = simpleParams;
nsCOMPtr<nsIPrincipal> principal = mPrincipal.get();
if (principal) {
PrincipalInfo info;
nsresult rv = PrincipalToPrincipalInfo(principal, &info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
hostParams.principal() = info;
} else {
hostParams.principal() = mozilla::void_t();
}
hostParams.revoked() = mRevoked;
aParams = hostParams;
}
@ -141,16 +105,7 @@ BlobURL::Deserialize(const mozilla::ipc::URIParams& aParams)
return false;
}
if (hostParams.principal().type() == OptionalPrincipalInfo::Tvoid_t) {
return true;
}
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(hostParams.principal().get_PrincipalInfo());
if (!principal) {
return false;
}
mPrincipal = new nsMainThreadPtrHolder<nsIPrincipal>("nsIPrincipal", principal, false);
mRevoked = hostParams.revoked();
return true;
}
@ -158,8 +113,7 @@ nsresult
BlobURL::SetScheme(const nsACString& aScheme)
{
// Disallow setting the scheme, since that could cause us to be associated
// with a different protocol handler that doesn't expect us to be carrying
// around a principal with nsIURIWithPrincipal.
// with a different protocol handler.
return NS_ERROR_FAILURE;
}
@ -181,8 +135,7 @@ BlobURL::CloneInternal(mozilla::net::nsSimpleURI::RefHandlingEnum aRefHandlingMo
#endif
BlobURL* u = static_cast<BlobURL*>(simpleClone.get());
u->mPrincipal = mPrincipal;
u->mRevoked = mRevoked;
simpleClone.forget(aClone);
return NS_OK;
@ -209,15 +162,7 @@ BlobURL::EqualsInternal(nsIURI* aOther,
*aResult = mozilla::net::nsSimpleURI::EqualsInternal(otherUri,
aRefHandlingMode);
#ifdef DEBUG
// mPrincipal can be null if the blobURL has been revoked.
if (*aResult && mPrincipal && otherUri->mPrincipal) {
bool equal = false;
nsresult rv = mPrincipal->Equals(otherUri->mPrincipal, &equal);
MOZ_ASSERT(NS_SUCCEEDED(rv) && equal);
}
#endif
// We don't want to compare the revoked flag.
return NS_OK;
}
@ -225,7 +170,6 @@ BlobURL::EqualsInternal(nsIURI* aOther,
NS_IMPL_NSIURIMUTATOR_ISUPPORTS(BlobURL::Mutator,
nsIURISetters,
nsIURIMutator,
nsIPrincipalURIMutator,
nsISerializable)
NS_IMETHODIMP

Просмотреть файл

@ -8,42 +8,25 @@
#define mozilla_dom_BlobURL_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/File.h"
#include "nsCOMPtr.h"
#include "nsIClassInfo.h"
#include "nsIPrincipal.h"
#include "nsISerializable.h"
#include "nsIURIWithPrincipal.h"
#include "nsSimpleURI.h"
#include "nsIIPCSerializableURI.h"
#include "nsProxyRelease.h"
#include "prtime.h"
namespace mozilla {
namespace dom {
/**
* These URIs refer to host objects with "blob" scheme. The underlying object is
* a BlobImpl.
* These URIs refer to host objects with "blob" scheme.
*/
class BlobURL final
: public mozilla::net::nsSimpleURI
, public nsIURIWithPrincipal
class BlobURL final : public mozilla::net::nsSimpleURI
{
private:
explicit BlobURL(nsIPrincipal* aPrincipal)
: mozilla::net::nsSimpleURI()
{
mPrincipal = new nsMainThreadPtrHolder<nsIPrincipal>("nsIPrincipal", aPrincipal, false);
}
// For use only from deserialization
explicit BlobURL()
: mozilla::net::nsSimpleURI()
{}
BlobURL();
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIURIWITHPRINCIPAL
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
NS_DECL_NSIIPCSERIALIZABLEURI
@ -65,9 +48,13 @@ public:
return url;
}
NS_IMETHOD Mutate(nsIURIMutator * *_retval) override;
bool
Revoked() const
{
return mRevoked;
}
nsMainThreadPtrHandle<nsIPrincipal> mPrincipal;
NS_IMETHOD Mutate(nsIURIMutator * *_retval) override;
private:
virtual ~BlobURL() = default;
@ -80,7 +67,6 @@ public:
class Mutator final
: public nsIURIMutator
, public BaseURIMutator<BlobURL>
, public nsIPrincipalURIMutator
, public nsISerializable
{
NS_DECL_ISUPPORTS
@ -90,24 +76,13 @@ public:
NS_IMETHOD
Write(nsIObjectOutputStream *aOutputStream) override
{
return NS_ERROR_NOT_IMPLEMENTED;
return NS_ERROR_NOT_IMPLEMENTED;
}
MOZ_MUST_USE NS_IMETHOD
Read(nsIObjectInputStream* aStream) override
{
return InitFromInputStream(aStream);
}
MOZ_MUST_USE NS_IMETHOD
SetPrincipal(nsIPrincipal *aPrincipal) override
{
if (!mURI) {
return NS_ERROR_NULL_POINTER;
}
MOZ_ASSERT(NS_IsMainThread());
mURI->mPrincipal = new nsMainThreadPtrHolder<nsIPrincipal>("nsIPrincipal", aPrincipal, false);
return NS_OK;
return InitFromInputStream(aStream);
}
Mutator() = default;
@ -119,6 +94,8 @@ public:
};
friend BaseURIMutator<BlobURL>;
bool mRevoked;
};
#define NS_HOSTOBJECTURI_CID \

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BlobURLChannel.h"
#include "mozilla/dom/BlobImpl.h"
using namespace mozilla::dom;

Просмотреть файл

@ -6,8 +6,8 @@
#include "BlobURLProtocolHandler.h"
#include "BlobURLChannel.h"
#include "mozilla/dom/BlobURL.h"
#include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
@ -18,6 +18,7 @@
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Preferences.h"
#include "mozilla/SystemGroup.h"
#include "nsClassHashtable.h"
@ -52,14 +53,18 @@ struct DataInfo
, mBlobImpl(aBlobImpl)
, mPrincipal(aPrincipal)
, mRevoked(false)
{}
{
MOZ_ASSERT(aPrincipal);
}
DataInfo(MediaSource* aMediaSource, nsIPrincipal* aPrincipal)
: mObjectType(eMediaSource)
, mMediaSource(aMediaSource)
, mPrincipal(aPrincipal)
, mRevoked(false)
{}
{
MOZ_ASSERT(aPrincipal);
}
ObjectType mObjectType;
@ -136,6 +141,7 @@ BroadcastBlobURLRegistration(const nsACString& aURI,
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobImpl);
MOZ_ASSERT(aPrincipal);
if (XRE_IsParentProcess()) {
dom::ContentParent::BroadcastBlobURLRegistration(aURI, aBlobImpl,
@ -406,12 +412,11 @@ public:
NS_DECL_ISUPPORTS_INHERITED
static void
Create(const nsACString& aURI, bool aBroadcastToOtherProcesses)
Create(const nsACString& aURI)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<ReleasingTimerHolder> holder =
new ReleasingTimerHolder(aURI, aBroadcastToOtherProcesses);
RefPtr<ReleasingTimerHolder> holder = new ReleasingTimerHolder(aURI);
auto raii = MakeScopeExit([holder] {
holder->CancelTimerAndRevokeURI();
@ -420,7 +425,7 @@ public:
nsresult rv =
SystemGroup::EventTargetFor(TaskCategory::Other)->Dispatch(holder.forget());
NS_ENSURE_SUCCESS_VOID(rv);
raii.release();
}
@ -456,7 +461,7 @@ public:
NS_IMETHOD
Notify(nsITimer* aTimer) override
{
RevokeURI(mBroadcastToOtherProcesses);
RevokeURI();
return NS_OK;
}
@ -488,17 +493,16 @@ public:
}
private:
ReleasingTimerHolder(const nsACString& aURI, bool aBroadcastToOtherProcesses)
explicit ReleasingTimerHolder(const nsACString& aURI)
: Runnable("ReleasingTimerHolder")
, mURI(aURI)
, mBroadcastToOtherProcesses(aBroadcastToOtherProcesses)
{}
~ReleasingTimerHolder()
{}
void
RevokeURI(bool aBroadcastToOtherProcesses)
RevokeURI()
{
// Remove the shutting down blocker
nsCOMPtr<nsIAsyncShutdownClient> phase = GetShutdownPhase();
@ -506,11 +510,6 @@ private:
phase->RemoveBlocker(this);
}
// If we have to broadcast the unregistration, let's do it now.
if (aBroadcastToOtherProcesses) {
BroadcastBlobURLUnregistration(mURI);
}
DataInfo* info = GetDataInfo(mURI, true /* We care about revoked dataInfo */);
if (!info) {
// Already gone!
@ -534,7 +533,7 @@ private:
mTimer = nullptr;
}
RevokeURI(false /* aBroadcastToOtherProcesses */);
RevokeURI();
}
static nsCOMPtr<nsIAsyncShutdownClient>
@ -551,8 +550,6 @@ private:
}
nsCString mURI;
bool mBroadcastToOtherProcesses;
nsCOMPtr<nsITimer> mTimer;
};
@ -598,6 +595,9 @@ BlobURLProtocolHandler::AddDataEntry(BlobImpl* aBlobImpl,
nsIPrincipal* aPrincipal,
nsACString& aUri)
{
MOZ_ASSERT(aBlobImpl);
MOZ_ASSERT(aPrincipal);
Init();
nsresult rv = GenerateURIString(aPrincipal, aUri);
@ -615,6 +615,9 @@ BlobURLProtocolHandler::AddDataEntry(MediaSource* aMediaSource,
nsIPrincipal* aPrincipal,
nsACString& aUri)
{
MOZ_ASSERT(aMediaSource);
MOZ_ASSERT(aPrincipal);
Init();
nsresult rv = GenerateURIString(aPrincipal, aUri);
@ -631,6 +634,9 @@ BlobURLProtocolHandler::AddDataEntry(const nsACString& aURI,
nsIPrincipal* aPrincipal,
BlobImpl* aBlobImpl)
{
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aBlobImpl);
return AddDataEntryInternal(aURI, aBlobImpl, aPrincipal);
}
@ -683,12 +689,14 @@ BlobURLProtocolHandler::RemoveDataEntry(const nsACString& aUri,
info->mRevoked = true;
if (aBroadcastToOtherProcesses && info->mObjectType == DataInfo::eBlobImpl) {
BroadcastBlobURLUnregistration(nsCString(aUri));
}
// The timer will take care of removing the entry for real after
// RELEASING_TIMER milliseconds. In the meantime, the DataInfo, marked as
// revoked, will not be exposed.
ReleasingTimerHolder::Create(aUri,
aBroadcastToOtherProcesses &&
info->mObjectType == DataInfo::eBlobImpl);
ReleasingTimerHolder::Create(aUri);
}
/* static */ void
@ -817,27 +825,28 @@ BlobURLProtocolHandler::NewURI(const nsACString& aSpec,
nsIURI **aResult)
{
*aResult = nullptr;
nsresult rv;
DataInfo* info = GetDataInfo(aSpec);
nsCOMPtr<nsIPrincipal> principal;
RefPtr<BlobImpl> blob;
if (info && info->mObjectType == DataInfo::eBlobImpl) {
MOZ_ASSERT(info->mBlobImpl);
principal = info->mPrincipal;
blob = info->mBlobImpl;
}
nsCOMPtr<nsIURI> uri;
rv = NS_MutateURI(new BlobURL::Mutator())
.SetSpec(aSpec)
.Apply(NS_MutatorMethod(&nsIPrincipalURIMutator::SetPrincipal, principal))
.Finalize(uri);
nsresult rv = NS_MutateURI(new BlobURL::Mutator())
.SetSpec(aSpec)
.Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
uri.forget(aResult);
bool revoked = true;
DataInfo* info = GetDataInfo(aSpec);
if (info && info->mObjectType == DataInfo::eBlobImpl) {
revoked = info->mRevoked;
}
RefPtr<BlobURL> blobURL;
rv = uri->QueryInterface(kHOSTOBJECTURICID,
getter_AddRefs(blobURL));
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(blobURL);
blobURL->mRevoked = revoked;
uri.forget(aResult);
return NS_OK;
}
@ -853,27 +862,22 @@ BlobURLProtocolHandler::NewChannel2(nsIURI* aURI,
channel.forget(aResult);
});
RefPtr<BlobURL> blobURL;
nsresult rv = aURI->QueryInterface(kHOSTOBJECTURICID,
getter_AddRefs(blobURL));
if (NS_FAILED(rv) || !blobURL) {
return NS_OK;
}
DataInfo* info = GetDataInfoFromURI(aURI, true /*aAlsoIfRevoked */);
if (!info || info->mObjectType != DataInfo::eBlobImpl || !info->mBlobImpl) {
return NS_OK;
}
RefPtr<BlobImpl> blobImpl = info->mBlobImpl;
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (!uriPrinc) {
if (blobURL->Revoked()) {
return NS_OK;
}
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = uriPrinc->GetPrincipal(getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, NS_OK);
if (!principal) {
return NS_OK;
}
MOZ_ASSERT(info->mPrincipal == principal);
// We want to be sure that we stop the creation of the channel if the blob URL
// is copy-and-pasted on a different context (ex. private browsing or
// containers).
@ -886,13 +890,13 @@ BlobURLProtocolHandler::NewChannel2(nsIURI* aURI,
if (aLoadInfo &&
!nsContentUtils::IsSystemPrincipal(aLoadInfo->LoadingPrincipal()) &&
!ChromeUtils::IsOriginAttributesEqualIgnoringFPD(aLoadInfo->GetOriginAttributes(),
BasePrincipal::Cast(principal)->OriginAttributesRef())) {
BasePrincipal::Cast(info->mPrincipal)->OriginAttributesRef())) {
return NS_OK;
}
raii.release();
channel->Initialize(blobImpl);
channel->Initialize(info->mBlobImpl);
channel.forget(aResult);
return NS_OK;
}
@ -919,6 +923,38 @@ BlobURLProtocolHandler::GetScheme(nsACString &result)
return NS_OK;
}
/* static */ bool
BlobURLProtocolHandler::GetBlobURLPrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
MOZ_ASSERT(aURI);
MOZ_ASSERT(aPrincipal);
RefPtr<BlobURL> blobURL;
nsresult rv = aURI->QueryInterface(kHOSTOBJECTURICID,
getter_AddRefs(blobURL));
if (NS_FAILED(rv) || !blobURL) {
return false;
}
DataInfo* info = GetDataInfoFromURI(aURI, true /*aAlsoIfRevoked */);
if (!info || info->mObjectType != DataInfo::eBlobImpl || !info->mBlobImpl) {
return false;
}
nsCOMPtr<nsIPrincipal> principal;
if (blobURL->Revoked()) {
principal =
NullPrincipal::Create(BasePrincipal::Cast(info->mPrincipal)->OriginAttributesRef());
} else {
principal = info->mPrincipal;
}
principal.forget(aPrincipal);
return true;
}
} // dom namespace
} // mozilla namespace

Просмотреть файл

@ -53,6 +53,9 @@ public:
nsIPrincipal* aPrincipal,
mozilla::dom::BlobImpl* aBlobImpl);
// This method revokes a blobURL. Because some operations could still be in
// progress, the revoking consists in marking the blobURL as revoked and in
// removing it after RELEASING_TIMER milliseconds.
static void RemoveDataEntry(const nsACString& aUri,
bool aBroadcastToOTherProcesses = true);
@ -67,6 +70,22 @@ public:
GetAllBlobURLEntries(nsTArray<mozilla::dom::BlobURLRegistrationData>& aRegistrations,
mozilla::dom::ContentParent* aCP);
// This method returns false if aURI is not a known BlobURL. Otherwise it
// returns true.
//
// When true is returned, the aPrincipal out param is meaningful. It gets
// set to the principal that a channel loaded from the blob would get if
// the blob is not already revoked and to a NullPrincipal if the blob is
// revoked.
//
// This means that for a revoked blob URL this method may either return
// false or return true and hand out a NullPrincipal in aPrincipal,
// depending on whether the "remove it from the hashtable" timer has
// fired. See RemoveDataEntry().
static bool
GetBlobURLPrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal);
private:
~BlobURLProtocolHandler();

Просмотреть файл

@ -71,7 +71,7 @@ struct NullPrincipalURIParams
struct HostObjectURIParams
{
SimpleURIParams simpleParams;
OptionalPrincipalInfo principal;
bool revoked;
};
union URIParams

Просмотреть файл

@ -126,7 +126,6 @@ XPIDL_SOURCES += [
'nsIURI.idl',
'nsIURIClassifier.idl',
'nsIURIMutator.idl',
'nsIURIWithPrincipal.idl',
'nsIURL.idl',
'nsIURLParser.idl',
'nsPILoadGroupInternal.idl',

Просмотреть файл

@ -1,39 +0,0 @@
/* 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 "nsISupports.idl"
interface nsIPrincipal;
interface nsIURI;
interface nsIURIMutator;
/**
* nsIURIWithPrincipal is implemented by URIs which are associated with a
* specific principal.
*/
[scriptable, builtinclass, uuid(626a5c0c-bfd8-4531-8b47-a8451b0daa33)]
interface nsIURIWithPrincipal : nsISupports
{
/**
* The principal associated with the resource returned when loading this
* uri.
*/
readonly attribute nsIPrincipal principal;
/**
* The uri for the principal.
*/
readonly attribute nsIURI principalUri;
};
[builtinclass, uuid(fa138a89-c76e-4b7f-95ec-c7b56ded5ef5)]
interface nsIPrincipalURIMutator : nsISupports
{
/**
* Associates a principal to the mutated URI.
* Would normally return nsIURIMutator, but since it only gets called
* from C++, there is no need for that.
*/
[must_use, noscript] void setPrincipal(in nsIPrincipal aPrincipal);
};

Просмотреть файл

@ -61,7 +61,6 @@
#include "nsStringStream.h"
#include "nsISyncStreamListener.h"
#include "nsITransport.h"
#include "nsIURIWithPrincipal.h"
#include "nsIURLParser.h"
#include "nsIUUIDGenerator.h"
#include "nsIViewSourceChannel.h"
@ -69,6 +68,7 @@
#include "plstr.h"
#include "nsINestedURI.h"
#include "mozilla/dom/nsCSPUtils.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/net/HttpBaseChannel.h"
#include "nsIScriptError.h"
#include "nsISiteSecurityService.h"
@ -84,6 +84,7 @@
using namespace mozilla;
using namespace mozilla::net;
using mozilla::dom::BlobURLProtocolHandler;
using mozilla::dom::ClientInfo;
using mozilla::dom::PerformanceStorage;
using mozilla::dom::ServiceWorkerDescriptor;
@ -2481,15 +2482,24 @@ NS_SecurityCompareURIs(nsIURI *aSourceURI,
nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
nsCOMPtr<nsIURI> targetBaseURI = NS_GetInnermostURI(aTargetURI);
// If either uri is an nsIURIWithPrincipal
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(sourceBaseURI);
if (uriPrinc) {
uriPrinc->GetPrincipalUri(getter_AddRefs(sourceBaseURI));
nsCOMPtr<nsIPrincipal> sourceBlobPrincipal;
if (BlobURLProtocolHandler::GetBlobURLPrincipal(sourceBaseURI,
getter_AddRefs(sourceBlobPrincipal))) {
nsCOMPtr<nsIURI> sourceBlobOwnerURI;
nsresult rv = sourceBlobPrincipal->GetURI(getter_AddRefs(sourceBlobOwnerURI));
if (NS_SUCCEEDED(rv)) {
sourceBaseURI = sourceBlobOwnerURI;
}
}
uriPrinc = do_QueryInterface(targetBaseURI);
if (uriPrinc) {
uriPrinc->GetPrincipalUri(getter_AddRefs(targetBaseURI));
nsCOMPtr<nsIPrincipal> targetBlobPrincipal;
if (BlobURLProtocolHandler::GetBlobURLPrincipal(targetBaseURI,
getter_AddRefs(targetBlobPrincipal))) {
nsCOMPtr<nsIURI> targetBlobOwnerURI;
nsresult rv = targetBlobPrincipal->GetURI(getter_AddRefs(targetBlobOwnerURI));
if (NS_SUCCEEDED(rv)) {
targetBaseURI = targetBlobOwnerURI;
}
}
if (!sourceBaseURI || !targetBaseURI)