Skip to content

Commit

Permalink
Bug 1173320 - patch 1/8 - Implement Directory object as string and no…
Browse files Browse the repository at this point in the history
…t as BlobImpl, r=smaug
  • Loading branch information
bakulf committed Mar 19, 2016
1 parent 13a1412 commit 940c58c
Show file tree
Hide file tree
Showing 42 changed files with 1,564 additions and 868 deletions.
22 changes: 2 additions & 20 deletions dom/base/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,6 @@ Blob::IsFile() const
return mImpl->IsFile();
}

bool
Blob::IsDirectory() const
{
return mImpl->IsDirectory();
}

const nsTArray<RefPtr<BlobImpl>>*
Blob::GetSubBlobImpls() const
{
Expand Down Expand Up @@ -420,11 +414,10 @@ 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, BlobDirState aDirState)
int64_t aLastModifiedDate)
{
RefPtr<File> file = new File(aParent,
new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
aDirState));
new BlobImplBase(aName, aContentType, aLength, aLastModifiedDate));
return file.forget();
}

Expand Down Expand Up @@ -946,17 +939,6 @@ 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;
}

////////////////////////////////////////////////////////////////////////////
// EmptyBlobImpl implementation

Expand Down
88 changes: 3 additions & 85 deletions dom/base/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ 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
Expand Down Expand Up @@ -101,22 +89,13 @@ class Blob : public nsIDOMBlob

bool IsFile() const;

/**
* This may return true if the Blob was created from an nsIFile that is a
* directory.
*/
bool IsDirectory() const;

const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;

// This method returns null if this Blob is not a File; it returns
// the same object in case this Blob already implements the File interface;
// 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,
Expand Down Expand Up @@ -194,7 +173,7 @@ class File final : public Blob
static already_AddRefed<File>
Create(nsISupports* aParent, const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate, BlobDirState aDirState);
int64_t aLastModifiedDate);

// The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
// freed by free so it must be allocated by malloc or something
Expand Down Expand Up @@ -339,28 +318,6 @@ class BlobImpl : public nsISupports

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 void SetIsDirectory(bool aIsDir) = 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
{
Expand All @@ -377,11 +334,9 @@ class BlobImplBase : public BlobImpl
{
public:
BlobImplBase(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate,
BlobDirState aDirState = BlobDirState::eUnknownIfDir)
uint64_t aLength, int64_t aLastModifiedDate)
: mIsFile(true)
, mImmutable(false)
, mDirState(aDirState)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
Expand All @@ -397,7 +352,6 @@ class BlobImplBase : public BlobImpl
uint64_t aLength)
: mIsFile(true)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
Expand All @@ -412,7 +366,6 @@ class BlobImplBase : public BlobImpl
BlobImplBase(const nsAString& aContentType, uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(0)
, mLength(aLength)
Expand All @@ -427,7 +380,6 @@ class BlobImplBase : public BlobImpl
uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mDirState(BlobDirState::eUnknownIfDir)
, mContentType(aContentType)
, mStart(aStart)
, mLength(aLength)
Expand Down Expand Up @@ -518,36 +470,6 @@ class BlobImplBase : public BlobImpl
return mIsFile;
}

virtual void LookupAndCacheIsDirectory() override
{
MOZ_ASSERT(false, "Why is this being called on a non-BlobImplFile?");
}

virtual void SetIsDirectory(bool aIsDir) override
{
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");
mDirState = aIsDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
}

/**
* 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() or "
"SetIsDirectory()");
return mDirState == BlobDirState::eIsDir;
}

virtual BlobDirState GetDirState() const override
{
return mDirState;
}

virtual bool IsSizeUnknown() const override
{
return mLength == UINT64_MAX;
Expand All @@ -565,7 +487,6 @@ class BlobImplBase : public BlobImpl

bool mIsFile;
bool mImmutable;
BlobDirState mDirState;

nsString mContentType;
nsString mName;
Expand All @@ -590,8 +511,7 @@ class BlobImplMemory final : public BlobImplBase

BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
const nsAString& aContentType, int64_t aLastModifiedDate)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate,
BlobDirState::eIsNotDir)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
Expand Down Expand Up @@ -792,8 +712,6 @@ class BlobImplFile : public BlobImplBase

void SetPath(const nsAString& aFullPath);

virtual void LookupAndCacheIsDirectory() override;

// We always have size and date for this kind of blob.
virtual bool IsSizeUnknown() const override { return false; }
virtual bool IsDateUnknown() const override { return false; }
Expand Down
1 change: 0 additions & 1 deletion dom/base/nsContentUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7625,7 +7625,6 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
// has this data available to it when passed over:
blobImpl->GetSize(rv);
blobImpl->GetLastModified(rv);
blobImpl->LookupAndCacheIsDirectory();
} else {
if (aInSyncMessage) {
// Can't do anything.
Expand Down
56 changes: 17 additions & 39 deletions dom/events/DataTransfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mItems)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
Expand Down Expand Up @@ -281,26 +281,28 @@ DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
FileList*
DataTransfer::GetFiles(ErrorResult& aRv)
{
return GetFilesInternal(aRv, nsContentUtils::SubjectPrincipal());
return GetFileListInternal(aRv, nsContentUtils::SubjectPrincipal());
}

FileList*
DataTransfer::GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal)
DataTransfer::GetFileListInternal(ErrorResult& aRv,
nsIPrincipal* aSubjectPrincipal)
{
if (mEventMessage != eDrop &&
mEventMessage != eLegacyDragDrop &&
mEventMessage != ePaste) {
return nullptr;
}

if (!mFiles) {
mFiles = new FileList(static_cast<nsIDOMDataTransfer*>(this));
if (!mFileList) {
mFileList = new FileList(static_cast<nsIDOMDataTransfer*>(this));

uint32_t count = mItems.Length();

for (uint32_t i = 0; i < count; i++) {
nsCOMPtr<nsIVariant> variant;
aRv = GetDataAtInternal(NS_ConvertUTF8toUTF16(kFileMime), i, aSubjectPrincipal, getter_AddRefs(variant));
aRv = GetDataAtInternal(NS_ConvertUTF8toUTF16(kFileMime), i,
aSubjectPrincipal, getter_AddRefs(variant));
if (aRv.Failed()) {
return nullptr;
}
Expand Down Expand Up @@ -338,21 +340,21 @@ DataTransfer::GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal
MOZ_ASSERT(domFile);
}

if (!mFiles->Append(domFile)) {
if (!mFileList->Append(domFile)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
}
}

return mFiles;
return mFileList;
}

NS_IMETHODIMP
DataTransfer::GetFiles(nsIDOMFileList** aFileList)
{
ErrorResult rv;
NS_IF_ADDREF(*aFileList = GetFilesInternal(rv, nsContentUtils::GetSystemPrincipal()));
NS_IF_ADDREF(*aFileList = GetFileListInternal(rv, nsContentUtils::GetSystemPrincipal()));
return rv.StealNSResult();
}

Expand Down Expand Up @@ -854,7 +856,7 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
return nullptr;
}

if (!mFiles) {
if (!mFileList) {
GetFiles(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
Expand All @@ -863,38 +865,14 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)

Sequence<OwningFileOrDirectory> filesAndDirsSeq;

if (mFiles && mFiles->Length()) {
if (!filesAndDirsSeq.SetLength(mFiles->Length(), mozilla::fallible_t())) {
if (mFileList && mFileList->Length()) {
if (!filesAndDirsSeq.SetLength(mFileList->Length(), mozilla::fallible_t())) {
p->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
return p.forget();
}

for (uint32_t i = 0; i < mFiles->Length(); ++i) {
if (mFiles->Item(i)->Impl()->IsDirectory()) {
#if defined(ANDROID) || defined(MOZ_B2G)
MOZ_ASSERT(false,
"Directory picking should have been redirected to normal "
"file picking for platforms that don't have a directory "
"picker");
#endif
nsAutoString path;
mFiles->Item(i)->GetMozFullPathInternal(path, aRv);
if (aRv.Failed()) {
return nullptr;
}
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);

RefPtr<OSFileSystem> fs = new OSFileSystem(dirname);
fs->Init(parentNode->OwnerDoc()->GetInnerWindow());

RefPtr<Directory> directory = new Directory(fs, basename);
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
filesAndDirsSeq[i].SetAsDirectory() = directory;
} else {
filesAndDirsSeq[i].SetAsFile() = mFiles->Item(i);
}
for (uint32_t i = 0; i < mFileList->Length(); ++i) {
filesAndDirsSeq[i].SetAsFile() = mFileList->Item(i);
}
}

Expand Down
7 changes: 4 additions & 3 deletions dom/events/DataTransfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class DataTransfer final : public nsIDOMDataTransfer,
void FillInExternalData(TransferItem& aItem, uint32_t aIndex);


FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
FileList* GetFileListInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal);
nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal* aSubjectPrincipal, nsIVariant** aData);
nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex,
Expand Down Expand Up @@ -300,8 +300,9 @@ class DataTransfer final : public nsIDOMDataTransfer,
// array of items, each containing an array of format->data pairs
nsTArray<nsTArray<TransferItem> > mItems;

// array of files, containing only the files present in the dataTransfer
RefPtr<FileList> mFiles;
// array of files and directories, containing only the files present in the
// dataTransfer
RefPtr<FileList> mFileList;

// the target of the drag. The drag and dragend events will fire at this.
nsCOMPtr<mozilla::dom::Element> mDragTarget;
Expand Down
3 changes: 1 addition & 2 deletions dom/filehandle/ActorsChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,7 @@ ConvertActorToFile(FileHandleBase* aFileHandle,
actor->SetMysteryBlobInfo(mutableFile->Name(),
mutableFile->Type(),
size.get_uint64_t(),
lastModified.get_int64_t(),
BlobDirState::eUnknownIfDir);
lastModified.get_int64_t());

RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
MOZ_ASSERT(blobImpl);
Expand Down
Loading

0 comments on commit 940c58c

Please sign in to comment.