Index: chrome/browser/sync/glue/new_non_frontend_data_type_controller.cc |
diff --git a/chrome/browser/sync/glue/new_non_frontend_data_type_controller.cc b/chrome/browser/sync/glue/new_non_frontend_data_type_controller.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ecea4b6b633874a3005e39b056fc6caadb1f809e |
--- /dev/null |
+++ b/chrome/browser/sync/glue/new_non_frontend_data_type_controller.cc |
@@ -0,0 +1,173 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/sync/glue/new_non_frontend_data_type_controller.h" |
+ |
+#include "base/logging.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/sync/api/sync_error.h" |
+#include "chrome/browser/sync/api/syncable_service.h" |
+#include "chrome/browser/sync/glue/shared_change_processor_ref.h" |
+#include "chrome/browser/sync/profile_sync_factory.h" |
+#include "chrome/browser/sync/profile_sync_service.h" |
+#include "chrome/browser/sync/syncable/model_type.h" |
+#include "content/browser/browser_thread.h" |
+ |
+namespace browser_sync { |
+ |
+NewNonFrontendDataTypeController::NewNonFrontendDataTypeController() |
+ : user_share_(NULL), |
+ local_service_(NULL), |
+ shared_change_processor_(NULL) {} |
+ |
+NewNonFrontendDataTypeController::NewNonFrontendDataTypeController( |
+ ProfileSyncFactory* profile_sync_factory, |
+ Profile* profile) |
+ : NonFrontendDataTypeController(profile_sync_factory, profile), |
+ user_share_(NULL), |
+ local_service_(NULL), |
+ shared_change_processor_(NULL) { |
+} |
+ |
+NewNonFrontendDataTypeController::~NewNonFrontendDataTypeController() {} |
+ |
+void NewNonFrontendDataTypeController::Start(StartCallback* start_callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(start_callback); |
+ if (state() != NOT_RUNNING) { |
+ start_callback->Run(BUSY, SyncError()); |
+ delete start_callback; |
+ return; |
+ } |
+ |
+ set_start_callback(start_callback); |
+ |
+ set_state(MODEL_STARTING); |
+ if (!StartModels()) { |
+ // If we are waiting for some external service to load before associating |
+ // or we failed to start the models, we exit early. |
+ DCHECK(state() == MODEL_STARTING || state() == NOT_RUNNING); |
+ return; |
+ } |
+ |
+ shared_change_processor_ = |
+ profile_sync_factory()->CreateSharedChangeProcessor(this); |
+ user_share_ = profile_sync_service()->GetUserShare(); |
+ |
+ // Kick off association on the thread the datatype resides on. |
+ set_state(ASSOCIATING); |
+ if (!StartAssociationAsync()) { |
+ shared_change_processor_ = NULL; |
+ SyncError error(FROM_HERE, "Failed to post StartAssociation", type()); |
+ StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, error); |
+ } |
+} |
+ |
+void NewNonFrontendDataTypeController::StartAssociation() { |
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK_EQ(state(), ASSOCIATING); |
+ |
+ local_service_ = GetSyncableService(); |
+ shared_change_processor_->Connect(local_service_, user_share_); |
+ |
+ if (!shared_change_processor_->CryptoReadyIfNecessary(type())) { |
+ StartFailed(NEEDS_CRYPTO, SyncError()); |
+ return; |
+ } |
+ |
+ bool sync_has_nodes = false; |
+ if (!shared_change_processor_->SyncModelHasUserCreatedNodes( |
+ type(), &sync_has_nodes)) { |
+ SyncError error(FROM_HERE, "Failed to load sync nodes", type()); |
+ StartFailed(UNRECOVERABLE_ERROR, error); |
+ return; |
+ } |
+ |
+ base::TimeTicks start_time = base::TimeTicks::Now(); |
+ SyncError error; |
+ SyncDataList initial_sync_data; |
+ error = shared_change_processor_->GetSyncDataForType(type(), |
+ &initial_sync_data); |
+ if (error.IsSet()) { |
+ StartFailed(ASSOCIATION_FAILED, error); |
+ return; |
+ } |
+ // Passes a reference to the shared_change_processor_; |
+ error = local_service_->MergeDataAndStartSyncing( |
+ type(), |
+ initial_sync_data, |
+ new SharedChangeProcessorRef(shared_change_processor_)); |
+ RecordAssociationTime(base::TimeTicks::Now() - start_time); |
+ if (error.IsSet()) { |
+ local_service_->StopSyncing(type()); |
+ StartFailed(ASSOCIATION_FAILED, error); |
+ return; |
+ } |
+ |
+ // This is kind of ugly, but safe since we guarantee that the SyncableService |
+ // will be around longer than the PSS, and hence the referene it holds |
+ // to the SharedChangeProcessor will stick around. |
+ profile_sync_service()->ActivateDataType(type(), model_safe_group(), |
+ shared_change_processor_); |
+ StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError()); |
+} |
+ |
+void NewNonFrontendDataTypeController::Stop() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ // Disconnect the change processor. At this point, the SyncableService |
+ // can no longer interact with the Syncer, even if it hasn't finished |
+ // MergeDataAndStartSyncing. The shared change processor is owned by |
+ // local_service_ so we don't have to delete it. Just post a task to tell it |
+ // to StopSyncing. |
+ if (shared_change_processor_.get()) { |
+ shared_change_processor_->Disconnect(); |
+ if (!StopLocalServiceAsync()) { |
+ LOG(ERROR) << "Failed to stop " << type() << "'s syncable service. " |
+ << "Continuing, but this may cause problems on sync restart."; |
+ } |
+ } |
+ |
+ // If we haven't finished starting, we need to abort the start. |
+ if (state() == MODEL_STARTING) { |
+ set_state(STOPPING); |
+ StartDoneImpl(ABORTED, NOT_RUNNING, SyncError()); |
+ return; // The datatype was never activated, we're done. |
+ } else if (state() == ASSOCIATING) { |
+ set_state(STOPPING); |
+ StartDoneImpl(ABORTED, NOT_RUNNING, SyncError()); |
+ // We continue on to deactivate the datatype. |
+ } else { |
+ // Datatype was fully started. |
+ set_state(STOPPING); |
+ StopModels(); |
+ } |
+ |
+ // Deactivate the DataType on the UI thread. We dont want to listen |
+ // for any more changes or process them from the server. |
+ profile_sync_service()->DeactivateDataType(type()); |
+ |
+ set_state(NOT_RUNNING); |
+} |
+ |
+// Static. |
+void NewNonFrontendDataTypeController::StopLocalService( |
+ SyncableService* service, syncable::ModelType type) { |
+ service->StopSyncing(type); |
+} |
+ |
+SyncableService* NewNonFrontendDataTypeController::local_service() const { |
+ return local_service_; |
+} |
+ |
+bool NewNonFrontendDataTypeController::StopAssociationAsync() { |
+ NOTIMPLEMENTED(); |
+ return false; |
+} |
+ |
+void NewNonFrontendDataTypeController::CreateSyncComponents() { |
+ NOTIMPLEMENTED(); |
+} |
+ |
+} // namepsace browser_sync |