| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/sync/engine/syncer_util.h" | 5 #include "chrome/browser/sync/engine/syncer_util.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "chrome/browser/sync/engine/conflict_resolver.h" | 11 #include "chrome/browser/sync/engine/conflict_resolver.h" |
| 12 #include "chrome/browser/sync/engine/syncer_proto_util.h" | 12 #include "chrome/browser/sync/engine/syncer_proto_util.h" |
| 13 #include "chrome/browser/sync/engine/syncer_types.h" | 13 #include "chrome/browser/sync/engine/syncer_types.h" |
| 14 #include "chrome/browser/sync/engine/syncproto.h" | 14 #include "chrome/browser/sync/engine/syncproto.h" |
| 15 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" | 15 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" |
| 16 #include "chrome/browser/sync/protocol/nigori_specifics.pb.h" |
| 17 #include "chrome/browser/sync/protocol/sync.pb.h" |
| 16 #include "chrome/browser/sync/syncable/directory_manager.h" | 18 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 17 #include "chrome/browser/sync/syncable/model_type.h" | 19 #include "chrome/browser/sync/syncable/model_type.h" |
| 18 #include "chrome/browser/sync/syncable/syncable.h" | 20 #include "chrome/browser/sync/syncable/syncable.h" |
| 19 #include "chrome/browser/sync/syncable/syncable_changes_version.h" | 21 #include "chrome/browser/sync/syncable/syncable_changes_version.h" |
| 20 #include "chrome/browser/sync/util/sync_types.h" | 22 #include "chrome/browser/sync/util/sync_types.h" |
| 21 | 23 |
| 22 using syncable::BASE_VERSION; | 24 using syncable::BASE_VERSION; |
| 23 using syncable::Blob; | 25 using syncable::Blob; |
| 24 using syncable::CHANGES_VERSION; | 26 using syncable::CHANGES_VERSION; |
| 25 using syncable::CREATE; | 27 using syncable::CREATE; |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // !local_entry.Good() means we don't have a left behind entry for this | 242 // !local_entry.Good() means we don't have a left behind entry for this |
| 241 // ID. We successfully committed before. In the future we should get rid | 243 // ID. We successfully committed before. In the future we should get rid |
| 242 // of this system and just have client side generated IDs as a whole. | 244 // of this system and just have client side generated IDs as a whole. |
| 243 } | 245 } |
| 244 } | 246 } |
| 245 | 247 |
| 246 // static | 248 // static |
| 247 UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry( | 249 UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry( |
| 248 syncable::WriteTransaction* const trans, | 250 syncable::WriteTransaction* const trans, |
| 249 syncable::MutableEntry* const entry, | 251 syncable::MutableEntry* const entry, |
| 250 ConflictResolver* resolver) { | 252 ConflictResolver* resolver, |
| 253 Cryptographer* cryptographer) { |
| 251 | 254 |
| 252 CHECK(entry->good()); | 255 CHECK(entry->good()); |
| 253 if (!entry->Get(IS_UNAPPLIED_UPDATE)) | 256 if (!entry->Get(IS_UNAPPLIED_UPDATE)) |
| 254 return SUCCESS; // No work to do. | 257 return SUCCESS; // No work to do. |
| 255 syncable::Id id = entry->Get(ID); | 258 syncable::Id id = entry->Get(ID); |
| 256 | 259 |
| 257 if (entry->Get(IS_UNSYNCED)) { | 260 if (entry->Get(IS_UNSYNCED)) { |
| 258 LOG(INFO) << "Skipping update, returning conflict for: " << id | 261 LOG(INFO) << "Skipping update, returning conflict for: " << id |
| 259 << " ; it's unsynced."; | 262 << " ; it's unsynced."; |
| 260 return CONFLICT; | 263 return CONFLICT; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 282 Directory::ChildHandles handles; | 285 Directory::ChildHandles handles; |
| 283 trans->directory()->GetChildHandles(trans, id, &handles); | 286 trans->directory()->GetChildHandles(trans, id, &handles); |
| 284 if (!handles.empty()) { | 287 if (!handles.empty()) { |
| 285 // If we have still-existing children, then we need to deal with | 288 // If we have still-existing children, then we need to deal with |
| 286 // them before we can process this change. | 289 // them before we can process this change. |
| 287 LOG(INFO) << "Not deleting directory; it's not empty " << *entry; | 290 LOG(INFO) << "Not deleting directory; it's not empty " << *entry; |
| 288 return CONFLICT; | 291 return CONFLICT; |
| 289 } | 292 } |
| 290 } | 293 } |
| 291 | 294 |
| 295 // We intercept updates to the Nigori node and update the Cryptographer here |
| 296 // because there is no Nigori ChangeProcessor. |
| 297 const sync_pb::EntitySpecifics& specifics = entry->Get(SERVER_SPECIFICS); |
| 298 if (specifics.HasExtension(sync_pb::nigori)) { |
| 299 const sync_pb::NigoriSpecifics& nigori = |
| 300 specifics.GetExtension(sync_pb::nigori); |
| 301 if (!nigori.encrypted().blob().empty()) { |
| 302 if (cryptographer->CanDecrypt(nigori.encrypted())) { |
| 303 cryptographer->SetKeys(nigori.encrypted()); |
| 304 } else { |
| 305 cryptographer->SetPendingKeys(nigori.encrypted()); |
| 306 } |
| 307 } |
| 308 } |
| 309 |
| 310 // Only apply updates that we can decrypt. Updates that can't be decrypted yet |
| 311 // will stay in conflict until the user provides a passphrase that lets the |
| 312 // Cryptographer decrypt them. |
| 313 if (!entry->Get(SERVER_IS_DIR) && specifics.HasExtension(sync_pb::password)) { |
| 314 const sync_pb::PasswordSpecifics& password = |
| 315 specifics.GetExtension(sync_pb::password); |
| 316 if (!cryptographer->CanDecrypt(password.encrypted())) { |
| 317 // We can't decrypt this node yet. |
| 318 return CONFLICT; |
| 319 } |
| 320 } |
| 321 |
| 292 SyncerUtil::UpdateLocalDataFromServerData(trans, entry); | 322 SyncerUtil::UpdateLocalDataFromServerData(trans, entry); |
| 293 | 323 |
| 294 return SUCCESS; | 324 return SUCCESS; |
| 295 } | 325 } |
| 296 | 326 |
| 297 namespace { | 327 namespace { |
| 298 // Helper to synthesize a new-style sync_pb::EntitySpecifics for use locally, | 328 // Helper to synthesize a new-style sync_pb::EntitySpecifics for use locally, |
| 299 // when the server speaks only the old sync_pb::SyncEntity_BookmarkData-based | 329 // when the server speaks only the old sync_pb::SyncEntity_BookmarkData-based |
| 300 // protocol. | 330 // protocol. |
| 301 void UpdateBookmarkSpecifics(const string& singleton_tag, | 331 void UpdateBookmarkSpecifics(const string& singleton_tag, |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 | 728 |
| 699 if (same_id->Get(SERVER_VERSION) > 0) { | 729 if (same_id->Get(SERVER_VERSION) > 0) { |
| 700 // Then we've had an update for this entry before. | 730 // Then we've had an update for this entry before. |
| 701 if (is_directory != same_id->Get(SERVER_IS_DIR) || | 731 if (is_directory != same_id->Get(SERVER_IS_DIR) || |
| 702 model_type != same_id->GetServerModelType()) { | 732 model_type != same_id->GetServerModelType()) { |
| 703 if (same_id->Get(IS_DEL)) { // If we've deleted the item, we don't care. | 733 if (same_id->Get(IS_DEL)) { // If we've deleted the item, we don't care. |
| 704 return VERIFY_SKIP; | 734 return VERIFY_SKIP; |
| 705 } else { | 735 } else { |
| 706 LOG(ERROR) << "Server update doesn't agree with previous updates. "; | 736 LOG(ERROR) << "Server update doesn't agree with previous updates. "; |
| 707 LOG(ERROR) << " Entry: " << *same_id; | 737 LOG(ERROR) << " Entry: " << *same_id; |
| 708 LOG(ERROR) << " Update: " << SyncerProtoUtil::SyncEntityDebugString(entr
y); | 738 LOG(ERROR) << " Update: " |
| 739 << SyncerProtoUtil::SyncEntityDebugString(entry); |
| 709 return VERIFY_FAIL; | 740 return VERIFY_FAIL; |
| 710 } | 741 } |
| 711 } | 742 } |
| 712 | 743 |
| 713 if (!deleted && | 744 if (!deleted && |
| 714 (same_id->Get(SERVER_IS_DEL) || | 745 (same_id->Get(SERVER_IS_DEL) || |
| 715 (!same_id->Get(IS_UNSYNCED) && same_id->Get(IS_DEL) && | 746 (!same_id->Get(IS_UNSYNCED) && same_id->Get(IS_DEL) && |
| 716 same_id->Get(BASE_VERSION) > 0))) { | 747 same_id->Get(BASE_VERSION) > 0))) { |
| 717 // An undelete. The latter case in the above condition is for | 748 // An undelete. The latter case in the above condition is for |
| 718 // when the server does not give us an update following the | 749 // when the server does not give us an update following the |
| 719 // commit of a delete, before undeleting. Undeletion is possible | 750 // commit of a delete, before undeleting. Undeletion is possible |
| 720 // in the server's storage backend, so it's possible on the client, | 751 // in the server's storage backend, so it's possible on the client, |
| 721 // though not expected to be something that is commonly possible. | 752 // though not expected to be something that is commonly possible. |
| 722 VerifyResult result = | 753 VerifyResult result = |
| 723 SyncerUtil::VerifyUndelete(trans, entry, same_id); | 754 SyncerUtil::VerifyUndelete(trans, entry, same_id); |
| 724 if (VERIFY_UNDECIDED != result) | 755 if (VERIFY_UNDECIDED != result) |
| 725 return result; | 756 return result; |
| 726 } | 757 } |
| 727 } | 758 } |
| 728 if (same_id->Get(BASE_VERSION) > 0) { | 759 if (same_id->Get(BASE_VERSION) > 0) { |
| 729 // We've committed this entry in the past. | 760 // We've committed this entry in the past. |
| 730 if (is_directory != same_id->Get(IS_DIR) || | 761 if (is_directory != same_id->Get(IS_DIR) || |
| 731 model_type != same_id->GetModelType()) { | 762 model_type != same_id->GetModelType()) { |
| 732 LOG(ERROR) << "Server update doesn't agree with committed item. "; | 763 LOG(ERROR) << "Server update doesn't agree with committed item. "; |
| 733 LOG(ERROR) << " Entry: " << *same_id; | 764 LOG(ERROR) << " Entry: " << *same_id; |
| 734 LOG(ERROR) << " Update: " << SyncerProtoUtil::SyncEntityDebugString(entry)
; | 765 LOG(ERROR) << " Update: " |
| 766 << SyncerProtoUtil::SyncEntityDebugString(entry); |
| 735 return VERIFY_FAIL; | 767 return VERIFY_FAIL; |
| 736 } | 768 } |
| 737 if (same_id->Get(BASE_VERSION) == entry.version() && | 769 if (same_id->Get(BASE_VERSION) == entry.version() && |
| 738 !same_id->Get(IS_UNSYNCED) && | 770 !same_id->Get(IS_UNSYNCED) && |
| 739 !SyncerProtoUtil::Compare(*same_id, entry)) { | 771 !SyncerProtoUtil::Compare(*same_id, entry)) { |
| 740 // TODO(sync): This constraint needs to be relaxed. For now it's OK to | 772 // TODO(sync): This constraint needs to be relaxed. For now it's OK to |
| 741 // fail the verification and deal with it when we ApplyUpdates. | 773 // fail the verification and deal with it when we ApplyUpdates. |
| 742 LOG(ERROR) << "Server update doesn't match local data with same " | 774 LOG(ERROR) << "Server update doesn't match local data with same " |
| 743 "version. A bug should be filed. Entry: " << *same_id << | 775 "version. A bug should be filed. Entry: " << *same_id << |
| 744 "Update: " << SyncerProtoUtil::SyncEntityDebugString(entry); | 776 "Update: " << SyncerProtoUtil::SyncEntityDebugString(entry); |
| 745 return VERIFY_FAIL; | 777 return VERIFY_FAIL; |
| 746 } | 778 } |
| 747 if (same_id->Get(SERVER_VERSION) > entry.version()) { | 779 if (same_id->Get(SERVER_VERSION) > entry.version()) { |
| 748 LOG(WARNING) << "We've already seen a more recent update from the server"; | 780 LOG(WARNING) << "We've already seen a more recent update from the server"; |
| 749 LOG(WARNING) << " Entry: " << *same_id; | 781 LOG(WARNING) << " Entry: " << *same_id; |
| 750 LOG(WARNING) << " Update: " << SyncerProtoUtil::SyncEntityDebugString(entr
y); | 782 LOG(WARNING) << " Update: " |
| 783 << SyncerProtoUtil::SyncEntityDebugString(entry); |
| 751 return VERIFY_SKIP; | 784 return VERIFY_SKIP; |
| 752 } | 785 } |
| 753 } | 786 } |
| 754 return VERIFY_SUCCESS; | 787 return VERIFY_SUCCESS; |
| 755 } | 788 } |
| 756 | 789 |
| 757 // Assumes we have an existing entry; verify an update that seems to be | 790 // Assumes we have an existing entry; verify an update that seems to be |
| 758 // expressing an 'undelete' | 791 // expressing an 'undelete' |
| 759 // static | 792 // static |
| 760 VerifyResult SyncerUtil::VerifyUndelete(syncable::WriteTransaction* trans, | 793 VerifyResult SyncerUtil::VerifyUndelete(syncable::WriteTransaction* trans, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 | 865 |
| 833 // |update_entry| is considered to be somewhere after |candidate|, so store | 866 // |update_entry| is considered to be somewhere after |candidate|, so store |
| 834 // it as the upper bound. | 867 // it as the upper bound. |
| 835 closest_sibling = candidate.Get(ID); | 868 closest_sibling = candidate.Get(ID); |
| 836 } | 869 } |
| 837 | 870 |
| 838 return closest_sibling; | 871 return closest_sibling; |
| 839 } | 872 } |
| 840 | 873 |
| 841 } // namespace browser_sync | 874 } // namespace browser_sync |
| OLD | NEW |