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