Bug 1231100 - Get rid of nsIDOMFileReader - patch 1, r=sicking
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 09 Dec 2015 15:52:15 -0500
changeset 310153 aa1fccef59946325e40a9330dfe302d0b3a3c7c2
parent 310152 6ff143ef49ebce4663092109c9e6affd3ec1aa17
child 310154 a22ade61487c77f74e09723224470ca3c8dac7e5
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs1231100
milestone45.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 1231100 - Get rid of nsIDOMFileReader - patch 1, r=sicking
b2g/components/LogCapture.jsm
browser/components/migration/MSMigrationUtils.jsm
devtools/server/actors/device.js
devtools/server/actors/webapps.js
dom/apps/ImportExport.jsm
dom/base/FileReader.cpp
dom/base/FileReader.h
dom/base/moz.build
dom/base/nsDOMClassInfo.cpp
dom/base/nsIDOMFileReader.idl
dom/base/test/test_ipc_messagemanager_blob.html
dom/indexedDB/test/test_message_manager_ipc.html
dom/indexedDB/test/unit/test_blob_file_backed.js
dom/indexedDB/test/unit/xpcshell-head-parent-process.js
dom/ipc/tests/test_blob_sliced_from_parent_process.html
dom/mobilemessage/gonk/MmsService.js
dom/webidl/FileReader.webidl
js/xpconnect/tests/mochitest/test_bug790732.html
layout/build/nsLayoutModule.cpp
toolkit/components/thumbnails/PageThumbs.jsm
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
toolkit/modules/PropertyListUtils.jsm
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
--- a/b2g/components/LogCapture.jsm
+++ b/b2g/components/LogCapture.jsm
@@ -193,19 +193,17 @@ var LogCapture = {
    * Dumping screenshot, returning a Promise. Will be resolved with the content
    * as an ArrayBuffer.
    */
   getScreenshot: function() {
     let deferred = Promise.defer();
     try {
       this.ensureLoaded();
 
-      let fr = Cc["@mozilla.org/files/filereader;1"]
-                  .createInstance(Ci.nsIDOMFileReader);
-
+      let fr = new FileReader();
       fr.onload = function(evt) {
         deferred.resolve(new Uint8Array(evt.target.result));
       };
 
       fr.onerror = function(evt) {
         deferred.reject(evt);
       };
 
--- a/browser/components/migration/MSMigrationUtils.jsm
+++ b/browser/components/migration/MSMigrationUtils.jsm
@@ -540,18 +540,17 @@ Cookies.prototype = {
       this.ctypesKernelHelpers.finalize();
 
       aCallback(success);
     }).apply(this);
     cookiesGenerator.next();
   },
 
   _readCookieFile(aFile, aCallback) {
-    let fileReader = Cc["@mozilla.org/files/filereader;1"].
-                     createInstance(Ci.nsIDOMFileReader);
+    let fileReader = new FileReader();
     let onLoadEnd = () => {
       fileReader.removeEventListener("loadend", onLoadEnd, false);
 
       if (fileReader.readyState != fileReader.DONE) {
         Cu.reportError("Could not read cookie contents: " + fileReader.error);
         aCallback(false);
         return;
       }
--- a/devtools/server/actors/device.js
+++ b/devtools/server/actors/device.js
@@ -20,17 +20,16 @@ var DeviceActor = exports.DeviceActor = 
 
   getDescription: method(function() {
     return getSystemInfo();
   }, {request: {},response: { value: RetVal("json")}}),
 
   getWallpaper: method(function() {
     let deferred = promise.defer();
     getSetting("wallpaper.image").then((blob) => {
-      let FileReader = CC("@mozilla.org/files/filereader;1");
       let reader = new FileReader();
       let conn = this.conn;
       reader.addEventListener("load", function() {
         let str = new LongStringActor(conn, reader.result);
         deferred.resolve(str);
       });
       reader.addEventListener("error", function() {
         deferred.reject(reader.error);
--- a/devtools/server/actors/webapps.js
+++ b/devtools/server/actors/webapps.js
@@ -846,18 +846,17 @@ WebappsActor.prototype = {
         deferred.resolve({
           error: "noIcon",
           message: "The icon file '" + iconURL + "' doesn't exist"
         });
         return;
       }
 
       // Convert the blog to a base64 encoded data URI
-      let reader = Cc["@mozilla.org/files/filereader;1"]
-                     .createInstance(Ci.nsIDOMFileReader);
+      let reader = new FileReader();
       reader.onload = function () {
         deferred.resolve({
           url: reader.result
         });
       };
       reader.onerror = function () {
         deferred.resolve({
           error: reader.error.name,
--- a/dom/apps/ImportExport.jsm
+++ b/dom/apps/ImportExport.jsm
@@ -257,18 +257,17 @@ this.ImportExport = {
   },
 
   // Returns a promise that resolves to the temp file path.
   _writeBlobToTempFile: function(aBlob) {
     // Save the blob to a temp file.
     debug("_writeBlobToTempFile");
     let path;
     return new Promise((aResolve, aReject) => {
-      let reader = Cc['@mozilla.org/files/filereader;1']
-                     .createInstance(Ci.nsIDOMFileReader);
+      let reader = new FileReader();
       reader.onloadend = () => {
         path = OS.Path.join(OS.Constants.Path.tmpDir, "app-blob.zip");
         debug("onloadend path=" + path);
         OS.File.openUnique(path).then(obj => {
           path = obj.path;
           let file = obj.file;
           debug("openUnique path=" + path);
           return file.write(new Uint8Array(reader.result))
--- a/dom/base/FileReader.cpp
+++ b/dom/base/FileReader.cpp
@@ -65,194 +65,108 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(FileReader,
                                                DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultArrayBuffer)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileReader)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(FileReader, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(FileReader, DOMEventTargetHelper)
 
-NS_IMPL_EVENT_HANDLER(FileReader, abort)
-NS_IMPL_EVENT_HANDLER(FileReader, error)
-NS_IMPL_EVENT_HANDLER(FileReader, progress)
-NS_IMPL_EVENT_HANDLER(FileReader, load)
-NS_IMPL_EVENT_HANDLER(FileReader, loadend)
-NS_IMPL_EVENT_HANDLER(FileReader, loadstart)
-
 void
 FileReader::RootResultArrayBuffer()
 {
   mozilla::HoldJSObjects(this);
 }
 
 //FileReader constructors/initializers
 
-FileReader::FileReader()
-  : mFileData(nullptr)
+FileReader::FileReader(nsPIDOMWindow* aWindow)
+  : DOMEventTargetHelper(aWindow)
+  , mFileData(nullptr)
   , mDataLen(0)
   , mDataFormat(FILE_AS_BINARY)
   , mResultArrayBuffer(nullptr)
   , mProgressEventWasDelayed(false)
   , mTimerIsActive(false)
-  , mReadyState(0)
+  , mReadyState(EMPTY)
   , mTotal(0)
   , mTransferred(0)
 {
   SetDOMStringToNull(mResult);
 }
 
 FileReader::~FileReader()
 {
   FreeFileData();
   mResultArrayBuffer = nullptr;
   DropJSObjects(this);
 }
 
-/**
- * This Init method is called from the factory constructor.
- */
-nsresult
-FileReader::Init()
-{
-  // Instead of grabbing some random global from the context stack,
-  // let's use the default one (junk scope) for now.
-  // We should move away from this Init...
-  BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
-  return NS_OK;
-}
-
 /* static */ already_AddRefed<FileReader>
 FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
-  RefPtr<FileReader> fileReader = new FileReader();
-
+  // The owner can be null when this object is used by chrome code.
   nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
-  if (!owner) {
-    NS_WARNING("Unexpected owner");
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
+  RefPtr<FileReader> fileReader = new FileReader(owner);
+
+  if (!owner && nsContentUtils::IsCallerChrome()) {
+    // Instead of grabbing some random global from the context stack,
+    // let's use the default one (junk scope) for now.
+    // We should move away from this Init...
+    fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
   }
 
-  fileReader->BindToOwner(owner);
   return fileReader.forget();
 }
 
 // nsIInterfaceRequestor
 
 NS_IMETHODIMP
 FileReader::GetInterface(const nsIID & aIID, void **aResult)
 {
   return QueryInterface(aIID, aResult);
 }
 
-// nsIDOMFileReader
-
-NS_IMETHODIMP
-FileReader::GetReadyState(uint16_t *aReadyState)
-{
-  *aReadyState = ReadyState();
-  return NS_OK;
-}
-
 void
-FileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
+FileReader::GetResult(JSContext* aCx,
+                      JS::MutableHandle<JS::Value> aResult,
                       ErrorResult& aRv)
 {
-  aRv = GetResult(aCx, aResult);
-}
+  JS::Rooted<JS::Value> result(aCx);
 
-NS_IMETHODIMP
-FileReader::GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult)
-{
-  JS::Rooted<JS::Value> result(aCx);
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
-    if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) {
+    if (mReadyState == DONE && mResultArrayBuffer) {
       result.setObject(*mResultArrayBuffer);
     } else {
       result.setNull();
     }
+
     if (!JS_WrapValue(aCx, &result)) {
-      return NS_ERROR_FAILURE;
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
     }
+
     aResult.set(result);
-    return NS_OK;
+    return;
   }
 
   nsString tmpResult = mResult;
   if (!xpc::StringToJsval(aCx, tmpResult, aResult)) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
   }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileReader::GetError(nsISupports** aError)
-{
-  NS_IF_ADDREF(*aError = GetError());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-FileReader::ReadAsArrayBuffer(nsIDOMBlob* aBlob, JSContext* aCx)
-{
-  NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER);
-  ErrorResult rv;
-  RefPtr<Blob> blob = static_cast<Blob*>(aBlob);
-  ReadAsArrayBuffer(aCx, *blob, rv);
-  return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-FileReader::ReadAsBinaryString(nsIDOMBlob* aBlob)
-{
-  NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER);
-  ErrorResult rv;
-  RefPtr<Blob> blob = static_cast<Blob*>(aBlob);
-  ReadAsBinaryString(*blob, rv);
-  return rv.StealNSResult();
 }
 
-NS_IMETHODIMP
-FileReader::ReadAsText(nsIDOMBlob* aBlob,
-                            const nsAString &aCharset)
-{
-  NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER);
-  ErrorResult rv;
-  RefPtr<Blob> blob = static_cast<Blob*>(aBlob);
-  ReadAsText(*blob, aCharset, rv);
-  return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-FileReader::ReadAsDataURL(nsIDOMBlob* aBlob)
-{
-  NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER);
-  ErrorResult rv;
-  RefPtr<Blob> blob = static_cast<Blob*>(aBlob);
-  ReadAsDataURL(*blob, rv);
-  return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-FileReader::Abort()
-{
-  ErrorResult rv;
-  Abort(rv);
-  return rv.StealNSResult();
-}
-
-static
-NS_METHOD
+static NS_IMETHODIMP
 ReadFuncBinaryString(nsIInputStream* in,
                      void* closure,
                      const char* fromRawSegment,
                      uint32_t toOffset,
                      uint32_t count,
                      uint32_t *writeCount)
 {
   char16_t* dest = static_cast<char16_t*>(closure) + toOffset;
@@ -385,81 +299,83 @@ FileReader::DoReadData(nsIAsyncInputStre
 
 void
 FileReader::ReadFileContent(Blob& aBlob,
                             const nsAString &aCharset,
                             eDataFormat aDataFormat,
                             ErrorResult& aRv)
 {
   //Implicit abort to clear any other activity going on
-  Abort();
+  ErrorResult error;
+  Abort(error);
+  error.SuppressException();
+
   mError = nullptr;
   SetDOMStringToNull(mResult);
   mTransferred = 0;
   mTotal = 0;
-  mReadyState = nsIDOMFileReader::EMPTY;
+  mReadyState = EMPTY;
   FreeFileData();
 
   mBlob = &aBlob;
   mDataFormat = aDataFormat;
   CopyUTF16toUTF8(aCharset, mCharset);
 
   nsresult rv;
-
   nsCOMPtr<nsIStreamTransportService> sts =
     do_GetService(kStreamTransportServiceCID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(rv);
     return;
   }
 
   nsCOMPtr<nsIInputStream> stream;
   mBlob->GetInternalStream(getter_AddRefs(stream), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   nsCOMPtr<nsITransport> transport;
-  rv = sts->CreateInputTransport(stream,
-                                 /* aStartOffset */ 0,
-                                 /* aReadLimit */ -1,
-                                 /* aCloseWhenDone */ true,
-                                 getter_AddRefs(transport));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
+  aRv = sts->CreateInputTransport(stream,
+                                  /* aStartOffset */ 0,
+                                  /* aReadLimit */ -1,
+                                  /* aCloseWhenDone */ true,
+                                  getter_AddRefs(transport));
+  if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   nsCOMPtr<nsIInputStream> wrapper;
-  rv = transport->OpenInputStream(/* aFlags */ 0,
-                                  /* aSegmentSize */ 0,
-                                  /* aSegmentCount */ 0,
-                                  getter_AddRefs(wrapper));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
+  aRv = transport->OpenInputStream(/* aFlags */ 0,
+                                   /* aSegmentSize */ 0,
+                                   /* aSegmentCount */ 0,
+                                   getter_AddRefs(wrapper));
+  if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(!mAsyncStream);
   mAsyncStream = do_QueryInterface(wrapper);
   MOZ_ASSERT(mAsyncStream);
 
   mTotal = mBlob->GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  rv = DoAsyncWait(mAsyncStream);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(rv);
+  aRv = mAsyncStream->AsyncWait(this,
+                                /* aFlags*/ 0,
+                                /* aRequestedCount */ 0,
+                                NS_GetCurrentThread());
+  if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   //FileReader should be in loading state here
-  mReadyState = nsIDOMFileReader::LOADING;
+  mReadyState = LOADING;
   DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
 
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     mFileData = js_pod_malloc<char>(mTotal);
     if (!mFileData) {
       NS_WARNING("Preallocation failed for ReadFileData");
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     }
@@ -509,17 +425,17 @@ FileReader::GetAsText(Blob *aBlob,
 nsresult
 FileReader::GetAsDataURL(Blob *aBlob,
                          const char *aFileData,
                          uint32_t aDataLen,
                          nsAString& aResult)
 {
   aResult.AssignLiteral("data:");
 
-  nsString contentType;
+  nsAutoString contentType;
   aBlob->GetType(contentType);
   if (!contentType.IsEmpty()) {
     aResult.Append(contentType);
   } else {
     aResult.AppendLiteral("application/octet-stream");
   }
   aResult.AppendLiteral(";base64,");
 
@@ -625,29 +541,32 @@ FileReader::Notify(nsITimer* aTimer)
 
   return NS_OK;
 }
 
 // InputStreamCallback
 NS_IMETHODIMP
 FileReader::OnInputStreamReady(nsIAsyncInputStream* aStream)
 {
-  if (mReadyState != 1 || aStream != mAsyncStream) {
+  if (mReadyState != LOADING || aStream != mAsyncStream) {
     return NS_OK;
   }
 
   uint64_t aCount;
   nsresult rv = aStream->Available(&aCount);
 
   if (NS_SUCCEEDED(rv) && aCount) {
     rv = DoReadData(aStream, aCount);
   }
 
   if (NS_SUCCEEDED(rv)) {
-    rv = DoAsyncWait(aStream);
+    rv = aStream->AsyncWait(this,
+                            /* aFlags*/ 0,
+                            /* aRequestedCount */ 0,
+                            NS_GetCurrentThread());
   }
 
   if (NS_FAILED(rv) || !aCount) {
     if (rv == NS_BASE_STREAM_CLOSED) {
       rv = NS_OK;
     }
     return OnLoadEnd(rv);
   }
@@ -669,57 +588,48 @@ FileReader::OnInputStreamReady(nsIAsyncI
 
 nsresult
 FileReader::OnLoadEnd(nsresult aStatus)
 {
   // Cancel the progress event timer
   ClearProgressEventTimer();
 
   // FileReader must be in DONE stage after an operation
-  mReadyState = 2;
+  mReadyState = DONE;
 
-  nsString successEvent, termEvent;
+  nsAutoString successEvent, termEvent;
   nsresult rv = DoOnLoadEnd(aStatus, successEvent, termEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set the status field as appropriate
   if (NS_FAILED(aStatus)) {
     DispatchError(aStatus, termEvent);
     return NS_OK;
   }
 
   // Dispatch event to signify end of a successful operation
   DispatchProgressEvent(successEvent);
   DispatchProgressEvent(termEvent);
 
   return NS_OK;
 }
 
-nsresult
-FileReader::DoAsyncWait(nsIAsyncInputStream* aStream)
-{
-  return aStream->AsyncWait(this,
-                            /* aFlags*/ 0,
-                            /* aRequestedCount */ 0,
-                            NS_GetCurrentThread());
-}
-
 void
 FileReader::Abort(ErrorResult& aRv)
 {
-  if (mReadyState != 1) {
+  if (mReadyState != LOADING) {
     // XXX The spec doesn't say this
     aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR);
     return;
   }
 
   ClearProgressEventTimer();
 
-  mReadyState = 2; // There are DONE constants on multiple interfaces,
-                   // but they all have value 2.
+  mReadyState = DONE;
+
   // XXX The spec doesn't say this
   mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError"));
 
   // Revert status and result attributes
   SetDOMStringToNull(mResult);
   mResultArrayBuffer = nullptr;
 
   mAsyncStream = nullptr;
--- a/dom/base/FileReader.h
+++ b/dom/base/FileReader.h
@@ -8,17 +8,16 @@
 #define mozilla_dom_FileReader_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/DOMError.h"
 
 #include "nsCOMPtr.h"
 #include "nsIAsyncInputStream.h"
-#include "nsIDOMFileReader.h"
 #include "nsIStreamListener.h"
 #include "nsISupportsUtils.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsITimer.h"
 #include "nsJSUtils.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
@@ -29,39 +28,32 @@
 namespace mozilla {
 namespace dom {
 
 class Blob;
 
 extern const uint64_t kUnknownSize;
 
 class FileReader final : public DOMEventTargetHelper,
-                         public nsIDOMFileReader,
                          public nsIInterfaceRequestor,
                          public nsSupportsWeakReference,
                          public nsIInputStreamCallback,
                          public nsITimerCallback
 {
 public:
-  FileReader();
+  explicit FileReader(nsPIDOMWindow* aWindow);
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  NS_DECL_NSIDOMFILEREADER
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSIINTERFACEREQUESTOR
 
-  NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(FileReader, DOMEventTargetHelper)
 
-  nsPIDOMWindow* GetParentObject() const
-  {
-    return GetOwner();
-  }
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL
   static already_AddRefed<FileReader>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
   void ReadAsArrayBuffer(JSContext* aCx, Blob& aBlob, ErrorResult& aRv)
   {
     ReadFileContent(aBlob, EmptyString(), FILE_AS_ARRAYBUFFER, aRv);
@@ -76,17 +68,17 @@ public:
   {
     ReadFileContent(aBlob, EmptyString(), FILE_AS_DATAURL, aRv);
   }
 
   void Abort(ErrorResult& aRv);
 
   uint16_t ReadyState() const
   {
-    return mReadyState;
+    return static_cast<uint16_t>(mReadyState);
   }
 
   DOMError* GetError() const
   {
     return mError;
   }
 
   void GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
@@ -99,21 +91,26 @@ public:
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(loadend)
 
   void ReadAsBinaryString(Blob& aBlob, ErrorResult& aRv)
   {
     ReadFileContent(aBlob, EmptyString(), FILE_AS_BINARY, aRv);
   }
 
-  nsresult Init();
-
 private:
   virtual ~FileReader();
 
+  // This must be in sync with dom/webidl/FileReader.webidl
+  enum eReadyState {
+    EMPTY = 0,
+    LOADING = 1,
+    DONE = 2
+  };
+
   enum eDataFormat {
     FILE_AS_ARRAYBUFFER,
     FILE_AS_BINARY,
     FILE_AS_TEXT,
     FILE_AS_DATAURL
   };
 
   void RootResultArrayBuffer();
@@ -123,17 +120,16 @@ private:
                        ErrorResult& aRv);
   nsresult GetAsText(Blob *aBlob, const nsACString &aCharset,
                      const char *aFileData, uint32_t aDataLen,
                      nsAString &aResult);
   nsresult GetAsDataURL(Blob *aBlob, const char *aFileData,
                         uint32_t aDataLen, nsAString &aResult);
 
   nsresult OnLoadEnd(nsresult aStatus);
-  nsresult DoAsyncWait(nsIAsyncInputStream* aStream);
 
   void StartProgressEventTimer();
   void ClearProgressEventTimer();
   void DispatchError(nsresult rv, nsAString& finalEvent);
   nsresult DispatchProgressEvent(const nsAString& aType);
 
   nsresult DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount);
 
@@ -161,17 +157,17 @@ private:
   nsCOMPtr<nsITimer> mProgressNotifier;
   bool mProgressEventWasDelayed;
   bool mTimerIsActive;
 
   nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
 
   RefPtr<DOMError> mError;
 
-  uint16_t mReadyState;
+  eReadyState mReadyState;
 
   uint64_t mTotal;
   uint64_t mTransferred;
 };
 
 } // dom namespace
 } // mozilla namespace
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -11,17 +11,16 @@ XPIDL_SOURCES += [
     'nsIContentPolicy.idl',
     'nsIContentPolicyBase.idl',
     'nsIDocumentEncoder.idl',
     'nsIDOMBlob.idl',
     'nsIDOMDataChannel.idl',
     'nsIDOMDOMCursor.idl',
     'nsIDOMDOMRequest.idl',
     'nsIDOMFileList.idl',
-    'nsIDOMFileReader.idl',
     'nsIDOMFormData.idl',
     'nsIDOMParser.idl',
     'nsIDOMSerializer.idl',
     'nsIDroppedLinkHandler.idl',
     'nsIEntropyCollector.idl',
     'nsIFrameLoader.idl',
     'nsIImageLoadingContent.idl',
     'nsIMessageManager.idl',
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2270,18 +2270,17 @@ struct InterfaceShimEntry {
   const char *geckoName;
   const char *domName;
 };
 
 // We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
 // interface that has interface constants that sites might be getting off
 // of Ci.
 const InterfaceShimEntry kInterfaceShimMap[] =
-{ { "nsIDOMFileReader", "FileReader" },
-  { "nsIXMLHttpRequest", "XMLHttpRequest" },
+{ { "nsIXMLHttpRequest", "XMLHttpRequest" },
   { "nsIDOMDOMException", "DOMException" },
   { "nsIDOMNode", "Node" },
   { "nsIDOMCSSPrimitiveValue", "CSSPrimitiveValue" },
   { "nsIDOMCSSRule", "CSSRule" },
   { "nsIDOMCSSValue", "CSSValue" },
   { "nsIDOMEvent", "Event" },
   { "nsIDOMNSEvent", "Event" },
   { "nsIDOMKeyEvent", "KeyEvent" },
deleted file mode 100644
--- a/dom/base/nsIDOMFileReader.idl
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsIDOMEventTarget.idl"
-
-interface nsIDOMEventListener;
-interface nsIDOMBlob;
-
-[builtinclass, uuid(2f34c719-bc14-4546-9fb9-2bab75e56e45)]
-interface nsIDOMFileReader : nsIDOMEventTarget
-{
-  [implicit_jscontext]
-  void readAsArrayBuffer(in nsIDOMBlob filedata);
-  void readAsBinaryString(in nsIDOMBlob filedata);
-  void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding);
-  void readAsDataURL(in nsIDOMBlob file);
-
-  void abort();
-
-  const unsigned short EMPTY = 0;
-  const unsigned short LOADING = 1;
-  const unsigned short DONE = 2;
-  readonly attribute unsigned short readyState;
-
-  [implicit_jscontext]
-  readonly attribute jsval result;
-
-  // This is a DOMError
-  readonly attribute nsISupports error;
-
-  [implicit_jscontext] attribute jsval onloadstart;
-  [implicit_jscontext] attribute jsval onprogress;
-  [implicit_jscontext] attribute jsval onload;
-  [implicit_jscontext] attribute jsval onabort;
-  [implicit_jscontext] attribute jsval onerror;
-  [implicit_jscontext] attribute jsval onloadend;
-};
-
-%{ C++
-#define NS_FILEREADER_CID                            \
-{0x06aa7c21, 0xfe05, 0x4cf2,                         \
-{0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}}
-#define NS_FILEREADER_CONTRACTID \
-"@mozilla.org/files/filereader;1"
-%}
--- a/dom/base/test/test_ipc_messagemanager_blob.html
+++ b/dom/base/test/test_ipc_messagemanager_blob.html
@@ -21,19 +21,17 @@
       "use strict";
 
       addMessageListener("test:ipcClonedMessage", function(message) {
         if (!(message.json instanceof Components.interfaces.nsIDOMBlob)) {
           sendAsyncMessage(message.name, message.json);
           return;
         }
 
-        let reader =
-          Components.classes["@mozilla.org/files/filereader;1"]
-                    .createInstance(Components.interfaces.nsIDOMFileReader);
+        let reader = new FileReader();
         reader.addEventListener("load", function() {
           let response = reader.result == "this is a great success!" ?
                          message.json :
                          "error";
           sendAsyncMessage(message.name, response);
         });
         reader.readAsText(message.json);
       });
--- a/dom/indexedDB/test/test_message_manager_ipc.html
+++ b/dom/indexedDB/test/test_message_manager_ipc.html
@@ -45,21 +45,16 @@ function childFrameScript() {
     let diag = pass ? "" : "got " + a + ", expected " + b;
     ok(pass, name, diag);
   }
 
   function finish(result) {
     sendAsyncMessage(mmName, { op: "done", result: result });
   }
 
-  function createFileReader() {
-    return Cc["@mozilla.org/files/filereader;1"]
-             .createInstance(Ci.nsIDOMFileReader);
-  }
-
   function grabAndContinue(arg) {
     testGenerator.send(arg);
   }
 
   function errorHandler(event) {
     ok(false,
        event.target + " received error event: '" + event.target.error.name +
        "'");
@@ -73,33 +68,33 @@ function childFrameScript() {
     let blob = message.data;
 
     ok(blob instanceof Ci.nsIDOMBlob, "Message manager sent a blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
-    let reader = createFileReader();
+    let reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
 
     yield undefined;
 
     is(reader.result, blobText, "Blob has correct data");
 
     let slice = blob.slice(0, blobData[0].length, blobType);
 
     ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a blob");
     is(slice.size, blobData[0].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading slice");
 
-    reader = createFileReader();
+    reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
 
     yield undefined;
 
     is(reader.result, blobData[0], "Slice has correct data");
 
     info("Deleting database");
@@ -150,17 +145,17 @@ function childFrameScript() {
     blob = event.target.result;
 
     ok(blob instanceof Ci.nsIDOMBlob, "Database gave us a blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
-    reader = createFileReader();
+    reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
 
     yield undefined;
 
     is(reader.result, blobText, "Blob has correct data");
 
     info("Storing slice from message manager in database");
@@ -185,17 +180,17 @@ function childFrameScript() {
     slice = event.target.result;
 
     ok(slice instanceof Ci.nsIDOMBlob, "Database gave us a blob");
     is(slice.size, blobData[0].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading Slice");
 
-    reader = createFileReader();
+    reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
 
     yield undefined;
 
     is(reader.result, blobData[0], "Slice has correct data");
 
     info("Sending blob and slice from database to message manager");
--- a/dom/indexedDB/test/unit/test_blob_file_backed.js
+++ b/dom/indexedDB/test/unit/test_blob_file_backed.js
@@ -2,21 +2,16 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 var disableWorkerTest = "This test uses SpecialPowers";
 
 var testGenerator = testSteps();
 
-function createFileReader() {
-  return SpecialPowers.Cc["@mozilla.org/files/filereader;1"]
-                      .createInstance(SpecialPowers.Ci.nsIDOMFileReader);
-}
-
 function testSteps()
 {
   const fileIOFlags = 0x02 | // PR_WRONLY
                       0x08 | // PR_CREATEFILE
                       0x20;  // PR_TRUNCATE
   const filePerms = 0664;
   const fileData = "abcdefghijklmnopqrstuvwxyz";
   const fileType = "text/plain";
@@ -43,17 +38,17 @@ function testSteps()
   outStream.write(fileData, fileData.length);
   outStream.close();
 
   let file = SpecialPowers.createDOMFile(testFile.path, { type: fileType });
   ok(file instanceof File, "Got a File object");
   is(file.size, fileData.length, "Correct size");
   is(file.type, fileType, "Correct type");
 
-  let fileReader = createFileReader();
+  let fileReader = new FileReader();
   fileReader.onload = grabEventAndContinueHandler;
   fileReader.readAsText(file);
 
   let event = yield undefined;
 
   is(fileReader.result, fileData, "Correct data");
 
   let request = indexedDB.open(databaseName, 1);
@@ -80,17 +75,17 @@ function testSteps()
   event = yield undefined;
 
   file = event.target.result;
 
   ok(file instanceof File, "Got a File object");
   is(file.size, fileData.length, "Correct size");
   is(file.type, fileType, "Correct type");
 
-  fileReader = createFileReader();
+  fileReader = new FileReader();
   fileReader.onload = grabEventAndContinueHandler;
   fileReader.readAsText(file);
 
   event = yield undefined;
 
   is(fileReader.result, fileData, "Correct data");
 
   finishTest();
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -334,22 +334,16 @@ function getBlob(str)
   return new Blob([str], {type: "type/text"});
 }
 
 function getFile(name, type, str)
 {
   return new File([str], name, {type: type});
 }
 
-function getFileReader()
-{
-  return SpecialPowers.Cc["@mozilla.org/files/filereader;1"]
-                      .createInstance(SpecialPowers.Ci.nsIDOMFileReader);
-}
-
 function compareBuffers(buffer1, buffer2)
 {
   if (buffer1.byteLength != buffer2.byteLength) {
     return false;
   }
   let view1 = new Uint8Array(buffer1);
   let view2 = new Uint8Array(buffer2);
   for (let i = 0; i < buffer1.byteLength; i++) {
@@ -383,29 +377,29 @@ function verifyBlob(blob1, blob2)
   for (let i = 0; i < bufferCache.length; i++) {
     if (bufferCache[i].blob == blob2) {
       buffer2 = bufferCache[i].buffer;
       break;
     }
   }
 
   if (!buffer2) {
-    let reader = getFileReader();
+    let reader = new FileReader();
     reader.readAsArrayBuffer(blob2);
     reader.onload = function(event) {
       buffer2 = event.target.result;
       bufferCache.push({ blob: blob2, buffer: buffer2 });
       if (buffer1) {
         verifyBuffers(buffer1, buffer2);
         testGenerator.next();
       }
     }
   }
 
-  let reader = getFileReader();
+  let reader = new FileReader();
   reader.readAsArrayBuffer(blob1);
   reader.onload = function(event) {
     buffer1 = event.target.result;
     if (buffer2) {
       verifyBuffers(buffer1, buffer2);
       testGenerator.next();
     }
   }
--- a/dom/ipc/tests/test_blob_sliced_from_parent_process.html
+++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html
@@ -39,38 +39,33 @@ function childFrameScript() {
     let diag = pass ? "" : "got " + a + ", expected " + b;
     ok(pass, name, diag);
   }
 
   function finish(result) {
     sendAsyncMessage(messageName, { op: "done", result: result });
   }
 
-  function createFileReader() {
-    return Cc["@mozilla.org/files/filereader;1"]
-             .createInstance(Ci.nsIDOMFileReader);
-  }
-
   function grabAndContinue(arg) {
     testGenerator.send(arg);
   }
 
   function testSteps() {
     addMessageListener(messageName, grabAndContinue);
     let message = yield undefined;
 
     let blob = message.data;
 
     ok(blob instanceof Ci.nsIDOMBlob, "Received a Blob");
     is(blob.size, blobText.length, "Blob has correct length");
     is(blob.type, blobType, "Blob has correct type");
 
     info("Reading blob");
 
-    let reader = createFileReader();
+    let reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
 
     yield undefined;
 
     is(reader.result, blobText, "Blob has correct data");
 
     let firstSliceStart = blobData[0].length + blobData[1].length;
@@ -79,17 +74,17 @@ function childFrameScript() {
     let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType);
 
     ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a Blob");
     is(slice.size, blobData[2].length, "Slice has correct length");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading slice");
 
-    reader = createFileReader();
+    reader = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
 
     yield undefined;
 
     is(reader.result, blobData[2], "Slice has correct data");
 
     let secondSliceStart = blobData[2].indexOf("a");
--- a/dom/mobilemessage/gonk/MmsService.js
+++ b/dom/mobilemessage/gonk/MmsService.js
@@ -1298,18 +1298,17 @@ SendTransaction.prototype = Object.creat
         if (!(aPart.content instanceof Blob)) {
           numPartsToLoad--;
           if (!numPartsToLoad) {
             callbackIfValid();
           }
           return;
         }
 
-        let fileReader = Cc["@mozilla.org/files/filereader;1"]
-                         .createInstance(Ci.nsIDOMFileReader);
+        let fileReader = new FileReader();
         fileReader.addEventListener("loadend", (aEvent) => {
           let arrayBuffer = aEvent.target.result;
           aPart.content = new Uint8Array(arrayBuffer);
           numPartsToLoad--;
           if (!numPartsToLoad) {
             callbackIfValid();
           }
         });
--- a/dom/webidl/FileReader.webidl
+++ b/dom/webidl/FileReader.webidl
@@ -5,17 +5,18 @@
  *
  * The origin of this IDL file is
  * http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader
  *
  * Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Constructor]
+[Constructor,
+ Exposed=(Window,System)]
 interface FileReader : EventTarget {
   // async read methods
   [Throws]
   void readAsArrayBuffer(Blob blob);
   [Throws]
   void readAsText(Blob blob, optional DOMString label = "");
   [Throws]
   void readAsDataURL(Blob blob);
--- a/js/xpconnect/tests/mochitest/test_bug790732.html
+++ b/js/xpconnect/tests/mochitest/test_bug790732.html
@@ -15,17 +15,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   var Ci = Components.interfaces;
   ok(Ci, "interfaces shim exists!");
   is(typeof Components.classes, 'undefined', "Shouldn't have a Cc");
 
   // Check each interface that we shim. We start by checking specific
   // constants for a couple of interfaces, and then once it's pretty clear that
   // it's working as intended we just check that the objects themselves are the
   // same.
-  is(Ci.nsIDOMFileReader.DONE, FileReader.DONE);
   is(Ci.nsIXMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.HEADERS_RECEIVED);
   is(Ci.nsIDOMDOMException.DATA_CLONE_ERR, DOMException.DATA_CLONE_ERR);
   is(Ci.nsIDOMNode.DOCUMENT_NODE, Node.DOCUMENT_NODE);
   is(Ci.nsIDOMCSSPrimitiveValue.CSS_PX, CSSPrimitiveValue.CSS_PX);
   is(Ci.nsIDOMCSSRule.NAMESPACE_RULE, CSSRule.NAMESPACE_RULE);
   is(Ci.nsIDOMCSSValue.CSS_PRIMITIVE_VALUE, CSSValue.CSS_PRIMITIVE_VALUE);
   is(Ci.nsIDOMEvent.FOCUS, Event.FOCUS);
   is(Ci.nsIDOMNSEvent.CLICK, Event.CLICK);
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -62,19 +62,16 @@
 
 #include "mozilla/dom/DOMParser.h"
 #include "nsDOMSerializer.h"
 #include "nsXMLHttpRequest.h"
 
 // view stuff
 #include "nsContentCreatorFunctions.h"
 
-// DOM includes
-#include "mozilla/dom/FileReader.h"
-
 #include "nsFormData.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHostObjectURI.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsIControllerCommandTable.h"
 #include "nsJSProtocolHandler.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsIControllerContext.h"
@@ -296,17 +293,16 @@ using mozilla::gmp::GeckoMediaPluginServ
 already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
 NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(FileReader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormData)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaStreamProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSourceProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontTableProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMParser)
 NS_GENERIC_FACTORY_CONSTRUCTOR(Exception)
@@ -746,17 +742,16 @@ NS_DEFINE_NAMED_CID(NS_WINDOWCONTROLLER_
 NS_DEFINE_NAMED_CID(NS_PLUGINDOCLOADERFACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_PLUGINDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_VIDEODOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_STYLESHEETSERVICE_CID);
 NS_DEFINE_NAMED_CID(TRANSFORMIIX_XSLT_PROCESSOR_CID);
 NS_DEFINE_NAMED_CID(TRANSFORMIIX_XPATH_EVALUATOR_CID);
 NS_DEFINE_NAMED_CID(TRANSFORMIIX_NODESET_CID);
 NS_DEFINE_NAMED_CID(NS_XMLSERIALIZER_CID);
-NS_DEFINE_NAMED_CID(NS_FILEREADER_CID);
 NS_DEFINE_NAMED_CID(NS_FORMDATA_CID);
 NS_DEFINE_NAMED_CID(NS_BLOBPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_MEDIASTREAMPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_MEDIASOURCEPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_FONTTABLEPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_HOSTOBJECTURI_CID);
 NS_DEFINE_NAMED_CID(NS_XMLHTTPREQUEST_CID);
 NS_DEFINE_NAMED_CID(NS_DOMPARSER_CID);
@@ -1054,17 +1049,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_PLUGINDOCLOADERFACTORY_CID, false, nullptr, CreateContentDLF },
   { &kNS_PLUGINDOCUMENT_CID, false, nullptr, CreatePluginDocument },
   { &kNS_VIDEODOCUMENT_CID, false, nullptr, CreateVideoDocument },
   { &kNS_STYLESHEETSERVICE_CID, false, nullptr, nsStyleSheetServiceConstructor },
   { &kTRANSFORMIIX_XSLT_PROCESSOR_CID, false, nullptr, txMozillaXSLTProcessorConstructor },
   { &kTRANSFORMIIX_XPATH_EVALUATOR_CID, false, nullptr, XPathEvaluatorConstructor },
   { &kTRANSFORMIIX_NODESET_CID, false, nullptr, txNodeSetAdaptorConstructor },
   { &kNS_XMLSERIALIZER_CID, false, nullptr, nsDOMSerializerConstructor },
-  { &kNS_FILEREADER_CID, false, nullptr, FileReaderConstructor },
   { &kNS_FORMDATA_CID, false, nullptr, nsFormDataConstructor },
   { &kNS_BLOBPROTOCOLHANDLER_CID, false, nullptr, nsBlobProtocolHandlerConstructor },
   { &kNS_MEDIASTREAMPROTOCOLHANDLER_CID, false, nullptr, nsMediaStreamProtocolHandlerConstructor },
   { &kNS_MEDIASOURCEPROTOCOLHANDLER_CID, false, nullptr, nsMediaSourceProtocolHandlerConstructor },
   { &kNS_FONTTABLEPROTOCOLHANDLER_CID, false, nullptr, nsFontTableProtocolHandlerConstructor },
   { &kNS_HOSTOBJECTURI_CID, false, nullptr, nsHostObjectURIConstructor },
   { &kNS_XMLHTTPREQUEST_CID, false, nullptr, nsXMLHttpRequestConstructor },
   { &kNS_DOMPARSER_CID, false, nullptr, DOMParserConstructor },
@@ -1222,17 +1216,16 @@ static const mozilla::Module::ContractID
   { NS_JSPROTOCOLHANDLER_CONTRACTID, &kNS_JSPROTOCOLHANDLER_CID },
   { NS_WINDOWCONTROLLER_CONTRACTID, &kNS_WINDOWCONTROLLER_CID },
   { PLUGIN_DLF_CONTRACTID, &kNS_PLUGINDOCLOADERFACTORY_CID },
   { NS_STYLESHEETSERVICE_CONTRACTID, &kNS_STYLESHEETSERVICE_CID },
   { TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID, &kTRANSFORMIIX_XSLT_PROCESSOR_CID },
   { NS_XPATH_EVALUATOR_CONTRACTID, &kTRANSFORMIIX_XPATH_EVALUATOR_CID },
   { TRANSFORMIIX_NODESET_CONTRACTID, &kTRANSFORMIIX_NODESET_CID },
   { NS_XMLSERIALIZER_CONTRACTID, &kNS_XMLSERIALIZER_CID },
-  { NS_FILEREADER_CONTRACTID, &kNS_FILEREADER_CID },
   { NS_FORMDATA_CONTRACTID, &kNS_FORMDATA_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME, &kNS_MEDIASTREAMPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASOURCEURI_SCHEME, &kNS_MEDIASOURCEPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX FONTTABLEURI_SCHEME, &kNS_FONTTABLEPROTOCOLHANDLER_CID },
   { NS_XMLHTTPREQUEST_CONTRACTID, &kNS_XMLHTTPREQUEST_CID },
   { NS_DOMPARSER_CONTRACTID, &kNS_DOMPARSER_CID },
   { XPC_EXCEPTION_CONTRACTID, &kNS_XPCEXCEPTION_CID },
--- a/toolkit/components/thumbnails/PageThumbs.jsm
+++ b/toolkit/components/thumbnails/PageThumbs.jsm
@@ -78,19 +78,19 @@ const TaskUtils = {
    * Read the bytes from a blob, asynchronously.
    *
    * @return {Promise}
    * @resolve {ArrayBuffer} In case of success, the bytes contained in the blob.
    * @reject {DOMError} In case of error, the underlying DOMError.
    */
   readBlob: function readBlob(blob) {
     let deferred = Promise.defer();
-    let reader = Cc["@mozilla.org/files/filereader;1"].createInstance(Ci.nsIDOMFileReader);
+    let reader = new FileReader();
     reader.onloadend = function onloadend() {
-      if (reader.readyState != Ci.nsIDOMFileReader.DONE) {
+      if (reader.readyState != FileReader.DONE) {
         deferred.reject(reader.error);
       } else {
         deferred.resolve(reader.result);
       }
     };
     reader.readAsArrayBuffer(blob);
     return deferred.promise;
   }
@@ -300,18 +300,17 @@ this.PageThumbs = {
       // Ignore events unrelated to our request
       if (aMsg.data.id != index) {
         return;
       }
 
       mm.removeMessageListener("Browser:Thumbnail:Response", thumbFunc);
       let imageBlob = aMsg.data.thumbnail;
       let doc = aBrowser.parentElement.ownerDocument;
-      let reader = Cc["@mozilla.org/files/filereader;1"].
-                   createInstance(Ci.nsIDOMFileReader);
+      let reader = new FileReader();
       reader.addEventListener("loadend", function() {
         let image = doc.createElementNS(PageThumbUtils.HTML_NAMESPACE, "img");
         image.onload = function () {
           let thumbnail = doc.createElementNS(PageThumbUtils.HTML_NAMESPACE, "canvas");
           thumbnail.width = image.naturalWidth;
           thumbnail.height = image.naturalHeight;
           let ctx = thumbnail.getContext("2d");
           ctx.drawImage(image, 0, 0);
--- a/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
@@ -136,18 +136,17 @@ const backgroundPageThumbsContent = {
       capture.imageBlob = new Blob([blob]);
       // Load about:blank to finish the capture and wait for onStateChange.
       this._loadAboutBlank();
     });
   },
 
   _finishCurrentCapture: function () {
     let capture = this._currentCapture;
-    let fileReader = Cc["@mozilla.org/files/filereader;1"].
-                     createInstance(Ci.nsIDOMFileReader);
+    let fileReader = new FileReader();
     fileReader.onloadend = () => {
       sendAsyncMessage("BackgroundPageThumbs:didCapture", {
         id: capture.id,
         imageData: fileReader.result,
         finalURL: capture.finalURL,
         telemetry: {
           CAPTURE_PAGE_LOAD_TIME_MS: capture.pageLoadTime,
           CAPTURE_CANVAS_DRAW_TIME_MS: capture.canvasDrawTime,
--- a/toolkit/modules/PropertyListUtils.jsm
+++ b/toolkit/modules/PropertyListUtils.jsm
@@ -95,18 +95,17 @@ this.PropertyListUtils = Object.freeze({
       try {
         if (file instanceof Ci.nsILocalFile) {
           if (!file.exists())
             throw new Error("The file pointed by aFile does not exist");
 
           file = new File(file);
         }
 
-        let fileReader = Cc["@mozilla.org/files/filereader;1"].
-                         createInstance(Ci.nsIDOMFileReader);
+        let fileReader = new FileReader();
         let onLoadEnd = function() {
           let root = null;
           try {
             fileReader.removeEventListener("loadend", onLoadEnd, false);
             if (fileReader.readyState != fileReader.DONE)
               throw new Error("Could not read file contents: " + fileReader.error);
 
             root = this._readFromArrayBufferSync(fileReader.result);
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -39,17 +39,16 @@
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMFileList.h"
-#include "nsIDOMFileReader.h"
 #include "nsIDOMFocusEvent.h"
 #include "nsIDOMFormData.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDOMHistory.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLBaseElement.h"
@@ -174,17 +173,16 @@
 #include "mozilla/dom/DocumentFragmentBinding.h"
 #include "mozilla/dom/DocumentTypeBinding.h"
 #include "mozilla/dom/DocumentBinding.h"
 #include "mozilla/dom/DragEventBinding.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/EventBinding.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/FileListBinding.h"
-#include "mozilla/dom/FileReaderBinding.h"
 #include "mozilla/dom/FocusEventBinding.h"
 #include "mozilla/dom/FormDataBinding.h"
 #include "mozilla/dom/HistoryBinding.h"
 #include "mozilla/dom/HTMLAnchorElementBinding.h"
 #include "mozilla/dom/HTMLAppletElementBinding.h"
 #include "mozilla/dom/HTMLAreaElementBinding.h"
 #include "mozilla/dom/HTMLBaseElementBinding.h"
 #include "mozilla/dom/HTMLBodyElementBinding.h"
@@ -363,17 +361,16 @@ const ComponentsInterfaceShimEntry kComp
   DEFINE_SHIM(Document),
   DEFINE_SHIM(DocumentFragment),
   DEFINE_SHIM(DocumentType),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMDocumentXBL, Document),
   DEFINE_SHIM(DragEvent),
   DEFINE_SHIM(Element),
   DEFINE_SHIM(Event),
   DEFINE_SHIM(EventTarget),
-  DEFINE_SHIM(FileReader),
   DEFINE_SHIM(FileList),
   DEFINE_SHIM(FocusEvent),
   DEFINE_SHIM(FormData),
   DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError),
   DEFINE_SHIM(History),
   DEFINE_SHIM(HTMLAnchorElement),
   DEFINE_SHIM(HTMLAppletElement),
   DEFINE_SHIM(HTMLAreaElement),