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/PersistenceType.h"
31 #include "mozilla/dom/quota/PQuota.h"
32 #include "mozilla/dom/quota/PQuotaRequest.h"
33 #include "mozilla/dom/quota/PQuotaUsageRequest.h"
34 #include "mozilla/dom/quota/OriginScope.h"
35 #include "mozilla/dom/quota/QuotaCommon.h"
36 #include "mozilla/dom/quota/QuotaManager.h"
37 #include "mozilla/dom/quota/QuotaManagerImpl.h"
38 #include "mozilla/dom/quota/ResultExtensions.h"
39 #include "mozilla/dom/quota/StreamUtils.h"
40 #include "mozilla/dom/quota/UsageInfo.h"
41 #include "mozilla/fallible.h"
42 #include "mozilla/ipc/BackgroundParent.h"
43 #include "mozilla/ipc/PBackgroundSharedTypes.h"
44 #include "NormalOriginOperationBase.h"
46 #include "nsTHashMap.h"
49 #include "nsHashKeys.h"
50 #include "nsIBinaryOutputStream.h"
52 #include "nsIObjectOutputStream.h"
53 #include "nsIOutputStream.h"
54 #include "nsLiteralString.h"
55 #include "nsPrintfCString.h"
58 #include "OriginInfo.h"
59 #include "OriginOperationBase.h"
60 #include "QuotaRequestBase.h"
61 #include "QuotaUsageRequestBase.h"
62 #include "ResolvableNormalOriginOp.h"
66 namespace mozilla::dom::quota
{
68 using namespace mozilla::ipc
;
71 class OpenStorageDirectoryHelper
: public Base
{
73 OpenStorageDirectoryHelper(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
75 : Base(std::move(aQuotaManager
), aName
) {}
77 RefPtr
<BoolPromise
> OpenStorageDirectory(
78 const Nullable
<PersistenceType
>& aPersistenceType
,
79 const OriginScope
& aOriginScope
,
80 const Nullable
<Client::Type
>& aClientType
, bool aExclusive
);
82 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
85 class FinalizeOriginEvictionOp
: public OriginOperationBase
{
86 nsTArray
<RefPtr
<OriginDirectoryLock
>> mLocks
;
89 FinalizeOriginEvictionOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
90 nsTArray
<RefPtr
<OriginDirectoryLock
>>&& aLocks
)
91 : OriginOperationBase(std::move(aQuotaManager
),
92 "dom::quota::FinalizeOriginEvictionOp"),
93 mLocks(std::move(aLocks
)) {
94 AssertIsOnOwningThread();
98 ~FinalizeOriginEvictionOp() = default;
100 virtual RefPtr
<BoolPromise
> Open() override
;
102 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
104 virtual void UnblockOpen() override
;
107 class SaveOriginAccessTimeOp
108 : public OpenStorageDirectoryHelper
<NormalOriginOperationBase
> {
109 const OriginMetadata mOriginMetadata
;
113 SaveOriginAccessTimeOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
114 const OriginMetadata
& aOriginMetadata
,
116 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
117 "dom::quota::SaveOriginAccessTimeOp"),
118 mOriginMetadata(aOriginMetadata
),
119 mTimestamp(aTimestamp
) {
120 AssertIsOnOwningThread();
124 ~SaveOriginAccessTimeOp() = default;
126 RefPtr
<BoolPromise
> OpenDirectory() override
;
128 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
130 virtual void SendResults() override
;
132 void CloseDirectory() override
;
135 class ClearPrivateRepositoryOp
136 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
138 explicit ClearPrivateRepositoryOp(
139 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
140 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
141 "dom::quota::ClearPrivateRepositoryOp") {
142 AssertIsOnOwningThread();
146 ~ClearPrivateRepositoryOp() = default;
148 RefPtr
<BoolPromise
> OpenDirectory() override
;
150 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
152 bool GetResolveValue() override
{ return true; }
154 void CloseDirectory() override
;
157 class ShutdownStorageOp
: public ResolvableNormalOriginOp
<bool> {
158 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
161 explicit ShutdownStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
162 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
163 "dom::quota::ShutdownStorageOp") {
164 AssertIsOnOwningThread();
168 ~ShutdownStorageOp() = default;
171 nsresult
DirectoryOpen() override
;
174 RefPtr
<BoolPromise
> OpenDirectory() override
;
176 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
178 bool GetResolveValue() override
{ return true; }
180 void CloseDirectory() override
;
183 // A mix-in class to simplify operations that need to process every origin in
184 // one or more repositories. Sub-classes should call TraverseRepository in their
185 // DoDirectoryWork and implement a ProcessOrigin method for their per-origin
187 class TraverseRepositoryHelper
{
189 TraverseRepositoryHelper() = default;
192 virtual ~TraverseRepositoryHelper() = default;
194 // If ProcessOrigin returns an error, TraverseRepository will immediately
195 // terminate and return the received error code to its caller.
196 nsresult
TraverseRepository(QuotaManager
& aQuotaManager
,
197 PersistenceType aPersistenceType
);
200 virtual const Atomic
<bool>& GetIsCanceledFlag() = 0;
202 virtual nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
,
203 nsIFile
& aOriginDir
, const bool aPersistent
,
204 const PersistenceType aPersistenceType
) = 0;
207 class GetUsageOp final
208 : public OpenStorageDirectoryHelper
<QuotaUsageRequestBase
>,
209 public TraverseRepositoryHelper
{
210 nsTArray
<OriginUsage
> mOriginUsages
;
211 nsTHashMap
<nsCStringHashKey
, uint32_t> mOriginUsagesIndex
;
216 GetUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
217 const UsageRequestParams
& aParams
);
220 ~GetUsageOp() = default;
222 void ProcessOriginInternal(QuotaManager
* aQuotaManager
,
223 const PersistenceType aPersistenceType
,
224 const nsACString
& aOrigin
,
225 const int64_t aTimestamp
, const bool aPersisted
,
226 const uint64_t aUsage
);
228 RefPtr
<BoolPromise
> OpenDirectory() override
;
230 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
232 const Atomic
<bool>& GetIsCanceledFlag() override
;
234 nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
, nsIFile
& aOriginDir
,
235 const bool aPersistent
,
236 const PersistenceType aPersistenceType
) override
;
238 void GetResponse(UsageRequestResponse
& aResponse
) override
;
240 void CloseDirectory() override
;
243 class GetOriginUsageOp final
244 : public OpenStorageDirectoryHelper
<QuotaUsageRequestBase
> {
245 const OriginUsageParams mParams
;
246 PrincipalMetadata mPrincipalMetadata
;
247 UsageInfo mUsageInfo
;
251 GetOriginUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
252 const UsageRequestParams
& aParams
);
255 ~GetOriginUsageOp() = default;
257 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
259 RefPtr
<BoolPromise
> OpenDirectory() override
;
261 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
263 void GetResponse(UsageRequestResponse
& aResponse
) override
;
265 void CloseDirectory() override
;
268 class StorageNameOp final
: public QuotaRequestBase
{
272 explicit StorageNameOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
275 ~StorageNameOp() = default;
277 RefPtr
<BoolPromise
> OpenDirectory() override
;
279 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
281 void GetResponse(RequestResponse
& aResponse
) override
;
283 void CloseDirectory() override
;
286 class InitializedRequestBase
: public ResolvableNormalOriginOp
<bool> {
290 InitializedRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
294 RefPtr
<BoolPromise
> OpenDirectory() override
;
296 void CloseDirectory() override
;
299 class StorageInitializedOp final
: public InitializedRequestBase
{
301 explicit StorageInitializedOp(
302 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
303 : InitializedRequestBase(std::move(aQuotaManager
),
304 "dom::quota::StorageInitializedOp") {}
307 ~StorageInitializedOp() = default;
309 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
311 bool GetResolveValue() override
;
314 class TemporaryStorageInitializedOp final
: public InitializedRequestBase
{
316 explicit TemporaryStorageInitializedOp(
317 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
318 : InitializedRequestBase(std::move(aQuotaManager
),
319 "dom::quota::StorageInitializedOp") {}
322 ~TemporaryStorageInitializedOp() = default;
324 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
326 bool GetResolveValue() override
;
329 class InitOp final
: public ResolvableNormalOriginOp
<bool> {
330 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
333 InitOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
334 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
339 RefPtr
<BoolPromise
> OpenDirectory() override
;
341 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
343 bool GetResolveValue() override
;
345 void CloseDirectory() override
;
348 class InitTemporaryStorageOp final
: public ResolvableNormalOriginOp
<bool> {
349 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
352 InitTemporaryStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
353 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
);
356 ~InitTemporaryStorageOp() = default;
358 RefPtr
<BoolPromise
> OpenDirectory() override
;
360 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
362 bool GetResolveValue() override
;
364 void CloseDirectory() override
;
367 class InitializeOriginRequestBase
: public QuotaRequestBase
{
369 const PrincipalInfo mPrincipalInfo
;
370 PrincipalMetadata mPrincipalMetadata
;
371 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
372 const PersistenceType mPersistenceType
;
375 InitializeOriginRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
377 PersistenceType aPersistenceType
,
378 const PrincipalInfo
& aPrincipalInfo
);
380 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
383 RefPtr
<BoolPromise
> OpenDirectory() override
;
385 void CloseDirectory() override
;
388 class InitializePersistentOriginOp final
: public InitializeOriginRequestBase
{
390 InitializePersistentOriginOp(
391 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
392 const RequestParams
& aParams
);
395 ~InitializePersistentOriginOp() = default;
397 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
399 void GetResponse(RequestResponse
& aResponse
) override
;
402 class InitializeTemporaryOriginOp final
: public InitializeOriginRequestBase
{
404 InitializeTemporaryOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
405 const RequestParams
& aParams
);
408 ~InitializeTemporaryOriginOp() = default;
410 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
412 void GetResponse(RequestResponse
& aResponse
) override
;
415 class InitializeClientBase
: public ResolvableNormalOriginOp
<bool> {
417 const PrincipalInfo mPrincipalInfo
;
418 ClientMetadata mClientMetadata
;
419 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
420 const PersistenceType mPersistenceType
;
421 const Client::Type mClientType
;
424 InitializeClientBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
425 const char* aName
, PersistenceType aPersistenceType
,
426 const PrincipalInfo
& aPrincipalInfo
,
427 Client::Type aClientType
);
429 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
432 RefPtr
<BoolPromise
> OpenDirectory() override
;
434 void CloseDirectory() override
;
437 class InitializePersistentClientOp
: public InitializeClientBase
{
439 InitializePersistentClientOp(
440 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
441 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
);
444 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
446 bool GetResolveValue() override
;
449 class InitializeTemporaryClientOp
: public InitializeClientBase
{
451 InitializeTemporaryClientOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
452 PersistenceType aPersistenceType
,
453 const PrincipalInfo
& aPrincipalInfo
,
454 Client::Type aClientType
);
457 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
459 bool GetResolveValue() override
;
462 class GetFullOriginMetadataOp
463 : public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
464 const GetFullOriginMetadataParams mParams
;
465 // XXX Consider wrapping with LazyInitializedOnce
466 OriginMetadata mOriginMetadata
;
467 Maybe
<FullOriginMetadata
> mMaybeFullOriginMetadata
;
470 GetFullOriginMetadataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
471 const GetFullOriginMetadataParams
& aParams
);
474 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
476 RefPtr
<BoolPromise
> OpenDirectory() override
;
478 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
480 void GetResponse(RequestResponse
& aResponse
) override
;
482 void CloseDirectory() override
;
485 class ClearStorageOp final
486 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
488 explicit ClearStorageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
491 ~ClearStorageOp() = default;
493 void DeleteFiles(QuotaManager
& aQuotaManager
);
495 void DeleteStorageFile(QuotaManager
& aQuotaManager
);
497 RefPtr
<BoolPromise
> OpenDirectory() override
;
499 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
501 bool GetResolveValue() override
;
503 void CloseDirectory() override
;
506 class ClearRequestBase
507 : public OpenStorageDirectoryHelper
<ResolvableNormalOriginOp
<bool>> {
509 ClearRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
511 : OpenStorageDirectoryHelper(std::move(aQuotaManager
), aName
) {
512 AssertIsOnOwningThread();
515 void DeleteFiles(QuotaManager
& aQuotaManager
,
516 const OriginMetadata
& aOriginMetadata
,
517 const Nullable
<Client::Type
>& aClientType
);
519 void DeleteFiles(QuotaManager
& aQuotaManager
,
520 PersistenceType aPersistenceType
,
521 const OriginScope
& aOriginScope
,
522 const Nullable
<Client::Type
>& aClientType
);
525 template <typename FileCollector
>
526 void DeleteFilesInternal(QuotaManager
& aQuotaManager
,
527 PersistenceType aPersistenceType
,
528 const OriginScope
& aOriginScope
,
529 const Nullable
<Client::Type
>& aClientType
,
530 const FileCollector
& aFileCollector
);
533 class ClearOriginOp final
: public ClearRequestBase
{
534 const PrincipalInfo mPrincipalInfo
;
535 PrincipalMetadata mPrincipalMetadata
;
536 const Nullable
<PersistenceType
> mPersistenceType
;
537 const Nullable
<Client::Type
> mClientType
;
540 ClearOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
541 const mozilla::Maybe
<PersistenceType
>& aPersistenceType
,
542 const PrincipalInfo
& aPrincipalInfo
,
543 const mozilla::Maybe
<Client::Type
>& aClientType
);
546 ~ClearOriginOp() = default;
548 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
550 RefPtr
<BoolPromise
> OpenDirectory() override
;
552 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
554 bool GetResolveValue() override
;
556 void CloseDirectory() override
;
559 class ClearStoragesForOriginPrefixOp final
560 : public OpenStorageDirectoryHelper
<ClearRequestBase
> {
561 const nsCString mPrefix
;
562 const Nullable
<PersistenceType
> mPersistenceType
;
565 ClearStoragesForOriginPrefixOp(
566 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
567 const Maybe
<PersistenceType
>& aPersistenceType
,
568 const PrincipalInfo
& aPrincipalInfo
);
571 ~ClearStoragesForOriginPrefixOp() = default;
573 RefPtr
<BoolPromise
> OpenDirectory() override
;
575 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
577 bool GetResolveValue() override
;
579 void CloseDirectory() override
;
582 class ClearDataOp final
: public ClearRequestBase
{
583 const OriginAttributesPattern mPattern
;
586 ClearDataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
587 const OriginAttributesPattern
& aPattern
);
590 ~ClearDataOp() = default;
592 RefPtr
<BoolPromise
> OpenDirectory() override
;
594 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
596 bool GetResolveValue() override
;
598 void CloseDirectory() override
;
601 class ResetOriginOp final
: public QuotaRequestBase
{
603 RefPtr
<UniversalDirectoryLock
> mDirectoryLock
;
604 Nullable
<PersistenceType
> mPersistenceType
;
605 Nullable
<Client::Type
> mClientType
;
608 ResetOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
609 const RequestParams
& aParams
);
612 ~ResetOriginOp() = default;
614 RefPtr
<BoolPromise
> OpenDirectory() override
;
616 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
618 void GetResponse(RequestResponse
& aResponse
) override
;
620 void CloseDirectory() override
;
623 class PersistRequestBase
: public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
624 const PrincipalInfo mPrincipalInfo
;
627 PrincipalMetadata mPrincipalMetadata
;
630 PersistRequestBase(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
631 const PrincipalInfo
& aPrincipalInfo
);
633 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
636 RefPtr
<BoolPromise
> OpenDirectory() override
;
638 void CloseDirectory() override
;
641 class PersistedOp final
: public PersistRequestBase
{
645 PersistedOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
646 const RequestParams
& aParams
);
649 ~PersistedOp() = default;
651 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
653 void GetResponse(RequestResponse
& aResponse
) override
;
656 class PersistOp final
: public PersistRequestBase
{
658 PersistOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
659 const RequestParams
& aParams
);
662 ~PersistOp() = default;
664 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
666 void GetResponse(RequestResponse
& aResponse
) override
;
669 class EstimateOp final
: public OpenStorageDirectoryHelper
<QuotaRequestBase
> {
670 const EstimateParams mParams
;
671 OriginMetadata mOriginMetadata
;
672 std::pair
<uint64_t, uint64_t> mUsageAndLimit
;
675 EstimateOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
676 const EstimateParams
& aParams
);
679 ~EstimateOp() = default;
681 nsresult
DoInit(QuotaManager
& aQuotaManager
) override
;
683 RefPtr
<BoolPromise
> OpenDirectory() override
;
685 virtual nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
687 void GetResponse(RequestResponse
& aResponse
) override
;
689 void CloseDirectory() override
;
692 class ListOriginsOp final
: public OpenStorageDirectoryHelper
<QuotaRequestBase
>,
693 public TraverseRepositoryHelper
{
694 // XXX Bug 1521541 will make each origin has it's own state.
695 nsTArray
<nsCString
> mOrigins
;
698 explicit ListOriginsOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
);
701 ~ListOriginsOp() = default;
703 RefPtr
<BoolPromise
> OpenDirectory() override
;
705 nsresult
DoDirectoryWork(QuotaManager
& aQuotaManager
) override
;
707 const Atomic
<bool>& GetIsCanceledFlag() override
;
709 nsresult
ProcessOrigin(QuotaManager
& aQuotaManager
, nsIFile
& aOriginDir
,
710 const bool aPersistent
,
711 const PersistenceType aPersistenceType
) override
;
713 void GetResponse(RequestResponse
& aResponse
) override
;
715 void CloseDirectory() override
;
718 RefPtr
<OriginOperationBase
> CreateFinalizeOriginEvictionOp(
719 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
720 nsTArray
<RefPtr
<OriginDirectoryLock
>>&& aLocks
) {
721 return MakeRefPtr
<FinalizeOriginEvictionOp
>(std::move(aQuotaManager
),
725 RefPtr
<NormalOriginOperationBase
> CreateSaveOriginAccessTimeOp(
726 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
727 const OriginMetadata
& aOriginMetadata
, int64_t aTimestamp
) {
728 return MakeRefPtr
<SaveOriginAccessTimeOp
>(std::move(aQuotaManager
),
729 aOriginMetadata
, aTimestamp
);
732 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearPrivateRepositoryOp(
733 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
734 return MakeRefPtr
<ClearPrivateRepositoryOp
>(std::move(aQuotaManager
));
737 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateShutdownStorageOp(
738 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
739 return MakeRefPtr
<ShutdownStorageOp
>(std::move(aQuotaManager
));
742 RefPtr
<QuotaUsageRequestBase
> CreateGetUsageOp(
743 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
744 const UsageRequestParams
& aParams
) {
745 return MakeRefPtr
<GetUsageOp
>(std::move(aQuotaManager
), aParams
);
748 RefPtr
<QuotaUsageRequestBase
> CreateGetOriginUsageOp(
749 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
750 const UsageRequestParams
& aParams
) {
751 return MakeRefPtr
<GetOriginUsageOp
>(std::move(aQuotaManager
), aParams
);
754 RefPtr
<QuotaRequestBase
> CreateStorageNameOp(
755 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
756 return MakeRefPtr
<StorageNameOp
>(std::move(aQuotaManager
));
759 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateStorageInitializedOp(
760 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
761 return MakeRefPtr
<StorageInitializedOp
>(std::move(aQuotaManager
));
764 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateTemporaryStorageInitializedOp(
765 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
766 return MakeRefPtr
<TemporaryStorageInitializedOp
>(std::move(aQuotaManager
));
769 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitOp(
770 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
771 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
772 return MakeRefPtr
<InitOp
>(std::move(aQuotaManager
),
773 std::move(aDirectoryLock
));
776 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitTemporaryStorageOp(
777 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
778 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
) {
779 return MakeRefPtr
<InitTemporaryStorageOp
>(std::move(aQuotaManager
),
780 std::move(aDirectoryLock
));
783 RefPtr
<QuotaRequestBase
> CreateInitializePersistentOriginOp(
784 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
785 const RequestParams
& aParams
) {
786 return MakeRefPtr
<InitializePersistentOriginOp
>(std::move(aQuotaManager
),
790 RefPtr
<QuotaRequestBase
> CreateInitializeTemporaryOriginOp(
791 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
792 const RequestParams
& aParams
) {
793 return MakeRefPtr
<InitializeTemporaryOriginOp
>(std::move(aQuotaManager
),
797 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializePersistentClientOp(
798 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
799 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
800 const Client::Type aClientType
) {
801 return MakeRefPtr
<InitializePersistentClientOp
>(std::move(aQuotaManager
),
802 aPrincipalInfo
, aClientType
);
805 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateInitializeTemporaryClientOp(
806 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
807 const PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
808 const Client::Type aClientType
) {
809 return MakeRefPtr
<InitializeTemporaryClientOp
>(
810 std::move(aQuotaManager
), aPersistenceType
, aPrincipalInfo
, aClientType
);
813 RefPtr
<QuotaRequestBase
> CreateGetFullOriginMetadataOp(
814 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
815 const GetFullOriginMetadataParams
& aParams
) {
816 return MakeRefPtr
<GetFullOriginMetadataOp
>(std::move(aQuotaManager
), aParams
);
819 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearStorageOp(
820 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
821 return MakeRefPtr
<ClearStorageOp
>(std::move(aQuotaManager
));
824 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearOriginOp(
825 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
826 const Maybe
<PersistenceType
>& aPersistenceType
,
827 const PrincipalInfo
& aPrincipalInfo
,
828 const Maybe
<Client::Type
>& aClientType
) {
829 return MakeRefPtr
<ClearOriginOp
>(std::move(aQuotaManager
), aPersistenceType
,
830 aPrincipalInfo
, aClientType
);
833 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearStoragesForOriginPrefixOp(
834 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
835 const Maybe
<PersistenceType
>& aPersistenceType
,
836 const PrincipalInfo
& aPrincipalInfo
) {
837 return MakeRefPtr
<ClearStoragesForOriginPrefixOp
>(
838 std::move(aQuotaManager
), aPersistenceType
, aPrincipalInfo
);
841 RefPtr
<ResolvableNormalOriginOp
<bool>> CreateClearDataOp(
842 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
843 const OriginAttributesPattern
& aPattern
) {
844 return MakeRefPtr
<ClearDataOp
>(std::move(aQuotaManager
), aPattern
);
847 RefPtr
<QuotaRequestBase
> CreateResetOriginOp(
848 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
849 const RequestParams
& aParams
) {
850 return MakeRefPtr
<ResetOriginOp
>(std::move(aQuotaManager
), aParams
);
853 RefPtr
<QuotaRequestBase
> CreatePersistedOp(
854 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
855 const RequestParams
& aParams
) {
856 return MakeRefPtr
<PersistedOp
>(std::move(aQuotaManager
), aParams
);
859 RefPtr
<QuotaRequestBase
> CreatePersistOp(
860 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
861 const RequestParams
& aParams
) {
862 return MakeRefPtr
<PersistOp
>(std::move(aQuotaManager
), aParams
);
865 RefPtr
<QuotaRequestBase
> CreateEstimateOp(
866 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
867 const EstimateParams
& aParams
) {
868 return MakeRefPtr
<EstimateOp
>(std::move(aQuotaManager
), aParams
);
871 RefPtr
<QuotaRequestBase
> CreateListOriginsOp(
872 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
) {
873 return MakeRefPtr
<ListOriginsOp
>(std::move(aQuotaManager
));
876 template <class Base
>
877 RefPtr
<BoolPromise
> OpenStorageDirectoryHelper
<Base
>::OpenStorageDirectory(
878 const Nullable
<PersistenceType
>& aPersistenceType
,
879 const OriginScope
& aOriginScope
, const Nullable
<Client::Type
>& aClientType
,
881 return Base::mQuotaManager
882 ->OpenStorageDirectory(aPersistenceType
, aOriginScope
, aClientType
,
884 ->Then(GetCurrentSerialEventTarget(), __func__
,
885 [self
= RefPtr(this)](
886 UniversalDirectoryLockPromise::ResolveOrRejectValue
&& aValue
) {
887 if (aValue
.IsReject()) {
888 return BoolPromise::CreateAndReject(aValue
.RejectValue(),
892 self
->mDirectoryLock
= std::move(aValue
.ResolveValue());
894 return BoolPromise::CreateAndResolve(true, __func__
);
898 RefPtr
<BoolPromise
> FinalizeOriginEvictionOp::Open() {
899 AssertIsOnOwningThread();
900 MOZ_ASSERT(!mLocks
.IsEmpty());
902 return BoolPromise::CreateAndResolve(true, __func__
);
905 nsresult
FinalizeOriginEvictionOp::DoDirectoryWork(
906 QuotaManager
& aQuotaManager
) {
907 AssertIsOnIOThread();
909 AUTO_PROFILER_LABEL("FinalizeOriginEvictionOp::DoDirectoryWork", OTHER
);
911 for (const auto& lock
: mLocks
) {
912 aQuotaManager
.OriginClearCompleted(
913 lock
->GetPersistenceType(), lock
->Origin(), Nullable
<Client::Type
>());
919 void FinalizeOriginEvictionOp::UnblockOpen() {
920 AssertIsOnOwningThread();
923 NoteActorDestroyed();
929 RefPtr
<BoolPromise
> SaveOriginAccessTimeOp::OpenDirectory() {
930 AssertIsOnOwningThread();
932 return OpenStorageDirectory(
933 Nullable
<PersistenceType
>(mOriginMetadata
.mPersistenceType
),
934 OriginScope::FromOrigin(mOriginMetadata
.mOrigin
),
935 Nullable
<Client::Type
>(),
936 /* aExclusive */ false);
939 nsresult
SaveOriginAccessTimeOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
940 AssertIsOnIOThread();
941 aQuotaManager
.AssertStorageIsInitializedInternal();
943 AUTO_PROFILER_LABEL("SaveOriginAccessTimeOp::DoDirectoryWork", OTHER
);
945 QM_TRY(MOZ_TO_RESULT(!QuotaManager::IsShuttingDown()), NS_ERROR_ABORT
);
947 QM_TRY_INSPECT(const auto& file
,
948 aQuotaManager
.GetOriginDirectory(mOriginMetadata
));
950 // The origin directory might not exist
951 // anymore, because it was deleted by a clear operation.
952 QM_TRY_INSPECT(const bool& exists
, MOZ_TO_RESULT_INVOKE_MEMBER(file
, Exists
));
955 QM_TRY(MOZ_TO_RESULT(file
->Append(nsLiteralString(METADATA_V2_FILE_NAME
))));
957 QM_TRY_INSPECT(const auto& stream
,
958 GetBinaryOutputStream(*file
, FileFlag::Update
));
961 QM_TRY(MOZ_TO_RESULT(stream
->Write64(mTimestamp
)));
967 void SaveOriginAccessTimeOp::SendResults() {
969 NoteActorDestroyed();
973 void SaveOriginAccessTimeOp::CloseDirectory() {
974 AssertIsOnOwningThread();
976 mDirectoryLock
= nullptr;
979 RefPtr
<BoolPromise
> ClearPrivateRepositoryOp::OpenDirectory() {
980 AssertIsOnOwningThread();
982 return OpenStorageDirectory(
983 Nullable
<PersistenceType
>(PERSISTENCE_TYPE_PRIVATE
),
984 OriginScope::FromNull(), Nullable
<Client::Type
>(),
985 /* aExclusive */ true);
988 nsresult
ClearPrivateRepositoryOp::DoDirectoryWork(
989 QuotaManager
& aQuotaManager
) {
990 AssertIsOnIOThread();
991 aQuotaManager
.AssertStorageIsInitializedInternal();
993 AUTO_PROFILER_LABEL("ClearPrivateRepositoryOp::DoDirectoryWork", OTHER
);
996 const auto& directory
,
997 QM_NewLocalFile(aQuotaManager
.GetStoragePath(PERSISTENCE_TYPE_PRIVATE
)));
999 nsresult rv
= directory
->Remove(true);
1000 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
1001 // This should never fail if we've closed all storage connections
1003 MOZ_ASSERT(false, "Failed to remove directory!");
1006 aQuotaManager
.RemoveQuotaForRepository(PERSISTENCE_TYPE_PRIVATE
);
1008 aQuotaManager
.RepositoryClearCompleted(PERSISTENCE_TYPE_PRIVATE
);
1013 void ClearPrivateRepositoryOp::CloseDirectory() {
1014 AssertIsOnOwningThread();
1016 mDirectoryLock
= nullptr;
1019 RefPtr
<BoolPromise
> ShutdownStorageOp::OpenDirectory() {
1020 AssertIsOnOwningThread();
1022 // Clear directory lock tables (which also saves origin access time) before
1023 // acquiring the exclusive lock below. Otherwise, saving of origin access
1024 // time would be scheduled after storage shutdown and that would initialize
1025 // storage again in the end.
1026 mQuotaManager
->ClearDirectoryLockTables();
1028 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
1029 Nullable
<PersistenceType
>(), OriginScope::FromNull(),
1030 Nullable
<Client::Type
>(),
1031 /* aExclusive */ true);
1033 return mDirectoryLock
->Acquire();
1037 nsresult
ShutdownStorageOp::DirectoryOpen() {
1038 AssertIsOnBackgroundThread();
1039 MOZ_ASSERT(mDirectoryLock
);
1040 mDirectoryLock
->AssertIsAcquiredExclusively();
1042 return NormalOriginOperationBase::DirectoryOpen();
1046 nsresult
ShutdownStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1047 AssertIsOnIOThread();
1049 AUTO_PROFILER_LABEL("ShutdownStorageOp::DoDirectoryWork", OTHER
);
1051 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
1052 "ShutdownStorageOp::DoDirectoryWork -> ShutdownStorageInternal."_ns
);
1054 aQuotaManager
.ShutdownStorageInternal();
1059 void ShutdownStorageOp::CloseDirectory() {
1060 AssertIsOnOwningThread();
1062 mDirectoryLock
= nullptr;
1065 nsresult
TraverseRepositoryHelper::TraverseRepository(
1066 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
) {
1067 AssertIsOnIOThread();
1070 const auto& directory
,
1071 QM_NewLocalFile(aQuotaManager
.GetStoragePath(aPersistenceType
)));
1073 QM_TRY_INSPECT(const bool& exists
,
1074 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
1080 QM_TRY(CollectEachFileAtomicCancelable(
1081 *directory
, GetIsCanceledFlag(),
1082 [this, aPersistenceType
, &aQuotaManager
,
1083 persistent
= aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
](
1084 const nsCOMPtr
<nsIFile
>& originDir
) -> Result
<Ok
, nsresult
> {
1085 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*originDir
));
1087 switch (dirEntryKind
) {
1088 case nsIFileKind::ExistsAsDirectory
:
1089 QM_TRY(MOZ_TO_RESULT(ProcessOrigin(aQuotaManager
, *originDir
,
1090 persistent
, aPersistenceType
)));
1093 case nsIFileKind::ExistsAsFile
: {
1094 QM_TRY_INSPECT(const auto& leafName
,
1095 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
1096 nsAutoString
, originDir
, GetLeafName
));
1098 // Unknown files during getting usages are allowed. Just warn if we
1100 if (!IsOSMetadata(leafName
)) {
1101 UNKNOWN_FILE_WARNING(leafName
);
1107 case nsIFileKind::DoesNotExist
:
1108 // Ignore files that got removed externally while iterating.
1118 GetUsageOp::GetUsageOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1119 const UsageRequestParams
& aParams
)
1120 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1121 "dom::quota::GetUsageOp"),
1122 mGetAll(aParams
.get_AllUsageParams().getAll()) {
1123 AssertIsOnOwningThread();
1124 MOZ_ASSERT(aParams
.type() == UsageRequestParams::TAllUsageParams
);
1127 void GetUsageOp::ProcessOriginInternal(QuotaManager
* aQuotaManager
,
1128 const PersistenceType aPersistenceType
,
1129 const nsACString
& aOrigin
,
1130 const int64_t aTimestamp
,
1131 const bool aPersisted
,
1132 const uint64_t aUsage
) {
1133 if (!mGetAll
&& aQuotaManager
->IsOriginInternal(aOrigin
)) {
1137 // We can't store pointers to OriginUsage objects in the hashtable
1138 // since AppendElement() reallocates its internal array buffer as number
1139 // of elements grows.
1140 const auto& originUsage
=
1141 mOriginUsagesIndex
.WithEntryHandle(aOrigin
, [&](auto&& entry
) {
1143 return WrapNotNullUnchecked(&mOriginUsages
[entry
.Data()]);
1146 entry
.Insert(mOriginUsages
.Length());
1148 return mOriginUsages
.EmplaceBack(nsCString
{aOrigin
}, false, 0, 0);
1151 if (aPersistenceType
== PERSISTENCE_TYPE_DEFAULT
) {
1152 originUsage
->persisted() = aPersisted
;
1155 originUsage
->usage() = originUsage
->usage() + aUsage
;
1157 originUsage
->lastAccessed() =
1158 std::max
<int64_t>(originUsage
->lastAccessed(), aTimestamp
);
1161 const Atomic
<bool>& GetUsageOp::GetIsCanceledFlag() {
1162 AssertIsOnIOThread();
1167 // XXX Remove aPersistent
1168 // XXX Remove aPersistenceType once GetUsageForOrigin uses the persistence
1169 // type from OriginMetadata
1170 nsresult
GetUsageOp::ProcessOrigin(QuotaManager
& aQuotaManager
,
1171 nsIFile
& aOriginDir
, const bool aPersistent
,
1172 const PersistenceType aPersistenceType
) {
1173 AssertIsOnIOThread();
1175 QM_TRY_UNWRAP(auto maybeMetadata
,
1178 aQuotaManager
.LoadFullOriginMetadataWithRestore(&aOriginDir
)
1179 .map([](auto metadata
) -> Maybe
<FullOriginMetadata
> {
1180 return Some(std::move(metadata
));
1183 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
1185 ErrToDefaultOk
<Maybe
<FullOriginMetadata
>>));
1187 if (!maybeMetadata
) {
1188 // Unknown directories during getting usage are allowed. Just warn if we
1190 QM_TRY_INSPECT(const auto& leafName
,
1191 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, aOriginDir
,
1194 UNKNOWN_FILE_WARNING(leafName
);
1198 auto metadata
= maybeMetadata
.extract();
1200 QM_TRY_INSPECT(const auto& usageInfo
,
1201 GetUsageForOrigin(aQuotaManager
, aPersistenceType
, metadata
));
1203 ProcessOriginInternal(&aQuotaManager
, aPersistenceType
, metadata
.mOrigin
,
1204 metadata
.mLastAccessTime
, metadata
.mPersisted
,
1205 usageInfo
.TotalUsage().valueOr(0));
1210 RefPtr
<BoolPromise
> GetUsageOp::OpenDirectory() {
1211 AssertIsOnOwningThread();
1213 return OpenStorageDirectory(Nullable
<PersistenceType
>(),
1214 OriginScope::FromNull(), Nullable
<Client::Type
>(),
1215 /* aExclusive */ false);
1218 nsresult
GetUsageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1219 AssertIsOnIOThread();
1220 aQuotaManager
.AssertStorageIsInitializedInternal();
1222 AUTO_PROFILER_LABEL("GetUsageOp::DoDirectoryWork", OTHER
);
1226 for (const PersistenceType type
: kAllPersistenceTypes
) {
1227 rv
= TraverseRepository(aQuotaManager
, type
);
1228 if (NS_WARN_IF(NS_FAILED(rv
))) {
1233 // TraverseRepository above only consulted the filesystem. We also need to
1234 // consider origins which may have pending quota usage, such as buffered
1235 // LocalStorage writes for an origin which didn't previously have any
1236 // LocalStorage data.
1238 aQuotaManager
.CollectPendingOriginsForListing(
1239 [this, &aQuotaManager
](const auto& originInfo
) {
1240 ProcessOriginInternal(
1241 &aQuotaManager
, originInfo
->GetGroupInfo()->GetPersistenceType(),
1242 originInfo
->Origin(), originInfo
->LockedAccessTime(),
1243 originInfo
->LockedPersisted(), originInfo
->LockedUsage());
1249 void GetUsageOp::GetResponse(UsageRequestResponse
& aResponse
) {
1250 AssertIsOnOwningThread();
1252 aResponse
= AllUsageResponse();
1254 aResponse
.get_AllUsageResponse().originUsages() = std::move(mOriginUsages
);
1257 void GetUsageOp::CloseDirectory() {
1258 AssertIsOnOwningThread();
1260 mDirectoryLock
= nullptr;
1263 GetOriginUsageOp::GetOriginUsageOp(
1264 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1265 const UsageRequestParams
& aParams
)
1266 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1267 "dom::quota::GetOriginUsageOp"),
1268 mParams(aParams
.get_OriginUsageParams()) {
1269 AssertIsOnOwningThread();
1270 MOZ_ASSERT(aParams
.type() == UsageRequestParams::TOriginUsageParams
);
1272 // Overwrite GetOriginUsageOp default values.
1273 mFromMemory
= mParams
.fromMemory();
1276 nsresult
GetOriginUsageOp::DoInit(QuotaManager
& aQuotaManager
) {
1277 AssertIsOnOwningThread();
1281 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mParams
.principalInfo()));
1283 mPrincipalMetadata
.AssertInvariants();
1288 RefPtr
<BoolPromise
> GetOriginUsageOp::OpenDirectory() {
1289 AssertIsOnOwningThread();
1291 return OpenStorageDirectory(
1292 Nullable
<PersistenceType
>(),
1293 OriginScope::FromOrigin(mPrincipalMetadata
.mOrigin
),
1294 Nullable
<Client::Type
>(),
1295 /* aExclusive */ false);
1298 nsresult
GetOriginUsageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1299 AssertIsOnIOThread();
1300 aQuotaManager
.AssertStorageIsInitializedInternal();
1301 MOZ_ASSERT(mUsageInfo
.TotalUsage().isNothing());
1303 AUTO_PROFILER_LABEL("GetOriginUsageOp::DoDirectoryWork", OTHER
);
1306 // Ensure temporary storage is initialized. If temporary storage hasn't been
1307 // initialized yet, the method will initialize it by traversing the
1308 // repositories for temporary and default storage (including our origin).
1309 QM_TRY(MOZ_TO_RESULT(
1310 aQuotaManager
.EnsureTemporaryStorageIsInitializedInternal()));
1312 // Get cached usage (the method doesn't have to stat any files). File usage
1313 // is not tracked in memory separately, so just add to the database usage.
1314 mUsageInfo
+= DatabaseUsageType(
1315 Some(aQuotaManager
.GetOriginUsage(mPrincipalMetadata
)));
1320 // Add all the persistent/temporary/default storage files we care about.
1321 for (const PersistenceType type
: kAllPersistenceTypes
) {
1322 const OriginMetadata originMetadata
= {mPrincipalMetadata
, type
};
1324 auto usageInfoOrErr
=
1325 GetUsageForOrigin(aQuotaManager
, type
, originMetadata
);
1326 if (NS_WARN_IF(usageInfoOrErr
.isErr())) {
1327 return usageInfoOrErr
.unwrapErr();
1330 mUsageInfo
+= usageInfoOrErr
.unwrap();
1336 void GetOriginUsageOp::GetResponse(UsageRequestResponse
& aResponse
) {
1337 AssertIsOnOwningThread();
1339 OriginUsageResponse usageResponse
;
1341 usageResponse
.usageInfo() = mUsageInfo
;
1343 aResponse
= usageResponse
;
1346 void GetOriginUsageOp::CloseDirectory() {
1347 AssertIsOnOwningThread();
1349 mDirectoryLock
= nullptr;
1352 StorageNameOp::StorageNameOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
1353 : QuotaRequestBase(std::move(aQuotaManager
), "dom::quota::StorageNameOp") {
1354 AssertIsOnOwningThread();
1357 RefPtr
<BoolPromise
> StorageNameOp::OpenDirectory() {
1358 AssertIsOnOwningThread();
1360 return BoolPromise::CreateAndResolve(true, __func__
);
1363 nsresult
StorageNameOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1364 AssertIsOnIOThread();
1366 AUTO_PROFILER_LABEL("StorageNameOp::DoDirectoryWork", OTHER
);
1368 mName
= aQuotaManager
.GetStorageName();
1373 void StorageNameOp::GetResponse(RequestResponse
& aResponse
) {
1374 AssertIsOnOwningThread();
1376 StorageNameResponse storageNameResponse
;
1378 storageNameResponse
.name() = mName
;
1380 aResponse
= storageNameResponse
;
1383 void StorageNameOp::CloseDirectory() { AssertIsOnOwningThread(); }
1385 InitializedRequestBase::InitializedRequestBase(
1386 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
)
1387 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
1388 mInitialized(false) {
1389 AssertIsOnOwningThread();
1392 RefPtr
<BoolPromise
> InitializedRequestBase::OpenDirectory() {
1393 AssertIsOnOwningThread();
1395 return BoolPromise::CreateAndResolve(true, __func__
);
1398 void InitializedRequestBase::CloseDirectory() { AssertIsOnOwningThread(); }
1400 nsresult
StorageInitializedOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1401 AssertIsOnIOThread();
1403 AUTO_PROFILER_LABEL("StorageInitializedOp::DoDirectoryWork", OTHER
);
1405 mInitialized
= aQuotaManager
.IsStorageInitializedInternal();
1410 bool StorageInitializedOp::GetResolveValue() {
1411 AssertIsOnOwningThread();
1413 return mInitialized
;
1416 nsresult
TemporaryStorageInitializedOp::DoDirectoryWork(
1417 QuotaManager
& aQuotaManager
) {
1418 AssertIsOnIOThread();
1420 AUTO_PROFILER_LABEL("TemporaryStorageInitializedOp::DoDirectoryWork", OTHER
);
1422 mInitialized
= aQuotaManager
.IsTemporaryStorageInitializedInternal();
1427 bool TemporaryStorageInitializedOp::GetResolveValue() {
1428 AssertIsOnOwningThread();
1430 return mInitialized
;
1433 InitOp::InitOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1434 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
1435 : ResolvableNormalOriginOp(std::move(aQuotaManager
), "dom::quota::InitOp"),
1436 mDirectoryLock(std::move(aDirectoryLock
)) {
1437 AssertIsOnOwningThread();
1438 MOZ_ASSERT(mDirectoryLock
);
1441 RefPtr
<BoolPromise
> InitOp::OpenDirectory() {
1442 AssertIsOnOwningThread();
1443 MOZ_ASSERT(mDirectoryLock
);
1445 return BoolPromise::CreateAndResolve(true, __func__
);
1448 nsresult
InitOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1449 AssertIsOnIOThread();
1451 AUTO_PROFILER_LABEL("InitOp::DoDirectoryWork", OTHER
);
1453 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.EnsureStorageIsInitializedInternal()));
1458 bool InitOp::GetResolveValue() { return true; }
1460 void InitOp::CloseDirectory() {
1461 AssertIsOnOwningThread();
1463 mDirectoryLock
= nullptr;
1466 InitTemporaryStorageOp::InitTemporaryStorageOp(
1467 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1468 RefPtr
<UniversalDirectoryLock
> aDirectoryLock
)
1469 : ResolvableNormalOriginOp(std::move(aQuotaManager
),
1470 "dom::quota::InitTemporaryStorageOp"),
1471 mDirectoryLock(std::move(aDirectoryLock
)) {
1472 AssertIsOnOwningThread();
1475 RefPtr
<BoolPromise
> InitTemporaryStorageOp::OpenDirectory() {
1476 AssertIsOnOwningThread();
1477 MOZ_ASSERT(mDirectoryLock
);
1479 return BoolPromise::CreateAndResolve(true, __func__
);
1482 nsresult
InitTemporaryStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1483 AssertIsOnIOThread();
1485 AUTO_PROFILER_LABEL("InitTemporaryStorageOp::DoDirectoryWork", OTHER
);
1487 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
1488 NS_ERROR_NOT_INITIALIZED
);
1490 QM_TRY(MOZ_TO_RESULT(
1491 aQuotaManager
.EnsureTemporaryStorageIsInitializedInternal()));
1496 bool InitTemporaryStorageOp::GetResolveValue() {
1497 AssertIsOnOwningThread();
1502 void InitTemporaryStorageOp::CloseDirectory() {
1503 AssertIsOnOwningThread();
1505 mDirectoryLock
= nullptr;
1508 InitializeOriginRequestBase::InitializeOriginRequestBase(
1509 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
1510 const PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
)
1511 : QuotaRequestBase(std::move(aQuotaManager
), aName
),
1512 mPrincipalInfo(aPrincipalInfo
),
1513 mPersistenceType(aPersistenceType
),
1515 AssertIsOnOwningThread();
1518 nsresult
InitializeOriginRequestBase::DoInit(QuotaManager
& aQuotaManager
) {
1519 AssertIsOnOwningThread();
1523 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo
));
1525 mPrincipalMetadata
.AssertInvariants();
1530 RefPtr
<BoolPromise
> InitializeOriginRequestBase::OpenDirectory() {
1531 AssertIsOnOwningThread();
1533 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
1534 Nullable
<PersistenceType
>(mPersistenceType
),
1535 OriginScope::FromOrigin(mPrincipalMetadata
.mOrigin
),
1536 Nullable
<Client::Type
>(), /* aExclusive */ false);
1538 return mDirectoryLock
->Acquire();
1541 void InitializeOriginRequestBase::CloseDirectory() {
1542 AssertIsOnOwningThread();
1544 mDirectoryLock
= nullptr;
1547 InitializePersistentOriginOp::InitializePersistentOriginOp(
1548 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1549 const RequestParams
& aParams
)
1550 : InitializeOriginRequestBase(
1551 std::move(aQuotaManager
), "dom::quota::InitializePersistentOriginOp",
1552 PERSISTENCE_TYPE_PERSISTENT
,
1553 aParams
.get_InitializePersistentOriginParams().principalInfo()) {
1554 AssertIsOnOwningThread();
1555 MOZ_ASSERT(aParams
.type() ==
1556 RequestParams::TInitializePersistentOriginParams
);
1559 nsresult
InitializePersistentOriginOp::DoDirectoryWork(
1560 QuotaManager
& aQuotaManager
) {
1561 AssertIsOnIOThread();
1563 AUTO_PROFILER_LABEL("InitializePersistentOriginOp::DoDirectoryWork", OTHER
);
1565 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
1566 NS_ERROR_NOT_INITIALIZED
);
1568 QM_TRY_UNWRAP(mCreated
,
1570 .EnsurePersistentOriginIsInitialized(OriginMetadata
{
1571 mPrincipalMetadata
, PERSISTENCE_TYPE_PERSISTENT
})
1572 .map([](const auto& res
) { return res
.second
; })));
1577 void InitializePersistentOriginOp::GetResponse(RequestResponse
& aResponse
) {
1578 AssertIsOnOwningThread();
1580 aResponse
= InitializePersistentOriginResponse(mCreated
);
1583 InitializeTemporaryOriginOp::InitializeTemporaryOriginOp(
1584 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1585 const RequestParams
& aParams
)
1586 : InitializeOriginRequestBase(
1587 std::move(aQuotaManager
), "dom::quota::InitializeTemporaryOriginOp",
1588 aParams
.get_InitializeTemporaryOriginParams().persistenceType(),
1589 aParams
.get_InitializeTemporaryOriginParams().principalInfo()) {
1590 AssertIsOnOwningThread();
1591 MOZ_ASSERT(aParams
.type() == RequestParams::TInitializeTemporaryOriginParams
);
1594 nsresult
InitializeTemporaryOriginOp::DoDirectoryWork(
1595 QuotaManager
& aQuotaManager
) {
1596 AssertIsOnIOThread();
1598 AUTO_PROFILER_LABEL("InitializeTemporaryOriginOp::DoDirectoryWork", OTHER
);
1600 QM_TRY(OkIf(aQuotaManager
.IsStorageInitializedInternal()),
1601 NS_ERROR_NOT_INITIALIZED
);
1603 QM_TRY(OkIf(aQuotaManager
.IsTemporaryStorageInitializedInternal()),
1604 NS_ERROR_NOT_INITIALIZED
);
1606 QM_TRY_UNWRAP(mCreated
,
1608 .EnsureTemporaryOriginIsInitialized(
1610 OriginMetadata
{mPrincipalMetadata
, mPersistenceType
})
1611 .map([](const auto& res
) { return res
.second
; })));
1616 void InitializeTemporaryOriginOp::GetResponse(RequestResponse
& aResponse
) {
1617 AssertIsOnOwningThread();
1619 aResponse
= InitializeTemporaryOriginResponse(mCreated
);
1622 InitializeClientBase::InitializeClientBase(
1623 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
, const char* aName
,
1624 const PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
1625 Client::Type aClientType
)
1626 : ResolvableNormalOriginOp(std::move(aQuotaManager
), aName
),
1627 mPrincipalInfo(aPrincipalInfo
),
1628 mPersistenceType(aPersistenceType
),
1629 mClientType(aClientType
),
1631 AssertIsOnOwningThread();
1634 nsresult
InitializeClientBase::DoInit(QuotaManager
& aQuotaManager
) {
1635 AssertIsOnOwningThread();
1638 PrincipalMetadata principalMetadata
,
1639 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo
));
1641 principalMetadata
.AssertInvariants();
1644 OriginMetadata
{std::move(principalMetadata
), mPersistenceType
},
1650 RefPtr
<BoolPromise
> InitializeClientBase::OpenDirectory() {
1651 AssertIsOnOwningThread();
1653 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
1654 Nullable(mPersistenceType
),
1655 OriginScope::FromOrigin(mClientMetadata
.mOrigin
),
1656 Nullable(mClientMetadata
.mClientType
), /* aExclusive */ false);
1658 return mDirectoryLock
->Acquire();
1661 void InitializeClientBase::CloseDirectory() {
1662 AssertIsOnOwningThread();
1664 mDirectoryLock
= nullptr;
1667 InitializePersistentClientOp::InitializePersistentClientOp(
1668 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1669 const PrincipalInfo
& aPrincipalInfo
, Client::Type aClientType
)
1670 : InitializeClientBase(
1671 std::move(aQuotaManager
), "dom::quota::InitializePersistentClientOp",
1672 PERSISTENCE_TYPE_PERSISTENT
, aPrincipalInfo
, aClientType
) {
1673 AssertIsOnOwningThread();
1676 nsresult
InitializePersistentClientOp::DoDirectoryWork(
1677 QuotaManager
& aQuotaManager
) {
1678 AssertIsOnIOThread();
1680 AUTO_PROFILER_LABEL("InitializePersistentClientOp::DoDirectoryWork", OTHER
);
1682 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsStorageInitializedInternal()),
1686 MOZ_TO_RESULT(aQuotaManager
.IsOriginInitialized(mClientMetadata
.mOrigin
)),
1691 (aQuotaManager
.EnsurePersistentClientIsInitialized(mClientMetadata
)
1692 .map([](const auto& res
) { return res
.second
; })));
1697 bool InitializePersistentClientOp::GetResolveValue() {
1698 AssertIsOnOwningThread();
1703 InitializeTemporaryClientOp::InitializeTemporaryClientOp(
1704 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1705 PersistenceType aPersistenceType
, const PrincipalInfo
& aPrincipalInfo
,
1706 Client::Type aClientType
)
1707 : InitializeClientBase(std::move(aQuotaManager
),
1708 "dom::quota::InitializeTemporaryClientOp",
1709 aPersistenceType
, aPrincipalInfo
, aClientType
) {
1710 AssertIsOnOwningThread();
1713 nsresult
InitializeTemporaryClientOp::DoDirectoryWork(
1714 QuotaManager
& aQuotaManager
) {
1715 AssertIsOnIOThread();
1717 AUTO_PROFILER_LABEL("InitializeTemporaryClientOp::DoDirectoryWork", OTHER
);
1719 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsStorageInitializedInternal()),
1722 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.IsTemporaryStorageInitializedInternal()),
1725 QM_TRY(MOZ_TO_RESULT(
1726 aQuotaManager
.IsTemporaryOriginInitialized(mClientMetadata
)),
1731 (aQuotaManager
.EnsureTemporaryClientIsInitialized(mClientMetadata
)
1732 .map([](const auto& res
) { return res
.second
; })));
1737 bool InitializeTemporaryClientOp::GetResolveValue() {
1738 AssertIsOnOwningThread();
1743 GetFullOriginMetadataOp::GetFullOriginMetadataOp(
1744 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
1745 const GetFullOriginMetadataParams
& aParams
)
1746 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1747 "dom::quota::GetFullOriginMetadataOp"),
1749 AssertIsOnOwningThread();
1752 nsresult
GetFullOriginMetadataOp::DoInit(QuotaManager
& aQuotaManager
) {
1753 AssertIsOnOwningThread();
1756 PrincipalMetadata principalMetadata
,
1757 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mParams
.principalInfo()));
1759 principalMetadata
.AssertInvariants();
1761 mOriginMetadata
= {std::move(principalMetadata
), mParams
.persistenceType()};
1766 RefPtr
<BoolPromise
> GetFullOriginMetadataOp::OpenDirectory() {
1767 AssertIsOnOwningThread();
1769 return OpenStorageDirectory(
1770 Nullable
<PersistenceType
>(mOriginMetadata
.mPersistenceType
),
1771 OriginScope::FromOrigin(mOriginMetadata
.mOrigin
),
1772 Nullable
<Client::Type
>(),
1773 /* aExclusive */ false);
1776 nsresult
GetFullOriginMetadataOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1777 AssertIsOnIOThread();
1778 aQuotaManager
.AssertStorageIsInitializedInternal();
1780 AUTO_PROFILER_LABEL("GetFullOriginMetadataOp::DoDirectoryWork", OTHER
);
1782 // Ensure temporary storage is initialized. If temporary storage hasn't
1783 // been initialized yet, the method will initialize it by traversing the
1784 // repositories for temporary and default storage (including our origin).
1785 QM_TRY(MOZ_TO_RESULT(
1786 aQuotaManager
.EnsureTemporaryStorageIsInitializedInternal()));
1788 // Get metadata cached in memory (the method doesn't have to stat any
1790 mMaybeFullOriginMetadata
=
1791 aQuotaManager
.GetFullOriginMetadata(mOriginMetadata
);
1796 void GetFullOriginMetadataOp::GetResponse(RequestResponse
& aResponse
) {
1797 AssertIsOnOwningThread();
1799 aResponse
= GetFullOriginMetadataResponse();
1800 aResponse
.get_GetFullOriginMetadataResponse().maybeFullOriginMetadata() =
1801 std::move(mMaybeFullOriginMetadata
);
1804 void GetFullOriginMetadataOp::CloseDirectory() {
1805 AssertIsOnOwningThread();
1807 mDirectoryLock
= nullptr;
1810 ClearStorageOp::ClearStorageOp(
1811 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
1812 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
1813 "dom::quota::ClearStorageOp") {
1814 AssertIsOnOwningThread();
1817 void ClearStorageOp::DeleteFiles(QuotaManager
& aQuotaManager
) {
1818 AssertIsOnIOThread();
1820 nsresult rv
= aQuotaManager
.AboutToClearOrigins(Nullable
<PersistenceType
>(),
1821 OriginScope::FromNull(),
1822 Nullable
<Client::Type
>());
1823 if (NS_WARN_IF(NS_FAILED(rv
))) {
1827 auto directoryOrErr
= QM_NewLocalFile(aQuotaManager
.GetStoragePath());
1828 if (NS_WARN_IF(directoryOrErr
.isErr())) {
1832 nsCOMPtr
<nsIFile
> directory
= directoryOrErr
.unwrap();
1834 rv
= directory
->Remove(true);
1835 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
1836 // This should never fail if we've closed all storage connections
1838 MOZ_ASSERT(false, "Failed to remove storage directory!");
1842 void ClearStorageOp::DeleteStorageFile(QuotaManager
& aQuotaManager
) {
1843 AssertIsOnIOThread();
1845 QM_TRY_INSPECT(const auto& storageFile
,
1846 QM_NewLocalFile(aQuotaManager
.GetBasePath()), QM_VOID
);
1848 QM_TRY(MOZ_TO_RESULT(storageFile
->Append(aQuotaManager
.GetStorageName() +
1852 const nsresult rv
= storageFile
->Remove(true);
1853 if (rv
!= NS_ERROR_FILE_NOT_FOUND
&& NS_FAILED(rv
)) {
1854 // This should never fail if we've closed the storage connection
1856 MOZ_ASSERT(false, "Failed to remove storage file!");
1860 RefPtr
<BoolPromise
> ClearStorageOp::OpenDirectory() {
1861 AssertIsOnOwningThread();
1863 // Clear directory lock tables (which also saves origin access time) before
1864 // acquiring the exclusive lock below. Otherwise, saving of origin access
1865 // time would be scheduled after storage clearing and that would initialize
1866 // storage again in the end.
1867 mQuotaManager
->ClearDirectoryLockTables();
1869 return OpenStorageDirectory(Nullable
<PersistenceType
>(),
1870 OriginScope::FromNull(), Nullable
<Client::Type
>(),
1871 /* aExclusive */ true);
1874 nsresult
ClearStorageOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
1875 AssertIsOnIOThread();
1876 aQuotaManager
.AssertStorageIsInitializedInternal();
1878 AUTO_PROFILER_LABEL("ClearStorageOp::DoDirectoryWork", OTHER
);
1880 DeleteFiles(aQuotaManager
);
1882 aQuotaManager
.RemoveQuota();
1884 aQuotaManager
.ShutdownStorageInternal();
1886 DeleteStorageFile(aQuotaManager
);
1891 bool ClearStorageOp::GetResolveValue() {
1892 AssertIsOnOwningThread();
1897 void ClearStorageOp::CloseDirectory() {
1898 AssertIsOnOwningThread();
1900 mDirectoryLock
= nullptr;
1903 void ClearRequestBase::DeleteFiles(QuotaManager
& aQuotaManager
,
1904 const OriginMetadata
& aOriginMetadata
,
1905 const Nullable
<Client::Type
>& aClientType
) {
1906 AssertIsOnIOThread();
1908 DeleteFilesInternal(
1909 aQuotaManager
, aOriginMetadata
.mPersistenceType
,
1910 OriginScope::FromOrigin(aOriginMetadata
.mOrigin
), aClientType
,
1911 [&aQuotaManager
, &aOriginMetadata
](
1912 const std::function
<Result
<Ok
, nsresult
>(nsCOMPtr
<nsIFile
>&&)>& aBody
)
1913 -> Result
<Ok
, nsresult
> {
1914 QM_TRY_UNWRAP(auto directory
,
1915 aQuotaManager
.GetOriginDirectory(aOriginMetadata
));
1917 QM_TRY_INSPECT(const bool& exists
,
1918 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
1924 QM_TRY_RETURN(aBody(std::move(directory
)));
1928 void ClearRequestBase::DeleteFiles(QuotaManager
& aQuotaManager
,
1929 PersistenceType aPersistenceType
,
1930 const OriginScope
& aOriginScope
,
1931 const Nullable
<Client::Type
>& aClientType
) {
1932 AssertIsOnIOThread();
1934 DeleteFilesInternal(
1935 aQuotaManager
, aPersistenceType
, aOriginScope
, aClientType
,
1936 [&aQuotaManager
, &aPersistenceType
](
1937 const std::function
<Result
<Ok
, nsresult
>(nsCOMPtr
<nsIFile
>&&)>& aBody
)
1938 -> Result
<Ok
, nsresult
> {
1940 const auto& directory
,
1941 QM_NewLocalFile(aQuotaManager
.GetStoragePath(aPersistenceType
)));
1943 QM_TRY_INSPECT(const bool& exists
,
1944 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
1950 QM_TRY_RETURN(CollectEachFile(*directory
, aBody
));
1954 template <typename FileCollector
>
1955 void ClearRequestBase::DeleteFilesInternal(
1956 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
1957 const OriginScope
& aOriginScope
, const Nullable
<Client::Type
>& aClientType
,
1958 const FileCollector
& aFileCollector
) {
1959 AssertIsOnIOThread();
1961 QM_TRY(MOZ_TO_RESULT(aQuotaManager
.AboutToClearOrigins(
1962 Nullable
<PersistenceType
>(aPersistenceType
), aOriginScope
,
1966 nsTArray
<nsCOMPtr
<nsIFile
>> directoriesForRemovalRetry
;
1968 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
1969 "ClearRequestBase: Starting deleting files"_ns
);
1972 aFileCollector([&aClientType
, &originScope
= aOriginScope
,
1973 aPersistenceType
, &aQuotaManager
,
1974 &directoriesForRemovalRetry
](nsCOMPtr
<nsIFile
>&& file
)
1975 -> mozilla::Result
<Ok
, nsresult
> {
1976 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*file
));
1979 const auto& leafName
,
1980 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, file
, GetLeafName
));
1982 switch (dirEntryKind
) {
1983 case nsIFileKind::ExistsAsDirectory
: {
1984 QM_TRY_UNWRAP(auto maybeMetadata
,
1987 aQuotaManager
.GetOriginMetadata(file
).map(
1988 [](auto metadata
) -> Maybe
<OriginMetadata
> {
1989 return Some(std::move(metadata
));
1992 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
1994 ErrToDefaultOk
<Maybe
<OriginMetadata
>>));
1996 if (!maybeMetadata
) {
1997 // Unknown directories during clearing are allowed. Just
1998 // warn if we find them.
1999 UNKNOWN_FILE_WARNING(leafName
);
2003 auto metadata
= maybeMetadata
.extract();
2005 MOZ_ASSERT(metadata
.mPersistenceType
== aPersistenceType
);
2007 // Skip the origin directory if it doesn't match the pattern.
2008 if (!originScope
.Matches(
2009 OriginScope::FromOrigin(metadata
.mOrigin
))) {
2013 if (!aClientType
.IsNull()) {
2014 nsAutoString clientDirectoryName
;
2015 QM_TRY(OkIf(Client::TypeToText(aClientType
.Value(),
2016 clientDirectoryName
, fallible
)),
2017 Err(NS_ERROR_FAILURE
));
2019 QM_TRY(MOZ_TO_RESULT(file
->Append(clientDirectoryName
)));
2021 QM_TRY_INSPECT(const bool& exists
,
2022 MOZ_TO_RESULT_INVOKE_MEMBER(file
, Exists
));
2029 // We can't guarantee that this will always succeed on
2032 aQuotaManager
.RemoveOriginDirectory(*file
), [&](const auto&) {
2033 directoriesForRemovalRetry
.AppendElement(std::move(file
));
2036 const bool initialized
=
2037 aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
2038 ? aQuotaManager
.IsOriginInitialized(metadata
.mOrigin
)
2039 : aQuotaManager
.IsTemporaryStorageInitializedInternal();
2041 // If it hasn't been initialized, we don't need to update the
2042 // quota and notify the removing client.
2047 if (aPersistenceType
!= PERSISTENCE_TYPE_PERSISTENT
) {
2048 if (aClientType
.IsNull()) {
2049 aQuotaManager
.RemoveQuotaForOrigin(aPersistenceType
, metadata
);
2051 aQuotaManager
.ResetUsageForClient(
2052 ClientMetadata
{metadata
, aClientType
.Value()});
2056 aQuotaManager
.OriginClearCompleted(aPersistenceType
,
2057 metadata
.mOrigin
, aClientType
);
2062 case nsIFileKind::ExistsAsFile
: {
2063 // Unknown files during clearing are allowed. Just warn if we
2065 if (!IsOSMetadata(leafName
)) {
2066 UNKNOWN_FILE_WARNING(leafName
);
2072 case nsIFileKind::DoesNotExist
:
2073 // Ignore files that got removed externally while iterating.
2081 // Retry removing any directories that failed to be removed earlier now.
2083 // XXX This will still block this operation. We might instead dispatch a
2084 // runnable to our own thread for each retry round with a timer. We must
2085 // ensure that the directory lock is upheld until we complete or give up
2087 for (uint32_t index
= 0; index
< 10; index
++) {
2088 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2089 return nsPrintfCString(
2090 "ClearRequestBase: Starting repeated directory removal #%d", index
);
2093 for (auto&& file
: std::exchange(directoriesForRemovalRetry
,
2094 nsTArray
<nsCOMPtr
<nsIFile
>>{})) {
2096 aQuotaManager
.RemoveOriginDirectory(*file
),
2097 ([&directoriesForRemovalRetry
, &file
](const auto&) {
2098 directoriesForRemovalRetry
.AppendElement(std::move(file
));
2102 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2103 return nsPrintfCString(
2104 "ClearRequestBase: Completed repeated directory removal #%d", index
);
2107 if (directoriesForRemovalRetry
.IsEmpty()) {
2111 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2112 return nsPrintfCString("ClearRequestBase: Before sleep #%d", index
);
2115 PR_Sleep(PR_MillisecondsToInterval(200));
2117 aQuotaManager
.MaybeRecordQuotaManagerShutdownStepWith([index
]() {
2118 return nsPrintfCString("ClearRequestBase: After sleep #%d", index
);
2122 QM_WARNONLY_TRY(OkIf(directoriesForRemovalRetry
.IsEmpty()));
2124 aQuotaManager
.MaybeRecordQuotaManagerShutdownStep(
2125 "ClearRequestBase: Completed deleting files"_ns
);
2128 ClearOriginOp::ClearOriginOp(
2129 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2130 const mozilla::Maybe
<PersistenceType
>& aPersistenceType
,
2131 const PrincipalInfo
& aPrincipalInfo
,
2132 const mozilla::Maybe
<Client::Type
>& aClientType
)
2133 : ClearRequestBase(std::move(aQuotaManager
), "dom::quota::ClearOriginOp"),
2134 mPrincipalInfo(aPrincipalInfo
),
2135 mPersistenceType(aPersistenceType
2136 ? Nullable
<PersistenceType
>(*aPersistenceType
)
2137 : Nullable
<PersistenceType
>()),
2138 mClientType(aClientType
? Nullable
<Client::Type
>(*aClientType
)
2139 : Nullable
<Client::Type
>()) {
2140 AssertIsOnOwningThread();
2143 nsresult
ClearOriginOp::DoInit(QuotaManager
& aQuotaManager
) {
2144 AssertIsOnOwningThread();
2148 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo
));
2150 mPrincipalMetadata
.AssertInvariants();
2155 RefPtr
<BoolPromise
> ClearOriginOp::OpenDirectory() {
2156 AssertIsOnOwningThread();
2158 return OpenStorageDirectory(
2159 mPersistenceType
, OriginScope::FromOrigin(mPrincipalMetadata
.mOrigin
),
2161 /* aExclusive */ true);
2164 nsresult
ClearOriginOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2165 AssertIsOnIOThread();
2166 aQuotaManager
.AssertStorageIsInitializedInternal();
2168 AUTO_PROFILER_LABEL("ClearRequestBase::DoDirectoryWork", OTHER
);
2170 if (mPersistenceType
.IsNull()) {
2171 for (const PersistenceType type
: kAllPersistenceTypes
) {
2172 DeleteFiles(aQuotaManager
, OriginMetadata(mPrincipalMetadata
, type
),
2176 DeleteFiles(aQuotaManager
,
2177 OriginMetadata(mPrincipalMetadata
, mPersistenceType
.Value()),
2184 bool ClearOriginOp::GetResolveValue() {
2185 AssertIsOnOwningThread();
2190 void ClearOriginOp::CloseDirectory() {
2191 AssertIsOnOwningThread();
2193 mDirectoryLock
= nullptr;
2196 ClearStoragesForOriginPrefixOp::ClearStoragesForOriginPrefixOp(
2197 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2198 const Maybe
<PersistenceType
>& aPersistenceType
,
2199 const PrincipalInfo
& aPrincipalInfo
)
2200 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2201 "dom::quota::ClearStoragesForOriginPrefixOp"),
2203 QuotaManager::GetOriginFromValidatedPrincipalInfo(aPrincipalInfo
)),
2204 mPersistenceType(aPersistenceType
2205 ? Nullable
<PersistenceType
>(*aPersistenceType
)
2206 : Nullable
<PersistenceType
>()) {
2207 AssertIsOnOwningThread();
2210 RefPtr
<BoolPromise
> ClearStoragesForOriginPrefixOp::OpenDirectory() {
2211 AssertIsOnOwningThread();
2213 return OpenStorageDirectory(mPersistenceType
,
2214 OriginScope::FromPrefix(mPrefix
),
2215 Nullable
<Client::Type
>(),
2216 /* aExclusive */ true);
2219 nsresult
ClearStoragesForOriginPrefixOp::DoDirectoryWork(
2220 QuotaManager
& aQuotaManager
) {
2221 AssertIsOnIOThread();
2223 AUTO_PROFILER_LABEL("ClearStoragesForOriginPrefixOp::DoDirectoryWork", OTHER
);
2225 if (mPersistenceType
.IsNull()) {
2226 for (const PersistenceType type
: kAllPersistenceTypes
) {
2227 DeleteFiles(aQuotaManager
, type
, OriginScope::FromPrefix(mPrefix
),
2228 Nullable
<Client::Type
>());
2231 DeleteFiles(aQuotaManager
, mPersistenceType
.Value(),
2232 OriginScope::FromPrefix(mPrefix
), Nullable
<Client::Type
>());
2238 bool ClearStoragesForOriginPrefixOp::GetResolveValue() {
2239 AssertIsOnOwningThread();
2244 void ClearStoragesForOriginPrefixOp::CloseDirectory() {
2245 AssertIsOnOwningThread();
2247 mDirectoryLock
= nullptr;
2250 ClearDataOp::ClearDataOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2251 const OriginAttributesPattern
& aPattern
)
2252 : ClearRequestBase(std::move(aQuotaManager
), "dom::quota::ClearDataOp"),
2253 mPattern(aPattern
) {}
2255 RefPtr
<BoolPromise
> ClearDataOp::OpenDirectory() {
2256 AssertIsOnOwningThread();
2258 return OpenStorageDirectory(Nullable
<PersistenceType
>(),
2259 OriginScope::FromPattern(mPattern
),
2260 Nullable
<Client::Type
>(),
2261 /* aExclusive */ true);
2264 nsresult
ClearDataOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2265 AssertIsOnIOThread();
2267 AUTO_PROFILER_LABEL("ClearRequestBase::DoDirectoryWork", OTHER
);
2269 for (const PersistenceType type
: kAllPersistenceTypes
) {
2270 DeleteFiles(aQuotaManager
, type
, OriginScope::FromPattern(mPattern
),
2271 Nullable
<Client::Type
>());
2277 bool ClearDataOp::GetResolveValue() {
2278 AssertIsOnOwningThread();
2283 void ClearDataOp::CloseDirectory() {
2284 AssertIsOnOwningThread();
2286 mDirectoryLock
= nullptr;
2289 ResetOriginOp::ResetOriginOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2290 const RequestParams
& aParams
)
2291 : QuotaRequestBase(std::move(aQuotaManager
), "dom::quota::ResetOriginOp") {
2292 AssertIsOnOwningThread();
2293 MOZ_ASSERT(aParams
.type() == RequestParams::TResetOriginParams
);
2295 const ClearResetOriginParams
& params
=
2296 aParams
.get_ResetOriginParams().commonParams();
2299 QuotaManager::GetOriginFromValidatedPrincipalInfo(params
.principalInfo());
2301 if (params
.persistenceTypeIsExplicit()) {
2302 mPersistenceType
.SetValue(params
.persistenceType());
2305 if (params
.clientTypeIsExplicit()) {
2306 mClientType
.SetValue(params
.clientType());
2310 RefPtr
<BoolPromise
> ResetOriginOp::OpenDirectory() {
2311 AssertIsOnOwningThread();
2313 mDirectoryLock
= mQuotaManager
->CreateDirectoryLockInternal(
2314 mPersistenceType
, OriginScope::FromOrigin(mOrigin
), mClientType
,
2315 /* aExclusive */ true);
2317 return mDirectoryLock
->Acquire();
2320 nsresult
ResetOriginOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2321 AssertIsOnIOThread();
2323 AUTO_PROFILER_LABEL("ResetOriginOp::DoDirectoryWork", OTHER
);
2325 // All the work is handled by NormalOriginOperationBase parent class. In
2326 // this particular case, we just needed to acquire an exclusive directory
2327 // lock and that's it.
2332 void ResetOriginOp::GetResponse(RequestResponse
& aResponse
) {
2333 AssertIsOnOwningThread();
2335 aResponse
= ResetOriginResponse();
2338 void ResetOriginOp::CloseDirectory() {
2339 AssertIsOnOwningThread();
2341 mDirectoryLock
= nullptr;
2344 PersistRequestBase::PersistRequestBase(
2345 MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2346 const PrincipalInfo
& aPrincipalInfo
)
2347 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2348 "dom::quota::PersistRequestBase"),
2349 mPrincipalInfo(aPrincipalInfo
) {
2350 AssertIsOnOwningThread();
2353 nsresult
PersistRequestBase::DoInit(QuotaManager
& aQuotaManager
) {
2354 AssertIsOnOwningThread();
2356 // Figure out which origin we're dealing with.
2359 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mPrincipalInfo
));
2361 mPrincipalMetadata
.AssertInvariants();
2366 RefPtr
<BoolPromise
> PersistRequestBase::OpenDirectory() {
2367 AssertIsOnOwningThread();
2369 return OpenStorageDirectory(
2370 Nullable
<PersistenceType
>(PERSISTENCE_TYPE_DEFAULT
),
2371 OriginScope::FromOrigin(mPrincipalMetadata
.mOrigin
),
2372 Nullable
<Client::Type
>(),
2373 /* aExclusive */ false);
2376 void PersistRequestBase::CloseDirectory() {
2377 AssertIsOnOwningThread();
2379 mDirectoryLock
= nullptr;
2382 PersistedOp::PersistedOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2383 const RequestParams
& aParams
)
2384 : PersistRequestBase(std::move(aQuotaManager
),
2385 aParams
.get_PersistedParams().principalInfo()),
2387 MOZ_ASSERT(aParams
.type() == RequestParams::TPersistedParams
);
2390 nsresult
PersistedOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2391 AssertIsOnIOThread();
2392 aQuotaManager
.AssertStorageIsInitializedInternal();
2394 AUTO_PROFILER_LABEL("PersistedOp::DoDirectoryWork", OTHER
);
2396 const OriginMetadata originMetadata
= {mPrincipalMetadata
,
2397 PERSISTENCE_TYPE_DEFAULT
};
2399 Nullable
<bool> persisted
= aQuotaManager
.OriginPersisted(originMetadata
);
2401 if (!persisted
.IsNull()) {
2402 mPersisted
= persisted
.Value();
2406 // If we get here, it means the origin hasn't been initialized yet.
2407 // Try to get the persisted flag from directory metadata on disk.
2409 QM_TRY_INSPECT(const auto& directory
,
2410 aQuotaManager
.GetOriginDirectory(originMetadata
));
2412 QM_TRY_INSPECT(const bool& exists
,
2413 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
2416 // Get the metadata. We only use the persisted flag.
2417 QM_TRY_INSPECT(const auto& metadata
,
2418 aQuotaManager
.LoadFullOriginMetadataWithRestore(directory
));
2420 mPersisted
= metadata
.mPersisted
;
2422 // The directory has not been created yet.
2429 void PersistedOp::GetResponse(RequestResponse
& aResponse
) {
2430 AssertIsOnOwningThread();
2432 PersistedResponse persistedResponse
;
2433 persistedResponse
.persisted() = mPersisted
;
2435 aResponse
= persistedResponse
;
2438 PersistOp::PersistOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2439 const RequestParams
& aParams
)
2440 : PersistRequestBase(std::move(aQuotaManager
),
2441 aParams
.get_PersistParams().principalInfo()) {
2442 MOZ_ASSERT(aParams
.type() == RequestParams::TPersistParams
);
2445 nsresult
PersistOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2446 AssertIsOnIOThread();
2447 aQuotaManager
.AssertStorageIsInitializedInternal();
2449 const OriginMetadata originMetadata
= {mPrincipalMetadata
,
2450 PERSISTENCE_TYPE_DEFAULT
};
2452 AUTO_PROFILER_LABEL("PersistOp::DoDirectoryWork", OTHER
);
2454 // Update directory metadata on disk first. Then, create/update the
2455 // originInfo if needed.
2456 QM_TRY_INSPECT(const auto& directory
,
2457 aQuotaManager
.GetOriginDirectory(originMetadata
));
2459 QM_TRY_INSPECT(const bool& created
,
2460 aQuotaManager
.EnsureOriginDirectory(*directory
));
2465 // Origin directory has been successfully created.
2466 // Create OriginInfo too if temporary storage was already initialized.
2467 if (aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
2468 timestamp
= aQuotaManager
.NoteOriginDirectoryCreated(
2469 originMetadata
, /* aPersisted */ true);
2471 timestamp
= PR_Now();
2474 QM_TRY(MOZ_TO_RESULT(QuotaManager::CreateDirectoryMetadata2(
2475 *directory
, timestamp
,
2476 /* aPersisted */ true, originMetadata
)));
2478 // Get the metadata (restore the metadata file if necessary). We only use
2479 // the persisted flag.
2480 QM_TRY_INSPECT(const auto& metadata
,
2481 aQuotaManager
.LoadFullOriginMetadataWithRestore(directory
));
2483 if (!metadata
.mPersisted
) {
2484 QM_TRY_INSPECT(const auto& file
,
2486 *directory
, nsLiteralString(METADATA_V2_FILE_NAME
)));
2488 QM_TRY_INSPECT(const auto& stream
,
2489 GetBinaryOutputStream(*file
, FileFlag::Update
));
2493 // Update origin access time while we are here.
2494 QM_TRY(MOZ_TO_RESULT(stream
->Write64(PR_Now())));
2496 // Set the persisted flag to true.
2497 QM_TRY(MOZ_TO_RESULT(stream
->WriteBoolean(true)));
2500 // Directory metadata has been successfully updated.
2501 // Update OriginInfo too if temporary storage was already initialized.
2502 if (aQuotaManager
.IsTemporaryStorageInitializedInternal()) {
2503 aQuotaManager
.PersistOrigin(originMetadata
);
2510 void PersistOp::GetResponse(RequestResponse
& aResponse
) {
2511 AssertIsOnOwningThread();
2513 aResponse
= PersistResponse();
2516 EstimateOp::EstimateOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
,
2517 const EstimateParams
& aParams
)
2518 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2519 "dom::quota::EstimateOp"),
2521 AssertIsOnOwningThread();
2524 nsresult
EstimateOp::DoInit(QuotaManager
& aQuotaManager
) {
2525 AssertIsOnOwningThread();
2528 PrincipalMetadata principalMetadata
,
2529 aQuotaManager
.GetInfoFromValidatedPrincipalInfo(mParams
.principalInfo()));
2531 principalMetadata
.AssertInvariants();
2533 mOriginMetadata
= {std::move(principalMetadata
), PERSISTENCE_TYPE_DEFAULT
};
2538 RefPtr
<BoolPromise
> EstimateOp::OpenDirectory() {
2539 AssertIsOnOwningThread();
2541 // XXX In theory, we should be locking entire group, not just one origin.
2542 return OpenStorageDirectory(
2543 Nullable
<PersistenceType
>(mOriginMetadata
.mPersistenceType
),
2544 OriginScope::FromOrigin(mOriginMetadata
.mOrigin
),
2545 Nullable
<Client::Type
>(),
2546 /* aExclusive */ false);
2549 nsresult
EstimateOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2550 AssertIsOnIOThread();
2551 aQuotaManager
.AssertStorageIsInitializedInternal();
2553 AUTO_PROFILER_LABEL("EstimateOp::DoDirectoryWork", OTHER
);
2555 // Ensure temporary storage is initialized. If temporary storage hasn't been
2556 // initialized yet, the method will initialize it by traversing the
2557 // repositories for temporary and default storage (including origins
2558 // belonging to our group).
2559 QM_TRY(MOZ_TO_RESULT(
2560 aQuotaManager
.EnsureTemporaryStorageIsInitializedInternal()));
2562 // Get cached usage (the method doesn't have to stat any files).
2563 mUsageAndLimit
= aQuotaManager
.GetUsageAndLimitForEstimate(mOriginMetadata
);
2568 void EstimateOp::GetResponse(RequestResponse
& aResponse
) {
2569 AssertIsOnOwningThread();
2571 EstimateResponse estimateResponse
;
2573 estimateResponse
.usage() = mUsageAndLimit
.first
;
2574 estimateResponse
.limit() = mUsageAndLimit
.second
;
2576 aResponse
= estimateResponse
;
2579 void EstimateOp::CloseDirectory() {
2580 AssertIsOnOwningThread();
2582 mDirectoryLock
= nullptr;
2585 ListOriginsOp::ListOriginsOp(MovingNotNull
<RefPtr
<QuotaManager
>> aQuotaManager
)
2586 : OpenStorageDirectoryHelper(std::move(aQuotaManager
),
2587 "dom::quota::ListOriginsOp") {
2588 AssertIsOnOwningThread();
2591 RefPtr
<BoolPromise
> ListOriginsOp::OpenDirectory() {
2592 AssertIsOnOwningThread();
2594 return OpenStorageDirectory(Nullable
<PersistenceType
>(),
2595 OriginScope::FromNull(), Nullable
<Client::Type
>(),
2596 /* aExclusive */ false);
2599 nsresult
ListOriginsOp::DoDirectoryWork(QuotaManager
& aQuotaManager
) {
2600 AssertIsOnIOThread();
2601 aQuotaManager
.AssertStorageIsInitializedInternal();
2603 AUTO_PROFILER_LABEL("ListOriginsOp::DoDirectoryWork", OTHER
);
2605 for (const PersistenceType type
: kAllPersistenceTypes
) {
2606 QM_TRY(MOZ_TO_RESULT(TraverseRepository(aQuotaManager
, type
)));
2609 // TraverseRepository above only consulted the file-system to get a list of
2610 // known origins, but we also need to include origins that have pending
2613 aQuotaManager
.CollectPendingOriginsForListing([this](const auto& originInfo
) {
2614 mOrigins
.AppendElement(originInfo
->Origin());
2620 const Atomic
<bool>& ListOriginsOp::GetIsCanceledFlag() {
2621 AssertIsOnIOThread();
2626 nsresult
ListOriginsOp::ProcessOrigin(QuotaManager
& aQuotaManager
,
2627 nsIFile
& aOriginDir
,
2628 const bool aPersistent
,
2629 const PersistenceType aPersistenceType
) {
2630 AssertIsOnIOThread();
2632 QM_TRY_UNWRAP(auto maybeMetadata
,
2635 aQuotaManager
.GetOriginMetadata(&aOriginDir
)
2636 .map([](auto metadata
) -> Maybe
<OriginMetadata
> {
2637 return Some(std::move(metadata
));
2640 IsSpecificError
<NS_ERROR_MALFORMED_URI
>,
2642 ErrToDefaultOk
<Maybe
<OriginMetadata
>>));
2644 if (!maybeMetadata
) {
2645 // Unknown directories during listing are allowed. Just warn if we find
2647 QM_TRY_INSPECT(const auto& leafName
,
2648 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, aOriginDir
,
2651 UNKNOWN_FILE_WARNING(leafName
);
2655 auto metadata
= maybeMetadata
.extract();
2657 if (aQuotaManager
.IsOriginInternal(metadata
.mOrigin
)) {
2661 mOrigins
.AppendElement(std::move(metadata
.mOrigin
));
2666 void ListOriginsOp::GetResponse(RequestResponse
& aResponse
) {
2667 AssertIsOnOwningThread();
2669 aResponse
= ListOriginsResponse();
2670 if (mOrigins
.IsEmpty()) {
2674 nsTArray
<nsCString
>& origins
= aResponse
.get_ListOriginsResponse().origins();
2675 mOrigins
.SwapElements(origins
);
2678 void ListOriginsOp::CloseDirectory() {
2679 AssertIsOnOwningThread();
2681 mDirectoryLock
= nullptr;
2684 } // namespace mozilla::dom::quota