OLD | NEW |
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/public/write_node.h" | 5 #include "components/sync/core/write_node.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "sync/internal_api/public/base_transaction.h" | 12 #include "components/sync/base/cryptographer.h" |
13 #include "sync/internal_api/public/write_transaction.h" | 13 #include "components/sync/core/base_transaction.h" |
14 #include "sync/internal_api/syncapi_internal.h" | 14 #include "components/sync/core/write_transaction.h" |
15 #include "sync/protocol/bookmark_specifics.pb.h" | 15 #include "components/sync/core_impl/syncapi_internal.h" |
16 #include "sync/protocol/typed_url_specifics.pb.h" | 16 #include "components/sync/protocol/bookmark_specifics.pb.h" |
17 #include "sync/syncable/mutable_entry.h" | 17 #include "components/sync/protocol/typed_url_specifics.pb.h" |
18 #include "sync/syncable/nigori_util.h" | 18 #include "components/sync/syncable/mutable_entry.h" |
19 #include "sync/syncable/syncable_util.h" | 19 #include "components/sync/syncable/nigori_util.h" |
20 #include "sync/util/cryptographer.h" | 20 #include "components/sync/syncable/syncable_util.h" |
21 | 21 |
22 using std::string; | 22 using std::string; |
23 using std::vector; | 23 using std::vector; |
24 | 24 |
25 namespace syncer { | 25 namespace syncer { |
26 | 26 |
27 using syncable::kEncryptedString; | 27 using syncable::kEncryptedString; |
28 using syncable::SPECIFICS; | 28 using syncable::SPECIFICS; |
29 | 29 |
30 static const char kDefaultNameForNewNodes[] = " "; | 30 static const char kDefaultNameForNewNodes[] = " "; |
(...skipping 21 matching lines...) Expand all Loading... |
52 std::string new_legal_title; | 52 std::string new_legal_title; |
53 if (type != BOOKMARKS && needs_encryption) { | 53 if (type != BOOKMARKS && needs_encryption) { |
54 new_legal_title = kEncryptedString; | 54 new_legal_title = kEncryptedString; |
55 } else { | 55 } else { |
56 DCHECK(base::IsStringUTF8(title)); | 56 DCHECK(base::IsStringUTF8(title)); |
57 SyncAPINameToServerName(title, &new_legal_title); | 57 SyncAPINameToServerName(title, &new_legal_title); |
58 base::TruncateUTF8ToByteSize(new_legal_title, 255, &new_legal_title); | 58 base::TruncateUTF8ToByteSize(new_legal_title, 255, &new_legal_title); |
59 } | 59 } |
60 | 60 |
61 std::string current_legal_title; | 61 std::string current_legal_title; |
62 if (BOOKMARKS == type && | 62 if (BOOKMARKS == type && entry_->GetSpecifics().has_encrypted()) { |
63 entry_->GetSpecifics().has_encrypted()) { | |
64 // Encrypted bookmarks only have their title in the unencrypted specifics. | 63 // Encrypted bookmarks only have their title in the unencrypted specifics. |
65 current_legal_title = GetBookmarkSpecifics().title(); | 64 current_legal_title = GetBookmarkSpecifics().title(); |
66 } else { | 65 } else { |
67 // Non-bookmarks and legacy bookmarks (those with no title in their | 66 // Non-bookmarks and legacy bookmarks (those with no title in their |
68 // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks | 67 // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks |
69 // store their title in specifics as well as NON_UNIQUE_NAME. | 68 // store their title in specifics as well as NON_UNIQUE_NAME. |
70 current_legal_title = entry_->GetNonUniqueName(); | 69 current_legal_title = entry_->GetNonUniqueName(); |
71 } | 70 } |
72 | 71 |
73 bool title_matches = (current_legal_title == new_legal_title); | 72 bool title_matches = (current_legal_title == new_legal_title); |
74 bool encrypted_without_overwriting_name = (needs_encryption && | 73 bool encrypted_without_overwriting_name = |
75 entry_->GetNonUniqueName() != kEncryptedString); | 74 (needs_encryption && entry_->GetNonUniqueName() != kEncryptedString); |
76 | 75 |
77 // For bookmarks, we also set the title field in the specifics. | 76 // For bookmarks, we also set the title field in the specifics. |
78 // TODO(zea): refactor bookmarks to not need this functionality. | 77 // TODO(zea): refactor bookmarks to not need this functionality. |
79 sync_pb::EntitySpecifics specifics = GetEntitySpecifics(); | 78 sync_pb::EntitySpecifics specifics = GetEntitySpecifics(); |
80 if (GetModelType() == BOOKMARKS && | 79 if (GetModelType() == BOOKMARKS && |
81 specifics.bookmark().title() != new_legal_title) { | 80 specifics.bookmark().title() != new_legal_title) { |
82 specifics.mutable_bookmark()->set_title(new_legal_title); | 81 specifics.mutable_bookmark()->set_title(new_legal_title); |
83 SetEntitySpecifics(specifics); // Does it's own encryption checking. | 82 SetEntitySpecifics(specifics); // Does it's own encryption checking. |
84 title_matches = false; | 83 title_matches = false; |
85 } | 84 } |
86 | 85 |
87 // If the title matches and the NON_UNIQUE_NAME is properly overwritten as | 86 // If the title matches and the NON_UNIQUE_NAME is properly overwritten as |
88 // necessary, nothing needs to change. | 87 // necessary, nothing needs to change. |
89 if (title_matches && !encrypted_without_overwriting_name) { | 88 if (title_matches && !encrypted_without_overwriting_name) { |
90 DVLOG(2) << "Title matches, dropping change."; | 89 DVLOG(2) << "Title matches, dropping change."; |
91 return; | 90 return; |
92 } | 91 } |
93 | 92 |
94 // For bookmarks, this has to happen after we set the title in the specifics, | 93 // For bookmarks, this has to happen after we set the title in the specifics, |
95 // because the presence of a title in the NON_UNIQUE_NAME is what controls | 94 // because the presence of a title in the NON_UNIQUE_NAME is what controls |
96 // the logic deciding whether this is an empty node or a legacy bookmark. | 95 // the logic deciding whether this is an empty node or a legacy bookmark. |
97 // See BaseNode::GetUnencryptedSpecific(..). | 96 // See BaseNode::GetUnencryptedSpecific(..). |
98 if (needs_encryption) | 97 if (needs_encryption) |
99 entry_->PutNonUniqueName(kEncryptedString); | 98 entry_->PutNonUniqueName(kEncryptedString); |
100 else | 99 else |
101 entry_->PutNonUniqueName(new_legal_title); | 100 entry_->PutNonUniqueName(new_legal_title); |
102 | 101 |
103 DVLOG(1) << "Overwriting title of type " | 102 DVLOG(1) << "Overwriting title of type " << ModelTypeToString(type) |
104 << ModelTypeToString(type) | |
105 << " and marking for syncing."; | 103 << " and marking for syncing."; |
106 MarkForSyncing(); | 104 MarkForSyncing(); |
107 } | 105 } |
108 | 106 |
109 void WriteNode::SetBookmarkSpecifics( | 107 void WriteNode::SetBookmarkSpecifics( |
110 const sync_pb::BookmarkSpecifics& new_value) { | 108 const sync_pb::BookmarkSpecifics& new_value) { |
111 sync_pb::EntitySpecifics entity_specifics; | 109 sync_pb::EntitySpecifics entity_specifics; |
112 entity_specifics.mutable_bookmark()->CopyFrom(new_value); | 110 entity_specifics.mutable_bookmark()->CopyFrom(new_value); |
113 SetEntitySpecifics(entity_specifics); | 111 SetEntitySpecifics(entity_specifics); |
114 } | 112 } |
115 | 113 |
116 void WriteNode::SetNigoriSpecifics( | 114 void WriteNode::SetNigoriSpecifics(const sync_pb::NigoriSpecifics& new_value) { |
117 const sync_pb::NigoriSpecifics& new_value) { | |
118 sync_pb::EntitySpecifics entity_specifics; | 115 sync_pb::EntitySpecifics entity_specifics; |
119 entity_specifics.mutable_nigori()->CopyFrom(new_value); | 116 entity_specifics.mutable_nigori()->CopyFrom(new_value); |
120 SetEntitySpecifics(entity_specifics); | 117 SetEntitySpecifics(entity_specifics); |
121 } | 118 } |
122 | 119 |
123 void WriteNode::SetPasswordSpecifics( | 120 void WriteNode::SetPasswordSpecifics( |
124 const sync_pb::PasswordSpecificsData& data) { | 121 const sync_pb::PasswordSpecificsData& data) { |
125 DCHECK_EQ(GetModelType(), PASSWORDS); | 122 DCHECK_EQ(GetModelType(), PASSWORDS); |
126 | 123 |
127 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); | 124 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); |
(...skipping 14 matching lines...) Expand all Loading... |
142 // This will only update password_specifics if the underlying unencrypted blob | 139 // This will only update password_specifics if the underlying unencrypted blob |
143 // was different from |data| or was not encrypted with the proper passphrase. | 140 // was different from |data| or was not encrypted with the proper passphrase. |
144 if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { | 141 if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { |
145 LOG(ERROR) << "Failed to encrypt password, possibly due to sync node " | 142 LOG(ERROR) << "Failed to encrypt password, possibly due to sync node " |
146 << "corruption"; | 143 << "corruption"; |
147 return; | 144 return; |
148 } | 145 } |
149 SetEntitySpecifics(entity_specifics); | 146 SetEntitySpecifics(entity_specifics); |
150 } | 147 } |
151 | 148 |
152 void WriteNode::SetEntitySpecifics( | 149 void WriteNode::SetEntitySpecifics(const sync_pb::EntitySpecifics& new_value) { |
153 const sync_pb::EntitySpecifics& new_value) { | 150 ModelType new_specifics_type = GetModelTypeFromSpecifics(new_value); |
154 ModelType new_specifics_type = | |
155 GetModelTypeFromSpecifics(new_value); | |
156 CHECK(!new_value.password().has_client_only_encrypted_data()); | 151 CHECK(!new_value.password().has_client_only_encrypted_data()); |
157 DCHECK_NE(new_specifics_type, UNSPECIFIED); | 152 DCHECK_NE(new_specifics_type, UNSPECIFIED); |
158 DVLOG(1) << "Writing entity specifics of type " | 153 DVLOG(1) << "Writing entity specifics of type " |
159 << ModelTypeToString(new_specifics_type); | 154 << ModelTypeToString(new_specifics_type); |
160 DCHECK_EQ(new_specifics_type, GetModelType()); | 155 DCHECK_EQ(new_specifics_type, GetModelType()); |
161 | 156 |
162 // Preserve unknown fields. | 157 // Preserve unknown fields. |
163 const sync_pb::EntitySpecifics& old_specifics = entry_->GetSpecifics(); | 158 const sync_pb::EntitySpecifics& old_specifics = entry_->GetSpecifics(); |
164 sync_pb::EntitySpecifics new_specifics; | 159 sync_pb::EntitySpecifics new_specifics; |
165 new_specifics.CopyFrom(new_value); | 160 new_specifics.CopyFrom(new_value); |
166 new_specifics.mutable_unknown_fields() | 161 new_specifics.mutable_unknown_fields()->append( |
167 ->append(old_specifics.unknown_fields()); | 162 old_specifics.unknown_fields()); |
168 | 163 |
169 // Will update the entry if encryption was necessary. | 164 // Will update the entry if encryption was necessary. |
170 if (!UpdateEntryWithEncryption(GetTransaction()->GetWrappedTrans(), | 165 if (!UpdateEntryWithEncryption(GetTransaction()->GetWrappedTrans(), |
171 new_specifics, | 166 new_specifics, entry_)) { |
172 entry_)) { | |
173 return; | 167 return; |
174 } | 168 } |
175 if (entry_->GetSpecifics().has_encrypted()) { | 169 if (entry_->GetSpecifics().has_encrypted()) { |
176 // EncryptIfNecessary already updated the entry for us and marked for | 170 // EncryptIfNecessary already updated the entry for us and marked for |
177 // syncing if it was needed. Now we just make a copy of the unencrypted | 171 // syncing if it was needed. Now we just make a copy of the unencrypted |
178 // specifics so that if this node is updated, we do not have to decrypt the | 172 // specifics so that if this node is updated, we do not have to decrypt the |
179 // old data. Note that this only modifies the node's local data, not the | 173 // old data. Note that this only modifies the node's local data, not the |
180 // entry itself. | 174 // entry itself. |
181 SetUnencryptedSpecifics(new_value); | 175 SetUnencryptedSpecifics(new_value); |
182 } | 176 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 return false; | 264 return false; |
271 } | 265 } |
272 | 266 |
273 syncable::Id parent_id = parent.GetSyncId(); | 267 syncable::Id parent_id = parent.GetSyncId(); |
274 DCHECK(!parent_id.IsNull()); | 268 DCHECK(!parent_id.IsNull()); |
275 | 269 |
276 // Start out with a dummy name. We expect | 270 // Start out with a dummy name. We expect |
277 // the caller to set a meaningful name after creation. | 271 // the caller to set a meaningful name after creation. |
278 string dummy(kDefaultNameForNewNodes); | 272 string dummy(kDefaultNameForNewNodes); |
279 | 273 |
280 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 274 entry_ = |
281 syncable::CREATE, BOOKMARKS, | 275 new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
282 parent_id, dummy); | 276 syncable::CREATE, BOOKMARKS, parent_id, dummy); |
283 | 277 |
284 if (!entry_->good()) | 278 if (!entry_->good()) |
285 return false; | 279 return false; |
286 | 280 |
287 // Entries are untitled folders by default. | 281 // Entries are untitled folders by default. |
288 entry_->PutIsDir(true); | 282 entry_->PutIsDir(true); |
289 | 283 |
290 if (!PutPredecessor(predecessor)) { | 284 if (!PutPredecessor(predecessor)) { |
291 return false; | 285 return false; |
292 } | 286 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 } // Else just reuse the existing entry. | 371 } // Else just reuse the existing entry. |
378 entry_ = existing_entry.release(); | 372 entry_ = existing_entry.release(); |
379 // If entry is undeleted, its specifics are reset to default, unencrypted | 373 // If entry is undeleted, its specifics are reset to default, unencrypted |
380 // value, and therefore no decryption is necessary. Moreover trying to | 374 // value, and therefore no decryption is necessary. Moreover trying to |
381 // decrypt the password entry will fail because passwords are expected to be | 375 // decrypt the password entry will fail because passwords are expected to be |
382 // encrypted. | 376 // encrypted. |
383 if (!entry_undeleted && !DecryptIfNecessary()) | 377 if (!entry_undeleted && !DecryptIfNecessary()) |
384 return INIT_FAILED_DECRYPT_EXISTING_ENTRY; | 378 return INIT_FAILED_DECRYPT_EXISTING_ENTRY; |
385 } else { | 379 } else { |
386 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 380 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
387 syncable::CREATE, | 381 syncable::CREATE, model_type, parent_id, |
388 model_type, parent_id, dummy); | 382 dummy); |
389 } | 383 } |
390 | 384 |
391 if (!entry_->good()) | 385 if (!entry_->good()) |
392 return INIT_FAILED_COULD_NOT_CREATE_ENTRY; | 386 return INIT_FAILED_COULD_NOT_CREATE_ENTRY; |
393 | 387 |
394 // Has no impact if the client tag is already set. | 388 // Has no impact if the client tag is already set. |
395 entry_->PutUniqueClientTag(hash); | 389 entry_->PutUniqueClientTag(hash); |
396 | 390 |
397 // We don't support directory and tag combinations. | 391 // We don't support directory and tag combinations. |
398 entry_->PutIsDir(false); | 392 entry_->PutIsDir(false); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 syncable::Id predecessor_id = | 469 syncable::Id predecessor_id = |
476 predecessor ? predecessor->GetSyncId() : syncable::Id(); | 470 predecessor ? predecessor->GetSyncId() : syncable::Id(); |
477 return entry_->PutPredecessor(predecessor_id); | 471 return entry_->PutPredecessor(predecessor_id); |
478 } | 472 } |
479 | 473 |
480 void WriteNode::MarkForSyncing() { | 474 void WriteNode::MarkForSyncing() { |
481 syncable::MarkForSyncing(entry_); | 475 syncable::MarkForSyncing(entry_); |
482 } | 476 } |
483 | 477 |
484 } // namespace syncer | 478 } // namespace syncer |
OLD | NEW |