OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/process_updates_command.h" | 5 #include "chrome/browser/sync/engine/process_updates_command.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "chrome/browser/sync/engine/syncer.h" | 11 #include "chrome/browser/sync/engine/syncer.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_util.h" | 13 #include "chrome/browser/sync/engine/syncer_util.h" |
14 #include "chrome/browser/sync/engine/syncproto.h" | 14 #include "chrome/browser/sync/engine/syncproto.h" |
15 #include "chrome/browser/sync/sessions/sync_session.h" | 15 #include "chrome/browser/sync/sessions/sync_session.h" |
16 #include "chrome/browser/sync/syncable/directory_manager.h" | 16 #include "chrome/browser/sync/syncable/directory_manager.h" |
17 #include "chrome/browser/sync/syncable/syncable.h" | 17 #include "chrome/browser/sync/syncable/syncable.h" |
| 18 #include "chrome/browser/sync/util/cryptographer.h" |
18 | 19 |
19 using std::vector; | 20 using std::vector; |
20 | 21 |
21 namespace browser_sync { | 22 namespace browser_sync { |
22 | 23 |
23 using sessions::SyncSession; | 24 using sessions::SyncSession; |
24 using sessions::StatusController; | 25 using sessions::StatusController; |
25 using sessions::UpdateProgress; | 26 using sessions::UpdateProgress; |
26 | 27 |
27 ProcessUpdatesCommand::ProcessUpdatesCommand() {} | 28 ProcessUpdatesCommand::ProcessUpdatesCommand() {} |
(...skipping 28 matching lines...) Expand all Loading... |
56 | 57 |
57 syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir); | 58 syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir); |
58 vector<sessions::VerifiedUpdate>::const_iterator it; | 59 vector<sessions::VerifiedUpdate>::const_iterator it; |
59 for (it = progress->VerifiedUpdatesBegin(); | 60 for (it = progress->VerifiedUpdatesBegin(); |
60 it != progress->VerifiedUpdatesEnd(); | 61 it != progress->VerifiedUpdatesEnd(); |
61 ++it) { | 62 ++it) { |
62 const sync_pb::SyncEntity& update = it->second; | 63 const sync_pb::SyncEntity& update = it->second; |
63 | 64 |
64 if (it->first != VERIFY_SUCCESS && it->first != VERIFY_UNDELETE) | 65 if (it->first != VERIFY_SUCCESS && it->first != VERIFY_UNDELETE) |
65 continue; | 66 continue; |
66 switch (ProcessUpdate(dir, update, &trans)) { | 67 switch (ProcessUpdate(dir, update, |
| 68 session->context()->directory_manager()->GetCryptographer(&trans), |
| 69 &trans)) { |
67 case SUCCESS_PROCESSED: | 70 case SUCCESS_PROCESSED: |
68 case SUCCESS_STORED: | 71 case SUCCESS_STORED: |
69 break; | 72 break; |
70 default: | 73 default: |
71 NOTREACHED(); | 74 NOTREACHED(); |
72 break; | 75 break; |
73 } | 76 } |
74 } | 77 } |
75 | 78 |
76 StatusController* status = session->mutable_status_controller(); | 79 StatusController* status = session->mutable_status_controller(); |
(...skipping 16 matching lines...) Expand all Loading... |
93 deleted, | 96 deleted, |
94 is_directory, | 97 is_directory, |
95 model_type); | 98 model_type); |
96 } | 99 } |
97 } // namespace | 100 } // namespace |
98 | 101 |
99 // Process a single update. Will avoid touching global state. | 102 // Process a single update. Will avoid touching global state. |
100 ServerUpdateProcessingResult ProcessUpdatesCommand::ProcessUpdate( | 103 ServerUpdateProcessingResult ProcessUpdatesCommand::ProcessUpdate( |
101 const syncable::ScopedDirLookup& dir, | 104 const syncable::ScopedDirLookup& dir, |
102 const sync_pb::SyncEntity& proto_update, | 105 const sync_pb::SyncEntity& proto_update, |
| 106 const Cryptographer* cryptographer, |
103 syncable::WriteTransaction* const trans) { | 107 syncable::WriteTransaction* const trans) { |
104 | 108 |
105 const SyncEntity& update = *static_cast<const SyncEntity*>(&proto_update); | 109 const SyncEntity& update = *static_cast<const SyncEntity*>(&proto_update); |
106 syncable::Id server_id = update.id(); | 110 syncable::Id server_id = update.id(); |
107 const std::string name = SyncerProtoUtil::NameFromSyncEntity(update); | 111 const std::string name = SyncerProtoUtil::NameFromSyncEntity(update); |
108 | 112 |
109 // Look to see if there's a local item that should recieve this update, | 113 // Look to see if there's a local item that should recieve this update, |
110 // maybe due to a duplicate client tag or a lost commit response. | 114 // maybe due to a duplicate client tag or a lost commit response. |
111 syncable::Id local_id = SyncerUtil::FindLocalIdToUpdate(trans, update); | 115 syncable::Id local_id = SyncerUtil::FindLocalIdToUpdate(trans, update); |
112 | 116 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 // fields for this entry. When BASE_VERSION is positive, consistency is | 150 // fields for this entry. When BASE_VERSION is positive, consistency is |
147 // enforced on the client fields at update-application time. Otherwise, | 151 // enforced on the client fields at update-application time. Otherwise, |
148 // we leave the BASE_VERSION field alone; it'll get updated the first time | 152 // we leave the BASE_VERSION field alone; it'll get updated the first time |
149 // we successfully apply this update. | 153 // we successfully apply this update. |
150 target_entry.Put(syncable::BASE_VERSION, update.version()); | 154 target_entry.Put(syncable::BASE_VERSION, update.version()); |
151 } | 155 } |
152 // Force application of this update, no matter what. | 156 // Force application of this update, no matter what. |
153 target_entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); | 157 target_entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); |
154 } | 158 } |
155 | 159 |
| 160 // If this is a newly received undecryptable update, and the only thing that |
| 161 // has changed are the specifics, store the original decryptable specifics, |
| 162 // (on which any current or future local changes are based) before we |
| 163 // overwrite SERVER_SPECIFICS. |
| 164 // MTIME, CTIME, and NON_UNIQUE_NAME are not enforced. |
| 165 if (!update.deleted() && !target_entry.Get(syncable::SERVER_IS_DEL) && |
| 166 (update.parent_id() == target_entry.Get(syncable::SERVER_PARENT_ID)) && |
| 167 (update.position_in_parent() == |
| 168 target_entry.Get(syncable::SERVER_POSITION_IN_PARENT)) && |
| 169 update.has_specifics() && update.specifics().has_encrypted() && |
| 170 !cryptographer->CanDecrypt(update.specifics().encrypted())) { |
| 171 sync_pb::EntitySpecifics prev_specifics = |
| 172 target_entry.Get(syncable::SERVER_SPECIFICS); |
| 173 // We only store the old specifics if they were decryptable and applied and |
| 174 // there is no BASE_SERVER_SPECIFICS already. Else do nothing. |
| 175 if (!target_entry.Get(syncable::IS_UNAPPLIED_UPDATE) && |
| 176 !syncable::IsRealDataType(syncable::GetModelTypeFromSpecifics( |
| 177 target_entry.Get(syncable::BASE_SERVER_SPECIFICS))) && |
| 178 (!prev_specifics.has_encrypted() || |
| 179 cryptographer->CanDecrypt(prev_specifics.encrypted()))) { |
| 180 DVLOG(2) << "Storing previous server specifcs: " |
| 181 << prev_specifics.SerializeAsString(); |
| 182 target_entry.Put(syncable::BASE_SERVER_SPECIFICS, prev_specifics); |
| 183 } |
| 184 } else if (syncable::IsRealDataType(syncable::GetModelTypeFromSpecifics( |
| 185 target_entry.Get(syncable::BASE_SERVER_SPECIFICS)))) { |
| 186 // We have a BASE_SERVER_SPECIFICS, but a subsequent non-specifics-only |
| 187 // change arrived. As a result, we can't use the specifics alone to detect |
| 188 // changes, so we clear BASE_SERVER_SPECIFICS. |
| 189 target_entry.Put(syncable::BASE_SERVER_SPECIFICS, |
| 190 sync_pb::EntitySpecifics()); |
| 191 } |
| 192 |
156 SyncerUtil::UpdateServerFieldsFromUpdate(&target_entry, update, name); | 193 SyncerUtil::UpdateServerFieldsFromUpdate(&target_entry, update, name); |
157 | 194 |
158 return SUCCESS_PROCESSED; | 195 return SUCCESS_PROCESSED; |
159 } | 196 } |
160 | 197 |
161 } // namespace browser_sync | 198 } // namespace browser_sync |
OLD | NEW |