OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/credential_cache_service_win.h" | 5 #include "chrome/browser/sync/credential_cache_service_win.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/time.h" | |
12 #include "base/values.h" | 13 #include "base/values.h" |
13 #include "base/win/windows_version.h" | 14 #include "base/win/windows_version.h" |
14 #include "chrome/browser/prefs/pref_service.h" | 15 #include "chrome/browser/prefs/pref_service.h" |
15 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
16 #include "chrome/browser/profiles/profile_manager.h" | 17 #include "chrome/browser/profiles/profile_manager.h" |
17 #include "chrome/browser/signin/signin_manager.h" | 18 #include "chrome/browser/signin/signin_manager.h" |
18 #include "chrome/browser/signin/token_service.h" | 19 #include "chrome/browser/signin/token_service.h" |
19 #include "chrome/browser/signin/token_service_factory.h" | 20 #include "chrome/browser/signin/token_service_factory.h" |
20 #include "chrome/browser/sync/glue/chrome_encryptor.h" | 21 #include "chrome/browser/sync/glue/chrome_encryptor.h" |
21 #include "chrome/browser/sync/profile_sync_service.h" | 22 #include "chrome/browser/sync/profile_sync_service.h" |
22 #include "chrome/browser/sync/profile_sync_service_factory.h" | 23 #include "chrome/browser/sync/profile_sync_service_factory.h" |
23 #include "chrome/common/chrome_constants.h" | 24 #include "chrome/common/chrome_constants.h" |
24 #include "chrome/common/chrome_notification_types.h" | 25 #include "chrome/common/chrome_notification_types.h" |
25 #include "chrome/common/chrome_paths_internal.h" | 26 #include "chrome/common/chrome_paths_internal.h" |
26 #include "chrome/common/net/gaia/gaia_auth_consumer.h" | 27 #include "chrome/common/net/gaia/gaia_auth_consumer.h" |
27 #include "chrome/common/net/gaia/gaia_constants.h" | 28 #include "chrome/common/net/gaia/gaia_constants.h" |
28 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
29 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
30 #include "content/public/browser/notification_details.h" | 31 #include "content/public/browser/notification_details.h" |
31 #include "content/public/browser/notification_source.h" | 32 #include "content/public/browser/notification_source.h" |
32 #include "sync/internal_api/public/base/model_type.h" | 33 #include "sync/internal_api/public/base/model_type.h" |
33 | 34 |
34 namespace syncer { | 35 namespace syncer { |
35 | 36 |
37 // The time delay (in seconds) between two consecutive polls of the alternate | |
38 // credential cache. A one minute delay seems like a reasonable amount of time | |
39 // in which to propagate changes to signed in state between Metro and Desktop. | |
40 const int kCredentialCachePollIntervalSecs = 60; | |
41 | |
42 using base::TimeDelta; | |
36 using content::BrowserThread; | 43 using content::BrowserThread; |
37 | 44 |
38 CredentialCacheService::CredentialCacheService(Profile* profile) | 45 CredentialCacheService::CredentialCacheService(Profile* profile) |
39 : profile_(profile), | 46 : profile_(profile), |
40 // |profile_| is null in unit tests. | 47 // |profile_| is null in unit tests. |
41 sync_prefs_(profile_ ? profile_->GetPrefs() : NULL), | 48 sync_prefs_(profile_ ? profile_->GetPrefs() : NULL), |
42 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 49 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
43 if (profile_) { | 50 if (profile_) { |
44 InitializeLocalCredentialCacheWriter(); | 51 InitializeLocalCredentialCacheWriter(); |
45 if (ShouldLookForCachedCredentialsInAlternateProfile()) | 52 if (ShouldLookForCachedCredentialsInAlternateProfile()) |
(...skipping 11 matching lines...) Expand all Loading... | |
57 } | 64 } |
58 | 65 |
59 if (alternate_store_.get()) { | 66 if (alternate_store_.get()) { |
60 alternate_store_->RemoveObserver(this); | 67 alternate_store_->RemoveObserver(this); |
61 alternate_store_.release(); | 68 alternate_store_.release(); |
62 } | 69 } |
63 } | 70 } |
64 | 71 |
65 void CredentialCacheService::OnInitializationCompleted(bool succeeded) { | 72 void CredentialCacheService::OnInitializationCompleted(bool succeeded) { |
66 DCHECK(succeeded); | 73 DCHECK(succeeded); |
67 // When the alternate credential store becomes available, begin consuming its | 74 // When the local and alternate credential stores become available, begin |
68 // cached credentials. | 75 // consuming the alternate cached credentials. We must also wait for the local |
69 if (alternate_store_.get() && alternate_store_->IsInitializationComplete()) { | 76 // credential store because the credentials read from the alternate cache and |
77 // applied locally must eventually get stored in the local cache. | |
78 if (alternate_store_.get() && | |
79 alternate_store_->IsInitializationComplete() && | |
80 local_store_.get() && | |
81 local_store_->IsInitializationComplete()) { | |
70 ReadCachedCredentialsFromAlternateProfile(); | 82 ReadCachedCredentialsFromAlternateProfile(); |
71 } | 83 } |
72 } | 84 } |
73 | 85 |
74 void CredentialCacheService::OnPrefValueChanged(const std::string& key) { | 86 void CredentialCacheService::OnPrefValueChanged(const std::string& key) { |
75 // Nothing to do here, since credentials are cached silently. | 87 // Nothing to do here, since credentials are cached silently. |
76 } | 88 } |
77 | 89 |
78 void CredentialCacheService::Observe( | 90 void CredentialCacheService::Observe( |
79 int type, | 91 int type, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 ProfileManager::GetDefaultProfileDir(alternate_user_data_dir); | 250 ProfileManager::GetDefaultProfileDir(alternate_user_data_dir); |
239 return alternate_default_profile_dir.Append(chrome::kSyncCredentialsFilename); | 251 return alternate_default_profile_dir.Append(chrome::kSyncCredentialsFilename); |
240 } | 252 } |
241 | 253 |
242 bool CredentialCacheService::ShouldLookForCachedCredentialsInAlternateProfile() | 254 bool CredentialCacheService::ShouldLookForCachedCredentialsInAlternateProfile() |
243 const { | 255 const { |
244 // We must look for credentials in the alternate profile iff the following are | 256 // We must look for credentials in the alternate profile iff the following are |
245 // true: | 257 // true: |
246 // 1) Sync is not disabled by policy. | 258 // 1) Sync is not disabled by policy. |
247 // 2) Sync startup is not suppressed. | 259 // 2) Sync startup is not suppressed. |
248 // 3) No user is currently signed in to sync. | 260 return !sync_prefs_.IsManaged() && !sync_prefs_.IsStartSuppressed(); |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
Should we document why we want to look for credent
Raghu Simha
2012/08/03 21:57:35
Yes, it is to detect sign outs in the alternate pr
| |
249 DCHECK(profile_); | |
250 PrefService* prefs = profile_->GetPrefs(); | |
251 DCHECK(prefs); | |
252 return !sync_prefs_.IsManaged() && | |
253 !sync_prefs_.IsStartSuppressed() && | |
254 prefs->GetString(prefs::kGoogleServicesUsername).empty(); | |
255 } | 261 } |
256 | 262 |
257 void CredentialCacheService::InitializeLocalCredentialCacheWriter() { | 263 void CredentialCacheService::InitializeLocalCredentialCacheWriter() { |
258 local_store_ = new JsonPrefStore( | 264 local_store_ = new JsonPrefStore( |
259 GetCredentialPathInCurrentProfile(), | 265 GetCredentialPathInCurrentProfile(), |
260 content::BrowserThread::GetMessageLoopProxyForThread( | 266 content::BrowserThread::GetMessageLoopProxyForThread( |
261 content::BrowserThread::FILE)); | 267 content::BrowserThread::FILE)); |
268 local_store_->AddObserver(this); | |
262 local_store_->ReadPrefsAsync(NULL); | 269 local_store_->ReadPrefsAsync(NULL); |
263 | 270 |
264 // Register for notifications for updates to the sync credentials, which are | 271 // Register for notifications for updates to the sync credentials, which are |
265 // stored in the PrefStore. | 272 // stored in the PrefStore. |
266 pref_registrar_.Init(profile_->GetPrefs()); | 273 pref_registrar_.Init(profile_->GetPrefs()); |
267 pref_registrar_.Add(prefs::kSyncEncryptionBootstrapToken, this); | 274 pref_registrar_.Add(prefs::kSyncEncryptionBootstrapToken, this); |
268 pref_registrar_.Add(prefs::kGoogleServicesUsername, this); | 275 pref_registrar_.Add(prefs::kGoogleServicesUsername, this); |
269 pref_registrar_.Add(prefs::kSyncKeepEverythingSynced, this); | 276 pref_registrar_.Add(prefs::kSyncKeepEverythingSynced, this); |
270 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 277 ModelTypeSet all_types = syncer::ModelTypeSet::All(); |
271 if (i == NIGORI) // The NIGORI preference is not persisted. | 278 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) { |
279 if (it.Get() == NIGORI) // The NIGORI preference is not persisted. | |
272 continue; | 280 continue; |
273 pref_registrar_.Add( | 281 pref_registrar_.Add( |
274 browser_sync::SyncPrefs::GetPrefNameForDataType(ModelTypeFromInt(i)), | 282 browser_sync::SyncPrefs::GetPrefNameForDataType(it.Get()), |
275 this); | 283 this); |
276 } | 284 } |
277 | 285 |
278 // Register for notifications for updates to lsid and sid, which are stored in | 286 // Register for notifications for updates to lsid and sid, which are stored in |
279 // the TokenService. | 287 // the TokenService. |
280 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 288 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
281 registrar_.Add(this, | 289 registrar_.Add(this, |
282 chrome::NOTIFICATION_TOKEN_SERVICE_CREDENTIALS_UPDATED, | 290 chrome::NOTIFICATION_TOKEN_SERVICE_CREDENTIALS_UPDATED, |
283 content::Source<TokenService>(token_service)); | 291 content::Source<TokenService>(token_service)); |
284 registrar_.Add(this, | 292 registrar_.Add(this, |
285 chrome::NOTIFICATION_TOKENS_CLEARED, | 293 chrome::NOTIFICATION_TOKENS_CLEARED, |
286 content::Source<TokenService>(token_service)); | 294 content::Source<TokenService>(token_service)); |
287 } | 295 } |
288 | 296 |
289 void CredentialCacheService::InitializeAlternateCredentialCacheReader( | 297 void CredentialCacheService::InitializeAlternateCredentialCacheReader( |
290 bool* should_initialize) { | 298 bool* should_initialize) { |
291 // If |should_initialize| is false, there was no credential cache in the | 299 // If |should_initialize| is false, there was no credential cache in the |
292 // alternate profile directory, and there is nothing to do. | 300 // alternate profile directory, and there is nothing to do right now. Schedule |
293 // TODO(rsimha): Add a polling mechanism that periodically examines the | 301 // another read in the future and exit. |
294 // credential file in the alternate profile directory so we can respond to the | |
295 // user signing in and signing out. | |
296 DCHECK(should_initialize); | 302 DCHECK(should_initialize); |
297 if (!*should_initialize) | 303 if (!*should_initialize) { |
304 ScheduleNextReadFromAlternateCredentialCache(); | |
298 return; | 305 return; |
306 } | |
307 | |
308 // A credential cache file was found in the alternate profile. Prepare to | |
309 // consume its contents. | |
299 alternate_store_ = new JsonPrefStore( | 310 alternate_store_ = new JsonPrefStore( |
300 GetCredentialPathInAlternateProfile(), | 311 GetCredentialPathInAlternateProfile(), |
301 content::BrowserThread::GetMessageLoopProxyForThread( | 312 content::BrowserThread::GetMessageLoopProxyForThread( |
302 content::BrowserThread::FILE)); | 313 content::BrowserThread::FILE)); |
303 alternate_store_->AddObserver(this); | 314 alternate_store_->AddObserver(this); |
304 alternate_store_->ReadPrefsAsync(NULL); | 315 alternate_store_->ReadPrefsAsync(NULL); |
305 } | 316 } |
306 | 317 |
307 bool CredentialCacheService::HasUserSignedOut() { | 318 bool CredentialCacheService::HasUserSignedOut() { |
308 DCHECK(local_store_.get()); | 319 DCHECK(local_store_.get()); |
309 // If HasPref() is false, the user never signed in, since there are no | 320 // If HasPref() is false, the user never signed in, since there are no |
310 // previously cached credentials. If the kGoogleServicesUsername pref is | 321 // previously cached credentials. If the kGoogleServicesUsername pref is |
311 // empty, it means that the user signed in and subsequently signed out. | 322 // empty, it means that the user signed in and subsequently signed out. |
312 return HasPref(local_store_, prefs::kGoogleServicesUsername) && | 323 return HasPref(local_store_, prefs::kGoogleServicesUsername) && |
313 GetAndUnpackStringPref(local_store_, | 324 GetAndUnpackStringPref(local_store_, |
314 prefs::kGoogleServicesUsername).empty(); | 325 prefs::kGoogleServicesUsername).empty(); |
315 } | 326 } |
316 | 327 |
317 namespace { | 328 namespace { |
318 | 329 |
319 // Determines if credentials should be read from the alternate profile based | 330 // Determines if there is a sync credential cache in the alternate profile. |
320 // on the existence of the local and alternate credential files. Returns | 331 // Returns true via |result| if there is a credential cache file in the |
321 // true via |result| if there is a credential cache file in the alternate | 332 // alternate profile. Returns false otherwise. |
322 // profile, but there isn't one in the local profile. Returns false otherwise. | 333 void AlternateCredentialCacheExists( |
323 void ShouldReadFromAlternateCache( | |
324 const FilePath& credential_path_in_current_profile, | |
325 const FilePath& credential_path_in_alternate_profile, | 334 const FilePath& credential_path_in_alternate_profile, |
326 bool* result) { | 335 bool* result) { |
327 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | 336 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
328 DCHECK(result); | 337 DCHECK(result); |
329 *result = !file_util::PathExists(credential_path_in_current_profile) && | 338 *result = file_util::PathExists(credential_path_in_alternate_profile); |
330 file_util::PathExists(credential_path_in_alternate_profile); | |
331 } | 339 } |
332 | 340 |
333 } // namespace | 341 } // namespace |
334 | 342 |
335 void CredentialCacheService::LookForCachedCredentialsInAlternateProfile() { | 343 void CredentialCacheService::LookForCachedCredentialsInAlternateProfile() { |
336 bool* should_initialize = new bool(false); | 344 bool* should_initialize = new bool(false); |
337 content::BrowserThread::PostTaskAndReply( | 345 content::BrowserThread::PostTaskAndReply( |
338 content::BrowserThread::FILE, | 346 content::BrowserThread::FILE, |
339 FROM_HERE, | 347 FROM_HERE, |
340 base::Bind(&ShouldReadFromAlternateCache, | 348 base::Bind(&AlternateCredentialCacheExists, |
341 GetCredentialPathInCurrentProfile(), | |
342 GetCredentialPathInAlternateProfile(), | 349 GetCredentialPathInAlternateProfile(), |
343 should_initialize), | 350 should_initialize), |
344 base::Bind( | 351 base::Bind( |
345 &CredentialCacheService::InitializeAlternateCredentialCacheReader, | 352 &CredentialCacheService::InitializeAlternateCredentialCacheReader, |
346 weak_factory_.GetWeakPtr(), | 353 weak_factory_.GetWeakPtr(), |
347 base::Owned(should_initialize))); | 354 base::Owned(should_initialize))); |
348 } | 355 } |
349 | 356 |
350 void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() { | 357 void CredentialCacheService::ReadCachedCredentialsFromAlternateProfile() { |
358 // If the local user has signed in and signed out, we do not consume cached | |
359 // credentials from the alternate profile. There is nothing more to do. | |
360 if (HasUserSignedOut()) | |
361 return; | |
362 | |
363 // Sanity check the alternate credential cache. If any string credentials | |
364 // are outright missing even though the file exists, something is awry with | |
365 // the alternate profile store. There is no sense in flagging an error as the | |
366 // problem lies in a different profile directory. Silently return as there is | |
367 // nothing to do. | |
351 DCHECK(alternate_store_.get()); | 368 DCHECK(alternate_store_.get()); |
352 if (!HasPref(alternate_store_, prefs::kGoogleServicesUsername) || | 369 if (!HasPref(alternate_store_, prefs::kGoogleServicesUsername) || |
353 !HasPref(alternate_store_, GaiaConstants::kGaiaLsid) || | 370 !HasPref(alternate_store_, GaiaConstants::kGaiaLsid) || |
354 !HasPref(alternate_store_, GaiaConstants::kGaiaSid) || | 371 !HasPref(alternate_store_, GaiaConstants::kGaiaSid) || |
355 !HasPref(alternate_store_, prefs::kSyncEncryptionBootstrapToken) || | 372 !HasPref(alternate_store_, prefs::kSyncEncryptionBootstrapToken) || |
356 !HasPref(alternate_store_, prefs::kSyncKeepEverythingSynced)) { | 373 !HasPref(alternate_store_, prefs::kSyncKeepEverythingSynced)) { |
357 VLOG(1) << "Could not find cached credentials."; | 374 VLOG(1) << "Could not find cached credentials in \"" |
375 << GetCredentialPathInAlternateProfile().value() << "\"."; | |
358 return; | 376 return; |
359 } | 377 } |
360 | 378 |
379 // Extract cached credentials from the alternate credential cache. | |
361 std::string google_services_username = | 380 std::string google_services_username = |
362 GetAndUnpackStringPref(alternate_store_, prefs::kGoogleServicesUsername); | 381 GetAndUnpackStringPref(alternate_store_, prefs::kGoogleServicesUsername); |
363 std::string lsid = | 382 std::string lsid = |
364 GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaLsid); | 383 GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaLsid); |
365 std::string sid = | 384 std::string sid = |
366 GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaSid); | 385 GetAndUnpackStringPref(alternate_store_, GaiaConstants::kGaiaSid); |
367 std::string encryption_bootstrap_token = | 386 std::string encryption_bootstrap_token = |
368 GetAndUnpackStringPref(alternate_store_, | 387 GetAndUnpackStringPref(alternate_store_, |
369 prefs::kSyncEncryptionBootstrapToken); | 388 prefs::kSyncEncryptionBootstrapToken); |
370 bool keep_everything_synced = | |
371 GetBooleanPref(alternate_store_, prefs::kSyncKeepEverythingSynced); | |
372 | 389 |
373 if (google_services_username.empty() || | 390 // Sign out of sync iff: |
374 lsid.empty() || | 391 // 1) The user is signed in to the local profile. |
375 sid.empty() || | 392 // 2) The user has never signed out of the local profile in the past. |
376 encryption_bootstrap_token.empty()) { | 393 // 3) We just notice that the user has signed out of the alternate profile. |
377 VLOG(1) << "Found empty cached credentials."; | 394 // 4) The user is not already in the process of configuring sync. |
395 // There is no need to schedule any more reads of the alternate profile | |
396 // cache because we only apply cached credentials for first-time sign-ins. | |
397 ProfileSyncService* service = | |
398 ProfileSyncServiceFactory::GetForProfile(profile_); | |
399 if (!sync_prefs_.GetGoogleServicesUsername().empty() && | |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
Let's change all these references to SigninManager
Raghu Simha
2012/08/03 21:57:35
Done.
| |
400 !HasUserSignedOut() && | |
401 google_services_username.empty() && | |
402 !service->setup_in_progress()) { | |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
Why do we want to avoid signing out the user if th
Raghu Simha
2012/08/03 21:57:35
If the user is configuring sync, we want to avoid
| |
403 VLOG(1) << "User has signed out on the other profile. Signing out."; | |
404 InitiateSignOut(); | |
378 return; | 405 return; |
379 } | 406 } |
380 | 407 |
381 bool datatype_prefs[MODEL_TYPE_COUNT] = { false }; | 408 // Extract cached sync prefs from the alternate credential cache. |
382 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 409 bool keep_everything_synced = |
383 if (i == NIGORI) // The NIGORI preference is not persisted. | 410 GetBooleanPref(alternate_store_, prefs::kSyncKeepEverythingSynced); |
411 ModelTypeSet preferred_types; | |
412 ModelTypeSet registered_types = service->GetRegisteredDataTypes(); | |
413 for (ModelTypeSet::Iterator it = registered_types.First(); | |
414 it.Good(); | |
415 it.Inc()) { | |
416 std::string datatype_pref_name = | |
417 browser_sync::SyncPrefs::GetPrefNameForDataType(it.Get()); | |
418 if (!HasPref(alternate_store_, datatype_pref_name)) { | |
419 // If there is no cached pref for a specific data type, it means that the | |
420 // user originally signed in with an older version of Chrome, and then | |
421 // upgraded to a version with a new datatype. In such cases, we leave the | |
422 // default initial datatype setting as false while reading cached | |
423 // credentials, just like we do in SyncPrefs::RegisterPreferences. | |
424 VLOG(1) << "Could not find cached datatype pref for " | |
425 << datatype_pref_name << " in " | |
426 << GetCredentialPathInAlternateProfile().value() << "."; | |
384 continue; | 427 continue; |
385 std::string datatype_pref_name = | |
386 browser_sync::SyncPrefs::GetPrefNameForDataType(ModelTypeFromInt(i)); | |
387 if (!HasPref(alternate_store_, datatype_pref_name)) { | |
388 VLOG(1) << "Could not find cached datatype prefs."; | |
389 return; | |
390 } | 428 } |
391 datatype_prefs[i] = GetBooleanPref(alternate_store_, datatype_pref_name); | 429 if (GetBooleanPref(alternate_store_, datatype_pref_name)) |
430 preferred_types.Put(it.Get()); | |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
Is this loop dangerous to execute if the user is c
Raghu Simha
2012/08/03 21:57:35
I don't think it's dangerous to run this loop. It'
| |
392 } | 431 } |
393 | 432 |
394 ApplyCachedCredentials(google_services_username, | 433 // Reconfigure if sync settings or credentials have changed. |
395 lsid, | 434 // Follow this up by scheduling a future read from the alternate profile. |
396 sid, | 435 if (MayReconfigureSync(google_services_username)) { |
397 encryption_bootstrap_token, | 436 if (HaveSyncPrefsChanged(keep_everything_synced, preferred_types)) { |
398 keep_everything_synced, | 437 VLOG(1) << "Sync prefs have changed in other profile. Reconfiguring."; |
399 datatype_prefs); | 438 service->OnUserChoseDatatypes(keep_everything_synced, preferred_types); |
439 } | |
440 if (HaveTokenServiceCredentialsChanged(lsid, sid)) { | |
441 VLOG(1) << "Token service credentials have changed in other profile."; | |
442 UpdateTokenServiceCredentials(lsid, sid); | |
443 } | |
444 ScheduleNextReadFromAlternateCredentialCache(); | |
445 return; | |
446 } | |
447 | |
448 // Try signing in with cached credentials from the alternate profile iff: | |
449 // 1) The user is not currently signed in to the local profile. | |
450 // 2) The user has never signed out of the local profile in the past. | |
451 // 3) Valid cached credentials are available in the alternate profile. | |
452 // 4) The user is not already in the process of configuring sync. | |
453 // Follow this up by scheduling a future read from the alternate profile. | |
454 if (sync_prefs_.GetGoogleServicesUsername().empty() && | |
455 !HasUserSignedOut() && | |
456 !google_services_username.empty() && | |
457 !lsid.empty() && | |
458 !sid.empty() && | |
459 !encryption_bootstrap_token.empty() && | |
460 !service->setup_in_progress()) { | |
461 InitiateSignInWithCachedCredentials(google_services_username, | |
462 encryption_bootstrap_token, | |
463 keep_everything_synced, | |
464 preferred_types); | |
465 UpdateTokenServiceCredentials(lsid, sid); | |
466 ScheduleNextReadFromAlternateCredentialCache(); | |
467 return; | |
468 } | |
400 } | 469 } |
401 | 470 |
402 void CredentialCacheService::ApplyCachedCredentials( | 471 void CredentialCacheService::InitiateSignInWithCachedCredentials( |
403 const std::string& google_services_username, | 472 const std::string& google_services_username, |
404 const std::string& lsid, | |
405 const std::string& sid, | |
406 const std::string& encryption_bootstrap_token, | 473 const std::string& encryption_bootstrap_token, |
407 bool keep_everything_synced, | 474 bool keep_everything_synced, |
408 const bool datatype_prefs[]) { | 475 ModelTypeSet preferred_types) { |
409 // Update the google username in the SigninManager and PrefStore. | 476 // Update the google username in the SigninManager and PrefStore. |
410 ProfileSyncService* service = | 477 ProfileSyncService* service = |
411 ProfileSyncServiceFactory::GetForProfile(profile_); | 478 ProfileSyncServiceFactory::GetForProfile(profile_); |
412 service->signin()->SetAuthenticatedUsername(google_services_username); | 479 service->signin()->SetAuthenticatedUsername(google_services_username); |
413 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, | 480 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, |
414 google_services_username); | 481 google_services_username); |
415 | 482 |
416 // Update the sync preferences. | 483 // Update the sync preferences. |
417 sync_prefs_.SetStartSuppressed(false); | 484 sync_prefs_.SetStartSuppressed(false); |
418 sync_prefs_.SetSyncSetupCompleted(); | 485 sync_prefs_.SetSyncSetupCompleted(); |
419 sync_prefs_.SetEncryptionBootstrapToken(encryption_bootstrap_token); | 486 sync_prefs_.SetEncryptionBootstrapToken(encryption_bootstrap_token); |
420 sync_prefs_.SetKeepEverythingSynced(keep_everything_synced); | 487 sync_prefs_.SetKeepEverythingSynced(keep_everything_synced); |
421 syncer::ModelTypeSet registered_types; | 488 sync_prefs_.SetPreferredDataTypes(service->GetRegisteredDataTypes(), |
422 syncer::ModelTypeSet preferred_types; | 489 preferred_types); |
423 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 490 } |
424 if (i == NIGORI) // The NIGORI preference is not persisted. | |
425 continue; | |
426 registered_types.Put(ModelTypeFromInt(i)); | |
427 if (datatype_prefs[i]) | |
428 preferred_types.Put(ModelTypeFromInt(i)); | |
429 } | |
430 sync_prefs_.SetPreferredDataTypes(registered_types, preferred_types); | |
431 | 491 |
432 // Update the lsid and sid in the TokenService and mint new tokens for all | 492 void CredentialCacheService::UpdateTokenServiceCredentials( |
433 // Chrome services. | 493 const std::string& lsid, |
494 const std::string& sid) { | |
434 GaiaAuthConsumer::ClientLoginResult login_result; | 495 GaiaAuthConsumer::ClientLoginResult login_result; |
435 login_result.lsid = lsid; | 496 login_result.lsid = lsid; |
436 login_result.sid = sid; | 497 login_result.sid = sid; |
437 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 498 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
438 token_service->UpdateCredentials(login_result); | 499 token_service->UpdateCredentials(login_result); |
439 DCHECK(token_service->AreCredentialsValid()); | 500 DCHECK(token_service->AreCredentialsValid()); |
440 token_service->StartFetchingTokens(); | 501 token_service->StartFetchingTokens(); |
441 } | 502 } |
442 | 503 |
504 void CredentialCacheService::InitiateSignOut() { | |
505 ProfileSyncService* service = | |
506 ProfileSyncServiceFactory::GetForProfile(profile_); | |
507 service->DisableForUser(); | |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
This is fine, but it's slightly better to use Sign
Raghu Simha
2012/08/03 21:57:35
Done.
Raghu Simha
2012/08/03 22:12:52
Actually, PSS doesn't handle the notification sent
| |
508 } | |
509 | |
510 bool CredentialCacheService::HaveSyncPrefsChanged( | |
511 bool keep_everything_synced, | |
512 const ModelTypeSet& preferred_types) const { | |
513 ProfileSyncService* service = | |
514 ProfileSyncServiceFactory::GetForProfile(profile_); | |
515 ModelTypeSet local_preferred_types = | |
516 sync_prefs_.GetPreferredDataTypes(service->GetRegisteredDataTypes()); | |
517 return | |
518 (keep_everything_synced != sync_prefs_.HasKeepEverythingSynced()) || | |
519 !Difference(preferred_types, local_preferred_types).Empty(); | |
520 } | |
521 | |
522 bool CredentialCacheService::HaveTokenServiceCredentialsChanged( | |
523 const std::string& lsid, | |
524 const std::string& sid) { | |
525 std::string local_lsid = | |
526 GetAndUnpackStringPref(local_store_, GaiaConstants::kGaiaLsid); | |
527 std::string local_sid = | |
528 GetAndUnpackStringPref(local_store_, GaiaConstants::kGaiaSid); | |
529 return local_lsid != lsid || local_sid != sid; | |
530 } | |
531 | |
532 bool CredentialCacheService::MayReconfigureSync( | |
533 const std::string& google_services_username) { | |
534 ProfileSyncService* service = | |
535 ProfileSyncServiceFactory::GetForProfile(profile_); | |
536 // We may attempt to reconfigure sync iff: | |
537 // 1) The user is signed in to the local profile. | |
538 // 2) The user has never signed out of the local profile in the past. | |
539 // 3) The user is signed in to the alternate profile with the same account. | |
Andrew T Wilson (Slow)
2012/08/03 20:39:56
You left out step 4: Profit
Raghu Simha
2012/08/03 21:57:35
Hah! Fixed.
| |
540 // 5) The user is not already in the process of configuring sync. | |
541 return !sync_prefs_.GetGoogleServicesUsername().empty() && | |
542 !HasUserSignedOut() && | |
543 google_services_username == sync_prefs_.GetGoogleServicesUsername() && | |
544 !service->setup_in_progress(); | |
545 } | |
546 | |
547 void CredentialCacheService::ScheduleNextReadFromAlternateCredentialCache() { | |
548 // We must reinitialize |alternate_store_| here because the underlying | |
549 // credential file in the alternate profile might have changed, and we must | |
550 // re-read it afresh. | |
551 if (alternate_store_.get()) { | |
552 alternate_store_->RemoveObserver(this); | |
553 alternate_store_.release(); | |
554 } | |
555 MessageLoop::current()->PostDelayedTask( | |
556 FROM_HERE, | |
557 base::Bind( | |
558 &CredentialCacheService::LookForCachedCredentialsInAlternateProfile, | |
559 weak_factory_.GetWeakPtr()), | |
560 TimeDelta::FromSeconds(kCredentialCachePollIntervalSecs)); | |
561 } | |
562 | |
443 } // namespace syncer | 563 } // namespace syncer |
OLD | NEW |