Bug 1285036 - Part 9: Clean up the XHR send() API endpoints, and how nsIVariants are handled. r=baku
This commit is contained in:
@@ -2106,6 +2106,167 @@ XMLHttpRequestMainThread::ChangeStateToDone()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<nsIDocument>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(mBody));
|
||||||
|
NS_ENSURE_STATE(domdoc);
|
||||||
|
aCharset.AssignLiteral("UTF-8");
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIStorageStream> storStream;
|
||||||
|
rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIOutputStream> output;
|
||||||
|
rv = storStream->GetOutputStream(0, getter_AddRefs(output));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (mBody->IsHTMLDocument()) {
|
||||||
|
aContentType.AssignLiteral("text/html");
|
||||||
|
|
||||||
|
nsString serialized;
|
||||||
|
if (!nsContentUtils::SerializeNodeToMarkup(mBody, true, serialized)) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
NS_ConvertUTF16toUTF8 utf8Serialized(serialized);
|
||||||
|
|
||||||
|
uint32_t written;
|
||||||
|
rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
MOZ_ASSERT(written == utf8Serialized.Length());
|
||||||
|
} else {
|
||||||
|
aContentType.AssignLiteral("application/xml");
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMSerializer> serializer =
|
||||||
|
do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Make sure to use the encoding we'll send
|
||||||
|
rv = serializer->SerializeToStream(domdoc, output, aCharset);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
output->Close();
|
||||||
|
|
||||||
|
uint32_t length;
|
||||||
|
rv = storStream->GetLength(&length);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
*aContentLength = length;
|
||||||
|
|
||||||
|
rv = storStream->NewInputStream(0, aResult);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<const nsAString>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
aContentType.AssignLiteral("text/plain");
|
||||||
|
aCharset.AssignLiteral("UTF-8");
|
||||||
|
|
||||||
|
nsCString converted = NS_ConvertUTF16toUTF8(*mBody);
|
||||||
|
*aContentLength = converted.Length();
|
||||||
|
nsresult rv = NS_NewCStringInputStream(aResult, converted);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<nsIInputStream>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
aContentType.AssignLiteral("text/plain");
|
||||||
|
aCharset.Truncate();
|
||||||
|
|
||||||
|
nsresult rv = mBody->Available(aContentLength);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIInputStream> stream(mBody);
|
||||||
|
stream.forget(aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<Blob>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
return mBody->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<FormData>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
return mBody->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<URLSearchParams>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
return mBody->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<nsIXHRSendable>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
return mBody->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
GetBufferDataAsStream(const uint8_t* aData, uint32_t aDataLength,
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset)
|
||||||
|
{
|
||||||
|
aContentType.SetIsVoid(true);
|
||||||
|
aCharset.Truncate();
|
||||||
|
|
||||||
|
*aContentLength = aDataLength;
|
||||||
|
const char* data = reinterpret_cast<const char*>(aData);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIInputStream> stream;
|
||||||
|
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, aDataLength,
|
||||||
|
NS_ASSIGNMENT_COPY);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
stream.forget(aResult);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<const ArrayBuffer>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
mBody->ComputeLengthAndData();
|
||||||
|
return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
|
||||||
|
aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> nsresult
|
||||||
|
XMLHttpRequestMainThread::RequestBody<const ArrayBufferView>::GetAsStream(
|
||||||
|
nsIInputStream** aResult, uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType, nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
mBody->ComputeLengthAndData();
|
||||||
|
return GetBufferDataAsStream(mBody->Data(), mBody->Length(),
|
||||||
|
aResult, aContentLength, aContentType, aCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
XMLHttpRequestMainThread::InitChannel()
|
XMLHttpRequestMainThread::InitChannel()
|
||||||
{
|
{
|
||||||
@@ -2181,154 +2342,31 @@ XMLHttpRequestMainThread::InitChannel()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
NS_IMETHODIMP
|
||||||
GetRequestBodyInternal(nsIDOMDocument* aDoc, nsIInputStream** aResult,
|
XMLHttpRequestMainThread::Send(nsIVariant* aVariant)
|
||||||
uint64_t* aContentLength, nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
|
if (!aVariant) {
|
||||||
NS_ENSURE_STATE(doc);
|
return SendInternal(nullptr);
|
||||||
aCharset.AssignLiteral("UTF-8");
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIStorageStream> storStream;
|
|
||||||
rv = NS_NewStorageStream(4096, UINT32_MAX, getter_AddRefs(storStream));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIOutputStream> output;
|
|
||||||
rv = storStream->GetOutputStream(0, getter_AddRefs(output));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (doc->IsHTMLDocument()) {
|
|
||||||
aContentType.AssignLiteral("text/html");
|
|
||||||
|
|
||||||
nsString serialized;
|
|
||||||
if (!nsContentUtils::SerializeNodeToMarkup(doc, true, serialized)) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
NS_ConvertUTF16toUTF8 utf8Serialized(serialized);
|
|
||||||
|
|
||||||
uint32_t written;
|
|
||||||
rv = output->Write(utf8Serialized.get(), utf8Serialized.Length(), &written);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
MOZ_ASSERT(written == utf8Serialized.Length());
|
|
||||||
} else {
|
|
||||||
aContentType.AssignLiteral("application/xml");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMSerializer> serializer =
|
|
||||||
do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// Make sure to use the encoding we'll send
|
|
||||||
rv = serializer->SerializeToStream(aDoc, output, aCharset);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output->Close();
|
|
||||||
|
|
||||||
uint32_t length;
|
|
||||||
rv = storStream->GetLength(&length);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
*aContentLength = length;
|
|
||||||
|
|
||||||
return storStream->NewInputStream(0, aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(const nsAString& aString, nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength, nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
|
||||||
aContentType.AssignLiteral("text/plain");
|
|
||||||
aCharset.AssignLiteral("UTF-8");
|
|
||||||
|
|
||||||
nsCString converted = NS_ConvertUTF16toUTF8(aString);
|
|
||||||
*aContentLength = converted.Length();
|
|
||||||
return NS_NewCStringInputStream(aResult, converted);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(nsIInputStream* aStream, nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength, nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
|
||||||
aContentType.AssignLiteral("text/plain");
|
|
||||||
aCharset.Truncate();
|
|
||||||
|
|
||||||
nsresult rv = aStream->Available(aContentLength);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
NS_ADDREF(*aResult = aStream);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(URLSearchParams* aURLSearchParams,
|
|
||||||
nsIInputStream** aResult, uint64_t* aContentLength,
|
|
||||||
nsACString& aContentType, nsACString& aCharset)
|
|
||||||
{
|
|
||||||
return aURLSearchParams->GetSendInfo(aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(nsIXHRSendable* aSendable, nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength, nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
|
||||||
return aSendable->GetSendInfo(aResult, aContentLength, aContentType, aCharset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for array buffers and array buffer views
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(const uint8_t* aData, uint32_t aDataLength,
|
|
||||||
nsIInputStream** aResult, uint64_t* aContentLength,
|
|
||||||
nsACString& aContentType, nsACString& aCharset)
|
|
||||||
{
|
|
||||||
aContentType.SetIsVoid(true);
|
|
||||||
aCharset.Truncate();
|
|
||||||
|
|
||||||
*aContentLength = aDataLength;
|
|
||||||
const char* data = reinterpret_cast<const char*>(aData);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> stream;
|
|
||||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, aDataLength,
|
|
||||||
NS_ASSIGNMENT_COPY);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
stream.forget(aResult);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static nsresult
|
|
||||||
GetRequestBodyInternal(nsIVariant* aBody, nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength, nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
|
||||||
*aResult = nullptr;
|
|
||||||
|
|
||||||
uint16_t dataType;
|
uint16_t dataType;
|
||||||
nsresult rv = aBody->GetDataType(&dataType);
|
nsresult rv = aVariant->GetDataType(&dataType);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (dataType == nsIDataType::VTYPE_INTERFACE ||
|
if (dataType == nsIDataType::VTYPE_INTERFACE ||
|
||||||
dataType == nsIDataType::VTYPE_INTERFACE_IS) {
|
dataType == nsIDataType::VTYPE_INTERFACE_IS) {
|
||||||
nsCOMPtr<nsISupports> supports;
|
nsCOMPtr<nsISupports> supports;
|
||||||
nsID *iid;
|
nsID *iid;
|
||||||
rv = aBody->GetAsInterface(&iid, getter_AddRefs(supports));
|
rv = aVariant->GetAsInterface(&iid, getter_AddRefs(supports));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
free(iid);
|
free(iid);
|
||||||
|
|
||||||
// document?
|
// document?
|
||||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(supports);
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(supports);
|
||||||
if (doc) {
|
if (doc) {
|
||||||
return GetRequestBodyInternal(doc, aResult, aContentLength, aContentType,
|
RequestBody<nsIDocument> body(doc);
|
||||||
aCharset);
|
return SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsISupportsString?
|
// nsISupportsString?
|
||||||
@@ -2336,153 +2374,56 @@ GetRequestBodyInternal(nsIVariant* aBody, nsIInputStream** aResult,
|
|||||||
if (wstr) {
|
if (wstr) {
|
||||||
nsAutoString string;
|
nsAutoString string;
|
||||||
wstr->GetData(string);
|
wstr->GetData(string);
|
||||||
|
RequestBody<const nsAString> body(&string);
|
||||||
return GetRequestBodyInternal(string, aResult, aContentLength,
|
return SendInternal(&body);
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIInputStream?
|
// nsIInputStream?
|
||||||
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(supports);
|
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(supports);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
return GetRequestBodyInternal(stream, aResult, aContentLength,
|
RequestBody<nsIInputStream> body(stream);
|
||||||
aContentType, aCharset);
|
return SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIXHRSendable?
|
// nsIXHRSendable?
|
||||||
nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(supports);
|
nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(supports);
|
||||||
if (sendable) {
|
if (sendable) {
|
||||||
return GetRequestBodyInternal(sendable, aResult, aContentLength,
|
RequestBody<nsIXHRSendable> body(sendable);
|
||||||
aContentType, aCharset);
|
return SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayBuffer?
|
// ArrayBuffer?
|
||||||
JSContext* rootingCx = nsContentUtils::RootingCx();
|
JSContext* rootingCx = nsContentUtils::RootingCx();
|
||||||
JS::Rooted<JS::Value> realVal(rootingCx);
|
JS::Rooted<JS::Value> realVal(rootingCx);
|
||||||
|
|
||||||
nsresult rv = aBody->GetAsJSVal(&realVal);
|
nsresult rv = aVariant->GetAsJSVal(&realVal);
|
||||||
if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
|
if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
|
||||||
JS::Rooted<JSObject*> obj(rootingCx, realVal.toObjectOrNull());
|
JS::Rooted<JSObject*> obj(rootingCx, realVal.toObjectOrNull());
|
||||||
RootedTypedArray<ArrayBuffer> buf(rootingCx);
|
RootedTypedArray<ArrayBuffer> buf(rootingCx);
|
||||||
if (buf.Init(obj)) {
|
if (buf.Init(obj)) {
|
||||||
buf.ComputeLengthAndData();
|
RequestBody<const ArrayBuffer> body(&buf);
|
||||||
return GetRequestBodyInternal(buf.Data(), buf.Length(), aResult,
|
return SendInternal(&body);
|
||||||
aContentLength, aContentType, aCharset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (dataType == nsIDataType::VTYPE_VOID ||
|
||||||
else if (dataType == nsIDataType::VTYPE_VOID ||
|
|
||||||
dataType == nsIDataType::VTYPE_EMPTY) {
|
dataType == nsIDataType::VTYPE_EMPTY) {
|
||||||
// Makes us act as if !aBody, don't upload anything
|
return SendInternal(nullptr);
|
||||||
aContentType.AssignLiteral("text/plain");
|
|
||||||
aCharset.AssignLiteral("UTF-8");
|
|
||||||
*aContentLength = 0;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char16_t* data = nullptr;
|
char16_t* data = nullptr;
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
rv = aBody->GetAsWStringWithSize(&len, &data);
|
rv = aVariant->GetAsWStringWithSize(&len, &data);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsString string;
|
nsString string;
|
||||||
string.Adopt(data, len);
|
string.Adopt(data, len);
|
||||||
|
|
||||||
return GetRequestBodyInternal(string, aResult, aContentLength, aContentType,
|
RequestBody<const nsAString> body(&string);
|
||||||
aCharset);
|
return SendInternal(&body);
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
nsresult
|
|
||||||
XMLHttpRequestMainThread::GetRequestBody(nsIVariant* aVariant,
|
|
||||||
const Nullable<RequestBody>& aBody,
|
|
||||||
nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength,
|
|
||||||
nsACString& aContentType,
|
|
||||||
nsACString& aCharset)
|
|
||||||
{
|
|
||||||
// null the content type and charset by default, as per XHR spec step 4
|
|
||||||
aContentType.SetIsVoid(true);
|
|
||||||
aCharset.SetIsVoid(true);
|
|
||||||
|
|
||||||
if (aVariant) {
|
|
||||||
return GetRequestBodyInternal(aVariant, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
|
|
||||||
const RequestBody& body = aBody.Value();
|
|
||||||
RequestBody::Value value = body.GetValue();
|
|
||||||
switch (body.GetType()) {
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eArrayBuffer:
|
|
||||||
{
|
|
||||||
const ArrayBuffer* buffer = value.mArrayBuffer;
|
|
||||||
buffer->ComputeLengthAndData();
|
|
||||||
return GetRequestBodyInternal(buffer->Data(), buffer->Length(), aResult,
|
|
||||||
aContentLength, aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eArrayBufferView:
|
|
||||||
{
|
|
||||||
const ArrayBufferView* view = value.mArrayBufferView;
|
|
||||||
view->ComputeLengthAndData();
|
|
||||||
return GetRequestBodyInternal(view->Data(), view->Length(), aResult,
|
|
||||||
aContentLength, aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eBlob:
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIDOMBlob> blob = value.mBlob;
|
|
||||||
nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(blob, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return GetRequestBodyInternal(sendable, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eDocument:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(value.mDocument);
|
|
||||||
return GetRequestBodyInternal(document, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eDOMString:
|
|
||||||
{
|
|
||||||
return GetRequestBodyInternal(*value.mString, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eFormData:
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(value.mFormData);
|
|
||||||
return GetRequestBodyInternal(value.mFormData, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eURLSearchParams:
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(value.mURLSearchParams);
|
|
||||||
return GetRequestBodyInternal(value.mURLSearchParams, aResult,
|
|
||||||
aContentLength, aContentType, aCharset);
|
|
||||||
}
|
|
||||||
case XMLHttpRequestMainThread::RequestBody::eInputStream:
|
|
||||||
{
|
|
||||||
return GetRequestBodyInternal(value.mStream, aResult, aContentLength,
|
|
||||||
aContentType, aCharset);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_NOTREACHED("Default cases exist for a reason");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
XMLHttpRequestMainThread::Send(nsIVariant *aBody)
|
|
||||||
{
|
|
||||||
return Send(aBody, Nullable<RequestBody>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
XMLHttpRequestMainThread::SendInternal(const RequestBodyBase* aBody)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
|
||||||
|
|
||||||
@@ -2561,7 +2502,7 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
|||||||
mErrorLoad = false;
|
mErrorLoad = false;
|
||||||
mLoadLengthComputable = false;
|
mLoadLengthComputable = false;
|
||||||
mLoadTotal = 0;
|
mLoadTotal = 0;
|
||||||
if ((aVariant || !aBody.IsNull()) && httpChannel &&
|
if (aBody && httpChannel &&
|
||||||
!method.LowerCaseEqualsLiteral("get") &&
|
!method.LowerCaseEqualsLiteral("get") &&
|
||||||
!method.LowerCaseEqualsLiteral("head")) {
|
!method.LowerCaseEqualsLiteral("head")) {
|
||||||
|
|
||||||
@@ -2570,8 +2511,8 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
|||||||
nsCOMPtr<nsIInputStream> postDataStream;
|
nsCOMPtr<nsIInputStream> postDataStream;
|
||||||
|
|
||||||
uint64_t size_u64;
|
uint64_t size_u64;
|
||||||
rv = GetRequestBody(aVariant, aBody, getter_AddRefs(postDataStream),
|
rv = aBody->GetAsStream(getter_AddRefs(postDataStream),
|
||||||
&size_u64, defaultContentType, charset);
|
&size_u64, defaultContentType, charset);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// make sure it fits within js MAX_SAFE_INTEGER
|
// make sure it fits within js MAX_SAFE_INTEGER
|
||||||
@@ -2579,7 +2520,7 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
|||||||
net::InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
|
net::InScriptableRange(size_u64) ? static_cast<int64_t>(size_u64) : -1;
|
||||||
|
|
||||||
if (postDataStream) {
|
if (postDataStream) {
|
||||||
// If author set no Content-Type, use the default from GetRequestBody().
|
// If author set no Content-Type, use the default from GetAsStream().
|
||||||
nsAutoCString contentType;
|
nsAutoCString contentType;
|
||||||
|
|
||||||
GetAuthorRequestHeaderValue("content-type", contentType);
|
GetAuthorRequestHeaderValue("content-type", contentType);
|
||||||
@@ -2833,7 +2774,6 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
|||||||
|
|
||||||
mWaitingForOnStopRequest = true;
|
mWaitingForOnStopRequest = true;
|
||||||
|
|
||||||
// Step 8
|
|
||||||
mFlagSend = true;
|
mFlagSend = true;
|
||||||
|
|
||||||
// If we're synchronous, spin an event loop here and wait
|
// If we're synchronous, spin an event loop here and wait
|
||||||
@@ -2892,8 +2832,7 @@ XMLHttpRequestMainThread::Send(nsIVariant* aVariant, const Nullable<RequestBody>
|
|||||||
if (mUpload && mUpload->HasListenersFor(nsGkAtoms::onprogress)) {
|
if (mUpload && mUpload->HasListenersFor(nsGkAtoms::onprogress)) {
|
||||||
StartProgressEventTimer();
|
StartProgressEventTimer();
|
||||||
}
|
}
|
||||||
DispatchProgressEvent(this, ProgressEventType::loadstart, false,
|
DispatchProgressEvent(this, ProgressEventType::loadstart, false, 0, 0);
|
||||||
0, 0);
|
|
||||||
if (mUpload && !mUploadComplete) {
|
if (mUpload && !mUploadComplete) {
|
||||||
DispatchProgressEvent(mUpload, ProgressEventType::loadstart, true,
|
DispatchProgressEvent(mUpload, ProgressEventType::loadstart, true,
|
||||||
0, mUploadTotal);
|
0, mUploadTotal);
|
||||||
|
|||||||
@@ -238,100 +238,34 @@ public:
|
|||||||
private:
|
private:
|
||||||
virtual ~XMLHttpRequestMainThread();
|
virtual ~XMLHttpRequestMainThread();
|
||||||
|
|
||||||
class RequestBody
|
class RequestBodyBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RequestBody() : mType(eUninitialized)
|
virtual nsresult GetAsStream(nsIInputStream** aResult,
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit RequestBody(const ArrayBuffer* aArrayBuffer) : mType(eArrayBuffer)
|
|
||||||
{
|
|
||||||
mValue.mArrayBuffer = aArrayBuffer;
|
|
||||||
}
|
|
||||||
explicit RequestBody(const ArrayBufferView* aArrayBufferView) : mType(eArrayBufferView)
|
|
||||||
{
|
|
||||||
mValue.mArrayBufferView = aArrayBufferView;
|
|
||||||
}
|
|
||||||
explicit RequestBody(Blob& aBlob) : mType(eBlob)
|
|
||||||
{
|
|
||||||
mValue.mBlob = &aBlob;
|
|
||||||
}
|
|
||||||
explicit RequestBody(mozilla::dom::URLSearchParams& aURLSearchParams) :
|
|
||||||
mType(eURLSearchParams)
|
|
||||||
{
|
|
||||||
mValue.mURLSearchParams = &aURLSearchParams;
|
|
||||||
}
|
|
||||||
explicit RequestBody(nsIDocument* aDocument) : mType(eDocument)
|
|
||||||
{
|
|
||||||
mValue.mDocument = aDocument;
|
|
||||||
}
|
|
||||||
explicit RequestBody(const nsAString& aString) : mType(eDOMString)
|
|
||||||
{
|
|
||||||
mValue.mString = &aString;
|
|
||||||
}
|
|
||||||
explicit RequestBody(FormData& aFormData) : mType(eFormData)
|
|
||||||
{
|
|
||||||
mValue.mFormData = &aFormData;
|
|
||||||
}
|
|
||||||
explicit RequestBody(nsIInputStream* aStream) : mType(eInputStream)
|
|
||||||
{
|
|
||||||
mValue.mStream = aStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
eUninitialized,
|
|
||||||
eArrayBuffer,
|
|
||||||
eArrayBufferView,
|
|
||||||
eBlob,
|
|
||||||
eDocument,
|
|
||||||
eDOMString,
|
|
||||||
eFormData,
|
|
||||||
eInputStream,
|
|
||||||
eURLSearchParams
|
|
||||||
};
|
|
||||||
union Value {
|
|
||||||
const ArrayBuffer* mArrayBuffer;
|
|
||||||
const ArrayBufferView* mArrayBufferView;
|
|
||||||
Blob* mBlob;
|
|
||||||
nsIDocument* mDocument;
|
|
||||||
const nsAString* mString;
|
|
||||||
FormData* mFormData;
|
|
||||||
nsIInputStream* mStream;
|
|
||||||
URLSearchParams* mURLSearchParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
Type GetType() const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mType != eUninitialized);
|
|
||||||
return mType;
|
|
||||||
}
|
|
||||||
Value GetValue() const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mType != eUninitialized);
|
|
||||||
return mValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type mType;
|
|
||||||
Value mValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
static nsresult GetRequestBody(nsIVariant* aVariant,
|
|
||||||
const Nullable<RequestBody>& aBody,
|
|
||||||
nsIInputStream** aResult,
|
|
||||||
uint64_t* aContentLength,
|
uint64_t* aContentLength,
|
||||||
nsACString& aContentType,
|
nsACString& aContentType,
|
||||||
nsACString& aCharset);
|
nsACString& aCharset) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(false, "RequestBodyBase should not be used directly.");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
|
template<typename Type>
|
||||||
nsresult Send(const Nullable<RequestBody>& aBody)
|
class RequestBody final : public RequestBodyBase
|
||||||
{
|
{
|
||||||
return Send(nullptr, aBody);
|
Type* mBody;
|
||||||
}
|
public:
|
||||||
nsresult Send(const RequestBody& aBody)
|
explicit RequestBody(Type* aBody) : mBody(aBody)
|
||||||
{
|
{
|
||||||
return Send(Nullable<RequestBody>(aBody));
|
}
|
||||||
}
|
nsresult GetAsStream(nsIInputStream** aResult,
|
||||||
|
uint64_t* aContentLength,
|
||||||
|
nsACString& aContentType,
|
||||||
|
nsACString& aCharset) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult SendInternal(const RequestBodyBase* aBody);
|
||||||
|
|
||||||
bool IsCrossSiteCORSRequest() const;
|
bool IsCrossSiteCORSRequest() const;
|
||||||
bool IsDeniedCrossSiteCORSRequest();
|
bool IsDeniedCrossSiteCORSRequest();
|
||||||
@@ -345,39 +279,44 @@ public:
|
|||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, ErrorResult& aRv) override
|
Send(JSContext* /*aCx*/, ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(Nullable<RequestBody>());
|
aRv = SendInternal(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, const ArrayBuffer& aArrayBuffer,
|
Send(JSContext* /*aCx*/, const ArrayBuffer& aArrayBuffer,
|
||||||
ErrorResult& aRv) override
|
ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(&aArrayBuffer));
|
RequestBody<const ArrayBuffer> body(&aArrayBuffer);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, const ArrayBufferView& aArrayBufferView,
|
Send(JSContext* /*aCx*/, const ArrayBufferView& aArrayBufferView,
|
||||||
ErrorResult& aRv) override
|
ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(&aArrayBufferView));
|
RequestBody<const ArrayBufferView> body(&aArrayBufferView);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, Blob& aBlob, ErrorResult& aRv) override
|
Send(JSContext* /*aCx*/, Blob& aBlob, ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(aBlob));
|
RequestBody<Blob> body(&aBlob);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Send(JSContext* /*aCx*/, URLSearchParams& aURLSearchParams,
|
virtual void Send(JSContext* /*aCx*/, URLSearchParams& aURLSearchParams,
|
||||||
ErrorResult& aRv) override
|
ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(aURLSearchParams));
|
RequestBody<URLSearchParams> body(&aURLSearchParams);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv) override
|
Send(JSContext* /*aCx*/, nsIDocument& aDoc, ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(&aDoc));
|
RequestBody<nsIDocument> body(&aDoc);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
@@ -385,16 +324,17 @@ public:
|
|||||||
{
|
{
|
||||||
if (DOMStringIsNull(aString)) {
|
if (DOMStringIsNull(aString)) {
|
||||||
Send(aCx, aRv);
|
Send(aCx, aRv);
|
||||||
}
|
} else {
|
||||||
else {
|
RequestBody<const nsAString> body(&aString);
|
||||||
aRv = Send(RequestBody(aString));
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Send(JSContext* /*aCx*/, FormData& aFormData, ErrorResult& aRv) override
|
Send(JSContext* /*aCx*/, FormData& aFormData, ErrorResult& aRv) override
|
||||||
{
|
{
|
||||||
aRv = Send(RequestBody(aFormData));
|
RequestBody<FormData> body(&aFormData);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
@@ -418,7 +358,8 @@ public:
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aRv = Send(RequestBody(aStream));
|
RequestBody<nsIInputStream> body(aStream);
|
||||||
|
aRv = SendInternal(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user