archive_manager.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright 2016 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 "components/offline_pages/core/archive_manager.h"
  5. #include "base/bind.h"
  6. #include "base/callback.h"
  7. #include "base/files/file_enumerator.h"
  8. #include "base/files/file_util.h"
  9. #include "base/location.h"
  10. #include "base/logging.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/metrics/histogram_macros.h"
  13. #include "base/strings/utf_string_conversions.h"
  14. #include "base/system/sys_info.h"
  15. #include "base/task/sequenced_task_runner.h"
  16. #include "base/threading/thread_task_runner_handle.h"
  17. #include "build/build_config.h"
  18. namespace offline_pages {
  19. namespace {
  20. using StorageStatsCallback =
  21. base::OnceCallback<void(const ArchiveManager::StorageStats& storage_stats)>;
  22. void EnsureArchivesDirCreatedImpl(const base::FilePath& archives_dir,
  23. bool is_temp) {
  24. base::File::Error error = base::File::FILE_OK;
  25. if (!base::DirectoryExists(archives_dir)) {
  26. if (!base::CreateDirectoryAndGetError(archives_dir, &error)) {
  27. LOG(ERROR) << "Failed to create offline pages archive directory: "
  28. << base::File::ErrorToString(error);
  29. }
  30. if (is_temp) {
  31. UMA_HISTOGRAM_ENUMERATION(
  32. "OfflinePages.ArchiveManager.ArchiveDirsCreationResult2.Temporary",
  33. -error, -base::File::FILE_ERROR_MAX);
  34. } else {
  35. UMA_HISTOGRAM_ENUMERATION(
  36. "OfflinePages.ArchiveManager.ArchiveDirsCreationResult2.Persistent",
  37. -error, -base::File::FILE_ERROR_MAX);
  38. }
  39. }
  40. }
  41. void GetStorageStatsImpl(const base::FilePath& temporary_archives_dir,
  42. const base::FilePath& private_archives_dir,
  43. const base::FilePath& public_archives_dir,
  44. scoped_refptr<base::SequencedTaskRunner> task_runner,
  45. StorageStatsCallback callback) {
  46. ArchiveManager::StorageStats storage_stats = {0, 0, 0, 0, 0};
  47. // Getting the free disk space of the volume that contains the temporary
  48. // archives directory. This value will be -1 if the directory is invalid.
  49. // Currently both temporary and private archive directories are in the
  50. // internal storage.
  51. storage_stats.internal_free_disk_space =
  52. base::SysInfo::AmountOfFreeDiskSpace(temporary_archives_dir);
  53. storage_stats.external_free_disk_space =
  54. base::SysInfo::AmountOfFreeDiskSpace(public_archives_dir);
  55. if (!temporary_archives_dir.empty()) {
  56. storage_stats.temporary_archives_size =
  57. base::ComputeDirectorySize(temporary_archives_dir);
  58. }
  59. if (!private_archives_dir.empty()) {
  60. storage_stats.private_archives_size =
  61. base::ComputeDirectorySize(private_archives_dir);
  62. }
  63. if (!public_archives_dir.empty()) {
  64. base::FileEnumerator file_enumerator(public_archives_dir, false,
  65. base::FileEnumerator::FILES);
  66. while (!file_enumerator.Next().empty()) {
  67. #if BUILDFLAG(IS_WIN)
  68. std::string extension = base::WideToUTF8(
  69. file_enumerator.GetInfo().GetName().FinalExtension());
  70. #else
  71. std::string extension =
  72. file_enumerator.GetInfo().GetName().FinalExtension();
  73. #endif
  74. if (extension == "mhtml" || extension == "mht")
  75. storage_stats.public_archives_size +=
  76. file_enumerator.GetInfo().GetSize();
  77. }
  78. }
  79. task_runner->PostTask(FROM_HERE,
  80. base::BindOnce(std::move(callback), storage_stats));
  81. }
  82. } // namespace
  83. // protected and used for testing.
  84. ArchiveManager::ArchiveManager() {}
  85. ArchiveManager::ArchiveManager(
  86. const base::FilePath& temporary_archives_dir,
  87. const base::FilePath& private_archives_dir,
  88. const base::FilePath& public_archives_dir,
  89. const scoped_refptr<base::SequencedTaskRunner>& task_runner)
  90. : temporary_archives_dir_(temporary_archives_dir),
  91. private_archives_dir_(private_archives_dir),
  92. public_archives_dir_(public_archives_dir),
  93. task_runner_(task_runner) {}
  94. ArchiveManager::~ArchiveManager() {}
  95. void ArchiveManager::EnsureArchivesDirCreated(
  96. base::OnceCallback<void()> callback) {
  97. // The callback will only be invoked once both directories are created.
  98. if (!temporary_archives_dir_.empty()) {
  99. task_runner_->PostTask(
  100. FROM_HERE, base::BindOnce(EnsureArchivesDirCreatedImpl,
  101. temporary_archives_dir_, true /* is_temp */));
  102. }
  103. task_runner_->PostTaskAndReply(
  104. FROM_HERE,
  105. base::BindOnce(EnsureArchivesDirCreatedImpl, private_archives_dir_,
  106. false /* is_temp */),
  107. std::move(callback));
  108. }
  109. void ArchiveManager::GetStorageStats(StorageStatsCallback callback) const {
  110. task_runner_->PostTask(
  111. FROM_HERE,
  112. base::BindOnce(GetStorageStatsImpl, temporary_archives_dir_,
  113. private_archives_dir_, public_archives_dir_,
  114. base::ThreadTaskRunnerHandle::Get(), std::move(callback)));
  115. }
  116. const base::FilePath& ArchiveManager::GetTemporaryArchivesDir() const {
  117. return temporary_archives_dir_;
  118. }
  119. const base::FilePath& ArchiveManager::GetPrivateArchivesDir() const {
  120. return private_archives_dir_;
  121. }
  122. const base::FilePath& ArchiveManager::GetPublicArchivesDir() {
  123. return public_archives_dir_;
  124. }
  125. } // namespace offline_pages