Merge inbound to mozilla-central. a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Sun, 16 Dec 2018 11:50:49 +0200
changeset 450865 5ca841fa4f30d1662c383967738b5d3fd058732c
parent 450864 4a013c72263f816976725b4b0423ae794c0b2838 (current diff)
parent 450855 fca2da2300420bb5a1108ae9fa2c8b4f2b990a40 (diff)
child 450866 cc14c9ba3a7e45a1624f64128c7baba46d822002
child 450868 36a2f27ecc477b912861228f537ce26223126343
child 450876 ac5584934955f5c018b6e45784fc53d523735a72
push id110553
push userncsoregi@mozilla.com
push dateSun, 16 Dec 2018 10:05:05 +0000
treeherdermozilla-inbound@cc14c9ba3a7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
5ca841fa4f30 / 66.0a1 / 20181216095236 / files
nightly linux64
5ca841fa4f30 / 66.0a1 / 20181216095236 / files
nightly mac
5ca841fa4f30 / 66.0a1 / 20181216095236 / files
nightly win32
5ca841fa4f30 / 66.0a1 / 20181216095236 / files
nightly win64
5ca841fa4f30 / 66.0a1 / 20181216095236 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/dom/file/BaseBlobImpl.h
+++ b/dom/file/BaseBlobImpl.h
@@ -9,58 +9,65 @@
 
 #include "mozilla/dom/BlobImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 class BaseBlobImpl : public BlobImpl {
  public:
-  BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength, int64_t aLastModifiedDate)
-      : mIsFile(true),
+  BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aName,
+               const nsAString& aContentType, uint64_t aLength,
+               int64_t aLastModifiedDate)
+      : mBlobImplType(aBlobImplType),
+        mIsFile(true),
         mImmutable(false),
         mContentType(aContentType),
         mName(aName),
         mStart(0),
         mLength(aLength),
         mLastModificationDate(aLastModifiedDate),
         mSerialNumber(NextSerialNumber()) {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
-               uint64_t aLength)
-      : mIsFile(true),
+  BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aName,
+               const nsAString& aContentType, uint64_t aLength)
+      : mBlobImplType(aBlobImplType),
+        mIsFile(true),
         mImmutable(false),
         mContentType(aContentType),
         mName(aName),
         mStart(0),
         mLength(aLength),
         mLastModificationDate(INT64_MAX),
         mSerialNumber(NextSerialNumber()) {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BaseBlobImpl(const nsAString& aContentType, uint64_t aLength)
-      : mIsFile(false),
+  BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aContentType,
+               uint64_t aLength)
+      : mBlobImplType(aBlobImplType),
+        mIsFile(false),
         mImmutable(false),
         mContentType(aContentType),
         mStart(0),
         mLength(aLength),
         mLastModificationDate(INT64_MAX),
         mSerialNumber(NextSerialNumber()) {
     // Ensure non-null mContentType by default
     mContentType.SetIsVoid(false);
   }
 
