зеркало из 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
|
||||
BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
|
||||
{
|
||||
if (Is<ExpandedPrincipal>()) {
|
||||
return As<ExpandedPrincipal>()->AddonAllowsLoad(aURI, aExplicit);
|
||||
}
|
||||
if (auto policy = AddonPolicy()) {
|
||||
return policy->CanAccessURI(aURI, aExplicit);
|
||||
}
|
||||
|
|
|
@ -180,6 +180,17 @@ ExpandedPrincipal::AddonHasPermission(const nsAtom* aPerm)
|
|||
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*
|
||||
ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
virtual bool AddonHasPermission(const nsAtom* aPerm) 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
|
||||
// URL. See BasePrincipal::PrincipalToInherit.
|
||||
nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "PerformanceResourceTiming.h"
|
||||
#include "mozilla/dom/PerformanceResourceTimingBinding.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -31,6 +32,11 @@ PerformanceResourceTiming::PerformanceResourceTiming(UniquePtr<PerformanceTiming
|
|||
, mPerformance(aPerformance)
|
||||
{
|
||||
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()
|
||||
|
@ -80,3 +86,35 @@ PerformanceResourceTiming::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSize
|
|||
? mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(aMallocSizeOf)
|
||||
: 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;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp RedirectStart() const {
|
||||
DOMHighResTimeStamp RedirectStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
// We have to check if all the redirect URIs had the same origin (since
|
||||
// there is no check in RedirectEndHighRes())
|
||||
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
||||
// there is no check in RedirectStartHighRes())
|
||||
return ReportRedirectForCaller(aSubjectPrincipal)
|
||||
? mTimingData->RedirectStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp RedirectEnd() const {
|
||||
DOMHighResTimeStamp RedirectEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
// We have to check if all the redirect URIs had the same origin (since
|
||||
// there is no check in RedirectEndHighRes())
|
||||
return mTimingData && mTimingData->ShouldReportCrossOriginRedirect()
|
||||
return ReportRedirectForCaller(aSubjectPrincipal)
|
||||
? mTimingData->RedirectEndHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp DomainLookupStart() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp DomainLookupStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->DomainLookupStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp DomainLookupEnd() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp DomainLookupEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->DomainLookupEndHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp ConnectStart() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp ConnectStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->ConnectStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp ConnectEnd() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp ConnectEnd(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->ConnectEndHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp RequestStart() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp RequestStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->RequestStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp ResponseStart() const {
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
DOMHighResTimeStamp ResponseStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->ResponseStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
@ -128,10 +128,10 @@ public:
|
|||
: 0;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp SecureConnectionStart() const
|
||||
DOMHighResTimeStamp SecureConnectionStart(Maybe<nsIPrincipal*>& aSubjectPrincipal) const
|
||||
{
|
||||
return mTimingData && mTimingData->TimingAllowed()
|
||||
? mTimingData->SecureConnectionStartHighRes(mPerformance)
|
||||
return TimingAllowedForCaller(aSubjectPrincipal)
|
||||
? mTimingData->SecureConnectionStartHighRes(mPerformance)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
@ -140,19 +140,25 @@ public:
|
|||
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
|
||||
|
@ -164,9 +170,21 @@ protected:
|
|||
size_t
|
||||
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;
|
||||
UniquePtr<PerformanceTimingData> mTimingData;
|
||||
RefPtr<Performance> mPerformance;
|
||||
|
||||
// The same initial requested URI as the `name` attribute.
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -54,17 +54,17 @@ public:
|
|||
|
||||
uint64_t TransferSize() const
|
||||
{
|
||||
return mTimingAllowed ? mTransferSize : 0;
|
||||
return mTransferSize;
|
||||
}
|
||||
|
||||
uint64_t EncodedBodySize() const
|
||||
{
|
||||
return mTimingAllowed ? mEncodedBodySize : 0;
|
||||
return mEncodedBodySize;
|
||||
}
|
||||
|
||||
uint64_t DecodedBodySize() const
|
||||
{
|
||||
return mTimingAllowed ? mDecodedBodySize : 0;
|
||||
return mDecodedBodySize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,20 +17,36 @@ interface PerformanceResourceTiming : PerformanceEntry
|
|||
readonly attribute DOMString nextHopProtocol;
|
||||
|
||||
readonly attribute DOMHighResTimeStamp workerStart;
|
||||
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp redirectStart;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp redirectEnd;
|
||||
|
||||
readonly attribute DOMHighResTimeStamp fetchStart;
|
||||
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp domainLookupStart;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp domainLookupEnd;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp connectStart;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp connectEnd;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp secureConnectionStart;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp requestStart;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMHighResTimeStamp responseStart;
|
||||
|
||||
readonly attribute DOMHighResTimeStamp responseEnd;
|
||||
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute unsigned long long transferSize;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute unsigned long long encodedBodySize;
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute unsigned long long decodedBodySize;
|
||||
|
||||
jsonifier;
|
||||
|
|
Загрузка…
Ссылка в новой задаче