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.
5 #include "chrome/browser/sync/glue/shared_change_processor.h"
7 #include "base/message_loop/message_loop_proxy.h"
8 #include "components/sync_driver/generic_change_processor.h"
9 #include "components/sync_driver/generic_change_processor_factory.h"
10 #include "components/sync_driver/sync_api_component_factory.h"
11 #include "sync/api/attachments/attachment_service.h"
12 #include "sync/api/attachments/fake_attachment_service.h"
13 #include "sync/api/attachments/fake_attachment_uploader.h"
14 #include "sync/api/sync_change.h"
18 namespace browser_sync {
20 SharedChangeProcessor::SharedChangeProcessor()
21 : disconnected_(false),
22 type_(syncer::UNSPECIFIED),
23 frontend_loop_(base::MessageLoopProxy::current()),
24 generic_change_processor_(NULL),
25 error_handler_(NULL) {
28 SharedChangeProcessor::~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 (frontend_loop_->BelongsToCurrentThread()) {
34 if (backend_loop_.get()) {
35 if (!backend_loop_->DeleteSoon(FROM_HERE, generic_change_processor_)) {
39 DCHECK(!generic_change_processor_);
42 DCHECK(backend_loop_.get());
43 DCHECK(backend_loop_->BelongsToCurrentThread());
44 delete generic_change_processor_;
48 base::WeakPtr<syncer::SyncableService> SharedChangeProcessor::Connect(
49 browser_sync::SyncApiComponentFactory* sync_factory,
50 GenericChangeProcessorFactory* processor_factory,
51 syncer::UserShare* user_share,
52 DataTypeErrorHandler* error_handler,
53 syncer::ModelType type,
54 const base::WeakPtr<syncer::SyncMergeResult>& merge_result) {
56 DCHECK(error_handler);
57 DCHECK_NE(type, syncer::UNSPECIFIED);
58 backend_loop_ = base::MessageLoopProxy::current();
59 AutoLock lock(monitor_lock_);
61 return base::WeakPtr<syncer::SyncableService>();
63 error_handler_ = error_handler;
64 base::WeakPtr<syncer::SyncableService> local_service =
65 sync_factory->GetSyncableServiceForType(type);
66 if (!local_service.get()) {
67 LOG(WARNING) << "SyncableService destroyed before DTC was stopped.";
69 return base::WeakPtr<syncer::SyncableService>();
72 // TODO(maniscalco): Use a shared (one per profile) thread-safe instance of
73 // AttachmentUpload instead of creating a new one per AttachmentService (bug
75 scoped_ptr<syncer::AttachmentUploader> attachment_uploader(
76 new syncer::FakeAttachmentUploader);
78 // TODO(maniscalco): Replace FakeAttachmentService with a real
79 // AttachmentService implementation once implemented (bug 356359).
80 scoped_ptr<syncer::AttachmentService> attachment_service(
81 new syncer::FakeAttachmentService(
82 sync_factory->CreateCustomAttachmentStoreForType(type),
83 attachment_uploader.Pass()));
85 generic_change_processor_ = processor_factory->CreateGenericChangeProcessor(
90 attachment_service.Pass()).release();
94 bool SharedChangeProcessor::Disconnect() {
95 // May be called from any thread.
96 DVLOG(1) << "Disconnecting change processor.";
97 AutoLock lock(monitor_lock_);
98 bool was_connected = !disconnected_;
100 error_handler_ = NULL;
101 return was_connected;
104 ChangeProcessor* SharedChangeProcessor::generic_change_processor() {
105 return generic_change_processor_;
108 int SharedChangeProcessor::GetSyncCount() {
109 DCHECK(backend_loop_.get());
110 DCHECK(backend_loop_->BelongsToCurrentThread());
111 AutoLock lock(monitor_lock_);
113 LOG(ERROR) << "Change processor disconnected.";
116 return generic_change_processor_->GetSyncCountForType(type_);
119 syncer::SyncError SharedChangeProcessor::ProcessSyncChanges(
120 const tracked_objects::Location& from_here,
121 const syncer::SyncChangeList& list_of_changes) {
122 DCHECK(backend_loop_.get());
123 DCHECK(backend_loop_->BelongsToCurrentThread());
124 AutoLock lock(monitor_lock_);
126 // The DTC that disconnects us must ensure it posts a StopSyncing task.
127 // If we reach this, it means it just hasn't executed yet.
128 syncer::SyncError error(FROM_HERE,
129 syncer::SyncError::DATATYPE_ERROR,
130 "Change processor disconnected.",
134 return generic_change_processor_->ProcessSyncChanges(
135 from_here, list_of_changes);
138 syncer::SyncDataList SharedChangeProcessor::GetAllSyncData(
139 syncer::ModelType type) const {
140 syncer::SyncDataList data;
141 GetAllSyncDataReturnError(type, &data); // Handles the disconnect case.
145 syncer::SyncError SharedChangeProcessor::GetAllSyncDataReturnError(
146 syncer::ModelType type,
147 syncer::SyncDataList* data) const {
148 DCHECK(backend_loop_.get());
149 DCHECK(backend_loop_->BelongsToCurrentThread());
150 AutoLock lock(monitor_lock_);
152 syncer::SyncError error(FROM_HERE,
153 syncer::SyncError::DATATYPE_ERROR,
154 "Change processor disconnected.",
158 return generic_change_processor_->GetAllSyncDataReturnError(type, data);
161 syncer::SyncError SharedChangeProcessor::UpdateDataTypeContext(
162 syncer::ModelType type,
163 syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status,
164 const std::string& context) {
165 DCHECK(backend_loop_.get());
166 DCHECK(backend_loop_->BelongsToCurrentThread());
167 AutoLock lock(monitor_lock_);
169 syncer::SyncError error(FROM_HERE,
170 syncer::SyncError::DATATYPE_ERROR,
171 "Change processor disconnected.",
175 return generic_change_processor_->UpdateDataTypeContext(
176 type, refresh_status, context);
179 bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) {
180 DCHECK(backend_loop_.get());
181 DCHECK(backend_loop_->BelongsToCurrentThread());
182 AutoLock lock(monitor_lock_);
184 LOG(ERROR) << "Change processor disconnected.";
187 return generic_change_processor_->SyncModelHasUserCreatedNodes(
191 bool SharedChangeProcessor::CryptoReadyIfNecessary() {
192 DCHECK(backend_loop_.get());
193 DCHECK(backend_loop_->BelongsToCurrentThread());
194 AutoLock lock(monitor_lock_);
196 LOG(ERROR) << "Change processor disconnected.";
197 return true; // Otherwise we get into infinite spin waiting.
199 return generic_change_processor_->CryptoReadyIfNecessary(type_);
202 bool SharedChangeProcessor::GetDataTypeContext(std::string* context) const {
203 DCHECK(backend_loop_.get());
204 DCHECK(backend_loop_->BelongsToCurrentThread());
205 AutoLock lock(monitor_lock_);
207 LOG(ERROR) << "Change processor disconnected.";
210 return generic_change_processor_->GetDataTypeContext(type_, context);
213 syncer::SyncError SharedChangeProcessor::CreateAndUploadError(
214 const tracked_objects::Location& location,
215 const std::string& message) {
216 AutoLock lock(monitor_lock_);
217 if (!disconnected_) {
218 return error_handler_->CreateAndUploadError(location, message, type_);
220 return syncer::SyncError(location,
221 syncer::SyncError::DATATYPE_ERROR,
227 } // namespace browser_sync