Add an API to access <input type="file"> data. r=smontagu (for charset stuff), r+sr=jonas
authordcamp@mozilla.com
Tue, 24 Jul 2007 21:29:47 -0700
changeset 3940 f3e484a0733c7b9c50743c68ac3c70bd3d69d152
parent 3939 820b532327c538c9452c06a064eba14de9c64c31
child 3941 59040f379535e476fe85a6eeaf60d1cc2f404a5d
push idunknown
push userunknown
push dateunknown
reviewerssmontagu
milestone1.9a7pre
Add an API to access <input type="file"> data. r=smontagu (for charset stuff), r+sr=jonas
content/base/public/Makefile.in
content/base/public/nsDOMFile.h
content/base/public/nsIDOMFile.idl
content/base/public/nsIDOMFileException.idl
content/base/public/nsIDOMFileList.idl
content/base/src/Makefile.in
content/base/src/nsDOMFile.cpp
content/html/content/src/Makefile.in
content/html/content/src/nsHTMLInputElement.cpp
dom/public/idl/html/nsIDOMNSHTMLInputElement.idl
dom/public/nsDOMClassInfoID.h
dom/public/nsDOMError.h
dom/src/base/domerr.msg
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsDOMClassInfo.h
dom/src/base/nsDOMException.cpp
dom/src/base/nsDOMException.h
dom/src/base/nsDOMScriptObjectFactory.cpp
xpcom/base/nsError.h
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -70,30 +70,34 @@ nsIXPathEvaluatorInternal.h \
 mozISanitizingSerializer.h \
 nsCaseTreatment.h \
 nsContentCID.h \
 nsCopySupport.h \
 nsContentCreatorFunctions.h \
 nsLineBreaker.h \
 nsXMLNameSpaceMap.h \
 nsPresShellIterator.h \
+nsDOMFile.h \
 $(NULL)
 
 ifndef DISABLE_XFORMS_HOOKS
 EXPORTS += nsIXFormsUtilityService.h
 endif
 
 SDK_XPIDLSRCS   = \
 		nsISelection.idl  \
 		$(NULL)
 
 XPIDLSRCS	= \
 		nsIChromeRegistry.idl       \
 		nsIContentPolicy.idl        \
 		nsIDocumentEncoder.idl      \
+		nsIDOMFile.idl \
+		nsIDOMFileList.idl \
+		nsIDOMFileException.idl \
 		nsIDOMParser.idl \
 		nsIDOMSerializer.idl \
 		nsISelection2.idl \
 		nsISelectionController.idl  \
 		nsISelectionDisplay.idl  \
 		nsISelectionListener.idl  \
 		nsISelectionPrivate.idl  \
 		nsIScriptLoaderObserver.idl  \
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsDOMFile.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozila.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dave Camp <dcamp@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDOMFile_h__
+#define nsDOMFile_h__
+
+#include "nsICharsetDetectionObserver.h"
+#include "nsIDOMFile.h"
+#include "nsIDOMFileList.h"
+#include "nsIInputStream.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+class nsIDOMDocument;
+class nsIFile;
+class nsIInputStream;
+
+class nsDOMFile : public nsIDOMFile,
+                  public nsICharsetDetectionObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMFILE
+
+  nsDOMFile(nsIFile *aFile)
+    : mFile(aFile)
+  {}
+  ~nsDOMFile() {}
+
+  // from nsICharsetDetectionObserver
+  NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
+
+private:
+  nsCOMPtr<nsIFile> mFile;
+  nsString mContentType;
+  nsCString mCharset;
+
+  nsresult GuessCharset(nsIInputStream *aStream,
+                        nsACString &aCharset);
+  nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
+                         nsAString &aResult);
+};
+
+class nsDOMFileList : public nsIDOMFileList
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMFILELIST
+
+  PRBool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
+
+  PRBool Remove(PRUint32 aIndex) { return mFiles.RemoveObjectAt(aIndex); }
+  void Clear() { return mFiles.Clear(); }
+
+private:
+  nsCOMArray<nsIDOMFile> mFiles;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsIDOMFile.idl
@@ -0,0 +1,52 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+[scriptable, uuid(4a17d83b-424f-43f3-8a7c-430f406921be)]
+interface nsIDOMFile : nsISupports
+{
+  readonly attribute DOMString fileName;
+  readonly attribute unsigned long long fileSize;
+
+  DOMString getAsText(in DOMString encoding);
+                                  // raises(FileException) on retrieval
+  DOMString getAsDataURL();
+                                  // raises(FileException) on retrieval
+  DOMString getAsBinary();
+                                  // raises(FileException) on retrieval
+};
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsIDOMFileException.idl
@@ -0,0 +1,47 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+[scriptable, uuid(b52356e1-45c5-4d61-b61a-fb9bd91690e1)]
+interface nsIDOMFileException : nsISupports
+{
+  const unsigned short NOT_FOUND_ERR    = 0;
+  const unsigned short NOT_READABLE_ERR = 1;
+
+  readonly attribute unsigned short code;
+};
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsIDOMFileList.idl
@@ -0,0 +1,47 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+interface nsIDOMFile;
+
+[scriptable, uuid(3bfef9fa-8ad3-4e49-bd62-d6cd75b29298)]
+interface nsIDOMFileList : nsISupports
+{
+  readonly attribute unsigned long length;
+  nsIDOMFile item(in unsigned long index);
+};
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -56,16 +56,18 @@ REQUIRES	= xpcom \
 		  view \
 		  locale \
 		  htmlparser \
 		  js \
 		  webshell \
 		  necko \
 		  nkcache \
 		  mimetype \
