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 |