Line data Source code
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/. */
6 :
7 : #include "mozilla/dom/Directory.h"
8 :
9 : #include "GetDirectoryListingTask.h"
10 : #include "GetFilesTask.h"
11 : #include "WorkerPrivate.h"
12 :
13 : #include "nsCharSeparatedTokenizer.h"
14 : #include "nsString.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 :
20 : namespace mozilla {
21 : namespace dom {
22 :
23 : NS_IMPL_CYCLE_COLLECTION_CLASS(Directory)
24 :
25 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Directory)
26 0 : if (tmp->mFileSystem) {
27 0 : tmp->mFileSystem->Unlink();
28 0 : tmp->mFileSystem = nullptr;
29 : }
30 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
31 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
32 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
33 :
34 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Directory)
35 0 : if (tmp->mFileSystem) {
36 0 : tmp->mFileSystem->Traverse(cb);
37 : }
38 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
39 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
40 :
41 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Directory)
42 :
43 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Directory)
44 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Directory)
45 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Directory)
46 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
47 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
48 0 : NS_INTERFACE_MAP_END
49 :
50 : /* static */ bool
51 2 : Directory::WebkitBlinkDirectoryPickerEnabled(JSContext* aCx, JSObject* aObj)
52 : {
53 2 : if (NS_IsMainThread()) {
54 1 : return Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false);
55 : }
56 :
57 : // aCx can be null when this function is called by something else than WebIDL
58 : // binding code.
59 : workers::WorkerPrivate* workerPrivate =
60 1 : workers::GetCurrentThreadWorkerPrivate();
61 1 : if (!workerPrivate) {
62 0 : return false;
63 : }
64 :
65 1 : return workerPrivate->WebkitBlinkDirectoryPickerEnabled();
66 : }
67 :
68 : /* static */ already_AddRefed<Directory>
69 0 : Directory::Constructor(const GlobalObject& aGlobal,
70 : const nsAString& aRealPath,
71 : ErrorResult& aRv)
72 : {
73 0 : nsCOMPtr<nsIFile> path;
74 0 : aRv = NS_NewLocalFile(aRealPath, true, getter_AddRefs(path));
75 0 : if (NS_WARN_IF(aRv.Failed())) {
76 0 : return nullptr;
77 : }
78 :
79 0 : return Create(aGlobal.GetAsSupports(), path);
80 : }
81 :
82 : /* static */ already_AddRefed<Directory>
83 0 : Directory::Create(nsISupports* aParent, nsIFile* aFile,
84 : FileSystemBase* aFileSystem)
85 : {
86 0 : MOZ_ASSERT(aParent);
87 0 : MOZ_ASSERT(aFile);
88 :
89 0 : RefPtr<Directory> directory = new Directory(aParent, aFile, aFileSystem);
90 0 : return directory.forget();
91 : }
92 :
93 0 : Directory::Directory(nsISupports* aParent,
94 : nsIFile* aFile,
95 0 : FileSystemBase* aFileSystem)
96 : : mParent(aParent)
97 0 : , mFile(aFile)
98 : {
99 0 : MOZ_ASSERT(aFile);
100 :
101 : // aFileSystem can be null. In this case we create a OSFileSystem when needed.
102 0 : if (aFileSystem) {
103 : // More likely, this is a OSFileSystem. This object keeps a reference of
104 : // mParent but it's not cycle collectable and to avoid manual
105 : // addref/release, it's better to have 1 object per directory. For this
106 : // reason we clone it here.
107 0 : mFileSystem = aFileSystem->Clone();
108 : }
109 0 : }
110 :
111 0 : Directory::~Directory()
112 : {
113 0 : }
114 :
115 : nsISupports*
116 0 : Directory::GetParentObject() const
117 : {
118 0 : return mParent;
119 : }
120 :
121 : JSObject*
122 0 : Directory::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
123 : {
124 0 : return DirectoryBinding::Wrap(aCx, this, aGivenProto);
125 : }
126 :
127 : void
128 0 : Directory::GetName(nsAString& aRetval, ErrorResult& aRv)
129 : {
130 0 : aRetval.Truncate();
131 :
132 0 : RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
133 0 : if (NS_WARN_IF(aRv.Failed())) {
134 0 : return;
135 : }
136 :
137 0 : fs->GetDirectoryName(mFile, aRetval, aRv);
138 : }
139 :
140 : void
141 0 : Directory::GetPath(nsAString& aRetval, ErrorResult& aRv)
142 : {
143 : // This operation is expensive. Better to cache the result.
144 0 : if (mPath.IsEmpty()) {
145 0 : RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
146 0 : if (NS_WARN_IF(aRv.Failed())) {
147 0 : return;
148 : }
149 :
150 0 : fs->GetDOMPath(mFile, mPath, aRv);
151 0 : if (NS_WARN_IF(aRv.Failed())) {
152 0 : return;
153 : }
154 : }
155 :
156 0 : aRetval = mPath;
157 : }
158 :
159 : nsresult
160 0 : Directory::GetFullRealPath(nsAString& aPath)
161 : {
162 0 : nsresult rv = mFile->GetPath(aPath);
163 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
164 0 : return rv;
165 : }
166 :
167 0 : return NS_OK;
168 : }
169 :
170 : already_AddRefed<Promise>
171 0 : Directory::GetFilesAndDirectories(ErrorResult& aRv)
172 : {
173 0 : RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
174 0 : if (NS_WARN_IF(aRv.Failed())) {
175 0 : return nullptr;
176 : }
177 :
178 : RefPtr<GetDirectoryListingTaskChild> task =
179 0 : GetDirectoryListingTaskChild::Create(fs, this, mFile, mFilters, aRv);
180 0 : if (NS_WARN_IF(aRv.Failed())) {
181 0 : return nullptr;
182 : }
183 :
184 0 : task->Start();
185 :
186 0 : return task->GetPromise();
187 : }
188 :
189 : already_AddRefed<Promise>
190 0 : Directory::GetFiles(bool aRecursiveFlag, ErrorResult& aRv)
191 : {
192 0 : ErrorResult rv;
193 0 : RefPtr<FileSystemBase> fs = GetFileSystem(rv);
194 0 : if (NS_WARN_IF(rv.Failed())) {
195 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
196 0 : return nullptr;
197 : }
198 :
199 : RefPtr<GetFilesTaskChild> task =
200 0 : GetFilesTaskChild::Create(fs, this, mFile, aRecursiveFlag, rv);
201 0 : if (NS_WARN_IF(rv.Failed())) {
202 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
203 0 : return nullptr;
204 : }
205 :
206 0 : task->Start();
207 :
208 0 : return task->GetPromise();
209 : }
210 :
211 : void
212 0 : Directory::SetContentFilters(const nsAString& aFilters)
213 : {
214 0 : mFilters = aFilters;
215 0 : }
216 :
217 : FileSystemBase*
218 0 : Directory::GetFileSystem(ErrorResult& aRv)
219 : {
220 0 : if (!mFileSystem) {
221 0 : nsAutoString path;
222 0 : aRv = mFile->GetPath(path);
223 0 : if (NS_WARN_IF(aRv.Failed())) {
224 0 : return nullptr;
225 : }
226 :
227 0 : RefPtr<OSFileSystem> fs = new OSFileSystem(path);
228 0 : fs->Init(mParent);
229 :
230 0 : mFileSystem = fs;
231 : }
232 :
233 0 : return mFileSystem;
234 : }
235 :
236 : } // namespace dom
237 : } // namespace mozilla
|