-  BaseBlobImpl(const nsAString& aContentType, uint64_t aStart, uint64_t aLength)
-      : mIsFile(false),
+  BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aContentType,
+               uint64_t aStart, uint64_t aLength)
+      : mBlobImplType(aBlobImplType),
+        mIsFile(false),
         mImmutable(false),
         mContentType(aContentType),
         mStart(aStart),
         mLength(aLength),
         mLastModificationDate(INT64_MAX),
         mSerialNumber(NextSerialNumber()) {
     MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
     // Ensure non-null mContentType by default
@@ -138,26 +145,32 @@ class BaseBlobImpl : public BlobImpl {
   virtual bool IsDateUnknown() const override {
     return mIsFile && mLastModificationDate == INT64_MAX;
   }
 
   virtual bool IsFile() const override { return mIsFile; }
 
   virtual bool IsSizeUnknown() const override { return mLength == UINT64_MAX; }
 
+  virtual void GetBlobImplType(nsAString& aBlobImplType) const override {
+    aBlobImplType = mBlobImplType;
+  }
+
  protected:
   virtual ~BaseBlobImpl() {}
 
   /**
    * Returns a new, effectively-unique serial number. This should be used
    * by implementations to obtain a serial number for GetSerialNumber().
    * The implementation is thread safe.
    */
   static uint64_t NextSerialNumber();
 
+  const nsString mBlobImplType;
+
   bool mIsFile;
   bool mImmutable;
 
   nsString mContentType;
   nsString mName;
   nsString mPath;  // The path relative to a directory chosen by the user
 
   uint64_t mStart;
--- a/dom/file/Blob.cpp
+++ b/dom/file/Blob.cpp
@@ -142,16 +142,20 @@ already_AddRefed<Blob> Blob::CreateSlice
   RefPtr<Blob> blob = Blob::Create(mParent, impl);
   return blob.forget();
 }
 
 uint64_t Blob::GetSize(ErrorResult& aRv) { return mImpl->GetSize(aRv); }
 
 void Blob::GetType(nsAString& aType) { mImpl->GetType(aType); }
 
+void Blob::GetBlobImplType(nsAString& aBlobImplType) {
+  mImpl->GetBlobImplType(aBlobImplType);
+}
+
 already_AddRefed<Blob> Blob::Slice(const Optional<int64_t>& aStart,
                                    const Optional<int64_t>& aEnd,
                                    const Optional<nsAString>& aContentType,
                                    ErrorResult& aRv) {
   nsAutoString contentType;
   if (aContentType.WasPassed()) {
     contentType = aContentType.Value();
   }
--- a/dom/file/Blob.h
+++ b/dom/file/Blob.h
@@ -103,16 +103,18 @@ class Blob : public nsIMutable,
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   uint64_t GetSize(ErrorResult& aRv);
 
   void GetType(nsAString& aType);
 
+  void GetBlobImplType(nsAString& aBlobImplType);
+
   already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
                                const Optional<int64_t>& aEnd,
                                const Optional<nsAString>& aContentType,
                                ErrorResult& aRv);
 
   size_t GetAllocationSize() const;
 
   nsresult GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
--- a/dom/file/BlobImpl.h
+++ b/dom/file/BlobImpl.h
@@ -49,16 +49,18 @@ class BlobImpl : public nsISupports {
 
   virtual void GetMozFullPathInternal(nsAString& aFileName,
                                       ErrorResult& aRv) const = 0;
 
   virtual uint64_t GetSize(ErrorResult& aRv) = 0;
 
   virtual void GetType(nsAString& aType) = 0;
 
+  virtual void GetBlobImplType(nsAString& aBlobImplType) const = 0;
+
   virtual size_t GetAllocationSize() const = 0;
   virtual size_t GetAllocationSize(
       FallibleTArray<BlobImpl*>& aVisitedBlobImpls) const = 0;
 
   /**
    * An effectively-unique serial number identifying this instance of FileImpl.
    *
    * Implementations should obtain a serial number from
--- a/dom/file/EmptyBlobImpl.h
+++ b/dom/file/EmptyBlobImpl.h
@@ -12,23 +12,25 @@
 namespace mozilla {
 namespace dom {
 
 class EmptyBlobImpl final : public BaseBlobImpl {
  public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(EmptyBlobImpl, BaseBlobImpl)
 
   explicit EmptyBlobImpl(const nsAString& aContentType)
-      : BaseBlobImpl(aContentType, 0 /* aLength */) {
+      : BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aContentType,
+                     0 /* aLength */) {
     mImmutable = true;
   }
 
   EmptyBlobImpl(const nsAString& aName, const nsAString& aContentType,
                 int64_t aLastModifiedDate)
-      : BaseBlobImpl(aName, aContentType, 0, aLastModifiedDate) {
+      : BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aName, aContentType, 0,
+                     aLastModifiedDate) {
     mImmutable = true;
   }
 
   virtual void CreateInputStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override;
 
   virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
                                                  uint64_t aLength,
--- a/dom/file/File.cpp
+++ b/dom/file/File.cpp
@@ -32,18 +32,18 @@ File::~File() {}
 }
 
 /* static */ already_AddRefed<File> File::Create(nsISupports* aParent,
                                                  const nsAString& aName,
                                                  const nsAString& aContentType,
                                                  uint64_t aLength,
                                                  int64_t aLastModifiedDate) {
   RefPtr<File> file = new File(
-      aParent,
-      new BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate));
+      aParent, new BaseBlobImpl(NS_LITERAL_STRING("BaseBlobImpl"), aName,
+                                aContentType, aLength, aLastModifiedDate));
   return file.forget();
 }
 
 /* static */ already_AddRefed<File> File::CreateMemoryFile(
     nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
     const nsAString& aName, const nsAString& aContentType,
     int64_t aLastModifiedDate) {
   RefPtr<File> file =
--- a/dom/file/FileBlobImpl.cpp
+++ b/dom/file/FileBlobImpl.cpp
@@ -14,66 +14,71 @@
 #include "nsIMIMEService.h"
 #include "nsNetUtil.h"
 #include "nsStreamUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 FileBlobImpl::FileBlobImpl(nsIFile* aFile)
-    : BaseBlobImpl(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX),
+    : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(),
+                   EmptyString(), UINT64_MAX, INT64_MAX),
       mFile(aFile),
       mWholeFile(true),
       mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   // Lazily get the content type and size
   mContentType.SetIsVoid(true);
   mFile->GetLeafName(mName);
 }
 
 FileBlobImpl::FileBlobImpl(const nsAString& aName,
                            const nsAString& aContentType, uint64_t aLength,
                            nsIFile* aFile)
