Bug 544698 part 4: Move the creation of the encoder to the nsFormSubmission ctor. Move the call to linkHandler->OnLinkClickSync to the nsHTMLFormElement. r=jst

This commit is contained in:
Jonas Sicking 2010-02-24 21:58:17 -08:00
parent 8af720df7e
commit 2163564df4
3 changed files with 66 additions and 129 deletions

View File

@ -61,21 +61,6 @@ class nsFormSubmission {
public: public:
virtual ~nsFormSubmission(); virtual ~nsFormSubmission();
/**
* Call to perform the submission
*
* @param aActionURL the URL to submit to (may be modified with GET contents)
* @param aTarget the target window
* @param aSource the element responsible for the submission (for web shell)
* @param aLinkHandler the link handler to use
* @param aDocShell (out param) the DocShell in which the submission was
* loaded
* @param aRequest (out param) the Request for the submission
*/
nsresult SubmitTo(nsIURI* aActionURI, const nsAString& aTarget,
nsIContent* aSource, nsILinkHandler* aLinkHandler,
nsIDocShell** aDocShell, nsIRequest** aRequest);
/** /**
* Submit a name/value pair * Submit a name/value pair
* *
@ -94,6 +79,16 @@ public:
virtual nsresult AddNameFilePair(const nsAString& aName, virtual nsresult AddNameFilePair(const nsAString& aName,
nsIFile* aFile) = 0; nsIFile* aFile) = 0;
/**
* Given a URI and the current submission, create the final URI and data
* stream that will be submitted. Subclasses *must* implement this.
*
* @param aURI the URI being submitted to [INOUT]
* @param aPostDataStream a data stream for POST data [OUT]
*/
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) = 0;
/** /**
* Get the charset that will be used for submission. * Get the charset that will be used for submission.
*/ */
@ -107,24 +102,11 @@ protected:
* Can only be constructed by subclasses. * Can only be constructed by subclasses.
* *
* @param aCharset the charset of the form as a string * @param aCharset the charset of the form as a string
* @param aEncoder an encoder that will encode Unicode names and values into
* bytes to be sent over the wire (usually a charset transformation)
* @param aBidiOptions the BIDI options flags for the current pres context * @param aBidiOptions the BIDI options flags for the current pres context
*/ */
nsFormSubmission(const nsACString& aCharset, nsFormSubmission(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions); PRInt32 aBidiOptions);
/**
* Given a URI and the current submission, create the final URI and data
* stream that will be submitted. Subclasses *must* implement this.
*
* @param aURI the URI being submitted to [INOUT]
* @param aPostDataStream a data stream for POST data [OUT]
*/
NS_IMETHOD GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) = 0;
/** /**
* Encode a Unicode string to bytes using the encoder (or just copy the input * Encode a Unicode string to bytes using the encoder (or just copy the input
* if there is no encoder). * if there is no encoder).
@ -141,8 +123,7 @@ protected:
* @param aOut the encoded string [OUT] * @param aOut the encoded string [OUT]
* @throws an error if the encoder fails * @throws an error if the encoder fails
*/ */
nsresult UnicodeToNewBytes(const nsAString& aStr, nsISaveAsCharset* aEncoder, nsresult UnicodeToNewBytes(const nsAString& aStr, nsACString& aOut);
nsACString& aOut);
// The name of the encoder charset // The name of the encoder charset
nsCString mCharset; nsCString mCharset;

View File

@ -95,18 +95,15 @@ class nsFSURLEncoded : public nsFormSubmission
public: public:
/** /**
* @param aCharset the charset of the form as a string * @param aCharset the charset of the form as a string
* @param aEncoder an encoder that will encode Unicode names and values into
* bytes to be sent over the wire (usually a charset transformation)
* @param aBidiOptions the BIDI options flags for the current pres context * @param aBidiOptions the BIDI options flags for the current pres context
* @param aMethod the method of the submit (either NS_FORM_METHOD_GET or * @param aMethod the method of the submit (either NS_FORM_METHOD_GET or
* NS_FORM_METHOD_POST). * NS_FORM_METHOD_POST).
*/ */
nsFSURLEncoded(const nsACString& aCharset, nsFSURLEncoded(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions, PRInt32 aBidiOptions,
PRInt32 aMethod, PRInt32 aMethod,
nsIDocument* aDocument) nsIDocument* aDocument)
: nsFormSubmission(aCharset, aEncoder, aBidiOptions), : nsFormSubmission(aCharset, aBidiOptions),
mMethod(aMethod), mMethod(aMethod),
mDocument(aDocument), mDocument(aDocument),
mWarnedFileControl(PR_FALSE) mWarnedFileControl(PR_FALSE)
@ -117,10 +114,10 @@ public:
const nsAString& aValue); const nsAString& aValue);
virtual nsresult AddNameFilePair(const nsAString& aName, virtual nsresult AddNameFilePair(const nsAString& aName,
nsIFile* aFile); nsIFile* aFile);
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream);
protected: protected:
NS_IMETHOD GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream);
/** /**
* URL encode a Unicode string by encoding it to bytes, converting linebreaks * URL encode a Unicode string by encoding it to bytes, converting linebreaks
@ -259,7 +256,7 @@ HandleMailtoSubject(nsCString& aPath) {
} }
} }
NS_IMETHODIMP nsresult
nsFSURLEncoded::GetEncodedSubmission(nsIURI* aURI, nsFSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) nsIInputStream** aPostDataStream)
{ {
@ -394,22 +391,19 @@ class nsFSMultipartFormData : public nsFormSubmission
public: public:
/** /**
* @param aCharset the charset of the form as a string * @param aCharset the charset of the form as a string
* @param aEncoder an encoder that will encode Unicode names and values into
* bytes to be sent over the wire (usually a charset transformation)
* @param aBidiOptions the BIDI options flags for the current pres context * @param aBidiOptions the BIDI options flags for the current pres context
*/ */
nsFSMultipartFormData(const nsACString& aCharset, nsFSMultipartFormData(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions); PRInt32 aBidiOptions);
virtual nsresult AddNameValuePair(const nsAString& aName, virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue); const nsAString& aValue);
virtual nsresult AddNameFilePair(const nsAString& aName, virtual nsresult AddNameFilePair(const nsAString& aName,
nsIFile* aFile); nsIFile* aFile);
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream);
protected: protected:
NS_IMETHOD GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream);
/** /**
* Roll up the data we have so far and add it to the multiplexed data stream. * Roll up the data we have so far and add it to the multiplexed data stream.
@ -442,9 +436,8 @@ private:
}; };
nsFSMultipartFormData::nsFSMultipartFormData(const nsACString& aCharset, nsFSMultipartFormData::nsFSMultipartFormData(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions) PRInt32 aBidiOptions)
: nsFormSubmission(aCharset, aEncoder, aBidiOptions) : nsFormSubmission(aCharset, aBidiOptions)
{ {
mPostDataStream = mPostDataStream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
@ -572,7 +565,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsresult
nsFSMultipartFormData::GetEncodedSubmission(nsIURI* aURI, nsFSMultipartFormData::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) nsIInputStream** aPostDataStream)
{ {
@ -628,9 +621,8 @@ class nsFSTextPlain : public nsFormSubmission
{ {
public: public:
nsFSTextPlain(const nsACString& aCharset, nsFSTextPlain(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions) PRInt32 aBidiOptions)
: nsFormSubmission(aCharset, aEncoder, aBidiOptions) : nsFormSubmission(aCharset, aBidiOptions)
{ {
} }
@ -638,9 +630,7 @@ public:
const nsAString& aValue); const nsAString& aValue);
virtual nsresult AddNameFilePair(const nsAString& aName, virtual nsresult AddNameFilePair(const nsAString& aName,
nsIFile* aFile); nsIFile* aFile);
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
protected:
NS_IMETHOD GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream); nsIInputStream** aPostDataStream);
private: private:
@ -673,7 +663,7 @@ nsFSTextPlain::AddNameFilePair(const nsAString& aName,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsresult
nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI, nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) nsIInputStream** aPostDataStream)
{ {
@ -728,13 +718,37 @@ nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
nsFormSubmission::nsFormSubmission(const nsACString& aCharset, nsFormSubmission::nsFormSubmission(const nsACString& aCharset,
nsISaveAsCharset* aEncoder,
PRInt32 aBidiOptions) PRInt32 aBidiOptions)
: mCharset(aCharset), : mCharset(aCharset),
mEncoder(aEncoder),
mBidiOptions(aBidiOptions) mBidiOptions(aBidiOptions)
{ {
MOZ_COUNT_CTOR(nsFormSubmission); MOZ_COUNT_CTOR(nsFormSubmission);
nsCAutoString charset(aCharset);
// canonical name is passed so that we just have to check against
// *our* canonical names listed in charsetaliases.properties
if (charset.EqualsLiteral("ISO-8859-1")) {
charset.AssignLiteral("windows-1252");
}
// use UTF-8 for UTF-16* and UTF-32* (per WHATWG and existing practice of
// MS IE/Opera).
if (StringBeginsWith(charset, NS_LITERAL_CSTRING("UTF-16")) ||
StringBeginsWith(charset, NS_LITERAL_CSTRING("UTF-32"))) {
charset.AssignLiteral("UTF-8");
}
mEncoder = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID);
if (mEncoder) {
nsresult rv =
mEncoder->Init(charset.get(),
(nsISaveAsCharset::attr_EntityAfterCharsetConv +
nsISaveAsCharset::attr_FallbackDecimalNCR),
0);
if (NS_FAILED(rv)) {
mEncoder = nsnull;
}
}
} }
nsFormSubmission::~nsFormSubmission() nsFormSubmission::~nsFormSubmission()
@ -742,31 +756,9 @@ nsFormSubmission::~nsFormSubmission()
MOZ_COUNT_DTOR(nsFormSubmission); MOZ_COUNT_DTOR(nsFormSubmission);
} }
nsresult
nsFormSubmission::SubmitTo(nsIURI* aActionURI, const nsAString& aTarget,
nsIContent* aSource, nsILinkHandler* aLinkHandler,
nsIDocShell** aDocShell, nsIRequest** aRequest)
{
nsresult rv;
// Finish encoding (get post data stream and URI)
nsCOMPtr<nsIInputStream> postDataStream;
rv = GetEncodedSubmission(aActionURI, getter_AddRefs(postDataStream));
NS_ENSURE_SUCCESS(rv, rv);
// Actually submit the data
NS_ENSURE_ARG_POINTER(aLinkHandler);
return aLinkHandler->OnLinkClickSync(aSource, aActionURI,
PromiseFlatString(aTarget).get(),
postDataStream, nsnull,
aDocShell, aRequest);
}
// i18n helper routines // i18n helper routines
nsresult nsresult
nsFormSubmission::UnicodeToNewBytes(const nsAString& aStr, nsFormSubmission::UnicodeToNewBytes(const nsAString& aStr,
nsISaveAsCharset* aEncoder,
nsACString& aOut) nsACString& aOut)
{ {
PRUint8 ctrlsModAtSubmit = GET_BIDI_OPTION_CONTROLSTEXTMODE(mBidiOptions); PRUint8 ctrlsModAtSubmit = GET_BIDI_OPTION_CONTROLSTEXTMODE(mBidiOptions);
@ -820,7 +812,7 @@ nsFormSubmission::UnicodeToNewBytes(const nsAString& aStr,
nsXPIDLCString res; nsXPIDLCString res;
if (!newBuffer.IsEmpty()) { if (!newBuffer.IsEmpty()) {
aOut.Truncate(); aOut.Truncate();
nsresult rv = aEncoder->Convert(newBuffer.get(), getter_Copies(res)); nsresult rv = mEncoder->Convert(newBuffer.get(), getter_Copies(res));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
@ -831,9 +823,8 @@ nsFormSubmission::UnicodeToNewBytes(const nsAString& aStr,
nsresult nsresult
nsFormSubmission::EncodeVal(const nsAString& aStr, nsACString& aOut) nsFormSubmission::EncodeVal(const nsAString& aStr, nsACString& aOut)
{ {
NS_ASSERTION(mEncoder, "Encoder not available. Losing data !");
if (mEncoder) if (mEncoder)
return UnicodeToNewBytes(aStr, mEncoder, aOut); return UnicodeToNewBytes(aStr, aOut);
// fall back to UTF-8 // fall back to UTF-8
CopyUTF16toUTF8(aStr, aOut); CopyUTF16toUTF8(aStr, aOut);
@ -909,42 +900,6 @@ GetSubmitCharset(nsGenericHTMLElement* aForm,
} }
} }
static nsresult
GetEncoder(nsGenericHTMLElement* aForm,
const nsACString& aCharset,
nsISaveAsCharset** aEncoder)
{
*aEncoder = nsnull;
nsresult rv = NS_OK;
nsCAutoString charset(aCharset);
// canonical name is passed so that we just have to check against
// *our* canonical names listed in charsetaliases.properties
if (charset.EqualsLiteral("ISO-8859-1")) {
charset.AssignLiteral("windows-1252");
}
// use UTF-8 for UTF-16* and UTF-32* (per WHATWG and existing practice of
// MS IE/Opera).
if (StringBeginsWith(charset, NS_LITERAL_CSTRING("UTF-16")) ||
StringBeginsWith(charset, NS_LITERAL_CSTRING("UTF-32"))) {
charset.AssignLiteral("UTF-8");
}
rv = CallCreateInstance( NS_SAVEASCHARSET_CONTRACTID, aEncoder);
NS_ASSERTION(NS_SUCCEEDED(rv), "create nsISaveAsCharset failed");
NS_ENSURE_SUCCESS(rv, rv);
rv = (*aEncoder)->Init(charset.get(),
(nsISaveAsCharset::attr_EntityAfterCharsetConv +
nsISaveAsCharset::attr_FallbackDecimalNCR),
0);
NS_ASSERTION(NS_SUCCEEDED(rv), "initialize nsISaveAsCharset failed");
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
static void static void
GetEnumAttr(nsGenericHTMLElement* aContent, GetEnumAttr(nsGenericHTMLElement* aContent,
nsIAtom* atom, PRInt32* aValue) nsIAtom* atom, PRInt32* aValue)
@ -980,18 +935,13 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
nsCAutoString charset; nsCAutoString charset;
GetSubmitCharset(aForm, ctrlsModAtSubmit, charset); GetSubmitCharset(aForm, ctrlsModAtSubmit, charset);
// Get unicode encoder
nsCOMPtr<nsISaveAsCharset> encoder;
GetEncoder(aForm, charset, getter_AddRefs(encoder));
// Choose encoder // Choose encoder
if (method == NS_FORM_METHOD_POST && if (method == NS_FORM_METHOD_POST &&
enctype == NS_FORM_ENCTYPE_MULTIPART) { enctype == NS_FORM_ENCTYPE_MULTIPART) {
*aFormSubmission = new nsFSMultipartFormData(charset, encoder, *aFormSubmission = new nsFSMultipartFormData(charset, bidiOptions);
bidiOptions);
} else if (method == NS_FORM_METHOD_POST && } else if (method == NS_FORM_METHOD_POST &&
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) { enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
*aFormSubmission = new nsFSTextPlain(charset, encoder, bidiOptions); *aFormSubmission = new nsFSTextPlain(charset, bidiOptions);
} else { } else {
if (enctype == NS_FORM_ENCTYPE_MULTIPART || if (enctype == NS_FORM_ENCTYPE_MULTIPART ||
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) { enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
@ -1001,7 +951,7 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
SendJSWarning(aForm->GetOwnerDoc(), "ForgotPostWarning", SendJSWarning(aForm->GetOwnerDoc(), "ForgotPostWarning",
&enctypeStrPtr, 1); &enctypeStrPtr, 1);
} }
*aFormSubmission = new nsFSURLEncoded(charset, encoder, bidiOptions, *aFormSubmission = new nsFSURLEncoded(charset, bidiOptions,
method, aForm->GetOwnerDoc()); method, aForm->GetOwnerDoc());
} }
NS_ENSURE_TRUE(*aFormSubmission, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(*aFormSubmission, NS_ERROR_OUT_OF_MEMORY);

View File

@ -856,12 +856,18 @@ nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput, PR_FALSE); nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput, PR_FALSE);
rv = aFormSubmission->SubmitTo(actionURI, target, this, linkHandler, nsCOMPtr<nsIInputStream> postDataStream;
rv = aFormSubmission->GetEncodedSubmission(actionURI,
getter_AddRefs(postDataStream));
NS_ENSURE_SUBMIT_SUCCESS(rv);
rv = linkHandler->OnLinkClickSync(this, actionURI,
target.get(),
postDataStream, nsnull,
getter_AddRefs(docShell), getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest)); getter_AddRefs(mSubmittingRequest));
}
NS_ENSURE_SUBMIT_SUCCESS(rv); NS_ENSURE_SUBMIT_SUCCESS(rv);
}
// Even if the submit succeeds, it's possible for there to be no docshell // Even if the submit succeeds, it's possible for there to be no docshell
// or request; for example, if it's to a named anchor within the same page // or request; for example, if it's to a named anchor within the same page