Chromium Code Reviews| 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/base_node.h" | 5 #include "sync/internal_api/public/base_node.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/sha1.h" | 8 #include "base/sha1.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 --length_to_copy; | 57 --length_to_copy; |
| 58 } | 58 } |
| 59 *out = std::string(server_name.c_str(), length_to_copy); | 59 *out = std::string(server_name.c_str(), length_to_copy); |
| 60 } | 60 } |
| 61 | 61 |
| 62 BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {} | 62 BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {} |
| 63 | 63 |
| 64 BaseNode::~BaseNode() {} | 64 BaseNode::~BaseNode() {} |
| 65 | 65 |
| 66 std::string BaseNode::GenerateSyncableHash( | 66 std::string BaseNode::GenerateSyncableHash( |
| 67 syncer::ModelType model_type, const std::string& client_tag) { | 67 ModelType model_type, const std::string& client_tag) { |
| 68 // Blank PB with just the field in it has termination symbol, | 68 // Blank PB with just the field in it has termination symbol, |
| 69 // handy for delimiter. | 69 // handy for delimiter. |
| 70 sync_pb::EntitySpecifics serialized_type; | 70 sync_pb::EntitySpecifics serialized_type; |
| 71 syncer::AddDefaultFieldValue(model_type, &serialized_type); | 71 AddDefaultFieldValue(model_type, &serialized_type); |
| 72 std::string hash_input; | 72 std::string hash_input; |
| 73 serialized_type.AppendToString(&hash_input); | 73 serialized_type.AppendToString(&hash_input); |
| 74 hash_input.append(client_tag); | 74 hash_input.append(client_tag); |
| 75 | 75 |
| 76 std::string encode_output; | 76 std::string encode_output; |
| 77 CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); | 77 CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); |
| 78 return encode_output; | 78 return encode_output; |
| 79 } | 79 } |
| 80 | 80 |
| 81 bool BaseNode::DecryptIfNecessary() { | 81 bool BaseNode::DecryptIfNecessary() { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 94 password_data_.swap(data); | 94 password_data_.swap(data); |
| 95 return true; | 95 return true; |
| 96 } | 96 } |
| 97 | 97 |
| 98 // We assume any node with the encrypted field set has encrypted data and if | 98 // We assume any node with the encrypted field set has encrypted data and if |
| 99 // not we have no work to do, with the exception of bookmarks. For bookmarks | 99 // not we have no work to do, with the exception of bookmarks. For bookmarks |
| 100 // we must make sure the bookmarks data has the title field supplied. If not, | 100 // we must make sure the bookmarks data has the title field supplied. If not, |
| 101 // we fill the unencrypted_data_ with a copy of the bookmark specifics that | 101 // we fill the unencrypted_data_ with a copy of the bookmark specifics that |
| 102 // follows the new bookmarks format. | 102 // follows the new bookmarks format. |
| 103 if (!specifics.has_encrypted()) { | 103 if (!specifics.has_encrypted()) { |
| 104 if (GetModelType() == syncer::BOOKMARKS && | 104 if (GetModelType() == BOOKMARKS && |
| 105 !specifics.bookmark().has_title() && | 105 !specifics.bookmark().has_title() && |
| 106 !GetTitle().empty()) { // Last check ensures this isn't a new node. | 106 !GetTitle().empty()) { // Last check ensures this isn't a new node. |
| 107 // We need to fill in the title. | 107 // We need to fill in the title. |
| 108 std::string title = GetTitle(); | 108 std::string title = GetTitle(); |
| 109 std::string server_legal_title; | 109 std::string server_legal_title; |
| 110 SyncAPINameToServerName(title, &server_legal_title); | 110 SyncAPINameToServerName(title, &server_legal_title); |
| 111 DVLOG(1) << "Reading from legacy bookmark, manually returning title " | 111 DVLOG(1) << "Reading from legacy bookmark, manually returning title " |
| 112 << title; | 112 << title; |
| 113 unencrypted_data_.CopyFrom(specifics); | 113 unencrypted_data_.CopyFrom(specifics); |
| 114 unencrypted_data_.mutable_bookmark()->set_title( | 114 unencrypted_data_.mutable_bookmark()->set_title( |
| 115 server_legal_title); | 115 server_legal_title); |
| 116 } | 116 } |
| 117 return true; | 117 return true; |
| 118 } | 118 } |
| 119 | 119 |
| 120 const sync_pb::EncryptedData& encrypted = specifics.encrypted(); | 120 const sync_pb::EncryptedData& encrypted = specifics.encrypted(); |
| 121 std::string plaintext_data = GetTransaction()->GetCryptographer()-> | 121 std::string plaintext_data = GetTransaction()->GetCryptographer()-> |
| 122 DecryptToString(encrypted); | 122 DecryptToString(encrypted); |
| 123 if (plaintext_data.length() == 0) { | 123 if (plaintext_data.length() == 0) { |
| 124 LOG(ERROR) << "Failed to decrypt encrypted node of type " << | 124 LOG(ERROR) << "Failed to decrypt encrypted node of type " << |
| 125 syncer::ModelTypeToString(GetModelType()) << "."; | 125 ModelTypeToString(GetModelType()) << "."; |
|
Nicolas Zea
2012/07/19 19:37:56
nit: fix up indent
akalin
2012/07/19 20:56:02
Done.
| |
| 126 // Debugging for crbug.com/123223. We failed to decrypt the data, which | 126 // Debugging for crbug.com/123223. We failed to decrypt the data, which |
| 127 // means we applied an update without having the key or lost the key at a | 127 // means we applied an update without having the key or lost the key at a |
| 128 // later point. | 128 // later point. |
| 129 CHECK(false); | 129 CHECK(false); |
| 130 return false; | 130 return false; |
| 131 } else if (!unencrypted_data_.ParseFromString(plaintext_data)) { | 131 } else if (!unencrypted_data_.ParseFromString(plaintext_data)) { |
| 132 // Debugging for crbug.com/123223. We should never succeed in decrypting | 132 // Debugging for crbug.com/123223. We should never succeed in decrypting |
| 133 // but fail to parse into a protobuf. | 133 // but fail to parse into a protobuf. |
| 134 CHECK(false); | 134 CHECK(false); |
| 135 return false; | 135 return false; |
| 136 } | 136 } |
| 137 DVLOG(2) << "Decrypted specifics of type " | 137 DVLOG(2) << "Decrypted specifics of type " |
| 138 << syncer::ModelTypeToString(GetModelType()) | 138 << ModelTypeToString(GetModelType()) |
| 139 << " with content: " << plaintext_data; | 139 << " with content: " << plaintext_data; |
| 140 return true; | 140 return true; |
| 141 } | 141 } |
| 142 | 142 |
| 143 const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( | 143 const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( |
| 144 const syncable::Entry* entry) const { | 144 const syncable::Entry* entry) const { |
| 145 const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); | 145 const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); |
| 146 if (specifics.has_encrypted()) { | 146 if (specifics.has_encrypted()) { |
| 147 DCHECK_NE(syncer::GetModelTypeFromSpecifics(unencrypted_data_), | 147 DCHECK_NE(GetModelTypeFromSpecifics(unencrypted_data_), UNSPECIFIED); |
| 148 syncer::UNSPECIFIED); | |
| 149 return unencrypted_data_; | 148 return unencrypted_data_; |
| 150 } else { | 149 } else { |
| 151 // Due to the change in bookmarks format, we need to check to see if this is | 150 // Due to the change in bookmarks format, we need to check to see if this is |
| 152 // a legacy bookmarks (and has no title field in the proto). If it is, we | 151 // a legacy bookmarks (and has no title field in the proto). If it is, we |
| 153 // return the unencrypted_data_, which was filled in with the title by | 152 // return the unencrypted_data_, which was filled in with the title by |
| 154 // DecryptIfNecessary(). | 153 // DecryptIfNecessary(). |
| 155 if (GetModelType() == syncer::BOOKMARKS) { | 154 if (GetModelType() == BOOKMARKS) { |
| 156 const sync_pb::BookmarkSpecifics& bookmark_specifics = | 155 const sync_pb::BookmarkSpecifics& bookmark_specifics = |
| 157 specifics.bookmark(); | 156 specifics.bookmark(); |
| 158 if (bookmark_specifics.has_title() || | 157 if (bookmark_specifics.has_title() || |
| 159 GetTitle().empty() || // For the empty node case | 158 GetTitle().empty() || // For the empty node case |
| 160 !GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { | 159 !GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { |
| 161 // It's possible we previously had to convert and set | 160 // It's possible we previously had to convert and set |
| 162 // |unencrypted_data_| but then wrote our own data, so we allow | 161 // |unencrypted_data_| but then wrote our own data, so we allow |
| 163 // |unencrypted_data_| to be non-empty. | 162 // |unencrypted_data_| to be non-empty. |
| 164 return specifics; | 163 return specifics; |
| 165 } else { | 164 } else { |
| 166 DCHECK_EQ(syncer::GetModelTypeFromSpecifics(unencrypted_data_), | 165 DCHECK_EQ(GetModelTypeFromSpecifics(unencrypted_data_), BOOKMARKS); |
| 167 syncer::BOOKMARKS); | |
| 168 return unencrypted_data_; | 166 return unencrypted_data_; |
| 169 } | 167 } |
| 170 } else { | 168 } else { |
| 171 DCHECK_EQ(syncer::GetModelTypeFromSpecifics(unencrypted_data_), | 169 DCHECK_EQ(GetModelTypeFromSpecifics(unencrypted_data_), UNSPECIFIED); |
| 172 syncer::UNSPECIFIED); | |
| 173 return specifics; | 170 return specifics; |
| 174 } | 171 } |
| 175 } | 172 } |
| 176 } | 173 } |
| 177 | 174 |
| 178 int64 BaseNode::GetParentId() const { | 175 int64 BaseNode::GetParentId() const { |
| 179 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), | 176 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), |
| 180 GetEntry()->Get(syncable::PARENT_ID)); | 177 GetEntry()->Get(syncable::PARENT_ID)); |
| 181 } | 178 } |
| 182 | 179 |
| 183 int64 BaseNode::GetId() const { | 180 int64 BaseNode::GetId() const { |
| 184 return GetEntry()->Get(syncable::META_HANDLE); | 181 return GetEntry()->Get(syncable::META_HANDLE); |
| 185 } | 182 } |
| 186 | 183 |
| 187 const base::Time& BaseNode::GetModificationTime() const { | 184 const base::Time& BaseNode::GetModificationTime() const { |
| 188 return GetEntry()->Get(syncable::MTIME); | 185 return GetEntry()->Get(syncable::MTIME); |
| 189 } | 186 } |
| 190 | 187 |
| 191 bool BaseNode::GetIsFolder() const { | 188 bool BaseNode::GetIsFolder() const { |
| 192 return GetEntry()->Get(syncable::IS_DIR); | 189 return GetEntry()->Get(syncable::IS_DIR); |
| 193 } | 190 } |
| 194 | 191 |
| 195 std::string BaseNode::GetTitle() const { | 192 std::string BaseNode::GetTitle() const { |
| 196 std::string result; | 193 std::string result; |
| 197 // TODO(zea): refactor bookmarks to not need this functionality. | 194 // TODO(zea): refactor bookmarks to not need this functionality. |
| 198 if (syncer::BOOKMARKS == GetModelType() && | 195 if (BOOKMARKS == GetModelType() && |
| 199 GetEntry()->Get(syncable::SPECIFICS).has_encrypted()) { | 196 GetEntry()->Get(syncable::SPECIFICS).has_encrypted()) { |
| 200 // Special case for legacy bookmarks dealing with encryption. | 197 // Special case for legacy bookmarks dealing with encryption. |
| 201 ServerNameToSyncAPIName(GetBookmarkSpecifics().title(), &result); | 198 ServerNameToSyncAPIName(GetBookmarkSpecifics().title(), &result); |
| 202 } else { | 199 } else { |
| 203 ServerNameToSyncAPIName(GetEntry()->Get(syncable::NON_UNIQUE_NAME), | 200 ServerNameToSyncAPIName(GetEntry()->Get(syncable::NON_UNIQUE_NAME), |
| 204 &result); | 201 &result); |
| 205 } | 202 } |
| 206 return result; | 203 return result; |
| 207 } | 204 } |
| 208 | 205 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 node_info->SetBoolean("isFolder", GetIsFolder()); | 246 node_info->SetBoolean("isFolder", GetIsFolder()); |
| 250 node_info->SetString("title", GetTitle()); | 247 node_info->SetString("title", GetTitle()); |
| 251 node_info->Set("type", ModelTypeToValue(GetModelType())); | 248 node_info->Set("type", ModelTypeToValue(GetModelType())); |
| 252 return node_info; | 249 return node_info; |
| 253 } | 250 } |
| 254 | 251 |
| 255 DictionaryValue* BaseNode::GetDetailsAsValue() const { | 252 DictionaryValue* BaseNode::GetDetailsAsValue() const { |
| 256 DictionaryValue* node_info = GetSummaryAsValue(); | 253 DictionaryValue* node_info = GetSummaryAsValue(); |
| 257 node_info->SetString( | 254 node_info->SetString( |
| 258 "modificationTime", | 255 "modificationTime", |
| 259 syncer::GetTimeDebugString(GetModificationTime())); | 256 GetTimeDebugString(GetModificationTime())); |
| 260 node_info->SetString("parentId", base::Int64ToString(GetParentId())); | 257 node_info->SetString("parentId", base::Int64ToString(GetParentId())); |
| 261 // Specifics are already in the Entry value, so no need to duplicate | 258 // Specifics are already in the Entry value, so no need to duplicate |
| 262 // it here. | 259 // it here. |
| 263 node_info->SetString("externalId", | 260 node_info->SetString("externalId", |
| 264 base::Int64ToString(GetExternalId())); | 261 base::Int64ToString(GetExternalId())); |
| 265 node_info->SetString("predecessorId", | 262 node_info->SetString("predecessorId", |
| 266 base::Int64ToString(GetPredecessorId())); | 263 base::Int64ToString(GetPredecessorId())); |
| 267 node_info->SetString("successorId", | 264 node_info->SetString("successorId", |
| 268 base::Int64ToString(GetSuccessorId())); | 265 base::Int64ToString(GetSuccessorId())); |
| 269 node_info->SetString("firstChildId", | 266 node_info->SetString("firstChildId", |
| 270 base::Int64ToString(GetFirstChildId())); | 267 base::Int64ToString(GetFirstChildId())); |
| 271 node_info->Set("entry", GetEntry()->ToValue()); | 268 node_info->Set("entry", GetEntry()->ToValue()); |
| 272 return node_info; | 269 return node_info; |
| 273 } | 270 } |
| 274 | 271 |
| 275 void BaseNode::GetFaviconBytes(std::vector<unsigned char>* output) const { | 272 void BaseNode::GetFaviconBytes(std::vector<unsigned char>* output) const { |
| 276 if (!output) | 273 if (!output) |
| 277 return; | 274 return; |
| 278 const std::string& favicon = GetBookmarkSpecifics().favicon(); | 275 const std::string& favicon = GetBookmarkSpecifics().favicon(); |
| 279 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), | 276 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), |
| 280 reinterpret_cast<const unsigned char*>(favicon.data() + | 277 reinterpret_cast<const unsigned char*>(favicon.data() + |
| 281 favicon.length())); | 278 favicon.length())); |
| 282 } | 279 } |
| 283 | 280 |
| 284 int64 BaseNode::GetExternalId() const { | 281 int64 BaseNode::GetExternalId() const { |
| 285 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); | 282 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); |
| 286 } | 283 } |
| 287 | 284 |
| 288 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { | 285 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { |
| 289 DCHECK_EQ(syncer::APPS, GetModelType()); | 286 DCHECK_EQ(GetModelType(), APPS); |
|
Nicolas Zea
2012/07/19 19:37:56
nit: these should be the other way around right? i
akalin
2012/07/19 20:56:02
that's only for gtest functions (EXPECT_EQ, ASSERT
| |
| 290 return GetEntitySpecifics().app(); | 287 return GetEntitySpecifics().app(); |
| 291 } | 288 } |
| 292 | 289 |
| 293 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { | 290 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { |
| 294 DCHECK_EQ(syncer::AUTOFILL, GetModelType()); | 291 DCHECK_EQ(GetModelType(), AUTOFILL); |
| 295 return GetEntitySpecifics().autofill(); | 292 return GetEntitySpecifics().autofill(); |
| 296 } | 293 } |
| 297 | 294 |
| 298 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { | 295 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { |
| 299 DCHECK_EQ(GetModelType(), syncer::AUTOFILL_PROFILE); | 296 DCHECK_EQ(GetModelType(), AUTOFILL_PROFILE); |
| 300 return GetEntitySpecifics().autofill_profile(); | 297 return GetEntitySpecifics().autofill_profile(); |
| 301 } | 298 } |
| 302 | 299 |
| 303 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { | 300 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { |
| 304 DCHECK_EQ(syncer::BOOKMARKS, GetModelType()); | 301 DCHECK_EQ(GetModelType(), BOOKMARKS); |
| 305 return GetEntitySpecifics().bookmark(); | 302 return GetEntitySpecifics().bookmark(); |
| 306 } | 303 } |
| 307 | 304 |
| 308 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { | 305 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { |
| 309 DCHECK_EQ(syncer::NIGORI, GetModelType()); | 306 DCHECK_EQ(GetModelType(), NIGORI); |
| 310 return GetEntitySpecifics().nigori(); | 307 return GetEntitySpecifics().nigori(); |
| 311 } | 308 } |
| 312 | 309 |
| 313 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { | 310 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { |
| 314 DCHECK_EQ(syncer::PASSWORDS, GetModelType()); | 311 DCHECK_EQ(GetModelType(), PASSWORDS); |
| 315 return *password_data_; | 312 return *password_data_; |
| 316 } | 313 } |
| 317 | 314 |
| 318 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { | 315 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { |
| 319 DCHECK_EQ(syncer::THEMES, GetModelType()); | 316 DCHECK_EQ(GetModelType(), THEMES); |
| 320 return GetEntitySpecifics().theme(); | 317 return GetEntitySpecifics().theme(); |
| 321 } | 318 } |
| 322 | 319 |
| 323 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { | 320 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { |
| 324 DCHECK_EQ(syncer::TYPED_URLS, GetModelType()); | 321 DCHECK_EQ(GetModelType(), TYPED_URLS); |
| 325 return GetEntitySpecifics().typed_url(); | 322 return GetEntitySpecifics().typed_url(); |
| 326 } | 323 } |
| 327 | 324 |
| 328 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { | 325 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { |
| 329 DCHECK_EQ(syncer::EXTENSIONS, GetModelType()); | 326 DCHECK_EQ(GetModelType(), EXTENSIONS); |
| 330 return GetEntitySpecifics().extension(); | 327 return GetEntitySpecifics().extension(); |
| 331 } | 328 } |
| 332 | 329 |
| 333 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { | 330 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { |
| 334 DCHECK_EQ(syncer::SESSIONS, GetModelType()); | 331 DCHECK_EQ(GetModelType(), SESSIONS); |
| 335 return GetEntitySpecifics().session(); | 332 return GetEntitySpecifics().session(); |
| 336 } | 333 } |
| 337 | 334 |
| 338 const sync_pb::EntitySpecifics& BaseNode::GetEntitySpecifics() const { | 335 const sync_pb::EntitySpecifics& BaseNode::GetEntitySpecifics() const { |
| 339 return GetUnencryptedSpecifics(GetEntry()); | 336 return GetUnencryptedSpecifics(GetEntry()); |
| 340 } | 337 } |
| 341 | 338 |
| 342 syncer::ModelType BaseNode::GetModelType() const { | 339 ModelType BaseNode::GetModelType() const { |
| 343 return GetEntry()->GetModelType(); | 340 return GetEntry()->GetModelType(); |
| 344 } | 341 } |
| 345 | 342 |
| 346 void BaseNode::SetUnencryptedSpecifics( | 343 void BaseNode::SetUnencryptedSpecifics( |
| 347 const sync_pb::EntitySpecifics& specifics) { | 344 const sync_pb::EntitySpecifics& specifics) { |
| 348 syncer::ModelType type = syncer::GetModelTypeFromSpecifics(specifics); | 345 ModelType type = GetModelTypeFromSpecifics(specifics); |
| 349 DCHECK_NE(syncer::UNSPECIFIED, type); | 346 DCHECK_NE(UNSPECIFIED, type); |
| 350 if (GetModelType() != syncer::UNSPECIFIED) { | 347 if (GetModelType() != UNSPECIFIED) { |
| 351 DCHECK_EQ(GetModelType(), type); | 348 DCHECK_EQ(GetModelType(), type); |
| 352 } | 349 } |
| 353 unencrypted_data_.CopyFrom(specifics); | 350 unencrypted_data_.CopyFrom(specifics); |
| 354 } | 351 } |
| 355 | 352 |
| 356 } // namespace syncer | 353 } // namespace syncer |
| OLD | NEW |