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

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: 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
« no previous file with comments | « chrome/browser/sync/profile_sync_service.h ('k') | chrome/browser/sync/sync_setup_flow.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 types, 361 types,
362 credentials, 362 credentials,
363 delete_sync_data_folder); 363 delete_sync_data_folder);
364 } 364 }
365 365
366 void ProfileSyncService::CreateBackend() { 366 void ProfileSyncService::CreateBackend() {
367 backend_.reset(new SyncBackendHost(profile_)); 367 backend_.reset(new SyncBackendHost(profile_));
368 } 368 }
369 369
370 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { 370 bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
371 if (!pending_types_for_encryption_.empty())
372 return true;
371 syncable::ModelTypeSet preferred_types; 373 syncable::ModelTypeSet preferred_types;
372 GetPreferredDataTypes(&preferred_types); 374 GetPreferredDataTypes(&preferred_types);
373 syncable::ModelTypeSet encrypted_types; 375 syncable::ModelTypeSet encrypted_types;
374 GetEncryptedDataTypes(&encrypted_types); 376 GetEncryptedDataTypes(&encrypted_types);
375 syncable::ModelTypeBitSet preferred_types_bitset = 377 syncable::ModelTypeBitSet preferred_types_bitset =
376 syncable::ModelTypeBitSetFromSet(preferred_types); 378 syncable::ModelTypeBitSetFromSet(preferred_types);
377 syncable::ModelTypeBitSet encrypted_types_bitset = 379 syncable::ModelTypeBitSet encrypted_types_bitset =
378 syncable::ModelTypeBitSetFromSet(encrypted_types); 380 syncable::ModelTypeBitSetFromSet(encrypted_types);
379 DCHECK(encrypted_types.count(syncable::PASSWORDS)); 381 DCHECK(encrypted_types.count(syncable::PASSWORDS));
380 return (preferred_types_bitset & encrypted_types_bitset).any(); 382 return (preferred_types_bitset & encrypted_types_bitset).any();
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 } 681 }
680 682
681 VLOG(1) << "Passphrase required with reason: " 683 VLOG(1) << "Passphrase required with reason: "
682 << sync_api::PassphraseRequiredReasonToString(reason); 684 << sync_api::PassphraseRequiredReasonToString(reason);
683 passphrase_required_reason_ = reason; 685 passphrase_required_reason_ = reason;
684 686
685 // We will skip the passphrase prompt and suppress the warning if the 687 // We will skip the passphrase prompt and suppress the warning if the
686 // passphrase is needed for decryption but the user is not syncing an 688 // passphrase is needed for decryption but the user is not syncing an
687 // encrypted data type on this machine. Otherwise we look for one. 689 // encrypted data type on this machine. Otherwise we look for one.
688 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) { 690 if (!IsEncryptedDatatypeEnabled() && IsPassphraseRequiredForDecryption()) {
689 VLOG(1) << "Not decrypting and no encrypted datatypes enabled" 691 VLOG(1) << "Decrypting and no encrypted datatypes enabled"
690 << ", accepted passphrase."; 692 << ", accepted passphrase.";
691 OnPassphraseAccepted(); 693 OnPassphraseAccepted();
692 } 694 }
693 695
694 // First try supplying gaia password as the passphrase. 696 // First try supplying gaia password as the passphrase.
695 if (!gaia_password_.empty()) { 697 if (!gaia_password_.empty()) {
696 VLOG(1) << "Attempting gaia passphrase."; 698 VLOG(1) << "Attempting gaia passphrase.";
697 SetPassphrase(gaia_password_, false, true); 699 std::string pass = gaia_password_;
698 gaia_password_ = std::string(); 700 gaia_password_ = std::string();
701 // May set gaia_password_ if the syncer isn't ready.
702 SetPassphrase(pass, false, true);
699 return; 703 return;
700 } 704 }
701 705
702 // If the above failed then try the custom passphrase the user might have 706 // If the above failed then try the custom passphrase the user might have
703 // entered in setup. 707 // entered in setup.
704 if (!cached_passphrase_.value.empty()) { 708 if (!cached_passphrase_.value.empty()) {
705 VLOG(1) << "Attempting cached passphrase."; 709 VLOG(1) << "Attempting cached passphrase.";
706 SetPassphrase(cached_passphrase_.value, 710 std::string pass = cached_passphrase_.value;
707 cached_passphrase_.is_explicit, 711 bool is_explicit = cached_passphrase_.is_explicit;
708 cached_passphrase_.is_creation); 712 bool is_creation = cached_passphrase_.is_creation;
709 cached_passphrase_ = CachedPassphrase(); 713 cached_passphrase_ = CachedPassphrase();
714 // May set cached_passphrase_ is the syncer isn't ready.
715 SetPassphrase(pass, is_explicit, is_creation);
710 return; 716 return;
711 } 717 }
712 718
713 // Prompt the user for a password. 719 // Prompt the user for a password.
714 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() && 720 if (WizardIsVisible() && IsEncryptedDatatypeEnabled() &&
715 IsPassphraseRequiredForDecryption()) { 721 IsPassphraseRequiredForDecryption()) {
716 VLOG(1) << "Prompting user for passphrase."; 722 VLOG(1) << "Prompting user for passphrase.";
717 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE); 723 wizard_.Step(SyncSetupWizard::ENTER_PASSPHRASE);
718 } 724 }
719 725
720 NotifyObservers(); 726 NotifyObservers();
721 } 727 }
722 728
723 void ProfileSyncService::OnPassphraseAccepted() { 729 void ProfileSyncService::OnPassphraseAccepted() {
724 VLOG(1) << "Received OnPassphraseAccepted."; 730 VLOG(1) << "Received OnPassphraseAccepted.";
731 // Don't hold on to a passphrase in raw form longer than needed.
732 gaia_password_ = std::string();
733 cached_passphrase_ = CachedPassphrase();
734
725 // Make sure the data types that depend on the passphrase are started at 735 // Make sure the data types that depend on the passphrase are started at
726 // this time. 736 // this time.
727 syncable::ModelTypeSet types; 737 syncable::ModelTypeSet types;
728 GetPreferredDataTypes(&types); 738 GetPreferredDataTypes(&types);
729 739
730 // Reset passphrase_required_reason_ before configuring the DataTypeManager 740 // Reset passphrase_required_reason_ before configuring the DataTypeManager
731 // since we know we no longer require the passphrase. 741 // since we know we no longer require the passphrase.
732 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED; 742 passphrase_required_reason_ = sync_api::REASON_PASSPHRASE_NOT_REQUIRED;
733 743
734 if (data_type_manager_.get()) { 744 if (data_type_manager_.get()) {
735 // Unblock the data type manager if necessary. 745 // Unblock the data type manager if necessary.
736 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will 746 // This will always trigger a SYNC_CONFIGURE_DONE on completion, which will
737 // step the UI wizard into DONE state (even if no datatypes have changed). 747 // step the UI wizard into DONE state (even if no datatypes have changed).
738 data_type_manager_->Configure(types, 748 data_type_manager_->Configure(types,
739 sync_api::CONFIGURE_REASON_RECONFIGURATION); 749 sync_api::CONFIGURE_REASON_RECONFIGURATION);
740 } 750 }
741 751
742 NotifyObservers(); 752 NotifyObservers();
743 } 753 }
744 754
745 void ProfileSyncService::OnEncryptionComplete( 755 void ProfileSyncService::OnEncryptionComplete(
746 const syncable::ModelTypeSet& encrypted_types) { 756 const syncable::ModelTypeSet& encrypted_types) {
757 if (!pending_types_for_encryption_.empty()) {
758 // The user had chosen to encrypt datatypes. This is the last thing to
759 // complete, so now that we're done notify the UI.
760 wizard_.Step(SyncSetupWizard::DONE);
Nicolas Zea 2011/08/02 21:18:26 This works because encryption only occurs in the S
761 }
762 pending_types_for_encryption_.clear();
747 NotifyObservers(); 763 NotifyObservers();
748 } 764 }
749 765
750 void ProfileSyncService::OnMigrationNeededForTypes( 766 void ProfileSyncService::OnMigrationNeededForTypes(
751 const syncable::ModelTypeSet& types) { 767 const syncable::ModelTypeSet& types) {
752 DCHECK(backend_initialized_); 768 DCHECK(backend_initialized_);
753 DCHECK(data_type_manager_.get()); 769 DCHECK(data_type_manager_.get());
754 770
755 // Migrator must be valid, because we don't sync until it is created and this 771 // Migrator must be valid, because we don't sync until it is created and this
756 // callback originates from a sync cycle. 772 // callback originates from a sync cycle.
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 if (!backend_.get()) 1176 if (!backend_.get())
1161 return; 1177 return;
1162 backend_->DeactivateDataType(data_type_controller, change_processor); 1178 backend_->DeactivateDataType(data_type_controller, change_processor);
1163 } 1179 }
1164 1180
1165 void ProfileSyncService::SetPassphrase(const std::string& passphrase, 1181 void ProfileSyncService::SetPassphrase(const std::string& passphrase,
1166 bool is_explicit, 1182 bool is_explicit,
1167 bool is_creation) { 1183 bool is_creation) {
1168 if (ShouldPushChanges() || IsPassphraseRequired()) { 1184 if (ShouldPushChanges() || IsPassphraseRequired()) {
1169 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit") 1185 VLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit")
1170 << " passphrase " << (is_creation ? " for creation" : ""); 1186 << " passphrase" << (is_creation ? " for creation" : "");
1171 backend_->SetPassphrase(passphrase, is_explicit); 1187 backend_->SetPassphrase(passphrase, is_explicit);
1172 } else { 1188 } else {
1173 if (is_explicit) { 1189 if (is_explicit) {
1174 cached_passphrase_.value = passphrase; 1190 cached_passphrase_.value = passphrase;
1175 cached_passphrase_.is_explicit = is_explicit; 1191 cached_passphrase_.is_explicit = is_explicit;
1176 cached_passphrase_.is_creation = is_creation; 1192 cached_passphrase_.is_creation = is_creation;
1177 } else { 1193 } else {
1178 gaia_password_ = passphrase; 1194 gaia_password_ = passphrase;
1179 } 1195 }
1180 } 1196 }
1181 } 1197 }
1182 1198
1183 void ProfileSyncService::EncryptDataTypes( 1199 void ProfileSyncService::EncryptDataTypes(
1184 const syncable::ModelTypeSet& encrypted_types) { 1200 const syncable::ModelTypeSet& encrypted_types) {
1185 if (HasSyncSetupCompleted()) { 1201 if (encrypted_types.empty()) {
1186 backend_->EncryptDataTypes(encrypted_types); 1202 // We can't unencrypt types.
1203 VLOG(1) << "No datatypes set for encryption, dropping encryption request.";
1187 pending_types_for_encryption_.clear(); 1204 pending_types_for_encryption_.clear();
Nicolas Zea 2011/08/02 21:18:26 This call will be combined with a configuredatatyp
1188 } else { 1205 return;
1189 pending_types_for_encryption_ = encrypted_types;
1190 } 1206 }
1207 // We require that every call to EncryptDatatypes be coupled with a
1208 // ConfigureDataTypeManager. The actual call to encrypt the datatypes happens
1209 // after SYNC_CONFIGURE_DONE, to ensure we've downloaded any new datatypes
1210 // before beginning encryption.
1211 // TODO(zea): This is very brittle and relies on ConfigureDataTypes being
1212 // called after the encryptdatatypes in sync_setup_flow.cc. Fix this.
1213 pending_types_for_encryption_ = encrypted_types;
1191 } 1214 }
1192 1215
1193 // This would open a transaction to get the encrypted types. Do not call this 1216 // This will open a transaction to get the encrypted types. Do not call this
1194 // if you already have a transaction open. 1217 // if you already have a transaction open.
1195 void ProfileSyncService::GetEncryptedDataTypes( 1218 void ProfileSyncService::GetEncryptedDataTypes(
1196 syncable::ModelTypeSet* encrypted_types) const { 1219 syncable::ModelTypeSet* encrypted_types) const {
1197 CHECK(encrypted_types); 1220 CHECK(encrypted_types);
1198 if (backend_.get()) { 1221 if (backend_.get()) {
1199 *encrypted_types = backend_->GetEncryptedDataTypes(); 1222 *encrypted_types = backend_->GetEncryptedDataTypes();
1200 DCHECK(encrypted_types->count(syncable::PASSWORDS)); 1223 DCHECK(encrypted_types->count(syncable::PASSWORDS));
1201 } else { 1224 } else {
1202 // Either we are in an unrecoverable error or the sync is not yet done 1225 // Either we are in an unrecoverable error or the sync is not yet done
1203 // initializing. In either case just return the password type. During 1226 // initializing. In either case just return the password type. During
(...skipping 17 matching lines...) Expand all
1221 Details<DataTypeManager::ConfigureResult>(details).ptr(); 1244 Details<DataTypeManager::ConfigureResult>(details).ptr();
1222 1245
1223 DataTypeManager::ConfigureStatus status = result->status; 1246 DataTypeManager::ConfigureStatus status = result->status;
1224 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with status: " << status; 1247 VLOG(1) << "PSS SYNC_CONFIGURE_DONE called with status: " << status;
1225 if (status == DataTypeManager::ABORTED && 1248 if (status == DataTypeManager::ABORTED &&
1226 expect_sync_configuration_aborted_) { 1249 expect_sync_configuration_aborted_) {
1227 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted"; 1250 VLOG(0) << "ProfileSyncService::Observe Sync Configure aborted";
1228 expect_sync_configuration_aborted_ = false; 1251 expect_sync_configuration_aborted_ = false;
1229 return; 1252 return;
1230 } 1253 }
1231 // Clear out the gaia password if it is already there.
1232 gaia_password_ = std::string();
1233 if (status != DataTypeManager::OK) { 1254 if (status != DataTypeManager::OK) {
1234 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected"; 1255 VLOG(0) << "ProfileSyncService::Observe: Unrecoverable error detected";
1235 std::string message = 1256 std::string message =
1236 "Sync Configuration failed while configuring " + 1257 "Sync Configuration failed while configuring " +
1237 syncable::ModelTypeSetToString(result->failed_types) + 1258 syncable::ModelTypeSetToString(result->failed_types) +
1238 ": " + DataTypeManager::ConfigureStatusToString(status); 1259 ": " + DataTypeManager::ConfigureStatusToString(status);
1239 OnUnrecoverableError(result->location, message); 1260 OnUnrecoverableError(result->location, message);
1240 cached_passphrase_ = CachedPassphrase(); 1261 cached_passphrase_ = CachedPassphrase();
1241 return; 1262 return;
1242 } 1263 }
1243 1264
1244 // If the user had entered a custom passphrase use it now.
Nicolas Zea 2011/08/02 21:18:26 This all now happens in OnPassphraseRequired and O
1245 if (!cached_passphrase_.value.empty()) {
1246 // Don't hold on to the passphrase in raw form longer than needed.
1247 SetPassphrase(cached_passphrase_.value,
1248 cached_passphrase_.is_explicit,
1249 cached_passphrase_.is_creation);
1250 cached_passphrase_ = CachedPassphrase();
1251 }
1252
1253 // We should never get in a state where we have no encrypted datatypes 1265 // We should never get in a state where we have no encrypted datatypes
1254 // enabled, and yet we still think we require a passphrase for decryption. 1266 // enabled, and yet we still think we require a passphrase for decryption.
1255 DCHECK(!(IsPassphraseRequiredForDecryption() && 1267 DCHECK(!(IsPassphraseRequiredForDecryption() &&
1256 !IsEncryptedDatatypeEnabled())); 1268 !IsEncryptedDatatypeEnabled()));
1257 1269
1258 // TODO(sync): Less wizard, more toast. 1270 if (!gaia_password_.empty()) {
1259 wizard_.Step(SyncSetupWizard::DONE); 1271 // If we haven't yet attempted to set the gaia passphrase use it now.
1260 NotifyObservers(); 1272 SetPassphrase(gaia_password_, false, true);
1273 gaia_password_ = std::string();
1274 } else if (!cached_passphrase_.value.empty()) {
1275 // If the user had entered a custom passphrase use it now.
1276 SetPassphrase(cached_passphrase_.value,
1277 cached_passphrase_.is_explicit,
1278 cached_passphrase_.is_creation);
1279 cached_passphrase_ = CachedPassphrase();
1280 }
1281
1261 1282
1262 // In the old world, this would be a no-op. With new syncer thread, 1283 // In the old world, this would be a no-op. With new syncer thread,
1263 // this is the point where it is safe to switch from config-mode to 1284 // this is the point where it is safe to switch from config-mode to
1264 // normal operation. 1285 // normal operation.
1265 backend_->StartSyncingWithServer(); 1286 backend_->StartSyncingWithServer();
1266 1287
1267 if (!pending_types_for_encryption_.empty()) { 1288 if (pending_types_for_encryption_.empty()) {
1268 EncryptDataTypes(pending_types_for_encryption_); 1289 // TODO(sync): Less wizard, more toast.
1269 pending_types_for_encryption_.clear(); 1290 wizard_.Step(SyncSetupWizard::DONE);
1291 NotifyObservers();
1292 } else {
1293 // Will clear pending_types_for_encryption_ on success. Has no effect
1294 // if pending_types_for_encryption_ matches the encrypted types.
1295 backend_->EncryptDataTypes(pending_types_for_encryption_);
1270 } 1296 }
1271 break; 1297 break;
1272 } 1298 }
1273 case chrome::NOTIFICATION_PREF_CHANGED: { 1299 case chrome::NOTIFICATION_PREF_CHANGED: {
1274 std::string* pref_name = Details<std::string>(details).ptr(); 1300 std::string* pref_name = Details<std::string>(details).ptr();
1275 if (*pref_name == prefs::kSyncManaged) { 1301 if (*pref_name == prefs::kSyncManaged) {
1276 NotifyObservers(); 1302 NotifyObservers();
1277 if (*pref_sync_managed_) { 1303 if (*pref_sync_managed_) {
1278 DisableForUser(); 1304 DisableForUser();
1279 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) { 1305 } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 // is initialized, all enabled data types are consistent with one 1395 // is initialized, all enabled data types are consistent with one
1370 // another, and no unrecoverable error has transpired. 1396 // another, and no unrecoverable error has transpired.
1371 if (unrecoverable_error_detected_) 1397 if (unrecoverable_error_detected_)
1372 return false; 1398 return false;
1373 1399
1374 if (!data_type_manager_.get()) 1400 if (!data_type_manager_.get())
1375 return false; 1401 return false;
1376 1402
1377 return data_type_manager_->state() == DataTypeManager::CONFIGURED; 1403 return data_type_manager_->state() == DataTypeManager::CONFIGURED;
1378 } 1404 }
OLDNEW
« no previous file with comments | « chrome/browser/sync/profile_sync_service.h ('k') | chrome/browser/sync/sync_setup_flow.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698