| 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 "sync/internal_api/public/write_node.h" |
| 6 | 6 |
| 7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
| 8 #include "base/values.h" | 8 #include "base/values.h" |
| 9 #include "sync/internal_api/public/base_transaction.h" | 9 #include "sync/internal_api/public/base_transaction.h" |
| 10 #include "sync/internal_api/public/write_transaction.h" | 10 #include "sync/internal_api/public/write_transaction.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 void WriteNode::SetIsFolder(bool folder) { | 34 void WriteNode::SetIsFolder(bool folder) { |
| 35 if (entry_->Get(syncable::IS_DIR) == folder) | 35 if (entry_->Get(syncable::IS_DIR) == folder) |
| 36 return; // Skip redundant changes. | 36 return; // Skip redundant changes. |
| 37 | 37 |
| 38 entry_->Put(syncable::IS_DIR, folder); | 38 entry_->Put(syncable::IS_DIR, folder); |
| 39 MarkForSyncing(); | 39 MarkForSyncing(); |
| 40 } | 40 } |
| 41 | 41 |
| 42 void WriteNode::SetTitle(const std::wstring& title) { | 42 void WriteNode::SetTitle(const std::wstring& title) { |
| 43 DCHECK_NE(GetModelType(), syncer::UNSPECIFIED); | 43 DCHECK_NE(GetModelType(), UNSPECIFIED); |
| 44 syncer::ModelType type = GetModelType(); | 44 ModelType type = GetModelType(); |
| 45 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); | 45 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); |
| 46 // It's possible the nigori lost the set of encrypted types. If the current | 46 // It's possible the nigori lost the set of encrypted types. If the current |
| 47 // specifics are already encrypted, we want to ensure we continue encrypting. | 47 // specifics are already encrypted, we want to ensure we continue encrypting. |
| 48 bool needs_encryption = cryptographer->GetEncryptedTypes().Has(type) || | 48 bool needs_encryption = cryptographer->GetEncryptedTypes().Has(type) || |
| 49 entry_->Get(SPECIFICS).has_encrypted(); | 49 entry_->Get(SPECIFICS).has_encrypted(); |
| 50 | 50 |
| 51 // If this datatype is encrypted and is not a bookmark, we disregard the | 51 // If this datatype is encrypted and is not a bookmark, we disregard the |
| 52 // specified title in favor of kEncryptedString. For encrypted bookmarks the | 52 // specified title in favor of kEncryptedString. For encrypted bookmarks the |
| 53 // NON_UNIQUE_NAME will still be kEncryptedString, but we store the real title | 53 // NON_UNIQUE_NAME will still be kEncryptedString, but we store the real title |
| 54 // into the specifics. All strings compared are server legal strings. | 54 // into the specifics. All strings compared are server legal strings. |
| 55 std::string new_legal_title; | 55 std::string new_legal_title; |
| 56 if (type != syncer::BOOKMARKS && needs_encryption) { | 56 if (type != BOOKMARKS && needs_encryption) { |
| 57 new_legal_title = kEncryptedString; | 57 new_legal_title = kEncryptedString; |
| 58 } else { | 58 } else { |
| 59 SyncAPINameToServerName(WideToUTF8(title), &new_legal_title); | 59 SyncAPINameToServerName(WideToUTF8(title), &new_legal_title); |
| 60 } | 60 } |
| 61 | 61 |
| 62 std::string current_legal_title; | 62 std::string current_legal_title; |
| 63 if (syncer::BOOKMARKS == type && | 63 if (BOOKMARKS == type && |
| 64 entry_->Get(syncable::SPECIFICS).has_encrypted()) { | 64 entry_->Get(syncable::SPECIFICS).has_encrypted()) { |
| 65 // Encrypted bookmarks only have their title in the unencrypted specifics. | 65 // Encrypted bookmarks only have their title in the unencrypted specifics. |
| 66 current_legal_title = GetBookmarkSpecifics().title(); | 66 current_legal_title = GetBookmarkSpecifics().title(); |
| 67 } else { | 67 } else { |
| 68 // Non-bookmarks and legacy bookmarks (those with no title in their | 68 // Non-bookmarks and legacy bookmarks (those with no title in their |
| 69 // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks | 69 // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks |
| 70 // store their title in specifics as well as NON_UNIQUE_NAME. | 70 // store their title in specifics as well as NON_UNIQUE_NAME. |
| 71 current_legal_title = entry_->Get(syncable::NON_UNIQUE_NAME); | 71 current_legal_title = entry_->Get(syncable::NON_UNIQUE_NAME); |
| 72 } | 72 } |
| 73 | 73 |
| 74 bool title_matches = (current_legal_title == new_legal_title); | 74 bool title_matches = (current_legal_title == new_legal_title); |
| 75 bool encrypted_without_overwriting_name = (needs_encryption && | 75 bool encrypted_without_overwriting_name = (needs_encryption && |
| 76 entry_->Get(syncable::NON_UNIQUE_NAME) != kEncryptedString); | 76 entry_->Get(syncable::NON_UNIQUE_NAME) != kEncryptedString); |
| 77 | 77 |
| 78 // If the title matches and the NON_UNIQUE_NAME is properly overwritten as | 78 // If the title matches and the NON_UNIQUE_NAME is properly overwritten as |
| 79 // necessary, nothing needs to change. | 79 // necessary, nothing needs to change. |
| 80 if (title_matches && !encrypted_without_overwriting_name) { | 80 if (title_matches && !encrypted_without_overwriting_name) { |
| 81 DVLOG(2) << "Title matches, dropping change."; | 81 DVLOG(2) << "Title matches, dropping change."; |
| 82 return; | 82 return; |
| 83 } | 83 } |
| 84 | 84 |
| 85 // For bookmarks, we also set the title field in the specifics. | 85 // For bookmarks, we also set the title field in the specifics. |
| 86 // TODO(zea): refactor bookmarks to not need this functionality. | 86 // TODO(zea): refactor bookmarks to not need this functionality. |
| 87 if (GetModelType() == syncer::BOOKMARKS) { | 87 if (GetModelType() == BOOKMARKS) { |
| 88 sync_pb::EntitySpecifics specifics = GetEntitySpecifics(); | 88 sync_pb::EntitySpecifics specifics = GetEntitySpecifics(); |
| 89 specifics.mutable_bookmark()->set_title(new_legal_title); | 89 specifics.mutable_bookmark()->set_title(new_legal_title); |
| 90 SetEntitySpecifics(specifics); // Does it's own encryption checking. | 90 SetEntitySpecifics(specifics); // Does it's own encryption checking. |
| 91 } | 91 } |
| 92 | 92 |
| 93 // 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, |
| 94 // 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 |
| 95 // 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. |
| 96 // See BaseNode::GetUnencryptedSpecific(..). | 96 // See BaseNode::GetUnencryptedSpecific(..). |
| 97 if (needs_encryption) | 97 if (needs_encryption) |
| 98 entry_->Put(syncable::NON_UNIQUE_NAME, kEncryptedString); | 98 entry_->Put(syncable::NON_UNIQUE_NAME, kEncryptedString); |
| 99 else | 99 else |
| 100 entry_->Put(syncable::NON_UNIQUE_NAME, new_legal_title); | 100 entry_->Put(syncable::NON_UNIQUE_NAME, new_legal_title); |
| 101 | 101 |
| 102 DVLOG(1) << "Overwriting title of type " | 102 DVLOG(1) << "Overwriting title of type " |
| 103 << syncer::ModelTypeToString(type) | 103 << ModelTypeToString(type) |
| 104 << " and marking for syncing."; | 104 << " and marking for syncing."; |
| 105 MarkForSyncing(); | 105 MarkForSyncing(); |
| 106 } | 106 } |
| 107 | 107 |
| 108 void WriteNode::SetURL(const GURL& url) { | 108 void WriteNode::SetURL(const GURL& url) { |
| 109 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); | 109 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); |
| 110 new_value.set_url(url.spec()); | 110 new_value.set_url(url.spec()); |
| 111 SetBookmarkSpecifics(new_value); | 111 SetBookmarkSpecifics(new_value); |
| 112 } | 112 } |
| 113 | 113 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 142 | 142 |
| 143 void WriteNode::SetNigoriSpecifics( | 143 void WriteNode::SetNigoriSpecifics( |
| 144 const sync_pb::NigoriSpecifics& new_value) { | 144 const sync_pb::NigoriSpecifics& new_value) { |
| 145 sync_pb::EntitySpecifics entity_specifics; | 145 sync_pb::EntitySpecifics entity_specifics; |
| 146 entity_specifics.mutable_nigori()->CopyFrom(new_value); | 146 entity_specifics.mutable_nigori()->CopyFrom(new_value); |
| 147 SetEntitySpecifics(entity_specifics); | 147 SetEntitySpecifics(entity_specifics); |
| 148 } | 148 } |
| 149 | 149 |
| 150 void WriteNode::SetPasswordSpecifics( | 150 void WriteNode::SetPasswordSpecifics( |
| 151 const sync_pb::PasswordSpecificsData& data) { | 151 const sync_pb::PasswordSpecificsData& data) { |
| 152 DCHECK_EQ(syncer::PASSWORDS, GetModelType()); | 152 DCHECK_EQ(GetModelType(), PASSWORDS); |
| 153 | 153 |
| 154 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); | 154 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); |
| 155 | 155 |
| 156 // We have to do the idempotency check here (vs in UpdateEntryWithEncryption) | 156 // We have to do the idempotency check here (vs in UpdateEntryWithEncryption) |
| 157 // because Passwords have their encrypted data within the PasswordSpecifics, | 157 // because Passwords have their encrypted data within the PasswordSpecifics, |
| 158 // vs within the EntitySpecifics like all the other types. | 158 // vs within the EntitySpecifics like all the other types. |
| 159 const sync_pb::EntitySpecifics& old_specifics = GetEntry()->Get(SPECIFICS); | 159 const sync_pb::EntitySpecifics& old_specifics = GetEntry()->Get(SPECIFICS); |
| 160 sync_pb::EntitySpecifics entity_specifics; | 160 sync_pb::EntitySpecifics entity_specifics; |
| 161 // Copy over the old specifics if they exist. | 161 // Copy over the old specifics if they exist. |
| 162 if (syncer::GetModelTypeFromSpecifics(old_specifics) == syncer::PASSWORDS) { | 162 if (GetModelTypeFromSpecifics(old_specifics) == PASSWORDS) { |
| 163 entity_specifics.CopyFrom(old_specifics); | 163 entity_specifics.CopyFrom(old_specifics); |
| 164 } else { | 164 } else { |
| 165 syncer::AddDefaultFieldValue(syncer::PASSWORDS, &entity_specifics); | 165 AddDefaultFieldValue(PASSWORDS, &entity_specifics); |
| 166 } | 166 } |
| 167 sync_pb::PasswordSpecifics* password_specifics = | 167 sync_pb::PasswordSpecifics* password_specifics = |
| 168 entity_specifics.mutable_password(); | 168 entity_specifics.mutable_password(); |
| 169 // This will only update password_specifics if the underlying unencrypted blob | 169 // This will only update password_specifics if the underlying unencrypted blob |
| 170 // was different from |data| or was not encrypted with the proper passphrase. | 170 // was different from |data| or was not encrypted with the proper passphrase. |
| 171 if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { | 171 if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { |
| 172 NOTREACHED() << "Failed to encrypt password, possibly due to sync node " | 172 NOTREACHED() << "Failed to encrypt password, possibly due to sync node " |
| 173 << "corruption"; | 173 << "corruption"; |
| 174 return; | 174 return; |
| 175 } | 175 } |
| 176 SetEntitySpecifics(entity_specifics); | 176 SetEntitySpecifics(entity_specifics); |
| 177 } | 177 } |
| 178 | 178 |
| 179 void WriteNode::SetThemeSpecifics( | 179 void WriteNode::SetThemeSpecifics( |
| 180 const sync_pb::ThemeSpecifics& new_value) { | 180 const sync_pb::ThemeSpecifics& new_value) { |
| 181 sync_pb::EntitySpecifics entity_specifics; | 181 sync_pb::EntitySpecifics entity_specifics; |
| 182 entity_specifics.mutable_theme()->CopyFrom(new_value); | 182 entity_specifics.mutable_theme()->CopyFrom(new_value); |
| 183 SetEntitySpecifics(entity_specifics); | 183 SetEntitySpecifics(entity_specifics); |
| 184 } | 184 } |
| 185 | 185 |
| 186 void WriteNode::SetSessionSpecifics( | 186 void WriteNode::SetSessionSpecifics( |
| 187 const sync_pb::SessionSpecifics& new_value) { | 187 const sync_pb::SessionSpecifics& new_value) { |
| 188 sync_pb::EntitySpecifics entity_specifics; | 188 sync_pb::EntitySpecifics entity_specifics; |
| 189 entity_specifics.mutable_session()->CopyFrom(new_value); | 189 entity_specifics.mutable_session()->CopyFrom(new_value); |
| 190 SetEntitySpecifics(entity_specifics); | 190 SetEntitySpecifics(entity_specifics); |
| 191 } | 191 } |
| 192 | 192 |
| 193 void WriteNode::SetEntitySpecifics( | 193 void WriteNode::SetEntitySpecifics( |
| 194 const sync_pb::EntitySpecifics& new_value) { | 194 const sync_pb::EntitySpecifics& new_value) { |
| 195 syncer::ModelType new_specifics_type = | 195 ModelType new_specifics_type = |
| 196 syncer::GetModelTypeFromSpecifics(new_value); | 196 GetModelTypeFromSpecifics(new_value); |
| 197 DCHECK_NE(new_specifics_type, syncer::UNSPECIFIED); | 197 DCHECK_NE(new_specifics_type, UNSPECIFIED); |
| 198 DVLOG(1) << "Writing entity specifics of type " | 198 DVLOG(1) << "Writing entity specifics of type " |
| 199 << syncer::ModelTypeToString(new_specifics_type); | 199 << ModelTypeToString(new_specifics_type); |
| 200 // GetModelType() can be unspecified if this is the first time this | 200 // GetModelType() can be unspecified if this is the first time this |
| 201 // node is being initialized (see PutModelType()). Otherwise, it | 201 // node is being initialized (see PutModelType()). Otherwise, it |
| 202 // should match |new_specifics_type|. | 202 // should match |new_specifics_type|. |
| 203 if (GetModelType() != syncer::UNSPECIFIED) { | 203 if (GetModelType() != UNSPECIFIED) { |
| 204 DCHECK_EQ(new_specifics_type, GetModelType()); | 204 DCHECK_EQ(new_specifics_type, GetModelType()); |
| 205 } | 205 } |
| 206 syncer::Cryptographer* cryptographer = | 206 Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); |
| 207 GetTransaction()->GetCryptographer(); | |
| 208 | 207 |
| 209 // Preserve unknown fields. | 208 // Preserve unknown fields. |
| 210 const sync_pb::EntitySpecifics& old_specifics = entry_->Get(SPECIFICS); | 209 const sync_pb::EntitySpecifics& old_specifics = entry_->Get(SPECIFICS); |
| 211 sync_pb::EntitySpecifics new_specifics; | 210 sync_pb::EntitySpecifics new_specifics; |
| 212 new_specifics.CopyFrom(new_value); | 211 new_specifics.CopyFrom(new_value); |
| 213 new_specifics.mutable_unknown_fields()->MergeFrom( | 212 new_specifics.mutable_unknown_fields()->MergeFrom( |
| 214 old_specifics.unknown_fields()); | 213 old_specifics.unknown_fields()); |
| 215 | 214 |
| 216 // Will update the entry if encryption was necessary. | 215 // Will update the entry if encryption was necessary. |
| 217 if (!UpdateEntryWithEncryption(cryptographer, new_specifics, entry_)) { | 216 if (!UpdateEntryWithEncryption(cryptographer, new_specifics, entry_)) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 return INIT_FAILED_ENTRY_NOT_GOOD; | 271 return INIT_FAILED_ENTRY_NOT_GOOD; |
| 273 if (entry_->Get(syncable::IS_DEL)) | 272 if (entry_->Get(syncable::IS_DEL)) |
| 274 return INIT_FAILED_ENTRY_IS_DEL; | 273 return INIT_FAILED_ENTRY_IS_DEL; |
| 275 return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; | 274 return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; |
| 276 } | 275 } |
| 277 | 276 |
| 278 // Find a node by client tag, and bind this WriteNode to it. | 277 // Find a node by client tag, and bind this WriteNode to it. |
| 279 // Return true if the write node was found, and was not deleted. | 278 // Return true if the write node was found, and was not deleted. |
| 280 // Undeleting a deleted node is possible by ClientTag. | 279 // Undeleting a deleted node is possible by ClientTag. |
| 281 BaseNode::InitByLookupResult WriteNode::InitByClientTagLookup( | 280 BaseNode::InitByLookupResult WriteNode::InitByClientTagLookup( |
| 282 syncer::ModelType model_type, | 281 ModelType model_type, |
| 283 const std::string& tag) { | 282 const std::string& tag) { |
| 284 DCHECK(!entry_) << "Init called twice"; | 283 DCHECK(!entry_) << "Init called twice"; |
| 285 if (tag.empty()) | 284 if (tag.empty()) |
| 286 return INIT_FAILED_PRECONDITION; | 285 return INIT_FAILED_PRECONDITION; |
| 287 | 286 |
| 288 const std::string hash = GenerateSyncableHash(model_type, tag); | 287 const std::string hash = GenerateSyncableHash(model_type, tag); |
| 289 | 288 |
| 290 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 289 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
| 291 syncable::GET_BY_CLIENT_TAG, hash); | 290 syncable::GET_BY_CLIENT_TAG, hash); |
| 292 if (!entry_->good()) | 291 if (!entry_->good()) |
| 293 return INIT_FAILED_ENTRY_NOT_GOOD; | 292 return INIT_FAILED_ENTRY_NOT_GOOD; |
| 294 if (entry_->Get(syncable::IS_DEL)) | 293 if (entry_->Get(syncable::IS_DEL)) |
| 295 return INIT_FAILED_ENTRY_IS_DEL; | 294 return INIT_FAILED_ENTRY_IS_DEL; |
| 296 return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; | 295 return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; |
| 297 } | 296 } |
| 298 | 297 |
| 299 BaseNode::InitByLookupResult WriteNode::InitByTagLookup( | 298 BaseNode::InitByLookupResult WriteNode::InitByTagLookup( |
| 300 const std::string& tag) { | 299 const std::string& tag) { |
| 301 DCHECK(!entry_) << "Init called twice"; | 300 DCHECK(!entry_) << "Init called twice"; |
| 302 if (tag.empty()) | 301 if (tag.empty()) |
| 303 return INIT_FAILED_PRECONDITION; | 302 return INIT_FAILED_PRECONDITION; |
| 304 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 303 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
| 305 syncable::GET_BY_SERVER_TAG, tag); | 304 syncable::GET_BY_SERVER_TAG, tag); |
| 306 if (!entry_->good()) | 305 if (!entry_->good()) |
| 307 return INIT_FAILED_ENTRY_NOT_GOOD; | 306 return INIT_FAILED_ENTRY_NOT_GOOD; |
| 308 if (entry_->Get(syncable::IS_DEL)) | 307 if (entry_->Get(syncable::IS_DEL)) |
| 309 return INIT_FAILED_ENTRY_IS_DEL; | 308 return INIT_FAILED_ENTRY_IS_DEL; |
| 310 syncer::ModelType model_type = GetModelType(); | 309 ModelType model_type = GetModelType(); |
| 311 DCHECK_EQ(syncer::NIGORI, model_type); | 310 DCHECK_EQ(model_type, NIGORI); |
| 312 return INIT_OK; | 311 return INIT_OK; |
| 313 } | 312 } |
| 314 | 313 |
| 315 void WriteNode::PutModelType(syncer::ModelType model_type) { | 314 void WriteNode::PutModelType(ModelType model_type) { |
| 316 // Set an empty specifics of the appropriate datatype. The presence | 315 // Set an empty specifics of the appropriate datatype. The presence |
| 317 // of the specific field will identify the model type. | 316 // of the specific field will identify the model type. |
| 318 DCHECK(GetModelType() == model_type || | 317 DCHECK(GetModelType() == model_type || |
| 319 GetModelType() == syncer::UNSPECIFIED); // Immutable once set. | 318 GetModelType() == UNSPECIFIED); // Immutable once set. |
| 320 | 319 |
| 321 sync_pb::EntitySpecifics specifics; | 320 sync_pb::EntitySpecifics specifics; |
| 322 syncer::AddDefaultFieldValue(model_type, &specifics); | 321 AddDefaultFieldValue(model_type, &specifics); |
| 323 SetEntitySpecifics(specifics); | 322 SetEntitySpecifics(specifics); |
| 324 } | 323 } |
| 325 | 324 |
| 326 // Create a new node with default properties, and bind this WriteNode to it. | 325 // Create a new node with default properties, and bind this WriteNode to it. |
| 327 // Return true on success. | 326 // Return true on success. |
| 328 bool WriteNode::InitByCreation(syncer::ModelType model_type, | 327 bool WriteNode::InitByCreation(ModelType model_type, |
| 329 const BaseNode& parent, | 328 const BaseNode& parent, |
| 330 const BaseNode* predecessor) { | 329 const BaseNode* predecessor) { |
| 331 DCHECK(!entry_) << "Init called twice"; | 330 DCHECK(!entry_) << "Init called twice"; |
| 332 // |predecessor| must be a child of |parent| or NULL. | 331 // |predecessor| must be a child of |parent| or NULL. |
| 333 if (predecessor && predecessor->GetParentId() != parent.GetId()) { | 332 if (predecessor && predecessor->GetParentId() != parent.GetId()) { |
| 334 DCHECK(false); | 333 DCHECK(false); |
| 335 return false; | 334 return false; |
| 336 } | 335 } |
| 337 | 336 |
| 338 syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); | 337 syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 356 return PutPredecessor(predecessor); | 355 return PutPredecessor(predecessor); |
| 357 } | 356 } |
| 358 | 357 |
| 359 // Create a new node with default properties and a client defined unique tag, | 358 // Create a new node with default properties and a client defined unique tag, |
| 360 // and bind this WriteNode to it. | 359 // and bind this WriteNode to it. |
| 361 // Return true on success. If the tag exists in the database, then | 360 // Return true on success. If the tag exists in the database, then |
| 362 // we will attempt to undelete the node. | 361 // we will attempt to undelete the node. |
| 363 // TODO(chron): Code datatype into hash tag. | 362 // TODO(chron): Code datatype into hash tag. |
| 364 // TODO(chron): Is model type ever lost? | 363 // TODO(chron): Is model type ever lost? |
| 365 WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreation( | 364 WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreation( |
| 366 syncer::ModelType model_type, | 365 ModelType model_type, |
| 367 const BaseNode& parent, | 366 const BaseNode& parent, |
| 368 const std::string& tag) { | 367 const std::string& tag) { |
| 369 // This DCHECK will only fail if init is called twice. | 368 // This DCHECK will only fail if init is called twice. |
| 370 DCHECK(!entry_); | 369 DCHECK(!entry_); |
| 371 if (tag.empty()) { | 370 if (tag.empty()) { |
| 372 LOG(WARNING) << "InitUniqueByCreation failed due to empty tag."; | 371 LOG(WARNING) << "InitUniqueByCreation failed due to empty tag."; |
| 373 return INIT_FAILED_EMPTY_TAG; | 372 return INIT_FAILED_EMPTY_TAG; |
| 374 } | 373 } |
| 375 | 374 |
| 376 const std::string hash = GenerateSyncableHash(model_type, tag); | 375 const std::string hash = GenerateSyncableHash(model_type, tag); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); | 503 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); |
| 505 new_value.set_favicon(bytes.empty() ? NULL : &bytes[0], bytes.size()); | 504 new_value.set_favicon(bytes.empty() ? NULL : &bytes[0], bytes.size()); |
| 506 SetBookmarkSpecifics(new_value); | 505 SetBookmarkSpecifics(new_value); |
| 507 } | 506 } |
| 508 | 507 |
| 509 void WriteNode::MarkForSyncing() { | 508 void WriteNode::MarkForSyncing() { |
| 510 syncable::MarkForSyncing(entry_); | 509 syncable::MarkForSyncing(entry_); |
| 511 } | 510 } |
| 512 | 511 |
| 513 } // namespace syncer | 512 } // namespace syncer |
| OLD | NEW |