Bug 690659 - Add the optional filename parameter to the FormData.append method. r=sicking
authorTom Schuster <evilpies@gmail.com>
Sun, 03 Mar 2013 19:30:13 +0100
changeset 134842 1370add87e777e4fc5c2624713135b2f392682ee
parent 134841 d6c2521c8f6f24068b8997a92e2ea0b3d8ce3f3e
child 134843 9f4e7e70cd69010bb9083c7c5d8611b8f79b8904
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs690659
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 690659 - Add the optional filename parameter to the FormData.append method. r=sicking
content/base/src/nsFormData.cpp
content/base/src/nsFormData.h
content/html/content/public/nsFormSubmission.h
content/html/content/src/nsFormSubmission.cpp
content/html/content/src/nsHTMLInputElement.cpp
dom/webidl/FormData.webidl
--- a/content/base/src/nsFormData.cpp
+++ b/content/base/src/nsFormData.cpp
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsFormData.h"
 #include "nsIVariant.h"
 #include "nsIInputStream.h"
 #include "nsIDOMFile.h"
 #include "nsHTMLFormElement.h"
 #include "mozilla/dom/FormDataBinding.h"
-#include "mozilla/dom/BindingUtils.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsFormData::nsFormData(nsISupports* aOwner)
   : nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
   , mOwner(aOwner)
@@ -42,29 +41,30 @@ nsFormData::GetEncodedSubmission(nsIURI*
 {
   NS_NOTREACHED("Shouldn't call nsFormData::GetEncodedSubmission");
   return NS_OK;
 }
 
 void
 nsFormData::Append(const nsAString& aName, const nsAString& aValue)
 {
-  FormDataTuple* data = mFormData.AppendElement();
-  data->name = aName;
-  data->stringValue = aValue;
-  data->valueIsFile = false;
+  AddNameValuePair(aName, aValue);
 }
 
 void
-nsFormData::Append(const nsAString& aName, nsIDOMBlob* aBlob)
+nsFormData::Append(const nsAString& aName, nsIDOMBlob* aBlob,
+                   const Optional<nsAString>& aFilename)
 {
-  FormDataTuple* data = mFormData.AppendElement();
-  data->name = aName;
-  data->fileValue = aBlob;
-  data->valueIsFile = true;
+  nsString filename;
+  if (aFilename.WasPassed()) {
+    filename = aFilename.Value();
+  } else {
+    filename.SetIsVoid(true);
+  }
+  AddNameFilePair(aName, aBlob, filename);
 }
 
 // -------------------------------------------------------------------------
 // nsIDOMFormData
 
 NS_IMETHODIMP
 nsFormData::Append(const nsAString& aName, nsIVariant* aValue)
 {
@@ -78,17 +78,17 @@ nsFormData::Append(const nsAString& aNam
     nsID *iid;
     rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsMemory::Free(iid);
 
     nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports);
     if (domBlob) {
-      Append(aName, domBlob);
+      Append(aName, domBlob, Optional<nsAString>());
       return NS_OK;
     }
   }
 
   PRUnichar* stringData = nullptr;
   uint32_t stringLen = 0;
   rv = aValue->GetAsWStringWithSize(&stringLen, &stringData);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -122,20 +122,21 @@ nsFormData::Constructor(const GlobalObje
 // -------------------------------------------------------------------------
 // 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);
+      fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue,
+                         mFormData[i].filename);
     }
     else {
       fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue);
     }
   }
 
   fs.GetContentType(aContentType);
   aCharset.Truncate();
--- a/content/base/src/nsFormData.h
+++ b/content/base/src/nsFormData.h
@@ -6,26 +6,26 @@
 #define nsFormData_h__
 
 #include "nsIDOMFormData.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsFormSubmission.h"
 #include "nsWrapperCache.h"
 #include "nsTArray.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/BindingDeclarations.h"
 
 class nsHTMLFormElement;
 class nsIDOMFile;
 
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
 class GlobalObject;
