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

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

Issue 160598: Add files to browser/sync. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 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
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host.h ('k') | chrome/browser/sync/personalization.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 #ifdef CHROME_PERSONALIZATION
6
7 #include "base/file_version_info.h"
8 #include "base/file_util.h"
9 #include "base/string_util.h"
10 #include "chrome/browser/sync/glue/sync_backend_host.h"
11 #include "chrome/browser/sync/glue/http_bridge.h"
12 #include "chrome/browser/sync/glue/bookmark_model_worker.h"
13 #include "webkit/glue/webkit_glue.h"
14
15 static const char kSwitchSyncServiceURL[] = "sync-url";
16 static const char kSwitchSyncServicePort[] = "sync-port";
17 static const int kSaveChangesIntervalSeconds = 10;
18 static const char kGaiaServiceId[] = "chromiumsync";
19 static const char kGaiaSourceForChrome[] = "ChromiumBrowser";
20 static const FilePath::CharType kSyncDataFolderName[] =
21 FILE_PATH_LITERAL("Sync Data");
22
23 namespace browser_sync {
24
25 SyncBackendHost::SyncBackendHost(SyncFrontend* frontend,
26 const FilePath& profile_path)
27 : core_thread_("Chrome_SyncCoreThread"),
28 frontend_loop_(MessageLoop::current()),
29 bookmark_model_worker_(NULL),
30 frontend_(frontend),
31 sync_data_folder_path_(profile_path.Append(kSyncDataFolderName)),
32 last_auth_error_(AUTH_ERROR_NONE) {
33 core_ = new Core(this);
34 }
35
36 SyncBackendHost::~SyncBackendHost() {
37 DCHECK(!core_ && !frontend_) << "Must call Shutdown before destructor.";
38 }
39
40 void SyncBackendHost::Initialize(const GURL& sync_service_url) {
41 if (!core_thread_.Start())
42 return;
43
44 bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_);
45 core_thread_.message_loop()->PostTask(FROM_HERE,
46 NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoInitialize,
47 sync_service_url, bookmark_model_worker_, true));
48 }
49
50 void SyncBackendHost::Authenticate(const std::string& username,
51 const std::string& password) {
52 core_thread_.message_loop()->PostTask(FROM_HERE,
53 NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoAuthenticate,
54 username, password));
55 }
56
57 void SyncBackendHost::Shutdown(bool sync_disabled) {
58 // Thread shutdown should occur in the following order:
59 // - SyncerThread
60 // - CoreThread
61 // - UI Thread (stops some time after we return from this call).
62 core_thread_.message_loop()->PostTask(FROM_HERE,
63 NewRunnableMethod(core_.get(),
64 &SyncBackendHost::Core::DoShutdown,
65 sync_disabled));
66
67 // Before joining the core_thread_, we wait for the BookmarkModelWorker to
68 // give us the green light that it is not depending on the frontend_loop_ to
69 // process any more tasks. Stop() blocks until this termination condition
70 // is true.
71 bookmark_model_worker_->Stop();
72
73 // Stop will return once the thread exits, which will be after DoShutdown
74 // runs. DoShutdown needs to run from core_thread_ because the sync backend
75 // requires any thread that opened sqlite handles to relinquish them
76 // personally. We need to join threads, because otherwise the main Chrome
77 // thread (ui loop) can exit before DoShutdown finishes, at which point
78 // virtually anything the sync backend does (or the post-back to
79 // frontend_loop_ by our Core) will epically fail because the CRT won't be
80 // initialized. For now this only ever happens at sync-enabled-Chrome exit,
81 // meaning bug 1482548 applies to prolonged "waiting" that may occur in
82 // DoShutdown.
83 core_thread_.Stop();
84
85 bookmark_model_worker_ = NULL;
86 frontend_ = NULL;
87 core_ = NULL; // Releases reference to core_.
88 }
89
90 void SyncBackendHost::Core::NotifyFrontend(FrontendNotification notification) {
91 if (!host_ || !host_->frontend_) {
92 return; // This can happen in testing because the UI loop processes tasks
93 // after an instance of SyncBackendHost was destroyed. In real
94 // life this doesn't happen.
95 }
96 switch (notification) {
97 case INITIALIZED:
98 host_->frontend_->OnBackendInitialized();
99 return;
100 case SYNC_CYCLE_COMPLETED:
101 host_->frontend_->OnSyncCycleCompleted();
102 return;
103 }
104 }
105
106 SyncBackendHost::UserShareHandle SyncBackendHost::GetUserShareHandle() const {
107 return core_->syncapi()->GetUserShare();
108 }
109
110 SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() {
111 return core_->syncapi()->GetDetailedStatus();
112 }
113
114 SyncBackendHost::StatusSummary SyncBackendHost::GetStatusSummary() {
115 return core_->syncapi()->GetStatusSummary();
116 }
117
118 string16 SyncBackendHost::GetAuthenticatedUsername() const {
119 return UTF8ToUTF16(core_->syncapi()->GetAuthenticatedUsername());
120 }
121
122 AuthErrorState SyncBackendHost::GetAuthErrorState() const {
123 return last_auth_error_;
124 }
125
126 SyncBackendHost::Core::Core(SyncBackendHost* backend)
127 : host_(backend),
128 syncapi_(new sync_api::SyncManager()) {
129 }
130
131 // Helper to construct a user agent string (ASCII) suitable for use by
132 // the syncapi for any HTTP communication. This string is used by the sync
133 // backend for classifying client types when calculating statistics.
134 std::string MakeUserAgentForSyncapi() {
135 std::string user_agent;
136 user_agent = "Chrome ";
137 #if defined(OS_WIN)
138 user_agent += "WIN ";
139 #elif defined(OS_LINUX)
140 user_agent += "LINUX ";
141 #elif defined(OS_MACOSX)
142 user_agent += "MAC ";
143 #endif
144 scoped_ptr<FileVersionInfo> version_info(
145 FileVersionInfo::CreateFileVersionInfoForCurrentModule());
146 if (version_info == NULL) {
147 DLOG(ERROR) << "Unable to create FileVersionInfo object";
148 return user_agent;
149 }
150
151 user_agent += WideToASCII(version_info->product_version());
152 user_agent += " (" + WideToASCII(version_info->last_change()) + ")";
153 if (!version_info->is_official_build())
154 user_agent += "-devel";
155 return user_agent;
156 }
157
158 void SyncBackendHost::Core::DoInitialize(
159 const GURL& service_url,
160 BookmarkModelWorker* bookmark_model_worker,
161 bool attempt_last_user_authentication) {
162 DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
163
164 // Make sure that the directory exists before initializing the backend.
165 // If it already exists, this will do no harm.
166 bool success = file_util::CreateDirectory(host_->sync_data_folder_path());
167 DCHECK(success);
168
169 syncapi_->SetObserver(this);
170 string16 path_str;
171 #if defined (OS_WIN)
172 path_str = host_->sync_data_folder_path().value();
173 #elif (defined(OS_LINUX) || defined(OS_MACOSX))
174 path_str = UTF8ToUTF16(sync_data_folder_path().value());
175 #endif
176 success = syncapi_->Init(path_str.c_str(),
177 (service_url.host() + service_url.path()).c_str(),
178 service_url.EffectiveIntPort(),
179 kGaiaServiceId,
180 kGaiaSourceForChrome,
181 service_url.SchemeIsSecure(),
182 new HttpBridgeFactory(),
183 new HttpBridgeFactory(),
184 bookmark_model_worker,
185 attempt_last_user_authentication,
186 MakeUserAgentForSyncapi().c_str());
187 DCHECK(success) << "Syncapi initialization failed!";
188 }
189
190 void SyncBackendHost::Core::DoAuthenticate(const std::string& username,
191 const std::string& password) {
192 DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
193 syncapi_->Authenticate(username.c_str(), password.c_str());
194 }
195
196 void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
197 DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
198
199 save_changes_timer_.Stop();
200 syncapi_->Shutdown(); // Stops the SyncerThread.
201 syncapi_->RemoveObserver();
202 host_->bookmark_model_worker_->OnSyncerShutdownComplete();
203
204 if (sync_disabled &&
205 file_util::DirectoryExists(host_->sync_data_folder_path())) {
206 // Delete the sync data folder to cleanup backend data.
207 bool success = file_util::Delete(host_->sync_data_folder_path(), true);
208 DCHECK(success);
209 }
210
211 host_ = NULL;
212 }
213
214 static AuthErrorState AuthProblemToAuthError(
215 const sync_api::SyncManager::AuthProblem& auth_problem) {
216 switch (auth_problem) {
217 case sync_api::SyncManager::AUTH_PROBLEM_NONE:
218 return AUTH_ERROR_NONE;
219 case sync_api::SyncManager::AUTH_PROBLEM_INVALID_GAIA_CREDENTIALS:
220 return AUTH_ERROR_INVALID_GAIA_CREDENTIALS;
221 case sync_api::SyncManager::AUTH_PROBLEM_CONNECTION_FAILED:
222 return AUTH_ERROR_CONNECTION_FAILED;
223 case sync_api::SyncManager::AUTH_PROBLEM_USER_NOT_SIGNED_UP:
224 return AUTH_ERROR_USER_NOT_SIGNED_UP;
225 }
226
227 NOTREACHED() << "Unknown AuthProblem.";
228 return AUTH_ERROR_NONE;
229 }
230
231 void SyncBackendHost::Core::OnChangesApplied(
232 const sync_api::BaseTransaction* trans,
233 const sync_api::SyncManager::ChangeRecord* changes,
234 int change_count) {
235 if (!host_ || !host_->frontend_) {
236 DCHECK(false) << "OnChangesApplied called after Shutdown?";
237 return;
238 }
239
240 // ChangesApplied is the one exception that should come over from the sync
241 // backend already on the service_loop_ thanks to our BookmarkModelWorker.
242 // SyncFrontend changes exclusively on the UI loop, because it updates
243 // the bookmark model. As such, we don't need to worry about changes that
244 // have been made to the bookmark model but not yet applied to the sync
245 // model -- such changes only happen on the UI loop, and there's no
246 // contention.
247 if (host_->frontend_loop_ != MessageLoop::current()) {
248 // TODO(ncarter): Bug 1480644. Make this a DCHECK once syncapi filters
249 // out all irrelevant changes.
250 DLOG(WARNING) << "Could not update bookmark model from non-UI thread";
251 return;
252 }
253 host_->frontend_->ApplyModelChanges(trans, changes, change_count);
254 }
255
256 void SyncBackendHost::Core::OnSyncCycleCompleted() {
257 host_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
258 &Core::NotifyFrontend, SYNC_CYCLE_COMPLETED));
259 }
260
261 void SyncBackendHost::Core::OnInitializationComplete() {
262 if (!host_ || !host_->frontend_)
263 return; // We may have been told to Shutdown before initialization
264 // completed.
265
266 // We could be on some random sync backend thread, so MessageLoop::current()
267 // can definitely be null in here.
268 host_->frontend_loop_->PostTask(FROM_HERE,
269 NewRunnableMethod(this, &Core::NotifyFrontend, INITIALIZED));
270
271 // Initialization is complete, so we can schedule recurring SaveChanges.
272 host_->core_thread_.message_loop()->PostTask(FROM_HERE,
273 NewRunnableMethod(this, &Core::StartSavingChanges));
274 }
275
276 void SyncBackendHost::Core::OnAuthProblem(
277 sync_api::SyncManager::AuthProblem auth_problem) {
278 // We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
279 // we can modify state.
280 host_->frontend_loop_->PostTask(FROM_HERE,
281 NewRunnableMethod(this, &Core::HandleAuthErrorEventOnFrontendLoop,
282 AuthProblemToAuthError(auth_problem)));
283 }
284
285 void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop(
286 AuthErrorState new_auth_error) {
287 if (!host_ || !host_->frontend_)
288 return;
289
290 DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
291
292 host_->last_auth_error_ = new_auth_error;
293 host_->frontend_->OnAuthError();
294 }
295
296 void SyncBackendHost::Core::StartSavingChanges() {
297 save_changes_timer_.Start(
298 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
299 this, &Core::SaveChanges);
300 }
301
302 void SyncBackendHost::Core::SaveChanges() {
303 syncapi_->SaveChanges();
304 }
305
306 } // namespace browser_sync
307
308 #endif
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host.h ('k') | chrome/browser/sync/personalization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698