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") { ...@@ -49,6 +49,8 @@ blink_modules_sources("filesystem") {
"file_system_client.h", "file_system_client.h",
"file_system_directory_handle.cc", "file_system_directory_handle.cc",
"file_system_directory_handle.h", "file_system_directory_handle.h",
"file_system_directory_iterator.cc",
"file_system_directory_iterator.h",
"file_system_file_handle.cc", "file_system_file_handle.cc",
"file_system_file_handle.h", "file_system_file_handle.h",
"file_system_writer.cc", "file_system_writer.cc",
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #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/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_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" #include "third_party/blink/renderer/modules/filesystem/local_file_system.h"
namespace blink { namespace blink {
...@@ -16,23 +17,30 @@ FileSystemDirectoryHandle::FileSystemDirectoryHandle( ...@@ -16,23 +17,30 @@ FileSystemDirectoryHandle::FileSystemDirectoryHandle(
const String& full_path) const String& full_path)
: FileSystemBaseHandle(file_system, full_path) {} : FileSystemBaseHandle(file_system, full_path) {}
ScriptPromise FileSystemDirectoryHandle::getFile(ScriptState* script_state, ScriptPromise FileSystemDirectoryHandle::getFile(
const String& name) { ScriptState* script_state,
const String& name,
const FileSystemGetFileOptions& options) {
FileSystemFlags flags;
flags.setCreateFlag(options.create());
auto* resolver = ScriptPromiseResolver::Create(script_state); auto* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise result = resolver->Promise(); ScriptPromise result = resolver->Promise();
filesystem()->GetFile(this, name, FileSystemFlags(), filesystem()->GetFile(this, name, flags,
new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver), new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
new PromiseErrorCallback(resolver)); new PromiseErrorCallback(resolver));
return result; return result;
} }
ScriptPromise FileSystemDirectoryHandle::getDirectory(ScriptState* script_state, ScriptPromise FileSystemDirectoryHandle::getDirectory(
const String& name) { ScriptState* script_state,
const String& name,
const FileSystemGetDirectoryOptions& options) {
FileSystemFlags flags;
flags.setCreateFlag(options.create());
auto* resolver = ScriptPromiseResolver::Create(script_state); auto* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise result = resolver->Promise(); ScriptPromise result = resolver->Promise();
filesystem()->GetDirectory( filesystem()->GetDirectory(
this, name, FileSystemFlags(), this, name, flags, new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
new EntryCallbacks::OnDidGetEntryPromiseImpl(resolver),
new PromiseErrorCallback(resolver)); new PromiseErrorCallback(resolver));
return result; return result;
} }
...@@ -55,4 +63,28 @@ ScriptPromise FileSystemDirectoryHandle::getSystemDirectory( ...@@ -55,4 +63,28 @@ ScriptPromise FileSystemDirectoryHandle::getSystemDirectory(
return result; 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 } // namespace blink
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_HANDLE_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_DIRECTORY_HANDLE_H_
#define 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_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" #include "third_party/blink/renderer/modules/filesystem/get_system_directory_options.h"
namespace blink { namespace blink {
...@@ -17,8 +20,13 @@ class FileSystemDirectoryHandle : public FileSystemBaseHandle { ...@@ -17,8 +20,13 @@ class FileSystemDirectoryHandle : public FileSystemBaseHandle {
FileSystemDirectoryHandle(DOMFileSystemBase*, const String& full_path); FileSystemDirectoryHandle(DOMFileSystemBase*, const String& full_path);
bool isDirectory() const override { return true; } bool isDirectory() const override { return true; }
ScriptPromise getFile(ScriptState*, const String& name); ScriptPromise getFile(ScriptState*,
ScriptPromise getDirectory(ScriptState*, const String& name); const String& name,
const FileSystemGetFileOptions&);
ScriptPromise getDirectory(ScriptState*,
const String& name,
const FileSystemGetDirectoryOptions&);
ScriptValue getEntries(ScriptState*);
static ScriptPromise getSystemDirectory( static ScriptPromise getSystemDirectory(
ScriptState*, ScriptState*,
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
[ [
RuntimeEnabled=WritableFiles RuntimeEnabled=WritableFiles
] interface FileSystemDirectoryHandle : FileSystemBaseHandle { ] interface FileSystemDirectoryHandle : FileSystemBaseHandle {
[CallWith=ScriptState] Promise<FileSystemFileHandle> getFile(USVString name); [CallWith=ScriptState] Promise<FileSystemFileHandle> getFile(USVString name, optional FileSystemGetFileOptions options);
[CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectory(USVString name); [CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectory(USVString name, optional FileSystemGetDirectoryOptions options);
// TODO(mek): Other methods such as getEntries etc. [CallWith=ScriptState] object getEntries();
[CallWith=ScriptState] [CallWith=ScriptState]
static Promise<FileSystemDirectoryHandle> getSystemDirectory(GetSystemDirectoryOptions options); 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 = ...@@ -140,6 +140,7 @@ modules_idl_files =
"filesystem/file_entry_sync.idl", "filesystem/file_entry_sync.idl",
"filesystem/file_system_base_handle.idl", "filesystem/file_system_base_handle.idl",
"filesystem/file_system_directory_handle.idl", "filesystem/file_system_directory_handle.idl",
"filesystem/file_system_directory_iterator.idl",
"filesystem/file_system_file_handle.idl", "filesystem/file_system_file_handle.idl",
"filesystem/file_system_callback.idl", "filesystem/file_system_callback.idl",
"filesystem/file_system_writer.idl", "filesystem/file_system_writer.idl",
...@@ -519,7 +520,10 @@ modules_dictionary_idl_files = ...@@ -519,7 +520,10 @@ modules_dictionary_idl_files =
"encryptedmedia/media_key_system_configuration.idl", "encryptedmedia/media_key_system_configuration.idl",
"encryptedmedia/media_key_system_media_capability.idl", "encryptedmedia/media_key_system_media_capability.idl",
"eventsource/event_source_init.idl", "eventsource/event_source_init.idl",
"filesystem/file_system_directory_iterator_entry.idl",
"filesystem/file_system_flags.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", "filesystem/get_system_directory_options.idl",
"gamepad/gamepad_effect_parameters.idl", "gamepad/gamepad_effect_parameters.idl",
"gamepad/gamepad_event_init.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