| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <ostream> | 9 #include <ostream> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 types, | 369 types, |
| 370 credentials, | 370 credentials, |
| 371 delete_sync_data_folder); | 371 delete_sync_data_folder); |
| 372 } | 372 } |
| 373 | 373 |
| 374 void ProfileSyncService::CreateBackend() { | 374 void ProfileSyncService::CreateBackend() { |
| 375 backend_.reset(new SyncBackendHost(profile_)); | 375 backend_.reset(new SyncBackendHost(profile_)); |
| 376 } | 376 } |
| 377 | 377 |
| 378 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { | 378 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { |
| 379 if (HasPendingEncryptedTypes()) |
| 380 return true; |
| 379 syncable::ModelTypeSet preferred_types; | 381 syncable::ModelTypeSet preferred_types; |
| 380 GetPreferredDataTypes(&preferred_types); | 382 GetPreferredDataTypes(&preferred_types); |
| 381 syncable::ModelTypeSet encrypted_types; | 383 syncable::ModelTypeSet encrypted_types; |
| 382 GetEncryptedDataTypes(&encrypted_types); | 384 GetEncryptedDataTypes(&encrypted_types); |
| 383 syncable::ModelTypeBitSet preferred_types_bitset = | 385 syncable::ModelTypeBitSet preferred_types_bitset = |
| 384 syncable::ModelTypeBitSetFromSet(preferred_types); | 386 syncable::ModelTypeBitSetFromSet(preferred_types); |
| 385 syncable::ModelTypeBitSet encrypted_types_bitset = | 387 syncable::ModelTypeBitSet encrypted_types_bitset = |
| 386 syncable::ModelTypeBitSetFromSet(encrypted_types); | 388 syncable::ModelTypeBitSetFromSet(encrypted_types); |
| 387 DCHECK(encrypted_types.count(syncable::PASSWORDS)); | 389 DCHECK(encrypted_types.count(syncable::PASSWORDS)); |
| 388 return (preferred_types_bitset & encrypted_types_bitset).any(); | 390 return (preferred_types_bitset & encrypted_types_bitset).any(); |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 if (unrecoverable_error_detected_) { | 686 if (unrecoverable_error_detected_) { |
| 685 // When unrecoverable error is detected we post a task to shutdown the | 687 // When unrecoverable error is detected we post a task to shutdown the |
| 686 // backend. The task might not have executed yet. | 688 // backend. The task might not have executed yet. |
| 687 return; | 689 return; |
| 688 } | 690 } |
| 689 | 691 |
| 690 VLOG(1) << "Passphrase required with reason: " | 692 VLOG(1) << "Passphrase required with reason: " |
| 691 << sync_api::PassphraseRequiredReasonToString(reason); | 693 << sync_api::PassphraseRequiredReasonToString(reason); |
| 692 passphrase_required_reason_ = reason; | 694 passphrase_required_reason_ = reason; |
| 693 | 695 |
| 696 // Store any passphrases we have into temps and clear out the originals so |
| 697 // we don't hold on to the passphrases any longer than we have to. We |
| 698 // then use the passphrases if they're present (after OnPassphraseAccepted). |
| 699 std::string gaia_password = gaia_password_; |
| 700 std::string cached_passphrase = cached_passphrase_.value; |
| 701 bool is_explicit = cached_passphrase_.is_explicit; |
| 702 bool is_creation = cached_passphrase_.is_creation; |
| 703 gaia_password_ = std::string(); |
| 704 cached_passphrase_ = CachedPassphrase(); |
| 705 |
| 694 // We will skip the passphrase prompt and suppress the warning if the | 706 // We will skip the passphrase prompt and suppress the warning if the |
| 695 // passphrase is needed for decryption but the user is not syncing an | 707 // passphrase is needed for decryption but the user is not syncing an |
| 696 // encrypted data type on this machine. Otherwise we look for one. | 708 // encrypted data type on this machine. Otherwise we look for one. |
| 697 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) { | 709 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) { |
| 698 VLOG(1) << "Not decrypting and no encrypted datatypes enabled" | 710 VLOG(1) << "Decrypting and no encrypted datatypes enabled" |
| 699 << ", accepted passphrase."; | 711 << ", accepted passphrase."; |
| 700 OnPassphraseAccepted(); | 712 OnPassphraseAccepted(); |
| 701 } | 713 } |
| 702 | 714 |
| 703 // First try supplying gaia password as the passphrase. | 715 // First try supplying gaia password as the passphrase. |
| 704 if (!gaia_password_.empty()) { | 716 if (!gaia_password.empty()) { |
| 705 VLOG(1) << "Attempting gaia passphrase."; | 717 VLOG(1) << "Attempting gaia passphrase."; |
| 706 SetPassphrase(gaia_password_, false, true); | 718 // SetPassphrase will set gaia_password_ if the syncer isn't ready. |
| 707 gaia_password_ = std::string(); | 719 SetPassphrase(gaia_password, false, true); |
| 708 return; | 720 return; |
| 709 } | 721 } |
| 710 | 722 |
| 711 // If the above failed then try the custom passphrase the user might have | 723 // If the above failed then try the custom passphrase the user might have |
| 712 // entered in setup. | 724 // entered in setup. |
| 713 if (!cached_passphrase_.value.empty()) { | 725 if (!cached_passphrase.empty()) { |
| 714 VLOG(1) << "Attempting cached passphrase."; | 726 VLOG(1) << "Attempting cached passphrase."; |
| 715 SetPassphrase(cached_passphrase_.value, | 727 // SetPassphrase will set cached_passphrase_ if the syncer isn't ready. |
| 716 cached_passphrase_.is_explicit, | 728 SetPassphrase(cached_passphrase, is_explicit, is_creation); |
| 717 cached_passphrase_.is_creation); | |
| 718 cached_passphrase_ = CachedPassphrase(); | |
| 719 return; | 729 return; |
| 720 } | 730 } |
| 721 | 731 |
| 722 // Prompt the user for a password. | 732 // Prompt the user for a password. |
| 723 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() && | 733 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() && |
| 724 IsPassphraseRequiredForDecryption()) { | 734 IsPassphraseRequiredForDecryption()) { |
| 725 VLOG(1) << "Prompting user for passphrase."; | 735 VLOG(1) << "Prompting user for passphrase."; |
| 726 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE); | 736 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE); |
| 727 } | 737 } |
| 728 | 738 |
| 729 NotifyObservers(); | 739 NotifyObservers(); |
| 730 } | 740 } |
| 731 | 741 |
| 732 void ProfileSyncService::OnPassphraseAccepted() { | 742 void ProfileSyncService::OnPassphraseAccepted() { |
| 733 VLOG(1) << "Received OnPassphraseAccepted."; | 743 VLOG(1) << "Received OnPassphraseAccepted."; |
| 744 // Don't hold on to a passphrase in raw form longer than needed. |
| 745 gaia_password_ = std::string(); |
| 746 cached_passphrase_ = CachedPassphrase(); |
| 747 |
| 734 // Make sure the data types that depend on the passphrase are started at | 748 // Make sure the data types that depend on the passphrase are started at |
| 735 // this time. | 749 // this time. |
| 736 syncable::ModelTypeSet types; | 750 syncable::ModelTypeSet types; |
| 737 GetPreferredDataTypes(&types); | 751 GetPreferredDataTypes(&types); |
| 738 | 752 |
| 739 // Reset passphrase_required_reason_ before configuring the DataTypeManager | 753 // Reset passphrase_required_reason_ before configuring the DataTypeManager |
| 740 // since we know we no longer require the passphrase. | 754 // since we know we no longer require the passphrase. |
| 741 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED; | 755 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED; |
| 742 | 756 |
| 743 if (data_type_manager_.get()) { | 757 if (data_type_manager_.get()) { |
| 744 // Unblock the data type manager if necessary. | 758 // Unblock the data type manager if necessary. |
| 745 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will | 759 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will |
| 746 // step the UI wizard into DONE state (even if no datatypes have changed). | 760 // step the UI wizard into DONE state (even if no datatypes have changed). |
| 747 data_type_manager_->Configure(types, | 761 data_type_manager_->Configure(types, |
| 748 sync_api::CONFIGURE_REASON_RECONFIGURATION); | 762 sync_api::CONFIGURE_REASON_RECONFIGURATION); |
| 749 } | 763 } |
| 750 | 764 |
| 751 NotifyObservers(); | 765 NotifyObservers(); |
| 752 } | 766 } |
| 753 | 767 |
| 754 void ProfileSyncService::OnEncryptionComplete( | 768 void ProfileSyncService::OnEncryptionComplete( |
| 755 const syncable::ModelTypeSet& encrypted_types) { | 769 const syncable::ModelTypeSet& encrypted_types) { |
| 770 if (!pending_types_for_encryption_.empty()) { |
| 771 // The user had chosen to encrypt datatypes. This is the last thing to |
| 772 // complete, so now that we're done notify the UI. |
| 773 wizard_.Step(SyncSetupWizard::DONE); |
| 774 } |
| 775 pending_types_for_encryption_.clear(); |
| 756 NotifyObservers(); | 776 NotifyObservers(); |
| 757 } | 777 } |
| 758 | 778 |
| 759 void ProfileSyncService::OnMigrationNeededForTypes( | 779 void ProfileSyncService::OnMigrationNeededForTypes( |
| 760 const syncable::ModelTypeSet& types) { | 780 const syncable::ModelTypeSet& types) { |
| 761 DCHECK(backend_initialized_); | 781 DCHECK(backend_initialized_); |
| 762 DCHECK(data_type_manager_.get()); | 782 DCHECK(data_type_manager_.get()); |
| 763 | 783 |
| 764 // Migrator must be valid, because we don't sync until it is created and this | 784 // Migrator must be valid, because we don't sync until it is created and this |
| 765 // callback originates from a sync cycle. | 785 // callback originates from a sync cycle. |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 if (!backend_.get()) | 1195 if (!backend_.get()) |
| 1176 return; | 1196 return; |
| 1177 backend_->DeactivateDataType(data_type_controller, change_processor); | 1197 backend_->DeactivateDataType(data_type_controller, change_processor); |
| 1178 } | 1198 } |
| 1179 | 1199 |
| 1180 void ProfileSyncService::SetPassphrase(const std::string& passphrase, | 1200 void ProfileSyncService::SetPassphrase(const std::string& passphrase, |
| 1181 bool is_explicit, | 1201 bool is_explicit, |
| 1182 bool is_creation) { | 1202 bool is_creation) { |
| 1183 if (ShouldPushChanges() || IsPassphraseRequired()) { | 1203 if (ShouldPushChanges() || IsPassphraseRequired()) { |
| 1184 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit") | 1204 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit") |
| 1185 << " passphrase " << (is_creation ? " for creation" : ""); | 1205 << " passphrase" << (is_creation ? " for creation" : ""); |
| 1186 backend_->SetPassphrase(passphrase, is_explicit); | 1206 backend_->SetPassphrase(passphrase, is_explicit); |
| 1187 } else { | 1207 } else { |
| 1188 if (is_explicit) { | 1208 if (is_explicit) { |
| 1189 cached_passphrase_.value = passphrase; | 1209 cached_passphrase_.value = passphrase; |
| 1190 cached_passphrase_.is_explicit = is_explicit; | 1210 cached_passphrase_.is_explicit = is_explicit; |
| 1191 cached_passphrase_.is_creation = is_creation; | 1211 cached_passphrase_.is_creation = is_creation; |
| 1192 } else { | 1212 } else { |
| 1193 gaia_password_ = passphrase; | 1213 gaia_password_ = passphrase; |
| 1194 } | 1214 } |
| 1195 } | 1215 } |
| 1196 } | 1216 } |
| 1197 | 1217 |
| 1198 void ProfileSyncService::EncryptDataTypes( | 1218 void ProfileSyncService::set_pending_types_for_encryption( |
| 1199 const syncable::ModelTypeSet& encrypted_types) { | 1219 const syncable::ModelTypeSet& encrypted_types) { |
| 1200 if (HasSyncSetupCompleted()) { | 1220 if (encrypted_types.empty()) { |
| 1201 backend_->EncryptDataTypes(encrypted_types); | 1221 // We can't unencrypt types. |
| 1222 VLOG(1) << "No datatypes set for encryption, dropping encryption request."; |
| 1202 pending_types_for_encryption_.clear(); | 1223 pending_types_for_encryption_.clear(); |
| 1203 } else { | 1224 return; |
| 1204 pending_types_for_encryption_ = encrypted_types; | |
| 1205 } | 1225 } |
| 1226 // Setting the pending types for encryption doesn't actually trigger |
| 1227 // encryption. The actual encryption will occur after the datatype manager |
| 1228 // is reconfigured. |
| 1229 pending_types_for_encryption_ = encrypted_types; |
| 1206 } | 1230 } |
| 1207 | 1231 |
| 1208 // This would open a transaction to get the encrypted types. Do not call this | 1232 // This will open a transaction to get the encrypted types. Do not call this |
| 1209 // if you already have a transaction open. | 1233 // if you already have a transaction open. |
| 1210 void ProfileSyncService::GetEncryptedDataTypes( | 1234 void ProfileSyncService::GetEncryptedDataTypes( |
| 1211 syncable::ModelTypeSet* encrypted_types) const { | 1235 syncable::ModelTypeSet* encrypted_types) const { |
| 1212 CHECK(encrypted_types); | 1236 CHECK(encrypted_types); |
| 1213 if (backend_.get()) { | 1237 if (backend_.get()) { |
| 1214 *encrypted_types = backend_->GetEncryptedDataTypes(); | 1238 *encrypted_types = backend_->GetEncryptedDataTypes(); |
| 1215 DCHECK(encrypted_types->count(syncable::PASSWORDS)); | 1239 DCHECK(encrypted_types->count(syncable::PASSWORDS)); |
| 1216 } else { | 1240 } else { |
| 1217 // Either we are in an unrecoverable error or the sync is not yet done | 1241 // Either we are in an unrecoverable error or the sync is not yet done |
| 1218 // initializing. In either case just return the password type. During | 1242 // initializing. In either case just return the password type. During |
| 1219 // sync initialization the UI might need to know what our encrypted | 1243 // sync initialization the UI might need to know what our encrypted |
| 1220 // types are. | 1244 // types are. |
| 1221 (*encrypted_types).insert(syncable::PASSWORDS); | 1245 (*encrypted_types).insert(syncable::PASSWORDS); |
| 1222 } | 1246 } |
| 1223 } | 1247 } |
| 1224 | 1248 |
| 1249 bool ProfileSyncService::HasPendingEncryptedTypes() const { |
| 1250 return !pending_types_for_encryption_.empty(); |
| 1251 } |
| 1252 |
| 1225 void ProfileSyncService::Observe(int type, | 1253 void ProfileSyncService::Observe(int type, |
| 1226 const NotificationSource& source, | 1254 const NotificationSource& source, |
| 1227 const NotificationDetails& details) { | 1255 const NotificationDetails& details) { |
| 1228 switch (type) { | 1256 switch (type) { |
| 1229 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: { | 1257 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: { |
| 1230 NotifyObservers(); | 1258 NotifyObservers(); |
| 1231 // TODO(sync): Maybe toast? | 1259 // TODO(sync): Maybe toast? |
| 1232 break; | 1260 break; |
| 1233 } | 1261 } |
| 1234 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: { | 1262 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: { |
| 1235 DataTypeManager::ConfigureResult* result = | 1263 DataTypeManager::ConfigureResult* result = |
| 1236 Details<DataTypeManager::ConfigureResult>(details).ptr(); | 1264 Details<DataTypeManager::ConfigureResult>(details).ptr(); |
| 1237 | 1265 |
| 1238 DataTypeManager::ConfigureStatus status = result->status; | 1266 DataTypeManager::ConfigureStatus status = result->status; |
| 1239 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with status: " << status; | 1267 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with status: " << status; |
| 1240 if (status == DataTypeManager::ABORTED && | 1268 if (status == DataTypeManager::ABORTED && |
| 1241 expect_sync_configuration_aborted_) { | 1269 expect_sync_configuration_aborted_) { |
| 1242 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted"; | 1270 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted"; |
| 1243 expect_sync_configuration_aborted_ = false; | 1271 expect_sync_configuration_aborted_ = false; |
| 1244 return; | 1272 return; |
| 1245 } | 1273 } |
| 1246 // Clear out the gaia password if it is already there. | |
| 1247 gaia_password_ = std::string(); | |
| 1248 if (status != DataTypeManager::OK) { | 1274 if (status != DataTypeManager::OK) { |
| 1249 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected"; | 1275 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected"; |
| 1250 std::string message = | 1276 std::string message = |
| 1251 "Sync Configuration failed while configuring " + | 1277 "Sync Configuration failed while configuring " + |
| 1252 syncable::ModelTypeSetToString(result->failed_types) + | 1278 syncable::ModelTypeSetToString(result->failed_types) + |
| 1253 ": " + DataTypeManager::ConfigureStatusToString(status); | 1279 ": " + DataTypeManager::ConfigureStatusToString(status); |
| 1254 OnUnrecoverableError(result->location, message); | 1280 OnUnrecoverableError(result->location, message); |
| 1255 cached_passphrase_ = CachedPassphrase(); | 1281 cached_passphrase_ = CachedPassphrase(); |
| 1256 return; | 1282 return; |
| 1257 } | 1283 } |
| 1258 | 1284 |
| 1259 // If the user had entered a custom passphrase use it now. | |
| 1260 if (!cached_passphrase_.value.empty()) { | |
| 1261 // Don't hold on to the passphrase in raw form longer than needed. | |
| 1262 SetPassphrase(cached_passphrase_.value, | |
| 1263 cached_passphrase_.is_explicit, | |
| 1264 cached_passphrase_.is_creation); | |
| 1265 cached_passphrase_ = CachedPassphrase(); | |
| 1266 } | |
| 1267 | |
| 1268 // We should never get in a state where we have no encrypted datatypes | 1285 // We should never get in a state where we have no encrypted datatypes |
| 1269 // enabled, and yet we still think we require a passphrase for decryption. | 1286 // enabled, and yet we still think we require a passphrase for decryption. |
| 1270 DCHECK(!(IsPassphraseRequiredForDecryption() && | 1287 DCHECK(!(IsPassphraseRequiredForDecryption() && |
| 1271 !IsEncryptedDatatypeEnabled())); | 1288 !IsEncryptedDatatypeEnabled())); |
| 1272 | 1289 |
| 1273 // TODO(sync): Less wizard, more toast. | |
| 1274 wizard_.Step(SyncSetupWizard::DONE); | |
| 1275 NotifyObservers(); | |
| 1276 | |
| 1277 // In the old world, this would be a no-op. With new syncer thread, | 1290 // In the old world, this would be a no-op. With new syncer thread, |
| 1278 // this is the point where it is safe to switch from config-mode to | 1291 // this is the point where it is safe to switch from config-mode to |
| 1279 // normal operation. | 1292 // normal operation. |
| 1280 backend_->StartSyncingWithServer(); | 1293 backend_->StartSyncingWithServer(); |
| 1281 | 1294 |
| 1282 if (!pending_types_for_encryption_.empty()) { | 1295 if (pending_types_for_encryption_.empty()) { |
| 1283 EncryptDataTypes(pending_types_for_encryption_); | 1296 wizard_.Step(SyncSetupWizard::DONE); |
| 1284 pending_types_for_encryption_.clear(); | 1297 NotifyObservers(); |
| 1298 } else { |
| 1299 // Will clear pending_types_for_encryption_ on success (via |
| 1300 // OnEncryptionComplete). Has no effect if pending_types_for_encryption_ |
| 1301 // matches the encrypted types (and will clear |
| 1302 // pending_types_for_encryption_). |
| 1303 backend_->EncryptDataTypes(pending_types_for_encryption_); |
| 1285 } | 1304 } |
| 1286 break; | 1305 break; |
| 1287 } | 1306 } |
| 1288 case chrome::NOTIFICATION_PREF_CHANGED: { | 1307 case chrome::NOTIFICATION_PREF_CHANGED: { |
| 1289 std::string* pref_name = Details<std::string>(details).ptr(); | 1308 std::string* pref_name = Details<std::string>(details).ptr(); |
| 1290 if (*pref_name == prefs::kSyncManaged) { | 1309 if (*pref_name == prefs::kSyncManaged) { |
| 1291 NotifyObservers(); | 1310 NotifyObservers(); |
| 1292 if (*pref_sync_managed_) { | 1311 if (*pref_sync_managed_) { |
| 1293 DisableForUser(); | 1312 DisableForUser(); |
| 1294 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { | 1313 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 // is initialized, all enabled data types are consistent with one | 1403 // is initialized, all enabled data types are consistent with one |
| 1385 // another, and no unrecoverable error has transpired. | 1404 // another, and no unrecoverable error has transpired. |
| 1386 if (unrecoverable_error_detected_) | 1405 if (unrecoverable_error_detected_) |
| 1387 return false; | 1406 return false; |
| 1388 | 1407 |
| 1389 if (!data_type_manager_.get()) | 1408 if (!data_type_manager_.get()) |
| 1390 return false; | 1409 return false; |
| 1391 | 1410 |
| 1392 return data_type_manager_->state() == DataTypeManager::CONFIGURED; | 1411 return data_type_manager_->state() == DataTypeManager::CONFIGURED; |
| 1393 } | 1412 } |
| OLD | NEW |