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 #ifndef mozilla_dom_quota_quotamanager_h__
8 #define mozilla_dom_quota_quotamanager_h__
13 #include "ErrorList.h"
14 #include "mozilla/AlreadyAddRefed.h"
15 #include "mozilla/Assertions.h"
16 #include "mozilla/InitializedOnce.h"
17 #include "mozilla/MozPromise.h"
18 #include "mozilla/Mutex.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/Result.h"
21 #include "mozilla/ThreadBound.h"
22 #include "mozilla/dom/Nullable.h"
23 #include "mozilla/dom/ipc/IdType.h"
24 #include "mozilla/dom/quota/Assertions.h"
25 #include "mozilla/dom/quota/BackgroundThreadObject.h"
26 #include "mozilla/dom/quota/CommonMetadata.h"
27 #include "mozilla/dom/quota/DirectoryLockCategory.h"
28 #include "mozilla/dom/quota/ForwardDecls.h"
29 #include "mozilla/dom/quota/HashKeys.h"
30 #include "mozilla/dom/quota/InitializationTypes.h"
31 #include "mozilla/dom/quota/NotifyUtils.h"
32 #include "mozilla/dom/quota/OriginOperationCallbacks.h"
33 #include "mozilla/dom/quota/PersistenceType.h"
35 #include "nsClassHashtable.h"
36 #include "nsTHashMap.h"
38 #include "nsHashKeys.h"
39 #include "nsISupports.h"
40 #include "nsStringFwd.h"
42 #include "nsTStringRepr.h"
46 #define GTEST_CLASS(testFixture, testName) testFixture##_##testName##_Test
48 class mozIStorageConnection
;
57 class OriginAttributes
;
58 class OriginAttributesPattern
;
66 } // namespace mozilla
68 namespace mozilla::dom::quota
{
70 class CanonicalQuotaObject
;
72 class ClearRequestBase
;
73 class ClientUsageArray
;
74 class ClientDirectoryLock
;
75 class DirectoryLockImpl
;
78 class NormalOriginOperationBase
;
79 class OriginDirectoryLock
;
83 class UniversalDirectoryLock
;
86 class GTEST_CLASS(TestQuotaManagerAndShutdownFixture
,
87 ThumbnailPrivateIdentityTemporaryOriginCount
);
90 class QuotaManager final
: public BackgroundThreadObject
{
91 friend class CanonicalQuotaObject
;
92 friend class ClearDataOp
;
93 friend class ClearRequestBase
;
94 friend class ClearStorageOp
;
95 friend class DirectoryLockImpl
;
96 friend class FinalizeOriginEvictionOp
;
97 friend class GroupInfo
;
99 friend class InitializePersistentOriginOp
;
100 friend class InitializePersistentStorageOp
;
101 friend class InitializeTemporaryGroupOp
;
102 friend class InitializeTemporaryOriginOp
;
103 friend class InitTemporaryStorageOp
;
104 friend class ListCachedOriginsOp
;
105 friend class OriginInfo
;
106 friend class PersistOp
;
107 friend class ShutdownStorageOp
;
108 friend class test::GTEST_CLASS(TestQuotaManagerAndShutdownFixture
,
109 ThumbnailPrivateIdentityTemporaryOriginCount
);
110 friend class UniversalDirectoryLock
;
112 friend Result
<PrincipalMetadata
, nsresult
> GetInfoFromValidatedPrincipalInfo(
113 QuotaManager
& aQuotaManager
,
114 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
);
116 using PrincipalInfo
= mozilla::ipc::PrincipalInfo
;
117 using DirectoryLockTable
=
118 nsClassHashtable
<nsCStringHashKey
, nsTArray
<NotNull
<DirectoryLockImpl
*>>>;
123 QuotaManager(const nsAString
& aBasePath
, const nsAString
& aStorageName
);
125 NS_INLINE_DECL_REFCOUNTING(QuotaManager
)
127 static nsresult
Initialize();
129 static bool IsRunningXPCShellTests() {
130 static bool kRunningXPCShellTests
=
131 !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
132 return kRunningXPCShellTests
;
135 static bool IsRunningGTests() {
136 static bool kRunningGTests
= !!PR_GetEnv("MOZ_RUN_GTEST");
137 return kRunningGTests
;
140 static const char kReplaceChars
[];
141 static const char16_t kReplaceChars16
[];
143 static Result
<MovingNotNull
<RefPtr
<QuotaManager
>>, nsresult
> GetOrCreate();
145 static Result
<Ok
, nsresult
> EnsureCreated();
147 // Returns a non-owning reference.
148 static QuotaManager
* Get();
150 // Use only in gtests!
151 static nsIObserver
* GetObserver();
153 // Returns true if we've begun the shutdown process.
154 static bool IsShuttingDown();
156 static void ShutdownInstance();
158 // Use only in gtests!
161 static bool IsOSMetadata(const nsAString
& aFileName
);
163 static bool IsDotFile(const nsAString
& aFileName
);
165 void RegisterNormalOriginOp(NormalOriginOperationBase
& aNormalOriginOp
);
167 void UnregisterNormalOriginOp(NormalOriginOperationBase
& aNormalOriginOp
);
169 bool IsPersistentOriginInitializedInternal(const nsACString
& aOrigin
) const {
170 AssertIsOnIOThread();
172 return mInitializedOriginsInternal
.Contains(aOrigin
);
175 bool IsTemporaryStorageInitializedInternal() const {
176 AssertIsOnIOThread();
178 return mTemporaryStorageInitializedInternal
;
182 * For initialization of an origin where the directory either exists or it
183 * does not. The directory exists case is used by InitializeOrigin once it
184 * has tallied origin usage by calling each of the QuotaClient InitOrigin
185 * methods. It's also used by LoadQuota when quota information is available
186 * from the cache. EnsureTemporaryStorageIsInitializedInternal calls this
187 * either if the directory exists or it does not depending on requirements
188 * of a particular quota client. The special case when origin directory is
189 * not created during origin initialization is currently utilized only by
192 void InitQuotaForOrigin(const FullOriginMetadata
& aFullOriginMetadata
,
193 const ClientUsageArray
& aClientUsages
,
194 uint64_t aUsageBytes
, bool aDirectoryExists
= true);
196 // XXX clients can use QuotaObject instead of calling this method directly.
197 void DecreaseUsageForClient(const ClientMetadata
& aClientMetadata
,
200 void ResetUsageForClient(const ClientMetadata
& aClientMetadata
);
202 UsageInfo
GetUsageForClient(PersistenceType aPersistenceType
,
203 const OriginMetadata
& aOriginMetadata
,
204 Client::Type aClientType
);
206 void UpdateOriginAccessTime(PersistenceType aPersistenceType
,
207 const OriginMetadata
& aOriginMetadata
);
211 void RemoveQuotaForRepository(PersistenceType aPersistenceType
) {
212 MutexAutoLock
lock(mQuotaMutex
);
213 LockedRemoveQuotaForRepository(aPersistenceType
);
216 void RemoveQuotaForOrigin(PersistenceType aPersistenceType
,
217 const OriginMetadata
& aOriginMetadata
) {
218 MutexAutoLock
lock(mQuotaMutex
);
219 LockedRemoveQuotaForOrigin(aOriginMetadata
);
222 nsresult
LoadQuota();
226 void RemoveOriginFromCache(const OriginMetadata
& aOriginMetadata
);
228 already_AddRefed
<QuotaObject
> GetQuotaObject(
229 PersistenceType aPersistenceType
, const OriginMetadata
& aOriginMetadata
,
230 Client::Type aClientType
, nsIFile
* aFile
, int64_t aFileSize
= -1,
231 int64_t* aFileSizeOut
= nullptr);
233 already_AddRefed
<QuotaObject
> GetQuotaObject(
234 PersistenceType aPersistenceType
, const OriginMetadata
& aOriginMetadata
,
235 Client::Type aClientType
, const nsAString
& aPath
, int64_t aFileSize
= -1,
236 int64_t* aFileSizeOut
= nullptr);
238 already_AddRefed
<QuotaObject
> GetQuotaObject(const int64_t aDirectoryLockId
,
239 const nsAString
& aPath
);
241 Nullable
<bool> OriginPersisted(const OriginMetadata
& aOriginMetadata
);
243 void PersistOrigin(const OriginMetadata
& aOriginMetadata
);
245 template <typename F
>
246 auto WithOriginInfo(const OriginMetadata
& aOriginMetadata
, F aFunction
)
247 -> std::invoke_result_t
<F
, const RefPtr
<OriginInfo
>&>;
249 using DirectoryLockIdTableArray
=
250 AutoTArray
<Client::DirectoryLockIdTable
, Client::TYPE_MAX
>;
251 void AbortOperationsForLocks(const DirectoryLockIdTableArray
& aLockIds
);
253 // Called when a process is being shot down. Aborts any running operations
254 // for the given process.
255 void AbortOperationsForProcess(ContentParentId aContentParentId
);
257 Result
<nsCOMPtr
<nsIFile
>, nsresult
> GetOriginDirectory(
258 const OriginMetadata
& aOriginMetadata
) const;
260 Result
<bool, nsresult
> DoesOriginDirectoryExist(
261 const OriginMetadata
& aOriginMetadata
) const;
263 Result
<nsCOMPtr
<nsIFile
>, nsresult
> GetOrCreateTemporaryOriginDirectory(
264 const OriginMetadata
& aOriginMetadata
);
266 Result
<Ok
, nsresult
> EnsureTemporaryOriginDirectoryCreated(
267 const OriginMetadata
& aOriginMetadata
);
269 static nsresult
CreateDirectoryMetadata(
270 nsIFile
& aDirectory
, int64_t aTimestamp
,
271 const OriginMetadata
& aOriginMetadata
);
273 static nsresult
CreateDirectoryMetadata2(
274 nsIFile
& aDirectory
, int64_t aTimestamp
, bool aPersisted
,
275 const OriginMetadata
& aOriginMetadata
);
277 nsresult
RestoreDirectoryMetadata2(nsIFile
* aDirectory
);
279 // XXX Remove aPersistenceType argument once the persistence type is stored
280 // in the metadata file.
281 Result
<FullOriginMetadata
, nsresult
> LoadFullOriginMetadata(
282 nsIFile
* aDirectory
, PersistenceType aPersistenceType
);
284 Result
<FullOriginMetadata
, nsresult
> LoadFullOriginMetadataWithRestore(
285 nsIFile
* aDirectory
);
287 Result
<OriginMetadata
, nsresult
> GetOriginMetadata(nsIFile
* aDirectory
);
289 Result
<Ok
, nsresult
> RemoveOriginDirectory(nsIFile
& aDirectory
);
291 Result
<bool, nsresult
> DoesClientDirectoryExist(
292 const ClientMetadata
& aClientMetadata
) const;
294 RefPtr
<UniversalDirectoryLockPromise
> OpenStorageDirectory(
295 const PersistenceScope
& aPersistenceScope
,
296 const OriginScope
& aOriginScope
,
297 const Nullable
<Client::Type
>& aClientType
, bool aExclusive
,
298 bool aInitializeOrigins
= false,
299 DirectoryLockCategory aCategory
= DirectoryLockCategory::None
,
300 Maybe
<RefPtr
<UniversalDirectoryLock
>&> aPendingDirectoryLockOut
=
303 // This is the main entry point into the QuotaManager API.
304 // Any storage API implementation (quota client) that participates in
305 // centralized quota and storage handling should call this method to get
306 // a directory lock which will protect client's files from being deleted
307 // while they are still in use.
308 // After a lock is acquired, client is notified by resolving the returned
309 // promise. If the lock couldn't be acquired, client is notified by rejecting
310 // the returned promise. The returned lock could have been invalidated by a
311 // clear operation so consumers are supposed to check that and eventually
312 // release the lock as soon as possible (this is usually not needed for short
313 // lived operations).
314 // A lock is a reference counted object and at the time the returned promise
315 // is resolved, there are no longer other strong references except the one
316 // held by the resolve value itself. So it's up to client to add a new
317 // reference in order to keep the lock alive.
318 // Unlocking is simply done by calling lock object's Drop method. Unlocking
319 // must be always done explicitly before the lock object is destroyed (when
320 // the last strong reference is removed).
321 RefPtr
<ClientDirectoryLockPromise
> OpenClientDirectory(
322 const ClientMetadata
& aClientMetadata
, bool aInitializeOrigins
= true,
323 bool aCreateIfNonExistent
= true,
324 Maybe
<RefPtr
<ClientDirectoryLock
>&> aPendingDirectoryLockOut
= Nothing());
326 RefPtr
<ClientDirectoryLock
> CreateDirectoryLock(
327 const ClientMetadata
& aClientMetadata
, bool aExclusive
);
329 // XXX RemoveMe once bug 1170279 gets fixed.
330 RefPtr
<UniversalDirectoryLock
> CreateDirectoryLockInternal(
331 const PersistenceScope
& aPersistenceScope
,
332 const OriginScope
& aOriginScope
,
333 const Nullable
<Client::Type
>& aClientType
, bool aExclusive
,
334 DirectoryLockCategory aCategory
= DirectoryLockCategory::None
);
336 // Collect inactive and the least recently used origins.
337 uint64_t CollectOriginsForEviction(
338 uint64_t aMinSizeToBeFreed
,
339 nsTArray
<RefPtr
<OriginDirectoryLock
>>& aLocks
);
342 * Helper method to invoke the provided predicate on all "pending" OriginInfo
343 * instances. These are origins for which the origin directory has not yet
344 * been created but for which quota is already being tracked. This happens,
345 * for example, for the LocalStorage client where an origin that previously
346 * was not using LocalStorage can start issuing writes which it buffers until
347 * eventually flushing them. We defer creating the origin directory for as
348 * long as possible in that case, so the directory won't exist. Logic that
349 * would otherwise only consult the filesystem also needs to use this method.
351 template <typename P
>
352 void CollectPendingOriginsForListing(P aPredicate
);
354 bool IsPendingOrigin(const OriginMetadata
& aOriginMetadata
) const;
356 RefPtr
<BoolPromise
> InitializeStorage();
358 RefPtr
<BoolPromise
> InitializeStorage(
359 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
361 RefPtr
<BoolPromise
> StorageInitialized();
363 bool IsStorageInitialized() const {
364 AssertIsOnOwningThread();
366 return mStorageInitialized
;
369 bool IsStorageInitializedInternal() const {
370 AssertIsOnIOThread();
371 return static_cast<bool>(mStorageConnection
);
374 void AssertStorageIsInitializedInternal() const
382 RefPtr
<BoolPromise
> TemporaryStorageInitialized();
385 nsresult
EnsureStorageIsInitializedInternal();
388 RefPtr
<BoolPromise
> InitializePersistentStorage();
390 RefPtr
<BoolPromise
> InitializePersistentStorage(
391 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
393 RefPtr
<BoolPromise
> PersistentStorageInitialized();
395 bool IsPersistentStorageInitialized() const {
396 AssertIsOnOwningThread();
398 return mPersistentStorageInitialized
;
401 bool IsPersistentStorageInitializedInternal() const {
402 AssertIsOnIOThread();
404 return mPersistentStorageInitializedInternal
;
408 nsresult
EnsurePersistentStorageIsInitializedInternal();
411 RefPtr
<BoolPromise
> InitializeTemporaryGroup(
412 const PrincipalMetadata
& aPrincipalMetadata
);
414 RefPtr
<BoolPromise
> InitializeTemporaryGroup(
415 const PrincipalMetadata
& aPrincipalMetadata
,
416 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
418 RefPtr
<BoolPromise
> TemporaryGroupInitialized(
419 const PrincipalMetadata
& aPrincipalMetadata
);
421 bool IsTemporaryGroupInitialized(const PrincipalMetadata
& aPrincipalMetadata
);
423 bool IsTemporaryGroupInitializedInternal(
424 const PrincipalMetadata
& aPrincipalMetadata
) const;
427 Result
<Ok
, nsresult
> EnsureTemporaryGroupIsInitializedInternal(
428 const PrincipalMetadata
& aPrincipalMetadata
);
431 RefPtr
<BoolPromise
> InitializePersistentOrigin(
432 const OriginMetadata
& aOriginMetadata
);
434 RefPtr
<BoolPromise
> InitializePersistentOrigin(
435 const OriginMetadata
& aOriginMetadata
,
436 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
438 RefPtr
<BoolPromise
> PersistentOriginInitialized(
439 const OriginMetadata
& aOriginMetadata
);
441 bool IsPersistentOriginInitialized(const OriginMetadata
& aOriginMetadata
);
443 bool IsPersistentOriginInitializedInternal(
444 const OriginMetadata
& aOriginMetadata
) const;
447 // Returns a pair of an nsIFile object referring to the directory, and a bool
448 // indicating whether the directory was newly created.
449 Result
<std::pair
<nsCOMPtr
<nsIFile
>, bool>, nsresult
>
450 EnsurePersistentOriginIsInitializedInternal(
451 const OriginMetadata
& aOriginMetadata
);
454 RefPtr
<BoolPromise
> InitializeTemporaryOrigin(
455 const OriginMetadata
& aOriginMetadata
, bool aCreateIfNonExistent
);
457 RefPtr
<BoolPromise
> InitializeTemporaryOrigin(
458 const OriginMetadata
& aOriginMetadata
, bool aCreateIfNonExistent
,
459 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
461 RefPtr
<BoolPromise
> TemporaryOriginInitialized(
462 const OriginMetadata
& aOriginMetadata
);
464 bool IsTemporaryOriginInitialized(const OriginMetadata
& aOriginMetadata
);
466 bool IsTemporaryOriginInitializedInternal(
467 const OriginMetadata
& aOriginMetadata
) const;
470 // Returns a pair of an nsIFile object referring to the directory, and a bool
471 // indicating whether the directory was newly created.
472 Result
<std::pair
<nsCOMPtr
<nsIFile
>, bool>, nsresult
>
473 EnsureTemporaryOriginIsInitializedInternal(
474 const OriginMetadata
& aOriginMetadata
, bool aCreateIfNonExistent
);
477 RefPtr
<BoolPromise
> InitializePersistentClient(
478 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
);
480 // Returns a pair of an nsIFile object referring to the directory, and a bool
481 // indicating whether the directory was newly created.
482 Result
<std::pair
<nsCOMPtr
<nsIFile
>, bool>, nsresult
>
483 EnsurePersistentClientIsInitialized(const ClientMetadata
& aClientMetadata
);
485 RefPtr
<BoolPromise
> InitializeTemporaryClient(
486 PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
487 Client::Type aClientType
);
489 // Returns a pair of an nsIFile object referring to the directory, and a bool
490 // indicating whether the directory was newly created.
491 Result
<std::pair
<nsCOMPtr
<nsIFile
>, bool>, nsresult
>
492 EnsureTemporaryClientIsInitialized(const ClientMetadata
& aClientMetadata
);
494 RefPtr
<BoolPromise
> InitializeTemporaryStorage();
496 RefPtr
<BoolPromise
> InitializeTemporaryStorage(
497 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
499 bool IsTemporaryStorageInitialized() const {
500 AssertIsOnOwningThread();
502 return mTemporaryStorageInitialized
;
506 nsresult
EnsureTemporaryStorageIsInitializedInternal();
509 RefPtr
<BoolPromise
> InitializeAllTemporaryOrigins();
511 RefPtr
<OriginUsageMetadataArrayPromise
> GetUsage(
512 bool aGetAll
, RefPtr
<BoolPromise
> aOnCancelPromise
= nullptr);
514 RefPtr
<UsageInfoPromise
> GetOriginUsage(
515 const PrincipalInfo
& aPrincipalInfo
,
516 RefPtr
<BoolPromise
> aOnCancelPromise
= nullptr);
518 RefPtr
<UInt64Promise
> GetCachedOriginUsage(
519 const PrincipalInfo
& aPrincipalInfo
);
521 RefPtr
<CStringArrayPromise
> ListOrigins();
523 RefPtr
<CStringArrayPromise
> ListCachedOrigins();
525 RefPtr
<BoolPromise
> ClearStoragesForOrigin(
526 const Maybe
<PersistenceType
>& aPersistenceType
,
527 const PrincipalInfo
& aPrincipalInfo
);
529 RefPtr
<BoolPromise
> ClearStoragesForClient(
530 Maybe
<PersistenceType
> aPersistenceType
,
531 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
);
533 RefPtr
<BoolPromise
> ClearStoragesForOriginPrefix(
534 const Maybe
<PersistenceType
>& aPersistenceType
,
535 const PrincipalInfo
& aPrincipalInfo
);
537 RefPtr
<BoolPromise
> ClearStoragesForOriginAttributesPattern(
538 const OriginAttributesPattern
& aPattern
);
540 RefPtr
<BoolPromise
> ClearPrivateRepository();
542 RefPtr
<BoolPromise
> ClearStorage();
544 RefPtr
<BoolPromise
> ShutdownStoragesForOrigin(
545 Maybe
<PersistenceType
> aPersistenceType
,
546 const PrincipalInfo
& aPrincipalInfo
);
548 RefPtr
<BoolPromise
> ShutdownStoragesForClient(
549 Maybe
<PersistenceType
> aPersistenceType
,
550 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
);
552 RefPtr
<BoolPromise
> ShutdownStorage(
553 Maybe
<OriginOperationCallbackOptions
> aCallbackOptions
= Nothing(),
554 Maybe
<OriginOperationCallbacks
&> aCallbacks
= Nothing());
556 void ShutdownStorageInternal();
558 // Returns a bool indicating whether the directory was newly created.
559 Result
<bool, nsresult
> EnsureOriginDirectory(nsIFile
& aDirectory
);
561 nsresult
AboutToClearOrigins(const PersistenceScope
& aPersistenceScope
,
562 const OriginScope
& aOriginScope
,
563 const Nullable
<Client::Type
>& aClientType
);
565 void OriginClearCompleted(const OriginMetadata
& aOriginMetadata
,
566 const Nullable
<Client::Type
>& aClientType
);
568 void RepositoryClearCompleted(PersistenceType aPersistenceType
);
570 void StartIdleMaintenance() {
571 AssertIsOnOwningThread();
573 for (const auto& client
: *mClients
) {
574 client
->StartIdleMaintenance();
577 NotifyMaintenanceStarted(*this);
580 void StopIdleMaintenance() {
581 AssertIsOnOwningThread();
583 for (const auto& client
: *mClients
) {
584 client
->StopIdleMaintenance();
588 void AssertCurrentThreadOwnsQuotaMutex() {
589 mQuotaMutex
.AssertCurrentThreadOwns();
592 void AssertNotCurrentThreadOwnsQuotaMutex() {
593 mQuotaMutex
.AssertNotCurrentThreadOwns();
596 nsIThread
* IOThread() { return mIOThread
->get(); }
598 Client
* GetClient(Client::Type aClientType
);
600 const AutoTArray
<Client::Type
, Client::TYPE_MAX
>& AllClientTypes();
602 const nsString
& GetBasePath() const { return mBasePath
; }
604 const nsString
& GetStorageName() const { return mStorageName
; }
606 const nsString
& GetStoragePath() const { return *mStoragePath
; }
608 const nsString
& GetStoragePath(PersistenceType aPersistenceType
) const {
609 if (aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
) {
610 return *mPermanentStoragePath
;
613 if (aPersistenceType
== PERSISTENCE_TYPE_TEMPORARY
) {
614 return *mTemporaryStoragePath
;
617 if (aPersistenceType
== PERSISTENCE_TYPE_DEFAULT
) {
618 return *mDefaultStoragePath
;
621 MOZ_ASSERT(aPersistenceType
== PERSISTENCE_TYPE_PRIVATE
);
623 return *mPrivateStoragePath
;
626 bool IsThumbnailPrivateIdentityIdKnown() const;
628 uint32_t GetThumbnailPrivateIdentityId() const;
630 void SetThumbnailPrivateIdentityId(uint32_t aThumbnailPrivateIdentityId
);
632 uint64_t GetGroupLimit() const;
634 std::pair
<uint64_t, uint64_t> GetUsageAndLimitForEstimate(
635 const OriginMetadata
& aOriginMetadata
);
637 uint64_t GetOriginUsage(const PrincipalMetadata
& aPrincipalMetadata
);
639 Maybe
<FullOriginMetadata
> GetFullOriginMetadata(
640 const OriginMetadata
& aOriginMetadata
);
643 * Retrieves the total number of directory iterations performed.
645 * @return The total count of directory iterations, which is currently
646 * incremented only during clearing operations.
648 uint64_t TotalDirectoryIterations() const;
650 // Record a quota client shutdown step, if shutting down.
651 // Assumes that the QuotaManager singleton is alive.
652 static void MaybeRecordQuotaClientShutdownStep(
653 const Client::Type aClientType
, const nsACString
& aStepDescription
);
655 // Record a quota client shutdown step, if shutting down.
656 // Checks if the QuotaManager singleton is alive.
657 static void SafeMaybeRecordQuotaClientShutdownStep(
658 Client::Type aClientType
, const nsACString
& aStepDescription
);
660 // Record a quota manager shutdown step, use only if shutdown is active.
661 void RecordQuotaManagerShutdownStep(const nsACString
& aStepDescription
);
663 // Record a quota manager shutdown step, if shutting down.
664 void MaybeRecordQuotaManagerShutdownStep(const nsACString
& aStepDescription
);
666 template <typename F
>
667 void MaybeRecordQuotaManagerShutdownStepWith(F
&& aFunc
);
669 static void GetStorageId(PersistenceType aPersistenceType
,
670 const nsACString
& aOrigin
, Client::Type aClientType
,
671 nsACString
& aDatabaseId
);
673 static bool IsOriginInternal(const nsACString
& aOrigin
);
675 static bool AreOriginsEqualOnDisk(const nsACString
& aOrigin1
,
676 const nsACString
& aOrigin2
);
678 // XXX This method currently expects the original origin string (not yet
680 static Result
<PrincipalInfo
, nsresult
> ParseOrigin(const nsACString
& aOrigin
);
682 static void InvalidateQuotaCache();
685 virtual ~QuotaManager();
691 void RegisterDirectoryLock(DirectoryLockImpl
& aLock
);
693 void UnregisterDirectoryLock(DirectoryLockImpl
& aLock
);
695 void AddPendingDirectoryLock(DirectoryLockImpl
& aLock
);
697 void RemovePendingDirectoryLock(DirectoryLockImpl
& aLock
);
699 uint64_t LockedCollectOriginsForEviction(
700 uint64_t aMinSizeToBeFreed
,
701 nsTArray
<RefPtr
<OriginDirectoryLock
>>& aLocks
);
703 void LockedRemoveQuotaForRepository(PersistenceType aPersistenceType
);
705 void LockedRemoveQuotaForOrigin(const OriginMetadata
& aOriginMetadata
);
707 bool LockedHasGroupInfoPair(const nsACString
& aGroup
) const;
709 already_AddRefed
<GroupInfo
> LockedGetOrCreateGroupInfo(
710 PersistenceType aPersistenceType
, const nsACString
& aSuffix
,
711 const nsACString
& aGroup
);
713 already_AddRefed
<OriginInfo
> LockedGetOriginInfo(
714 PersistenceType aPersistenceType
,
715 const OriginMetadata
& aOriginMetadata
) const;
717 nsresult
UpgradeFromIndexedDBDirectoryToPersistentStorageDirectory(
718 nsIFile
* aIndexedDBDir
);
720 nsresult
UpgradeFromPersistentStorageDirectoryToDefaultStorageDirectory(
721 nsIFile
* aPersistentStorageDir
);
723 nsresult
MaybeUpgradeToDefaultStorageDirectory(nsIFile
& aStorageFile
);
725 template <typename Helper
>
726 nsresult
UpgradeStorage(const int32_t aOldVersion
, const int32_t aNewVersion
,
727 mozIStorageConnection
* aConnection
);
729 nsresult
UpgradeStorageFrom0_0To1_0(mozIStorageConnection
* aConnection
);
731 nsresult
UpgradeStorageFrom1_0To2_0(mozIStorageConnection
* aConnection
);
733 nsresult
UpgradeStorageFrom2_0To2_1(mozIStorageConnection
* aConnection
);
735 nsresult
UpgradeStorageFrom2_1To2_2(mozIStorageConnection
* aConnection
);
737 nsresult
UpgradeStorageFrom2_2To2_3(mozIStorageConnection
* aConnection
);
739 nsresult
MaybeCreateOrUpgradeStorage(mozIStorageConnection
& aConnection
);
741 OkOrErr
MaybeRemoveLocalStorageArchiveTmpFile();
743 nsresult
MaybeRemoveLocalStorageDataAndArchive(nsIFile
& aLsArchiveFile
);
745 nsresult
MaybeRemoveLocalStorageDirectories();
747 Result
<Ok
, nsresult
> CopyLocalStorageArchiveFromWebAppsStore(
748 nsIFile
& aLsArchiveFile
) const;
750 Result
<nsCOMPtr
<mozIStorageConnection
>, nsresult
>
751 CreateLocalStorageArchiveConnection(nsIFile
& aLsArchiveFile
) const;
753 Result
<nsCOMPtr
<mozIStorageConnection
>, nsresult
>
754 RecopyLocalStorageArchiveFromWebAppsStore(nsIFile
& aLsArchiveFile
);
756 Result
<nsCOMPtr
<mozIStorageConnection
>, nsresult
>
757 DowngradeLocalStorageArchive(nsIFile
& aLsArchiveFile
);
759 Result
<nsCOMPtr
<mozIStorageConnection
>, nsresult
>
760 UpgradeLocalStorageArchiveFromLessThan4To4(nsIFile
& aLsArchiveFile
);
763 nsresult UpgradeLocalStorageArchiveFrom4To5();
766 Result
<Ok
, nsresult
> MaybeCreateOrUpgradeLocalStorageArchive(
767 nsIFile
& aLsArchiveFile
);
769 Result
<Ok
, nsresult
> CreateEmptyLocalStorageArchive(
770 nsIFile
& aLsArchiveFile
) const;
772 template <typename OriginFunc
>
773 nsresult
InitializeRepository(PersistenceType aPersistenceType
,
774 OriginFunc
&& aOriginFunc
);
776 nsresult
InitializeOrigin(PersistenceType aPersistenceType
,
777 const OriginMetadata
& aOriginMetadata
,
778 int64_t aAccessTime
, bool aPersisted
,
779 nsIFile
* aDirectory
, bool aForGroup
= false);
781 using OriginInfosFlatTraversable
=
782 nsTArray
<NotNull
<RefPtr
<const OriginInfo
>>>;
784 using OriginInfosNestedTraversable
=
785 nsTArray
<nsTArray
<NotNull
<RefPtr
<const OriginInfo
>>>>;
787 OriginInfosNestedTraversable
GetOriginInfosExceedingGroupLimit() const;
789 OriginInfosNestedTraversable
GetOriginInfosExceedingGlobalLimit() const;
791 void ClearOrigins(const OriginInfosNestedTraversable
& aDoomedOriginInfos
);
793 void CleanupTemporaryStorage();
795 void DeleteOriginDirectory(const OriginMetadata
& aOriginMetadata
);
797 void FinalizeOriginEviction(nsTArray
<RefPtr
<OriginDirectoryLock
>>&& aLocks
);
799 Result
<Ok
, nsresult
> ArchiveOrigins(
800 const nsTArray
<FullOriginMetadata
>& aFullOriginMetadatas
);
802 void ReleaseIOThreadObjects() {
803 AssertIsOnIOThread();
805 for (Client::Type type
: AllClientTypes()) {
806 (*mClients
)[type
]->ReleaseIOThreadObjects();
810 DirectoryLockTable
& GetDirectoryLockTable(PersistenceType aPersistenceType
);
812 void ClearDirectoryLockTables();
814 void AddTemporaryOrigin(const FullOriginMetadata
& aFullOriginMetadata
);
816 void RemoveTemporaryOrigin(const OriginMetadata
& aOriginMetadata
);
818 void RemoveTemporaryOrigins(PersistenceType aPersistenceType
);
820 void RemoveTemporaryOrigins();
823 * Retrieves the count of thumbnail private identity temporary origins.
825 * This method returns the current count of temporary origins associated with
826 * thumbnail private identity contexts. It requires that the thumbnail
827 * private identity id is known.
829 * @return The count of thumbnail private identity temporary origins.
831 * @note The thumbnail private identity id must be known before calling this
832 * method. If the id is not known, it will cause a debug assertion failure
833 * due to the `MOZ_ASSERT`.
835 uint32_t ThumbnailPrivateIdentityTemporaryOriginCount() const;
837 PrincipalMetadataArray
GetAllTemporaryGroups() const;
839 OriginMetadataArray
GetAllTemporaryOrigins() const;
841 void NoteInitializedOrigin(PersistenceType aPersistenceType
,
842 const nsACString
& aOrigin
);
844 void NoteUninitializedOrigins(
845 const OriginMetadataArray
& aOriginMetadataArray
);
847 void NoteUninitializedRepository(PersistenceType aPersistenceType
);
849 bool IsOriginInitialized(PersistenceType aPersistenceType
,
850 const nsACString
& aOrigin
) const;
852 bool IsSanitizedOriginValid(const nsACString
& aSanitizedOrigin
);
854 Result
<nsCString
, nsresult
> EnsureStorageOriginFromOrigin(
855 const nsACString
& aOrigin
);
857 Result
<nsCString
, nsresult
> GetOriginFromStorageOrigin(
858 const nsACString
& aStorageOrigin
);
860 int64_t GenerateDirectoryLockId();
862 bool ShutdownStarted() const;
864 void RecordShutdownStep(Maybe
<Client::Type
> aClientType
,
865 const nsACString
& aStepDescription
);
867 template <typename Func
>
868 auto ExecuteInitialization(Initialization aInitialization
, Func
&& aFunc
)
869 -> std::invoke_result_t
<Func
, const FirstInitializationAttempt
<
870 Initialization
, StringGenerator
>&>;
872 template <typename Func
>
873 auto ExecuteInitialization(Initialization aInitialization
,
874 const nsACString
& aContext
, Func
&& aFunc
)
875 -> std::invoke_result_t
<Func
, const FirstInitializationAttempt
<
876 Initialization
, StringGenerator
>&>;
878 template <typename Func
>
879 auto ExecuteGroupInitialization(const nsACString
& aGroup
,
880 const GroupInitialization aInitialization
,
881 const nsACString
& aContext
, Func
&& aFunc
)
882 -> std::invoke_result_t
<Func
, const FirstInitializationAttempt
<
883 Initialization
, StringGenerator
>&>;
885 template <typename Func
>
886 auto ExecuteOriginInitialization(const nsACString
& aOrigin
,
887 const OriginInitialization aInitialization
,
888 const nsACString
& aContext
, Func
&& aFunc
)
889 -> std::invoke_result_t
<Func
, const FirstInitializationAttempt
<
890 Initialization
, StringGenerator
>&>;
893 * Increments the counter tracking the total number of directory iterations.
895 * @note This is currently called only during clearing operations to update
896 * the mTotalDirectoryIterations member.
898 void IncreaseTotalDirectoryIterations();
900 template <typename Iterator
>
901 static void MaybeInsertNonPersistedOriginInfos(
902 Iterator aDest
, const RefPtr
<GroupInfo
>& aTemporaryGroupInfo
,
903 const RefPtr
<GroupInfo
>& aDefaultGroupInfo
,
904 const RefPtr
<GroupInfo
>& aPrivateGroupInfo
);
906 template <typename Collect
, typename Pred
>
907 static OriginInfosFlatTraversable
CollectLRUOriginInfosUntil(
908 Collect
&& aCollect
, Pred
&& aPred
);
910 // Thread on which IO is performed.
911 LazyInitializedOnceNotNull
<const nsCOMPtr
<nsIThread
>> mIOThread
;
913 nsCOMPtr
<mozIStorageConnection
> mStorageConnection
;
915 EnumeratedArray
<Client::Type
, nsCString
, size_t(Client::TYPE_MAX
)>
917 LazyInitializedOnce
<const TimeStamp
> mShutdownStartedAt
;
919 // Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex.
920 nsCString mQuotaManagerShutdownSteps
;
922 mutable mozilla::Mutex mQuotaMutex MOZ_UNANNOTATED
;
924 nsClassHashtable
<nsCStringHashKey
, GroupInfoPair
> mGroupInfoPairs
;
926 // Maintains a list of directory locks that are queued.
927 nsTArray
<RefPtr
<DirectoryLockImpl
>> mPendingDirectoryLocks
;
929 // Maintains a list of directory locks that are acquired or queued. It can be
930 // accessed on the owning (PBackground) thread only.
931 nsTArray
<NotNull
<DirectoryLockImpl
*>> mDirectoryLocks
;
933 // Only modifed on the owning thread, but read on multiple threads. Therefore
934 // all modifications (including those on the owning thread) and all reads off
935 // the owning thread must be protected by mQuotaMutex. In other words, only
936 // reads on the owning thread don't have to be protected by mQuotaMutex.
937 nsTHashMap
<nsUint64HashKey
, NotNull
<DirectoryLockImpl
*>>
938 mDirectoryLockIdTable
;
940 // Directory lock tables that are used to update origin access time.
941 DirectoryLockTable mTemporaryDirectoryLockTable
;
942 DirectoryLockTable mDefaultDirectoryLockTable
;
943 DirectoryLockTable mPrivateDirectoryLockTable
;
945 // Things touched on the owning (PBackground) thread only.
946 struct BackgroundThreadAccessible
{
947 PrincipalMetadataArray mUninitializedGroups
;
948 nsTHashSet
<nsCString
> mInitializedGroups
;
950 ThreadBound
<BackgroundThreadAccessible
> mBackgroundThreadAccessible
;
952 using BoolArray
= AutoTArray
<bool, PERSISTENCE_TYPE_INVALID
>;
953 nsTHashMap
<nsCStringHashKeyWithDisabledMemmove
, BoolArray
>
956 // Things touched on the IO thread only.
957 struct IOThreadAccessible
{
958 nsTHashMap
<nsCStringHashKey
, nsTArray
<FullOriginMetadata
>>
959 mAllTemporaryOrigins
;
960 Maybe
<uint32_t> mThumbnailPrivateIdentityId
;
961 // Tracks the total number of directory iterations.
962 // Note: This is currently incremented only during clearing operations.
963 uint64_t mTotalDirectoryIterations
= 0;
964 // Tracks the count of thumbnail private identity temporary origins.
965 uint32_t mThumbnailPrivateIdentityTemporaryOriginCount
= 0;
967 ThreadBound
<IOThreadAccessible
> mIOThreadAccessible
;
969 // A list of all successfully initialized persistent origins. This list isn't
970 // protected by any mutex but it is only ever touched on the IO thread.
971 nsTArray
<nsCString
> mInitializedOriginsInternal
;
973 // A hash table that is used to cache origin parser results for given
974 // sanitized origin strings. This hash table isn't protected by any mutex but
975 // it is only ever touched on the IO thread.
976 nsTHashMap
<nsCStringHashKey
, bool> mValidOrigins
;
978 // These maps are protected by mQuotaMutex.
979 nsTHashMap
<nsCStringHashKey
, nsCString
> mOriginToStorageOriginMap
;
980 nsTHashMap
<nsCStringHashKey
, nsCString
> mStorageOriginToOriginMap
;
982 // This array is populated at initialization time and then never modified, so
983 // it can be iterated on any thread.
984 LazyInitializedOnce
<const AutoTArray
<RefPtr
<Client
>, Client::TYPE_MAX
>>
987 using ClientTypesArray
= AutoTArray
<Client::Type
, Client::TYPE_MAX
>;
988 LazyInitializedOnce
<const ClientTypesArray
> mAllClientTypes
;
989 LazyInitializedOnce
<const ClientTypesArray
> mAllClientTypesExceptLS
;
991 // This object isn't protected by any mutex but it is only ever touched on
993 InitializationInfo mInitializationInfo
;
995 const nsString mBasePath
;
996 const nsString mStorageName
;
997 LazyInitializedOnce
<const nsString
> mIndexedDBPath
;
998 LazyInitializedOnce
<const nsString
> mStoragePath
;
999 LazyInitializedOnce
<const nsString
> mStorageArchivesPath
;
1000 LazyInitializedOnce
<const nsString
> mPermanentStoragePath
;
1001 LazyInitializedOnce
<const nsString
> mTemporaryStoragePath
;
1002 LazyInitializedOnce
<const nsString
> mDefaultStoragePath
;
1003 LazyInitializedOnce
<const nsString
> mPrivateStoragePath
;
1004 LazyInitializedOnce
<const nsString
> mToBeRemovedStoragePath
;
1006 MozPromiseHolder
<BoolPromise
> mInitializeAllTemporaryOriginsPromiseHolder
;
1008 uint64_t mTemporaryStorageLimit
;
1009 uint64_t mTemporaryStorageUsage
;
1010 int64_t mNextDirectoryLockId
;
1011 bool mStorageInitialized
;
1012 bool mPersistentStorageInitialized
;
1013 bool mPersistentStorageInitializedInternal
;
1014 bool mTemporaryStorageInitialized
;
1015 bool mTemporaryStorageInitializedInternal
;
1016 bool mInitializingAllTemporaryOrigins
;
1017 bool mAllTemporaryOriginsInitialized
;
1021 } // namespace mozilla::dom::quota
1023 #endif /* mozilla_dom_quota_quotamanager_h__ */