shared_change_processor.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 3// found in the LICENSE file. 4 5#include "chrome/browser/sync/glue/shared_change_processor.h" 6 7#include "chrome/browser/sync/glue/generic_change_processor.h" 8#include "chrome/browser/sync/profile_sync_components_factory.h" 9#include "chrome/browser/sync/profile_sync_service.h" 10#include "content/public/browser/browser_thread.h" 11#include "sync/api/sync_change.h" 12 13using base::AutoLock; 14using content::BrowserThread; 15 16namespace browser_sync { 17 18SharedChangeProcessor::SharedChangeProcessor() 19 : disconnected_(false), 20 type_(syncer::UNSPECIFIED), 21 sync_service_(NULL), 22 generic_change_processor_(NULL), 23 error_handler_(NULL) { 24 // We're always created on the UI thread. 25 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 26} 27 28SharedChangeProcessor::~SharedChangeProcessor() { 29 // We can either be deleted when the DTC is destroyed (on UI 30 // thread), or when the syncer::SyncableService stop's syncing (datatype 31 // thread). |generic_change_processor_|, if non-NULL, must be 32 // deleted on |backend_loop_|. 33 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 34 if (backend_loop_.get()) { 35 if (!backend_loop_->DeleteSoon(FROM_HERE, generic_change_processor_)) { 36 NOTREACHED(); 37 } 38 } else { 39 DCHECK(!generic_change_processor_); 40 } 41 } else { 42 DCHECK(backend_loop_.get()); 43 DCHECK(backend_loop_->BelongsToCurrentThread()); 44 delete generic_change_processor_; 45 } 46} 47 48base::WeakPtr<syncer::SyncableService> SharedChangeProcessor::Connect( 49 ProfileSyncComponentsFactory* sync_factory, 50 ProfileSyncService* sync_service, 51 DataTypeErrorHandler* error_handler, 52 syncer::ModelType type, 53 const base::WeakPtr<syncer::SyncMergeResult>& merge_result) { 54 DCHECK(sync_factory); 55 DCHECK(sync_service); 56 DCHECK(error_handler); 57 DCHECK_NE(type, syncer::UNSPECIFIED); 58 backend_loop_ = base::MessageLoopProxy::current(); 59 AutoLock lock(monitor_lock_); 60 if (disconnected_) 61 return base::WeakPtr<syncer::SyncableService>(); 62 type_ = type; 63 sync_service_ = sync_service; 64 error_handler_ = error_handler; 65 base::WeakPtr<syncer::SyncableService> local_service = 66 sync_factory->GetSyncableServiceForType(type); 67 if (!local_service.get()) { 68 NOTREACHED() << "SyncableService destroyed before DTC was stopped."; 69 disconnected_ = true; 70 return base::WeakPtr<syncer::SyncableService>(); 71 } 72 73 // TODO(zea): Pass |merge_result| to the generic change processor. 74 generic_change_processor_ = 75 sync_factory->CreateGenericChangeProcessor(sync_service_, 76 error_handler, 77 local_service, 78 merge_result); 79 return local_service; 80} 81 82bool SharedChangeProcessor::Disconnect() { 83 // May be called from any thread. 84 DVLOG(1) << "Disconnecting change processor."; 85 AutoLock lock(monitor_lock_); 86 bool was_connected = !disconnected_; 87 disconnected_ = true; 88 error_handler_ = NULL; 89 return was_connected; 90} 91 92syncer::SyncError SharedChangeProcessor::GetSyncData( 93 syncer::SyncDataList* current_sync_data) { 94 DCHECK(backend_loop_.get()); 95 DCHECK(backend_loop_->BelongsToCurrentThread()); 96 AutoLock lock(monitor_lock_); 97 if (disconnected_) { 98 syncer::SyncError error(FROM_HERE, "Change processor disconnected.", type_); 99 return error; 100 } 101 return generic_change_processor_->GetSyncDataForType(type_, 102 current_sync_data); 103} 104 105int SharedChangeProcessor::GetSyncCount() { 106 DCHECK(backend_loop_.get()); 107 DCHECK(backend_loop_->BelongsToCurrentThread()); 108 AutoLock lock(monitor_lock_); 109 if (disconnected_) { 110 LOG(ERROR) << "Change processor disconnected."; 111 return 0; 112 } 113 return generic_change_processor_->GetSyncCountForType(type_); 114} 115 116syncer::SyncError SharedChangeProcessor::ProcessSyncChanges( 117 const tracked_objects::Location& from_here, 118 const syncer::SyncChangeList& list_of_changes) { 119 DCHECK(backend_loop_.get()); 120 DCHECK(backend_loop_->BelongsToCurrentThread()); 121 AutoLock lock(monitor_lock_); 122 if (disconnected_) { 123 // The DTC that disconnects us must ensure it posts a StopSyncing task. 124 // If we reach this, it means it just hasn't executed yet. 125 syncer::SyncError error(FROM_HERE, "Change processor disconnected.", type_); 126 return error; 127 } 128 return generic_change_processor_->ProcessSyncChanges( 129 from_here, list_of_changes); 130} 131 132bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) { 133 DCHECK(backend_loop_.get()); 134 DCHECK(backend_loop_->BelongsToCurrentThread()); 135 AutoLock lock(monitor_lock_); 136 if (disconnected_) { 137 LOG(ERROR) << "Change processor disconnected."; 138 return false; 139 } 140 return generic_change_processor_->SyncModelHasUserCreatedNodes( 141 type_, has_nodes); 142} 143 144bool SharedChangeProcessor::CryptoReadyIfNecessary() { 145 DCHECK(backend_loop_.get()); 146 DCHECK(backend_loop_->BelongsToCurrentThread()); 147 AutoLock lock(monitor_lock_); 148 if (disconnected_) { 149 LOG(ERROR) << "Change processor disconnected."; 150 return true; // Otherwise we get into infinite spin waiting. 151 } 152 return generic_change_processor_->CryptoReadyIfNecessary(type_); 153} 154 155void SharedChangeProcessor::ActivateDataType( 156 syncer::ModelSafeGroup model_safe_group) { 157 DCHECK(backend_loop_.get()); 158 DCHECK(backend_loop_->BelongsToCurrentThread()); 159 AutoLock lock(monitor_lock_); 160 if (disconnected_) { 161 LOG(ERROR) << "Change processor disconnected."; 162 return; 163 } 164 sync_service_->ActivateDataType(type_, 165 model_safe_group, 166 generic_change_processor_); 167} 168 169syncer::SyncError SharedChangeProcessor::CreateAndUploadError( 170 const tracked_objects::Location& location, 171 const std::string& message) { 172 AutoLock lock(monitor_lock_); 173 if (!disconnected_) { 174 return error_handler_->CreateAndUploadError(location, message, type_); 175 } else { 176 return syncer::SyncError(location, message, type_); 177 } 178} 179 180} // namespace browser_sync 181