Bug 1758055 - Establish file system content and parent process IPC. r=janv,dom-storage-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D140486
This commit is contained in:
Jari Jalkanen 2022-06-28 16:04:17 +00:00
parent d8cb8edd49
commit 516845de8f
33 changed files with 1886 additions and 10 deletions

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileSystemDirectoryHandle.h"
#include "fs/FileSystemRequestHandler.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/FileSystemDirectoryHandleBinding.h"
@ -14,6 +15,16 @@
namespace mozilla::dom {
FileSystemDirectoryHandle::FileSystemDirectoryHandle(
nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler)
: FileSystemHandle(aGlobal, aMetadata, aRequestHandler) {}
FileSystemDirectoryHandle::FileSystemDirectoryHandle(
nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata)
: FileSystemDirectoryHandle(aGlobal, aMetadata,
new fs::FileSystemRequestHandler()) {}
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(FileSystemDirectoryHandle,
FileSystemHandle)
NS_IMPL_CYCLE_COLLECTION_INHERITED(FileSystemDirectoryHandle, FileSystemHandle)
@ -27,7 +38,7 @@ JSObject* FileSystemDirectoryHandle::WrapObject(
// WebIDL Interface
FileSystemHandleKind FileSystemDirectoryHandle::Kind() {
FileSystemHandleKind FileSystemDirectoryHandle::Kind() const {
return FileSystemHandleKind::Directory;
}

View File

@ -22,6 +22,13 @@ struct FileSystemRemoveOptions;
class FileSystemDirectoryHandle final : public FileSystemHandle {
public:
FileSystemDirectoryHandle(nsIGlobalObject* aGlobal,
const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler);
FileSystemDirectoryHandle(nsIGlobalObject* aGlobal,
const fs::FileSystemEntryMetadata& aMetadata);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileSystemDirectoryHandle,
FileSystemHandle)
@ -31,7 +38,7 @@ class FileSystemDirectoryHandle final : public FileSystemHandle {
JS::Handle<JSObject*> aGivenProto) override;
// WebIDL Interface
FileSystemHandleKind Kind() override;
FileSystemHandleKind Kind() const override;
[[nodiscard]] already_AddRefed<FileSystemDirectoryIterator> Entries();

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileSystemFileHandle.h"
#include "fs/FileSystemRequestHandler.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/FileSystemFileHandleBinding.h"
@ -17,6 +18,16 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(FileSystemFileHandle,
FileSystemHandle)
NS_IMPL_CYCLE_COLLECTION_INHERITED(FileSystemFileHandle, FileSystemHandle)
FileSystemFileHandle::FileSystemFileHandle(
nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler)
: FileSystemHandle(aGlobal, aMetadata, aRequestHandler) {}
FileSystemFileHandle::FileSystemFileHandle(
nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata)
: FileSystemFileHandle(aGlobal, aMetadata,
new fs::FileSystemRequestHandler()) {}
// WebIDL Boilerplate
JSObject* FileSystemFileHandle::WrapObject(JSContext* aCx,
@ -26,7 +37,7 @@ JSObject* FileSystemFileHandle::WrapObject(JSContext* aCx,
// WebIDL Interface
FileSystemHandleKind FileSystemFileHandle::Kind() {
FileSystemHandleKind FileSystemFileHandle::Kind() const {
return FileSystemHandleKind::File;
}

View File

@ -19,6 +19,13 @@ struct FileSystemCreateWritableOptions;
class FileSystemFileHandle final : public FileSystemHandle {
public:
FileSystemFileHandle(nsIGlobalObject* aGlobal,
const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler);
FileSystemFileHandle(nsIGlobalObject* aGlobal,
const fs::FileSystemEntryMetadata& aMetadata);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileSystemFileHandle,
FileSystemHandle)
@ -28,7 +35,7 @@ class FileSystemFileHandle final : public FileSystemHandle {
JS::Handle<JSObject*> aGivenProto) override;
// WebIDL interface
FileSystemHandleKind Kind() override;
FileSystemHandleKind Kind() const override;
already_AddRefed<Promise> GetFile(ErrorResult& aError);

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileSystemHandle.h"
#include "fs/FileSystemRequestHandler.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/FileSystemHandleBinding.h"
@ -20,6 +21,13 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemHandle);
NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemHandle);
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemHandle, mGlobal);
FileSystemHandle::FileSystemHandle(
nsIGlobalObject* aGlobal, const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler)
: mGlobal(aGlobal),
mMetadata(aMetadata),
mRequestHandler(aRequestHandler) {}
// WebIDL Boilerplate
nsIGlobalObject* FileSystemHandle::GetParentObject() const { return mGlobal; }
@ -31,10 +39,12 @@ JSObject* FileSystemHandle::WrapObject(JSContext* aCx,
// WebIDL Interface
void FileSystemHandle::GetName(DOMString& aResult) { aResult.SetNull(); }
void FileSystemHandle::GetName(nsAString& aResult) {
aResult = mMetadata.entryName();
}
already_AddRefed<Promise> FileSystemHandle::IsSameEntry(
FileSystemHandle& aOther, ErrorResult& aError) {
FileSystemHandle& aOther, ErrorResult& aError) const {
RefPtr<Promise> promise = Promise::Create(GetParentObject(), aError);
if (aError.Failed()) {
return nullptr;

View File

@ -7,6 +7,7 @@
#ifndef DOM_FS_FILESYSTEMHANDLE_H_
#define DOM_FS_FILESYSTEMHANDLE_H_
#include "mozilla/dom/PBackgroundFileSystem.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
@ -23,8 +24,16 @@ class DOMString;
enum class FileSystemHandleKind : uint8_t;
class Promise;
namespace fs {
class FileSystemRequestHandler;
} // namespace fs
class FileSystemHandle : public nsISupports, public nsWrapperCache {
public:
FileSystemHandle(nsIGlobalObject* aGlobal,
const fs::FileSystemEntryMetadata& aMetadata,
fs::FileSystemRequestHandler* aRequestHandler);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FileSystemHandle)
@ -35,17 +44,21 @@ class FileSystemHandle : public nsISupports, public nsWrapperCache {
JS::Handle<JSObject*> aGivenProto) override;
// WebIDL Interface
virtual FileSystemHandleKind Kind() = 0;
virtual FileSystemHandleKind Kind() const = 0;
void GetName(DOMString& aResult);
void GetName(nsAString& aResult);
already_AddRefed<Promise> IsSameEntry(FileSystemHandle& aOther,
ErrorResult& aError);
ErrorResult& aError) const;
protected:
virtual ~FileSystemHandle() = default;
nsCOMPtr<nsIGlobalObject> mGlobal;
const fs::FileSystemEntryMetadata mMetadata;
const UniquePtr<fs::FileSystemRequestHandler> mRequestHandler;
};
} // namespace dom

View File

@ -22,4 +22,10 @@ UNIFIED_SOURCES += [
"FileSystemWritableFileStream.cpp",
]
LOCAL_INCLUDES += [
"/dom/fs/include",
]
FINAL_LIBRARY = "xul"
include("/ipc/chromium/chromium-config.mozbuild")

View File

@ -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_BACKGROUNDFILESYSTEMCHILD_H_
#define DOM_FS_CHILD_BACKGROUNDFILESYSTEMCHILD_H_
#include "mozilla/dom/PBackgroundFileSystemChild.h"
#include "nsISupports.h"
namespace mozilla::dom {
class BackgroundFileSystemChild : public PBackgroundFileSystemChild {
NS_INLINE_DECL_REFCOUNTING(BackgroundFileSystemChild);
protected:
virtual ~BackgroundFileSystemChild() = default;
};
} // namespace mozilla::dom
#endif // DOM_FS_CHILD_BACKGROUNDFILESYSTEMCHILD_H_

View File

@ -0,0 +1,372 @@
/* -*- 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/FileSystemRequestHandler.h"
#include "fs/FileSystemConstants.h"
#include "mozilla/dom/BackgroundFileSystemChild.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileSystemFileHandle.h"
#include "mozilla/dom/FileSystemDirectoryHandle.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
using namespace mozilla::ipc;
namespace mozilla::dom::fs {
namespace {
// Not static: BackgroundFileSystemChild must be owned by calling thread
RefPtr<mozilla::dom::BackgroundFileSystemChild> GetRootProvider() {
mozilla::dom::BackgroundFileSystemChild* inputPtr =
new mozilla::dom::BackgroundFileSystemChild();
mozilla::ipc::PBackgroundChild* bgAccessor =
mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
// TODO: Would be nice to convert this to QM_TRY some time later.
if (NS_WARN_IF(!bgAccessor)) {
MOZ_ASSERT(false);
return nullptr;
}
RefPtr<mozilla::dom::BackgroundFileSystemChild> getterPtr =
static_cast<mozilla::dom::BackgroundFileSystemChild*>(
bgAccessor->SendPBackgroundFileSystemConstructor(inputPtr));
MOZ_ASSERT(getterPtr);
return getterPtr;
}
// TODO: This is just a dummy implementation
RefPtr<File> MakeGetFileResult(const nsString& aName, const nsString& aType,
int64_t aLastModifiedMilliSeconds,
nsTArray<Name>&& aPath,
mozilla::ipc::FileDescriptor&& aFile,
nsIGlobalObject* aGlobal) {
// TODO: Replace with a real implementation
RefPtr<File> result = File::CreateMemoryFileWithCustomLastModified(
aGlobal, static_cast<void*>(new uint8_t[1]), sizeof(uint8_t), aName,
aType, aLastModifiedMilliSeconds);
return result;
}
void GetDirectoryContentsResponseHandler(
RefPtr<FileSystemActorHolder>& /* aActor */,
FileSystemDirectoryListing&& aResponse, nsIGlobalObject* aGlobal,
ArrayAppendable& /* aSink */) {
// TODO: Add page size to FileSystemConstants, preallocate and handle overflow
nsTArray<RefPtr<FileSystemHandle>> batch;
for (const auto& it : aResponse.files()) {
RefPtr<FileSystemHandle> handle = new FileSystemFileHandle(aGlobal, it);
batch.AppendElement(handle);
}
for (const auto& it : aResponse.directories()) {
RefPtr<FileSystemHandle> handle =
new FileSystemDirectoryHandle(aGlobal, it);
batch.AppendElement(handle);
}
}
RefPtr<FileSystemDirectoryHandle> MakeResolution(
nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse,
const RefPtr<FileSystemDirectoryHandle>& /* aResolution */,
const Name& aName, RefPtr<FileSystemActorHolder>& aActor) {
RefPtr<FileSystemDirectoryHandle> result = new FileSystemDirectoryHandle(
aGlobal, FileSystemEntryMetadata(aResponse.get_EntryId(), aName));
return result;
}
RefPtr<FileSystemFileHandle> MakeResolution(
nsIGlobalObject* aGlobal, FileSystemGetHandleResponse&& aResponse,
const RefPtr<FileSystemFileHandle>& /* aResolution */, const Name& aName,
RefPtr<FileSystemActorHolder>& aActor) {
RefPtr<FileSystemFileHandle> result = new FileSystemFileHandle(
aGlobal, FileSystemEntryMetadata(aResponse.get_EntryId(), aName));
return result;
}
RefPtr<File> MakeResolution(nsIGlobalObject* aGlobal,
FileSystemGetFileResponse&& aResponse,
const RefPtr<File>& /* aResolution */,
const Name& aName,
RefPtr<FileSystemActorHolder>& aActor) {
auto& fileProperties = aResponse.get_FileSystemFileProperties();
return MakeGetFileResult(aName, fileProperties.type(),
fileProperties.last_modified_ms(),
std::move(fileProperties.path()),
std::move(fileProperties.file()), aGlobal);
}
template <class TResponse, class... Args>
void ResolveCallback(
TResponse&& aResponse,
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
Args&&... args) {
MOZ_ASSERT(aPromise);
QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID);
if (TResponse::Tnsresult == aResponse.type()) {
aPromise->MaybeReject(aResponse.get_nsresult());
return;
}
aPromise->MaybeResolve(MakeResolution(aPromise->GetParentObject(),
std::forward<TResponse>(aResponse),
std::forward<Args>(args)...));
}
template <>
void ResolveCallback(
FileSystemRemoveEntryResponse&& aResponse,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(aPromise);
QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID);
MOZ_ASSERT(FileSystemRemoveEntryResponse::Tnsresult == aResponse.type());
const auto& status = aResponse.get_nsresult();
if (NS_ERROR_FILE_ACCESS_DENIED == status) {
aPromise->MaybeRejectWithNotAllowedError("Permission denied");
} else if (NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR == status) {
aPromise->MaybeRejectWithInvalidModificationError("Disallowed by system");
} else if (NS_FAILED(status)) {
aPromise->MaybeRejectWithUnknownError("Unknown failure");
} else {
aPromise->MaybeResolveWithUndefined();
}
}
// NOLINTBEGIN(readability-inconsistent-declaration-parameter-name)
template <>
void ResolveCallback(FileSystemGetEntriesResponse&& aResponse,
// NOLINTNEXTLINE(performance-unnecessary-value-param)
RefPtr<Promise> aPromise, ArrayAppendable& aSink,
RefPtr<FileSystemActorHolder>& aActor) {
// NOLINTEND(readability-inconsistent-declaration-parameter-name)
MOZ_ASSERT(aPromise);
QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID);
if (FileSystemGetEntriesResponse::Tnsresult == aResponse.type()) {
aPromise->MaybeReject(aResponse.get_nsresult());
return;
}
GetDirectoryContentsResponseHandler(
aActor,
std::forward<FileSystemDirectoryListing>(
aResponse.get_FileSystemDirectoryListing()),
aPromise->GetParentObject(), aSink);
// TODO: Remove this when sink is ready
aPromise->MaybeReject(NS_ERROR_NOT_IMPLEMENTED);
}
template <class TResponse, class TReturns, class... Args,
std::enable_if_t<std::is_same<TReturns, void>::value, bool> = true>
mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback(
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
Args&&... args) {
using TOverload = void (*)(TResponse&&, RefPtr<Promise>, Args...);
return static_cast<std::function<void(TResponse &&)>>(
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1,
aPromise, std::forward<Args>(args)...));
}
template <class TResponse, class TReturns, class... Args,
std::enable_if_t<!std::is_same<TReturns, void>::value, bool> = true>
mozilla::ipc::ResolveCallback<TResponse> SelectResolveCallback(
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
Args&&... args) {
using TOverload =
void (*)(TResponse&&, RefPtr<Promise>, const TReturns&, Args...);
return static_cast<std::function<void(TResponse &&)>>(
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(static_cast<TOverload>(ResolveCallback), std::placeholders::_1,
aPromise, TReturns(), std::forward<Args>(args)...));
}
// TODO: Find a better way to deal with these errors
void IPCRejectReporter(mozilla::ipc::ResponseRejectReason aReason) {
switch (aReason) {
case mozilla::ipc::ResponseRejectReason::ActorDestroyed:
// This is ok
break;
case mozilla::ipc::ResponseRejectReason::HandlerRejected:
QM_TRY(OkIf(false), QM_VOID);
break;
case mozilla::ipc::ResponseRejectReason::ChannelClosed:
QM_TRY(OkIf(false), QM_VOID);
break;
case mozilla::ipc::ResponseRejectReason::ResolverDestroyed:
QM_TRY(OkIf(false), QM_VOID);
break;
case mozilla::ipc::ResponseRejectReason::SendError:
QM_TRY(OkIf(false), QM_VOID);
break;
default:
QM_TRY(OkIf(false), QM_VOID);
break;
}
}
void RejectHandler(
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
mozilla::ipc::ResponseRejectReason aReason) {
IPCRejectReporter(aReason);
QM_TRY(OkIf(Promise::PromiseState::Pending == aPromise->State()), QM_VOID);
aPromise->MaybeRejectWithUndefined();
}
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));
}
} // namespace
void FileSystemRequestHandler::GetRoot(
const Origin& aOrigin,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(!aOrigin.IsEmpty());
MOZ_ASSERT(aPromise);
RefPtr<FileSystemActorHolder> dummyActor =
MakeAndAddRef<FileSystemActorHolder>();
Name name = kRootName;
auto&& onResolve = SelectResolveCallback<FileSystemGetHandleResponse,
RefPtr<FileSystemDirectoryHandle>>(
aPromise, name, dummyActor);
auto&& onReject = GetRejectCallback(aPromise);
// XXX do something (register with global?) so that we can Close() the actor
// before the event queue starts to shut down. That will cancel all
// outstanding async requests (returns lambdas with errors).
RefPtr<mozilla::dom::BackgroundFileSystemChild> rootProvider =
GetRootProvider();
if (!rootProvider) {
aPromise->MaybeRejectWithUnknownError("Could not access the file system");
return;
}
rootProvider->SendGetRoot(aOrigin, std::move(onResolve), std::move(onReject));
}
void FileSystemRequestHandler::GetDirectoryHandle(
RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aDirectory, bool aCreate,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(!aDirectory.parentId().IsEmpty());
MOZ_ASSERT(aPromise);
FileSystemGetHandleRequest request(aDirectory, aCreate);
auto&& onResolve = SelectResolveCallback<FileSystemGetHandleResponse,
RefPtr<FileSystemDirectoryHandle>>(
aPromise, aDirectory.childName(), aActor);
auto&& onReject = GetRejectCallback(aPromise);
auto actor = GetRootProvider();
QM_TRY(OkIf(actor), QM_VOID);
actor->SendGetDirectoryHandle(request, std::move(onResolve),
std::move(onReject));
}
void FileSystemRequestHandler::GetFileHandle(
RefPtr<FileSystemActorHolder>& aActor, const FileSystemChildMetadata& aFile,
bool aCreate,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(!aFile.parentId().IsEmpty());
MOZ_ASSERT(aPromise);
FileSystemGetHandleRequest request(aFile, aCreate);
auto&& onResolve = SelectResolveCallback<FileSystemGetHandleResponse,
RefPtr<FileSystemFileHandle>>(
aPromise, aFile.childName(), aActor);
auto&& onReject = GetRejectCallback(aPromise);
auto actor = GetRootProvider();
QM_TRY(OkIf(actor), QM_VOID);
actor->SendGetFileHandle(request, std::move(onResolve), std::move(onReject));
}
void FileSystemRequestHandler::GetFile(
RefPtr<FileSystemActorHolder>& aActor, const FileSystemEntryMetadata& aFile,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(!aFile.entryId().IsEmpty());
MOZ_ASSERT(aPromise);
FileSystemGetFileRequest request(aFile.entryId());
auto&& onResolve =
SelectResolveCallback<FileSystemGetFileResponse, RefPtr<File>>(
aPromise, aFile.entryName(), aActor);
auto&& onReject = GetRejectCallback(aPromise);
auto actor = GetRootProvider();
QM_TRY(OkIf(actor), QM_VOID);
actor->SendGetFile(request, std::move(onResolve), std::move(onReject));
}
void FileSystemRequestHandler::GetEntries(
RefPtr<FileSystemActorHolder>& aActor, const EntryId& aDirectory,
PageNumber aPage,
RefPtr<Promise> aPromise, // NOLINT(performance-unnecessary-value-param)
ArrayAppendable& aSink) {
MOZ_ASSERT(!aDirectory.IsEmpty());
MOZ_ASSERT(aPromise);
FileSystemGetEntriesRequest request(aDirectory, aPage);
using TOverload = void (*)(FileSystemGetEntriesResponse&&, RefPtr<Promise>,
ArrayAppendable&, RefPtr<FileSystemActorHolder>&);
// We are not allowed to pass a promise to an external function in a lambda
auto&& onResolve =
static_cast<std::function<void(FileSystemGetEntriesResponse &&)>>(
// NOLINTNEXTLINE(modernize-avoid-bind)
std::bind(static_cast<TOverload>(ResolveCallback),
std::placeholders::_1, aPromise, std::ref(aSink), aActor));
auto&& onReject = GetRejectCallback(aPromise);
auto actor = GetRootProvider();
QM_TRY(OkIf(actor), QM_VOID);
actor->SendGetEntries(request, std::move(onResolve), std::move(onReject));
}
void FileSystemRequestHandler::RemoveEntry(
RefPtr<FileSystemActorHolder>& /* aActor */,
const FileSystemChildMetadata& aEntry, bool aRecursive,
RefPtr<Promise> aPromise) { // NOLINT(performance-unnecessary-value-param)
MOZ_ASSERT(!aEntry.parentId().IsEmpty());
MOZ_ASSERT(aPromise);
FileSystemRemoveEntryRequest request(aEntry, aRecursive);
auto&& onResolve =
SelectResolveCallback<FileSystemRemoveEntryResponse, void>(aPromise);
auto&& onReject = GetRejectCallback(aPromise);
auto actor = GetRootProvider();
QM_TRY(OkIf(actor), QM_VOID);
actor->SendRemoveEntry(request, std::move(onResolve), std::move(onReject));
}
} // namespace mozilla::dom::fs

