QuotaManager.h (44784B)
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 #ifndef mozilla_dom_quota_quotamanager_h__ 8 #define mozilla_dom_quota_quotamanager_h__ 9 10 #include <cstdint> 11 #include <utility> 12 13 #include "Client.h" 14 #include "ErrorList.h" 15 #include "mozilla/AlreadyAddRefed.h" 16 #include "mozilla/Assertions.h" 17 #include "mozilla/InitializedOnce.h" 18 #include "mozilla/MozPromise.h" 19 #include "mozilla/Mutex.h" 20 #include "mozilla/RefPtr.h" 21 #include "mozilla/Result.h" 22 #include "mozilla/ThreadBound.h" 23 #include "mozilla/dom/Nullable.h" 24 #include "mozilla/dom/ipc/IdType.h" 25 #include "mozilla/dom/quota/Assertions.h" 26 #include "mozilla/dom/quota/BackgroundThreadObject.h" 27 #include "mozilla/dom/quota/CommonMetadata.h" 28 #include "mozilla/dom/quota/DirectoryLockCategory.h" 29 #include "mozilla/dom/quota/ForwardDecls.h" 30 #include "mozilla/dom/quota/HashKeys.h" 31 #include "mozilla/dom/quota/InitializationTypes.h" 32 #include "mozilla/dom/quota/NotifyUtils.h" 33 #include "mozilla/dom/quota/OpenClientDirectoryInfo.h" 34 #include "mozilla/dom/quota/OriginOperationCallbacks.h" 35 #include "mozilla/dom/quota/PersistenceType.h" 36 #include "nsCOMPtr.h" 37 #include "nsClassHashtable.h" 38 #include "nsDebug.h" 39 #include "nsHashKeys.h" 40 #include "nsISupports.h" 41 #include "nsStringFwd.h" 42 #include "nsTArray.h" 43 #include "nsTHashMap.h" 44 #include "nsTStringRepr.h" 45 #include "nscore.h" 46 #include "prenv.h" 47 48 #define GTEST_CLASS(testFixture, testName) testFixture##_##testName##_Test 49 50 class mozIStorageConnection; 51 class nsIEventTarget; 52 class nsIFile; 53 class nsIRunnable; 54 class nsIThread; 55 class nsITimer; 56 57 namespace mozilla { 58 59 class OriginAttributes; 60 class OriginAttributesPattern; 61 62 namespace ipc { 63 64 class PrincipalInfo; 65 66 } // namespace ipc 67 68 } // namespace mozilla 69 70 namespace mozilla::dom::quota { 71 72 class CanonicalQuotaObject; 73 class ClearDataOp; 74 class ClearRequestBase; 75 class ClientStorageScope; 76 class ClientUsageArray; 77 class ClientDirectoryLock; 78 class ClientDirectoryLockHandle; 79 class DirectoryLockImpl; 80 class GroupInfo; 81 class GroupInfoPair; 82 class NormalOriginOperationBase; 83 class OriginDirectoryLock; 84 class OriginInfo; 85 class OriginScope; 86 class QuotaObject; 87 class SaveOriginAccessTimeOp; 88 class UniversalDirectoryLock; 89 90 namespace test { 91 class GTEST_CLASS(TestQuotaManagerAndShutdownFixture, 92 ThumbnailPrivateIdentityTemporaryOriginCount); 93 } 94 95 class QuotaManager final : public BackgroundThreadObject { 96 friend class CanonicalQuotaObject; 97 friend class ClearDataOp; 98 friend class ClearRequestBase; 99 friend class ClearStorageOp; 100 friend class ClientDirectoryLockHandle; 101 friend class DirectoryLockImpl; 102 friend class FinalizeOriginEvictionOp; 103 friend class GroupInfo; 104 friend class InitOp; 105 friend class InitializePersistentOriginOp; 106 friend class InitializePersistentStorageOp; 107 friend class InitializeTemporaryGroupOp; 108 friend class InitializeTemporaryOriginOp; 109 friend class InitTemporaryStorageOp; 110 friend class ListCachedOriginsOp; 111 friend class OriginInfo; 112 friend class PersistOp; 113 friend class SaveOriginAccessTimeOp; 114 friend class ShutdownStorageOp; 115 friend class test::GTEST_CLASS(TestQuotaManagerAndShutdownFixture, 116 ThumbnailPrivateIdentityTemporaryOriginCount); 117 friend class UniversalDirectoryLock; 118 119 friend Result<PrincipalMetadata, nsresult> GetInfoFromValidatedPrincipalInfo( 120 QuotaManager& aQuotaManager, 121 const mozilla::ipc::PrincipalInfo& aPrincipalInfo); 122 123 using PrincipalInfo = mozilla::ipc::PrincipalInfo; 124 125 class Observer; 126 127 public: 128 using ClientDirectoryLockHandlePromise = 129 MozPromise<ClientDirectoryLockHandle, nsresult, true>; 130 131 QuotaManager(const nsAString& aBasePath, const nsAString& aStorageName); 132 133 NS_INLINE_DECL_REFCOUNTING(QuotaManager) 134 135 static nsresult Initialize(); 136 137 static bool IsRunningXPCShellTests() { 138 static bool kRunningXPCShellTests = 139 !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR"); 140 return kRunningXPCShellTests; 141 } 142 143 static bool IsRunningGTests() { 144 static bool kRunningGTests = !!PR_GetEnv("MOZ_RUN_GTEST"); 145 return kRunningGTests; 146 } 147 148 static const char kReplaceChars[]; 149 static const char16_t kReplaceChars16[]; 150 151 static Result<MovingNotNull<RefPtr<QuotaManager>>, nsresult> GetOrCreate(); 152 153 static Result<Ok, nsresult> EnsureCreated(); 154 155 // Returns a non-owning reference. 156 static QuotaManager* Get(); 157 158 // Use only in gtests! 159 static nsIObserver* GetObserver(); 160 161 /** 162 * Ensures that all pending normal origin operations and their follow-up 163 * events are processed and completed. 164 * 165 * This is useful in cases where operations are scheduled asynchronously 166 * without a way to explicitly await their completion, and must be finalized 167 * before continuing with further checks or logic. 168 * 169 * This method asserts that gtests are currently running and must not be used 170 * outside of gtest code. 171 */ 172 static void ProcessPendingNormalOriginOperations(); 173 174 // Returns true if we've begun the shutdown process. 175 static bool IsShuttingDown(); 176 177 static void ShutdownInstance(); 178 179 // Use only in gtests! 180 static void Reset(); 181 182 static bool IsOSMetadata(const nsAString& aFileName); 183 184 static bool IsDotFile(const nsAString& aFileName); 185 186 void RegisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp); 187 188 void UnregisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp); 189 190 bool IsPersistentOriginInitializedInternal(const nsACString& aOrigin) const { 191 AssertIsOnIOThread(); 192 193 return mInitializedOriginsInternal.Contains(aOrigin); 194 } 195 196 bool IsTemporaryStorageInitializedInternal() const { 197 AssertIsOnIOThread(); 198 199 return mTemporaryStorageInitializedInternal; 200 } 201 202 /** 203 * For initialization of an origin where the directory either exists or it 204 * does not. The directory exists case is used by InitializeOrigin once it 205 * has tallied origin usage by calling each of the QuotaClient InitOrigin 206 * methods. It's also used by LoadQuota when quota information is available 207 * from the cache. EnsureTemporaryStorageIsInitializedInternal calls this 208 * either if the directory exists or it does not depending on requirements 209 * of a particular quota client. The special case when origin directory is 210 * not created during origin initialization is currently utilized only by 211 * LSNG. 212 */ 213 void InitQuotaForOrigin(const FullOriginMetadata& aFullOriginMetadata, 214 bool aDirectoryExists = true); 215 216 // XXX clients can use QuotaObject instead of calling this method directly. 217 void DecreaseUsageForClient(const ClientMetadata& aClientMetadata, 218 int64_t aSize); 219 220 void ResetUsageForClient(const ClientMetadata& aClientMetadata); 221 222 UsageInfo GetUsageForClient(PersistenceType aPersistenceType, 223 const OriginMetadata& aOriginMetadata, 224 Client::Type aClientType); 225 226 void UpdateOriginAccessTime(const OriginMetadata& aOriginMetadata, 227 int64_t aTimestamp); 228 229 void UpdateOriginMaintenanceDate(const OriginMetadata& aOriginMetadata, 230 int32_t aMaintenanceDate); 231 232 void UpdateOriginAccessed(const OriginMetadata& aOriginMetadata); 233 234 void RemoveQuota(); 235 236 void RemoveQuotaForRepository(PersistenceType aPersistenceType) { 237 MutexAutoLock lock(mQuotaMutex); 238 LockedRemoveQuotaForRepository(aPersistenceType); 239 } 240 241 void RemoveQuotaForOrigin(PersistenceType aPersistenceType, 242 const OriginMetadata& aOriginMetadata) { 243 MutexAutoLock lock(mQuotaMutex); 244 LockedRemoveQuotaForOrigin(aOriginMetadata); 245 } 246 247 nsresult LoadQuota(); 248 249 void UnloadQuota(); 250 251 void RemoveOriginFromCache(const OriginMetadata& aOriginMetadata); 252 253 already_AddRefed<QuotaObject> GetQuotaObject( 254 PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata, 255 Client::Type aClientType, nsIFile* aFile, int64_t aFileSize = -1, 256 int64_t* aFileSizeOut = nullptr); 257 258 already_AddRefed<QuotaObject> GetQuotaObject( 259 PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata, 260 Client::Type aClientType, const nsAString& aPath, int64_t aFileSize = -1, 261 int64_t* aFileSizeOut = nullptr); 262 263 already_AddRefed<QuotaObject> GetQuotaObject(const int64_t aDirectoryLockId, 264 const nsAString& aPath); 265 266 Nullable<bool> OriginPersisted(const OriginMetadata& aOriginMetadata); 267 268 void PersistOrigin(const OriginMetadata& aOriginMetadata); 269 270 template <typename F> 271 auto WithOriginInfo(const OriginMetadata& aOriginMetadata, F aFunction) 272 -> std::invoke_result_t<F, const RefPtr<OriginInfo>&>; 273 274 using DirectoryLockIdTableArray = 275 AutoTArray<Client::DirectoryLockIdTable, Client::TYPE_MAX>; 276 void AbortOperationsForLocks(const DirectoryLockIdTableArray& aLockIds); 277 278 // Called when a process is being shot down. Aborts any running operations 279 // for the given process. 280 void AbortOperationsForProcess(ContentParentId aContentParentId); 281 282 Result<nsCOMPtr<nsIFile>, nsresult> GetOriginDirectory( 283 const OriginMetadata& aOriginMetadata) const; 284 285 Result<bool, nsresult> DoesOriginDirectoryExist( 286 const OriginMetadata& aOriginMetadata) const; 287 288 Result<nsCOMPtr<nsIFile>, nsresult> GetOrCreateTemporaryOriginDirectory( 289 const OriginMetadata& aOriginMetadata); 290 291 Result<Ok, nsresult> EnsureTemporaryOriginDirectoryCreated( 292 const OriginMetadata& aOriginMetadata); 293 294 static nsresult CreateDirectoryMetadata2( 295 nsIFile& aDirectory, const FullOriginMetadata& aFullOriginMetadata); 296 297 nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory); 298 299 // XXX Remove aPersistenceType argument once the persistence type is stored 300 // in the metadata file. 301 Result<FullOriginMetadata, nsresult> LoadFullOriginMetadata( 302 nsIFile* aDirectory, PersistenceType aPersistenceType); 303 304 Result<FullOriginMetadata, nsresult> LoadFullOriginMetadataWithRestore( 305 nsIFile* aDirectory); 306 307 Result<std::pair<FullOriginMetadata, bool /* restore status */>, nsresult> 308 LoadFullOriginMetadataWithRestoreAndStatus(nsIFile* aDirectory); 309 310 Result<OriginMetadata, nsresult> GetOriginMetadata(nsIFile* aDirectory); 311 312 Result<Ok, nsresult> RemoveOriginDirectory(nsIFile& aDirectory); 313 314 Result<bool, nsresult> DoesClientDirectoryExist( 315 const ClientMetadata& aClientMetadata) const; 316 317 RefPtr<UniversalDirectoryLockPromise> OpenStorageDirectory( 318 const PersistenceScope& aPersistenceScope, 319 const OriginScope& aOriginScope, 320 const ClientStorageScope& aClientStorageScope, bool aExclusive, 321 bool aInitializeOrigins = false, 322 DirectoryLockCategory aCategory = DirectoryLockCategory::None, 323 Maybe<RefPtr<UniversalDirectoryLock>&> aPendingDirectoryLockOut = 324 Nothing()); 325 326 // This is the main entry point into the QuotaManager API. 327 // Any storage API implementation (quota client) that participates in 328 // centralized quota and storage handling should call this method to obtain 329 // a directory lock, ensuring the client’s files are protected from deletion 330 // while in use. 331 // 332 // After a lock is acquired, the client is notified by resolving the returned 333 // promise. If the lock couldn't be acquired, the promise is rejected. 334 // 335 // The returned lock is encapsulated in ClientDirectoryLockHandle, which 336 // manages ownership and automatically drops the lock when destroyed. Clients 337 // should retain ownership of the handle for as long as the lock is needed. 338 // 339 // The lock may still be invalidated by a clear operation, so consumers 340 // should check its validity and release it as soon as it is no longer 341 // required. 342 // 343 // Internally, QuotaManager may perform various initialization steps before 344 // resolving the promise. This can include storage, temporary storage, group 345 // and origin initialization. 346 // 347 // Optionally, an output parameter (aPendingDirectoryLockOut) can be provided 348 // to receive a reference to the ClientDirectoryLock before wrapping it in 349 // ClientDirectoryLockHandle. This allows tracking pending locks separately. 350 RefPtr<ClientDirectoryLockHandlePromise> OpenClientDirectory( 351 const ClientMetadata& aClientMetadata, bool aInitializeOrigins = true, 352 bool aCreateIfNonExistent = true, 353 Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut = Nothing()); 354 355 RefPtr<ClientDirectoryLockHandlePromise> OpenClientDirectoryImpl( 356 const ClientMetadata& aClientMetadata, bool aInitializeOrigins, 357 bool aCreateIfNonExistent, 358 Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut); 359 360 RefPtr<ClientDirectoryLock> CreateDirectoryLock( 361 const ClientMetadata& aClientMetadata, bool aExclusive); 362 363 // XXX RemoveMe once bug 1170279 gets fixed. 364 RefPtr<UniversalDirectoryLock> CreateDirectoryLockInternal( 365 const PersistenceScope& aPersistenceScope, 366 const OriginScope& aOriginScope, 367 const ClientStorageScope& aClientStorageScope, bool aExclusive, 368 DirectoryLockCategory aCategory = DirectoryLockCategory::None); 369 370 // Collect inactive and the least recently used origins. 371 uint64_t CollectOriginsForEviction( 372 uint64_t aMinSizeToBeFreed, 373 nsTArray<RefPtr<OriginDirectoryLock>>& aLocks); 374 375 /** 376 * Helper method to invoke the provided predicate on all "pending" OriginInfo 377 * instances. These are origins for which the origin directory has not yet 378 * been created but for which quota is already being tracked. This happens, 379 * for example, for the LocalStorage client where an origin that previously 380 * was not using LocalStorage can start issuing writes which it buffers until 381 * eventually flushing them. We defer creating the origin directory for as 382 * long as possible in that case, so the directory won't exist. Logic that 383 * would otherwise only consult the filesystem also needs to use this method. 384 */ 385 template <typename P> 386 void CollectPendingOriginsForListing(P aPredicate); 387 388 bool IsPendingOrigin(const OriginMetadata& aOriginMetadata) const; 389 390 RefPtr<BoolPromise> InitializeStorage(); 391 392 RefPtr<BoolPromise> InitializeStorage( 393 RefPtr<UniversalDirectoryLock> aDirectoryLock); 394 395 RefPtr<BoolPromise> StorageInitialized(); 396 397 bool IsStorageInitialized() const { 398 AssertIsOnOwningThread(); 399 400 return mStorageInitialized; 401 } 402 403 bool IsStorageInitializedInternal() const { 404 AssertIsOnIOThread(); 405 return static_cast<bool>(mStorageConnection); 406 } 407 408 void AssertStorageIsInitializedInternal() const 409 #ifdef DEBUG 410 ; 411 #else 412 { 413 } 414 #endif 415 416 RefPtr<BoolPromise> TemporaryStorageInitialized(); 417 418 private: 419 nsresult EnsureStorageIsInitializedInternal(); 420 421 public: 422 RefPtr<BoolPromise> InitializePersistentStorage(); 423 424 RefPtr<BoolPromise> InitializePersistentStorage( 425 RefPtr<UniversalDirectoryLock> aDirectoryLock); 426 427 RefPtr<BoolPromise> PersistentStorageInitialized(); 428 429 bool IsPersistentStorageInitialized() const { 430 AssertIsOnOwningThread(); 431 432 return mPersistentStorageInitialized; 433 } 434 435 bool IsPersistentStorageInitializedInternal() const { 436 AssertIsOnIOThread(); 437 438 return mPersistentStorageInitializedInternal; 439 } 440 441 private: 442 nsresult EnsurePersistentStorageIsInitializedInternal(); 443 444 public: 445 RefPtr<BoolPromise> InitializeTemporaryGroup( 446 const PrincipalMetadata& aPrincipalMetadata); 447 448 RefPtr<BoolPromise> InitializeTemporaryGroup( 449 const PrincipalMetadata& aPrincipalMetadata, 450 RefPtr<UniversalDirectoryLock> aDirectoryLock); 451 452 RefPtr<BoolPromise> TemporaryGroupInitialized( 453 const PrincipalMetadata& aPrincipalMetadata); 454 455 bool IsTemporaryGroupInitialized(const PrincipalMetadata& aPrincipalMetadata); 456 457 bool IsTemporaryGroupInitializedInternal( 458 const PrincipalMetadata& aPrincipalMetadata) const; 459 460 private: 461 Result<Ok, nsresult> EnsureTemporaryGroupIsInitializedInternal( 462 const PrincipalMetadata& aPrincipalMetadata); 463 464 public: 465 RefPtr<BoolPromise> InitializePersistentOrigin( 466 const OriginMetadata& aOriginMetadata); 467 468 RefPtr<BoolPromise> InitializePersistentOrigin( 469 const OriginMetadata& aOriginMetadata, 470 RefPtr<UniversalDirectoryLock> aDirectoryLock); 471 472 RefPtr<BoolPromise> PersistentOriginInitialized( 473 const OriginMetadata& aOriginMetadata); 474 475 bool IsPersistentOriginInitialized(const OriginMetadata& aOriginMetadata); 476 477 bool IsPersistentOriginInitializedInternal( 478 const OriginMetadata& aOriginMetadata) const; 479 480 private: 481 // Returns a pair of an nsIFile object referring to the directory, and a bool 482 // indicating whether the directory was newly created. 483 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult> 484 EnsurePersistentOriginIsInitializedInternal( 485 const OriginMetadata& aOriginMetadata); 486 487 public: 488 RefPtr<BoolPromise> InitializeTemporaryOrigin( 489 const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent); 490 491 RefPtr<BoolPromise> InitializeTemporaryOrigin( 492 const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent, 493 RefPtr<UniversalDirectoryLock> aDirectoryLock); 494 495 RefPtr<BoolPromise> TemporaryOriginInitialized( 496 const OriginMetadata& aOriginMetadata); 497 498 bool IsTemporaryOriginInitialized(const OriginMetadata& aOriginMetadata); 499 500 bool IsTemporaryOriginInitializedInternal( 501 const OriginMetadata& aOriginMetadata) const; 502 503 private: 504 // Returns a pair of an nsIFile object referring to the directory, and a bool 505 // indicating whether the directory was newly created. 506 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult> 507 EnsureTemporaryOriginIsInitializedInternal( 508 const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent); 509 510 public: 511 RefPtr<BoolPromise> InitializePersistentClient( 512 const ClientMetadata& aClientMetadata); 513 514 RefPtr<BoolPromise> InitializePersistentClient( 515 const ClientMetadata& aClientMetadata, 516 RefPtr<UniversalDirectoryLock> aDirectoryLock); 517 518 bool IsPersistentClientInitialized(const ClientMetadata& aClientMetadata); 519 520 // Returns a pair of an nsIFile object referring to the directory, and a bool 521 // indicating whether the directory was newly created. 522 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult> 523 EnsurePersistentClientIsInitialized(const ClientMetadata& aClientMetadata); 524 525 RefPtr<BoolPromise> InitializeTemporaryClient( 526 const ClientMetadata& aClientMetadata, bool aCreateIfNonExistent); 527 528 RefPtr<BoolPromise> InitializeTemporaryClient( 529 const ClientMetadata& aClientMetadata, bool aCreateIfNonExistent, 530 RefPtr<UniversalDirectoryLock> aDirectoryLock); 531 532 bool IsTemporaryClientInitialized(const ClientMetadata& aClientMetadata); 533 534 // Returns a pair of an nsIFile object referring to the directory, and a bool 535 // indicating whether the directory was newly created. 536 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult> 537 EnsureTemporaryClientIsInitialized(const ClientMetadata& aClientMetadata, 538 bool aCreateIfNonExistent); 539 540 RefPtr<BoolPromise> InitializeTemporaryStorage(); 541 542 RefPtr<BoolPromise> InitializeTemporaryStorage( 543 RefPtr<UniversalDirectoryLock> aDirectoryLock); 544 545 bool IsTemporaryStorageInitialized() const { 546 AssertIsOnOwningThread(); 547 548 return mTemporaryStorageInitialized; 549 } 550 551 private: 552 nsresult InitializeTemporaryStorageInternal(); 553 554 nsresult EnsureTemporaryStorageIsInitializedInternal(); 555 556 public: 557 RefPtr<BoolPromise> InitializeAllTemporaryOrigins(); 558 559 RefPtr<BoolPromise> SaveOriginAccessTime( 560 const OriginMetadata& aOriginMetadata); 561 562 RefPtr<BoolPromise> SaveOriginAccessTime( 563 const OriginMetadata& aOriginMetadata, 564 RefPtr<UniversalDirectoryLock> aDirectoryLock); 565 566 RefPtr<OriginUsageMetadataArrayPromise> GetUsage( 567 bool aGetAll, RefPtr<BoolPromise> aOnCancelPromise = nullptr); 568 569 RefPtr<UsageInfoPromise> GetOriginUsage( 570 const PrincipalInfo& aPrincipalInfo, 571 RefPtr<BoolPromise> aOnCancelPromise = nullptr); 572 573 RefPtr<UInt64Promise> GetCachedOriginUsage( 574 const PrincipalInfo& aPrincipalInfo); 575 576 RefPtr<CStringArrayPromise> ListOrigins(); 577 578 RefPtr<CStringArrayPromise> ListCachedOrigins(); 579 580 RefPtr<BoolPromise> ClearStoragesForOrigin( 581 const Maybe<PersistenceType>& aPersistenceType, 582 const PrincipalInfo& aPrincipalInfo); 583 584 RefPtr<BoolPromise> ClearStoragesForClient( 585 Maybe<PersistenceType> aPersistenceType, 586 const PrincipalInfo& aPrincipalInfo, Client::Type aClientType); 587 588 RefPtr<BoolPromise> ClearStoragesForOriginPrefix( 589 const Maybe<PersistenceType>& aPersistenceType, 590 const PrincipalInfo& aPrincipalInfo); 591 592 RefPtr<BoolPromise> ClearStoragesForOriginAttributesPattern( 593 const OriginAttributesPattern& aPattern); 594 595 RefPtr<BoolPromise> ClearPrivateRepository(); 596 597 RefPtr<BoolPromise> ClearStorage(); 598 599 RefPtr<BoolPromise> ShutdownStoragesForOrigin( 600 Maybe<PersistenceType> aPersistenceType, 601 const PrincipalInfo& aPrincipalInfo); 602 603 RefPtr<BoolPromise> ShutdownStoragesForClient( 604 Maybe<PersistenceType> aPersistenceType, 605 const PrincipalInfo& aPrincipalInfo, Client::Type aClientType); 606 607 RefPtr<BoolPromise> ShutdownStorage( 608 Maybe<OriginOperationCallbackOptions> aCallbackOptions = Nothing(), 609 Maybe<OriginOperationCallbacks&> aCallbacks = Nothing()); 610 611 void ShutdownStorageInternal(); 612 613 // Returns a bool indicating whether the directory was newly created. 614 Result<bool, nsresult> EnsureOriginDirectory(nsIFile& aDirectory); 615 616 nsresult AboutToClearOrigins(const PersistenceScope& aPersistenceScope, 617 const OriginScope& aOriginScope, 618 const ClientStorageScope& aClientStorageScope); 619 620 void OriginClearCompleted(const OriginMetadata& aOriginMetadata, 621 const ClientStorageScope& aClientStorageScope); 622 623 void RepositoryClearCompleted(PersistenceType aPersistenceType); 624 625 void StartIdleMaintenance() { 626 AssertIsOnOwningThread(); 627 628 for (const auto& client : *mClients) { 629 client->StartIdleMaintenance(); 630 } 631 632 NotifyMaintenanceStarted(*this); 633 } 634 635 void StopIdleMaintenance() { 636 AssertIsOnOwningThread(); 637 638 for (const auto& client : *mClients) { 639 client->StopIdleMaintenance(); 640 } 641 } 642 643 void AssertCurrentThreadOwnsQuotaMutex() { 644 mQuotaMutex.AssertCurrentThreadOwns(); 645 } 646 647 void AssertNotCurrentThreadOwnsQuotaMutex() { 648 mQuotaMutex.AssertNotCurrentThreadOwns(); 649 } 650 651 nsIThread* IOThread() { return mIOThread->get(); } 652 653 Client* GetClient(Client::Type aClientType); 654 655 const AutoTArray<Client::Type, Client::TYPE_MAX>& AllClientTypes(); 656 657 const nsString& GetBasePath() const { return mBasePath; } 658 659 const nsString& GetStorageName() const { return mStorageName; } 660 661 const nsString& GetStoragePath() const { return *mStoragePath; } 662 663 const nsString& GetStoragePath(PersistenceType aPersistenceType) const { 664 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) { 665 return *mPermanentStoragePath; 666 } 667 668 if (aPersistenceType == PERSISTENCE_TYPE_TEMPORARY) { 669 return *mTemporaryStoragePath; 670 } 671 672 if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) { 673 return *mDefaultStoragePath; 674 } 675 676 MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_PRIVATE); 677 678 return *mPrivateStoragePath; 679 } 680 681 bool IsThumbnailPrivateIdentityIdKnown() const; 682 683 uint32_t GetThumbnailPrivateIdentityId() const; 684 685 void SetThumbnailPrivateIdentityId(uint32_t aThumbnailPrivateIdentityId); 686 687 uint64_t GetGroupLimit() const; 688 static uint64_t GetGroupLimitForLimit(uint64_t aLimit); 689 690 Maybe<OriginStateMetadata> GetOriginStateMetadata( 691 const OriginMetadata& aOriginMetadata); 692 693 std::pair<uint64_t, uint64_t> GetUsageAndLimitForEstimate( 694 const OriginMetadata& aOriginMetadata); 695 696 uint64_t GetOriginUsage(const PrincipalMetadata& aPrincipalMetadata); 697 698 Maybe<FullOriginMetadata> GetFullOriginMetadata( 699 const OriginMetadata& aOriginMetadata); 700 701 /** 702 * Retrieves the total number of directory iterations performed. 703 * 704 * @return The total count of directory iterations, which is currently 705 * incremented only during clearing operations. 706 */ 707 uint64_t TotalDirectoryIterations() const; 708 709 /** 710 * Retrieves the number of metadata updates performed by SaveOriginAccessTime 711 * operation, as tracked on the background thread. This count is incremented 712 * after the operation has fully completed. 713 */ 714 uint64_t SaveOriginAccessTimeCount() const; 715 716 /** 717 * Retrieves the number of metadata updates performed by SaveOriginAccessTime 718 * operation, as tracked internally on the I/O thread. This count is 719 * incremented when the actual metadata file update occurs. 720 */ 721 uint64_t SaveOriginAccessTimeCountInternal() const; 722 723 // Record a quota client shutdown step, if shutting down. 724 // Assumes that the QuotaManager singleton is alive. 725 static void MaybeRecordQuotaClientShutdownStep( 726 const Client::Type aClientType, const nsACString& aStepDescription); 727 728 // Record a quota client shutdown step, if shutting down. 729 // Checks if the QuotaManager singleton is alive. 730 static void SafeMaybeRecordQuotaClientShutdownStep( 731 Client::Type aClientType, const nsACString& aStepDescription); 732 733 // Record a quota manager shutdown step, use only if shutdown is active. 734 void RecordQuotaManagerShutdownStep(const nsACString& aStepDescription); 735 736 // Record a quota manager shutdown step, if shutting down. 737 void MaybeRecordQuotaManagerShutdownStep(const nsACString& aStepDescription); 738 739 template <typename F> 740 void MaybeRecordQuotaManagerShutdownStepWith(F&& aFunc); 741 742 static void GetStorageId(PersistenceType aPersistenceType, 743 const nsACString& aOrigin, Client::Type aClientType, 744 nsACString& aDatabaseId); 745 746 static bool IsOriginInternal(const nsACString& aOrigin); 747 748 static bool AreOriginsEqualOnDisk(const nsACString& aOrigin1, 749 const nsACString& aOrigin2); 750 751 // XXX This method currently expects the original origin string (not yet 752 // sanitized). 753 static Result<PrincipalInfo, nsresult> ParseOrigin(const nsACString& aOrigin); 754 755 static void InvalidateQuotaCache(); 756 757 private: 758 virtual ~QuotaManager(); 759 760 nsresult Init(); 761 762 void Shutdown(); 763 764 void RegisterDirectoryLock(DirectoryLockImpl& aLock); 765 766 void UnregisterDirectoryLock(DirectoryLockImpl& aLock); 767 768 void AddPendingDirectoryLock(DirectoryLockImpl& aLock); 769 770 void RemovePendingDirectoryLock(DirectoryLockImpl& aLock); 771 772 uint64_t LockedCollectOriginsForEviction( 773 uint64_t aMinSizeToBeFreed, 774 nsTArray<RefPtr<OriginDirectoryLock>>& aLocks); 775 776 void LockedRemoveQuotaForRepository(PersistenceType aPersistenceType); 777 778 void LockedRemoveQuotaForOrigin(const OriginMetadata& aOriginMetadata); 779 780 bool LockedHasGroupInfoPair(const nsACString& aGroup) const; 781 782 already_AddRefed<GroupInfo> LockedGetOrCreateGroupInfo( 783 PersistenceType aPersistenceType, const nsACString& aSuffix, 784 const nsACString& aGroup); 785 786 already_AddRefed<OriginInfo> LockedGetOriginInfo( 787 PersistenceType aPersistenceType, 788 const OriginMetadata& aOriginMetadata) const; 789 790 nsresult UpgradeFromIndexedDBDirectoryToPersistentStorageDirectory( 791 nsIFile* aIndexedDBDir); 792 793 nsresult UpgradeFromPersistentStorageDirectoryToDefaultStorageDirectory( 794 nsIFile* aPersistentStorageDir); 795 796 nsresult MaybeUpgradeToDefaultStorageDirectory(nsIFile& aStorageFile); 797 798 template <typename Helper> 799 nsresult UpgradeStorage(const int32_t aOldVersion, const int32_t aNewVersion, 800 mozIStorageConnection* aConnection); 801 802 nsresult UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection); 803 804 nsresult UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection); 805 806 nsresult UpgradeStorageFrom2_0To2_1(mozIStorageConnection* aConnection); 807 808 nsresult UpgradeStorageFrom2_1To2_2(mozIStorageConnection* aConnection); 809 810 nsresult UpgradeStorageFrom2_2To2_3(mozIStorageConnection* aConnection); 811 812 nsresult MaybeCreateOrUpgradeStorage(mozIStorageConnection& aConnection); 813 814 OkOrErr MaybeRemoveLocalStorageArchiveTmpFile(); 815 816 nsresult MaybeRemoveLocalStorageDataAndArchive(nsIFile& aLsArchiveFile); 817 818 nsresult MaybeRemoveLocalStorageDirectories(); 819 820 Result<Ok, nsresult> CopyLocalStorageArchiveFromWebAppsStore( 821 nsIFile& aLsArchiveFile) const; 822 823 Result<nsCOMPtr<mozIStorageConnection>, nsresult> 824 CreateLocalStorageArchiveConnection(nsIFile& aLsArchiveFile) const; 825 826 Result<nsCOMPtr<mozIStorageConnection>, nsresult> 827 RecopyLocalStorageArchiveFromWebAppsStore(nsIFile& aLsArchiveFile); 828 829 Result<nsCOMPtr<mozIStorageConnection>, nsresult> 830 DowngradeLocalStorageArchive(nsIFile& aLsArchiveFile); 831 832 Result<nsCOMPtr<mozIStorageConnection>, nsresult> 833 UpgradeLocalStorageArchiveFromLessThan4To4(nsIFile& aLsArchiveFile); 834 835 /* 836 nsresult UpgradeLocalStorageArchiveFrom4To5(); 837 */ 838 839 Result<Ok, nsresult> MaybeCreateOrUpgradeLocalStorageArchive( 840 nsIFile& aLsArchiveFile); 841 842 Result<Ok, nsresult> CreateEmptyLocalStorageArchive( 843 nsIFile& aLsArchiveFile) const; 844 845 template <typename OriginFunc> 846 nsresult InitializeRepository(PersistenceType aPersistenceType, 847 OriginFunc&& aOriginFunc); 848 849 nsresult InitializeOrigin(nsIFile* aDirectory, 850 const FullOriginMetadata& aFullOriginMetadata, 851 bool aForGroup = false); 852 853 using OriginInfosFlatTraversable = 854 nsTArray<NotNull<RefPtr<const OriginInfo>>>; 855 856 using OriginInfosNestedTraversable = 857 nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>; 858 859 OriginInfosNestedTraversable GetOriginInfosExceedingGroupLimit() const; 860 861 OriginInfosNestedTraversable GetOriginInfosExceedingGlobalLimit() const; 862 863 // Returns origins with zero usage. If aCutoffAccessTime is provided, origins 864 // whose last access time is newer than the cutoff are excluded. 865 // 866 // The cutoff time is expressed as an int64_t value in microseconds since the 867 // Unix epoch (1970-01-01 00:00:00 UTC), matching the format returned by 868 // PR_Now(). This is the same time unit used throughout Quota Manager for 869 // access and modification timestamps. 870 // 871 // Typically callers compute it as: 872 // const int64_t cutoff = PR_Now() - (N * PR_USEC_PER_SEC); 873 // where N is the desired age threshold in seconds (for example, one week). 874 OriginInfosNestedTraversable GetOriginInfosWithZeroUsage( 875 const Maybe<int64_t>& aCutoffAccessTime = Nothing()) const; 876 877 /** 878 * Clears the given set of origins. 879 * 880 * @param aDoomedOriginInfos 881 * Origins to be cleared. 882 * @param aChecker 883 * A callable invoked for each origin before clearing. Typically used to 884 * enforce or assert invariants at the call site. 885 * @param aMaxOriginsToClear 886 * Optional cap on the number of origins cleared in a single run. If 887 * Nothing(), all doomed origins are cleared. 888 */ 889 template <typename Checker> 890 void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos, 891 Checker&& aChecker, 892 const Maybe<size_t>& aMaxOriginsToClear = Nothing()); 893 894 void CleanupTemporaryStorage(); 895 896 void RecordTemporaryStorageMetrics(); 897 898 void DeleteOriginDirectory(const OriginMetadata& aOriginMetadata); 899 900 void FinalizeOriginEviction(nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks); 901 902 Result<Ok, nsresult> ArchiveOrigins( 903 const nsTArray<FullOriginMetadata>& aFullOriginMetadatas); 904 905 void ReleaseIOThreadObjects() { 906 AssertIsOnIOThread(); 907 908 for (Client::Type type : AllClientTypes()) { 909 (*mClients)[type]->ReleaseIOThreadObjects(); 910 } 911 } 912 913 void AddTemporaryOrigin(const FullOriginMetadata& aFullOriginMetadata); 914 915 void RemoveTemporaryOrigin(const OriginMetadata& aOriginMetadata); 916 917 void RemoveTemporaryOrigins(PersistenceType aPersistenceType); 918 919 void RemoveTemporaryOrigins(); 920 921 /** 922 * Retrieves the count of thumbnail private identity temporary origins. 923 * 924 * This method returns the current count of temporary origins associated with 925 * thumbnail private identity contexts. It requires that the thumbnail 926 * private identity id is known. 927 * 928 * @return The count of thumbnail private identity temporary origins. 929 * 930 * @note The thumbnail private identity id must be known before calling this 931 * method. If the id is not known, it will cause a debug assertion failure 932 * due to the `MOZ_ASSERT`. 933 */ 934 uint32_t ThumbnailPrivateIdentityTemporaryOriginCount() const; 935 936 PrincipalMetadataArray GetAllTemporaryGroups() const; 937 938 OriginMetadataArray GetAllTemporaryOrigins() const; 939 940 void NoteInitializedOrigin(PersistenceType aPersistenceType, 941 const nsACString& aOrigin); 942 943 void NoteUninitializedOrigins( 944 const OriginMetadataArray& aOriginMetadataArray); 945 946 void NoteUninitializedRepository(PersistenceType aPersistenceType); 947 948 bool IsOriginInitialized(PersistenceType aPersistenceType, 949 const nsACString& aOrigin) const; 950 951 void NoteInitializedClient(PersistenceType aPersistenceType, 952 const nsACString& aOrigin, 953 Client::Type aClientType); 954 955 void NoteUninitializedClients( 956 const ClientMetadataArray& aClientMetadataArray); 957 958 void NoteUninitializedClients( 959 const OriginMetadataArray& aOriginMetadataArray); 960 961 void NoteUninitializedClients(PersistenceType aPersistenceType); 962 963 bool IsClientInitialized(PersistenceType aPersistenceType, 964 const nsACString& aOrigin, 965 Client::Type aClientType) const; 966 967 bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin); 968 969 Result<nsCString, nsresult> EnsureStorageOriginFromOrigin( 970 const nsACString& aOrigin); 971 972 Result<nsCString, nsresult> GetOriginFromStorageOrigin( 973 const nsACString& aStorageOrigin); 974 975 int64_t GenerateDirectoryLockId(); 976 977 /** 978 * Registers a ClientDirectoryLockHandle for the given origin. 979 * 980 * Tracks the handle in internal bookkeeping. If this is the first handle 981 * registered for the origin, the caller-provided update callback is invoked. 982 * 983 * The update callback can be used to perform first-time setup, such as 984 * updating the origin’s access time. 985 */ 986 template <typename UpdateCallback> 987 void RegisterClientDirectoryLockHandle(const OriginMetadata& aOriginMetadata, 988 UpdateCallback&& aUpdateCallback); 989 990 /** 991 * Invokes the given callback with the active OpenClientDirectoryInfo entry 992 * for the specified origin. 993 * 994 * This method is typically used after the first handle has been registered 995 * via RegisterClientDirectoryLockHandle. It provides easy access to the 996 * associated OpenClientDirectoryInfo for reading and/or updating its data. 997 * 998 * Currently, it is primarily used in the final step of OpenClientDirectory 999 * to retrieve the first-access promise returned by SaveOriginAccessTime, 1000 * which is stored during the first handle registration. The returned promise 1001 * is then used to ensure that client access is blocked until the origin 1002 * access time update is complete. 1003 */ 1004 template <typename Callback> 1005 auto WithOpenClientDirectoryInfo(const OriginMetadata& aOriginMetadata, 1006 Callback&& aCallback) 1007 -> std::invoke_result_t<Callback, OpenClientDirectoryInfo&>; 1008 1009 /** 1010 * Unregisters a ClientDirectoryLockHandle for the given origin. 1011 * 1012 * Decreases the active handle count and removes the internal tracking entry 1013 * if this was the last handle (in some shutdown cases, the entry may no 1014 * longer exist; this is currently tolerated, see comment in implementation). 1015 * If the handle being unregistered was the last one for the origin, the 1016 * caller-provided update callback is invoked. 1017 * 1018 * The update callback can be used to perform final cleanup, such as updating 1019 * the origin’s access time. 1020 */ 1021 template <typename UpdateCallback> 1022 void UnregisterClientDirectoryLockHandle( 1023 const OriginMetadata& aOriginMetadata, UpdateCallback&& aUpdateCallback); 1024 1025 /** 1026 * This wrapper is used by ClientDirectoryLockHandle to notify the 1027 * QuotaManager when a non-inert (i.e., owning) handle is being destroyed. 1028 * 1029 * This extra abstraction (ClientDirectoryLockHandle could call 1030 * UnregisterClientDirectoryLockHandle directly) enables future changes to 1031 * the registration methods, such as templating them. Without this wrapper, 1032 * such changes would require exposing their implementation in 1033 * QuotaManagerImpl.h, which would allow access from another translation unit. 1034 */ 1035 void ClientDirectoryLockHandleDestroy(ClientDirectoryLockHandle& aHandle); 1036 1037 bool ShutdownStarted() const; 1038 1039 void RecordShutdownStep(Maybe<Client::Type> aClientType, 1040 const nsACString& aStepDescription); 1041 1042 template <typename Func> 1043 auto ExecuteInitialization(Initialization aInitialization, Func&& aFunc) 1044 -> std::invoke_result_t<Func, const FirstInitializationAttempt< 1045 Initialization, StringGenerator>&>; 1046 1047 template <typename Func> 1048 auto ExecuteInitialization(Initialization aInitialization, 1049 const nsACString& aContext, Func&& aFunc) 1050 -> std::invoke_result_t<Func, const FirstInitializationAttempt< 1051 Initialization, StringGenerator>&>; 1052 1053 template <typename Func> 1054 auto ExecuteGroupInitialization(const nsACString& aGroup, 1055 const GroupInitialization aInitialization, 1056 const nsACString& aContext, Func&& aFunc) 1057 -> std::invoke_result_t<Func, const FirstInitializationAttempt< 1058 Initialization, StringGenerator>&>; 1059 1060 template <typename Func> 1061 auto ExecuteOriginInitialization(const nsACString& aOrigin, 1062 const OriginInitialization aInitialization, 1063 const nsACString& aContext, Func&& aFunc) 1064 -> std::invoke_result_t<Func, const FirstInitializationAttempt< 1065 Initialization, StringGenerator>&>; 1066 1067 /** 1068 * Increments the counter tracking the total number of directory iterations. 1069 * 1070 * @note This is currently called only during clearing operations to update 1071 * the mTotalDirectoryIterations member. 1072 */ 1073 void IncreaseTotalDirectoryIterations(); 1074 1075 /** 1076 * Increments the counter tracking SaveOriginAccessTime metadata updates, 1077 * recorded on the background thread after the operation has completed. 1078 */ 1079 void IncreaseSaveOriginAccessTimeCount(); 1080 1081 /** 1082 * Increments the counter tracking SaveOriginAccessTime metadata updates, 1083 * recorded internally on the I/O thread when the metadata file is updated. 1084 */ 1085 void IncreaseSaveOriginAccessTimeCountInternal(); 1086 1087 template <typename Collect, typename Pred> 1088 static OriginInfosFlatTraversable CollectLRUOriginInfosUntil( 1089 Collect&& aCollect, Pred&& aPred); 1090 1091 // Thread on which IO is performed. 1092 LazyInitializedOnceNotNull<const nsCOMPtr<nsIThread>> mIOThread; 1093 1094 nsCOMPtr<mozIStorageConnection> mStorageConnection; 1095 1096 EnumeratedArray<Client::Type, nsCString, size_t(Client::TYPE_MAX)> 1097 mShutdownSteps; 1098 LazyInitializedOnce<const TimeStamp> mShutdownStartedAt; 1099 1100 // Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex. 1101 nsCString mQuotaManagerShutdownSteps; 1102 1103 mutable mozilla::Mutex mQuotaMutex MOZ_UNANNOTATED; 1104 1105 nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs; 1106 1107 // Maintains a list of directory locks that are queued. 1108 nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks; 1109 1110 // Maintains a list of directory locks that are acquired or queued. It can be 1111 // accessed on the owning (PBackground) thread only. 1112 nsTArray<NotNull<DirectoryLockImpl*>> mDirectoryLocks; 1113 1114 // Maintains a list of directory locks that are exclusive. This is a subset 1115 // of mDirectoryLocks and is used to optimize lock acquisition by allowing 1116 // shared locks to skip unnecessary comparisons. It is accessed only on the 1117 // owning (PBackground) thread. 1118 nsTArray<NotNull<DirectoryLockImpl*>> mExclusiveDirectoryLocks; 1119 1120 // Only modifed on the owning thread, but read on multiple threads. Therefore 1121 // all modifications (including those on the owning thread) and all reads off 1122 // the owning thread must be protected by mQuotaMutex. In other words, only 1123 // reads on the owning thread don't have to be protected by mQuotaMutex. 1124 nsTHashMap<nsUint64HashKey, NotNull<DirectoryLockImpl*>> 1125 mDirectoryLockIdTable; 1126 1127 // Things touched on the owning (PBackground) thread only. 1128 struct BackgroundThreadAccessible { 1129 PrincipalMetadataArray mUninitializedGroups; 1130 nsTHashSet<nsCString> mInitializedGroups; 1131 1132 // Tracks active origin directories for updating origin access time. 1133 nsTHashMap<nsCStringHashKey, OpenClientDirectoryInfo> 1134 mOpenClientDirectoryInfos; 1135 1136 // Tracks how many times SaveOriginAccessTime resulted in updating metadata. 1137 uint64_t mSaveOriginAccessTimeCount = 0; 1138 }; 1139 ThreadBound<BackgroundThreadAccessible> mBackgroundThreadAccessible; 1140 1141 using BoolArray = AutoTArray<bool, PERSISTENCE_TYPE_INVALID>; 1142 nsTHashMap<nsCStringHashKeyWithDisabledMemmove, BoolArray> 1143 mInitializedOrigins; 1144 1145 using BitSetArray = 1146 AutoTArray<BitSet<Client::TYPE_MAX>, PERSISTENCE_TYPE_INVALID>; 1147 nsTHashMap<nsCStringHashKeyWithDisabledMemmove, BitSetArray> 1148 mInitializedClients; 1149 1150 // Things touched on the IO thread only. 1151 struct IOThreadAccessible { 1152 nsTHashMap<nsCStringHashKey, nsTArray<FullOriginMetadata>> 1153 mAllTemporaryOrigins; 1154 Maybe<uint32_t> mThumbnailPrivateIdentityId; 1155 // Tracks the total number of directory iterations. 1156 // Note: This is currently incremented only during clearing operations. 1157 uint64_t mTotalDirectoryIterations = 0; 1158 // Tracks how many times SaveOriginAccessTime resulted in updating metadata. 1159 uint64_t mSaveOriginAccessTimeCount = 0; 1160 // Tracks the count of thumbnail private identity temporary origins. 1161 uint32_t mThumbnailPrivateIdentityTemporaryOriginCount = 0; 1162 }; 1163 ThreadBound<IOThreadAccessible> mIOThreadAccessible; 1164 1165 // A list of all successfully initialized persistent origins. This list isn't 1166 // protected by any mutex but it is only ever touched on the IO thread. 1167 nsTArray<nsCString> mInitializedOriginsInternal; 1168 1169 // A hash table that is used to cache origin parser results for given 1170 // sanitized origin strings. This hash table isn't protected by any mutex but 1171 // it is only ever touched on the IO thread. 1172 nsTHashMap<nsCStringHashKey, bool> mValidOrigins; 1173 1174 // These maps are protected by mQuotaMutex. 1175 nsTHashMap<nsCStringHashKey, nsCString> mOriginToStorageOriginMap; 1176 nsTHashMap<nsCStringHashKey, nsCString> mStorageOriginToOriginMap; 1177 1178 // This array is populated at initialization time and then never modified, so 1179 // it can be iterated on any thread. 1180 LazyInitializedOnce<const AutoTArray<RefPtr<Client>, Client::TYPE_MAX>> 1181 mClients; 1182 1183 using ClientTypesArray = AutoTArray<Client::Type, Client::TYPE_MAX>; 1184 LazyInitializedOnce<const ClientTypesArray> mAllClientTypes; 1185 LazyInitializedOnce<const ClientTypesArray> mAllClientTypesExceptLS; 1186 1187 // This object isn't protected by any mutex but it is only ever touched on 1188 // the IO thread. 1189 InitializationInfo mInitializationInfo; 1190 1191 const nsString mBasePath; 1192 const nsString mStorageName; 1193 LazyInitializedOnce<const nsString> mIndexedDBPath; 1194 LazyInitializedOnce<const nsString> mStoragePath; 1195 LazyInitializedOnce<const nsString> mStorageArchivesPath; 1196 LazyInitializedOnce<const nsString> mPermanentStoragePath; 1197 LazyInitializedOnce<const nsString> mTemporaryStoragePath; 1198 LazyInitializedOnce<const nsString> mDefaultStoragePath; 1199 LazyInitializedOnce<const nsString> mPrivateStoragePath; 1200 LazyInitializedOnce<const nsString> mToBeRemovedStoragePath; 1201 1202 MozPromiseHolder<BoolPromise> mInitializeAllTemporaryOriginsPromiseHolder; 1203 1204 uint64_t mTemporaryStorageLimit; 1205 uint64_t mTemporaryStorageUsage; 1206 int64_t mNextDirectoryLockId; 1207 bool mStorageInitialized; 1208 bool mPersistentStorageInitialized; 1209 bool mPersistentStorageInitializedInternal; 1210 bool mTemporaryStorageInitialized; 1211 bool mTemporaryStorageInitializedInternal; 1212 bool mInitializingAllTemporaryOrigins; 1213 bool mAllTemporaryOriginsInitialized; 1214 bool mCacheUsable; 1215 }; 1216 1217 } // namespace mozilla::dom::quota 1218 1219 #endif /* mozilla_dom_quota_quotamanager_h__ */