Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: chrome/browser/sync/glue/non_frontend_data_type_controller.cc

Issue 8065016: [Sync] Refactor non-frontend DTC to handle new API properly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase++++ Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/glue/non_frontend_data_type_controller.h" 5 #include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
6 6
7 #include "base/bind.h"
8 #include "base/callback.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
8 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/sync/api/sync_error.h" 11 #include "chrome/browser/sync/api/sync_error.h"
10 #include "chrome/browser/sync/glue/change_processor.h" 12 #include "chrome/browser/sync/glue/change_processor.h"
11 #include "chrome/browser/sync/glue/model_associator.h" 13 #include "chrome/browser/sync/glue/model_associator.h"
12 #include "chrome/browser/sync/profile_sync_factory.h" 14 #include "chrome/browser/sync/profile_sync_factory.h"
13 #include "chrome/browser/sync/profile_sync_service.h" 15 #include "chrome/browser/sync/profile_sync_service.h"
14 #include "chrome/browser/sync/syncable/model_type.h" 16 #include "chrome/browser/sync/syncable/model_type.h"
15 #include "content/browser/browser_thread.h" 17 #include "content/browser/browser_thread.h"
16 18
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 delete start_callback; 55 delete start_callback;
54 return; 56 return;
55 } 57 }
56 58
57 start_callback_.reset(start_callback); 59 start_callback_.reset(start_callback);
58 abort_association_ = false; 60 abort_association_ = false;
59 61
60 state_ = MODEL_STARTING; 62 state_ = MODEL_STARTING;
61 if (!StartModels()) { 63 if (!StartModels()) {
62 // If we are waiting for some external service to load before associating 64 // If we are waiting for some external service to load before associating
63 // or we failed to start the models, we exit early. state_ will control 65 // or we failed to start the models, we exit early.
64 // what we perform next.
65 DCHECK(state_ == NOT_RUNNING || state_ == MODEL_STARTING); 66 DCHECK(state_ == NOT_RUNNING || state_ == MODEL_STARTING);
66 return; 67 return;
67 } 68 }
68 69
69 // Kick off association on the thread the datatype resides on. 70 // Kick off association on the thread the datatype resides on.
70 state_ = ASSOCIATING; 71 state_ = ASSOCIATING;
71 if (!StartAssociationAsync()) { 72 if (!StartAssociationAsync()) {
72 SyncError error(FROM_HERE, "Failed to post StartAssociation", type()); 73 SyncError error(FROM_HERE, "Failed to post StartAssociation", type());
73 StartDoneImpl(ASSOCIATION_FAILED, DISABLED, error); 74 StartDoneImpl(ASSOCIATION_FAILED, DISABLED, error);
74 } 75 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 base::TimeTicks start_time = base::TimeTicks::Now(); 110 base::TimeTicks start_time = base::TimeTicks::Now();
110 SyncError error; 111 SyncError error;
111 bool merge_success = model_associator_->AssociateModels(&error); 112 bool merge_success = model_associator_->AssociateModels(&error);
112 RecordAssociationTime(base::TimeTicks::Now() - start_time); 113 RecordAssociationTime(base::TimeTicks::Now() - start_time);
113 if (!merge_success) { 114 if (!merge_success) {
114 StartFailed(ASSOCIATION_FAILED, error); 115 StartFailed(ASSOCIATION_FAILED, error);
115 return; 116 return;
116 } 117 }
117 118
118 profile_sync_service_->ActivateDataType(type(), model_safe_group(), 119 profile_sync_service_->ActivateDataType(type(), model_safe_group(),
119 change_processor_.get()); 120 change_processor());
120 StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError()); 121 StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, SyncError());
121 } 122 }
122 123
123 void NonFrontendDataTypeController::StartFailed(StartResult result, 124 void NonFrontendDataTypeController::StartFailed(StartResult result,
124 const SyncError& error) { 125 const SyncError& error) {
125 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 126 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
126 model_associator_.reset(); 127 model_associator_.reset();
127 change_processor_.reset(); 128 change_processor_.reset();
128 StartDone(result, 129 StartDone(result,
129 result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING, 130 result == ASSOCIATION_FAILED ? DISABLED : NOT_RUNNING,
130 error); 131 error);
131 } 132 }
132 133
133 void NonFrontendDataTypeController::StartDone( 134 void NonFrontendDataTypeController::StartDone(
134 DataTypeController::StartResult result, 135 DataTypeController::StartResult result,
135 DataTypeController::State new_state, 136 DataTypeController::State new_state,
136 const SyncError& error) { 137 const SyncError& error) {
137 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 138 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
138 abort_association_complete_.Signal(); 139 abort_association_complete_.Signal();
139 base::AutoLock lock(abort_association_lock_); 140 base::AutoLock lock(abort_association_lock_);
140 if (!abort_association_) { 141 if (!abort_association_) {
141 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
142 NewRunnableMethod( 143 base::Bind(&NonFrontendDataTypeController::StartDoneImpl,
143 this, 144 this,
144 &NonFrontendDataTypeController::StartDoneImpl, 145 result,
145 result, 146 new_state,
146 new_state, 147 error));
147 error));
148 } 148 }
149 } 149 }
150 150
151 void NonFrontendDataTypeController::StartDoneImpl( 151 void NonFrontendDataTypeController::StartDoneImpl(
152 DataTypeController::StartResult result, 152 DataTypeController::StartResult result,
153 DataTypeController::State new_state, 153 DataTypeController::State new_state,
154 const SyncError& error) { 154 const SyncError& error) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 156 // It's possible to have StartDoneImpl called first from the UI thread
157 // (due to Stop being called) and then posted from the non-UI thread. In
158 // this case, we drop the second call because we've already been stopped.
157 if (state_ == NOT_RUNNING) { 159 if (state_ == NOT_RUNNING) {
158 // During stop it is possible startdoneimpl can be called twice. Once from
159 // the |StartDone| method and once from the |Stop| method.
160 DCHECK(!start_callback_.get()); 160 DCHECK(!start_callback_.get());
161 return; 161 return;
162 } 162 }
163
163 state_ = new_state; 164 state_ = new_state;
164 if (state_ != RUNNING) { 165 if (state_ != RUNNING) {
165 // Start failed. 166 // Start failed.
166 StopModels(); 167 StopModels();
167 RecordStartFailure(result); 168 RecordStartFailure(result);
168 } 169 }
169 170
170 // We have to release the callback before we call it, since it's possible 171 // We have to release the callback before we call it, since it's possible
171 // invoking the callback will trigger a call to STOP(), which will get 172 // invoking the callback will trigger a call to STOP(), which will get
172 // confused by the non-NULL start_callback_. 173 // confused by the non-NULL start_callback_.
173 scoped_ptr<StartCallback> callback(start_callback_.release()); 174 scoped_ptr<StartCallback> callback(start_callback_.release());
174 callback->Run(result, error); 175 callback->Run(result, error);
175 } 176 }
176 177
177 // TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of 178 // TODO(sync): Blocking the UI thread at shutdown is bad. The new API avoids
178 // distinguishing chrome shutdown from sync shutdown, we should be able to avoid 179 // this. Once all non-frontend datatypes use the new API, we can get rid of this
179 // this (http://crbug.com/55662). 180 // locking (see implementation in AutofillProfileDataTypeController).
180 void NonFrontendDataTypeController::Stop() { 181 void NonFrontendDataTypeController::Stop() {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 // If Stop() is called while Start() is waiting for association to 183 // If Stop() is called while Start() is waiting for association to
183 // complete, we need to abort the association and wait for the DB 184 // complete, we need to abort the association and wait for the DB
184 // thread to finish the StartImpl() task. 185 // thread to finish the StartImpl() task.
185 if (state_ == ASSOCIATING) { 186 if (state_ == ASSOCIATING) {
186 state_ = STOPPING; 187 state_ = STOPPING;
187 { 188 {
188 base::AutoLock lock(abort_association_lock_); 189 base::AutoLock lock(abort_association_lock_);
189 abort_association_ = true; 190 abort_association_ = true;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 247
247 DataTypeController::State NonFrontendDataTypeController::state() const { 248 DataTypeController::State NonFrontendDataTypeController::state() const {
248 return state_; 249 return state_;
249 } 250 }
250 251
251 void NonFrontendDataTypeController::OnUnrecoverableError( 252 void NonFrontendDataTypeController::OnUnrecoverableError(
252 const tracked_objects::Location& from_here, 253 const tracked_objects::Location& from_here,
253 const std::string& message) { 254 const std::string& message) {
254 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 255 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
255 RecordUnrecoverableError(from_here, message); 256 RecordUnrecoverableError(from_here, message);
256 BrowserThread::PostTask(BrowserThread::UI, from_here, NewRunnableMethod(this, 257 BrowserThread::PostTask(BrowserThread::UI, from_here,
257 &NonFrontendDataTypeController::OnUnrecoverableErrorImpl, from_here, 258 base::Bind(&NonFrontendDataTypeController::OnUnrecoverableErrorImpl,
258 message)); 259 this,
260 from_here,
261 message));
259 } 262 }
260 263
261 void NonFrontendDataTypeController::OnUnrecoverableErrorImpl( 264 void NonFrontendDataTypeController::OnUnrecoverableErrorImpl(
262 const tracked_objects::Location& from_here, 265 const tracked_objects::Location& from_here,
263 const std::string& message) { 266 const std::string& message) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 profile_sync_service_->OnUnrecoverableError(from_here, message); 268 profile_sync_service_->OnUnrecoverableError(from_here, message);
266 } 269 }
267 270
268 ProfileSyncFactory* NonFrontendDataTypeController::profile_sync_factory() 271 ProfileSyncFactory* NonFrontendDataTypeController::profile_sync_factory()
269 const { 272 const {
270 return profile_sync_factory_; 273 return profile_sync_factory_;
271 } 274 }
272 275
273 Profile* NonFrontendDataTypeController::profile() const { 276 Profile* NonFrontendDataTypeController::profile() const {
274 return profile_; 277 return profile_;
275 } 278 }
276 279
277 ProfileSyncService* NonFrontendDataTypeController::profile_sync_service() 280 ProfileSyncService* NonFrontendDataTypeController::profile_sync_service()
278 const { 281 const {
279 return profile_sync_service_; 282 return profile_sync_service_;
280 } 283 }
281 284
285 void NonFrontendDataTypeController::set_start_callback(
286 StartCallback* callback) {
287 start_callback_.reset(callback);
288 }
282 void NonFrontendDataTypeController::set_state(State state) { 289 void NonFrontendDataTypeController::set_state(State state) {
283 state_ = state; 290 state_ = state;
284 } 291 }
285 292
293 AssociatorInterface* NonFrontendDataTypeController::associator() const {
294 return model_associator_.get();
295 }
296
286 void NonFrontendDataTypeController::set_model_associator( 297 void NonFrontendDataTypeController::set_model_associator(
287 AssociatorInterface* associator) { 298 AssociatorInterface* associator) {
288 model_associator_.reset(associator); 299 model_associator_.reset(associator);
289 } 300 }
290 301
302 ChangeProcessor* NonFrontendDataTypeController::change_processor() const {
303 return change_processor_.get();
304 }
305
291 void NonFrontendDataTypeController::set_change_processor( 306 void NonFrontendDataTypeController::set_change_processor(
292 ChangeProcessor* change_processor) { 307 ChangeProcessor* change_processor) {
293 change_processor_.reset(change_processor); 308 change_processor_.reset(change_processor);
294 } 309 }
295 310
296 } // namespace browser_sync 311 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698