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 |