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 "QuotaUsageRequestBase.h"
9 #include "mozilla/dom/quota/Assertions.h"
10 #include "mozilla/dom/quota/CommonMetadata.h"
11 #include "mozilla/dom/quota/FileUtils.h"
12 #include "mozilla/dom/quota/PQuotaRequest.h"
13 #include "mozilla/dom/quota/QuotaCommon.h"
14 #include "mozilla/dom/quota/QuotaManager.h"
15 #include "mozilla/dom/quota/ResultExtensions.h"
16 #include "mozilla/dom/quota/UsageInfo.h"
19 namespace mozilla::dom::quota
{
21 Result
<UsageInfo
, nsresult
> QuotaUsageRequestBase::GetUsageForOrigin(
22 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
23 const OriginMetadata
& aOriginMetadata
) {
25 MOZ_ASSERT(aOriginMetadata
.mPersistenceType
== aPersistenceType
);
27 QM_TRY_INSPECT(const auto& directory
,
28 aQuotaManager
.GetOriginDirectory(aOriginMetadata
));
30 QM_TRY_INSPECT(const bool& exists
,
31 MOZ_TO_RESULT_INVOKE_MEMBER(directory
, Exists
));
33 if (!exists
|| mCanceled
) {
37 // If the directory exists then enumerate all the files inside, adding up
38 // the sizes to get the final usage statistic.
41 if (aPersistenceType
== PERSISTENCE_TYPE_PERSISTENT
) {
42 initialized
= aQuotaManager
.IsOriginInitialized(aOriginMetadata
.mOrigin
);
44 initialized
= aQuotaManager
.IsTemporaryStorageInitializedInternal();
47 return GetUsageForOriginEntries(aQuotaManager
, aPersistenceType
,
48 aOriginMetadata
, *directory
, initialized
);
51 Result
<UsageInfo
, nsresult
> QuotaUsageRequestBase::GetUsageForOriginEntries(
52 QuotaManager
& aQuotaManager
, PersistenceType aPersistenceType
,
53 const OriginMetadata
& aOriginMetadata
, nsIFile
& aDirectory
,
54 const bool aInitialized
) {
57 QM_TRY_RETURN((ReduceEachFileAtomicCancelable(
58 aDirectory
, mCanceled
, UsageInfo
{},
59 [&](UsageInfo oldUsageInfo
, const nsCOMPtr
<nsIFile
>& file
)
60 -> mozilla::Result
<UsageInfo
, nsresult
> {
63 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString
, file
, GetLeafName
));
65 QM_TRY_INSPECT(const auto& dirEntryKind
, GetDirEntryKind(*file
));
67 switch (dirEntryKind
) {
68 case nsIFileKind::ExistsAsDirectory
: {
69 Client::Type clientType
;
71 Client::TypeFromText(leafName
, clientType
, fallible
);
73 // Unknown directories during getting usage for an origin (even
74 // for an uninitialized origin) are now allowed. Just warn if we
76 UNKNOWN_FILE_WARNING(leafName
);
80 Client
* const client
= aQuotaManager
.GetClient(clientType
);
84 const auto& usageInfo
,
85 aInitialized
? client
->GetUsageForOrigin(
86 aPersistenceType
, aOriginMetadata
, mCanceled
)
87 : client
->InitOrigin(aPersistenceType
,
88 aOriginMetadata
, mCanceled
));
89 return oldUsageInfo
+ usageInfo
;
92 case nsIFileKind::ExistsAsFile
:
93 // We are maintaining existing behavior for unknown files here (just
95 // This can possibly be used by developers to add temporary backups
96 // into origin directories without losing get usage functionality.
97 if (IsTempMetadata(leafName
)) {
99 QM_TRY(MOZ_TO_RESULT(file
->Remove(/* recursive */ false)));
105 if (IsOriginMetadata(leafName
) || IsOSMetadata(leafName
) ||
106 IsDotFile(leafName
)) {
110 // Unknown files during getting usage for an origin (even for an
111 // uninitialized origin) are now allowed. Just warn if we find them.
112 UNKNOWN_FILE_WARNING(leafName
);
115 case nsIFileKind::DoesNotExist
:
116 // Ignore files that got removed externally while iterating.
124 void QuotaUsageRequestBase::SendResults() {
125 AssertIsOnOwningThread();
127 if (IsActorDestroyed()) {
128 if (NS_SUCCEEDED(mResultCode
)) {
129 mResultCode
= NS_ERROR_FAILURE
;
133 mResultCode
= NS_ERROR_FAILURE
;
136 UsageRequestResponse response
;
138 if (NS_SUCCEEDED(mResultCode
)) {
139 GetResponse(response
);
141 response
= mResultCode
;
144 Unused
<< PQuotaUsageRequestParent::Send__delete__(this, response
);
148 void QuotaUsageRequestBase::ActorDestroy(ActorDestroyReason aWhy
) {
149 AssertIsOnOwningThread();
151 NoteActorDestroyed();
154 mozilla::ipc::IPCResult
QuotaUsageRequestBase::RecvCancel() {
155 AssertIsOnOwningThread();
157 if (mCanceled
.exchange(true)) {
158 NS_WARNING("Canceled more than once?!");
159 return IPC_FAIL(this, "Request canceled more than once");
165 } // namespace mozilla::dom::quota