blob: 99bd8635cd40c26b341004193169b93559c5ec49 [file] [log] [blame]
// Copyright 2019 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/native_file_system/native_file_system_directory_handle.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.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/core/fileapi/file_error.h"
#include "third_party/blink/renderer/modules/native_file_system/file_system_get_directory_options.h"
#include "third_party/blink/renderer/modules/native_file_system/file_system_get_file_options.h"
#include "third_party/blink/renderer/modules/native_file_system/file_system_remove_options.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
namespace {
// The name to use for the root directory of a sandboxed file system.
constexpr const char kSandboxRootDirectoryName[] = "";
} // namespace
using mojom::blink::NativeFileSystemErrorPtr;
NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle(
ExecutionContext* context,
const String& name,
mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> mojo_ptr)
: NativeFileSystemHandle(context, name),
mojo_ptr_(std::move(mojo_ptr),
context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
DCHECK(mojo_ptr_);
}
ScriptPromise NativeFileSystemDirectoryHandle::getFile(
ScriptState* script_state,
const String& name,
const FileSystemGetFileOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
mojo_ptr_->GetFile(
name, options->create(),
WTF::Bind(
[](ScriptPromiseResolver* resolver, const String& name,
NativeFileSystemErrorPtr result,
mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle>
handle) {
ExecutionContext* context = resolver->GetExecutionContext();
if (!context)
return;
if (result->status != mojom::blink::NativeFileSystemStatus::kOk) {
native_file_system_error::Reject(resolver, *result);
return;
}
resolver->Resolve(MakeGarbageCollected<NativeFileSystemFileHandle>(
context, name, std::move(handle)));
},
WrapPersistent(resolver), name));
return result;
}
ScriptPromise NativeFileSystemDirectoryHandle::getDirectory(
ScriptState* script_state,
const String& name,
const FileSystemGetDirectoryOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
mojo_ptr_->GetDirectory(
name, options->create(),
WTF::Bind(
[](ScriptPromiseResolver* resolver, const String& name,
NativeFileSystemErrorPtr result,
mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>
handle) {
ExecutionContext* context = resolver->GetExecutionContext();
if (!context)
return;
if (result->status != mojom::blink::NativeFileSystemStatus::kOk) {
native_file_system_error::Reject(resolver, *result);
return;
}
resolver->Resolve(
MakeGarbageCollected<NativeFileSystemDirectoryHandle>(
context, name, std::move(handle)));
},
WrapPersistent(resolver), name));
return result;
}
namespace {
void ReturnDataFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
V8SetReturnValue(info, info.Data());
}
} // namespace
ScriptValue NativeFileSystemDirectoryHandle::getEntries(
ScriptState* script_state) {
auto* iterator = MakeGarbageCollected<NativeFileSystemDirectoryIterator>(
this, ExecutionContext::From(script_state));
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())
.ToChecked()) {
return ScriptValue();
}
return ScriptValue(script_state->GetIsolate(), result);
}
ScriptPromise NativeFileSystemDirectoryHandle::removeEntry(
ScriptState* script_state,
const String& name,
const FileSystemRemoveOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
mojo_ptr_->RemoveEntry(
name, options->recursive(),
WTF::Bind(
[](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result) {
native_file_system_error::ResolveOrReject(resolver, *result);
},
WrapPersistent(resolver)));
return result;
}
// static
ScriptPromise NativeFileSystemDirectoryHandle::getSystemDirectory(
ScriptState* script_state,
const GetSystemDirectoryOptions* options) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
// TODO(mek): Cache mojo::Remote<mojom::blink::NativeFileSystemManager>
// associated with an ExecutionContext, so we don't have to request a new one
// for each operation, and can avoid code duplication between here and other
// uses.
mojo::Remote<mojom::blink::NativeFileSystemManager> manager;
auto* provider = ExecutionContext::From(script_state)->GetInterfaceProvider();
if (!provider) {
resolver->Reject(file_error::CreateDOMException(
base::File::FILE_ERROR_INVALID_OPERATION));
return result;
}
provider->GetInterface(manager.BindNewPipeAndPassReceiver());
auto* raw_manager = manager.get();
raw_manager->GetSandboxedFileSystem(WTF::Bind(
[](ScriptPromiseResolver* resolver,
mojo::Remote<mojom::blink::NativeFileSystemManager>,
NativeFileSystemErrorPtr result,
mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>
handle) {
ExecutionContext* context = resolver->GetExecutionContext();
if (!context)
return;
if (result->status != mojom::blink::NativeFileSystemStatus::kOk) {
native_file_system_error::Reject(resolver, *result);
return;
}
resolver->Resolve(MakeGarbageCollected<NativeFileSystemDirectoryHandle>(
context, kSandboxRootDirectoryName, std::move(handle)));
},
WrapPersistent(resolver), std::move(manager)));
return result;
}
mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>
NativeFileSystemDirectoryHandle::Transfer() {
mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> result;
mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver());
return result;
}
void NativeFileSystemDirectoryHandle::QueryPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) {
mojo_ptr_->GetPermissionStatus(writable, std::move(callback));
}
void NativeFileSystemDirectoryHandle::RequestPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr,
mojom::blink::PermissionStatus)> callback) {
mojo_ptr_->RequestPermission(writable, std::move(callback));
}
void NativeFileSystemDirectoryHandle::ContextDestroyed(ExecutionContext*) {
mojo_ptr_.reset();
}
} // namespace blink