Commit 422f32b9 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

[FileSystem] Implement getEntries() and ability to create new files and directories.

This takes a somewhat hacky approach to return an async iterator from
getEntries(), but at least it makes for await work on it.

Also adds create option to getFile and getDirectory to be able to create
new entries.

Bug: 872465
Change-Id: I297c89c917bc86dfc2b3bbcf2d501ff5e59a85d7
Reviewed-on: https://chromium-review.googlesource.com/1197904
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590438}
parent cd3c168d
......@@ -49,6 +49,8 @@ blink_modules_sources("filesystem") {
"file_system_client.h",
"file_system_directory_handle.cc",
"file_system_directory_handle.h",
"file_system_directory_iterator.cc",
"file_system_directory_iterator.h",
"file_system_file_handle.cc",
"file_system_file_handle.h",
"file_system_writer.cc",
......
......@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system_base.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.h"
#include "third_party/blink/renderer/modules/filesystem/local_file_system.h"
namespace blink {
......@@ -16,23 +17,30 @@ FileSystemDirectoryHandle::FileSystemDirectoryHandle(
const String& full_path)
: FileSystemBaseHandle(file_system, full_path) {}
ScriptPromise FileSystemDirectoryHandle::getFile(ScriptState* script_state,
const String& name) {
ScriptPromise FileSystemDirectoryHandle::getFile(
ScriptState* script_state,
const String& name,
const FileSystemGetFileOptions& options) {
FileSystemFlags flags;
flags.setCreateFlag(options.create());
auto* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise result = resolver->Promise();
filesystem()->GetFile(this, name, FileSystemFlags(),
filesystem()->GetFile(this, name, flags,
new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
new PromiseErrorCallback(resolver));
return result;
}
ScriptPromise FileSystemDirectoryHandle::getDirectory(ScriptState* script_state,
const String& name) {
ScriptPromise FileSystemDirectoryHandle::getDirectory(
ScriptState* script_state,
const String& name,
const FileSystemGetDirectoryOptions& options) {
FileSystemFlags flags;
flags.setCreateFlag(options.create());
auto* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise result = resolver->Promise();
filesystem()->GetDirectory(
this, name, FileSystemFlags(),
new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
this, name, flags, new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
new PromiseErrorCallback(resolver));
return result;
}
......@@ -55,4 +63,28 @@ ScriptPromise FileSystemDirectoryHandle::getSystemDirectory(
return result;
}
namespace {
void ReturnDataFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
V8SetReturnValue(info, info.Data());
}
} // namespace
ScriptValue FileSystemDirectoryHandle::getEntries(ScriptState* script_state) {
auto* iterator = new FileSystemDirectoryIterator(filesystem(), fullPath());
auto* isolate = script_state->GetIsolate();
auto context = script_state->GetContext();
v8::Local<v8::Object> result = v8::Object::New(isolate);
if (!result
->Set(context, v8::Symbol::GetAsyncIterator(isolate),
v8::Function::New(context, &ReturnDataFunction,
ToV8(iterator, script_state))
.ToLocalChecked())
.FromMaybe(false)) {
return ScriptValue();
}
return ScriptValue(script_state, result);
}
} // namespace blink
......@@ -5,7 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_HANDLE_H_
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_base_handle.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_get_directory_options.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_get_file_options.h"
#include "third_party/blink/renderer/modules/filesystem/get_system_directory_options.h"
namespace blink {
......@@ -17,8 +20,13 @@ class FileSystemDirectoryHandle : public FileSystemBaseHandle {
FileSystemDirectoryHandle(DOMFileSystemBase*, const String& full_path);
bool isDirectory() const override { return true; }
ScriptPromise getFile(ScriptState*, const String& name);
ScriptPromise getDirectory(ScriptState*, const String& name);
ScriptPromise getFile(ScriptState*,
const String& name,
const FileSystemGetFileOptions&);
ScriptPromise getDirectory(ScriptState*,
const String& name,
const FileSystemGetDirectoryOptions&);
ScriptValue getEntries(ScriptState*);
static ScriptPromise getSystemDirectory(
ScriptState*,
......
......@@ -6,9 +6,9 @@
[
RuntimeEnabled=WritableFiles
] interface FileSystemDirectoryHandle : FileSystemBaseHandle {
[CallWith=ScriptState] Promise<FileSystemFileHandle> getFile(USVString name);
[CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectory(USVString name);
// TODO(mek): Other methods such as getEntries etc.
[CallWith=ScriptState] Promise<FileSystemFileHandle> getFile(USVString name, optional FileSystemGetFileOptions options);
[CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectory(USVString name, optional FileSystemGetDirectoryOptions options);
[CallWith=ScriptState] object getEntries();
[CallWith=ScriptState]
static Promise<FileSystemDirectoryHandle> getSystemDirectory(GetSystemDirectoryOptions options);
......
// Copyright 2018 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 "third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/filesystem/entry.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_base_handle.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_directory_iterator_entry.h"
namespace blink {
class FileSystemDirectoryIterator::EntriesCallbackHelper
: public EntriesCallbacks::OnDidGetEntriesCallback {
public:
explicit EntriesCallbackHelper(FileSystemDirectoryIterator* reader)
: reader_(reader) {}
void Trace(Visitor* visitor) override {
EntriesCallbacks::OnDidGetEntriesCallback::Trace(visitor);
visitor->Trace(reader_);
}
void OnSuccess(EntryHeapVector* entries) override {
reader_->AddEntries(*entries);
}
private:
// TODO(https://crbug.com/350285): This Member keeps the reader alive until
// all of the readDirectory results are received.
Member<FileSystemDirectoryIterator> reader_;
};
class FileSystemDirectoryIterator::ErrorCallbackHelper final
: public ErrorCallbackBase {
public:
explicit ErrorCallbackHelper(FileSystemDirectoryIterator* reader)
: reader_(reader) {}
void Invoke(FileError::ErrorCode error) override { reader_->OnError(error); }
void Trace(Visitor* visitor) override {
ErrorCallbackBase::Trace(visitor);
visitor->Trace(reader_);
}
private:
Member<FileSystemDirectoryIterator> reader_;
};
FileSystemDirectoryIterator::FileSystemDirectoryIterator(
DOMFileSystemBase* file_system,
const String& full_path)
: DirectoryReaderBase(file_system, full_path) {
Filesystem()->ReadDirectory(this, full_path_, new EntriesCallbackHelper(this),
new ErrorCallbackHelper(this));
}
ScriptPromise FileSystemDirectoryIterator::next(ScriptState* script_state) {
if (error_ != FileError::kOK) {
return ScriptPromise::RejectWithDOMException(
script_state, FileError::CreateDOMException(error_));
}
if (!entries_.IsEmpty()) {
FileSystemDirectoryIteratorEntry result;
result.setValue(entries_.TakeFirst()->asFileSystemHandle());
return ScriptPromise::Cast(script_state, ToV8(result, script_state));
}
if (has_more_entries_) {
DCHECK(!pending_next_);
pending_next_ = ScriptPromiseResolver::Create(script_state);
return pending_next_->Promise();
}
FileSystemDirectoryIteratorEntry result;
result.setDone(true);
return ScriptPromise::Cast(script_state, ToV8(result, script_state));
}
void FileSystemDirectoryIterator::Trace(Visitor* visitor) {
DirectoryReaderBase::Trace(visitor);
visitor->Trace(entries_);
visitor->Trace(pending_next_);
}
void FileSystemDirectoryIterator::AddEntries(const EntryHeapVector& entries) {
for (const auto& e : entries)
entries_.emplace_back(e);
if (pending_next_) {
ScriptState::Scope scope(pending_next_->GetScriptState());
pending_next_->Resolve(
next(pending_next_->GetScriptState()).GetScriptValue());
pending_next_ = nullptr;
}
}
void FileSystemDirectoryIterator::OnError(FileError::ErrorCode error) {
error_ = error;
if (pending_next_) {
pending_next_->Reject(FileError::CreateDOMException(error));
pending_next_ = nullptr;
}
}
} // namespace blink
// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_ITERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_ITERATOR_H_
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/modules/filesystem/directory_reader_base.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
namespace blink {
class ScriptPromise;
class ScriptPromiseResolver;
class ScriptState;
class FileSystemDirectoryIterator : public DirectoryReaderBase {
DEFINE_WRAPPERTYPEINFO();
public:
FileSystemDirectoryIterator(DOMFileSystemBase*, const String& full_path);
ScriptPromise next(ScriptState*);
void IteratorReturn() {}
void Trace(Visitor*) override;
private:
class EntriesCallbackHelper;
class ErrorCallbackHelper;
void AddEntries(const EntryHeapVector& entries);
void OnError(FileError::ErrorCode);
FileError::ErrorCode error_ = FileError::kOK;
HeapDeque<Member<Entry>> entries_;
Member<ScriptPromiseResolver> pending_next_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_ITERATOR_H_
// Copyright 2018 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.
// Async iterator returned by FileSystemDirectoryHandle.getEntries().
// https://github.com/WICG/writable-files/blob/master/EXPLAINER.md
[
NoInterfaceObject,
RuntimeEnabled=WritableFiles
] interface FileSystemDirectoryIterator {
[CallWith=ScriptState] Promise next();
[ImplementedAs=IteratorReturn] void return();
};
// Copyright 2018 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.
// Used by FileSystemDirectoryIterator to represents results of next() calls.
// https://github.com/WICG/writable-files/blob/master/EXPLAINER.md
dictionary FileSystemDirectoryIteratorEntry {
FileSystemBaseHandle value;
boolean done = false;
};
// Copyright 2018 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.
// https://github.com/WICG/writable-files/blob/master/EXPLAINER.md
dictionary FileSystemGetDirectoryOptions {
boolean create = false;
};
// Copyright 2018 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.
// https://github.com/WICG/writable-files/blob/master/EXPLAINER.md
dictionary FileSystemGetFileOptions {
boolean create = false;
};
......@@ -140,6 +140,7 @@ modules_idl_files =
"filesystem/file_entry_sync.idl",
"filesystem/file_system_base_handle.idl",
"filesystem/file_system_directory_handle.idl",
"filesystem/file_system_directory_iterator.idl",
"filesystem/file_system_file_handle.idl",
"filesystem/file_system_callback.idl",
"filesystem/file_system_writer.idl",
......@@ -519,7 +520,10 @@ modules_dictionary_idl_files =
"encryptedmedia/media_key_system_configuration.idl",
"encryptedmedia/media_key_system_media_capability.idl",
"eventsource/event_source_init.idl",
"filesystem/file_system_directory_iterator_entry.idl",
"filesystem/file_system_flags.idl",
"filesystem/file_system_get_directory_options.idl",
"filesystem/file_system_get_file_options.idl",
"filesystem/get_system_directory_options.idl",
"gamepad/gamepad_effect_parameters.idl",
"gamepad/gamepad_event_init.idl",
......
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