Bug 1258694 - Implement Directory::GetFiles(), r=smaug

This commit is contained in:
Andrea Marchesini 2016-04-13 07:15:56 -04:00
parent 11ea1f64cc
commit e3a78f6247
22 changed files with 683 additions and 123 deletions

View File

@ -131,7 +131,7 @@ CreateDirectoryTaskChild::HandlerCallback()
void
CreateDirectoryTaskChild::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(CREATE_DIRECTORY_TASK_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_CREATE_PERMISSION);
}
/**
@ -216,7 +216,7 @@ CreateDirectoryTaskParent::IOWork()
void
CreateDirectoryTaskParent::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(CREATE_DIRECTORY_TASK_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_CREATE_PERMISSION);
}
} // namespace dom

View File

@ -11,8 +11,6 @@
#include "nsAutoPtr.h"
#include "mozilla/ErrorResult.h"
#define CREATE_DIRECTORY_TASK_PERMISSION "create"
namespace mozilla {
namespace dom {

View File

@ -5,8 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CreateFileTask.h"
#include "CreateDirectoryTask.h"
#include "RemoveTask.h"
#include <algorithm>
@ -27,10 +25,10 @@
#define GET_PERMISSION_ACCESS_TYPE(aAccess) \
if (mReplace) { \
aAccess.AssignLiteral(REMOVE_TASK_PERMISSION); \
aAccess.AssignLiteral(DIRECTORY_WRITE_PERMISSION); \
return; \
} \
aAccess.AssignLiteral(CREATE_DIRECTORY_TASK_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_CREATE_PERMISSION);
namespace mozilla {
namespace dom {

View File

@ -11,6 +11,7 @@
#include "FileSystemPermissionRequest.h"
#include "GetDirectoryListingTask.h"
#include "GetFileOrDirectoryTask.h"
#include "GetFilesTask.h"
#include "RemoveTask.h"
#include "nsCharSeparatedTokenizer.h"
@ -446,6 +447,27 @@ Directory::GetFilesAndDirectories(ErrorResult& aRv)
return task->GetPromise();
}
already_AddRefed<Promise>
Directory::GetFiles(bool aRecursiveFlag, ErrorResult& aRv)
{
ErrorResult rv;
RefPtr<FileSystemBase> fs = GetFileSystem(rv);
if (NS_WARN_IF(rv.Failed())) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
RefPtr<GetFilesTaskChild> task =
GetFilesTaskChild::Create(fs, mFile, aRecursiveFlag, rv);
if (NS_WARN_IF(rv.Failed())) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
FileSystemPermissionRequest::RequestForTask(task);
return task->GetPromise();
}
void
Directory::SetContentFilters(const nsAString& aFilters)
{

View File

@ -112,6 +112,9 @@ public:
already_AddRefed<Promise>
GetFilesAndDirectories(ErrorResult& aRv);
already_AddRefed<Promise>
GetFiles(bool aRecursiveFlag, ErrorResult& aRv);
// =========== End WebIDL bindings.============
/**

View File

@ -53,6 +53,7 @@ FileSystemRequestParent::Initialize(const FileSystemParams& aParams)
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(CreateFile)
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetDirectoryListing)
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFileOrDirectory)
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(GetFiles)
FILESYSTEM_REQUEST_PARENT_DISPATCH_ENTRY(Remove)
default: {

View File

@ -20,6 +20,10 @@ class FileSystemBase;
class FileSystemParams;
class PBlobParent;
#define DIRECTORY_READ_PERMISSION "read"
#define DIRECTORY_WRITE_PERMISSION "write"
#define DIRECTORY_CREATE_PERMISSION "create"
/*
* The base class to implement a Task class.
* The file system operations can only be performed in the parent process. In

View File

@ -18,8 +18,6 @@
#include "nsIFile.h"
#include "nsStringGlue.h"
#define GET_DIRECTORY_LISTING_PERMISSION "read"
namespace mozilla {
namespace dom {
@ -206,7 +204,7 @@ GetDirectoryListingTaskChild::HandlerCallback()
void
GetDirectoryListingTaskChild::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(GET_DIRECTORY_LISTING_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
}
/**
@ -394,7 +392,7 @@ GetDirectoryListingTaskParent::IOWork()
void
GetDirectoryListingTaskParent::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(GET_DIRECTORY_LISTING_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
}
} // namespace dom

View File

@ -17,8 +17,6 @@
#include "nsIFile.h"
#include "nsStringGlue.h"
#define GET_FILE_OR_DIRECTORY_PERMISSION "read"
namespace mozilla {
namespace dom {
@ -171,7 +169,7 @@ GetFileOrDirectoryTaskChild::HandlerCallback()
void
GetFileOrDirectoryTaskChild::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(GET_FILE_OR_DIRECTORY_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
}
/**
@ -298,7 +296,7 @@ GetFileOrDirectoryTaskParent::IOWork()
void
GetFileOrDirectoryTaskParent::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(GET_FILE_OR_DIRECTORY_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
}
} // namespace dom

View File

@ -0,0 +1,359 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GetFilesTask.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "js/Value.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/PFileSystemParams.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "nsIFile.h"
#include "nsStringGlue.h"
namespace mozilla {
namespace dom {
/**
* GetFilesTaskChild
*/
/* static */ already_AddRefed<GetFilesTaskChild>
GetFilesTaskChild::Create(FileSystemBase* aFileSystem,
nsIFile* aTargetPath,
bool aRecursiveFlag,
ErrorResult& aRv)
{
MOZ_ASSERT(aFileSystem);
aFileSystem->AssertIsOnOwningThread();
nsCOMPtr<nsIGlobalObject> globalObject =
do_QueryInterface(aFileSystem->GetParentObject());
if (NS_WARN_IF(!globalObject)) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<GetFilesTaskChild> task =
new GetFilesTaskChild(aFileSystem, aTargetPath, aRecursiveFlag);
// aTargetPath can be null. In this case SetError will be called.
task->mPromise = Promise::Create(globalObject, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return task.forget();
}
GetFilesTaskChild::GetFilesTaskChild(FileSystemBase* aFileSystem,
nsIFile* aTargetPath,
bool aRecursiveFlag)
: FileSystemTaskChildBase(aFileSystem)
, mTargetPath(aTargetPath)
, mRecursiveFlag(aRecursiveFlag)
{
MOZ_ASSERT(aFileSystem);
aFileSystem->AssertIsOnOwningThread();
}
GetFilesTaskChild::~GetFilesTaskChild()
{
mFileSystem->AssertIsOnOwningThread();
}
already_AddRefed<Promise>
GetFilesTaskChild::GetPromise()
{
mFileSystem->AssertIsOnOwningThread();
return RefPtr<Promise>(mPromise).forget();
}
FileSystemParams
GetFilesTaskChild::GetRequestParams(const nsString& aSerializedDOMPath,
ErrorResult& aRv) const
{
mFileSystem->AssertIsOnOwningThread();
nsAutoString path;
aRv = mTargetPath->GetPath(path);
if (NS_WARN_IF(aRv.Failed())) {
return FileSystemGetFilesParams();
}
return FileSystemGetFilesParams(aSerializedDOMPath, path, mRecursiveFlag);
}
void
GetFilesTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
ErrorResult& aRv)
{
mFileSystem->AssertIsOnOwningThread();
MOZ_ASSERT(aValue.type() ==
FileSystemResponseValue::TFileSystemFilesResponse);
FileSystemFilesResponse r = aValue;
if (!mTargetData.SetLength(r.data().Length(), mozilla::fallible_t())) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
for (uint32_t i = 0; i < r.data().Length(); ++i) {
const FileSystemFileResponse& data = r.data()[i];
mTargetData[i] = data.realPath();
}
}
void
GetFilesTaskChild::HandlerCallback()
{
mFileSystem->AssertIsOnOwningThread();
if (mFileSystem->IsShutdown()) {
mPromise = nullptr;
return;
}
if (HasError()) {
mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
mPromise = nullptr;
return;
}
size_t count = mTargetData.Length();
Sequence<RefPtr<File>> listing;
if (!listing.SetLength(count, mozilla::fallible_t())) {
mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
mPromise = nullptr;
return;
}
for (unsigned i = 0; i < count; i++) {
nsCOMPtr<nsIFile> path;
NS_ConvertUTF16toUTF8 fullPath(mTargetData[i]);
nsresult rv = NS_NewNativeLocalFile(fullPath, true, getter_AddRefs(path));
if (NS_WARN_IF(NS_FAILED(rv))) {
mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
mPromise = nullptr;
return;
}
#ifdef DEBUG
nsCOMPtr<nsIFile> rootPath;
rv = NS_NewLocalFile(mFileSystem->LocalOrDeviceStorageRootPath(), false,
getter_AddRefs(rootPath));
if (NS_WARN_IF(NS_FAILED(rv))) {
mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
mPromise = nullptr;
return;
}
MOZ_ASSERT(FileSystemUtils::IsDescendantPath(rootPath, path));
#endif
RefPtr<File> file =
File::CreateFromFile(mFileSystem->GetParentObject(), path);
MOZ_ASSERT(file);
listing[i] = file;
}
mPromise->MaybeResolve(listing);
mPromise = nullptr;
}
void
GetFilesTaskChild::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral("read");
}
/**
* GetFilesTaskParent
*/
/* static */ already_AddRefed<GetFilesTaskParent>
GetFilesTaskParent::Create(FileSystemBase* aFileSystem,
const FileSystemGetFilesParams& aParam,
FileSystemRequestParent* aParent,
ErrorResult& aRv)
{
MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
AssertIsOnBackgroundThread();
MOZ_ASSERT(aFileSystem);
RefPtr<GetFilesTaskParent> task =
new GetFilesTaskParent(aFileSystem, aParam, aParent);
NS_ConvertUTF16toUTF8 path(aParam.realPath());
aRv = NS_NewNativeLocalFile(path, true, getter_AddRefs(task->mTargetPath));
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return task.forget();
}
GetFilesTaskParent::GetFilesTaskParent(FileSystemBase* aFileSystem,
const FileSystemGetFilesParams& aParam,
FileSystemRequestParent* aParent)
: FileSystemTaskParentBase(aFileSystem, aParam, aParent)
, mRecursiveFlag(aParam.recursiveFlag())
{
MOZ_ASSERT(XRE_IsParentProcess(), "Only call from parent process!");
AssertIsOnBackgroundThread();
MOZ_ASSERT(aFileSystem);
}
FileSystemResponseValue
GetFilesTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
{
AssertIsOnBackgroundThread();
InfallibleTArray<PBlobParent*> blobs;
FallibleTArray<FileSystemFileResponse> inputs;
if (!inputs.SetLength(mTargetData.Length(), mozilla::fallible_t())) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
FileSystemFilesResponse response;
return response;
}
for (unsigned i = 0; i < mTargetData.Length(); i++) {
FileSystemFileResponse fileData;
fileData.realPath() = mTargetData[i];
inputs[i] = fileData;
}
FileSystemFilesResponse response;
response.data().SwapElements(inputs);
return response;
}
nsresult
GetFilesTaskParent::IOWork()
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on I/O thread!");
if (mFileSystem->IsShutdown()) {
return NS_ERROR_FAILURE;
}
bool exists;
nsresult rv = mTargetPath->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
return NS_OK;
}
// Get isDirectory.
rv = ExploreDirectory(mTargetPath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
GetFilesTaskParent::ExploreDirectory(nsIFile* aPath)
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
MOZ_ASSERT(aPath);
bool isDir;
nsresult rv = aPath->IsDirectory(&isDir);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!isDir) {
return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
}
nsCOMPtr<nsISimpleEnumerator> entries;
rv = aPath->GetDirectoryEntries(getter_AddRefs(entries));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
for (;;) {
bool hasMore = false;
if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
break;
}
nsCOMPtr<nsISupports> supp;
if (NS_WARN_IF(NS_FAILED(entries->GetNext(getter_AddRefs(supp))))) {
break;
}
nsCOMPtr<nsIFile> currFile = do_QueryInterface(supp);
MOZ_ASSERT(currFile);
bool isLink, isSpecial, isFile;
if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
isLink || isSpecial) {
continue;
}
if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
NS_FAILED(currFile->IsDirectory(&isDir))) ||
!(isFile || isDir)) {
continue;
}
if (isFile) {
nsAutoString path;
if (NS_WARN_IF(NS_FAILED(currFile->GetPath(path)))) {
continue;
}
if (!mTargetData.AppendElement(path, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
continue;
}
MOZ_ASSERT(isDir);
if (!mRecursiveFlag) {
continue;
}
// Recursive.
rv = ExploreDirectory(currFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
void
GetFilesTaskParent::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(DIRECTORY_READ_PERMISSION);
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,99 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_GetFilesTask_h
#define mozilla_dom_GetFilesTask_h
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/FileSystemTaskBase.h"
#include "mozilla/ErrorResult.h"
#include "nsAutoPtr.h"
namespace mozilla {
namespace dom {
class BlobImpl;
class GetFilesTaskChild final : public FileSystemTaskChildBase
{
public:
static already_AddRefed<GetFilesTaskChild>
Create(FileSystemBase* aFileSystem,
nsIFile* aTargetPath,
bool aRecursiveFlag,
ErrorResult& aRv);
virtual
~GetFilesTaskChild();
already_AddRefed<Promise>
GetPromise();
virtual void
GetPermissionAccessType(nsCString& aAccess) const override;
private:
// If aDirectoryOnly is set, we should ensure that the target is a directory.
GetFilesTaskChild(FileSystemBase* aFileSystem,
nsIFile* aTargetPath,
bool aRecursiveFlag);
virtual FileSystemParams
GetRequestParams(const nsString& aSerializedDOMPath,
ErrorResult& aRv) const override;
virtual void
SetSuccessRequestResult(const FileSystemResponseValue& aValue,
ErrorResult& aRv) override;
virtual void
HandlerCallback() override;
RefPtr<Promise> mPromise;
nsCOMPtr<nsIFile> mTargetPath;
bool mRecursiveFlag;
// We store the fullpath of Files.
FallibleTArray<nsString> mTargetData;
};
class GetFilesTaskParent final : public FileSystemTaskParentBase
{
public:
static already_AddRefed<GetFilesTaskParent>
Create(FileSystemBase* aFileSystem,
const FileSystemGetFilesParams& aParam,
FileSystemRequestParent* aParent,
ErrorResult& aRv);
virtual void
GetPermissionAccessType(nsCString& aAccess) const override;
private:
GetFilesTaskParent(FileSystemBase* aFileSystem,
const FileSystemGetFilesParams& aParam,
FileSystemRequestParent* aParent);
virtual FileSystemResponseValue
GetSuccessRequestResult(ErrorResult& aRv) const override;
virtual nsresult
IOWork() override;
nsresult
ExploreDirectory(nsIFile* aPath);
nsCOMPtr<nsIFile> mTargetPath;
bool mRecursiveFlag;
// We store the fullpath of Files.
FallibleTArray<nsString> mTargetData;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_GetFilesTask_h

View File

@ -44,6 +44,13 @@ struct FileSystemGetDirectoryListingParams
nsString filters;
};
struct FileSystemGetFilesParams
{
nsString filesystem;
nsString realPath;
bool recursiveFlag;
};
struct FileSystemGetFileOrDirectoryParams
{
nsString filesystem;
@ -64,6 +71,7 @@ union FileSystemParams
FileSystemCreateDirectoryParams;
FileSystemCreateFileParams;
FileSystemGetDirectoryListingParams;
FileSystemGetFilesParams;
FileSystemGetFileOrDirectoryParams;
FileSystemRemoveParams;
};

View File

@ -43,6 +43,11 @@ struct FileSystemDirectoryListingResponse
FileSystemDirectoryListingResponseData[] data;
};
struct FileSystemFilesResponse
{
FileSystemFileResponse[] data;
};
struct FileSystemErrorResponse
{
nsresult error;
@ -59,6 +64,7 @@ union FileSystemResponseValue
FileSystemDirectoryResponse;
FileSystemDirectoryListingResponse;
FileSystemFileResponse;
FileSystemFilesResponse;
FileSystemErrorResponse;
};

View File

@ -142,7 +142,7 @@ RemoveTaskChild::HandlerCallback()
void
RemoveTaskChild::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(REMOVE_TASK_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_WRITE_PERMISSION);
}
/**
@ -252,7 +252,7 @@ RemoveTaskParent::IOWork()
void
RemoveTaskParent::GetPermissionAccessType(nsCString& aAccess) const
{
aAccess.AssignLiteral(REMOVE_TASK_PERMISSION);
aAccess.AssignLiteral(DIRECTORY_WRITE_PERMISSION);
}
} // namespace dom

View File

@ -11,8 +11,6 @@
#include "nsAutoPtr.h"
#include "mozilla/ErrorResult.h"
#define REMOVE_TASK_PERMISSION "write"
namespace mozilla {
namespace dom {

View File

@ -28,6 +28,7 @@ UNIFIED_SOURCES += [
'FileSystemUtils.cpp',
'GetDirectoryListingTask.cpp',
'GetFileOrDirectoryTask.cpp',
'GetFilesTask.cpp',
'OSFileSystem.cpp',
'RemoveTask.cpp',
]

View File

@ -0,0 +1,75 @@
function test_basic(aDirectory, aNext) {
ok(aDirectory, "Directory exists.");
ok(aDirectory instanceof Directory, "We have a directory.");
is(aDirectory.name, '/', "directory.name must be '/'");
is(aDirectory.path, '/', "directory.path must be '/'");
aNext();
}
function test_getFilesAndDirectories(aDirectory, aRecursive, aNext) {
function checkSubDir(dir) {
return dir.getFilesAndDirectories().then(
function(data) {
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories");
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
isnot(data[i].path, '/', "Subdirectory path should be called with the leafname");
isnot(data[i].path, dir.path, "Subdirectory path should contain the parent path.");
is(data[i].path,dir.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
}
}
}
);
}
aDirectory.getFilesAndDirectories().then(
function(data) {
ok(data.length, "We should have some data.");
var promises = [];
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories: " + data[i].name);
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
is(data[i].path, '/' + data[i].name, "Subdirectory path should be called '/' + leafname");
if (aRecursive) {
promises.push(checkSubDir(data[i]));
}
}
}
return Promise.all(promises);
},
function() {
ok(false, "Something when wrong");
}
).then(aNext);
}
function test_getFiles(aDirectory, aRecursive, aNext) {
aDirectory.getFiles(aRecursive).then(
function(data) {
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File, "File: " + data[i].name);
}
},
function() {
ok(false, "Something when wrong");
}
).then(aNext);
}
function test_getFiles_recursiveComparison(aDirectory, aNext) {
aDirectory.getFiles(true).then(function(data) {
is(data.length, 2, "Only 2 files for this test.");
ok(data[0].name == 'foo.txt' || data[0].name == 'bar.txt', "First filename matches");
ok(data[1].name == 'foo.txt' || data[1].name == 'bar.txt', "Second filename matches");
}).then(function() {
return aDirectory.getFiles(false);
}).then(function(data) {
is(data.length, 1, "Only 1 file for this test.");
ok(data[0].name == 'foo.txt' || data[0].name == 'bar.txt', "First filename matches");
}).catch(function() {
ok(false, "Something when wrong");
}).then(aNext);
}

View File

@ -1,5 +1,6 @@
[DEFAULT]
support-files =
filesystem_commons.js
script_fileList.js
worker_basic.js

View File

@ -1,22 +1,67 @@
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.importGlobalProperties(["File"]);
addMessageListener("dir.open", function (e) {
var testFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get(e.path == 'root' ? 'ProfD' : e.path, Ci.nsIFile);
function createProfDFile() {
return Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get('ProfD', Ci.nsIFile);
}
function createRootFile() {
var testFile = createProfDFile();
// Let's go back to the root of the FileSystem
if (e.path == 'root') {
while (true) {
var parent = testFile.parent;
if (!parent) {
break;
}
testFile = parent;
while (true) {
var parent = testFile.parent;
if (!parent) {
break;
}
testFile = parent;
}
return testFile;
}
function createTestFile() {
var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get('TmpD', Ci.nsIFile)
tmpFile.append('dir-test');
tmpFile.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
var file1 = tmpFile.clone();
file1.append('foo.txt');
file1.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
var dir = tmpFile.clone();
dir.append('subdir');
dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
var file2 = dir.clone();
file2.append('bar.txt');
file2.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
return tmpFile;
}
addMessageListener("dir.open", function (e) {
var testFile;
switch (e.path) {
case 'ProfD':
testFile = createProfDFile();
break;
case 'root':
testFile = createRootFile();
break;
case 'test':
testFile = createTestFile();
break;
}
sendAsyncMessage("dir.opened", {

View File

@ -3,6 +3,7 @@
<head>
<title>Test for Directory API</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="filesystem_commons.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
@ -34,63 +35,20 @@ function create_fileList(aPath) {
script.sendAsyncMessage("dir.open", { path: aPath });
}
function test_basic() {
ok(directory, "Directory exists.");
ok(directory instanceof Directory, "We have a directory.");
is(directory.name, '/', "directory.name must be '/'");
is(directory.path, '/', "directory.path must be '/'");
next();
}
function checkSubDir(dir) {
return dir.getFilesAndDirectories().then(
function(data) {
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories");
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname: " + data[i].name);
isnot(data[i].path, '/', "Subdirectory path should be called with the leafname:" + data[i].path);
isnot(data[i].path, dir.path, "Subdirectory path should contain the parent path.");
is(data[i].path,dir.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
}
}
}
);
}
function getFilesAndDirectories(aRecursive) {
directory.getFilesAndDirectories().then(
function(data) {
ok(data.length, "We should have some data.");
var promises = [];
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories");
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
is(data[i].path, '/' + data[i].name, "Subdirectory path should be called '/' + leafname");
if (aRecursive) {
promises.push(checkSubDir(data[i]));
}
}
}
return Promise.all(promises);
},
function() {
ok(false, "Something when wrong");
}
).then(next);
}
var tests = [
function() { create_fileList('ProfD') },
test_basic,
function() { getFilesAndDirectories(true) },
function() { test_basic(directory, next); },
function() { test_getFilesAndDirectories(directory, true, next); },
function() { test_getFiles(directory, false, next); },
function() { test_getFiles(directory, true, next); },
function() { create_fileList('root') },
test_basic,
function() { getFilesAndDirectories(false) },
function() { create_fileList('test') },
function() { test_getFiles_recursiveComparison(directory, next); },
function() { create_fileList('root'); },
function() { test_basic(directory, next); },
function() { test_getFilesAndDirectories(directory, false, next); },
function() { test_getFiles(directory, false, next); },
];
function next() {

View File

@ -1,3 +1,5 @@
importScripts('filesystem_commons.js');
function finish() {
postMessage({ type: 'finish' });
}
@ -14,43 +16,26 @@ function isnot(a, b, msg) {
ok(a != b, msg);
}
function checkSubDir(dir) {
return dir.getFilesAndDirectories().then(
function(data) {
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories");
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
isnot(data[i].path, '/', "Subdirectory path should be called with the leafname");
isnot(data[i].path, dir.path, "Subdirectory path should contain the parent path.");
is(data[i].path,dir.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
}
}
}
);
var tests = [
function() { test_basic(directory, next); },
function() { test_getFilesAndDirectories(directory, true, next); },
function() { test_getFiles(directory, false, next); },
function() { test_getFiles(directory, true, next); },
];
function next() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
var directory;
onmessage = function(e) {
var directory = e.data;
ok(directory instanceof Directory, "This is a directory.");
directory.getFilesAndDirectories().then(
function(data) {
ok(data.length, "We should have some data.");
var promises = [];
for (var i = 0; i < data.length; ++i) {
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories");
if (data[i] instanceof Directory) {
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
is(data[i].path, '/' + data[i].name, "Subdirectory path should be called '/' + leafname");
promises.push(checkSubDir(data[i]));
}
}
return Promise.all(promises);
},
function() {
ok(false, "Something when wrong");
}
).then(finish);
directory = e.data;
next();
}

View File

@ -114,6 +114,9 @@ partial interface Directory {
*/
[Throws]
Promise<sequence<(File or Directory)>> getFilesAndDirectories();
[Throws]
Promise<sequence<File>> getFiles(optional boolean recursiveFlag = false);
};
enum CreateIfExistsMode { "replace", "fail" };