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 "chrome/browser/sync/profile_sync_service.h"
9 #include "components/sync_driver/generic_change_processor.h"
10 #include "components/sync_driver/generic_change_processor_factory.h"
11 #include "components/sync_driver/sync_api_component_factory.h"
12 #include "sync/api/attachments/attachment_service.h"
13 #include "sync/api/attachments/fake_attachment_service.h"
14 #include "sync/api/attachments/fake_attachment_uploader.h"
15 #include "sync/api/sync_change.h"
19 namespace browser_sync
{
21 SharedChangeProcessor::SharedChangeProcessor()
22 : disconnected_(false),
23 type_(syncer::UNSPECIFIED
),
25 frontend_loop_(base::MessageLoopProxy::current()),
26 generic_change_processor_(NULL
),
27 error_handler_(NULL
) {
30 SharedChangeProcessor::~SharedChangeProcessor() {
31 // We can either be deleted when the DTC is destroyed (on UI
32 // thread), or when the syncer::SyncableService stop's syncing (datatype
33 // thread). |generic_change_processor_|, if non-NULL, must be
34 // deleted on |backend_loop_|.
35 if (frontend_loop_
->BelongsToCurrentThread()) {
36 if (backend_loop_
.get()) {
37 if (!backend_loop_
->DeleteSoon(FROM_HERE
, generic_change_processor_
)) {
41 DCHECK(!generic_change_processor_
);
44 DCHECK(backend_loop_
.get());
45 DCHECK(backend_loop_
->BelongsToCurrentThread());
46 delete generic_change_processor_
;
50 base::WeakPtr
<syncer::SyncableService
> SharedChangeProcessor::Connect(
51 browser_sync::SyncApiComponentFactory
* sync_factory
,
52 GenericChangeProcessorFactory
* processor_factory
,
53 ProfileSyncService
* sync_service
,
54 DataTypeErrorHandler
* error_handler
,
55 syncer::ModelType type
,
56 const base::WeakPtr
<syncer::SyncMergeResult
>& merge_result
) {
59 DCHECK(error_handler
);
60 DCHECK_NE(type
, syncer::UNSPECIFIED
);
61 backend_loop_
= base::MessageLoopProxy::current();
62 AutoLock
lock(monitor_lock_
);
64 return base::WeakPtr
<syncer::SyncableService
>();
66 sync_service_
= sync_service
;
67 error_handler_
= error_handler
;
68 base::WeakPtr
<syncer::SyncableService
> local_service
=
69 sync_factory
->GetSyncableServiceForType(type
);
70 if (!local_service
.get()) {
71 LOG(WARNING
) << "SyncableService destroyed before DTC was stopped.";
73 return base::WeakPtr
<syncer::SyncableService
>();
76 // TODO(maniscalco): Use a shared (one per profile) thread-safe instance of
77 // AttachmentUpload instead of creating a new one per AttachmentService (bug
79 scoped_ptr
<syncer::AttachmentUploader
> attachment_uploader(
80 new syncer::FakeAttachmentUploader
);
81 // TODO(maniscalco): Replace FakeAttachmentService with a real
82 // AttachmentService implementation once implemented (bug 356359).
83 scoped_ptr
<syncer::AttachmentService
> attachment_service(
84 new syncer::FakeAttachmentService(
85 sync_factory
->CreateCustomAttachmentStoreForType(type
),
86 attachment_uploader
.Pass()));
88 generic_change_processor_
= processor_factory
->CreateGenericChangeProcessor(
89 sync_service_
->GetUserShare(),
93 attachment_service
.Pass()).release();
97 bool SharedChangeProcessor::Disconnect() {
98 // May be called from any thread.
99 DVLOG(1) << "Disconnecting change processor.";
100 AutoLock
lock(monitor_lock_
);
101 bool was_connected
= !disconnected_
;
102 disconnected_
= true;
103 error_handler_
= NULL
;
104 return was_connected
;
107 int SharedChangeProcessor::GetSyncCount() {
108 DCHECK(backend_loop_
.get());
109 DCHECK(backend_loop_
->BelongsToCurrentThread());
110 AutoLock
lock(monitor_lock_
);
112 LOG(ERROR
) << "Change processor disconnected.";
115 return generic_change_processor_
->GetSyncCountForType(type_
);
118 syncer::SyncError
SharedChangeProcessor::ProcessSyncChanges(
119 const tracked_objects::Location
& from_here
,
120 const syncer::SyncChangeList
& list_of_changes
) {
121 DCHECK(backend_loop_
.get());
122 DCHECK(backend_loop_
->BelongsToCurrentThread());
123 AutoLock
lock(monitor_lock_
);
125 // The DTC that disconnects us must ensure it posts a StopSyncing task.
126 // If we reach this, it means it just hasn't executed yet.
127 syncer::SyncError
error(FROM_HERE
,
128 syncer::SyncError::DATATYPE_ERROR
,
129 "Change processor disconnected.",
133 return generic_change_processor_
->ProcessSyncChanges(
134 from_here
, list_of_changes
);
137 syncer::SyncDataList
SharedChangeProcessor::GetAllSyncData(
138 syncer::ModelType type
) const {
139 syncer::SyncDataList data
;
140 GetAllSyncDataReturnError(type
, &data
); // Handles the disconnect case.
144 syncer::SyncError
SharedChangeProcessor::GetAllSyncDataReturnError(
145 syncer::ModelType type
,
146 syncer::SyncDataList
* data
) const {
147 DCHECK(backend_loop_
.get());
148 DCHECK(backend_loop_
->BelongsToCurrentThread());
149 AutoLock
lock(monitor_lock_
);
151 syncer::SyncError
error(FROM_HERE
,
152 syncer::SyncError::DATATYPE_ERROR
,
153 "Change processor disconnected.",
157 return generic_change_processor_
->GetAllSyncDataReturnError(type
, data
);
160 syncer::SyncError
SharedChangeProcessor::UpdateDataTypeContext(
161 syncer::ModelType type
,
162 syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status
,
163 const std::string
& context
) {
164 DCHECK(backend_loop_
.get());
165 DCHECK(backend_loop_
->BelongsToCurrentThread());
166 AutoLock
lock(monitor_lock_
);
168 syncer::SyncError
error(FROM_HERE
,
169 syncer::SyncError::DATATYPE_ERROR
,
170 "Change processor disconnected.",
174 return generic_change_processor_
->UpdateDataTypeContext(
175 type
, refresh_status
, context
);
178 bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes
) {
179 DCHECK(backend_loop_
.get());
180 DCHECK(backend_loop_
->BelongsToCurrentThread());
181 AutoLock
lock(monitor_lock_
);
183 LOG(ERROR
) << "Change processor disconnected.";
186 return generic_change_processor_
->SyncModelHasUserCreatedNodes(
190 bool SharedChangeProcessor::CryptoReadyIfNecessary() {
191 DCHECK(backend_loop_
.get());
192 DCHECK(backend_loop_
->BelongsToCurrentThread());
193 AutoLock
lock(monitor_lock_
);
195 LOG(ERROR
) << "Change processor disconnected.";
196 return true; // Otherwise we get into infinite spin waiting.
198 return generic_change_processor_
->CryptoReadyIfNecessary(type_
);
201 bool SharedChangeProcessor::GetDataTypeContext(std::string
* context
) const {
202 DCHECK(backend_loop_
.get());
203 DCHECK(backend_loop_
->BelongsToCurrentThread());
204 AutoLock
lock(monitor_lock_
);
206 LOG(ERROR
) << "Change processor disconnected.";
209 return generic_change_processor_
->GetDataTypeContext(type_
, context
);
212 void SharedChangeProcessor::ActivateDataType(
213 syncer::ModelSafeGroup model_safe_group
) {
214 DCHECK(backend_loop_
.get());
215 DCHECK(backend_loop_
->BelongsToCurrentThread());
216 AutoLock
lock(monitor_lock_
);
218 LOG(ERROR
) << "Change processor disconnected.";
221 sync_service_
->ActivateDataType(type_
,
223 generic_change_processor_
);
226 syncer::SyncError
SharedChangeProcessor::CreateAndUploadError(
227 const tracked_objects::Location
& location
,
228 const std::string
& message
) {
229 AutoLock
lock(monitor_lock_
);
230 if (!disconnected_
) {
231 return error_handler_
->CreateAndUploadError(location
, message
, type_
);
233 return syncer::SyncError(location
,
234 syncer::SyncError::DATATYPE_ERROR
,
240 } // namespace browser_sync