21
dom/fs/child/moz.build Normal file
View File

@ -0,0 +1,21 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.dom += [
"BackgroundFileSystemChild.h",
]
UNIFIED_SOURCES += [
"FileSystemRequestHandler.cpp",
]
LOCAL_INCLUDES += [
"/dom/fs/include",
]
FINAL_LIBRARY = "xul"
include("/ipc/chromium/chromium-config.mozbuild")

View File

@ -0,0 +1,18 @@
/* -*- 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_FILESYSTEMCONSTANTS_H_
#define DOM_FS_FILESYSTEMCONSTANTS_H_
#include "nsLiteralString.h"
namespace mozilla::dom::fs {
constexpr nsLiteralString kRootName = u"root"_ns;
} // namespace mozilla::dom::fs
#endif // DOM_FS_FILESYSTEMCONSTANTS_H_

View File

@ -0,0 +1,67 @@
/* -*- 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_FILESYSTEMREQUESTHANDLER_H_
#define DOM_FS_CHILD_FILESYSTEMREQUESTHANDLER_H_
#include "nsStringFwd.h"
#include "mozilla/dom/FileSystemTypes.h"
#include "mozilla/dom/FileSystemHandle.h"
template <class T>
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;
} // namespace mozilla::dom
namespace mozilla::dom::fs {
class FileSystemChildMetadata;
class FileSystemEntryMetadata;
class ArrayAppendable {};
class FileSystemRequestHandler {
public:
virtual void GetRoot(const Origin& aOrigin, RefPtr<Promise> aPromise);
virtual void GetDirectoryHandle(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aDirectory,
bool aCreate, RefPtr<Promise> aPromise);
virtual void GetFileHandle(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aFile, bool aCreate,
RefPtr<Promise> aPromise);
virtual void GetFile(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemEntryMetadata& aFile,
RefPtr<Promise> aPromise);
virtual void GetEntries(RefPtr<FileSystemActorHolder>& aActor,
const EntryId& aDirectory, PageNumber aPage,
RefPtr<Promise> aPromise, ArrayAppendable& aSink);
virtual void RemoveEntry(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aEntry,
bool aRecursive, RefPtr<Promise> aPromise);
virtual ~FileSystemRequestHandler() = default;
}; // class FileSystemRequestHandler
} // namespace mozilla::dom::fs
#endif // DOM_FS_CHILD_FILESYSTEMREQUESTHANDLER_H_

View File

@ -4,6 +4,11 @@
# 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/.
DIRS += ["api"]
DIRS += [
"api",
"child",
"parent",
"shared",
]
TEST_DIRS += ["test"]

View File

@ -0,0 +1,71 @@
/* -*- 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 "BackgroundFileSystemParent.h"
#include "mozilla/dom/FileSystemTypes.h"
using IPCResult = mozilla::ipc::IPCResult;
namespace mozilla::dom {
IPCResult BackgroundFileSystemParent::RecvGetRoot(const fs::Origin& aOrigin,
GetRootResolver&& aResolver) {
FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED);
aResolver(response);
return IPC_OK();
}
IPCResult BackgroundFileSystemParent::RecvGetDirectoryHandle(
FileSystemGetHandleRequest&& /* aRequest */,
GetDirectoryHandleResolver&& aResolver) {
FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED);
aResolver(response);
return IPC_OK();
}
IPCResult BackgroundFileSystemParent::RecvGetFileHandle(
FileSystemGetHandleRequest&& aRequest, GetFileHandleResolver&& aResolver) {
FileSystemGetHandleResponse response(NS_ERROR_NOT_IMPLEMENTED);
aResolver(response);
return IPC_OK();
}
IPCResult BackgroundFileSystemParent::RecvGetFile(
FileSystemGetFileRequest&& aRequest, GetFileResolver&& aResolver) {
FileSystemGetFileResponse response(NS_ERROR_NOT_IMPLEMENTED);
aResolver(response);
return IPC_OK();
}
IPCResult BackgroundFileSystemParent::RecvResolve(
FileSystemResolveRequest&& aRequest, ResolveResolver&& aResolver) {
FileSystemResolveResponse response(NS_ERROR_NOT_IMPLEMENTED);
aResolver(response);
return IPC_OK();
}
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);
return IPC_OK();
}
} // namespace mozilla::dom

