| Index: chrome/browser/sync/glue/generic_change_processor.cc | 
| diff --git a/chrome/browser/sync/glue/generic_change_processor.cc b/chrome/browser/sync/glue/generic_change_processor.cc | 
| index 8a064af20c4d499b27e6799e7d027245416e36b0..eb8e4b45bba969b8e46d68ab387ae37d853a17cb 100644 | 
| --- a/chrome/browser/sync/glue/generic_change_processor.cc | 
| +++ b/chrome/browser/sync/glue/generic_change_processor.cc | 
| @@ -17,21 +17,45 @@ | 
| #include "chrome/browser/sync/internal_api/write_transaction.h" | 
| #include "chrome/browser/sync/unrecoverable_error_handler.h" | 
|  | 
| +using base::AutoLock; | 
| + | 
| namespace browser_sync { | 
|  | 
| GenericChangeProcessor::GenericChangeProcessor( | 
| -    SyncableService* local_service, | 
| +    UnrecoverableErrorHandler* error_handler) | 
| +    : ChangeProcessor(error_handler), | 
| +      local_service_(NULL), | 
| +      user_share_(NULL), | 
| +      disconnected_(false) {} | 
| + | 
| +GenericChangeProcessor::GenericChangeProcessor( | 
| UnrecoverableErrorHandler* error_handler, | 
| +    SyncableService* local_service, | 
| sync_api::UserShare* user_share) | 
| : ChangeProcessor(error_handler), | 
| -      local_service_(local_service), | 
| -      user_share_(user_share) { | 
| -  DCHECK(local_service_); | 
| +      local_service_(NULL), | 
| +      user_share_(NULL), | 
| +      disconnected_(false) { | 
| +  Connect(local_service, user_share); | 
| +} | 
| + | 
| +GenericChangeProcessor::~GenericChangeProcessor() {} | 
| + | 
| +// Connect to the syncer and SyncableService specified. | 
| +void GenericChangeProcessor::Connect(SyncableService* local_service, | 
| +                                     sync_api::UserShare* user_share) { | 
| +  AutoLock lock(monitor_lock_); | 
| +  if (disconnected_) | 
| +    return; | 
| +  DCHECK(local_service); | 
| +  local_service_ = local_service; | 
| +  user_share_ = user_share; | 
| } | 
|  | 
| -GenericChangeProcessor::~GenericChangeProcessor() { | 
| -  // Set to null to ensure it's not used after destruction. | 
| -  local_service_ = NULL; | 
| +void GenericChangeProcessor::Disconnect() { | 
| +  VLOG(1) << "Disconnecting change processor."; | 
| +  AutoLock lock(monitor_lock_); | 
| +  disconnected_ = true; | 
| } | 
|  | 
| void GenericChangeProcessor::ApplyChangesFromSyncModel( | 
| @@ -70,7 +94,7 @@ void GenericChangeProcessor::CommitChangesFromSyncModel() { | 
| if (syncer_changes_.empty()) | 
| return; | 
| SyncError error = local_service_->ProcessSyncChanges(FROM_HERE, | 
| -                                                        syncer_changes_); | 
| +                                                       syncer_changes_); | 
| syncer_changes_.clear(); | 
| if (error.IsSet()) { | 
| error_handler()->OnUnrecoverableError(error.location(), error.message()); | 
| @@ -80,6 +104,11 @@ void GenericChangeProcessor::CommitChangesFromSyncModel() { | 
| SyncError GenericChangeProcessor::GetSyncDataForType( | 
| syncable::ModelType type, | 
| SyncDataList* current_sync_data) { | 
| +  AutoLock lock(monitor_lock_); | 
| +  if (disconnected_) { | 
| +    SyncError error(FROM_HERE, "Change processor disconnected.", type); | 
| +    return error; | 
| +  } | 
| std::string type_name = syncable::ModelTypeToString(type); | 
| sync_api::ReadTransaction trans(FROM_HERE, share_handle()); | 
| sync_api::ReadNode root(&trans); | 
| @@ -137,6 +166,17 @@ bool AttemptDelete(const SyncChange& change, sync_api::WriteNode* node) { | 
| SyncError GenericChangeProcessor::ProcessSyncChanges( | 
| const tracked_objects::Location& from_here, | 
| const SyncChangeList& list_of_changes) { | 
| +  AutoLock lock(monitor_lock_); | 
| +  if (disconnected_) { | 
| +    syncable::ModelType type; | 
| +    if (list_of_changes.size() > 0) { | 
| +      type = list_of_changes[0].sync_data().GetDataType(); | 
| +      local_service_->StopSyncing(type); | 
| +    } | 
| +    SyncError error(FROM_HERE, "Change processor disconnected.", | 
| +                    syncable::UNSPECIFIED); | 
| +    return error; | 
| +  } | 
| sync_api::WriteTransaction trans(from_here, share_handle()); | 
|  | 
| for (SyncChangeList::const_iterator iter = list_of_changes.begin(); | 
| @@ -216,6 +256,11 @@ SyncError GenericChangeProcessor::ProcessSyncChanges( | 
| bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( | 
| syncable::ModelType type, | 
| bool* has_nodes) { | 
| +  AutoLock lock(monitor_lock_); | 
| +  if (disconnected_) { | 
| +    LOG(ERROR) << "Change processor disconnected."; | 
| +    return false; | 
| +  } | 
| DCHECK(has_nodes); | 
| DCHECK_NE(type, syncable::UNSPECIFIED); | 
| std::string type_name = syncable::ModelTypeToString(type); | 
| @@ -236,6 +281,11 @@ bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( | 
| } | 
|  | 
| bool GenericChangeProcessor::CryptoReadyIfNecessary(syncable::ModelType type) { | 
| +  AutoLock lock(monitor_lock_); | 
| +  if (disconnected_) { | 
| +    LOG(ERROR) << "Change processor disconnected."; | 
| +    return true;  // Otherwise we get into infinite spin waiting. | 
| +  } | 
| DCHECK_NE(type, syncable::UNSPECIFIED); | 
| // We only access the cryptographer while holding a transaction. | 
| sync_api::ReadTransaction trans(FROM_HERE, share_handle()); | 
| @@ -247,7 +297,9 @@ bool GenericChangeProcessor::CryptoReadyIfNecessary(syncable::ModelType type) { | 
|  | 
| void GenericChangeProcessor::StartImpl(Profile* profile) {} | 
|  | 
| -void GenericChangeProcessor::StopImpl() {} | 
| +void GenericChangeProcessor::StopImpl() { | 
| +  Disconnect(); | 
| +} | 
|  | 
| sync_api::UserShare* GenericChangeProcessor::share_handle() { | 
| return user_share_; | 
|  |