mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1768050: Test request handler. r=jesup
Depends on D147273 Differential Revision: https://phabricator.services.mozilla.com/D149983
This commit is contained in:
parent
3a934f66ac
commit
96bbb1edea
@ -68,6 +68,7 @@ class FileSystemHandle : public nsISupports, public nsWrapperCache {
|
||||
virtual ~FileSystemHandle() = default;
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
|
||||
RefPtr<FileSystemActorHolder> mActor;
|
||||
|
||||
const fs::FileSystemEntryMetadata mMetadata;
|
||||
|
103
dom/fs/child/FileSystemChildFactory.cpp
Normal file
103
dom/fs/child/FileSystemChildFactory.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- 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 "fs/FileSystemChildFactory.h"
|
||||
#include "mozilla/dom/POriginPrivateFileSystemChild.h"
|
||||
#include "mozilla/dom/OriginPrivateFileSystemChild.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla::dom::fs {
|
||||
|
||||
namespace {
|
||||
|
||||
using ResolveGetHandle =
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetHandleResponse>;
|
||||
using ResolveGetFile =
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetFileResponse>;
|
||||
using ResolveResolve =
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemResolveResponse>;
|
||||
using ResolveGetEntries =
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetEntriesResponse>;
|
||||
using ResolveRemoveEntry =
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemRemoveEntryResponse>;
|
||||
using DoReject = mozilla::ipc::RejectCallback;
|
||||
|
||||
class OriginPrivateFileSystemChildImpl final
|
||||
: public OriginPrivateFileSystemChild {
|
||||
public:
|
||||
class TOriginPrivateFileSystem final : public POriginPrivateFileSystemChild {
|
||||
NS_INLINE_DECL_REFCOUNTING(TOriginPrivateFileSystem);
|
||||
|
||||
protected:
|
||||
~TOriginPrivateFileSystem() = default;
|
||||
};
|
||||
|
||||
OriginPrivateFileSystemChildImpl() : mImpl(new TOriginPrivateFileSystem()) {}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(OriginPrivateFileSystemChildImpl, override)
|
||||
|
||||
void SendGetDirectoryHandle(const fs::FileSystemGetHandleRequest& aRequest,
|
||||
ResolveGetHandle&& aResolve,
|
||||
DoReject&& aReject) override {
|
||||
mImpl->SendGetDirectoryHandle(aRequest,
|
||||
std::forward<ResolveGetHandle>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
void SendGetFileHandle(const fs::FileSystemGetHandleRequest& aRequest,
|
||||
ResolveGetHandle&& aResolve,
|
||||
DoReject&& aReject) override {
|
||||
mImpl->SendGetFileHandle(aRequest, std::forward<ResolveGetHandle>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
void SendGetFile(const fs::FileSystemGetFileRequest& aRequest,
|
||||
ResolveGetFile&& aResolve, DoReject&& aReject) override {
|
||||
mImpl->SendGetFile(aRequest, std::forward<ResolveGetFile>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
void SendResolve(const fs::FileSystemResolveRequest& aRequest,
|
||||
ResolveResolve&& aResolve, DoReject&& aReject) override {
|
||||
mImpl->SendResolve(aRequest, std::forward<ResolveResolve>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
void SendGetEntries(const fs::FileSystemGetEntriesRequest& aRequest,
|
||||
ResolveGetEntries&& aResolve,
|
||||
DoReject&& aReject) override {
|
||||
mImpl->SendGetEntries(aRequest, std::forward<ResolveGetEntries>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
void SendRemoveEntry(const fs::FileSystemRemoveEntryRequest& aRequest,
|
||||
ResolveRemoveEntry&& aResolve,
|
||||
DoReject&& aReject) override {
|
||||
mImpl->SendRemoveEntry(aRequest, std::forward<ResolveRemoveEntry>(aResolve),
|
||||
std::forward<DoReject>(aReject));
|
||||
}
|
||||
|
||||
virtual bool IsCloseable() const override { return mImpl->IsOnCxxStack(); }
|
||||
|
||||
void Close() override { mImpl->Close(); }
|
||||
|
||||
POriginPrivateFileSystemChild* AsBindable() override { return mImpl.get(); };
|
||||
|
||||
protected:
|
||||
~OriginPrivateFileSystemChildImpl() = default;
|
||||
|
||||
const RefPtr<TOriginPrivateFileSystem> mImpl;
|
||||
}; // class OriginPrivateFileSystemChildImpl
|
||||
|
||||
} // namespace
|
||||
|
||||
already_AddRefed<OriginPrivateFileSystemChild> FileSystemChildFactory::Create()
|
||||
const {
|
||||
return MakeAndAddRef<OriginPrivateFileSystemChildImpl>();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::fs
|
@ -15,9 +15,9 @@
|
||||
#include "mozilla/dom/FileSystemDirectoryHandle.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
|
||||
namespace mozilla::dom::fs {
|
||||
@ -192,6 +192,11 @@ void ResolveCallback(
|
||||
MOZ_ASSERT(aPromise);
|
||||
QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID);
|
||||
|
||||
if (FileSystemRemoveEntryResponse::Tvoid_t == aResponse.type()) {
|
||||
aPromise->MaybeResolveWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(FileSystemRemoveEntryResponse::Tnsresult == aResponse.type());
|
||||
const auto& status = aResponse.get_nsresult();
|
||||
if (NS_ERROR_FILE_ACCESS_DENIED == status) {
|
||||
@ -279,7 +284,7 @@ void IPCRejectReporter(mozilla::ipc::ResponseRejectReason aReason) {
|
||||
}
|
||||
}
|
||||
|
||||
void RejectHandler(
|
||||
void RejectCallback(
|
||||
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
|
||||
mozilla::ipc::ResponseRejectReason aReason) {
|
||||
IPCRejectReporter(aReason);
|
||||
@ -291,7 +296,7 @@ mozilla::ipc::RejectCallback GetRejectCallback(
|
||||
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
|
||||
return static_cast<mozilla::ipc::RejectCallback>(
|
||||
// NOLINTNEXTLINE(modernize-avoid-bind)
|
||||
std::bind(RejectHandler, aPromise, std::placeholders::_1));
|
||||
std::bind(RejectCallback, aPromise, std::placeholders::_1));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -309,8 +314,8 @@ void FileSystemRequestHandler::GetRoot(
|
||||
POriginPrivateFileSystem::CreateEndpoints(&parentEp, &childEp));
|
||||
|
||||
RefPtr<FileSystemActorHolder> actor =
|
||||
MakeAndAddRef<FileSystemActorHolder>(new OriginPrivateFileSystemChild());
|
||||
if (!childEp.Bind(actor->Actor())) {
|
||||
MakeAndAddRef<FileSystemActorHolder>(mChildFactory->Create().take());
|
||||
if (!childEp.Bind(actor->Actor()->AsBindable())) {
|
||||
aPromise->MaybeRejectWithUndefined();
|
||||
return;
|
||||
}
|
||||
@ -348,7 +353,9 @@ void FileSystemRequestHandler::GetDirectoryHandle(
|
||||
|
||||
auto&& onReject = GetRejectCallback(aPromise);
|
||||
|
||||
QM_TRY(OkIf(aActor), QM_VOID);
|
||||
QM_TRY(OkIf(aActor), QM_VOID, [aPromise](const auto&) {
|
||||
aPromise->MaybeRejectWithUnknownError("Invalid actor");
|
||||
});
|
||||
aActor->Actor()->SendGetDirectoryHandle(request, std::move(onResolve),
|
||||
std::move(onReject));
|
||||
}
|
||||
@ -368,7 +375,9 @@ void FileSystemRequestHandler::GetFileHandle(
|
||||
|
||||
auto&& onReject = GetRejectCallback(aPromise);
|
||||
|
||||
QM_TRY(OkIf(aActor), QM_VOID);
|
||||
QM_TRY(OkIf(aActor), QM_VOID, [aPromise](const auto&) {
|
||||
aPromise->MaybeRejectWithUnknownError("Invalid actor");
|
||||
});
|
||||
aActor->Actor()->SendGetFileHandle(request, std::move(onResolve),
|
||||
std::move(onReject));
|
||||
}
|
||||
@ -387,7 +396,9 @@ void FileSystemRequestHandler::GetFile(
|
||||
|
||||
auto&& onReject = GetRejectCallback(aPromise);
|
||||
|
||||
QM_TRY(OkIf(aActor), QM_VOID);
|
||||
QM_TRY(OkIf(aActor), QM_VOID, [aPromise](const auto&) {
|
||||
aPromise->MaybeRejectWithUnknownError("Invalid actor");
|
||||
});
|
||||
aActor->Actor()->SendGetFile(request, std::move(onResolve),
|
||||
std::move(onReject));
|
||||
}
|
||||
@ -414,7 +425,9 @@ void FileSystemRequestHandler::GetEntries(
|
||||
|
||||
auto&& onReject = GetRejectCallback(aPromise);
|
||||
|
||||
QM_TRY(OkIf(aActor), QM_VOID);
|
||||
QM_TRY(OkIf(aActor), QM_VOID, [aPromise](const auto&) {
|
||||
aPromise->MaybeRejectWithUnknownError("Invalid actor");
|
||||
});
|
||||
aActor->Actor()->SendGetEntries(request, std::move(onResolve),
|
||||
std::move(onReject));
|
||||
}
|
||||
@ -433,7 +446,9 @@ void FileSystemRequestHandler::RemoveEntry(
|
||||
|
||||
auto&& onReject = GetRejectCallback(aPromise);
|
||||
|
||||
QM_TRY(OkIf(aActor), QM_VOID);
|
||||
QM_TRY(OkIf(aActor), QM_VOID, [aPromise](const auto&) {
|
||||
aPromise->MaybeRejectWithUnknownError("Invalid actor");
|
||||
});
|
||||
aActor->Actor()->SendRemoveEntry(request, std::move(onResolve),
|
||||
std::move(onReject));
|
||||
}
|
||||
|
@ -8,12 +8,52 @@
|
||||
#define DOM_FS_CHILD_ORIGINPRIVATEFILESYSTEMCHILD_H_
|
||||
|
||||
#include "mozilla/dom/POriginPrivateFileSystemChild.h"
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class OriginPrivateFileSystemChild : public POriginPrivateFileSystemChild {
|
||||
NS_INLINE_DECL_REFCOUNTING(OriginPrivateFileSystemChild);
|
||||
class OriginPrivateFileSystemChild {
|
||||
public:
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
|
||||
virtual void SendGetDirectoryHandle(
|
||||
const fs::FileSystemGetHandleRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetHandleResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual void SendGetFileHandle(
|
||||
const fs::FileSystemGetHandleRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetHandleResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual void SendGetFile(
|
||||
const fs::FileSystemGetFileRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetFileResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual void SendResolve(
|
||||
const fs::FileSystemResolveRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemResolveResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual void SendGetEntries(
|
||||
const fs::FileSystemGetEntriesRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemGetEntriesResponse>&&
|
||||
aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual void SendRemoveEntry(
|
||||
const fs::FileSystemRemoveEntryRequest& request,
|
||||
mozilla::ipc::ResolveCallback<fs::FileSystemRemoveEntryResponse>&&
|
||||
aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject) = 0;
|
||||
|
||||
virtual bool IsCloseable() const = 0;
|
||||
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual POriginPrivateFileSystemChild* AsBindable() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~OriginPrivateFileSystemChild() = default;
|
||||
|
@ -10,6 +10,7 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"FileSystemChildFactory.cpp",
|
||||
"FileSystemRequestHandler.cpp",
|
||||
]
|
||||
|
||||
|
33
dom/fs/include/fs/FileSystemChildFactory.h
Normal file
33
dom/fs/include/fs/FileSystemChildFactory.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- 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_FILESYSTEMCHILDFACTORY_H_
|
||||
#define DOM_FS_FILESYSTEMCHILDFACTORY_H_
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
class OriginPrivateFileSystemChild;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla::dom::fs {
|
||||
|
||||
class FileSystemChildFactory {
|
||||
public:
|
||||
virtual already_AddRefed<OriginPrivateFileSystemChild> Create() const;
|
||||
|
||||
virtual ~FileSystemChildFactory() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom::fs
|
||||
|
||||
#endif // DOM_FS_FILESYSTEMCHILDFACTORY_H_
|
@ -7,16 +7,16 @@
|
||||
#ifndef DOM_FS_CHILD_FILESYSTEMREQUESTHANDLER_H_
|
||||
#define DOM_FS_CHILD_FILESYSTEMREQUESTHANDLER_H_
|
||||
|
||||
#include "nsStringFwd.h"
|
||||
#include "mozilla/dom/FileSystemActorHolder.h"
|
||||
#include "fs/FileSystemChildFactory.h"
|
||||
|
||||
#include "mozilla/dom/FileSystemTypes.h"
|
||||
#include "mozilla/dom/FileSystemHandle.h"
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
template <class T>
|
||||
class RefPtr;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class FileSystemHandle;
|
||||
class Promise;
|
||||
class OriginPrivateFileSystemChild;
|
||||
@ -31,6 +31,12 @@ class ArrayAppendable {};
|
||||
|
||||
class FileSystemRequestHandler {
|
||||
public:
|
||||
explicit FileSystemRequestHandler(FileSystemChildFactory* aChildFactory)
|
||||
: mChildFactory(aChildFactory) {}
|
||||
|
||||
FileSystemRequestHandler()
|
||||
: FileSystemRequestHandler(new FileSystemChildFactory()) {}
|
||||
|
||||
virtual void GetRoot(RefPtr<Promise> aPromise);
|
||||
|
||||
virtual void GetDirectoryHandle(RefPtr<FileSystemActorHolder>& aActor,
|
||||
@ -54,6 +60,10 @@ class FileSystemRequestHandler {
|
||||
bool aRecursive, RefPtr<Promise> aPromise);
|
||||
|
||||
virtual ~FileSystemRequestHandler() = default;
|
||||
|
||||
protected:
|
||||
const UniquePtr<FileSystemChildFactory> mChildFactory;
|
||||
|
||||
}; // class FileSystemRequestHandler
|
||||
|
||||
} // namespace mozilla::dom::fs
|
||||
|
@ -9,11 +9,11 @@
|
||||
|
||||
#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/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
@ -53,12 +53,14 @@ using RootPromise = MozPromise<fs::FileSystemGetRootResponse, nsresult, false>;
|
||||
mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot(
|
||||
Endpoint<POriginPrivateFileSystemParent>&& aParentEp,
|
||||
GetRootResolver&& aResolver) {
|
||||
if (!StaticPrefs::dom_fs_enabled()) {
|
||||
return IPC_FAIL(this, "OPFS is disabled");
|
||||
}
|
||||
if (!aParentEp.IsValid()) {
|
||||
return IPC_FAIL(this, "Invalid endpoint");
|
||||
}
|
||||
QM_TRY(
|
||||
OkIf(StaticPrefs::dom_fs_enabled()), IPC_OK(), [aResolver](const auto&) {
|
||||
aResolver(fs::FileSystemGetRootResponse(NS_ERROR_DOM_NOT_ALLOWED_ERR));
|
||||
});
|
||||
|
||||
QM_TRY(OkIf(aParentEp.IsValid()), IPC_OK(), [aResolver](const auto&) {
|
||||
aResolver(fs::FileSystemGetRootResponse(NS_ERROR_INVALID_ARG));
|
||||
});
|
||||
|
||||
nsAutoCString origin =
|
||||
quota::QuotaManager::GetOriginFromValidatedPrincipalInfo(mPrincipalInfo);
|
||||
@ -66,12 +68,11 @@ mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot(
|
||||
// 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));
|
||||
QM_TRY(OkIf(res.isErr()), IPC_OK(), [aResolver](const auto&) {
|
||||
aResolver(fs::FileSystemGetRootResponse(NS_ERROR_UNEXPECTED));
|
||||
});
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
UniquePtr<fs::data::FileSystemDataManager> data(res.unwrap());
|
||||
nsCOMPtr<nsIThread> pbackground = NS_GetCurrentThread();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
@ -87,8 +88,8 @@ mozilla::ipc::IPCResult BackgroundFileSystemParent::RecvGetRoot(
|
||||
// new channel, but that's an extra IPC instead.
|
||||
InvokeAsync(
|
||||
taskqueue, __func__,
|
||||
[origin, parentEp = std::move(aParentEp), aResolver, data = res.unwrap(),
|
||||
taskqueue, pbackground]() mutable {
|
||||
[origin, parentEp = std::move(aParentEp), aResolver,
|
||||
data = std::move(data), taskqueue, pbackground]() mutable {
|
||||
RefPtr<OriginPrivateFileSystemParent> parent =
|
||||
new OriginPrivateFileSystemParent(taskqueue);
|
||||
if (!parentEp.Bind(parent)) {
|
||||
|
@ -9,8 +9,8 @@
|
||||
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/dom/PBackgroundFileSystemParent.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/dom/POriginPrivateFileSystemParent.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
@ -23,7 +23,7 @@ class BackgroundFileSystemParent : public PBackgroundFileSystemParent {
|
||||
: mPrincipalInfo(aPrincipalInfo) {}
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetRoot(
|
||||
Endpoint<POriginPrivateFileSystemParent>&& aParentEp,
|
||||
mozilla::ipc::Endpoint<POriginPrivateFileSystemParent>&& aParentEp,
|
||||
GetRootResolver&& aResolver);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(BackgroundFileSystemParent)
|
||||
|
@ -5,11 +5,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/OriginPrivateFileSystemChild.h"
|
||||
#include "mozilla/ipc/ActorHolder.h"
|
||||
#include "mozilla/ipc/ToplevelActorHolder.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
using FileSystemActorHolder =
|
||||
mozilla::ipc::TopLevelActorHolder<OriginPrivateFileSystemChild>;
|
||||
mozilla::ipc::ToplevelActorHolder<OriginPrivateFileSystemChild>;
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -7,8 +7,6 @@ include protocol POriginPrivateFileSystem;
|
||||
|
||||
using mozilla::dom::fs::EntryId from "mozilla/dom/FileSystemTypes.h";
|
||||
|
||||
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace fs {
|
||||
@ -30,7 +28,6 @@ async protocol PBackgroundFileSystem
|
||||
/**
|
||||
* This will set up a POriginPrivateFileSystem IPC connection
|
||||
*/
|
||||
|
||||
async GetRoot(Endpoint<POriginPrivateFileSystemParent> aParentEP) returns(FileSystemGetRootResponse handle);
|
||||
|
||||
child:
|
||||
|
@ -26,7 +26,8 @@ struct FileSystemEntryMetadata
|
||||
};
|
||||
|
||||
/**
|
||||
* Identifies a file or a directory with its parent identifier and user provided name.
|
||||
* Identifies a file or a directory with its parent identifier and
|
||||
* user provided name.
|
||||
*/
|
||||
struct FileSystemChildMetadata
|
||||
{
|
||||
@ -207,7 +208,8 @@ async protocol POriginPrivateFileSystem
|
||||
*
|
||||
* @returns error or entry handle
|
||||
*/
|
||||
async GetDirectoryHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle);
|
||||
async GetDirectoryHandle(FileSystemGetHandleRequest request)
|
||||
returns(FileSystemGetHandleResponse handle);
|
||||
|
||||
/**
|
||||
* Initiates an asynchronous request for the handle to
|
||||
@ -225,7 +227,8 @@ async protocol POriginPrivateFileSystem
|
||||
*
|
||||
* @returns error or entry handle
|
||||
*/
|
||||
async GetFileHandle(FileSystemGetHandleRequest request) returns(FileSystemGetHandleResponse handle);
|
||||
async GetFileHandle(FileSystemGetHandleRequest request)
|
||||
returns(FileSystemGetHandleResponse handle);
|
||||
|
||||
/**
|
||||
* Initiates an asynchronous request for a read-only object representing the
|
||||
@ -242,17 +245,20 @@ async protocol POriginPrivateFileSystem
|
||||
*
|
||||
* @returns error or file object
|
||||
*/
|
||||
async GetFile(FileSystemGetFileRequest request) returns(FileSystemGetFileResponse response);
|
||||
async GetFile(FileSystemGetFileRequest request)
|
||||
returns(FileSystemGetFileResponse response);
|
||||
|
||||
/**
|
||||
* TODO: documentation
|
||||
*/
|
||||
async GetAccessHandle(FileSystemGetFileRequest request) returns(FileSystemGetAccessHandleResponse fileData);
|
||||
async GetAccessHandle(FileSystemGetFileRequest request)
|
||||
returns(FileSystemGetAccessHandleResponse fileData);
|
||||
|
||||
/**
|
||||
* TODO: documentation
|
||||
*/
|
||||
async GetWritable(FileSystemGetFileRequest request) returns(FileSystemGetAccessHandleResponse fileData);
|
||||
async GetWritable(FileSystemGetFileRequest request)
|
||||
returns(FileSystemGetAccessHandleResponse fileData);
|
||||
|
||||
/**
|
||||
* Initiates an asynchronous request for the file system path
|
||||
@ -262,32 +268,35 @@ async protocol POriginPrivateFileSystem
|
||||
*
|
||||
* @returns error or file system path
|
||||
*/
|
||||
async Resolve(FileSystemResolveRequest request) returns(FileSystemResolveResponse response);
|
||||
async Resolve(FileSystemResolveRequest request)
|
||||
returns(FileSystemResolveResponse response);
|
||||
|
||||
/**
|
||||
* Initiates an asynchronous request for an iterator to the child entries under
|
||||
* the current directory handle.
|
||||
* Initiates an asynchronous request for an iterator to the child entries
|
||||
* under the calling 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.
|
||||
* 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);
|
||||
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.
|
||||
* Initiates an asynchronous request to delete a directory or file with a
|
||||
* given name under the calling 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.
|
||||
* 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.
|
||||
*
|
||||
@ -295,7 +304,9 @@ async protocol POriginPrivateFileSystem
|
||||
*
|
||||
* @returns error information
|
||||
*/
|
||||
async RemoveEntry(FileSystemRemoveEntryRequest request) returns(FileSystemRemoveEntryResponse response);
|
||||
async RemoveEntry(FileSystemRemoveEntryRequest request)
|
||||
returns(FileSystemRemoveEntryResponse response);
|
||||
|
||||
/**
|
||||
* TODO: documentation
|
||||
* So we can implement exclusive access
|
||||
@ -303,10 +314,12 @@ async protocol POriginPrivateFileSystem
|
||||
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.
|
||||
* 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);
|
||||
async NeedQuota(FileSystemQuotaRequest aRequest)
|
||||
returns (uint64_t aQuotaGranted);
|
||||
|
||||
child:
|
||||
|
||||
|
@ -11,12 +11,15 @@
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "TestHelpers.h"
|
||||
|
||||
#include "fs/FileSystemRequestHandler.h"
|
||||
#include "fs/FileSystemChildFactory.h"
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/OriginPrivateFileSystemChild.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
@ -24,6 +27,7 @@
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
@ -39,29 +43,36 @@ nsIGlobalObject* GetGlobal();
|
||||
|
||||
class MockFileSystemRequestHandler : public FileSystemRequestHandler {
|
||||
public:
|
||||
MOCK_METHOD1(GetRoot, void(RefPtr<Promise> aPromise));
|
||||
MOCK_METHOD(void, GetRoot, (RefPtr<Promise> aPromise), (override));
|
||||
|
||||
MOCK_METHOD4(GetDirectoryHandle,
|
||||
void(RefPtr<FileSystemActorHolder>& aActor,
|
||||
const FileSystemChildMetadata& aDirectory, bool aCreate,
|
||||
RefPtr<Promise> aPromise));
|
||||
MOCK_METHOD(void, GetDirectoryHandle,
|
||||
(RefPtr<FileSystemActorHolder> & aActor,
|
||||
const FileSystemChildMetadata& aDirectory, bool aCreate,
|
||||
RefPtr<Promise> aPromise),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD4(GetFileHandle, void(RefPtr<FileSystemActorHolder>& aActor,
|
||||
const FileSystemChildMetadata& aFile,
|
||||
bool aCreate, RefPtr<Promise> aPromise));
|
||||
MOCK_METHOD(void, GetFileHandle,
|
||||
(RefPtr<FileSystemActorHolder> & aActor,
|
||||
const FileSystemChildMetadata& aFile, bool aCreate,
|
||||
RefPtr<Promise> aPromise),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD3(GetFile, void(RefPtr<FileSystemActorHolder>& aActor,
|
||||
const FileSystemEntryMetadata& aFile,
|
||||
RefPtr<Promise> aPromise));
|
||||
MOCK_METHOD(void, GetFile,
|
||||
(RefPtr<FileSystemActorHolder> & aActor,
|
||||
const FileSystemEntryMetadata& aFile, RefPtr<Promise> aPromise),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD5(GetEntries,
|
||||
void(RefPtr<FileSystemActorHolder>& aActor,
|
||||
const EntryId& aDirectory, PageNumber aPage,
|
||||
RefPtr<Promise> aPromise, ArrayAppendable& aSink));
|
||||
MOCK_METHOD(void, GetEntries,
|
||||
(RefPtr<FileSystemActorHolder> & aActor,
|
||||
const EntryId& aDirectory, PageNumber aPage,
|
||||
RefPtr<Promise> aPromise, ArrayAppendable& aSink),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD4(RemoveEntry, void(RefPtr<FileSystemActorHolder>& aActor,
|
||||
const FileSystemChildMetadata& aEntry,
|
||||
bool aRecursive, RefPtr<Promise> aPromise));
|
||||
MOCK_METHOD(void, RemoveEntry,
|
||||
(RefPtr<FileSystemActorHolder> & aActor,
|
||||
const FileSystemChildMetadata& aEntry, bool aRecursive,
|
||||
RefPtr<Promise> aPromise),
|
||||
(override));
|
||||
};
|
||||
|
||||
class WaitablePromiseListener {
|
||||
@ -83,7 +94,11 @@ template <class SuccessHandler, class ErrorHandler,
|
||||
class TestPromiseListener : public PromiseNativeHandler,
|
||||
public WaitablePromiseListener {
|
||||
public:
|
||||
TestPromiseListener() : mIsDone(std::make_shared<bool>(false)), mTimer() {
|
||||
TestPromiseListener()
|
||||
: mIsDone(std::make_shared<bool>(false)),
|
||||
mTimer(),
|
||||
mOnSuccess(),
|
||||
mOnError() {
|
||||
ClearDone();
|
||||
}
|
||||
|
||||
@ -102,17 +117,23 @@ class TestPromiseListener : public PromiseNativeHandler,
|
||||
|
||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
ErrorResult& aRv) override {
|
||||
mozilla::ScopeExit flagAsDone([isDone = mIsDone] { *isDone = true; });
|
||||
mozilla::ScopeExit flagAsDone([isDone = mIsDone, timer = mTimer] {
|
||||
timer->Cancel();
|
||||
*isDone = true;
|
||||
});
|
||||
|
||||
SuccessHandler{}();
|
||||
mOnSuccess();
|
||||
}
|
||||
|
||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
ErrorResult& aRv) override {
|
||||
mozilla::ScopeExit flagAsDone([isDone = mIsDone] { *isDone = true; });
|
||||
mozilla::ScopeExit flagAsDone([isDone = mIsDone, timer = mTimer] {
|
||||
timer->Cancel();
|
||||
*isDone = true;
|
||||
});
|
||||
|
||||
if (aValue.isInt32()) {
|
||||
ErrorHandler{}(static_cast<nsresult>(aValue.toInt32()));
|
||||
mOnError(static_cast<nsresult>(aValue.toInt32()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -122,7 +143,7 @@ class TestPromiseListener : public PromiseNativeHandler,
|
||||
RefPtr<Exception> exception;
|
||||
UNWRAP_OBJECT(Exception, exceptionObject, exception);
|
||||
if (exception) {
|
||||
ErrorHandler{}(static_cast<nsresult>(exception->Result()));
|
||||
mOnError(static_cast<nsresult>(exception->Result()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -136,6 +157,7 @@ class TestPromiseListener : public PromiseNativeHandler,
|
||||
}
|
||||
auto timerCallback = [isDone = mIsDone](nsITimer* aTimer) {
|
||||
*isDone = true;
|
||||
FAIL() << "Timed out!";
|
||||
};
|
||||
const char* timerName = "fs::TestPromiseListener::ClearDone";
|
||||
auto res = NS_NewTimerWithCallback(timerCallback, MilliSeconds,
|
||||
@ -149,12 +171,106 @@ class TestPromiseListener : public PromiseNativeHandler,
|
||||
|
||||
PromiseNativeHandler* AsHandler() override { return this; }
|
||||
|
||||
SuccessHandler& GetSuccessHandler() { return mOnSuccess; }
|
||||
|
||||
SuccessHandler& GetErrorHandler() { return mOnError; }
|
||||
|
||||
protected:
|
||||
virtual ~TestPromiseListener() = default;
|
||||
|
||||
std::shared_ptr<bool> mIsDone; // We pass this to a callback
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
SuccessHandler mOnSuccess;
|
||||
|
||||
ErrorHandler mOnError;
|
||||
};
|
||||
|
||||
class TestOriginPrivateFileSystemChild : public OriginPrivateFileSystemChild {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(TestOriginPrivateFileSystemChild, override)
|
||||
|
||||
void ManualRelease() {
|
||||
if (mRefCnt > 0u) {
|
||||
--mRefCnt;
|
||||
}
|
||||
}
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendGetDirectoryHandle,
|
||||
(const FileSystemGetHandleRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemGetHandleResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendGetFileHandle,
|
||||
(const FileSystemGetHandleRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemGetHandleResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendGetFile,
|
||||
(const FileSystemGetFileRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemGetFileResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendResolve,
|
||||
(const FileSystemResolveRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemResolveResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendGetEntries,
|
||||
(const FileSystemGetEntriesRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemGetEntriesResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(
|
||||
void, SendRemoveEntry,
|
||||
(const FileSystemRemoveEntryRequest& request,
|
||||
mozilla::ipc::ResolveCallback<FileSystemRemoveEntryResponse>&& aResolve,
|
||||
mozilla::ipc::RejectCallback&& aReject),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(bool, IsCloseable, (), (const, override));
|
||||
|
||||
MOCK_METHOD(void, Close, (), (override));
|
||||
|
||||
MOCK_METHOD(POriginPrivateFileSystemChild*, AsBindable, (), (override));
|
||||
|
||||
protected:
|
||||
virtual ~TestOriginPrivateFileSystemChild() = default;
|
||||
};
|
||||
|
||||
class TestFileSystemChildFactory final : public FileSystemChildFactory {
|
||||
public:
|
||||
explicit TestFileSystemChildFactory(TestOriginPrivateFileSystemChild* aChild)
|
||||
: mChild(aChild) {}
|
||||
|
||||
already_AddRefed<OriginPrivateFileSystemChild> Create() const override {
|
||||
return RefPtr<TestOriginPrivateFileSystemChild>(mChild).forget();
|
||||
}
|
||||
|
||||
~TestFileSystemChildFactory() = default;
|
||||
|
||||
private:
|
||||
TestOriginPrivateFileSystemChild* mChild;
|
||||
};
|
||||
|
||||
struct MockExpectMe {
|
||||
MOCK_METHOD0(InvokeMe, void());
|
||||
|
||||
template <class... Args>
|
||||
void operator()(Args...) {
|
||||
InvokeMe();
|
||||
}
|
||||
};
|
||||
|
||||
template <nsresult Expected>
|
||||
@ -163,7 +279,10 @@ struct NSErrorMatcher {
|
||||
};
|
||||
|
||||
struct FailOnCall {
|
||||
void operator()() { FAIL(); }
|
||||
template <class... Args>
|
||||
void operator()(Args...) {
|
||||
FAIL();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom::fs::test
|
||||
@ -175,4 +294,7 @@ MOCK_PROMISE_LISTENER(
|
||||
ExpectNotImplemented, mozilla::dom::fs::test::FailOnCall,
|
||||
mozilla::dom::fs::test::NSErrorMatcher<NS_ERROR_NOT_IMPLEMENTED>);
|
||||
|
||||
MOCK_PROMISE_LISTENER(ExpectResolveCalled, mozilla::dom::fs::test::MockExpectMe,
|
||||
mozilla::dom::fs::test::FailOnCall);
|
||||
|
||||
#endif // DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "FileSystemMocks.h"
|
||||
|
||||
#include "mozilla/dom/FileSystemActorHolder.h"
|
||||
#include "mozilla/dom/FileSystemDirectoryHandle.h"
|
||||
#include "mozilla/dom/FileSystemDirectoryHandleBinding.h"
|
||||
#include "mozilla/dom/FileSystemDirectoryIterator.h"
|
||||
@ -26,7 +27,8 @@ class TestFileSystemDirectoryHandle : public ::testing::Test {
|
||||
mRequestHandler = MakeUnique<MockFileSystemRequestHandler>();
|
||||
mMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns);
|
||||
mName = u"testDir"_ns;
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(nullptr);
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(
|
||||
MakeUnique<FileSystemChildFactory>()->Create().take());
|
||||
}
|
||||
|
||||
nsIGlobalObject* mGlobal = GetGlobal();
|
||||
|
@ -8,6 +8,9 @@
|
||||
|
||||
#include "FileSystemMocks.h"
|
||||
|
||||
#include "fs/FileSystemChildFactory.h"
|
||||
|
||||
#include "mozilla/dom/FileSystemActorHolder.h"
|
||||
#include "mozilla/dom/FileSystemFileHandle.h"
|
||||
#include "mozilla/dom/FileSystemFileHandleBinding.h"
|
||||
#include "mozilla/dom/FileSystemHandle.h"
|
||||
@ -24,7 +27,8 @@ class TestFileSystemFileHandle : public ::testing::Test {
|
||||
void SetUp() override {
|
||||
mRequestHandler = MakeUnique<MockFileSystemRequestHandler>();
|
||||
mMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns);
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(nullptr);
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(
|
||||
MakeUnique<FileSystemChildFactory>()->Create().take());
|
||||
}
|
||||
|
||||
nsIGlobalObject* mGlobal = GetGlobal();
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
#include "FileSystemMocks.h"
|
||||
|
||||
#include "fs/FileSystemChildFactory.h"
|
||||
|
||||
#include "mozilla/dom/FileSystemActorHolder.h"
|
||||
#include "mozilla/dom/FileSystemHandle.h"
|
||||
#include "mozilla/dom/FileSystemDirectoryHandle.h"
|
||||
#include "mozilla/dom/FileSystemFileHandle.h"
|
||||
#include "mozilla/dom/FileSystemHandle.h"
|
||||
@ -21,7 +25,8 @@ class TestFileSystemHandle : public ::testing::Test {
|
||||
void SetUp() override {
|
||||
mDirMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns);
|
||||
mFileMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns);
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(nullptr);
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(
|
||||
MakeUnique<FileSystemChildFactory>()->Create().take());
|
||||
}
|
||||
|
||||
nsIGlobalObject* mGlobal = GetGlobal();
|
||||
|
@ -8,23 +8,32 @@
|
||||
|
||||
#include "FileSystemMocks.h"
|
||||
#include "fs/FileSystemRequestHandler.h"
|
||||
|
||||
#include "mozilla/dom/IPCBlob.h"
|
||||
#include "mozilla/dom/OriginPrivateFileSystemChild.h"
|
||||
#include "mozilla/dom/POriginPrivateFileSystem.h"
|
||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||
#include "mozilla/ipc/IPCCore.h"
|
||||
#include "mozilla/SpinEventLoopUntil.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::ByRef;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::Return;
|
||||
|
||||
namespace mozilla::dom::fs::test {
|
||||
|
||||
class TestFileSystemRequestHandler : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mListener = MakeAndAddRef<ExpectNotImplemented>();
|
||||
|
||||
mRequestHandler = MakeUnique<FileSystemRequestHandler>();
|
||||
mListener = MakeAndAddRef<ExpectResolveCalled>();
|
||||
|
||||
mChild = FileSystemChildMetadata("parent"_ns, u"ChildName"_ns);
|
||||
mEntry = FileSystemEntryMetadata("myid"_ns, u"EntryName"_ns);
|
||||
mName = u"testDir"_ns;
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(nullptr);
|
||||
mOPFSChild = MakeAndAddRef<TestOriginPrivateFileSystemChild>();
|
||||
mActor = MakeAndAddRef<FileSystemActorHolder>(mOPFSChild.get());
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> GetDefaultPromise() {
|
||||
@ -36,57 +45,169 @@ class TestFileSystemRequestHandler : public ::testing::Test {
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
UniquePtr<FileSystemRequestHandler> GetFileSystemRequestHandler() {
|
||||
return MakeUnique<FileSystemRequestHandler>(
|
||||
new TestFileSystemChildFactory(mOPFSChild));
|
||||
}
|
||||
|
||||
nsIGlobalObject* mGlobal = GetGlobal();
|
||||
RefPtr<ExpectNotImplemented> mListener;
|
||||
UniquePtr<FileSystemRequestHandler> mRequestHandler;
|
||||
RefPtr<ExpectResolveCalled> mListener;
|
||||
|
||||
FileSystemChildMetadata mChild;
|
||||
FileSystemEntryMetadata mEntry;
|
||||
nsString mName;
|
||||
RefPtr<TestOriginPrivateFileSystemChild> mOPFSChild;
|
||||
RefPtr<FileSystemActorHolder> mActor;
|
||||
};
|
||||
|
||||
class TestOPFSChild : public POriginPrivateFileSystemChild {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(TestOPFSChild)
|
||||
|
||||
MOCK_METHOD(void, Close, ());
|
||||
|
||||
protected:
|
||||
~TestOPFSChild() {
|
||||
mozilla::ipc::MessageChannel* channel = GetIPCChannel();
|
||||
channel->Close();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isGetRootSuccessful) {
|
||||
EXPECT_CALL(*mOPFSChild, AsBindable())
|
||||
.WillOnce(Invoke([]() -> POriginPrivateFileSystemChild* {
|
||||
return new TestOPFSChild();
|
||||
}));
|
||||
|
||||
// 1) In the parent process, at the end of get root
|
||||
// 2) In the content process, when the handle is destroyed
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(2);
|
||||
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
mRequestHandler->GetRoot(promise);
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
testable->GetRoot(promise);
|
||||
// Promise should be rejected
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
mOPFSChild->ManualRelease(); // Otherwise leak
|
||||
}
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isGetDirectoryHandleSuccessful) {
|
||||
auto fakeResponse = [](const auto& /* aRequest */, auto&& aResolve,
|
||||
auto&& /* aReject */) {
|
||||
EntryId expected = "expected"_ns;
|
||||
FileSystemGetHandleResponse response(expected);
|
||||
aResolve(std::move(response));
|
||||
};
|
||||
|
||||
EXPECT_CALL(mListener->GetSuccessHandler(), InvokeMe());
|
||||
EXPECT_CALL(*mOPFSChild, SendGetDirectoryHandle(_, _, _))
|
||||
.WillOnce(Invoke(fakeResponse));
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(1);
|
||||
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
mRequestHandler->GetDirectoryHandle(mActor, mChild,
|
||||
/* create */ true, promise);
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
testable->GetDirectoryHandle(mActor, mChild,
|
||||
/* create */ true, promise);
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
}
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isGetFileHandleSuccessful) {
|
||||
auto fakeResponse = [](const auto& /* aRequest */, auto&& aResolve,
|
||||
auto&& /* aReject */) {
|
||||
EntryId expected = "expected"_ns;
|
||||
FileSystemGetHandleResponse response(expected);
|
||||
aResolve(std::move(response));
|
||||
};
|
||||
|
||||
EXPECT_CALL(mListener->GetSuccessHandler(), InvokeMe());
|
||||
EXPECT_CALL(*mOPFSChild, SendGetFileHandle(_, _, _))
|
||||
.WillOnce(Invoke(fakeResponse));
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(1);
|
||||
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
mRequestHandler->GetFileHandle(mActor, mChild, /* create */ true, promise);
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
testable->GetFileHandle(mActor, mChild, /* create */ true, promise);
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
}
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isGetFileSuccessful) {
|
||||
auto fakeResponse = [](const auto& /* aRequest */, auto&& aResolve,
|
||||
auto&& /* aReject */) {
|
||||
TimeStamp last_modified_ms = 0;
|
||||
mozilla::dom::IPCBlob file;
|
||||
ContentType type = u"txt"_ns;
|
||||
|
||||
nsTArray<Name> path;
|
||||
path.AppendElement(u"root"_ns);
|
||||
path.AppendElement(u"Trash"_ns);
|
||||
|
||||
FileSystemFileProperties properties(last_modified_ms, file, type, path);
|
||||
FileSystemGetFileResponse response(properties);
|
||||
aResolve(std::move(response));
|
||||
};
|
||||
|
||||
EXPECT_CALL(mListener->GetSuccessHandler(), InvokeMe());
|
||||
EXPECT_CALL(*mOPFSChild, SendGetFile(_, _, _)).WillOnce(Invoke(fakeResponse));
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(1);
|
||||
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
mRequestHandler->GetFile(mActor, mEntry, promise);
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
testable->GetFile(mActor, mEntry, promise);
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
}
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isGetEntriesSuccessful) {
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
auto fakeResponse = [](const auto& /* aRequest */, auto&& aResolve,
|
||||
auto&& /* aReject */) {
|
||||
nsTArray<FileSystemEntryMetadata> files;
|
||||
nsTArray<FileSystemEntryMetadata> directories;
|
||||
FileSystemDirectoryListing listing(files, directories);
|
||||
FileSystemGetEntriesResponse response(listing);
|
||||
aResolve(std::move(response));
|
||||
};
|
||||
|
||||
RefPtr<ExpectNotImplemented> listener = MakeAndAddRef<ExpectNotImplemented>();
|
||||
IgnoredErrorResult rv;
|
||||
listener->ClearDone();
|
||||
RefPtr<Promise> promise = Promise::Create(mGlobal, rv);
|
||||
promise->AppendNativeHandler(listener);
|
||||
|
||||
EXPECT_CALL(*mOPFSChild, SendGetEntries(_, _, _))
|
||||
.WillOnce(Invoke(fakeResponse));
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(1);
|
||||
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
ArrayAppendable sink;
|
||||
mRequestHandler->GetEntries(mActor, mEntry.entryId(), /* page */ 0, promise,
|
||||
sink);
|
||||
testable->GetEntries(mActor, mEntry.entryId(), /* page */ 0, promise, sink);
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
[listener]() { return listener->IsDone(); });
|
||||
}
|
||||
|
||||
TEST_F(TestFileSystemRequestHandler, isRemoveEntrySuccessful) {
|
||||
auto fakeResponse = [](const auto& /* aRequest */, auto&& aResolve,
|
||||
auto&& /* aReject */) {
|
||||
FileSystemRemoveEntryResponse response(mozilla::void_t{});
|
||||
aResolve(std::move(response));
|
||||
};
|
||||
|
||||
EXPECT_CALL(mListener->GetSuccessHandler(), InvokeMe());
|
||||
EXPECT_CALL(*mOPFSChild, SendRemoveEntry(_, _, _))
|
||||
.WillOnce(Invoke(fakeResponse));
|
||||
EXPECT_CALL(*mOPFSChild, IsCloseable()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mOPFSChild, Close()).Times(1);
|
||||
|
||||
auto testable = GetFileSystemRequestHandler();
|
||||
RefPtr<Promise> promise = GetDefaultPromise();
|
||||
mRequestHandler->RemoveEntry(mActor, mChild, /* recursive */ true, promise);
|
||||
testable->RemoveEntry(mActor, mChild, /* recursive */ true, promise);
|
||||
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
|
||||
[this]() { return mListener->IsDone(); });
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
* 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
|
||||
#ifndef MOZILLA_IPC_TOPLEVELACTORHOLDER_H
|
||||
#define MOZILLA_IPC_TOPLEVELACTORHOLDER_H
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
@ -21,17 +21,17 @@ namespace mozilla::ipc {
|
||||
// You can avoid calling Close() on an un-connected Actor (for example if
|
||||
// Bind() fails) by calling RemoveActor();
|
||||
template <typename T>
|
||||
class TopLevelActorHolder final {
|
||||
class ToplevelActorHolder final {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(TopLevelActorHolder)
|
||||
NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(ToplevelActorHolder)
|
||||
|
||||
explicit TopLevelActorHolder(T* aActor) : mActor(aActor) {}
|
||||
explicit ToplevelActorHolder(T* aActor) : mActor(aActor) {}
|
||||
|
||||
constexpr T* Actor() const { return mActor; }
|
||||
inline void RemoveActor() { mActor = nullptr; }
|
||||
|
||||
private:
|
||||
inline ~TopLevelActorHolder() {
|
||||
inline ~ToplevelActorHolder() {
|
||||
if (mActor) {
|
||||
mActor->Close();
|
||||
}
|
||||
@ -42,4 +42,4 @@ class TopLevelActorHolder final {
|
||||
|
||||
} // namespace mozilla::ipc
|
||||
|
||||
#endif // MOZILLA_IPC_ACTORHOLDER_H
|
||||
#endif // MOZILLA_IPC_TOPLEVELACTORHOLDER_H
|
@ -10,7 +10,6 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.ipc += [
|
||||
"ActorHolder.h",
|
||||
"AsyncBlockers.h",
|
||||
"BackgroundChild.h",
|
||||
"BackgroundParent.h",
|
||||
@ -60,6 +59,7 @@ EXPORTS.mozilla.ipc += [
|
||||
"ShmemMessageUtils.h",
|
||||
"TaintingIPCUtils.h",
|
||||
"TaskFactory.h",
|
||||
"ToplevelActorHolder.h",
|
||||
"TransportSecurityInfoUtils.h",
|
||||
"URIUtils.h",
|
||||
"UtilityAudioDecoderChild.h",
|
||||
|
Loading…
Reference in New Issue
Block a user