View File

@ -0,0 +1,48 @@
/* -*- 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_BACKGROUNDFILESYSTEMPARENT_H_
#define DOM_FS_PARENT_BACKGROUNDFILESYSTEMPARENT_H_
#include "mozilla/dom/PBackgroundFileSystemParent.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "nsISupports.h"
namespace mozilla::dom {
class BackgroundFileSystemParent : public PBackgroundFileSystemParent {
public:
mozilla::ipc::IPCResult RecvGetRoot(const fs::Origin& aOrigin,
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);
NS_INLINE_DECL_REFCOUNTING(BackgroundFileSystemParent)
protected:
virtual ~BackgroundFileSystemParent() = default;
};
} // namespace mozilla::dom
#endif // DOM_FS_PARENT_BACKGROUNDFILESYSTEMPARENT_H_

17
dom/fs/parent/moz.build Normal file
View File

@ -0,0 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.dom += [
"BackgroundFileSystemParent.h",
]
UNIFIED_SOURCES += [
"BackgroundFileSystemParent.cpp",
]
FINAL_LIBRARY = "xul"
include("/ipc/chromium/chromium-config.mozbuild")

View File

@ -0,0 +1,27 @@
/* -*- 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_FILESYSTEMTYPES_H_
#define DOM_FS_FILESYSTEMTYPES_H_
#include "nsStringFwd.h"
template <class T>
class nsTArray;
namespace mozilla::dom::fs {
using ContentType = nsString;
using EntryId = nsCString;
using Name = nsString;
using Origin = nsCString;
using PageNumber = uint32_t;
using Path = nsTArray<Name>;
using TimeStamp = int64_t;
} // namespace mozilla::dom::fs
#endif // DOM_FS_FILESYSTEMTYPES_H_

View File

@ -0,0 +1,296 @@
/* 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 protocol PBackground;
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;
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
{
manager PBackground;
parent:
/**
* Initiates an asynchronous request for the directory handle of
* the file system's root level. On first call, may conduct initialization
* activities.
*
* @param[in] origin of the file system
*
* @returns error or entry handle
*/
async GetRoot(Origin origin) 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);
child:
/**
* Mandatory IPC managed lifecycle request.
*/
async __delete__();
};
} // namespace dom
} // namespace mozilla