-    : BaseBlobImpl(aName, aContentType, aLength, UINT64_MAX),
+    : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
+                   aLength, UINT64_MAX),
       mFile(aFile),
       mWholeFile(true),
       mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
 }
 
 FileBlobImpl::FileBlobImpl(const nsAString& aName,
                            const nsAString& aContentType, uint64_t aLength,
                            nsIFile* aFile, int64_t aLastModificationDate)
-    : BaseBlobImpl(aName, aContentType, aLength, aLastModificationDate),
+    : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
+                   aLength, aLastModificationDate),
       mFile(aFile),
       mWholeFile(true),
       mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
 }
 
 FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
                            const nsAString& aContentType)
-    : BaseBlobImpl(aName, aContentType, UINT64_MAX, INT64_MAX),
+    : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
+                   UINT64_MAX, INT64_MAX),
       mFile(aFile),
       mWholeFile(true),
       mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   if (aContentType.IsEmpty()) {
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
   }
 }
 
 FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
                            uint64_t aLength, const nsAString& aContentType)
-    : BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength),
+    : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType,
+                   aOther->mStart + aStart, aLength),
       mFile(aOther->mFile),
       mWholeFile(false),
       mFileId(-1) {
   MOZ_ASSERT(mFile, "must have file");
   MOZ_ASSERT(XRE_IsParentProcess());
   mImmutable = aOther->mImmutable;
 }
 
--- a/dom/file/MemoryBlobImpl.h
+++ b/dom/file/MemoryBlobImpl.h
@@ -21,24 +21,26 @@ namespace mozilla {
 namespace dom {
 
 class MemoryBlobImpl final : public BaseBlobImpl {
  public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(MemoryBlobImpl, BaseBlobImpl)
 
   MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
                  const nsAString& aContentType, int64_t aLastModifiedDate)
-      : BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate),
+      : BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aName, aContentType,
+                     aLength, aLastModifiedDate),
         mDataOwner(new DataOwner(aMemoryBuffer, aLength)) {
     MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength,
                  const nsAString& aContentType)
