1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "FileSystemDirectoryReader.h"
8 #include "CallbackRunnables.h"
9 #include "FileSystemFileEntry.h"
10 #include "js/Array.h" // JS::NewArrayObject
11 #include "js/PropertyAndElement.h" // JS_GetElement
12 #include "mozilla/dom/FileBinding.h"
13 #include "mozilla/dom/FileSystem.h"
14 #include "mozilla/dom/FileSystemDirectoryReaderBinding.h"
15 #include "mozilla/dom/FileSystemUtils.h"
16 #include "mozilla/dom/Directory.h"
17 #include "mozilla/dom/DirectoryBinding.h"
18 #include "mozilla/dom/Promise.h"
19 #include "mozilla/dom/PromiseNativeHandler.h"
21 namespace mozilla::dom
{
25 class PromiseHandler final
: public PromiseNativeHandler
{
29 PromiseHandler(FileSystemDirectoryEntry
* aParentEntry
,
30 FileSystem
* aFileSystem
,
31 FileSystemEntriesCallback
* aSuccessCallback
,
32 ErrorCallback
* aErrorCallback
)
33 : mParentEntry(aParentEntry
),
34 mFileSystem(aFileSystem
),
35 mSuccessCallback(aSuccessCallback
),
36 mErrorCallback(aErrorCallback
) {
37 MOZ_ASSERT(aParentEntry
);
38 MOZ_ASSERT(aFileSystem
);
39 MOZ_ASSERT(aSuccessCallback
);
43 virtual void ResolvedCallback(JSContext
* aCx
, JS::Handle
<JS::Value
> aValue
,
44 ErrorResult
& aRv
) override
{
45 if (NS_WARN_IF(!aValue
.isObject())) {
49 JS::Rooted
<JSObject
*> obj(aCx
, &aValue
.toObject());
52 if (NS_WARN_IF(!JS::GetArrayLength(aCx
, obj
, &length
))) {
56 Sequence
<OwningNonNull
<FileSystemEntry
>> sequence
;
57 if (NS_WARN_IF(!sequence
.SetLength(length
, fallible
))) {
61 for (uint32_t i
= 0; i
< length
; ++i
) {
62 JS::Rooted
<JS::Value
> value(aCx
);
63 if (NS_WARN_IF(!JS_GetElement(aCx
, obj
, i
, &value
))) {
67 if (NS_WARN_IF(!value
.isObject())) {
71 JS::Rooted
<JSObject
*> valueObj(aCx
, &value
.toObject());
74 if (NS_SUCCEEDED(UNWRAP_OBJECT(File
, valueObj
, file
))) {
75 RefPtr
<FileSystemFileEntry
> entry
= new FileSystemFileEntry(
76 mParentEntry
->GetParentObject(), file
, mParentEntry
, mFileSystem
);
81 RefPtr
<Directory
> directory
;
83 NS_FAILED(UNWRAP_OBJECT(Directory
, valueObj
, directory
)))) {
87 RefPtr
<FileSystemDirectoryEntry
> entry
=
88 new FileSystemDirectoryEntry(mParentEntry
->GetParentObject(),
89 directory
, mParentEntry
, mFileSystem
);
93 mSuccessCallback
->Call(sequence
);
96 virtual void RejectedCallback(JSContext
* aCx
, JS::Handle
<JS::Value
> aValue
,
97 ErrorResult
& aRv
) override
{
99 RefPtr
<ErrorCallbackRunnable
> runnable
= new ErrorCallbackRunnable(
100 mParentEntry
->GetParentObject(), mErrorCallback
,
101 NS_ERROR_DOM_INVALID_STATE_ERR
);
103 FileSystemUtils::DispatchRunnable(mParentEntry
->GetParentObject(),
109 ~PromiseHandler() = default;
111 RefPtr
<FileSystemDirectoryEntry
> mParentEntry
;
112 RefPtr
<FileSystem
> mFileSystem
;
113 const RefPtr
<FileSystemEntriesCallback
> mSuccessCallback
;
114 RefPtr
<ErrorCallback
> mErrorCallback
;
117 NS_IMPL_ISUPPORTS0(PromiseHandler
);
119 } // anonymous namespace
121 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemDirectoryReader
, mParentEntry
,
122 mDirectory
, mFileSystem
)
124 NS_IMPL_CYCLE_COLLECTING_ADDREF(FileSystemDirectoryReader
)
125 NS_IMPL_CYCLE_COLLECTING_RELEASE(FileSystemDirectoryReader
)
127 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FileSystemDirectoryReader
)
128 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
129 NS_INTERFACE_MAP_ENTRY(nsISupports
)
132 FileSystemDirectoryReader::FileSystemDirectoryReader(
133 FileSystemDirectoryEntry
* aParentEntry
, FileSystem
* aFileSystem
,
134 Directory
* aDirectory
)
135 : mParentEntry(aParentEntry
),
136 mFileSystem(aFileSystem
),
137 mDirectory(aDirectory
),
138 mAlreadyRead(false) {
139 MOZ_ASSERT(aParentEntry
);
140 MOZ_ASSERT(aFileSystem
);
143 FileSystemDirectoryReader::~FileSystemDirectoryReader() = default;
145 JSObject
* FileSystemDirectoryReader::WrapObject(
146 JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
147 return FileSystemDirectoryReader_Binding::Wrap(aCx
, this, aGivenProto
);
150 void FileSystemDirectoryReader::ReadEntries(
151 FileSystemEntriesCallback
& aSuccessCallback
,
152 const Optional
<OwningNonNull
<ErrorCallback
>>& aErrorCallback
,
154 MOZ_ASSERT(mDirectory
);
157 RefPtr
<EmptyEntriesCallbackRunnable
> runnable
=
158 new EmptyEntriesCallbackRunnable(&aSuccessCallback
);
160 FileSystemUtils::DispatchRunnable(GetParentObject(), runnable
.forget());
164 // This object can be used only once.
168 RefPtr
<Promise
> promise
= mDirectory
->GetFilesAndDirectories(rv
);
169 if (NS_WARN_IF(rv
.Failed())) {
170 ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback
,
175 RefPtr
<PromiseHandler
> handler
= new PromiseHandler(
176 mParentEntry
, mFileSystem
, &aSuccessCallback
,
177 aErrorCallback
.WasPassed() ? &aErrorCallback
.Value() : nullptr);
178 promise
->AppendNativeHandler(handler
);
181 } // namespace mozilla::dom