| Index: chrome/browser/sync/glue/non_frontend_data_type_controller.cc
|
| diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
|
| index 2aa51491eda0ee384851873fd6df64c6fd93863b..7a0b89a7fc6a4855d871e0665195ed8a916f284f 100644
|
| --- a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
|
| +++ b/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
|
| @@ -22,15 +22,6 @@ using content::BrowserThread;
|
|
|
| namespace browser_sync {
|
|
|
| -NonFrontendDataTypeController::NonFrontendDataTypeController()
|
| - : profile_sync_factory_(NULL),
|
| - profile_(NULL),
|
| - profile_sync_service_(NULL),
|
| - state_(NOT_RUNNING),
|
| - abort_association_(false),
|
| - abort_association_complete_(false, false),
|
| - datatype_stopped_(false, false) {}
|
| -
|
| NonFrontendDataTypeController::NonFrontendDataTypeController(
|
| ProfileSyncComponentsFactory* profile_sync_factory,
|
| Profile* profile,
|
| @@ -48,10 +39,6 @@ NonFrontendDataTypeController::NonFrontendDataTypeController(
|
| DCHECK(profile_sync_service_);
|
| }
|
|
|
| -NonFrontendDataTypeController::~NonFrontendDataTypeController() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -}
|
| -
|
| void NonFrontendDataTypeController::Start(const StartCallback& start_callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| DCHECK(!start_callback.is_null());
|
| @@ -80,110 +67,6 @@ void NonFrontendDataTypeController::Start(const StartCallback& start_callback) {
|
| }
|
| }
|
|
|
| -bool NonFrontendDataTypeController::StartModels() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK_EQ(state_, MODEL_STARTING);
|
| - // By default, no additional services need to be started before we can proceed
|
| - // with model association, so do nothing.
|
| - return true;
|
| -}
|
| -
|
| -void NonFrontendDataTypeController::StartAssociation() {
|
| - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK_EQ(state_, ASSOCIATING);
|
| - {
|
| - base::AutoLock lock(abort_association_lock_);
|
| - if (abort_association_) {
|
| - abort_association_complete_.Signal();
|
| - return;
|
| - }
|
| - CreateSyncComponents();
|
| - }
|
| -
|
| - if (!model_associator_->CryptoReadyIfNecessary()) {
|
| - StartFailed(NEEDS_CRYPTO, SyncError());
|
| - return;
|
| - }
|
| -
|
| - bool sync_has_nodes = false;
|
| - if (!model_associator_->SyncModelHasUserCreatedNodes(&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;
|
| - error = model_associator_->AssociateModels();
|
| - // TODO(lipalani): crbug.com/122690 - handle abort.
|
| - RecordAssociationTime(base::TimeTicks::Now() - start_time);
|
| - if (error.IsSet()) {
|
| - StartFailed(ASSOCIATION_FAILED, error);
|
| - return;
|
| - }
|
| -
|
| - profile_sync_service_->ActivateDataType(type(), model_safe_group(),
|
| - change_processor());
|
| - StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError());
|
| -}
|
| -
|
| -void NonFrontendDataTypeController::StartFailed(StartResult result,
|
| - const SyncError& error) {
|
| - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - if (IsUnrecoverableResult(result))
|
| - RecordUnrecoverableError(FROM_HERE, "StartFailed");
|
| - StopAssociation();
|
| - StartDone(result,
|
| - result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING,
|
| - error);
|
| -}
|
| -
|
| -void NonFrontendDataTypeController::StartDone(
|
| - DataTypeController::StartResult result,
|
| - DataTypeController::State new_state,
|
| - const SyncError& error) {
|
| - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - abort_association_complete_.Signal();
|
| - base::AutoLock lock(abort_association_lock_);
|
| - if (!abort_association_) {
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&NonFrontendDataTypeController::StartDoneImpl,
|
| - this,
|
| - result,
|
| - new_state,
|
| - error));
|
| - }
|
| -}
|
| -
|
| -void NonFrontendDataTypeController::StartDoneImpl(
|
| - DataTypeController::StartResult result,
|
| - DataTypeController::State new_state,
|
| - const SyncError& error) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - // It's possible to have StartDoneImpl called first from the UI thread
|
| - // (due to Stop being called) and then posted from the non-UI thread. In
|
| - // this case, we drop the second call because we've already been stopped.
|
| - if (state_ == NOT_RUNNING) {
|
| - DCHECK(start_callback_.is_null());
|
| - return;
|
| - }
|
| -
|
| - state_ = new_state;
|
| - if (state_ != RUNNING) {
|
| - // Start failed.
|
| - StopModels();
|
| - RecordStartFailure(result);
|
| - }
|
| -
|
| - // We have to release the callback before we call it, since it's possible
|
| - // invoking the callback will trigger a call to STOP(), which will get
|
| - // confused by the non-NULL start_callback_.
|
| - StartCallback callback = start_callback_;
|
| - start_callback_.Reset();
|
| - callback.Run(result, error);
|
| -}
|
| -
|
| // TODO(sync): Blocking the UI thread at shutdown is bad. The new API avoids
|
| // this. Once all non-frontend datatypes use the new API, we can get rid of this
|
| // locking (see implementation in AutofillProfileDataTypeController).
|
| @@ -239,24 +122,6 @@ void NonFrontendDataTypeController::Stop() {
|
| state_ = NOT_RUNNING;
|
| }
|
|
|
| -void NonFrontendDataTypeController::StopModels() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(state_ == STOPPING || state_ == NOT_RUNNING || state_ == DISABLED);
|
| - DVLOG(1) << "NonFrontendDataTypeController::StopModels(): State = " << state_;
|
| - // Do nothing by default.
|
| -}
|
| -
|
| -void NonFrontendDataTypeController::StopAssociation() {
|
| - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - if (model_associator_.get()) {
|
| - SyncError error; // Not used.
|
| - error = model_associator_->DisassociateModels();
|
| - }
|
| - model_associator_.reset();
|
| - change_processor_.reset();
|
| - datatype_stopped_.Signal();
|
| -}
|
| -
|
| std::string NonFrontendDataTypeController::name() const {
|
| // For logging only.
|
| return syncable::ModelTypeToString(type());
|
| @@ -290,28 +155,97 @@ void NonFrontendDataTypeController::OnSingleDatatypeUnrecoverableError(
|
| message));
|
| }
|
|
|
| -void NonFrontendDataTypeController::OnUnrecoverableErrorImpl(
|
| - const tracked_objects::Location& from_here,
|
| - const std::string& message) {
|
| +NonFrontendDataTypeController::NonFrontendDataTypeController()
|
| + : profile_sync_factory_(NULL),
|
| + profile_(NULL),
|
| + profile_sync_service_(NULL),
|
| + state_(NOT_RUNNING),
|
| + abort_association_(false),
|
| + abort_association_complete_(false, false),
|
| + datatype_stopped_(false, false) {
|
| +}
|
| +
|
| +NonFrontendDataTypeController::~NonFrontendDataTypeController() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - profile_sync_service_->OnUnrecoverableError(from_here, message);
|
| }
|
|
|
| -bool NonFrontendDataTypeController::StartAssociationAsync() {
|
| +bool NonFrontendDataTypeController::StartModels() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK_EQ(state(), ASSOCIATING);
|
| - return PostTaskOnBackendThread(
|
| - FROM_HERE,
|
| - base::Bind(&NonFrontendDataTypeController::StartAssociation, this));
|
| + DCHECK_EQ(state_, MODEL_STARTING);
|
| + // By default, no additional services need to be started before we can proceed
|
| + // with model association, so do nothing.
|
| + return true;
|
| }
|
|
|
| -bool NonFrontendDataTypeController::StopAssociationAsync() {
|
| +void NonFrontendDataTypeController::StartFailed(StartResult result,
|
| + const SyncError& error) {
|
| + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (IsUnrecoverableResult(result))
|
| + RecordUnrecoverableError(FROM_HERE, "StartFailed");
|
| + StopAssociation();
|
| + StartDone(result,
|
| + result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING,
|
| + error);
|
| +}
|
| +
|
| +void NonFrontendDataTypeController::StartDone(
|
| + DataTypeController::StartResult result,
|
| + DataTypeController::State new_state,
|
| + const SyncError& error) {
|
| + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + abort_association_complete_.Signal();
|
| + base::AutoLock lock(abort_association_lock_);
|
| + if (!abort_association_) {
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&NonFrontendDataTypeController::StartDoneImpl,
|
| + this,
|
| + result,
|
| + new_state,
|
| + error));
|
| + }
|
| +}
|
| +
|
| +void NonFrontendDataTypeController::StartDoneImpl(
|
| + DataTypeController::StartResult result,
|
| + DataTypeController::State new_state,
|
| + const SyncError& error) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK_EQ(state(), STOPPING);
|
| - return PostTaskOnBackendThread(
|
| - FROM_HERE,
|
| - base::Bind(
|
| - &NonFrontendDataTypeController::StopAssociation, this));
|
| + // It's possible to have StartDoneImpl called first from the UI thread
|
| + // (due to Stop being called) and then posted from the non-UI thread. In
|
| + // this case, we drop the second call because we've already been stopped.
|
| + if (state_ == NOT_RUNNING) {
|
| + DCHECK(start_callback_.is_null());
|
| + return;
|
| + }
|
| +
|
| + state_ = new_state;
|
| + if (state_ != RUNNING) {
|
| + // Start failed.
|
| + StopModels();
|
| + RecordStartFailure(result);
|
| + }
|
| +
|
| + // We have to release the callback before we call it, since it's possible
|
| + // invoking the callback will trigger a call to STOP(), which will get
|
| + // confused by the non-NULL start_callback_.
|
| + StartCallback callback = start_callback_;
|
| + start_callback_.Reset();
|
| + callback.Run(result, error);
|
| +}
|
| +
|
| +void NonFrontendDataTypeController::StopModels() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK(state_ == STOPPING || state_ == NOT_RUNNING || state_ == DISABLED);
|
| + DVLOG(1) << "NonFrontendDataTypeController::StopModels(): State = " << state_;
|
| + // Do nothing by default.
|
| +}
|
| +
|
| +void NonFrontendDataTypeController::OnUnrecoverableErrorImpl(
|
| + const tracked_objects::Location& from_here,
|
| + const std::string& message) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + profile_sync_service_->OnUnrecoverableError(from_here, message);
|
| }
|
|
|
| void NonFrontendDataTypeController::DisableImpl(
|
| @@ -341,6 +275,14 @@ void NonFrontendDataTypeController::RecordStartFailure(StartResult result) {
|
| #undef PER_DATA_TYPE_MACRO
|
| }
|
|
|
| +bool NonFrontendDataTypeController::StartAssociationAsync() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK_EQ(state(), ASSOCIATING);
|
| + return PostTaskOnBackendThread(
|
| + FROM_HERE,
|
| + base::Bind(&NonFrontendDataTypeController::StartAssociation, this));
|
| +}
|
| +
|
| ProfileSyncComponentsFactory*
|
| NonFrontendDataTypeController::profile_sync_factory() const {
|
| return profile_sync_factory_;
|
| @@ -359,6 +301,7 @@ void NonFrontendDataTypeController::set_start_callback(
|
| const StartCallback& callback) {
|
| start_callback_ = callback;
|
| }
|
| +
|
| void NonFrontendDataTypeController::set_state(State state) {
|
| state_ = state;
|
| }
|
| @@ -381,4 +324,63 @@ void NonFrontendDataTypeController::set_change_processor(
|
| change_processor_.reset(change_processor);
|
| }
|
|
|
| +void NonFrontendDataTypeController::StartAssociation() {
|
| + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK_EQ(state_, ASSOCIATING);
|
| + {
|
| + base::AutoLock lock(abort_association_lock_);
|
| + if (abort_association_) {
|
| + abort_association_complete_.Signal();
|
| + return;
|
| + }
|
| + CreateSyncComponents();
|
| + }
|
| +
|
| + if (!model_associator_->CryptoReadyIfNecessary()) {
|
| + StartFailed(NEEDS_CRYPTO, SyncError());
|
| + return;
|
| + }
|
| +
|
| + bool sync_has_nodes = false;
|
| + if (!model_associator_->SyncModelHasUserCreatedNodes(&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;
|
| + error = model_associator_->AssociateModels();
|
| + // TODO(lipalani): crbug.com/122690 - handle abort.
|
| + RecordAssociationTime(base::TimeTicks::Now() - start_time);
|
| + if (error.IsSet()) {
|
| + StartFailed(ASSOCIATION_FAILED, error);
|
| + return;
|
| + }
|
| +
|
| + profile_sync_service_->ActivateDataType(type(), model_safe_group(),
|
| + change_processor());
|
| + StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError());
|
| +}
|
| +
|
| +bool NonFrontendDataTypeController::StopAssociationAsync() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + DCHECK_EQ(state(), STOPPING);
|
| + return PostTaskOnBackendThread(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &NonFrontendDataTypeController::StopAssociation, this));
|
| +}
|
| +
|
| +void NonFrontendDataTypeController::StopAssociation() {
|
| + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (model_associator_.get()) {
|
| + SyncError error; // Not used.
|
| + error = model_associator_->DisassociateModels();
|
| + }
|
| + model_associator_.reset();
|
| + change_processor_.reset();
|
| + datatype_stopped_.Signal();
|
| +}
|
| +
|
| } // namespace browser_sync
|
|
|