OLD | NEW |
| (Empty) |
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/sync_change.h" | |
12 | |
13 using base::AutoLock; | |
14 | |
15 namespace browser_sync { | |
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 browser_sync::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(user_share, | |
71 error_handler, | |
72 local_service, | |
73 merge_result, | |
74 sync_factory).release(); | |
75 return local_service; | |
76 } | |
77 | |
78 bool SharedChangeProcessor::Disconnect() { | |
79 // May be called from any thread. | |
80 DVLOG(1) << "Disconnecting change processor."; | |
81 AutoLock lock(monitor_lock_); | |
82 bool was_connected = !disconnected_; | |
83 disconnected_ = true; | |
84 error_handler_ = NULL; | |
85 return was_connected; | |
86 } | |
87 | |
88 ChangeProcessor* SharedChangeProcessor::generic_change_processor() { | |
89 return generic_change_processor_; | |
90 } | |
91 | |
92 int SharedChangeProcessor::GetSyncCount() { | |
93 DCHECK(backend_loop_.get()); | |
94 DCHECK(backend_loop_->BelongsToCurrentThread()); | |
95 AutoLock lock(monitor_lock_); | |
96 if (disconnected_) { | |
97 LOG(ERROR) << "Change processor disconnected."; | |
98 return 0; | |
99 } | |
100 return generic_change_processor_->GetSyncCountForType(type_); | |
101 } | |
102 | |
103 syncer::SyncError SharedChangeProcessor::ProcessSyncChanges( | |
104 const tracked_objects::Location& from_here, | |
105 const syncer::SyncChangeList& list_of_changes) { | |
106 DCHECK(backend_loop_.get()); | |
107 DCHECK(backend_loop_->BelongsToCurrentThread()); | |
108 AutoLock lock(monitor_lock_); | |
109 if (disconnected_) { | |
110 // The DTC that disconnects us must ensure it posts a StopSyncing task. | |
111 // If we reach this, it means it just hasn't executed yet. | |
112 syncer::SyncError error(FROM_HERE, | |
113 syncer::SyncError::DATATYPE_ERROR, | |
114 "Change processor disconnected.", | |
115 type_); | |
116 return error; | |
117 } | |
118 return generic_change_processor_->ProcessSyncChanges( | |
119 from_here, list_of_changes); | |
120 } | |
121 | |
122 syncer::SyncDataList SharedChangeProcessor::GetAllSyncData( | |
123 syncer::ModelType type) const { | |
124 syncer::SyncDataList data; | |
125 GetAllSyncDataReturnError(type, &data); // Handles the disconnect case. | |
126 return data; | |
127 } | |
128 | |
129 syncer::SyncError SharedChangeProcessor::GetAllSyncDataReturnError( | |
130 syncer::ModelType type, | |
131 syncer::SyncDataList* data) const { | |
132 DCHECK(backend_loop_.get()); | |
133 DCHECK(backend_loop_->BelongsToCurrentThread()); | |
134 AutoLock lock(monitor_lock_); | |
135 if (disconnected_) { | |
136 syncer::SyncError error(FROM_HERE, | |
137 syncer::SyncError::DATATYPE_ERROR, | |
138 "Change processor disconnected.", | |
139 type_); | |
140 return error; | |
141 } | |
142 return generic_change_processor_->GetAllSyncDataReturnError(type, data); | |
143 } | |
144 | |
145 syncer::SyncError SharedChangeProcessor::UpdateDataTypeContext( | |
146 syncer::ModelType type, | |
147 syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status, | |
148 const std::string& context) { | |
149 DCHECK(backend_loop_.get()); | |
150 DCHECK(backend_loop_->BelongsToCurrentThread()); | |
151 AutoLock lock(monitor_lock_); | |
152 if (disconnected_) { | |
153 syncer::SyncError error(FROM_HERE, | |
154 syncer::SyncError::DATATYPE_ERROR, | |
155 "Change processor disconnected.", | |
156 type_); | |
157 return error; | |
158 } | |
159 return generic_change_processor_->UpdateDataTypeContext( | |
160 type, refresh_status, context); | |
161 } | |
162 | |
163 bool SharedChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) { | |
164 DCHECK(backend_loop_.get()); | |
165 DCHECK(backend_loop_->BelongsToCurrentThread()); | |
166 AutoLock lock(monitor_lock_); | |
167 if (disconnected_) { | |
168 LOG(ERROR) << "Change processor disconnected."; | |
169 return false; | |
170 } | |
171 return generic_change_processor_->SyncModelHasUserCreatedNodes( | |
172 type_, 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(type_); | |
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(type_, 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 browser_sync | |
OLD | NEW |