summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc269
1 files changed, 269 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc b/chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc
new file mode 100644
index 00000000000..0fad4c7a7a6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/native_io/native_io_manager.cc
@@ -0,0 +1,269 @@
+// Copyright 2020 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_io/native_io_manager.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/files/file.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/native_io/native_io.mojom-blink.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/native_io/native_io_file.h"
+#include "third_party/blink/renderer/modules/native_io/native_io_file_sync.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+namespace {
+
+bool IsValidNativeIONameCharacter(int name_char) {
+ return (name_char >= 'a' && name_char <= 'z') ||
+ (name_char >= '0' && name_char <= '9') || name_char == '_';
+}
+
+bool IsValidNativeIOName(const String& name) {
+ if (name.IsEmpty())
+ return false;
+
+ if (name.Is8Bit()) {
+ return std::all_of(name.Span8().begin(), name.Span8().end(),
+ &IsValidNativeIONameCharacter);
+ }
+ return std::all_of(name.Span16().begin(), name.Span16().end(),
+ &IsValidNativeIONameCharacter);
+}
+
+void OnOpenResult(ScriptPromiseResolver* resolver,
+ mojo::Remote<mojom::blink::NativeIOFileHost> backend_file,
+ base::File backing_file) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ if (!backing_file.IsValid()) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kUnknownError,
+ "open() failed"));
+ return;
+ }
+
+ NativeIOFile* file = MakeGarbageCollected<NativeIOFile>(
+ std::move(backing_file), std::move(backend_file),
+ ExecutionContext::From(script_state));
+ resolver->Resolve(file);
+}
+
+void OnDeleteResult(ScriptPromiseResolver* resolver, bool backend_success) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ if (!backend_success) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kUnknownError,
+ "delete() failed"));
+ return;
+ }
+
+ resolver->Resolve();
+}
+
+void OnGetAllResult(ScriptPromiseResolver* resolver,
+ bool backend_success,
+ const Vector<String>& file_names) {
+ ScriptState* script_state = resolver->GetScriptState();
+ if (!script_state->ContextIsValid())
+ return;
+ ScriptState::Scope scope(script_state);
+
+ if (!backend_success) {
+ resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kUnknownError,
+ "getAll() failed"));
+ return;
+ }
+
+ resolver->Resolve(file_names);
+}
+
+} // namespace
+
+NativeIOManager::NativeIOManager(
+ ExecutionContext* execution_context,
+ mojo::Remote<mojom::blink::NativeIOHost> backend)
+ : ExecutionContextLifecycleObserver(execution_context),
+ // TODO(pwnall): Get a dedicated queue when the specification matures.
+ receiver_task_runner_(
+ execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)),
+ backend_(std::move(backend)) {
+ backend_.set_disconnect_handler(WTF::Bind(
+ &NativeIOManager::OnBackendDisconnect, WrapWeakPersistent(this)));
+}
+
+NativeIOManager::~NativeIOManager() = default;
+
+ScriptPromise NativeIOManager::open(ScriptState* script_state,
+ String name,
+ ExceptionState& exception_state) {
+ if (!IsValidNativeIOName(name)) {
+ exception_state.ThrowTypeError("Invalid file name");
+ return ScriptPromise();
+ }
+
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return ScriptPromise();
+ }
+
+ ExecutionContext* execution_context = GetExecutionContext();
+ DCHECK(execution_context);
+
+ mojo::Remote<mojom::blink::NativeIOFileHost> backend_file;
+ mojo::PendingReceiver<mojom::blink::NativeIOFileHost> backend_file_receiver =
+ backend_file.BindNewPipeAndPassReceiver(receiver_task_runner_);
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ backend_->OpenFile(name, std::move(backend_file_receiver),
+ WTF::Bind(&OnOpenResult, WrapPersistent(resolver),
+ std::move(backend_file)));
+ return resolver->Promise();
+}
+
+ScriptPromise NativeIOManager::Delete(ScriptState* script_state,
+ String name,
+ ExceptionState& exception_state) {
+ if (!IsValidNativeIOName(name)) {
+ exception_state.ThrowTypeError("Invalid file name");
+ return ScriptPromise();
+ }
+
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ backend_->DeleteFile(name,
+ WTF::Bind(&OnDeleteResult, WrapPersistent(resolver)));
+ return resolver->Promise();
+}
+
+ScriptPromise NativeIOManager::getAll(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ backend_->GetAllFileNames(
+ WTF::Bind(&OnGetAllResult, WrapPersistent(resolver)));
+ return resolver->Promise();
+}
+
+NativeIOFileSync* NativeIOManager::openSync(String name,
+ ExceptionState& exception_state) {
+ if (!IsValidNativeIOName(name)) {
+ exception_state.ThrowTypeError("Invalid file name");
+ return nullptr;
+ }
+
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return nullptr;
+ }
+
+ ExecutionContext* execution_context = GetExecutionContext();
+ DCHECK(execution_context);
+
+ mojo::Remote<mojom::blink::NativeIOFileHost> backend_file;
+ mojo::PendingReceiver<mojom::blink::NativeIOFileHost> backend_file_receiver =
+ backend_file.BindNewPipeAndPassReceiver(receiver_task_runner_);
+
+ base::File backing_file;
+ bool call_succeeded =
+ backend_->OpenFile(name, std::move(backend_file_receiver), &backing_file);
+
+ if (!call_succeeded || !backing_file.IsValid()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
+ "openSync() failed");
+ return nullptr;
+ }
+
+ return MakeGarbageCollected<NativeIOFileSync>(
+ std::move(backing_file), std::move(backend_file), execution_context);
+}
+
+void NativeIOManager::deleteSync(String name, ExceptionState& exception_state) {
+ if (!IsValidNativeIOName(name)) {
+ exception_state.ThrowTypeError("Invalid file name");
+ return;
+ }
+
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return;
+ }
+
+ bool backend_success = false;
+ bool call_succeeded = backend_->DeleteFile(name, &backend_success);
+
+ if (!call_succeeded || !backend_success) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
+ "deleteSync() failed");
+ }
+}
+
+Vector<String> NativeIOManager::getAllSync(ExceptionState& exception_state) {
+ Vector<String> result;
+ if (!backend_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "NativeIOHost backend went away");
+ return result;
+ }
+
+ bool backend_success = false;
+ bool call_succeeded = backend_->GetAllFileNames(&backend_success, &result);
+
+ if (!call_succeeded || !backend_success) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
+ "getAllSync() failed");
+ }
+ return result;
+}
+
+void NativeIOManager::Trace(Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ ExecutionContextLifecycleObserver::Trace(visitor);
+}
+
+void NativeIOManager::ContextDestroyed() {
+ backend_.reset();
+}
+
+void NativeIOManager::OnBackendDisconnect() {
+ backend_.reset();
+}
+
+} // namespace blink