1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "OriginOperations.h"
13 #include "ErrorList.h"
14 #include "FileUtils.h"
15 #include "GroupInfo.h"
16 #include "MainThreadUtils.h"
17 #include "mozilla/Assertions.h"
18 #include "mozilla/Atomics.h"
19 #include "mozilla/Maybe.h"
20 #include "mozilla/NotNull.h"
21 #include "mozilla/ProfilerLabels.h"
22 #include "mozilla/RefPtr.h"
23 #include "mozilla/Result.h"
24 #include "mozilla/ResultExtensions.h"
25 #include "mozilla/dom/Nullable.h"
26 #include "mozilla/dom/quota/CommonMetadata.h"
27 #include "mozilla/dom/quota/Client.h"
28 #include "mozilla/dom/quota/Constants.h"
29 #include "mozilla/dom/quota/DirectoryLock.h"
30 #include "mozilla/dom/quota/DirectoryLockInlines.h"
31 #include "mozilla/dom/quota/OriginDirectoryLock.h"
32 #include "mozilla/dom/quota/PersistenceType.h"
33 #include "mozilla/dom/quota/PrincipalUtils.h"
34 #include "mozilla/dom/quota/PQuota.h"
35 #include "mozilla/dom/quota/PQuotaRequest.h"
36 #include "mozilla/dom/quota/PQuotaUsageRequest.h"
37 #include "mozilla/dom/quota/OriginScope.h"
38 #include "mozilla/dom/quota/PersistenceScope.h"
39 #include "mozilla/dom/quota/QuotaCommon.h"
40 #include "mozilla/dom/quota/QuotaManager.h"
41 #include "mozilla/dom/quota/QuotaManagerImpl.h"
42 #include "mozilla/dom/quota/ResultExtensions.h"
43 #include "mozilla/dom/quota/StreamUtils.h"
44 #include "mozilla/dom/quota/UniversalDirectoryLock.h"
45 #include "mozilla/dom/quota/UsageInfo.h"
46 #include "mozilla/fallible.h"
47 #include "mozilla/ipc/BackgroundParent.h"
48 #include "mozilla/ipc/PBackgroundSharedTypes.h"
49 #include "NormalOriginOperationBase.h"
51 #include "nsTHashMap.h"
54 #include "nsHashKeys.h"
55 #include "nsIBinaryOutputStream.h"
57 #include "nsIObjectOutputStream.h"
58 #include "nsIOutputStream.h"
59 #include "nsLiteralString.h"
60 #include "nsPrintfCString.h"
63 #include "OriginInfo.h"
64 #include "OriginOperationBase.h"
65 #include "OriginParser.h"
66 #include "QuotaRequestBase.h"
67 #include "ResolvableNormalOriginOp.h"
71 namespace mozilla::dom::quota
{
73 using namespace mozilla::ipc
;
76 class OpenStorageDirectoryHelper
: public Base
{
78 OpenStorageDirectoryHelper(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
80 : Base(std::move(aQuotaManager
), aName
) {}
82 RefPtr
<BoolPromise
> OpenStorageDirectory(
83 const PersistenceScope
& aPersistenceScope
,
84 const OriginScope
& aOriginScope
,
85 const Nullable
<Client::Type
>& aClientType
, bool aExclusive
,
86 bool aInitializeOrigins
= false,
87 DirectoryLockCategory aCategory
= DirectoryLockCategory::None
);
89 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
92 class FinalizeOriginEvictionOp
: public OriginOperationBase
{
93 nsTArray
<RefPtr
<OriginDirectoryLock
>> mLocks
;
96 FinalizeOriginEvictionOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
97 nsTArray
<RefPtr
<OriginDirectoryLock
>>&& aLocks
)
98 : OriginOperationBase(std::move(aQuotaManager
),
99 "dom::quota::FinalizeOriginEvictionOp"),
100 mLocks(std::move(aLocks
)) {
101 AssertIsOnOwningThread();
104 NS_INLINE_DECL_REFCOUNTING(FinalizeOriginEvictionOp
, override
)
107 ~FinalizeOriginEvictionOp() = default;
109 virtual RefPtr
<BoolPromise
> Open() override
;
111 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
113 virtual void UnblockOpen() override
;
116 class SaveOriginAccessTimeOp
117 : public OpenStorageDirectoryHelper
<NormalOriginOperationBase
> {
118 const OriginMetadata mOriginMetadata
;
122 SaveOriginAccessTimeOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
123 const OriginMetadata
& aOriginMetadata
,
125 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
126 "dom::quota::SaveOriginAccessTimeOp"),
127 mOriginMetadata(aOriginMetadata
),
128 mTimestamp(aTimestamp
) {
129 AssertIsOnOwningThread();
132 NS_INLINE_DECL_REFCOUNTING(SaveOriginAccessTimeOp
, override
)
135 ~SaveOriginAccessTimeOp() = default;
137 RefPtr
<BoolPromise
> OpenDirectory() override
;
139 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
141 virtual void SendResults() override
;
143 void CloseDirectory() override
;
146 class ClearPrivateRepositoryOp
147 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
149 explicit ClearPrivateRepositoryOp(
150 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
151 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
152 "dom::quota::ClearPrivateRepositoryOp") {
153 AssertIsOnOwningThread();
157 ~ClearPrivateRepositoryOp() = default;
159 RefPtr
<BoolPromise
> OpenDirectory() override
;
161 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
163 bool UnwrapResolveValue() override
{ return true; }
165 void CloseDirectory() override
;
168 class ShutdownStorageOp
: public ResolvableNormalOriginOp
<bool> {
169 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
172 explicit ShutdownStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
173 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
174 "dom::quota::ShutdownStorageOp") {
175 AssertIsOnOwningThread();
179 ~ShutdownStorageOp() = default;
182 nsresult
DirectoryOpen() override
;
185 RefPtr
<BoolPromise
> OpenDirectory() override
;
187 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
189 bool UnwrapResolveValue() override
{ return true; }
191 void CloseDirectory() override
;
194 class CancelableHelper
{
196 virtual const Atomic
<bool>& GetIsCanceledFlag() = 0;
199 // A mix-in class to simplify operations that need to process every origin in
200 // one or more repositories. Sub-classes should call TraverseRepository in their
201 // DoDirectoryWork and implement a ProcessOrigin method for their per-origin
203 class TraverseRepositoryHelper
: public CancelableHelper
{
205 TraverseRepositoryHelper() = default;
208 virtual ~TraverseRepositoryHelper() = default;
210 // If ProcessOrigin returns an error, TraverseRepository will immediately
211 // terminate and return the received error code to its caller.
212 nsresult
TraverseRepository(QuotaManager
& aQuotaManager
,
213 PersistenceType aPersistenceType
);
216 virtual nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
,
217 nsIFile
& aOriginDir
, const bool aPersistent
,
218 const PersistenceType aPersistenceType
) = 0;
221 class OriginUsageHelper
: public CancelableHelper
{
223 mozilla::Result
<UsageInfo
, nsresult
> GetUsageForOrigin(
224 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
225 const OriginMetadata
& aOriginMetadata
);
228 mozilla::Result
<UsageInfo
, nsresult
> GetUsageForOriginEntries(
229 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
230 const OriginMetadata
& aOriginMetadata
, nsIFile
& aDirectory
,
234 class GetUsageOp final
235 : public OpenStorageDirectoryHelper
<
236 ResolvableNormalOriginOp
<OriginUsageMetadataArray
, true>>,
237 public TraverseRepositoryHelper
,
238 public OriginUsageHelper
{
239 OriginUsageMetadataArray mOriginUsages
;
240 nsTHashMap
<nsCStringHashKey
, uint32_t> mOriginUsagesIndex
;
245 GetUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, bool aGetAll
);
248 ~GetUsageOp() = default;
250 void ProcessOriginInternal(QuotaManager
* aQuotaManager
,
251 const PersistenceType aPersistenceType
,
252 const nsACString
& aOrigin
,
253 const int64_t aTimestamp
, const bool aPersisted
,
254 const uint64_t aUsage
);
256 RefPtr
<BoolPromise
> OpenDirectory() override
;
258 const Atomic
<bool>& GetIsCanceledFlag() override
;
260 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
262 nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
, nsIFile
& aOriginDir
,
263 const bool aPersistent
,
264 const PersistenceType aPersistenceType
) override
;
266 OriginUsageMetadataArray
UnwrapResolveValue() override
;
268 void CloseDirectory() override
;
271 class GetOriginUsageOp final
272 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<UsageInfo
>>,
273 public OriginUsageHelper
{
274 const PrincipalInfo mPrincipalInfo
;
275 PrincipalMetadata mPrincipalMetadata
;
276 UsageInfo mUsageInfo
;
279 GetOriginUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
280 const PrincipalInfo
& aPrincipalInfo
);
283 ~GetOriginUsageOp() = default;
285 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
287 RefPtr
<BoolPromise
> OpenDirectory() override
;
289 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
291 const Atomic
<bool>& GetIsCanceledFlag() override
;
293 UsageInfo
UnwrapResolveValue() override
;
295 void CloseDirectory() override
;
298 class StorageNameOp final
: public QuotaRequestBase
{
302 explicit StorageNameOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
305 ~StorageNameOp() = default;
307 RefPtr
<BoolPromise
> OpenDirectory() override
;
309 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
311 void GetResponse(RequestResponse
& aResponse
) override
;
313 void CloseDirectory() override
;
316 class InitializedRequestBase
: public ResolvableNormalOriginOp
<bool> {
320 InitializedRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
324 RefPtr
<BoolPromise
> OpenDirectory() override
;
326 void CloseDirectory() override
;
329 class StorageInitializedOp final
: public InitializedRequestBase
{
331 explicit StorageInitializedOp(
332 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
333 : InitializedRequestBase(std::move(aQuotaManager
),
334 "dom::quota::StorageInitializedOp") {}
337 ~StorageInitializedOp() = default;
339 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
341 bool UnwrapResolveValue() override
;
344 class PersistentStorageInitializedOp final
: public InitializedRequestBase
{
346 explicit PersistentStorageInitializedOp(
347 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
348 : InitializedRequestBase(std::move(aQuotaManager
),
349 "dom::quota::PersistentStorageInitializedOp") {}
352 ~PersistentStorageInitializedOp() = default;
354 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
356 bool UnwrapResolveValue() override
;
359 class TemporaryStorageInitializedOp final
: public InitializedRequestBase
{
361 explicit TemporaryStorageInitializedOp(
362 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
363 : InitializedRequestBase(std::move(aQuotaManager
),
364 "dom::quota::TemporaryStorageInitializedOp") {}
367 ~TemporaryStorageInitializedOp() = default;
369 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
371 bool UnwrapResolveValue() override
;
374 class TemporaryGroupInitializedOp final
375 : public ResolvableNormalOriginOp
<bool> {
376 const PrincipalMetadata mPrincipalMetadata
;
380 explicit TemporaryGroupInitializedOp(
381 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
382 const PrincipalMetadata
& aPrincipalMetadata
);
385 ~TemporaryGroupInitializedOp() = default;
387 RefPtr
<BoolPromise
> OpenDirectory() override
;
389 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
391 bool UnwrapResolveValue() override
;
393 void CloseDirectory() override
;
396 class InitializedOriginRequestBase
: public ResolvableNormalOriginOp
<bool> {
398 const PrincipalMetadata mPrincipalMetadata
;
401 InitializedOriginRequestBase(
402 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
403 const PrincipalMetadata
& aPrincipalMetadata
);
406 RefPtr
<BoolPromise
> OpenDirectory() override
;
408 void CloseDirectory() override
;
411 class PersistentOriginInitializedOp final
412 : public InitializedOriginRequestBase
{
414 explicit PersistentOriginInitializedOp(
415 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
416 const OriginMetadata
& aOriginMetadata
);
419 ~PersistentOriginInitializedOp() = default;
421 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
423 bool UnwrapResolveValue() override
;
426 class TemporaryOriginInitializedOp final
: public InitializedOriginRequestBase
{
427 const PersistenceType mPersistenceType
;
430 explicit TemporaryOriginInitializedOp(
431 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
432 const OriginMetadata
& aOriginMetadata
);
435 ~TemporaryOriginInitializedOp() = default;
437 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
439 bool UnwrapResolveValue() override
;
442 class InitOp final
: public ResolvableNormalOriginOp
<bool> {
443 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
446 InitOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
447 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
452 RefPtr
<BoolPromise
> OpenDirectory() override
;
454 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
456 bool UnwrapResolveValue() override
;
458 void CloseDirectory() override
;
461 class InitializePersistentStorageOp final
462 : public ResolvableNormalOriginOp
<bool> {
463 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
466 InitializePersistentStorageOp(
467 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
468 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
471 ~InitializePersistentStorageOp() = default;
473 RefPtr
<BoolPromise
> OpenDirectory() override
;
475 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
477 bool UnwrapResolveValue() override
;
479 void CloseDirectory() override
;
482 class InitTemporaryStorageOp final
483 : public ResolvableNormalOriginOp
<MaybePrincipalMetadataArray
, true> {
484 MaybePrincipalMetadataArray mAllTemporaryGroups
;
485 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
488 InitTemporaryStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
489 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
492 ~InitTemporaryStorageOp() = default;
494 RefPtr
<BoolPromise
> OpenDirectory() override
;
496 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
498 MaybePrincipalMetadataArray
UnwrapResolveValue() override
;
500 void CloseDirectory() override
;
503 class InitializeTemporaryGroupOp final
: public ResolvableNormalOriginOp
<bool> {
504 const PrincipalMetadata mPrincipalMetadata
;
505 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
508 InitializeTemporaryGroupOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
509 const PrincipalMetadata
& aPrincipalMetadata
,
510 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
513 ~InitializeTemporaryGroupOp() = default;
515 RefPtr
<BoolPromise
> OpenDirectory() override
;
517 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
519 bool UnwrapResolveValue() override
;
521 void CloseDirectory() override
;
524 class InitializeOriginRequestBase
: public ResolvableNormalOriginOp
<bool> {
526 const PrincipalMetadata mPrincipalMetadata
;
527 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
530 InitializeOriginRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
532 const PrincipalMetadata
& aPrincipalMetadata
,
533 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
536 RefPtr
<BoolPromise
> OpenDirectory() override
;
538 void CloseDirectory() override
;
541 class InitializePersistentOriginOp final
: public InitializeOriginRequestBase
{
543 InitializePersistentOriginOp(
544 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
545 const OriginMetadata
& aOriginMetadata
,
546 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
549 ~InitializePersistentOriginOp() = default;
551 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
553 bool UnwrapResolveValue() override
;
556 class InitializeTemporaryOriginOp final
: public InitializeOriginRequestBase
{
557 const PersistenceType mPersistenceType
;
558 const bool mCreateIfNonExistent
;
561 InitializeTemporaryOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
562 const OriginMetadata
& aOriginMetadata
,
563 bool aCreateIfNonExistent
,
564 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
567 ~InitializeTemporaryOriginOp() = default;
569 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
571 bool UnwrapResolveValue() override
;
574 class InitializeClientBase
: public ResolvableNormalOriginOp
<bool> {
576 const PrincipalInfo mPrincipalInfo
;
577 ClientMetadata mClientMetadata
;
578 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
579 const PersistenceType mPersistenceType
;
580 const Client::Type mClientType
;
583 InitializeClientBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
584 const char* aName
, PersistenceType aPersistenceType
,
585 const PrincipalInfo
& aPrincipalInfo
,
586 Client::Type aClientType
);
588 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
591 RefPtr
<BoolPromise
> OpenDirectory() override
;
593 void CloseDirectory() override
;
596 class InitializePersistentClientOp
: public InitializeClientBase
{
598 InitializePersistentClientOp(
599 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
600 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
);
603 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
605 bool UnwrapResolveValue() override
;
608 class InitializeTemporaryClientOp
: public InitializeClientBase
{
610 InitializeTemporaryClientOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
611 PersistenceType aPersistenceType
,
612 const PrincipalInfo
& aPrincipalInfo
,
613 Client::Type aClientType
);
616 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
618 bool UnwrapResolveValue() override
;
621 class GetFullOriginMetadataOp
622 : public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
623 const GetFullOriginMetadataParams mParams
;
624 // XXX Consider wrapping with LazyInitializedOnce
625 OriginMetadata mOriginMetadata
;
626 Maybe
<FullOriginMetadata
> mMaybeFullOriginMetadata
;
629 GetFullOriginMetadataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
630 const GetFullOriginMetadataParams
& aParams
);
633 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
635 RefPtr
<BoolPromise
> OpenDirectory() override
;
637 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
639 void GetResponse(RequestResponse
& aResponse
) override
;
641 void CloseDirectory() override
;
644 class GetCachedOriginUsageOp
645 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<uint64_t>> {
646 const PrincipalInfo mPrincipalInfo
;
647 PrincipalMetadata mPrincipalMetadata
;
651 GetCachedOriginUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
652 const PrincipalInfo
& aPrincipalInfo
);
655 ~GetCachedOriginUsageOp() = default;
657 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
659 RefPtr
<BoolPromise
> OpenDirectory() override
;
661 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
663 uint64_t UnwrapResolveValue() override
;
665 void CloseDirectory() override
;
668 class ListCachedOriginsOp final
669 : public OpenStorageDirectoryHelper
<
670 ResolvableNormalOriginOp
<CStringArray
, /* IsExclusive */ true>> {
671 nsTArray
<nsCString
> mOrigins
;
674 explicit ListCachedOriginsOp(
675 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
678 ~ListCachedOriginsOp() = default;
680 RefPtr
<BoolPromise
> OpenDirectory() override
;
682 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
684 CStringArray
UnwrapResolveValue() override
;
686 void CloseDirectory() override
;
689 class ClearStorageOp final
690 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
692 explicit ClearStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
695 ~ClearStorageOp() = default;
697 void DeleteFiles(QuotaManager
& aQuotaManager
);
699 void DeleteStorageFile(QuotaManager
& aQuotaManager
);
701 RefPtr
<BoolPromise
> OpenDirectory() override
;
703 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
705 bool UnwrapResolveValue() override
;
707 void CloseDirectory() override
;
710 class ClearRequestBase
711 : public OpenStorageDirectoryHelper
<
712 ResolvableNormalOriginOp
<OriginMetadataArray
, true>> {
713 Atomic
<uint64_t> mIterations
;
716 OriginMetadataArray mOriginMetadataArray
;
718 ClearRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
720 : OpenStorageDirectoryHelper(std::move(aQuotaManager
), aName
),
722 AssertIsOnOwningThread();
725 void DeleteFiles(QuotaManager
& aQuotaManager
,
726 const OriginMetadata
& aOriginMetadata
);
728 void DeleteFiles(QuotaManager
& aQuotaManager
,
729 PersistenceType aPersistenceType
,
730 const OriginScope
& aOriginScope
);
733 template <typename FileCollector
>
734 void DeleteFilesInternal(QuotaManager
& aQuotaManager
,
735 PersistenceType aPersistenceType
,
736 const OriginScope
& aOriginScope
,
737 const FileCollector
& aFileCollector
);
739 void DoStringify(nsACString
& aData
) override
{
740 aData
.Append("ClearRequestBase "_ns
+
742 kStringifyStartInstance
+
745 IntToCString(static_cast<uint64_t>(mIterations
)) +
747 kStringifyEndInstance
);
751 class ClearOriginOp final
: public ClearRequestBase
{
752 const PrincipalInfo mPrincipalInfo
;
753 PrincipalMetadata mPrincipalMetadata
;
754 const PersistenceScope mPersistenceScope
;
757 ClearOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
758 const mozilla::Maybe
<PersistenceType
>& aPersistenceType
,
759 const PrincipalInfo
& aPrincipalInfo
);
762 ~ClearOriginOp() = default;
764 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
766 RefPtr
<BoolPromise
> OpenDirectory() override
;
768 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
770 OriginMetadataArray
UnwrapResolveValue() override
;
772 void CloseDirectory() override
;
775 class ClearClientOp final
776 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
777 const PrincipalInfo mPrincipalInfo
;
778 PrincipalMetadata mPrincipalMetadata
;
779 const PersistenceScope mPersistenceScope
;
780 const Client::Type mClientType
;
783 ClearClientOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
784 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
785 const PrincipalInfo
& aPrincipalInfo
,
786 const Client::Type aClientType
);
789 ~ClearClientOp() = default;
791 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
793 RefPtr
<BoolPromise
> OpenDirectory() override
;
795 void DeleteFiles(const ClientMetadata
& aClientMetadata
);
797 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
799 bool UnwrapResolveValue() override
;
801 void CloseDirectory() override
;
804 class ClearStoragesForOriginPrefixOp final
805 : public OpenStorageDirectoryHelper
<ClearRequestBase
> {
806 const PrincipalInfo mPrincipalInfo
;
807 PrincipalMetadata mPrincipalMetadata
;
808 const PersistenceScope mPersistenceScope
;
811 ClearStoragesForOriginPrefixOp(
812 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
813 const Maybe
<PersistenceType
>& aPersistenceType
,
814 const PrincipalInfo
& aPrincipalInfo
);
817 ~ClearStoragesForOriginPrefixOp() = default;
819 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
821 RefPtr
<BoolPromise
> OpenDirectory() override
;
823 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
825 OriginMetadataArray
UnwrapResolveValue() override
;
827 void CloseDirectory() override
;
830 class ClearDataOp final
: public ClearRequestBase
{
831 const OriginAttributesPattern mPattern
;
834 ClearDataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
835 const OriginAttributesPattern
& aPattern
);
838 ~ClearDataOp() = default;
840 RefPtr
<BoolPromise
> OpenDirectory() override
;
842 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
844 OriginMetadataArray
UnwrapResolveValue() override
;
846 void CloseDirectory() override
;
849 class ShutdownOriginOp final
850 : public ResolvableNormalOriginOp
<OriginMetadataArray
, true> {
851 const PrincipalInfo mPrincipalInfo
;
852 PrincipalMetadata mPrincipalMetadata
;
853 OriginMetadataArray mOriginMetadataArray
;
854 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
855 const PersistenceScope mPersistenceScope
;
858 ShutdownOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
859 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
860 const PrincipalInfo
& aPrincipalInfo
);
863 ~ShutdownOriginOp() = default;
865 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
867 RefPtr
<BoolPromise
> OpenDirectory() override
;
869 void CollectOriginMetadata(const OriginMetadata
& aOriginMetadata
);
871 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
873 OriginMetadataArray
UnwrapResolveValue() override
;
875 void CloseDirectory() override
;
878 class ShutdownClientOp final
: public ResolvableNormalOriginOp
<bool> {
879 const PrincipalInfo mPrincipalInfo
;
880 PrincipalMetadata mPrincipalMetadata
;
881 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
882 const PersistenceScope mPersistenceScope
;
883 const Client::Type mClientType
;
886 ShutdownClientOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
887 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
888 const PrincipalInfo
& aPrincipalInfo
,
889 const Client::Type aClientType
);
892 ~ShutdownClientOp() = default;
894 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
896 RefPtr
<BoolPromise
> OpenDirectory() override
;
898 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
900 bool UnwrapResolveValue() override
;
902 void CloseDirectory() override
;
905 class PersistRequestBase
: public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
906 const PrincipalInfo mPrincipalInfo
;
909 PrincipalMetadata mPrincipalMetadata
;
912 PersistRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
913 const PrincipalInfo
& aPrincipalInfo
);
915 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
918 RefPtr
<BoolPromise
> OpenDirectory() override
;
920 void CloseDirectory() override
;
923 class PersistedOp final
: public PersistRequestBase
{
927 PersistedOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
928 const RequestParams
& aParams
);
931 ~PersistedOp() = default;
933 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
935 void GetResponse(RequestResponse
& aResponse
) override
;
938 class PersistOp final
: public PersistRequestBase
{
940 PersistOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
941 const RequestParams
& aParams
);
944 ~PersistOp() = default;
946 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
948 void GetResponse(RequestResponse
& aResponse
) override
;
951 class EstimateOp final
: public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
952 const EstimateParams mParams
;
953 OriginMetadata mOriginMetadata
;
954 std::pair
<uint64_t, uint64_t> mUsageAndLimit
;
957 EstimateOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
958 const EstimateParams
& aParams
);
961 ~EstimateOp() = default;
963 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
965 RefPtr
<BoolPromise
> OpenDirectory() override
;
967 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
969 void GetResponse(RequestResponse
& aResponse
) override
;
971 void CloseDirectory() override
;
974 class ListOriginsOp final
975 : public OpenStorageDirectoryHelper
<
976 ResolvableNormalOriginOp
<CStringArray
, /* IsExclusive */ true>>,
977 public TraverseRepositoryHelper
{
978 // XXX Bug 1521541 will make each origin has it's own state.
979 nsTArray
<nsCString
> mOrigins
;
982 explicit ListOriginsOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
985 ~ListOriginsOp() = default;
987 RefPtr
<BoolPromise
> OpenDirectory() override
;
989 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
991 const Atomic
<bool>& GetIsCanceledFlag() override
;
993 nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
, nsIFile
& aOriginDir
,
994 const bool aPersistent
,
995 const PersistenceType aPersistenceType
) override
;
997 CStringArray
UnwrapResolveValue() override
;
999 void CloseDirectory() override
;
1002 RefPtr
<OriginOperationBase
> CreateFinalizeOriginEvictionOp(
1003 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1004 nsTArray
<RefPtr
<OriginDirectoryLock
>>&& aLocks
) {
1005 return MakeRefPtr
<FinalizeOriginEvictionOp
>(std::move(aQuotaManager
),
1009 RefPtr
<NormalOriginOperationBase
> CreateSaveOriginAccessTimeOp(
1010 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1011 const OriginMetadata
& aOriginMetadata
, int64_t aTimestamp
) {
1012 return MakeRefPtr
<SaveOriginAccessTimeOp
>(std::move(aQuotaManager
),
1013 aOriginMetadata
, aTimestamp
);
1016 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearPrivateRepositoryOp(
1017 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1018 return MakeRefPtr
<ClearPrivateRepositoryOp
>(std::move(aQuotaManager
));
1021 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateShutdownStorageOp(
1022 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1023 return MakeRefPtr
<ShutdownStorageOp
>(std::move(aQuotaManager
));
1026 RefPtr
<ResolvableNormalOriginOp
<OriginUsageMetadataArray
, true>>
1027 CreateGetUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1029 return MakeRefPtr
<GetUsageOp
>(std::move(aQuotaManager
), aGetAll
);
1032 RefPtr
<ResolvableNormalOriginOp
<UsageInfo
>> CreateGetOriginUsageOp(
1033 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1034 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
) {
1035 return MakeRefPtr
<GetOriginUsageOp
>(std::move(aQuotaManager
), aPrincipalInfo
);
1038 RefPtr
<QuotaRequestBase
> CreateStorageNameOp(
1039 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1040 return MakeRefPtr
<StorageNameOp
>(std::move(aQuotaManager
));
1043 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateStorageInitializedOp(
1044 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1045 return MakeRefPtr
<StorageInitializedOp
>(std::move(aQuotaManager
));
1048 RefPtr
<ResolvableNormalOriginOp
<bool>> CreatePersistentStorageInitializedOp(
1049 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1050 return MakeRefPtr
<PersistentStorageInitializedOp
>(std::move(aQuotaManager
));
1053 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateTemporaryStorageInitializedOp(
1054 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1055 return MakeRefPtr
<TemporaryStorageInitializedOp
>(std::move(aQuotaManager
));
1058 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateTemporaryGroupInitializedOp(
1059 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1060 const PrincipalMetadata
& aPrincipalMetadata
) {
1061 return MakeRefPtr
<TemporaryGroupInitializedOp
>(std::move(aQuotaManager
),
1062 aPrincipalMetadata
);
1065 RefPtr
<ResolvableNormalOriginOp
<bool>> CreatePersistentOriginInitializedOp(
1066 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1067 const OriginMetadata
& aOriginMetadata
) {
1068 return MakeRefPtr
<PersistentOriginInitializedOp
>(std::move(aQuotaManager
),
1072 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateTemporaryOriginInitializedOp(
1073 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1074 const OriginMetadata
& aOriginMetadata
) {
1075 return MakeRefPtr
<TemporaryOriginInitializedOp
>(std::move(aQuotaManager
),
1079 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitOp(
1080 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1081 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1082 return MakeRefPtr
<InitOp
>(std::move(aQuotaManager
),
1083 std::move(aDirectoryLock
));
1086 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializePersistentStorageOp(
1087 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1088 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1089 return MakeRefPtr
<InitializePersistentStorageOp
>(std::move(aQuotaManager
),
1090 std::move(aDirectoryLock
));
1093 RefPtr
<ResolvableNormalOriginOp
<MaybePrincipalMetadataArray
, true>>
1094 CreateInitTemporaryStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1095 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1096 return MakeRefPtr
<InitTemporaryStorageOp
>(std::move(aQuotaManager
),
1097 std::move(aDirectoryLock
));
1100 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializeTemporaryGroupOp(
1101 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1102 const PrincipalMetadata
& aPrincipalMetadata
,
1103 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1104 return MakeRefPtr
<InitializeTemporaryGroupOp
>(
1105 std::move(aQuotaManager
), aPrincipalMetadata
, std::move(aDirectoryLock
));
1108 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializePersistentOriginOp(
1109 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1110 const OriginMetadata
& aOriginMetadata
,
1111 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1112 return MakeRefPtr
<InitializePersistentOriginOp
>(
1113 std::move(aQuotaManager
), aOriginMetadata
, std::move(aDirectoryLock
));
1116 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializeTemporaryOriginOp(
1117 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1118 const OriginMetadata
& aOriginMetadata
, bool aCreateIfNonExistent
,
1119 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
1120 return MakeRefPtr
<InitializeTemporaryOriginOp
>(
1121 std::move(aQuotaManager
), aOriginMetadata
, aCreateIfNonExistent
,
1122 std::move(aDirectoryLock
));
1125 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializePersistentClientOp(
1126 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1127 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
1128 const Client::Type aClientType
) {
1129 return MakeRefPtr
<InitializePersistentClientOp
>(std::move(aQuotaManager
),
1130 aPrincipalInfo
, aClientType
);
1133 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializeTemporaryClientOp(
1134 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1135 const PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
1136 const Client::Type aClientType
) {
1137 return MakeRefPtr
<InitializeTemporaryClientOp
>(
1138 std::move(aQuotaManager
), aPersistenceType
, aPrincipalInfo
, aClientType
);
1141 RefPtr
<QuotaRequestBase
> CreateGetFullOriginMetadataOp(
1142 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1143 const GetFullOriginMetadataParams
& aParams
) {
1144 return MakeRefPtr
<GetFullOriginMetadataOp
>(std::move(aQuotaManager
), aParams
);
1147 RefPtr
<ResolvableNormalOriginOp
<uint64_t>> CreateGetCachedOriginUsageOp(
1148 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1149 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
) {
1150 return MakeRefPtr
<GetCachedOriginUsageOp
>(std::move(aQuotaManager
),
1154 RefPtr
<ResolvableNormalOriginOp
<CStringArray
, true>> CreateListCachedOriginsOp(
1155 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1156 return MakeRefPtr
<ListCachedOriginsOp
>(std::move(aQuotaManager
));
1159 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearStorageOp(
1160 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1161 return MakeRefPtr
<ClearStorageOp
>(std::move(aQuotaManager
));
1164 RefPtr
<ResolvableNormalOriginOp
<OriginMetadataArray
, true>> CreateClearOriginOp(
1165 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1166 const Maybe
<PersistenceType
>& aPersistenceType
,
1167 const PrincipalInfo
& aPrincipalInfo
) {
1168 return MakeRefPtr
<ClearOriginOp
>(std::move(aQuotaManager
), aPersistenceType
,
1172 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearClientOp(
1173 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1174 Maybe
<PersistenceType
> aPersistenceType
,
1175 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
) {
1176 return MakeRefPtr
<ClearClientOp
>(std::move(aQuotaManager
), aPersistenceType
,
1177 aPrincipalInfo
, aClientType
);
1180 RefPtr
<ResolvableNormalOriginOp
<OriginMetadataArray
, true>>
1181 CreateClearStoragesForOriginPrefixOp(
1182 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1183 const Maybe
<PersistenceType
>& aPersistenceType
,
1184 const PrincipalInfo
& aPrincipalInfo
) {
1185 return MakeRefPtr
<ClearStoragesForOriginPrefixOp
>(
1186 std::move(aQuotaManager
), aPersistenceType
, aPrincipalInfo
);
1189 RefPtr
<ResolvableNormalOriginOp
<OriginMetadataArray
, true>> CreateClearDataOp(
1190 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1191 const OriginAttributesPattern
& aPattern
) {
1192 return MakeRefPtr
<ClearDataOp
>(std::move(aQuotaManager
), aPattern
);
1195 RefPtr
<ResolvableNormalOriginOp
<OriginMetadataArray
, true>>
1196 CreateShutdownOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1197 Maybe
<PersistenceType
> aPersistenceType
,
1198 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
) {
1199 return MakeRefPtr
<ShutdownOriginOp
>(std::move(aQuotaManager
),
1200 aPersistenceType
, aPrincipalInfo
);
1203 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateShutdownClientOp(
1204 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1205 Maybe
<PersistenceType
> aPersistenceType
,
1206 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
) {
1207 return MakeRefPtr
<ShutdownClientOp
>(
1208 std::move(aQuotaManager
), aPersistenceType
, aPrincipalInfo
, aClientType
);
1211 RefPtr
<QuotaRequestBase
> CreatePersistedOp(
1212 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1213 const RequestParams
& aParams
) {
1214 return MakeRefPtr
<PersistedOp
>(std::move(aQuotaManager
), aParams
);
1217 RefPtr
<QuotaRequestBase
> CreatePersistOp(
1218 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1219 const RequestParams
& aParams
) {
1220 return MakeRefPtr
<PersistOp
>(std::move(aQuotaManager
), aParams
);
1223 RefPtr
<QuotaRequestBase
> CreateEstimateOp(
1224 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1225 const EstimateParams
& aParams
) {
1226 return MakeRefPtr
<EstimateOp
>(std::move(aQuotaManager
), aParams
);
1229 RefPtr
<ResolvableNormalOriginOp
<CStringArray
, /* IsExclusive */ true>>
1230 CreateListOriginsOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
1231 return MakeRefPtr
<ListOriginsOp
>(std::move(aQuotaManager
));
1234 template <class Base
>
1235 RefPtr
<BoolPromise
> OpenStorageDirectoryHelper
<Base
>::OpenStorageDirectory(
1236 const PersistenceScope
& aPersistenceScope
, const OriginScope
& aOriginScope
,
1237 const Nullable
<Client::Type
>& aClientType
, bool aExclusive
,
1238 bool aInitializeOrigins
, const DirectoryLockCategory aCategory
) {
1239 return Base::mQuotaManager
1240 ->OpenStorageDirectory(aPersistenceScope
, aOriginScope
, aClientType
,
1241 aExclusive
, aInitializeOrigins
, aCategory
)
1242 ->Then(GetCurrentSerialEventTarget(), __func__
,
1243 [self
= RefPtr(this)](
1244 UniversalDirectoryLockPromise::ResolveOrRejectValue
&& aValue
) {
1245 if (aValue
.IsReject()) {
1246 return BoolPromise::CreateAndReject(aValue
.RejectValue(),
1250 self
->mDirectoryLock
= std::move(aValue
.ResolveValue());
1252 return BoolPromise::CreateAndResolve(true, __func__
);
1256 RefPtr
<BoolPromise
> FinalizeOriginEvictionOp::Open() {
1257 AssertIsOnOwningThread();
1258 MOZ_ASSERT(!mLocks
.IsEmpty());
1260 return BoolPromise::CreateAndResolve(true, __func__
);
1263 nsresult
FinalizeOriginEvictionOp::DoDirectoryWork(
1264 QuotaManager
& aQuotaManager
) {
1265 AssertIsOnIOThread();
1267 AUTO_PROFILER_LABEL("FinalizeOriginEvictionOp::DoDirectoryWork", OTHER
);
1269 for (const auto& lock
: mLocks
) {
1270 aQuotaManager
.OriginClearCompleted(lock
->OriginMetadata(),
1271 Nullable
<Client::Type
>());
1277 void FinalizeOriginEvictionOp::UnblockOpen() {
1278 AssertIsOnOwningThread();
1280 nsTArray
<OriginMetadata
> origins
;
1282 std::transform(mLocks
.cbegin(), mLocks
.cend(), MakeBackInserter(origins
),
1283 [](const auto& lock
) { return lock
->OriginMetadata(); });
1285 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(NS_NewRunnableFunction(
1286 "dom::quota::FinalizeOriginEvictionOp::UnblockOpen",
1287 [quotaManager
= mQuotaManager
, origins
= std::move(origins
)]() {
1288 quotaManager
->NoteUninitializedOrigins(origins
);
1291 for (const auto& lock
: mLocks
) {
1297 RefPtr
<BoolPromise
> SaveOriginAccessTimeOp::OpenDirectory() {
1298 AssertIsOnOwningThread();
1300 return OpenStorageDirectory(
1301 PersistenceScope::CreateFromValue(mOriginMetadata
.mPersistenceType
),
1302 OriginScope::FromOrigin(mOriginMetadata
), Nullable
<Client::Type
>(),
1303 /* aExclusive */ false);
1306 nsresult
SaveOriginAccessTimeOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1307 AssertIsOnIOThread();
1308 aQuotaManager
.AssertStorageIsInitializedInternal();
1310 AUTO_PROFILER_LABEL("SaveOriginAccessTimeOp::DoDirectoryWork", OTHER
);
1312 QM_TRY(MOZ_TO_RESULT(!QuotaManager::IsShuttingDown()), NS_ERROR_ABORT
);
1314 QM_TRY_INSPECT(const auto& file
,
1315 aQuotaManager
.GetOriginDirectory(mOriginMetadata
));
1317 // The origin directory might not exist
1318 // anymore, because it was deleted by a clear operation.
1319 QM_TRY_INSPECT(const bool& exists
, MOZ_TO_RESULT_INVOKE_MEMBER(file
, Exists
));
1322 QM_TRY(MOZ_TO_RESULT(file
->Append(nsLiteralString(METADATA_V2_FILE_NAME
))));
1324 QM_TRY_INSPECT(const auto& stream
,
1325 GetBinaryOutputStream(*file
, FileFlag::Update
));
1328 QM_TRY(MOZ_TO_RESULT(stream
->Write64(mTimestamp
)));
1334 void SaveOriginAccessTimeOp::SendResults() {}
1336 void SaveOriginAccessTimeOp::CloseDirectory() {
1337 AssertIsOnOwningThread();
1339 SafeDropDirectoryLock(mDirectoryLock
);
1342 RefPtr
<BoolPromise
> ClearPrivateRepositoryOp::OpenDirectory() {
1343 AssertIsOnOwningThread();
1345 return OpenStorageDirectory(
1346 PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PRIVATE
),
1347 OriginScope::FromNull(), Nullable
<Client::Type
>(),
1348 /* aExclusive */ true, /* aInitializeOrigins */ false,
1349 DirectoryLockCategory::UninitOrigins
);
1352 nsresult
ClearPrivateRepositoryOp::DoDirectoryWork(
1353 QuotaManager
& aQuotaManager
) {
1354 AssertIsOnIOThread();
1355 aQuotaManager
.AssertStorageIsInitializedInternal();
1357 AUTO_PROFILER_LABEL("ClearPrivateRepositoryOp::DoDirectoryWork", OTHER
);
1360 const auto& directory
,
1361 QM_NewLocalFile(aQuotaManager
.GetStoragePath(PERSISTENCE_TYPE_PRIVATE
)));
1363 nsresult rv
= directory
->Remove(true);
1364 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
1365 // This should never fail if we've closed all storage connections
1367 MOZ_ASSERT(false, "Failed to remove directory!");
1370 aQuotaManager
.RemoveQuotaForRepository(PERSISTENCE_TYPE_PRIVATE
);
1372 aQuotaManager
.RepositoryClearCompleted(PERSISTENCE_TYPE_PRIVATE
);
1377 void ClearPrivateRepositoryOp::CloseDirectory() {
1378 AssertIsOnOwningThread();
1380 SafeDropDirectoryLock(mDirectoryLock
);
1383 RefPtr
<BoolPromise
> ShutdownStorageOp::OpenDirectory() {
1384 AssertIsOnOwningThread();
1386 // Clear directory lock tables (which also saves origin access time) before
1387 // acquiring the exclusive lock below. Otherwise, saving of origin access
1388 // time would be scheduled after storage shutdown and that would initialize
1389 // storage again in the end.
1390 mQuotaManager
->ClearDirectoryLockTables();
1392 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
1393 PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
1394 Nullable
<Client::Type
>(),
1395 /* aExclusive */ true, DirectoryLockCategory::UninitStorage
);
1397 return mDirectoryLock
->Acquire();
1401 nsresult
ShutdownStorageOp::DirectoryOpen() {
1402 AssertIsOnBackgroundThread();
1403 MOZ_ASSERT(mDirectoryLock
);
1404 mDirectoryLock
->AssertIsAcquiredExclusively();
1406 return NormalOriginOperationBase::DirectoryOpen();
1410 nsresult
ShutdownStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1411 AssertIsOnIOThread();
1413 AUTO_PROFILER_LABEL("ShutdownStorageOp::DoDirectoryWork", OTHER
);
1415 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
1416 "ShutdownStorageOp::DoDirectoryWork -> ShutdownStorageInternal."_ns
);
1418 aQuotaManager
.ShutdownStorageInternal();
1423 void ShutdownStorageOp::CloseDirectory() {
1424 AssertIsOnOwningThread();
1426 DropDirectoryLockIfNotDropped(mDirectoryLock
);
1429 nsresult
TraverseRepositoryHelper::TraverseRepository(
1430 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
) {
1431 AssertIsOnIOThread();
1434 const auto& directory
,
1435 QM_NewLocalFile(aQuotaManager
.GetStoragePath(aPersistenceType
)));
1437 QM_TRY_INSPECT(const bool& exists
,
1438 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
1444 QM_TRY(CollectEachFileAtomicCancelable(
1445 *directory
, GetIsCanceledFlag(),
1446 [this, aPersistenceType
, &aQuotaManager
,
1447 persistent
= aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
](
1448 const nsCOMPtr
<nsIFile
>& originDir
) -> Result
<Ok
, nsresult
> {
1449 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*originDir
));
1451 switch (dirEntryKind
) {
1452 case nsIFileKind::ExistsAsDirectory
:
1453 QM_TRY(MOZ_TO_RESULT(ProcessOrigin(aQuotaManager
, *originDir
,
1454 persistent
, aPersistenceType
)));
1457 case nsIFileKind::ExistsAsFile
: {
1458 QM_TRY_INSPECT(const auto& leafName
,
1459 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
1460 nsAutoString
, originDir
, GetLeafName
));
1462 // Unknown files during getting usages are allowed. Just warn if we
1464 if (!IsOSMetadata(leafName
)) {
1465 UNKNOWN_FILE_WARNING(leafName
);
1471 case nsIFileKind::DoesNotExist
:
1472 // Ignore files that got removed externally while iterating.
1482 Result
<UsageInfo
, nsresult
> OriginUsageHelper::GetUsageForOrigin(
1483 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
1484 const OriginMetadata
& aOriginMetadata
) {
1485 AssertIsOnIOThread();
1486 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
== aPersistenceType
);
1488 QM_TRY_INSPECT(const auto& directory
,
1489 aQuotaManager
.GetOriginDirectory(aOriginMetadata
));
1491 QM_TRY_INSPECT(const bool& exists
,
1492 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
1494 if (!exists
|| GetIsCanceledFlag()) {
1498 // If the directory exists then enumerate all the files inside, adding up
1499 // the sizes to get the final usage statistic.
1502 if (aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
) {
1503 initialized
= aQuotaManager
.IsPersistentOriginInitializedInternal(
1504 aOriginMetadata
.mOrigin
);
1506 initialized
= aQuotaManager
.IsTemporaryStorageInitializedInternal();
1509 return GetUsageForOriginEntries(aQuotaManager
, aPersistenceType
,
1510 aOriginMetadata
, *directory
, initialized
);
1513 Result
<UsageInfo
, nsresult
> OriginUsageHelper::GetUsageForOriginEntries(
1514 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
1515 const OriginMetadata
& aOriginMetadata
, nsIFile
& aDirectory
,
1516 const bool aInitialized
) {
1517 AssertIsOnIOThread();
1519 QM_TRY_RETURN((ReduceEachFileAtomicCancelable(
1520 aDirectory
, GetIsCanceledFlag(), UsageInfo
{},
1521 [&](UsageInfo oldUsageInfo
, const nsCOMPtr
<nsIFile
>& file
)
1522 -> mozilla::Result
<UsageInfo
, nsresult
> {
1524 const auto& leafName
,
1525 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, file
, GetLeafName
));
1527 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*file
));
1529 switch (dirEntryKind
) {
1530 case nsIFileKind::ExistsAsDirectory
: {
1531 Client::Type clientType
;
1533 Client::TypeFromText(leafName
, clientType
, fallible
);
1535 // Unknown directories during getting usage for an origin (even
1536 // for an uninitialized origin) are now allowed. Just warn if we
1538 UNKNOWN_FILE_WARNING(leafName
);
1542 Client
* const client
= aQuotaManager
.GetClient(clientType
);
1545 QM_TRY_INSPECT(const auto& usageInfo
,
1546 aInitialized
? client
->GetUsageForOrigin(
1547 aPersistenceType
, aOriginMetadata
,
1548 GetIsCanceledFlag())
1549 : client
->InitOrigin(
1550 aPersistenceType
, aOriginMetadata
,
1551 GetIsCanceledFlag()));
1552 return oldUsageInfo
+ usageInfo
;
1555 case nsIFileKind::ExistsAsFile
:
1556 // We are maintaining existing behavior for unknown files here (just
1558 // This can possibly be used by developers to add temporary backups
1559 // into origin directories without losing get usage functionality.
1560 if (IsTempMetadata(leafName
)) {
1561 if (!aInitialized
) {
1562 QM_TRY(MOZ_TO_RESULT(file
->Remove(/* recursive */ false)));
1568 if (IsOriginMetadata(leafName
) || IsOSMetadata(leafName
) ||
1569 IsDotFile(leafName
)) {
1573 // Unknown files during getting usage for an origin (even for an
1574 // uninitialized origin) are now allowed. Just warn if we find them.
1575 UNKNOWN_FILE_WARNING(leafName
);
1578 case nsIFileKind::DoesNotExist
:
1579 // Ignore files that got removed externally while iterating.
1583 return oldUsageInfo
;
1587 GetUsageOp::GetUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1589 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1590 "dom::quota::GetUsageOp"),
1592 AssertIsOnOwningThread();
1595 void GetUsageOp::ProcessOriginInternal(QuotaManager
* aQuotaManager
,
1596 const PersistenceType aPersistenceType
,
1597 const nsACString
& aOrigin
,
1598 const int64_t aTimestamp
,
1599 const bool aPersisted
,
1600 const uint64_t aUsage
) {
1601 if (!mGetAll
&& aQuotaManager
->IsOriginInternal(aOrigin
)) {
1605 // We can't store pointers to OriginUsage objects in the hashtable
1606 // since AppendElement() reallocates its internal array buffer as number
1607 // of elements grows.
1608 const auto& originUsage
=
1609 mOriginUsagesIndex
.WithEntryHandle(aOrigin
, [&](auto&& entry
) {
1611 return WrapNotNullUnchecked(&mOriginUsages
[entry
.Data()]);
1614 entry
.Insert(mOriginUsages
.Length());
1616 OriginUsageMetadata metadata
;
1617 metadata
.mOrigin
= aOrigin
;
1618 metadata
.mPersistenceType
= PERSISTENCE_TYPE_DEFAULT
;
1619 metadata
.mPersisted
= false;
1620 metadata
.mLastAccessTime
= 0;
1621 metadata
.mUsage
= 0;
1623 return mOriginUsages
.EmplaceBack(std::move(metadata
));
1626 if (aPersistenceType
== PERSISTENCE_TYPE_DEFAULT
) {
1627 originUsage
->mPersisted
= aPersisted
;
1630 originUsage
->mUsage
= originUsage
->mUsage
+ aUsage
;
1632 originUsage
->mLastAccessTime
=
1633 std::max
<int64_t>(originUsage
->mLastAccessTime
, aTimestamp
);
1636 const Atomic
<bool>& GetUsageOp::GetIsCanceledFlag() {
1637 AssertIsOnIOThread();
1642 // XXX Remove aPersistent
1643 // XXX Remove aPersistenceType once GetUsageForOrigin uses the persistence
1644 // type from OriginMetadata
1645 nsresult
GetUsageOp::ProcessOrigin(QuotaManager
& aQuotaManager
,
1646 nsIFile
& aOriginDir
, const bool aPersistent
,
1647 const PersistenceType aPersistenceType
) {
1648 AssertIsOnIOThread();
1650 QM_TRY_UNWRAP(auto maybeMetadata
,
1653 aQuotaManager
.LoadFullOriginMetadataWithRestore(&aOriginDir
)
1654 .map([](auto metadata
) -> Maybe
<FullOriginMetadata
> {
1655 return Some(std::move(metadata
));
1658 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
1660 ErrToDefaultOk
<Maybe
<FullOriginMetadata
>>));
1662 if (!maybeMetadata
) {
1663 // Unknown directories during getting usage are allowed. Just warn if we
1665 QM_TRY_INSPECT(const auto& leafName
,
1666 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, aOriginDir
,
1669 UNKNOWN_FILE_WARNING(leafName
);
1673 auto metadata
= maybeMetadata
.extract();
1675 QM_TRY_INSPECT(const auto& usageInfo
,
1676 GetUsageForOrigin(aQuotaManager
, aPersistenceType
, metadata
));
1678 ProcessOriginInternal(&aQuotaManager
, aPersistenceType
, metadata
.mOrigin
,
1679 metadata
.mLastAccessTime
, metadata
.mPersisted
,
1680 usageInfo
.TotalUsage().valueOr(0));
1685 RefPtr
<BoolPromise
> GetUsageOp::OpenDirectory() {
1686 AssertIsOnOwningThread();
1688 return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
1689 OriginScope::FromNull(), Nullable
<Client::Type
>(),
1690 /* aExclusive */ false);
1693 nsresult
GetUsageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1694 AssertIsOnIOThread();
1695 aQuotaManager
.AssertStorageIsInitializedInternal();
1697 AUTO_PROFILER_LABEL("GetUsageOp::DoDirectoryWork", OTHER
);
1701 for (const PersistenceType type
: kAllPersistenceTypes
) {
1702 rv
= TraverseRepository(aQuotaManager
, type
);
1703 if (NS_WARN_IF(NS_FAILED(rv
))) {
1708 // TraverseRepository above only consulted the filesystem. We also need to
1709 // consider origins which may have pending quota usage, such as buffered
1710 // LocalStorage writes for an origin which didn't previously have any
1711 // LocalStorage data.
1713 aQuotaManager
.CollectPendingOriginsForListing(
1714 [this, &aQuotaManager
](const auto& originInfo
) {
1715 ProcessOriginInternal(
1716 &aQuotaManager
, originInfo
->GetGroupInfo()->GetPersistenceType(),
1717 originInfo
->Origin(), originInfo
->LockedAccessTime(),
1718 originInfo
->LockedPersisted(), originInfo
->LockedUsage());
1724 OriginUsageMetadataArray
GetUsageOp::UnwrapResolveValue() {
1725 AssertIsOnOwningThread();
1727 return std::move(mOriginUsages
);
1730 void GetUsageOp::CloseDirectory() {
1731 AssertIsOnOwningThread();
1733 SafeDropDirectoryLock(mDirectoryLock
);
1736 GetOriginUsageOp::GetOriginUsageOp(
1737 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1738 const PrincipalInfo
& aPrincipalInfo
)
1739 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1740 "dom::quota::GetOriginUsageOp"),
1741 mPrincipalInfo(aPrincipalInfo
) {
1742 AssertIsOnOwningThread();
1745 nsresult
GetOriginUsageOp::DoInit(QuotaManager
& aQuotaManager
) {
1746 AssertIsOnOwningThread();
1748 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
1749 aQuotaManager
, mPrincipalInfo
));
1751 mPrincipalMetadata
.AssertInvariants();
1756 RefPtr
<BoolPromise
> GetOriginUsageOp::OpenDirectory() {
1757 AssertIsOnOwningThread();
1759 return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
1760 OriginScope::FromOrigin(mPrincipalMetadata
),
1761 Nullable
<Client::Type
>(),
1762 /* aExclusive */ false);
1765 const Atomic
<bool>& GetOriginUsageOp::GetIsCanceledFlag() {
1766 AssertIsOnIOThread();
1771 nsresult
GetOriginUsageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1772 AssertIsOnIOThread();
1773 aQuotaManager
.AssertStorageIsInitializedInternal();
1774 MOZ_ASSERT(mUsageInfo
.TotalUsage().isNothing());
1776 AUTO_PROFILER_LABEL("GetOriginUsageOp::DoDirectoryWork", OTHER
);
1778 // Add all the persistent/temporary/default/private storage files we care
1780 for (const PersistenceType type
: kAllPersistenceTypes
) {
1781 const OriginMetadata originMetadata
= {mPrincipalMetadata
, type
};
1783 auto usageInfoOrErr
=
1784 GetUsageForOrigin(aQuotaManager
, type
, originMetadata
);
1785 if (NS_WARN_IF(usageInfoOrErr
.isErr())) {
1786 return usageInfoOrErr
.unwrapErr();
1789 mUsageInfo
+= usageInfoOrErr
.unwrap();
1795 UsageInfo
GetOriginUsageOp::UnwrapResolveValue() {
1796 AssertIsOnOwningThread();
1801 void GetOriginUsageOp::CloseDirectory() {
1802 AssertIsOnOwningThread();
1804 SafeDropDirectoryLock(mDirectoryLock
);
1807 StorageNameOp::StorageNameOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
1808 : QuotaRequestBase(std::move(aQuotaManager
), "dom::quota::StorageNameOp") {
1809 AssertIsOnOwningThread();
1812 RefPtr
<BoolPromise
> StorageNameOp::OpenDirectory() {
1813 AssertIsOnOwningThread();
1815 return BoolPromise::CreateAndResolve(true, __func__
);
1818 nsresult
StorageNameOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1819 AssertIsOnIOThread();
1821 AUTO_PROFILER_LABEL("StorageNameOp::DoDirectoryWork", OTHER
);
1823 mName
= aQuotaManager
.GetStorageName();
1828 void StorageNameOp::GetResponse(RequestResponse
& aResponse
) {
1829 AssertIsOnOwningThread();
1831 StorageNameResponse storageNameResponse
;
1833 storageNameResponse
.name() = mName
;
1835 aResponse
= storageNameResponse
;
1838 void StorageNameOp::CloseDirectory() { AssertIsOnOwningThread(); }
1840 InitializedRequestBase::InitializedRequestBase(
1841 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
)
1842 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
1843 mInitialized(false) {
1844 AssertIsOnOwningThread();
1847 RefPtr
<BoolPromise
> InitializedRequestBase::OpenDirectory() {
1848 AssertIsOnOwningThread();
1850 return BoolPromise::CreateAndResolve(true, __func__
);
1853 void InitializedRequestBase::CloseDirectory() { AssertIsOnOwningThread(); }
1855 nsresult
StorageInitializedOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1856 AssertIsOnIOThread();
1858 AUTO_PROFILER_LABEL("StorageInitializedOp::DoDirectoryWork", OTHER
);
1860 mInitialized
= aQuotaManager
.IsStorageInitializedInternal();
1865 bool StorageInitializedOp::UnwrapResolveValue() {
1866 AssertIsOnOwningThread();
1868 return mInitialized
;
1871 nsresult
PersistentStorageInitializedOp::DoDirectoryWork(
1872 QuotaManager
& aQuotaManager
) {
1873 AssertIsOnIOThread();
1875 AUTO_PROFILER_LABEL("PersistentStorageInitializedOp::DoDirectoryWork", OTHER
);
1877 mInitialized
= aQuotaManager
.IsPersistentStorageInitializedInternal();
1882 bool PersistentStorageInitializedOp::UnwrapResolveValue() {
1883 AssertIsOnOwningThread();
1885 return mInitialized
;
1888 nsresult
TemporaryStorageInitializedOp::DoDirectoryWork(
1889 QuotaManager
& aQuotaManager
) {
1890 AssertIsOnIOThread();
1892 AUTO_PROFILER_LABEL("TemporaryStorageInitializedOp::DoDirectoryWork", OTHER
);
1894 mInitialized
= aQuotaManager
.IsTemporaryStorageInitializedInternal();
1899 bool TemporaryStorageInitializedOp::UnwrapResolveValue() {
1900 AssertIsOnOwningThread();
1902 return mInitialized
;
1905 TemporaryGroupInitializedOp::TemporaryGroupInitializedOp(
1906 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1907 const PrincipalMetadata
& aPrincipalMetadata
)
1908 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
1909 "dom::quota::TemporaryGroupInitializedOp"),
1910 mPrincipalMetadata(aPrincipalMetadata
),
1911 mInitialized(false) {
1912 AssertIsOnOwningThread();
1915 RefPtr
<BoolPromise
> TemporaryGroupInitializedOp::OpenDirectory() {
1916 AssertIsOnOwningThread();
1918 return BoolPromise::CreateAndResolve(true, __func__
);
1921 nsresult
TemporaryGroupInitializedOp::DoDirectoryWork(
1922 QuotaManager
& aQuotaManager
) {
1923 AssertIsOnIOThread();
1925 AUTO_PROFILER_LABEL("TemporaryGroupInitializedOp::DoDirectoryWork", OTHER
);
1928 aQuotaManager
.IsTemporaryGroupInitializedInternal(mPrincipalMetadata
);
1933 bool TemporaryGroupInitializedOp::UnwrapResolveValue() {
1934 AssertIsOnOwningThread();
1936 return mInitialized
;
1939 void TemporaryGroupInitializedOp::CloseDirectory() { AssertIsOnOwningThread(); }
1941 InitializedOriginRequestBase::InitializedOriginRequestBase(
1942 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
1943 const PrincipalMetadata
& aPrincipalMetadata
)
1944 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
1945 mPrincipalMetadata(aPrincipalMetadata
),
1946 mInitialized(false) {
1947 AssertIsOnOwningThread();
1950 RefPtr
<BoolPromise
> InitializedOriginRequestBase::OpenDirectory() {
1951 AssertIsOnOwningThread();
1953 return BoolPromise::CreateAndResolve(true, __func__
);
1956 void InitializedOriginRequestBase::CloseDirectory() {
1957 AssertIsOnOwningThread();
1960 PersistentOriginInitializedOp::PersistentOriginInitializedOp(
1961 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1962 const OriginMetadata
& aOriginMetadata
)
1963 : InitializedOriginRequestBase(std::move(aQuotaManager
),
1964 "dom::quota::PersistentOriginInitializedOp",
1966 AssertIsOnOwningThread();
1967 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
);
1970 nsresult
PersistentOriginInitializedOp::DoDirectoryWork(
1971 QuotaManager
& aQuotaManager
) {
1972 AssertIsOnIOThread();
1974 AUTO_PROFILER_LABEL("PersistentOriginInitializedOp::DoDirectoryWork", OTHER
);
1976 mInitialized
= aQuotaManager
.IsPersistentOriginInitializedInternal(
1977 OriginMetadata
{mPrincipalMetadata
, PERSISTENCE_TYPE_PERSISTENT
});
1982 bool PersistentOriginInitializedOp::UnwrapResolveValue() {
1983 AssertIsOnOwningThread();
1985 return mInitialized
;
1988 TemporaryOriginInitializedOp::TemporaryOriginInitializedOp(
1989 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1990 const OriginMetadata
& aOriginMetadata
)
1991 : InitializedOriginRequestBase(std::move(aQuotaManager
),
1992 "dom::quota::TemporaryOriginInitializedOp",
1994 mPersistenceType(aOriginMetadata
.mPersistenceType
) {
1995 AssertIsOnOwningThread();
1996 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
);
1999 nsresult
TemporaryOriginInitializedOp::DoDirectoryWork(
2000 QuotaManager
& aQuotaManager
) {
2001 AssertIsOnIOThread();
2003 AUTO_PROFILER_LABEL("TemporaryOriginInitializedOp::DoDirectoryWork", OTHER
);
2005 mInitialized
= aQuotaManager
.IsTemporaryOriginInitializedInternal(
2006 OriginMetadata
{mPrincipalMetadata
, mPersistenceType
});
2011 bool TemporaryOriginInitializedOp::UnwrapResolveValue() {
2012 AssertIsOnOwningThread();
2014 return mInitialized
;
2017 InitOp::InitOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2018 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2019 : ResolvableNormalOriginOp(std::move(aQuotaManager
), "dom::quota::InitOp"),
2020 mDirectoryLock(std::move(aDirectoryLock
)) {
2021 AssertIsOnOwningThread();
2022 MOZ_ASSERT(mDirectoryLock
);
2025 RefPtr
<BoolPromise
> InitOp::OpenDirectory() {
2026 AssertIsOnOwningThread();
2027 MOZ_ASSERT(mDirectoryLock
);
2029 return BoolPromise::CreateAndResolve(true, __func__
);
2032 nsresult
InitOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2033 AssertIsOnIOThread();
2035 AUTO_PROFILER_LABEL("InitOp::DoDirectoryWork", OTHER
);
2037 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.EnsureStorageIsInitializedInternal()));
2042 bool InitOp::UnwrapResolveValue() { return true; }
2044 void InitOp::CloseDirectory() {
2045 AssertIsOnOwningThread();
2047 DropDirectoryLock(mDirectoryLock
);
2050 InitializePersistentStorageOp::InitializePersistentStorageOp(
2051 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2052 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2053 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
2054 "dom::quota::InitializePersistentStorageOp"),
2055 mDirectoryLock(std::move(aDirectoryLock
)) {
2056 AssertIsOnOwningThread();
2059 RefPtr
<BoolPromise
> InitializePersistentStorageOp::OpenDirectory() {
2060 AssertIsOnOwningThread();
2061 MOZ_ASSERT(mDirectoryLock
);
2063 return BoolPromise::CreateAndResolve(true, __func__
);
2066 nsresult
InitializePersistentStorageOp::DoDirectoryWork(
2067 QuotaManager
& aQuotaManager
) {
2068 AssertIsOnIOThread();
2070 AUTO_PROFILER_LABEL("InitializePersistentStorageOp::DoDirectoryWork", OTHER
);
2072 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
2073 NS_ERROR_NOT_INITIALIZED
);
2075 QM_TRY(MOZ_TO_RESULT(
2076 aQuotaManager
.EnsurePersistentStorageIsInitializedInternal()));
2081 bool InitializePersistentStorageOp::UnwrapResolveValue() {
2082 AssertIsOnOwningThread();
2087 void InitializePersistentStorageOp::CloseDirectory() {
2088 AssertIsOnOwningThread();
2090 DropDirectoryLock(mDirectoryLock
);
2093 InitTemporaryStorageOp::InitTemporaryStorageOp(
2094 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2095 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2096 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
2097 "dom::quota::InitTemporaryStorageOp"),
2098 mDirectoryLock(std::move(aDirectoryLock
)) {
2099 AssertIsOnOwningThread();
2102 RefPtr
<BoolPromise
> InitTemporaryStorageOp::OpenDirectory() {
2103 AssertIsOnOwningThread();
2104 MOZ_ASSERT(mDirectoryLock
);
2106 return BoolPromise::CreateAndResolve(true, __func__
);
2109 nsresult
InitTemporaryStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2110 AssertIsOnIOThread();
2112 AUTO_PROFILER_LABEL("InitTemporaryStorageOp::DoDirectoryWork", OTHER
);
2114 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
2115 NS_ERROR_NOT_INITIALIZED
);
2117 const bool wasInitialized
=
2118 aQuotaManager
.IsTemporaryStorageInitializedInternal();
2120 if (!wasInitialized
) {
2121 QM_TRY(MOZ_TO_RESULT(
2122 aQuotaManager
.EnsureTemporaryStorageIsInitializedInternal()));
2124 mAllTemporaryGroups
= Some(aQuotaManager
.GetAllTemporaryGroups());
2130 MaybePrincipalMetadataArray
InitTemporaryStorageOp::UnwrapResolveValue() {
2131 AssertIsOnOwningThread();
2133 return std::move(mAllTemporaryGroups
);
2136 void InitTemporaryStorageOp::CloseDirectory() {
2137 AssertIsOnOwningThread();
2139 DropDirectoryLock(mDirectoryLock
);
2142 InitializeTemporaryGroupOp::InitializeTemporaryGroupOp(
2143 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2144 const PrincipalMetadata
& aPrincipalMetadata
,
2145 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2146 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
2147 "dom::quota::InitializeTemporaryGroupOp"),
2148 mPrincipalMetadata(aPrincipalMetadata
),
2149 mDirectoryLock(std::move(aDirectoryLock
)) {
2150 AssertIsOnOwningThread();
2153 RefPtr
<BoolPromise
> InitializeTemporaryGroupOp::OpenDirectory() {
2154 AssertIsOnOwningThread();
2155 MOZ_ASSERT(mDirectoryLock
);
2157 return BoolPromise::CreateAndResolve(true, __func__
);
2160 nsresult
InitializeTemporaryGroupOp::DoDirectoryWork(
2161 QuotaManager
& aQuotaManager
) {
2162 AssertIsOnIOThread();
2164 AUTO_PROFILER_LABEL("InitializeTemporaryGroupOp::DoDirectoryWork", OTHER
);
2166 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
2167 NS_ERROR_NOT_INITIALIZED
);
2169 QM_TRY(OkIf(aQuotaManager
.IsTemporaryStorageInitializedInternal()),
2170 NS_ERROR_NOT_INITIALIZED
);
2172 QM_TRY(aQuotaManager
.EnsureTemporaryGroupIsInitializedInternal(
2173 mPrincipalMetadata
));
2178 bool InitializeTemporaryGroupOp::UnwrapResolveValue() {
2179 AssertIsOnOwningThread();
2184 void InitializeTemporaryGroupOp::CloseDirectory() {
2185 AssertIsOnOwningThread();
2187 DropDirectoryLock(mDirectoryLock
);
2190 InitializeOriginRequestBase::InitializeOriginRequestBase(
2191 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
2192 const PrincipalMetadata
& aPrincipalMetadata
,
2193 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2194 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
2195 mPrincipalMetadata(aPrincipalMetadata
),
2196 mDirectoryLock(std::move(aDirectoryLock
)),
2198 AssertIsOnOwningThread();
2201 RefPtr
<BoolPromise
> InitializeOriginRequestBase::OpenDirectory() {
2202 AssertIsOnOwningThread();
2203 MOZ_ASSERT(mDirectoryLock
);
2205 return BoolPromise::CreateAndResolve(true, __func__
);
2208 void InitializeOriginRequestBase::CloseDirectory() {
2209 AssertIsOnOwningThread();
2211 DropDirectoryLockIfNotDropped(mDirectoryLock
);
2214 InitializePersistentOriginOp::InitializePersistentOriginOp(
2215 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2216 const OriginMetadata
& aOriginMetadata
,
2217 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2218 : InitializeOriginRequestBase(std::move(aQuotaManager
),
2219 "dom::quota::InitializePersistentOriginOp",
2220 aOriginMetadata
, std::move(aDirectoryLock
)) {
2221 AssertIsOnOwningThread();
2222 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
);
2225 nsresult
InitializePersistentOriginOp::DoDirectoryWork(
2226 QuotaManager
& aQuotaManager
) {
2227 AssertIsOnIOThread();
2229 AUTO_PROFILER_LABEL("InitializePersistentOriginOp::DoDirectoryWork", OTHER
);
2231 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
2232 NS_ERROR_NOT_INITIALIZED
);
2237 .EnsurePersistentOriginIsInitializedInternal(
2238 OriginMetadata
{mPrincipalMetadata
, PERSISTENCE_TYPE_PERSISTENT
})
2239 .map([](const auto& res
) { return res
.second
; })));
2244 bool InitializePersistentOriginOp::UnwrapResolveValue() {
2245 AssertIsOnOwningThread();
2250 InitializeTemporaryOriginOp::InitializeTemporaryOriginOp(
2251 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2252 const OriginMetadata
& aOriginMetadata
, bool aCreateIfNonExistent
,
2253 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
2254 : InitializeOriginRequestBase(std::move(aQuotaManager
),
2255 "dom::quota::InitializeTemporaryOriginOp",
2256 aOriginMetadata
, std::move(aDirectoryLock
)),
2257 mPersistenceType(aOriginMetadata
.mPersistenceType
),
2258 mCreateIfNonExistent(aCreateIfNonExistent
) {
2259 AssertIsOnOwningThread();
2260 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
);
2263 nsresult
InitializeTemporaryOriginOp::DoDirectoryWork(
2264 QuotaManager
& aQuotaManager
) {
2265 AssertIsOnIOThread();
2267 AUTO_PROFILER_LABEL("InitializeTemporaryOriginOp::DoDirectoryWork", OTHER
);
2269 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
2270 NS_ERROR_NOT_INITIALIZED
);
2272 QM_TRY(OkIf(aQuotaManager
.IsTemporaryStorageInitializedInternal()),
2273 NS_ERROR_NOT_INITIALIZED
);
2275 QM_TRY_UNWRAP(mCreated
,
2277 .EnsureTemporaryOriginIsInitializedInternal(
2278 OriginMetadata
{mPrincipalMetadata
, mPersistenceType
},
2279 mCreateIfNonExistent
)
2280 .map([](const auto& res
) { return res
.second
; })));
2285 bool InitializeTemporaryOriginOp::UnwrapResolveValue() {
2286 AssertIsOnOwningThread();
2291 InitializeClientBase::InitializeClientBase(
2292 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
2293 const PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
2294 Client::Type aClientType
)
2295 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
2296 mPrincipalInfo(aPrincipalInfo
),
2297 mPersistenceType(aPersistenceType
),
2298 mClientType(aClientType
),
2300 AssertIsOnOwningThread();
2303 nsresult
InitializeClientBase::DoInit(QuotaManager
& aQuotaManager
) {
2304 AssertIsOnOwningThread();
2307 PrincipalMetadata principalMetadata
,
2308 GetInfoFromValidatedPrincipalInfo(aQuotaManager
, mPrincipalInfo
));
2310 principalMetadata
.AssertInvariants();
2313 OriginMetadata
{std::move(principalMetadata
), mPersistenceType
},
2319 RefPtr
<BoolPromise
> InitializeClientBase::OpenDirectory() {
2320 AssertIsOnOwningThread();
2322 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
2323 PersistenceScope::CreateFromValue(mPersistenceType
),
2324 OriginScope::FromOrigin(mClientMetadata
),
2325 Nullable(mClientMetadata
.mClientType
), /* aExclusive */ false);
2327 return mDirectoryLock
->Acquire();
2330 void InitializeClientBase::CloseDirectory() {
2331 AssertIsOnOwningThread();
2333 DropDirectoryLockIfNotDropped(mDirectoryLock
);
2336 InitializePersistentClientOp::InitializePersistentClientOp(
2337 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2338 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
)
2339 : InitializeClientBase(
2340 std::move(aQuotaManager
), "dom::quota::InitializePersistentClientOp",
2341 PERSISTENCE_TYPE_PERSISTENT
, aPrincipalInfo
, aClientType
) {
2342 AssertIsOnOwningThread();
2345 nsresult
InitializePersistentClientOp::DoDirectoryWork(
2346 QuotaManager
& aQuotaManager
) {
2347 AssertIsOnIOThread();
2349 AUTO_PROFILER_LABEL("InitializePersistentClientOp::DoDirectoryWork", OTHER
);
2351 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsStorageInitializedInternal()),
2354 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsPersistentOriginInitializedInternal(
2355 mClientMetadata
.mOrigin
)),
2360 (aQuotaManager
.EnsurePersistentClientIsInitialized(mClientMetadata
)
2361 .map([](const auto& res
) { return res
.second
; })));
2366 bool InitializePersistentClientOp::UnwrapResolveValue() {
2367 AssertIsOnOwningThread();
2372 InitializeTemporaryClientOp::InitializeTemporaryClientOp(
2373 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2374 PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
2375 Client::Type aClientType
)
2376 : InitializeClientBase(std::move(aQuotaManager
),
2377 "dom::quota::InitializeTemporaryClientOp",
2378 aPersistenceType
, aPrincipalInfo
, aClientType
) {
2379 AssertIsOnOwningThread();
2382 nsresult
InitializeTemporaryClientOp::DoDirectoryWork(
2383 QuotaManager
& aQuotaManager
) {
2384 AssertIsOnIOThread();
2386 AUTO_PROFILER_LABEL("InitializeTemporaryClientOp::DoDirectoryWork", OTHER
);
2388 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsStorageInitializedInternal()),
2391 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsTemporaryStorageInitializedInternal()),
2394 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsTemporaryOriginInitializedInternal(
2400 (aQuotaManager
.EnsureTemporaryClientIsInitialized(mClientMetadata
)
2401 .map([](const auto& res
) { return res
.second
; })));
2406 bool InitializeTemporaryClientOp::UnwrapResolveValue() {
2407 AssertIsOnOwningThread();
2412 GetFullOriginMetadataOp::GetFullOriginMetadataOp(
2413 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2414 const GetFullOriginMetadataParams
& aParams
)
2415 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2416 "dom::quota::GetFullOriginMetadataOp"),
2418 AssertIsOnOwningThread();
2421 nsresult
GetFullOriginMetadataOp::DoInit(QuotaManager
& aQuotaManager
) {
2422 AssertIsOnOwningThread();
2424 QM_TRY_UNWRAP(PrincipalMetadata principalMetadata
,
2425 GetInfoFromValidatedPrincipalInfo(aQuotaManager
,
2426 mParams
.principalInfo()));
2428 principalMetadata
.AssertInvariants();
2430 mOriginMetadata
= {std::move(principalMetadata
), mParams
.persistenceType()};
2435 RefPtr
<BoolPromise
> GetFullOriginMetadataOp::OpenDirectory() {
2436 AssertIsOnOwningThread();
2438 return OpenStorageDirectory(
2439 PersistenceScope::CreateFromValue(mOriginMetadata
.mPersistenceType
),
2440 OriginScope::FromOrigin(mOriginMetadata
), Nullable
<Client::Type
>(),
2441 /* aExclusive */ false,
2442 /* aInitializeOrigins */ true);
2445 nsresult
GetFullOriginMetadataOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2446 AssertIsOnIOThread();
2447 aQuotaManager
.AssertStorageIsInitializedInternal();
2449 AUTO_PROFILER_LABEL("GetFullOriginMetadataOp::DoDirectoryWork", OTHER
);
2451 // Get metadata cached in memory (the method doesn't have to stat any
2453 mMaybeFullOriginMetadata
=
2454 aQuotaManager
.GetFullOriginMetadata(mOriginMetadata
);
2459 void GetFullOriginMetadataOp::GetResponse(RequestResponse
& aResponse
) {
2460 AssertIsOnOwningThread();
2462 aResponse
= GetFullOriginMetadataResponse();
2463 aResponse
.get_GetFullOriginMetadataResponse().maybeFullOriginMetadata() =
2464 std::move(mMaybeFullOriginMetadata
);
2467 void GetFullOriginMetadataOp::CloseDirectory() {
2468 AssertIsOnOwningThread();
2470 SafeDropDirectoryLock(mDirectoryLock
);
2473 GetCachedOriginUsageOp::GetCachedOriginUsageOp(
2474 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2475 const PrincipalInfo
& aPrincipalInfo
)
2476 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2477 "dom::quota::GetCachedOriginUsageOp"),
2478 mPrincipalInfo(aPrincipalInfo
),
2480 AssertIsOnOwningThread();
2483 nsresult
GetCachedOriginUsageOp::DoInit(QuotaManager
& aQuotaManager
) {
2484 AssertIsOnOwningThread();
2486 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
2487 aQuotaManager
, mPrincipalInfo
));
2489 mPrincipalMetadata
.AssertInvariants();
2494 RefPtr
<BoolPromise
> GetCachedOriginUsageOp::OpenDirectory() {
2495 AssertIsOnOwningThread();
2497 return OpenStorageDirectory(
2498 PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY
,
2499 PERSISTENCE_TYPE_DEFAULT
,
2500 PERSISTENCE_TYPE_PRIVATE
),
2501 OriginScope::FromOrigin(mPrincipalMetadata
), Nullable
<Client::Type
>(),
2502 /* aExclusive */ false);
2505 nsresult
GetCachedOriginUsageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2506 AssertIsOnIOThread();
2507 MOZ_ASSERT(mUsage
== 0);
2509 AUTO_PROFILER_LABEL("GetCachedOriginUsageOp::DoDirectoryWork", OTHER
);
2511 // If temporary storage hasn't been initialized yet, there's no cached usage
2513 if (!aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
2517 // Get cached usage (the method doesn't have to stat any files).
2518 mUsage
= aQuotaManager
.GetOriginUsage(mPrincipalMetadata
);
2523 uint64_t GetCachedOriginUsageOp::UnwrapResolveValue() {
2524 AssertIsOnOwningThread();
2529 void GetCachedOriginUsageOp::CloseDirectory() {
2530 AssertIsOnOwningThread();
2532 SafeDropDirectoryLock(mDirectoryLock
);
2535 ListCachedOriginsOp::ListCachedOriginsOp(
2536 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
2537 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2538 "dom::quota::ListCachedOriginsOp") {
2539 AssertIsOnOwningThread();
2542 RefPtr
<BoolPromise
> ListCachedOriginsOp::OpenDirectory() {
2543 AssertIsOnOwningThread();
2545 return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
2546 OriginScope::FromNull(), Nullable
<Client::Type
>(),
2547 /* aExclusive */ false);
2550 nsresult
ListCachedOriginsOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2551 AssertIsOnIOThread();
2552 MOZ_ASSERT(mOrigins
.Length() == 0);
2554 AUTO_PROFILER_LABEL("ListCachedOriginsOp::DoDirectoryWork", OTHER
);
2556 // If temporary storage hasn't been initialized yet, there are no cached
2557 // origins to report.
2558 if (!aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
2562 // Get cached origins (the method doesn't have to stat any files).
2563 OriginMetadataArray originMetadataArray
=
2564 aQuotaManager
.GetAllTemporaryOrigins();
2566 std::transform(originMetadataArray
.cbegin(), originMetadataArray
.cend(),
2567 MakeBackInserter(mOrigins
), [](const auto& originMetadata
) {
2568 return originMetadata
.mOrigin
;
2574 CStringArray
ListCachedOriginsOp::UnwrapResolveValue() {
2575 AssertIsOnOwningThread();
2576 MOZ_ASSERT(!ResolveValueConsumed());
2578 return std::move(mOrigins
);
2581 void ListCachedOriginsOp::CloseDirectory() {
2582 AssertIsOnOwningThread();
2584 SafeDropDirectoryLock(mDirectoryLock
);
2587 ClearStorageOp::ClearStorageOp(
2588 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
2589 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2590 "dom::quota::ClearStorageOp") {
2591 AssertIsOnOwningThread();
2594 void ClearStorageOp::DeleteFiles(QuotaManager
& aQuotaManager
) {
2595 AssertIsOnIOThread();
2597 nsresult rv
= aQuotaManager
.AboutToClearOrigins(
2598 PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
2599 Nullable
<Client::Type
>());
2600 if (NS_WARN_IF(NS_FAILED(rv
))) {
2604 auto directoryOrErr
= QM_NewLocalFile(aQuotaManager
.GetStoragePath());
2605 if (NS_WARN_IF(directoryOrErr
.isErr())) {
2609 nsCOMPtr
<nsIFile
> directory
= directoryOrErr
.unwrap();
2611 rv
= directory
->Remove(true);
2612 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
2613 // This should never fail if we've closed all storage connections
2615 MOZ_ASSERT(false, "Failed to remove storage directory!");
2619 void ClearStorageOp::DeleteStorageFile(QuotaManager
& aQuotaManager
) {
2620 AssertIsOnIOThread();
2622 QM_TRY_INSPECT(const auto& storageFile
,
2623 QM_NewLocalFile(aQuotaManager
.GetBasePath()), QM_VOID
);
2625 QM_TRY(MOZ_TO_RESULT(storageFile
->Append(aQuotaManager
.GetStorageName() +
2629 const nsresult rv
= storageFile
->Remove(true);
2630 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
2631 // This should never fail if we've closed the storage connection
2633 MOZ_ASSERT(false, "Failed to remove storage file!");
2637 RefPtr
<BoolPromise
> ClearStorageOp::OpenDirectory() {
2638 AssertIsOnOwningThread();
2640 // Clear directory lock tables (which also saves origin access time) before
2641 // acquiring the exclusive lock below. Otherwise, saving of origin access
2642 // time would be scheduled after storage clearing and that would initialize
2643 // storage again in the end.
2644 mQuotaManager
->ClearDirectoryLockTables();
2646 return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
2647 OriginScope::FromNull(), Nullable
<Client::Type
>(),
2648 /* aExclusive */ true,
2649 /* aInitializeOrigins */ false,
2650 DirectoryLockCategory::UninitStorage
);
2653 nsresult
ClearStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2654 AssertIsOnIOThread();
2655 aQuotaManager
.AssertStorageIsInitializedInternal();
2657 AUTO_PROFILER_LABEL("ClearStorageOp::DoDirectoryWork", OTHER
);
2659 DeleteFiles(aQuotaManager
);
2661 aQuotaManager
.RemoveQuota();
2663 aQuotaManager
.ShutdownStorageInternal();
2665 DeleteStorageFile(aQuotaManager
);
2670 bool ClearStorageOp::UnwrapResolveValue() {
2671 AssertIsOnOwningThread();
2676 void ClearStorageOp::CloseDirectory() {
2677 AssertIsOnOwningThread();
2679 SafeDropDirectoryLock(mDirectoryLock
);
2682 void ClearRequestBase::DeleteFiles(QuotaManager
& aQuotaManager
,
2683 const OriginMetadata
& aOriginMetadata
) {
2684 AssertIsOnIOThread();
2686 DeleteFilesInternal(
2687 aQuotaManager
, aOriginMetadata
.mPersistenceType
,
2688 OriginScope::FromOrigin(aOriginMetadata
),
2689 [&aQuotaManager
, &aOriginMetadata
](
2690 const std::function
<Result
<Ok
, nsresult
>(nsCOMPtr
<nsIFile
>)>& aBody
)
2691 -> Result
<Ok
, nsresult
> {
2692 QM_TRY_UNWRAP(auto directory
,
2693 aQuotaManager
.GetOriginDirectory(aOriginMetadata
));
2695 // We're not checking if the origin directory actualy exists because
2696 // it can be a pending origin (OriginInfo does exist but the origin
2697 // directory hasn't been created yet).
2699 QM_TRY_RETURN(aBody(std::move(directory
)));
2703 void ClearRequestBase::DeleteFiles(QuotaManager
& aQuotaManager
,
2704 PersistenceType aPersistenceType
,
2705 const OriginScope
& aOriginScope
) {
2706 AssertIsOnIOThread();
2708 DeleteFilesInternal(
2709 aQuotaManager
, aPersistenceType
, aOriginScope
,
2710 [&aQuotaManager
, &aPersistenceType
](
2711 const std::function
<Result
<Ok
, nsresult
>(nsCOMPtr
<nsIFile
>)>& aBody
)
2712 -> Result
<Ok
, nsresult
> {
2714 const auto& directory
,
2715 QM_NewLocalFile(aQuotaManager
.GetStoragePath(aPersistenceType
)));
2717 QM_TRY_INSPECT(const bool& exists
,
2718 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
2724 QM_TRY(CollectEachFile(*directory
, aBody
));
2726 // CollectEachFile above only consulted the file-system to get a list of
2727 // known origins, but we also need to include origins that have pending
2730 nsTArray
<OriginMetadata
> originMetadataArray
;
2731 aQuotaManager
.CollectPendingOriginsForListing(
2732 [aPersistenceType
, &originMetadataArray
](const auto& originInfo
) {
2733 if (originInfo
->GetGroupInfo()->GetPersistenceType() !=
2737 originMetadataArray
.AppendElement(
2738 originInfo
->FlattenToOriginMetadata());
2741 if (originMetadataArray
.IsEmpty()) {
2745 nsTArray
<nsCOMPtr
<nsIFile
>> originDirectories
;
2746 QM_TRY(TransformAbortOnErr(
2747 originMetadataArray
, MakeBackInserter(originDirectories
),
2748 [&aQuotaManager
](const auto& originMetadata
)
2749 -> Result
<nsCOMPtr
<nsIFile
>, nsresult
> {
2750 QM_TRY_UNWRAP(auto originDirectory
,
2751 aQuotaManager
.GetOriginDirectory(originMetadata
));
2752 return originDirectory
;
2755 QM_TRY_RETURN(CollectEachInRange(originDirectories
, aBody
));
2759 template <typename FileCollector
>
2760 void ClearRequestBase::DeleteFilesInternal(
2761 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
2762 const OriginScope
& aOriginScope
, const FileCollector
& aFileCollector
) {
2763 AssertIsOnIOThread();
2765 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.AboutToClearOrigins(
2766 PersistenceScope::CreateFromValue(aPersistenceType
), aOriginScope
,
2767 Nullable
<Client::Type
>())),
2770 nsTArray
<nsCOMPtr
<nsIFile
>> directoriesForRemovalRetry
;
2772 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
2773 "ClearRequestBase: Starting deleting files"_ns
);
2776 aFileCollector([&originScope
= aOriginScope
, aPersistenceType
,
2777 &aQuotaManager
, &directoriesForRemovalRetry
,
2778 this](nsCOMPtr
<nsIFile
> file
)
2779 -> mozilla::Result
<Ok
, nsresult
> {
2780 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*file
));
2783 const auto& leafName
,
2784 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, file
, GetLeafName
));
2786 switch (dirEntryKind
) {
2787 case nsIFileKind::ExistsAsDirectory
: {
2788 QM_TRY_UNWRAP(auto maybeMetadata
,
2791 aQuotaManager
.GetOriginMetadata(file
).map(
2792 [](auto metadata
) -> Maybe
<OriginMetadata
> {
2793 return Some(std::move(metadata
));
2796 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
2798 ErrToDefaultOk
<Maybe
<OriginMetadata
>>));
2800 if (!maybeMetadata
) {
2801 // Unknown directories during clearing are allowed. Just
2802 // warn if we find them.
2803 UNKNOWN_FILE_WARNING(leafName
);
2807 auto metadata
= maybeMetadata
.extract();
2809 MOZ_ASSERT(metadata
.mPersistenceType
== aPersistenceType
);
2811 // Skip the origin directory if it doesn't match the pattern.
2812 if (!originScope
.Matches(OriginScope::FromOrigin(metadata
))) {
2816 // We can't guarantee that this will always succeed on
2819 aQuotaManager
.RemoveOriginDirectory(*file
), [&](const auto&) {
2820 directoriesForRemovalRetry
.AppendElement(std::move(file
));
2823 mOriginMetadataArray
.AppendElement(metadata
);
2825 const bool initialized
=
2826 aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
2827 ? aQuotaManager
.IsPersistentOriginInitializedInternal(
2829 : aQuotaManager
.IsTemporaryStorageInitializedInternal();
2831 // If it hasn't been initialized, we don't need to update the
2832 // quota and notify the removing client, but we do need to remove
2833 // it from quota info cache.
2835 aQuotaManager
.RemoveOriginFromCache(metadata
);
2839 if (aPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
) {
2840 aQuotaManager
.RemoveQuotaForOrigin(aPersistenceType
, metadata
);
2843 aQuotaManager
.OriginClearCompleted(metadata
,
2844 Nullable
<Client::Type
>());
2849 case nsIFileKind::ExistsAsFile
: {
2850 // Unknown files during clearing are allowed. Just warn if we
2852 if (!IsOSMetadata(leafName
)) {
2853 UNKNOWN_FILE_WARNING(leafName
);
2859 case nsIFileKind::DoesNotExist
: {
2860 if (aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
) {
2864 QM_TRY_UNWRAP(auto metadata
, aQuotaManager
.GetOriginMetadata(file
));
2866 MOZ_ASSERT(metadata
.mPersistenceType
== aPersistenceType
);
2868 // Skip the origin directory if it doesn't match the pattern.
2869 if (!originScope
.Matches(OriginScope::FromOrigin(metadata
))) {
2873 if (!aQuotaManager
.IsPendingOrigin(metadata
)) {
2877 mOriginMetadataArray
.AppendElement(metadata
);
2879 aQuotaManager
.RemoveQuotaForOrigin(aPersistenceType
, metadata
);
2881 aQuotaManager
.OriginClearCompleted(metadata
,
2882 Nullable
<Client::Type
>());
2889 aQuotaManager
.IncreaseTotalDirectoryIterations();
2895 // Retry removing any directories that failed to be removed earlier now.
2897 // XXX This will still block this operation. We might instead dispatch a
2898 // runnable to our own thread for each retry round with a timer. We must
2899 // ensure that the directory lock is upheld until we complete or give up
2901 for (uint32_t index
= 0; index
< 10; index
++) {
2902 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2903 return nsPrintfCString(
2904 "ClearRequestBase: Starting repeated directory removal #%d", index
);
2907 for (auto&& file
: std::exchange(directoriesForRemovalRetry
,
2908 nsTArray
<nsCOMPtr
<nsIFile
>>{})) {
2910 aQuotaManager
.RemoveOriginDirectory(*file
),
2911 ([&directoriesForRemovalRetry
, &file
](const auto&) {
2912 directoriesForRemovalRetry
.AppendElement(std::move(file
));
2916 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2917 return nsPrintfCString(
2918 "ClearRequestBase: Completed repeated directory removal #%d", index
);
2921 if (directoriesForRemovalRetry
.IsEmpty()) {
2925 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2926 return nsPrintfCString("ClearRequestBase: Before sleep #%d", index
);
2929 PR_Sleep(PR_MillisecondsToInterval(200));
2931 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2932 return nsPrintfCString("ClearRequestBase: After sleep #%d", index
);
2936 QM_WARNONLY_TRY(OkIf(directoriesForRemovalRetry
.IsEmpty()));
2938 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
2939 "ClearRequestBase: Completed deleting files"_ns
);
2942 ClearOriginOp::ClearOriginOp(
2943 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2944 const mozilla::Maybe
<PersistenceType
>& aPersistenceType
,
2945 const PrincipalInfo
& aPrincipalInfo
)
2946 : ClearRequestBase(std::move(aQuotaManager
), "dom::quota::ClearOriginOp"),
2947 mPrincipalInfo(aPrincipalInfo
),
2948 mPersistenceScope(aPersistenceType
? PersistenceScope::CreateFromValue(
2950 : PersistenceScope::CreateFromNull()) {
2951 AssertIsOnOwningThread();
2954 nsresult
ClearOriginOp::DoInit(QuotaManager
& aQuotaManager
) {
2955 AssertIsOnOwningThread();
2957 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
2958 aQuotaManager
, mPrincipalInfo
));
2960 mPrincipalMetadata
.AssertInvariants();
2965 RefPtr
<BoolPromise
> ClearOriginOp::OpenDirectory() {
2966 AssertIsOnOwningThread();
2968 return OpenStorageDirectory(
2969 mPersistenceScope
, OriginScope::FromOrigin(mPrincipalMetadata
),
2970 Nullable
<Client::Type
>(), /* aExclusive */ true,
2971 /* aInitializeOrigins */ false, DirectoryLockCategory::UninitOrigins
);
2974 nsresult
ClearOriginOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2975 AssertIsOnIOThread();
2976 aQuotaManager
.AssertStorageIsInitializedInternal();
2978 AUTO_PROFILER_LABEL("ClearRequestBase::DoDirectoryWork", OTHER
);
2980 if (mPersistenceScope
.IsNull()) {
2981 for (const PersistenceType type
: kAllPersistenceTypes
) {
2982 DeleteFiles(aQuotaManager
, OriginMetadata(mPrincipalMetadata
, type
));
2985 MOZ_ASSERT(mPersistenceScope
.IsValue());
2987 DeleteFiles(aQuotaManager
, OriginMetadata(mPrincipalMetadata
,
2988 mPersistenceScope
.GetValue()));
2994 OriginMetadataArray
ClearOriginOp::UnwrapResolveValue() {
2995 AssertIsOnOwningThread();
2997 return std::move(mOriginMetadataArray
);
3000 void ClearOriginOp::CloseDirectory() {
3001 AssertIsOnOwningThread();
3003 SafeDropDirectoryLock(mDirectoryLock
);
3006 ClearClientOp::ClearClientOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3007 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
3008 const PrincipalInfo
& aPrincipalInfo
,
3009 Client::Type aClientType
)
3010 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
3011 "dom::quota::ClearClientOp"),
3012 mPrincipalInfo(aPrincipalInfo
),
3013 mPersistenceScope(aPersistenceType
? PersistenceScope::CreateFromValue(
3015 : PersistenceScope::CreateFromNull()),
3016 mClientType(aClientType
) {
3017 AssertIsOnOwningThread();
3020 nsresult
ClearClientOp::DoInit(QuotaManager
& aQuotaManager
) {
3021 AssertIsOnOwningThread();
3023 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
3024 aQuotaManager
, mPrincipalInfo
));
3026 mPrincipalMetadata
.AssertInvariants();
3031 RefPtr
<BoolPromise
> ClearClientOp::OpenDirectory() {
3032 AssertIsOnOwningThread();
3034 return OpenStorageDirectory(mPersistenceScope
,
3035 OriginScope::FromOrigin(mPrincipalMetadata
),
3036 Nullable(mClientType
), /* aExclusive */ true);
3039 void ClearClientOp::DeleteFiles(const ClientMetadata
& aClientMetadata
) {
3040 AssertIsOnIOThread();
3043 MOZ_TO_RESULT(mQuotaManager
->AboutToClearOrigins(
3044 PersistenceScope::CreateFromValue(aClientMetadata
.mPersistenceType
),
3045 OriginScope::FromOrigin(aClientMetadata
),
3046 Nullable(aClientMetadata
.mClientType
))),
3049 QM_TRY_INSPECT(const auto& directory
,
3050 mQuotaManager
->GetOriginDirectory(aClientMetadata
), QM_VOID
);
3052 QM_TRY(MOZ_TO_RESULT(directory
->Append(
3053 Client::TypeToString(aClientMetadata
.mClientType
))),
3056 QM_TRY_INSPECT(const bool& exists
,
3057 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
), QM_VOID
);
3062 QM_TRY(MOZ_TO_RESULT(directory
->Remove(true)), QM_VOID
);
3064 const bool initialized
=
3065 aClientMetadata
.mPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
3066 ? mQuotaManager
->IsPersistentOriginInitializedInternal(
3067 aClientMetadata
.mOrigin
)
3068 : mQuotaManager
->IsTemporaryStorageInitializedInternal();
3074 if (aClientMetadata
.mPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
) {
3075 mQuotaManager
->ResetUsageForClient(aClientMetadata
);
3078 mQuotaManager
->OriginClearCompleted(aClientMetadata
,
3079 Nullable(aClientMetadata
.mClientType
));
3082 nsresult
ClearClientOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3083 AssertIsOnIOThread();
3084 aQuotaManager
.AssertStorageIsInitializedInternal();
3086 AUTO_PROFILER_LABEL("ClearClientOp::DoDirectoryWork", OTHER
);
3088 if (mPersistenceScope
.IsNull()) {
3089 for (const PersistenceType type
: kAllPersistenceTypes
) {
3090 DeleteFiles(ClientMetadata(OriginMetadata(mPrincipalMetadata
, type
),
3094 MOZ_ASSERT(mPersistenceScope
.IsValue());
3096 DeleteFiles(ClientMetadata(
3097 OriginMetadata(mPrincipalMetadata
, mPersistenceScope
.GetValue()),
3104 bool ClearClientOp::UnwrapResolveValue() {
3105 AssertIsOnOwningThread();
3110 void ClearClientOp::CloseDirectory() {
3111 AssertIsOnOwningThread();
3113 SafeDropDirectoryLock(mDirectoryLock
);
3116 ClearStoragesForOriginPrefixOp::ClearStoragesForOriginPrefixOp(
3117 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3118 const Maybe
<PersistenceType
>& aPersistenceType
,
3119 const PrincipalInfo
& aPrincipalInfo
)
3120 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
3121 "dom::quota::ClearStoragesForOriginPrefixOp"),
3122 mPrincipalInfo(aPrincipalInfo
),
3123 mPersistenceScope(aPersistenceType
? PersistenceScope::CreateFromValue(
3125 : PersistenceScope::CreateFromNull()) {
3126 AssertIsOnOwningThread();
3129 nsresult
ClearStoragesForOriginPrefixOp::DoInit(QuotaManager
& aQuotaManager
) {
3130 AssertIsOnOwningThread();
3132 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
3133 aQuotaManager
, mPrincipalInfo
));
3135 mPrincipalMetadata
.AssertInvariants();
3140 RefPtr
<BoolPromise
> ClearStoragesForOriginPrefixOp::OpenDirectory() {
3141 AssertIsOnOwningThread();
3143 return OpenStorageDirectory(
3144 mPersistenceScope
, OriginScope::FromPrefix(mPrincipalMetadata
),
3145 Nullable
<Client::Type
>(), /* aExclusive */ true,
3146 /* aInitializeOrigins */ false, DirectoryLockCategory::UninitOrigins
);
3149 nsresult
ClearStoragesForOriginPrefixOp::DoDirectoryWork(
3150 QuotaManager
& aQuotaManager
) {
3151 AssertIsOnIOThread();
3153 AUTO_PROFILER_LABEL("ClearStoragesForOriginPrefixOp::DoDirectoryWork", OTHER
);
3155 if (mPersistenceScope
.IsNull()) {
3156 for (const PersistenceType type
: kAllPersistenceTypes
) {
3157 DeleteFiles(aQuotaManager
, type
,
3158 OriginScope::FromPrefix(mPrincipalMetadata
));
3161 MOZ_ASSERT(mPersistenceScope
.IsValue());
3163 DeleteFiles(aQuotaManager
, mPersistenceScope
.GetValue(),
3164 OriginScope::FromPrefix(mPrincipalMetadata
));
3170 OriginMetadataArray
ClearStoragesForOriginPrefixOp::UnwrapResolveValue() {
3171 AssertIsOnOwningThread();
3173 return std::move(mOriginMetadataArray
);
3176 void ClearStoragesForOriginPrefixOp::CloseDirectory() {
3177 AssertIsOnOwningThread();
3179 SafeDropDirectoryLock(mDirectoryLock
);
3182 ClearDataOp::ClearDataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3183 const OriginAttributesPattern
& aPattern
)
3184 : ClearRequestBase(std::move(aQuotaManager
), "dom::quota::ClearDataOp"),
3185 mPattern(aPattern
) {}
3187 RefPtr
<BoolPromise
> ClearDataOp::OpenDirectory() {
3188 AssertIsOnOwningThread();
3190 return OpenStorageDirectory(
3191 PersistenceScope::CreateFromNull(), OriginScope::FromPattern(mPattern
),
3192 Nullable
<Client::Type
>(), /* aExclusive */ true,
3193 /* aInitializeOrigins */ false, DirectoryLockCategory::UninitOrigins
);
3196 nsresult
ClearDataOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3197 AssertIsOnIOThread();
3199 AUTO_PROFILER_LABEL("ClearRequestBase::DoDirectoryWork", OTHER
);
3201 // Optimize clearing of thumbnail private identity temporary origins by
3202 // skipping potentially expensive temporary repository traversals when there
3203 // are no thumbnail private identity temporary origins (this is especially
3204 // important during shutdown).
3206 // XXX Can we do the skipping also when temporary storage is not initialized
3207 // (no new thumbnail private identity temporary origins could be created yet)?
3208 if (aQuotaManager
.IsThumbnailPrivateIdentityIdKnown() &&
3209 IsUserContextPattern(mPattern
,
3210 aQuotaManager
.GetThumbnailPrivateIdentityId()) &&
3211 aQuotaManager
.IsTemporaryStorageInitializedInternal() &&
3212 aQuotaManager
.ThumbnailPrivateIdentityTemporaryOriginCount() == 0) {
3213 DeleteFiles(aQuotaManager
, PERSISTENCE_TYPE_PERSISTENT
,
3214 OriginScope::FromPattern(mPattern
));
3219 for (const PersistenceType type
: kAllPersistenceTypes
) {
3220 DeleteFiles(aQuotaManager
, type
, OriginScope::FromPattern(mPattern
));
3226 OriginMetadataArray
ClearDataOp::UnwrapResolveValue() {
3227 AssertIsOnOwningThread();
3229 return std::move(mOriginMetadataArray
);
3232 void ClearDataOp::CloseDirectory() {
3233 AssertIsOnOwningThread();
3235 SafeDropDirectoryLock(mDirectoryLock
);
3238 ShutdownOriginOp::ShutdownOriginOp(
3239 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3240 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
3241 const PrincipalInfo
& aPrincipalInfo
)
3242 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
3243 "dom::quota::ShutdownOriginOp"),
3244 mPrincipalInfo(aPrincipalInfo
),
3245 mPersistenceScope(aPersistenceType
? PersistenceScope::CreateFromValue(
3247 : PersistenceScope::CreateFromNull()) {
3248 AssertIsOnOwningThread();
3251 nsresult
ShutdownOriginOp::DoInit(QuotaManager
& aQuotaManager
) {
3252 AssertIsOnOwningThread();
3254 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
3255 aQuotaManager
, mPrincipalInfo
));
3257 mPrincipalMetadata
.AssertInvariants();
3262 RefPtr
<BoolPromise
> ShutdownOriginOp::OpenDirectory() {
3263 AssertIsOnOwningThread();
3265 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
3266 mPersistenceScope
, OriginScope::FromOrigin(mPrincipalMetadata
),
3267 Nullable
<Client::Type
>(), /* aExclusive */ true,
3268 DirectoryLockCategory::UninitOrigins
);
3270 return mDirectoryLock
->Acquire();
3273 void ShutdownOriginOp::CollectOriginMetadata(
3274 const OriginMetadata
& aOriginMetadata
) {
3275 AssertIsOnIOThread();
3277 QM_TRY_INSPECT(const auto& directory
,
3278 mQuotaManager
->GetOriginDirectory(aOriginMetadata
), QM_VOID
);
3280 QM_TRY_INSPECT(const bool& exists
,
3281 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
), QM_VOID
);
3283 if (aOriginMetadata
.mPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
&&
3284 mQuotaManager
->IsPendingOrigin(aOriginMetadata
)) {
3285 mOriginMetadataArray
.AppendElement(aOriginMetadata
);
3291 mOriginMetadataArray
.AppendElement(aOriginMetadata
);
3294 nsresult
ShutdownOriginOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3295 AssertIsOnIOThread();
3297 AUTO_PROFILER_LABEL("ShutdownOriginOp::DoDirectoryWork", OTHER
);
3299 if (mPersistenceScope
.IsNull()) {
3300 for (const PersistenceType type
: kAllPersistenceTypes
) {
3301 CollectOriginMetadata(OriginMetadata(mPrincipalMetadata
, type
));
3304 MOZ_ASSERT(mPersistenceScope
.IsValue());
3306 CollectOriginMetadata(
3307 OriginMetadata(mPrincipalMetadata
, mPersistenceScope
.GetValue()));
3313 OriginMetadataArray
ShutdownOriginOp::UnwrapResolveValue() {
3314 AssertIsOnOwningThread();
3316 return std::move(mOriginMetadataArray
);
3319 void ShutdownOriginOp::CloseDirectory() {
3320 AssertIsOnOwningThread();
3322 DropDirectoryLockIfNotDropped(mDirectoryLock
);
3325 ShutdownClientOp::ShutdownClientOp(
3326 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3327 mozilla::Maybe
<PersistenceType
> aPersistenceType
,
3328 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
)
3329 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
3330 "dom::quota::ShutdownClientOp"),
3331 mPrincipalInfo(aPrincipalInfo
),
3332 mPersistenceScope(aPersistenceType
? PersistenceScope::CreateFromValue(
3334 : PersistenceScope::CreateFromNull()),
3335 mClientType(aClientType
) {
3336 AssertIsOnOwningThread();
3339 nsresult
ShutdownClientOp::DoInit(QuotaManager
& aQuotaManager
) {
3340 AssertIsOnOwningThread();
3342 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
3343 aQuotaManager
, mPrincipalInfo
));
3345 mPrincipalMetadata
.AssertInvariants();
3350 RefPtr
<BoolPromise
> ShutdownClientOp::OpenDirectory() {
3351 AssertIsOnOwningThread();
3353 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
3354 mPersistenceScope
, OriginScope::FromOrigin(mPrincipalMetadata
),
3355 Nullable(mClientType
), /* aExclusive */ true);
3357 return mDirectoryLock
->Acquire();
3360 nsresult
ShutdownClientOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3361 AssertIsOnIOThread();
3363 AUTO_PROFILER_LABEL("ShutdownClientOp::DoDirectoryWork", OTHER
);
3365 // All the work is handled by NormalOriginOperationBase parent class. In
3366 // this particular case, we just needed to acquire an exclusive directory
3367 // lock and that's it.
3372 bool ShutdownClientOp::UnwrapResolveValue() {
3373 AssertIsOnOwningThread();
3378 void ShutdownClientOp::CloseDirectory() {
3379 AssertIsOnOwningThread();
3381 DropDirectoryLockIfNotDropped(mDirectoryLock
);
3384 PersistRequestBase::PersistRequestBase(
3385 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3386 const PrincipalInfo
& aPrincipalInfo
)
3387 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
3388 "dom::quota::PersistRequestBase"),
3389 mPrincipalInfo(aPrincipalInfo
) {
3390 AssertIsOnOwningThread();
3393 nsresult
PersistRequestBase::DoInit(QuotaManager
& aQuotaManager
) {
3394 AssertIsOnOwningThread();
3396 // Figure out which origin we're dealing with.
3397 QM_TRY_UNWRAP(mPrincipalMetadata
, GetInfoFromValidatedPrincipalInfo(
3398 aQuotaManager
, mPrincipalInfo
));
3400 mPrincipalMetadata
.AssertInvariants();
3405 RefPtr
<BoolPromise
> PersistRequestBase::OpenDirectory() {
3406 AssertIsOnOwningThread();
3408 return OpenStorageDirectory(
3409 PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_DEFAULT
),
3410 OriginScope::FromOrigin(mPrincipalMetadata
), Nullable
<Client::Type
>(),
3411 /* aExclusive */ false);
3414 void PersistRequestBase::CloseDirectory() {
3415 AssertIsOnOwningThread();
3417 SafeDropDirectoryLock(mDirectoryLock
);
3420 PersistedOp::PersistedOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3421 const RequestParams
& aParams
)
3422 : PersistRequestBase(std::move(aQuotaManager
),
3423 aParams
.get_PersistedParams().principalInfo()),
3425 MOZ_ASSERT(aParams
.type() == RequestParams::TPersistedParams
);
3428 nsresult
PersistedOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3429 AssertIsOnIOThread();
3430 aQuotaManager
.AssertStorageIsInitializedInternal();
3432 AUTO_PROFILER_LABEL("PersistedOp::DoDirectoryWork", OTHER
);
3434 const OriginMetadata originMetadata
= {mPrincipalMetadata
,
3435 PERSISTENCE_TYPE_DEFAULT
};
3437 Nullable
<bool> persisted
= aQuotaManager
.OriginPersisted(originMetadata
);
3439 if (!persisted
.IsNull()) {
3440 mPersisted
= persisted
.Value();
3444 // If we get here, it means the origin hasn't been initialized yet.
3445 // Try to get the persisted flag from directory metadata on disk.
3447 QM_TRY_INSPECT(const auto& directory
,
3448 aQuotaManager
.GetOriginDirectory(originMetadata
));
3450 QM_TRY_INSPECT(const bool& exists
,
3451 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
3454 // Get the metadata. We only use the persisted flag.
3455 QM_TRY_INSPECT(const auto& metadata
,
3456 aQuotaManager
.LoadFullOriginMetadataWithRestore(directory
));
3458 mPersisted
= metadata
.mPersisted
;
3460 // The directory has not been created yet.
3467 void PersistedOp::GetResponse(RequestResponse
& aResponse
) {
3468 AssertIsOnOwningThread();
3470 PersistedResponse persistedResponse
;
3471 persistedResponse
.persisted() = mPersisted
;
3473 aResponse
= persistedResponse
;
3476 PersistOp::PersistOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3477 const RequestParams
& aParams
)
3478 : PersistRequestBase(std::move(aQuotaManager
),
3479 aParams
.get_PersistParams().principalInfo()) {
3480 MOZ_ASSERT(aParams
.type() == RequestParams::TPersistParams
);
3483 nsresult
PersistOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3484 AssertIsOnIOThread();
3485 aQuotaManager
.AssertStorageIsInitializedInternal();
3487 const OriginMetadata originMetadata
= {mPrincipalMetadata
,
3488 PERSISTENCE_TYPE_DEFAULT
};
3490 AUTO_PROFILER_LABEL("PersistOp::DoDirectoryWork", OTHER
);
3492 // Update directory metadata on disk first. Then, create/update the
3493 // originInfo if needed.
3495 QM_TRY_INSPECT(const auto& directory
,
3496 aQuotaManager
.GetOriginDirectory(originMetadata
));
3498 QM_TRY_INSPECT(const bool& created
,
3499 aQuotaManager
.EnsureOriginDirectory(*directory
));
3502 // A new origin directory has been created.
3504 // XXX The code below could be converted to a function which returns the
3508 // Update OriginInfo too if temporary origin was already initialized.
3509 if (aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
3510 if (aQuotaManager
.IsTemporaryOriginInitializedInternal(originMetadata
)) {
3511 // We have a temporary origin which has been initialized without
3512 // ensuring respective origin directory. So OriginInfo already exists
3513 // and it needs to be updated because the origin directory has been
3516 timestamp
= aQuotaManager
.WithOriginInfo(
3517 originMetadata
, [](const auto& originInfo
) {
3518 const int64_t timestamp
= originInfo
->LockedAccessTime();
3520 originInfo
->LockedDirectoryCreated();
3525 timestamp
= PR_Now();
3528 FullOriginMetadata fullOriginMetadata
=
3529 FullOriginMetadata
{originMetadata
, /* aPersisted */ true, timestamp
};
3531 // Usually, infallible operations are placed after fallible ones.
3532 // However, since we lack atomic support for creating the origin
3533 // directory along with its metadata, we need to add the origin to cached
3534 // origins right after directory creation.
3535 aQuotaManager
.AddTemporaryOrigin(fullOriginMetadata
);
3537 timestamp
= PR_Now();
3540 QM_TRY(MOZ_TO_RESULT(QuotaManager::CreateDirectoryMetadata2(
3541 *directory
, timestamp
, /* aPersisted */ true, originMetadata
)));
3543 // Update or create OriginInfo too if temporary storage was already
3545 if (aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
3546 if (aQuotaManager
.IsTemporaryOriginInitializedInternal(originMetadata
)) {
3547 // In this case, we have a temporary origin which has been initialized
3548 // without ensuring respective origin directory. So OriginInfo already
3549 // exists and it needs to be updated because the origin directory has
3550 // been just created.
3552 aQuotaManager
.PersistOrigin(originMetadata
);
3554 // In this case, we have a temporary origin which hasn't been
3555 // initialized yet. So OriginInfo needs to be created because the
3556 // origin directory has been just created.
3558 FullOriginMetadata fullOriginMetadata
= FullOriginMetadata
{
3559 originMetadata
, /* aPersisted */ true, timestamp
};
3561 aQuotaManager
.InitQuotaForOrigin(fullOriginMetadata
, ClientUsageArray(),
3562 /* aUsageBytes */ 0);
3567 const bool& persisted
,
3568 ([&aQuotaManager
, &originMetadata
,
3569 &directory
]() -> mozilla::Result
<bool, nsresult
> {
3570 Nullable
<bool> persisted
=
3571 aQuotaManager
.OriginPersisted(originMetadata
);
3573 if (!persisted
.IsNull()) {
3574 return persisted
.Value();
3577 // Get the metadata (restore the metadata file if necessary). We only
3578 // use the persisted flag.
3580 const auto& metadata
,
3581 aQuotaManager
.LoadFullOriginMetadataWithRestore(directory
));
3583 return metadata
.mPersisted
;
3587 QM_TRY_INSPECT(const auto& file
,
3589 *directory
, nsLiteralString(METADATA_V2_FILE_NAME
)));
3591 QM_TRY_INSPECT(const auto& stream
,
3592 GetBinaryOutputStream(*file
, FileFlag::Update
));
3596 // Update origin access time while we are here.
3597 QM_TRY(MOZ_TO_RESULT(stream
->Write64(PR_Now())));
3599 // Set the persisted flag to true.
3600 QM_TRY(MOZ_TO_RESULT(stream
->WriteBoolean(true)));
3602 QM_TRY(MOZ_TO_RESULT(stream
->Close()));
3604 // Directory metadata has been successfully updated.
3605 // Update OriginInfo too if temporary storage was already initialized.
3606 if (aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
3607 aQuotaManager
.PersistOrigin(originMetadata
);
3615 void PersistOp::GetResponse(RequestResponse
& aResponse
) {
3616 AssertIsOnOwningThread();
3618 aResponse
= PersistResponse();
3621 EstimateOp::EstimateOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
3622 const EstimateParams
& aParams
)
3623 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
3624 "dom::quota::EstimateOp"),
3626 AssertIsOnOwningThread();
3629 nsresult
EstimateOp::DoInit(QuotaManager
& aQuotaManager
) {
3630 AssertIsOnOwningThread();
3632 QM_TRY_UNWRAP(PrincipalMetadata principalMetadata
,
3633 GetInfoFromValidatedPrincipalInfo(aQuotaManager
,
3634 mParams
.principalInfo()));
3636 principalMetadata
.AssertInvariants();
3638 mOriginMetadata
= {std::move(principalMetadata
), PERSISTENCE_TYPE_DEFAULT
};
3643 RefPtr
<BoolPromise
> EstimateOp::OpenDirectory() {
3644 AssertIsOnOwningThread();
3646 return OpenStorageDirectory(
3647 PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY
,
3648 PERSISTENCE_TYPE_DEFAULT
,
3649 PERSISTENCE_TYPE_PRIVATE
),
3650 OriginScope::FromGroup(mOriginMetadata
.mGroup
), Nullable
<Client::Type
>(),
3651 /* aExclusive */ false,
3652 /* aInitializeOrigins */ true);
3655 nsresult
EstimateOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3656 AssertIsOnIOThread();
3657 aQuotaManager
.AssertStorageIsInitializedInternal();
3659 AUTO_PROFILER_LABEL("EstimateOp::DoDirectoryWork", OTHER
);
3661 // Get cached usage (the method doesn't have to stat any files).
3662 mUsageAndLimit
= aQuotaManager
.GetUsageAndLimitForEstimate(mOriginMetadata
);
3667 void EstimateOp::GetResponse(RequestResponse
& aResponse
) {
3668 AssertIsOnOwningThread();
3670 EstimateResponse estimateResponse
;
3672 estimateResponse
.usage() = mUsageAndLimit
.first
;
3673 estimateResponse
.limit() = mUsageAndLimit
.second
;
3675 aResponse
= estimateResponse
;
3678 void EstimateOp::CloseDirectory() {
3679 AssertIsOnOwningThread();
3681 SafeDropDirectoryLock(mDirectoryLock
);
3684 ListOriginsOp::ListOriginsOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
3685 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
3686 "dom::quota::ListOriginsOp") {
3687 AssertIsOnOwningThread();
3690 RefPtr
<BoolPromise
> ListOriginsOp::OpenDirectory() {
3691 AssertIsOnOwningThread();
3693 return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
3694 OriginScope::FromNull(), Nullable
<Client::Type
>(),
3695 /* aExclusive */ false);
3698 nsresult
ListOriginsOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
3699 AssertIsOnIOThread();
3700 aQuotaManager
.AssertStorageIsInitializedInternal();
3702 AUTO_PROFILER_LABEL("ListOriginsOp::DoDirectoryWork", OTHER
);
3704 for (const PersistenceType type
: kAllPersistenceTypes
) {
3705 QM_TRY(MOZ_TO_RESULT(TraverseRepository(aQuotaManager
, type
)));
3708 // TraverseRepository above only consulted the file-system to get a list of
3709 // known origins, but we also need to include origins that have pending
3712 aQuotaManager
.CollectPendingOriginsForListing([this](const auto& originInfo
) {
3713 mOrigins
.AppendElement(originInfo
->Origin());
3719 const Atomic
<bool>& ListOriginsOp::GetIsCanceledFlag() {
3720 AssertIsOnIOThread();
3725 nsresult
ListOriginsOp::ProcessOrigin(QuotaManager
& aQuotaManager
,
3726 nsIFile
& aOriginDir
,
3727 const bool aPersistent
,
3728 const PersistenceType aPersistenceType
) {
3729 AssertIsOnIOThread();
3731 QM_TRY_UNWRAP(auto maybeMetadata
,
3734 aQuotaManager
.GetOriginMetadata(&aOriginDir
)
3735 .map([](auto metadata
) -> Maybe
<OriginMetadata
> {
3736 return Some(std::move(metadata
));
3739 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
3741 ErrToDefaultOk
<Maybe
<OriginMetadata
>>));
3743 if (!maybeMetadata
) {
3744 // Unknown directories during listing are allowed. Just warn if we find
3746 QM_TRY_INSPECT(const auto& leafName
,
3747 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, aOriginDir
,
3750 UNKNOWN_FILE_WARNING(leafName
);
3754 auto metadata
= maybeMetadata
.extract();
3756 if (aQuotaManager
.IsOriginInternal(metadata
.mOrigin
)) {
3760 mOrigins
.AppendElement(std::move(metadata
.mOrigin
));
3765 CStringArray
ListOriginsOp::UnwrapResolveValue() {
3766 AssertIsOnOwningThread();
3767 MOZ_ASSERT(!ResolveValueConsumed());
3769 return std::move(mOrigins
);
3772 void ListOriginsOp::CloseDirectory() {
3773 AssertIsOnOwningThread();
3775 SafeDropDirectoryLock(mDirectoryLock
);
3778 } // namespace mozilla::dom::quota