Bug 1863873 - Block ability to perform audio decoding outside of Utility on release...
[gecko.git] / dom / filesystem / Directory.cpp
blobda5d6e551564e423da9565e49515568f8d051eae
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"
12 #include "nsIFile.h"
13 #include "nsString.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)
46 NS_INTERFACE_MAP_END
48 /* static */
49 already_AddRefed<Directory> Directory::Constructor(const GlobalObject& aGlobal,
50 const nsAString& aRealPath,
51 ErrorResult& aRv) {
52 nsCOMPtr<nsIFile> path;
53 aRv = NS_NewLocalFile(aRealPath, true, getter_AddRefs(path));
54 if (NS_WARN_IF(aRv.Failed())) {
55 return nullptr;
58 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
59 if (NS_WARN_IF(!global)) {
60 aRv.Throw(NS_ERROR_FAILURE);
61 return nullptr;
64 return Create(global, path);
67 /* static */
68 already_AddRefed<Directory> Directory::Create(nsIGlobalObject* aGlobal,
69 nsIFile* aFile,
70 FileSystemBase* aFileSystem) {
71 MOZ_ASSERT(aGlobal);
72 MOZ_ASSERT(aFile);
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) {
81 MOZ_ASSERT(aFile);
83 // aFileSystem can be null. In this case we create a OSFileSystem when needed.
84 if (aFileSystem) {
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) {
103 aRetval.Truncate();
105 RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
106 if (NS_WARN_IF(aRv.Failed())) {
107 return;
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())) {
118 return;
121 fs->GetDOMPath(mFile, mPath, aRv);
122 if (NS_WARN_IF(aRv.Failed())) {
123 return;
127 aRetval = mPath;
130 nsresult Directory::GetFullRealPath(nsAString& aPath) {
131 nsresult rv = mFile->GetPath(aPath);
132 if (NS_WARN_IF(NS_FAILED(rv))) {
133 return rv;
136 return NS_OK;
139 already_AddRefed<Promise> Directory::GetFilesAndDirectories(ErrorResult& aRv) {
140 RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
141 if (NS_WARN_IF(aRv.Failed())) {
142 return nullptr;
145 RefPtr<GetDirectoryListingTaskChild> task =
146 GetDirectoryListingTaskChild::Create(fs, this, mFile, mFilters, aRv);
147 if (NS_WARN_IF(aRv.Failed())) {
148 return nullptr;
151 task->Start();
153 return task->GetPromise();
156 already_AddRefed<Promise> Directory::GetFiles(bool aRecursiveFlag,
157 ErrorResult& aRv) {
158 ErrorResult rv;
159 RefPtr<FileSystemBase> fs = GetFileSystem(rv);
160 if (NS_WARN_IF(rv.Failed())) {
161 aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
162 return nullptr;
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);
169 return nullptr;
172 task->Start();
174 return task->GetPromise();
177 void Directory::SetContentFilters(const nsAString& aFilters) {
178 mFilters = aFilters;
181 FileSystemBase* Directory::GetFileSystem(ErrorResult& aRv) {
182 if (!mFileSystem) {
183 nsAutoString path;
184 aRv = mFile->GetPath(path);
185 if (NS_WARN_IF(aRv.Failed())) {
186 return nullptr;
189 RefPtr<OSFileSystem> fs = new OSFileSystem(path);
190 fs->Init(mGlobal);
192 mFileSystem = fs;
195 return mFileSystem;
198 } // namespace mozilla::dom