Bug 1177688, part 1 - Add API and functionality to the BlobImpl classes so that BlobImpl's that are created from an nsIFile can provide information about whether or not the nsIFile was a directory. r=baku

This commit is contained in:
Jonathan Watt 2015-06-23 00:31:28 +01:00
Родитель 1e25aaced0
Коммит 2cd9883d4c
7 изменённых файлов: 198 добавлений и 38 удалений

Просмотреть файл

@ -229,6 +229,12 @@ Blob::IsFile() const
return mImpl->IsFile();
}
bool
Blob::IsDirectory() const
{
return mImpl->IsDirectory();
}
const nsTArray<nsRefPtr<BlobImpl>>*
Blob::GetSubBlobImpls() const
{
@ -421,10 +427,11 @@ File::Create(nsISupports* aParent, BlobImpl* aImpl)
/* static */ already_AddRefed<File>
File::Create(nsISupports* aParent, const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate)
int64_t aLastModifiedDate, BlobDirState aDirState)
{
nsRefPtr<File> file = new File(aParent,
new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
aDirState));
return file.forget();
}
@ -1056,6 +1063,17 @@ BlobImplFile::SetPath(const nsAString& aPath)
mPath = aPath;
}
void
BlobImplFile::LookupAndCacheIsDirectory()
{
MOZ_ASSERT(mIsFile,
"This should only be called when this object has been created "
"from an nsIFile to note that the nsIFile is a directory");
bool isDir;
mFile->IsDirectory(&isDir);
mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
}
////////////////////////////////////////////////////////////////////////////
// BlobImplMemory implementation

Просмотреть файл

