| 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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 UpdateCredentials(credentials); | 458 UpdateCredentials(credentials); |
| 484 | 459 |
| 485 // Cryptographer should only be accessed while holding a | 460 // Cryptographer should only be accessed while holding a |
| 486 // transaction. Grabbing the user share for the transaction | 461 // transaction. Grabbing the user share for the transaction |
| 487 // checks the initialization state, so this must come after | 462 // checks the initialization state, so this must come after |
| 488 // |initialized_| is set to true. | 463 // |initialized_| is set to true. |
| 489 ReadTransaction trans(FROM_HERE, GetUserShare()); | 464 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 490 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); | 465 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); |
| 491 trans.GetCryptographer()->BootstrapKeystoreKey( | 466 trans.GetCryptographer()->BootstrapKeystoreKey( |
| 492 restored_keystore_key_for_bootstrapping); | 467 restored_keystore_key_for_bootstrapping); |
| 493 trans.GetCryptographer()->AddObserver(this); | 468 |
| 469 sync_encryption_handler_.reset(new SyncEncryptionHandlerImpl( |
| 470 &share_, |
| 471 trans.GetCryptographer())); |
| 472 sync_encryption_handler_->AddObserver(this); |
| 473 sync_encryption_handler_->AddObserver(&debug_info_event_listener_); |
| 474 sync_encryption_handler_->AddObserver(&js_sync_encryption_handler_observer_); |
| 475 trans.GetCryptographer()->SetSyncEncryptionHandlerDelegate( |
| 476 sync_encryption_handler_.get()); |
| 494 | 477 |
| 495 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 478 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 496 OnInitializationComplete( | 479 OnInitializationComplete( |
| 497 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), | 480 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), |
| 498 true, InitialSyncEndedTypes())); | 481 true, InitialSyncEndedTypes())); |
| 499 } | 482 } |
| 500 | 483 |
| 501 void SyncManagerImpl::RefreshNigori(const std::string& chrome_version, | 484 void SyncManagerImpl::UpdateSessionNameCallback( |
| 502 const base::Closure& done_callback) { | |
| 503 DCHECK(initialized_); | |
| 504 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 505 GetSessionName( | |
| 506 blocking_task_runner_, | |
| 507 base::Bind( | |
| 508 &SyncManagerImpl::UpdateCryptographerAndNigoriCallback, | |
| 509 weak_ptr_factory_.GetWeakPtr(), | |
| 510 chrome_version, | |
| 511 done_callback)); | |
| 512 } | |
| 513 | |
| 514 void SyncManagerImpl::UpdateNigoriEncryptionState( | |
| 515 Cryptographer* cryptographer, | |
| 516 WriteNode* nigori_node) { | |
| 517 DCHECK(nigori_node); | |
| 518 sync_pb::NigoriSpecifics nigori = nigori_node->GetNigoriSpecifics(); | |
| 519 | |
| 520 if (cryptographer->is_ready() && | |
| 521 nigori_overwrite_count_ < kNigoriOverwriteLimit) { | |
| 522 // Does not modify the encrypted blob if the unencrypted data already | |
| 523 // matches what is about to be written. | |
| 524 sync_pb::EncryptedData original_keys = nigori.encrypted(); | |
| 525 if (!cryptographer->GetKeys(nigori.mutable_encrypted())) | |
| 526 NOTREACHED(); | |
| 527 | |
| 528 if (nigori.encrypted().SerializeAsString() != | |
| 529 original_keys.SerializeAsString()) { | |
| 530 // We've updated the nigori node's encryption keys. In order to prevent | |
| 531 // a possible looping of two clients constantly overwriting each other, | |
| 532 // we limit the absolute number of overwrites per client instantiation. | |
| 533 nigori_overwrite_count_++; | |
| 534 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", | |
| 535 nigori_overwrite_count_); | |
| 536 } | |
| 537 | |
| 538 // Note: we don't try to set using_explicit_passphrase here since if that | |
| 539 // is lost the user can always set it again. The main point is to preserve | |
| 540 // the encryption keys so all data remains decryptable. | |
| 541 } | |
| 542 cryptographer->UpdateNigoriFromEncryptedTypes(&nigori); | |
| 543 | |
| 544 // If nothing has changed, this is a no-op. | |
| 545 nigori_node->SetNigoriSpecifics(nigori); | |
| 546 } | |
| 547 | |
| 548 void SyncManagerImpl::UpdateCryptographerAndNigoriCallback( | |
| 549 const std::string& chrome_version, | 485 const std::string& chrome_version, |
| 550 const base::Closure& done_callback, | |
| 551 const std::string& session_name) { | 486 const std::string& session_name) { |
| 552 if (!directory()->initial_sync_ended_for_type(NIGORI)) { | 487 WriteTransaction trans(FROM_HERE, GetUserShare()); |
| 553 done_callback.Run(); // Should only happen during first time sync. | 488 WriteNode node(&trans); |
| 489 // TODO(rlarocque): switch to device info node. |
| 490 if (node.InitByTagLookup(syncer::kNigoriTag) != syncer::BaseNode::INIT_OK) { |
| 554 return; | 491 return; |
| 555 } | 492 } |
| 556 | 493 |
| 557 bool success = false; | 494 sync_pb::NigoriSpecifics nigori(node.GetNigoriSpecifics()); |
| 558 { | 495 // Add or update device information. |
| 559 WriteTransaction trans(FROM_HERE, GetUserShare()); | 496 bool contains_this_device = false; |
| 560 Cryptographer* cryptographer = trans.GetCryptographer(); | 497 for (int i = 0; i < nigori.device_information_size(); ++i) { |
| 561 WriteNode node(&trans); | 498 const sync_pb::DeviceInformation& device_information = |
| 562 | 499 nigori.device_information(i); |
| 563 if (node.InitByTagLookup(kNigoriTag) == BaseNode::INIT_OK) { | 500 if (device_information.cache_guid() == directory()->cache_guid()) { |
| 564 sync_pb::NigoriSpecifics nigori(node.GetNigoriSpecifics()); | 501 // Update the version number in case it changed due to an update. |
| 565 Cryptographer::UpdateResult result = cryptographer->Update(nigori); | 502 if (device_information.chrome_version() != chrome_version) { |
| 566 if (result == Cryptographer::NEEDS_PASSPHRASE) { | 503 sync_pb::DeviceInformation* mutable_device_information = |
| 567 sync_pb::EncryptedData pending_keys; | 504 nigori.mutable_device_information(i); |
| 568 if (cryptographer->has_pending_keys()) | 505 mutable_device_information->set_chrome_version( |
| 569 pending_keys = cryptographer->GetPendingKeys(); | 506 chrome_version); |
| 570 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 571 OnPassphraseRequired(REASON_DECRYPTION, | |
| 572 pending_keys)); | |
| 573 } | 507 } |
| 574 | 508 contains_this_device = true; |
| 575 // Add or update device information. | |
| 576 bool contains_this_device = false; | |
| 577 for (int i = 0; i < nigori.device_information_size(); ++i) { | |
| 578 const sync_pb::DeviceInformation& device_information = | |
| 579 nigori.device_information(i); | |
| 580 if (device_information.cache_guid() == directory()->cache_guid()) { | |
| 581 // Update the version number in case it changed due to an update. | |
| 582 if (device_information.chrome_version() != chrome_version) { | |
| 583 sync_pb::DeviceInformation* mutable_device_information = | |
| 584 nigori.mutable_device_information(i); | |
| 585 mutable_device_information->set_chrome_version( | |
| 586 chrome_version); | |
| 587 } | |
| 588 contains_this_device = true; | |
| 589 } | |
| 590 } | |
| 591 | |
| 592 if (!contains_this_device) { | |
| 593 sync_pb::DeviceInformation* device_information = | |
| 594 nigori.add_device_information(); | |
| 595 device_information->set_cache_guid(directory()->cache_guid()); | |
| 596 #if defined(OS_CHROMEOS) | |
| 597 device_information->set_platform("ChromeOS"); | |
| 598 #elif defined(OS_LINUX) | |
| 599 device_information->set_platform("Linux"); | |
| 600 #elif defined(OS_MACOSX) | |
| 601 device_information->set_platform("Mac"); | |
| 602 #elif defined(OS_WIN) | |
| 603 device_information->set_platform("Windows"); | |
| 604 #endif | |
| 605 device_information->set_name(session_name); | |
| 606 device_information->set_chrome_version(chrome_version); | |
| 607 } | |
| 608 // Disabled to avoid nigori races. TODO(zea): re-enable. crbug.com/122837 | |
| 609 // node.SetNigoriSpecifics(nigori); | |
| 610 | |
| 611 // Make sure the nigori node has the up to date encryption info. | |
| 612 UpdateNigoriEncryptionState(cryptographer, &node); | |
| 613 | |
| 614 NotifyCryptographerState(cryptographer); | |
| 615 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 616 | |
| 617 success = cryptographer->is_ready(); | |
| 618 } else { | |
| 619 NOTREACHED(); | |
| 620 } | 509 } |
| 621 } | 510 } |
| 622 | 511 |
| 623 if (success) | 512 if (!contains_this_device) { |
| 624 RefreshEncryption(); | 513 sync_pb::DeviceInformation* device_information = |
| 625 done_callback.Run(); | 514 nigori.add_device_information(); |
| 515 device_information->set_cache_guid(directory()->cache_guid()); |
| 516 #if defined(OS_CHROMEOS) |
| 517 device_information->set_platform("ChromeOS"); |
| 518 #elif defined(OS_LINUX) |
| 519 device_information->set_platform("Linux"); |
| 520 #elif defined(OS_MACOSX) |
| 521 device_information->set_platform("Mac"); |
| 522 #elif defined(OS_WIN) |
| 523 device_information->set_platform("Windows"); |
| 524 #endif |
| 525 device_information->set_name(session_name); |
| 526 device_information->set_chrome_version(chrome_version); |
| 527 } |
| 528 node.SetNigoriSpecifics(nigori); |
| 626 } | 529 } |
| 627 | 530 |
| 628 void SyncManagerImpl::NotifyCryptographerState(Cryptographer * cryptographer) { | 531 |
| 629 // TODO(lipalani): Explore the possibility of hooking this up to | 532 void SyncManagerImpl::OnPassphraseRequired( |
| 630 // SyncManager::Observer and making |AllStatus| a listener for that. | 533 PassphraseRequiredReason reason, |
| 534 const sync_pb::EncryptedData& pending_keys) { |
| 535 // Does nothing. |
| 536 } |
| 537 |
| 538 void SyncManagerImpl::OnPassphraseAccepted() { |
| 539 // Does nothing. |
| 540 } |
| 541 |
| 542 void SyncManagerImpl::OnBootstrapTokenUpdated( |
| 543 const std::string& bootstrap_token) { |
| 544 // Does nothing. |
| 545 } |
| 546 |
| 547 void SyncManagerImpl::OnEncryptedTypesChanged(ModelTypeSet encrypted_types, |
| 548 bool encrypt_everything) { |
| 549 allstatus_.SetEncryptedTypes(encrypted_types); |
| 550 } |
| 551 |
| 552 void SyncManagerImpl::OnEncryptionComplete() { |
| 553 // Does nothing. |
| 554 } |
| 555 |
| 556 void SyncManagerImpl::OnCryptographerStateChanged( |
| 557 Cryptographer* cryptographer) { |
| 631 allstatus_.SetCryptographerReady(cryptographer->is_ready()); | 558 allstatus_.SetCryptographerReady(cryptographer->is_ready()); |
| 632 allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys()); | 559 allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys()); |
| 633 debug_info_event_listener_.SetCryptographerReady(cryptographer->is_ready()); | |
| 634 debug_info_event_listener_.SetCrytographerHasPendingKeys( | |
| 635 cryptographer->has_pending_keys()); | |
| 636 } | 560 } |
| 637 | 561 |
| 638 void SyncManagerImpl::StartSyncingNormally( | 562 void SyncManagerImpl::StartSyncingNormally( |
| 639 const ModelSafeRoutingInfo& routing_info) { | 563 const ModelSafeRoutingInfo& routing_info) { |
| 640 // Start the sync scheduler. | 564 // Start the sync scheduler. |
| 641 // TODO(sync): We always want the newest set of routes when we switch back | 565 // TODO(sync): We always want the newest set of routes when we switch back |
| 642 // to normal mode. Figure out how to enforce set_routing_info is always | 566 // to normal mode. Figure out how to enforce set_routing_info is always |
| 643 // appropriately set and that it's only modified when switching to normal | 567 // appropriately set and that it's only modified when switching to normal |
| 644 // mode. | 568 // mode. |
| 645 DCHECK(thread_checker_.CalledOnValidThread()); | 569 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 ModelTypeSetToObjectIdSet(enabled_types)); | 662 ModelTypeSetToObjectIdSet(enabled_types)); |
| 739 } | 663 } |
| 740 | 664 |
| 741 void SyncManagerImpl::UpdateRegisteredInvalidationIds( | 665 void SyncManagerImpl::UpdateRegisteredInvalidationIds( |
| 742 SyncNotifierObserver* handler, | 666 SyncNotifierObserver* handler, |
| 743 const ObjectIdSet& ids) { | 667 const ObjectIdSet& ids) { |
| 744 DCHECK(thread_checker_.CalledOnValidThread()); | 668 DCHECK(thread_checker_.CalledOnValidThread()); |
| 745 sync_notifier_->UpdateRegisteredIds(handler, ids); | 669 sync_notifier_->UpdateRegisteredIds(handler, ids); |
| 746 } | 670 } |
| 747 | 671 |
| 748 void SyncManagerImpl::SetEncryptionPassphrase( | |
| 749 const std::string& passphrase, | |
| 750 bool is_explicit) { | |
| 751 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 752 // We do not accept empty passphrases. | |
| 753 if (passphrase.empty()) { | |
| 754 NOTREACHED() << "Cannot encrypt with an empty passphrase."; | |
| 755 return; | |
| 756 } | |
| 757 | |
| 758 // All accesses to the cryptographer are protected by a transaction. | |
| 759 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 760 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 761 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 762 WriteNode node(&trans); | |
| 763 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 764 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 765 NOTREACHED(); | |
| 766 return; | |
| 767 } | |
| 768 | |
| 769 bool nigori_has_explicit_passphrase = | |
| 770 node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 771 std::string bootstrap_token; | |
| 772 sync_pb::EncryptedData pending_keys; | |
| 773 if (cryptographer->has_pending_keys()) | |
| 774 pending_keys = cryptographer->GetPendingKeys(); | |
| 775 bool success = false; | |
| 776 | |
| 777 | |
| 778 // There are six cases to handle here: | |
| 779 // 1. The user has no pending keys and is setting their current GAIA password | |
| 780 // as the encryption passphrase. This happens either during first time sync | |
| 781 // with a clean profile, or after re-authenticating on a profile that was | |
| 782 // already signed in with the cryptographer ready. | |
| 783 // 2. The user has no pending keys, and is overwriting an (already provided) | |
| 784 // implicit passphrase with an explicit (custom) passphrase. | |
| 785 // 3. The user has pending keys for an explicit passphrase that is somehow set | |
| 786 // to their current GAIA passphrase. | |
| 787 // 4. The user has pending keys encrypted with their current GAIA passphrase | |
| 788 // and the caller passes in the current GAIA passphrase. | |
| 789 // 5. The user has pending keys encrypted with an older GAIA passphrase | |
| 790 // and the caller passes in the current GAIA passphrase. | |
| 791 // 6. The user has previously done encryption with an explicit passphrase. | |
| 792 // Furthermore, we enforce the fact that the bootstrap encryption token will | |
| 793 // always be derived from the newest GAIA password if the account is using | |
| 794 // an implicit passphrase (even if the data is encrypted with an old GAIA | |
| 795 // password). If the account is using an explicit (custom) passphrase, the | |
| 796 // bootstrap token will be derived from the most recently provided explicit | |
| 797 // passphrase (that was able to decrypt the data). | |
| 798 if (!nigori_has_explicit_passphrase) { | |
| 799 if (!cryptographer->has_pending_keys()) { | |
| 800 if (cryptographer->AddKey(key_params)) { | |
| 801 // Case 1 and 2. We set a new GAIA passphrase when there are no pending | |
| 802 // keys (1), or overwriting an implicit passphrase with a new explicit | |
| 803 // one (2) when there are no pending keys. | |
| 804 DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) | |
| 805 << " passphrase for encryption."; | |
| 806 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 807 success = true; | |
| 808 } else { | |
| 809 NOTREACHED() << "Failed to add key to cryptographer."; | |
| 810 success = false; | |
| 811 } | |
| 812 } else { // cryptographer->has_pending_keys() == true | |
| 813 if (is_explicit) { | |
| 814 // This can only happen if the nigori node is updated with a new | |
| 815 // implicit passphrase while a client is attempting to set a new custom | |
| 816 // passphrase (race condition). | |
| 817 DVLOG(1) << "Failing because an implicit passphrase is already set."; | |
| 818 success = false; | |
| 819 } else { // is_explicit == false | |
| 820 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 821 // Case 4. We successfully decrypted with the implicit GAIA passphrase | |
| 822 // passed in. | |
| 823 DVLOG(1) << "Implicit internal passphrase accepted for decryption."; | |
| 824 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 825 success = true; | |
| 826 } else { | |
| 827 // Case 5. Encryption was done with an old GAIA password, but we were | |
| 828 // provided with the current GAIA password. We need to generate a new | |
| 829 // bootstrap token to preserve it. We build a temporary cryptographer | |
| 830 // to allow us to extract these params without polluting our current | |
| 831 // cryptographer. | |
| 832 DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding " | |
| 833 << "anyways as default passphrase and persisting via " | |
| 834 << "bootstrap token."; | |
| 835 Cryptographer temp_cryptographer(encryptor_); | |
| 836 temp_cryptographer.AddKey(key_params); | |
| 837 temp_cryptographer.GetBootstrapToken(&bootstrap_token); | |
| 838 // We then set the new passphrase as the default passphrase of the | |
| 839 // real cryptographer, even though we have pending keys. This is safe, | |
| 840 // as although Cryptographer::is_initialized() will now be true, | |
| 841 // is_ready() will remain false due to having pending keys. | |
| 842 cryptographer->AddKey(key_params); | |
| 843 success = false; | |
| 844 } | |
| 845 } // is_explicit | |
| 846 } // cryptographer->has_pending_keys() | |
| 847 } else { // nigori_has_explicit_passphrase == true | |
| 848 // Case 6. We do not want to override a previously set explicit passphrase, | |
| 849 // so we return a failure. | |
| 850 DVLOG(1) << "Failing because an explicit passphrase is already set."; | |
| 851 success = false; | |
| 852 } | |
| 853 | |
| 854 DVLOG_IF(1, !success) | |
| 855 << "Failure in SetEncryptionPassphrase; notifying and returning."; | |
| 856 DVLOG_IF(1, success) | |
| 857 << "Successfully set encryption passphrase; updating nigori and " | |
| 858 "reencrypting."; | |
| 859 | |
| 860 FinishSetPassphrase( | |
| 861 success, bootstrap_token, is_explicit, &trans, &node); | |
| 862 } | |
| 863 | |
| 864 void SyncManagerImpl::SetDecryptionPassphrase( | |
| 865 const std::string& passphrase) { | |
| 866 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 867 // We do not accept empty passphrases. | |
| 868 if (passphrase.empty()) { | |
| 869 NOTREACHED() << "Cannot decrypt with an empty passphrase."; | |
| 870 return; | |
| 871 } | |
| 872 | |
| 873 // All accesses to the cryptographer are protected by a transaction. | |
| 874 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 875 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 876 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 877 WriteNode node(&trans); | |
| 878 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 879 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 880 NOTREACHED(); | |
| 881 return; | |
| 882 } | |
| 883 | |
| 884 if (!cryptographer->has_pending_keys()) { | |
| 885 // Note that this *can* happen in a rare situation where data is | |
| 886 // re-encrypted on another client while a SetDecryptionPassphrase() call is | |
| 887 // in-flight on this client. It is rare enough that we choose to do nothing. | |
| 888 NOTREACHED() << "Attempt to set decryption passphrase failed because there " | |
| 889 << "were no pending keys."; | |
| 890 return; | |
| 891 } | |
| 892 | |
| 893 bool nigori_has_explicit_passphrase = | |
| 894 node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 895 std::string bootstrap_token; | |
| 896 sync_pb::EncryptedData pending_keys; | |
| 897 pending_keys = cryptographer->GetPendingKeys(); | |
| 898 bool success = false; | |
| 899 | |
| 900 // There are three cases to handle here: | |
| 901 // 7. We're using the current GAIA password to decrypt the pending keys. This | |
| 902 // happens when signing in to an account with a previously set implicit | |
| 903 // passphrase, where the data is already encrypted with the newest GAIA | |
| 904 // password. | |
| 905 // 8. The user is providing an old GAIA password to decrypt the pending keys. | |
| 906 // In this case, the user is using an implicit passphrase, but has changed | |
| 907 // their password since they last encrypted their data, and therefore | |
| 908 // their current GAIA password was unable to decrypt the data. This will | |
| 909 // happen when the user is setting up a new profile with a previously | |
| 910 // encrypted account (after changing passwords). | |
| 911 // 9. The user is providing a previously set explicit passphrase to decrypt | |
| 912 // the pending keys. | |
| 913 if (!nigori_has_explicit_passphrase) { | |
| 914 if (cryptographer->is_initialized()) { | |
| 915 // We only want to change the default encryption key to the pending | |
| 916 // one if the pending keybag already contains the current default. | |
| 917 // This covers the case where a different client re-encrypted | |
| 918 // everything with a newer gaia passphrase (and hence the keybag | |
| 919 // contains keys from all previously used gaia passphrases). | |
| 920 // Otherwise, we're in a situation where the pending keys are | |
| 921 // encrypted with an old gaia passphrase, while the default is the | |
| 922 // current gaia passphrase. In that case, we preserve the default. | |
| 923 Cryptographer temp_cryptographer(encryptor_); | |
| 924 temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys()); | |
| 925 if (temp_cryptographer.DecryptPendingKeys(key_params)) { | |
| 926 // Check to see if the pending bag of keys contains the current | |
| 927 // default key. | |
| 928 sync_pb::EncryptedData encrypted; | |
| 929 cryptographer->GetKeys(&encrypted); | |
| 930 if (temp_cryptographer.CanDecrypt(encrypted)) { | |
| 931 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 932 << "decryption, overwriting default."; | |
| 933 // Case 7. The pending keybag contains the current default. Go ahead | |
| 934 // and update the cryptographer, letting the default change. | |
| 935 cryptographer->DecryptPendingKeys(key_params); | |
| 936 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 937 success = true; | |
| 938 } else { | |
| 939 // Case 8. The pending keybag does not contain the current default | |
| 940 // encryption key. We decrypt the pending keys here, and in | |
| 941 // FinishSetPassphrase, re-encrypt everything with the current GAIA | |
| 942 // passphrase instead of the passphrase just provided by the user. | |
| 943 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 944 << "decryption, restoring implicit internal passphrase " | |
| 945 << "as default."; | |
| 946 std::string bootstrap_token_from_current_key; | |
| 947 cryptographer->GetBootstrapToken( | |
| 948 &bootstrap_token_from_current_key); | |
| 949 cryptographer->DecryptPendingKeys(key_params); | |
| 950 // Overwrite the default from the pending keys. | |
| 951 cryptographer->AddKeyFromBootstrapToken( | |
| 952 bootstrap_token_from_current_key); | |
| 953 success = true; | |
| 954 } | |
| 955 } else { // !temp_cryptographer.DecryptPendingKeys(..) | |
| 956 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 957 success = false; | |
| 958 } // temp_cryptographer.DecryptPendingKeys(...) | |
| 959 } else { // cryptographer->is_initialized() == false | |
| 960 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 961 // This can happpen in two cases: | |
| 962 // - First time sync on android, where we'll never have a | |
| 963 // !user_provided passphrase. | |
| 964 // - This is a restart for a client that lost their bootstrap token. | |
| 965 // In both cases, we should go ahead and initialize the cryptographer | |
| 966 // and persist the new bootstrap token. | |
| 967 // | |
| 968 // Note: at this point, we cannot distinguish between cases 7 and 8 | |
| 969 // above. This user provided passphrase could be the current or the | |
| 970 // old. But, as long as we persist the token, there's nothing more | |
| 971 // we can do. | |
| 972 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 973 DVLOG(1) << "Implicit user provided passphrase accepted, initializing" | |
| 974 << " cryptographer."; | |
| 975 success = true; | |
| 976 } else { | |
| 977 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 978 success = false; | |
| 979 } | |
| 980 } // cryptographer->is_initialized() | |
| 981 } else { // nigori_has_explicit_passphrase == true | |
| 982 // Case 9. Encryption was done with an explicit passphrase, and we decrypt | |
| 983 // with the passphrase provided by the user. | |
| 984 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 985 DVLOG(1) << "Explicit passphrase accepted for decryption."; | |
| 986 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 987 success = true; | |
| 988 } else { | |
| 989 DVLOG(1) << "Explicit passphrase failed to decrypt."; | |
| 990 success = false; | |
| 991 } | |
| 992 } // nigori_has_explicit_passphrase | |
| 993 | |
| 994 DVLOG_IF(1, !success) | |
| 995 << "Failure in SetDecryptionPassphrase; notifying and returning."; | |
| 996 DVLOG_IF(1, success) | |
| 997 << "Successfully set decryption passphrase; updating nigori and " | |
| 998 "reencrypting."; | |
| 999 | |
| 1000 FinishSetPassphrase(success, | |
| 1001 bootstrap_token, | |
| 1002 nigori_has_explicit_passphrase, | |
| 1003 &trans, | |
| 1004 &node); | |
| 1005 } | |
| 1006 | |
| 1007 void SyncManagerImpl::FinishSetPassphrase( | |
| 1008 bool success, | |
| 1009 const std::string& bootstrap_token, | |
| 1010 bool is_explicit, | |
| 1011 WriteTransaction* trans, | |
| 1012 WriteNode* nigori_node) { | |
| 1013 Cryptographer* cryptographer = trans->GetCryptographer(); | |
| 1014 NotifyCryptographerState(cryptographer); | |
| 1015 | |
| 1016 // It's possible we need to change the bootstrap token even if we failed to | |
| 1017 // set the passphrase (for example if we need to preserve the new GAIA | |
| 1018 // passphrase). | |
| 1019 if (!bootstrap_token.empty()) { | |
| 1020 DVLOG(1) << "Bootstrap token updated."; | |
| 1021 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1022 OnBootstrapTokenUpdated(bootstrap_token)); | |
| 1023 } | |
| 1024 | |
| 1025 if (!success) { | |
| 1026 if (cryptographer->is_ready()) { | |
| 1027 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " | |
| 1028 << "was ready."; | |
| 1029 } else if (cryptographer->has_pending_keys()) { | |
| 1030 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1031 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1032 cryptographer->GetPendingKeys())); | |
| 1033 } else { | |
| 1034 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1035 OnPassphraseRequired(REASON_ENCRYPTION, | |
| 1036 sync_pb::EncryptedData())); | |
| 1037 } | |
| 1038 return; | |
| 1039 } | |
| 1040 | |
| 1041 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1042 OnPassphraseAccepted()); | |
| 1043 DCHECK(cryptographer->is_ready()); | |
| 1044 | |
| 1045 // TODO(tim): Bug 58231. It would be nice if setting a passphrase didn't | |
| 1046 // require messing with the Nigori node, because we can't set a passphrase | |
| 1047 // until download conditions are met vs Cryptographer init. It seems like | |
| 1048 // it's safe to defer this work. | |
| 1049 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); | |
| 1050 // Does not modify specifics.encrypted() if the original decrypted data was | |
| 1051 // the same. | |
| 1052 if (!cryptographer->GetKeys(specifics.mutable_encrypted())) { | |
| 1053 NOTREACHED(); | |
| 1054 return; | |
| 1055 } | |
| 1056 specifics.set_using_explicit_passphrase(is_explicit); | |
| 1057 nigori_node->SetNigoriSpecifics(specifics); | |
| 1058 | |
| 1059 // Does nothing if everything is already encrypted or the cryptographer has | |
| 1060 // pending keys. | |
| 1061 ReEncryptEverything(trans); | |
| 1062 } | |
| 1063 | |
| 1064 bool SyncManagerImpl::IsUsingExplicitPassphrase() { | |
| 1065 ReadTransaction trans(FROM_HERE, &share_); | |
| 1066 ReadNode node(&trans); | |
| 1067 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 1068 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | |
| 1069 NOTREACHED(); | |
| 1070 return false; | |
| 1071 } | |
| 1072 | |
| 1073 return node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 1074 } | |
| 1075 | |
| 1076 bool SyncManagerImpl::GetKeystoreKeyBootstrapToken(std::string* token) { | 672 bool SyncManagerImpl::GetKeystoreKeyBootstrapToken(std::string* token) { |
| 1077 ReadTransaction trans(FROM_HERE, GetUserShare()); | 673 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 1078 return trans.GetCryptographer()->GetKeystoreKeyBootstrapToken(token); | 674 return trans.GetCryptographer()->GetKeystoreKeyBootstrapToken(token); |
| 1079 } | 675 } |
| 1080 | 676 |
| 1081 void SyncManagerImpl::RefreshEncryption() { | |
| 1082 DCHECK(initialized_); | |
| 1083 | |
| 1084 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 1085 WriteNode node(&trans); | |
| 1086 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 1087 NOTREACHED() << "Unable to set encrypted datatypes because Nigori node not " | |
| 1088 << "found."; | |
| 1089 return; | |
| 1090 } | |
| 1091 | |
| 1092 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1093 | |
| 1094 if (!cryptographer->is_ready()) { | |
| 1095 DVLOG(1) << "Attempting to encrypt datatypes when cryptographer not " | |
| 1096 << "initialized, prompting for passphrase."; | |
| 1097 // TODO(zea): this isn't really decryption, but that's the only way we have | |
| 1098 // to prompt the user for a passsphrase. See http://crbug.com/91379. | |
| 1099 sync_pb::EncryptedData pending_keys; | |
| 1100 if (cryptographer->has_pending_keys()) | |
| 1101 pending_keys = cryptographer->GetPendingKeys(); | |
| 1102 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1103 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1104 pending_keys)); | |
| 1105 return; | |
| 1106 } | |
| 1107 | |
| 1108 UpdateNigoriEncryptionState(cryptographer, &node); | |
| 1109 | |
| 1110 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 1111 | |
| 1112 // We reencrypt everything regardless of whether the set of encrypted | |
| 1113 // types changed to ensure that any stray unencrypted entries are overwritten. | |
| 1114 ReEncryptEverything(&trans); | |
| 1115 } | |
| 1116 | |
| 1117 // This function iterates over all encrypted types. There are many scenarios in | |
| 1118 // which data for some or all types is not currently available. In that case, | |
| 1119 // the lookup of the root node will fail and we will skip encryption for that | |
| 1120 // type. | |
| 1121 void SyncManagerImpl::ReEncryptEverything( | |
| 1122 WriteTransaction* trans) { | |
| 1123 Cryptographer* cryptographer = trans->GetCryptographer(); | |
| 1124 if (!cryptographer || !cryptographer->is_ready()) | |
| 1125 return; | |
| 1126 ModelTypeSet encrypted_types = GetEncryptedTypes(trans); | |
| 1127 for (ModelTypeSet::Iterator iter = encrypted_types.First(); | |
| 1128 iter.Good(); iter.Inc()) { | |
| 1129 if (iter.Get() == PASSWORDS || iter.Get() == NIGORI) | |
| 1130 continue; // These types handle encryption differently. | |
| 1131 | |
| 1132 ReadNode type_root(trans); | |
| 1133 std::string tag = ModelTypeToRootTag(iter.Get()); | |
| 1134 if (type_root.InitByTagLookup(tag) != BaseNode::INIT_OK) | |
| 1135 continue; // Don't try to reencrypt if the type's data is unavailable. | |
| 1136 | |
| 1137 // Iterate through all children of this datatype. | |
| 1138 std::queue<int64> to_visit; | |
| 1139 int64 child_id = type_root.GetFirstChildId(); | |
| 1140 to_visit.push(child_id); | |
| 1141 while (!to_visit.empty()) { | |
| 1142 child_id = to_visit.front(); | |
| 1143 to_visit.pop(); | |
| 1144 if (child_id == kInvalidId) | |
| 1145 continue; | |
| 1146 | |
| 1147 WriteNode child(trans); | |
| 1148 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) { | |
| 1149 NOTREACHED(); | |
| 1150 continue; | |
| 1151 } | |
| 1152 if (child.GetIsFolder()) { | |
| 1153 to_visit.push(child.GetFirstChildId()); | |
| 1154 } | |
| 1155 if (child.GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { | |
| 1156 // Rewrite the specifics of the node with encrypted data if necessary | |
| 1157 // (only rewrite the non-unique folders). | |
| 1158 child.ResetFromSpecifics(); | |
| 1159 } | |
| 1160 to_visit.push(child.GetSuccessorId()); | |
| 1161 } | |
| 1162 } | |
| 1163 | |
| 1164 // Passwords are encrypted with their own legacy scheme. Passwords are always | |
| 1165 // encrypted so we don't need to check GetEncryptedTypes() here. | |
| 1166 ReadNode passwords_root(trans); | |
| 1167 std::string passwords_tag = ModelTypeToRootTag(PASSWORDS); | |
| 1168 if (passwords_root.InitByTagLookup(passwords_tag) == BaseNode::INIT_OK) { | |
| 1169 int64 child_id = passwords_root.GetFirstChildId(); | |
| 1170 while (child_id != kInvalidId) { | |
| 1171 WriteNode child(trans); | |
| 1172 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) { | |
| 1173 NOTREACHED(); | |
| 1174 return; | |
| 1175 } | |
| 1176 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); | |
| 1177 child_id = child.GetSuccessorId(); | |
| 1178 } | |
| 1179 } | |
| 1180 | |
| 1181 // NOTE: We notify from within a transaction. | |
| 1182 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1183 OnEncryptionComplete()); | |
| 1184 } | |
| 1185 | |
| 1186 void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) { | 677 void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) { |
| 1187 DCHECK(thread_checker_.CalledOnValidThread()); | 678 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1188 observers_.AddObserver(observer); | 679 observers_.AddObserver(observer); |
| 1189 } | 680 } |
| 1190 | 681 |
| 1191 void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) { | 682 void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) { |
| 1192 DCHECK(thread_checker_.CalledOnValidThread()); | 683 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1193 observers_.RemoveObserver(observer); | 684 observers_.RemoveObserver(observer); |
| 1194 } | 685 } |
| 1195 | 686 |
| 1196 void SyncManagerImpl::StopSyncingForShutdown(const base::Closure& callback) { | 687 void SyncManagerImpl::StopSyncingForShutdown(const base::Closure& callback) { |
| 1197 DVLOG(2) << "StopSyncingForShutdown"; | 688 DVLOG(2) << "StopSyncingForShutdown"; |
| 1198 scheduler_->RequestStop(callback); | 689 scheduler_->RequestStop(callback); |
| 1199 if (connection_manager_.get()) | 690 if (connection_manager_.get()) |
| 1200 connection_manager_->TerminateAllIO(); | 691 connection_manager_->TerminateAllIO(); |
| 1201 } | 692 } |
| 1202 | 693 |
| 1203 void SyncManagerImpl::ShutdownOnSyncThread() { | 694 void SyncManagerImpl::ShutdownOnSyncThread() { |
| 1204 DCHECK(thread_checker_.CalledOnValidThread()); | 695 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1205 | 696 |
| 1206 // Prevent any in-flight method calls from running. Also | 697 // Prevent any in-flight method calls from running. Also |
| 1207 // invalidates |weak_handle_this_| and |change_observer_|. | 698 // invalidates |weak_handle_this_| and |change_observer_|. |
| 1208 weak_ptr_factory_.InvalidateWeakPtrs(); | 699 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 1209 js_mutation_event_observer_.InvalidateWeakPtrs(); | 700 js_mutation_event_observer_.InvalidateWeakPtrs(); |
| 1210 | 701 |
| 1211 scheduler_.reset(); | 702 scheduler_.reset(); |
| 1212 session_context_.reset(); | 703 session_context_.reset(); |
| 1213 | 704 |
| 705 if (sync_encryption_handler_.get()) { |
| 706 sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_); |
| 707 sync_encryption_handler_->RemoveObserver(this); |
| 708 } |
| 709 |
| 1214 SetJsEventHandler(WeakHandle<JsEventHandler>()); | 710 SetJsEventHandler(WeakHandle<JsEventHandler>()); |
| 1215 RemoveObserver(&js_sync_manager_observer_); | 711 RemoveObserver(&js_sync_manager_observer_); |
| 1216 | 712 |
| 1217 RemoveObserver(&debug_info_event_listener_); | 713 RemoveObserver(&debug_info_event_listener_); |
| 1218 | 714 |
| 1219 if (sync_notifier_.get()) { | 715 if (sync_notifier_.get()) { |
| 1220 sync_notifier_->UpdateRegisteredIds(this, ObjectIdSet()); | 716 sync_notifier_->UpdateRegisteredIds(this, ObjectIdSet()); |
| 1221 } | 717 } |
| 1222 sync_notifier_.reset(); | 718 sync_notifier_.reset(); |
| 1223 | 719 |
| 1224 if (connection_manager_.get()) { | 720 if (connection_manager_.get()) { |
| 1225 connection_manager_->RemoveListener(this); | 721 connection_manager_->RemoveListener(this); |
| 1226 } | 722 } |
| 1227 connection_manager_.reset(); | 723 connection_manager_.reset(); |
| 1228 | 724 |
| 1229 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 725 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| 1230 observing_ip_address_changes_ = false; | 726 observing_ip_address_changes_ = false; |
| 1231 | 727 |
| 1232 if (initialized_ && directory()) { | 728 if (initialized_ && directory()) { |
| 1233 { | |
| 1234 // Cryptographer should only be accessed while holding a | |
| 1235 // transaction. | |
| 1236 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
| 1237 trans.GetCryptographer()->RemoveObserver(this); | |
| 1238 } | |
| 1239 directory()->SaveChanges(); | 729 directory()->SaveChanges(); |
| 1240 } | 730 } |
| 1241 | 731 |
| 1242 share_.directory.reset(); | 732 share_.directory.reset(); |
| 1243 | 733 |
| 1244 change_delegate_ = NULL; | 734 change_delegate_ = NULL; |
| 1245 | 735 |
| 1246 initialized_ = false; | 736 initialized_ = false; |
| 1247 | 737 |
| 1248 // We reset these here, since only now we know they will not be | 738 // 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... |
| 1481 void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) { | 971 void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) { |
| 1482 DCHECK(thread_checker_.CalledOnValidThread()); | 972 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1483 // Only send an event if this is due to a cycle ending and this cycle | 973 // Only send an event if this is due to a cycle ending and this cycle |
| 1484 // concludes a canonical "sync" process; that is, based on what is known | 974 // concludes a canonical "sync" process; that is, based on what is known |
| 1485 // locally we are "all happy" and up-to-date. There may be new changes on | 975 // locally we are "all happy" and up-to-date. There may be new changes on |
| 1486 // the server, but we'll get them on a subsequent sync. | 976 // the server, but we'll get them on a subsequent sync. |
| 1487 // | 977 // |
| 1488 // Notifications are sent at the end of every sync cycle, regardless of | 978 // Notifications are sent at the end of every sync cycle, regardless of |
| 1489 // whether we should sync again. | 979 // whether we should sync again. |
| 1490 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { | 980 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { |
| 1491 { | |
| 1492 // Check to see if we need to notify the frontend that we have newly | |
| 1493 // encrypted types or that we require a passphrase. | |
| 1494 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
| 1495 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1496 // If we've completed a sync cycle and the cryptographer isn't ready | |
| 1497 // yet, prompt the user for a passphrase. | |
| 1498 if (cryptographer->has_pending_keys()) { | |
| 1499 DVLOG(1) << "OnPassPhraseRequired Sent"; | |
| 1500 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); | |
| 1501 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1502 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1503 pending_keys)); | |
| 1504 } else if (!cryptographer->is_ready() && | |
| 1505 event.snapshot.initial_sync_ended().Has(NIGORI)) { | |
| 1506 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " | |
| 1507 << "ready"; | |
| 1508 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1509 OnPassphraseRequired(REASON_ENCRYPTION, | |
| 1510 sync_pb::EncryptedData())); | |
| 1511 } | |
| 1512 | |
| 1513 NotifyCryptographerState(cryptographer); | |
| 1514 allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); | |
| 1515 } | |
| 1516 | |
| 1517 if (!initialized_) { | 981 if (!initialized_) { |
| 1518 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " | 982 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " |
| 1519 << "initialized"; | 983 << "initialized"; |
| 1520 return; | 984 return; |
| 1521 } | 985 } |
| 1522 | 986 |
| 1523 if (!event.snapshot.has_more_to_sync()) { | 987 if (!event.snapshot.has_more_to_sync()) { |
| 1524 { | |
| 1525 // To account for a nigori node arriving with stale/bad data, we ensure | |
| 1526 // that the nigori node is up to date at the end of each cycle. | |
| 1527 WriteTransaction trans(FROM_HERE, GetUserShare()); | |
| 1528 WriteNode nigori_node(&trans); | |
| 1529 if (nigori_node.InitByTagLookup(kNigoriTag) == BaseNode::INIT_OK) { | |
| 1530 Cryptographer* cryptographer = trans.GetCryptographer(); | |
| 1531 UpdateNigoriEncryptionState(cryptographer, &nigori_node); | |
| 1532 } | |
| 1533 } | |
| 1534 | |
| 1535 DVLOG(1) << "Sending OnSyncCycleCompleted"; | 988 DVLOG(1) << "Sending OnSyncCycleCompleted"; |
| 1536 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 989 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 1537 OnSyncCycleCompleted(event.snapshot)); | 990 OnSyncCycleCompleted(event.snapshot)); |
| 1538 } | 991 } |
| 1539 | 992 |
| 1540 // This is here for tests, which are still using p2p notifications. | 993 // This is here for tests, which are still using p2p notifications. |
| 1541 // | 994 // |
| 1542 // TODO(chron): Consider changing this back to track has_more_to_sync | 995 // TODO(chron): Consider changing this back to track has_more_to_sync |
| 1543 // only notify peers if a successful commit has occurred. | 996 // only notify peers if a successful commit has occurred. |
| 1544 bool is_notifiable_commit = | 997 bool is_notifiable_commit = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1574 return; | 1027 return; |
| 1575 } | 1028 } |
| 1576 | 1029 |
| 1577 } | 1030 } |
| 1578 | 1031 |
| 1579 void SyncManagerImpl::SetJsEventHandler( | 1032 void SyncManagerImpl::SetJsEventHandler( |
| 1580 const WeakHandle<JsEventHandler>& event_handler) { | 1033 const WeakHandle<JsEventHandler>& event_handler) { |
| 1581 js_event_handler_ = event_handler; | 1034 js_event_handler_ = event_handler; |
| 1582 js_sync_manager_observer_.SetJsEventHandler(js_event_handler_); | 1035 js_sync_manager_observer_.SetJsEventHandler(js_event_handler_); |
| 1583 js_mutation_event_observer_.SetJsEventHandler(js_event_handler_); | 1036 js_mutation_event_observer_.SetJsEventHandler(js_event_handler_); |
| 1037 js_sync_encryption_handler_observer_.SetJsEventHandler(js_event_handler_); |
| 1584 } | 1038 } |
| 1585 | 1039 |
| 1586 void SyncManagerImpl::ProcessJsMessage( | 1040 void SyncManagerImpl::ProcessJsMessage( |
| 1587 const std::string& name, const JsArgList& args, | 1041 const std::string& name, const JsArgList& args, |
| 1588 const WeakHandle<JsReplyHandler>& reply_handler) { | 1042 const WeakHandle<JsReplyHandler>& reply_handler) { |
| 1589 if (!initialized_) { | 1043 if (!initialized_) { |
| 1590 NOTREACHED(); | 1044 NOTREACHED(); |
| 1591 return; | 1045 return; |
| 1592 } | 1046 } |
| 1593 | 1047 |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1779 id, &child_handles); | 1233 id, &child_handles); |
| 1780 for (syncable::Directory::ChildHandles::const_iterator it = | 1234 for (syncable::Directory::ChildHandles::const_iterator it = |
| 1781 child_handles.begin(); it != child_handles.end(); ++it) { | 1235 child_handles.begin(); it != child_handles.end(); ++it) { |
| 1782 child_ids->Append(Value::CreateStringValue( | 1236 child_ids->Append(Value::CreateStringValue( |
| 1783 base::Int64ToString(*it))); | 1237 base::Int64ToString(*it))); |
| 1784 } | 1238 } |
| 1785 } | 1239 } |
| 1786 return JsArgList(&return_args); | 1240 return JsArgList(&return_args); |
| 1787 } | 1241 } |
| 1788 | 1242 |
| 1789 void SyncManagerImpl::OnEncryptedTypesChanged( | |
| 1790 ModelTypeSet encrypted_types, | |
| 1791 bool encrypt_everything) { | |
| 1792 // NOTE: We're in a transaction. | |
| 1793 FOR_EACH_OBSERVER( | |
| 1794 SyncManager::Observer, observers_, | |
| 1795 OnEncryptedTypesChanged(encrypted_types, encrypt_everything)); | |
| 1796 } | |
| 1797 | |
| 1798 void SyncManagerImpl::UpdateNotificationInfo( | 1243 void SyncManagerImpl::UpdateNotificationInfo( |
| 1799 const ModelTypePayloadMap& type_payloads) { | 1244 const ModelTypePayloadMap& type_payloads) { |
| 1800 for (ModelTypePayloadMap::const_iterator it = type_payloads.begin(); | 1245 for (ModelTypePayloadMap::const_iterator it = type_payloads.begin(); |
| 1801 it != type_payloads.end(); ++it) { | 1246 it != type_payloads.end(); ++it) { |
| 1802 NotificationInfo* info = ¬ification_info_map_[it->first]; | 1247 NotificationInfo* info = ¬ification_info_map_[it->first]; |
| 1803 info->total_count++; | 1248 info->total_count++; |
| 1804 info->payload = it->second; | 1249 info->payload = it->second; |
| 1805 } | 1250 } |
| 1806 } | 1251 } |
| 1807 | 1252 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1866 | 1311 |
| 1867 const std::string& SyncManagerImpl::username_for_share() const { | 1312 const std::string& SyncManagerImpl::username_for_share() const { |
| 1868 return share_.name; | 1313 return share_.name; |
| 1869 } | 1314 } |
| 1870 | 1315 |
| 1871 UserShare* SyncManagerImpl::GetUserShare() { | 1316 UserShare* SyncManagerImpl::GetUserShare() { |
| 1872 DCHECK(initialized_); | 1317 DCHECK(initialized_); |
| 1873 return &share_; | 1318 return &share_; |
| 1874 } | 1319 } |
| 1875 | 1320 |
| 1876 bool SyncManagerImpl::ReceivedExperiment(Experiments* experiments) { | |
| 1877 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
| 1878 ReadNode node(&trans); | |
| 1879 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | |
| 1880 DVLOG(1) << "Couldn't find Nigori node."; | |
| 1881 return false; | |
| 1882 } | |
| 1883 bool found_experiment = false; | |
| 1884 if (node.GetNigoriSpecifics().sync_tab_favicons()) { | |
| 1885 experiments->sync_tab_favicons = true; | |
| 1886 found_experiment = true; | |
| 1887 } | |
| 1888 return found_experiment; | |
| 1889 } | |
| 1890 | |
| 1891 bool SyncManagerImpl::HasUnsyncedItems() { | 1321 bool SyncManagerImpl::HasUnsyncedItems() { |
| 1892 ReadTransaction trans(FROM_HERE, GetUserShare()); | 1322 ReadTransaction trans(FROM_HERE, GetUserShare()); |
| 1893 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); | 1323 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); |
| 1894 } | 1324 } |
| 1895 | 1325 |
| 1326 SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() { |
| 1327 return sync_encryption_handler_.get(); |
| 1328 } |
| 1329 |
| 1896 // static. | 1330 // static. |
| 1897 int SyncManagerImpl::GetDefaultNudgeDelay() { | 1331 int SyncManagerImpl::GetDefaultNudgeDelay() { |
| 1898 return kDefaultNudgeDelayMilliseconds; | 1332 return kDefaultNudgeDelayMilliseconds; |
| 1899 } | 1333 } |
| 1900 | 1334 |
| 1901 // static. | 1335 // static. |
| 1902 int SyncManagerImpl::GetPreferencesNudgeDelay() { | 1336 int SyncManagerImpl::GetPreferencesNudgeDelay() { |
| 1903 return kPreferencesNudgeDelayMilliseconds; | 1337 return kPreferencesNudgeDelayMilliseconds; |
| 1904 } | 1338 } |
| 1905 | 1339 |
| 1906 } // namespace syncer | 1340 } // namespace syncer |
| OLD | NEW |