-      : BaseBlobImpl(aContentType, aLength),
+      : BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aContentType,
+                     aLength),
         mDataOwner(new DataOwner(aMemoryBuffer, aLength)) {
     MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
   }
 
   virtual void CreateInputStream(nsIInputStream** aStream,
                                  ErrorResult& aRv) override;
 
   virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
@@ -137,17 +139,18 @@ class MemoryBlobImpl final : public Base
     nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
     nsCOMPtr<nsICloneableInputStream> mCloneableInputStream;
   };
 
  private:
   // Create slice
   MemoryBlobImpl(const MemoryBlobImpl* aOther, uint64_t aStart,
                  uint64_t aLength, const nsAString& aContentType)
-      : BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength),
+      : BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aContentType,
+                     aOther->mStart + aStart, aLength),
         mDataOwner(aOther->mDataOwner) {
     MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
     mImmutable = aOther->mImmutable;
   }
 
   ~MemoryBlobImpl() {}
 
   // Used when backed by a memory store
--- a/dom/file/MultipartBlobImpl.cpp
+++ b/dom/file/MultipartBlobImpl.cpp
@@ -425,8 +425,25 @@ size_t MultipartBlobImpl::GetAllocationS
         return 0;
       }
       total += blobImpl->GetAllocationSize(aVisitedBlobs);
     }
   }
 
   return total;
 }
+
+void MultipartBlobImpl::GetBlobImplType(nsAString& aBlobImplType) const {
+  aBlobImplType.AssignLiteral("MultipartBlobImpl[");
+
+  for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
+    if (i != 0) {
+      aBlobImplType.AppendLiteral(", ");
+    }
+
+    nsAutoString blobImplType;
+    mBlobImpls[i]->GetBlobImplType(blobImplType);
+
+    aBlobImplType.Append(blobImplType);
+  }
+
+  aBlobImplType.AppendLiteral("]");
+}
--- a/dom/file/MultipartBlobImpl.h
+++ b/dom/file/MultipartBlobImpl.h
@@ -26,21 +26,25 @@ class MultipartBlobImpl final : public B
 
   // Create as a blob
   static already_AddRefed<MultipartBlobImpl> Create(
       nsTArray<RefPtr<BlobImpl>>&& aBlobImpls, const nsAString& aContentType,
       ErrorResult& aRv);
 
   // Create as a file to be later initialized
   explicit MultipartBlobImpl(const nsAString& aName)
-      : BaseBlobImpl(aName, EmptyString(), UINT64_MAX), mIsFromNsIFile(false) {}
+      : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
+                     EmptyString(), UINT64_MAX),
+        mIsFromNsIFile(false) {}
 
   // Create as a blob to be later initialized
   MultipartBlobImpl()
-      : BaseBlobImpl(EmptyString(), UINT64_MAX), mIsFromNsIFile(false) {}
+      : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), EmptyString(),
+                     UINT64_MAX),
+        mIsFromNsIFile(false) {}
 
   void InitializeBlob(ErrorResult& aRv);
 
   void InitializeBlob(const Sequence<Blob::BlobPart>& aData,
                       const nsAString& aContentType, bool aNativeEOL,
                       ErrorResult& aRv);
 
   nsresult InitializeChromeFile(nsIFile* aData, const nsAString& aType,
@@ -70,26 +74,30 @@ class MultipartBlobImpl final : public B
   void SetName(const nsAString& aName) { mName = aName; }
 
   virtual bool MayBeClonedToOtherThreads() const override;
 
   size_t GetAllocationSize() const override;
   size_t GetAllocationSize(
       FallibleTArray<BlobImpl*>& aVisitedBlobImpls) const override;
 
+  void GetBlobImplType(nsAString& aBlobImplType) const override;
+
  protected:
   MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
                     const nsAString& aName, const nsAString& aContentType)
