Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / sync_driver / shared_change_processor.cc
1 // Copyright 2014 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 "components/sync_driver/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/sync_change.h"
12
13 using base::AutoLock;
14
15 namespace sync_driver {
16
17 SharedChangeProcessor::SharedChangeProcessor()
18     : disconnected_(false),
19       type_(syncer::UNSPECIFIED),
20       frontend_loop_(base::MessageLoopProxy::current()),
21       generic_change_processor_(NULL),
22       error_handler_(NULL) {
23 }
24
25 SharedChangeProcessor::~SharedChangeProcessor() {
26   // We can either be deleted when the DTC is destroyed (on UI
27   // thread), or when the syncer::SyncableService stop's syncing (datatype
28   // thread).  |generic_change_processor_|, if non-NULL, must be
29   // deleted on |backend_loop_|.
30   if (frontend_loop_->BelongsToCurrentThread()) {
31     if (backend_loop_.get()) {
32       if (!backend_loop_->DeleteSoon(FROM_HERE, generic_change_processor_)) {
33         NOTREACHED();
34       }
35     } else {
36       DCHECK(!generic_change_processor_);
37     }
38   } else {
39     DCHECK(backend_loop_.get());
40     DCHECK(backend_loop_->BelongsToCurrentThread());
41     delete generic_change_processor_;
42   }
43 }
44
45 base::WeakPtr<syncer::SyncableService> SharedChangeProcessor::Connect(
46     SyncApiComponentFactory* sync_factory,
47     GenericChangeProcessorFactory* processor_factory,
48     syncer::UserShare* user_share,
49     DataTypeErrorHandler* error_handler,
50     syncer::ModelType type,
51     const base::WeakPtr<syncer::SyncMergeResult>& merge_result) {
52   DCHECK(sync_factory);
53   DCHECK(error_handler);
54   DCHECK_NE(type, syncer::UNSPECIFIED);
55   backend_loop_ = base::MessageLoopProxy::current();
56   AutoLock lock(monitor_lock_);
57   if (disconnected_)
58     return base::WeakPtr<syncer::SyncableService>();
59   type_ = type;
60   error_handler_ = error_handler;
61   base::WeakPtr<syncer::SyncableService> local_service =
62       sync_factory->GetSyncableServiceForType(type);
63   if (!local_service.get()) {
64     LOG(WARNING) << "SyncableService destroyed before DTC was stopped.";
65     disconnected_ = true;
66     return base::WeakPtr<syncer::SyncableService>();
67   }
68
69   generic_change_processor_ =
70       processor_factory->CreateGenericChangeProcessor(type,
71                                                       user_share,
72                                                       error_handler,
73                                                       local_service,
74                                                       merge_result,
75                                                       sync_factory).release();
76   return local_service;
77 }
78
79 bool SharedChangeProcessor::Disconnect() {
80   // May be called from any thread.
81   DVLOG(1) << "Disconnecting change processor.";
82   AutoLock lock(monitor_lock_);
83   bool was_connected = !disconnected_;
84   disconnected_ = true;
85   error_handler_ = NULL;
86   return was_connected;
87 }
88
89 ChangeProcessor* SharedChangeProcessor::generic_change_processor() {
90   return generic_change_processor_;
91 }
92
93 int SharedChangeProcessor::GetSyncCount() {
94   DCHECK(backend_loop_.get());
95   DCHECK(backend_loop_->BelongsToCurrentThread());
96   AutoLock lock(monitor_lock_);
97   if (disconnected_) {
98     LOG(ERROR) << "Change processor disconnected.";
99     return 0;
100   }
101   return generic_change_processor_->GetSyncCount();
102 }
103
104 syncer::SyncError SharedChangeProcessor::ProcessSyncChanges(
105     const tracked_objects::Location& from_here,
106     const syncer::SyncChangeList& list_of_changes) {
107   DCHECK(backend_loop_.get());
108   DCHECK(backend_loop_->BelongsToCurrentThread());
109   AutoLock lock(monitor_lock_);
110   if (disconnected_) {
111     // The DTC that disconnects us must ensure it posts a StopSyncing task.
112     // If we reach this, it means it just hasn't executed yet.
113     syncer::SyncError error(FROM_HERE,
114                             syncer::SyncError::DATATYPE_ERROR,
115                             "Change processor disconnected.",
116                             type_);
117     return error;
118   }
119   return generic_change_processor_->ProcessSyncChanges(
120       from_here, list_of_changes);
121 }
122
123 syncer::SyncDataList SharedChangeProcessor::GetAllSyncData(
124     syncer::ModelType type) const {
125   syncer::SyncDataList data;
126   GetAllSyncDataReturnError(type, &data);  // Handles the disconnect case.
127   return data;
128 }
129
130 syncer::SyncError SharedChangeProcessor::GetAllSyncDataReturnError(
131     syncer::ModelType type,
132     syncer::SyncDataList* data) const {
133   DCHECK(backend_loop_.get());
134   DCHECK(backend_loop_->BelongsToCurrentThread());
135   AutoLock lock(monitor_lock_);
136   if (disconnected_) {
137     syncer::SyncError error(FROM_HERE,
138                             syncer::SyncError::DATATYPE_ERROR,
139                             "Change processor disconnected.",
140                             type_);
141     return error;
142   }
143   return generic_change_processor_->GetAllSyncDataReturnError(data);
144 }
145
146 syncer::SyncError SharedChangeProcessor::UpdateDataTypeContext(
147     syncer::ModelType type,
148     syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status,
149     const std::string& context) {
150   DCHECK(backend_loop_.get());
151   DCHECK(backend_loop_->BelongsToCurrentThread());
152   AutoLock lock(monitor_lock_);
153   if (disconnected_) {
154     syncer::SyncError error(FROM_HERE,
155                             syncer::SyncError::DATATYPE_ERROR,
156                             "Change processor disconnected.",
157                             type_);
158     return error;
159   }
160   return generic_change_processor_->UpdateDataTypeContext(
161       type, refresh_status, context);
162 }
163
164 bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) {
165   DCHECK(backend_loop_.get());
166   DCHECK(backend_loop_->BelongsToCurrentThread());
167   AutoLock lock(monitor_lock_);
168   if (disconnected_) {
169     LOG(ERROR) << "Change processor disconnected.";
170     return false;
171   }
172   return generic_change_processor_->SyncModelHasUserCreatedNodes(has_nodes);
173 }
174
175 bool SharedChangeProcessor::CryptoReadyIfNecessary() {
176   DCHECK(backend_loop_.get());
177   DCHECK(backend_loop_->BelongsToCurrentThread());
178   AutoLock lock(monitor_lock_);
179   if (disconnected_) {
180     LOG(ERROR) << "Change processor disconnected.";
181     return true;  // Otherwise we get into infinite spin waiting.
182   }
183   return generic_change_processor_->CryptoReadyIfNecessary();
184 }
185
186 bool SharedChangeProcessor::GetDataTypeContext(std::string* context) const {
187   DCHECK(backend_loop_.get());
188   DCHECK(backend_loop_->BelongsToCurrentThread());
189   AutoLock lock(monitor_lock_);
190   if (disconnected_) {
191     LOG(ERROR) << "Change processor disconnected.";
192     return false;
193   }
194   return generic_change_processor_->GetDataTypeContext(context);
195 }
196
197 syncer::SyncError SharedChangeProcessor::CreateAndUploadError(
198     const tracked_objects::Location& location,
199     const std::string& message) {
200   AutoLock lock(monitor_lock_);
201   if (!disconnected_) {
202     return error_handler_->CreateAndUploadError(location, message, type_);
203   } else {
204     return syncer::SyncError(location,
205                              syncer::SyncError::DATATYPE_ERROR,
206                              message,
207                              type_);
208   }
209 }
210
211 }  // namespace sync_driver