Files
palemoon27/dom/base/nsFormData.cpp
T
roytam1 6e0ee8992d import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1189506. Remove no-longer-used TimeVarying.h. r=karlt (8d2cec3e0c)
- Bug 1189506. Set mStartBlocking in UpdateCurrentTimeForStreams to indicate that blocking time has been processed. r=karlt (22495c3d57)
- Bug 1189506. Remove INCLUDE_TRAILING_BLOCKED_INTERVAL from PlayVideo. r=karlt (5b748ce70c)
- Bug 1189506. Call StreamTimeToGraphTime in MediaStreamGraphImpl::UpdateCurrentTimeForStreams, since we know blocking has been taken account of already there. r=karlt (cffde8399d)
- Bug 1189506. Call GraphTimeToStreamTime in DecodedStreamGraphListener::NotifyOutput, since there's no blocking pending there. r=karlt (dd620d1eb5)
- Bug 1189506. Call GraphTimeToStreamTime in AudioNodeExternalInputStream. r=karlt (840ec52c58)
- Bug 1189506. Use GraphTimeToStreamTime in PrepareUpdatesToMainThreadState. r=karlt (5f19765ab5)
- Bug 1189506. Relax assertions a bit. karlt (a75421cc9e)
- Bug 1189506. Make PlayVideo use GraphTimeToStreamTime/StreamTimeToGraphTime and remove StreamTimeToGraphTimeWithBlocking. r=karlt (09e05f2197)
- Bug 1189506. Make PlayAudio use GraphTimeToStreamTime. r=karlt (2e220a691b)
- Bug 1218593 - switch back to the AudioCallbackDriver when there is new audio again. r=padenot (4f8a192db8)
- bug 1217625 remove unused MessageQueue() and document message queue thread access r=padenot (6c1b342c9b)
- bug 1217625 remove declarations of undefined methods r=padenot (989b7691ed)
- Bug 1215699. Ensure that AudioGraphDriver uses the MediaStreamGraph's AudioChannel. r=padenot (455fcf6847)
- Bug 1196451 - tweak comment in nsRefPtr.h to be more clear; r=botond (4838f7b333)
- bug 1214864 - fixup SetCaret() changes on windows (8fbf8a53fb)
- bug 1192353 - make HyperTextProxyAccessibleWrap inherit from (bf4756be27)
- bug 1192330 - move static text change data from HyperTextAccessibleWrap to ia2AccessibleText r=surkov (b10597a5d5)
- Bug 1192330 - remove ia2AccessibleText::GetModifiedText() r=surkov (e24f7208a4)
- bug 1192330 - add ia2AccessibleText::UpdateTextChangeData r=surkov (46ca279dcb)
- bug 120684 may have changed which .cpp files are compiled together in unified builds causing ScreenOrientation.cpp to not compile on Windows, a=bustage, CLOSED TREE (67b5220301)
- bug 120684, add ChromeNodeList so that chrome JS can create proper NodeList objects, r=baku (05a628700c)
- Bug 120684 - use ChromeNodeList in toolkit's listboxes' selectedItems implementation, r=dao,smaug (ee185e34e9)
- Bug 120684 - followup: adjust DOM interface test, implied-r=smaug,bustage (4ca143acf4)
- missing byRef subsitution  of Bug 1207245 - part 3 (97150a9786)
- bug 1217625 add a means to schedule a callback after processing on the graph thread r=padenot (810d14b96b)
- bug 1217625 remove ADD_STREAM_SUSPENDED r=padenot (872586f13d)
- Bug 1216417 - Add logging for audio and video output changes in MSG. r=roc (59bad99c2c)
- align pointer type to FF/TFF (856841ec9b)
- Bug 1152298 - Implement AutoDriver for CanvasCaptureMediaStream. r=mt (b57c7be8be)
- Bug 912342 - Move code MediaOperationTask from .h to .cpp. r=jesup (45a16b4b72)
- Bug 912342 - Change capture resolution. r=jesup (12d7a036c6)
- Bug 912342 - Pass in Audio/VideoDevice in place of Audio/VideoSource. r=jesup (788fced553)
- Bug 1152381 - implement mediaDevices.getSupportedConstraints. r=smaug, r=jesup (04dda577ed)
- Bug 1186198 - s/unexpected/unanticipated/. r=drno (02dab80572)
- Bug 1191296 - Revert use of .includes() to .indexOf() != -1. r=jesup (99234d311b)
- Bug 1181896 - rename .constraintName to .constraint in MediaStreamError r=jesup,bz (7b799900d7)
- Bug 1191298 - don't fail on unknown audio constraints e.g. getUserMedia({ audio: {} }) (regression) r=jesup (8d5b9173a6)
- Bug 1181883 - Add serializer on MediaDeviceInfo. r=smaug (ac6baa26e8)
- Bug 1186209 - Check for VTYPE_EMPTY_ARRAY in enumerateDevices + test. r=jesup (4a158a5d5b)
- Bug 1161615 - Clean up gUM mochitest to use promises. r=mt (8823d4466d)
- Bug 1181896 - make gUM fail w/OverconstrainedError and candidate argument r=jesup (a146b6150f)
- Bug 912342 - Move code SelectSettings to MediaConstraintsHelper. r=jesup (3bfe2277bc)
- Bug 1195951 - fix heap type on stack error in MediaUtils' Pledge class. r=jesup (0a4ab1f26f)
- Bug 912342 - get Promise out. r=jesup (983b58ce56)
- Bug 1170958 - Refactor DOMMediaStream to contain a 3-stage track chain. r=roc (ae86da997c)
- bug 1210267 remove custom AudioParam::Release and disconnect in destructor r=baku (16b7be9ddc)
- Bug 1192170 - Remove media capture indicator when all tracks have ended. r=jib (d9864efcaf)
- Bug 1103188 - Always call MediaManager::NotifyFinished/NotifyRemoved on main thread. r=jib (5754c8c562)
- Bug 1103188 - Keep track of capture stop only in gUM stream listener. r=jib (7759b218f7)
- Bug 1103188 - Keep track of stopped tracks in gUM stream listener. r=jib (97b176edb5)
- Bug 1210852 - do SelectSettings of device capabilities on media thread. r=jesup (b2b2eb0374)
- Bug 1213738 - media::NewRunnableFrom() and media::NewTaskFrom() move lambda arg instead of copying it. r=jesup (0e73aef22b)
- Bug 1213738 - media::Pledge.Then() moves lambda args instead of copying them. r=jesup (07a9dcb150)
- and convert back some malloc/realloc/free to use the one with moz_ prefix
2022-10-19 10:33:24 +08:00