+		  exthandler \
+		  chardet \
 		  caps \
 		  lwbrk \
 		  uconv \
 		  docshell \
 		  pref \
 		  xpconnect \
 		  unicharutil \
 		  intl \
@@ -110,16 +112,17 @@ CPPSRCS		= \
 		nsContentPolicy.cpp \
 		nsContentSink.cpp \
 		nsContentUtils.cpp \
 		nsCopySupport.cpp \
 		nsDataDocumentContentPolicy.cpp \
 		nsDOMAttribute.cpp \
 		nsDOMAttributeMap.cpp \
 		nsDOMDocumentType.cpp \
+		nsDOMFile.cpp \
 		nsDOMLists.cpp \
 		nsDOMParser.cpp \
 		nsDOMSerializer.cpp \
 		nsDocument.cpp \
 		nsDocumentEncoder.cpp \
 		nsDocumentFragment.cpp \
 		nsFrameLoader.cpp \
 		nsGenConImageContent.cpp \
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsDOMFile.cpp
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozila.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dave Camp <dcamp@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDOMFile.h"
+
+#include "nsCExternalHandlerService.h"
+#include "nsContentCID.h"
+#include "nsContentUtils.h"
+#include "nsDOMClassInfo.h"
+#include "nsDOMError.h"
+#include "nsICharsetAlias.h"
+#include "nsICharsetDetector.h"
+#include "nsICharsetConverterManager.h"
+#include "nsIConverterInputStream.h"
+#include "nsIDocument.h"
+#include "nsIDOMDocument.h"
+#include "nsIFile.h"
+#include "nsIFileStreams.h"
+#include "nsIInputStream.h"
+#include "nsIMIMEService.h"
+#include "nsIPlatformCharset.h"
+#include "nsISeekableStream.h"
+#include "nsIUnicharInputStream.h"
+#include "nsIUnicodeDecoder.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+
+#include "plbase64.h"
+#include "prmem.h"
+
+// nsDOMFile implementation
+
+NS_INTERFACE_MAP_BEGIN(nsDOMFile)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMFile)
+  NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(File)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(nsDOMFile)
+NS_IMPL_RELEASE(nsDOMFile)
+
+static nsresult
+DOMFileResult(nsresult rv)
+{
+  if (rv == NS_ERROR_FILE_NOT_FOUND) {
+    return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
+  }
+
+  if (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_FILES) {
+    return NS_ERROR_DOM_FILE_NOT_READABLE_ERR;
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP
+nsDOMFile::GetFileName(nsAString &aFileName)
+{
+  return mFile->GetLeafName(aFileName);
+}
+
+NS_IMETHODIMP
+nsDOMFile::GetFileSize(PRUint64 *aFileSize)
+{
+  PRInt64 fileSize;
+  nsresult rv = mFile->GetFileSize(&fileSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (fileSize < 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *aFileSize = fileSize;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMFile::GetAsText(const nsAString &aCharset, nsAString &aResult)
+{
+  aResult.Truncate();
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewLocalFileInputStream
+                  (getter_AddRefs(stream),
+                   mFile, -1, -1, 0);
+  NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+
+  nsCAutoString charsetGuess;
+  if (!aCharset.IsEmpty()) {
+    CopyUTF16toUTF8(aCharset, charsetGuess);
+  } else {
+    rv = GuessCharset(stream, charsetGuess);
+    NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+
+    nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(stream);
+    if (!seekable) return NS_ERROR_FAILURE;
+    rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+    NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+  }
+
+  nsCAutoString charset;
+  nsCOMPtr<nsICharsetAlias> alias =
+    do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = alias->GetPreferred(charsetGuess, charset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return ConvertStream(stream, charset.get(), aResult);
+}
+
+NS_IMETHODIMP
+nsDOMFile::GetAsDataURL(nsAString &aResult)
+{
+  aResult.AssignLiteral("data:");
+
+  nsresult rv;
+  nsCOMPtr<nsIMIMEService> mimeService =
+    do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCAutoString contentType;
+  rv = mimeService->GetTypeFromFile(mFile, contentType);
+  if (NS_SUCCEEDED(rv)) {
+    AppendUTF8toUTF16(contentType, aResult);
+  } else {
+    aResult.AppendLiteral("application/octet-stream");
+  }
+  aResult.AppendLiteral(";base64,");
+
+  nsCOMPtr<nsIInputStream> stream;
+  rv = NS_NewLocalFileInputStream(getter_AddRefs(stream),
+                                  mFile, -1, -1,
+                                  nsIFileInputStream::CLOSE_ON_EOF);
+  NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+
+  char readBuf[4096];
+  PRUint32 leftOver = 0;
+  PRUint32 numRead;
+  do {
+    rv = stream->Read(readBuf + leftOver, sizeof(readBuf) - leftOver, &numRead);
+    NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+
+    PRUint32 numEncode = numRead + leftOver;
+    leftOver = 0;
+
+    if (numEncode == 0) break;
+
+    // unless this is the end of the file, encode in multiples of 3
+    if (numRead > 0) {
+      leftOver = numEncode % 3;
+      numEncode -= leftOver;
+    }
+
+    // out buffer should be at least 4/3rds the read buf, plus a terminator
+    char *base64 = PL_Base64Encode(readBuf, numEncode, nsnull);
+    AppendASCIItoUTF16(base64, aResult);
+    PR_Free(base64);
+
+    if (leftOver) {
+      memmove(readBuf, readBuf + numEncode, leftOver);
+    }
+  } while (numRead > 0);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMFile::GetAsBinary(nsAString &aResult)
+{
+  aResult.Truncate();
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewLocalFileInputStream
+                  (getter_AddRefs(stream),
+                   mFile, -1, -1,
+                   nsIFileInputStream::CLOSE_ON_EOF);
+  NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+
+  PRUint32 numRead;
+  do {
+    char readBuf[4096];
+    rv = stream->Read(readBuf, sizeof(readBuf), &numRead);
+    NS_ENSURE_SUCCESS(rv, DOMFileResult(rv));
+    AppendASCIItoUTF16(Substring(readBuf, readBuf + numRead), aResult);
+  } while (numRead > 0);
+
+  return NS_OK;
+}
+
+nsresult
+nsDOMFile::GuessCharset(nsIInputStream *aStream,
+                        nsACString &aCharset)
+{
+
+  if (!mCharset.IsEmpty()) {
+    aCharset = mCharset;
+    return NS_OK;
+  }
+
+  // First try the universal charset detector
+  nsCOMPtr<nsICharsetDetector> detector
+    = do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
+                        "universal_charset_detector");
+  if (!detector) {
+    // No universal charset detector, try the default charset detector
+    const nsAdoptingString& detectorName =
+      nsContentUtils::GetLocalizedStringPref("intl.charset.detector");
+    if (!detectorName.IsEmpty()) {
+      nsCAutoString detectorContractID;
+      detectorContractID.AssignLiteral(NS_CHARSET_DETECTOR_CONTRACTID_BASE);
+      AppendUTF16toUTF8(detectorName, detectorContractID);
+      detector = do_CreateInstance(detectorContractID.get());
+    }
+  }
+
+  nsresult rv;
+  if (detector) {
+    detector->Init(this);
+
+    PRBool done;
+    PRUint32 numRead;
+    do {
+      char readBuf[4096];
+      rv = aStream->Read(readBuf, sizeof(readBuf), &numRead);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = detector->DoIt(readBuf, numRead, &done);
+      NS_ENSURE_SUCCESS(rv, rv);
+    } while (!done && numRead > 0);
+
+    rv = detector->Done();
+    NS_ENSURE_SUCCESS(rv, rv);
+  } else {
+    // no charset detector available, check the BOM
+    unsigned char sniffBuf[4];
+    PRUint32 numRead;
+    rv = aStream->Read(reinterpret_cast<char*>(sniffBuf),
+                       sizeof(sniffBuf), &numRead);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (numRead >= 4 &&
+        sniffBuf[0] == 0x00 &&
+        sniffBuf[1] == 0x00 &&
+        sniffBuf[2] == 0xfe &&
+        sniffBuf[3] == 0xff) {
+      mCharset = "UTF-32BE";
+    } else if (numRead >= 4 &&
+               sniffBuf[0] == 0xff &&
+               sniffBuf[1] == 0xfe &&
+               sniffBuf[2] == 0x00 &&
+               sniffBuf[3] == 0x00) {
+      mCharset = "UTF-32LE";
+    } else if (numRead >= 2 &&
+               sniffBuf[0] == 0xfe &&
+               sniffBuf[1] == 0xff) {
+      mCharset = "UTF-16BE";
+    } else if (numRead >= 2 &&
+               sniffBuf[0] == 0xff &&
+               sniffBuf[1] == 0xfe) {
+      mCharset = "UTF-16LE";
+    } else if (numRead >= 3 &&
+               sniffBuf[0] == 0xef &&
+               sniffBuf[1] == 0xbb &&
+               sniffBuf[2] == 0xbf) {
+      mCharset = "UTF-8";
+    }
+  }
+
+  if (mCharset.IsEmpty()) {
+    // no charset detected, default to the system charset
+    nsCOMPtr<nsIPlatformCharset> platformCharset =
+      do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
+    if (NS_SUCCEEDED(rv)) {
+      rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
+                                       mCharset);
+    }
+  }
+
+  if (mCharset.IsEmpty()) {
+    // no sniffed or default charset, try UTF-8
+    mCharset.AssignLiteral("UTF-8");
+  }
+
+  aCharset = mCharset;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMFile::Notify(const char* aCharset, nsDetectionConfident aConf)
+{
+  mCharset.Assign(aCharset);
+
+  return NS_OK;
+}
+
+nsresult
+nsDOMFile::ConvertStream(nsIInputStream *aStream,
+                         const char *aCharset,
+                         nsAString &aResult)
+{
+  nsCOMPtr<nsIConverterInputStream> converterStream =
+    do_CreateInstance("@mozilla.org/intl/converter-input-stream;1");
+  if (!converterStream) return NS_ERROR_FAILURE;
+
+  nsresult rv = converterStream->Init
+                  (aStream, aCharset,
+                   8192,
+                   nsIConverterInputStream::DEFAULT_REPLACEMENT_CHARACTER);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIUnicharInputStream> unicharStream =
+    do_QueryInterface(converterStream);
+  if (!unicharStream) return NS_ERROR_FAILURE;
+
+  PRUint32 numChars;
+  return unicharStream->ReadString(PR_UINT32_MAX, aResult, &numChars);
+}
+
+// nsDOMFileList implementation
+
+NS_INTERFACE_MAP_BEGIN(nsDOMFileList)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMFileList)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileList)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(nsDOMFileList)
+NS_IMPL_RELEASE(nsDOMFileList)
+
+NS_IMETHODIMP
+nsDOMFileList::GetLength(PRUint32* aLength)
+{
+  *aLength = mFiles.Count();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
+{
+  NS_IF_ADDREF(*aFile = mFiles.SafeObjectAt(aIndex));
+
+  return NS_OK;
+}
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -64,16 +64,17 @@ REQUIRES	= xpcom \
 		  docshell \
 		  xpconnect \
 		  xuldoc \
 		  caps \
 		  editor \
 		  imglib2 \
 		  mimetype \
 		  exthandler \
+		  chardet \
 		  uconv \
 		  intl \
 		  plugin \
 		  $(NULL)
 
 EXPORTS		= \
 		nsImageMapUtils.h \
 		$(NULL)
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -100,16 +100,17 @@
 
 // input type=file
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIFile.h"
 #include "nsILocalFile.h"
 #include "nsIFileStreams.h"
 #include "nsNetUtil.h"
+#include "nsDOMFile.h"
 
 // input type=image
 #include "nsImageLoadingContent.h"
 #include "nsIDOMWindowInternal.h"
 
 // XXX align=left, hspace, vspace, border? other nav4 attrs
 
 static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
@@ -310,17 +311,27 @@ protected:
    */
   nsresult SetCheckedInternal(PRBool aValue, PRBool aNotify);
 
   /**
    * MaybeSubmitForm looks for a submit input or a single text control
    * and submits the form if either is present.
    */
   nsresult MaybeSubmitForm(nsPresContext* aPresContext);
-  
+
+  /**
+   * Get an nsIFile for the currently selected file in an file control.
+   */
+  nsresult GetFile(nsIFile** aFile);
+
+  /**
+   * Update mFileList with the currently selected file.
+   */
+  nsresult UpdateFileList();
+
   nsCOMPtr<nsIControllers> mControllers;
 
   /**
    * The type of this input (<input type=...>) as an integer.
    * @see nsIFormControl.h (specifically NS_FORM_INPUT_*)
    */
   PRInt8                   mType;
   /**
@@ -338,16 +349,18 @@ protected:
    * so that it won't be possible to 'leak' the value from a text-input to a
    * file-input. Additionally, the logic for this value is kept as simple as
    * possible to avoid accidental errors where the wrong filename is used.
    * Therefor the filename is always owned by this member, never by the frame.
    * Whenever the frame wants to change the filename it has to call
    * SetFileName to update this member.
    */
   nsAutoPtr<nsString>      mFileName;
+
+  nsRefPtr<nsDOMFileList>  mFileList;
 };
 
 #ifdef ACCESSIBILITY
 //Helper method
 static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
                                           nsPresContext* aPresContext,
                                           const nsAString& aEventType);
 #endif
@@ -806,21 +819,74 @@ nsHTMLInputElement::SetFileName(const ns
 
   // No need to flush here, if there's no frame at this point we
   // don't need to force creation of one just to tell it about this
   // new value.  We just want the display to update as needed.
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
   if (formControlFrame) {
     formControlFrame->SetFormProperty(nsGkAtoms::value, aValue);
   }
+
+  UpdateFileList();
   
   SetValueChanged(PR_TRUE);
 }
 
 nsresult
+nsHTMLInputElement::GetFile(nsIFile** aFile)
+{
+  *aFile = nsnull;
+
+  if (!mFileName || mType != NS_FORM_INPUT_FILE) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsresult rv = NS_ERROR_NOT_AVAILABLE;
+
+  if (StringBeginsWith(*mFileName, NS_LITERAL_STRING("file:"),
+                       nsCaseInsensitiveStringComparator())) {
+    // Converts the URL string into the corresponding nsIFile if possible.
+    // A local file will be created if the URL string begins with file://.
+    rv = NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(*mFileName), aFile);
+  }
+
+  if (!(*aFile)) {
+    // this is no "file://", try as local file
+    nsCOMPtr<nsILocalFile> localFile;
+    rv = NS_NewLocalFile(*mFileName, PR_FALSE, getter_AddRefs(localFile));
+    NS_IF_ADDREF(*aFile = localFile);
+  }
+
+  return rv;
+}
+
+nsresult
+nsHTMLInputElement::UpdateFileList()
+{
+  if (mFileList) {
+    mFileList->Clear();
+
+    if (mType == NS_FORM_INPUT_FILE && mFileName) {
+      nsCOMPtr<nsIFile> file;
+      nsresult rv = GetFile(getter_AddRefs(file));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      nsRefPtr<nsDOMFile> domFile = new nsDOMFile(file);
+      if (domFile) {
+        if (!mFileList->Append(domFile)) {
+          return NS_ERROR_FAILURE;
+        }
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
 nsHTMLInputElement::SetValueInternal(const nsAString& aValue,
                                      nsITextControlFrame* aFrame)
 {
   NS_PRECONDITION(mType != NS_FORM_INPUT_FILE,
                   "Don't call SetValueInternal for file inputs");
 
   if (mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) {
 
@@ -1888,39 +1954,43 @@ nsHTMLInputElement::ParseAttribute(PRInt
                                    nsIAtom* aAttribute,
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       // XXX ARG!! This is major evilness. ParseAttribute
       // shouldn't set members. Override SetAttr instead
-      if (!aResult.ParseEnumValue(aValue, kInputTypeTable)) {
-        mType = NS_FORM_INPUT_TEXT;
-        return PR_FALSE;
+      PRInt32 newType;
+      PRBool success;
+      if ((success = aResult.ParseEnumValue(aValue, kInputTypeTable))) {
+        newType = aResult.GetEnumValue();
+      } else {
+        newType = NS_FORM_INPUT_TEXT;
       }
 
       // Make sure to do the check for newType being NS_FORM_INPUT_FILE and the
       // corresponding SetValueInternal() call _before_ we set mType.  That way
       // the logic in SetValueInternal() will work right (that logic makes
       // assumptions about our frame based on mType, but we won't have had time
       // to recreate frames yet -- that happens later in the SetAttr()
       // process).
-      PRInt32 newType = aResult.GetEnumValue();
       if (newType == NS_FORM_INPUT_FILE) {
         // These calls aren't strictly needed any more since we'll never
         // confuse values and filenames. However they're there for backwards
         // compat.
         SetFileName(EmptyString());
         SetValueInternal(EmptyString(), nsnull);
+      } else if (mType == NS_FORM_INPUT_FILE) {
+        SetFileName(EmptyString());
       }
 
       mType = newType;
 
-      return PR_TRUE;
+      return success;
     }
     if (aAttribute == nsGkAtoms::width) {
       return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
     }
     if (aAttribute == nsGkAtoms::height) {
       return aResult.ParseSpecialIntValue(aValue, PR_TRUE, PR_FALSE);
     }
     if (aAttribute == nsGkAtoms::maxlength) {
@@ -2146,16 +2216,37 @@ nsHTMLInputElement::SetSelectionEnd(PRIn
 
     if (textControlFrame)
       rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
   }
 
   return rv;
 }
 
+NS_IMETHODIMP
+nsHTMLInputElement::GetFileList(nsIDOMFileList** aFileList)
+{
+  *aFileList = nsnull;
+
+  if (mType != NS_FORM_INPUT_FILE) {
+    return NS_OK;
+  }
+
+  if (!mFileList) {
+    mFileList = new nsDOMFileList();
+    if (!mFileList) return NS_ERROR_OUT_OF_MEMORY;
+
+    UpdateFileList();
+  }
+
+  NS_ADDREF(*aFileList = mFileList);
+
+  return NS_OK;
+}
+
 nsresult
 nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart,
                                       PRInt32* aSelectionEnd)
 {
   nsresult rv = NS_ERROR_FAILURE;
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
 
   if (formControlFrame) {
@@ -2361,31 +2452,17 @@ nsHTMLInputElement::SubmitNamesValues(ns
   // Submit file if it's input type=file and this encoding method accepts files
   //
   if (mType == NS_FORM_INPUT_FILE) {
     //
     // Open the file
     //
     nsCOMPtr<nsIFile> file;
  
-    if (mFileName) {
-      if (StringBeginsWith(*mFileName, NS_LITERAL_STRING("file:"),
-                           nsCaseInsensitiveStringComparator())) {
-        // Converts the URL string into the corresponding nsIFile if possible.
-        // A local file will be created if the URL string begins with file://.
-        rv = NS_GetFileFromURLSpec(NS_ConvertUTF16toUTF8(*mFileName),
-                                   getter_AddRefs(file));
-      }
-      if (!file) {
-        // this is no "file://", try as local file
-        nsCOMPtr<nsILocalFile> localFile;
-        rv = NS_NewLocalFile(*mFileName, PR_FALSE, getter_AddRefs(localFile));
-        file = localFile;
-      }
-    }
+    rv = GetFile(getter_AddRefs(file));
 
     if (file) {
 
       //
       // Get the leaf path name (to be submitted as the value)
       //
       nsAutoString filename;
       rv = file->GetLeafName(filename);
@@ -3010,8 +3087,9 @@ NS_GetRadioGetCheckedChangedVisitor(PRBo
                                                   aExcludeElement);
   if (!*aVisitor) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   NS_ADDREF(*aVisitor);
 
   return NS_OK;
 }
+
--- a/dom/public/idl/html/nsIDOMNSHTMLInputElement.idl
+++ b/dom/public/idl/html/nsIDOMNSHTMLInputElement.idl
@@ -35,24 +35,26 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 
 interface nsIControllers;
-
+interface nsIDOMFileList;
 
-[scriptable, uuid(993d2efc-a768-11d3-bccd-0060b0fc76bd)]
+[scriptable, uuid(7564318a-8d75-4191-890d-f0150488d431)]
 interface nsIDOMNSHTMLInputElement : nsISupports
 {
 	readonly attribute nsIControllers   controllers;
 	
 	readonly attribute long             textLength;
 	
            attribute long             selectionStart;
            attribute long             selectionEnd;
 
+	readonly attribute nsIDOMFileList   fileList;
+
 	/* convenience */
   void                      setSelectionRange(in long selectionStart,
                                               in long selectionEnd);
 };
--- a/dom/public/nsDOMClassInfoID.h
+++ b/dom/public/nsDOMClassInfoID.h
@@ -397,16 +397,20 @@ enum nsDOMClassInfoID {
   eDOMClassInfo_XULCommandEvent_id,
   eDOMClassInfo_CommandEvent_id,
 
   eDOMClassInfo_OfflineResourceList_id,
   eDOMClassInfo_LoadStatusList_id,
   eDOMClassInfo_LoadStatus_id,
   eDOMClassInfo_LoadStatusEvent_id,
 
+  eDOMClassInfo_FileList_id,
+  eDOMClassInfo_File_id,
+  eDOMClassInfo_FileException_id,
+
   // This one better be the last one in this list
   eDOMClassInfoIDCount
 };
 
 /**
  * nsIClassInfo helper macros
  */
 
--- a/dom/public/nsDOMError.h
+++ b/dom/public/nsDOMError.h
@@ -100,10 +100,12 @@
 #define NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR      NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1008)
 #define NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN         NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1009)
 #define NS_ERROR_DOM_PROP_ACCESS_DENIED          NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1010)
 #define NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1011)
 #define NS_ERROR_DOM_BAD_URI                     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1012)
 #define NS_ERROR_DOM_RETVAL_UNDEFINED            NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1013)
 #define NS_ERROR_DOM_QUOTA_REACHED               NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM,1014)
 
+#define NS_ERROR_DOM_FILE_NOT_FOUND_ERR          NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 0)
+#define NS_ERROR_DOM_FILE_NOT_READABLE_ERR       NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 1)
 
 #endif // nsDOMError_h__
--- a/dom/src/base/domerr.msg
+++ b/dom/src/base/domerr.msg
@@ -96,16 +96,19 @@ DOM_MSG_DEF(NS_ERROR_DOM_NOT_FUNCTION_ER
 DOM_MSG_DEF(NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR, "Too few parameters to method")
 DOM_MSG_DEF(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN, "Illegal document.domain value")
 DOM_MSG_DEF(NS_ERROR_DOM_PROP_ACCESS_DENIED, "Access to property denied")
 DOM_MSG_DEF(NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED, "Access to XPConnect service denied")
 DOM_MSG_DEF(NS_ERROR_DOM_BAD_URI, "Access to restricted URI denied")
 DOM_MSG_DEF(NS_ERROR_DOM_RETVAL_UNDEFINED, "Return value is undefined")
 DOM_MSG_DEF(NS_ERROR_DOM_QUOTA_REACHED, "Persistent storage maximum size reached")
 
+DOM_MSG_DEF(NS_ERROR_DOM_FILE_NOT_FOUND_ERR, "File was not found")
+DOM_MSG_DEF(NS_ERROR_DOM_FILE_NOT_READABLE_ERR, "File could not be read")
+
 /* common global codes (from nsError.h) */
 
 DOM_MSG_DEF(NS_OK                                  , "Success")
 DOM_MSG_DEF(NS_ERROR_NOT_INITIALIZED               , "Component not initialized")
 DOM_MSG_DEF(NS_ERROR_ALREADY_INITIALIZED           , "Component already initialized")
 DOM_MSG_DEF(NS_ERROR_NOT_IMPLEMENTED               , "Method not implemented")
 DOM_MSG_DEF(NS_NOINTERFACE                         , "Component does not have requested interface")
 DOM_MSG_DEF(NS_ERROR_NO_INTERFACE                  , "Component does not have requested interface")
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -432,16 +432,20 @@
 #include "nsIDOMStorageEvent.h"
 #include "nsIDOMToString.h"
 
 // Offline includes
 #include "nsIDOMLoadStatusList.h"
 #include "nsIDOMLoadStatus.h"
 #include "nsIDOMLoadStatusEvent.h"
 
+#include "nsIDOMFileList.h"
+#include "nsIDOMFile.h"
+#include "nsIDOMFileException.h"
+
 static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
 //       are defined in nsIDOMClassInfo.h.
@@ -1187,16 +1191,24 @@ static nsDOMClassInfoData sClassInfoData
                            ARRAY_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(LoadStatusList, nsLoadStatusListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(LoadStatus, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(LoadStatusEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
+  NS_DEFINE_CLASSINFO_DATA(FileList, nsFileListSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(FileException, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
 };
 
 // Objects that shuld be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
   const char *mContractID;
 };
@@ -3226,16 +3238,29 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(TextRectangle, nsIDOMTextRectangle)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTextRectangle)
    DOM_CLASSINFO_MAP_END
  
   DOM_CLASSINFO_MAP_BEGIN(TextRectangleList, nsIDOMTextRectangleList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTextRectangleList)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(FileList, nsIDOMFileList)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileList)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(FileException, nsIDOMFileException)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileException)
+    DOM_CLASSINFO_MAP_ENTRY(nsIException)
+  DOM_CLASSINFO_MAP_END
+
 #ifdef NS_DEBUG
   {
     PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData);
 
     if (i != eDOMClassInfoIDCount) {
       NS_ERROR("The number of items in sClassInfoData doesn't match the "
                "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
 
@@ -10108,8 +10133,24 @@ nsLoadStatusListSH::GetItemAt(nsISupport
 
   nsIDOMLoadStatus *status = nsnull; // Weak, transfer the ownership over to aResult
   nsresult rv = list->Item(aIndex, &status);
 
   *aResult = status;
 
   return rv;
 }
+
+// nsFileListSH
+nsresult
+nsFileListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                        nsISupports **aResult)
+{
+  nsCOMPtr<nsIDOMFileList> list(do_QueryInterface(aNative));
+  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
+
+  nsIDOMFile *file = nsnull; // weak, transfer ownership over to aResult
+  nsresult rv = list->Item(aIndex, &file);
+
+  *aResult = file;
+
+  return rv;
+}
--- a/dom/src/base/nsDOMClassInfo.h
+++ b/dom/src/base/nsDOMClassInfo.h
@@ -1639,13 +1639,33 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsLoadStatusListSH(aData);
   }
 };
 
+class nsFileListSH : public nsArraySH
+{
+protected:
+  nsFileListSH(nsDOMClassInfoData *aData) : nsArraySH(aData)
+  {
+  }
+
+  virtual ~nsFileListSH()
+  {
+  }
+
+  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                             nsISupports **aResult);
+
+public:
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
+  {
+    return new nsFileListSH(aData);
+  }
+};
 
 void InvalidateContextAndWrapperCache();
 
 
 #endif /* nsDOMClassInfo_h___ */
--- a/dom/src/base/nsDOMException.cpp
+++ b/dom/src/base/nsDOMException.cpp
@@ -38,16 +38,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMError.h"
 #include "nsDOMException.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMRangeException.h"
+#include "nsIDOMFileException.h"
 #ifdef MOZ_SVG
 #include "nsIDOMSVGException.h"
 #endif
 #include "nsIDOMXPathException.h"
 #include "nsString.h"
 #include "prprf.h"
 
 #define DOM_MSG_DEF(val, message) {(val), #val, message},
@@ -198,16 +199,33 @@ nsXPathException::GetCode(PRUint16* aCod
   NS_ENSURE_ARG_POINTER(aCode);
   nsresult result;
   GetResult(&result);
   *aCode = NS_ERROR_GET_CODE(result);
 
   return NS_OK;
 }
 
+IMPL_INTERNAL_DOM_EXCEPTION_HEAD(nsDOMFileException, nsIDOMFileException)
+  NS_DECL_NSIDOMFILEEXCEPTION
+IMPL_INTERNAL_DOM_EXCEPTION_TAIL(nsDOMFileException, nsIDOMFileException,
+                                 FileException, NS_ERROR_MODULE_DOM_FILE,
+                                 NSResultToNameAndMessage)
+
+NS_IMETHODIMP
+nsDOMFileException::GetCode(PRUint16* aCode)
+{
+  NS_ENSURE_ARG_POINTER(aCode);
+  nsresult result;
+  GetResult(&result);
+  *aCode = NS_ERROR_GET_CODE(result);
+
+  return NS_OK;
+}
+
 nsBaseDOMException::nsBaseDOMException()
 {
 }
 
 nsBaseDOMException::~nsBaseDOMException()
 {
 }
 
--- a/dom/src/base/nsDOMException.h
+++ b/dom/src/base/nsDOMException.h
@@ -68,8 +68,9 @@ NS_New##domname(nsresult aNSResult, nsIE
 
 
 DECL_INTERNAL_DOM_EXCEPTION(DOMException)
 DECL_INTERNAL_DOM_EXCEPTION(RangeException)
 #ifdef MOZ_SVG
 DECL_INTERNAL_DOM_EXCEPTION(SVGException)
 #endif
 DECL_INTERNAL_DOM_EXCEPTION(XPathException)
+DECL_INTERNAL_DOM_EXCEPTION(FileException)
--- a/dom/src/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/src/base/nsDOMScriptObjectFactory.cpp
@@ -345,16 +345,18 @@ nsDOMScriptObjectFactory::GetException(n
 #ifdef MOZ_SVG
     case NS_ERROR_MODULE_SVG:
       return NS_NewSVGException(result, aDefaultException, _retval);
 #endif
     case NS_ERROR_MODULE_DOM_XPATH:
       return NS_NewXPathException(result, aDefaultException, _retval);
     case NS_ERROR_MODULE_XPCONNECT:
       return CreateXPConnectException(result, aDefaultException, _retval);
+    case NS_ERROR_MODULE_DOM_FILE:
+      return NS_NewFileException(result, aDefaultException, _retval);
     default:
       return NS_NewDOMException(result, aDefaultException, _retval);
   }
 }
 
 NS_IMETHODIMP
 nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
 					       nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
--- a/xpcom/base/nsError.h
+++ b/xpcom/base/nsError.h
@@ -91,16 +91,17 @@
 #define NS_ERROR_MODULE_URILOADER  24
 #define NS_ERROR_MODULE_CONTENT    25
 #define NS_ERROR_MODULE_PYXPCOM    26
 #define NS_ERROR_MODULE_XSLT       27
 #define NS_ERROR_MODULE_IPC        28
 #define NS_ERROR_MODULE_SVG        29
 #define NS_ERROR_MODULE_STORAGE    30
 #define NS_ERROR_MODULE_SCHEMA     31
+#define NS_ERROR_MODULE_DOM_FILE   32
 
 /* NS_ERROR_MODULE_GENERAL should be used by modules that do not
  * care if return code values overlap. Callers of methods that
  * return such codes should be aware that they are not
  * globally unique. Implementors should be careful about blindly
  * returning codes from other modules that might also use
  * the generic base.
  */