bookmark_storage.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2014 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/bookmarks/browser/bookmark_storage.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <unordered_map>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/compiler_specific.h"
  11. #include "base/files/file_util.h"
  12. #include "base/guid.h"
  13. #include "base/json/json_file_value_serializer.h"
  14. #include "base/json/json_string_value_serializer.h"
  15. #include "base/numerics/safe_conversions.h"
  16. #include "base/task/sequenced_task_runner.h"
  17. #include "base/task/task_traits.h"
  18. #include "base/task/thread_pool.h"
  19. #include "components/bookmarks/browser/bookmark_codec.h"
  20. #include "components/bookmarks/browser/bookmark_model.h"
  21. #include "components/bookmarks/browser/bookmark_node.h"
  22. #include "components/bookmarks/common/bookmark_metrics.h"
  23. namespace bookmarks {
  24. namespace {
  25. // Extension used for backup files (copy of main file created during startup).
  26. const base::FilePath::CharType kBackupExtension[] = FILE_PATH_LITERAL("bak");
  27. void BackupCallback(const base::FilePath& path) {
  28. base::FilePath backup_path = path.ReplaceExtension(kBackupExtension);
  29. base::CopyFile(path, backup_path);
  30. }
  31. } // namespace
  32. // static
  33. constexpr base::TimeDelta BookmarkStorage::kSaveDelay;
  34. BookmarkStorage::BookmarkStorage(BookmarkModel* model,
  35. const base::FilePath& file_path)
  36. : model_(model),
  37. backend_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
  38. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  39. base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
  40. writer_(file_path, backend_task_runner_, kSaveDelay, "BookmarkStorage"),
  41. last_scheduled_save_(base::TimeTicks::Now()) {}
  42. BookmarkStorage::~BookmarkStorage() {
  43. if (writer_.HasPendingWrite())
  44. writer_.DoScheduledWrite();
  45. }
  46. void BookmarkStorage::ScheduleSave() {
  47. // If this is the first scheduled save, create a backup before overwriting the
  48. // JSON file.
  49. if (!backup_triggered_) {
  50. backup_triggered_ = true;
  51. backend_task_runner_->PostTask(
  52. FROM_HERE, base::BindOnce(&BackupCallback, writer_.path()));
  53. }
  54. writer_.ScheduleWriteWithBackgroundDataSerializer(this);
  55. const base::TimeDelta schedule_delta =
  56. base::TimeTicks::Now() - last_scheduled_save_;
  57. metrics::RecordTimeSinceLastScheduledSave(schedule_delta);
  58. last_scheduled_save_ = base::TimeTicks::Now();
  59. }
  60. void BookmarkStorage::BookmarkModelDeleted() {
  61. // We need to save now as otherwise by the time SerializeData() is invoked
  62. // the model is gone.
  63. if (writer_.HasPendingWrite()) {
  64. writer_.DoScheduledWrite();
  65. DCHECK(!writer_.HasPendingWrite());
  66. }
  67. model_ = nullptr;
  68. }
  69. base::ImportantFileWriter::BackgroundDataProducerCallback
  70. BookmarkStorage::GetSerializedDataProducerForBackgroundSequence() {
  71. BookmarkCodec codec;
  72. base::Value value(
  73. codec.Encode(model_, model_->client()->EncodeBookmarkSyncMetadata()));
  74. return base::BindOnce(
  75. [](base::Value value, std::string* output) {
  76. // This runs on the background sequence.
  77. JSONStringValueSerializer serializer(output);
  78. serializer.set_pretty_print(true);
  79. return serializer.Serialize(value);
  80. },
  81. std::move(value));
  82. }
  83. bool BookmarkStorage::HasScheduledSaveForTesting() const {
  84. return writer_.HasPendingWrite();
  85. }
  86. } // namespace bookmarks