OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/profile_sync_service.h" | 5 #include "chrome/browser/sync/profile_sync_service.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "chrome/browser/prefs/pref_service.h" | 23 #include "chrome/browser/prefs/pref_service.h" |
24 #include "chrome/browser/profile.h" | 24 #include "chrome/browser/profile.h" |
25 #include "chrome/browser/net/gaia/token_service.h" | 25 #include "chrome/browser/net/gaia/token_service.h" |
26 #include "chrome/browser/sync/engine/syncapi.h" | 26 #include "chrome/browser/sync/engine/syncapi.h" |
27 #include "chrome/browser/sync/glue/change_processor.h" | 27 #include "chrome/browser/sync/glue/change_processor.h" |
28 #include "chrome/browser/sync/glue/data_type_controller.h" | 28 #include "chrome/browser/sync/glue/data_type_controller.h" |
29 #include "chrome/browser/sync/glue/data_type_manager.h" | 29 #include "chrome/browser/sync/glue/data_type_manager.h" |
30 #include "chrome/browser/sync/glue/session_data_type_controller.h" | 30 #include "chrome/browser/sync/glue/session_data_type_controller.h" |
31 #include "chrome/browser/sync/profile_sync_factory.h" | 31 #include "chrome/browser/sync/profile_sync_factory.h" |
32 #include "chrome/browser/sync/syncable/directory_manager.h" | 32 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 33 #include "chrome/browser/sync/token_migrator.h" |
| 34 #include "chrome/browser/sync/util/user_settings.h" |
33 #include "chrome/common/chrome_switches.h" | 35 #include "chrome/common/chrome_switches.h" |
| 36 #include "chrome/common/net/gaia/gaia_constants.h" |
34 #include "chrome/common/notification_details.h" | 37 #include "chrome/common/notification_details.h" |
35 #include "chrome/common/notification_service.h" | 38 #include "chrome/common/notification_service.h" |
36 #include "chrome/common/notification_source.h" | 39 #include "chrome/common/notification_source.h" |
37 #include "chrome/common/notification_type.h" | 40 #include "chrome/common/notification_type.h" |
38 #include "chrome/common/pref_names.h" | 41 #include "chrome/common/pref_names.h" |
39 #include "chrome/common/time_format.h" | 42 #include "chrome/common/time_format.h" |
40 #include "grit/generated_resources.h" | 43 #include "grit/generated_resources.h" |
41 #include "net/base/cookie_monster.h" | 44 #include "net/base/cookie_monster.h" |
42 | 45 |
43 using browser_sync::ChangeProcessor; | 46 using browser_sync::ChangeProcessor; |
44 using browser_sync::DataTypeController; | 47 using browser_sync::DataTypeController; |
45 using browser_sync::DataTypeManager; | 48 using browser_sync::DataTypeManager; |
46 using browser_sync::SyncBackendHost; | 49 using browser_sync::SyncBackendHost; |
| 50 using sync_api::SyncCredentials; |
47 | 51 |
48 typedef GoogleServiceAuthError AuthError; | 52 typedef GoogleServiceAuthError AuthError; |
49 | 53 |
50 const char* ProfileSyncService::kSyncServerUrl = | 54 const char* ProfileSyncService::kSyncServerUrl = |
51 "https://clients4.google.com/chrome-sync"; | 55 "https://clients4.google.com/chrome-sync"; |
52 | 56 |
53 const char* ProfileSyncService::kDevServerUrl = | 57 const char* ProfileSyncService::kDevServerUrl = |
54 "https://clients4.google.com/chrome-sync/dev"; | 58 "https://clients4.google.com/chrome-sync/dev"; |
55 | 59 |
56 ProfileSyncService::ProfileSyncService(ProfileSyncFactory* factory, | 60 ProfileSyncService::ProfileSyncService(ProfileSyncFactory* factory, |
57 Profile* profile, | 61 Profile* profile, |
58 bool bootstrap_sync_authentication) | 62 const std::string& cros_user) |
59 : last_auth_error_(AuthError::None()), | 63 : last_auth_error_(AuthError::None()), |
60 factory_(factory), | 64 factory_(factory), |
61 profile_(profile), | 65 profile_(profile), |
62 bootstrap_sync_authentication_(bootstrap_sync_authentication), | 66 cros_user_(cros_user), |
63 sync_service_url_(kDevServerUrl), | 67 sync_service_url_(kDevServerUrl), |
64 backend_initialized_(false), | 68 backend_initialized_(false), |
65 expecting_first_run_auth_needed_event_(false), | |
66 is_auth_in_progress_(false), | 69 is_auth_in_progress_(false), |
67 ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)), | 70 ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)), |
68 unrecoverable_error_detected_(false), | 71 unrecoverable_error_detected_(false), |
69 use_chrome_async_socket_(false), | 72 use_chrome_async_socket_(false), |
70 notification_method_(browser_sync::kDefaultNotificationMethod), | 73 notification_method_(browser_sync::kDefaultNotificationMethod), |
71 ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)) { | 74 ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)), |
| 75 token_migrator_(NULL) { |
72 DCHECK(factory); | 76 DCHECK(factory); |
73 DCHECK(profile); | 77 DCHECK(profile); |
74 registrar_.Add(this, | 78 registrar_.Add(this, |
75 NotificationType::SYNC_CONFIGURE_START, | 79 NotificationType::SYNC_CONFIGURE_START, |
76 NotificationService::AllSources()); | 80 NotificationService::AllSources()); |
77 registrar_.Add(this, | 81 registrar_.Add(this, |
78 NotificationType::SYNC_CONFIGURE_DONE, | 82 NotificationType::SYNC_CONFIGURE_DONE, |
79 NotificationService::AllSources()); | 83 NotificationService::AllSources()); |
80 registrar_.Add(this, | 84 registrar_.Add(this, |
81 NotificationType::SYNC_PASSPHRASE_REQUIRED, | 85 NotificationType::SYNC_PASSPHRASE_REQUIRED, |
(...skipping 20 matching lines...) Expand all Loading... |
102 } | 106 } |
103 #else | 107 #else |
104 LOG(INFO) << "Unofficial build, using dev channel sync server."; | 108 LOG(INFO) << "Unofficial build, using dev channel sync server."; |
105 #endif | 109 #endif |
106 } | 110 } |
107 | 111 |
108 ProfileSyncService::ProfileSyncService() | 112 ProfileSyncService::ProfileSyncService() |
109 : last_auth_error_(AuthError::None()), | 113 : last_auth_error_(AuthError::None()), |
110 factory_(NULL), | 114 factory_(NULL), |
111 profile_(NULL), | 115 profile_(NULL), |
112 bootstrap_sync_authentication_(false), | |
113 sync_service_url_(kSyncServerUrl), | 116 sync_service_url_(kSyncServerUrl), |
114 backend_initialized_(false), | 117 backend_initialized_(false), |
115 expecting_first_run_auth_needed_event_(false), | |
116 is_auth_in_progress_(false), | 118 is_auth_in_progress_(false), |
117 ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)), | 119 ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)), |
118 unrecoverable_error_detected_(false), | 120 unrecoverable_error_detected_(false), |
119 use_chrome_async_socket_(false), | 121 use_chrome_async_socket_(false), |
120 notification_method_(browser_sync::kDefaultNotificationMethod), | 122 notification_method_(browser_sync::kDefaultNotificationMethod), |
121 ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)), | 123 ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)), |
122 expect_sync_configuration_aborted_(false) { | 124 expect_sync_configuration_aborted_(false) { |
123 } | 125 } |
124 | 126 |
125 ProfileSyncService::~ProfileSyncService() { | 127 ProfileSyncService::~ProfileSyncService() { |
126 Shutdown(false); | 128 Shutdown(false); |
127 } | 129 } |
128 | 130 |
| 131 bool ProfileSyncService::AreCredentialsAvailable() { |
| 132 if (IsManaged()) { |
| 133 return false; |
| 134 } |
| 135 |
| 136 if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) { |
| 137 return false; |
| 138 } |
| 139 |
| 140 // CrOS user is always logged in. Chrome uses signin_ to check logged in. |
| 141 if (!cros_user_.empty() || !signin_.GetUsername().empty()) { |
| 142 // TODO(chron): Verify CrOS unit test behavior. |
| 143 if (profile()->GetTokenService() && |
| 144 profile()->GetTokenService()->HasTokenForService( |
| 145 GaiaConstants::kSyncService)) { |
| 146 return true; |
| 147 } |
| 148 } |
| 149 return false; |
| 150 } |
| 151 |
| 152 void ProfileSyncService::LoadMigratedCredentials(const std::string& username, |
| 153 const std::string& token) { |
| 154 signin_.SetUsername(username); |
| 155 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username); |
| 156 profile()->GetTokenService()->OnIssueAuthTokenSuccess( |
| 157 GaiaConstants::kSyncService, token); |
| 158 profile()->GetPrefs()->SetBoolean(prefs::kSyncCredentialsMigrated, true); |
| 159 token_migrator_.reset(); |
| 160 } |
| 161 |
129 void ProfileSyncService::Initialize() { | 162 void ProfileSyncService::Initialize() { |
130 LOG(INFO) << "Starting ProfileSyncService."; | 163 LOG(INFO) << "Starting ProfileSyncService."; |
131 InitSettings(); | 164 InitSettings(); |
132 RegisterPreferences(); | 165 RegisterPreferences(); |
133 | 166 |
134 // Watch the preference that indicates sync is managed so we can take | 167 // Watch the preference that indicates sync is managed so we can take |
135 // appropriate action. | 168 // appropriate action. |
136 pref_sync_managed_.Init(prefs::kSyncManaged, profile_->GetPrefs(), this); | 169 pref_sync_managed_.Init(prefs::kSyncManaged, profile_->GetPrefs(), this); |
137 | 170 |
138 // For now, the only thing we can do through policy is to turn sync off. | 171 // For now, the only thing we can do through policy is to turn sync off. |
139 if (IsManaged()) { | 172 if (IsManaged()) { |
140 DisableForUser(); | 173 DisableForUser(); |
141 return; | 174 return; |
142 } | 175 } |
143 | 176 |
144 if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) { | 177 RegisterAuthNotifications(); |
| 178 |
| 179 // In Chrome, we integrate a SigninManager which works with the sync |
| 180 // setup wizard to kick off the TokenService. CrOS does its own plumbing |
| 181 // for the TokenService. |
| 182 if (cros_user_.empty()) { |
| 183 // Will load tokens from DB and broadcast Token events after. |
| 184 signin_.Initialize(profile_); |
| 185 } |
| 186 |
| 187 if (!HasSyncSetupCompleted()) { |
145 DisableForUser(); // Clean up in case of previous crash / setup abort. | 188 DisableForUser(); // Clean up in case of previous crash / setup abort. |
| 189 if (!cros_user_.empty() && AreCredentialsAvailable()) { |
| 190 StartUp(); // Under ChromeOS, just autostart it anyway if creds are here. |
| 191 } |
| 192 } else if (AreCredentialsAvailable()) { |
| 193 // If we have credentials and sync setup finished, autostart the backend. |
| 194 // Note that if we haven't finished setting up sync, backend bring up will |
| 195 // be done by the wizard. |
| 196 StartUp(); |
| 197 } else { |
| 198 // Try to migrate the tokens (if that hasn't already succeeded). |
| 199 if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncCredentialsMigrated)) { |
| 200 token_migrator_.reset(new TokenMigrator(this, profile_->GetPath())); |
| 201 token_migrator_->TryMigration(); |
| 202 } |
| 203 } |
146 | 204 |
147 // Automatically start sync in Chromium OS. | 205 } |
148 if (bootstrap_sync_authentication_ && | 206 |
149 !profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) { | 207 void ProfileSyncService::RegisterAuthNotifications() { |
150 // If the LSID is empty, we're in a CrOS UI test that is not testing sync | 208 registrar_.Add(this, |
151 // behavior, so we don't want the sync service to start. | 209 NotificationType::TOKEN_AVAILABLE, |
152 if (profile()->GetTokenService() && | 210 NotificationService::AllSources()); |
153 !profile()->GetTokenService()->HasLsid()) { | 211 registrar_.Add(this, |
154 LOG(WARNING) << "Skipping CrOS sync startup, no LSID present."; | 212 NotificationType::TOKEN_LOADING_FINISHED, |
155 return; | 213 NotificationService::AllSources()); |
156 } | 214 registrar_.Add(this, |
157 StartUp(); | 215 NotificationType::GOOGLE_SIGNIN_SUCCESSFUL, |
158 } | 216 NotificationService::AllSources()); |
159 } else { | 217 registrar_.Add(this, |
160 StartUp(); | 218 NotificationType::GOOGLE_SIGNIN_FAILED, |
161 } | 219 NotificationService::AllSources()); |
162 } | 220 } |
163 | 221 |
164 void ProfileSyncService::RegisterDataTypeController( | 222 void ProfileSyncService::RegisterDataTypeController( |
165 DataTypeController* data_type_controller) { | 223 DataTypeController* data_type_controller) { |
166 DCHECK_EQ(data_type_controllers_.count(data_type_controller->type()), 0U); | 224 DCHECK_EQ(data_type_controllers_.count(data_type_controller->type()), 0U); |
167 data_type_controllers_[data_type_controller->type()] = | 225 data_type_controllers_[data_type_controller->type()] = |
168 data_type_controller; | 226 data_type_controller; |
169 } | 227 } |
170 | 228 |
171 browser_sync::SessionModelAssociator* | 229 browser_sync::SessionModelAssociator* |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 283 } |
226 } | 284 } |
227 | 285 |
228 void ProfileSyncService::RegisterPreferences() { | 286 void ProfileSyncService::RegisterPreferences() { |
229 PrefService* pref_service = profile_->GetPrefs(); | 287 PrefService* pref_service = profile_->GetPrefs(); |
230 if (pref_service->FindPreference(prefs::kSyncLastSyncedTime)) | 288 if (pref_service->FindPreference(prefs::kSyncLastSyncedTime)) |
231 return; | 289 return; |
232 pref_service->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0); | 290 pref_service->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0); |
233 pref_service->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, false); | 291 pref_service->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, false); |
234 pref_service->RegisterBooleanPref(prefs::kSyncSuppressStart, false); | 292 pref_service->RegisterBooleanPref(prefs::kSyncSuppressStart, false); |
| 293 pref_service->RegisterBooleanPref(prefs::kSyncCredentialsMigrated, false); |
235 | 294 |
236 // If you've never synced before, or if you're using Chrome OS, all datatypes | 295 // If you've never synced before, or if you're using Chrome OS, all datatypes |
237 // are on by default. | 296 // are on by default. |
238 // TODO(nick): Perhaps a better model would be to always default to false, | 297 // TODO(nick): Perhaps a better model would be to always default to false, |
239 // and explicitly call SetDataTypes() when the user shows the wizard. | 298 // and explicitly call SetDataTypes() when the user shows the wizard. |
240 #if defined(OS_CHROMEOS) | 299 #if defined(OS_CHROMEOS) |
241 bool enable_by_default = true; | 300 bool enable_by_default = true; |
242 #else | 301 #else |
243 bool enable_by_default = | 302 bool enable_by_default = |
244 !pref_service->HasPrefPath(prefs::kSyncHasSetupCompleted); | 303 !pref_service->HasPrefPath(prefs::kSyncHasSetupCompleted); |
(...skipping 17 matching lines...) Expand all Loading... |
262 void ProfileSyncService::ClearPreferences() { | 321 void ProfileSyncService::ClearPreferences() { |
263 PrefService* pref_service = profile_->GetPrefs(); | 322 PrefService* pref_service = profile_->GetPrefs(); |
264 pref_service->ClearPref(prefs::kSyncLastSyncedTime); | 323 pref_service->ClearPref(prefs::kSyncLastSyncedTime); |
265 pref_service->ClearPref(prefs::kSyncHasSetupCompleted); | 324 pref_service->ClearPref(prefs::kSyncHasSetupCompleted); |
266 pref_service->ClearPref(prefs::kEncryptionBootstrapToken); | 325 pref_service->ClearPref(prefs::kEncryptionBootstrapToken); |
267 // TODO(nick): The current behavior does not clear e.g. prefs::kSyncBookmarks. | 326 // TODO(nick): The current behavior does not clear e.g. prefs::kSyncBookmarks. |
268 // Is that really what we want? | 327 // Is that really what we want? |
269 pref_service->ScheduleSavePersistentPrefs(); | 328 pref_service->ScheduleSavePersistentPrefs(); |
270 } | 329 } |
271 | 330 |
| 331 SyncCredentials ProfileSyncService::GetCredentials() { |
| 332 SyncCredentials credentials; |
| 333 credentials.email = !cros_user_.empty() ? cros_user_ : signin_.GetUsername(); |
| 334 DCHECK(!credentials.email.empty()); |
| 335 TokenService* service = profile_->GetTokenService(); |
| 336 credentials.sync_token = service->GetTokenForService( |
| 337 GaiaConstants::kSyncService); |
| 338 return credentials; |
| 339 } |
| 340 |
272 void ProfileSyncService::InitializeBackend(bool delete_sync_data_folder) { | 341 void ProfileSyncService::InitializeBackend(bool delete_sync_data_folder) { |
273 if (!backend_.get()) { | 342 if (!backend_.get()) { |
274 NOTREACHED(); | 343 NOTREACHED(); |
275 return; | 344 return; |
276 } | 345 } |
277 | 346 |
278 // TODO(akalin): Gather all the command-line-controlled switches | 347 // TODO(chron): Reimplement invalidate XMPP login / Sync login |
279 // into an Options struct to make passing them down less annoying. | 348 // command line switches. Perhaps make it a command |
| 349 // line in the TokenService itself to pass an arbitrary |
| 350 // token. |
280 | 351 |
281 bool invalidate_sync_login = false; | |
282 bool invalidate_sync_xmpp_login = false; | |
283 bool try_ssltcp_first = false; | 352 bool try_ssltcp_first = false; |
284 #if !defined(NDEBUG) | 353 #if !defined(NDEBUG) |
285 invalidate_sync_login = CommandLine::ForCurrentProcess()->HasSwitch( | |
286 switches::kInvalidateSyncLogin); | |
287 invalidate_sync_xmpp_login = CommandLine::ForCurrentProcess()->HasSwitch( | |
288 switches::kInvalidateSyncXmppLogin); | |
289 try_ssltcp_first = CommandLine::ForCurrentProcess()->HasSwitch( | 354 try_ssltcp_first = CommandLine::ForCurrentProcess()->HasSwitch( |
290 switches::kSyncUseSslTcp); | 355 switches::kSyncUseSslTcp); |
291 #endif | 356 #endif |
292 | 357 |
293 syncable::ModelTypeSet types; | 358 syncable::ModelTypeSet types; |
294 // If sync setup hasn't finished, we don't want to initialize routing info | 359 // If sync setup hasn't finished, we don't want to initialize routing info |
295 // for any data types so that we don't download updates for types that the | 360 // for any data types so that we don't download updates for types that the |
296 // user chooses not to sync on the first DownloadUpdatesCommand. | 361 // user chooses not to sync on the first DownloadUpdatesCommand. |
297 if (HasSyncSetupCompleted()) | 362 if (HasSyncSetupCompleted()) { |
298 GetPreferredDataTypes(&types); | 363 GetPreferredDataTypes(&types); |
| 364 } |
| 365 |
| 366 SyncCredentials credentials = GetCredentials(); |
| 367 |
299 backend_->Initialize(sync_service_url_, | 368 backend_->Initialize(sync_service_url_, |
300 types, | 369 types, |
301 profile_->GetRequestContext(), | 370 profile_->GetRequestContext(), |
302 profile_->GetTokenService()->GetLsid(), | 371 credentials, |
303 delete_sync_data_folder, | 372 delete_sync_data_folder, |
304 invalidate_sync_login, | |
305 invalidate_sync_xmpp_login, | |
306 use_chrome_async_socket_, | 373 use_chrome_async_socket_, |
307 try_ssltcp_first, | 374 try_ssltcp_first, |
308 notification_method_); | 375 notification_method_); |
309 } | 376 } |
310 | 377 |
311 void ProfileSyncService::CreateBackend() { | 378 void ProfileSyncService::CreateBackend() { |
312 backend_.reset( | 379 backend_.reset( |
313 new SyncBackendHost(this, profile_, profile_->GetPath(), | 380 new SyncBackendHost(this, profile_, profile_->GetPath(), |
314 data_type_controllers_)); | 381 data_type_controllers_)); |
315 } | 382 } |
316 | 383 |
317 void ProfileSyncService::StartUp() { | 384 void ProfileSyncService::StartUp() { |
318 // Don't start up multiple times. | 385 // Don't start up multiple times. |
319 if (backend_.get()) { | 386 if (backend_.get()) { |
320 LOG(INFO) << "Skipping bringing up backend host."; | 387 LOG(INFO) << "Skipping bringing up backend host."; |
321 return; | 388 return; |
322 } | 389 } |
323 | 390 |
324 LOG(INFO) << "ProfileSyncSerivce bringing up backend host."; | 391 DCHECK(AreCredentialsAvailable()); |
| 392 |
| 393 LOG(INFO) << "ProfileSyncService bringing up backend host."; |
325 | 394 |
326 last_synced_time_ = base::Time::FromInternalValue( | 395 last_synced_time_ = base::Time::FromInternalValue( |
327 profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime)); | 396 profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime)); |
328 | 397 |
329 CreateBackend(); | 398 CreateBackend(); |
330 // Initialize the backend. Every time we start up a new SyncBackendHost, | 399 // Initialize the backend. Every time we start up a new SyncBackendHost, |
331 // we'll want to start from a fresh SyncDB, so delete any old one that might | 400 // we'll want to start from a fresh SyncDB, so delete any old one that might |
332 // be there. | 401 // be there. |
333 InitializeBackend(!HasSyncSetupCompleted()); | 402 InitializeBackend(!HasSyncSetupCompleted()); |
334 } | 403 } |
(...skipping 13 matching lines...) Expand all Loading... |
348 | 417 |
349 if (doomed_backend.get()) | 418 if (doomed_backend.get()) |
350 doomed_backend->Shutdown(sync_disabled); | 419 doomed_backend->Shutdown(sync_disabled); |
351 | 420 |
352 doomed_backend.reset(); | 421 doomed_backend.reset(); |
353 | 422 |
354 | 423 |
355 // Clear various flags. | 424 // Clear various flags. |
356 is_auth_in_progress_ = false; | 425 is_auth_in_progress_ = false; |
357 backend_initialized_ = false; | 426 backend_initialized_ = false; |
358 expecting_first_run_auth_needed_event_ = false; | |
359 last_attempted_user_email_.clear(); | 427 last_attempted_user_email_.clear(); |
360 } | 428 } |
361 | 429 |
362 void ProfileSyncService::EnableForUser(gfx::NativeWindow parent_window) { | 430 void ProfileSyncService::DisableForUser() { |
363 if (WizardIsVisible()) { | 431 LOG(INFO) << "Disabling sync for user."; |
364 wizard_.Focus(); | |
365 return; | |
366 } | |
367 expecting_first_run_auth_needed_event_ = true; | |
368 DCHECK(!data_type_manager_.get()); | |
369 | 432 |
370 wizard_.SetParent(parent_window); | 433 // Clear prefs (including SyncSetupHasCompleted) before shutting down so |
371 StartUp(); | |
372 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | |
373 } | |
374 | |
375 void ProfileSyncService::DisableForUser() { | |
376 LOG(INFO) << "Clearing Sync DB."; | |
377 | |
378 // Clear prefs (including SyncSetupHasCompleted) before shutting down so | |
379 // PSS clients don't think we're set up while we're shutting down. | 434 // PSS clients don't think we're set up while we're shutting down. |
380 ClearPreferences(); | 435 ClearPreferences(); |
381 Shutdown(true); | 436 Shutdown(true); |
382 | 437 |
| 438 if (cros_user_.empty()) { |
| 439 signin_.SignOut(); |
| 440 } |
| 441 |
383 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 442 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
384 } | 443 } |
385 | 444 |
386 bool ProfileSyncService::HasSyncSetupCompleted() const { | 445 bool ProfileSyncService::HasSyncSetupCompleted() const { |
387 return profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted); | 446 return profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted); |
388 } | 447 } |
389 | 448 |
390 void ProfileSyncService::SetSyncSetupCompleted() { | 449 void ProfileSyncService::SetSyncSetupCompleted() { |
391 PrefService* prefs = profile()->GetPrefs(); | 450 PrefService* prefs = profile()->GetPrefs(); |
392 prefs->SetBoolean(prefs::kSyncHasSetupCompleted, true); | 451 prefs->SetBoolean(prefs::kSyncHasSetupCompleted, true); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 void ProfileSyncService::OnUnrecoverableError( | 493 void ProfileSyncService::OnUnrecoverableError( |
435 const tracked_objects::Location& from_here, | 494 const tracked_objects::Location& from_here, |
436 const std::string& message) { | 495 const std::string& message) { |
437 unrecoverable_error_detected_ = true; | 496 unrecoverable_error_detected_ = true; |
438 unrecoverable_error_message_ = message; | 497 unrecoverable_error_message_ = message; |
439 unrecoverable_error_location_.reset( | 498 unrecoverable_error_location_.reset( |
440 new tracked_objects::Location(from_here.function_name(), | 499 new tracked_objects::Location(from_here.function_name(), |
441 from_here.file_name(), | 500 from_here.file_name(), |
442 from_here.line_number())); | 501 from_here.line_number())); |
443 | 502 |
444 // Shut all data types down. | |
445 if (data_type_manager_.get()) | |
446 data_type_manager_->Stop(); | |
447 | |
448 // Tell the wizard so it can inform the user only if it is already open. | 503 // Tell the wizard so it can inform the user only if it is already open. |
449 wizard_.Step(SyncSetupWizard::FATAL_ERROR); | 504 wizard_.Step(SyncSetupWizard::FATAL_ERROR); |
450 | 505 |
451 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 506 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
452 LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable."; | 507 LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable." |
| 508 << message; |
453 std::string location; | 509 std::string location; |
454 from_here.Write(true, true, &location); | 510 from_here.Write(true, true, &location); |
455 LOG(ERROR) << location; | 511 LOG(ERROR) << location; |
456 | 512 |
457 if (SetupInProgress()) { | 513 // Shut all data types down. |
458 // We've hit an error in the middle of a startup process- shutdown all the | 514 MessageLoop::current()->PostTask(FROM_HERE, |
459 // backend stuff, and then restart it, so we're in the same state as before. | |
460 MessageLoop::current()->PostTask(FROM_HERE, | |
461 scoped_runnable_method_factory_.NewRunnableMethod( | 515 scoped_runnable_method_factory_.NewRunnableMethod( |
462 &ProfileSyncService::Shutdown, true)); | 516 &ProfileSyncService::Shutdown, true)); |
463 MessageLoop::current()->PostTask(FROM_HERE, | |
464 scoped_runnable_method_factory_.NewRunnableMethod( | |
465 &ProfileSyncService::StartUp)); | |
466 } | |
467 } | 517 } |
468 | 518 |
469 void ProfileSyncService::OnBackendInitialized() { | 519 void ProfileSyncService::OnBackendInitialized() { |
470 backend_initialized_ = true; | 520 backend_initialized_ = true; |
471 | 521 |
472 // The very first time the backend initializes is effectively the first time | 522 // The very first time the backend initializes is effectively the first time |
473 // we can say we successfully "synced". last_synced_time_ will only be null | 523 // we can say we successfully "synced". last_synced_time_ will only be null |
474 // in this case, because the pref wasn't restored on StartUp. | 524 // in this case, because the pref wasn't restored on StartUp. |
475 if (last_synced_time_.is_null()) | 525 if (last_synced_time_.is_null()) { |
476 UpdateLastSyncedTime(); | 526 UpdateLastSyncedTime(); |
| 527 } |
477 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 528 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
478 | 529 |
479 if (bootstrap_sync_authentication_) { | 530 if (!cros_user_.empty()) { |
480 if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) { | 531 if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) { |
481 ShowChooseDataTypes(NULL); | 532 ShowChooseDataTypes(NULL); |
482 } else { | 533 } else { |
483 SetSyncSetupCompleted(); | 534 SetSyncSetupCompleted(); |
484 } | 535 } |
485 } | 536 } |
486 | 537 |
487 if (HasSyncSetupCompleted()) | 538 if (HasSyncSetupCompleted()) { |
488 ConfigureDataTypeManager(); | 539 ConfigureDataTypeManager(); |
| 540 } |
489 } | 541 } |
490 | 542 |
491 void ProfileSyncService::OnSyncCycleCompleted() { | 543 void ProfileSyncService::OnSyncCycleCompleted() { |
492 UpdateLastSyncedTime(); | 544 UpdateLastSyncedTime(); |
493 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 545 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
494 } | 546 } |
495 | 547 |
496 void ProfileSyncService::OnAuthError() { | 548 void ProfileSyncService::UpdateAuthErrorState( |
497 last_auth_error_ = backend_->GetAuthError(); | 549 const GoogleServiceAuthError& error) { |
| 550 last_auth_error_ = error; |
498 // Protect against the in-your-face dialogs that pop out of nowhere. | 551 // Protect against the in-your-face dialogs that pop out of nowhere. |
499 // Require the user to click somewhere to run the setup wizard in the case | 552 // Require the user to click somewhere to run the setup wizard in the case |
500 // of a steady-state auth failure. | 553 // of a steady-state auth failure. |
501 if (WizardIsVisible() || expecting_first_run_auth_needed_event_) { | 554 if (WizardIsVisible()) { |
502 wizard_.Step(AuthError::NONE == last_auth_error_.state() ? | 555 wizard_.Step(AuthError::NONE == last_auth_error_.state() ? |
503 SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GAIA_LOGIN); | 556 SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GAIA_LOGIN); |
504 } | 557 } else { |
505 | |
506 if (expecting_first_run_auth_needed_event_) { | |
507 last_auth_error_ = AuthError::None(); | |
508 expecting_first_run_auth_needed_event_ = false; | |
509 } | |
510 | |
511 if (!WizardIsVisible()) { | |
512 auth_error_time_ == base::TimeTicks::Now(); | 558 auth_error_time_ == base::TimeTicks::Now(); |
513 } | 559 } |
514 | 560 |
515 if (!auth_start_time_.is_null()) { | 561 if (!auth_start_time_.is_null()) { |
516 UMA_HISTOGRAM_TIMES("Sync.AuthorizationTimeInNetwork", | 562 UMA_HISTOGRAM_TIMES("Sync.AuthorizationTimeInNetwork", |
517 base::TimeTicks::Now() - auth_start_time_); | 563 base::TimeTicks::Now() - auth_start_time_); |
518 auth_start_time_ = base::TimeTicks(); | 564 auth_start_time_ = base::TimeTicks(); |
519 } | 565 } |
520 | 566 |
521 is_auth_in_progress_ = false; | 567 is_auth_in_progress_ = false; |
522 // Fan the notification out to interested UI-thread components. | 568 // Fan the notification out to interested UI-thread components. |
523 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 569 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
524 } | 570 } |
525 | 571 |
| 572 void ProfileSyncService::OnAuthError() { |
| 573 UpdateAuthErrorState(backend_->GetAuthError()); |
| 574 } |
| 575 |
526 void ProfileSyncService::OnStopSyncingPermanently() { | 576 void ProfileSyncService::OnStopSyncingPermanently() { |
527 if (SetupInProgress()) { | 577 if (SetupInProgress()) { |
528 wizard_.Step(SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR); | 578 wizard_.Step(SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR); |
529 expect_sync_configuration_aborted_ = true; | 579 expect_sync_configuration_aborted_ = true; |
530 } | 580 } |
531 profile_->GetPrefs()->SetBoolean(prefs::kSyncSuppressStart, true); | 581 profile_->GetPrefs()->SetBoolean(prefs::kSyncSuppressStart, true); |
532 DisableForUser(); | 582 DisableForUser(); |
533 } | 583 } |
534 | 584 |
535 void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) { | 585 void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) { |
| 586 // TODO(johnnyg): File a bug to make sure this doesn't happen. |
| 587 if (!cros_user_.empty()) { |
| 588 LOG(WARNING) << "ShowLoginDialog called on Chrome OS."; |
| 589 return; |
| 590 } |
| 591 |
536 if (WizardIsVisible()) { | 592 if (WizardIsVisible()) { |
537 wizard_.Focus(); | 593 wizard_.Focus(); |
538 return; | 594 return; |
539 } | 595 } |
540 | 596 |
541 if (!auth_error_time_.is_null()) { | 597 if (!auth_error_time_.is_null()) { |
542 UMA_HISTOGRAM_LONG_TIMES("Sync.ReauthorizationTime", | 598 UMA_HISTOGRAM_LONG_TIMES("Sync.ReauthorizationTime", |
543 base::TimeTicks::Now() - auth_error_time_); | 599 base::TimeTicks::Now() - auth_error_time_); |
544 auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null. | 600 auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null. |
545 } | 601 } |
546 | 602 |
547 if (last_auth_error_.state() != AuthError::NONE) { | 603 wizard_.SetParent(parent_window); |
548 wizard_.SetParent(parent_window); | 604 wizard_.Step(SyncSetupWizard::GAIA_LOGIN); |
549 wizard_.Step(SyncSetupWizard::GAIA_LOGIN); | 605 |
550 } | 606 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
551 } | 607 } |
552 | 608 |
553 void ProfileSyncService::ShowChooseDataTypes(gfx::NativeWindow parent_window) { | 609 void ProfileSyncService::ShowChooseDataTypes(gfx::NativeWindow parent_window) { |
554 if (WizardIsVisible()) { | 610 if (WizardIsVisible()) { |
555 wizard_.Focus(); | 611 wizard_.Focus(); |
556 return; | 612 return; |
557 } | 613 } |
558 wizard_.SetParent(parent_window); | 614 wizard_.SetParent(parent_window); |
559 wizard_.Step(SyncSetupWizard::CHOOSE_DATA_TYPES); | 615 wizard_.Step(SyncSetupWizard::CHOOSE_DATA_TYPES); |
560 } | 616 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 string16 ProfileSyncService::GetAuthenticatedUsername() const { | 672 string16 ProfileSyncService::GetAuthenticatedUsername() const { |
617 if (backend_.get() && backend_initialized_) | 673 if (backend_.get() && backend_initialized_) |
618 return backend_->GetAuthenticatedUsername(); | 674 return backend_->GetAuthenticatedUsername(); |
619 else | 675 else |
620 return string16(); | 676 return string16(); |
621 } | 677 } |
622 | 678 |
623 void ProfileSyncService::OnUserSubmittedAuth( | 679 void ProfileSyncService::OnUserSubmittedAuth( |
624 const std::string& username, const std::string& password, | 680 const std::string& username, const std::string& password, |
625 const std::string& captcha) { | 681 const std::string& captcha) { |
626 if (!backend_.get()) { | |
627 NOTREACHED(); | |
628 return; | |
629 } | |
630 last_attempted_user_email_ = username; | 682 last_attempted_user_email_ = username; |
631 is_auth_in_progress_ = true; | 683 is_auth_in_progress_ = true; |
632 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 684 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
633 | 685 |
634 auth_start_time_ = base::TimeTicks::Now(); | 686 auth_start_time_ = base::TimeTicks::Now(); |
635 backend_->Authenticate(username, password, captcha); | 687 |
| 688 // TODO(chron): Mechanism for ChromeOS auth renewal? |
| 689 // (maybe just run the dialog anyway?) |
| 690 // or send it to the CrOS login somehow? |
| 691 if (!cros_user_.empty()) { |
| 692 LOG(WARNING) << "No mechanism on ChromeOS yet. See http://crbug.com/50292"; |
| 693 } |
| 694 |
| 695 if (!signin_.GetUsername().empty()) { |
| 696 signin_.SignOut(); |
| 697 } |
| 698 signin_.StartSignIn(username, |
| 699 password, |
| 700 last_auth_error_.captcha().token, |
| 701 captcha); |
636 } | 702 } |
637 | 703 |
638 void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything, | 704 void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything, |
639 const syncable::ModelTypeSet& chosen_types) { | 705 const syncable::ModelTypeSet& chosen_types) { |
640 if (!backend_.get()) { | 706 if (!backend_.get()) { |
641 NOTREACHED(); | 707 NOTREACHED(); |
642 return; | 708 return; |
643 } | 709 } |
644 profile_->GetPrefs()->SetBoolean(prefs::kKeepEverythingSynced, | 710 profile_->GetPrefs()->SetBoolean(prefs::kKeepEverythingSynced, |
645 sync_everything); | 711 sync_everything); |
646 | 712 |
647 ChangePreferredDataTypes(chosen_types); | 713 ChangePreferredDataTypes(chosen_types); |
648 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); | 714 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); |
649 } | 715 } |
650 | 716 |
651 void ProfileSyncService::OnUserCancelledDialog() { | 717 void ProfileSyncService::OnUserCancelledDialog() { |
652 if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) { | 718 if (!HasSyncSetupCompleted()) { |
653 // A sync dialog was aborted before authentication. | 719 // A sync dialog was aborted before authentication. |
654 // Rollback. | 720 // Rollback. |
655 expect_sync_configuration_aborted_ = true; | 721 expect_sync_configuration_aborted_ = true; |
656 DisableForUser(); | 722 DisableForUser(); |
657 } | 723 } |
658 wizard_.SetParent(NULL); | 724 wizard_.SetParent(NULL); |
659 | 725 |
660 // Though an auth could still be in progress, once the dialog is closed we | 726 // Though an auth could still be in progress, once the dialog is closed we |
661 // don't want the UI to stay stuck in the "waiting for authentication" state | 727 // don't want the UI to stay stuck in the "waiting for authentication" state |
662 // as that could take forever. We set this to false so the buttons to re- | 728 // as that could take forever. We set this to false so the buttons to re- |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 GetPreferredDataTypes(&types); | 874 GetPreferredDataTypes(&types); |
809 data_type_manager_->Configure(types); | 875 data_type_manager_->Configure(types); |
810 | 876 |
811 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 877 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
812 break; | 878 break; |
813 } | 879 } |
814 case NotificationType::PREF_CHANGED: { | 880 case NotificationType::PREF_CHANGED: { |
815 std::string* pref_name = Details<std::string>(details).ptr(); | 881 std::string* pref_name = Details<std::string>(details).ptr(); |
816 if (*pref_name == prefs::kSyncManaged) { | 882 if (*pref_name == prefs::kSyncManaged) { |
817 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); | 883 FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); |
818 if (*pref_sync_managed_) | 884 if (*pref_sync_managed_) { |
819 DisableForUser(); | 885 DisableForUser(); |
820 else if (HasSyncSetupCompleted()) | 886 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { |
821 StartUp(); | 887 StartUp(); |
| 888 } |
| 889 } |
| 890 break; |
| 891 } |
| 892 case NotificationType::GOOGLE_SIGNIN_SUCCESSFUL: { |
| 893 LOG(INFO) << "Signin OK. Waiting on tokens."; |
| 894 // TODO(chron): UI update? |
| 895 // TODO(chron): Timeout? |
| 896 break; |
| 897 } |
| 898 case NotificationType::GOOGLE_SIGNIN_FAILED: { |
| 899 GoogleServiceAuthError error = |
| 900 *(Details<GoogleServiceAuthError>(details).ptr()); |
| 901 UpdateAuthErrorState(error); |
| 902 break; |
| 903 } |
| 904 case NotificationType::TOKEN_AVAILABLE: { |
| 905 if (AreCredentialsAvailable()) { |
| 906 if (backend_initialized_) { |
| 907 backend_->UpdateCredentials(GetCredentials()); |
| 908 } |
| 909 |
| 910 StartUp(); |
| 911 } |
| 912 break; |
| 913 } |
| 914 case NotificationType::TOKEN_LOADING_FINISHED: { |
| 915 // If not in Chrome OS, and we have a username without tokens, |
| 916 // the user will need to signin again, so sign out. |
| 917 if (cros_user_.empty() && |
| 918 !signin_.GetUsername().empty() && |
| 919 !AreCredentialsAvailable()) { |
| 920 DisableForUser(); |
822 } | 921 } |
823 break; | 922 break; |
824 } | 923 } |
825 default: { | 924 default: { |
826 NOTREACHED(); | 925 NOTREACHED(); |
827 } | 926 } |
828 } | 927 } |
829 } | 928 } |
830 | 929 |
831 void ProfileSyncService::AddObserver(Observer* observer) { | 930 void ProfileSyncService::AddObserver(Observer* observer) { |
(...skipping 25 matching lines...) Expand all Loading... |
857 // is initialized, all enabled data types are consistent with one | 956 // is initialized, all enabled data types are consistent with one |
858 // another, and no unrecoverable error has transpired. | 957 // another, and no unrecoverable error has transpired. |
859 if (unrecoverable_error_detected_) | 958 if (unrecoverable_error_detected_) |
860 return false; | 959 return false; |
861 | 960 |
862 if (!data_type_manager_.get()) | 961 if (!data_type_manager_.get()) |
863 return false; | 962 return false; |
864 | 963 |
865 return data_type_manager_->state() == DataTypeManager::CONFIGURED; | 964 return data_type_manager_->state() == DataTypeManager::CONFIGURED; |
866 } | 965 } |
OLD | NEW |