From 3a934f66ac06ced1a94262e2e0f42ae5af7c673d Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Wed, 6 Jul 2022 18:00:04 +0000 Subject: [PATCH] Bug 1768050: Move OPFS operations off PBackground r=janv,nika Depends on D149260 Differential Revision: https://phabricator.services.mozilla.com/D147273 --- dom/fs/api/FileSystemDirectoryHandle.cpp | 11 +- dom/fs/api/FileSystemDirectoryHandle.h | 2 + dom/fs/api/FileSystemFileHandle.cpp | 11 +- dom/fs/api/FileSystemFileHandle.h | 2 + dom/fs/api/FileSystemHandle.cpp | 13 +- dom/fs/api/FileSystemHandle.h | 16 +- dom/fs/child/FileSystemRequestHandler.cpp | 111 +++--- dom/fs/child/OriginPrivateFileSystemChild.h | 24 ++ dom/fs/child/moz.build | 1 + dom/fs/include/fs/FileSystemRequestHandler.h | 8 +- dom/fs/parent/BackgroundFileSystemParent.cpp | 132 ++++--- dom/fs/parent/BackgroundFileSystemParent.h | 26 +- .../parent/OriginPrivateFileSystemParent.cpp | 111 ++++++ dom/fs/parent/OriginPrivateFileSystemParent.h | 80 +++++ dom/fs/parent/moz.build | 2 + dom/fs/shared/FileSystemActorHolder.h | 15 + dom/fs/shared/FileSystemTypes.h | 1 + dom/fs/shared/PBackgroundFileSystem.ipdl | 261 +------------- dom/fs/shared/POriginPrivateFileSystem.ipdl | 321 ++++++++++++++++++ dom/fs/shared/moz.build | 2 + .../api/TestFileSystemDirectoryHandle.cpp | 29 +- .../gtest/api/TestFileSystemFileHandle.cpp | 18 +- .../test/gtest/api/TestFileSystemHandle.cpp | 22 +- .../child/TestFileSystemRequestHandler.cpp | 3 +- ipc/glue/ActorHolder.h | 45 +++ ipc/glue/moz.build | 1 + 26 files changed, 856 insertions(+), 412 deletions(-) create mode 100644 dom/fs/child/OriginPrivateFileSystemChild.h create mode 100644 dom/fs/parent/OriginPrivateFileSystemParent.cpp create mode 100644 dom/fs/parent/OriginPrivateFileSystemParent.h create mode 100644 dom/fs/shared/FileSystemActorHolder.h create mode 100644 dom/fs/shared/POriginPrivateFileSystem.ipdl create mode 100644 ipc/glue/ActorHolder.h diff --git a/dom/fs/api/FileSystemDirectoryHandle.cpp b/dom/fs/api/FileSystemDirectoryHandle.cpp index 8020d1d89005..4c42bbd2d716 100644 --- a/dom/fs/api/FileSystemDirectoryHandle.cpp +++ b/dom/fs/api/FileSystemDirectoryHandle.cpp @@ -11,18 +11,21 @@ #include "mozilla/dom/FileSystemDirectoryHandleBinding.h" #include "mozilla/dom/FileSystemDirectoryIterator.h" #include "mozilla/dom/FileSystemHandleBinding.h" +#include "mozilla/dom/POriginPrivateFileSystem.h" #include "mozilla/dom/Promise.h" namespace mozilla::dom { FileSystemDirectoryHandle::FileSystemDirectoryHandle( - nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata, + nsIGlobalObject* aGlobal, RefPtr& aActor, + const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler) - : FileSystemHandle(aGlobal, aMetadata, aRequestHandler) {} + : FileSystemHandle(aGlobal, aActor, aMetadata, aRequestHandler) {} FileSystemDirectoryHandle::FileSystemDirectoryHandle( - nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata) - : FileSystemDirectoryHandle(aGlobal, aMetadata, + nsIGlobalObject* aGlobal, RefPtr& aActor, + const fs::FileSystemEntryMetadata& aMetadata) + : FileSystemDirectoryHandle(aGlobal, aActor, aMetadata, new fs::FileSystemRequestHandler()) {} NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(FileSystemDirectoryHandle, diff --git a/dom/fs/api/FileSystemDirectoryHandle.h b/dom/fs/api/FileSystemDirectoryHandle.h index 35bd96ea128a..1d0134cb224c 100644 --- a/dom/fs/api/FileSystemDirectoryHandle.h +++ b/dom/fs/api/FileSystemDirectoryHandle.h @@ -23,10 +23,12 @@ struct FileSystemRemoveOptions; class FileSystemDirectoryHandle final : public FileSystemHandle { public: FileSystemDirectoryHandle(nsIGlobalObject* aGlobal, + RefPtr& aActor, const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler); FileSystemDirectoryHandle(nsIGlobalObject* aGlobal, + RefPtr& aActor, const fs::FileSystemEntryMetadata& aMetadata); NS_DECL_ISUPPORTS_INHERITED diff --git a/dom/fs/api/FileSystemFileHandle.cpp b/dom/fs/api/FileSystemFileHandle.cpp index d3c71c0c1a3d..fc828917bf26 100644 --- a/dom/fs/api/FileSystemFileHandle.cpp +++ b/dom/fs/api/FileSystemFileHandle.cpp @@ -10,6 +10,7 @@ #include "mozilla/ErrorResult.h" #include "mozilla/dom/FileSystemFileHandleBinding.h" #include "mozilla/dom/FileSystemHandleBinding.h" +#include "mozilla/dom/POriginPrivateFileSystem.h" #include "mozilla/dom/Promise.h" namespace mozilla::dom { @@ -19,13 +20,15 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(FileSystemFileHandle, NS_IMPL_CYCLE_COLLECTION_INHERITED(FileSystemFileHandle, FileSystemHandle) FileSystemFileHandle::FileSystemFileHandle( - nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata, + nsIGlobalObject* aGlobal, RefPtr& aActor, + const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler) - : FileSystemHandle(aGlobal, aMetadata, aRequestHandler) {} + : FileSystemHandle(aGlobal, aActor, aMetadata, aRequestHandler) {} FileSystemFileHandle::FileSystemFileHandle( - nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata) - : FileSystemFileHandle(aGlobal, aMetadata, + nsIGlobalObject* aGlobal, RefPtr& aActor, + const fs::FileSystemEntryMetadata& aMetadata) + : FileSystemFileHandle(aGlobal, aActor, aMetadata, new fs::FileSystemRequestHandler()) {} // WebIDL Boilerplate diff --git a/dom/fs/api/FileSystemFileHandle.h b/dom/fs/api/FileSystemFileHandle.h index 90e51f7f81c3..3cf6b1021dec 100644 --- a/dom/fs/api/FileSystemFileHandle.h +++ b/dom/fs/api/FileSystemFileHandle.h @@ -20,10 +20,12 @@ struct FileSystemCreateWritableOptions; class FileSystemFileHandle final : public FileSystemHandle { public: FileSystemFileHandle(nsIGlobalObject* aGlobal, + RefPtr& aActor, const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler); FileSystemFileHandle(nsIGlobalObject* aGlobal, + RefPtr& aActor, const fs::FileSystemEntryMetadata& aMetadata); NS_DECL_ISUPPORTS_INHERITED diff --git a/dom/fs/api/FileSystemHandle.cpp b/dom/fs/api/FileSystemHandle.cpp index b472f379a983..7af24373f5ae 100644 --- a/dom/fs/api/FileSystemHandle.cpp +++ b/dom/fs/api/FileSystemHandle.cpp @@ -9,6 +9,7 @@ #include "mozilla/ErrorResult.h" #include "mozilla/dom/FileSystemHandleBinding.h" +#include "mozilla/dom/OriginPrivateFileSystemChild.h" #include "mozilla/dom/Promise.h" namespace mozilla::dom { @@ -22,11 +23,15 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemHandle); NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemHandle, mGlobal); FileSystemHandle::FileSystemHandle( - nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata, + nsIGlobalObject* aGlobal, RefPtr& aActor, + const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler) : mGlobal(aGlobal), + mActor(aActor), mMetadata(aMetadata), - mRequestHandler(aRequestHandler) {} + mRequestHandler(aRequestHandler) { + MOZ_ASSERT(!mMetadata.entryId().IsEmpty()); +} // WebIDL Boilerplate @@ -55,4 +60,8 @@ already_AddRefed FileSystemHandle::IsSameEntry( return promise.forget(); } +OriginPrivateFileSystemChild* FileSystemHandle::Actor() const { + return mActor->Actor(); +} + } // namespace mozilla::dom diff --git a/dom/fs/api/FileSystemHandle.h b/dom/fs/api/FileSystemHandle.h index e2f41ba74772..28400f7e4daf 100644 --- a/dom/fs/api/FileSystemHandle.h +++ b/dom/fs/api/FileSystemHandle.h @@ -7,7 +7,9 @@ #ifndef DOM_FS_FILESYSTEMHANDLE_H_ #define DOM_FS_FILESYSTEMHANDLE_H_ -#include "mozilla/dom/PBackgroundFileSystem.h" +#include "mozilla/dom/FileSystemActorHolder.h" +#include "mozilla/dom/POriginPrivateFileSystem.h" +#include "mozilla/Logging.h" #include "nsCOMPtr.h" #include "nsISupports.h" #include "nsWrapperCache.h" @@ -16,12 +18,20 @@ class nsIGlobalObject; namespace mozilla { +extern LazyLogModule gOPFSLog; + +#define LOG(args) MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Verbose, args) + +#define LOG_DEBUG(args) \ + MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Debug, args) + class ErrorResult; namespace dom { class DOMString; enum class FileSystemHandleKind : uint8_t; +class OriginPrivateFileSystemChild; class Promise; namespace fs { @@ -31,6 +41,7 @@ class FileSystemRequestHandler; class FileSystemHandle : public nsISupports, public nsWrapperCache { public: FileSystemHandle(nsIGlobalObject* aGlobal, + RefPtr& aActor, const fs::FileSystemEntryMetadata& aMetadata, fs::FileSystemRequestHandler* aRequestHandler); @@ -51,10 +62,13 @@ class FileSystemHandle : public nsISupports, public nsWrapperCache { already_AddRefed IsSameEntry(FileSystemHandle& aOther, ErrorResult& aError) const; + OriginPrivateFileSystemChild* Actor() const; + protected: virtual ~FileSystemHandle() = default; nsCOMPtr mGlobal; + RefPtr mActor; const fs::FileSystemEntryMetadata mMetadata; diff --git a/dom/fs/child/FileSystemRequestHandler.cpp b/dom/fs/child/FileSystemRequestHandler.cpp index 130a29a1a309..3fde8edc8568 100644 --- a/dom/fs/child/FileSystemRequestHandler.cpp +++ b/dom/fs/child/FileSystemRequestHandler.cpp @@ -9,6 +9,7 @@ #include "nsIScriptObjectPrincipal.h" #include "mozilla/dom/BackgroundFileSystemChild.h" +#include "mozilla/dom/OriginPrivateFileSystemChild.h" #include "mozilla/dom/File.h" #include "mozilla/dom/FileSystemFileHandle.h" #include "mozilla/dom/FileSystemDirectoryHandle.h" @@ -16,17 +17,23 @@ #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/Endpoint.h" #include "mozilla/ipc/PBackgroundChild.h" -using namespace mozilla::ipc; - namespace mozilla::dom::fs { +using mozilla::ipc::RejectCallback; + namespace { // Not static: BackgroundFileSystemChild must be owned by calling thread RefPtr GetRootProvider( nsIGlobalObject* aGlobal) { + using mozilla::dom::BackgroundFileSystemChild; + using mozilla::ipc::BackgroundChild; + using mozilla::ipc::PBackgroundChild; + using mozilla::ipc::PrincipalInfo; + // TODO: It would be nice to convert all error checks to QM_TRY some time // later. @@ -61,7 +68,7 @@ RefPtr GetRootProvider( return nullptr; } - BackgroundFileSystemChild* actor = new BackgroundFileSystemChild(); + auto* actor = new BackgroundFileSystemChild(); result = static_cast( backgroundActor->SendPBackgroundFileSystemConstructor(actor, @@ -88,11 +95,11 @@ RefPtr GetRootProvider( } // TODO: This is just a dummy implementation -RefPtr MakeGetFileResult(const nsString& aName, const nsString& aType, +RefPtr MakeGetFileResult(nsIGlobalObject* aGlobal, const nsString& aName, + const nsString& aType, int64_t aLastModifiedMilliSeconds, - nsTArray&& aPath, - mozilla::ipc::FileDescriptor&& aFile, - nsIGlobalObject* aGlobal) { + nsTArray&& aPath, IPCBlob&& /* aFile */, + RefPtr& aActor) { // TODO: Replace with a real implementation RefPtr result = File::CreateMemoryFileWithCustomLastModified( aGlobal, static_cast(new uint8_t[1]), sizeof(uint8_t), aName, @@ -102,30 +109,40 @@ RefPtr MakeGetFileResult(const nsString& aName, const nsString& aType, } void GetDirectoryContentsResponseHandler( - RefPtr& /* aActor */, - FileSystemDirectoryListing&& aResponse, nsIGlobalObject* aGlobal, - ArrayAppendable& /* aSink */) { + nsIGlobalObject* aGlobal, FileSystemDirectoryListing&& aResponse, + ArrayAppendable& /* aSink */, RefPtr& aActor) { // TODO: Add page size to FileSystemConstants, preallocate and handle overflow nsTArray> batch; for (const auto& it : aResponse.files()) { - RefPtr handle = new FileSystemFileHandle(aGlobal, it); + RefPtr handle = + new FileSystemFileHandle(aGlobal, aActor, it); batch.AppendElement(handle); } for (const auto& it : aResponse.directories()) { RefPtr handle = - new FileSystemDirectoryHandle(aGlobal, it); + new FileSystemDirectoryHandle(aGlobal, aActor, it); batch.AppendElement(handle); } } +RefPtr MakeResolution( + nsIGlobalObject* aGlobal, FileSystemGetRootResponse&& aResponse, + const RefPtr& /* aResolution */, + const Name& aName, RefPtr& aActor) { + RefPtr result = new FileSystemDirectoryHandle( + aGlobal, aActor, FileSystemEntryMetadata(aResponse.get_EntryId(), aName)); + return result; +} + RefPtr MakeResolution( nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse, const RefPtr& /* aResolution */, const Name& aName, RefPtr& aActor) { RefPtr result = new FileSystemDirectoryHandle( - aGlobal, FileSystemEntryMetadata(aResponse.get_EntryId(), aName)); + aGlobal, aActor, FileSystemEntryMetadata(aResponse.get_EntryId(), aName)); + return result; } @@ -134,7 +151,7 @@ RefPtr MakeResolution( const RefPtr& /* aResolution */, const Name& aName, RefPtr& aActor) { RefPtr result = new FileSystemFileHandle( - aGlobal, FileSystemEntryMetadata(aResponse.get_EntryId(), aName)); + aGlobal, aActor, FileSystemEntryMetadata(aResponse.get_EntryId(), aName)); return result; } @@ -144,10 +161,10 @@ RefPtr MakeResolution(nsIGlobalObject* aGlobal, const Name& aName, RefPtr& aActor) { auto& fileProperties = aResponse.get_FileSystemFileProperties(); - return MakeGetFileResult(aName, fileProperties.type(), + return MakeGetFileResult(aGlobal, aName, fileProperties.type(), fileProperties.last_modified_ms(), std::move(fileProperties.path()), - std::move(fileProperties.file()), aGlobal); + std::move(fileProperties.file()), aActor); } template @@ -204,10 +221,10 @@ void ResolveCallback(FileSystemGetEntriesResponse&& aResponse, } GetDirectoryContentsResponseHandler( - aActor, + aPromise->GetParentObject(), std::forward( aResponse.get_FileSystemDirectoryListing()), - aPromise->GetParentObject(), aSink); + aSink, aActor); // TODO: Remove this when sink is ready aPromise->MaybeReject(NS_ERROR_NOT_IMPLEMENTED); @@ -281,16 +298,26 @@ mozilla::ipc::RejectCallback GetRejectCallback( void FileSystemRequestHandler::GetRoot( RefPtr aPromise) { // NOLINT(performance-unnecessary-value-param) + using mozilla::ipc::Endpoint; + MOZ_ASSERT(aPromise); - RefPtr dummyActor = - MakeAndAddRef(); + // Create a new IPC connection + Endpoint parentEp; + Endpoint childEp; + MOZ_ALWAYS_SUCCEEDS( + POriginPrivateFileSystem::CreateEndpoints(&parentEp, &childEp)); - Name name = kRootName; - auto&& onResolve = SelectResolveCallback actor = + MakeAndAddRef(new OriginPrivateFileSystemChild()); + if (!childEp.Bind(actor->Actor())) { + aPromise->MaybeRejectWithUndefined(); + return; + } + + auto&& onResolve = SelectResolveCallback>( - aPromise, name, dummyActor); - + aPromise, kRootName, actor); auto&& onReject = GetRejectCallback(aPromise); // XXX do something (register with global?) so that we can Close() the actor @@ -302,7 +329,8 @@ void FileSystemRequestHandler::GetRoot( aPromise->MaybeRejectWithUnknownError("Could not access the file system"); return; } - rootProvider->SendGetRoot(std::move(onResolve), std::move(onReject)); + rootProvider->SendGetRoot(std::move(parentEp), std::move(onResolve), + std::move(onReject)); } void FileSystemRequestHandler::GetDirectoryHandle( @@ -320,10 +348,9 @@ void FileSystemRequestHandler::GetDirectoryHandle( auto&& onReject = GetRejectCallback(aPromise); - auto actor = GetRootProvider(aPromise->GetGlobalObject()); - QM_TRY(OkIf(actor), QM_VOID); - actor->SendGetDirectoryHandle(request, std::move(onResolve), - std::move(onReject)); + QM_TRY(OkIf(aActor), QM_VOID); + aActor->Actor()->SendGetDirectoryHandle(request, std::move(onResolve), + std::move(onReject)); } void FileSystemRequestHandler::GetFileHandle( @@ -341,9 +368,9 @@ void FileSystemRequestHandler::GetFileHandle( auto&& onReject = GetRejectCallback(aPromise); - auto actor = GetRootProvider(aPromise->GetGlobalObject()); - QM_TRY(OkIf(actor), QM_VOID); - actor->SendGetFileHandle(request, std::move(onResolve), std::move(onReject)); + QM_TRY(OkIf(aActor), QM_VOID); + aActor->Actor()->SendGetFileHandle(request, std::move(onResolve), + std::move(onReject)); } void FileSystemRequestHandler::GetFile( @@ -360,9 +387,9 @@ void FileSystemRequestHandler::GetFile( auto&& onReject = GetRejectCallback(aPromise); - auto actor = GetRootProvider(aPromise->GetGlobalObject()); - QM_TRY(OkIf(actor), QM_VOID); - actor->SendGetFile(request, std::move(onResolve), std::move(onReject)); + QM_TRY(OkIf(aActor), QM_VOID); + aActor->Actor()->SendGetFile(request, std::move(onResolve), + std::move(onReject)); } void FileSystemRequestHandler::GetEntries( @@ -387,13 +414,13 @@ void FileSystemRequestHandler::GetEntries( auto&& onReject = GetRejectCallback(aPromise); - auto actor = GetRootProvider(aPromise->GetGlobalObject()); - QM_TRY(OkIf(actor), QM_VOID); - actor->SendGetEntries(request, std::move(onResolve), std::move(onReject)); + QM_TRY(OkIf(aActor), QM_VOID); + aActor->Actor()->SendGetEntries(request, std::move(onResolve), + std::move(onReject)); } void FileSystemRequestHandler::RemoveEntry( - RefPtr& /* aActor */, + RefPtr& aActor, const FileSystemChildMetadata& aEntry, bool aRecursive, RefPtr aPromise) { // NOLINT(performance-unnecessary-value-param) MOZ_ASSERT(!aEntry.parentId().IsEmpty()); @@ -406,9 +433,9 @@ void FileSystemRequestHandler::RemoveEntry( auto&& onReject = GetRejectCallback(aPromise); - auto actor = GetRootProvider(aPromise->GetGlobalObject()); - QM_TRY(OkIf(actor), QM_VOID); - actor->SendRemoveEntry(request, std::move(onResolve), std::move(onReject)); + QM_TRY(OkIf(aActor), QM_VOID); + aActor->Actor()->SendRemoveEntry(request, std::move(onResolve), + std::move(onReject)); } } // namespace mozilla::dom::fs diff --git a/dom/fs/child/OriginPrivateFileSystemChild.h b/dom/fs/child/OriginPrivateFileSystemChild.h new file mode 100644 index 000000000000..b101c93c1ce1 --- /dev/null +++ b/dom/fs/child/OriginPrivateFileSystemChild.h @@ -0,0 +1,24 @@ +/* -*- 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/. */ + +#ifndef DOM_FS_CHILD_ORIGINPRIVATEFILESYSTEMCHILD_H_ +#define DOM_FS_CHILD_ORIGINPRIVATEFILESYSTEMCHILD_H_ + +#include "mozilla/dom/POriginPrivateFileSystemChild.h" +#include "nsISupports.h" + +namespace mozilla::dom { + +class OriginPrivateFileSystemChild : public POriginPrivateFileSystemChild { + NS_INLINE_DECL_REFCOUNTING(OriginPrivateFileSystemChild); + + protected: + virtual ~OriginPrivateFileSystemChild() = default; +}; + +} // namespace mozilla::dom + +#endif // DOM_FS_CHILD_ORIGINPRIVATEFILESYSTEMCHILD_H_ diff --git a/dom/fs/child/moz.build b/dom/fs/child/moz.build index 5be549513609..35b19562bfb6 100644 --- a/dom/fs/child/moz.build +++ b/dom/fs/child/moz.build @@ -6,6 +6,7 @@ EXPORTS.mozilla.dom += [ "BackgroundFileSystemChild.h", + "OriginPrivateFileSystemChild.h", ] UNIFIED_SOURCES += [ diff --git a/dom/fs/include/fs/FileSystemRequestHandler.h b/dom/fs/include/fs/FileSystemRequestHandler.h index 06c90fb3ea3f..4e65bf509d89 100644 --- a/dom/fs/include/fs/FileSystemRequestHandler.h +++ b/dom/fs/include/fs/FileSystemRequestHandler.h @@ -8,6 +8,7 @@ #define DOM_FS_CHILD_FILESYSTEMREQUESTHANDLER_H_ #include "nsStringFwd.h" +#include "mozilla/dom/FileSystemActorHolder.h" #include "mozilla/dom/FileSystemTypes.h" #include "mozilla/dom/FileSystemHandle.h" @@ -16,13 +17,6 @@ class RefPtr; namespace mozilla::dom { -// TODO: Replace this dummy class with real implementation -class FileSystemActorHolder { - NS_INLINE_DECL_REFCOUNTING(FileSystemActorHolder) - protected: - virtual ~FileSystemActorHolder() = default; -}; - class FileSystemHandle; class Promise; class OriginPrivateFileSystemChild; diff --git a/dom/fs/parent/BackgroundFileSystemParent.cpp b/dom/fs/parent/BackgroundFileSystemParent.cpp index d090c4e44450..6c0230d7901e 100644 --- a/dom/fs/parent/BackgroundFileSystemParent.cpp +++ b/dom/fs/parent/BackgroundFileSystemParent.cpp @@ -5,64 +5,110 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BackgroundFileSystemParent.h" -#include "mozilla/dom/FileSystemTypes.h" +#include "OriginPrivateFileSystemParent.h" -using IPCResult = mozilla::ipc::IPCResult; +#include "nsNetCID.h" +#include "mozilla/dom/FileSystemTypes.h" +#include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/ipc/Endpoint.h" +#include "mozilla/ipc/FileDescriptorUtils.h" +#include "mozilla/Maybe.h" +#include "mozilla/MozPromise.h" +#include "mozilla/StaticPrefs_dom.h" +#include "nsServiceManagerUtils.h" + +namespace mozilla { +LazyLogModule gOPFSLog("OPFS"); +} + +#define LOG(args) MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Verbose, args) + +#define LOG_DEBUG(args) \ + MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Debug, args) namespace mozilla::dom { -IPCResult BackgroundFileSystemParent::RecvGetRoot(GetRootResolver&& aResolver) { - FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); +namespace fs::data { - return IPC_OK(); +EntryId GetRootHandle(const Origin& aOrigin) { return "not implemented"_ns; } + +// TODO: Replace with real FileSystemDataManager +class FileSystemDataManager : public FileSystemDataManagerBase { + public: + using result_t = Result; + static FileSystemDataManager::result_t CreateFileSystemDataManager( + const fs::Origin& aOrigin); +}; + +FileSystemDataManager::result_t +FileSystemDataManager::CreateFileSystemDataManager( + const fs::Origin& /*aOrigin*/) { + return nullptr; } -IPCResult BackgroundFileSystemParent::RecvGetDirectoryHandle( - FileSystemGetHandleRequest&& /* aRequest */, - GetDirectoryHandleResolver&& aResolver) { - FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); +} // namespace fs::data - return IPC_OK(); -} +using RootPromise = MozPromise; -IPCResult BackgroundFileSystemParent::RecvGetFileHandle( - FileSystemGetHandleRequest&& aRequest, GetFileHandleResolver&& aResolver) { - FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); +mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot( + Endpoint&& aParentEp, + GetRootResolver&& aResolver) { + if (!StaticPrefs::dom_fs_enabled()) { + return IPC_FAIL(this, "OPFS is disabled"); + } + if (!aParentEp.IsValid()) { + return IPC_FAIL(this, "Invalid endpoint"); + } - return IPC_OK(); -} + nsAutoCString origin = + quota::QuotaManager::GetOriginFromValidatedPrincipalInfo(mPrincipalInfo); -IPCResult BackgroundFileSystemParent::RecvGetFile( - FileSystemGetFileRequest&& aRequest, GetFileResolver&& aResolver) { - FileSystemGetFileResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); + // This opens the quota manager, which has to be done on PBackground + auto res = + fs::data::FileSystemDataManager::CreateFileSystemDataManager(origin); + if (NS_WARN_IF(res.isErr())) { + MOZ_ASSERT(false, "Can't create FileSystemDataManager"); + aResolver(fs::FileSystemGetRootResponse(NS_ERROR_FAILURE)); - return IPC_OK(); -} + return IPC_OK(); + } + nsCOMPtr pbackground = NS_GetCurrentThread(); -IPCResult BackgroundFileSystemParent::RecvResolve( - FileSystemResolveRequest&& aRequest, ResolveResolver&& aResolver) { - FileSystemResolveResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); + nsCOMPtr target = + do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); + MOZ_ASSERT(target); - return IPC_OK(); -} + nsCString name("OPFS "); + name += origin; + RefPtr taskqueue = + TaskQueue::Create(target.forget(), PromiseFlatCString(name).get()); + // We'll have to thread-hop back to this thread to respond. We could + // just have the create be one-way, then send the actual request on the + // new channel, but that's an extra IPC instead. + InvokeAsync( + taskqueue, __func__, + [origin, parentEp = std::move(aParentEp), aResolver, data = res.unwrap(), + taskqueue, pbackground]() mutable { + RefPtr parent = + new OriginPrivateFileSystemParent(taskqueue); + if (!parentEp.Bind(parent)) { + auto response = fs::FileSystemGetRootResponse(NS_ERROR_FAILURE); + return RootPromise::CreateAndReject(response, __func__); + } -IPCResult BackgroundFileSystemParent::RecvGetEntries( - FileSystemGetEntriesRequest&& aRequest, GetEntriesResolver&& aResolver) { - FileSystemGetEntriesResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); - - return IPC_OK(); -} - -IPCResult BackgroundFileSystemParent::RecvRemoveEntry( - FileSystemRemoveEntryRequest&& aRequest, RemoveEntryResolver&& aResolver) { - FileSystemRemoveEntryResponse response(NS_ERROR_NOT_IMPLEMENTED); - aResolver(response); + // Send response back to pbackground to send to child + auto response = + fs::FileSystemGetRootResponse(fs::data::GetRootHandle(origin)); + return RootPromise::CreateAndResolve(response, __func__); + }) + ->Then(GetCurrentSerialEventTarget(), __func__, + [aResolver](const RootPromise::ResolveOrRejectValue& aValue) { + if (aValue.IsReject()) { + aResolver(aValue.RejectValue()); + } else { + aResolver(aValue.ResolveValue()); + } + }); return IPC_OK(); } diff --git a/dom/fs/parent/BackgroundFileSystemParent.h b/dom/fs/parent/BackgroundFileSystemParent.h index 02d1b068ee76..4eb3822f33a3 100644 --- a/dom/fs/parent/BackgroundFileSystemParent.h +++ b/dom/fs/parent/BackgroundFileSystemParent.h @@ -10,7 +10,8 @@ #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/dom/PBackgroundFileSystemParent.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" -#include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/dom/POriginPrivateFileSystemParent.h" +#include "mozilla/TaskQueue.h" #include "nsISupports.h" namespace mozilla::dom { @@ -21,26 +22,9 @@ class BackgroundFileSystemParent : public PBackgroundFileSystemParent { const mozilla::ipc::PrincipalInfo& aPrincipalInfo) : mPrincipalInfo(aPrincipalInfo) {} - mozilla::ipc::IPCResult RecvGetRoot(GetRootResolver&& aResolver); - - mozilla::ipc::IPCResult RecvGetDirectoryHandle( - FileSystemGetHandleRequest&& aRequest, - GetDirectoryHandleResolver&& aResolver); - - mozilla::ipc::IPCResult RecvGetFileHandle( - FileSystemGetHandleRequest&& aRequest, GetFileHandleResolver&& aResolver); - - mozilla::ipc::IPCResult RecvGetFile(FileSystemGetFileRequest&& aRequest, - GetFileResolver&& aResolver); - - mozilla::ipc::IPCResult RecvResolve(FileSystemResolveRequest&& aRequest, - ResolveResolver&& aResolver); - - mozilla::ipc::IPCResult RecvGetEntries(FileSystemGetEntriesRequest&& aRequest, - GetEntriesResolver&& aResolver); - - mozilla::ipc::IPCResult RecvRemoveEntry( - FileSystemRemoveEntryRequest&& aRequest, RemoveEntryResolver&& aResolver); + mozilla::ipc::IPCResult RecvGetRoot( + Endpoint&& aParentEp, + GetRootResolver&& aResolver); NS_INLINE_DECL_REFCOUNTING(BackgroundFileSystemParent) diff --git a/dom/fs/parent/OriginPrivateFileSystemParent.cpp b/dom/fs/parent/OriginPrivateFileSystemParent.cpp new file mode 100644 index 000000000000..546ef8547c41 --- /dev/null +++ b/dom/fs/parent/OriginPrivateFileSystemParent.cpp @@ -0,0 +1,111 @@ +/* -*- 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 "OriginPrivateFileSystemParent.h" +#include "nsNetCID.h" +#include "mozilla/dom/FileSystemTypes.h" +#include "mozilla/ipc/Endpoint.h" + +using IPCResult = mozilla::ipc::IPCResult; + +namespace mozilla { +extern LazyLogModule gOPFSLog; +} + +#define LOG(args) MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Verbose, args) + +#define LOG_DEBUG(args) \ + MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Debug, args) + +namespace mozilla::dom { + +IPCResult OriginPrivateFileSystemParent::RecvGetDirectoryHandle( + FileSystemGetHandleRequest&& /* aRequest */, + GetDirectoryHandleResolver&& aResolver) { + FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvGetFileHandle( + FileSystemGetHandleRequest&& aRequest, GetFileHandleResolver&& aResolver) { + FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvGetFile( + FileSystemGetFileRequest&& aRequest, GetFileResolver&& aResolver) { + FileSystemGetFileResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvResolve( + FileSystemResolveRequest&& aRequest, ResolveResolver&& aResolver) { + FileSystemResolveResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvGetEntries( + FileSystemGetEntriesRequest&& aRequest, GetEntriesResolver&& aResolver) { + FileSystemGetEntriesResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvRemoveEntry( + FileSystemRemoveEntryRequest&& aRequest, RemoveEntryResolver&& aResolver) { + FileSystemRemoveEntryResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvCloseFile( + FileSystemGetFileRequest&& aRequest) { + LOG(("Closing file")); // painful to print out the id + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvGetAccessHandle( + FileSystemGetFileRequest&& aRequest, GetAccessHandleResolver&& aResolver) { + FileSystemGetAccessHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvGetWritable( + FileSystemGetFileRequest&& aRequest, GetWritableResolver&& aResolver) { + FileSystemGetAccessHandleResponse response(NS_ERROR_NOT_IMPLEMENTED); + aResolver(response); + + return IPC_OK(); +} + +IPCResult OriginPrivateFileSystemParent::RecvNeedQuota( + FileSystemQuotaRequest&& aRequest, NeedQuotaResolver&& aResolver) { + aResolver(0u); + + return IPC_OK(); +} + +OriginPrivateFileSystemParent::~OriginPrivateFileSystemParent() { + LOG(("Destroying OPFS Parent %p", this)); + if (mTaskQueue) { + mTaskQueue->BeginShutdown(); + } +} + +} // namespace mozilla::dom diff --git a/dom/fs/parent/OriginPrivateFileSystemParent.h b/dom/fs/parent/OriginPrivateFileSystemParent.h new file mode 100644 index 000000000000..5a69a274f450 --- /dev/null +++ b/dom/fs/parent/OriginPrivateFileSystemParent.h @@ -0,0 +1,80 @@ +/* -*- 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/. */ + +#ifndef DOM_FS_PARENT_ORIGINPRIVATEFILESYSTEMPARENT_H_ +#define DOM_FS_PARENT_ORIGINPRIVATEFILESYSTEMPARENT_H_ + +#include "ErrorList.h" +#include "mozilla/dom/PBackgroundFileSystemParent.h" +#include "mozilla/dom/POriginPrivateFileSystemParent.h" +#include "mozilla/TaskQueue.h" +#include "nsISupports.h" + +namespace mozilla { +extern LazyLogModule gOPFSLog; +} + +#define LOG(args) MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Verbose, args) + +#define LOG_DEBUG(args) \ + MOZ_LOG(mozilla::gOPFSLog, mozilla::LogLevel::Debug, args) + +namespace mozilla::dom { + +namespace fs::data { +// TODO: Replace dummy with real FileSystemDataManager +class FileSystemDataManagerBase {}; +} // namespace fs::data + +class OriginPrivateFileSystemParent : public POriginPrivateFileSystemParent { + public: + explicit OriginPrivateFileSystemParent(TaskQueue* aTaskQueue) + : mTaskQueue(aTaskQueue), mData() {} + + mozilla::ipc::IPCResult RecvGetDirectoryHandle( + FileSystemGetHandleRequest&& aRequest, + GetDirectoryHandleResolver&& aResolver); + + mozilla::ipc::IPCResult RecvGetFileHandle( + FileSystemGetHandleRequest&& aRequest, GetFileHandleResolver&& aResolver); + + mozilla::ipc::IPCResult RecvGetFile(FileSystemGetFileRequest&& aRequest, + GetFileResolver&& aResolver); + + mozilla::ipc::IPCResult RecvResolve(FileSystemResolveRequest&& aRequest, + ResolveResolver&& aResolver); + + mozilla::ipc::IPCResult RecvGetEntries(FileSystemGetEntriesRequest&& aRequest, + GetEntriesResolver&& aResolver); + + mozilla::ipc::IPCResult RecvRemoveEntry( + FileSystemRemoveEntryRequest&& aRequest, RemoveEntryResolver&& aResolver); + + mozilla::ipc::IPCResult RecvCloseFile(FileSystemGetFileRequest&& aRequest); + + mozilla::ipc::IPCResult RecvGetAccessHandle( + FileSystemGetFileRequest&& aRequest, GetAccessHandleResolver&& aResolver); + + mozilla::ipc::IPCResult RecvGetWritable(FileSystemGetFileRequest&& aRequest, + GetWritableResolver&& aResolver); + + mozilla::ipc::IPCResult RecvNeedQuota(FileSystemQuotaRequest&& aRequest, + NeedQuotaResolver&& aResolver); + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginPrivateFileSystemParent) + + protected: + virtual ~OriginPrivateFileSystemParent(); + + private: + RefPtr mTaskQueue; + + UniquePtr mData; +}; + +} // namespace mozilla::dom + +#endif // DOM_FS_PARENT_ORIGINPRIVATEFILESYSTEMPARENT_H_ diff --git a/dom/fs/parent/moz.build b/dom/fs/parent/moz.build index 6f4f2942bc1a..3b83c79f66f8 100644 --- a/dom/fs/parent/moz.build +++ b/dom/fs/parent/moz.build @@ -6,10 +6,12 @@ EXPORTS.mozilla.dom += [ "BackgroundFileSystemParent.h", + "OriginPrivateFileSystemParent.h", ] UNIFIED_SOURCES += [ "BackgroundFileSystemParent.cpp", + "OriginPrivateFileSystemParent.cpp", ] FINAL_LIBRARY = "xul" diff --git a/dom/fs/shared/FileSystemActorHolder.h b/dom/fs/shared/FileSystemActorHolder.h new file mode 100644 index 000000000000..6aede3ea4a1e --- /dev/null +++ b/dom/fs/shared/FileSystemActorHolder.h @@ -0,0 +1,15 @@ +/* -*- 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/OriginPrivateFileSystemChild.h" +#include "mozilla/ipc/ActorHolder.h" + +namespace mozilla::dom { + +using FileSystemActorHolder = + mozilla::ipc::TopLevelActorHolder; + +} // namespace mozilla::dom diff --git a/dom/fs/shared/FileSystemTypes.h b/dom/fs/shared/FileSystemTypes.h index 5517dd23584b..8f97479b5218 100644 --- a/dom/fs/shared/FileSystemTypes.h +++ b/dom/fs/shared/FileSystemTypes.h @@ -21,6 +21,7 @@ using Origin = nsCString; using PageNumber = uint32_t; using Path = nsTArray; using TimeStamp = int64_t; +using Usage = int64_t; } // namespace mozilla::dom::fs diff --git a/dom/fs/shared/PBackgroundFileSystem.ipdl b/dom/fs/shared/PBackgroundFileSystem.ipdl index e175977e14d9..644648c4372b 100644 --- a/dom/fs/shared/PBackgroundFileSystem.ipdl +++ b/dom/fs/shared/PBackgroundFileSystem.ipdl @@ -3,170 +3,22 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PBackground; +include protocol POriginPrivateFileSystem; -using mozilla::dom::fs::ContentType from "mozilla/dom/FileSystemTypes.h"; using mozilla::dom::fs::EntryId from "mozilla/dom/FileSystemTypes.h"; -using mozilla::dom::fs::Name from "mozilla/dom/FileSystemTypes.h"; -using mozilla::dom::fs::PageNumber from "mozilla/dom/FileSystemTypes.h"; -using mozilla::dom::fs::TimeStamp from "mozilla/dom/FileSystemTypes.h"; + using struct mozilla::void_t from "mozilla/ipc/IPCCore.h"; namespace mozilla { namespace dom { namespace fs { -/** - * Identifies a file or a directory and contains its user provided name. - */ -struct FileSystemEntryMetadata -{ - EntryId entryId; - Name entryName; -}; - -/** - * Identifies a file or a directory with its parent identifier and user provided name. - */ -struct FileSystemChildMetadata -{ - EntryId parentId; - Name childName; -}; - -/** - * Identifies a file with its parent directory and name, and - * indicates whether the file may be created if it is missing. - */ -struct FileSystemGetHandleRequest -{ - FileSystemChildMetadata handle; - bool create; -}; - -/** - * Contains a file or directory or an error. - */ -union FileSystemGetHandleResponse +union FileSystemGetRootResponse { nsresult; EntryId; }; -/** - * Contains an identifier for a parent directory and a page number - * which is used to fetch the next set of entries when the directory - * contains so many items that communicating all of them in one message - * is an impractical. - */ -struct FileSystemGetEntriesRequest -{ - EntryId parentId; - PageNumber page; -}; - -/** - * Contains a set of directories and files - * under the same parent directory. - */ -struct FileSystemDirectoryListing -{ - FileSystemEntryMetadata[] directories; - FileSystemEntryMetadata[] files; -}; - -/** - * Contains a set of entries or an error. - */ -union FileSystemGetEntriesResponse -{ - nsresult; - FileSystemDirectoryListing; -}; - -/** - * Contains entry handle information. - */ -struct FileSystemGetFileRequest -{ - EntryId entryId; -}; - -/** - * Contains the properties of a file and a file descriptor. - * The properties may differ from the properties of the - * underlying object of the file descriptor. - */ -struct FileSystemFileProperties -{ - TimeStamp last_modified_ms; - FileDescriptor file; - ContentType type; - Name[] path; -}; - -/** - * Contains file properties or an error. - */ -union FileSystemGetFileResponse -{ - nsresult; - FileSystemFileProperties; -}; - -/** - * Represents a pair of file system entries which - * are not necessarily connected by a path. - */ -struct FileSystemEntryPair -{ - EntryId parentId; - EntryId childId; -}; - -/** - * Contains a pair of file system entries. - */ -struct FileSystemResolveRequest -{ - FileSystemEntryPair endpoints; -}; - -/** - * Contains a file system path. - */ -struct FileSystemPath -{ - Name[] path; -}; - -/** - * Contains a potentially empty path or an error. - */ -union FileSystemResolveResponse -{ - nsresult; - FileSystemPath?; -}; - -/** - * Identifies a file with its parent directory and name, and - * indicates whether all the children of a directory may be removed. - */ -struct FileSystemRemoveEntryRequest -{ - FileSystemChildMetadata handle; - bool recursive; -}; - -/** - * Contains an error or nothing. - */ -union FileSystemRemoveEntryResponse -{ - nsresult; - void_t; -}; - } // namespace fs async protocol PBackgroundFileSystem @@ -176,115 +28,12 @@ async protocol PBackgroundFileSystem parent: /** - * Initiates an asynchronous request for the directory handle of - * the file system's root level. On first call, may conduct initialization - * activities. - * - * @returns error or entry handle + * This will set up a POriginPrivateFileSystem IPC connection */ - async GetRoot() returns(FileSystemGetHandleResponse handle); - /** - * Initiates an asynchronous request for the handle of - * a subdirectory with a given name under the current directory. - * - * Invalid names are rejected with an appropriate error. - * - * If the subdirectory exists, a handle to it is always returned. - * - * If no child of any kind with the given name exists and - * the create-flag of the input is set, the subdirectory will be created, - * otherwise an appropriate error is returned. - * - * @param[in] handle request containing a create flag - * - * @returns error or entry handle - */ - async GetDirectoryHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle); - - /** - * Initiates an asynchronous request for the handle to - * a file with a given name under the current directory. - * - * Invalid names are rejected with an appropriate error. - * - * If the file exists, a handle to it is always returned. - * - * If no child of any kind with the given name exists and - * the create-flag of the input is set, the file will be created, - * otherwise an appropriate error is returned. - * - * @param[in] handle request containing a create flag - * - * @returns error or entry handle - */ - async GetFileHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle); - - /** - * Initiates an asynchronous request for a read-only object representing the - * file corresponding to the current file handle. - * - * The returned object provides read-only access. - * - * If the underlying file object is modified through a mutable interface, - * the returned value is considered stale. Concurrent changes are not - * guaranteed to be visible or invisible. Using a stale object - * returns appropriate errors when the results are unpredictable. - * - * @param[in] request for a file object - * - * @returns error or file object - */ - async GetFile(FileSystemGetFileRequest request) returns(FileSystemGetFileResponse response); - - /** - * Initiates an asynchronous request for the file system path - * associated with a file system entry. - * - * @param[in] request identifying a file object - * - * @returns error or file system path - */ - async Resolve(FileSystemResolveRequest request) returns(FileSystemResolveResponse response); - - /** - * Initiates an asynchronous request for an iterator to the child entries under - * the current directory handle. - * - * If the directory item names or the directory structure is modified while the iterator - * is in use, the iterator remains safe to use but no guarantees are made regarding - * the visibility of the concurrent changes. It is possible that a file which is added after - * the iteration has begun will not be returned, or that among the values there - * are invalid file handles whose underlying objects have been removed - * after the iteration started. - * - * @param[in] request for a iterator - * - * @returns error or iterator - */ - async GetEntries(FileSystemGetEntriesRequest request) returns(FileSystemGetEntriesResponse entries); - - /** - * Initiates an asynchronous request to delete a directory or file with a given name - * under the current directory handle. - * - * If recursive flag of the request is not set, a request to remove a non-empty - * directory returns an appropriate error, otherwise all the child files and - * directories are made to vanish. - * - * The recursive flag has no impact on files. - * - * @param[in] request containing a recursive flag - * - * @returns error information - */ - async RemoveEntry(FileSystemRemoveEntryRequest request) returns(FileSystemRemoveEntryResponse response); + async GetRoot(Endpoint aParentEP) returns(FileSystemGetRootResponse handle); child: - - /** - * Mandatory IPC managed lifecycle request. - */ async __delete__(); }; diff --git a/dom/fs/shared/POriginPrivateFileSystem.ipdl b/dom/fs/shared/POriginPrivateFileSystem.ipdl new file mode 100644 index 000000000000..bd6504cbf857 --- /dev/null +++ b/dom/fs/shared/POriginPrivateFileSystem.ipdl @@ -0,0 +1,321 @@ +/* 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 IPCBlob; + +using mozilla::dom::fs::ContentType from "mozilla/dom/FileSystemTypes.h"; +using mozilla::dom::fs::EntryId from "mozilla/dom/FileSystemTypes.h"; +using mozilla::dom::fs::Name from "mozilla/dom/FileSystemTypes.h"; +using mozilla::dom::fs::Origin from "mozilla/dom/FileSystemTypes.h"; +using mozilla::dom::fs::PageNumber from "mozilla/dom/FileSystemTypes.h"; +using mozilla::dom::fs::TimeStamp from "mozilla/dom/FileSystemTypes.h"; +using struct mozilla::void_t from "mozilla/ipc/IPCCore.h"; + +namespace mozilla { +namespace dom { +namespace fs { + +/** + * Identifies a file or a directory and contains its user provided name. + */ +struct FileSystemEntryMetadata +{ + EntryId entryId; + Name entryName; +}; + +/** + * Identifies a file or a directory with its parent identifier and user provided name. + */ +struct FileSystemChildMetadata +{ + EntryId parentId; + Name childName; +}; + +/** + * Identifies a file with its parent directory and name, and + * indicates whether the file may be created if it is missing. + */ +struct FileSystemGetHandleRequest +{ + FileSystemChildMetadata handle; + bool create; +}; + +/** + * Contains a file or directory or an error. + */ +union FileSystemGetHandleResponse +{ + nsresult; + EntryId; +}; + +/** + * Contains an identifier for a parent directory and a page number + * which is used to fetch the next set of entries when the directory + * contains so many items that communicating all of them in one message + * is an impractical. + */ +struct FileSystemGetEntriesRequest +{ + EntryId parentId; + PageNumber page; +}; + +/** + * Contains a set of directories and files + * under the same parent directory. + */ +struct FileSystemDirectoryListing +{ + FileSystemEntryMetadata[] directories; + FileSystemEntryMetadata[] files; +}; + +/** + * Contains a set of entries or an error. + */ +union FileSystemGetEntriesResponse +{ + nsresult; + FileSystemDirectoryListing; +}; + +/** + * Contains entry handle information. + */ +struct FileSystemGetFileRequest +{ + EntryId entryId; +}; + +/** + * Contains the properties of a file and a file descriptor. + * The properties may differ from the properties of the + * underlying object of the file descriptor. + */ +struct FileSystemFileProperties +{ + TimeStamp last_modified_ms; + IPCBlob file; + ContentType type; + Name[] path; +}; + +/** + * Contains file properties or an error. + */ +union FileSystemGetFileResponse +{ + nsresult; + FileSystemFileProperties; +}; + +struct FileSystemGetAccessHandleData +{ + FileDescriptor file; +}; + +union FileSystemGetAccessHandleResponse +{ + FileSystemGetAccessHandleData; + nsresult; +}; + +/** + * Represents a pair of file system entries which + * are not necessarily connected by a path. + */ +struct FileSystemEntryPair +{ + EntryId parentId; + EntryId childId; +}; + +/** + * Contains a pair of file system entries. + */ +struct FileSystemResolveRequest +{ + FileSystemEntryPair endpoints; +}; + +/** + * Contains a file system path. + */ +struct FileSystemPath +{ + Name[] path; +}; + +/** + * Contains a potentially empty path or an error. + */ +union FileSystemResolveResponse +{ + nsresult; + FileSystemPath?; +}; + +/** + * Identifies a file with its parent directory and name, and + * indicates whether all the children of a directory may be removed. + */ +struct FileSystemRemoveEntryRequest +{ + FileSystemChildMetadata handle; + bool recursive; +}; + +/** + * Contains an error or nothing. + */ +union FileSystemRemoveEntryResponse +{ + nsresult; + void_t; +}; + +struct FileSystemQuotaRequest +{ + FileSystemChildMetadata handle; + uint64_t quotaNeeded; +}; + +} // namespace fs + +async protocol POriginPrivateFileSystem +{ + parent: + + /** + * Initiates an asynchronous request for the handle of + * a subdirectory with a given name under the current directory. + * + * Invalid names are rejected with an appropriate error. + * + * If the subdirectory exists, a handle to it is always returned. + * + * If no child of any kind with the given name exists and + * the create-flag of the input is set, the subdirectory will be created, + * otherwise an appropriate error is returned. + * + * @param[in] handle request containing a create flag + * + * @returns error or entry handle + */ + async GetDirectoryHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle); + + /** + * Initiates an asynchronous request for the handle to + * a file with a given name under the current directory. + * + * Invalid names are rejected with an appropriate error. + * + * If the file exists, a handle to it is always returned. + * + * If no child of any kind with the given name exists and + * the create-flag of the input is set, the file will be created, + * otherwise an appropriate error is returned. + * + * @param[in] handle request containing a create flag + * + * @returns error or entry handle + */ + async GetFileHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle); + + /** + * Initiates an asynchronous request for a read-only object representing the + * file corresponding to the current file handle. + * + * The returned object provides read-only access. + * + * If the underlying file object is modified through a mutable interface, + * the returned value is considered stale. Concurrent changes are not + * guaranteed to be visible or invisible. Using a stale object + * returns appropriate errors when the results are unpredictable. + * + * @param[in] request for a file object + * + * @returns error or file object + */ + async GetFile(FileSystemGetFileRequest request) returns(FileSystemGetFileResponse response); + + /** + * TODO: documentation + */ + async GetAccessHandle(FileSystemGetFileRequest request) returns(FileSystemGetAccessHandleResponse fileData); + + /** + * TODO: documentation + */ + async GetWritable(FileSystemGetFileRequest request) returns(FileSystemGetAccessHandleResponse fileData); + + /** + * Initiates an asynchronous request for the file system path + * associated with a file system entry. + * + * @param[in] request identifying a file object + * + * @returns error or file system path + */ + async Resolve(FileSystemResolveRequest request) returns(FileSystemResolveResponse response); + + /** + * Initiates an asynchronous request for an iterator to the child entries under + * the current directory handle. + * + * If the directory item names or the directory structure is modified while the iterator + * is in use, the iterator remains safe to use but no guarantees are made regarding + * the visibility of the concurrent changes. It is possible that a file which is added after + * the iteration has begun will not be returned, or that among the values there + * are invalid file handles whose underlying objects have been removed + * after the iteration started. + * + * @param[in] request for a iterator + * + * @returns error or iterator + */ + async GetEntries(FileSystemGetEntriesRequest request) returns(FileSystemGetEntriesResponse entries); + + /** + * Initiates an asynchronous request to delete a directory or file with a given name + * under the current directory handle. + * + * If recursive flag of the request is not set, a request to remove a non-empty + * directory returns an appropriate error, otherwise all the child files and + * directories are made to vanish. + * + * The recursive flag has no impact on files. + * + * @param[in] request containing a recursive flag + * + * @returns error information + */ + async RemoveEntry(FileSystemRemoveEntryRequest request) returns(FileSystemRemoveEntryResponse response); + /** + * TODO: documentation + * So we can implement exclusive access + */ + async CloseFile(FileSystemGetFileRequest request); + + /** + * Request for quota needed to finish a write, beyond the amount preallocated at creation of the AccessHandle. + * While officially async, this is used in a sync manner from write() by spinning an event loop. + */ + async NeedQuota(FileSystemQuotaRequest aRequest) returns (uint64_t aQuotaGranted); + + child: + + /** + * Mandatory IPC managed lifecycle request. + */ + async __delete__(); +}; + +} // namespace dom +} // namespace mozilla + diff --git a/dom/fs/shared/moz.build b/dom/fs/shared/moz.build index c36ea2df0b35..40e8d6a27863 100644 --- a/dom/fs/shared/moz.build +++ b/dom/fs/shared/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.dom += [ + "FileSystemActorHolder.h", "FileSystemTypes.h", ] @@ -12,6 +13,7 @@ FINAL_LIBRARY = "xul" IPDL_SOURCES += [ "PBackgroundFileSystem.ipdl", + "POriginPrivateFileSystem.ipdl", ] include("/ipc/chromium/chromium-config.mozbuild") diff --git a/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp b/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp index 41320123ec38..f3f0850b528e 100644 --- a/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp +++ b/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp @@ -13,6 +13,7 @@ #include "mozilla/dom/FileSystemDirectoryIterator.h" #include "mozilla/dom/FileSystemHandle.h" #include "mozilla/dom/FileSystemHandleBinding.h" +#include "mozilla/dom/OriginPrivateFileSystemChild.h" #include "mozilla/UniquePtr.h" #include "nsIGlobalObject.h" @@ -25,24 +26,26 @@ class TestFileSystemDirectoryHandle : public ::testing::Test { mRequestHandler = MakeUnique(); mMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns); mName = u"testDir"_ns; + mActor = MakeAndAddRef(nullptr); } nsIGlobalObject* mGlobal = GetGlobal(); UniquePtr mRequestHandler; FileSystemEntryMetadata mMetadata; nsString mName; + RefPtr mActor; }; TEST_F(TestFileSystemDirectoryHandle, constructDirectoryHandleRefPointer) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata); + MakeAndAddRef(mGlobal, mActor, mMetadata); ASSERT_TRUE(dirHandle); } TEST_F(TestFileSystemDirectoryHandle, areEntriesReturned) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -53,7 +56,7 @@ TEST_F(TestFileSystemDirectoryHandle, areEntriesReturned) { TEST_F(TestFileSystemDirectoryHandle, areKeysReturned) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -64,7 +67,7 @@ TEST_F(TestFileSystemDirectoryHandle, areKeysReturned) { TEST_F(TestFileSystemDirectoryHandle, areValuesReturned) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -75,7 +78,7 @@ TEST_F(TestFileSystemDirectoryHandle, areValuesReturned) { TEST_F(TestFileSystemDirectoryHandle, isHandleKindDirectory) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -85,7 +88,7 @@ TEST_F(TestFileSystemDirectoryHandle, isHandleKindDirectory) { TEST_F(TestFileSystemDirectoryHandle, isFileHandleReturned) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -100,7 +103,7 @@ TEST_F(TestFileSystemDirectoryHandle, isFileHandleReturned) { TEST_F(TestFileSystemDirectoryHandle, doesGetFileHandleFailOnNullGlobal) { mGlobal = nullptr; RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata); + MakeAndAddRef(mGlobal, mActor, mMetadata); ASSERT_TRUE(dirHandle); @@ -113,7 +116,7 @@ TEST_F(TestFileSystemDirectoryHandle, doesGetFileHandleFailOnNullGlobal) { TEST_F(TestFileSystemDirectoryHandle, isDirectoryHandleReturned) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -128,7 +131,7 @@ TEST_F(TestFileSystemDirectoryHandle, isDirectoryHandleReturned) { TEST_F(TestFileSystemDirectoryHandle, doesGetDirectoryHandleFailOnNullGlobal) { mGlobal = nullptr; RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata); + MakeAndAddRef(mGlobal, mActor, mMetadata); ASSERT_TRUE(dirHandle); @@ -141,7 +144,7 @@ TEST_F(TestFileSystemDirectoryHandle, doesGetDirectoryHandleFailOnNullGlobal) { TEST_F(TestFileSystemDirectoryHandle, isRemoveEntrySuccessful) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -156,7 +159,7 @@ TEST_F(TestFileSystemDirectoryHandle, isRemoveEntrySuccessful) { TEST_F(TestFileSystemDirectoryHandle, doesRemoveEntryFailOnNullGlobal) { mGlobal = nullptr; RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata); + MakeAndAddRef(mGlobal, mActor, mMetadata); ASSERT_TRUE(dirHandle); @@ -169,7 +172,7 @@ TEST_F(TestFileSystemDirectoryHandle, doesRemoveEntryFailOnNullGlobal) { TEST_F(TestFileSystemDirectoryHandle, isResolveSuccessful) { RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata, + MakeAndAddRef(mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(dirHandle); @@ -183,7 +186,7 @@ TEST_F(TestFileSystemDirectoryHandle, isResolveSuccessful) { TEST_F(TestFileSystemDirectoryHandle, doesResolveFailOnNullGlobal) { mGlobal = nullptr; RefPtr dirHandle = - MakeAndAddRef(mGlobal, mMetadata); + MakeAndAddRef(mGlobal, mActor, mMetadata); ASSERT_TRUE(dirHandle); diff --git a/dom/fs/test/gtest/api/TestFileSystemFileHandle.cpp b/dom/fs/test/gtest/api/TestFileSystemFileHandle.cpp index 2cdeb5b29120..5483979d583b 100644 --- a/dom/fs/test/gtest/api/TestFileSystemFileHandle.cpp +++ b/dom/fs/test/gtest/api/TestFileSystemFileHandle.cpp @@ -24,23 +24,25 @@ class TestFileSystemFileHandle : public ::testing::Test { void SetUp() override { mRequestHandler = MakeUnique(); mMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns); + mActor = MakeAndAddRef(nullptr); } nsIGlobalObject* mGlobal = GetGlobal(); UniquePtr mRequestHandler; FileSystemEntryMetadata mMetadata; + RefPtr mActor; }; TEST_F(TestFileSystemFileHandle, constructFileHandleRefPointer) { RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); } TEST_F(TestFileSystemFileHandle, isHandleKindFile) { RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -49,7 +51,7 @@ TEST_F(TestFileSystemFileHandle, isHandleKindFile) { TEST_F(TestFileSystemFileHandle, isFileReturned) { RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -62,7 +64,7 @@ TEST_F(TestFileSystemFileHandle, isFileReturned) { TEST_F(TestFileSystemFileHandle, doesGetFileFailOnNullGlobal) { mGlobal = nullptr; RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -74,7 +76,7 @@ TEST_F(TestFileSystemFileHandle, doesGetFileFailOnNullGlobal) { TEST_F(TestFileSystemFileHandle, isWritableReturned) { RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -88,7 +90,7 @@ TEST_F(TestFileSystemFileHandle, isWritableReturned) { TEST_F(TestFileSystemFileHandle, doesCreateWritableFailOnNullGlobal) { mGlobal = nullptr; RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -101,7 +103,7 @@ TEST_F(TestFileSystemFileHandle, doesCreateWritableFailOnNullGlobal) { TEST_F(TestFileSystemFileHandle, isSyncAccessHandleReturned) { RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); @@ -114,7 +116,7 @@ TEST_F(TestFileSystemFileHandle, isSyncAccessHandleReturned) { TEST_F(TestFileSystemFileHandle, doesCreateSyncAccessHandleFailOnNullGlobal) { mGlobal = nullptr; RefPtr fileHandle = MakeAndAddRef( - mGlobal, mMetadata, mRequestHandler.release()); + mGlobal, mActor, mMetadata, mRequestHandler.release()); ASSERT_TRUE(fileHandle); diff --git a/dom/fs/test/gtest/api/TestFileSystemHandle.cpp b/dom/fs/test/gtest/api/TestFileSystemHandle.cpp index 8804e740c83a..1dfec531314e 100644 --- a/dom/fs/test/gtest/api/TestFileSystemHandle.cpp +++ b/dom/fs/test/gtest/api/TestFileSystemHandle.cpp @@ -21,18 +21,20 @@ class TestFileSystemHandle : public ::testing::Test { void SetUp() override { mDirMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns); mFileMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns); + mActor = MakeAndAddRef(nullptr); } nsIGlobalObject* mGlobal = GetGlobal(); FileSystemEntryMetadata mDirMetadata; FileSystemEntryMetadata mFileMetadata; + RefPtr mActor; }; TEST_F(TestFileSystemHandle, createAndDestroyHandles) { RefPtr dirHandle = - new FileSystemDirectoryHandle(mGlobal, mDirMetadata); + new FileSystemDirectoryHandle(mGlobal, mActor, mDirMetadata); RefPtr fileHandle = - new FileSystemFileHandle(mGlobal, mFileMetadata); + new FileSystemFileHandle(mGlobal, mActor, mFileMetadata); EXPECT_TRUE(dirHandle); EXPECT_TRUE(fileHandle); @@ -40,9 +42,9 @@ TEST_F(TestFileSystemHandle, createAndDestroyHandles) { TEST_F(TestFileSystemHandle, areFileNamesAsExpected) { RefPtr dirHandle = - new FileSystemDirectoryHandle(mGlobal, mDirMetadata); + new FileSystemDirectoryHandle(mGlobal, mActor, mDirMetadata); RefPtr fileHandle = - new FileSystemFileHandle(mGlobal, mFileMetadata); + new FileSystemFileHandle(mGlobal, mActor, mFileMetadata); auto GetEntryName = [](const RefPtr& aHandle) { DOMString domName; @@ -62,16 +64,16 @@ TEST_F(TestFileSystemHandle, areFileNamesAsExpected) { TEST_F(TestFileSystemHandle, isParentObjectReturned) { ASSERT_TRUE(mGlobal); RefPtr dirHandle = - new FileSystemDirectoryHandle(mGlobal, mDirMetadata); + new FileSystemDirectoryHandle(mGlobal, mActor, mDirMetadata); ASSERT_EQ(mGlobal, dirHandle->GetParentObject()); } TEST_F(TestFileSystemHandle, areHandleKindsAsExpected) { RefPtr dirHandle = - new FileSystemDirectoryHandle(mGlobal, mDirMetadata); + new FileSystemDirectoryHandle(mGlobal, mActor, mDirMetadata); RefPtr fileHandle = - new FileSystemFileHandle(mGlobal, mFileMetadata); + new FileSystemFileHandle(mGlobal, mActor, mFileMetadata); EXPECT_EQ(FileSystemHandleKind::Directory, dirHandle->Kind()); EXPECT_EQ(FileSystemHandleKind::File, fileHandle->Kind()); @@ -79,9 +81,9 @@ TEST_F(TestFileSystemHandle, areHandleKindsAsExpected) { TEST_F(TestFileSystemHandle, isDifferentEntry) { RefPtr dirHandle = - new FileSystemDirectoryHandle(mGlobal, mDirMetadata); + new FileSystemDirectoryHandle(mGlobal, mActor, mDirMetadata); RefPtr fileHandle = - new FileSystemFileHandle(mGlobal, mFileMetadata); + new FileSystemFileHandle(mGlobal, mActor, mFileMetadata); IgnoredErrorResult rv; RefPtr promise = dirHandle->IsSameEntry(*fileHandle, rv); @@ -92,7 +94,7 @@ TEST_F(TestFileSystemHandle, isDifferentEntry) { TEST_F(TestFileSystemHandle, isSameEntry) { RefPtr fileHandle = - new FileSystemFileHandle(mGlobal, mFileMetadata); + new FileSystemFileHandle(mGlobal, mActor, mFileMetadata); IgnoredErrorResult rv; RefPtr promise = fileHandle->IsSameEntry(*fileHandle, rv); diff --git a/dom/fs/test/gtest/child/TestFileSystemRequestHandler.cpp b/dom/fs/test/gtest/child/TestFileSystemRequestHandler.cpp index 6d586550606a..43557b28d980 100644 --- a/dom/fs/test/gtest/child/TestFileSystemRequestHandler.cpp +++ b/dom/fs/test/gtest/child/TestFileSystemRequestHandler.cpp @@ -8,6 +8,7 @@ #include "FileSystemMocks.h" #include "fs/FileSystemRequestHandler.h" +#include "mozilla/dom/OriginPrivateFileSystemChild.h" #include "mozilla/SpinEventLoopUntil.h" #include "mozilla/UniquePtr.h" @@ -23,7 +24,7 @@ class TestFileSystemRequestHandler : public ::testing::Test { mChild = FileSystemChildMetadata("parent"_ns, u"ChildName"_ns); mEntry = FileSystemEntryMetadata("myid"_ns, u"EntryName"_ns); mName = u"testDir"_ns; - mActor = MakeAndAddRef(); + mActor = MakeAndAddRef(nullptr); } already_AddRefed GetDefaultPromise() { diff --git a/ipc/glue/ActorHolder.h b/ipc/glue/ActorHolder.h new file mode 100644 index 000000000000..fb1c2a97345f --- /dev/null +++ b/ipc/glue/ActorHolder.h @@ -0,0 +1,45 @@ +/* -*- 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/. */ + +#ifndef MOZILLA_IPC_ACTORHOLDER_H +#define MOZILLA_IPC_ACTORHOLDER_H + +#include "nsISupports.h" + +namespace mozilla::ipc { + +// Class to let us close the actor when we're not using it anymore. You +// should create a single instance of this, and when you have no more +// references it will be destroyed and will Close() the underlying +// top-level channel. +// When you want to send something, you use something like +// aActor->Actor()->SendFoo() + +// You can avoid calling Close() on an un-connected Actor (for example if +// Bind() fails) by calling RemoveActor(); +template +class TopLevelActorHolder final { + public: + NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(TopLevelActorHolder) + + explicit TopLevelActorHolder(T* aActor) : mActor(aActor) {} + + constexpr T* Actor() const { return mActor; } + inline void RemoveActor() { mActor = nullptr; } + + private: + inline ~TopLevelActorHolder() { + if (mActor) { + mActor->Close(); + } + } + + RefPtr mActor; +}; + +} // namespace mozilla::ipc + +#endif // MOZILLA_IPC_ACTORHOLDER_H diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build index c4b7c1d69e86..9f1a571ad483 100644 --- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -10,6 +10,7 @@ EXPORTS += [ ] EXPORTS.mozilla.ipc += [ + "ActorHolder.h", "AsyncBlockers.h", "BackgroundChild.h", "BackgroundParent.h",