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

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

Issue 6811003: [Sync] Make generic non-frontend thread datatype controller. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix autofill Created 9 years, 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/sync/glue/change_processor.h"
10 #include "chrome/browser/sync/glue/model_associator.h"
11 #include "chrome/browser/sync/profile_sync_factory.h"
12 #include "chrome/browser/sync/profile_sync_service.h"
13 #include "chrome/browser/sync/syncable/model_type.h"
14 #include "content/browser/browser_thread.h"
15
16 namespace browser_sync {
17
18 NonFrontendDataTypeController::NonFrontendDataTypeController()
19 : profile_sync_factory_(NULL),
20 profile_(NULL),
21 sync_service_(NULL),
22 abort_association_(false),
23 abort_association_complete_(false, false),
24 datatype_stopped_(false, false) {}
25
26 NonFrontendDataTypeController::NonFrontendDataTypeController(
27 ProfileSyncFactory* profile_sync_factory,
28 Profile* profile,
29 ProfileSyncService* sync_service)
30 : profile_sync_factory_(profile_sync_factory),
31 profile_(profile),
32 sync_service_(sync_service),
33 state_(NOT_RUNNING),
34 abort_association_(false),
35 abort_association_complete_(false, false),
36 datatype_stopped_(false, false) {
37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
38 DCHECK(profile_sync_factory);
39 DCHECK(profile);
40 DCHECK(sync_service);
41 }
42
43 NonFrontendDataTypeController::~NonFrontendDataTypeController() {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
45 }
46
47 void NonFrontendDataTypeController::Start(StartCallback* start_callback) {
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
49 DCHECK(start_callback);
50 if (state_ != NOT_RUNNING) {
51 start_callback->Run(BUSY, FROM_HERE);
52 delete start_callback;
53 return;
54 }
55
56 start_callback_.reset(start_callback);
57 abort_association_ = false;
58
59 state_ = MODEL_STARTING;
60 if (!StartModels()) {
61 // If we are waiting for some external service to load before associating
62 // or we failed to start the models, we exit early. state_ will control
63 // what we perform next.
64 DCHECK(state_ == NOT_RUNNING || state_ == MODEL_STARTING);
65 return;
66 }
67
68 // Kick off association on the thread the datatype resides on.
69 state_ = ASSOCIATING;
70 if (!KickOffAssociation()) {
71 StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, FROM_HERE);
72 }
73 }
74
75 bool NonFrontendDataTypeController::StartModels() {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
77 DCHECK_EQ(state_, MODEL_STARTING);
78 // By default, no additional services need to be started before we can proceed
79 // with model association, so do nothing.
80 return true;
81 }
82
83 void NonFrontendDataTypeController::Associate() {
84 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
85 DCHECK_EQ(state_, ASSOCIATING);
86 {
87 base::AutoLock lock(abort_association_lock_);
88 if (abort_association_) {
89 abort_association_complete_.Signal();
90 return;
91 }
92 CreateSyncComponents();
93 }
94
95 if (!model_associator_->CryptoReadyIfNecessary()) {
96 StartFailed(NEEDS_CRYPTO, FROM_HERE);
97 return;
98 }
99
100 bool sync_has_nodes = false;
101 if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
102 StartFailed(UNRECOVERABLE_ERROR, FROM_HERE);
103 return;
104 }
105
106 base::TimeTicks start_time = base::TimeTicks::Now();
107 bool merge_success = model_associator_->AssociateModels();
108 RecordAssociationTime(base::TimeTicks::Now() - start_time);
109 if (!merge_success) {
110 StartFailed(ASSOCIATION_FAILED, FROM_HERE);
111 return;
112 }
113
114 sync_service_->ActivateDataType(this, change_processor_.get());
115 StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, FROM_HERE);
116 }
117
118 void NonFrontendDataTypeController::StartFailed(StartResult result,
119 const tracked_objects::Location& location) {
120 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
121 model_associator_.reset();
122 change_processor_.reset();
123 StartDone(result, NOT_RUNNING, location);
124 }
125
126 void NonFrontendDataTypeController::StartDone(
127 DataTypeController::StartResult result,
128 DataTypeController::State new_state,
129 const tracked_objects::Location& location) {
130 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
131 abort_association_complete_.Signal();
132 base::AutoLock lock(abort_association_lock_);
133 if (!abort_association_) {
134 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
135 NewRunnableMethod(
136 this,
137 &NonFrontendDataTypeController::StartDoneImpl,
138 result,
139 new_state,
140 location));
141 }
142 }
143
144 void NonFrontendDataTypeController::StartDoneImpl(
145 DataTypeController::StartResult result,
146 DataTypeController::State new_state,
147 const tracked_objects::Location& location) {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
149 state_ = new_state;
150 if (state_ != RUNNING) {
151 // Start failed.
152 CleanUpState();
153 RecordStartFailure(result);
154 }
155 start_callback_->Run(result, location);
156 start_callback_.reset();
157 }
158
159 // TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of
160 // distinguishing chrome shutdown from sync shutdown, we should be able to avoid
161 // this (http://crbug.com/55662).
162 void NonFrontendDataTypeController::Stop() {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 // If Stop() is called while Start() is waiting for association to
165 // complete, we need to abort the association and wait for the DB
166 // thread to finish the StartImpl() task.
167 if (state_ == ASSOCIATING) {
168 state_ = STOPPING;
169 {
170 base::AutoLock lock(abort_association_lock_);
171 abort_association_ = true;
172 if (model_associator_.get())
173 model_associator_->AbortAssociation();
174 }
175 // Wait for the model association to abort.
176 abort_association_complete_.Wait();
177 StartDoneImpl(ABORTED, STOPPING, FROM_HERE);
178 } else if (state_ == MODEL_STARTING) {
179 state_ = STOPPING;
180 // If Stop() is called while Start() is waiting for the models to start,
181 // abort the start. We don't need to continue on since it means we haven't
182 // kicked off the association, and once we call CleanUpState, we never will.
183 StartDoneImpl(ABORTED, NOT_RUNNING, FROM_HERE);
184 return;
185 } else {
186 state_ = STOPPING;
187
188 // Clean up any state we changed while starting (for example models we
189 // started).
190 CleanUpState();
191 }
192 DCHECK(!start_callback_.get());
193
194 // Deactivate the change processor on the UI thread. We dont want to listen
195 // for any more changes or process them from server.
196 if (change_processor_ != NULL)
197 sync_service_->DeactivateDataType(this, change_processor_.get());
198
199 if (KickOffDestroy()) {
200 datatype_stopped_.Wait();
201 } else {
202 // We do DFATAL here because this will eventually lead to a failed CHECK
203 // when the change processor gets destroyed on the wrong thread.
204 LOG(DFATAL) << "Failed to destroy datatype " << name();
205 }
206 state_ = NOT_RUNNING;
207 }
208
209 void NonFrontendDataTypeController::CleanUpState() {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 DCHECK(state_ == STOPPING || state_ == NOT_RUNNING);
212 // Do nothing by default.
213 }
214
215 void NonFrontendDataTypeController::Destroy() {
216 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
217 if (model_associator_ != NULL)
218 model_associator_->DisassociateModels();
219 change_processor_.reset();
220 model_associator_.reset();
221 datatype_stopped_.Signal();
222 }
223
224 std::string NonFrontendDataTypeController::name() const {
225 // For logging only.
226 return syncable::ModelTypeToString(type());
227 }
228
229 DataTypeController::State NonFrontendDataTypeController::state() const {
230 return state_;
231 }
232
233 void NonFrontendDataTypeController::OnUnrecoverableError(
234 const tracked_objects::Location& from_here,
235 const std::string& message) {
236 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
237 RecordUnrecoverableError(from_here, message);
238 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this,
239 &NonFrontendDataTypeController::OnUnrecoverableErrorImpl, from_here,
240 message));
241 }
242
243 void NonFrontendDataTypeController::OnUnrecoverableErrorImpl(
244 const tracked_objects::Location& from_here,
245 const std::string& message) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
247 sync_service_->OnUnrecoverableError(from_here, message);
248 }
249
250
251 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698