17
dom/fs/shared/moz.build Normal file
View File

@ -0,0 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.dom += [
"FileSystemTypes.h",
]
FINAL_LIBRARY = "xul"
IPDL_SOURCES += [
"PBackgroundFileSystem.ipdl",
]
include("/ipc/chromium/chromium-config.mozbuild")

View File

@ -0,0 +1,29 @@
/* -*- 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 "FileSystemMocks.h"
#include "jsapi.h"
#include "nsISupports.h"
#include "js/RootingAPI.h"
namespace mozilla::dom::fs::test {
nsIGlobalObject* GetGlobal() {
AutoJSAPI jsapi;
DebugOnly<bool> ok = jsapi.Init(xpc::PrivilegedJunkScope());
MOZ_ASSERT(ok);
JSContext* cx = jsapi.cx();
mozilla::dom::GlobalObject globalObject(cx, JS::CurrentGlobalOrNull(cx));
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(globalObject.GetAsSupports());
MOZ_ASSERT(global);
return global.get();
}
} // namespace mozilla::dom::fs::test

View File

@ -0,0 +1,178 @@
/* -*- 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_TEST_GTEST_FILESYSTEMMOCKS_H_
#define DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "TestHelpers.h"
#include "fs/FileSystemRequestHandler.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/UniquePtr.h"
#include "nsIGlobalObject.h"
#include "nsISupportsImpl.h"
#include "nsITimer.h"
#include "jsapi.h"
#include "js/Promise.h"
#include "js/RootingAPI.h"
#include <memory> // We don't have a mozilla shared pointer for pod types
namespace mozilla::dom::fs::test {
nsIGlobalObject* GetGlobal();
class MockFileSystemRequestHandler : public FileSystemRequestHandler {
public:
MOCK_METHOD2(GetRoot, void(const Origin& aOrigin, RefPtr<Promise> aPromise));
MOCK_METHOD4(GetDirectoryHandle,
void(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aDirectory, bool aCreate,
RefPtr<Promise> aPromise));
MOCK_METHOD4(GetFileHandle, void(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aFile,
bool aCreate, RefPtr<Promise> aPromise));
MOCK_METHOD3(GetFile, void(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemEntryMetadata& aFile,
RefPtr<Promise> aPromise));
MOCK_METHOD5(GetEntries,
void(RefPtr<FileSystemActorHolder>& aActor,
const EntryId& aDirectory, PageNumber aPage,
RefPtr<Promise> aPromise, ArrayAppendable& aSink));
MOCK_METHOD4(RemoveEntry, void(RefPtr<FileSystemActorHolder>& aActor,
const FileSystemChildMetadata& aEntry,
bool aRecursive, RefPtr<Promise> aPromise));
};
class WaitablePromiseListener {
public:
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
virtual void ClearDone() = 0;
virtual bool IsDone() const = 0;
virtual PromiseNativeHandler* AsHandler() = 0;
protected:
virtual ~WaitablePromiseListener() = default;
};
template <class SuccessHandler, class ErrorHandler,
uint32_t MilliSeconds = 2000u>
class TestPromiseListener : public PromiseNativeHandler,
public WaitablePromiseListener {
public:
TestPromiseListener() : mIsDone(std::make_shared<bool>(false)), mTimer() {
ClearDone();
}
// nsISupports implementation
NS_IMETHODIMP QueryInterface(REFNSIID aIID, void** aInstancePtr) override {
nsresult rv = NS_ERROR_UNEXPECTED;
NS_INTERFACE_TABLE0(TestPromiseListener)
return rv;
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestPromiseListener, override)
// PromiseNativeHandler implementation
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
ErrorResult& aRv) override {
mozilla::ScopeExit flagAsDone([isDone = mIsDone] { *isDone = true; });
SuccessHandler{}();
}
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
ErrorResult& aRv) override {
mozilla::ScopeExit flagAsDone([isDone = mIsDone] { *isDone = true; });
if (aValue.isInt32()) {
ErrorHandler{}(static_cast<nsresult>(aValue.toInt32()));
return;
}
ASSERT_TRUE(aValue.isObject());
JS::Rooted<JSObject*> exceptionObject(aCx, &aValue.toObject());
RefPtr<Exception> exception;
UNWRAP_OBJECT(Exception, exceptionObject, exception);
if (exception) {
ErrorHandler{}(static_cast<nsresult>(exception->Result()));
return;
}
}
// WaitablePromiseListener implementation
void ClearDone() override {
*mIsDone = false;
if (mTimer) {
mTimer->Cancel();
}
auto timerCallback = [isDone = mIsDone](nsITimer* aTimer) {
*isDone = true;
};
const char* timerName = "fs::TestPromiseListener::ClearDone";
auto res = NS_NewTimerWithCallback(timerCallback, MilliSeconds,
nsITimer::TYPE_ONE_SHOT, timerName);
if (res.isOk()) {
mTimer = res.unwrap();
}
}
bool IsDone() const override { return *mIsDone; }
PromiseNativeHandler* AsHandler() override { return this; }
protected:
virtual ~TestPromiseListener() = default;
std::shared_ptr<bool> mIsDone; // We pass this to a callback
nsCOMPtr<nsITimer> mTimer;
};
template <nsresult Expected>
struct NSErrorMatcher {
void operator()(nsresult aErr) { ASSERT_NSEQ(Expected, aErr); }
};
struct FailOnCall {
void operator()() { FAIL(); }
};
} // namespace mozilla::dom::fs::test
#define MOCK_PROMISE_LISTENER(name, ...) \
using name = mozilla::dom::fs::test::TestPromiseListener<__VA_ARGS__>;
MOCK_PROMISE_LISTENER(
ExpectNotImplemented, mozilla::dom::fs::test::FailOnCall,
mozilla::dom::fs::test::NSErrorMatcher<NS_ERROR_NOT_IMPLEMENTED>);
#endif // DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_

View File

@ -0,0 +1,18 @@
/* -*- 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_TEST_GTEST_TESTHELPERS_H_
#define DOM_FS_TEST_GTEST_TESTHELPERS_H_
#include "gtest/gtest.h"
#include "ErrorList.h"
#include "mozilla/ErrorNames.h"
#define ASSERT_NSEQ(lhs, rhs) \
ASSERT_STREQ(GetStaticErrorName((lhs)), GetStaticErrorName((rhs)))
#endif // DOM_FS_TEST_GTEST_TESTHELPERS_H_

View File

@ -0,0 +1,196 @@
/* -*- 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 "gtest/gtest.h"
#include "FileSystemMocks.h"
#include "mozilla/dom/FileSystemDirectoryHandle.h"
#include "mozilla/dom/FileSystemDirectoryHandleBinding.h"
#include "mozilla/dom/FileSystemDirectoryIterator.h"
#include "mozilla/dom/FileSystemHandle.h"
#include "mozilla/dom/FileSystemHandleBinding.h"
#include "mozilla/UniquePtr.h"
#include "nsIGlobalObject.h"
namespace mozilla::dom::fs::test {
class TestFileSystemDirectoryHandle : public ::testing::Test {
protected:
void SetUp() override {
mRequestHandler = MakeUnique<MockFileSystemRequestHandler>();
mMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns);
mName = u"testDir"_ns;
}
nsIGlobalObject* mGlobal = GetGlobal();
UniquePtr<MockFileSystemRequestHandler> mRequestHandler;
FileSystemEntryMetadata mMetadata;
nsString mName;
};
TEST_F(TestFileSystemDirectoryHandle, constructDirectoryHandleRefPointer) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata);
ASSERT_TRUE(dirHandle);
}
TEST_F(TestFileSystemDirectoryHandle, areEntriesReturned) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
RefPtr<FileSystemDirectoryIterator> entries = dirHandle->Entries();
ASSERT_TRUE(entries);
}
TEST_F(TestFileSystemDirectoryHandle, areKeysReturned) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
RefPtr<FileSystemDirectoryIterator> keys = dirHandle->Keys();
ASSERT_TRUE(keys);
}
TEST_F(TestFileSystemDirectoryHandle, areValuesReturned) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
RefPtr<FileSystemDirectoryIterator> values = dirHandle->Values();
ASSERT_TRUE(values);
}
TEST_F(TestFileSystemDirectoryHandle, isHandleKindDirectory) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
ASSERT_EQ(FileSystemHandleKind::Directory, dirHandle->Kind());
}
TEST_F(TestFileSystemDirectoryHandle, isFileHandleReturned) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
FileSystemGetFileOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->GetFileHandle(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemDirectoryHandle, doesGetFileHandleFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata);
ASSERT_TRUE(dirHandle);
FileSystemGetFileOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->GetFileHandle(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
TEST_F(TestFileSystemDirectoryHandle, isDirectoryHandleReturned) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
FileSystemGetDirectoryOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->GetDirectoryHandle(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemDirectoryHandle, doesGetDirectoryHandleFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata);
ASSERT_TRUE(dirHandle);
FileSystemGetDirectoryOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->GetDirectoryHandle(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
TEST_F(TestFileSystemDirectoryHandle, isRemoveEntrySuccessful) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
FileSystemRemoveOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->RemoveEntry(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemDirectoryHandle, doesRemoveEntryFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata);
ASSERT_TRUE(dirHandle);
FileSystemRemoveOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->RemoveEntry(mName, options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
TEST_F(TestFileSystemDirectoryHandle, isResolveSuccessful) {
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata,
mRequestHandler.release());
ASSERT_TRUE(dirHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->Resolve(*dirHandle, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemDirectoryHandle, doesResolveFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemDirectoryHandle> dirHandle =
MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mMetadata);
ASSERT_TRUE(dirHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->Resolve(*dirHandle, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
} // namespace mozilla::dom::fs::test

View File

@ -0,0 +1,127 @@
/* -*- 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 "gtest/gtest.h"
#include "FileSystemMocks.h"
#include "mozilla/dom/FileSystemFileHandle.h"
#include "mozilla/dom/FileSystemFileHandleBinding.h"
#include "mozilla/dom/FileSystemHandle.h"
#include "mozilla/dom/FileSystemHandleBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/UniquePtr.h"
#include "nsIGlobalObject.h"
namespace mozilla::dom::fs::test {
class TestFileSystemFileHandle : public ::testing::Test {
protected:
void SetUp() override {
mRequestHandler = MakeUnique<MockFileSystemRequestHandler>();
mMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns);
}
nsIGlobalObject* mGlobal = GetGlobal();
UniquePtr<MockFileSystemRequestHandler> mRequestHandler;
FileSystemEntryMetadata mMetadata;
};
TEST_F(TestFileSystemFileHandle, constructFileHandleRefPointer) {
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
}
TEST_F(TestFileSystemFileHandle, isHandleKindFile) {
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
ASSERT_EQ(FileSystemHandleKind::File, fileHandle->Kind());
}
TEST_F(TestFileSystemFileHandle, isFileReturned) {
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->GetFile(rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemFileHandle, doesGetFileFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->GetFile(rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
TEST_F(TestFileSystemFileHandle, isWritableReturned) {
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
FileSystemCreateWritableOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->CreateWritable(options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemFileHandle, doesCreateWritableFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
FileSystemCreateWritableOptions options;
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->CreateWritable(options, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
TEST_F(TestFileSystemFileHandle, isSyncAccessHandleReturned) {
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->CreateSyncAccessHandle(rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
}
TEST_F(TestFileSystemFileHandle, doesCreateSyncAccessHandleFailOnNullGlobal) {
mGlobal = nullptr;
RefPtr<FileSystemFileHandle> fileHandle = MakeAndAddRef<FileSystemFileHandle>(
mGlobal, mMetadata, mRequestHandler.release());
ASSERT_TRUE(fileHandle);
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->CreateSyncAccessHandle(rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_ERROR_UNEXPECTED));
}
} // namespace mozilla::dom::fs::test

View File

@ -0,0 +1,104 @@
/* -*- 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 "gtest/gtest.h"
#include "FileSystemMocks.h"
#include "mozilla/dom/FileSystemDirectoryHandle.h"
#include "mozilla/dom/FileSystemFileHandle.h"
#include "mozilla/dom/FileSystemHandle.h"
#include "mozilla/dom/FileSystemHandleBinding.h"
#include "nsIGlobalObject.h"
namespace mozilla::dom::fs::test {
class TestFileSystemHandle : public ::testing::Test {
protected:
void SetUp() override {
mDirMetadata = FileSystemEntryMetadata("dir"_ns, u"Directory"_ns);
mFileMetadata = FileSystemEntryMetadata("file"_ns, u"File"_ns);
}
nsIGlobalObject* mGlobal = GetGlobal();
FileSystemEntryMetadata mDirMetadata;
FileSystemEntryMetadata mFileMetadata;
};
TEST_F(TestFileSystemHandle, createAndDestroyHandles) {
RefPtr<FileSystemHandle> dirHandle =
new FileSystemDirectoryHandle(mGlobal, mDirMetadata);
RefPtr<FileSystemHandle> fileHandle =
new FileSystemFileHandle(mGlobal, mFileMetadata);
EXPECT_TRUE(dirHandle);
EXPECT_TRUE(fileHandle);
}
TEST_F(TestFileSystemHandle, areFileNamesAsExpected) {
RefPtr<FileSystemHandle> dirHandle =
new FileSystemDirectoryHandle(mGlobal, mDirMetadata);
RefPtr<FileSystemHandle> fileHandle =
new FileSystemFileHandle(mGlobal, mFileMetadata);
auto GetEntryName = [](const RefPtr<FileSystemHandle>& aHandle) {
DOMString domName;
aHandle->GetName(domName);
nsString result;
domName.ToString(result);
return result;
};
const nsString& dirName = GetEntryName(dirHandle);
EXPECT_TRUE(mDirMetadata.entryName().Equals(dirName));
const nsString& fileName = GetEntryName(fileHandle);
EXPECT_TRUE(mFileMetadata.entryName().Equals(fileName));
}
TEST_F(TestFileSystemHandle, isParentObjectReturned) {
ASSERT_TRUE(mGlobal);
RefPtr<FileSystemHandle> dirHandle =
new FileSystemDirectoryHandle(mGlobal, mDirMetadata);
ASSERT_EQ(mGlobal, dirHandle->GetParentObject());
}
TEST_F(TestFileSystemHandle, areHandleKindsAsExpected) {
RefPtr<FileSystemHandle> dirHandle =
new FileSystemDirectoryHandle(mGlobal, mDirMetadata);
RefPtr<FileSystemHandle> fileHandle =
new FileSystemFileHandle(mGlobal, mFileMetadata);
EXPECT_EQ(FileSystemHandleKind::Directory, dirHandle->Kind());
EXPECT_EQ(FileSystemHandleKind::File, fileHandle->Kind());
}
TEST_F(TestFileSystemHandle, isDifferentEntry) {
RefPtr<FileSystemHandle> dirHandle =
new FileSystemDirectoryHandle(mGlobal, mDirMetadata);
RefPtr<FileSystemHandle> fileHandle =
new FileSystemFileHandle(mGlobal, mFileMetadata);
IgnoredErrorResult rv;
RefPtr<Promise> promise = dirHandle->IsSameEntry(*fileHandle, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
ASSERT_TRUE(promise);
ASSERT_EQ(Promise::PromiseState::Rejected, promise->State());
}
TEST_F(TestFileSystemHandle, isSameEntry) {
RefPtr<FileSystemHandle> fileHandle =
new FileSystemFileHandle(mGlobal, mFileMetadata);
IgnoredErrorResult rv;
RefPtr<Promise> promise = fileHandle->IsSameEntry(*fileHandle, rv);
ASSERT_TRUE(rv.ErrorCodeIs(NS_OK));
ASSERT_TRUE(promise);
ASSERT_EQ(Promise::PromiseState::Rejected, promise->State());
}
} // namespace mozilla::dom::fs::test

View File

@ -0,0 +1,21 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES = [
"TestFileSystemDirectoryHandle.cpp",
"TestFileSystemFileHandle.cpp",
"TestFileSystemHandle.cpp",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul-gtest"
LOCAL_INCLUDES += [
"/dom/fs/api",
"/dom/fs/include",
"/dom/fs/test/gtest",
]

View File

@ -0,0 +1,94 @@
/* -*- 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 "gtest/gtest.h"
#include "FileSystemMocks.h"
#include "fs/FileSystemRequestHandler.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/UniquePtr.h"
namespace mozilla::dom::fs::test {
class TestFileSystemRequestHandler : public ::testing::Test {
protected:
void SetUp() override {
mListener = MakeAndAddRef<ExpectNotImplemented>();
mRequestHandler = MakeUnique<FileSystemRequestHandler>();
mChild = FileSystemChildMetadata("parent"_ns, u"ChildName"_ns);
mEntry = FileSystemEntryMetadata("myid"_ns, u"EntryName"_ns);
mName = u"testDir"_ns;
mActor = MakeAndAddRef<FileSystemActorHolder>();
}
already_AddRefed<Promise> GetDefaultPromise() {
IgnoredErrorResult rv;
RefPtr<Promise> result = Promise::Create(mGlobal, rv);
mListener->ClearDone();
result->AppendNativeHandler(mListener->AsHandler());
return result.forget();
}
nsIGlobalObject* mGlobal = GetGlobal();
RefPtr<ExpectNotImplemented> mListener;
UniquePtr<FileSystemRequestHandler> mRequestHandler;
FileSystemChildMetadata mChild;
FileSystemEntryMetadata mEntry;
nsString mName;
RefPtr<FileSystemActorHolder> mActor;
};
TEST_F(TestFileSystemRequestHandler, isGetRootSuccessful) {
const Origin origin = "http://example.com"_ns;
RefPtr<Promise> promise = GetDefaultPromise();
mRequestHandler->GetRoot(origin, promise);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
TEST_F(TestFileSystemRequestHandler, isGetDirectoryHandleSuccessful) {
RefPtr<Promise> promise = GetDefaultPromise();
mRequestHandler->GetDirectoryHandle(mActor, mChild,
/* create */ true, promise);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
TEST_F(TestFileSystemRequestHandler, isGetFileHandleSuccessful) {
RefPtr<Promise> promise = GetDefaultPromise();
mRequestHandler->GetFileHandle(mActor, mChild, /* create */ true, promise);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
TEST_F(TestFileSystemRequestHandler, isGetFileSuccessful) {
RefPtr<Promise> promise = GetDefaultPromise();
mRequestHandler->GetFile(mActor, mEntry, promise);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
TEST_F(TestFileSystemRequestHandler, isGetEntriesSuccessful) {
RefPtr<Promise> promise = GetDefaultPromise();
ArrayAppendable sink;
mRequestHandler->GetEntries(mActor, mEntry.entryId(), /* page */ 0, promise,
sink);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
TEST_F(TestFileSystemRequestHandler, isRemoveEntrySuccessful) {
RefPtr<Promise> promise = GetDefaultPromise();
mRequestHandler->RemoveEntry(mActor, mChild, /* recursive */ true, promise);
SpinEventLoopUntil("Promise is fulfilled or timeout"_ns,
[this]() { return mListener->IsDone(); });
}
} // namespace mozilla::dom::fs::test

View File

@ -0,0 +1,19 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES = [
"TestFileSystemRequestHandler.cpp",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul-gtest"
LOCAL_INCLUDES += [
"/dom/fs/child",
"/dom/fs/include",
"/dom/fs/test/gtest",
]

View File

@ -0,0 +1,22 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
TEST_DIRS += [
"api",
"child",
]
UNIFIED_SOURCES = [
"FileSystemMocks.cpp",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul-gtest"
LOCAL_INCLUDES += [
"/dom/fs/include",
]

View File

@ -26,3 +26,7 @@ TEST_HARNESS_FILES.xpcshell.dom.fs.test.common += [
"common/nsresult.js",
"common/test_basics.js",
]
TEST_DIRS += [
"gtest",
]

View File

@ -14,6 +14,7 @@
#include "mozilla/RDDProcessManager.h"
#include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/BackgroundFileSystemParent.h"
#include "mozilla/dom/BackgroundSessionStorageServiceParent.h"
#include "mozilla/dom/ClientManagerActors.h"
#include "mozilla/dom/ContentParent.h"
@ -183,6 +184,14 @@ auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent(
return AllocPBackgroundIDBFactoryParent(aLoggingInfo);
}
auto BackgroundParentImpl::AllocPBackgroundFileSystemParent()
-> already_AddRefed<PBackgroundFileSystemParent> {
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return MakeAndAddRef<mozilla::dom::BackgroundFileSystemParent>();
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor(
PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo) {

View File

@ -28,6 +28,9 @@ class BackgroundParentImpl : public PBackgroundParent {
bool DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) override;
already_AddRefed<PBackgroundFileSystemParent>
AllocPBackgroundFileSystemParent() override;
already_AddRefed<PBackgroundIDBFactoryParent>
AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo) override;

View File

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackgroundDataBridge;
include protocol PBackgroundFileSystem;
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIndexedDBUtils;
include protocol PBackgroundSDBConnection;
@ -81,6 +82,7 @@ namespace ipc {
sync protocol PBackground
{
manages PBackgroundDataBridge;
manages PBackgroundFileSystem;
manages PBackgroundIDBFactory;
manages PBackgroundIndexedDBUtils;
manages PBackgroundSDBConnection;
@ -132,6 +134,8 @@ parent:
// Only called at startup during mochitests to check the basic infrastructure.
async PBackgroundTest(nsCString testArg);
async PBackgroundFileSystem();
async PBackgroundDataBridge(uint64_t channelID);
async PBackgroundIDBFactory(LoggingInfo loggingInfo);