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

Side by Side Diff: sync/internal_api/sync_manager_impl.cc

Issue 10827266: [Sync] Add SyncEncryptionHandler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments 3 Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 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
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
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
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
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()->SetNigoriHandler(
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
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
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
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
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 = &notification_info_map_[it->first]; 1247 NotificationInfo* info = &notification_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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 found_experiment = true; 1331 found_experiment = true;
1887 } 1332 }
1888 return found_experiment; 1333 return found_experiment;
1889 } 1334 }
1890 1335
1891 bool SyncManagerImpl::HasUnsyncedItems() { 1336 bool SyncManagerImpl::HasUnsyncedItems() {
1892 ReadTransaction trans(FROM_HERE, GetUserShare()); 1337 ReadTransaction trans(FROM_HERE, GetUserShare());
1893 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); 1338 return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0);
1894 } 1339 }
1895 1340
1341 SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() {
1342 return sync_encryption_handler_.get();
1343 }
1344
1896 // static. 1345 // static.
1897 int SyncManagerImpl::GetDefaultNudgeDelay() { 1346 int SyncManagerImpl::GetDefaultNudgeDelay() {
1898 return kDefaultNudgeDelayMilliseconds; 1347 return kDefaultNudgeDelayMilliseconds;
1899 } 1348 }
1900 1349
1901 // static. 1350 // static.
1902 int SyncManagerImpl::GetPreferencesNudgeDelay() { 1351 int SyncManagerImpl::GetPreferencesNudgeDelay() {
1903 return kPreferencesNudgeDelayMilliseconds; 1352 return kPreferencesNudgeDelayMilliseconds;
1904 } 1353 }
1905 1354
1906 } // namespace syncer 1355 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698