Commit 470a8703 authored by mtomasz@chromium.org's avatar mtomasz@chromium.org

[fsp] Add support for opening files.

This patch adds support to opening a file. It is currently no-op, and it is
not yet bound to fileapi.

In order to bound it to fileapi::AsyncFileUtil, we need to implement closing
operation, and reading operations first. Otherwise, creating a snapshot
(required by fileapi::AsyncFileUtil) is not possible.

TEST=unit_tests: *FileSystemProvider*OpenFile*
BUG=248427

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270040 0039d316-1c4b-4281-b951-d872f2087c98
parent d7f04496
......@@ -149,4 +149,24 @@ FileSystemProviderInternalReadDirectoryRequestedErrorFunction::RunWhenValid() {
return true;
}
bool
FileSystemProviderInternalOpenFileRequestedSuccessFunction::RunWhenValid() {
using api::file_system_provider_internal::OpenFileRequestedSuccess::Params;
scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
FulfillRequest(scoped_ptr<RequestValue>(new RequestValue()),
false /* has_more */);
return true;
}
bool FileSystemProviderInternalOpenFileRequestedErrorFunction::RunWhenValid() {
using api::file_system_provider_internal::OpenFileRequestedError::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
RejectRequest(ProviderErrorToFileError(params->error));
return true;
}
} // namespace extensions
......@@ -102,6 +102,30 @@ class FileSystemProviderInternalReadDirectoryRequestedErrorFunction
virtual bool RunWhenValid() OVERRIDE;
};
class FileSystemProviderInternalOpenFileRequestedSuccessFunction
: public FileSystemProviderInternalFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"fileSystemProviderInternal.openFileRequestedSuccess",
FILESYSTEMPROVIDERINTERNAL_OPENFILEREQUESTEDSUCCESS)
protected:
virtual ~FileSystemProviderInternalOpenFileRequestedSuccessFunction() {}
virtual bool RunWhenValid() OVERRIDE;
};
class FileSystemProviderInternalOpenFileRequestedErrorFunction
: public FileSystemProviderInternalFunction {
public:
DECLARE_EXTENSION_FUNCTION(
"fileSystemProviderInternal.openFileRequestedError",
FILESYSTEMPROVIDERINTERNAL_OPENFILEREQUESTEDERROR)
protected:
virtual ~FileSystemProviderInternalOpenFileRequestedErrorFunction() {}
virtual bool RunWhenValid() OVERRIDE;
};
} // namespace extensions
#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_SYSTEM_PROVIDER_FILE_SYSTEM_PROVIDER_API_H_
......@@ -118,6 +118,20 @@ void FakeProvidedFileSystem::ReadDirectory(
}
}
void FakeProvidedFileSystem::OpenFile(
const base::FilePath& file_path,
OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback) {
if (file_path.AsUTF8Unsafe() != "/hello.txt" ||
mode == OPEN_FILE_MODE_WRITE || create) {
callback.Run(base::File::FILE_ERROR_SECURITY);
return;
}
callback.Run(base::File::FILE_OK);
}
const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
const {
return file_system_info_;
......
......@@ -34,6 +34,11 @@ class FakeProvidedFileSystem : public ProvidedFileSystemInterface {
virtual void ReadDirectory(
const base::FilePath& directory_path,
const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) OVERRIDE;
virtual void OpenFile(
const base::FilePath& file_path,
OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const OVERRIDE;
virtual RequestManager* GetRequestManager() OVERRIDE;
......
// 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/open_file.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 {
OpenFile::OpenFile(extensions::EventRouter* event_router,
const ProvidedFileSystemInfo& file_system_info,
const base::FilePath& file_path,
ProvidedFileSystemInterface::OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback)
: Operation(event_router, file_system_info),
file_path_(file_path),
mode_(mode),
create_(create),
callback_(callback) {
}
OpenFile::~OpenFile() {
}
bool OpenFile::Execute(int request_id) {
scoped_ptr<base::ListValue> values(new base::ListValue);
values->AppendString(file_path_.AsUTF8Unsafe());
switch (mode_) {
case ProvidedFileSystemInterface::OPEN_FILE_MODE_READ:
values->AppendString(extensions::api::file_system_provider::ToString(
extensions::api::file_system_provider::OPEN_FILE_MODE_READ));
break;
case ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE:
values->AppendString(extensions::api::file_system_provider::ToString(
extensions::api::file_system_provider::OPEN_FILE_MODE_WRITE));
break;
}
values->AppendBoolean(create_);
return SendEvent(
request_id,
extensions::api::file_system_provider::OnOpenFileRequested::kEventName,
values.Pass());
}
void OpenFile::OnSuccess(int /* request_id */,
scoped_ptr<RequestValue> result,
bool has_next) {
callback_.Run(base::File::FILE_OK);
}
void OpenFile::OnError(int /* request_id */, 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_OPEN_FILE_H_
#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_OPEN_FILE_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 {
// Opens a file for either read or write, with optionally creating the file
// first. Note, that this is part of fileapi::CreateOrOpen file, but it does
// not download the file locally. Created per request.
class OpenFile : public Operation {
public:
OpenFile(extensions::EventRouter* event_router,
const ProvidedFileSystemInfo& file_system_info,
const base::FilePath& file_path,
ProvidedFileSystemInterface::OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback);
virtual ~OpenFile();
// Operation overrides.
virtual bool Execute(int request_id) OVERRIDE;
virtual void OnSuccess(int request_id,
scoped_ptr<RequestValue> result,
bool has_next) OVERRIDE;
virtual void OnError(int request_id, base::File::Error error) OVERRIDE;
private:
base::FilePath file_path_;
ProvidedFileSystemInterface::OpenFileMode mode_;
bool create_;
const fileapi::AsyncFileUtil::StatusCallback callback_;
DISALLOW_COPY_AND_ASSIGN(OpenFile);
};
} // namespace operations
} // namespace file_system_provider
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OPERATIONS_OPEN_FILE_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/open_file.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 int kFileSystemId = 1;
const int kRequestId = 2;
const base::FilePath::CharType kFilePath[] = "/directory/blueberries.txt";
// Fake event dispatcher implementation with extra logging capability. Acts as
// a providing extension end-point.
class LoggingDispatchEventImpl {
public:
explicit LoggingDispatchEventImpl(bool dispatch_reply)
: dispatch_reply_(dispatch_reply) {}
virtual ~LoggingDispatchEventImpl() {}
bool OnDispatchEventImpl(scoped_ptr<extensions::Event> event) {
events_.push_back(event->DeepCopy());
return dispatch_reply_;
}
ScopedVector<extensions::Event>& events() { return events_; }
private:
ScopedVector<extensions::Event> events_;
bool dispatch_reply_;
DISALLOW_COPY_AND_ASSIGN(LoggingDispatchEventImpl);
};
// Callback invocation logger. Acts as a fileapi end-point.
class CallbackLogger {
public:
CallbackLogger() : weak_ptr_factory_(this) {}
virtual ~CallbackLogger() {}
void OnOpenFile(base::File::Error result) { events_.push_back(result); }
std::vector<base::File::Error>& events() { return events_; }
base::WeakPtr<CallbackLogger> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
std::vector<base::File::Error> events_;
base::WeakPtrFactory<CallbackLogger> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CallbackLogger);
};
} // namespace
class FileSystemProviderOperationsOpenFileTest : public testing::Test {
protected:
FileSystemProviderOperationsOpenFileTest() {}
virtual ~FileSystemProviderOperationsOpenFileTest() {}
virtual void SetUp() OVERRIDE {
file_system_info_ =
ProvidedFileSystemInfo(kExtensionId,
kFileSystemId,
"" /* file_system_name */,
base::FilePath() /* mount_path */);
}
ProvidedFileSystemInfo file_system_info_;
};
TEST_F(FileSystemProviderOperationsOpenFileTest, Execute) {
LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
CallbackLogger callback_logger;
OpenFile open_file(
NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
false /* create */,
base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
open_file.SetDispatchEventImplForTesting(
base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(open_file.Execute(kRequestId));
ASSERT_EQ(1u, dispatcher.events().size());
extensions::Event* event = dispatcher.events()[0];
EXPECT_EQ(
extensions::api::file_system_provider::OnOpenFileRequested::kEventName,
event->event_name);
base::ListValue* event_args = event->event_args.get();
ASSERT_EQ(5u, event_args->GetSize());
int event_file_system_id = -1;
EXPECT_TRUE(event_args->GetInteger(0, &event_file_system_id));
EXPECT_EQ(kFileSystemId, event_file_system_id);
int event_request_id = -1;
EXPECT_TRUE(event_args->GetInteger(1, &event_request_id));
EXPECT_EQ(kRequestId, event_request_id);
std::string event_file_path;
EXPECT_TRUE(event_args->GetString(2, &event_file_path));
EXPECT_EQ(kFilePath, event_file_path);
std::string event_file_open_mode;
EXPECT_TRUE(event_args->GetString(3, &event_file_open_mode));
const std::string expected_file_open_mode =
extensions::api::file_system_provider::ToString(
extensions::api::file_system_provider::OPEN_FILE_MODE_READ);
EXPECT_EQ(expected_file_open_mode, event_file_open_mode);
bool event_create;
EXPECT_TRUE(event_args->GetBoolean(4, &event_create));
EXPECT_FALSE(event_create);
}
TEST_F(FileSystemProviderOperationsOpenFileTest, Execute_NoListener) {
LoggingDispatchEventImpl dispatcher(false /* dispatch_reply */);
CallbackLogger callback_logger;
OpenFile open_file(
NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
false /* create */,
base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
open_file.SetDispatchEventImplForTesting(
base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_FALSE(open_file.Execute(kRequestId));
}
TEST_F(FileSystemProviderOperationsOpenFileTest, OnSuccess) {
using extensions::api::file_system_provider::EntryMetadata;
using extensions::api::file_system_provider_internal::
OpenFileRequestedSuccess::Params;
LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
CallbackLogger callback_logger;
OpenFile open_file(
NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
false /* create */,
base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
open_file.SetDispatchEventImplForTesting(
base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(open_file.Execute(kRequestId));
open_file.OnSuccess(kRequestId,
scoped_ptr<RequestValue>(new RequestValue()),
false /* has_next */);
ASSERT_EQ(1u, callback_logger.events().size());
EXPECT_EQ(base::File::FILE_OK, callback_logger.events()[0]);
}
TEST_F(FileSystemProviderOperationsOpenFileTest, OnError) {
using extensions::api::file_system_provider::EntryMetadata;
using extensions::api::file_system_provider_internal::OpenFileRequestedError::
Params;
LoggingDispatchEventImpl dispatcher(true /* dispatch_reply */);
CallbackLogger callback_logger;
OpenFile open_file(
NULL,
file_system_info_,
base::FilePath::FromUTF8Unsafe(kFilePath),
ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
false /* create */,
base::Bind(&CallbackLogger::OnOpenFile, callback_logger.GetWeakPtr()));
open_file.SetDispatchEventImplForTesting(
base::Bind(&LoggingDispatchEventImpl::OnDispatchEventImpl,
base::Unretained(&dispatcher)));
EXPECT_TRUE(open_file.Execute(kRequestId));
open_file.OnError(kRequestId, base::File::FILE_ERROR_TOO_MANY_OPENED);
ASSERT_EQ(1u, callback_logger.events().size());
EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED,
callback_logger.events()[0]);
}
} // namespace operations
} // namespace file_system_provider
} // namespace chromeos
......@@ -6,6 +6,7 @@
#include "base/files/file.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"
#include "chrome/browser/chromeos/file_system_provider/operations/unmount.h"
#include "chrome/browser/chromeos/file_system_provider/request_manager.h"
......@@ -29,9 +30,8 @@ ProvidedFileSystem::~ProvidedFileSystem() {}
void ProvidedFileSystem::RequestUnmount(
const fileapi::AsyncFileUtil::StatusCallback& callback) {
if (!request_manager_.CreateRequest(
make_scoped_ptr<RequestManager::HandlerInterface>(
new operations::Unmount(
event_router_, file_system_info_, callback)))) {
scoped_ptr<RequestManager::HandlerInterface>(new operations::Unmount(
event_router_, file_system_info_, callback)))) {
callback.Run(base::File::FILE_ERROR_SECURITY);
}
}
......@@ -40,7 +40,7 @@ void ProvidedFileSystem::GetMetadata(
const base::FilePath& entry_path,
const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) {
if (!request_manager_.CreateRequest(
make_scoped_ptr<RequestManager::HandlerInterface>(
scoped_ptr<RequestManager::HandlerInterface>(
new operations::GetMetadata(
event_router_, file_system_info_, entry_path, callback)))) {
callback.Run(base::File::FILE_ERROR_SECURITY, base::File::Info());
......@@ -50,7 +50,7 @@ void ProvidedFileSystem::GetMetadata(
void ProvidedFileSystem::ReadDirectory(
const base::FilePath& directory_path,
const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) {
if (!request_manager_.CreateRequest(make_scoped_ptr<
if (!request_manager_.CreateRequest(scoped_ptr<
RequestManager::HandlerInterface>(new operations::ReadDirectory(
event_router_, file_system_info_, directory_path, callback)))) {
callback.Run(base::File::FILE_ERROR_SECURITY,
......@@ -59,6 +59,30 @@ void ProvidedFileSystem::ReadDirectory(
}
}
void ProvidedFileSystem::OpenFile(
const base::FilePath& file_path,
OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback) {
// Writing is not supported. Note, that this includes a situation, when a file
// exists, but |create| is set to true.
if (mode == OPEN_FILE_MODE_WRITE || create) {
callback.Run(base::File::FILE_ERROR_SECURITY);
return;
}
if (!request_manager_.CreateRequest(
scoped_ptr<RequestManager::HandlerInterface>(
new operations::OpenFile(event_router_,
file_system_info_,
file_path,
mode,
create,
callback)))) {
callback.Run(base::File::FILE_ERROR_SECURITY);
}
}
const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
return file_system_info_;
}
......
......@@ -38,6 +38,11 @@ class ProvidedFileSystem : public ProvidedFileSystemInterface {
virtual void ReadDirectory(
const base::FilePath& directory_path,
const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) OVERRIDE;
virtual void OpenFile(
const base::FilePath& file_path,
OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback) OVERRIDE;
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const OVERRIDE;
virtual RequestManager* GetRequestManager() OVERRIDE;
......
......@@ -24,6 +24,9 @@ class RequestManager;
// TODO(mtomasz): Add more methods once implemented.
class ProvidedFileSystemInterface {
public:
// Mode of opening a file. Used by OpenFile().
enum OpenFileMode { OPEN_FILE_MODE_READ, OPEN_FILE_MODE_WRITE };
virtual ~ProvidedFileSystemInterface() {}
// Requests unmounting of the file system. The callback is called when the
......@@ -43,6 +46,14 @@ class ProvidedFileSystemInterface {
const base::FilePath& directory_path,
const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) = 0;
// Requests opening a file at |file_path|. If |create| is set to true, it will
// create a file and return succes in case it didn't exist.
virtual void OpenFile(
const base::FilePath& file_path,
OpenFileMode mode,
bool create,
const fileapi::AsyncFileUtil::StatusCallback& callback) = 0;
// Returns a provided file system info for this file system.
virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const = 0;
......
......@@ -382,6 +382,8 @@
'browser/chromeos/file_system_provider/observer.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',
'browser/chromeos/file_system_provider/operations/open_file.h',
'browser/chromeos/file_system_provider/operations/operation.cc',
'browser/chromeos/file_system_provider/operations/operation.h',
'browser/chromeos/file_system_provider/operations/read_directory.cc',
......
......@@ -711,6 +711,7 @@
'browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc',
'browser/chromeos/file_system_provider/mount_path_util_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',
'browser/chromeos/file_system_provider/provided_file_system_unittest.cc',
'browser/chromeos/file_system_provider/request_manager_unittest.cc',
......
......@@ -29,6 +29,12 @@ namespace fileSystemProvider {
IO
};
// Mode of opening a file. Used by <code>onOpenFileRequested</code>.
enum OpenFileMode {
READ,
WRITE
};
// Represents metadata of a file or a directory.
dictionary EntryMetadata {
// True if it is a directory.
......@@ -116,7 +122,7 @@ namespace fileSystemProvider {
long fileSystemId,
DOMString entryPath,
MetadataCallback successCallback,
ErrorCallback errorCallback);
ProviderErrorCallback errorCallback);
// Raised when contents of a directory at <code>directoryPath</code> are
// requested. The results should be returned in chunks by calling the <code>
......@@ -126,7 +132,18 @@ namespace fileSystemProvider {
long fileSystemId,
DOMString directoryPath,
EntriesCallback successCallback,
ErrorCallback errorCallback);
ProviderErrorCallback errorCallback);
// Raised when opening a file at <code>filePath</code> is requested.
// If <code>create</code> is set to <code>true</code> and the file does not
// exist, then it should be created.
[maxListeners=1] static void onOpenFileRequested(
long fileSystemId,
DOMString filePath,
OpenFileMode mode,
boolean create,
ProviderSuccessCallback successCallback,
ProviderErrorCallback errorCallback);
};
};
......@@ -48,6 +48,19 @@ namespace fileSystemProviderInternal {
long fileSystemId,
long requestId,
fileSystemProvider.ProviderError error);
// Internal. Success callback of the <code>onOpenFileRequested</code> event.
// Must be called, when opening succeeds.
static void openFileRequestedSuccess(
long fileSystemId,
long requestId);
// Internal. Error callback of the <code>onOpenFileRequested</code> event.
// Must be called when opening fails.
static void openFileRequestedError(
long fileSystemId,
long requestId,
fileSystemProvider.ProviderError error);
};
};
......@@ -161,4 +161,24 @@ eventBindings.registerArgumentMassager(
fileSystemId, directoryPath, onSuccessCallback, onErrorCallback]);
});
eventBindings.registerArgumentMassager(
'fileSystemProvider.onOpenFileRequested',
function(args, dispatch) {
var fileSystemId = args[0];
var requestId = args[1];
var filePath = args[2];
var mode = args[3];
var create = args[4];
var onSuccessCallback = function() {
fileSystemProviderInternal.openFileRequestedSuccess(
fileSystemId, requestId);
};
var onErrorCallback = function(error) {
fileSystemProviderInternal.openFileRequestedError(
fileSystemId, requestId, error);
}
dispatch([fileSystemId, filePath, mode, create, onSuccessCallback,
onErrorCallback]);
});
exports.binding = binding.generate();
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