-template<class> class Optional;
 } // namespace dom
 } // namespace mozilla
 
 class nsFormData : public nsIDOMFormData,
                    public nsIXHRSendable,
                    public nsFormSubmission,
                    public nsWrapperCache
 {
@@ -49,41 +49,51 @@ public:
   {
     return mOwner;
   }
   static already_AddRefed<nsFormData>
   Constructor(const mozilla::dom::GlobalObject& aGlobal,
               const mozilla::dom::Optional<nsHTMLFormElement*>& aFormElement,
               mozilla::ErrorResult& aRv);
   void Append(const nsAString& aName, const nsAString& aValue);
-  void Append(const nsAString& aName, nsIDOMBlob* aBlob);
+  void Append(const nsAString& aName, nsIDOMBlob* aBlob,
+              const mozilla::dom::Optional<nsAString>& aFilename);
 
   // nsFormSubmission
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream);
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue)
   {
-    Append(aName, aValue);
+    FormDataTuple* data = mFormData.AppendElement();
+    data->name = aName;
+    data->stringValue = aValue;
+    data->valueIsFile = false;
     return NS_OK;
   }
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob)
+                                   nsIDOMBlob* aBlob,
+                                   const nsString& aFilename)
   {
-    Append(aName, aBlob);
+    FormDataTuple* data = mFormData.AppendElement();
+    data->name = aName;
+    data->fileValue = aBlob;
+    data->filename = aFilename;
+    data->valueIsFile = true;
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsISupports> mOwner;
 
   struct FormDataTuple
   {
     nsString name;
     nsString stringValue;
     nsCOMPtr<nsIDOMBlob> fileValue;
+    nsString filename;
     bool valueIsFile;
   };
 
   nsTArray<FormDataTuple> mFormData;
 };
 
 #endif // nsFormData_h__
--- a/content/html/content/public/nsFormSubmission.h
+++ b/content/html/content/public/nsFormSubmission.h
@@ -43,19 +43,21 @@ public:
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue) = 0;
 
   /**
    * Submit a name/file pair
    *
    * @param aName the name of the parameter
    * @param aBlob the file to submit
+   * @param aFilename the filename to be used (not void)
    */
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob) = 0;
+                                   nsIDOMBlob* aBlob,
+                                   const nsString& aFilename) = 0;
   
   /**
    * Reports whether the instance supports AddIsindex().
    *
    * @return true if supported.
    */
   virtual bool SupportsIsindexSubmission()
   {
@@ -154,17 +156,18 @@ public:
    */
   nsFSMultipartFormData(const nsACString& aCharset,
                         nsIContent* aOriginatingElement);
   ~nsFSMultipartFormData();
  
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue);
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob);
+                                   nsIDOMBlob* aBlob,
+                                   const nsString& aFilename);
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream);
 
   void GetContentType(nsACString& aContentType)
   {
     aContentType =
       NS_LITERAL_CSTRING("multipart/form-data; boundary=") + mBoundary;
   }
--- a/content/html/content/src/nsFormSubmission.cpp
+++ b/content/html/content/src/nsFormSubmission.cpp
@@ -76,17 +76,18 @@ public:
       mDocument(aDocument),
       mWarnedFileControl(false)
   {
   }
 
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue);
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob);
+                                   nsIDOMBlob* aBlob,
+                                   const nsString& aFilename);
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream);
 
   virtual bool SupportsIsindexSubmission()
   {
     return true;
   }
 
