Backed out changeset 166555b48e77 (bug 1258482)

This commit is contained in:
Sebastian Hengst 2016-04-12 17:56:00 +02:00
Родитель 2a9bc780d3
Коммит 08c222b359
11 изменённых файлов: 241 добавлений и 109 удалений

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

@ -12,7 +12,7 @@
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileList, mFiles, mParent)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileList, mFilesOrDirectories, mParent)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@ -29,6 +29,20 @@ FileList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return mozilla::dom::FileListBinding::Wrap(aCx, this, aGivenProto);
}
void
FileList::Append(File* aFile)
{
OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
element->SetAsFile() = aFile;
}
void
FileList::Append(Directory* aDirectory)
{
OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
element->SetAsDirectory() = aDirectory;
}
NS_IMETHODIMP
FileList::GetLength(uint32_t* aLength)
{
@ -40,47 +54,75 @@ FileList::GetLength(uint32_t* aLength)
NS_IMETHODIMP
FileList::Item(uint32_t aIndex, nsISupports** aValue)
{
nsCOMPtr<nsIDOMBlob> file = Item(aIndex);
file.forget(aValue);
if (aIndex >= mFilesOrDirectories.Length()) {
return NS_ERROR_FAILURE;
}
if (mFilesOrDirectories[aIndex].IsFile()) {
nsCOMPtr<nsIDOMBlob> file = mFilesOrDirectories[aIndex].GetAsFile();
file.forget(aValue);
return NS_OK;
}
MOZ_ASSERT(mFilesOrDirectories[aIndex].IsDirectory());
RefPtr<Directory> directory = mFilesOrDirectories[aIndex].GetAsDirectory();
directory.forget(aValue);
return NS_OK;
}
File*
FileList::Item(uint32_t aIndex) const
{
if (aIndex >= mFiles.Length()) {
return nullptr;
}
return mFiles[aIndex];
}
File*
FileList::IndexedGetter(uint32_t aIndex, bool& aFound) const
{
aFound = aIndex < mFiles.Length();
return Item(aIndex);
}
void
FileList::ToSequence(Sequence<RefPtr<File>>& aSequence,
ErrorResult& aRv) const
FileList::Item(uint32_t aIndex, Nullable<OwningFileOrDirectory>& aValue,
ErrorResult& aRv) const
{
MOZ_ASSERT(aSequence.IsEmpty());
if (mFiles.IsEmpty()) {
if (aIndex >= mFilesOrDirectories.Length()) {
aValue.SetNull();
return;
}
if (!aSequence.SetLength(mFiles.Length(),
aValue.SetValue(mFilesOrDirectories[aIndex]);
}
void
FileList::IndexedGetter(uint32_t aIndex, bool& aFound,
Nullable<OwningFileOrDirectory>& aFileOrDirectory,
ErrorResult& aRv) const
{
aFound = aIndex < mFilesOrDirectories.Length();
Item(aIndex, aFileOrDirectory, aRv);
}
void
FileList::ToSequence(Sequence<OwningFileOrDirectory>& aSequence,
ErrorResult& aRv) const
{
MOZ_ASSERT(aSequence.IsEmpty());
if (mFilesOrDirectories.IsEmpty()) {
return;
}
if (!aSequence.SetLength(mFilesOrDirectories.Length(),
mozilla::fallible_t())) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
for (uint32_t i = 0; i < mFiles.Length(); ++i) {
aSequence[i] = mFiles[i];
for (uint32_t i = 0; i < mFilesOrDirectories.Length(); ++i) {
aSequence[i] = mFilesOrDirectories[i];
}
}
bool
FileList::ClonableToDifferentThreadOrProcess() const
{
for (uint32_t i = 0; i < mFilesOrDirectories.Length(); ++i) {
if (mFilesOrDirectories[i].IsDirectory() &&
!mFilesOrDirectories[i].GetAsDirectory()->ClonableToDifferentThreadOrProcess()) {
return false;
}
}
return true;
}
} // namespace dom
} // namespace mozilla

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

@ -40,16 +40,13 @@ public:
return mParent;
}
bool Append(File* aFile)
{
MOZ_ASSERT(aFile);
return mFiles.AppendElement(aFile, fallible);
}
void Append(File* aFile);
void Append(Directory* aDirectory);
bool Remove(uint32_t aIndex)
{
if (aIndex < mFiles.Length()) {
mFiles.RemoveElementAt(aIndex);
if (aIndex < mFilesOrDirectories.Length()) {
mFilesOrDirectories.RemoveElementAt(aIndex);
return true;
}
@ -58,7 +55,7 @@ public:
void Clear()
{
return mFiles.Clear();
return mFilesOrDirectories.Clear();
}
static FileList* FromSupports(nsISupports* aSupports)
@ -78,22 +75,34 @@ public:
return static_cast<FileList*>(aSupports);
}
File* Item(uint32_t aIndex) const;
const OwningFileOrDirectory& UnsafeItem(uint32_t aIndex) const
{
MOZ_ASSERT(aIndex < Length());
return mFilesOrDirectories[aIndex];
}
File* IndexedGetter(uint32_t aIndex, bool& aFound) const;
void Item(uint32_t aIndex,
Nullable<OwningFileOrDirectory>& aFileOrDirectory,
ErrorResult& aRv) const;
void IndexedGetter(uint32_t aIndex, bool& aFound,
Nullable<OwningFileOrDirectory>& aFileOrDirectory,
ErrorResult& aRv) const;
uint32_t Length() const
{
return mFiles.Length();
return mFilesOrDirectories.Length();
}
void ToSequence(Sequence<RefPtr<File>>& aSequence,
void ToSequence(Sequence<OwningFileOrDirectory>& aSequence,
ErrorResult& aRv) const;
bool ClonableToDifferentThreadOrProcess() const;
private:
~FileList() {}
FallibleTArray<RefPtr<File>> mFiles;
nsTArray<OwningFileOrDirectory> mFilesOrDirectories;
nsCOMPtr<nsISupports> mParent;
};

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

@ -794,35 +794,59 @@ ReadFileList(JSContext* aCx,
{
RefPtr<FileList> fileList = new FileList(aHolder->ParentDuringRead());
uint32_t zero, index;
// |index| is the index of the first blobImpl.
if (!JS_ReadUint32Pair(aReader, &zero, &index)) {
return nullptr;
}
MOZ_ASSERT(zero == 0);
// |aCount| is the number of BlobImpls to use from the |index|.
// |aCount| is the number of Files or Directory for this FileList.
for (uint32_t i = 0; i < aCount; ++i) {
uint32_t pos = index + i;
MOZ_ASSERT(pos < aHolder->BlobImpls().Length());
RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[pos];
MOZ_ASSERT(blobImpl->IsFile());
ErrorResult rv;
blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
uint32_t tagOrDirectoryType, indexOrLengthOfString;
if (!JS_ReadUint32Pair(aReader, &tagOrDirectoryType,
&indexOrLengthOfString)) {
return nullptr;
}
MOZ_ASSERT(blobImpl);
MOZ_ASSERT(tagOrDirectoryType == SCTAG_DOM_BLOB ||
tagOrDirectoryType == Directory::eDOMRootDirectory ||
tagOrDirectoryType == Directory::eNotDOMRootDirectory);
RefPtr<File> file = File::Create(aHolder->ParentDuringRead(), blobImpl);
if (!fileList->Append(file)) {
if (tagOrDirectoryType == SCTAG_DOM_BLOB) {
MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length());
RefPtr<BlobImpl> blobImpl =
aHolder->BlobImpls()[indexOrLengthOfString];
MOZ_ASSERT(blobImpl->IsFile());
ErrorResult rv;
blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
RefPtr<File> file =
File::Create(aHolder->ParentDuringRead(), blobImpl);
MOZ_ASSERT(file);
fileList->Append(file);
continue;
}
nsAutoString path;
path.SetLength(indexOrLengthOfString);
size_t charSize = sizeof(nsString::char_type);
if (!JS_ReadBytes(aReader, (void*) path.BeginWriting(),
indexOrLengthOfString * charSize)) {
return nullptr;
}
nsCOMPtr<nsIFile> file;
nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
RefPtr<Directory> directory =
Directory::Create(aHolder->ParentDuringRead(), file,
(Directory::DirectoryType) tagOrDirectoryType);
fileList->Append(directory);
}
if (!ToJSValue(aCx, fileList, &val)) {
@ -835,7 +859,13 @@ ReadFileList(JSContext* aCx,
// The format of the FileList serialization is:
// - pair of ints: SCTAG_DOM_FILELIST, Length of the FileList
// - pair of ints: 0, The offset of the BlobImpl array
// - for each element of the FileList:
// - if it's a blob:
// - pair of ints: SCTAG_DOM_BLOB, index of the BlobImpl in the array
// mBlobImplArray.
// - else:
// - pair of ints: 0/1 is root, string length
// - value string
bool
WriteFileList(JSStructuredCloneWriter* aWriter,
FileList* aFileList,
@ -845,13 +875,8 @@ WriteFileList(JSStructuredCloneWriter* aWriter,
MOZ_ASSERT(aFileList);
MOZ_ASSERT(aHolder);
// A FileList is serialized writing the X number of elements and the offset
// from mBlobImplArray. The Read will take X elements from mBlobImplArray
// starting from the offset.
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST,
aFileList->Length()) ||
!JS_WriteUint32Pair(aWriter, 0,
aHolder->BlobImpls().Length())) {
aFileList->Length())) {
return false;
}
@ -859,18 +884,39 @@ WriteFileList(JSStructuredCloneWriter* aWriter,
nsTArray<RefPtr<BlobImpl>> blobImpls;
for (uint32_t i = 0; i < aFileList->Length(); ++i) {
RefPtr<BlobImpl> blobImpl =
EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl(), nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
const OwningFileOrDirectory& data = aFileList->UnsafeItem(i);
if (data.IsFile()) {
RefPtr<BlobImpl> blobImpl =
EnsureBlobForBackgroundManager(data.GetAsFile()->Impl(), nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
}
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
aHolder->BlobImpls().Length())) {
return false;
}
aHolder->BlobImpls().AppendElement(blobImpl);
continue;
}
MOZ_ASSERT(blobImpl);
blobImpls.AppendElement(blobImpl);
MOZ_ASSERT(data.IsDirectory());
nsAutoString path;
data.GetAsDirectory()->GetFullRealPath(path);
size_t charSize = sizeof(nsString::char_type);
if (!JS_WriteUint32Pair(aWriter,
(uint32_t)data.GetAsDirectory()->Type(),
path.Length()) ||
!JS_WriteBytes(aWriter, path.get(), path.Length() * charSize)) {
return false;
}
}
aHolder->BlobImpls().AppendElements(blobImpls);
return true;
}
@ -1086,7 +1132,9 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
// See if this is a FileList object.
{
FileList* fileList = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList))) {
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, aObj, fileList)) &&
(mSupportedContext == SameProcessSameThread ||
fileList->ClonableToDifferentThreadOrProcess())) {
return WriteFileList(aWriter, fileList, this);
}
}

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

@ -72,7 +72,7 @@ var clonableObjects = [
new ImageData(2, 2),
];
function create_fileList() {
function create_fileList_forFile() {
var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
var script = SpecialPowers.loadChromeScript(url);
@ -93,6 +93,27 @@ function create_fileList() {
script.sendAsyncMessage("file.open");
}
function create_fileList_forDir() {
var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
var script = SpecialPowers.loadChromeScript(url);
function onOpened(message) {
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
// Just a simple test
is(fileList.files.length, 1, "Filelist has 1 element");
ok(fileList.files[0] instanceof Directory, "We have a directory.");
clonableObjects.push(fileList.files);
script.destroy();
next();
}
script.addMessageListener("dir.opened", onOpened);
script.sendAsyncMessage("dir.open");
}
function create_directory() {
if (navigator.userAgent.toLowerCase().indexOf('Android') != -1) {
next();
@ -527,7 +548,8 @@ function test_messagePort_inWorkers() {
}
var tests = [
create_fileList,
create_fileList_forFile,
create_fileList_forDir,
create_directory,
test_windowToWindow,

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

@ -866,13 +866,13 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
}
}
Sequence<RefPtr<File>> filesSeq;
mFileList->ToSequence(filesSeq, aRv);
Sequence<OwningFileOrDirectory> filesAndDirsSeq;
mFileList->ToSequence(filesAndDirsSeq, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
p->MaybeResolve(filesSeq);
p->MaybeResolve(filesAndDirsSeq);
return p.forget();
}

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

@ -20,14 +20,14 @@ function create_fileList(aPath) {
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
fileList.getFilesAndDirectories().then(function(array) {
is(array.length, 1, "We want just 1 directory.");
ok(array[0] instanceof Directory, "We want just 1 directory.");
// Just a simple test
is(fileList.files.length, 1, "Filelist has 1 element");
ok(fileList.files[0] instanceof Directory, "We have a directory.");
directory = array[0];
script.destroy();
next();
});
directory = fileList.files[0];
script.destroy();
next();
}
script.addMessageListener("dir.opened", onOpened);

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

@ -17,6 +17,11 @@ function create_fileList() {
function onOpened(message) {
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
// Just a simple test
is(fileList.files.length, 1, "Filelist has 1 element");
ok(fileList.files[0] instanceof Directory, "We have a directory.");
script.destroy();
next();
}
@ -27,21 +32,20 @@ function create_fileList() {
function test_worker() {
var fileList = document.getElementById('fileList');
fileList.getFilesAndDirectories().then(function(array) {
var worker = new Worker('worker_basic.js');
worker.onmessage = function(e) {
if (e.data.type == 'finish') {
next();
return;
}
if (e.data.type == 'test') {
ok(e.data.test, e.data.message);
}
var worker = new Worker('worker_basic.js');
worker.onmessage = function(e) {
if (e.data.type == 'finish') {
next();
return;
}
worker.postMessage(array[0]);
});
if (e.data.type == 'test') {
ok(e.data.test, e.data.message);
}
}
worker.postMessage(fileList.files);
}
var tests = [

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

@ -31,10 +31,12 @@ function checkSubDir(dir) {
}
onmessage = function(e) {
var directory = e.data;
ok(directory instanceof Directory, "This is a directory.");
var fileList = e.data;
ok(fileList instanceof FileList, "This is a fileList.");
is(fileList.length, 1, "We want just 1 element.");
ok(fileList[0] instanceof Directory, "This is a directory.");
directory.getFilesAndDirectories().then(
fileList[0].getFilesAndDirectories().then(
function(data) {
ok(data.length, "We should have some data.");
var promises = [];

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

@ -2562,7 +2562,7 @@ HTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
aFiles->GetLength(&listLength);
for (uint32_t i = 0; i < listLength; i++) {
OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
element->SetAsFile() = files->Item(i);
*element = files->UnsafeItem(i);
}
}
@ -2678,6 +2678,9 @@ HTMLInputElement::UpdateFileList()
for (uint32_t i = 0; i < array.Length(); ++i) {
if (array[i].IsFile()) {
mFileList->Append(array[i].GetAsFile());
} else {
MOZ_ASSERT(array[i].IsDirectory());
mFileList->Append(array[i].GetAsDirectory());
}
}
}

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

@ -11,6 +11,8 @@
*/
interface FileList {
getter File? item(unsigned long index);
[Throws]
getter (File or Directory)? item(unsigned long index);
readonly attribute unsigned long length;
};

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

@ -1186,7 +1186,7 @@ DefaultTooltipTextProvider::GetNodeText(nsIDOMNode* aNode, char16_t** aText,
NS_ENSURE_SUCCESS(rv, rv);
} else {
FileList* fl = static_cast<FileList*>(fileList.get());
fl->Item(0)->GetName(outText);
fl->UnsafeItem(0).GetAsFile()->GetName(outText);
// For UX and performance (jank) reasons we cap the number of
// files that we list in the tooltip to 20 plus a "and xxx more"
@ -1195,7 +1195,7 @@ DefaultTooltipTextProvider::GetNodeText(nsIDOMNode* aNode, char16_t** aText,
uint32_t count = std::min(listLength, TRUNCATED_FILE_COUNT);
for (uint32_t i = 1; i < count; ++i) {
nsString fileName;
fl->Item(i)->GetName(fileName);
fl->UnsafeItem(i).GetAsFile()->GetName(fileName);
outText.Append(NS_LITERAL_STRING("\n"));
outText.Append(fileName);
}