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

Side by Side Diff: chrome/browser/sync/profile_sync_service.cc

Issue 7583032: Merge 95693 - [Sync] Fix encryption/passphrase handling. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/835/src/
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 types, 368 types,
369 credentials, 369 credentials,
370 delete_sync_data_folder); 370 delete_sync_data_folder);
371 } 371 }
372 372
373 void ProfileSyncService::CreateBackend() { 373 void ProfileSyncService::CreateBackend() {
374 backend_.reset(new SyncBackendHost(profile_)); 374 backend_.reset(new SyncBackendHost(profile_));
375 } 375 }
376 376
377 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { 377 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
378 if (HasPendingEncryptedTypes())
379 return true;
378 syncable::ModelTypeSet preferred_types; 380 syncable::ModelTypeSet preferred_types;
379 GetPreferredDataTypes(&preferred_types); 381 GetPreferredDataTypes(&preferred_types);
380 syncable::ModelTypeSet encrypted_types; 382 syncable::ModelTypeSet encrypted_types;
381 GetEncryptedDataTypes(&encrypted_types); 383 GetEncryptedDataTypes(&encrypted_types);
382 syncable::ModelTypeBitSet preferred_types_bitset = 384 syncable::ModelTypeBitSet preferred_types_bitset =
383 syncable::ModelTypeBitSetFromSet(preferred_types); 385 syncable::ModelTypeBitSetFromSet(preferred_types);
384 syncable::ModelTypeBitSet encrypted_types_bitset = 386 syncable::ModelTypeBitSet encrypted_types_bitset =
385 syncable::ModelTypeBitSetFromSet(encrypted_types); 387 syncable::ModelTypeBitSetFromSet(encrypted_types);
386 DCHECK(encrypted_types.count(syncable::PASSWORDS)); 388 DCHECK(encrypted_types.count(syncable::PASSWORDS));
387 return (preferred_types_bitset & encrypted_types_bitset).any(); 389 return (preferred_types_bitset & encrypted_types_bitset).any();
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 if (unrecoverable_error_detected_) { 737 if (unrecoverable_error_detected_) {
736 // When unrecoverable error is detected we post a task to shutdown the 738 // When unrecoverable error is detected we post a task to shutdown the
737 // backend. The task might not have executed yet. 739 // backend. The task might not have executed yet.
738 return; 740 return;
739 } 741 }
740 742
741 VLOG(1) << "Passphrase required with reason: " 743 VLOG(1) << "Passphrase required with reason: "
742 << sync_api::PassphraseRequiredReasonToString(reason); 744 << sync_api::PassphraseRequiredReasonToString(reason);
743 passphrase_required_reason_ = reason; 745 passphrase_required_reason_ = reason;
744 746
747 // Store any passphrases we have into temps and clear out the originals so
748 // we don't hold on to the passphrases any longer than we have to. We
749 // then use the passphrases if they're present (after OnPassphraseAccepted).
750 std::string gaia_password = gaia_password_;
751 std::string cached_passphrase = cached_passphrase_.value;
752 bool is_explicit = cached_passphrase_.is_explicit;
753 bool is_creation = cached_passphrase_.is_creation;
754 gaia_password_ = std::string();
755 cached_passphrase_ = CachedPassphrase();
756
745 // We will skip the passphrase prompt and suppress the warning if the 757 // We will skip the passphrase prompt and suppress the warning if the
746 // passphrase is needed for decryption but the user is not syncing an 758 // passphrase is needed for decryption but the user is not syncing an
747 // encrypted data type on this machine. Otherwise we look for one. 759 // encrypted data type on this machine. Otherwise we look for one.
748 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) { 760 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) {
749 VLOG(1) << "Not decrypting and no encrypted datatypes enabled" 761 VLOG(1) << "Decrypting and no encrypted datatypes enabled"
750 << ", accepted passphrase."; 762 << ", accepted passphrase.";
751 OnPassphraseAccepted(); 763 OnPassphraseAccepted();
752 } 764 }
753 765
754 // First try supplying gaia password as the passphrase. 766 // First try supplying gaia password as the passphrase.
755 if (!gaia_password_.empty()) { 767 if (!gaia_password.empty()) {
756 VLOG(1) << "Attempting gaia passphrase."; 768 VLOG(1) << "Attempting gaia passphrase.";
757 SetPassphrase(gaia_password_, false, true); 769 // SetPassphrase will set gaia_password_ if the syncer isn't ready.
758 gaia_password_ = std::string(); 770 SetPassphrase(gaia_password, false, true);
759 return; 771 return;
760 } 772 }
761 773
762 // If the above failed then try the custom passphrase the user might have 774 // If the above failed then try the custom passphrase the user might have
763 // entered in setup. 775 // entered in setup.
764 if (!cached_passphrase_.value.empty()) { 776 if (!cached_passphrase.empty()) {
765 VLOG(1) << "Attempting cached passphrase."; 777 VLOG(1) << "Attempting cached passphrase.";
766 SetPassphrase(cached_passphrase_.value, 778 // SetPassphrase will set cached_passphrase_ if the syncer isn't ready.
767 cached_passphrase_.is_explicit, 779 SetPassphrase(cached_passphrase, is_explicit, is_creation);
768 cached_passphrase_.is_creation);
769 cached_passphrase_ = CachedPassphrase();
770 return; 780 return;
771 } 781 }
772 782
773 // Prompt the user for a password. 783 // Prompt the user for a password.
774 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() && 784 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() &&
775 IsPassphraseRequiredForDecryption()) { 785 IsPassphraseRequiredForDecryption()) {
776 VLOG(1) << "Prompting user for passphrase."; 786 VLOG(1) << "Prompting user for passphrase.";
777 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE); 787 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE);
778 } 788 }
779 789
780 NotifyObservers(); 790 NotifyObservers();
781 } 791 }
782 792
783 void ProfileSyncService::OnPassphraseAccepted() { 793 void ProfileSyncService::OnPassphraseAccepted() {
784 VLOG(1) << "Received OnPassphraseAccepted."; 794 VLOG(1) << "Received OnPassphraseAccepted.";
795 // Don't hold on to a passphrase in raw form longer than needed.
796 gaia_password_ = std::string();
797 cached_passphrase_ = CachedPassphrase();
798
785 // Make sure the data types that depend on the passphrase are started at 799 // Make sure the data types that depend on the passphrase are started at
786 // this time. 800 // this time.
787 syncable::ModelTypeSet types; 801 syncable::ModelTypeSet types;
788 GetPreferredDataTypes(&types); 802 GetPreferredDataTypes(&types);
789 803
790 // Reset passphrase_required_reason_ before configuring the DataTypeManager 804 // Reset passphrase_required_reason_ before configuring the DataTypeManager
791 // since we know we no longer require the passphrase. 805 // since we know we no longer require the passphrase.
792 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED; 806 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED;
793 807
794 if (data_type_manager_.get()) { 808 if (data_type_manager_.get()) {
795 // Unblock the data type manager if necessary. 809 // Unblock the data type manager if necessary.
796 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will 810 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will
797 // step the UI wizard into DONE state (even if no datatypes have changed). 811 // step the UI wizard into DONE state (even if no datatypes have changed).
798 data_type_manager_->Configure(types, 812 data_type_manager_->Configure(types,
799 sync_api::CONFIGURE_REASON_RECONFIGURATION); 813 sync_api::CONFIGURE_REASON_RECONFIGURATION);
800 } 814 }
801 815
802 NotifyObservers(); 816 NotifyObservers();
803 } 817 }
804 818
805 void ProfileSyncService::OnEncryptionComplete( 819 void ProfileSyncService::OnEncryptionComplete(
806 const syncable::ModelTypeSet& encrypted_types) { 820 const syncable::ModelTypeSet& encrypted_types) {
821 if (!pending_types_for_encryption_.empty()) {
822 // The user had chosen to encrypt datatypes. This is the last thing to
823 // complete, so now that we're done notify the UI.
824 wizard_.Step(SyncSetupWizard::DONE);
825 }
826 pending_types_for_encryption_.clear();
807 NotifyObservers(); 827 NotifyObservers();
808 } 828 }
809 829
810 void ProfileSyncService::OnMigrationNeededForTypes( 830 void ProfileSyncService::OnMigrationNeededForTypes(
811 const syncable::ModelTypeSet& types) { 831 const syncable::ModelTypeSet& types) {
812 DCHECK(backend_initialized_); 832 DCHECK(backend_initialized_);
813 DCHECK(data_type_manager_.get()); 833 DCHECK(data_type_manager_.get());
814 834
815 // Migrator must be valid, because we don't sync until it is created and this 835 // Migrator must be valid, because we don't sync until it is created and this
816 // callback originates from a sync cycle. 836 // callback originates from a sync cycle.
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 if (!backend_.get()) 1234 if (!backend_.get())
1215 return; 1235 return;
1216 backend_->DeactivateDataType(data_type_controller, change_processor); 1236 backend_->DeactivateDataType(data_type_controller, change_processor);
1217 } 1237 }
1218 1238
1219 void ProfileSyncService::SetPassphrase(const std::string& passphrase, 1239 void ProfileSyncService::SetPassphrase(const std::string& passphrase,
1220 bool is_explicit, 1240 bool is_explicit,
1221 bool is_creation) { 1241 bool is_creation) {
1222 if (ShouldPushChanges() || IsPassphraseRequired()) { 1242 if (ShouldPushChanges() || IsPassphraseRequired()) {
1223 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit") 1243 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit")
1224 << " passphrase " << (is_creation ? " for creation" : ""); 1244 << " passphrase" << (is_creation ? " for creation" : "");
1225 backend_->SetPassphrase(passphrase, is_explicit); 1245 backend_->SetPassphrase(passphrase, is_explicit);
1226 } else { 1246 } else {
1227 if (is_explicit) { 1247 if (is_explicit) {
1228 cached_passphrase_.value = passphrase; 1248 cached_passphrase_.value = passphrase;
1229 cached_passphrase_.is_explicit = is_explicit; 1249 cached_passphrase_.is_explicit = is_explicit;
1230 cached_passphrase_.is_creation = is_creation; 1250 cached_passphrase_.is_creation = is_creation;
1231 } else { 1251 } else {
1232 gaia_password_ = passphrase; 1252 gaia_password_ = passphrase;
1233 } 1253 }
1234 } 1254 }
1235 } 1255 }
1236 1256
1237 void ProfileSyncService::EncryptDataTypes( 1257 void ProfileSyncService::set_pending_types_for_encryption(
1238 const syncable::ModelTypeSet& encrypted_types) { 1258 const syncable::ModelTypeSet& encrypted_types) {
1239 if (HasSyncSetupCompleted()) { 1259 if (encrypted_types.empty()) {
1240 backend_->EncryptDataTypes(encrypted_types); 1260 // We can't unencrypt types.
1261 VLOG(1) << "No datatypes set for encryption, dropping encryption request.";
1241 pending_types_for_encryption_.clear(); 1262 pending_types_for_encryption_.clear();
1242 } else { 1263 return;
1243 pending_types_for_encryption_ = encrypted_types;
1244 } 1264 }
1265 // Setting the pending types for encryption doesn't actually trigger
1266 // encryption. The actual encryption will occur after the datatype manager
1267 // is reconfigured.
1268 pending_types_for_encryption_ = encrypted_types;
1245 } 1269 }
1246 1270
1247 // This would open a transaction to get the encrypted types. Do not call this 1271 // This will open a transaction to get the encrypted types. Do not call this
1248 // if you already have a transaction open. 1272 // if you already have a transaction open.
1249 void ProfileSyncService::GetEncryptedDataTypes( 1273 void ProfileSyncService::GetEncryptedDataTypes(
1250 syncable::ModelTypeSet* encrypted_types) const { 1274 syncable::ModelTypeSet* encrypted_types) const {
1251 CHECK(encrypted_types); 1275 CHECK(encrypted_types);
1252 if (backend_.get()) { 1276 if (backend_.get()) {
1253 *encrypted_types = backend_->GetEncryptedDataTypes(); 1277 *encrypted_types = backend_->GetEncryptedDataTypes();
1254 DCHECK(encrypted_types->count(syncable::PASSWORDS)); 1278 DCHECK(encrypted_types->count(syncable::PASSWORDS));
1255 } else { 1279 } else {
1256 // Either we are in an unrecoverable error or the sync is not yet done 1280 // Either we are in an unrecoverable error or the sync is not yet done
1257 // initializing. In either case just return the password type. During 1281 // initializing. In either case just return the password type. During
1258 // sync initialization the UI might need to know what our encrypted 1282 // sync initialization the UI might need to know what our encrypted
1259 // types are. 1283 // types are.
1260 (*encrypted_types).insert(syncable::PASSWORDS); 1284 (*encrypted_types).insert(syncable::PASSWORDS);
1261 } 1285 }
1262 } 1286 }
1263 1287
1288 bool ProfileSyncService::HasPendingEncryptedTypes() const {
1289 return !pending_types_for_encryption_.empty();
1290 }
1291
1264 void ProfileSyncService::Observe(int type, 1292 void ProfileSyncService::Observe(int type,
1265 const NotificationSource& source, 1293 const NotificationSource& source,
1266 const NotificationDetails& details) { 1294 const NotificationDetails& details) {
1267 switch (type) { 1295 switch (type) {
1268 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: { 1296 case chrome::NOTIFICATION_SYNC_CONFIGURE_START: {
1269 NotifyObservers(); 1297 NotifyObservers();
1270 // TODO(sync): Maybe toast? 1298 // TODO(sync): Maybe toast?
1271 break; 1299 break;
1272 } 1300 }
1273 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: { 1301 case chrome::NOTIFICATION_SYNC_CONFIGURE_DONE: {
1274 DataTypeManager::ConfigureResultWithErrorLocation* result_with_location = 1302 DataTypeManager::ConfigureResultWithErrorLocation* result_with_location =
1275 Details<DataTypeManager::ConfigureResultWithErrorLocation>( 1303 Details<DataTypeManager::ConfigureResultWithErrorLocation>(
1276 details).ptr(); 1304 details).ptr();
1277 1305
1278 DataTypeManager::ConfigureResult result = result_with_location->result; 1306 DataTypeManager::ConfigureResult result = result_with_location->result;
1279 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with result: " << result; 1307 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with result: " << result;
1280 if (result == DataTypeManager::ABORTED && 1308 if (result == DataTypeManager::ABORTED &&
1281 expect_sync_configuration_aborted_) { 1309 expect_sync_configuration_aborted_) {
1282 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted"; 1310 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
1283 expect_sync_configuration_aborted_ = false; 1311 expect_sync_configuration_aborted_ = false;
1284 return; 1312 return;
1285 } 1313 }
1286 // Clear out the gaia password if it is already there.
1287 gaia_password_ = std::string();
1288 if (result != DataTypeManager::OK) { 1314 if (result != DataTypeManager::OK) {
1289 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected"; 1315 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected";
1290 std::string message = StringPrintf("Sync Configuration failed with %d", 1316 std::string message = StringPrintf("Sync Configuration failed with %d",
1291 result); 1317 result);
1292 OnUnrecoverableError(*(result_with_location->location), message); 1318 OnUnrecoverableError(*(result_with_location->location), message);
1293 cached_passphrase_ = CachedPassphrase(); 1319 cached_passphrase_ = CachedPassphrase();
1294 return; 1320 return;
1295 } 1321 }
1296 1322
1297 // If the user had entered a custom passphrase use it now.
1298 if (!cached_passphrase_.value.empty()) {
1299 // Don't hold on to the passphrase in raw form longer than needed.
1300 SetPassphrase(cached_passphrase_.value,
1301 cached_passphrase_.is_explicit,
1302 cached_passphrase_.is_creation);
1303 cached_passphrase_ = CachedPassphrase();
1304 }
1305
1306 // We should never get in a state where we have no encrypted datatypes 1323 // We should never get in a state where we have no encrypted datatypes
1307 // enabled, and yet we still think we require a passphrase for decryption. 1324 // enabled, and yet we still think we require a passphrase for decryption.
1308 DCHECK(!(IsPassphraseRequiredForDecryption() && 1325 DCHECK(!(IsPassphraseRequiredForDecryption() &&
1309 !IsEncryptedDatatypeEnabled())); 1326 !IsEncryptedDatatypeEnabled()));
1310 1327
1311 // TODO(sync): Less wizard, more toast.
1312 wizard_.Step(SyncSetupWizard::DONE);
1313 NotifyObservers();
1314
1315 // In the old world, this would be a no-op. With new syncer thread, 1328 // In the old world, this would be a no-op. With new syncer thread,
1316 // this is the point where it is safe to switch from config-mode to 1329 // this is the point where it is safe to switch from config-mode to
1317 // normal operation. 1330 // normal operation.
1318 backend_->StartSyncingWithServer(); 1331 backend_->StartSyncingWithServer();
1319 1332
1320 if (!pending_types_for_encryption_.empty()) { 1333 if (pending_types_for_encryption_.empty()) {
1321 EncryptDataTypes(pending_types_for_encryption_); 1334 wizard_.Step(SyncSetupWizard::DONE);
1322 pending_types_for_encryption_.clear(); 1335 NotifyObservers();
1336 } else {
1337 // Will clear pending_types_for_encryption_ on success (via
1338 // OnEncryptionComplete). Has no effect if pending_types_for_encryption_
1339 // matches the encrypted types (and will clear
1340 // pending_types_for_encryption_).
1341 backend_->EncryptDataTypes(pending_types_for_encryption_);
1323 } 1342 }
1324 break; 1343 break;
1325 } 1344 }
1326 case chrome::NOTIFICATION_PREF_CHANGED: { 1345 case chrome::NOTIFICATION_PREF_CHANGED: {
1327 std::string* pref_name = Details<std::string>(details).ptr(); 1346 std::string* pref_name = Details<std::string>(details).ptr();
1328 if (*pref_name == prefs::kSyncManaged) { 1347 if (*pref_name == prefs::kSyncManaged) {
1329 NotifyObservers(); 1348 NotifyObservers();
1330 if (*pref_sync_managed_) { 1349 if (*pref_sync_managed_) {
1331 DisableForUser(); 1350 DisableForUser();
1332 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { 1351 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 // is initialized, all enabled data types are consistent with one 1446 // is initialized, all enabled data types are consistent with one
1428 // another, and no unrecoverable error has transpired. 1447 // another, and no unrecoverable error has transpired.
1429 if (unrecoverable_error_detected_) 1448 if (unrecoverable_error_detected_)
1430 return false; 1449 return false;
1431 1450
1432 if (!data_type_manager_.get()) 1451 if (!data_type_manager_.get())
1433 return false; 1452 return false;
1434 1453
1435 return data_type_manager_->state() == DataTypeManager::CONFIGURED; 1454 return data_type_manager_->state() == DataTypeManager::CONFIGURED;
1436 } 1455 }
OLDNEW
« no previous file with comments | « chrome/browser/sync/profile_sync_service.h ('k') | chrome/browser/sync/profile_sync_service_harness.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698