Backed out changeset 16fefebdbb50 (bug 1285036) for static build bustage

This commit is contained in:
Carsten "Tomcat" Book 2016-07-21 06:14:41 +02:00
parent 7d34c388a9
commit 87a58ba2c4
6 changed files with 122 additions and 103 deletions

View File

@ -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])) {

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);

View File

@ -0,0 +1,5 @@
[setrequestheader-case-insensitive.htm]
type: testharness
[XMLHttpRequest: setRequestHeader() - headers that differ in case]
expected: FAIL

View File

@ -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