-      : BaseBlobImpl(aName, aContentType, UINT64_MAX),
+      : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
+                     aContentType, UINT64_MAX),
         mBlobImpls(std::move(aBlobImpls)),
         mIsFromNsIFile(false) {}
 
   MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
                     const nsAString& aContentType)
-      : BaseBlobImpl(aContentType, UINT64_MAX),
+      : BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aContentType,
+                     UINT64_MAX),
         mBlobImpls(std::move(aBlobImpls)),
         mIsFromNsIFile(false) {}
 
   virtual ~MultipartBlobImpl() {}
 
   void SetLengthAndModifiedDate(ErrorResult& aRv);
 
   nsTArray<RefPtr<BlobImpl>> mBlobImpls;
--- a/dom/file/StreamBlobImpl.cpp
+++ b/dom/file/StreamBlobImpl.cpp
@@ -37,28 +37,29 @@ NS_IMPL_ISUPPORTS_INHERITED(StreamBlobIm
   RefPtr<StreamBlobImpl> blobImplStream = new StreamBlobImpl(
       inputStream.forget(), aName, aContentType, aLastModifiedDate, aLength);
   blobImplStream->MaybeRegisterMemoryReporter();
   return blobImplStream.forget();
 }
 
 StreamBlobImpl::StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
                                const nsAString& aContentType, uint64_t aLength)
-    : BaseBlobImpl(aContentType, aLength),
+    : BaseBlobImpl(NS_LITERAL_STRING("StreamBlobImpl"), aContentType, aLength),
       mInputStream(std::move(aInputStream)),
       mIsDirectory(false),
       mFileId(-1) {
   mImmutable = true;
 }
 
 StreamBlobImpl::StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
                                const nsAString& aName,
                                const nsAString& aContentType,
                                int64_t aLastModifiedDate, uint64_t aLength)
-    : BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate),
+    : BaseBlobImpl(NS_LITERAL_STRING("StreamBlobImpl"), aName, aContentType,
+                   aLength, aLastModifiedDate),
       mInputStream(std::move(aInputStream)),
       mIsDirectory(false),
       mFileId(-1) {
   mImmutable = true;
 }
 
 StreamBlobImpl::~StreamBlobImpl() { UnregisterWeakMemoryReporter(this); }
 
--- a/dom/file/StringBlobImpl.cpp
+++ b/dom/file/StringBlobImpl.cpp
@@ -16,17 +16,19 @@ NS_IMPL_ISUPPORTS_INHERITED(StringBlobIm
     const nsACString& aData, const nsAString& aContentType) {
   RefPtr<StringBlobImpl> blobImpl = new StringBlobImpl(aData, aContentType);
   RegisterWeakMemoryReporter(blobImpl);
   return blobImpl.forget();
 }
 
 StringBlobImpl::StringBlobImpl(const nsACString& aData,
                                const nsAString& aContentType)
