| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/sync/glue/new_non_frontend_data_type_controller.h" | 5 #include "chrome/browser/sync/glue/new_non_frontend_data_type_controller.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "chrome/browser/sync/glue/shared_change_processor_ref.h" | 8 #include "chrome/browser/sync/glue/shared_change_processor_ref.h" |
| 9 #include "chrome/browser/sync/profile_sync_components_factory.h" | 9 #include "chrome/browser/sync/profile_sync_components_factory.h" |
| 10 #include "chrome/browser/sync/profile_sync_service.h" | 10 #include "chrome/browser/sync/profile_sync_service.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 ProfileSyncService* sync_service) | 23 ProfileSyncService* sync_service) |
| 24 : NonFrontendDataTypeController(profile_sync_factory, | 24 : NonFrontendDataTypeController(profile_sync_factory, |
| 25 profile, | 25 profile, |
| 26 sync_service) {} | 26 sync_service) {} |
| 27 | 27 |
| 28 void NewNonFrontendDataTypeController::LoadModels( | 28 void NewNonFrontendDataTypeController::LoadModels( |
| 29 const ModelLoadCallback& model_load_callback) { | 29 const ModelLoadCallback& model_load_callback) { |
| 30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 31 DCHECK(!model_load_callback.is_null()); | 31 DCHECK(!model_load_callback.is_null()); |
| 32 if (state() != NOT_RUNNING) { | 32 if (state() != NOT_RUNNING) { |
| 33 model_load_callback.Run(type(), SyncError(FROM_HERE, | 33 model_load_callback.Run(type(), csync::SyncError(FROM_HERE, |
| 34 "Model already running", | 34 "Model already running", |
| 35 type())); | 35 type())); |
| 36 return; | 36 return; |
| 37 } | 37 } |
| 38 | 38 |
| 39 set_state(MODEL_STARTING); | 39 set_state(MODEL_STARTING); |
| 40 | 40 |
| 41 // Since we can't be called multiple times before Stop() is called, | 41 // Since we can't be called multiple times before Stop() is called, |
| 42 // |shared_change_processor_| must be NULL here. | 42 // |shared_change_processor_| must be NULL here. |
| 43 DCHECK(!shared_change_processor_.get()); | 43 DCHECK(!shared_change_processor_.get()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 56 OnModelLoaded(); | 56 OnModelLoaded(); |
| 57 } | 57 } |
| 58 | 58 |
| 59 void NewNonFrontendDataTypeController::OnModelLoaded() { | 59 void NewNonFrontendDataTypeController::OnModelLoaded() { |
| 60 DCHECK_EQ(state_, MODEL_STARTING); | 60 DCHECK_EQ(state_, MODEL_STARTING); |
| 61 DCHECK(!model_load_callback_.is_null()); | 61 DCHECK(!model_load_callback_.is_null()); |
| 62 set_state(MODEL_LOADED); | 62 set_state(MODEL_LOADED); |
| 63 | 63 |
| 64 ModelLoadCallback model_load_callback = model_load_callback_; | 64 ModelLoadCallback model_load_callback = model_load_callback_; |
| 65 model_load_callback_.Reset(); | 65 model_load_callback_.Reset(); |
| 66 model_load_callback.Run(type(), SyncError()); | 66 model_load_callback.Run(type(), csync::SyncError()); |
| 67 } | 67 } |
| 68 | 68 |
| 69 void NewNonFrontendDataTypeController::StartAssociating( | 69 void NewNonFrontendDataTypeController::StartAssociating( |
| 70 const StartCallback& start_callback) { | 70 const StartCallback& start_callback) { |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 72 DCHECK(!start_callback.is_null()); | 72 DCHECK(!start_callback.is_null()); |
| 73 DCHECK_EQ(state_, MODEL_LOADED); | 73 DCHECK_EQ(state_, MODEL_LOADED); |
| 74 set_state(ASSOCIATING); | 74 set_state(ASSOCIATING); |
| 75 | 75 |
| 76 set_start_callback(start_callback); | 76 set_start_callback(start_callback); |
| 77 if (!StartAssociationAsync()) { | 77 if (!StartAssociationAsync()) { |
| 78 SyncError error(FROM_HERE, "Failed to post StartAssociation", type()); | 78 csync::SyncError error( |
| 79 FROM_HERE, "Failed to post StartAssociation", type()); |
| 79 StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, error); | 80 StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, error); |
| 80 // StartDoneImpl should have called ClearSharedChangeProcessor(); | 81 // StartDoneImpl should have called ClearSharedChangeProcessor(); |
| 81 DCHECK(!shared_change_processor_.get()); | 82 DCHECK(!shared_change_processor_.get()); |
| 82 return; | 83 return; |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 86 void NewNonFrontendDataTypeController::Stop() { | 87 void NewNonFrontendDataTypeController::Stop() { |
| 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 88 if (state() == NOT_RUNNING) { | 89 if (state() == NOT_RUNNING) { |
| 89 // Stop() should never be called for datatypes that are already stopped. | 90 // Stop() should never be called for datatypes that are already stopped. |
| 90 NOTREACHED(); | 91 NOTREACHED(); |
| 91 return; | 92 return; |
| 92 } | 93 } |
| 93 | 94 |
| 94 // Disconnect the change processor. At this point, the | 95 // Disconnect the change processor. At this point, the |
| 95 // SyncableService can no longer interact with the Syncer, even if | 96 // csync::SyncableService can no longer interact with the Syncer, even if |
| 96 // it hasn't finished MergeDataAndStartSyncing. | 97 // it hasn't finished MergeDataAndStartSyncing. |
| 97 ClearSharedChangeProcessor(); | 98 ClearSharedChangeProcessor(); |
| 98 | 99 |
| 99 // If we haven't finished starting, we need to abort the start. | 100 // If we haven't finished starting, we need to abort the start. |
| 100 switch (state()) { | 101 switch (state()) { |
| 101 case MODEL_STARTING: | 102 case MODEL_STARTING: |
| 102 set_state(STOPPING); | 103 set_state(STOPPING); |
| 103 AbortModelStarting(); | 104 AbortModelStarting(); |
| 104 return; // The datatype was never activated, we're done. | 105 return; // The datatype was never activated, we're done. |
| 105 case ASSOCIATING: | 106 case ASSOCIATING: |
| 106 set_state(STOPPING); | 107 set_state(STOPPING); |
| 107 StartDoneImpl(ABORTED, NOT_RUNNING, SyncError()); | 108 StartDoneImpl(ABORTED, NOT_RUNNING, csync::SyncError()); |
| 108 // We continue on to deactivate the datatype and stop the local service. | 109 // We continue on to deactivate the datatype and stop the local service. |
| 109 break; | 110 break; |
| 110 case DISABLED: | 111 case DISABLED: |
| 111 // If we're disabled we never succeded associating and never activated the | 112 // If we're disabled we never succeded associating and never activated the |
| 112 // datatype. We would have already stopped the local service in | 113 // datatype. We would have already stopped the local service in |
| 113 // StartDoneImpl(..). | 114 // StartDoneImpl(..). |
| 114 set_state(NOT_RUNNING); | 115 set_state(NOT_RUNNING); |
| 115 StopModels(); | 116 StopModels(); |
| 116 return; | 117 return; |
| 117 default: | 118 default: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 134 set_state(NOT_RUNNING); | 135 set_state(NOT_RUNNING); |
| 135 } | 136 } |
| 136 | 137 |
| 137 NewNonFrontendDataTypeController::NewNonFrontendDataTypeController() {} | 138 NewNonFrontendDataTypeController::NewNonFrontendDataTypeController() {} |
| 138 | 139 |
| 139 NewNonFrontendDataTypeController::~NewNonFrontendDataTypeController() {} | 140 NewNonFrontendDataTypeController::~NewNonFrontendDataTypeController() {} |
| 140 | 141 |
| 141 void NewNonFrontendDataTypeController::StartDone( | 142 void NewNonFrontendDataTypeController::StartDone( |
| 142 DataTypeController::StartResult result, | 143 DataTypeController::StartResult result, |
| 143 DataTypeController::State new_state, | 144 DataTypeController::State new_state, |
| 144 const SyncError& error) { | 145 const csync::SyncError& error) { |
| 145 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 147 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 147 base::Bind( | 148 base::Bind( |
| 148 &NewNonFrontendDataTypeController::StartDoneImpl, | 149 &NewNonFrontendDataTypeController::StartDoneImpl, |
| 149 this, | 150 this, |
| 150 result, | 151 result, |
| 151 new_state, | 152 new_state, |
| 152 error)); | 153 error)); |
| 153 } | 154 } |
| 154 | 155 |
| 155 void NewNonFrontendDataTypeController::StartDoneImpl( | 156 void NewNonFrontendDataTypeController::StartDoneImpl( |
| 156 DataTypeController::StartResult result, | 157 DataTypeController::StartResult result, |
| 157 DataTypeController::State new_state, | 158 DataTypeController::State new_state, |
| 158 const SyncError& error) { | 159 const csync::SyncError& error) { |
| 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 160 // If we failed to start up, and we haven't been stopped yet, we need to | 161 // If we failed to start up, and we haven't been stopped yet, we need to |
| 161 // ensure we clean up the local service and shared change processor properly. | 162 // ensure we clean up the local service and shared change processor properly. |
| 162 if (new_state != RUNNING && state() != NOT_RUNNING && state() != STOPPING) { | 163 if (new_state != RUNNING && state() != NOT_RUNNING && state() != STOPPING) { |
| 163 ClearSharedChangeProcessor(); | 164 ClearSharedChangeProcessor(); |
| 164 StopLocalServiceAsync(); | 165 StopLocalServiceAsync(); |
| 165 } | 166 } |
| 166 NonFrontendDataTypeController::StartDoneImpl(result, new_state, error); | 167 NonFrontendDataTypeController::StartDoneImpl(result, new_state, error); |
| 167 } | 168 } |
| 168 | 169 |
| 169 void NewNonFrontendDataTypeController::AbortModelStarting() { | 170 void NewNonFrontendDataTypeController::AbortModelStarting() { |
| 170 set_state(NOT_RUNNING); | 171 set_state(NOT_RUNNING); |
| 171 StopModels(); | 172 StopModels(); |
| 172 ModelLoadCallback model_load_callback = model_load_callback_; | 173 ModelLoadCallback model_load_callback = model_load_callback_; |
| 173 model_load_callback_.Reset(); | 174 model_load_callback_.Reset(); |
| 174 model_load_callback.Run(type(), SyncError(FROM_HERE, | 175 model_load_callback.Run(type(), csync::SyncError(FROM_HERE, |
| 175 "ABORTED", | 176 "ABORTED", |
| 176 type())); | 177 type())); |
| 177 } | 178 } |
| 178 | 179 |
| 179 bool NewNonFrontendDataTypeController::StartAssociationAsync() { | 180 bool NewNonFrontendDataTypeController::StartAssociationAsync() { |
| 180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 181 DCHECK_EQ(state(), ASSOCIATING); | 182 DCHECK_EQ(state(), ASSOCIATING); |
| 182 return PostTaskOnBackendThread( | 183 return PostTaskOnBackendThread( |
| 183 FROM_HERE, | 184 FROM_HERE, |
| 184 base::Bind( | 185 base::Bind( |
| 185 &NewNonFrontendDataTypeController:: | 186 &NewNonFrontendDataTypeController:: |
| 186 StartAssociationWithSharedChangeProcessor, | 187 StartAssociationWithSharedChangeProcessor, |
| 187 this, | 188 this, |
| 188 shared_change_processor_)); | 189 shared_change_processor_)); |
| 189 } | 190 } |
| 190 | 191 |
| 191 // This method can execute after we've already stopped (and possibly even | 192 // This method can execute after we've already stopped (and possibly even |
| 192 // destroyed) both the Syncer and the SyncableService. As a result, all actions | 193 // destroyed) both the Syncer and the SyncableService. As a result, all actions |
| 193 // must either have no side effects outside of the DTC or must be protected | 194 // must either have no side effects outside of the DTC or must be protected |
| 194 // by |shared_change_processor|, which is guaranteed to have been Disconnected | 195 // by |shared_change_processor|, which is guaranteed to have been Disconnected |
| 195 // if the syncer shut down. | 196 // if the syncer shut down. |
| 196 void NewNonFrontendDataTypeController:: | 197 void NewNonFrontendDataTypeController:: |
| 197 StartAssociationWithSharedChangeProcessor( | 198 StartAssociationWithSharedChangeProcessor( |
| 198 const scoped_refptr<SharedChangeProcessor>& shared_change_processor) { | 199 const scoped_refptr<SharedChangeProcessor>& shared_change_processor) { |
| 199 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | 200 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 200 DCHECK(shared_change_processor.get()); | 201 DCHECK(shared_change_processor.get()); |
| 201 | 202 |
| 202 // Connect |shared_change_processor| to the syncer and get the | 203 // Connect |shared_change_processor| to the syncer and get the |
| 203 // SyncableService associated with type(). | 204 // csync::SyncableService associated with type(). |
| 204 // Note that it's possible the shared_change_processor has already been | 205 // Note that it's possible the shared_change_processor has already been |
| 205 // disconnected at this point, so all our accesses to the syncer from this | 206 // disconnected at this point, so all our accesses to the syncer from this |
| 206 // point on are through it. | 207 // point on are through it. |
| 207 local_service_ = shared_change_processor->Connect(profile_sync_factory(), | 208 local_service_ = shared_change_processor->Connect(profile_sync_factory(), |
| 208 profile_sync_service(), | 209 profile_sync_service(), |
| 209 this, | 210 this, |
| 210 type()); | 211 type()); |
| 211 if (!local_service_.get()) { | 212 if (!local_service_.get()) { |
| 212 SyncError error(FROM_HERE, "Failed to connect to syncer.", type()); | 213 csync::SyncError error(FROM_HERE, "Failed to connect to syncer.", type()); |
| 213 StartFailed(UNRECOVERABLE_ERROR, error); | 214 StartFailed(UNRECOVERABLE_ERROR, error); |
| 214 return; | 215 return; |
| 215 } | 216 } |
| 216 | 217 |
| 217 if (!shared_change_processor->CryptoReadyIfNecessary()) { | 218 if (!shared_change_processor->CryptoReadyIfNecessary()) { |
| 218 StartFailed(NEEDS_CRYPTO, SyncError()); | 219 StartFailed(NEEDS_CRYPTO, csync::SyncError()); |
| 219 return; | 220 return; |
| 220 } | 221 } |
| 221 | 222 |
| 222 bool sync_has_nodes = false; | 223 bool sync_has_nodes = false; |
| 223 if (!shared_change_processor->SyncModelHasUserCreatedNodes(&sync_has_nodes)) { | 224 if (!shared_change_processor->SyncModelHasUserCreatedNodes(&sync_has_nodes)) { |
| 224 SyncError error(FROM_HERE, "Failed to load sync nodes", type()); | 225 csync::SyncError error(FROM_HERE, "Failed to load sync nodes", type()); |
| 225 StartFailed(UNRECOVERABLE_ERROR, error); | 226 StartFailed(UNRECOVERABLE_ERROR, error); |
| 226 return; | 227 return; |
| 227 } | 228 } |
| 228 | 229 |
| 229 base::TimeTicks start_time = base::TimeTicks::Now(); | 230 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 230 SyncError error; | 231 csync::SyncError error; |
| 231 SyncDataList initial_sync_data; | 232 csync::SyncDataList initial_sync_data; |
| 232 error = shared_change_processor->GetSyncData(&initial_sync_data); | 233 error = shared_change_processor->GetSyncData(&initial_sync_data); |
| 233 if (error.IsSet()) { | 234 if (error.IsSet()) { |
| 234 StartFailed(ASSOCIATION_FAILED, error); | 235 StartFailed(ASSOCIATION_FAILED, error); |
| 235 return; | 236 return; |
| 236 } | 237 } |
| 237 // Passes a reference to |shared_change_processor|. | 238 // Passes a reference to |shared_change_processor|. |
| 238 error = local_service_->MergeDataAndStartSyncing( | 239 error = local_service_->MergeDataAndStartSyncing( |
| 239 type(), | 240 type(), |
| 240 initial_sync_data, | 241 initial_sync_data, |
| 241 scoped_ptr<SyncChangeProcessor>( | 242 scoped_ptr<csync::SyncChangeProcessor>( |
| 242 new SharedChangeProcessorRef(shared_change_processor)), | 243 new SharedChangeProcessorRef(shared_change_processor)), |
| 243 scoped_ptr<SyncErrorFactory>( | 244 scoped_ptr<csync::SyncErrorFactory>( |
| 244 new SharedChangeProcessorRef(shared_change_processor))); | 245 new SharedChangeProcessorRef(shared_change_processor))); |
| 245 RecordAssociationTime(base::TimeTicks::Now() - start_time); | 246 RecordAssociationTime(base::TimeTicks::Now() - start_time); |
| 246 if (error.IsSet()) { | 247 if (error.IsSet()) { |
| 247 StartFailed(ASSOCIATION_FAILED, error); | 248 StartFailed(ASSOCIATION_FAILED, error); |
| 248 return; | 249 return; |
| 249 } | 250 } |
| 250 | 251 |
| 251 // If we've been disconnected, profile_sync_service() may return an invalid | 252 // If we've been disconnected, profile_sync_service() may return an invalid |
| 252 // pointer, but |shared_change_processor| protects us from attempting to | 253 // pointer, but |shared_change_processor| protects us from attempting to |
| 253 // access it. | 254 // access it. |
| 254 // Note: This must be done on the datatype's thread to ensure local_service_ | 255 // Note: This must be done on the datatype's thread to ensure local_service_ |
| 255 // doesn't start trying to push changes from its thread before we activate | 256 // doesn't start trying to push changes from its thread before we activate |
| 256 // the datatype. | 257 // the datatype. |
| 257 shared_change_processor->ActivateDataType(model_safe_group()); | 258 shared_change_processor->ActivateDataType(model_safe_group()); |
| 258 StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError()); | 259 StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, csync::SyncError()); |
| 259 } | 260 } |
| 260 | 261 |
| 261 void NewNonFrontendDataTypeController::ClearSharedChangeProcessor() { | 262 void NewNonFrontendDataTypeController::ClearSharedChangeProcessor() { |
| 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 263 // |shared_change_processor_| can already be NULL if Stop() is | 264 // |shared_change_processor_| can already be NULL if Stop() is |
| 264 // called after StartDoneImpl(_, DISABLED, _). | 265 // called after StartDoneImpl(_, DISABLED, _). |
| 265 if (shared_change_processor_.get()) { | 266 if (shared_change_processor_.get()) { |
| 266 shared_change_processor_->Disconnect(); | 267 shared_change_processor_->Disconnect(); |
| 267 shared_change_processor_ = NULL; | 268 shared_change_processor_ = NULL; |
| 268 } | 269 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 280 if (local_service_.get()) | 281 if (local_service_.get()) |
| 281 local_service_->StopSyncing(type()); | 282 local_service_->StopSyncing(type()); |
| 282 local_service_.reset(); | 283 local_service_.reset(); |
| 283 } | 284 } |
| 284 | 285 |
| 285 void NewNonFrontendDataTypeController::CreateSyncComponents() { | 286 void NewNonFrontendDataTypeController::CreateSyncComponents() { |
| 286 NOTIMPLEMENTED(); | 287 NOTIMPLEMENTED(); |
| 287 } | 288 } |
| 288 | 289 |
| 289 } // namepsace browser_sync | 290 } // namepsace browser_sync |
| OLD | NEW |