| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sync/driver/non_ui_data_type_controller.h" | 5 #include "components/sync/driver/async_directory_type_controller.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "components/sync/base/bind_to_task_runner.h" | 11 #include "components/sync/base/bind_to_task_runner.h" |
| 12 #include "components/sync/base/data_type_histogram.h" | 12 #include "components/sync/base/data_type_histogram.h" |
| 13 #include "components/sync/base/model_type.h" | 13 #include "components/sync/base/model_type.h" |
| 14 #include "components/sync/driver/generic_change_processor_factory.h" | 14 #include "components/sync/driver/generic_change_processor_factory.h" |
| 15 #include "components/sync/driver/sync_api_component_factory.h" | 15 #include "components/sync/driver/sync_api_component_factory.h" |
| 16 #include "components/sync/driver/sync_client.h" | 16 #include "components/sync/driver/sync_client.h" |
| 17 #include "components/sync/driver/sync_service.h" | 17 #include "components/sync/driver/sync_service.h" |
| 18 #include "components/sync/model/data_type_error_handler_impl.h" | 18 #include "components/sync/model/data_type_error_handler_impl.h" |
| 19 #include "components/sync/model/sync_error.h" | 19 #include "components/sync/model/sync_error.h" |
| 20 #include "components/sync/model/sync_merge_result.h" | 20 #include "components/sync/model/sync_merge_result.h" |
| 21 #include "components/sync/model/syncable_service.h" | 21 #include "components/sync/model/syncable_service.h" |
| 22 | 22 |
| 23 namespace syncer { | 23 namespace syncer { |
| 24 | 24 |
| 25 SharedChangeProcessor* NonUIDataTypeController::CreateSharedChangeProcessor() { | 25 SharedChangeProcessor* |
| 26 AsyncDirectoryTypeController::CreateSharedChangeProcessor() { |
| 26 return new SharedChangeProcessor(type()); | 27 return new SharedChangeProcessor(type()); |
| 27 } | 28 } |
| 28 | 29 |
| 29 NonUIDataTypeController::NonUIDataTypeController( | 30 AsyncDirectoryTypeController::AsyncDirectoryTypeController( |
| 30 ModelType type, | 31 ModelType type, |
| 31 const base::Closure& dump_stack, | 32 const base::Closure& dump_stack, |
| 32 SyncClient* sync_client, | 33 SyncClient* sync_client, |
| 33 ModelSafeGroup model_safe_group, | 34 ModelSafeGroup model_safe_group, |
| 34 scoped_refptr<base::SequencedTaskRunner> model_thread) | 35 scoped_refptr<base::SequencedTaskRunner> model_thread) |
| 35 : DirectoryDataTypeController(type, | 36 : DirectoryDataTypeController(type, |
| 36 dump_stack, | 37 dump_stack, |
| 37 sync_client, | 38 sync_client, |
| 38 model_safe_group), | 39 model_safe_group), |
| 39 user_share_(nullptr), | 40 user_share_(nullptr), |
| 40 processor_factory_(new GenericChangeProcessorFactory()), | 41 processor_factory_(new GenericChangeProcessorFactory()), |
| 41 state_(NOT_RUNNING), | 42 state_(NOT_RUNNING), |
| 42 model_thread_(std::move(model_thread)) {} | 43 model_thread_(std::move(model_thread)) {} |
| 43 | 44 |
| 44 void NonUIDataTypeController::LoadModels( | 45 void AsyncDirectoryTypeController::LoadModels( |
| 45 const ModelLoadCallback& model_load_callback) { | 46 const ModelLoadCallback& model_load_callback) { |
| 46 DCHECK(CalledOnValidThread()); | 47 DCHECK(CalledOnValidThread()); |
| 47 model_load_callback_ = model_load_callback; | 48 model_load_callback_ = model_load_callback; |
| 48 if (state() != NOT_RUNNING) { | 49 if (state() != NOT_RUNNING) { |
| 49 model_load_callback.Run(type(), | 50 model_load_callback.Run(type(), |
| 50 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, | 51 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
| 51 "Model already running", type())); | 52 "Model already running", type())); |
| 52 return; | 53 return; |
| 53 } | 54 } |
| 54 | 55 |
| 55 state_ = MODEL_STARTING; | 56 state_ = MODEL_STARTING; |
| 56 // Since we can't be called multiple times before Stop() is called, | 57 // Since we can't be called multiple times before Stop() is called, |
| 57 // |shared_change_processor_| must be null here. | 58 // |shared_change_processor_| must be null here. |
| 58 DCHECK(!shared_change_processor_.get()); | 59 DCHECK(!shared_change_processor_.get()); |
| 59 shared_change_processor_ = CreateSharedChangeProcessor(); | 60 shared_change_processor_ = CreateSharedChangeProcessor(); |
| 60 DCHECK(shared_change_processor_.get()); | 61 DCHECK(shared_change_processor_.get()); |
| 61 if (!StartModels()) { | 62 if (!StartModels()) { |
| 62 // If we are waiting for some external service to load before associating | 63 // If we are waiting for some external service to load before associating |
| 63 // or we failed to start the models, we exit early. | 64 // or we failed to start the models, we exit early. |
| 64 DCHECK(state() == MODEL_STARTING || state() == NOT_RUNNING); | 65 DCHECK(state() == MODEL_STARTING || state() == NOT_RUNNING); |
| 65 return; | 66 return; |
| 66 } | 67 } |
| 67 | 68 |
| 68 OnModelLoaded(); | 69 OnModelLoaded(); |
| 69 } | 70 } |
| 70 | 71 |
| 71 void NonUIDataTypeController::OnModelLoaded() { | 72 void AsyncDirectoryTypeController::OnModelLoaded() { |
| 72 DCHECK(CalledOnValidThread()); | 73 DCHECK(CalledOnValidThread()); |
| 73 DCHECK_EQ(state_, MODEL_STARTING); | 74 DCHECK_EQ(state_, MODEL_STARTING); |
| 74 state_ = MODEL_LOADED; | 75 state_ = MODEL_LOADED; |
| 75 model_load_callback_.Run(type(), SyncError()); | 76 model_load_callback_.Run(type(), SyncError()); |
| 76 } | 77 } |
| 77 | 78 |
| 78 bool NonUIDataTypeController::StartModels() { | 79 bool AsyncDirectoryTypeController::StartModels() { |
| 79 DCHECK(CalledOnValidThread()); | 80 DCHECK(CalledOnValidThread()); |
| 80 DCHECK_EQ(state_, MODEL_STARTING); | 81 DCHECK_EQ(state_, MODEL_STARTING); |
| 81 // By default, no additional services need to be started before we can proceed | 82 // By default, no additional services need to be started before we can proceed |
| 82 // with model association. | 83 // with model association. |
| 83 return true; | 84 return true; |
| 84 } | 85 } |
| 85 | 86 |
| 86 void NonUIDataTypeController::StopModels() { | 87 void AsyncDirectoryTypeController::StopModels() { |
| 87 DCHECK(CalledOnValidThread()); | 88 DCHECK(CalledOnValidThread()); |
| 88 } | 89 } |
| 89 | 90 |
| 90 bool NonUIDataTypeController::PostTaskOnModelThread( | 91 bool AsyncDirectoryTypeController::PostTaskOnModelThread( |
| 91 const tracked_objects::Location& from_here, | 92 const tracked_objects::Location& from_here, |
| 92 const base::Closure& task) { | 93 const base::Closure& task) { |
| 93 DCHECK(CalledOnValidThread()); | 94 DCHECK(CalledOnValidThread()); |
| 94 return model_thread_->PostTask(from_here, task); | 95 return model_thread_->PostTask(from_here, task); |
| 95 } | 96 } |
| 96 | 97 |
| 97 void NonUIDataTypeController::StartAssociating( | 98 void AsyncDirectoryTypeController::StartAssociating( |
| 98 const StartCallback& start_callback) { | 99 const StartCallback& start_callback) { |
| 99 DCHECK(CalledOnValidThread()); | 100 DCHECK(CalledOnValidThread()); |
| 100 DCHECK(!start_callback.is_null()); | 101 DCHECK(!start_callback.is_null()); |
| 101 DCHECK_EQ(state_, MODEL_LOADED); | 102 DCHECK_EQ(state_, MODEL_LOADED); |
| 102 state_ = ASSOCIATING; | 103 state_ = ASSOCIATING; |
| 103 | 104 |
| 104 // Store UserShare now while on UI thread to avoid potential race | 105 // Store UserShare now while on UI thread to avoid potential race |
| 105 // condition in StartAssociationWithSharedChangeProcessor. | 106 // condition in StartAssociationWithSharedChangeProcessor. |
| 106 DCHECK(sync_client_->GetSyncService()); | 107 DCHECK(sync_client_->GetSyncService()); |
| 107 user_share_ = sync_client_->GetSyncService()->GetUserShare(); | 108 user_share_ = sync_client_->GetSyncService()->GetUserShare(); |
| 108 | 109 |
| 109 start_callback_ = start_callback; | 110 start_callback_ = start_callback; |
| 110 if (!StartAssociationAsync()) { | 111 if (!StartAssociationAsync()) { |
| 111 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, | 112 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
| 112 "Failed to post StartAssociation", type()); | 113 "Failed to post StartAssociation", type()); |
| 113 SyncMergeResult local_merge_result(type()); | 114 SyncMergeResult local_merge_result(type()); |
| 114 local_merge_result.set_error(error); | 115 local_merge_result.set_error(error); |
| 115 StartDone(ASSOCIATION_FAILED, local_merge_result, SyncMergeResult(type())); | 116 StartDone(ASSOCIATION_FAILED, local_merge_result, SyncMergeResult(type())); |
| 116 // StartDone should have cleared the SharedChangeProcessor. | 117 // StartDone should have cleared the SharedChangeProcessor. |
| 117 DCHECK(!shared_change_processor_.get()); | 118 DCHECK(!shared_change_processor_.get()); |
| 118 return; | 119 return; |
| 119 } | 120 } |
| 120 } | 121 } |
| 121 | 122 |
| 122 void NonUIDataTypeController::Stop() { | 123 void AsyncDirectoryTypeController::Stop() { |
| 123 DCHECK(CalledOnValidThread()); | 124 DCHECK(CalledOnValidThread()); |
| 124 | 125 |
| 125 if (state() == NOT_RUNNING) | 126 if (state() == NOT_RUNNING) |
| 126 return; | 127 return; |
| 127 | 128 |
| 128 // Disconnect the change processor. At this point, the | 129 // Disconnect the change processor. At this point, the |
| 129 // SyncableService can no longer interact with the Syncer, even if | 130 // SyncableService can no longer interact with the Syncer, even if |
| 130 // it hasn't finished MergeDataAndStartSyncing. | 131 // it hasn't finished MergeDataAndStartSyncing. |
| 131 DisconnectSharedChangeProcessor(); | 132 DisconnectSharedChangeProcessor(); |
| 132 | 133 |
| 133 // If we haven't finished starting, we need to abort the start. | 134 // If we haven't finished starting, we need to abort the start. |
| 134 bool service_started = state() == ASSOCIATING || state() == RUNNING; | 135 bool service_started = state() == ASSOCIATING || state() == RUNNING; |
| 135 state_ = service_started ? STOPPING : NOT_RUNNING; | 136 state_ = service_started ? STOPPING : NOT_RUNNING; |
| 136 StopModels(); | 137 StopModels(); |
| 137 | 138 |
| 138 if (service_started) | 139 if (service_started) |
| 139 StopSyncableService(); | 140 StopSyncableService(); |
| 140 | 141 |
| 141 shared_change_processor_ = nullptr; | 142 shared_change_processor_ = nullptr; |
| 142 state_ = NOT_RUNNING; | 143 state_ = NOT_RUNNING; |
| 143 } | 144 } |
| 144 | 145 |
| 145 std::string NonUIDataTypeController::name() const { | 146 std::string AsyncDirectoryTypeController::name() const { |
| 146 // For logging only. | 147 // For logging only. |
| 147 return ModelTypeToString(type()); | 148 return ModelTypeToString(type()); |
| 148 } | 149 } |
| 149 | 150 |
| 150 DataTypeController::State NonUIDataTypeController::state() const { | 151 DataTypeController::State AsyncDirectoryTypeController::state() const { |
| 151 return state_; | 152 return state_; |
| 152 } | 153 } |
| 153 | 154 |
| 154 void NonUIDataTypeController::SetGenericChangeProcessorFactoryForTest( | 155 void AsyncDirectoryTypeController::SetGenericChangeProcessorFactoryForTest( |
| 155 std::unique_ptr<GenericChangeProcessorFactory> factory) { | 156 std::unique_ptr<GenericChangeProcessorFactory> factory) { |
| 156 DCHECK_EQ(state_, NOT_RUNNING); | 157 DCHECK_EQ(state_, NOT_RUNNING); |
| 157 processor_factory_ = std::move(factory); | 158 processor_factory_ = std::move(factory); |
| 158 } | 159 } |
| 159 | 160 |
| 160 NonUIDataTypeController::NonUIDataTypeController() | 161 AsyncDirectoryTypeController::AsyncDirectoryTypeController() |
| 161 : DirectoryDataTypeController(UNSPECIFIED, | 162 : DirectoryDataTypeController(UNSPECIFIED, |
| 162 base::Closure(), | 163 base::Closure(), |
| 163 nullptr, | 164 nullptr, |
| 164 GROUP_PASSIVE) {} | 165 GROUP_PASSIVE) {} |
| 165 | 166 |
| 166 NonUIDataTypeController::~NonUIDataTypeController() {} | 167 AsyncDirectoryTypeController::~AsyncDirectoryTypeController() {} |
| 167 | 168 |
| 168 void NonUIDataTypeController::StartDone( | 169 void AsyncDirectoryTypeController::StartDone( |
| 169 DataTypeController::ConfigureResult start_result, | 170 DataTypeController::ConfigureResult start_result, |
| 170 const SyncMergeResult& local_merge_result, | 171 const SyncMergeResult& local_merge_result, |
| 171 const SyncMergeResult& syncer_merge_result) { | 172 const SyncMergeResult& syncer_merge_result) { |
| 172 DCHECK(CalledOnValidThread()); | 173 DCHECK(CalledOnValidThread()); |
| 173 | 174 |
| 174 DataTypeController::State new_state; | 175 DataTypeController::State new_state; |
| 175 if (IsSuccessfulResult(start_result)) { | 176 if (IsSuccessfulResult(start_result)) { |
| 176 new_state = RUNNING; | 177 new_state = RUNNING; |
| 177 } else { | 178 } else { |
| 178 new_state = (start_result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING); | 179 new_state = (start_result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 196 state_ = new_state; | 197 state_ = new_state; |
| 197 if (state_ != RUNNING) { | 198 if (state_ != RUNNING) { |
| 198 // Start failed. | 199 // Start failed. |
| 199 StopModels(); | 200 StopModels(); |
| 200 RecordStartFailure(start_result); | 201 RecordStartFailure(start_result); |
| 201 } | 202 } |
| 202 | 203 |
| 203 start_callback_.Run(start_result, local_merge_result, syncer_merge_result); | 204 start_callback_.Run(start_result, local_merge_result, syncer_merge_result); |
| 204 } | 205 } |
| 205 | 206 |
| 206 void NonUIDataTypeController::RecordStartFailure(ConfigureResult result) { | 207 void AsyncDirectoryTypeController::RecordStartFailure(ConfigureResult result) { |
| 207 DCHECK(CalledOnValidThread()); | 208 DCHECK(CalledOnValidThread()); |
| 208 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures", | 209 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures", |
| 209 ModelTypeToHistogramInt(type()), MODEL_TYPE_COUNT); | 210 ModelTypeToHistogramInt(type()), MODEL_TYPE_COUNT); |
| 210 #define PER_DATA_TYPE_MACRO(type_str) \ | 211 #define PER_DATA_TYPE_MACRO(type_str) \ |
| 211 UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ | 212 UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ |
| 212 MAX_CONFIGURE_RESULT); | 213 MAX_CONFIGURE_RESULT); |
| 213 SYNC_DATA_TYPE_HISTOGRAM(type()); | 214 SYNC_DATA_TYPE_HISTOGRAM(type()); |
| 214 #undef PER_DATA_TYPE_MACRO | 215 #undef PER_DATA_TYPE_MACRO |
| 215 } | 216 } |
| 216 | 217 |
| 217 void NonUIDataTypeController::DisableImpl(const SyncError& error) { | 218 void AsyncDirectoryTypeController::DisableImpl(const SyncError& error) { |
| 218 DCHECK(CalledOnValidThread()); | 219 DCHECK(CalledOnValidThread()); |
| 219 if (!model_load_callback_.is_null()) { | 220 if (!model_load_callback_.is_null()) { |
| 220 model_load_callback_.Run(type(), error); | 221 model_load_callback_.Run(type(), error); |
| 221 } | 222 } |
| 222 } | 223 } |
| 223 | 224 |
| 224 bool NonUIDataTypeController::StartAssociationAsync() { | 225 bool AsyncDirectoryTypeController::StartAssociationAsync() { |
| 225 DCHECK(CalledOnValidThread()); | 226 DCHECK(CalledOnValidThread()); |
| 226 DCHECK_EQ(state(), ASSOCIATING); | 227 DCHECK_EQ(state(), ASSOCIATING); |
| 227 return PostTaskOnModelThread( | 228 return PostTaskOnModelThread( |
| 228 FROM_HERE, | 229 FROM_HERE, |
| 229 base::Bind( | 230 base::Bind( |
| 230 &SharedChangeProcessor::StartAssociation, shared_change_processor_, | 231 &SharedChangeProcessor::StartAssociation, shared_change_processor_, |
| 231 BindToCurrentThread(base::Bind(&NonUIDataTypeController::StartDone, | 232 BindToCurrentThread(base::Bind( |
| 232 base::AsWeakPtr(this))), | 233 &AsyncDirectoryTypeController::StartDone, base::AsWeakPtr(this))), |
| 233 sync_client_, processor_factory_.get(), user_share_, | 234 sync_client_, processor_factory_.get(), user_share_, |
| 234 base::Passed(CreateErrorHandler()))); | 235 base::Passed(CreateErrorHandler()))); |
| 235 } | 236 } |
| 236 | 237 |
| 237 ChangeProcessor* NonUIDataTypeController::GetChangeProcessor() const { | 238 ChangeProcessor* AsyncDirectoryTypeController::GetChangeProcessor() const { |
| 238 DCHECK(CalledOnValidThread()); | 239 DCHECK(CalledOnValidThread()); |
| 239 DCHECK_EQ(state_, RUNNING); | 240 DCHECK_EQ(state_, RUNNING); |
| 240 return shared_change_processor_->generic_change_processor(); | 241 return shared_change_processor_->generic_change_processor(); |
| 241 } | 242 } |
| 242 | 243 |
| 243 void NonUIDataTypeController::DisconnectSharedChangeProcessor() { | 244 void AsyncDirectoryTypeController::DisconnectSharedChangeProcessor() { |
| 244 DCHECK(CalledOnValidThread()); | 245 DCHECK(CalledOnValidThread()); |
| 245 // |shared_change_processor_| can already be null if Stop() is | 246 // |shared_change_processor_| can already be null if Stop() is |
| 246 // called after StartDone(_, DISABLED, _). | 247 // called after StartDone(_, DISABLED, _). |
| 247 if (shared_change_processor_.get()) { | 248 if (shared_change_processor_.get()) { |
| 248 shared_change_processor_->Disconnect(); | 249 shared_change_processor_->Disconnect(); |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| 252 void NonUIDataTypeController::StopSyncableService() { | 253 void AsyncDirectoryTypeController::StopSyncableService() { |
| 253 DCHECK(CalledOnValidThread()); | 254 DCHECK(CalledOnValidThread()); |
| 254 if (shared_change_processor_.get()) { | 255 if (shared_change_processor_.get()) { |
| 255 PostTaskOnModelThread(FROM_HERE, | 256 PostTaskOnModelThread(FROM_HERE, |
| 256 base::Bind(&SharedChangeProcessor::StopLocalService, | 257 base::Bind(&SharedChangeProcessor::StopLocalService, |
| 257 shared_change_processor_)); | 258 shared_change_processor_)); |
| 258 } | 259 } |
| 259 } | 260 } |
| 260 | 261 |
| 261 std::unique_ptr<DataTypeErrorHandler> | 262 std::unique_ptr<DataTypeErrorHandler> |
| 262 NonUIDataTypeController::CreateErrorHandler() { | 263 AsyncDirectoryTypeController::CreateErrorHandler() { |
| 263 DCHECK(CalledOnValidThread()); | 264 DCHECK(CalledOnValidThread()); |
| 264 return base::MakeUnique<DataTypeErrorHandlerImpl>( | 265 return base::MakeUnique<DataTypeErrorHandlerImpl>( |
| 265 base::ThreadTaskRunnerHandle::Get(), dump_stack_, | 266 base::ThreadTaskRunnerHandle::Get(), dump_stack_, |
| 266 base::Bind(&NonUIDataTypeController::DisableImpl, base::AsWeakPtr(this))); | 267 base::Bind(&AsyncDirectoryTypeController::DisableImpl, |
| 268 base::AsWeakPtr(this))); |
| 267 } | 269 } |
| 268 | 270 |
| 269 } // namespace syncer | 271 } // namespace syncer |
| OLD | NEW |