@@ -162,17 +163,18 @@ nsFSURLEncoded::AddIsindex(const nsAStri
     mQueryString += NS_LITERAL_CSTRING("&isindex=") + convValue;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
-                                nsIDOMBlob* aBlob)
+                                nsIDOMBlob* aBlob,
+                                const nsString& aFilename)
 {
   if (!mWarnedFileControl) {
     SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
     mWarnedFileControl = true;
   }
 
   nsAutoString filename;
   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
@@ -437,62 +439,69 @@ nsFSMultipartFormData::AddNameValuePair(
                  + nameStr + NS_LITERAL_CSTRING("\"" CRLF CRLF)
                  + valueStr + NS_LITERAL_CSTRING(CRLF);
 
   return NS_OK;
 }
 
 nsresult
 nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
-                                       nsIDOMBlob* aBlob)
+                                       nsIDOMBlob* aBlob,
+                                       const nsString& aFilename)
 {
   // Encode the control name
   nsAutoCString nameStr;
   nsresult rv = EncodeVal(aName, nameStr, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString filename, contentType;
   nsCOMPtr<nsIInputStream> fileStream;
   if (aBlob) {
-    // Get and encode the filename
-    nsAutoString filename16;
-    nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
-    if (file) {
-      rv = file->GetName(filename16);
+    // We prefer the explicitly passed filename
+    if (!aFilename.IsVoid()) {
+      rv = EncodeVal(aFilename, filename, true);
+      NS_ENSURE_SUCCESS(rv, rv);
+    } else {
+      // Get and encode the filename
+      nsAutoString filename16;
+      nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
+      if (file) {
+        rv = file->GetName(filename16);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+
+      if (filename16.IsEmpty()) {
+        filename16.AssignLiteral("blob");
+      }
+
+      rv = EncodeVal(filename16, filename, true);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    if (filename16.IsEmpty()) {
-      filename16.AssignLiteral("blob");
-    }
-
-    rv = EncodeVal(filename16, filename, true);
-    NS_ENSURE_SUCCESS(rv, rv);
-  
     // Get content type
     nsAutoString contentType16;
     rv = aBlob->GetType(contentType16);
     if (NS_FAILED(rv) || contentType16.IsEmpty()) {
       contentType16.AssignLiteral("application/octet-stream");
     }
     contentType.Adopt(nsLinebreakConverter::
                       ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
                                         nsLinebreakConverter::eLinebreakAny,
                                         nsLinebreakConverter::eLinebreakSpace));
-  
+
     // Get input stream
     rv = aBlob->GetInternalStream(getter_AddRefs(fileStream));
     NS_ENSURE_SUCCESS(rv, rv);
     if (fileStream) {
       // Create buffered stream (for efficiency)
       nsCOMPtr<nsIInputStream> bufferedStream;
       rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
                                      fileStream, 8192);
       NS_ENSURE_SUCCESS(rv, rv);
-  
+
       fileStream = bufferedStream;
     }
   }
   else {
     contentType.AssignLiteral("application/octet-stream");
   }
 
   //
@@ -581,17 +590,18 @@ public:
   nsFSTextPlain(const nsACString& aCharset, nsIContent* aOriginatingElement)
     : nsEncodingFormSubmission(aCharset, aOriginatingElement)
   {
   }
 
   virtual nsresult AddNameValuePair(const nsAString& aName,
                                     const nsAString& aValue);
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob);
+                                   nsIDOMBlob* aBlob,
+                                   const nsString& aFilename);
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream);
 
 private:
   nsString mBody;
 };
 
 nsresult
@@ -604,24 +614,25 @@ nsFSTextPlain::AddNameValuePair(const ns
   mBody.Append(aName + NS_LITERAL_STRING("=") + aValue +
                NS_LITERAL_STRING(CRLF));
 
   return NS_OK;
 }
 
 nsresult
 nsFSTextPlain::AddNameFilePair(const nsAString& aName,
-                               nsIDOMBlob* aBlob)
+                               nsIDOMBlob* aBlob,
+                               const nsString& aFilename)
 {
   nsAutoString filename;
   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(aBlob);
   if (file) {
     file->GetName(filename);
   }
-    
+
   AddNameValuePair(aName, filename);
   return NS_OK;
 }
 
 nsresult
 nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
                                     nsIInputStream** aPostDataStream)
 {
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -4051,33 +4051,33 @@ nsHTMLInputElement::SubmitNamesValues(ns
   if (mType == NS_FORM_INPUT_SUBMIT && value.IsEmpty() &&
       !HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
     // Get our default value, which is the same as our default label
     nsXPIDLString defaultValue;
     nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
                                        "Submit", defaultValue);
     value = defaultValue;
   }
-      
+
   //
   // Submit file if its input type=file and this encoding method accepts files
   //
   if (mType == NS_FORM_INPUT_FILE) {
     // Submit files
 
     const nsCOMArray<nsIDOMFile>& files = GetFiles();
 
     for (int32_t i = 0; i < files.Count(); ++i) {
-      aFormSubmission->AddNameFilePair(name, files[i]);
+      aFormSubmission->AddNameFilePair(name, files[i], NullString());
     }
 
     if (files.Count() == 0) {
       // If no file was selected, pretend we had an empty file with an
       // empty filename.
-      aFormSubmission->AddNameFilePair(name, nullptr);
+      aFormSubmission->AddNameFilePair(name, nullptr, NullString());
 
     }
 
     return NS_OK;
   }
 
   if (mType == NS_FORM_INPUT_HIDDEN && name.EqualsLiteral("_charset_")) {
     nsCString charset;
--- a/dom/webidl/FormData.webidl
+++ b/dom/webidl/FormData.webidl
@@ -6,13 +6,11 @@
  * The origin of this IDL file is
  * http://xhr.spec.whatwg.org
  */
 
 interface HTMLFormElement;
 
 [Constructor(optional HTMLFormElement form)]
 interface FormData {
-  // Not supported (bug 739174)
-  // void append(DOMString name, Blob value, optional DOMString filename);
-  void append(DOMString name, Blob value);
+  void append(DOMString name, Blob value, optional DOMString filename);
   void append(DOMString name, DOMString value);
-};
+};
\ No newline at end of file