-    : BaseBlobImpl(aContentType, aData.Length()), mData(aData) {}
+    : BaseBlobImpl(NS_LITERAL_STRING("StringBlobImpl"), aContentType,
+                   aData.Length()),
+      mData(aData) {}
 
 StringBlobImpl::~StringBlobImpl() { UnregisterWeakMemoryReporter(this); }
 
 already_AddRefed<BlobImpl> StringBlobImpl::CreateSlice(
     uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
     ErrorResult& aRv) {
   RefPtr<BlobImpl> impl =
       new StringBlobImpl(Substring(mData, aStart, aLength), aContentType);
--- a/dom/file/TemporaryFileBlobImpl.cpp
+++ b/dom/file/TemporaryFileBlobImpl.cpp
@@ -89,16 +89,19 @@ TemporaryFileBlobImpl::TemporaryFileBlob
                                              const nsAString& aContentType)
     : FileBlobImpl(aFile, EmptyString(), aContentType)
 #ifdef DEBUG
       ,
       mInputStreamCreated(false)
 #endif
 {
   MOZ_ASSERT(XRE_IsParentProcess());
+
+  // This must be considered a blob.
+  mIsFile = false;
 }
 
 TemporaryFileBlobImpl::~TemporaryFileBlobImpl() {
   MOZ_ASSERT(mInputStreamCreated);
 }
 
 already_AddRefed<BlobImpl> TemporaryFileBlobImpl::CreateSlice(
     uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -197,16 +197,26 @@ BlobImpl* BlobImplSnapshot::GetBlobImpl(
   RefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
   if (!fileHandle || !fileHandle->IsOpen()) {
     return nullptr;
   }
 
   return mBlobImpl;
 }
 
+void BlobImplSnapshot::GetBlobImplType(nsAString& aBlobImplType) const {
+  aBlobImplType.AssignLiteral("BlobImplSnapshot[");
+
+  nsAutoString blobImplType;
+  mBlobImpl->GetBlobImplType(blobImplType);
+  aBlobImplType.Append(blobImplType);
+
+  aBlobImplType.AppendLiteral("]");
+}
+
 StreamWrapper::~StreamWrapper() {
   AssertIsOnOwningThread();
 
   Finish();
 }
 
 NS_IMPL_ADDREF(StreamWrapper)
 NS_IMPL_RELEASE_WITH_DESTROY(StreamWrapper, Destroy())
--- a/dom/indexedDB/FileSnapshot.h
+++ b/dom/indexedDB/FileSnapshot.h
@@ -82,16 +82,18 @@ class BlobImplSnapshot final : public Bl
   }
 
   virtual uint64_t GetSize(ErrorResult& aRv) override {
     return mBlobImpl->GetSize(aRv);
   }
 
   virtual void GetType(nsAString& aType) override { mBlobImpl->GetType(aType); }
 
+  virtual void GetBlobImplType(nsAString& aBlobImplType) const override;
+
   size_t GetAllocationSize() const override {
     return mBlobImpl->GetAllocationSize();
   }
 
   size_t GetAllocationSize(
       FallibleTArray<BlobImpl*>& aVisitedBlobs) const override {
     return mBlobImpl->GetAllocationSize(aVisitedBlobs);
   }
--- a/dom/webidl/Blob.webidl
+++ b/dom/webidl/Blob.webidl
@@ -31,8 +31,15 @@ interface Blob {
 };
 
 enum EndingTypes { "transparent", "native" };
 
 dictionary BlobPropertyBag {
   DOMString type = "";
   EndingTypes endings = "transparent";
 };
+
+partial interface Blob {
+  // This returns the type of BlobImpl used for this Blob.
+  [ChromeOnly]
+  readonly attribute DOMString blobImplType;
+};
+
--- a/dom/xhr/tests/browser.ini
+++ b/dom/xhr/tests/browser.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 support-files =
   browser_xhr_onchange_leak.html
 [browser_blobFromFile.js]
