file_system_quota_client.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "storage/browser/file_system/file_system_quota_client.h"
  5. #include <numeric>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/barrier_callback.h"
  10. #include "base/barrier_closure.h"
  11. #include "base/bind.h"
  12. #include "base/check.h"
  13. #include "base/containers/span.h"
  14. #include "base/files/file.h"
  15. #include "base/location.h"
  16. #include "base/sequence_checker.h"
  17. #include "base/task/sequenced_task_runner.h"
  18. #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
  19. #include "storage/browser/file_system/file_system_backend.h"
  20. #include "storage/browser/file_system/file_system_context.h"
  21. #include "storage/common/file_system/file_system_types.h"
  22. #include "storage/common/file_system/file_system_util.h"
  23. #include "third_party/blink/public/common/features.h"
  24. #include "third_party/blink/public/common/storage_key/storage_key.h"
  25. #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
  26. namespace storage {
  27. namespace {
  28. static const FileSystemType kTemporaryAndPersistent[] = {
  29. kFileSystemTypeTemporary,
  30. kFileSystemTypePersistent,
  31. };
  32. static const FileSystemType kTemporary[] = {kFileSystemTypeTemporary};
  33. static const FileSystemType kPersistent[] = {kFileSystemTypePersistent};
  34. static const FileSystemType kSyncable[] = {kFileSystemTypeSyncable};
  35. template <typename T>
  36. std::vector<T> MergeWithoutDuplicates(const std::vector<std::vector<T>>& tss) {
  37. if (tss.size() == 1) {
  38. // We assume that each vector contains no duplicates, already.
  39. return tss[0];
  40. }
  41. std::vector<T> merged;
  42. merged.reserve(std::accumulate(
  43. tss.begin(), tss.end(), 0U,
  44. [](size_t acc, const std::vector<T>& ts) { return acc + ts.size(); }));
  45. for (const auto& ts : tss) {
  46. merged.insert(merged.end(), ts.begin(), ts.end());
  47. }
  48. base::ranges::sort(merged);
  49. merged.erase(base::ranges::unique(merged), merged.end());
  50. return merged;
  51. }
  52. // Converts StorageType to the FileSystemTypes that are used for that quota
  53. // type.
  54. base::span<const FileSystemType> QuotaStorageTypeToFileSystemTypes(
  55. blink::mojom::StorageType storage_type) {
  56. using StorageType = blink::mojom::StorageType;
  57. if (blink::features::IsPersistentQuotaIsTemporaryQuota()) {
  58. DCHECK_NE(storage_type, StorageType::kPersistent);
  59. if (storage_type == StorageType::kTemporary)
  60. return kTemporaryAndPersistent;
  61. }
  62. switch (storage_type) {
  63. case StorageType::kTemporary:
  64. return kTemporary;
  65. case StorageType::kPersistent:
  66. return kPersistent;
  67. case StorageType::kSyncable:
  68. return kSyncable;
  69. case StorageType::kDeprecatedQuotaNotManaged:
  70. case StorageType::kUnknown:
  71. NOTREACHED();
  72. return {};
  73. }
  74. }
  75. std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner(
  76. FileSystemContext* context,
  77. FileSystemType type) {
  78. FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type);
  79. if (!quota_util)
  80. return {};
  81. return quota_util->GetStorageKeysForTypeOnFileTaskRunner(type);
  82. }
  83. blink::mojom::QuotaStatusCode DeleteBucketOnFileTaskRunner(
  84. FileSystemContext* context,
  85. const BucketLocator& bucket_locator,
  86. FileSystemType type) {
  87. FileSystemBackend* provider = context->GetFileSystemBackend(type);
  88. if (!provider || !provider->GetQuotaUtil())
  89. return blink::mojom::QuotaStatusCode::kErrorNotSupported;
  90. base::File::Error result =
  91. provider->GetQuotaUtil()->DeleteBucketDataOnFileTaskRunner(
  92. context, context->quota_manager_proxy().get(), bucket_locator, type);
  93. if (result == base::File::FILE_OK)
  94. return blink::mojom::QuotaStatusCode::kOk;
  95. return blink::mojom::QuotaStatusCode::kErrorInvalidModification;
  96. }
  97. void PerformStorageCleanupOnFileTaskRunner(FileSystemContext* context,
  98. FileSystemType type) {
  99. FileSystemBackend* provider = context->GetFileSystemBackend(type);
  100. if (!provider || !provider->GetQuotaUtil())
  101. return;
  102. provider->GetQuotaUtil()->PerformStorageCleanupOnFileTaskRunner(
  103. context, context->quota_manager_proxy().get(), type);
  104. }
  105. } // namespace
  106. FileSystemQuotaClient::FileSystemQuotaClient(
  107. FileSystemContext* file_system_context)
  108. : file_system_context_(file_system_context) {
  109. DCHECK(file_system_context_);
  110. DETACH_FROM_SEQUENCE(sequence_checker_);
  111. }
  112. FileSystemQuotaClient::~FileSystemQuotaClient() {
  113. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  114. }
  115. void FileSystemQuotaClient::GetBucketUsage(const BucketLocator& bucket,
  116. GetBucketUsageCallback callback) {
  117. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  118. DCHECK(!callback.is_null());
  119. base::span<const FileSystemType> types =
  120. QuotaStorageTypeToFileSystemTypes(bucket.type);
  121. base::RepeatingCallback<void(int64_t)> barrier =
  122. base::BarrierCallback<int64_t>(
  123. types.size(), base::BindOnce([](std::vector<int64_t> usages) {
  124. return std::accumulate(usages.begin(), usages.end(),
  125. 0U);
  126. }).Then(std::move(callback)));
  127. for (auto type : types) {
  128. FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type);
  129. if (quota_util) {
  130. file_task_runner()->PostTaskAndReplyWithResult(
  131. FROM_HERE,
  132. // It is safe to pass Unretained(quota_util) since context owns it.
  133. base::BindOnce(&FileSystemQuotaUtil::GetBucketUsageOnFileTaskRunner,
  134. base::Unretained(quota_util),
  135. base::RetainedRef(file_system_context_.get()), bucket,
  136. type),
  137. barrier);
  138. } else {
  139. barrier.Run(0);
  140. }
  141. }
  142. }
  143. void FileSystemQuotaClient::GetStorageKeysForType(
  144. blink::mojom::StorageType storage_type,
  145. GetStorageKeysForTypeCallback callback) {
  146. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  147. DCHECK(!callback.is_null());
  148. base::span<const FileSystemType> types =
  149. QuotaStorageTypeToFileSystemTypes(storage_type);
  150. base::RepeatingCallback<void(std::vector<blink::StorageKey>)> barrier =
  151. base::BarrierCallback<std::vector<blink::StorageKey>>(
  152. types.size(),
  153. base::BindOnce(&MergeWithoutDuplicates<blink::StorageKey>)
  154. .Then(std::move(callback)));
  155. for (auto type : types) {
  156. file_task_runner()->PostTaskAndReplyWithResult(
  157. FROM_HERE,
  158. base::BindOnce(&GetStorageKeysForTypeOnFileTaskRunner,
  159. base::RetainedRef(file_system_context_.get()), type),
  160. barrier);
  161. }
  162. }
  163. void FileSystemQuotaClient::DeleteBucketData(
  164. const BucketLocator& bucket,
  165. DeleteBucketDataCallback callback) {
  166. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  167. DCHECK(!callback.is_null());
  168. base::span<const FileSystemType> fs_types =
  169. QuotaStorageTypeToFileSystemTypes(bucket.type);
  170. base::RepeatingCallback<void(blink::mojom::QuotaStatusCode)> barrier =
  171. base::BarrierCallback<blink::mojom::QuotaStatusCode>(
  172. fs_types.size(),
  173. base::BindOnce([](const std::vector<blink::mojom::QuotaStatusCode>&
  174. statuses) {
  175. for (auto status : statuses) {
  176. if (status != blink::mojom::QuotaStatusCode::kOk)
  177. return status;
  178. }
  179. return blink::mojom::QuotaStatusCode::kOk;
  180. }).Then(std::move(callback)));
  181. for (const auto fs_type : fs_types) {
  182. file_task_runner()->PostTaskAndReplyWithResult(
  183. FROM_HERE,
  184. base::BindOnce(&DeleteBucketOnFileTaskRunner,
  185. base::RetainedRef(file_system_context_.get()), bucket,
  186. fs_type),
  187. barrier);
  188. }
  189. }
  190. void FileSystemQuotaClient::PerformStorageCleanup(
  191. blink::mojom::StorageType type,
  192. PerformStorageCleanupCallback callback) {
  193. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  194. DCHECK(!callback.is_null());
  195. base::span<const FileSystemType> fs_types =
  196. QuotaStorageTypeToFileSystemTypes(type);
  197. base::RepeatingClosure barrier =
  198. base::BarrierClosure(fs_types.size(), std::move(callback));
  199. for (auto fs_type : fs_types) {
  200. file_task_runner()->PostTaskAndReply(
  201. FROM_HERE,
  202. base::BindOnce(&PerformStorageCleanupOnFileTaskRunner,
  203. base::RetainedRef(file_system_context_.get()), fs_type),
  204. barrier);
  205. }
  206. }
  207. base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const {
  208. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  209. return file_system_context_->default_file_task_runner();
  210. }
  211. } // namespace storage