• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 browser_sync {
16 
SharedChangeProcessor()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 
~SharedChangeProcessor()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 
Connect(browser_sync::SyncApiComponentFactory * sync_factory,GenericChangeProcessorFactory * processor_factory,syncer::UserShare * user_share,DataTypeErrorHandler * error_handler,syncer::ModelType type,const base::WeakPtr<syncer::SyncMergeResult> & merge_result)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 
Disconnect()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 
generic_change_processor()88 ChangeProcessor* SharedChangeProcessor::generic_change_processor() {
89   return generic_change_processor_;
90 }
91 
GetSyncCount()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 
ProcessSyncChanges(const tracked_objects::Location & from_here,const syncer::SyncChangeList & list_of_changes)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 
GetAllSyncData(syncer::ModelType type) const122 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 
GetAllSyncDataReturnError(syncer::ModelType type,syncer::SyncDataList * data) const129 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 
UpdateDataTypeContext(syncer::ModelType type,syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status,const std::string & context)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 
SyncModelHasUserCreatedNodes(bool * has_nodes)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 
CryptoReadyIfNecessary()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 
GetDataTypeContext(std::string * context) const186 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 
CreateAndUploadError(const tracked_objects::Location & location,const std::string & message)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
212