Bug 1462964: Remove obsolete nsIDOMBlob interface. r=bz
authorKris Maglione <maglione.k@gmail.com>
Mon, 21 May 2018 17:32:44 -0700
changeset 419332 4f8b341fea03c37954f49dff6f6c1d91e8efafec
parent 419331 2fab91090fafb967999a5d500093c2b7a33ecd77
child 419333 a1bf5dfd3c00c5e59a59272fb03d0d6684539b82
push id34037
push userdluca@mozilla.com
push dateWed, 23 May 2018 09:51:55 +0000
treeherdermozilla-central@d36cd8bdbc5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1462964
milestone62.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 1462964: Remove obsolete nsIDOMBlob interface. r=bz MozReview-Commit-ID: 2HIlaSrvfBe
dom/events/DataTransferItem.cpp
dom/file/Blob.cpp
dom/file/Blob.h
dom/file/moz.build
dom/file/nsIDOMBlob.idl
dom/file/tests/test_ipc_messagemanager_blob.html
dom/html/HTMLInputElement.cpp
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/test/file.js
dom/indexedDB/test/test_message_manager_ipc.html
dom/indexedDB/test/unit/xpcshell-head-parent-process.js
dom/interfaces/base/nsIDOMWindow.idl
dom/ipc/tests/test_blob_sliced_from_parent_process.html
dom/media/nsIDOMNavigatorUserMedia.idl
dom/presentation/PresentationService.cpp
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/PresentationSessionInfo.h
dom/presentation/PresentationTCPSessionTransport.cpp
dom/presentation/interfaces/nsIPresentationService.idl
dom/presentation/interfaces/nsIPresentationSessionTransport.idl
dom/presentation/ipc/PresentationBuilderParent.cpp
dom/presentation/ipc/PresentationContentSessionInfo.cpp
dom/presentation/ipc/PresentationContentSessionInfo.h
dom/presentation/ipc/PresentationIPCService.cpp
editor/libeditor/HTMLEditorDataTransfer.cpp
editor/nsIEditorUtils.idl
ipc/glue/BackgroundChild.h
js/xpconnect/tests/chrome/test_cloneInto.xul
js/xpconnect/tests/unit/component-blob.js
js/xpconnect/tests/unit/test_blob2.js
toolkit/modules/PropertyListUtils.jsm
widget/nsBaseFilePicker.cpp
widget/nsFilePickerProxy.cpp
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -104,17 +104,17 @@ DataTransferItem::SetData(nsIVariant* aD
 
 /* static */ DataTransferItem::eKind
 DataTransferItem::KindFromData(nsIVariant* aData)
 {
   nsCOMPtr<nsISupports> supports;
   nsresult rv = aData->GetAsISupports(getter_AddRefs(supports));
   if (NS_SUCCEEDED(rv) && supports) {
     // Check if we have one of the supported file data formats
-    if (nsCOMPtr<nsIDOMBlob>(do_QueryInterface(supports)) ||
+    if (RefPtr<Blob>(do_QueryObject(supports)) ||
         nsCOMPtr<BlobImpl>(do_QueryInterface(supports)) ||
         nsCOMPtr<nsIFile>(do_QueryInterface(supports))) {
       return KIND_FILE;
     }
   }
 
   nsAutoString string;
   // If we can't get the data type as a string, that means that the object
@@ -287,18 +287,17 @@ DataTransferItem::GetAsFile(nsIPrincipal
     nsCOMPtr<nsISupports> supports;
     aRv = data->GetAsISupports(getter_AddRefs(supports));
     MOZ_ASSERT(!aRv.Failed() && supports,
                "File objects should be stored as nsISupports variants");
     if (aRv.Failed() || !supports) {
       return nullptr;
     }
 
-    if (nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports)) {
-      Blob* blob = static_cast<Blob*>(domBlob.get());
+    if (RefPtr<Blob> blob = do_QueryObject(supports)) {
       mCachedFile = blob->ToFile();
     } else if (nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(supports)) {
       MOZ_ASSERT(blobImpl->IsFile());
       mCachedFile = File::Create(mDataTransfer, blobImpl);
     } else if (nsCOMPtr<nsIFile> ifile = do_QueryInterface(supports)) {
       mCachedFile = File::CreateFromFile(mDataTransfer, ifile);
     } else {
       MOZ_ASSERT(false, "One of the above code paths should be taken");
--- a/dom/file/Blob.cpp
+++ b/dom/file/Blob.cpp
@@ -29,18 +29,22 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMBlob)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutable)
+  // Alas, there is no helper macro for this.
+  if (aIID.Equals(NS_GET_IID(Blob))) {
+    *aInstancePtr = do_AddRef(this).take();
+    return NS_OK;
+  } else
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
 
 void
--- a/dom/file/Blob.h
+++ b/dom/file/Blob.h
@@ -8,41 +8,44 @@
 #define mozilla_dom_Blob_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/BlobImpl.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
-#include "nsIDOMBlob.h"
 #include "nsIMutable.h"
 #include "nsWrapperCache.h"
 #include "nsWeakReference.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 
 struct BlobPropertyBag;
 class File;
 class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
 
-class Blob : public nsIDOMBlob
-           , public nsIMutable
+#define NS_DOM_BLOB_IID \
+{ 0x648c2a83, 0xbdb1, 0x4a7d, \
+  { 0xb5, 0x0a, 0xca, 0xcd, 0x92, 0x87, 0x45, 0xc2 } }
+
+
+class Blob : public nsIMutable
            , public nsSupportsWeakReference
            , public nsWrapperCache
 {
 public:
-  NS_DECL_NSIDOMBLOB
   NS_DECL_NSIMUTABLE
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIMutable)
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_BLOB_IID)
 
   typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
 
   // This creates a Blob or a File based on the type of BlobImpl.
   static Blob*
   Create(nsISupports* aParent, BlobImpl* aImpl);
 
   static already_AddRefed<Blob>
@@ -142,16 +145,24 @@ protected:
   // between threads.
   // Note: we should not store any other state in this class!
   RefPtr<BlobImpl> mImpl;
 
 private:
   nsCOMPtr<nsISupports> mParent;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(Blob, NS_DOM_BLOB_IID)
+
 // Override BindingJSObjectMallocBytes for blobs to tell the JS GC how much
 // memory is held live by the binding object.
 size_t BindingJSObjectMallocBytes(Blob* aBlob);
 
 } // namespace dom
 } // namespace mozilla
 
