| 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 "sync/internal_api/sync_manager_impl.h" | 5 #include "sync/internal_api/sync_manager_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "sync/internal_api/public/write_node.h" | 34 #include "sync/internal_api/public/write_node.h" |
| 35 #include "sync/internal_api/public/write_transaction.h" | 35 #include "sync/internal_api/public/write_transaction.h" |
| 36 #include "sync/internal_api/syncapi_internal.h" | 36 #include "sync/internal_api/syncapi_internal.h" |
| 37 #include "sync/internal_api/syncapi_server_connection_manager.h" | 37 #include "sync/internal_api/syncapi_server_connection_manager.h" |
| 38 #include "sync/js/js_arg_list.h" | 38 #include "sync/js/js_arg_list.h" |
| 39 #include "sync/js/js_event_details.h" | 39 #include "sync/js/js_event_details.h" |
| 40 #include "sync/js/js_event_handler.h" | 40 #include "sync/js/js_event_handler.h" |
| 41 #include "sync/js/js_reply_handler.h" | 41 #include "sync/js/js_reply_handler.h" |
| 42 #include "sync/notifier/invalidation_util.h" | 42 #include "sync/notifier/invalidation_util.h" |
| 43 #include "sync/notifier/sync_notifier.h" | 43 #include "sync/notifier/sync_notifier.h" |
| 44 #include "sync/protocol/encryption.pb.h" | |
| 45 #include "sync/protocol/proto_value_conversions.h" | 44 #include "sync/protocol/proto_value_conversions.h" |
| 46 #include "sync/protocol/sync.pb.h" | 45 #include "sync/protocol/sync.pb.h" |
| 47 #include "sync/syncable/directory.h" | 46 #include "sync/syncable/directory.h" |
| 48 #include "sync/syncable/entry.h" | 47 #include "sync/syncable/entry.h" |
| 49 #include "sync/syncable/in_memory_directory_backing_store.h" | 48 #include "sync/syncable/in_memory_directory_backing_store.h" |
| 50 #include "sync/syncable/nigori_util.h" | |
| 51 #include "sync/syncable/on_disk_directory_backing_store.h" | 49 #include "sync/syncable/on_disk_directory_backing_store.h" |
| 52 #include "sync/util/get_session_name.h" | 50 #include "sync/util/get_session_name.h" |
| 53 | 51 |
| 54 using base::TimeDelta; | 52 using base::TimeDelta; |
| 55 using sync_pb::GetUpdatesCallerInfo; | 53 using sync_pb::GetUpdatesCallerInfo; |
| 56 | 54 |
| 57 namespace syncer { | 55 namespace syncer { |
| 58 | 56 |
| 59 using sessions::SyncSessionContext; | 57 using sessions::SyncSessionContext; |
| 60 using syncable::ImmutableWriteTransactionInfo; | 58 using syncable::ImmutableWriteTransactionInfo; |
| 61 using syncable::SPECIFICS; | 59 using syncable::SPECIFICS; |
| 62 | 60 |
| 63 namespace { | 61 namespace { |
| 64 | 62 |
| 65 // Delays for syncer nudges. | 63 // Delays for syncer nudges. |
| 66 static const int kDefaultNudgeDelayMilliseconds = 200; | 64 static const int kDefaultNudgeDelayMilliseconds = 200; |
| 67 static const int kPreferencesNudgeDelayMilliseconds = 2000; | 65 static const int kPreferencesNudgeDelayMilliseconds = 2000; |
| 68 static const int kSyncRefreshDelayMsec = 500; | 66 static const int kSyncRefreshDelayMsec = 500; |
| 69 static const int kSyncSchedulerDelayMsec = 250; | 67 static const int kSyncSchedulerDelayMsec = 250; |
| 70 | 68 |
| 71 // The maximum number of times we will automatically overwrite the nigori node | |
| 72 // because the encryption keys don't match (per chrome instantiation). | |
| 73 static const int kNigoriOverwriteLimit = 10; | |
| 74 | |
| 75 // Maximum count and size for traffic recorder. | 69 // Maximum count and size for traffic recorder. |
| 76 static const unsigned int kMaxMessagesToRecord = 10; | 70 static const unsigned int kMaxMessagesToRecord = 10; |
| 77 static const unsigned int kMaxMessageSizeToRecord = 5 * 1024; | 71 static const unsigned int kMaxMessageSizeToRecord = 5 * 1024; |
| 78 | 72 |
| 79 GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason( | 73 GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason( |
| 80 ConfigureReason reason) { | 74 ConfigureReason reason) { |
| 81 switch (reason) { | 75 switch (reason) { |
| 82 case CONFIGURE_REASON_RECONFIGURATION: | 76 case CONFIGURE_REASON_RECONFIGURATION: |
| 83 return GetUpdatesCallerInfo::RECONFIGURATION; | 77 return GetUpdatesCallerInfo::RECONFIGURATION; |
| 84 case CONFIGURE_REASON_MIGRATION: | 78 case CONFIGURE_REASON_MIGRATION: |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 : name_(name), | 166 : name_(name), |
| 173 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 167 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 174 change_delegate_(NULL), | 168 change_delegate_(NULL), |
| 175 initialized_(false), | 169 initialized_(false), |
| 176 observing_ip_address_changes_(false), | 170 observing_ip_address_changes_(false), |
| 177 notifications_disabled_reason_(TRANSIENT_NOTIFICATION_ERROR), | 171 notifications_disabled_reason_(TRANSIENT_NOTIFICATION_ERROR), |
| 178 throttled_data_type_tracker_(&allstatus_), | 172 throttled_data_type_tracker_(&allstatus_), |
| 179 traffic_recorder_(kMaxMessagesToRecord, kMaxMessageSizeToRecord), | 173 traffic_recorder_(kMaxMessagesToRecord, kMaxMessageSizeToRecord), |
| 180 encryptor_(NULL), | 174 encryptor_(NULL), |
| 181 unrecoverable_error_handler_(NULL), | 175 unrecoverable_error_handler_(NULL), |
| 182 report_unrecoverable_error_function_(NULL), | 176 report_unrecoverable_error_function_(NULL) { |
| 183 nigori_overwrite_count_(0) { | |
| 184 // Pre-fill |notification_info_map_|. | 177 // Pre-fill |notification_info_map_|. |
| 185 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 178 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { |
| 186 notification_info_map_.insert( | 179 notification_info_map_.insert( |
| 187 std::make_pair(ModelTypeFromInt(i), NotificationInfo())); | 180 std::make_pair(ModelTypeFromInt(i), NotificationInfo())); |
| 188 } | 181 } |
| 189 | 182 |
| 190 // Bind message handlers. | 183 // Bind message handlers. |
| 191 BindJsMessageHandler( | 184 BindJsMessageHandler( |
| 192 "getNotificationState", | 185 "getNotificationState", |
| 193 &SyncManagerImpl::GetNotificationState); | 186 &SyncManagerImpl::GetNotificationState); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 sync_pb::DataTypeProgressMarker marker; | 296 sync_pb::DataTypeProgressMarker marker; |
| 304 directory()->GetDownloadProgress(i.Get(), &marker); | 297 directory()->GetDownloadProgress(i.Get(), &marker); |
| 305 | 298 |
| 306 if (marker.token().empty()) | 299 if (marker.token().empty()) |
| 307 result.Put(i.Get()); | 300 result.Put(i.Get()); |
| 308 | 301 |
| 309 } | 302 } |
| 310 return result; | 303 return result; |
| 311 } | 304 } |
| 312 | 305 |
| 313 void SyncManagerImpl::EnableEncryptEverything() { | |
| 314 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 315 { | |
| 316 // Update the cryptographer to know we're now encrypting everything. | |
| 317 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 318 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 319 // Only set encrypt everything if we know we can encrypt. This allows the | |
| 320 // user to cancel encryption if they have forgotten their passphrase. | |
| 321 if (cryptographer->is_ready()) | |
| 322 cryptographer->set_encrypt_everything(); | |
| 323 } | |
| 324 | |
| 325 // Reads from cryptographer so will automatically encrypt all | |
| 326 // datatypes and update the nigori node as necessary. Will trigger | |
| 327 // OnPassphraseRequired if necessary. | |
| 328 RefreshEncryption(); | |
| 329 } | |
| 330 | |
| 331 void SyncManagerImpl::ConfigureSyncer( | 306 void SyncManagerImpl::ConfigureSyncer( |
| 332 ConfigureReason reason, | 307 ConfigureReason reason, |
| 333 const ModelTypeSet& types_to_config, | 308 const ModelTypeSet& types_to_config, |
| 334 const ModelSafeRoutingInfo& new_routing_info, | 309 const ModelSafeRoutingInfo& new_routing_info, |
| 335 const base::Closure& ready_task, | 310 const base::Closure& ready_task, |
| 336 const base::Closure& retry_task) { | 311 const base::Closure& retry_task) { |
| 337 DCHECK(thread_checker_.CalledOnValidThread()); | 312 DCHECK(thread_checker_.CalledOnValidThread()); |
| 338 DCHECK(!ready_task.is_null()); | 313 DCHECK(!ready_task.is_null()); |
| 339 DCHECK(!retry_task.is_null()); | 314 DCHECK(!retry_task.is_null()); |
| 340 | 315 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 UpdateCredentials(credentials); | 457 UpdateCredentials(credentials); |
| 483 | 458 |
| 484 // Cryptographer should only be accessed while holding a | 459 // Cryptographer should only be accessed while holding a |
| 485 // transaction. Grabbing the user share for the transaction | 460 // transaction. Grabbing the user share for the transaction |
| 486 // checks the initialization state, so this must come after | 461 // checks the initialization state, so this must come after |
| 487 // |initialized_| is set to true. | 462 // |initialized_| is set to true. |
| 488 ReadTransaction trans(FROM_HERE, GetUserShare()); | 463 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 489 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); | 464 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); |
| 490 trans.GetCryptographer()->BootstrapKeystoreKey( | 465 trans.GetCryptographer()->BootstrapKeystoreKey( |
| 491 restored_keystore_key_for_bootstrapping); | 466 restored_keystore_key_for_bootstrapping); |
| 492 trans.GetCryptographer()->AddObserver(this); | 467 |
| 468 sync_encryption_handler_.reset(new SyncEncryptionHandlerImpl( |
| 469 &share_, |
| 470 trans.GetCryptographer())); |
| 471 sync_encryption_handler_->AddObserver(this); |
| 472 sync_encryption_handler_->AddObserver(&debug_info_event_listener_); |
| 473 sync_encryption_handler_->AddObserver(&js_sync_encryption_handler_observer_); |
| 474 trans.GetCryptographer()->SetNigoriHandler( |
| 475 sync_encryption_handler_.get()); |
| 493 | 476 |
| 494 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 477 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 495 OnInitializationComplete( | 478 OnInitializationComplete( |
| 496 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), | 479 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), |
| 497 true, InitialSyncEndedTypes())); | 480 true, InitialSyncEndedTypes())); |
| 498 } | 481 } |
| 499 | 482 |
| 500 void SyncManagerImpl::RefreshNigori(const std::string& chrome_version, | 483 void SyncManagerImpl::UpdateSessionNameCallback( |
| 501 const base::Closure& done_callback) { | |
| 502 DCHECK(initialized_); | |
| 503 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 504 GetSessionName( | |
| 505 blocking_task_runner_, | |
| 506 base::Bind( | |
| 507 &SyncManagerImpl::UpdateCryptographerAndNigoriCallback, | |
| 508 weak_ptr_factory_.GetWeakPtr(), | |
| 509 chrome_version, | |
| 510 done_callback)); | |
| 511 } | |
| 512 | |
| 513 void SyncManagerImpl::UpdateNigoriEncryptionState( | |
| 514 Cryptographer* cryptographer, | |
| 515 WriteNode* nigori_node) { | |
| 516 DCHECK(nigori_node); | |
| 517 sync_pb::NigoriSpecifics nigori = nigori_node->GetNigoriSpecifics(); | |
| 518 | |
| 519 if (cryptographer->is_ready() && | |
| 520 nigori_overwrite_count_ < kNigoriOverwriteLimit) { | |
| 521 // Does not modify the encrypted blob if the unencrypted data already | |
| 522 // matches what is about to be written. | |
| 523 sync_pb::EncryptedData original_keys = nigori.encrypted(); | |
| 524 if (!cryptographer->GetKeys(nigori.mutable_encrypted())) | |
| 525 NOTREACHED(); | |
| 526 | |
| 527 if (nigori.encrypted().SerializeAsString() != | |
| 528 original_keys.SerializeAsString()) { | |
| 529 // We've updated the nigori node's encryption keys. In order to prevent | |
| 530 // a possible looping of two clients constantly overwriting each other, | |
| 531 // we limit the absolute number of overwrites per client instantiation. | |
| 532 nigori_overwrite_count_++; | |
| 533 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", | |
| 534 nigori_overwrite_count_); | |
| 535 } | |
| 536 | |
| 537 // Note: we don't try to set using_explicit_passphrase here since if that | |
| 538 // is lost the user can always set it again. The main point is to preserve | |
| 539 // the encryption keys so all data remains decryptable. | |
| 540 } | |
| 541 cryptographer->UpdateNigoriFromEncryptedTypes(&nigori); | |
| 542 | |
| 543 // If nothing has changed, this is a no-op. | |
| 544 nigori_node->SetNigoriSpecifics(nigori); | |
| 545 } | |
| 546 | |
| 547 void SyncManagerImpl::UpdateCryptographerAndNigoriCallback( | |
| 548 const std::string& chrome_version, | 484 const std::string& chrome_version, |
| 549 const base::Closure& done_callback, | |
| 550 const std::string& session_name) { | 485 const std::string& session_name) { |
| 551 if (!directory()->initial_sync_ended_for_type(NIGORI)) { | 486 WriteTransaction trans(FROM_HERE, GetUserShare()); |
| 552 done_callback.Run(); // Should only happen during first time sync. | 487 WriteNode node(&trans); |
| 488 // TODO(rlarocque): switch to device info node. |
| 489 if (node.InitByTagLookup(syncer::kNigoriTag) != syncer::BaseNode::INIT_OK) { |
| 553 return; | 490 return; |
| 554 } | 491 } |
| 555 | 492 |
| 556 bool success = false; | 493 sync_pb::NigoriSpecifics nigori(node.GetNigoriSpecifics()); |
| 557 { | 494 // Add or update device information. |
| 558 WriteTransaction trans(FROM_HERE, GetUserShare()); | 495 bool contains_this_device = false; |
| 559 Cryptographer* cryptographer = trans.GetCryptographer(); | 496 for (int i = 0; i < nigori.device_information_size(); ++i) { |
| 560 WriteNode node(&trans); | 497 const sync_pb::DeviceInformation& device_information = |
| 561 | 498 nigori.device_information(i); |
| 562 if (node.InitByTagLookup(kNigoriTag) == BaseNode::INIT_OK) { | 499 if (device_information.cache_guid() == directory()->cache_guid()) { |
| 563 sync_pb::NigoriSpecifics nigori(node.GetNigoriSpecifics()); | 500 // Update the version number in case it changed due to an update. |
| 564 Cryptographer::UpdateResult result = cryptographer->Update(nigori); | 501 if (device_information.chrome_version() != chrome_version) { |
| 565 if (result == Cryptographer::NEEDS_PASSPHRASE) { | 502 sync_pb::DeviceInformation* mutable_device_information = |
| 566 sync_pb::EncryptedData pending_keys; | 503 nigori.mutable_device_information(i); |
| 567 if (cryptographer->has_pending_keys()) | 504 mutable_device_information->set_chrome_version( |
| 568 pending_keys = cryptographer->GetPendingKeys(); | 505 chrome_version); |
| 569 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 570 OnPassphraseRequired(REASON_DECRYPTION, | |
| 571 pending_keys)); | |
| 572 } | 506 } |
| 573 | 507 contains_this_device = true; |
| 574 // Add or update device information. | |
| 575 bool contains_this_device = false; | |
| 576 for (int i = 0; i < nigori.device_information_size(); ++i) { | |
| 577 const sync_pb::DeviceInformation& device_information = | |
| 578 nigori.device_information(i); | |
| 579 if (device_information.cache_guid() == directory()->cache_guid()) { | |
| 580 // Update the version number in case it changed due to an update. | |
| 581 if (device_information.chrome_version() != chrome_version) { | |
| 582 sync_pb::DeviceInformation* mutable_device_information = | |
| 583 nigori.mutable_device_information(i); | |
| 584 mutable_device_information->set_chrome_version( | |
| 585 chrome_version); | |
| 586 } | |
| 587 contains_this_device = true; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 if (!contains_this_device) { | |
| 592 sync_pb::DeviceInformation* device_information = | |
| 593 nigori.add_device_information(); | |
| 594 device_information->set_cache_guid(directory()->cache_guid()); | |
| 595 #if defined(OS_CHROMEOS) | |
| 596 device_information->set_platform("ChromeOS"); | |
| 597 #elif defined(OS_LINUX) | |
| 598 device_information->set_platform("Linux"); | |
| 599 #elif defined(OS_MACOSX) | |
| 600 device_information->set_platform("Mac"); | |
| 601 #elif defined(OS_WIN) | |
| 602 device_information->set_platform("Windows"); | |
| 603 #endif | |
| 604 device_information->set_name(session_name); | |
| 605 device_information->set_chrome_version(chrome_version); | |
| 606 } | |
| 607 // Disabled to avoid nigori races. TODO(zea): re-enable. crbug.com/122837 | |
| 608 // node.SetNigoriSpecifics(nigori); | |
| 609 | |
| 610 // Make sure the nigori node has the up to date encryption info. | |
| 611 UpdateNigoriEncryptionState(cryptographer, &node); | |
| 612 | |
| 613 NotifyCryptographerState(cryptographer); | |
| 614 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 615 | |
| 616 success = cryptographer->is_ready(); | |
| 617 } else { | |
| 618 NOTREACHED(); | |
| 619 } | 508 } |
| 620 } | 509 } |
| 621 | 510 |
| 622 if (success) | 511 if (!contains_this_device) { |
| 623 RefreshEncryption(); | 512 sync_pb::DeviceInformation* device_information = |
| 624 done_callback.Run(); | 513 nigori.add_device_information(); |
| 514 device_information->set_cache_guid(directory()->cache_guid()); |
| 515 #if defined(OS_CHROMEOS) |
| 516 device_information->set_platform("ChromeOS"); |
| 517 #elif defined(OS_LINUX) |
| 518 device_information->set_platform("Linux"); |
| 519 #elif defined(OS_MACOSX) |
| 520 device_information->set_platform("Mac"); |
| 521 #elif defined(OS_WIN) |
| 522 device_information->set_platform("Windows"); |
| 523 #endif |
| 524 device_information->set_name(session_name); |
| 525 device_information->set_chrome_version(chrome_version); |
| 526 } |
| 527 node.SetNigoriSpecifics(nigori); |
| 625 } | 528 } |
| 626 | 529 |
| 627 void SyncManagerImpl::NotifyCryptographerState(Cryptographer * cryptographer) { | 530 |
| 628 // TODO(lipalani): Explore the possibility of hooking this up to | 531 void SyncManagerImpl::OnPassphraseRequired( |
| 629 // SyncManager::Observer and making |AllStatus| a listener for that. | 532 PassphraseRequiredReason reason, |
| 533 const sync_pb::EncryptedData& pending_keys) { |
| 534 // Does nothing. |
| 535 } |
| 536 |
| 537 void SyncManagerImpl::OnPassphraseAccepted() { |
| 538 // Does nothing. |
| 539 } |
| 540 |
| 541 void SyncManagerImpl::OnBootstrapTokenUpdated( |
| 542 const std::string& bootstrap_token) { |
| 543 // Does nothing. |
| 544 } |
| 545 |
| 546 void SyncManagerImpl::OnEncryptedTypesChanged(ModelTypeSet encrypted_types, |
| 547 bool encrypt_everything) { |
| 548 allstatus_.SetEncryptedTypes(encrypted_types); |
| 549 } |
| 550 |
| 551 void SyncManagerImpl::OnEncryptionComplete() { |
| 552 // Does nothing. |
| 553 } |
| 554 |
| 555 void SyncManagerImpl::OnCryptographerStateChanged( |
| 556 Cryptographer* cryptographer) { |
| 630 allstatus_.SetCryptographerReady(cryptographer->is_ready()); | 557 allstatus_.SetCryptographerReady(cryptographer->is_ready()); |
| 631 allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys()); | 558 allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys()); |
| 632 debug_info_event_listener_.SetCryptographerReady(cryptographer->is_ready()); | |
| 633 debug_info_event_listener_.SetCrytographerHasPendingKeys( | |
| 634 cryptographer->has_pending_keys()); | |
| 635 } | 559 } |
| 636 | 560 |
| 637 void SyncManagerImpl::StartSyncingNormally( | 561 void SyncManagerImpl::StartSyncingNormally( |
| 638 const ModelSafeRoutingInfo& routing_info) { | 562 const ModelSafeRoutingInfo& routing_info) { |
| 639 // Start the sync scheduler. | 563 // Start the sync scheduler. |
| 640 // TODO(sync): We always want the newest set of routes when we switch back | 564 // TODO(sync): We always want the newest set of routes when we switch back |
| 641 // to normal mode. Figure out how to enforce set_routing_info is always | 565 // to normal mode. Figure out how to enforce set_routing_info is always |
| 642 // appropriately set and that it's only modified when switching to normal | 566 // appropriately set and that it's only modified when switching to normal |
| 643 // mode. | 567 // mode. |
| 644 DCHECK(thread_checker_.CalledOnValidThread()); | 568 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 sync_notifier_->UpdateRegisteredIds(handler, ids); | 677 sync_notifier_->UpdateRegisteredIds(handler, ids); |
| 754 } | 678 } |
| 755 | 679 |
| 756 void SyncManagerImpl::UnregisterInvalidationHandler( | 680 void SyncManagerImpl::UnregisterInvalidationHandler( |
| 757 SyncNotifierObserver* handler) { | 681 SyncNotifierObserver* handler) { |
| 758 DCHECK(thread_checker_.CalledOnValidThread()); | 682 DCHECK(thread_checker_.CalledOnValidThread()); |
| 759 DCHECK(initialized_); | 683 DCHECK(initialized_); |
| 760 sync_notifier_->UnregisterHandler(handler); | 684 sync_notifier_->UnregisterHandler(handler); |
| 761 } | 685 } |
| 762 | 686 |
| 763 void SyncManagerImpl::SetEncryptionPassphrase( | |
| 764 const std::string& passphrase, | |
| 765 bool is_explicit) { | |
| 766 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 767 // We do not accept empty passphrases. | |
| 768 if (passphrase.empty()) { | |
| 769 NOTREACHED() << "Cannot encrypt with an empty passphrase."; | |
| 770 return; | |
| 771 } | |
| 772 | |
| 773 // All accesses to the cryptographer are protected by a transaction. | |
| 774 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 775 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 776 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 777 WriteNode node(&trans); | |
| 778 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 779 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 780 NOTREACHED(); | |
| 781 return; | |
| 782 } | |
| 783 | |
| 784 bool nigori_has_explicit_passphrase = | |
| 785 node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 786 std::string bootstrap_token; | |
| 787 sync_pb::EncryptedData pending_keys; | |
| 788 if (cryptographer->has_pending_keys()) | |
| 789 pending_keys = cryptographer->GetPendingKeys(); | |
| 790 bool success = false; | |
| 791 | |
| 792 | |
| 793 // There are six cases to handle here: | |
| 794 // 1. The user has no pending keys and is setting their current GAIA password | |
| 795 // as the encryption passphrase. This happens either during first time sync | |
| 796 // with a clean profile, or after re-authenticating on a profile that was | |
| 797 // already signed in with the cryptographer ready. | |
| 798 // 2. The user has no pending keys, and is overwriting an (already provided) | |
| 799 // implicit passphrase with an explicit (custom) passphrase. | |
| 800 // 3. The user has pending keys for an explicit passphrase that is somehow set | |
| 801 // to their current GAIA passphrase. | |
| 802 // 4. The user has pending keys encrypted with their current GAIA passphrase | |
| 803 // and the caller passes in the current GAIA passphrase. | |
| 804 // 5. The user has pending keys encrypted with an older GAIA passphrase | |
| 805 // and the caller passes in the current GAIA passphrase. | |
| 806 // 6. The user has previously done encryption with an explicit passphrase. | |
| 807 // Furthermore, we enforce the fact that the bootstrap encryption token will | |
| 808 // always be derived from the newest GAIA password if the account is using | |
| 809 // an implicit passphrase (even if the data is encrypted with an old GAIA | |
| 810 // password). If the account is using an explicit (custom) passphrase, the | |
| 811 // bootstrap token will be derived from the most recently provided explicit | |
| 812 // passphrase (that was able to decrypt the data). | |
| 813 if (!nigori_has_explicit_passphrase) { | |
| 814 if (!cryptographer->has_pending_keys()) { | |
| 815 if (cryptographer->AddKey(key_params)) { | |
| 816 // Case 1 and 2. We set a new GAIA passphrase when there are no pending | |
| 817 // keys (1), or overwriting an implicit passphrase with a new explicit | |
| 818 // one (2) when there are no pending keys. | |
| 819 DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) | |
| 820 << " passphrase for encryption."; | |
| 821 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 822 success = true; | |
| 823 } else { | |
| 824 NOTREACHED() << "Failed to add key to cryptographer."; | |
| 825 success = false; | |
| 826 } | |
| 827 } else { // cryptographer->has_pending_keys() == true | |
| 828 if (is_explicit) { | |
| 829 // This can only happen if the nigori node is updated with a new | |
| 830 // implicit passphrase while a client is attempting to set a new custom | |
| 831 // passphrase (race condition). | |
| 832 DVLOG(1) << "Failing because an implicit passphrase is already set."; | |
| 833 success = false; | |
| 834 } else { // is_explicit == false | |
| 835 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 836 // Case 4. We successfully decrypted with the implicit GAIA passphrase | |
| 837 // passed in. | |
| 838 DVLOG(1) << "Implicit internal passphrase accepted for decryption."; | |
| 839 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 840 success = true; | |
| 841 } else { | |
| 842 // Case 5. Encryption was done with an old GAIA password, but we were | |
| 843 // provided with the current GAIA password. We need to generate a new | |
| 844 // bootstrap token to preserve it. We build a temporary cryptographer | |
| 845 // to allow us to extract these params without polluting our current | |
| 846 // cryptographer. | |
| 847 DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding " | |
| 848 << "anyways as default passphrase and persisting via " | |
| 849 << "bootstrap token."; | |
| 850 Cryptographer temp_cryptographer(encryptor_); | |
| 851 temp_cryptographer.AddKey(key_params); | |
| 852 temp_cryptographer.GetBootstrapToken(&bootstrap_token); | |
| 853 // We then set the new passphrase as the default passphrase of the | |
| 854 // real cryptographer, even though we have pending keys. This is safe, | |
| 855 // as although Cryptographer::is_initialized() will now be true, | |
| 856 // is_ready() will remain false due to having pending keys. | |
| 857 cryptographer->AddKey(key_params); | |
| 858 success = false; | |
| 859 } | |
| 860 } // is_explicit | |
| 861 } // cryptographer->has_pending_keys() | |
| 862 } else { // nigori_has_explicit_passphrase == true | |
| 863 // Case 6. We do not want to override a previously set explicit passphrase, | |
| 864 // so we return a failure. | |
| 865 DVLOG(1) << "Failing because an explicit passphrase is already set."; | |
| 866 success = false; | |
| 867 } | |
| 868 | |
| 869 DVLOG_IF(1, !success) | |
| 870 << "Failure in SetEncryptionPassphrase; notifying and returning."; | |
| 871 DVLOG_IF(1, success) | |
| 872 << "Successfully set encryption passphrase; updating nigori and " | |
| 873 "reencrypting."; | |
| 874 | |
| 875 FinishSetPassphrase( | |
| 876 success, bootstrap_token, is_explicit, &trans, &node); | |
| 877 } | |
| 878 | |
| 879 void SyncManagerImpl::SetDecryptionPassphrase( | |
| 880 const std::string& passphrase) { | |
| 881 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 882 // We do not accept empty passphrases. | |
| 883 if (passphrase.empty()) { | |
| 884 NOTREACHED() << "Cannot decrypt with an empty passphrase."; | |
| 885 return; | |
| 886 } | |
| 887 | |
| 888 // All accesses to the cryptographer are protected by a transaction. | |
| 889 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 890 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 891 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 892 WriteNode node(&trans); | |
| 893 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 894 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 895 NOTREACHED(); | |
| 896 return; | |
| 897 } | |
| 898 | |
| 899 if (!cryptographer->has_pending_keys()) { | |
| 900 // Note that this *can* happen in a rare situation where data is | |
| 901 // re-encrypted on another client while a SetDecryptionPassphrase() call is | |
| 902 // in-flight on this client. It is rare enough that we choose to do nothing. | |
| 903 NOTREACHED() << "Attempt to set decryption passphrase failed because there " | |
| 904 << "were no pending keys."; | |
| 905 return; | |
| 906 } | |
| 907 | |
| 908 bool nigori_has_explicit_passphrase = | |
| 909 node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 910 std::string bootstrap_token; | |
| 911 sync_pb::EncryptedData pending_keys; | |
| 912 pending_keys = cryptographer->GetPendingKeys(); | |
| 913 bool success = false; | |
| 914 | |
| 915 // There are three cases to handle here: | |
| 916 // 7. We're using the current GAIA password to decrypt the pending keys. This | |
| 917 // happens when signing in to an account with a previously set implicit | |
| 918 // passphrase, where the data is already encrypted with the newest GAIA | |
| 919 // password. | |
| 920 // 8. The user is providing an old GAIA password to decrypt the pending keys. | |
| 921 // In this case, the user is using an implicit passphrase, but has changed | |
| 922 // their password since they last encrypted their data, and therefore | |
| 923 // their current GAIA password was unable to decrypt the data. This will | |
| 924 // happen when the user is setting up a new profile with a previously | |
| 925 // encrypted account (after changing passwords). | |
| 926 // 9. The user is providing a previously set explicit passphrase to decrypt | |
| 927 // the pending keys. | |
| 928 if (!nigori_has_explicit_passphrase) { | |
| 929 if (cryptographer->is_initialized()) { | |
| 930 // We only want to change the default encryption key to the pending | |
| 931 // one if the pending keybag already contains the current default. | |
| 932 // This covers the case where a different client re-encrypted | |
| 933 // everything with a newer gaia passphrase (and hence the keybag | |
| 934 // contains keys from all previously used gaia passphrases). | |
| 935 // Otherwise, we're in a situation where the pending keys are | |
| 936 // encrypted with an old gaia passphrase, while the default is the | |
| 937 // current gaia passphrase. In that case, we preserve the default. | |
| 938 Cryptographer temp_cryptographer(encryptor_); | |
| 939 temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys()); | |
| 940 if (temp_cryptographer.DecryptPendingKeys(key_params)) { | |
| 941 // Check to see if the pending bag of keys contains the current | |
| 942 // default key. | |
| 943 sync_pb::EncryptedData encrypted; | |
| 944 cryptographer->GetKeys(&encrypted); | |
| 945 if (temp_cryptographer.CanDecrypt(encrypted)) { | |
| 946 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 947 << "decryption, overwriting default."; | |
| 948 // Case 7. The pending keybag contains the current default. Go ahead | |
| 949 // and update the cryptographer, letting the default change. | |
| 950 cryptographer->DecryptPendingKeys(key_params); | |
| 951 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 952 success = true; | |
| 953 } else { | |
| 954 // Case 8. The pending keybag does not contain the current default | |
| 955 // encryption key. We decrypt the pending keys here, and in | |
| 956 // FinishSetPassphrase, re-encrypt everything with the current GAIA | |
| 957 // passphrase instead of the passphrase just provided by the user. | |
| 958 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 959 << "decryption, restoring implicit internal passphrase " | |
| 960 << "as default."; | |
| 961 std::string bootstrap_token_from_current_key; | |
| 962 cryptographer->GetBootstrapToken( | |
| 963 &bootstrap_token_from_current_key); | |
| 964 cryptographer->DecryptPendingKeys(key_params); | |
| 965 // Overwrite the default from the pending keys. | |
| 966 cryptographer->AddKeyFromBootstrapToken( | |
| 967 bootstrap_token_from_current_key); | |
| 968 success = true; | |
| 969 } | |
| 970 } else { // !temp_cryptographer.DecryptPendingKeys(..) | |
| 971 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 972 success = false; | |
| 973 } // temp_cryptographer.DecryptPendingKeys(...) | |
| 974 } else { // cryptographer->is_initialized() == false | |
| 975 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 976 // This can happpen in two cases: | |
| 977 // - First time sync on android, where we'll never have a | |
| 978 // !user_provided passphrase. | |
| 979 // - This is a restart for a client that lost their bootstrap token. | |
| 980 // In both cases, we should go ahead and initialize the cryptographer | |
| 981 // and persist the new bootstrap token. | |
| 982 // | |
| 983 // Note: at this point, we cannot distinguish between cases 7 and 8 | |
| 984 // above. This user provided passphrase could be the current or the | |
| 985 // old. But, as long as we persist the token, there's nothing more | |
| 986 // we can do. | |
| 987 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 988 DVLOG(1) << "Implicit user provided passphrase accepted, initializing" | |
| 989 << " cryptographer."; | |
| 990 success = true; | |
| 991 } else { | |
| 992 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 993 success = false; | |
| 994 } | |
| 995 } // cryptographer->is_initialized() | |
| 996 } else { // nigori_has_explicit_passphrase == true | |
| 997 // Case 9. Encryption was done with an explicit passphrase, and we decrypt | |
| 998 // with the passphrase provided by the user. | |
| 999 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 1000 DVLOG(1) << "Explicit passphrase accepted for decryption."; | |
| 1001 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 1002 success = true; | |
| 1003 } else { | |
| 1004 DVLOG(1) << "Explicit passphrase failed to decrypt."; | |
| 1005 success = false; | |
| 1006 } | |
| 1007 } // nigori_has_explicit_passphrase | |
| 1008 | |
| 1009 DVLOG_IF(1, !success) | |
| 1010 << "Failure in SetDecryptionPassphrase; notifying and returning."; | |
| 1011 DVLOG_IF(1, success) | |
| 1012 << "Successfully set decryption passphrase; updating nigori and " | |
| 1013 "reencrypting."; | |
| 1014 | |
| 1015 FinishSetPassphrase(success, | |
| 1016 bootstrap_token, | |
| 1017 nigori_has_explicit_passphrase, | |
| 1018 &trans, | |
| 1019 &node); | |
| 1020 } | |
| 1021 | |
| 1022 void SyncManagerImpl::FinishSetPassphrase( | |
| 1023 bool success, | |
| 1024 const std::string& bootstrap_token, | |
| 1025 bool is_explicit, | |
| 1026 WriteTransaction* trans, | |
| 1027 WriteNode* nigori_node) { | |
| 1028 Cryptographer* cryptographer = trans->GetCryptographer(); | |
| 1029 NotifyCryptographerState(cryptographer); | |
| 1030 | |
| 1031 // It's possible we need to change the bootstrap token even if we failed to | |
| 1032 // set the passphrase (for example if we need to preserve the new GAIA | |
| 1033 // passphrase). | |
| 1034 if (!bootstrap_token.empty()) { | |
| 1035 DVLOG(1) << "Bootstrap token updated."; | |
| 1036 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1037 OnBootstrapTokenUpdated(bootstrap_token)); | |
| 1038 } | |
| 1039 | |
| 1040 if (!success) { | |
| 1041 if (cryptographer->is_ready()) { | |
| 1042 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " | |
| 1043 << "was ready."; | |
| 1044 } else if (cryptographer->has_pending_keys()) { | |
| 1045 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1046 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1047 cryptographer->GetPendingKeys())); | |
| 1048 } else { | |
| 1049 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1050 OnPassphraseRequired(REASON_ENCRYPTION, | |
| 1051 sync_pb::EncryptedData())); | |
| 1052 } | |
| 1053 return; | |
| 1054 } | |
| 1055 | |
| 1056 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1057 OnPassphraseAccepted()); | |
| 1058 DCHECK(cryptographer->is_ready()); | |
| 1059 | |
| 1060 // TODO(tim): Bug 58231. It would be nice if setting a passphrase didn't | |
| 1061 // require messing with the Nigori node, because we can't set a passphrase | |
| 1062 // until download conditions are met vs Cryptographer init. It seems like | |
| 1063 // it's safe to defer this work. | |
| 1064 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); | |
| 1065 // Does not modify specifics.encrypted() if the original decrypted data was | |
| 1066 // the same. | |
| 1067 if (!cryptographer->GetKeys(specifics.mutable_encrypted())) { | |
| 1068 NOTREACHED(); | |
| 1069 return; | |
| 1070 } | |
| 1071 specifics.set_using_explicit_passphrase(is_explicit); | |
| 1072 nigori_node->SetNigoriSpecifics(specifics); | |
| 1073 | |
| 1074 // Does nothing if everything is already encrypted or the cryptographer has | |
| 1075 // pending keys. | |
| 1076 ReEncryptEverything(trans); | |
| 1077 } | |
| 1078 | |
| 1079 bool SyncManagerImpl::IsUsingExplicitPassphrase() { | |
| 1080 ReadTransaction trans(FROM_HERE, &share_); | |
| 1081 ReadNode node(&trans); | |
| 1082 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 1083 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 1084 NOTREACHED(); | |
| 1085 return false; | |
| 1086 } | |
| 1087 | |
| 1088 return node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 1089 } | |
| 1090 | |
| 1091 bool SyncManagerImpl::GetKeystoreKeyBootstrapToken(std::string* token) { | 687 bool SyncManagerImpl::GetKeystoreKeyBootstrapToken(std::string* token) { |
| 1092 ReadTransaction trans(FROM_HERE, GetUserShare()); | 688 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 1093 return trans.GetCryptographer()->GetKeystoreKeyBootstrapToken(token); | 689 return trans.GetCryptographer()->GetKeystoreKeyBootstrapToken(token); |
| 1094 } | 690 } |
| 1095 | 691 |
| 1096 void SyncManagerImpl::RefreshEncryption() { | |
| 1097 DCHECK(initialized_); | |
| 1098 | |
| 1099 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 1100 WriteNode node(&trans); | |
| 1101 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 1102 NOTREACHED() << "Unable to set encrypted datatypes because Nigori node not " | |
| 1103 << "found."; | |
| 1104 return; | |
| 1105 } | |
| 1106 | |
| 1107 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1108 | |
| 1109 if (!cryptographer->is_ready()) { | |
| 1110 DVLOG(1) << "Attempting to encrypt datatypes when cryptographer not " | |
| 1111 << "initialized, prompting for passphrase."; | |
| 1112 // TODO(zea): this isn't really decryption, but that's the only way we have | |
| 1113 // to prompt the user for a passsphrase. See http://crbug.com/91379. | |
| 1114 sync_pb::EncryptedData pending_keys; | |
| 1115 if (cryptographer->has_pending_keys()) | |
| 1116 pending_keys = cryptographer->GetPendingKeys(); | |
| 1117 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1118 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1119 pending_keys)); | |
| 1120 return; | |
| 1121 } | |
| 1122 | |
| 1123 UpdateNigoriEncryptionState(cryptographer, &node); | |
| 1124 | |
| 1125 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 1126 | |
| 1127 // We reencrypt everything regardless of whether the set of encrypted | |
| 1128 // types changed to ensure that any stray unencrypted entries are overwritten. | |
| 1129 ReEncryptEverything(&trans); | |
| 1130 } | |
| 1131 | |
| 1132 // This function iterates over all encrypted types. There are many scenarios in | |
| 1133 // which data for some or all types is not currently available. In that case, | |
| 1134 // the lookup of the root node will fail and we will skip encryption for that | |
| 1135 // type. | |
| 1136 void SyncManagerImpl::ReEncryptEverything( | |
| 1137 WriteTransaction* trans) { | |
| 1138 Cryptographer* cryptographer = trans->GetCryptographer(); | |
| 1139 if (!cryptographer || !cryptographer->is_ready()) | |
| 1140 return; | |
| 1141 ModelTypeSet encrypted_types = GetEncryptedTypes(trans); | |
| 1142 for (ModelTypeSet::Iterator iter = encrypted_types.First(); | |
| 1143 iter.Good(); iter.Inc()) { | |
| 1144 if (iter.Get() == PASSWORDS || iter.Get() == NIGORI) | |
| 1145 continue; // These types handle encryption differently. | |
| 1146 | |
| 1147 ReadNode type_root(trans); | |
| 1148 std::string tag = ModelTypeToRootTag(iter.Get()); | |
| 1149 if (type_root.InitByTagLookup(tag) != BaseNode::INIT_OK) | |
| 1150 continue; // Don't try to reencrypt if the type's data is unavailable. | |
| 1151 | |
| 1152 // Iterate through all children of this datatype. | |
| 1153 std::queue<int64> to_visit; | |
| 1154 int64 child_id = type_root.GetFirstChildId(); | |
| 1155 to_visit.push(child_id); | |
| 1156 while (!to_visit.empty()) { | |
| 1157 child_id = to_visit.front(); | |
| 1158 to_visit.pop(); | |
| 1159 if (child_id == kInvalidId) | |
| 1160 continue; | |
| 1161 | |
| 1162 WriteNode child(trans); | |
| 1163 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) { | |
| 1164 NOTREACHED(); | |
| 1165 continue; | |
| 1166 } | |
| 1167 if (child.GetIsFolder()) { | |
| 1168 to_visit.push(child.GetFirstChildId()); | |
| 1169 } | |
| 1170 if (child.GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { | |
| 1171 // Rewrite the specifics of the node with encrypted data if necessary | |
| 1172 // (only rewrite the non-unique folders). | |
| 1173 child.ResetFromSpecifics(); | |
| 1174 } | |
| 1175 to_visit.push(child.GetSuccessorId()); | |
| 1176 } | |
| 1177 } | |
| 1178 | |
| 1179 // Passwords are encrypted with their own legacy scheme. Passwords are always | |
| 1180 // encrypted so we don't need to check GetEncryptedTypes() here. | |
| 1181 ReadNode passwords_root(trans); | |
| 1182 std::string passwords_tag = ModelTypeToRootTag(PASSWORDS); | |
| 1183 if (passwords_root.InitByTagLookup(passwords_tag) == BaseNode::INIT_OK) { | |
| 1184 int64 child_id = passwords_root.GetFirstChildId(); | |
| 1185 while (child_id != kInvalidId) { | |
| 1186 WriteNode child(trans); | |
| 1187 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) { | |
| 1188 NOTREACHED(); | |
| 1189 return; | |
| 1190 } | |
| 1191 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); | |
| 1192 child_id = child.GetSuccessorId(); | |
| 1193 } | |
| 1194 } | |
| 1195 | |
| 1196 // NOTE: We notify from within a transaction. | |
| 1197 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1198 OnEncryptionComplete()); | |
| 1199 } | |
| 1200 | |
| 1201 void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) { | 692 void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) { |
| 1202 DCHECK(thread_checker_.CalledOnValidThread()); | 693 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1203 observers_.AddObserver(observer); | 694 observers_.AddObserver(observer); |
| 1204 } | 695 } |
| 1205 | 696 |
| 1206 void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) { | 697 void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) { |
| 1207 DCHECK(thread_checker_.CalledOnValidThread()); | 698 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1208 observers_.RemoveObserver(observer); | 699 observers_.RemoveObserver(observer); |
| 1209 } | 700 } |
| 1210 | 701 |
| 1211 void SyncManagerImpl::StopSyncingForShutdown(const base::Closure& callback) { | 702 void SyncManagerImpl::StopSyncingForShutdown(const base::Closure& callback) { |
| 1212 DVLOG(2) << "StopSyncingForShutdown"; | 703 DVLOG(2) << "StopSyncingForShutdown"; |
| 1213 scheduler_->RequestStop(callback); | 704 scheduler_->RequestStop(callback); |
| 1214 if (connection_manager_.get()) | 705 if (connection_manager_.get()) |
| 1215 connection_manager_->TerminateAllIO(); | 706 connection_manager_->TerminateAllIO(); |
| 1216 } | 707 } |
| 1217 | 708 |
| 1218 void SyncManagerImpl::ShutdownOnSyncThread() { | 709 void SyncManagerImpl::ShutdownOnSyncThread() { |
| 1219 DCHECK(thread_checker_.CalledOnValidThread()); | 710 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1220 | 711 |
| 1221 // Prevent any in-flight method calls from running. Also | 712 // Prevent any in-flight method calls from running. Also |
| 1222 // invalidates |weak_handle_this_| and |change_observer_|. | 713 // invalidates |weak_handle_this_| and |change_observer_|. |
| 1223 weak_ptr_factory_.InvalidateWeakPtrs(); | 714 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 1224 js_mutation_event_observer_.InvalidateWeakPtrs(); | 715 js_mutation_event_observer_.InvalidateWeakPtrs(); |
| 1225 | 716 |
| 1226 scheduler_.reset(); | 717 scheduler_.reset(); |
| 1227 session_context_.reset(); | 718 session_context_.reset(); |
| 1228 | 719 |
| 720 if (sync_encryption_handler_.get()) { |
| 721 sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_); |
| 722 sync_encryption_handler_->RemoveObserver(this); |
| 723 } |
| 724 |
| 1229 SetJsEventHandler(WeakHandle<JsEventHandler>()); | 725 SetJsEventHandler(WeakHandle<JsEventHandler>()); |
| 1230 RemoveObserver(&js_sync_manager_observer_); | 726 RemoveObserver(&js_sync_manager_observer_); |
| 1231 | 727 |
| 1232 RemoveObserver(&debug_info_event_listener_); | 728 RemoveObserver(&debug_info_event_listener_); |
| 1233 | 729 |
| 1234 // |sync_notifier_| and |connection_manager_| may end up being NULL here in | 730 // |sync_notifier_| and |connection_manager_| may end up being NULL here in |
| 1235 // tests (in synchronous initialization mode). | 731 // tests (in synchronous initialization mode). |
| 1236 // | 732 // |
| 1237 // TODO(akalin): Fix this behavior. | 733 // TODO(akalin): Fix this behavior. |
| 1238 | 734 |
| 1239 if (sync_notifier_.get()) | 735 if (sync_notifier_.get()) |
| 1240 sync_notifier_->UnregisterHandler(this); | 736 sync_notifier_->UnregisterHandler(this); |
| 1241 sync_notifier_.reset(); | 737 sync_notifier_.reset(); |
| 1242 | 738 |
| 1243 if (connection_manager_.get()) | 739 if (connection_manager_.get()) |
| 1244 connection_manager_->RemoveListener(this); | 740 connection_manager_->RemoveListener(this); |
| 1245 connection_manager_.reset(); | 741 connection_manager_.reset(); |
| 1246 | 742 |
| 1247 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 743 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 1248 observing_ip_address_changes_ = false; | 744 observing_ip_address_changes_ = false; |
| 1249 | 745 |
| 1250 if (initialized_ && directory()) { | 746 if (initialized_ && directory()) { |
| 1251 { | |
| 1252 // Cryptographer should only be accessed while holding a | |
| 1253 // transaction. | |
| 1254 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
| 1255 trans.GetCryptographer()->RemoveObserver(this); | |
| 1256 } | |
| 1257 directory()->SaveChanges(); | 747 directory()->SaveChanges(); |
| 1258 } | 748 } |
| 1259 | 749 |
| 1260 share_.directory.reset(); | 750 share_.directory.reset(); |
| 1261 | 751 |
| 1262 change_delegate_ = NULL; | 752 change_delegate_ = NULL; |
| 1263 | 753 |
| 1264 initialized_ = false; | 754 initialized_ = false; |
| 1265 | 755 |
| 1266 // We reset these here, since only now we know they will not be | 756 // We reset these here, since only now we know they will not be |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) { | 989 void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) { |
| 1500 DCHECK(thread_checker_.CalledOnValidThread()); | 990 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1501 // Only send an event if this is due to a cycle ending and this cycle | 991 // Only send an event if this is due to a cycle ending and this cycle |
| 1502 // concludes a canonical "sync" process; that is, based on what is known | 992 // concludes a canonical "sync" process; that is, based on what is known |
| 1503 // locally we are "all happy" and up-to-date. There may be new changes on | 993 // locally we are "all happy" and up-to-date. There may be new changes on |
| 1504 // the server, but we'll get them on a subsequent sync. | 994 // the server, but we'll get them on a subsequent sync. |
| 1505 // | 995 // |
| 1506 // Notifications are sent at the end of every sync cycle, regardless of | 996 // Notifications are sent at the end of every sync cycle, regardless of |
| 1507 // whether we should sync again. | 997 // whether we should sync again. |
| 1508 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { | 998 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { |
| 1509 { | |
| 1510 // Check to see if we need to notify the frontend that we have newly | |
| 1511 // encrypted types or that we require a passphrase. | |
| 1512 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
| 1513 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1514 // If we've completed a sync cycle and the cryptographer isn't ready | |
| 1515 // yet, prompt the user for a passphrase. | |
| 1516 if (cryptographer->has_pending_keys()) { | |
| 1517 DVLOG(1) << "OnPassPhraseRequired Sent"; | |
| 1518 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); | |
| 1519 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1520 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1521 pending_keys)); | |
| 1522 } else if (!cryptographer->is_ready() && | |
| 1523 event.snapshot.initial_sync_ended().Has(NIGORI)) { | |
| 1524 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " | |
| 1525 << "ready"; | |
| 1526 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1527 OnPassphraseRequired(REASON_ENCRYPTION, | |
| 1528 sync_pb::EncryptedData())); | |
| 1529 } | |
| 1530 | |
| 1531 NotifyCryptographerState(cryptographer); | |
| 1532 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 1533 } | |
| 1534 | |
| 1535 if (!initialized_) { | 999 if (!initialized_) { |
| 1536 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " | 1000 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " |
| 1537 << "initialized"; | 1001 << "initialized"; |
| 1538 return; | 1002 return; |
| 1539 } | 1003 } |
| 1540 | 1004 |
| 1541 if (!event.snapshot.has_more_to_sync()) { | 1005 if (!event.snapshot.has_more_to_sync()) { |
| 1542 { | |
| 1543 // To account for a nigori node arriving with stale/bad data, we ensure | |
| 1544 // that the nigori node is up to date at the end of each cycle. | |
| 1545 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 1546 WriteNode nigori_node(&trans); | |
| 1547 if (nigori_node.InitByTagLookup(kNigoriTag) == BaseNode::INIT_OK) { | |
| 1548 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1549 UpdateNigoriEncryptionState(cryptographer, &nigori_node); | |
| 1550 } | |
| 1551 } | |
| 1552 | |
| 1553 DVLOG(1) << "Sending OnSyncCycleCompleted"; | 1006 DVLOG(1) << "Sending OnSyncCycleCompleted"; |
| 1554 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 1007 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 1555 OnSyncCycleCompleted(event.snapshot)); | 1008 OnSyncCycleCompleted(event.snapshot)); |
| 1556 } | 1009 } |
| 1557 | 1010 |
| 1558 // This is here for tests, which are still using p2p notifications. | 1011 // This is here for tests, which are still using p2p notifications. |
| 1559 // | 1012 // |
| 1560 // TODO(chron): Consider changing this back to track has_more_to_sync | 1013 // TODO(chron): Consider changing this back to track has_more_to_sync |
| 1561 // only notify peers if a successful commit has occurred. | 1014 // only notify peers if a successful commit has occurred. |
| 1562 bool is_notifiable_commit = | 1015 bool is_notifiable_commit = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1592 return; | 1045 return; |
| 1593 } | 1046 } |
| 1594 | 1047 |
| 1595 } | 1048 } |
| 1596 | 1049 |
| 1597 void SyncManagerImpl::SetJsEventHandler( | 1050 void SyncManagerImpl::SetJsEventHandler( |
| 1598 const WeakHandle<JsEventHandler>& event_handler) { | 1051 const WeakHandle<JsEventHandler>& event_handler) { |
| 1599 js_event_handler_ = event_handler; | 1052 js_event_handler_ = event_handler; |
| 1600 js_sync_manager_observer_.SetJsEventHandler(js_event_handler_); | 1053 js_sync_manager_observer_.SetJsEventHandler(js_event_handler_); |
| 1601 js_mutation_event_observer_.SetJsEventHandler(js_event_handler_); | 1054 js_mutation_event_observer_.SetJsEventHandler(js_event_handler_); |
| 1055 js_sync_encryption_handler_observer_.SetJsEventHandler(js_event_handler_); |
| 1602 } | 1056 } |
| 1603 | 1057 |
| 1604 void SyncManagerImpl::ProcessJsMessage( | 1058 void SyncManagerImpl::ProcessJsMessage( |
| 1605 const std::string& name, const JsArgList& args, | 1059 const std::string& name, const JsArgList& args, |
| 1606 const WeakHandle<JsReplyHandler>& reply_handler) { | 1060 const WeakHandle<JsReplyHandler>& reply_handler) { |
| 1607 if (!initialized_) { | 1061 if (!initialized_) { |
| 1608 NOTREACHED(); | 1062 NOTREACHED(); |
| 1609 return; | 1063 return; |
| 1610 } | 1064 } |
| 1611 | 1065 |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1797 id, &child_handles); | 1251 id, &child_handles); |
| 1798 for (syncable::Directory::ChildHandles::const_iterator it = | 1252 for (syncable::Directory::ChildHandles::const_iterator it = |
| 1799 child_handles.begin(); it != child_handles.end(); ++it) { | 1253 child_handles.begin(); it != child_handles.end(); ++it) { |
| 1800 child_ids->Append(Value::CreateStringValue( | 1254 child_ids->Append(Value::CreateStringValue( |
| 1801 base::Int64ToString(*it))); | 1255 base::Int64ToString(*it))); |
| 1802 } | 1256 } |
| 1803 } | 1257 } |
| 1804 return JsArgList(&return_args); | 1258 return JsArgList(&return_args); |
| 1805 } | 1259 } |
| 1806 | 1260 |
| 1807 void SyncManagerImpl::OnEncryptedTypesChanged( | |
| 1808 ModelTypeSet encrypted_types, | |
| 1809 bool encrypt_everything) { | |
| 1810 // NOTE: We're in a transaction. | |
| 1811 FOR_EACH_OBSERVER( | |
| 1812 SyncManager::Observer, observers_, | |
| 1813 OnEncryptedTypesChanged(encrypted_types, encrypt_everything)); | |
| 1814 } | |
| 1815 | |
| 1816 void SyncManagerImpl::UpdateNotificationInfo( | 1261 void SyncManagerImpl::UpdateNotificationInfo( |
| 1817 const ModelTypePayloadMap& type_payloads) { | 1262 const ModelTypePayloadMap& type_payloads) { |
| 1818 for (ModelTypePayloadMap::const_iterator it = type_payloads.begin(); | 1263 for (ModelTypePayloadMap::const_iterator it = type_payloads.begin(); |
| 1819 it != type_payloads.end(); ++it) { | 1264 it != type_payloads.end(); ++it) { |
| 1820 NotificationInfo* info = ¬ification_info_map_[it->first]; | 1265 NotificationInfo* info = ¬ification_info_map_[it->first]; |
| 1821 info->total_count++; | 1266 info->total_count++; |
| 1822 info->payload = it->second; | 1267 info->payload = it->second; |
| 1823 } | 1268 } |
| 1824 } | 1269 } |
| 1825 | 1270 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1904 found_experiment = true; | 1349 found_experiment = true; |
| 1905 } | 1350 } |
| 1906 return found_experiment; | 1351 return found_experiment; |
| 1907 } | 1352 } |
| 1908 | 1353 |
| 1909 bool SyncManagerImpl::HasUnsyncedItems() { | 1354 bool SyncManagerImpl::HasUnsyncedItems() { |
| 1910 ReadTransaction trans(FROM_HERE, GetUserShare()); | 1355 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 1911 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); | 1356 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); |
| 1912 } | 1357 } |
| 1913 | 1358 |
| 1359 SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() { |
| 1360 return sync_encryption_handler_.get(); |
| 1361 } |
| 1362 |
| 1914 // static. | 1363 // static. |
| 1915 int SyncManagerImpl::GetDefaultNudgeDelay() { | 1364 int SyncManagerImpl::GetDefaultNudgeDelay() { |
| 1916 return kDefaultNudgeDelayMilliseconds; | 1365 return kDefaultNudgeDelayMilliseconds; |
| 1917 } | 1366 } |
| 1918 | 1367 |
| 1919 // static. | 1368 // static. |
| 1920 int SyncManagerImpl::GetPreferencesNudgeDelay() { | 1369 int SyncManagerImpl::GetPreferencesNudgeDelay() { |
| 1921 return kPreferencesNudgeDelayMilliseconds; | 1370 return kPreferencesNudgeDelayMilliseconds; |
| 1922 } | 1371 } |
| 1923 | 1372 |
| 1924 } // namespace syncer | 1373 } // namespace syncer |
| OLD | NEW |