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

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

Issue 7551024: [Sync] Fix encryption/passphrase handling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase + fix allstatus 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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
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