Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / html / HTMLFormSubmission.h
blob7e4d3a0e4e3e8ffc24049ed28e5116f69039b558
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_HTMLFormSubmission_h
8 #define mozilla_dom_HTMLFormSubmission_h
10 #include "mozilla/Attributes.h"
11 #include "mozilla/dom/UserActivation.h"
12 #include "mozilla/dom/HTMLDialogElement.h"
13 #include "nsCOMPtr.h"
14 #include "mozilla/Encoding.h"
15 #include "nsString.h"
17 class nsIURI;
18 class nsIInputStream;
19 class nsGenericHTMLElement;
20 class nsIMultiplexInputStream;
22 namespace mozilla::dom {
24 class Blob;
25 class DialogFormSubmission;
26 class Directory;
27 class Element;
28 class HTMLFormElement;
30 /**
31 * Class for form submissions; encompasses the function to call to submit as
32 * well as the form submission name/value pairs
34 class HTMLFormSubmission {
35 public:
36 /**
37 * Get a submission object based on attributes in the form (ENCTYPE and
38 * METHOD)
40 * @param aForm the form to get a submission object based on
41 * @param aSubmitter the submitter element (can be null)
42 * @param aEncoding the submiter element's encoding
43 * @param aFormSubmission the form submission object (out param)
45 static nsresult GetFromForm(HTMLFormElement* aForm,
46 nsGenericHTMLElement* aSubmitter,
47 NotNull<const Encoding*>& aEncoding,
48 HTMLFormSubmission** aFormSubmission);
50 MOZ_COUNTED_DTOR_VIRTUAL(HTMLFormSubmission)
52 /**
53 * Submit a name/value pair
55 * @param aName the name of the parameter
56 * @param aValue the value of the parameter
58 virtual nsresult AddNameValuePair(const nsAString& aName,
59 const nsAString& aValue) = 0;
61 /**
62 * Submit a name/blob pair
64 * @param aName the name of the parameter
65 * @param aBlob the blob to submit. The file's name will be used if the Blob
66 * is actually a File, otherwise 'blob' string is used instead. Must not be
67 * null.
69 virtual nsresult AddNameBlobPair(const nsAString& aName, Blob* aBlob) = 0;
71 /**
72 * Submit a name/directory pair
74 * @param aName the name of the parameter
75 * @param aBlob the directory to submit.
77 virtual nsresult AddNameDirectoryPair(const nsAString& aName,
78 Directory* aDirectory) = 0;
80 /**
81 * Given a URI and the current submission, create the final URI and data
82 * stream that will be submitted. Subclasses *must* implement this.
84 * @param aURI the URI being submitted to [IN]
85 * @param aPostDataStream a data stream for POST data [OUT]
86 * @param aOutURI the resulting URI. May be the same as aURI [OUT]
88 virtual nsresult GetEncodedSubmission(nsIURI* aURI,
89 nsIInputStream** aPostDataStream,
90 nsCOMPtr<nsIURI>& aOutURI) = 0;
92 /**
93 * Get the charset that will be used for submission.
95 void GetCharset(nsACString& aCharset) { mEncoding->Name(aCharset); }
97 /**
98 * Get the action URI that will be used for submission.
100 nsIURI* GetActionURL() const { return mActionURL; }
103 * Get the target that will be used for submission.
105 void GetTarget(nsAString& aTarget) { aTarget = mTarget; }
108 * Return true if this form submission was user-initiated.
110 bool IsInitiatedFromUserInput() const { return mInitiatedFromUserInput; }
112 virtual DialogFormSubmission* GetAsDialogSubmission() { return nullptr; }
114 protected:
116 * Can only be constructed by subclasses.
118 * @param aEncoding the character encoding of the form
120 HTMLFormSubmission(nsIURI* aActionURL, const nsAString& aTarget,
121 mozilla::NotNull<const mozilla::Encoding*> aEncoding);
123 // The action url.
124 nsCOMPtr<nsIURI> mActionURL;
126 // The target.
127 nsString mTarget;
129 // The character encoding of this form submission
130 mozilla::NotNull<const mozilla::Encoding*> mEncoding;
132 // Keep track of whether this form submission was user-initiated or not
133 bool mInitiatedFromUserInput;
136 class EncodingFormSubmission : public HTMLFormSubmission {
137 public:
138 EncodingFormSubmission(nsIURI* aActionURL, const nsAString& aTarget,
139 mozilla::NotNull<const mozilla::Encoding*> aEncoding,
140 Element* aSubmitter);
142 virtual ~EncodingFormSubmission();
144 // Indicates the type of newline normalization and escaping to perform in
145 // `EncodeVal`, in addition to encoding the string into bytes.
146 enum EncodeType {
147 // Normalizes newlines to CRLF and then escapes for use in
148 // `Content-Disposition`. (Useful for `multipart/form-data` entry names.)
149 eNameEncode,
150 // Escapes for use in `Content-Disposition`. (Useful for
151 // `multipart/form-data` filenames.)
152 eFilenameEncode,
153 // Normalizes newlines to CRLF.
154 eValueEncode,
158 * Encode a Unicode string to bytes, additionally performing escapes or
159 * normalizations.
160 * @param aStr the string to encode
161 * @param aOut the encoded string [OUT]
162 * @param aEncodeType The type of escapes or normalizations to perform on the
163 * encoded string.
164 * @throws an error if UnicodeToNewBytes fails
166 nsresult EncodeVal(const nsAString& aStr, nsCString& aOut,
167 EncodeType aEncodeType);
170 class DialogFormSubmission final : public HTMLFormSubmission {
171 public:
172 DialogFormSubmission(nsAString& aResult, NotNull<const Encoding*> aEncoding,
173 HTMLDialogElement* aDialogElement)
174 : HTMLFormSubmission(nullptr, u""_ns, aEncoding),
175 mDialogElement(aDialogElement),
176 mReturnValue(aResult) {}
177 nsresult AddNameValuePair(const nsAString& aName,
178 const nsAString& aValue) override {
179 MOZ_CRASH("This method should not be called");
180 return NS_OK;
183 nsresult AddNameBlobPair(const nsAString& aName, Blob* aBlob) override {
184 MOZ_CRASH("This method should not be called");
185 return NS_OK;
188 nsresult AddNameDirectoryPair(const nsAString& aName,
189 Directory* aDirectory) override {
190 MOZ_CRASH("This method should not be called");
191 return NS_OK;
194 nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream,
195 nsCOMPtr<nsIURI>& aOutURI) override {
196 MOZ_CRASH("This method should not be called");
197 return NS_OK;
200 DialogFormSubmission* GetAsDialogSubmission() override { return this; }
202 HTMLDialogElement* DialogElement() { return mDialogElement; }
204 nsString& ReturnValue() { return mReturnValue; }
206 private:
207 const RefPtr<HTMLDialogElement> mDialogElement;
208 nsString mReturnValue;
212 * Handle multipart/form-data encoding, which does files as well as normal
213 * inputs. This always does POST.
215 class FSMultipartFormData : public EncodingFormSubmission {
216 public:
218 * @param aEncoding the character encoding of the form
220 FSMultipartFormData(nsIURI* aActionURL, const nsAString& aTarget,
221 mozilla::NotNull<const mozilla::Encoding*> aEncoding,
222 Element* aSubmitter);
223 ~FSMultipartFormData();
225 virtual nsresult AddNameValuePair(const nsAString& aName,
226 const nsAString& aValue) override;
228 virtual nsresult AddNameBlobPair(const nsAString& aName,
229 Blob* aBlob) override;
231 virtual nsresult AddNameDirectoryPair(const nsAString& aName,
232 Directory* aDirectory) override;
234 virtual nsresult GetEncodedSubmission(nsIURI* aURI,
235 nsIInputStream** aPostDataStream,
236 nsCOMPtr<nsIURI>& aOutURI) override;
238 void GetContentType(nsACString& aContentType) {
239 aContentType = "multipart/form-data; boundary="_ns + mBoundary;
242 nsIInputStream* GetSubmissionBody(uint64_t* aContentLength);
244 protected:
246 * Roll up the data we have so far and add it to the multiplexed data stream.
248 nsresult AddPostDataStream();
250 private:
251 void AddDataChunk(const nsACString& aName, const nsACString& aFilename,
252 const nsACString& aContentType,
253 nsIInputStream* aInputStream, uint64_t aInputStreamSize);
255 * The post data stream as it is so far. This is a collection of smaller
256 * chunks--string streams and file streams interleaved to make one big POST
257 * stream.
259 nsCOMPtr<nsIMultiplexInputStream> mPostData;
262 * The same stream, but as an nsIInputStream.
263 * Raw pointers because it is just QI of mInputStream.
265 nsIInputStream* mPostDataStream;
268 * The current string chunk. When a file is hit, the string chunk gets
269 * wrapped up into an input stream and put into mPostDataStream so that the
270 * file input stream can then be appended and everything is in the right
271 * order. Then the string chunk gets appended to again as we process more
272 * name/value pairs.
274 nsCString mPostDataChunk;
277 * The boundary string to use after each "part" (the boundary that marks the
278 * end of a value). This is computed randomly and is different for each
279 * submission.
281 nsCString mBoundary;
284 * The total length in bytes of the streams that make up mPostDataStream
286 uint64_t mTotalLength;
289 } // namespace mozilla::dom
291 #endif /* mozilla_dom_HTMLFormSubmission_h */