Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / shared_change_processor.cc
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 "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"
15
16 using base::AutoLock;
17
18 namespace browser_sync {
19
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) {
26 }
27
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_)) {
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
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) {
55   DCHECK(sync_factory);
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   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.";
68     disconnected_ = true;
69     return base::WeakPtr<syncer::SyncableService>();
70   }
71
72   // TODO(maniscalco): Use a shared (one per profile) thread-safe instance of
73   // AttachmentUpload instead of creating a new one per AttachmentService (bug
74   // 369536).
75   scoped_ptr<syncer::AttachmentUploader> attachment_uploader(
76       new syncer::FakeAttachmentUploader);
77
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()));
84
85   generic_change_processor_ = processor_factory->CreateGenericChangeProcessor(
86       user_share,
87       error_handler,
88       local_service,
89       merge_result,
90       attachment_service.Pass()).release();
91   return local_service;
92 }
93
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_;
99   disconnected_ = true;
100   error_handler_ = NULL;
101   return was_connected;
102 }
103
104 ChangeProcessor* SharedChangeProcessor::generic_change_processor() {
105   return generic_change_processor_;
106 }
107
108 int SharedChangeProcessor::GetSyncCount() {
109   DCHECK(backend_loop_.get());
110   DCHECK(backend_loop_->BelongsToCurrentThread());
111   AutoLock lock(monitor_lock_);
112   if (disconnected_) {
113     LOG(ERROR) << "Change processor disconnected.";
114     return 0;
115   }
116   return generic_change_processor_->GetSyncCountForType(type_);
117 }
118
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_);
125   if (disconnected_) {
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.",
131                             type_);
132     return error;
133   }
134   return generic_change_processor_->ProcessSyncChanges(
135       from_here, list_of_changes);
136 }
137
138 syncer::SyncDataList SharedChangeProcessor::GetAllSyncData(
139     syncer::ModelType type) const {
140   syncer::SyncDataList data;
141   GetAllSyncDataReturnError(type, &data);  // Handles the disconnect case.
142   return data;
143 }
144
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_);
151   if (disconnected_) {
152     syncer::SyncError error(FROM_HERE,
153                             syncer::SyncError::DATATYPE_ERROR,
154                             "Change processor disconnected.",
155                             type_);
156     return error;
157   }
158   return generic_change_processor_->GetAllSyncDataReturnError(type, data);
159 }
160
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_);
168   if (disconnected_) {
169     syncer::SyncError error(FROM_HERE,
170                             syncer::SyncError::DATATYPE_ERROR,
171                             "Change processor disconnected.",
172                             type_);
173     return error;
174   }
175   return generic_change_processor_->UpdateDataTypeContext(
176       type, refresh_status, context);
177 }
178
179 bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) {
180   DCHECK(backend_loop_.get());
181   DCHECK(backend_loop_->BelongsToCurrentThread());
182   AutoLock lock(monitor_lock_);
183   if (disconnected_) {
184     LOG(ERROR) << "Change processor disconnected.";
185     return false;
186   }
187   return generic_change_processor_->SyncModelHasUserCreatedNodes(
188       type_, has_nodes);
189 }
190
191 bool SharedChangeProcessor::CryptoReadyIfNecessary() {
192   DCHECK(backend_loop_.get());
193   DCHECK(backend_loop_->BelongsToCurrentThread());
194   AutoLock lock(monitor_lock_);
195   if (disconnected_) {
196     LOG(ERROR) << "Change processor disconnected.";
197     return true;  // Otherwise we get into infinite spin waiting.
198   }
199   return generic_change_processor_->CryptoReadyIfNecessary(type_);
200 }
201
202 bool SharedChangeProcessor::GetDataTypeContext(std::string* context) const {
203   DCHECK(backend_loop_.get());
204   DCHECK(backend_loop_->BelongsToCurrentThread());
205   AutoLock lock(monitor_lock_);
206   if (disconnected_) {
207     LOG(ERROR) << "Change processor disconnected.";
208     return false;
209   }
210   return generic_change_processor_->GetDataTypeContext(type_, context);
211 }
212
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_);
219   } else {
220     return syncer::SyncError(location,
221                              syncer::SyncError::DATATYPE_ERROR,
222                              message,
223                              type_);
224   }
225 }
226
227 }  // namespace browser_sync