Bug 1882465 - Update .hg-annotate-ignore-revs and .git-blame-ignore-revs to reflect...
[gecko.git] / dom / system / PathUtils.h
blob1870d92f23525497e688bdc3e700de5e20147824
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_PathUtils__
8 #define mozilla_dom_PathUtils__
10 #include "mozilla/DataMutex.h"
11 #include "mozilla/EnumeratedArray.h"
12 #include "mozilla/Maybe.h"
13 #include "mozilla/MozPromise.h"
14 #include "mozilla/Mutex.h"
15 #include "mozilla/Result.h"
16 #include "mozilla/dom/PathUtilsBinding.h"
17 #include "mozilla/dom/Promise.h"
18 #include "nsAppDirectoryServiceDefs.h"
19 #include "nsDirectoryServiceDefs.h"
20 #include "nsString.h"
21 #include "nsTArray.h"
23 namespace mozilla {
24 class ErrorResult;
26 namespace dom {
28 class PathUtils final {
29 public:
30 /**
31 * Initialize the given nsIFile with the given path.
33 * This is equivalent to calling nsIFile::InitWithPath() with the caveat that
34 * on Windows debug or during Windows CI tests, we will crash if the path
35 * contains a forward slash.
37 * @param aFile The file to initialize.
38 * @param aPath The path to initialize the file with.
40 * @return The result of calling nsIFile::InitWithPath.
42 static nsresult InitFileWithPath(nsIFile* aFile, const nsAString& aPath);
44 static void Filename(const GlobalObject&, const nsAString& aPath,
45 nsString& aResult, ErrorResult& aErr);
47 static void Parent(const GlobalObject&, const nsAString& aPath,
48 const int32_t aDepth, nsString& aResult,
49 ErrorResult& aErr);
51 static void Join(const GlobalObject&, const Sequence<nsString>& aComponents,
52 nsString& aResult, ErrorResult& aErr);
54 /**
55 * Join a sequence of path components and return an nsIFile with the resulting
56 * path.
58 * @param aComponents A sequence of path components. The first component must
59 * be an absolute path.
60 * @param aErr The error result, if any.
62 * @return An nsIFile with the resulting path, if there were no errors.
63 * Otherwise, nullptr is returned.
65 static already_AddRefed<nsIFile> Join(const Span<const nsString>& aComponents,
66 ErrorResult& aErr);
68 static void JoinRelative(const GlobalObject&, const nsAString& aBasePath,
69 const nsAString& aRelativePath, nsString& aResult,
70 ErrorResult& aErr);
72 static void ToExtendedWindowsPath(const GlobalObject&, const nsAString& aPath,
73 nsString& aResult, ErrorResult& aErr);
75 static void Normalize(const GlobalObject&, const nsAString& aPath,
76 nsString& aResult, ErrorResult& aErr);
78 static void Split(const GlobalObject&, const nsAString& aPath,
79 nsTArray<nsString>& aResult, ErrorResult& aErr);
81 static void SplitRelative(const GlobalObject& aGlobal, const nsAString& aPath,
82 const SplitRelativeOptions& aOptions,
83 nsTArray<nsString>& aResult, ErrorResult& aErr);
85 static void ToFileURI(const GlobalObject&, const nsAString& aPath,
86 nsCString& aResult, ErrorResult& aErr);
88 static bool IsAbsolute(const GlobalObject&, const nsAString& aPath);
90 static void GetProfileDirSync(const GlobalObject&, nsString& aResult,
91 ErrorResult& aErr);
92 static void GetLocalProfileDirSync(const GlobalObject&, nsString& aResult,
93 ErrorResult& aErr);
94 static void GetTempDirSync(const GlobalObject&, nsString& aResult,
95 ErrorResult& aErr);
96 static void GetXulLibraryPathSync(const GlobalObject&, nsString& aResult,
97 ErrorResult& aErr);
99 static already_AddRefed<Promise> GetProfileDirAsync(
100 const GlobalObject& aGlobal, ErrorResult& aErr);
101 static already_AddRefed<Promise> GetLocalProfileDirAsync(
102 const GlobalObject& aGlobal, ErrorResult& aErr);
103 static already_AddRefed<Promise> GetTempDirAsync(const GlobalObject& aGlobal,
104 ErrorResult& aErr);
105 static already_AddRefed<Promise> GetXulLibraryPathAsync(
106 const GlobalObject& aGlobal, ErrorResult& aErr);
108 private:
109 class DirectoryCache;
110 friend class DirectoryCache;
112 static StaticDataMutex<Maybe<DirectoryCache>> sDirCache;
116 * A cache of commonly used directories
118 class PathUtils::DirectoryCache final {
119 public:
121 * A directory that can be requested via |GetDirectorySync| or
122 * |GetDirectoryAsync|.
124 enum class Directory {
126 * The user's profile directory.
128 Profile,
130 * The user's local profile directory.
132 LocalProfile,
134 * The OS temporary directory.
136 Temp,
138 * The libxul path.
140 XulLibrary,
142 * The number of Directory entries.
144 Count,
147 DirectoryCache();
148 DirectoryCache(const DirectoryCache&) = delete;
149 DirectoryCache(DirectoryCache&&) = delete;
150 DirectoryCache& operator=(const DirectoryCache&) = delete;
151 DirectoryCache& operator=(DirectoryCache&&) = delete;
154 * Ensure the cache is instantiated and schedule its destructor to run at
155 * shutdown.
157 * If the cache is already instantiated, this is a no-op.
159 * @param aCache The cache to ensure is instantiated.
161 static DirectoryCache& Ensure(Maybe<DirectoryCache>& aCache);
163 void GetDirectorySync(nsString& aResult, ErrorResult& aErr,
164 const Directory aRequestedDir);
167 * Request the path of a specific directory.
169 * If the directory has not been requested before, this may require a trip to
170 * the main thread to retrieve its path.
172 * @param aGlobalObject The JavaScript global.
173 * @param aErr The error result.
174 * @param aRequestedDir The directory for which the path is to be retrieved.
176 * @return A promise that resolves to the path of the requested directory.
178 already_AddRefed<Promise> GetDirectoryAsync(const GlobalObject& aGlobalObject,
179 ErrorResult& aErr,
180 const Directory aRequestedDir);
182 private:
183 using PopulateDirectoriesPromise = MozPromise<Ok, nsresult, false>;
186 * Populate the directory cache entry for the requested directory.
188 * @param aRequestedDir The directory cache entry that was requested via
189 * |GetDirectory|.
191 * @return If the requested directory has not been populated, this returns a
192 * promise that resolves when the population is complete.
194 * If the requested directory has already been populated, it returns
195 * nullptr instead.
197 already_AddRefed<PopulateDirectoriesPromise> PopulateDirectories(
198 const Directory aRequestedDir);
201 * Initialize the requested directory cache entry.
203 * If |Directory::Temp| is requested, all cache entries will be populated.
204 * Otherwise, only the profile and local profile cache entries will be
205 * populated. The profile and local profile cache entries have no additional
206 * overhead for populating them, but the temp directory requires creating a
207 * directory on the main thread if it has not already happened.
209 * Must be called on the main thread.
211 * @param aRequestedDir The requested directory.
213 * @return The result of initializing directories.
215 nsresult PopulateDirectoriesImpl(const Directory aRequestedDir);
218 * Resolve the internal PopulateDirectoriesPromise corresponding to
219 * |aRequestedDir| with the given result.
221 * This will allow all pending queries for the requested directory to resolve
222 * or be rejected.
224 * @param aRv The return value from PopulateDirectoriesImpl.
225 * @param aRequestedDir The requested directory cache entry. This is used to
226 * determine which internal MozPromiseHolder we are
227 * resolving.
229 void ResolvePopulateDirectoriesPromise(nsresult aRv,
230 const Directory aRequestedDir);
233 * Resolve the given JS promise with the path of the requested directory
235 * Can only be called once the cache entry for the requested directory is
236 * populated.
238 * @param aPromise The JS promise to resolve.
239 * @param aRequestedDir The requested directory cache entry.
241 void ResolveWithDirectory(Promise* aPromise, const Directory aRequestedDir);
243 template <typename T>
244 using DirectoryArray =
245 EnumeratedArray<Directory, T, size_t(Directory::Count)>;
247 DirectoryArray<nsString> mDirectories;
248 DirectoryArray<MozPromiseHolder<PopulateDirectoriesPromise>> mPromises;
250 static constexpr DirectoryArray<const char*> kDirectoryNames{
251 NS_APP_USER_PROFILE_50_DIR,
252 NS_APP_USER_PROFILE_LOCAL_50_DIR,
253 NS_OS_TEMP_DIR,
254 NS_XPCOM_LIBRARY_FILE,
258 } // namespace dom
259 } // namespace mozilla
261 #endif