зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1441336 - Use addon permissions for PerformanceTiming properties r=bz,kmag
We need to side-step existing cross-origin checks in Performance Timing code when the caller is a web extension content script that otherwise has permission to access the cross-origin resource. MozReview-Commit-ID: 8IgtqZgPWgY --HG-- extra : rebase_source : e8152c5d8ab32096d1ff7f97311c1b43b57c3694
This commit is contained in:
Родитель
d06d126e5d
Коммит
9e09943ad5
|
@ -464,6 +464,9 @@ BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain()
|
||||||
bool
|
bool
|
||||||
BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
|
BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
|
||||||
{
|
{
|
||||||
|
if (Is<ExpandedPrincipal>()) {
|
||||||
|
return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
|
||||||
|
}
|
||||||
if (auto policy = AddonPolicy()) {
|
if (auto policy = AddonPolicy()) {
|
||||||
return policy->CanAccessURI(aURI, aExplicit);
|
return policy->CanAccessURI(aURI, aExplicit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,17 @@ ExpandedPrincipal::AddonHasPermission(const nsAtom* aPerm)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ExpandedPrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
|
||||||
|
{
|
||||||
|
for (const auto& principal : mPrincipals) {
|
||||||
|
if (Cast(principal)->AddonAllowsLoad(aURI, aExplicit)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nsIPrincipal*
|
nsIPrincipal*
|
||||||
ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
|
ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
virtual bool AddonHasPermission(const nsAtom* aPerm) override;
|
virtual bool AddonHasPermission(const nsAtom* aPerm) override;
|
||||||
virtual nsresult GetScriptLocation(nsACString &aStr) override;
|
virtual nsresult GetScriptLocation(nsACString &aStr) override;
|
||||||
|
|
||||||
|
bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false);
|
||||||
|
|
||||||
// Returns the principal to inherit when this principal requests the given
|
// Returns the principal to inherit when this principal requests the given
|
||||||
// URL. See BasePrincipal::PrincipalToInherit.
|
// URL. See BasePrincipal::PrincipalToInherit.
|
||||||
nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
|
nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "PerformanceResourceTiming.h"
|
#include "PerformanceResourceTiming.h"
|
||||||
#include "mozilla/dom/PerformanceResourceTimingBinding.h"
|
#include "mozilla/dom/PerformanceResourceTimingBinding.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
@ -31,6 +32,11 @@ PerformanceResourceTiming::PerformanceResourceTiming(UniquePtr<PerformanceTiming
|
||||||
, mPerformance(aPerformance)
|
, mPerformance(aPerformance)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
MOZ_ASSERT(aPerformance, "Parent performance object should be provided");
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
// Used to check if an addon content script has access to this timing.
|
||||||
|
// We don't need it in workers, and ignore mOriginalURI if null.
|
||||||
|
NS_NewURI(getter_AddRefs(mOriginalURI), aName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceResourceTiming::~PerformanceResourceTiming()
|
PerformanceResourceTiming::~PerformanceResourceTiming()
|
||||||
|
@ -80,3 +86,35 @@ PerformanceResourceTiming::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSize
|
||||||
? mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(aMallocSizeOf)
|
? mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(aMallocSizeOf)
|
||||||
: 0);
|
: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PerformanceResourceTiming::TimingAllowedForCaller(Maybe<nsIPrincipal*>& aCaller) const
|
||||||
|
{
|
||||||
|
if (!mTimingData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTimingData->TimingAllowed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the addon has permission to access the cross-origin resource.
|
||||||
|
return mOriginalURI && aCaller.isSome() &&
|
||||||
|
BasePrincipal::Cast(aCaller.value())->AddonAllowsLoad(mOriginalURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PerformanceResourceTiming::ReportRedirectForCaller(Maybe<nsIPrincipal*>& aCaller) const
|
||||||
|
{
|
||||||
|
if (!mTimingData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTimingData->ShouldReportCrossOriginRedirect()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only report cross-origin redirect if the addon has <all_urls> permission.
|
||||||
|
return aCaller.isSome() &&
|
||||||
|
BasePrincipal::Cast(aCaller.value())->AddonHasPermission(nsGkAtoms::all_urlsPermission);
|
||||||
|
}
|
||||||
|
|
|
@ -70,54 +70,54 @@ public:
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RedirectStart() const {
|
DOMHighResTimeStamp RedirectStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
// We have to check if all the redirect URIs had the same origin (since
|
// We have to check if all the redirect URIs had the same origin (since
|
||||||
// there is no check in RedirectEndHighRes())
|
// there is no check in RedirectStartHighRes())
|
||||||
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
return ReportRedirectForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->RedirectStartHighRes(mPerformance)
|
? mTimingData->RedirectStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RedirectEnd() const {
|
DOMHighResTimeStamp RedirectEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
// We have to check if all the redirect URIs had the same origin (since
|
// We have to check if all the redirect URIs had the same origin (since
|
||||||
// there is no check in RedirectEndHighRes())
|
// there is no check in RedirectEndHighRes())
|
||||||
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
return ReportRedirectForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->RedirectEndHighRes(mPerformance)
|
? mTimingData->RedirectEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp DomainLookupStart() const {
|
DOMHighResTimeStamp DomainLookupStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->DomainLookupStartHighRes(mPerformance)
|
? mTimingData->DomainLookupStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp DomainLookupEnd() const {
|
DOMHighResTimeStamp DomainLookupEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->DomainLookupEndHighRes(mPerformance)
|
? mTimingData->DomainLookupEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ConnectStart() const {
|
DOMHighResTimeStamp ConnectStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->ConnectStartHighRes(mPerformance)
|
? mTimingData->ConnectStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ConnectEnd() const {
|
DOMHighResTimeStamp ConnectEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->ConnectEndHighRes(mPerformance)
|
? mTimingData->ConnectEndHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp RequestStart() const {
|
DOMHighResTimeStamp RequestStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->RequestStartHighRes(mPerformance)
|
? mTimingData->RequestStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp ResponseStart() const {
|
DOMHighResTimeStamp ResponseStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->ResponseStartHighRes(mPerformance)
|
? mTimingData->ResponseStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
@ -128,10 +128,10 @@ public:
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp SecureConnectionStart() const
|
DOMHighResTimeStamp SecureConnectionStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const
|
||||||
{
|
{
|
||||||
return mTimingData && mTimingData->TimingAllowed()
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
? mTimingData->SecureConnectionStartHighRes(mPerformance)
|
? mTimingData->SecureConnectionStartHighRes(mPerformance)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,19 +140,25 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TransferSize() const
|
uint64_t TransferSize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const
|
||||||
{
|
{
|
||||||
return mTimingData ? mTimingData->TransferSize() : 0;
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
|
? mTimingData->TransferSize()
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t EncodedBodySize() const
|
uint64_t EncodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const
|
||||||
{
|
{
|
||||||
return mTimingData ? mTimingData->EncodedBodySize() : 0;
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
|
? mTimingData->EncodedBodySize()
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DecodedBodySize() const
|
uint64_t DecodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const
|
||||||
{
|
{
|
||||||
return mTimingData ? mTimingData->DecodedBodySize() : 0;
|
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||||
|
? mTimingData->DecodedBodySize()
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -164,9 +170,21 @@ protected:
|
||||||
size_t
|
size_t
|
||||||
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||||
|
|
||||||
|
// Check if caller has access to cross-origin timings, either by the rules
|
||||||
|
// from the spec, or based on addon permissions.
|
||||||
|
bool
|
||||||
|
TimingAllowedForCaller(Maybe<nsIPrincipal*>& aCaller) const;
|
||||||
|
|
||||||
|
// Check if cross-origin redirects should be reported to the caller.
|
||||||
|
bool
|
||||||
|
ReportRedirectForCaller(Maybe<nsIPrincipal*>& aCaller) const;
|
||||||
|
|
||||||
nsString mInitiatorType;
|
nsString mInitiatorType;
|
||||||
UniquePtr<PerformanceTimingData> mTimingData;
|
UniquePtr<PerformanceTimingData> mTimingData;
|
||||||
RefPtr<Performance> mPerformance;
|
RefPtr<Performance> mPerformance;
|
||||||
|
|
||||||
|
// The same initial requested URI as the `name` attribute.
|
||||||
|
nsCOMPtr<nsIURI> mOriginalURI;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -54,17 +54,17 @@ public:
|
||||||
|
|
||||||
uint64_t TransferSize() const
|
uint64_t TransferSize() const
|
||||||
{
|
{
|
||||||
return mTimingAllowed ? mTransferSize : 0;
|
return mTransferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t EncodedBodySize() const
|
uint64_t EncodedBodySize() const
|
||||||
{
|
{
|
||||||
return mTimingAllowed ? mEncodedBodySize : 0;
|
return mEncodedBodySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DecodedBodySize() const
|
uint64_t DecodedBodySize() const
|
||||||
{
|
{
|
||||||
return mTimingAllowed ? mDecodedBodySize : 0;
|
return mDecodedBodySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,20 +17,36 @@ interface PerformanceResourceTiming : PerformanceEntry
|
||||||
readonly attribute DOMString nextHopProtocol;
|
readonly attribute DOMString nextHopProtocol;
|
||||||
|
|
||||||
readonly attribute DOMHighResTimeStamp workerStart;
|
readonly attribute DOMHighResTimeStamp workerStart;
|
||||||
|
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp redirectStart;
|
readonly attribute DOMHighResTimeStamp redirectStart;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp redirectEnd;
|
readonly attribute DOMHighResTimeStamp redirectEnd;
|
||||||
|
|
||||||
readonly attribute DOMHighResTimeStamp fetchStart;
|
readonly attribute DOMHighResTimeStamp fetchStart;
|
||||||
|
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp domainLookupStart;
|
readonly attribute DOMHighResTimeStamp domainLookupStart;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp domainLookupEnd;
|
readonly attribute DOMHighResTimeStamp domainLookupEnd;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp connectStart;
|
readonly attribute DOMHighResTimeStamp connectStart;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp connectEnd;
|
readonly attribute DOMHighResTimeStamp connectEnd;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp secureConnectionStart;
|
readonly attribute DOMHighResTimeStamp secureConnectionStart;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp requestStart;
|
readonly attribute DOMHighResTimeStamp requestStart;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute DOMHighResTimeStamp responseStart;
|
readonly attribute DOMHighResTimeStamp responseStart;
|
||||||
|
|
||||||
readonly attribute DOMHighResTimeStamp responseEnd;
|
readonly attribute DOMHighResTimeStamp responseEnd;
|
||||||
|
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute unsigned long long transferSize;
|
readonly attribute unsigned long long transferSize;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute unsigned long long encodedBodySize;
|
readonly attribute unsigned long long encodedBodySize;
|
||||||
|
[NeedsSubjectPrincipal]
|
||||||
readonly attribute unsigned long long decodedBodySize;
|
readonly attribute unsigned long long decodedBodySize;
|
||||||
|
|
||||||
jsonifier;
|
jsonifier;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче