Commit e6abea11 authored by mtomasz@chromium.org's avatar mtomasz@chromium.org

[fsp] Add support for deleting entries.

This CL adds support for deleting files and directories, including recursively.
The new event in IDL has [nodoc], since we don't want to show it on
developer.chrome.com before most of the R/W features are done.

TBR=kalman@chromium.org
TEST=unit_tests, browser_tests: *FileSystemProvider*DeleteEntry*
BUG=391362

Review URL: https://codereview.chromium.org/375543002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282605 0039d316-1c4b-4281-b951-d872f2087c98
parent f96c0e81
......@@ -80,4 +80,10 @@ IN_PROC_BROWSER_TEST_F(FileSystemProviderApiTest, CreateDirectory) {
<< message_;
}
IN_PROC_BROWSER_TEST_F(FileSystemProviderApiTest, DeleteEntry) {
ASSERT_TRUE(RunPlatformAppTestWithFlags("file_system_provider/delete_entry",
kFlagLoadAsComponent))
<< message_;
}
} // namespace extensions
......@@ -236,6 +236,14 @@ void FakeProvidedFileSystem::CreateDirectory(
FROM_HERE, base::Bind(callback, base::File::FILE_OK));
}
void FakeProvidedFileSystem::DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE, base::Bind(callback, base::File::FILE_OK));
}
const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
const {
return file_system_info_;
......
......@@ -62,6 +62,10 @@ class FakeProvidedFileSystem : public ProvidedFileSystemInterface {
bool exclusive,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual void DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const OVERRIDE;
virtual RequestManager* GetRequestManager() OVERRIDE;
virtual base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() OVERRIDE;
......
......@@ -107,6 +107,28 @@ void OnCreateDirectory(const fileapi::AsyncFileUtil::StatusCallback& callback,
BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
}
// Executes DeleteEntry on the UI thread.
void DeleteEntryOnUIThread(
scoped_ptr<fileapi::FileSystemOperationContext> context,
const fileapi::FileSystemURL& url,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) {
util::FileSystemURLParser parser(url);
if (!parser.Parse()) {
callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
return;
}
parser.file_system()->DeleteEntry(parser.file_path(), recursive, callback);
}
// Routes the response of DeleteEntry back to the IO thread.
void OnDeleteEntry(const fileapi::AsyncFileUtil::StatusCallback& callback,
base::File::Error result) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
}
} // namespace
ProviderAsyncFileUtil::ProviderAsyncFileUtil() {}
......@@ -238,7 +260,13 @@ void ProviderAsyncFileUtil::DeleteFile(
const fileapi::FileSystemURL& url,
const StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&DeleteEntryOnUIThread,
base::Passed(&context),
url,
false, // recursive
base::Bind(&OnDeleteEntry, callback)));
}
void ProviderAsyncFileUtil::DeleteDirectory(
......@@ -246,7 +274,13 @@ void ProviderAsyncFileUtil::DeleteDirectory(
const fileapi::FileSystemURL& url,
const StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&DeleteEntryOnUIThread,
base::Passed(&context),
url,
false, // recursive
base::Bind(&OnDeleteEntry, callback)));
}
void ProviderAsyncFileUtil::DeleteRecursively(
......@@ -254,7 +288,13 @@ void ProviderAsyncFileUtil::DeleteRecursively(
const fileapi::FileSystemURL& url,
const StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&DeleteEntryOnUIThread,
base::Passed(&context),
url,
true, // recursive
base::Bind(&OnDeleteEntry, callback)));
}
void ProviderAsyncFileUtil::CreateSnapshotFile(
......
......@@ -377,9 +377,10 @@ TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteFile) {
CreateOperationContext(),
file_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(logger.result());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.result());
EXPECT_EQ(base::File::FILE_OK, *logger.result());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteDirectory) {
......@@ -389,9 +390,10 @@ TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteDirectory) {
CreateOperationContext(),
directory_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(logger.result());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.result());
EXPECT_EQ(base::File::FILE_OK, *logger.result());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteRecursively) {
......@@ -401,9 +403,10 @@ TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteRecursively) {
CreateOperationContext(),
directory_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(logger.result());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.result());
EXPECT_EQ(base::File::FILE_OK, *logger.result());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateSnapshotFile) {
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h"
#include <string>
#include "chrome/common/extensions/api/file_system_provider.h"
#include "chrome/common/extensions/api/file_system_provider_internal.h"
namespace chromeos {
namespace file_system_provider {
namespace operations {
DeleteEntry::DeleteEntry(extensions::EventRouter* event_router,
const ProvidedFileSystemInfo& file_system_info,
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback)
: Operation(event_router, file_system_info),
entry_path_(entry_path),
recursive_(recursive),
callback_(callback) {
}
DeleteEntry::~DeleteEntry() {
}
bool DeleteEntry::Execute(int request_id) {
scoped_ptr<base::DictionaryValue> values(new base::DictionaryValue);
values->SetString("entryPath", entry_path_.AsUTF8Unsafe());
values->SetBoolean("recursive", recursive_);
return SendEvent(
request_id,
extensions::api::file_system_provider::OnDeleteEntryRequested::kEventName,
values.Pass());
}
void DeleteEntry::OnSuccess(int /* request_id */,
scoped_ptr<RequestValue> /* result */,
bool has_more) {
callback_.Run(base::File::FILE_OK);
}
void DeleteEntry::OnError(int /* request_id */,
scoped_ptr<RequestValue> /* result */,
base::File::Error error) {
callback_.Run(error);
}
} // namespace operations
} // namespace file_system_provider
} // namespace chromeos
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_DELETE_ENTRY_H_
#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_DELETE_ENTRY_H_
#include "base/files/file.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/file_system_provider/operations/operation.h"
#include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
#include "chrome/browser/chromeos/file_system_provider/request_value.h"
#include "webkit/browser/fileapi/async_file_util.h"
namespace base {
class FilePath;
} // namespace base
namespace extensions {
class EventRouter;
} // namespace extensions
namespace chromeos {
namespace file_system_provider {
namespace operations {
// Deletes an entry. If |recursive| is passed and the entry is a directory, then
// all contents of it (recursively) will be deleted too. Created per request.
class DeleteEntry : public Operation {
public:
DeleteEntry(extensions::EventRouter* event_router,
const ProvidedFileSystemInfo& file_system_info,
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback);
virtual ~DeleteEntry();
// Operation overrides.
virtual bool Execute(int request_id) OVERRIDE;
virtual void OnSuccess(int request_id,
scoped_ptr<RequestValue> result,
bool has_more) OVERRIDE;
virtual void OnError(int request_id,
scoped_ptr<RequestValue> result,
base::File::Error error) OVERRIDE;
private:
base::FilePath entry_path_;
ProvidedFileSystemInterface::OpenFileMode mode_;
bool recursive_;
const fileapi::AsyncFileUtil::StatusCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteEntry);
};
} // namespace operations
} // namespace file_system_provider
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_DELETE_ENTRY_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <vector>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h"
#include "chrome/browser/chromeos/file_system_provider/operations/test_util.h"
#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
#include "chrome/common/extensions/api/file_system_provider.h"
#include "chrome/common/extensions/api/file_system_provider_internal.h"
#include "extensions/browser/event_router.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/browser/fileapi/async_file_util.h"
namespace chromeos {
namespace file_system_provider {
namespace operations {
namespace {
const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
const char kFileSystemId[] = "testing-file-system";
const int kRequestId = 2;
const base::FilePath::CharType kEntryPath[] = "/kitty/and/puppy/happy";
} // namespace
class FileSystemProviderOperationsDeleteEntryTest : public testing::Test {
protected:
FileSystemProviderOperationsDeleteEntryTest() {}
virtual ~FileSystemProviderOperationsDeleteEntryTest() {}
virtual void SetUp() OVERRIDE {
file_system_info_ =
ProvidedFileSystemInfo(kExtensionId,
kFileSystemId,
"" /* file_system_name */,
base::FilePath() /* mount_path */);
}
ProvidedFileSystemInfo file_system_info_;
};
TEST_F(FileSystemProviderOperationsDeleteEntryTest, Execute) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
DeleteEntry delete_entry(NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kEntryPath),
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
delete_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(delete_entry.Execute(kRequestId));
ASSERT_EQ(1u, dispatcher.events().size());
extensions::Event* event = dispatcher.events()[0];
EXPECT_EQ(
extensions::api::file_system_provider::OnDeleteEntryRequested::kEventName,
event->event_name);
base::ListValue* event_args = event->event_args.get();
ASSERT_EQ(1u, event_args->GetSize());
base::DictionaryValue* options = NULL;
ASSERT_TRUE(event_args->GetDictionary(0, &options));
std::string event_file_system_id;
EXPECT_TRUE(options->GetString("fileSystemId", &event_file_system_id));
EXPECT_EQ(kFileSystemId, event_file_system_id);
int event_request_id = -1;
EXPECT_TRUE(options->GetInteger("requestId", &event_request_id));
EXPECT_EQ(kRequestId, event_request_id);
std::string event_entry_path;
EXPECT_TRUE(options->GetString("entryPath", &event_entry_path));
EXPECT_EQ(kEntryPath, event_entry_path);
bool event_recursive;
EXPECT_TRUE(options->GetBoolean("recursive", &event_recursive));
EXPECT_TRUE(event_recursive);
}
TEST_F(FileSystemProviderOperationsDeleteEntryTest, Execute_NoListener) {
util::LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
util::StatusCallbackLog callback_log;
DeleteEntry delete_entry(NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kEntryPath),
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
delete_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(delete_entry.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsDeleteEntryTest, OnSuccess) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
DeleteEntry delete_entry(NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kEntryPath),
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
delete_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(delete_entry.Execute(kRequestId));
delete_entry.OnSuccess(kRequestId,
scoped_ptr<RequestValue>(new RequestValue()),
false /* has_more */);
ASSERT_EQ(1u, callback_log.size());
EXPECT_EQ(base::File::FILE_OK, callback_log[0]);
}
TEST_F(FileSystemProviderOperationsDeleteEntryTest, OnError) {
util::LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
util::StatusCallbackLog callback_log;
DeleteEntry delete_entry(NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kEntryPath),
true /* recursive */,
base::Bind(&util::LogStatusCallback, &callback_log));
delete_entry.SetDispatchEventImplForTesting(
base::Bind(&util::LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(delete_entry.Execute(kRequestId));
delete_entry.OnError(kRequestId,
scoped_ptr<RequestValue>(new RequestValue()),
base::File::FILE_ERROR_TOO_MANY_OPENED);
ASSERT_EQ(1u, callback_log.size());
EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, callback_log[0]);
}
} // namespace operations
} // namespace file_system_provider
} // namespace chromeos
......@@ -9,6 +9,7 @@
#include "chrome/browser/chromeos/file_system_provider/notification_manager.h"
#include "chrome/browser/chromeos/file_system_provider/operations/close_file.h"
#include "chrome/browser/chromeos/file_system_provider/operations/create_directory.h"
#include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h"
#include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h"
#include "chrome/browser/chromeos/file_system_provider/operations/open_file.h"
#include "chrome/browser/chromeos/file_system_provider/operations/read_directory.h"
......@@ -149,6 +150,22 @@ void ProvidedFileSystem::CreateDirectory(
}
}
void ProvidedFileSystem::DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) {
if (!request_manager_.CreateRequest(
DELETE_ENTRY,
scoped_ptr<RequestManager::HandlerInterface>(
new operations::DeleteEntry(event_router_,
file_system_info_,
entry_path,
recursive,
callback)))) {
callback.Run(base::File::FILE_ERROR_SECURITY);
}
}
const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
return file_system_info_;
}
......
......@@ -62,6 +62,10 @@ class ProvidedFileSystem : public ProvidedFileSystemInterface {
bool exclusive,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual void DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const OVERRIDE;
virtual RequestManager* GetRequestManager() OVERRIDE;
virtual base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() OVERRIDE;
......
......@@ -109,6 +109,13 @@ class ProvidedFileSystemInterface {
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) = 0;
// Requests deleting a directory. If |recursive| is passed and the entry is
// a directory, then all contents of it (recursively) will be deleted too.
virtual void DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
const fileapi::AsyncFileUtil::StatusCallback& callback) = 0;
// Returns a provided file system info for this file system.
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const = 0;
......
......@@ -34,6 +34,8 @@ std::string RequestTypeToString(RequestType type) {
return "READ_FILE";
case CREATE_DIRECTORY:
return "CREATE_DIRECTORY";
case DELETE_ENTRY:
return "DELETE_ENTRY";
case TESTING:
return "TESTING";
}
......
......@@ -31,6 +31,7 @@ enum RequestType {
CLOSE_FILE,
READ_FILE,
CREATE_DIRECTORY,
DELETE_ENTRY,
TESTING
};
......
......@@ -396,6 +396,8 @@
'browser/chromeos/file_system_provider/operations/close_file.h',
'browser/chromeos/file_system_provider/operations/create_directory.cc',
'browser/chromeos/file_system_provider/operations/create_directory.h',
'browser/chromeos/file_system_provider/operations/delete_entry.cc',
'browser/chromeos/file_system_provider/operations/delete_entry.h',
'browser/chromeos/file_system_provider/operations/get_metadata.cc',
'browser/chromeos/file_system_provider/operations/get_metadata.h',
'browser/chromeos/file_system_provider/operations/open_file.cc',
......
......@@ -746,6 +746,7 @@
'browser/chromeos/file_system_provider/operations/test_util.h',
'browser/chromeos/file_system_provider/operations/close_file_unittest.cc',
'browser/chromeos/file_system_provider/operations/create_directory_unittest.cc',
'browser/chromeos/file_system_provider/operations/delete_entry_unittest.cc',
'browser/chromeos/file_system_provider/operations/get_metadata_unittest.cc',
'browser/chromeos/file_system_provider/operations/open_file_unittest.cc',
'browser/chromeos/file_system_provider/operations/read_directory_unittest.cc',
......
......@@ -117,6 +117,14 @@ namespace fileSystemProvider {
boolean recursive;
};
// Options for the <code>onDeleteEntryRequested()</code> event.
dictionary DeleteEntryRequestedOptions {
DOMString fileSystemId;
long requestId;
DOMString entryPath;
boolean recursive;
};
// Callback to receive the result of mount() function.
callback MountCallback = void([nodoc, instanceOf=DOMError] object error);
......@@ -227,13 +235,21 @@ namespace fileSystemProvider {
ProviderErrorCallback errorCallback);
// Raised when creating a directory is requested. If <code>exclusive</code>
// is set to true, then the operation should fail if the target directory
// is set to true, then the operation must fail if the target directory
// already exists. If <code>recursive</code> is true, then all of the
// missing directories on the directory path should be created.
// missing directories on the directory path must be created.
[maxListeners=1, nodoc] static void onCreateDirectoryRequested(
CreateDirectoryRequestedOptions options,
ProviderSuccessCallback successCallback,
ProviderErrorCallback errorCallback);
// Raised when deleting an entry is requested. If <code>recursive</code> is
// true, and the entry is a directory, then all of the entries inside
// must be recursively deleted as well.
[maxListeners=1, nodoc] static void onDeleteEntryRequested(
DeleteEntryRequestedOptions options,
ProviderSuccessCallback successCallback,
ProviderErrorCallback errorCallback);
};
};
......@@ -204,4 +204,8 @@ eventBindings.registerArgumentMassager(
'fileSystemProvider.onCreateDirectoryRequested',
massageArgumentsDefault);
eventBindings.registerArgumentMassager(
'fileSystemProvider.onDeleteEntryRequested',
massageArgumentsDefault);
exports.binding = binding.generate();
{
"key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDOuXEIuoK1kAkBe0SKiJn/N9oNn3oUxGa4dwj40MnJqPn+w0aR2vuyocm0R4Drp67aYwtLjOVPF4CICRq6ICP6eU07gGwQxGdZ7HJASXV8hm0tab5I70oJmRLfFJyVAMCeWlFaOGq05v2i6EbifZM0qO5xALKNGQt+yjXi5INM5wIBIw==",
"name": "chrome.fileSystemProvider.onDeleteEntryRequested",
"version": "0.1",
"manifest_version": 2,
"description":
"Test for chrome.fileSystemProvider.onDeleteEntryRequested().",
"permissions": [
"fileSystemProvider",
"fileBrowserPrivate",
"fileBrowserHandler"
],
"app": {
"background": {
"scripts": [
"chrome-extension://gfnblenhaahcnmfdbebgincjohfkbnch/test_util.js",
"test.js"
]
}
}
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* @type {Object}
* @const
*/
var TESTING_A_DIRECTORY = Object.freeze({
isDirectory: true,
name: 'a',
size: 0,
modificationTime: new Date(2014, 4, 28, 10, 39, 15)
});
/**
* @type {Object}
* @const
*/
var TESTING_B_DIRECTORY = Object.freeze({
isDirectory: true,
name: 'b',
size: 0,
modificationTime: new Date(2014, 4, 28, 10, 39, 15)
});
/**
* @type {Object}
* @const
*/
var TESTING_C_FILE = Object.freeze({
isDirectory: false,
name: 'c',
size: 0,
modificationTime: new Date(2014, 4, 28, 10, 39, 15)
});
/**
* Deletes an entry.
*
* @param {DeleteEntryRequestedOptions} options Options.
* @param {function(Object)} onSuccess Success callback
* @param {function(string)} onError Error callback with an error code.
*/
function onDeleteEntryRequested(options, onSuccess, onError) {
if (options.fileSystemId != test_util.FILE_SYSTEM_ID) {
onError('SECURITY'); // enum ProviderError.
return;
}
if (options.entryPath == '/') {
onError('INVALID_OPERATION');
return;
}
if (options.entryPath == '/' + TESTING_A_DIRECTORY.name) {
if (options.recursive)
onSuccess();
else
onError('INVALID_OPERATION');
return;
}
if (options.entryPath == '/' + TESTING_C_FILE.name ||
options.entryPath == '/' + TESTING_A_DIRECTORY.name + '/' +
TESTING_B_DIRECTORY.name) {
onSuccess();
return;
}
onError('NOT_FOUND'); // enum ProviderError.
}
/**
* Sets up the tests. Called once per all test cases. In case of a failure,
* the callback is not called.
*
* @param {function()} callback Success callback.
*/
function setUp(callback) {
chrome.fileSystemProvider.onGetMetadataRequested.addListener(
test_util.onGetMetadataRequestedDefault);
test_util.defaultMetadata['/' + TESTING_A_DIRECTORY.name] =
TESTING_A_DIRECTORY;
test_util.defaultMetadata['/' + TESTING_A_DIRECTORY.name + '/' +
TESTING_B_DIRECTORY.name] = TESTING_B_DIRECTORY;
test_util.defaultMetadata['/' + TESTING_C_FILE.name] =
TESTING_C_FILE;
chrome.fileSystemProvider.onDeleteEntryRequested.addListener(
onDeleteEntryRequested);
test_util.mountFileSystem(callback);
}
/**
* Runs all of the test cases, one by one.
*/
function runTests() {
chrome.test.runTests([
// Delete a file. Should succeed.
function deleteDirectorySuccessSimple() {
var onSuccess = chrome.test.callbackPass();
test_util.fileSystem.root.getFile(
TESTING_C_FILE.name, {create: false},
function(entry) {
chrome.test.assertEq(TESTING_C_FILE.name, entry.name);
chrome.test.assertFalse(entry.isDirectory);
entry.remove(onSuccess, function(error) {
chrome.test.fail(error.name);
});
}, function(error) {
chrome.test.fail(error.name);
});
},
// Delete a directory which has contents, non-recursively. Should fail.
function deleteDirectoryErrorNotEmpty() {
var onSuccess = chrome.test.callbackPass();
test_util.fileSystem.root.getDirectory(
TESTING_A_DIRECTORY.name, {create: false},
function(entry) {
chrome.test.assertEq(TESTING_A_DIRECTORY.name, entry.name);
chrome.test.assertTrue(entry.isDirectory);
entry.remove(function() {
chrome.test.fail('Unexpectedly succeded to remove a directory.');
}, onSuccess);
}, function(error) {
chrome.test.fail(error.name);
});
},
// Delete a directory which has contents, recursively. Should succeed.
function deleteDirectoryRecursively() {
var onSuccess = chrome.test.callbackPass();
test_util.fileSystem.root.getDirectory(
TESTING_A_DIRECTORY.name, {create: false},
function(entry) {
chrome.test.assertEq(TESTING_A_DIRECTORY.name, entry.name);
chrome.test.assertTrue(entry.isDirectory);
entry.removeRecursively(onSuccess, function(error) {
chrome.test.fail(error);
});
}, function(error) {
chrome.test.fail(error.name);
});
}
]);
}
// Setup and run all of the test cases.
setUp(runTests);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment