Bug 1800443 - Support the contentType attribute of the Resource Timing API, and have it and the encoded/decoded body size use the CORS check rather than TAO; r=sefeng,valentin,webidl,necko-reviewers,saschanaz,emilio
Differential Revision: https://phabricator.services.mozilla.com/D208965
This commit is contained in:
@@ -85,6 +85,8 @@ size_t PerformanceResourceTiming::SizeOfExcludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||
return PerformanceEntry::SizeOfExcludingThis(aMallocSizeOf) +
|
||||
mInitiatorType.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
|
||||
mTimingData->ContentType().SizeOfExcludingThisIfUnshared(
|
||||
aMallocSizeOf) +
|
||||
mTimingData->NextHopProtocol().SizeOfExcludingThisIfUnshared(
|
||||
aMallocSizeOf);
|
||||
}
|
||||
@@ -109,6 +111,19 @@ void PerformanceResourceTiming::GetServerTiming(
|
||||
}
|
||||
}
|
||||
|
||||
nsITimedChannel::BodyInfoAccess
|
||||
PerformanceResourceTiming::BodyInfoAccessAllowedForCaller(
|
||||
nsIPrincipal& aCaller) const {
|
||||
// If the addon has permission to access the cross-origin resource,
|
||||
// allow it full access to the bodyInfo.
|
||||
if (mOriginalURI &&
|
||||
BasePrincipal::Cast(&aCaller)->AddonAllowsLoad(mOriginalURI)) {
|
||||
return nsITimedChannel::BodyInfoAccess::ALLOW_ALL;
|
||||
}
|
||||
|
||||
return mTimingData->BodyInfoAccessAllowed();
|
||||
}
|
||||
|
||||
bool PerformanceResourceTiming::TimingAllowedForCaller(
|
||||
nsIPrincipal& aCaller) const {
|
||||
if (mTimingData->TimingAllowed()) {
|
||||
|
||||
@@ -33,6 +33,16 @@ enum class RenderBlockingStatusType : uint8_t;
|
||||
return allowed ? mTimingData->name() : 0; \
|
||||
}
|
||||
|
||||
#define IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(name) \
|
||||
uint64_t name(nsIPrincipal& aSubjectPrincipal) const { \
|
||||
bool allowed = BodyInfoAccessAllowedForCaller(aSubjectPrincipal); \
|
||||
if (!allowed && mTimingData->RedirectCountReal()) { \
|
||||
ReportRedirectForCaller(aSubjectPrincipal, true); \
|
||||
return 0; \
|
||||
} \
|
||||
return allowed ? mTimingData->name() : 0; \
|
||||
}
|
||||
|
||||
// http://www.w3.org/TR/resource-timing/#performanceresourcetiming
|
||||
class PerformanceResourceTiming : public PerformanceEntry {
|
||||
public:
|
||||
@@ -134,11 +144,38 @@ class PerformanceResourceTiming : public PerformanceEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(TransferSize)
|
||||
IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(EncodedBodySize);
|
||||
IMPL_RESOURCE_TIMING_CORS_PROTECTED_SIZE_PROP(DecodedBodySize);
|
||||
|
||||
IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(EncodedBodySize)
|
||||
uint64_t TransferSize(nsIPrincipal& aSubjectPrincipal) const {
|
||||
const bool allowed =
|
||||
!mTimingData->RedirectCountReal()
|
||||
? TimingAllowedForCaller(aSubjectPrincipal)
|
||||
: ReportRedirectForCaller(aSubjectPrincipal, false);
|
||||
if (!allowed) {
|
||||
return 0;
|
||||
}
|
||||
// Resource is cached.
|
||||
if (!mTimingData->TransferSize()) {
|
||||
return 0;
|
||||
}
|
||||
auto encodedBodySize = EncodedBodySize(aSubjectPrincipal);
|
||||
// The constant number added to transferSize replaces exposing the
|
||||
// total byte size of the HTTP headers, as that may expose the
|
||||
// presence of certain cookies.
|
||||
// https://github.com/w3c/resource-timing/issues/238
|
||||
return encodedBodySize + 300;
|
||||
}
|
||||
|
||||
IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(DecodedBodySize)
|
||||
void GetContentType(nsAString& aContentType,
|
||||
nsIPrincipal& aSubjectPrincipal) const {
|
||||
if (BodyInfoAccessAllowedForCaller(aSubjectPrincipal) ==
|
||||
nsITimedChannel::BodyInfoAccess::ALLOW_ALL) {
|
||||
aContentType = mTimingData->ContentType();
|
||||
} else if (mTimingData->RedirectCountReal()) {
|
||||
ReportRedirectForCaller(aSubjectPrincipal, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval,
|
||||
nsIPrincipal& aSubjectPrincipal);
|
||||
@@ -152,6 +189,10 @@ class PerformanceResourceTiming : public PerformanceEntry {
|
||||
size_t SizeOfExcludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
// Check if caller has access to the bodyInfo of the request, per Fetch spec.
|
||||
nsITimedChannel::BodyInfoAccess BodyInfoAccessAllowedForCaller(
|
||||
nsIPrincipal& aCaller) const;
|
||||
|
||||
// Check if caller has access to cross-origin timings, either by the rules
|
||||
// from the spec, or based on addon permissions.
|
||||
bool TimingAllowedForCaller(nsIPrincipal& aCaller) const;
|
||||
|
||||
@@ -239,9 +239,11 @@ PerformanceTimingData::PerformanceTimingData(
|
||||
mRenderBlockingStatus(aIPCData.renderBlocking()
|
||||
? RenderBlockingStatusType::Blocking
|
||||
: RenderBlockingStatusType::Non_blocking),
|
||||
mContentType(aIPCData.contentType()),
|
||||
mAllRedirectsSameOrigin(aIPCData.allRedirectsSameOrigin()),
|
||||
mAllRedirectsPassTAO(aIPCData.allRedirectsPassTAO()),
|
||||
mSecureConnection(aIPCData.secureConnection()),
|
||||
mBodyInfoAccessAllowed(aIPCData.bodyInfoAccessAllowed()),
|
||||
mTimingAllowed(aIPCData.timingAllowed()),
|
||||
mInitialized(aIPCData.initialized()) {
|
||||
for (const auto& serverTimingData : aIPCData.serverTiming()) {
|
||||
@@ -273,8 +275,9 @@ IPCPerformanceTimingData PerformanceTimingData::ToIPC() {
|
||||
mCacheReadStart, mResponseEnd, mCacheReadEnd, mWorkerStart,
|
||||
mWorkerRequestStart, mWorkerResponseEnd, mZeroTime, mFetchStart,
|
||||
mEncodedBodySize, mTransferSize, mDecodedBodySize, mRedirectCount,
|
||||
renderBlocking, mAllRedirectsSameOrigin, mAllRedirectsPassTAO,
|
||||
mSecureConnection, mTimingAllowed, mInitialized);
|
||||
renderBlocking, mContentType, mAllRedirectsSameOrigin,
|
||||
mAllRedirectsPassTAO, mSecureConnection, mBodyInfoAccessAllowed,
|
||||
mTimingAllowed, mInitialized);
|
||||
}
|
||||
|
||||
void PerformanceTimingData::SetPropertiesFromHttpChannel(
|
||||
@@ -292,7 +295,13 @@ void PerformanceTimingData::SetPropertiesFromHttpChannel(
|
||||
mDecodedBodySize = mEncodedBodySize;
|
||||
}
|
||||
|
||||
mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel);
|
||||
nsAutoCString contentType;
|
||||
Unused << aHttpChannel->GetContentType(contentType);
|
||||
CopyUTF8toUTF16(contentType, mContentType);
|
||||
|
||||
mBodyInfoAccessAllowed =
|
||||
CheckBodyInfoAccessAllowedForOrigin(aHttpChannel, aChannel);
|
||||
mTimingAllowed = CheckTimingAllowedForOrigin(aHttpChannel, aChannel);
|
||||
aChannel->GetAllRedirectsPassTimingAllowCheck(&mAllRedirectsPassTAO);
|
||||
|
||||
aChannel->GetNativeServerTiming(mServerTiming);
|
||||
@@ -328,13 +337,46 @@ DOMTimeMilliSec PerformanceTiming::FetchStart() {
|
||||
return static_cast<int64_t>(mTimingData->FetchStartHighRes(mPerformance));
|
||||
}
|
||||
|
||||
bool PerformanceTimingData::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||
nsITimedChannel* aChannel) {
|
||||
nsITimedChannel::BodyInfoAccess
|
||||
PerformanceTimingData::CheckBodyInfoAccessAllowedForOrigin(
|
||||
nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel) {
|
||||
// Check if the resource is either same origin as the page that started
|
||||
// the load, or if the response contains an Access-Control-Allow-Origin
|
||||
// header with the domain of the page that started the load.
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
if (!IsInitialized()) {
|
||||
return nsITimedChannel::BodyInfoAccess::DISALLOWED;
|
||||
}
|
||||
|
||||
// Check that the current document passes the check.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aResourceChannel->LoadInfo();
|
||||
|
||||
// TYPE_DOCUMENT loads have no loadingPrincipal.
|
||||
if (loadInfo->GetExternalContentPolicyType() ==
|
||||
ExtContentPolicy::TYPE_DOCUMENT) {
|
||||
return nsITimedChannel::BodyInfoAccess::ALLOW_ALL;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal();
|
||||
if (!principal) {
|
||||
return nsITimedChannel::BodyInfoAccess::DISALLOWED;
|
||||
}
|
||||
return aChannel->BodyInfoAccessAllowedCheck(principal);
|
||||
}
|
||||
|
||||
bool PerformanceTimingData::CheckTimingAllowedForOrigin(
|
||||
nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel) {
|
||||
// Check if the resource is either same origin as the page that started
|
||||
// the load, or if the response contains the proper Timing-Allow-Origin
|
||||
// header with the domain of the page that started the load.
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
if (!IsInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the current document passes the ckeck.
|
||||
// Check that the current document passes the check.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aResourceChannel->LoadInfo();
|
||||
|
||||
// TYPE_DOCUMENT loads have no loadingPrincipal.
|
||||
@@ -344,11 +386,7 @@ bool PerformanceTimingData::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal();
|
||||
|
||||
// Check if the resource is either same origin as the page that started
|
||||
// the load, or if the response contains the proper Timing-Allow-Origin
|
||||
// header with the domain of the page that started the load.
|
||||
return aChannel->TimingAllowCheck(principal);
|
||||
return principal && aChannel->TimingAllowCheck(principal);
|
||||
}
|
||||
|
||||
uint8_t PerformanceTimingData::GetRedirectCount() const {
|
||||
|
||||
@@ -63,6 +63,8 @@ class PerformanceTimingData final {
|
||||
|
||||
uint64_t DecodedBodySize() const { return mDecodedBodySize; }
|
||||
|
||||
const nsString& ContentType() const { return mContentType; }
|
||||
|
||||
/**
|
||||
* @param aStamp
|
||||
* The TimeStamp recorded for a specific event. This TimeStamp can
|
||||
@@ -159,7 +161,12 @@ class PerformanceTimingData final {
|
||||
bool ShouldReportCrossOriginRedirect(
|
||||
bool aEnsureSameOriginAndIgnoreTAO) const;
|
||||
|
||||
// Cached result of CheckAllowedOrigin. If false, security sensitive
|
||||
// Cached result of CheckBodyInfoAccessAllowedForOrigin.
|
||||
nsITimedChannel::BodyInfoAccess BodyInfoAccessAllowed() const {
|
||||
return mBodyInfoAccessAllowed;
|
||||
}
|
||||
|
||||
// Cached result of CheckTimingAllowedForOrigin. If false, security sensitive
|
||||
// attributes of the resourceTiming object will be set to 0
|
||||
bool TimingAllowed() const { return mTimingAllowed; }
|
||||
|
||||
@@ -170,10 +177,15 @@ class PerformanceTimingData final {
|
||||
}
|
||||
|
||||
private:
|
||||
// Checks if the bodyInfo for Resource and Navigation Timing should be
|
||||
// kept opaque or exposed, per Fetch spec.
|
||||
nsITimedChannel::BodyInfoAccess CheckBodyInfoAccessAllowedForOrigin(
|
||||
nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel);
|
||||
|
||||
// Checks if the resource is either same origin as the page that started
|
||||
// the load, or if the response contains the Timing-Allow-Origin header
|
||||
// with a value of * or matching the domain of the loading Principal
|
||||
bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel,
|
||||
bool CheckTimingAllowedForOrigin(nsIHttpChannel* aResourceChannel,
|
||||
nsITimedChannel* aChannel);
|
||||
|
||||
nsTArray<nsCOMPtr<nsIServerTiming>> mServerTiming;
|
||||
@@ -214,12 +226,17 @@ class PerformanceTimingData final {
|
||||
|
||||
RenderBlockingStatusType mRenderBlockingStatus;
|
||||
|
||||
nsString mContentType;
|
||||
|
||||
bool mAllRedirectsSameOrigin = false;
|
||||
|
||||
bool mAllRedirectsPassTAO = false;
|
||||
|
||||
bool mSecureConnection = false;
|
||||
|
||||
nsITimedChannel::BodyInfoAccess mBodyInfoAccessAllowed =
|
||||
nsITimedChannel::BodyInfoAccess::DISALLOWED;
|
||||
|
||||
bool mTimingAllowed = false;
|
||||
|
||||
bool mInitialized = false;
|
||||
@@ -458,9 +475,11 @@ struct IPDLParamTraits<mozilla::dom::PerformanceTimingData> {
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mTransferSize);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mDecodedBodySize);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mRedirectCount);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mContentType);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mAllRedirectsSameOrigin);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mAllRedirectsPassTAO);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mSecureConnection);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mBodyInfoAccessAllowed);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mTimingAllowed);
|
||||
WriteIPDLParam(aWriter, aActor, aParam.mInitialized);
|
||||
}
|
||||
@@ -539,6 +558,9 @@ struct IPDLParamTraits<mozilla::dom::PerformanceTimingData> {
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mRedirectCount)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mContentType)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mAllRedirectsSameOrigin)) {
|
||||
return false;
|
||||
}
|
||||
@@ -548,6 +570,9 @@ struct IPDLParamTraits<mozilla::dom::PerformanceTimingData> {
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mSecureConnection)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mBodyInfoAccessAllowed)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadIPDLParam(aReader, aActor, &aResult->mTimingAllowed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
21
dom/performance/PerformanceTimingIPCUtils.h
Normal file
21
dom/performance/PerformanceTimingIPCUtils.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 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/. */
|
||||
#ifndef _mozilla_dom_PerformanceTimingIPCUtils_h
|
||||
#define _mozilla_dom_PerformanceTimingIPCUtils_h
|
||||
|
||||
#include "mozilla/EnumTypeTraits.h"
|
||||
#include "ipc/EnumSerializer.h"
|
||||
#include "nsITimedChannel.h"
|
||||
|
||||
namespace IPC {
|
||||
template <>
|
||||
struct ParamTraits<nsITimedChannel::BodyInfoAccess>
|
||||
: ContiguousEnumSerializerInclusive<
|
||||
nsITimedChannel::BodyInfoAccess,
|
||||
nsITimedChannel::BodyInfoAccess::DISALLOWED,
|
||||
nsITimedChannel::BodyInfoAccess::ALLOW_ALL> {};
|
||||
} // namespace IPC
|
||||
#endif // _mozilla_dom_PerformanceTimingIPCUtils_h
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||
using DOMHighResTimeStamp from "nsDOMNavigationTiming.h";
|
||||
using nsITimedChannel::BodyInfoAccess from "mozilla/dom/PerformanceTimingIPCUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@@ -40,9 +41,11 @@ struct IPCPerformanceTimingData {
|
||||
uint64_t decodedBodySize;
|
||||
uint8_t redirectCount;
|
||||
bool renderBlocking;
|
||||
nsString contentType;
|
||||
bool allRedirectsSameOrigin;
|
||||
bool allRedirectsPassTAO;
|
||||
bool secureConnection;
|
||||
BodyInfoAccess bodyInfoAccessAllowed;
|
||||
bool timingAllowed;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ EXPORTS.mozilla.dom += [
|
||||
"PerformanceStorage.h",
|
||||
"PerformanceStorageWorker.h",
|
||||
"PerformanceTiming.h",
|
||||
"PerformanceTimingIPCUtils.h",
|
||||
"PerformanceWorker.h",
|
||||
]
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@ interface PerformanceResourceTiming : PerformanceEntry
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute unsigned long long decodedBodySize;
|
||||
|
||||
// https://w3c.github.io/server-timing/#extension-to-the-performanceresourcetiming-interface
|
||||
[NeedsSubjectPrincipal]
|
||||
readonly attribute DOMString contentType;
|
||||
|
||||
// TODO: Use FrozenArray once available. (Bug 1236777)
|
||||
// readonly attribute FrozenArray<PerformanceServerTiming> serverTiming;
|
||||
[SecureContext, Frozen, Cached, Pure, NeedsSubjectPrincipal]
|
||||
|
||||
@@ -11,6 +11,7 @@ class TimeStamp;
|
||||
}
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
%}
|
||||
|
||||
native TimeStamp(mozilla::TimeStamp);
|
||||
@@ -85,6 +86,20 @@ interface nsITimedChannel : nsISupports {
|
||||
return NS_SUCCEEDED(TimingAllowCheck(aOrigin, &allowed)) && allowed;
|
||||
}
|
||||
%}
|
||||
// Determines if bodyInfo should be opaque to the given origin
|
||||
cenum BodyInfoAccess : 8 {
|
||||
DISALLOWED = 0,
|
||||
ALLOW_SIZES = 1,
|
||||
ALLOW_ALL = 2
|
||||
};
|
||||
[noscript] nsITimedChannel_BodyInfoAccess bodyInfoAccessAllowedCheck(in nsIPrincipal origin);
|
||||
%{C++
|
||||
inline BodyInfoAccess BodyInfoAccessAllowedCheck(nsIPrincipal* aOrigin) {
|
||||
BodyInfoAccess allowed = BodyInfoAccess::DISALLOWED;
|
||||
mozilla::Unused << BodyInfoAccessAllowedCheck(aOrigin, &allowed);
|
||||
return allowed;
|
||||
}
|
||||
%}
|
||||
|
||||
// Whether this request is render-blocking:
|
||||
// https://w3c.github.io/resource-timing/#dom-renderblockingstatustype
|
||||
|
||||
@@ -5460,6 +5460,112 @@ HttpBaseChannel::SetAllRedirectsPassTimingAllowCheck(bool aPassesCheck) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#cors-check
|
||||
bool HttpBaseChannel::PerformCORSCheck() {
|
||||
// Step 1
|
||||
// Let origin be the result of getting `Access-Control-Allow-Origin`
|
||||
// from response’s header list.
|
||||
nsAutoCString origin;
|
||||
nsresult rv = GetResponseHeader("Access-Control-Allow-Origin"_ns, origin);
|
||||
|
||||
// Step 2
|
||||
// If origin is null, then return failure. (Note: null, not 'null').
|
||||
if (NS_FAILED(rv) || origin.IsVoid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
// If request’s credentials mode is not "include"
|
||||
// and origin is `*`, then return success.
|
||||
uint32_t cookiePolicy = mLoadInfo->GetCookiePolicy();
|
||||
if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE &&
|
||||
origin.EqualsLiteral("*")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
// If the result of byte-serializing a request origin
|
||||
// with request is not origin, then return failure.
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
nsCOMPtr<nsIPrincipal> resourcePrincipal;
|
||||
rv = ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
|
||||
if (NS_FAILED(rv) || !resourcePrincipal) {
|
||||
return false;
|
||||
}
|
||||
nsAutoCString serializedOrigin;
|
||||
nsContentSecurityManager::GetSerializedOrigin(
|
||||
mLoadInfo->TriggeringPrincipal(), resourcePrincipal, serializedOrigin,
|
||||
mLoadInfo);
|
||||
if (!serializedOrigin.Equals(origin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
// If request’s credentials mode is not "include", then return success.
|
||||
if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 6
|
||||
// Let credentials be the result of getting
|
||||
// `Access-Control-Allow-Credentials` from response’s header list.
|
||||
nsAutoCString credentials;
|
||||
rv = GetResponseHeader("Access-Control-Allow-Credentials"_ns, credentials);
|
||||
|
||||
// Step 7 and 8
|
||||
// If credentials is `true`, then return success.
|
||||
// (else) return failure.
|
||||
return NS_SUCCEEDED(rv) && credentials.EqualsLiteral("true");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::BodyInfoAccessAllowedCheck(nsIPrincipal* aOrigin,
|
||||
BodyInfoAccess* _retval) {
|
||||
// Per the Fetch spec, https://fetch.spec.whatwg.org/#response-body-info,
|
||||
// the bodyInfo for Resource Timing and Navigation Timing info consists of
|
||||
// encoded size, decoded size, and content type. It is however made opaque
|
||||
// whenever the response is turned into a network error, which sets its
|
||||
// bodyInfo to its default values (sizes=0, content-type="").
|
||||
|
||||
// Case 1:
|
||||
// "no-cors" -> Upon success, fetch will return an opaque filtered response.
|
||||
// An opaque(-redirect) filtered response is a filtered response
|
||||
// whose ... body info is a new response body info.
|
||||
auto tainting = mLoadInfo->GetTainting();
|
||||
if (tainting == mozilla::LoadTainting::Opaque) {
|
||||
*_retval = BodyInfoAccess::DISALLOWED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Case 2:
|
||||
// If request’s response tainting is "cors" and a CORS check for request
|
||||
// and response returns failure, then return a network error.
|
||||
if (tainting == mozilla::LoadTainting::CORS && !PerformCORSCheck()) {
|
||||
*_retval = BodyInfoAccess::DISALLOWED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise:
|
||||
// The fetch response handover, given a fetch params fetchParams
|
||||
// and a response response, run these steps:
|
||||
// processResponseEndOfBody:
|
||||
// - If fetchParams’s request’s mode is not "navigate" or response’s
|
||||
// has-cross-origin-redirects is false:
|
||||
// - Let mimeType be the result of extracting a MIME type from
|
||||
// response’s header list.
|
||||
// - If mimeType is not failure, then set bodyInfo’s content type to the
|
||||
// result of minimizing a supported MIME type given mimeType.
|
||||
dom::RequestMode requestMode;
|
||||
MOZ_ALWAYS_SUCCEEDS(GetRequestMode(&requestMode));
|
||||
if (requestMode != RequestMode::Navigate || LoadAllRedirectsSameOrigin()) {
|
||||
*_retval = BodyInfoAccess::ALLOW_ALL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = BodyInfoAccess::ALLOW_SIZES;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#tao-check
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::TimingAllowCheck(nsIPrincipal* aOrigin, bool* _retval) {
|
||||
|
||||
@@ -1088,6 +1088,8 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
||||
void RemoveAsNonTailRequest();
|
||||
|
||||
void EnsureBrowserId();
|
||||
|
||||
bool PerformCORSCheck();
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)
|
||||
|
||||
@@ -741,6 +741,13 @@ NullHttpChannel::SetAllRedirectsPassTimingAllowCheck(
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullHttpChannel::BodyInfoAccessAllowedCheck(nsIPrincipal* aOrigin,
|
||||
BodyInfoAccess* _retval) {
|
||||
*_retval = BodyInfoAccess::DISALLOWED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NullHttpChannel::TimingAllowCheck(nsIPrincipal* aOrigin, bool* _retval) {
|
||||
*_retval = false;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
[body-size-cross-origin.https.html]
|
||||
[Retrieving a same-origin resource without Timing-Allow-Origin should expose body size]
|
||||
expected: FAIL
|
||||
|
||||
[Retrieving a same-origin resource with Timing-Allow-Origin should expose body size]
|
||||
expected: FAIL
|
||||
|
||||
[Retrieving a no-cors resource with Timing-Allow-Origin should not expose body size]
|
||||
expected: FAIL
|
||||
|
||||
[Retrieving a cors resource without Timing-Allow-Origin should expose body size]
|
||||
expected: FAIL
|
||||
|
||||
[Retrieving a cors resource with Timing-Allow-Origin should expose body size]
|
||||
expected: FAIL
|
||||
@@ -1,16 +1,4 @@
|
||||
[content-type-parsing.html]
|
||||
[content-type 0 : ,text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 1 : text/plain,]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 2 : text/html,text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 3 : text/plain;charset=gbk,text/html]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 4 : text/plain;charset=gbk,text/html;charset=windows-1254]
|
||||
expected: FAIL
|
||||
|
||||
@@ -26,39 +14,12 @@
|
||||
[content-type 8 : text/plain;charset=gbk;x=foo,text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 9 : text/html;charset=gbk,text/plain,text/html]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 10 : text/plain,*/*]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 11 : text/html,*/*]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 12 : */*,text/html]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 13 : text/plain,*/*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 14 : text/html,*/*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 15 : text/html;x=",text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 16 : text/html;",text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 17 : text/html;",\\",text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 18 : text/html;",\\",text/plain,";charset=GBK]
|
||||
expected: FAIL
|
||||
|
||||
[content-type 19 : text/html;",",text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 1 : text/html;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
@@ -77,9 +38,6 @@
|
||||
[mime-type 8 : text/html;charset=();charset=GBK]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 10 : text/html;charset =gbk]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 11 : text/html ;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
@@ -92,18 +50,6 @@
|
||||
[mime-type 14 : text/html;charset= "gbk"]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 16 : text/html;charset=\x0bgbk]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 17 : text/html;charset=\x0cgbk]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 18 : text/html;\x0bcharset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 19 : text/html;\x0ccharset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[mime-type 21 : text/html;charset='gbk']
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,83 +1,3 @@
|
||||
[content-type.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[This test validates the content-type of resources.]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 1]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 2]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 3]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 4]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 5]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 6]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 7]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 8]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 9]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 10]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 11]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 12]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 13]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 14]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 15]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 16]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 17]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 18]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 19]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 20]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 21]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 22]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 23]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 24]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 25]
|
||||
expected: FAIL
|
||||
|
||||
[This test validates the content-type of resources. 26]
|
||||
expected: FAIL
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
[PerformanceResourceTiming interface: resource must inherit property "firstInterimResponseStart" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: attribute contentType]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "contentType" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[idlharness.any.worker.html]
|
||||
expected:
|
||||
@@ -52,9 +46,3 @@
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "firstInterimResponseStart" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: attribute contentType]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "contentType" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
[sizes-redirect-img.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[PerformanceResourceTiming sizes redirect image - direct URL]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming sizes redirect image - same origin redirect]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming sizes redirect image - cross origin redirect]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming sizes redirect image - cross origin to same origin redirect]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming sizes redirect image - same origin to remote origin to same origin redirect]
|
||||
expected: FAIL
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
|
||||
|
||||
[sizes-redirect.any.html]
|
||||
[PerformanceResourceTiming sizes Fetch with redirect test]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[sizes-redirect.any.worker.html]
|
||||
[PerformanceResourceTiming sizes Fetch with redirect test]
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
[PerformanceResourceTiming interface: resource must inherit property "firstInterimResponseStart" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: attribute contentType]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "contentType" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[idlharness.https.any.worker.html]
|
||||
[PerformanceResourceTiming interface: attribute renderBlockingStatus]
|
||||
@@ -60,9 +54,3 @@
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "firstInterimResponseStart" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: attribute contentType]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceResourceTiming interface: resource must inherit property "contentType" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
@@ -112,6 +112,16 @@ attribute_test(
|
||||
`content-type should be exposed for iframes having only same origin redirects`);
|
||||
});
|
||||
|
||||
// Content-type for iframes is not exposed if any redirect is not same origin.
|
||||
var finalDestUrl = `${SAME_ORIGIN}/resource-timing/resources/content-type.py?content_type=text/html`;
|
||||
var interimDestUrl = `${REMOTE_ORIGIN}/resource-timing/resources/resources/redirect-cors.py?location=` + encodeURIComponent(finalDestUrl);
|
||||
var destUrl = `${SAME_ORIGIN}/resource-timing/resources/redirect-cors.py?location=` + encodeURIComponent(interimDestUrl);
|
||||
attribute_test(
|
||||
load.iframe, new URL(destUrl),
|
||||
entry => {
|
||||
assert_equals(entry.contentType, "",
|
||||
`content-type should not be exposed for iframes with any non-same-origin redirect`);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user