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 "mozilla/dom/Directory.h"
9 #include "GetDirectoryListingTask.h"
10 #include "GetFilesTask.h"
14 #include "mozilla/dom/BlobImpl.h"
15 #include "mozilla/dom/DirectoryBinding.h"
16 #include "mozilla/dom/FileSystemBase.h"
17 #include "mozilla/dom/FileSystemUtils.h"
18 #include "mozilla/dom/OSFileSystem.h"
19 #include "mozilla/dom/WorkerPrivate.h"
21 namespace mozilla::dom
{
23 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Directory
)
25 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Directory
)
26 if (tmp
->mFileSystem
) {
27 tmp
->mFileSystem
->Unlink();
28 tmp
->mFileSystem
= nullptr;
30 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal
)
31 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Directory
)
35 if (tmp
->mFileSystem
) {
36 tmp
->mFileSystem
->Traverse(cb
);
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal
)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41 NS_IMPL_CYCLE_COLLECTING_ADDREF(Directory
)
42 NS_IMPL_CYCLE_COLLECTING_RELEASE(Directory
)
43 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Directory
)
44 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
45 NS_INTERFACE_MAP_ENTRY(nsISupports
)
49 already_AddRefed
<Directory
> Directory::Constructor(const GlobalObject
& aGlobal
,
50 const nsAString
& aRealPath
,
52 nsCOMPtr
<nsIFile
> path
;
53 aRv
= NS_NewLocalFile(aRealPath
, true, getter_AddRefs(path
));
54 if (NS_WARN_IF(aRv
.Failed())) {
58 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
59 if (NS_WARN_IF(!global
)) {
60 aRv
.Throw(NS_ERROR_FAILURE
);
64 return Create(global
, path
);
68 already_AddRefed
<Directory
> Directory::Create(nsIGlobalObject
* aGlobal
,
70 FileSystemBase
* aFileSystem
) {
74 RefPtr
<Directory
> directory
= new Directory(aGlobal
, aFile
, aFileSystem
);
75 return directory
.forget();
78 Directory::Directory(nsIGlobalObject
* aGlobal
, nsIFile
* aFile
,
79 FileSystemBase
* aFileSystem
)
80 : mGlobal(aGlobal
), mFile(aFile
) {
83 // aFileSystem can be null. In this case we create a OSFileSystem when needed.
85 // More likely, this is a OSFileSystem. This object keeps a reference of
86 // mGlobal but it's not cycle collectable and to avoid manual
87 // addref/release, it's better to have 1 object per directory. For this
88 // reason we clone it here.
89 mFileSystem
= aFileSystem
->Clone();
93 Directory::~Directory() = default;
95 nsIGlobalObject
* Directory::GetParentObject() const { return mGlobal
; }
97 JSObject
* Directory::WrapObject(JSContext
* aCx
,
98 JS::Handle
<JSObject
*> aGivenProto
) {
99 return Directory_Binding::Wrap(aCx
, this, aGivenProto
);
102 void Directory::GetName(nsAString
& aRetval
, ErrorResult
& aRv
) {
105 RefPtr
<FileSystemBase
> fs
= GetFileSystem(aRv
);
106 if (NS_WARN_IF(aRv
.Failed())) {
110 fs
->GetDirectoryName(mFile
, aRetval
, aRv
);
113 void Directory::GetPath(nsAString
& aRetval
, ErrorResult
& aRv
) {
114 // This operation is expensive. Better to cache the result.
115 if (mPath
.IsEmpty()) {
116 RefPtr
<FileSystemBase
> fs
= GetFileSystem(aRv
);
117 if (NS_WARN_IF(aRv
.Failed())) {
121 fs
->GetDOMPath(mFile
, mPath
, aRv
);
122 if (NS_WARN_IF(aRv
.Failed())) {
130 nsresult
Directory::GetFullRealPath(nsAString
& aPath
) {
131 nsresult rv
= mFile
->GetPath(aPath
);
132 if (NS_WARN_IF(NS_FAILED(rv
))) {
139 already_AddRefed
<Promise
> Directory::GetFilesAndDirectories(ErrorResult
& aRv
) {
140 RefPtr
<FileSystemBase
> fs
= GetFileSystem(aRv
);
141 if (NS_WARN_IF(aRv
.Failed())) {
145 RefPtr
<GetDirectoryListingTaskChild
> task
=
146 GetDirectoryListingTaskChild::Create(fs
, this, mFile
, mFilters
, aRv
);
147 if (NS_WARN_IF(aRv
.Failed())) {
153 return task
->GetPromise();
156 already_AddRefed
<Promise
> Directory::GetFiles(bool aRecursiveFlag
,
159 RefPtr
<FileSystemBase
> fs
= GetFileSystem(rv
);
160 if (NS_WARN_IF(rv
.Failed())) {
161 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
165 RefPtr
<GetFilesTaskChild
> task
=
166 GetFilesTaskChild::Create(fs
, this, mFile
, aRecursiveFlag
, rv
);
167 if (NS_WARN_IF(rv
.Failed())) {
168 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
174 return task
->GetPromise();
177 void Directory::SetContentFilters(const nsAString
& aFilters
) {
181 FileSystemBase
* Directory::GetFileSystem(ErrorResult
& aRv
) {
184 aRv
= mFile
->GetPath(path
);
185 if (NS_WARN_IF(aRv
.Failed())) {
189 RefPtr
<OSFileSystem
> fs
= new OSFileSystem(path
);
198 } // namespace mozilla::dom