non_ui_syncable_service_based_model_type_controller.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2018 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/sync/driver/non_ui_syncable_service_based_model_type_controller.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "components/sync/base/model_type.h"
  10. #include "components/sync/model/client_tag_based_model_type_processor.h"
  11. #include "components/sync/model/forwarding_model_type_controller_delegate.h"
  12. #include "components/sync/model/proxy_model_type_controller_delegate.h"
  13. #include "components/sync/model/syncable_service_based_bridge.h"
  14. namespace syncer {
  15. namespace {
  16. // Helper object that allows constructing and destructing the
  17. // SyncableServiceBasedBridge on the model thread. Gets constructed on the UI
  18. // thread, but all other operations including destruction happen on the model
  19. // thread.
  20. class BridgeBuilder {
  21. public:
  22. BridgeBuilder(
  23. ModelType type,
  24. OnceModelTypeStoreFactory store_factory,
  25. NonUiSyncableServiceBasedModelTypeController::SyncableServiceProvider
  26. syncable_service_provider,
  27. const base::RepeatingClosure& dump_stack,
  28. scoped_refptr<base::SequencedTaskRunner> task_runner)
  29. : task_runner_(task_runner) {
  30. DCHECK(store_factory);
  31. DCHECK(syncable_service_provider);
  32. // Unretained is safe because destruction also happens on |task_runner_| and
  33. // can't overtake this task.
  34. task_runner_->PostTask(
  35. FROM_HERE,
  36. base::BindOnce(&BridgeBuilder::InitOnModelThread,
  37. base::Unretained(this), type, std::move(store_factory),
  38. std::move(syncable_service_provider), dump_stack));
  39. }
  40. BridgeBuilder(const BridgeBuilder&) = delete;
  41. BridgeBuilder& operator=(const BridgeBuilder&) = delete;
  42. ~BridgeBuilder() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); }
  43. // Indirectly called for each operation by ProxyModelTypeControllerDelegate.
  44. base::WeakPtr<ModelTypeControllerDelegate> GetBridgeDelegate() {
  45. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  46. DCHECK(bridge_);
  47. return bridge_->change_processor()->GetControllerDelegate();
  48. }
  49. private:
  50. void InitOnModelThread(
  51. ModelType type,
  52. OnceModelTypeStoreFactory store_factory,
  53. NonUiSyncableServiceBasedModelTypeController::SyncableServiceProvider
  54. syncable_service_provider,
  55. const base::RepeatingClosure& dump_stack) {
  56. DCHECK(task_runner_->RunsTasksInCurrentSequence());
  57. DCHECK(!bridge_);
  58. base::WeakPtr<SyncableService> syncable_service =
  59. std::move(syncable_service_provider).Run();
  60. // |syncable_service| can be null in tests.
  61. if (syncable_service) {
  62. bridge_ = std::make_unique<SyncableServiceBasedBridge>(
  63. type, std::move(store_factory),
  64. std::make_unique<ClientTagBasedModelTypeProcessor>(type, dump_stack),
  65. syncable_service.get());
  66. }
  67. }
  68. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  69. std::unique_ptr<ModelTypeSyncBridge> bridge_;
  70. };
  71. // This is a slightly adapted version of base::OnTaskRunnerDeleter: The one
  72. // difference is that if the destruction request already happens on the target
  73. // sequence, then this avoids posting a task, and instead deletes the given
  74. // object immediately. See https://crbug.com/970354#c19.
  75. struct CustomOnTaskRunnerDeleter {
  76. explicit CustomOnTaskRunnerDeleter(
  77. scoped_refptr<base::SequencedTaskRunner> task_runner)
  78. : task_runner_(std::move(task_runner)) {}
  79. ~CustomOnTaskRunnerDeleter() = default;
  80. CustomOnTaskRunnerDeleter(CustomOnTaskRunnerDeleter&&) = default;
  81. // For compatibility with std:: deleters.
  82. template <typename T>
  83. void operator()(const T* ptr) {
  84. if (!ptr)
  85. return;
  86. if (task_runner_->RunsTasksInCurrentSequence()) {
  87. delete ptr;
  88. } else {
  89. task_runner_->DeleteSoon(FROM_HERE, ptr);
  90. }
  91. }
  92. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  93. };
  94. ProxyModelTypeControllerDelegate::DelegateProvider BuildDelegateProvider(
  95. ModelType type,
  96. OnceModelTypeStoreFactory store_factory,
  97. NonUiSyncableServiceBasedModelTypeController::SyncableServiceProvider
  98. syncable_service_provider,
  99. const base::RepeatingClosure& dump_stack,
  100. scoped_refptr<base::SequencedTaskRunner> task_runner) {
  101. // Can't use std::make_unique or base::WrapUnique because of custom deleter.
  102. auto bridge_builder =
  103. std::unique_ptr<BridgeBuilder, CustomOnTaskRunnerDeleter>(
  104. new BridgeBuilder(type, std::move(store_factory),
  105. std::move(syncable_service_provider), dump_stack,
  106. task_runner),
  107. CustomOnTaskRunnerDeleter(task_runner));
  108. // Note that the binding owns the BridgeBuilder instance.
  109. return base::BindRepeating(&BridgeBuilder::GetBridgeDelegate,
  110. std::move(bridge_builder));
  111. }
  112. } // namespace
  113. NonUiSyncableServiceBasedModelTypeController::
  114. NonUiSyncableServiceBasedModelTypeController(
  115. ModelType type,
  116. OnceModelTypeStoreFactory store_factory,
  117. SyncableServiceProvider syncable_service_provider,
  118. const base::RepeatingClosure& dump_stack,
  119. scoped_refptr<base::SequencedTaskRunner> task_runner,
  120. bool allow_transport_mode)
  121. : ModelTypeController(type) {
  122. auto full_sync_mode_delegate =
  123. std::make_unique<ProxyModelTypeControllerDelegate>(
  124. task_runner,
  125. BuildDelegateProvider(type, std::move(store_factory),
  126. std::move(syncable_service_provider),
  127. dump_stack, task_runner));
  128. // In transport mode we want the same behavior as full sync mode, so we use
  129. // the same thread-proxying delegate, which shares the BridgeBuilder, which
  130. // shares the underlying ModelTypeSyncBridge.
  131. auto transport_mode_delegate =
  132. allow_transport_mode
  133. ? std::make_unique<ForwardingModelTypeControllerDelegate>(
  134. full_sync_mode_delegate.get())
  135. : nullptr;
  136. InitModelTypeController(std::move(full_sync_mode_delegate),
  137. std::move(transport_mode_delegate));
  138. }
  139. NonUiSyncableServiceBasedModelTypeController::
  140. ~NonUiSyncableServiceBasedModelTypeController() = default;
  141. } // namespace syncer