summaryrefslogtreecommitdiffstats
path: root/dom/fs/api/FileSystemManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/fs/api/FileSystemManager.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/dom/fs/api/FileSystemManager.cpp b/dom/fs/api/FileSystemManager.cpp
new file mode 100644
index 0000000000..099739f8a1
--- /dev/null
+++ b/dom/fs/api/FileSystemManager.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/FileSystemManager.h"
+
+#include "FileSystemBackgroundRequestHandler.h"
+#include "fs/FileSystemRequestHandler.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/FileSystemManagerChild.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/StorageManager.h"
+#include "mozilla/dom/fs/ManagedMozPromiseRequestHolder.h"
+#include "mozilla/dom/quota/QuotaCommon.h"
+#include "mozilla/dom/quota/ResultExtensions.h"
+
+namespace mozilla::dom {
+
+FileSystemManager::FileSystemManager(
+ nsIGlobalObject* aGlobal, RefPtr<StorageManager> aStorageManager,
+ RefPtr<FileSystemBackgroundRequestHandler> aBackgroundRequestHandler)
+ : mGlobal(aGlobal),
+ mStorageManager(std::move(aStorageManager)),
+ mBackgroundRequestHandler(std::move(aBackgroundRequestHandler)),
+ mRequestHandler(new fs::FileSystemRequestHandler()) {}
+
+FileSystemManager::FileSystemManager(nsIGlobalObject* aGlobal,
+ RefPtr<StorageManager> aStorageManager)
+ : FileSystemManager(aGlobal, std::move(aStorageManager),
+ MakeRefPtr<FileSystemBackgroundRequestHandler>()) {}
+
+FileSystemManager::~FileSystemManager() { MOZ_ASSERT(mShutdown); }
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileSystemManager)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemManager);
+NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemManager);
+NS_IMPL_CYCLE_COLLECTION(FileSystemManager, mGlobal, mStorageManager);
+
+void FileSystemManager::Shutdown() {
+ mShutdown.Flip();
+
+ auto shutdownAndDisconnect = [self = RefPtr(this)]() {
+ self->mBackgroundRequestHandler->Shutdown();
+
+ for (RefPtr<PromiseRequestHolder<BoolPromise>> holder :
+ self->mPromiseRequestHolders.ForwardRange()) {
+ holder->DisconnectIfExists();
+ }
+ };
+
+ if (NS_IsMainThread()) {
+ if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
+ mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
+ ->CloseAllWritables(
+ [shutdownAndDisconnect = std::move(shutdownAndDisconnect)]() {
+ shutdownAndDisconnect();
+ });
+ } else {
+ shutdownAndDisconnect();
+ }
+ } else {
+ if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
+ // FileSystemAccessHandles and FileSystemWritableFileStreams prevent
+ // shutdown until they are full closed, so at this point, they all should
+ // be closed.
+ MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
+ ->AllSyncAccessHandlesClosed());
+ MOZ_ASSERT(mBackgroundRequestHandler->FileSystemManagerChildStrongRef()
+ ->AllWritableFileStreamsClosed());
+ }
+
+ shutdownAndDisconnect();
+ }
+}
+
+const RefPtr<FileSystemManagerChild>& FileSystemManager::ActorStrongRef()
+ const {
+ return mBackgroundRequestHandler->FileSystemManagerChildStrongRef();
+}
+
+void FileSystemManager::RegisterPromiseRequestHolder(
+ PromiseRequestHolder<BoolPromise>* aHolder) {
+ mPromiseRequestHolders.AppendElement(aHolder);
+}
+
+void FileSystemManager::UnregisterPromiseRequestHolder(
+ PromiseRequestHolder<BoolPromise>* aHolder) {
+ mPromiseRequestHolders.RemoveElement(aHolder);
+}
+
+void FileSystemManager::BeginRequest(
+ std::function<void(const RefPtr<FileSystemManagerChild>&)>&& aSuccess,
+ std::function<void(nsresult)>&& aFailure) {
+ MOZ_ASSERT(!mShutdown);
+
+ MOZ_ASSERT(mGlobal);
+
+ // Check if we're allowed to use storage
+ if (mGlobal->GetStorageAccess() < StorageAccess::eSessionScoped) {
+ aFailure(NS_ERROR_DOM_SECURITY_ERR);
+ return;
+ }
+
+ if (mBackgroundRequestHandler->FileSystemManagerChildStrongRef()) {
+ aSuccess(mBackgroundRequestHandler->FileSystemManagerChildStrongRef());
+ return;
+ }
+
+ QM_TRY_INSPECT(const auto& principalInfo, mGlobal->GetStorageKey(), QM_VOID,
+ [&aFailure](nsresult rv) { aFailure(rv); });
+
+ auto holder = MakeRefPtr<PromiseRequestHolder<BoolPromise>>(this);
+
+ mBackgroundRequestHandler->CreateFileSystemManagerChild(principalInfo)
+ ->Then(GetCurrentSerialEventTarget(), __func__,
+ [self = RefPtr<FileSystemManager>(this), holder,
+ success = std::move(aSuccess), failure = std::move(aFailure)](
+ const BoolPromise::ResolveOrRejectValue& aValue) {
+ holder->Complete();
+
+ if (aValue.IsResolve()) {
+ success(self->mBackgroundRequestHandler
+ ->FileSystemManagerChildStrongRef());
+ } else {
+ failure(aValue.RejectValue());
+ }
+ })
+ ->Track(*holder);
+}
+
+already_AddRefed<Promise> FileSystemManager::GetDirectory(ErrorResult& aError) {
+ MOZ_ASSERT(mGlobal);
+
+ RefPtr<Promise> promise = Promise::Create(mGlobal, aError);
+ if (NS_WARN_IF(aError.Failed())) {
+ return nullptr;
+ }
+
+ MOZ_ASSERT(promise);
+
+ mRequestHandler->GetRootHandle(this, promise, aError);
+ if (NS_WARN_IF(aError.Failed())) {
+ return nullptr;
+ }
+
+ return promise.forget();
+}
+
+} // namespace mozilla::dom