Bug 1874684 - Part 6: Limit day length calculations to safe integers. r=mgaudet
[gecko.git] / dom / quota / QuotaUsageRequestBase.cpp
blob17b37cbf290b69fec8d1c0032a5d8a9a4c0956a6
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"
17 #include "nsIFile.h"
19 namespace mozilla::dom::quota {
21 Result<UsageInfo, nsresult> QuotaUsageRequestBase::GetUsageForOrigin(
22 QuotaManager& aQuotaManager, PersistenceType aPersistenceType,
23 const OriginMetadata& aOriginMetadata) {
24 AssertIsOnIOThread();
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) {
34 return UsageInfo();
37 // If the directory exists then enumerate all the files inside, adding up
38 // the sizes to get the final usage statistic.
39 bool initialized;
41 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
42 initialized = aQuotaManager.IsOriginInitialized(aOriginMetadata.mOrigin);
43 } else {
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) {
55 AssertIsOnIOThread();
57 QM_TRY_RETURN((ReduceEachFileAtomicCancelable(
58 aDirectory, mCanceled, UsageInfo{},
59 [&](UsageInfo oldUsageInfo, const nsCOMPtr<nsIFile>& file)
60 -> mozilla::Result<UsageInfo, nsresult> {
61 QM_TRY_INSPECT(
62 const auto& leafName,
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;
70 const bool ok =
71 Client::TypeFromText(leafName, clientType, fallible);
72 if (!ok) {
73 // Unknown directories during getting usage for an origin (even
74 // for an uninitialized origin) are now allowed. Just warn if we
75 // find them.
76 UNKNOWN_FILE_WARNING(leafName);
77 break;
80 Client* const client = aQuotaManager.GetClient(clientType);
81 MOZ_ASSERT(client);
83 QM_TRY_INSPECT(
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
94 // continuing).
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)) {
98 if (!aInitialized) {
99 QM_TRY(MOZ_TO_RESULT(file->Remove(/* recursive */ false)));
102 break;
105 if (IsOriginMetadata(leafName) || IsOSMetadata(leafName) ||
106 IsDotFile(leafName)) {
107 break;
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);
113 break;
115 case nsIFileKind::DoesNotExist:
116 // Ignore files that got removed externally while iterating.
117 break;
120 return oldUsageInfo;
121 })));
124 void QuotaUsageRequestBase::SendResults() {
125 AssertIsOnOwningThread();
127 if (IsActorDestroyed()) {
128 if (NS_SUCCEEDED(mResultCode)) {
129 mResultCode = NS_ERROR_FAILURE;
131 } else {
132 if (mCanceled) {
133 mResultCode = NS_ERROR_FAILURE;
136 UsageRequestResponse response;
138 if (NS_SUCCEEDED(mResultCode)) {
139 GetResponse(response);
140 } else {
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");
162 return IPC_OK();
165 } // namespace mozilla::dom::quota