mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Backed out changeset 16fefebdbb50 (bug 1285036) for static build bustage
This commit is contained in:
parent
7d34c388a9
commit
87a58ba2c4
@ -7071,8 +7071,9 @@ nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader)
|
||||
static const char *kInvalidHeaders[] = {
|
||||
"accept-charset", "accept-encoding", "access-control-request-headers",
|
||||
"access-control-request-method", "connection", "content-length",
|
||||
"cookie", "cookie2", "date", "dnt", "expect", "host", "keep-alive",
|
||||
"origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", "via"
|
||||
"cookie", "cookie2", "content-transfer-encoding", "date", "dnt",
|
||||
"expect", "host", "keep-alive", "origin", "referer", "te", "trailer",
|
||||
"transfer-encoding", "upgrade", "via"
|
||||
};
|
||||
for (uint32_t i = 0; i < ArrayLength(kInvalidHeaders); ++i) {
|
||||
if (aHeader.LowerCaseEqualsASCII(kInvalidHeaders[i])) {
|
||||
|
@ -1465,7 +1465,7 @@ XMLHttpRequestMainThread::Open(const nsACString& inMethod, const nsACString& url
|
||||
|
||||
// Clear our record of previously set headers so future header set
|
||||
// operations will merge/override correctly.
|
||||
mAuthorRequestHeaders.Clear();
|
||||
mAlreadySetHeaders.Clear();
|
||||
|
||||
// When we are called from JS we can find the load group for the page,
|
||||
// and add ourselves to it. This way any pending requests
|
||||
@ -2480,9 +2480,6 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
|
||||
if (httpChannel) {
|
||||
// Spec step 5
|
||||
SetAuthorRequestHeadersOnChannel(httpChannel);
|
||||
|
||||
httpChannel->GetRequestMethod(method); // If GET, method name will be uppercase
|
||||
|
||||
if (!IsSystemXHR()) {
|
||||
@ -2537,14 +2534,15 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
||||
net::InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
|
||||
|
||||
if (postDataStream) {
|
||||
// If author set no Content-Type, use the default from GetRequestBody().
|
||||
// If no content type header was set by the client, we set it to
|
||||
// application/xml.
|
||||
nsAutoCString contentType;
|
||||
|
||||
GetAuthorRequestHeaderValue("content-type", contentType);
|
||||
if (contentType.IsVoid()) {
|
||||
if (NS_FAILED(httpChannel->
|
||||
GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
|
||||
contentType))) {
|
||||
contentType = defaultContentType;
|
||||
|
||||
if (!charset.IsEmpty()) {
|
||||
if (!charset.IsEmpty() && !contentType.IsVoid()) {
|
||||
// If we are providing the default content type, then we also need to
|
||||
// provide a charset declaration.
|
||||
contentType.Append(NS_LITERAL_CSTRING(";charset="));
|
||||
@ -2722,26 +2720,8 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
||||
|
||||
// Set up the preflight if needed
|
||||
if (!IsSystemXHR()) {
|
||||
nsTArray<nsCString> CORSUnsafeHeaders;
|
||||
const char *kCrossOriginSafeHeaders[] = {
|
||||
"accept", "accept-language", "content-language", "content-type",
|
||||
"last-event-id"
|
||||
};
|
||||
for (RequestHeader& header : mAuthorRequestHeaders) {
|
||||
bool safe = false;
|
||||
for (uint32_t i = 0; i < ArrayLength(kCrossOriginSafeHeaders); ++i) {
|
||||
if (header.name.EqualsASCII(kCrossOriginSafeHeaders[i])) {
|
||||
safe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!safe) {
|
||||
CORSUnsafeHeaders.AppendElement(header.name);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
|
||||
loadInfo->SetCorsPreflightInfo(CORSUnsafeHeaders,
|
||||
loadInfo->SetCorsPreflightInfo(mCORSUnsafeHeaders,
|
||||
mFlagHadUploadListenersOnSend);
|
||||
}
|
||||
|
||||
@ -2867,62 +2847,99 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
||||
|
||||
// http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-setrequestheader
|
||||
NS_IMETHODIMP
|
||||
XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
|
||||
const nsACString& aValue)
|
||||
XMLHttpRequestMainThread::SetRequestHeader(const nsACString& header,
|
||||
const nsACString& value)
|
||||
{
|
||||
// Steps 1 and 2
|
||||
if (mState != State::opened || mFlagSend) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
NS_ASSERTION(mChannel, "mChannel must be valid if we're OPENED.");
|
||||
|
||||
// Step 3
|
||||
nsAutoCString value(aValue);
|
||||
static const char kHTTPWhitespace[] = "\n\t\r ";
|
||||
value.Trim(kHTTPWhitespace);
|
||||
|
||||
// Step 4
|
||||
if (!NS_IsValidHTTPToken(aName) || !NS_IsReasonableHTTPHeaderValue(value)) {
|
||||
// Make sure we don't store an invalid header name in mCORSUnsafeHeaders
|
||||
if (!NS_IsValidHTTPToken(header)) {
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
bool isPrivilegedCaller = IsSystemXHR();
|
||||
bool isForbiddenHeader = nsContentUtils::IsForbiddenRequestHeader(aName);
|
||||
if (!isPrivilegedCaller && isForbiddenHeader) {
|
||||
NS_WARNING("refusing to set request header");
|
||||
if (!mChannel) // open() initializes mChannel, and open()
|
||||
return NS_ERROR_FAILURE; // must be called before first setRequestHeader()
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
|
||||
if (!httpChannel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Step 6.1
|
||||
nsAutoCString lowercaseName;
|
||||
nsContentUtils::ASCIIToLower(aName, lowercaseName);
|
||||
// We will merge XHR headers, per the spec (secion 4.6.2) unless:
|
||||
// 1 - The caller is privileged and setting an invalid header,
|
||||
// or
|
||||
// 2 - we have not yet explicitly set that header; this allows web
|
||||
// content to override default headers the first time they set them.
|
||||
bool mergeHeaders = true;
|
||||
|
||||
// Step 6.2
|
||||
bool notAlreadySet = true;
|
||||
for (RequestHeader& header : mAuthorRequestHeaders) {
|
||||
if (header.name.Equals(lowercaseName)) {
|
||||
// Gecko-specific: invalid headers can be set by privileged
|
||||
// callers, but will not merge.
|
||||
if (isPrivilegedCaller && isForbiddenHeader) {
|
||||
header.value.Assign(value);
|
||||
} else {
|
||||
header.value.AppendLiteral(", ");
|
||||
header.value.Append(value);
|
||||
if (!IsSystemXHR()) {
|
||||
// Step 5: Check for dangerous headers.
|
||||
// Prevent modification to certain HTTP headers (see bug 302263), unless
|
||||
// the executing script is privileged.
|
||||
if (nsContentUtils::IsForbiddenRequestHeader(header)) {
|
||||
NS_WARNING("refusing to set request header");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check for dangerous cross-site headers
|
||||
bool safeHeader = IsSystemXHR();
|
||||
if (!safeHeader) {
|
||||
// Content-Type isn't always safe, but we'll deal with it in Send()
|
||||
const char *kCrossOriginSafeHeaders[] = {
|
||||
"accept", "accept-language", "content-language", "content-type",
|
||||
"last-event-id"
|
||||
};
|
||||
for (uint32_t i = 0; i < ArrayLength(kCrossOriginSafeHeaders); ++i) {
|
||||
if (header.LowerCaseEqualsASCII(kCrossOriginSafeHeaders[i])) {
|
||||
safeHeader = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
notAlreadySet = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!safeHeader) {
|
||||
if (!mCORSUnsafeHeaders.Contains(header, nsCaseInsensitiveCStringArrayComparator())) {
|
||||
mCORSUnsafeHeaders.AppendElement(header);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Case 1 above
|
||||
if (nsContentUtils::IsForbiddenSystemRequestHeader(header)) {
|
||||
mergeHeaders = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6.3
|
||||
if (notAlreadySet) {
|
||||
RequestHeader newHeader = {
|
||||
nsCString(lowercaseName), nsCString(value)
|
||||
};
|
||||
mAuthorRequestHeaders.AppendElement(newHeader);
|
||||
if (!mAlreadySetHeaders.Contains(header)) {
|
||||
// Case 2 above
|
||||
mergeHeaders = false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
nsresult rv;
|
||||
if (value.IsEmpty()) {
|
||||
rv = httpChannel->SetEmptyRequestHeader(header);
|
||||
} else {
|
||||
// Merge headers depending on what we decided above.
|
||||
rv = httpChannel->SetRequestHeader(header, value, mergeHeaders);
|
||||
}
|
||||
if (rv == NS_ERROR_INVALID_ARG) {
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Remember that we've set this header, so subsequent set operations will merge values.
|
||||
mAlreadySetHeaders.PutEntry(nsCString(header));
|
||||
|
||||
// We'll want to duplicate this header for any replacement channels (eg. on redirect)
|
||||
RequestHeader reqHeader = {
|
||||
nsCString(header), nsCString(value)
|
||||
};
|
||||
mModifiedRequestHeaders.AppendElement(reqHeader);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -3162,32 +3179,6 @@ XMLHttpRequestMainThread::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestMainThread::GetAuthorRequestHeaderValue(const char* aName,
|
||||
nsACString& outValue)
|
||||
{
|
||||
for (RequestHeader& header : mAuthorRequestHeaders) {
|
||||
if (header.name.Equals(aName)) {
|
||||
outValue.Assign(header.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
outValue.SetIsVoid(true);
|
||||
}
|
||||
|
||||
void
|
||||
XMLHttpRequestMainThread::SetAuthorRequestHeadersOnChannel(
|
||||
nsCOMPtr<nsIHttpChannel> aHttpChannel)
|
||||
{
|
||||
for (RequestHeader& header : mAuthorRequestHeaders) {
|
||||
if (header.value.IsEmpty()) {
|
||||
aHttpChannel->SetEmptyRequestHeader(header.name);
|
||||
} else {
|
||||
aHttpChannel->SetRequestHeader(header.name, header.value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
XMLHttpRequestMainThread::OnRedirectVerifyCallback(nsresult result)
|
||||
{
|
||||
@ -3200,7 +3191,15 @@ XMLHttpRequestMainThread::OnRedirectVerifyCallback(nsresult result)
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
if (httpChannel) {
|
||||
// Ensure all original headers are duplicated for the new channel (bug #553888)
|
||||
SetAuthorRequestHeadersOnChannel(httpChannel);
|
||||
for (RequestHeader& requestHeader : mModifiedRequestHeaders) {
|
||||
if (requestHeader.value.IsEmpty()) {
|
||||
httpChannel->SetEmptyRequestHeader(requestHeader.header);
|
||||
} else {
|
||||
httpChannel->SetRequestHeader(requestHeader.header,
|
||||
requestHeader.value,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mErrorLoad = true;
|
||||
@ -3516,8 +3515,9 @@ XMLHttpRequestMainThread::ShouldBlockAuthPrompt()
|
||||
// Verify that it's ok to prompt for credentials here, per spec
|
||||
// http://xhr.spec.whatwg.org/#the-send%28%29-method
|
||||
|
||||
for (RequestHeader& requestHeader : mAuthorRequestHeaders) {
|
||||
if (requestHeader.name.EqualsLiteral("authorization")) {
|
||||
for (uint32_t i = 0, len = mModifiedRequestHeaders.Length(); i < len; ++i) {
|
||||
if (mModifiedRequestHeaders[i].header.
|
||||
LowerCaseEqualsLiteral("authorization")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -220,10 +220,10 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
SetRequestHeader(const nsACString& aName, const nsACString& aValue,
|
||||
SetRequestHeader(const nsACString& aHeader, const nsACString& aValue,
|
||||
ErrorResult& aRv) override
|
||||
{
|
||||
aRv = SetRequestHeader(aName, aValue);
|
||||
aRv = SetRequestHeader(aHeader, aValue);
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
@ -620,6 +620,7 @@ protected:
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsIDocument> mResponseXML;
|
||||
nsTArray<nsCString> mCORSUnsafeHeaders;
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
|
||||
|
||||
@ -790,13 +791,12 @@ protected:
|
||||
|
||||
struct RequestHeader
|
||||
{
|
||||
nsCString name;
|
||||
nsCString header;
|
||||
nsCString value;
|
||||
};
|
||||
nsTArray<RequestHeader> mAuthorRequestHeaders;
|
||||
nsTArray<RequestHeader> mModifiedRequestHeaders;
|
||||
|
||||
void GetAuthorRequestHeaderValue(const char* aName, nsACString& outValue);
|
||||
void SetAuthorRequestHeadersOnChannel(nsCOMPtr<nsIHttpChannel> aChannel);
|
||||
nsTHashtable<nsCStringHashKey> mAlreadySetHeaders;
|
||||
|
||||
// Helper object to manage our XPCOM scriptability bits
|
||||
nsXMLHttpRequestXPCOMifier* mXPCOMifier;
|
||||
|
@ -28,6 +28,7 @@ var headers = [
|
||||
"coNtEnt-LEngth",
|
||||
"CoOKIe",
|
||||
"cOOkiE2",
|
||||
"cOntEnt-tRAnsFer-enCoDiNg",
|
||||
"DATE",
|
||||
"dNT",
|
||||
"exPeCt",
|
||||
@ -53,7 +54,6 @@ function startTest() {
|
||||
request.open("GET", window.location.href);
|
||||
for (i = 0; i < headers.length; i++)
|
||||
request.setRequestHeader(headers[i], "test" + i);
|
||||
request.send(); // headers aren't set on the channel until send()
|
||||
|
||||
// Read out headers
|
||||
var channel = SpecialPowers.wrap(request).channel.QueryInterface(SpecialPowers.Ci.nsIHttpChannel);
|
||||
@ -73,7 +73,6 @@ function startTest() {
|
||||
request.open("GET", window.location.href);
|
||||
for (i = 0; i < headers.length; i++)
|
||||
request.setRequestHeader(headers[i], "test" + i);
|
||||
request.send(); // headers aren't set on the channel until send()
|
||||
|
||||
// Read out headers
|
||||
var channel = SpecialPowers.wrap(request).channel.QueryInterface(SpecialPowers.Ci.nsIHttpChannel);
|
||||
|
@ -0,0 +1,5 @@
|
||||
[setrequestheader-case-insensitive.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: setRequestHeader() - headers that differ in case]
|
||||
expected: FAIL
|
||||
|
@ -0,0 +1,14 @@
|
||||
[setrequestheader-header-allowed.htm]
|
||||
type: testharness
|
||||
[XMLHttpRequest: setRequestHeader() - headers that are allowed (Authorization)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: setRequestHeader() - headers that are allowed (Content-Transfer-Encoding)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: setRequestHeader() - headers that are allowed (Content-Type)]
|
||||
expected: FAIL
|
||||
|
||||
[XMLHttpRequest: setRequestHeader() - headers that are allowed (User-Agent)]
|
||||
expected: FAIL
|
||||
|
Loading…
x
Reference in New Issue
Block a user