@ -51,6 +51,18 @@ class BlobImpl;
class File;
class OwningArrayBufferOrArrayBufferViewOrBlobOrString;
/**
* Used to indicate when a Blob/BlobImpl that was created from an nsIFile
* (when IsFile() will return true) was from an nsIFile for which
* nsIFile::IsDirectory() returned true. This is a tri-state to enable us to
* assert that the state is always set when callers request it.
*/
enum BlobDirState : uint32_t {
eIsDir,
eIsNotDir,
eUnknownIfDir
};
class Blob : public nsIDOMBlob
, public nsIXHRSendable
, public nsIMutable
@ -95,6 +107,12 @@ public:
bool IsFile() const;
/**
* This may return true if the Blob was created from an nsIFile that is a
* directory.
*/
bool IsDirectory() const;
const nsTArray<nsRefPtr<BlobImpl>>* GetSubBlobImpls() const;
// This method returns null if this Blob is not a File; it returns
@ -102,6 +120,9 @@ public:
// otherwise it returns a new File object with the same BlobImpl.
already_AddRefed<File> ToFile();
// XXXjwatt Consider having a ToDirectory() method. The need for a FileSystem
// object complicates that though.
// This method creates a new File object with the given name and the same
// BlobImpl.
already_AddRefed<File> ToFile(const nsAString& aName) const;
@ -184,7 +205,7 @@ public:
static already_AddRefed<File>
Create(nsISupports* aParent, const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate);
int64_t aLastModifiedDate, BlobDirState aDirState);
static already_AddRefed<File>
Create(nsISupports* aParent, const nsAString& aName,
@ -342,7 +363,8 @@ public:
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate) = 0;
int64_t aLastModifiedDate,
BlobDirState aDirState) = 0;
virtual bool IsMemoryFile() const = 0;
@ -352,6 +374,27 @@ public:
virtual bool IsFile() const = 0;
/**
* Called when this BlobImpl was created from an nsIFile in order to call
* nsIFile::IsDirectory() and cache the result so that when the BlobImpl is
* copied to another process that informaton is available.
* nsIFile::IsDirectory() does synchronous I/O, and BlobImpl objects may be
* created on the main thread or in a non-chrome process (where I/O is not
* allowed). Do not call this on a non-chrome process, and preferably do not
* call it on the main thread.
*
* Not all creators of BlobImplFile will call this method, in which case
* calling IsDirectory will MOZ_ASSERT.
*/
virtual void LookupAndCacheIsDirectory() = 0;
virtual bool IsDirectory() const = 0;
/**
* Prefer IsDirectory(). This exists to help consumer code pass on state from
* one BlobImpl when creating another.
*/
virtual BlobDirState GetDirState() const = 0;
// True if this implementation can be sent to other threads.
virtual bool MayBeClonedToOtherThreads() const
{
@ -368,9 +411,11 @@ class BlobImplBase : public BlobImpl
{
public:
BlobImplBase(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate)
uint64_t aLength, int64_t aLastModifiedDate,
BlobDirState aDirState)
: mIsFile(true)
, mImmutable(false)
, mDirState(aDirState)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
@ -386,6 +431,7 @@ public:
uint64_t aLength)
: mIsFile(true)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
@ -400,6 +446,7 @@ public:
BlobImplBase(const nsAString& aContentType, uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(0)
, mLength(aLength)
@ -414,6 +461,7 @@ public:
uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(aStart)
, mLength(aLength)
@ -485,7 +533,8 @@ public:
virtual void
SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate) override
uint64_t aLength, int64_t aLastModifiedDate,
BlobDirState aDirState) override
{
NS_ASSERTION(aLength, "must have length");
@ -511,6 +560,27 @@ public:
return mIsFile;
}
virtual void LookupAndCacheIsDirectory() override
{
MOZ_ASSERT(false, "Why is this being called on a non-BlobImplFile?");
}
/**
* Returns true if the nsIFile that this object wraps is a directory.
*/
virtual bool IsDirectory() const override
{
MOZ_ASSERT(mDirState != BlobDirState::eUnknownIfDir,
"Must only be used by callers for whom the code paths are "
"know to call LookupAndCacheIsDirectory()");
return mDirState == BlobDirState::eIsDir;
}
virtual BlobDirState GetDirState() const override
{
return mDirState;
}
virtual bool IsStoredFile() const
{
return false;
@ -552,6 +622,7 @@ protected:
bool mIsFile;
bool mImmutable;
BlobDirState mDirState;
nsString mContentType;
nsString mName;
@ -579,7 +650,8 @@ public:
BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
const nsAString& aContentType, int64_t aLastModifiedDate)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
BlobDirState::eIsNotDir)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
@ -709,7 +781,8 @@ public:
// Create as a file
explicit BlobImplFile(nsIFile* aFile, bool aTemporary = false)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(false)
@ -722,7 +795,8 @@ public:
}
BlobImplFile(nsIFile* aFile, indexedDB::FileInfo* aFileInfo)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(true)
@ -740,7 +814,8 @@ public:
// Create as a file
BlobImplFile(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile)
: BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
: BlobImplBase(aName, aContentType, aLength, UINT64_MAX,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(false)
@ -752,7 +827,8 @@ public:
BlobImplFile(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
int64_t aLastModificationDate)
: BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
: BlobImplBase(aName, aContentType, aLength, aLastModificationDate,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(false)
@ -764,7 +840,8 @@ public:
// Create as a file with custom name
BlobImplFile(nsIFile* aFile, const nsAString& aName,
const nsAString& aContentType)
: BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
: BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(false)
@ -781,7 +858,8 @@ public:
BlobImplFile(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
indexedDB::FileInfo* aFileInfo)
: BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
: BlobImplBase(aName, aContentType, aLength, UINT64_MAX,
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
, mStoredFile(true)
@ -806,7 +884,8 @@ public:
// Create as a file to be later initialized
BlobImplFile()
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX,
BlobDirState::eUnknownIfDir)
, mWholeFile(true)
, mStoredFile(false)
, mIsTemporary(false)
@ -828,6 +907,8 @@ public:
void SetPath(const nsAString& aFullPath);
virtual void LookupAndCacheIsDirectory() override;
protected:
virtual ~BlobImplFile() {
if (mFile && mIsTemporary) {

Просмотреть файл

@ -9,6 +9,7 @@
#include "IDBFileHandle.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/MetadataHelper.h"
#ifdef DEBUG
@ -29,7 +30,8 @@ BlobImplSnapshot::BlobImplSnapshot(const nsAString& aName,
: BlobImplBase(aName,
aContentType,
aMetadataParams->Size(),
aMetadataParams->LastModified())
aMetadataParams->LastModified(),
BlobDirState::eUnknownIfDir)
, mFile(aFile)
, mWholeFile(true)
{

Просмотреть файл

@ -439,7 +439,8 @@ ResolveMysteryFile(BlobImpl* aImpl,
BlobChild* actor = ActorFromRemoteBlobImpl(aImpl);
if (actor) {
return actor->SetMysteryBlobInfo(aName, aContentType,
aSize, aLastModifiedDate);
aSize, aLastModifiedDate,
BlobDirState::eUnknownIfDir);
}
return true;
}

Просмотреть файл

@ -670,7 +670,8 @@ public:
EmptyBlobImpl(const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate)
: BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
: BlobImplBase(aName, aContentType, 0, aLastModifiedDate,
BlobDirState::eIsNotDir)
{
mImmutable = true;
}
@ -733,7 +734,8 @@ public:
uint64_t aLength,
int64_t aLastModifiedDate,
nsIInputStream* aInputStream)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
BlobDirState::eIsNotDir)
, mInputStream(aInputStream)
{
MOZ_ASSERT(aLength != UINT64_MAX);
@ -772,12 +774,14 @@ struct MOZ_STACK_CLASS CreateBlobImplMetadata final
nsString mName;
uint64_t mLength;
int64_t mLastModifiedDate;
BlobDirState mDirState;
bool mHasRecursed;
const bool mIsSameProcessActor;
explicit CreateBlobImplMetadata(bool aIsSameProcessActor)
: mLength(0)
, mLastModifiedDate(0)
, mDirState(BlobDirState::eUnknownIfDir)
, mHasRecursed(false)
, mIsSameProcessActor(aIsSameProcessActor)
{
@ -1054,6 +1058,7 @@ CreateBlobImpl(const ParentBlobConstructorParams& aParams,
metadata.mName = params.name();
metadata.mLength = params.length();
metadata.mLastModifiedDate = params.modDate();
metadata.mDirState = BlobDirState(params.dirState());
}
nsRefPtr<BlobImpl> blobImpl =
@ -1855,7 +1860,8 @@ public:
const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aModDate);
int64_t aModDate,
BlobDirState aDirState);
// For Blob.
RemoteBlobImpl(BlobChild* aActor,
@ -1868,7 +1874,8 @@ public:
const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aModDate);
int64_t aModDate,
BlobDirState aDirState);
// For same-process blobs.
RemoteBlobImpl(BlobChild* aActor,
@ -2129,7 +2136,8 @@ public:
SetLazyData(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate) override;
int64_t aLastModifiedDate,
BlobDirState aDirState) override;
virtual bool
IsMemoryFile() const override;
@ -2143,6 +2151,15 @@ public:
virtual bool
IsFile() const override;
virtual void
LookupAndCacheIsDirectory() override;
virtual bool
IsDirectory() const override;
virtual BlobDirState
GetDirState() const override;
virtual bool
MayBeClonedToOtherThreads() const override;
@ -2172,8 +2189,9 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aModDate)
: BlobImplBase(aName, aContentType, aLength, aModDate)
int64_t aModDate,
BlobDirState aDirState)
: BlobImplBase(aName, aContentType, aLength, aModDate, aDirState)
, mIsSlice(false)
{
CommonInit(aActor);
@ -2195,8 +2213,9 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aModDate)
: BlobImplBase(aName, aContentType, aLength, aModDate)
int64_t aModDate,
BlobDirState aDirState)
: BlobImplBase(aName, aContentType, aLength, aModDate, aDirState)
, mSameProcessBlobImpl(aSameProcessBlobImpl)
, mIsSlice(false)
{
@ -2223,7 +2242,8 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
BlobChild::
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX,
BlobDirState::eUnknownIfDir)
, mIsSlice(false)
{
CommonInit(aActor);
@ -2884,7 +2904,8 @@ BlobParent::
RemoteBlobImpl::SetLazyData(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate)
int64_t aLastModifiedDate,
BlobDirState aDirState)
{
MOZ_CRASH("This should never be called!");
}
@ -2917,6 +2938,27 @@ RemoteBlobImpl::IsFile() const
return mBlobImpl->IsFile();
}
void
BlobParent::
RemoteBlobImpl::LookupAndCacheIsDirectory()
{
return mBlobImpl->LookupAndCacheIsDirectory();
}
bool
BlobParent::
RemoteBlobImpl::IsDirectory() const
{
return mBlobImpl->IsDirectory();
}
BlobDirState
BlobParent::
RemoteBlobImpl::GetDirState() const
{
return mBlobImpl->GetDirState();
}
bool
BlobParent::
RemoteBlobImpl::MayBeClonedToOtherThreads() const
@ -3107,7 +3149,8 @@ BlobChild::CommonInit(BlobChild* aOther, BlobImpl* aBlobImpl)
int64_t modDate = otherImpl->GetLastModified(rv);
MOZ_ASSERT(!rv.Failed());
remoteBlob = new RemoteBlobImpl(this, name, contentType, length, modDate);
remoteBlob = new RemoteBlobImpl(this, name, contentType, length, modDate,
otherImpl->GetDirState());
} else {
remoteBlob = new RemoteBlobImpl(this, contentType, length);
}
@ -3149,7 +3192,8 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
params.name(),
params.contentType(),
params.length(),
params.modDate());
params.modDate(),
BlobDirState(params.dirState()));
break;
}
@ -3183,7 +3227,8 @@ BlobChild::CommonInit(const ChildBlobConstructorParams& aParams)
name,
contentType,
size,
lastModifiedDate);
lastModifiedDate,
blobImpl->GetDirState());
} else {
remoteBlob = new RemoteBlobImpl(this, blobImpl, contentType, size);
}
@ -3368,7 +3413,8 @@ BlobChild::GetOrCreateFromImpl(ChildManagerType* aManager,
MOZ_ASSERT(!rv.Failed());
blobParams =
FileBlobConstructorParams(name, contentType, length, modDate, blobData);
FileBlobConstructorParams(name, contentType, length, modDate,
aBlobImpl->GetDirState(), blobData);
} else {
blobParams = NormalBlobConstructorParams(contentType, length, blobData);
}
@ -3541,19 +3587,22 @@ bool
BlobChild::SetMysteryBlobInfo(const nsString& aName,
const nsString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate)
int64_t aLastModifiedDate,
BlobDirState aDirState)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mBlobImpl);
MOZ_ASSERT(mRemoteBlobImpl);
MOZ_ASSERT(aLastModifiedDate != INT64_MAX);
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate);
mBlobImpl->SetLazyData(aName, aContentType, aLength, aLastModifiedDate,
aDirState);
FileBlobConstructorParams params(aName,
aContentType,
aLength,
aLastModifiedDate,
aDirState,
void_t() /* optionalBlobData */);
return SendResolveMystery(params);
}
@ -3568,7 +3617,8 @@ BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
nsString voidString;
voidString.SetIsVoid(true);
mBlobImpl->SetLazyData(voidString, aContentType, aLength, INT64_MAX);
mBlobImpl->SetLazyData(voidString, aContentType, aLength, INT64_MAX,
BlobDirState::eUnknownIfDir);
NormalBlobConstructorParams params(aContentType,
aLength,
@ -3910,7 +3960,8 @@ BlobParent::GetOrCreateFromImpl(ParentManagerType* aManager,
MOZ_ASSERT(!rv.Failed());
blobParams =
FileBlobConstructorParams(name, contentType, length, modDate, void_t());
FileBlobConstructorParams(name, contentType, length, modDate,
aBlobImpl->GetDirState(), void_t());
} else {
blobParams = NormalBlobConstructorParams(contentType, length, void_t());
}
@ -4388,7 +4439,8 @@ BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
mBlobImpl->SetLazyData(voidString,
params.contentType(),
params.length(),
INT64_MAX);
INT64_MAX,
BlobDirState::eUnknownIfDir);
return true;
}
@ -4413,7 +4465,8 @@ BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
mBlobImpl->SetLazyData(params.name(),
params.contentType(),
params.length(),
params.modDate());
params.modDate(),
BlobDirState(params.dirState()));
return true;
}

Просмотреть файл

@ -25,11 +25,14 @@ class PBackgroundChild;
namespace dom {
class Blob;
class BlobImpl;
class ContentChild;
class nsIContentChild;
class PBlobStreamChild;
enum BlobDirState : uint32_t;
class BlobChild final
: public PBlobChild
{
@ -114,7 +117,8 @@ public:
SetMysteryBlobInfo(const nsString& aName,
const nsString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate);
int64_t aLastModifiedDate,
BlobDirState aDirState);
// Use this for non-file blobs.
bool

Просмотреть файл

@ -67,6 +67,7 @@ struct FileBlobConstructorParams
nsString contentType;
uint64_t length;
int64_t modDate;
uint32_t dirState;
// This must be of type BlobData in a child->parent message, and will always
// be of type void_t in a parent->child message.