Bug 1113062 - IndexedDB FileSnapshot not CCed. r=janv, a=sledru
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -124,25 +124,24 @@ nsresult DataOwnerAdapter::Create(DataOw
}
////////////////////////////////////////////////////////////////////////////
// mozilla::dom::File implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(File)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(File)
- MOZ_ASSERT(tmp->mImpl);
- tmp->mImpl->Unlink();
+ // No unlink for mImpl bacause FileImpl is not CC-able.
+ tmp->mImpl = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(File)
- MOZ_ASSERT(tmp->mImpl);
- tmp->mImpl->Traverse(cb);
+ // No traverse for mImpl bacause FileImpl is not CC-able.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(File)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -210,17 +210,17 @@ public:
private:
~File() {};
// The member is the real backend implementation of this File/Blob.
// It's thread-safe and not CC-able and it's the only element that is moved
// between threads.
// Note: we should not store any other state in this class!
- const nsRefPtr<FileImpl> mImpl;
+ nsRefPtr<FileImpl> mImpl;
nsCOMPtr<nsISupports> mParent;
};
// This is the abstract class for any File backend. It must be nsISupports
// because this class must be ref-counted and it has to work with IPC.
class FileImpl : public nsISupports
{
@@ -281,23 +281,20 @@ public:
virtual bool IsMemoryFile() const = 0;
virtual bool IsSizeUnknown() const = 0;
virtual bool IsDateUnknown() const = 0;
virtual bool IsFile() const = 0;
- // These 2 methods are used when the implementation has to CC something.
- virtual void Unlink() = 0;
- virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) = 0;
-
- virtual bool IsCCed() const
+ // True if this implementation can be sent to other threads.
+ virtual bool MayBeClonedToOtherThreads() const
{
- return false;
+ return true;
}
protected:
virtual ~FileImpl() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(FileImpl, FILEIMPL_IID)
@@ -455,19 +452,16 @@ public:
return false;
}
virtual bool IsSizeUnknown() const
{
return mLength == UINT64_MAX;
}
- virtual void Unlink() {}
- virtual void Traverse(nsCycleCollectionTraversalCallback &aCb) {}
-
protected:
virtual ~FileImplBase() {}
indexedDB::FileInfo* GetFileInfo() const
{
NS_ASSERTION(IsStoredFile(), "Should only be called on stored files!");
NS_ASSERTION(!mFileInfos.IsEmpty(), "Must have at least one file info!");
--- a/dom/base/MultipartFileImpl.cpp
+++ b/dom/base/MultipartFileImpl.cpp
@@ -347,8 +347,20 @@ MultipartFileImpl::InitializeChromeFile(
nsCOMPtr<nsIFile> file;
aRv = NS_NewLocalFile(aData, false, getter_AddRefs(file));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
InitializeChromeFile(aWindow, file, aBag, false, aRv);
}
+
+bool
+MultipartFileImpl::MayBeClonedToOtherThreads() const
+{
+ for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
+ if (!mBlobImpls[i]->MayBeClonedToOtherThreads()) {
+ return false;
+ }
+ }
+
+ return true;
+}
--- a/dom/base/MultipartFileImpl.h
+++ b/dom/base/MultipartFileImpl.h
@@ -106,16 +106,18 @@ public:
mName = aName;
}
void SetFromNsIFile(bool aValue)
{
mIsFromNsIFile = aValue;
}
+ virtual bool MayBeClonedToOtherThreads() const MOZ_OVERRIDE;
+
protected:
virtual ~MultipartFileImpl() {}
void SetLengthAndModifiedDate();
nsTArray<nsRefPtr<FileImpl>> mBlobImpls;
bool mIsFromNsIFile;
};
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -26,28 +26,30 @@ FileImplSnapshot::FileImplSnapshot(const
nsIFile* aFile,
IDBFileHandle* aFileHandle,
FileInfo* aFileInfo)
: FileImplBase(aName,
aContentType,
aMetadataParams->Size(),
aMetadataParams->LastModified())
, mFile(aFile)
- , mFileHandle(aFileHandle)
, mWholeFile(true)
{
AssertSanity();
MOZ_ASSERT(aMetadataParams);
MOZ_ASSERT(aMetadataParams->Size() != UINT64_MAX);
MOZ_ASSERT(aMetadataParams->LastModified() != INT64_MAX);
MOZ_ASSERT(aFile);
MOZ_ASSERT(aFileHandle);
MOZ_ASSERT(aFileInfo);
mFileInfos.AppendElement(aFileInfo);
+
+ mFileHandle =
+ do_GetWeakReference(NS_ISUPPORTS_CAST(EventTarget*, aFileHandle));
}
// Create slice
FileImplSnapshot::FileImplSnapshot(const FileImplSnapshot* aOther,
uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType)
: FileImplBase(aContentType, aOther->mStart + aStart, aLength)
@@ -83,49 +85,29 @@ FileImplSnapshot::AssertSanity()
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
}
#endif // DEBUG
NS_IMPL_ISUPPORTS_INHERITED(FileImplSnapshot, FileImpl, PIFileImplSnapshot)
-void
-FileImplSnapshot::Unlink()
-{
- AssertSanity();
-
- FileImplSnapshot* tmp = this;
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileHandle);
-}
-
-void
-FileImplSnapshot::Traverse(nsCycleCollectionTraversalCallback &cb)
-{
- AssertSanity();
-
- FileImplSnapshot* tmp = this;
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileHandle);
-}
-
-bool
-FileImplSnapshot::IsCCed() const
-{
- AssertSanity();
-
- return true;
-}
-
nsresult
FileImplSnapshot::GetInternalStream(nsIInputStream** aStream)
{
AssertSanity();
- nsresult rv = mFileHandle->OpenInputStream(mWholeFile, mStart, mLength,
- aStream);
+ nsCOMPtr<EventTarget> et = do_QueryReferent(mFileHandle);
+ nsRefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
+ if (!fileHandle) {
+ return NS_ERROR_DOM_FILEHANDLE_INACTIVE_ERR;
+ }
+
+ nsresult rv = fileHandle->OpenInputStream(mWholeFile, mStart, mLength,
+ aStream);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
already_AddRefed<FileImpl>
--- a/dom/indexedDB/FileSnapshot.h
+++ b/dom/indexedDB/FileSnapshot.h
@@ -7,16 +7,17 @@
#ifndef mozilla_dom_indexeddb_filesnapshot_h__
#define mozilla_dom_indexeddb_filesnapshot_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/File.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
+#include "nsWeakPtr.h"
#define FILEIMPLSNAPSHOT_IID \
{0x0dfc11b1, 0x75d3, 0x473b, {0x8c, 0x67, 0xb7, 0x23, 0xf4, 0x67, 0xd6, 0x73}}
class PIFileImplSnapshot : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(FILEIMPLSNAPSHOT_IID)
@@ -35,17 +36,17 @@ class IDBFileHandle;
class FileImplSnapshot MOZ_FINAL
: public FileImplBase
, public PIFileImplSnapshot
{
typedef mozilla::dom::MetadataParameters MetadataParameters;
nsCOMPtr<nsIFile> mFile;
- nsRefPtr<IDBFileHandle> mFileHandle;
+ nsWeakPtr mFileHandle;
bool mWholeFile;
public:
// Create as a stored file
FileImplSnapshot(const nsAString& aName,
const nsAString& aContentType,
MetadataParameters* aMetadataParams,
@@ -73,24 +74,20 @@ private:
#endif
virtual void
GetMozFullPathInternal(nsAString& aFullPath, ErrorResult& aRv) MOZ_OVERRIDE;
virtual nsresult
GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
- virtual void
- Unlink() MOZ_OVERRIDE;
-
- virtual void
- Traverse(nsCycleCollectionTraversalCallback &aCb) MOZ_OVERRIDE;
-
- virtual bool
- IsCCed() const MOZ_OVERRIDE;
+ virtual bool MayBeClonedToOtherThreads() const MOZ_OVERRIDE
+ {
+ return false;
+ }
virtual already_AddRefed<FileImpl>
CreateSlice(uint64_t aStart,
uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv) MOZ_OVERRIDE;
virtual bool
--- a/dom/indexedDB/IDBFileHandle.cpp
+++ b/dom/indexedDB/IDBFileHandle.cpp
@@ -82,16 +82,17 @@ IDBFileHandle::MutableFile() const
return mMutableFile;
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(IDBFileHandle, DOMEventTargetHelper,
mMutableFile)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBFileHandle)
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
+ NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IDBFileHandle, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBFileHandle, DOMEventTargetHelper)
nsresult
IDBFileHandle::PreHandleEvent(EventChainPreVisitor& aVisitor)
{
--- a/dom/indexedDB/IDBFileHandle.h
+++ b/dom/indexedDB/IDBFileHandle.h
@@ -10,31 +10,33 @@
#include "IDBFileRequest.h"
#include "js/TypeDecls.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/FileHandle.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "nsCycleCollectionParticipant.h"
+#include "nsWeakReference.h"
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
struct IDBFileMetadataParameters;
namespace indexedDB {
class IDBMutableFile;
class IDBFileHandle MOZ_FINAL : public DOMEventTargetHelper,
public nsIRunnable,
- public FileHandleBase
+ public FileHandleBase,
+ public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBFileHandle, DOMEventTargetHelper)
static already_AddRefed<IDBFileHandle>
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -1821,21 +1821,18 @@ public:
IsSizeUnknown() const MOZ_OVERRIDE;
virtual bool
IsDateUnknown() const MOZ_OVERRIDE;
virtual bool
IsFile() const MOZ_OVERRIDE;
- virtual void
- Unlink() MOZ_OVERRIDE;
-
- virtual void
- Traverse(nsCycleCollectionTraversalCallback& aCallback) MOZ_OVERRIDE;
+ virtual bool
+ MayBeClonedToOtherThreads() const MOZ_OVERRIDE;
virtual BlobChild*
GetBlobChild() MOZ_OVERRIDE;
virtual BlobParent*
GetBlobParent() MOZ_OVERRIDE;
private:
@@ -2527,28 +2524,21 @@ RemoteBlobImpl::IsDateUnknown() const
bool
BlobParent::
RemoteBlobImpl::IsFile() const
{
return mBlobImpl->IsFile();
}
-void
+bool
BlobParent::
-RemoteBlobImpl::Unlink()
+RemoteBlobImpl::MayBeClonedToOtherThreads() const
{
- return mBlobImpl->Unlink();
-}
-
-void
-BlobParent::
-RemoteBlobImpl::Traverse(nsCycleCollectionTraversalCallback& aCallback)
-{
- return mBlobImpl->Traverse(aCallback);
+ return mBlobImpl->MayBeClonedToOtherThreads();
}
BlobChild*
BlobParent::
RemoteBlobImpl::GetBlobChild()
{
return nullptr;
}
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -451,18 +451,18 @@ struct MainThreadWorkerStructuredCloneCa
nsTArray<nsCOMPtr<nsISupports> >* clonedObjects =
static_cast<nsTArray<nsCOMPtr<nsISupports> >*>(aClosure);
// See if this is a Blob/File object.
{
File* blob = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob))) {
FileImpl* blobImpl = blob->Impl();
- if (blobImpl->IsCCed()) {
- NS_WARNING("Cycle collected blob objects are not supported!");
+ if (!blobImpl->MayBeClonedToOtherThreads()) {
+ NS_WARNING("Not all the blob implementations can be sent between threads.");
} else if (NS_SUCCEEDED(blobImpl->SetMutable(false)) &&
JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0) &&
JS_WriteBytes(aWriter, &blobImpl, sizeof(blobImpl))) {
clonedObjects->AppendElement(blobImpl);
return true;
}
}
}