Bug 1163388 - patch 1 - make nsIDOMFile an empty interface, r=ehsan
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 18 May 2015 14:51:54 +0100
changeset 265189 bbee8cb95f97d1a44a6eb4f47f8b0c406495a29d
parent 265188 61455ff4e6ef91611424e9a669aba8fab8b629fc
child 265190 a6bf6230c4a57a61468d57fa4279de3710a7fcd1
push id2102
push usermartin.thomson@gmail.com
push dateMon, 18 May 2015 17:35:37 +0000
reviewersehsan
bugs1163388
milestone41.0a1
Bug 1163388 - patch 1 - make nsIDOMFile an empty interface, r=ehsan
dom/archivereader/ArchiveRequest.cpp
dom/base/File.cpp
dom/base/File.h
dom/base/MultipartBlobImpl.cpp
dom/base/nsDOMWindowUtils.cpp
dom/base/nsIDOMFile.idl
dom/bluetooth/bluedroid/BluetoothOppManager.cpp
dom/bluetooth/bluetooth1/BluetoothService.h
dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.h
dom/bluetooth/bluez/BluetoothDBusService.cpp
dom/bluetooth/bluez/BluetoothDBusService.h
dom/bluetooth/bluez/BluetoothOppManager.cpp
dom/bluetooth/bluez/BluetoothOppManager.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/nsFormSubmission.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/ipc/Blob.cpp
dom/webidl/File.webidl
dom/webidl/HTMLInputElement.webidl
--- a/dom/archivereader/ArchiveRequest.cpp
+++ b/dom/archivereader/ArchiveRequest.cpp
@@ -172,35 +172,32 @@ ArchiveRequest::ReaderReady(nsTArray<nsR
 }
 
 nsresult
 ArchiveRequest::GetFilenamesResult(JSContext* aCx,
                                    JS::Value* aValue,
                                    nsTArray<nsRefPtr<File>>& aFileList)
 {
   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
-  nsresult rv;
 
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JSString*> str(aCx);
   for (uint32_t i = 0; i < aFileList.Length(); ++i) {
     nsRefPtr<File> file = aFileList[i];
 
     nsString filename;
-    rv = file->GetName(filename);
-    NS_ENSURE_SUCCESS(rv, rv);
+    file->GetName(filename);
 
     str = JS_NewUCStringCopyZ(aCx, filename.get());
     NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
 
-    if (NS_FAILED(rv) ||
-        !JS_DefineElement(aCx, array, i, str, JSPROP_ENUMERATE)) {
+    if (!JS_DefineElement(aCx, array, i, str, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   if (!JS_FreezeObject(aCx, array)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -212,18 +209,17 @@ nsresult
 ArchiveRequest::GetFileResult(JSContext* aCx,
                               JS::MutableHandle<JS::Value> aValue,
                               nsTArray<nsRefPtr<File>>& aFileList)
 {
   for (uint32_t i = 0; i < aFileList.Length(); ++i) {
     nsRefPtr<File> file = aFileList[i];
 
     nsString filename;
-    nsresult rv = file->GetName(filename);
-    NS_ENSURE_SUCCESS(rv, rv);
+    file->GetName(filename);
 
     if (filename == mFilename) {
       if (!ToJSValue(aCx, file, aValue)) {
         return NS_ERROR_FAILURE;
       }
 
       return NS_OK;
     }
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -548,27 +548,26 @@ File::CreateFromFile(nsISupports* aParen
 }
 
 JSObject*
 File::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return FileBinding::Wrap(aCx, this, aGivenProto);
 }
 
-NS_IMETHODIMP
+void
 File::GetName(nsAString& aFileName)
 {
   mImpl->GetName(aFileName);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-File::GetPath(nsAString& aPath)
+void
+File::GetPath(nsAString& aPath, ErrorResult& aRv)
 {
-  return mImpl->GetPath(aPath);
+  mImpl->GetPath(aPath, aRv);
 }
 
 Date
 File::GetLastModifiedDate(ErrorResult& aRv)
 {
   int64_t value = GetLastModified(aRv);
   if (aRv.Failed()) {
     return Date();
@@ -578,63 +577,26 @@ File::GetLastModifiedDate(ErrorResult& a
 }
 
 int64_t
 File::GetLastModified(ErrorResult& aRv)
 {
   return mImpl->GetLastModified(aRv);
 }
 
-NS_IMETHODIMP
-File::GetLastModifiedDate(JSContext* aCx,
-                          JS::MutableHandle<JS::Value> aDate)
-{
-  ErrorResult rv;
-  Date value = GetLastModifiedDate(rv);
-  if (rv.Failed()) {
-    return rv.StealNSResult();
-  }
-
-  if (!value.ToDateObject(aCx, aDate)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-File::GetMozFullPath(nsAString& aFileName)
-{
-  ErrorResult rv;
-  GetMozFullPath(aFileName, rv);
-  return rv.StealNSResult();
-}
-
 void
 File::GetMozFullPath(nsAString& aFilename, ErrorResult& aRv)
 {
   mImpl->GetMozFullPath(aFilename, aRv);
 }
 
-NS_IMETHODIMP
-File::GetMozFullPathInternal(nsAString& aFileName)
+void
+File::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv)
 {
-  ErrorResult rv;
-  mImpl->GetMozFullPathInternal(aFileName, rv);
-  return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
-File::GetMozLastModifiedDate(int64_t* aDate)
-{
-  MOZ_ASSERT(aDate);
-
-  ErrorResult rv;
-  *aDate = GetLastModified(rv);
-  return rv.StealNSResult();
+  mImpl->GetMozFullPathInternal(aFileName, aRv);
 }
 
 // Makes sure that aStart and aEnd is less then or equal to aSize and greater
 // than 0
 static void
 ParseSize(int64_t aSize, int64_t& aStart, int64_t& aEnd)
 {
   CheckedInt64 newStartOffset = aStart;
@@ -812,22 +774,21 @@ NS_IMPL_ISUPPORTS_INHERITED0(BlobImplFil
 
 void
 BlobImplBase::GetName(nsAString& aName)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   aName = mName;
 }
 
-nsresult
-BlobImplBase::GetPath(nsAString& aPath)
+void
+BlobImplBase::GetPath(nsAString& aPath, ErrorResult& aRv)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   aPath = mPath;
-  return NS_OK;
 }
 
 void
 BlobImplBase::GetMozFullPath(nsAString& aFileName, ErrorResult& aRv)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
 
   aFileName.Truncate();
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -240,25 +240,28 @@ public:
 
   // File constructor - ChromeOnly
   static already_AddRefed<File>
   Constructor(const GlobalObject& aGlobal,
               nsIFile* aData,
               const ChromeFilePropertyBag& aBag,
               ErrorResult& aRv);
 
-  // XPCOM GetName is OK
+  void GetName(nsAString& aName);
 
   int64_t GetLastModified(ErrorResult& aRv);
 
   Date GetLastModifiedDate(ErrorResult& aRv);
 
+  void GetPath(nsAString& aName, ErrorResult& aRv);
 
   void GetMozFullPath(nsAString& aFilename, ErrorResult& aRv);
 
+  void GetMozFullPathInternal(nsAString& aName, ErrorResult& aRv);
+
 protected:
   virtual bool HasFileInterface() const override { return true; }
 
 private:
   // File constructor should never be used directly. Use Blob::Create or
   // File::Create.
   File(nsISupports* aParent, BlobImpl* aImpl);
   ~File() {};
@@ -271,17 +274,17 @@ class BlobImpl : public nsISupports
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(FILEIMPL_IID)
   NS_DECL_THREADSAFE_ISUPPORTS
 
   BlobImpl() {}
 
   virtual void GetName(nsAString& aName) = 0;
 
-  virtual nsresult GetPath(nsAString& aName) = 0;
+  virtual void GetPath(nsAString& aName, ErrorResult& aRv) = 0;
 
   virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
 
   virtual void SetLastModified(int64_t aLastModified) = 0;
 
   virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) = 0;
 
   virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) = 0;
@@ -399,17 +402,17 @@ public:
     NS_ASSERTION(aLength != UINT64_MAX,
                  "Must know length when creating slice");
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
   virtual void GetName(nsAString& aName) override;
 
-  virtual nsresult GetPath(nsAString& aName) override;
+  virtual void GetPath(nsAString& aName, ErrorResult& aRv) override;
 
   virtual int64_t GetLastModified(ErrorResult& aRv) override;
 
   virtual void SetLastModified(int64_t aLastModified) override;
 
   virtual void GetMozFullPath(nsAString& aName, ErrorResult& aRv) override;
 
   virtual void GetMozFullPathInternal(nsAString& aFileName,
--- a/dom/base/MultipartBlobImpl.cpp
+++ b/dom/base/MultipartBlobImpl.cpp
@@ -361,18 +361,17 @@ MultipartBlobImpl::InitializeChromeFile(
   // Pre-cache size.
   uint64_t unused;
   aRv = blob->GetSize(&unused);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // Pre-cache modified date.
-  int64_t unusedDate;
-  aRv = blob->GetMozLastModifiedDate(&unusedDate);
+  blob->GetLastModified(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // XXXkhuey this is terrible
   if (mContentType.IsEmpty()) {
     blob->GetType(mContentType);
   }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -53,16 +53,17 @@
 #include "nsComputedDOMStyle.h"
 #include "nsIPresShell.h"
 #include "nsCSSProps.h"
 #include "nsTArrayHelpers.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/dom/File.h"
+#include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/DOMRect.h"
 #include <algorithm>
 
 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK)
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #endif
 
@@ -2853,25 +2854,23 @@ nsDOMWindowUtils::GetFilePath(JS::Handle
 
   if (aFile.isPrimitive()) {
     _retval.Truncate();
     return NS_OK;
   }
 
   JSObject* obj = aFile.toObjectOrNull();
 
-  nsISupports* nativeObj =
-    nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
-
-  nsCOMPtr<nsIDOMFile> file = do_QueryInterface(nativeObj);
-  if (file) {
+  File* file = nullptr;
+  if (NS_SUCCEEDED(UNWRAP_OBJECT(File, obj, file))) {
     nsString filePath;
-    nsresult rv = file->GetMozFullPathInternal(filePath);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    ErrorResult rv;
+    file->GetMozFullPathInternal(filePath, rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      return rv.StealNSResult();
     }
 
     _retval = filePath;
     return NS_OK;
   }
 
   _retval.Truncate();
   return NS_OK;
--- a/dom/base/nsIDOMFile.idl
+++ b/dom/base/nsIDOMFile.idl
@@ -53,25 +53,14 @@ interface nsIDOMBlob : nsISupports
   // Return true if this blob is a memory file.
   [notxpcom] bool isMemoryFile();
 };
 
 // We want to avoid multiple inheritance of nsIDOMBlob so we can downcast from
 // nsIDOMBlob to Blob safely.  Our chain is:
 //  - Blob -> nsIDOMBlob
 //  - File -> nsIDOMFile and Blob
-[scriptable, builtinclass, uuid(cc28cf12-f1d4-44ff-843f-9289aa14613b)]
+[scriptable, builtinclass, uuid(26e292a6-f5aa-4560-b523-ae22a4c7dfca)]
 interface nsIDOMFile : nsISupports
 {
-  readonly attribute DOMString name;
-
-  readonly attribute DOMString path;
-
-  [implicit_jscontext]
-  readonly attribute jsval lastModifiedDate;
-
-  readonly attribute DOMString mozFullPath;
-
-  // This performs no security checks!
-  [noscript] readonly attribute DOMString mozFullPathInternal;
-
-  [noscript] readonly attribute int64_t mozLastModifiedDate;
+  // Empty interface used by addons and some test to check if the object is a
+  // blob or file. This interface will be removed by bug 1163388
 };
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -789,17 +789,17 @@ BluetoothOppManager::ExtractBlobHeaders(
   return true;
 }
 
 void
 BluetoothOppManager::RetrieveSentFileName()
 {
   mFileName.Truncate();
 
-  nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
+  nsRefPtr<File> file = static_cast<Blob*>(mBlob.get()).ToFile();
   if (file) {
     file->GetName(mFileName);
   }
 
   /**
    * We try our best to get the file extention to avoid interoperability issues.
    * However, once we found that we are unable to get suitable extension or
    * information about the content type, sending a pre-defined file name without
--- a/dom/bluetooth/bluetooth1/BluetoothService.h
+++ b/dom/bluetooth/bluetooth1/BluetoothService.h
@@ -6,25 +6,23 @@
 
 #ifndef mozilla_dom_bluetooth_bluetootheventservice_h__
 #define mozilla_dom_bluetooth_bluetootheventservice_h__
 
 #include "BluetoothCommon.h"
 #include "BluetoothProfileManagerBase.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
-#include "nsIDOMFile.h"
 #include "nsIObserver.h"
 #include "nsTObserverArray.h"
 #include "nsThreadUtils.h"
 
-class nsIDOMBlob;
-
 namespace mozilla {
 namespace dom {
+class Blob;
 class BlobChild;
 class BlobParent;
 }
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothNamedValue;
@@ -236,17 +234,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
--- a/dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.cpp
@@ -261,17 +261,17 @@ BluetoothServiceChildProcess::SendFile(
 {
   SendRequest(aRunnable,
               SendFileRequest(nsString(aDeviceAddress), nullptr, aBlobChild));
 }
 
 void
 BluetoothServiceChildProcess::SendFile(
   const nsAString& aDeviceAddress,
-  nsIDOMBlob* aBlobChild,
+  Blob* aBlobChild,
   BluetoothReplyRunnable* aRunnable)
 {
   // Parent-process-only method
   MOZ_CRASH("This should never be called!");
 }
 
 void
 BluetoothServiceChildProcess::StopSendingFile(
--- a/dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/bluetooth1/ipc/BluetoothServiceChildProcess.h
@@ -106,17 +106,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress,
--- a/dom/bluetooth/bluez/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp
@@ -4156,17 +4156,17 @@ BluetoothDBusService::SendFile(const nsA
     errorStr.AssignLiteral("Calling SendFile() failed");
   }
 
   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
 }
 
 void
 BluetoothDBusService::SendFile(const nsAString& aDeviceAddress,
-                               nsIDOMBlob* aBlob,
+                               Blob* aBlob,
                                BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Currently we only support one device sending one file at a time,
   // so we don't need aDeviceAddress here because the target device
   // has been determined when calling 'Connect()'. Nevertheless, keep
   // it for future use.
--- a/dom/bluetooth/bluez/BluetoothDBusService.h
+++ b/dom/bluetooth/bluez/BluetoothDBusService.h
@@ -169,17 +169,17 @@ public:
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
-           nsIDOMBlob* aBlob,
+           Blob* aBlob,
            BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable) override;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
--- a/dom/bluetooth/bluez/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothOppManager.cpp
@@ -68,26 +68,27 @@ namespace {
       0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
     }
   };
 
   StaticRefPtr<BluetoothOppManager> sBluetoothOppManager;
   static bool sInShutdown = false;
 }
 
-class mozilla::dom::bluetooth::SendFileBatch {
+class mozilla::dom::bluetooth::SendFileBatch
+{
 public:
-  SendFileBatch(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob)
+  SendFileBatch(const nsAString& aDeviceAddress, Blob* aBlob)
     : mDeviceAddress(aDeviceAddress)
   {
     mBlobs.AppendElement(aBlob);
   }
 
   nsString mDeviceAddress;
-  nsCOMArray<nsIDOMBlob> mBlobs;
+  nsTArray<nsRefPtr<Blob>> mBlobs;
 };
 
 NS_IMETHODIMP
 BluetoothOppManager::Observe(nsISupports* aSubject,
                              const char* aTopic,
                              const char16_t* aData)
 {
   MOZ_ASSERT(sBluetoothOppManager);
@@ -380,38 +381,38 @@ BluetoothOppManager::StartSendingNextFil
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               BlobParent* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsRefPtr<BlobImpl> impl = aActor->GetBlobImpl();
-  nsCOMPtr<nsIDOMBlob> blob = Blob::Create(nullptr, impl);
+  nsRefPtr<Blob> blob = Blob::Create(nullptr, impl);
 
-  return SendFile(aDeviceAddress, blob.get());
+  return SendFile(aDeviceAddress, blob);
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
-                              nsIDOMBlob* aBlob)
+                              Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   AppendBlobToSend(aDeviceAddress, aBlob);
   if (!mSocket) {
     ProcessNextBatch();
   }
 
   return true;
 }
 
 void
 BluetoothOppManager::AppendBlobToSend(const nsAString& aDeviceAddress,
-                                      nsIDOMBlob* aBlob)
+                                      Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   int indexTail = mBatches.Length() - 1;
 
   /**
    * Create a new batch if
    * - mBatches is empty, or
@@ -761,17 +762,17 @@ BluetoothOppManager::ExtractBlobHeaders(
   return true;
 }
 
 void
 BluetoothOppManager::RetrieveSentFileName()
 {
   mFileName.Truncate();
 
-  nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
+  nsRefPtr<File> file = mBlob->ToFile();
   if (file) {
     file->GetName(mFileName);
   }
 
   /**
    * We try our best to get the file extention to avoid interoperability issues.
    * However, once we found that we are unable to get suitable extension or
    * information about the content type, sending a pre-defined file name without
--- a/dom/bluetooth/bluez/BluetoothOppManager.h
+++ b/dom/bluetooth/bluez/BluetoothOppManager.h
@@ -9,23 +9,23 @@
 
 #include "BluetoothCommon.h"
 #include "BluetoothProfileManagerBase.h"
 #include "BluetoothSocketObserver.h"
 #include "DeviceStorage.h"
 #include "mozilla/ipc/SocketBase.h"
 #include "nsCOMArray.h"
 
-class nsIDOMBlob;
 class nsIOutputStream;
 class nsIInputStream;
 class nsIVolumeMountLock;
 
 namespace mozilla {
 namespace dom {
+class Blob;
 class BlobParent;
 }
 }
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocket;
 class ObexHeaderSet;
@@ -46,17 +46,17 @@ public:
 
   static BluetoothOppManager* Get();
   void ClientDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
   void ServerDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
 
   bool Listen();
 
   bool SendFile(const nsAString& aDeviceAddress, BlobParent* aActor);
-  bool SendFile(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob);
+  bool SendFile(const nsAString& aDeviceAddress, Blob* aBlob);
   bool StopSendingFile();
   bool ConfirmReceivingFile(bool aConfirm);
 
   void SendConnectRequest();
   void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize);
   void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength);
   void SendPutFinalRequest();
   void SendDisconnectRequest();
@@ -91,17 +91,17 @@ private:
   void AfterOppDisconnected();
   void ValidateFileName();
   bool IsReservedChar(char16_t c);
   void ClearQueue();
   void RetrieveSentFileName();
   void NotifyAboutFileChange();
   bool AcquireSdcardMountLock();
   void SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize);
-  void AppendBlobToSend(const nsAString& aDeviceAddress, nsIDOMBlob* aBlob);
+  void AppendBlobToSend(const nsAString& aDeviceAddress, Blob* aBlob);
   void DiscardBlobsToSend();
   bool ProcessNextBatch();
   void ConnectInternal(const nsAString& aDeviceAddress);
 
   /**
    * Usually we won't get a full PUT packet in one operation, which means that
    * a packet may be devided into several parts and BluetoothOppManager should
    * be in charge of assembling.
@@ -188,17 +188,17 @@ private:
   uint32_t mFileLength;
   uint32_t mSentFileLength;
   bool mWaitingToSendPutFinal;
 
   nsAutoArrayPtr<uint8_t> mBodySegment;
   nsAutoArrayPtr<uint8_t> mReceivedDataBuffer;
 
   int mCurrentBlobIndex;
-  nsCOMPtr<nsIDOMBlob> mBlob;
+  nsRefPtr<Blob> mBlob;
   nsTArray<SendFileBatch> mBatches;
 
   /**
    * A seperate member thread is required because our read calls can block
    * execution, which is not allowed to happen on the IOThread.
    */
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -488,28 +488,33 @@ NS_IMPL_ISUPPORTS(DirPickerRecursiveFile
 
 /**
  * This may return nullptr if aDomFile's implementation of
  * nsIDOMFile::mozFullPathInternal does not successfully return a non-empty
  * string that is a valid path. This can happen on Firefox OS, for example,
  * where the file picker can create Blobs.
  */
 static already_AddRefed<nsIFile>
-DOMFileToLocalFile(nsIDOMFile* aDomFile)
+DOMFileToLocalFile(File* aDomFile)
 {
   nsString path;
-  nsresult rv = aDomFile->GetMozFullPathInternal(path);
-  if (NS_FAILED(rv) || path.IsEmpty()) {
+  ErrorResult rv;
+  aDomFile->GetMozFullPathInternal(path, rv);
+  if (rv.Failed() || path.IsEmpty()) {
+    rv.SuppressException();
     return nullptr;
   }
 
   nsCOMPtr<nsIFile> localFile;
   rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
                              getter_AddRefs(localFile));
-  NS_ENSURE_SUCCESS(rv, nullptr);
+  if (NS_WARN_IF(rv.Failed())) {
+    rv.SuppressException();
+    return nullptr;
+  }
 
   return localFile.forget();
 }
 
 } // anonymous namespace
 
 class DirPickerFileListBuilderTask final
   : public nsRunnable
@@ -964,17 +969,21 @@ HTMLInputElement::InitFilePicker(FilePic
 
   nsCOMPtr<nsIFilePickerShownCallback> callback =
     new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
 
   if (!oldFiles.IsEmpty() &&
       aType != FILE_PICKER_DIRECTORY) {
     nsString path;
 
-    oldFiles[0]->GetMozFullPathInternal(path);
+    ErrorResult error;
+    oldFiles[0]->GetMozFullPathInternal(path, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
+    }
 
     nsCOMPtr<nsIFile> localFile;
     rv = NS_NewLocalFile(path, false, getter_AddRefs(localFile));
 
     if (NS_SUCCEEDED(rv)) {
       nsCOMPtr<nsIFile> parentFile;
       rv = localFile->GetParent(getter_AddRefs(parentFile));
       if (NS_SUCCEEDED(rv)) {
@@ -1703,26 +1712,33 @@ HTMLInputElement::GetValueInternal(nsASt
     case VALUE_MODE_FILENAME:
       if (nsContentUtils::IsCallerChrome()) {
 #ifndef MOZ_CHILD_PERMISSIONS
         aValue.Assign(mFirstFilePath);
 #else
         // XXX We'd love to assert that this can't happen, but some mochitests
         // use SpecialPowers to circumvent our more sane security model.
         if (!mFiles.IsEmpty()) {
-          return mFiles[0]->GetMozFullPath(aValue);
+          ErrorResult rv;
+          mFiles[0]->GetMozFullPath(aValue, rv);
+          if (NS_WARN_IF(rv.Failed())) {
+            return rv.StealNSResult();
+          }
+          return NS_OK;
         }
         else {
           aValue.Truncate();
         }
 #endif
       } else {
         // Just return the leaf name
-        if (mFiles.IsEmpty() || NS_FAILED(mFiles[0]->GetName(aValue))) {
+        if (mFiles.IsEmpty()) {
           aValue.Truncate();
+        } else {
+          mFiles[0]->GetName(aValue);
         }
       }
 
       return NS_OK;
 
     case VALUE_MODE_DEFAULT:
       // Treat defaultValue as value.
       GetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue);
@@ -2302,37 +2318,46 @@ void
 HTMLInputElement::FlushFrames()
 {
   if (GetComposedDoc()) {
     GetComposedDoc()->FlushPendingNotifications(Flush_Frames);
   }
 }
 
 void
-HTMLInputElement::MozGetFileNameArray(nsTArray< nsString >& aArray)
+HTMLInputElement::MozGetFileNameArray(nsTArray<nsString>& aArray,
+                                      ErrorResult& aRv)
 {
   for (uint32_t i = 0; i < mFiles.Length(); i++) {
     nsString str;
-    mFiles[i]->GetMozFullPathInternal(str);
+    mFiles[i]->GetMozFullPathInternal(str, aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return;
+    }
+
     aArray.AppendElement(str);
   }
 }
 
 
 NS_IMETHODIMP
 HTMLInputElement::MozGetFileNameArray(uint32_t* aLength, char16_t*** aFileNames)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     // Since this function returns full paths it's important that normal pages
     // can't call it.
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  ErrorResult rv;
   nsTArray<nsString> array;
-  MozGetFileNameArray(array);
+  MozGetFileNameArray(array, rv);
+  if (NS_WARN_IF(rv.Failed())) {
+    return rv.StealNSResult();
+  }
 
   *aLength = array.Length();
   char16_t** ret =
     static_cast<char16_t**>(moz_xmalloc(*aLength * sizeof(char16_t*)));
   if (!ret) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
@@ -2682,17 +2707,21 @@ HTMLInputElement::AfterSetFiles(bool aSe
   // Grab the full path here for any chrome callers who access our .value via a
   // CPOW. This path won't be called from a CPOW meaning the potential sync IPC
   // call under GetMozFullPath won't be rejected for not being urgent.
   // XXX Protected by the ifndef because the blob code doesn't allow us to send
   // this message in b2g.
   if (mFiles.IsEmpty()) {
     mFirstFilePath.Truncate();
   } else {
-    mFiles[0]->GetMozFullPath(mFirstFilePath);
+    ErrorResult rv;
+    mFiles[0]->GetMozFullPath(mFirstFilePath, rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      rv.SuppressException();
+    }
   }
 #endif
 
   UpdateFileList();
 
   if (aSetValueChanged) {
     SetValueChanged(true);
   }
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -708,17 +708,17 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::usemap, aValue, aRv);
   }
 
   nsIControllers* GetControllers(ErrorResult& aRv);
 
   int32_t GetTextLength(ErrorResult& aRv);
 
-  void MozGetFileNameArray(nsTArray< nsString >& aFileNames);
+  void MozGetFileNameArray(nsTArray<nsString>& aFileNames, ErrorResult& aRv);
 
   void MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv);
   void MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles);
 
   HTMLInputElement* GetOwnerNumberControl();
 
   void StartNumberControlSpinnerSpin();
   void StopNumberControlSpinnerSpin();
--- a/dom/html/nsFormSubmission.cpp
+++ b/dom/html/nsFormSubmission.cpp
@@ -446,25 +446,23 @@ nsFSMultipartFormData::AddNameFilePair(c
   nsAutoCString nameStr;
   nsresult rv = EncodeVal(aName, nameStr, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString filename, contentType;
   nsCOMPtr<nsIInputStream> fileStream;
   if (aFile) {
     nsAutoString filename16;
-    rv = aFile->GetName(filename16);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
+    aFile->GetName(filename16);
 
+    ErrorResult error;
     nsAutoString filepath16;
-    rv = aFile->GetPath(filepath16);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    aFile->GetPath(filepath16, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.StealNSResult();
     }
 
     if (!filepath16.IsEmpty()) {
       // File.path includes trailing "/"
       filename16 = filepath16 + filename16;
     }
 
     rv = EncodeVal(filename16, filename, true);
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -329,24 +329,24 @@ StructuredCloneWriteCallback(JSContext* 
           !JS_WriteBytes(aWriter, &size, sizeof(size)) ||
           !JS_WriteBytes(aWriter, &convTypeLength, sizeof(convTypeLength)) ||
           !JS_WriteBytes(aWriter, convType.get(), convType.Length())) {
         return false;
       }
 
       nsRefPtr<File> file = blob->ToFile();
       if (file) {
-        int64_t lastModifiedDate;
-        MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
-          file->GetMozLastModifiedDate(&lastModifiedDate)));
+        ErrorResult rv;
+        int64_t lastModifiedDate = file->GetLastModified(rv);
+        MOZ_ALWAYS_TRUE(!rv.Failed());
 
         lastModifiedDate = NativeEndian::swapToLittleEndian(lastModifiedDate);
 
         nsString name;
-        MOZ_ALWAYS_TRUE(NS_SUCCEEDED(file->GetName(name)));
+        file->GetName(name);
 
         NS_ConvertUTF16toUTF8 convName(name);
         uint32_t convNameLength =
           NativeEndian::swapToLittleEndian(convName.Length());
 
         if (!JS_WriteBytes(aWriter, &lastModifiedDate, sizeof(lastModifiedDate)) || 
             !JS_WriteBytes(aWriter, &convNameLength, sizeof(convNameLength)) ||
             !JS_WriteBytes(aWriter, convName.get(), convName.Length())) {
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -2059,18 +2059,18 @@ public:
   void
   NoteDyingActor();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual void
   GetName(nsAString& aName) override;
 
-  virtual nsresult
-  GetPath(nsAString& aPath) override;
+  virtual void
+  GetPath(nsAString& aPath, ErrorResult& aRv) override;
 
   virtual int64_t
   GetLastModified(ErrorResult& aRv) override;
 
   virtual void
   SetLastModified(int64_t aLastModified) override;
 
   virtual void
@@ -2737,21 +2737,21 @@ NS_IMPL_QUERY_INTERFACE_INHERITED(BlobPa
 
 void
 BlobParent::
 RemoteBlobImpl::GetName(nsAString& aName)
 {
   mBlobImpl->GetName(aName);
 }
 
-nsresult
+void
 BlobParent::
-RemoteBlobImpl::GetPath(nsAString& aPath)
+RemoteBlobImpl::GetPath(nsAString& aPath, ErrorResult& aRv)
 {
-  return mBlobImpl->GetPath(aPath);
+  mBlobImpl->GetPath(aPath, aRv);
 }
 
 int64_t
 BlobParent::
 RemoteBlobImpl::GetLastModified(ErrorResult& aRv)
 {
   return mBlobImpl->GetLastModified(aRv);
 }
--- a/dom/webidl/File.webidl
+++ b/dom/webidl/File.webidl
@@ -40,11 +40,13 @@ dictionary ChromeFilePropertyBag : FileP
 
 // Mozilla extensions
 partial interface File {
 
   [GetterThrows]
   readonly attribute Date lastModifiedDate;
 
   [GetterThrows, ChromeOnly]
-  readonly attribute DOMString mozFullPath;
+  readonly attribute DOMString path;
 
+  [GetterThrows, ChromeOnly]
+  readonly attribute DOMString mozFullPath;
 };
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -143,17 +143,17 @@ partial interface HTMLInputElement {
   [Throws]
   void setSelectionRange(long start, long end, optional DOMString direction);
 
   [GetterThrows, ChromeOnly]
   readonly attribute nsIControllers        controllers;
   [GetterThrows]
   readonly attribute long                  textLength;
 
-  [ChromeOnly]
+  [Throws, ChromeOnly]
   sequence<DOMString> mozGetFileNameArray();
 
   [ChromeOnly, Throws]
   void mozSetFileNameArray(sequence<DOMString> fileNames);
 
   [ChromeOnly]
   void mozSetFileArray(sequence<File> files);