+inline nsISupports*
+ToSupports(mozilla::dom::Blob* aBlob)
+{
+  return static_cast<nsIMutable*>(aBlob);
+}
+
 #endif // mozilla_dom_Blob_h
--- a/dom/file/moz.build
+++ b/dom/file/moz.build
@@ -4,22 +4,16 @@
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM: File")
 
 DIRS += ['ipc']
 
-XPIDL_SOURCES += [
-    'nsIDOMBlob.idl',
-]
-
-XPIDL_MODULE = 'dom_file'
-
 EXPORTS += [
     'nsHostObjectProtocolHandler.h',
     'nsHostObjectURI.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'BaseBlobImpl.h',
     'Blob.h',
deleted file mode 100644
--- a/dom/file/nsIDOMBlob.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-/* -*- Mode: IDL; 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 "nsISupports.idl"
-
-[scriptable, builtinclass, uuid(f344146a-ee1f-417e-8a68-6984ca56f0ae)]
-interface nsIDOMBlob : nsISupports
-{
-  // Just an empty interface.
-};
--- a/dom/file/tests/test_ipc_messagemanager_blob.html
+++ b/dom/file/tests/test_ipc_messagemanager_blob.html
@@ -14,18 +14,20 @@
 
     SimpleTest.waitForExplicitFinish();
 
     const childFrameURL = "file_ipc_messagemanager_blob.html";
 
     function childFrameScript() {
       "use strict";
 
+      Cu.importGlobalProperties(["Blob"]);
+
       addMessageListener("test:ipcClonedMessage", function(message) {
-        if (!(message.json instanceof Ci.nsIDOMBlob)) {
+        if (!Blob.isInstance(message.json)) {
           sendAsyncMessage(message.name, message.json);
           return;
         }
 
         let reader = new FileReader();
         reader.addEventListener("load", function() {
           let response = reader.result == "this is a great success!" ?
                          message.json :
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/WheelEventBinding.h"
 #include "nsAttrValueInlines.h"
 #include "nsCRTGlue.h"
+#include "nsQueryObject.h"
 
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioVisitor.h"
 #include "InputType.h"
 
 #include "HTMLFormSubmissionConstants.h"
 #include "mozilla/Telemetry.h"
@@ -503,36 +504,36 @@ HTMLInputElement::nsFilePickerShownCallb
       return NS_OK;
     }
 
     nsCOMPtr<nsISupports> tmp;
     bool hasMore = true;
 
     while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
       iter->GetNext(getter_AddRefs(tmp));
-      nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(tmp);
+      RefPtr<Blob> domBlob = do_QueryObject(tmp);
       MOZ_ASSERT(domBlob,
                  "Null file object from FilePicker's file enumerator?");
       if (!domBlob) {
         continue;
       }
 
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
-      element->SetAsFile() = static_cast<File*>(domBlob.get());
+      element->SetAsFile() = domBlob->ToFile();
     }
   } else {
     MOZ_ASSERT(mode == static_cast<int16_t>(nsIFilePicker::modeOpen) ||
                mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder));
     nsCOMPtr<nsISupports> tmp;
     nsresult rv = mFilePicker->GetDomFileOrDirectory(getter_AddRefs(tmp));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(tmp);
+    RefPtr<Blob> blob = do_QueryObject(tmp);
     if (blob) {
-      RefPtr<File> file = static_cast<Blob*>(blob.get())->ToFile();
+      RefPtr<File> file = blob->ToFile();
       MOZ_ASSERT(file);
 
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
       element->SetAsFile() = file;
     } else if (tmp) {
       RefPtr<Directory> directory = static_cast<Directory*>(tmp.get());
       OwningFileOrDirectory* element = newFilesOrDirectories.AppendElement();
       element->SetAsDirectory() = directory;
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -910,18 +910,17 @@ IDBDatabase::GetOrCreateFileActorForBlob
   AssertIsOnOwningThread();
   MOZ_ASSERT(aBlob);
   MOZ_ASSERT(mBackgroundActor);
 
   // We use the File's nsIWeakReference as the key to the table because
   // a) it is unique per blob, b) it is reference-counted so that we can
   // guarantee that it stays alive, and c) it doesn't hold the actual File
   // alive.
-  nsCOMPtr<nsIDOMBlob> blob = aBlob;
-  nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(blob);
+  nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(aBlob);
   MOZ_ASSERT(weakRef);
 
   PBackgroundIDBDatabaseFileChild* actor = nullptr;
 
   if (!mFileActors.Get(weakRef, &actor)) {
     BlobImpl* blobImpl = aBlob->Impl();
     MOZ_ASSERT(blobImpl);
 
--- a/dom/indexedDB/test/file.js
+++ b/dom/indexedDB/test/file.js
@@ -105,18 +105,18 @@ function getWasmModule(binary)
 function verifyBuffers(buffer1, buffer2)
 {
   ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
 }
 
 function verifyBlob(blob1, blob2, fileId, blobReadHandler)
 {
   // eslint-disable-next-line mozilla/use-cc-etc
-  is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
-     "Instance of nsIDOMBlob");
+  is(SpecialPowers.wrap(Blob).isInstance(blob1), true,
+     "Instance of Blob");
   is(blob1 instanceof File, blob2 instanceof File,
      "Instance of DOM File");
   is(blob1.size, blob2.size, "Correct size");
   is(blob1.type, blob2.type, "Correct type");
   if (blob2 instanceof File) {
     is(blob1.name, blob2.name, "Correct name");
   }
   is(utils.getFileId(blob1), fileId, "Correct file id");
--- a/dom/indexedDB/test/test_message_manager_ipc.html
+++ b/dom/indexedDB/test/test_message_manager_ipc.html
@@ -20,17 +20,17 @@ function childFrameScript() {
   const dbVersion = 1;
   const objStoreName = "bar";
   const key = 1;
 
   const blobData = ["So", " ", "many", " ", "blobs!"];
   const blobText = blobData.join("");
   const blobType = "text/plain";
 
-  Cu.importGlobalProperties(["indexedDB"]);
+  Cu.importGlobalProperties(["indexedDB", "Blob"]);
 
   function info(msg) {
     sendAsyncMessage(mmName, { op: "info", msg });
   }
 
   function ok(condition, name, diag) {
     sendAsyncMessage(mmName,
                      { op: "ok",
@@ -61,33 +61,33 @@ function childFrameScript() {
   }
 
   function* testSteps() {
     addMessageListener(mmName, grabAndContinue);
     let message = yield undefined;
 
     let blob = message.data;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Message manager sent a blob");
+    ok(Blob.isInstance(blob), "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 = 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");
+    ok(Blob.isInstance(slice), "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 = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
@@ -138,17 +138,17 @@ function childFrameScript() {
     req = objectStore.get(key);
     req.onerror = errorHandler;
     req.onsuccess = grabAndContinue;
 
     event = yield undefined;
 
     blob = event.target.result;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Database gave us a blob");
+    ok(Blob.isInstance(blob), "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 = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
@@ -173,17 +173,17 @@ function childFrameScript() {
     req = objectStore.get(key);
     req.onerror = errorHandler;
     req.onsuccess = grabAndContinue;
 
     event = yield undefined;
 
     slice = event.target.result;
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Database gave us a blob");
+    ok(Blob.isInstance(slice), "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 = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -5,16 +5,18 @@
 
 // Tests using testGenerator are expected to define it themselves.
 /* global testGenerator */
 
 var { "classes": Cc, "interfaces": Ci, "utils": Cu } = Components;
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+Cu.importGlobalProperties(["Blob"]);
+
 if (!("self" in this)) {
   this.self = this;
 }
 
 var bufferCache = [];
 
 function is(a, b, msg) {
   Assert.equal(a, b, msg);
@@ -421,17 +423,17 @@ function compareBuffers(buffer1, buffer2
 
 function verifyBuffers(buffer1, buffer2)
 {
   ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
 }
 
 function verifyBlob(blob1, blob2)
 {
-  is(blob1 instanceof Ci.nsIDOMBlob, true,
+  is(Blob.isInstance(blob1), true,
      "Instance of nsIDOMBlob");
   is(blob1 instanceof File, blob2 instanceof File,
      "Instance of DOM File");
   is(blob1.size, blob2.size, "Correct size");
   is(blob1.type, blob2.type, "Correct type");
   if (blob2 instanceof File) {
     is(blob1.name, blob2.name, "Correct name");
   }
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -1,17 +1,16 @@
 /* -*- Mode: IDL; 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 "domstubs.idl"
 
 interface nsIControllers;
-interface nsIDOMBlob;
 interface nsIDOMOfflineResourceList;
 interface nsIPrompt;
 interface nsIVariant;
 
 /**
  * Empty interface for compatibility with older versions.
  * @deprecated Use WebIDL for script visible features,
  *             nsPIDOMWindow for C++ callers.
--- a/dom/ipc/tests/test_blob_sliced_from_parent_process.html
+++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html
@@ -47,17 +47,17 @@ function childFrameScript() {
   }
 
   function* testSteps() {
     addMessageListener(messageName, grabAndContinue);
     let message = yield undefined;
 
     let blob = message.data;
 
-    ok(blob instanceof Ci.nsIDOMBlob, "Received a Blob");
+    ok(Blob.isInstance(blob), "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 = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(blob);
@@ -66,17 +66,17 @@ function childFrameScript() {
 
     is(reader.result, blobText, "Blob has correct data");
 
     let firstSliceStart = blobData[0].length + blobData[1].length;
     let firstSliceEnd = firstSliceStart + blobData[2].length;
 
     let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType);
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a Blob");
+    ok(Blob.isInstance(slice), "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 = new FileReader();
     reader.addEventListener("load", grabAndContinue);
     reader.readAsText(slice);
@@ -85,17 +85,17 @@ function childFrameScript() {
 
     is(reader.result, blobData[2], "Slice has correct data");
 
     let secondSliceStart = blobData[2].indexOf("a");
     let secondSliceEnd = secondSliceStart + sliceText.length;
 
     slice = slice.slice(secondSliceStart, secondSliceEnd, blobType);
 
-    ok(slice instanceof Ci.nsIDOMBlob, "Second slice returned a Blob");
+    ok(Blob.isInstance(slice), "Second slice returned a Blob");
     is(slice.size, sliceText.length, "Second slice has correct length");
     is(slice.type, blobType, "Second slice has correct type");
 
     info("Sending second slice");
     finish(slice);
   }
 
   let testGenerator = testSteps();
--- a/dom/media/nsIDOMNavigatorUserMedia.idl
+++ b/dom/media/nsIDOMNavigatorUserMedia.idl
@@ -21,17 +21,17 @@ interface nsIGetUserMediaDevicesSuccessC
 {
   void onSuccess(in nsIVariant devices);
 };
 
 [scriptable, function, uuid(f2a144fc-3534-4761-8c5d-989ae720f89a)]
 interface nsIDOMGetUserMediaSuccessCallback : nsISupports
 {
   /*
-   * value must be a nsIDOMBlob if picture is true and a
+   * value must be a Blob if picture is true and a
    * DOMLocalMediaStream if either audio or video are true.
    */
   void onSuccess(in nsISupports value);
 };
 
 [scriptable, function, uuid(39e96c61-2636-4f0e-918e-9bb64276492a)]
 interface nsIDOMGetUserMediaErrorCallback : nsISupports
 {
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -803,17 +803,17 @@ PresentationService::SendSessionBinaryMs
   }
 
   return info->SendBinaryMsg(aData);
 }
 
 NS_IMETHODIMP
 PresentationService::SendSessionBlob(const nsAString& aSessionId,
                                      uint8_t aRole,
-                                     nsIDOMBlob* aBlob)
+                                     Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
   MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
              aRole == nsIPresentationService::ROLE_RECEIVER);
   MOZ_ASSERT(aBlob);
 
   RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -286,17 +286,17 @@ PresentationSessionInfo::SendBinaryMsg(c
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBinaryMsg(aData);
 }
 
 nsresult
-PresentationSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+PresentationSessionInfo::SendBlob(Blob* aBlob)
 {
   if (NS_WARN_IF(!IsSessionReady())) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -97,17 +97,17 @@ public:
       mControlChannel->SetListener(this);
     }
   }
 
   nsresult Send(const nsAString& aData);
 
   nsresult SendBinaryMsg(const nsACString& aData);
 
-  nsresult SendBlob(nsIDOMBlob* aBlob);
+  nsresult SendBlob(Blob* aBlob);
 
   nsresult Close(nsresult aReason,
                  uint32_t aState);
 
   nsresult OnTerminate(nsIPresentationControlChannel* aControlChannel);
 
   nsresult ReplyError(nsresult aReason);
 
--- a/dom/presentation/PresentationTCPSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -419,17 +419,17 @@ PresentationTCPSessionTransport::Send(co
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::SendBinaryMsg(const nsACString& aData)
 {
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 NS_IMETHODIMP
-PresentationTCPSessionTransport::SendBlob(nsIDOMBlob* aBlob)
+PresentationTCPSessionTransport::SendBlob(Blob* aBlob)
 {
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::Close(nsresult aReason)
 {
   PRES_DEBUG("%s:reason[%" PRIx32 "]\n", __func__, static_cast<uint32_t>(aReason));
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -1,22 +1,22 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMBlob;
 interface nsIInputStream;
 interface nsIPresentationAvailabilityListener;
 interface nsIPresentationRespondingListener;
 interface nsIPresentationSessionListener;
 interface nsIPresentationTransportBuilderConstructor;
 interface nsIPrincipal;
 
+webidl Blob;
 webidl EventTarget;
 
 %{C++
 #define PRESENTATION_SERVICE_CID \
   { 0x1d9bb10c, 0xc0ab, 0x4fe8, \
     { 0x9e, 0x4f, 0x40, 0x58, 0xb8, 0x51, 0x98, 0x32 } }
 #define PRESENTATION_SERVICE_CONTRACTID \
   "@mozilla.org/presentation/presentationservice;1"
@@ -115,17 +115,17 @@ interface nsIPresentationService : nsISu
    * Send the blob to the session.
    *
    * @param sessionId: An ID to identify presentation session.
    * @param role: Identify the function called by controller or receiver.
    * @param blob: The input blob to be sent.
    */
   void sendSessionBlob(in DOMString sessionId,
                        in uint8_t role,
-                       in nsIDOMBlob blob);
+                       in Blob blob);
 
   /*
    * Close the session.
    *
    * @param sessionId: An ID to identify presentation session.
    * @param role: Identify the function called by controller or receiver.
    */
   void closeSession(in DOMString sessionId,
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -1,18 +1,19 @@
 /* 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 "nsISupports.idl"
 
-interface nsIDOMBlob;
 interface nsIInputStream;
 interface nsINetAddr;
 
+webidl Blob;
+
 %{C++
 #define PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID \
   "@mozilla.org/presentation/presentationtcpsessiontransport;1"
 %}
 
 /*
  * The callback for session transport events.
  */
@@ -54,16 +55,16 @@ interface nsIPresentationSessionTranspor
    * @param data: the message being sent out.
    */
   void sendBinaryMsg(in ACString data);
 
   /*
    * Send the blob to the remote endpoint.
    * @param blob: The input blob to be sent.
    */
-  void sendBlob(in nsIDOMBlob blob);
+  void sendBlob(in Blob blob);
 
   /*
    * Close this session transport.
    * @param reason The reason for closing this session transport.
    */
   void close(in nsresult reason);
 };
--- a/dom/presentation/ipc/PresentationBuilderParent.cpp
+++ b/dom/presentation/ipc/PresentationBuilderParent.cpp
@@ -79,17 +79,17 @@ PresentationSessionTransportIPC::Send(co
 
 NS_IMETHODIMP
 PresentationSessionTransportIPC::SendBinaryMsg(const nsACString& aData)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PresentationSessionTransportIPC::SendBlob(nsIDOMBlob* aBlob)
+PresentationSessionTransportIPC::SendBlob(Blob* aBlob)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationSessionTransportIPC::Close(nsresult aReason)
 {
   if (NS_WARN_IF(!mParent->SendNotifyCloseSessionTransport(mSessionId,
--- a/dom/presentation/ipc/PresentationContentSessionInfo.cpp
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.cpp
@@ -41,17 +41,17 @@ PresentationContentSessionInfo::SendBina
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBinaryMsg(aData);
 }
 
 nsresult
-PresentationContentSessionInfo::SendBlob(nsIDOMBlob* aBlob)
+PresentationContentSessionInfo::SendBlob(Blob* aBlob)
 {
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->SendBlob(aBlob);
 }
 
--- a/dom/presentation/ipc/PresentationContentSessionInfo.h
+++ b/dom/presentation/ipc/PresentationContentSessionInfo.h
@@ -39,17 +39,17 @@ public:
   }
 
   nsresult Init();
 
   nsresult Send(const nsAString& aData);
 
   nsresult SendBinaryMsg(const nsACString& aData);
 
-  nsresult SendBlob(nsIDOMBlob* aBlob);
+  nsresult SendBlob(Blob* aBlob);
 
   nsresult Close(nsresult aReason);
 
 private:
   virtual ~PresentationContentSessionInfo() {}
 
   nsString mSessionId;
   uint8_t mRole;
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -124,17 +124,17 @@ PresentationIPCService::SendSessionBinar
   }
 
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
 PresentationIPCService::SendSessionBlob(const nsAString& aSessionId,
                                         uint8_t aRole,
-                                        nsIDOMBlob* aBlob)
+                                        Blob* aBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
   MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
              aRole == nsIPresentationService::ROLE_RECEIVER);
   MOZ_ASSERT(aBlob);
 
   RefPtr<PresentationContentSessionInfo> info =
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1040,17 +1040,17 @@ HTMLEditor::InsertObject(const nsACStrin
                                            aDoDeleteSelection);
     nsCOMPtr<nsIEditorUtils> utils =
       do_GetService("@mozilla.org/editor-utils;1");
     NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsINode> node = do_QueryInterface(aDestinationNode);
     MOZ_ASSERT(node);
 
-    nsCOMPtr<nsIDOMBlob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
+    RefPtr<Blob> domBlob = Blob::Create(node->GetOwnerGlobal(), blob);
     NS_ENSURE_TRUE(domBlob, NS_ERROR_FAILURE);
 
     return utils->SlurpBlob(domBlob, node->OwnerDoc()->GetWindow(), br);
   }
 
   nsAutoCString type(aType);
 
   // Check to see if we can insert an image file
--- a/editor/nsIEditorUtils.idl
+++ b/editor/nsIEditorUtils.idl
@@ -2,19 +2,20 @@
  *
  * 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 "nsISupports.idl"
 #include "domstubs.idl"
 
-interface nsIDOMBlob;
 interface mozIDOMWindowProxy;
 
+webidl Blob;
+
 [scriptable, builtinclass, uuid(eb8b8ad9-5d8f-43bd-8ce5-5b943c180d56)]
 interface nsIEditorBlobListener : nsISupports
 {
   void onResult(in ACString aResult);
   void onError(in AString aErrorName);
 };
 
 /**
@@ -22,11 +23,11 @@ interface nsIEditorBlobListener : nsISup
  * done in JavaScript.
  */
 [scriptable, uuid(4bf94928-575e-4bd1-8321-a2c4b3d0119e)]
 interface nsIEditorUtils : nsISupports
 {
   /**
    * Given a blob, returns the data from that blob, asynchronously.
    */
-  void slurpBlob(in nsIDOMBlob aBlob, in mozIDOMWindowProxy aScope,
+  void slurpBlob(in Blob aBlob, in mozIDOMWindowProxy aScope,
                  in nsIEditorBlobListener aListener);
 };
--- a/ipc/glue/BackgroundChild.h
+++ b/ipc/glue/BackgroundChild.h
@@ -6,18 +6,16 @@
 
 #ifndef mozilla_ipc_backgroundchild_h__
 #define mozilla_ipc_backgroundchild_h__
 
 #include "base/process.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/Transport.h"
 
-class nsIDOMBlob;
-
 namespace mozilla {
 namespace dom {
 
 class BlobImpl;
 class ContentChild;
 class ContentParent;
 
 } // namespace dom
--- a/js/xpconnect/tests/chrome/test_cloneInto.xul
+++ b/js/xpconnect/tests/chrome/test_cloneInto.xul
@@ -44,17 +44,17 @@
       return 'null';
 
     if (Array.isArray(a))
       return 'array';
 
     if (a instanceof File)
       return 'file';
 
-    if (a instanceof Ci.nsIDOMBlob)
+    if (a instanceof Blob)
       return 'blob';
 
     if (TypedArrayThings.includes(a.constructor.name))
       return a.constructor.name;
 
     if (typeof a == 'object')
       return 'object';
 
--- a/js/xpconnect/tests/unit/component-blob.js
+++ b/js/xpconnect/tests/unit/component-blob.js
@@ -22,17 +22,17 @@ BlobComponent.prototype =
 {
   doTest: function() {
     // throw if anything goes wrong
     let testContent = "<a id=\"a\"><b id=\"b\">hey!<\/b><\/a>";
     // should be able to construct a file
     var f1 = new Blob([testContent], {"type" : "text/xml"});
 
     // do some tests
-    Assert.ok(f1 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
+    Assert.ok(f1 instanceof Blob, "Should be a DOM Blob");
 
     Assert.ok(!(f1 instanceof File), "Should not be a DOM File");
 
     Assert.ok(f1.type == "text/xml", "Wrong type");
 
     Assert.ok(f1.size == testContent.length, "Wrong content size");
 
     var f2 = new Blob();
--- a/js/xpconnect/tests/unit/test_blob2.js
+++ b/js/xpconnect/tests/unit/test_blob2.js
@@ -6,17 +6,17 @@ Cu.importGlobalProperties(['Blob', 'File
 
 function run_test() {
   // throw if anything goes wrong
   let testContent = "<a id=\"a\"><b id=\"b\">hey!<\/b><\/a>";
   // should be able to construct a file
   var f1 = new Blob([testContent], {"type" : "text/xml"});
 
   // do some tests
-  Assert.ok(f1 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
+  Assert.ok(f1 instanceof Blob, "Should be a DOM Blob");
 
   Assert.ok(!(f1 instanceof File), "Should not be a DOM File");
 
   Assert.ok(f1.type == "text/xml", "Wrong type");
 
   Assert.ok(f1.size == testContent.length, "Wrong content size");
 
   var f2 = new Blob();
--- a/toolkit/modules/PropertyListUtils.jsm
+++ b/toolkit/modules/PropertyListUtils.jsm
@@ -64,17 +64,17 @@ ChromeUtils.defineModuleGetter(this, "ct
                                "resource://gre/modules/ctypes.jsm");
 ChromeUtils.defineModuleGetter(this, "Services",
                                "resource://gre/modules/Services.jsm");
 
 var PropertyListUtils = Object.freeze({
   /**
    * Asynchronously reads a file as a property list.
    *
-   * @param aFile (nsIDOMBlob/nsIFile)
+   * @param aFile (Blob/nsIFile)
    *        the file to be read as a property list.
    * @param aCallback
    *        If the property list is read successfully, aPropertyListRoot is set
    *        to the root object of the property list.
    *        Use getPropertyListObjectType to detect its type.
    *        If it's not read successfully, aPropertyListRoot is set to null.
    *        The reaon for failure is reported to the Error Console.
    */
--- a/widget/nsBaseFilePicker.cpp
+++ b/widget/nsBaseFilePicker.cpp
@@ -48,18 +48,17 @@ LocalFileToDirectoryOrBlob(nsPIDOMWindow
 
     RefPtr<Directory> directory = Directory::Create(aWindow, aFile);
     MOZ_ASSERT(directory);
 
     directory.forget(aResult);
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMBlob> blob = File::CreateFromFile(aWindow, aFile);
-  blob.forget(aResult);
+  *aResult = ToSupports(File::CreateFromFile(aWindow, aFile).take());
   return NS_OK;
 }
 
 } // anonymous namespace
 
 /**
  * A runnable to dispatch from the main thread to the main thread to display
  * the file picker while letting the showAsync method return right away.
--- a/widget/nsFilePickerProxy.cpp
+++ b/widget/nsFilePickerProxy.cpp
@@ -202,17 +202,17 @@ nsFilePickerProxy::GetDomFileOrDirectory
   *aValue = nullptr;
   if (mFilesOrDirectories.IsEmpty()) {
     return NS_OK;
   }
 
   MOZ_ASSERT(mFilesOrDirectories.Length() == 1);
 
   if (mFilesOrDirectories[0].IsFile()) {
-    nsCOMPtr<nsIDOMBlob> blob = mFilesOrDirectories[0].GetAsFile().get();
+    nsCOMPtr<nsISupports> blob = ToSupports(mFilesOrDirectories[0].GetAsFile());
     blob.forget(aValue);
     return NS_OK;
   }
 
   MOZ_ASSERT(mFilesOrDirectories[0].IsDirectory());
   RefPtr<Directory> directory = mFilesOrDirectories[0].GetAsDirectory();
   directory.forget(aValue);
   return NS_OK;
@@ -242,17 +242,17 @@ public:
   NS_IMETHOD
   GetNext(nsISupports** aValue) override
   {
     NS_ENSURE_TRUE(mIndex < mFilesOrDirectories.Length(), NS_ERROR_FAILURE);
 
     uint32_t index = mIndex++;
 
     if (mFilesOrDirectories[index].IsFile()) {
-      nsCOMPtr<nsIDOMBlob> blob = mFilesOrDirectories[index].GetAsFile().get();
+      nsCOMPtr<nsISupports> blob = ToSupports(mFilesOrDirectories[index].GetAsFile());
       blob.forget(aValue);
       return NS_OK;
     }
 
     MOZ_ASSERT(mFilesOrDirectories[index].IsDirectory());
     RefPtr<Directory> directory = mFilesOrDirectories[index].GetAsDirectory();
     directory.forget(aValue);
     return NS_OK;