315 lines
8.6 KiB
C++

/* -*- 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/. */
#include "nsFormData.h"
#include "nsIVariant.h"
#include "nsIInputStream.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "MultipartBlobImpl.h"
using namespace mozilla;
using namespace mozilla::dom;
nsFormData::nsFormData(nsISupports* aOwner)
: nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
, mOwner(aOwner)
{
}
namespace {
// Implements steps 3 and 4 of the "create an entry" algorithm of FormData.
already_AddRefed<File>
CreateNewFileInstance(Blob& aBlob, const Optional<nsAString>& aFilename)
{
// Step 3 "If value is a Blob object and not a File object, set value to
// a new File object, representing the same bytes, whose name attribute value
// is "blob"."
// Step 4 "If value is a File object and filename is given, set value to
// a new File object, representing the same bytes, whose name attribute
// value is filename."
nsAutoString filename;
if (aFilename.WasPassed()) {
filename = aFilename.Value();
} else {
// If value is already a File and filename is not passed, the spec says not
// to create a new instance.
RefPtr<File> file = aBlob.ToFile();
if (file) {
return file.forget();
}
filename = NS_LITERAL_STRING("blob");
}
return aBlob.ToFile(filename);
}
} // anonymous namespace
// -------------------------------------------------------------------------
// nsISupports
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormData)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue,
"mFormData[i].fileValue", 0);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsFormData)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormData)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormData)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFormData)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMFormData)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormData)
NS_INTERFACE_MAP_END
// -------------------------------------------------------------------------
// nsFormSubmission
nsresult
nsFormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
{
NS_NOTREACHED("Shouldn't call nsFormData::GetEncodedSubmission");
return NS_OK;
}
void
nsFormData::Append(const nsAString& aName, const nsAString& aValue)
{
AddNameValuePair(aName, aValue);
}
void
nsFormData::Append(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename)
{
RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename);
AddNameFilePair(aName, file);
}
void
nsFormData::Delete(const nsAString& aName)
{
// We have to use this slightly awkward for loop since uint32_t >= 0 is an
// error for being always true.
for (uint32_t i = mFormData.Length(); i-- > 0; ) {
if (aName.Equals(mFormData[i].name)) {
mFormData.RemoveElementAt(i);
}
}
}
void
nsFormData::ExtractValue(const FormDataTuple& aTuple,
OwningFileOrUSVString* aOutValue)
{
if (aTuple.valueIsFile) {
aOutValue->SetAsFile() = aTuple.fileValue;
} else {
aOutValue->SetAsUSVString() = aTuple.stringValue;
}
}
void
nsFormData::Get(const nsAString& aName,
Nullable<OwningFileOrUSVString>& aOutValue)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) {
ExtractValue(mFormData[i], &aOutValue.SetValue());
return;
}
}
aOutValue.SetNull();
}
void
nsFormData::GetAll(const nsAString& aName,
nsTArray<OwningFileOrUSVString>& aValues)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) {
OwningFileOrUSVString* element = aValues.AppendElement();
ExtractValue(mFormData[i], element);
}
}
}
bool
nsFormData::Has(const nsAString& aName)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) {
return true;
}
}
return false;
}
nsresult
nsFormData::AddNameFilePair(const nsAString& aName, File* aFile)
{
FormDataTuple* data = mFormData.AppendElement();
SetNameFilePair(data, aName, aFile);
return NS_OK;
}
nsFormData::FormDataTuple*
nsFormData::RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName)
{
FormDataTuple* lastFoundTuple = nullptr;
uint32_t lastFoundIndex = mFormData.Length();
// We have to use this slightly awkward for loop since uint32_t >= 0 is an
// error for being always true.
for (uint32_t i = mFormData.Length(); i-- > 0; ) {
if (aName.Equals(mFormData[i].name)) {
if (lastFoundTuple) {
// The one we found earlier was not the first one, we can remove it.
mFormData.RemoveElementAt(lastFoundIndex);
}
lastFoundTuple = &mFormData[i];
lastFoundIndex = i;
}
}
return lastFoundTuple;
}
void
nsFormData::Set(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename)
{
FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
if (tuple) {
RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename);
SetNameFilePair(tuple, aName, file);
} else {
Append(aName, aBlob, aFilename);
}
}
void
nsFormData::Set(const nsAString& aName, const nsAString& aValue)
{
FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
if (tuple) {
SetNameValuePair(tuple, aName, aValue);
} else {
Append(aName, aValue);
}
}
// -------------------------------------------------------------------------
// nsIDOMFormData
NS_IMETHODIMP
nsFormData::Append(const nsAString& aName, nsIVariant* aValue)
{
uint16_t dataType;
nsresult rv = aValue->GetDataType(&dataType);
NS_ENSURE_SUCCESS(rv, rv);
if (dataType == nsIDataType::VTYPE_INTERFACE ||
dataType == nsIDataType::VTYPE_INTERFACE_IS) {
nsCOMPtr<nsISupports> supports;
nsID *iid;
rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
NS_ENSURE_SUCCESS(rv, rv);
moz_free(iid);
nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports);
RefPtr<Blob> blob = static_cast<Blob*>(domBlob.get());
if (domBlob) {
Optional<nsAString> temp;
Append(aName, *blob, temp);
return NS_OK;
}
}
char16_t* stringData = nullptr;
uint32_t stringLen = 0;
rv = aValue->GetAsWStringWithSize(&stringLen, &stringData);
NS_ENSURE_SUCCESS(rv, rv);
nsString valAsString;
valAsString.Adopt(stringData, stringLen);
Append(aName, valAsString);
return NS_OK;
}
/* virtual */ JSObject*
nsFormData::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return FormDataBinding::Wrap(aCx, this, aGivenProto);
}
/* static */ already_AddRefed<nsFormData>
nsFormData::Constructor(const GlobalObject& aGlobal,
const Optional<NonNull<HTMLFormElement> >& aFormElement,
ErrorResult& aRv)
{
RefPtr<nsFormData> formData = new nsFormData(aGlobal.GetAsSupports());
if (aFormElement.WasPassed()) {
aRv = aFormElement.Value().WalkFormElements(formData);
}
return formData.forget();
}
// -------------------------------------------------------------------------
// nsIXHRSendable
NS_IMETHODIMP
nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsACString& aContentType, nsACString& aCharset)
{
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (mFormData[i].valueIsFile) {
fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue);
}
else {
fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue);
}
}
fs.GetContentType(aContentType);
aCharset.Truncate();
*aContentLength = 0;
NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));
return NS_OK;
}