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/profile_sync_service.h" | 5 #include "chrome/browser/sync/profile_sync_service.h" |
6 | 6 |
7 #include <cstddef> | 7 #include <cstddef> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <utility> | 10 #include <utility> |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 sync_service_url_ = GURL(kSyncServerUrl); | 151 sync_service_url_ = GURL(kSyncServerUrl); |
152 } | 152 } |
153 #endif | 153 #endif |
154 } | 154 } |
155 | 155 |
156 ProfileSyncService::~ProfileSyncService() { | 156 ProfileSyncService::~ProfileSyncService() { |
157 sync_prefs_.RemoveSyncPrefObserver(this); | 157 sync_prefs_.RemoveSyncPrefObserver(this); |
158 Shutdown(); | 158 Shutdown(); |
159 } | 159 } |
160 | 160 |
161 bool ProfileSyncService::AreCredentialsAvailable() { | 161 bool ProfileSyncService::IsSyncEnabledAndLoggedIn() { |
162 if (IsManaged()) { | 162 // Exit if sync is disabled. |
163 return false; | 163 if (IsManaged() || sync_prefs_.IsStartSuppressed()) |
164 } | |
165 | |
166 // If we have start suppressed, then basically just act like we have no | |
167 // credentials (login is required to fix this, since we need the user's | |
168 // passphrase to encrypt/decrypt anyway). | |
169 // TODO(sync): Revisit this when we move to a server-based keystore. | |
170 if (sync_prefs_.IsStartSuppressed()) | |
171 return false; | 164 return false; |
172 | 165 |
173 // CrOS user is always logged in. Chrome uses signin_ to check logged in. | 166 // Sync is logged in if there is a non-empty authenticated username. |
174 if (signin_->GetAuthenticatedUsername().empty()) | 167 return !signin_->GetAuthenticatedUsername().empty(); |
175 return false; | 168 } |
176 | 169 |
| 170 bool ProfileSyncService::IsSyncTokenAvailable() { |
177 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 171 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
178 if (!token_service) | 172 if (!token_service) |
179 return false; | 173 return false; |
180 | |
181 // TODO(chron): Verify CrOS unit test behavior. | |
182 return token_service->HasTokenForService(GaiaConstants::kSyncService); | 174 return token_service->HasTokenForService(GaiaConstants::kSyncService); |
183 } | 175 } |
184 | 176 |
185 void ProfileSyncService::Initialize() { | 177 void ProfileSyncService::Initialize() { |
186 InitSettings(); | 178 InitSettings(); |
187 | 179 |
188 // We clear this here (vs Shutdown) because we want to remember that an error | 180 // We clear this here (vs Shutdown) because we want to remember that an error |
189 // happened on shutdown so we can display details (message, location) about it | 181 // happened on shutdown so we can display details (message, location) about it |
190 // in about:sync. | 182 // in about:sync. |
191 ClearStaleErrors(); | 183 ClearStaleErrors(); |
192 | 184 |
193 sync_prefs_.AddSyncPrefObserver(this); | 185 sync_prefs_.AddSyncPrefObserver(this); |
194 | 186 |
195 // For now, the only thing we can do through policy is to turn sync off. | 187 // For now, the only thing we can do through policy is to turn sync off. |
196 if (IsManaged()) { | 188 if (IsManaged()) { |
197 DisableForUser(); | 189 DisableForUser(); |
198 return; | 190 return; |
199 } | 191 } |
200 | 192 |
201 RegisterAuthNotifications(); | 193 RegisterAuthNotifications(); |
202 | 194 |
203 if (!HasSyncSetupCompleted()) | 195 if (!HasSyncSetupCompleted()) |
204 DisableForUser(); // Clean up in case of previous crash / setup abort. | 196 DisableForUser(); // Clean up in case of previous crash / setup abort. |
205 | 197 |
206 TryStart(); | 198 TryStart(); |
207 } | 199 } |
208 | 200 |
209 void ProfileSyncService::TryStart() { | 201 void ProfileSyncService::TryStart() { |
210 if (!sync_prefs_.IsStartSuppressed() && AreCredentialsAvailable()) { | 202 if (!IsSyncEnabledAndLoggedIn()) |
| 203 return; |
| 204 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| 205 if (!token_service) |
| 206 return; |
| 207 // Don't start the backend if the token service hasn't finished loading tokens |
| 208 // yet (if the backend is started before the sync token has been loaded, |
| 209 // GetCredentials() will return bogus credentials). |
| 210 if (IsSyncTokenAvailable() || token_service->TokensLoadedFromDB()) { |
211 if (HasSyncSetupCompleted() || auto_start_enabled_) { | 211 if (HasSyncSetupCompleted() || auto_start_enabled_) { |
212 // If sync setup has completed we always start the backend. | 212 // If sync setup has completed we always start the backend. |
213 // If autostart is enabled, but we haven't completed sync setup, we try to | 213 // If autostart is enabled, but we haven't completed sync setup, we try to |
214 // start sync anyway, since it's possible we crashed/shutdown after | 214 // start sync anyway, since it's possible we crashed/shutdown after |
215 // logging in but before the backend finished initializing the last time. | 215 // logging in but before the backend finished initializing the last time. |
216 // Note that if we haven't finished setting up sync, backend bring up will | 216 // Note that if we haven't finished setting up sync, backend bring up will |
217 // be done by the wizard. | 217 // be done by the wizard. |
218 StartUp(); | 218 StartUp(); |
219 } | 219 } |
220 } else if (HasSyncSetupCompleted()) { | |
221 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | |
222 if (token_service && token_service->TokensLoadedFromDB() && | |
223 !AreCredentialsAvailable()) { | |
224 // The token service has lost sync's tokens. We cannot recover from this | |
225 // without signing back in, which is not yet supported. For now, we | |
226 // trigger an unrecoverable error. | |
227 OnUnrecoverableError(FROM_HERE, "Sync credentials lost."); | |
228 } | |
229 } | 220 } |
230 } | 221 } |
231 | 222 |
232 void ProfileSyncService::StartSyncingWithServer() { | 223 void ProfileSyncService::StartSyncingWithServer() { |
233 if (backend_.get()) | 224 if (backend_.get()) |
234 backend_->StartSyncingWithServer(); | 225 backend_->StartSyncingWithServer(); |
235 } | 226 } |
236 | 227 |
237 void ProfileSyncService::RegisterAuthNotifications() { | 228 void ProfileSyncService::RegisterAuthNotifications() { |
238 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 229 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 } | 296 } |
306 } | 297 } |
307 } | 298 } |
308 } | 299 } |
309 | 300 |
310 SyncCredentials ProfileSyncService::GetCredentials() { | 301 SyncCredentials ProfileSyncService::GetCredentials() { |
311 SyncCredentials credentials; | 302 SyncCredentials credentials; |
312 credentials.email = signin_->GetAuthenticatedUsername(); | 303 credentials.email = signin_->GetAuthenticatedUsername(); |
313 DCHECK(!credentials.email.empty()); | 304 DCHECK(!credentials.email.empty()); |
314 TokenService* service = TokenServiceFactory::GetForProfile(profile_); | 305 TokenService* service = TokenServiceFactory::GetForProfile(profile_); |
315 credentials.sync_token = service->GetTokenForService( | 306 if (service->HasTokenForService(GaiaConstants::kSyncService)) { |
316 GaiaConstants::kSyncService); | 307 credentials.sync_token = service->GetTokenForService( |
| 308 GaiaConstants::kSyncService); |
| 309 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", false); |
| 310 } else { |
| 311 // We've lost our sync credentials (crbug.com/121755), so just make up some |
| 312 // invalid credentials so the backend will generate an auth error. |
| 313 UMA_HISTOGRAM_BOOLEAN("Sync.CredentialsLost", true); |
| 314 credentials.sync_token = "credentials_lost"; |
| 315 } |
317 return credentials; | 316 return credentials; |
318 } | 317 } |
319 | 318 |
320 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { | 319 void ProfileSyncService::InitializeBackend(bool delete_stale_data) { |
321 if (!backend_.get()) { | 320 if (!backend_.get()) { |
322 NOTREACHED(); | 321 NOTREACHED(); |
323 return; | 322 return; |
324 } | 323 } |
325 | 324 |
326 syncable::ModelTypeSet initial_types; | 325 syncable::ModelTypeSet initial_types; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 396 } |
398 | 397 |
399 | 398 |
400 void ProfileSyncService::StartUp() { | 399 void ProfileSyncService::StartUp() { |
401 // Don't start up multiple times. | 400 // Don't start up multiple times. |
402 if (backend_.get()) { | 401 if (backend_.get()) { |
403 DVLOG(1) << "Skipping bringing up backend host."; | 402 DVLOG(1) << "Skipping bringing up backend host."; |
404 return; | 403 return; |
405 } | 404 } |
406 | 405 |
407 DCHECK(AreCredentialsAvailable()); | 406 DCHECK(IsSyncEnabledAndLoggedIn()); |
408 | 407 |
409 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); | 408 last_synced_time_ = sync_prefs_.GetLastSyncedTime(); |
410 | 409 |
411 #if defined(OS_CHROMEOS) | 410 #if defined(OS_CHROMEOS) |
412 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); | 411 std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken(); |
413 if (bootstrap_token.empty()) { | 412 if (bootstrap_token.empty()) { |
414 sync_prefs_.SetEncryptionBootstrapToken( | 413 sync_prefs_.SetEncryptionBootstrapToken( |
415 sync_prefs_.GetSpareBootstrapToken()); | 414 sync_prefs_.GetSpareBootstrapToken()); |
416 } | 415 } |
417 #endif | 416 #endif |
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 DCHECK(encrypted_types_.Has(syncable::PASSWORDS)); | 1385 DCHECK(encrypted_types_.Has(syncable::PASSWORDS)); |
1387 // We may be called during the setup process before we're | 1386 // We may be called during the setup process before we're |
1388 // initialized. In this case, we default to the sensitive types. | 1387 // initialized. In this case, we default to the sensitive types. |
1389 return encrypted_types_; | 1388 return encrypted_types_; |
1390 } | 1389 } |
1391 | 1390 |
1392 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) { | 1391 void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) { |
1393 NotifyObservers(); | 1392 NotifyObservers(); |
1394 if (is_sync_managed) { | 1393 if (is_sync_managed) { |
1395 DisableForUser(); | 1394 DisableForUser(); |
1396 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { | 1395 } else if (HasSyncSetupCompleted() && |
| 1396 IsSyncEnabledAndLoggedIn() && |
| 1397 IsSyncTokenAvailable()) { |
| 1398 // Previously-configured sync has been re-enabled, so start sync now. |
1397 StartUp(); | 1399 StartUp(); |
1398 } | 1400 } |
1399 } | 1401 } |
1400 | 1402 |
1401 void ProfileSyncService::Observe(int type, | 1403 void ProfileSyncService::Observe(int type, |
1402 const content::NotificationSource& source, | 1404 const content::NotificationSource& source, |
1403 const content::NotificationDetails& details) { | 1405 const content::NotificationDetails& details) { |
1404 switch (type) { | 1406 switch (type) { |
1405 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: | 1407 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: |
1406 case chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED: | 1408 case chrome::NOTIFICATION_SYNC_CONFIGURE_BLOCKED: |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1508 // Track the fact that we're still waiting for auth to complete. | 1510 // Track the fact that we're still waiting for auth to complete. |
1509 is_auth_in_progress_ = true; | 1511 is_auth_in_progress_ = true; |
1510 } | 1512 } |
1511 break; | 1513 break; |
1512 } | 1514 } |
1513 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { | 1515 case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { |
1514 const TokenService::TokenRequestFailedDetails& token_details = | 1516 const TokenService::TokenRequestFailedDetails& token_details = |
1515 *(content::Details<const TokenService::TokenRequestFailedDetails>( | 1517 *(content::Details<const TokenService::TokenRequestFailedDetails>( |
1516 details).ptr()); | 1518 details).ptr()); |
1517 if (IsTokenServiceRelevant(token_details.service()) && | 1519 if (IsTokenServiceRelevant(token_details.service()) && |
1518 !AreCredentialsAvailable()) { | 1520 !IsSyncTokenAvailable()) { |
1519 // The additional check around AreCredentialsAvailable above prevents us | 1521 // The additional check around IsSyncTokenAvailable() above prevents us |
1520 // sounding the alarm if we actually have a valid token but a refresh | 1522 // sounding the alarm if we actually have a valid token but a refresh |
1521 // attempt by TokenService failed for any variety of reasons (e.g. flaky | 1523 // attempt by TokenService failed for any variety of reasons (e.g. flaky |
1522 // network). It's possible the token we do have is also invalid, but in | 1524 // network). It's possible the token we do have is also invalid, but in |
1523 // that case we should already have (or can expect) an auth error sent | 1525 // that case we should already have (or can expect) an auth error sent |
1524 // from the sync backend. | 1526 // from the sync backend. |
1525 GoogleServiceAuthError error( | 1527 GoogleServiceAuthError error( |
1526 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); | 1528 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
1527 UpdateAuthErrorState(error); | 1529 UpdateAuthErrorState(error); |
1528 } | 1530 } |
1529 break; | 1531 break; |
1530 } | 1532 } |
1531 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { | 1533 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { |
1532 const TokenService::TokenAvailableDetails& token_details = | 1534 const TokenService::TokenAvailableDetails& token_details = |
1533 *(content::Details<const TokenService::TokenAvailableDetails>( | 1535 *(content::Details<const TokenService::TokenAvailableDetails>( |
1534 details).ptr()); | 1536 details).ptr()); |
1535 if (IsTokenServiceRelevant(token_details.service()) && | 1537 if (IsTokenServiceRelevant(token_details.service()) && |
1536 AreCredentialsAvailable()) { | 1538 IsSyncEnabledAndLoggedIn() && |
| 1539 IsSyncTokenAvailable()) { |
1537 if (backend_initialized_) | 1540 if (backend_initialized_) |
1538 backend_->UpdateCredentials(GetCredentials()); | 1541 backend_->UpdateCredentials(GetCredentials()); |
1539 else if (!sync_prefs_.IsStartSuppressed()) | 1542 else |
1540 StartUp(); | 1543 StartUp(); |
1541 } | 1544 } |
1542 break; | 1545 break; |
1543 } | 1546 } |
1544 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { | 1547 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { |
1545 // This notification gets fired when TokenService loads the tokens | 1548 // This notification gets fired when TokenService loads the tokens |
1546 // from storage. | 1549 // from storage. |
1547 if (AreCredentialsAvailable()) { | 1550 if (IsSyncEnabledAndLoggedIn()) { |
1548 // Initialize the backend if sync token was loaded. | 1551 // Initialize the backend if sync is enabled. If the sync token was |
1549 if (backend_initialized_) { | 1552 // not loaded, GetCredentials() will generate invalid credentials to |
| 1553 // cause the backend to generate an auth error (crbug.com/121755). |
| 1554 if (backend_initialized_) |
1550 backend_->UpdateCredentials(GetCredentials()); | 1555 backend_->UpdateCredentials(GetCredentials()); |
1551 } | 1556 else |
1552 if (!sync_prefs_.IsStartSuppressed()) | |
1553 StartUp(); | 1557 StartUp(); |
1554 } else if (!auto_start_enabled_ && | |
1555 !signin_->GetAuthenticatedUsername().empty() && | |
1556 HasSyncSetupCompleted()) { | |
1557 // If not in auto-start / Chrome OS mode, and we have a username | |
1558 // without tokens, the user will need to signin again. At the moment | |
1559 // this is not supported, so we trigger an unrecoverable error. | |
1560 OnUnrecoverableError(FROM_HERE, "Sync credentials lost."); | |
1561 } | 1558 } |
1562 break; | 1559 break; |
1563 } | 1560 } |
1564 default: { | 1561 default: { |
1565 NOTREACHED(); | 1562 NOTREACHED(); |
1566 } | 1563 } |
1567 } | 1564 } |
1568 } | 1565 } |
1569 | 1566 |
1570 void ProfileSyncService::AddObserver(Observer* observer) { | 1567 void ProfileSyncService::AddObserver(Observer* observer) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine
d-behaviour-after-directly-calling-the-destru. | 1664 // See http://stackoverflow.com/questions/6224121/is-new-this-myclass-undefine
d-behaviour-after-directly-calling-the-destru. |
1668 ProfileSyncService* old_this = this; | 1665 ProfileSyncService* old_this = this; |
1669 this->~ProfileSyncService(); | 1666 this->~ProfileSyncService(); |
1670 new(old_this) ProfileSyncService( | 1667 new(old_this) ProfileSyncService( |
1671 new ProfileSyncComponentsFactoryImpl(profile, | 1668 new ProfileSyncComponentsFactoryImpl(profile, |
1672 CommandLine::ForCurrentProcess()), | 1669 CommandLine::ForCurrentProcess()), |
1673 profile, | 1670 profile, |
1674 signin, | 1671 signin, |
1675 behavior); | 1672 behavior); |
1676 } | 1673 } |
OLD | NEW |