-[browser_xhr_onchange_leak.js]
\ No newline at end of file
+[browser_xhr_onchange_leak.js]
+[browser_temporaryFile.js]
+support-files =  temporaryFileBlob.sjs
new file mode 100644
--- /dev/null
+++ b/dom/xhr/tests/browser_temporaryFile.js
@@ -0,0 +1,45 @@
+add_task(async _ => {
+  await new Promise(resolve => {
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs");
+    xhr.responseType = 'blob';
+    xhr.send("");
+    xhr.onloadend = _ => {
+      is(xhr.response.blobImplType, "EmptyBlobImpl", "We want a EmptyBlobImpl");
+      resolve();
+    }
+  });
+});
+
+add_task(async _ => {
+  var data = new Array(2).join("1234567890ABCDEF");
+
+  await new Promise(resolve => {
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs");
+    xhr.responseType = 'blob';
+    xhr.send({toString: function() { return data; }});
+    xhr.onloadend = _ => {
+      is(xhr.response.blobImplType, "MemoryBlobImpl", "We want a MemoryBlobImpl");
+      resolve();
+    }
+  });
+});
+
+add_task(async _ => {
+  // TemporaryBlobImpl is not exposed. It's sent via PBackground and received as StreamBlobImpl.
+  await SpecialPowers.pushPrefEnv({ "set" : [[ "dom.blob.memoryToTemporaryFile", 1 ]] });
+
+  var data = new Array(2).join("1234567890ABCDEF");
+
+  await new Promise(resolve => {
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://mochi.test:8888/browser/dom/xhr/tests/temporaryFileBlob.sjs");
+    xhr.responseType = 'blob';
+    xhr.send({toString: function() { return data; }});
+    xhr.onloadend = _ => {
+      is(xhr.response.blobImplType, "StreamBlobImpl", "We want a StreamBlobImpl");
+      resolve();
+    }
+  });
+});
--- a/dom/xhr/tests/common_temporaryFileBlob.js
+++ b/dom/xhr/tests/common_temporaryFileBlob.js
@@ -10,16 +10,20 @@ function createXHR() {
 
 function test_simple() {
   info("Simple test");
 
   var xhr = createXHR();
 
   xhr.onloadend = function() {
     ok(xhr.response instanceof Blob, "We have a blob!");
+    ok(!(xhr.response instanceof File), "Our blob is not a file!");
+    if ("SpecialPowers" in self) {
+      is(SpecialPowers.wrap(xhr.response).blobImplType, "StreamBlobImpl", "We have a blob stored into a stream file");
+    }
     is(xhr.response.size, data.length, "Data length matches");
 
     var fr = new FileReader();
     fr.readAsText(xhr.response);
     fr.onload = function() {
       is(fr.result, data, "Data content matches");
       next();
     }
@@ -44,16 +48,20 @@ function test_abort() {
 function test_reuse() {
   info("Reuse test");
 
   var xhr = createXHR();
 
   var count = 0;
   xhr.onloadend = function() {
     ok(xhr.response instanceof Blob, "We have a blob!");
+    ok(!(xhr.response instanceof File), "Our blob is not a file!");
+    if ("SpecialPowers" in self) {
+      is(SpecialPowers.wrap(xhr.response).blobImplType, "StreamBlobImpl", "We have a blob stored into a stream file");
+    }
     is(xhr.response.size, data.length, "Data length matches");
 
     var fr = new FileReader();
     fr.readAsText(xhr.response);
     fr.onload = function() {
       is(fr.result, data, "Data content matches");
       if (++count > 2) {
         next();
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -291,25 +291,29 @@ static bool FunctionForwarder(JSContext*
     thisVal.setObject(*thisObject);
   }
 
   {
     // We manually implement the contents of CrossCompartmentWrapper::call
     // here, because certain function wrappers (notably content->nsEP) are
     // not callable.
     JSAutoRealm ar(cx, unwrappedFun);
-    if (!CheckSameOriginArg(cx, options, thisVal) ||
-        !JS_WrapValue(cx, &thisVal)) {
-      return false;
-    }
+    bool crossCompartment = js::GetObjectCompartment(unwrappedFun) !=
+                            js::GetObjectCompartment(&args.callee());
+    if (crossCompartment) {
+      if (!CheckSameOriginArg(cx, options, thisVal) ||
+          !JS_WrapValue(cx, &thisVal)) {
+        return false;
+      }
 
-    for (size_t n = 0; n < args.length(); ++n) {
-      if (!CheckSameOriginArg(cx, options, args[n]) ||
-          !JS_WrapValue(cx, args[n])) {
-        return false;
+      for (size_t n = 0; n < args.length(); ++n) {
+        if (!CheckSameOriginArg(cx, options, args[n]) ||
+            !JS_WrapValue(cx, args[n])) {
+          return false;
+        }
       }
     }
 
     RootedValue fval(cx, ObjectValue(*unwrappedFun));
     if (args.isConstructing()) {
       RootedObject obj(cx);
       if (!JS::Construct(cx, fval, args, &obj)) {
         return false;