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

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

Powered by Google App Engine
This is Rietveld 408576698