Bug 1285036 - Part 9: Clean up the XHR send() API endpoints, and how nsIVariants are handled. r=baku

This commit is contained in:
Thomas Wisniewski
2016-07-21 00:36:26 -04:00
parent fd7c2e2702
commit 81ceac77cc
2 changed files with 230 additions and 350 deletions

View File

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

View File

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