| 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_blocking_data_type_controller.h" | 5 #include "components/sync/driver/non_blocking_data_type_controller.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "components/sync/api/data_type_error_handler_impl.h" | 15 #include "components/sync/api/data_type_error_handler_impl.h" |
| 16 #include "components/sync/api/model_type_change_processor.h" | 16 #include "components/sync/api/model_type_change_processor.h" |
| 17 #include "components/sync/api/model_type_service.h" | 17 #include "components/sync/api/model_type_service.h" |
| 18 #include "components/sync/api/sync_error.h" | 18 #include "components/sync/api/sync_error.h" |
| 19 #include "components/sync/api/sync_merge_result.h" | 19 #include "components/sync/api/sync_merge_result.h" |
| 20 #include "components/sync/base/bind_to_task_runner.h" | 20 #include "components/sync/base/bind_to_task_runner.h" |
| 21 #include "components/sync/base/data_type_histogram.h" | 21 #include "components/sync/base/data_type_histogram.h" |
| 22 #include "components/sync/core/activation_context.h" | 22 #include "components/sync/core/activation_context.h" |
| 23 #include "components/sync/driver/backend_data_type_configurer.h" | 23 #include "components/sync/driver/backend_data_type_configurer.h" |
| 24 #include "components/sync/driver/sync_client.h" | 24 #include "components/sync/driver/sync_client.h" |
| 25 | 25 |
| 26 namespace sync_driver_v2 { | 26 namespace syncer { |
| 27 | 27 |
| 28 NonBlockingDataTypeController::NonBlockingDataTypeController( | 28 NonBlockingDataTypeController::NonBlockingDataTypeController( |
| 29 syncer::ModelType type, | 29 ModelType type, |
| 30 const base::Closure& dump_stack, | 30 const base::Closure& dump_stack, |
| 31 sync_driver::SyncClient* sync_client) | 31 SyncClient* sync_client) |
| 32 : sync_driver::DataTypeController(type, dump_stack), | 32 : DataTypeController(type, dump_stack), |
| 33 sync_client_(sync_client), | 33 sync_client_(sync_client), |
| 34 sync_prefs_(sync_client->GetPrefService()), | 34 sync_prefs_(sync_client->GetPrefService()), |
| 35 state_(NOT_RUNNING) {} | 35 state_(NOT_RUNNING) {} |
| 36 | 36 |
| 37 NonBlockingDataTypeController::~NonBlockingDataTypeController() {} | 37 NonBlockingDataTypeController::~NonBlockingDataTypeController() {} |
| 38 | 38 |
| 39 bool NonBlockingDataTypeController::ShouldLoadModelBeforeConfigure() const { | 39 bool NonBlockingDataTypeController::ShouldLoadModelBeforeConfigure() const { |
| 40 // USS datatypes require loading models because model controls storage where | 40 // USS datatypes require loading models because model controls storage where |
| 41 // data type context and progress marker are persisted. | 41 // data type context and progress marker are persisted. |
| 42 return true; | 42 return true; |
| 43 } | 43 } |
| 44 | 44 |
| 45 void NonBlockingDataTypeController::LoadModels( | 45 void NonBlockingDataTypeController::LoadModels( |
| 46 const ModelLoadCallback& model_load_callback) { | 46 const ModelLoadCallback& model_load_callback) { |
| 47 DCHECK(CalledOnValidThread()); | 47 DCHECK(CalledOnValidThread()); |
| 48 DCHECK(!model_load_callback.is_null()); | 48 DCHECK(!model_load_callback.is_null()); |
| 49 model_load_callback_ = model_load_callback; | 49 model_load_callback_ = model_load_callback; |
| 50 | 50 |
| 51 if (state() != NOT_RUNNING) { | 51 if (state() != NOT_RUNNING) { |
| 52 LoadModelsDone( | 52 LoadModelsDone(RUNTIME_ERROR, |
| 53 RUNTIME_ERROR, | 53 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
| 54 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 54 "Model already running", type())); |
| 55 "Model already running", type())); | |
| 56 return; | 55 return; |
| 57 } | 56 } |
| 58 | 57 |
| 59 state_ = MODEL_STARTING; | 58 state_ = MODEL_STARTING; |
| 60 | 59 |
| 61 // Callback that posts back to the UI thread. | 60 // Callback that posts back to the UI thread. |
| 62 syncer_v2::ModelTypeChangeProcessor::StartCallback callback = | 61 ModelTypeChangeProcessor::StartCallback callback = BindToCurrentThread( |
| 63 syncer::BindToCurrentThread( | 62 base::Bind(&NonBlockingDataTypeController::OnProcessorStarted, |
| 64 base::Bind(&NonBlockingDataTypeController::OnProcessorStarted, | 63 base::AsWeakPtr(this))); |
| 65 base::AsWeakPtr(this))); | |
| 66 | 64 |
| 67 // Start the type processor on the model thread. | 65 // Start the type processor on the model thread. |
| 68 if (!RunOnModelThread( | 66 if (!RunOnModelThread( |
| 69 FROM_HERE, | 67 FROM_HERE, |
| 70 base::Bind(&syncer_v2::ModelTypeService::OnSyncStarting, | 68 base::Bind(&ModelTypeService::OnSyncStarting, |
| 71 sync_client_->GetModelTypeServiceForType(type()), | 69 sync_client_->GetModelTypeServiceForType(type()), |
| 72 base::Passed(CreateErrorHandler()), callback))) { | 70 base::Passed(CreateErrorHandler()), callback))) { |
| 73 LoadModelsDone( | 71 LoadModelsDone(UNRECOVERABLE_ERROR, |
| 74 UNRECOVERABLE_ERROR, | 72 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
| 75 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 73 "Failed to post model Start", type())); |
| 76 "Failed to post model Start", type())); | |
| 77 } | 74 } |
| 78 } | 75 } |
| 79 | 76 |
| 80 void NonBlockingDataTypeController::GetAllNodes( | 77 void NonBlockingDataTypeController::GetAllNodes( |
| 81 const AllNodesCallback& callback) { | 78 const AllNodesCallback& callback) { |
| 82 base::WeakPtr<syncer_v2::ModelTypeService> service = | 79 base::WeakPtr<ModelTypeService> service = |
| 83 sync_client_->GetModelTypeServiceForType(type()); | 80 sync_client_->GetModelTypeServiceForType(type()); |
| 84 // TODO(gangwu): Casting should happen "near" where the processor factory has | 81 // TODO(gangwu): Casting should happen "near" where the processor factory has |
| 85 // code that instantiates a new processor. | 82 // code that instantiates a new processor. |
| 86 syncer_v2::SharedModelTypeProcessor* processor = | 83 SharedModelTypeProcessor* processor = |
| 87 (syncer_v2::SharedModelTypeProcessor*)service->change_processor(); | 84 (SharedModelTypeProcessor*)service->change_processor(); |
| 88 RunOnModelThread(FROM_HERE, | 85 RunOnModelThread(FROM_HERE, |
| 89 base::Bind(&syncer_v2::SharedModelTypeProcessor::GetAllNodes, | 86 base::Bind(&SharedModelTypeProcessor::GetAllNodes, |
| 90 base::Unretained(processor), | 87 base::Unretained(processor), |
| 91 base::ThreadTaskRunnerHandle::Get(), callback)); | 88 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 92 } | 89 } |
| 93 | 90 |
| 94 void NonBlockingDataTypeController::LoadModelsDone( | 91 void NonBlockingDataTypeController::LoadModelsDone(ConfigureResult result, |
| 95 ConfigureResult result, | 92 const SyncError& error) { |
| 96 const syncer::SyncError& error) { | |
| 97 DCHECK(CalledOnValidThread()); | 93 DCHECK(CalledOnValidThread()); |
| 98 | 94 |
| 99 if (state_ == NOT_RUNNING) { | 95 if (state_ == NOT_RUNNING) { |
| 100 // The callback arrived on the UI thread after the type has been already | 96 // The callback arrived on the UI thread after the type has been already |
| 101 // stopped. | 97 // stopped. |
| 102 RecordStartFailure(ABORTED); | 98 RecordStartFailure(ABORTED); |
| 103 return; | 99 return; |
| 104 } | 100 } |
| 105 | 101 |
| 106 if (IsSuccessfulResult(result)) { | 102 if (IsSuccessfulResult(result)) { |
| 107 DCHECK_EQ(MODEL_STARTING, state_); | 103 DCHECK_EQ(MODEL_STARTING, state_); |
| 108 state_ = MODEL_LOADED; | 104 state_ = MODEL_LOADED; |
| 109 } else { | 105 } else { |
| 110 RecordStartFailure(result); | 106 RecordStartFailure(result); |
| 111 } | 107 } |
| 112 | 108 |
| 113 if (!model_load_callback_.is_null()) { | 109 if (!model_load_callback_.is_null()) { |
| 114 model_load_callback_.Run(type(), error); | 110 model_load_callback_.Run(type(), error); |
| 115 } | 111 } |
| 116 } | 112 } |
| 117 | 113 |
| 118 void NonBlockingDataTypeController::OnProcessorStarted( | 114 void NonBlockingDataTypeController::OnProcessorStarted( |
| 119 syncer::SyncError error, | 115 SyncError error, |
| 120 std::unique_ptr<syncer_v2::ActivationContext> activation_context) { | 116 std::unique_ptr<ActivationContext> activation_context) { |
| 121 DCHECK(CalledOnValidThread()); | 117 DCHECK(CalledOnValidThread()); |
| 122 // Hold on to the activation context until ActivateDataType is called. | 118 // Hold on to the activation context until ActivateDataType is called. |
| 123 if (state_ == MODEL_STARTING) { | 119 if (state_ == MODEL_STARTING) { |
| 124 activation_context_ = std::move(activation_context); | 120 activation_context_ = std::move(activation_context); |
| 125 } | 121 } |
| 126 // TODO(stanisc): Figure out if UNRECOVERABLE_ERROR is OK in this case. | 122 // TODO(stanisc): Figure out if UNRECOVERABLE_ERROR is OK in this case. |
| 127 ConfigureResult result = error.IsSet() ? UNRECOVERABLE_ERROR : OK; | 123 ConfigureResult result = error.IsSet() ? UNRECOVERABLE_ERROR : OK; |
| 128 LoadModelsDone(result, error); | 124 LoadModelsDone(result, error); |
| 129 } | 125 } |
| 130 | 126 |
| 131 void NonBlockingDataTypeController::RegisterWithBackend( | 127 void NonBlockingDataTypeController::RegisterWithBackend( |
| 132 sync_driver::BackendDataTypeConfigurer* configurer) { | 128 BackendDataTypeConfigurer* configurer) { |
| 133 DCHECK(CalledOnValidThread()); | 129 DCHECK(CalledOnValidThread()); |
| 134 if (activated_) | 130 if (activated_) |
| 135 return; | 131 return; |
| 136 DCHECK(configurer); | 132 DCHECK(configurer); |
| 137 DCHECK(activation_context_); | 133 DCHECK(activation_context_); |
| 138 DCHECK_EQ(MODEL_LOADED, state_); | 134 DCHECK_EQ(MODEL_LOADED, state_); |
| 139 configurer->ActivateNonBlockingDataType(type(), | 135 configurer->ActivateNonBlockingDataType(type(), |
| 140 std::move(activation_context_)); | 136 std::move(activation_context_)); |
| 141 activated_ = true; | 137 activated_ = true; |
| 142 } | 138 } |
| 143 | 139 |
| 144 void NonBlockingDataTypeController::StartAssociating( | 140 void NonBlockingDataTypeController::StartAssociating( |
| 145 const StartCallback& start_callback) { | 141 const StartCallback& start_callback) { |
| 146 DCHECK(CalledOnValidThread()); | 142 DCHECK(CalledOnValidThread()); |
| 147 DCHECK(!start_callback.is_null()); | 143 DCHECK(!start_callback.is_null()); |
| 148 | 144 |
| 149 state_ = RUNNING; | 145 state_ = RUNNING; |
| 150 | 146 |
| 151 // There is no association, just call back promptly. | 147 // There is no association, just call back promptly. |
| 152 syncer::SyncMergeResult merge_result(type()); | 148 SyncMergeResult merge_result(type()); |
| 153 start_callback.Run(OK, merge_result, merge_result); | 149 start_callback.Run(OK, merge_result, merge_result); |
| 154 } | 150 } |
| 155 | 151 |
| 156 void NonBlockingDataTypeController::ActivateDataType( | 152 void NonBlockingDataTypeController::ActivateDataType( |
| 157 sync_driver::BackendDataTypeConfigurer* configurer) { | 153 BackendDataTypeConfigurer* configurer) { |
| 158 DCHECK(CalledOnValidThread()); | 154 DCHECK(CalledOnValidThread()); |
| 159 DCHECK(configurer); | 155 DCHECK(configurer); |
| 160 DCHECK_EQ(RUNNING, state_); | 156 DCHECK_EQ(RUNNING, state_); |
| 161 // In contrast with directory datatypes, non-blocking data types should be | 157 // In contrast with directory datatypes, non-blocking data types should be |
| 162 // activated in RegisterWithBackend. activation_context_ should be passed | 158 // activated in RegisterWithBackend. activation_context_ should be passed |
| 163 // to backend before call to ActivateDataType. | 159 // to backend before call to ActivateDataType. |
| 164 DCHECK(!activation_context_); | 160 DCHECK(!activation_context_); |
| 165 } | 161 } |
| 166 | 162 |
| 167 void NonBlockingDataTypeController::DeactivateDataType( | 163 void NonBlockingDataTypeController::DeactivateDataType( |
| 168 sync_driver::BackendDataTypeConfigurer* configurer) { | 164 BackendDataTypeConfigurer* configurer) { |
| 169 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
| 170 DCHECK(configurer); | 166 DCHECK(configurer); |
| 171 DCHECK(activated_); | 167 DCHECK(activated_); |
| 172 configurer->DeactivateNonBlockingDataType(type()); | 168 configurer->DeactivateNonBlockingDataType(type()); |
| 173 activated_ = false; | 169 activated_ = false; |
| 174 } | 170 } |
| 175 | 171 |
| 176 void NonBlockingDataTypeController::Stop() { | 172 void NonBlockingDataTypeController::Stop() { |
| 177 DCHECK(CalledOnValidThread()); | 173 DCHECK(CalledOnValidThread()); |
| 178 | 174 |
| 179 if (state() == NOT_RUNNING) | 175 if (state() == NOT_RUNNING) |
| 180 return; | 176 return; |
| 181 | 177 |
| 182 // Check preferences if datatype is not in preferred datatypes. Only call | 178 // Check preferences if datatype is not in preferred datatypes. Only call |
| 183 // DisableSync if service is ready to handle it (controller is in loaded | 179 // DisableSync if service is ready to handle it (controller is in loaded |
| 184 // state). | 180 // state). |
| 185 syncer::ModelTypeSet preferred_types = | 181 ModelTypeSet preferred_types = |
| 186 sync_prefs_.GetPreferredDataTypes(syncer::ModelTypeSet(type())); | 182 sync_prefs_.GetPreferredDataTypes(ModelTypeSet(type())); |
| 187 if ((state() == MODEL_LOADED || state() == RUNNING) && | 183 if ((state() == MODEL_LOADED || state() == RUNNING) && |
| 188 (!sync_prefs_.IsFirstSetupComplete() || !preferred_types.Has(type()))) { | 184 (!sync_prefs_.IsFirstSetupComplete() || !preferred_types.Has(type()))) { |
| 189 RunOnModelThread( | 185 RunOnModelThread( |
| 190 FROM_HERE, | 186 FROM_HERE, |
| 191 base::Bind(&syncer_v2::ModelTypeService::DisableSync, | 187 base::Bind(&ModelTypeService::DisableSync, |
| 192 sync_client_->GetModelTypeServiceForType(type()))); | 188 sync_client_->GetModelTypeServiceForType(type()))); |
| 193 } | 189 } |
| 194 | 190 |
| 195 state_ = NOT_RUNNING; | 191 state_ = NOT_RUNNING; |
| 196 } | 192 } |
| 197 | 193 |
| 198 std::string NonBlockingDataTypeController::name() const { | 194 std::string NonBlockingDataTypeController::name() const { |
| 199 // For logging only. | 195 // For logging only. |
| 200 return syncer::ModelTypeToString(type()); | 196 return ModelTypeToString(type()); |
| 201 } | 197 } |
| 202 | 198 |
| 203 sync_driver::DataTypeController::State NonBlockingDataTypeController::state() | 199 DataTypeController::State NonBlockingDataTypeController::state() const { |
| 204 const { | |
| 205 return state_; | 200 return state_; |
| 206 } | 201 } |
| 207 | 202 |
| 208 std::unique_ptr<syncer::DataTypeErrorHandler> | 203 std::unique_ptr<DataTypeErrorHandler> |
| 209 NonBlockingDataTypeController::CreateErrorHandler() { | 204 NonBlockingDataTypeController::CreateErrorHandler() { |
| 210 DCHECK(CalledOnValidThread()); | 205 DCHECK(CalledOnValidThread()); |
| 211 return base::MakeUnique<syncer::DataTypeErrorHandlerImpl>( | 206 return base::MakeUnique<DataTypeErrorHandlerImpl>( |
| 212 base::ThreadTaskRunnerHandle::Get(), dump_stack_, | 207 base::ThreadTaskRunnerHandle::Get(), dump_stack_, |
| 213 base::Bind(&NonBlockingDataTypeController::ReportLoadModelError, | 208 base::Bind(&NonBlockingDataTypeController::ReportLoadModelError, |
| 214 base::AsWeakPtr(this))); | 209 base::AsWeakPtr(this))); |
| 215 } | 210 } |
| 216 | 211 |
| 217 void NonBlockingDataTypeController::ReportLoadModelError( | 212 void NonBlockingDataTypeController::ReportLoadModelError( |
| 218 const syncer::SyncError& error) { | 213 const SyncError& error) { |
| 219 DCHECK(CalledOnValidThread()); | 214 DCHECK(CalledOnValidThread()); |
| 220 LoadModelsDone(UNRECOVERABLE_ERROR, error); | 215 LoadModelsDone(UNRECOVERABLE_ERROR, error); |
| 221 } | 216 } |
| 222 | 217 |
| 223 void NonBlockingDataTypeController::RecordStartFailure( | 218 void NonBlockingDataTypeController::RecordStartFailure( |
| 224 ConfigureResult result) const { | 219 ConfigureResult result) const { |
| 225 DCHECK(CalledOnValidThread()); | 220 DCHECK(CalledOnValidThread()); |
| 226 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures", | 221 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures", |
| 227 ModelTypeToHistogramInt(type()), | 222 ModelTypeToHistogramInt(type()), MODEL_TYPE_COUNT); |
| 228 syncer::MODEL_TYPE_COUNT); | |
| 229 #define PER_DATA_TYPE_MACRO(type_str) \ | 223 #define PER_DATA_TYPE_MACRO(type_str) \ |
| 230 UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ | 224 UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ |
| 231 MAX_CONFIGURE_RESULT); | 225 MAX_CONFIGURE_RESULT); |
| 232 SYNC_DATA_TYPE_HISTOGRAM(type()); | 226 SYNC_DATA_TYPE_HISTOGRAM(type()); |
| 233 #undef PER_DATA_TYPE_MACRO | 227 #undef PER_DATA_TYPE_MACRO |
| 234 } | 228 } |
| 235 | 229 |
| 236 } // namespace sync_driver_v2 | 230 } // namespace syncer |
| OLD | NEW |