| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/syncapi.h" | 5 #include "chrome/browser/sync/engine/syncapi.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <bitset> | 7 #include <bitset> |
| 9 #include <iomanip> | 8 #include <iomanip> |
| 10 #include <list> | 9 #include <list> |
| 11 #include <queue> | |
| 12 #include <string> | 10 #include <string> |
| 13 #include <vector> | 11 #include <vector> |
| 14 | 12 |
| 15 #include "base/base64.h" | 13 #include "base/base64.h" |
| 16 #include "base/logging.h" | 14 #include "base/logging.h" |
| 17 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
| 18 #include "base/observer_list.h" | 16 #include "base/observer_list.h" |
| 19 #include "base/scoped_ptr.h" | 17 #include "base/scoped_ptr.h" |
| 20 #include "base/sha1.h" | 18 #include "base/sha1.h" |
| 21 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 47 #include "chrome/browser/sync/protocol/proto_value_conversions.h" | 45 #include "chrome/browser/sync/protocol/proto_value_conversions.h" |
| 48 #include "chrome/browser/sync/protocol/service_constants.h" | 46 #include "chrome/browser/sync/protocol/service_constants.h" |
| 49 #include "chrome/browser/sync/protocol/session_specifics.pb.h" | 47 #include "chrome/browser/sync/protocol/session_specifics.pb.h" |
| 50 #include "chrome/browser/sync/protocol/sync.pb.h" | 48 #include "chrome/browser/sync/protocol/sync.pb.h" |
| 51 #include "chrome/browser/sync/protocol/theme_specifics.pb.h" | 49 #include "chrome/browser/sync/protocol/theme_specifics.pb.h" |
| 52 #include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" | 50 #include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" |
| 53 #include "chrome/browser/sync/sessions/sync_session.h" | 51 #include "chrome/browser/sync/sessions/sync_session.h" |
| 54 #include "chrome/browser/sync/sessions/sync_session_context.h" | 52 #include "chrome/browser/sync/sessions/sync_session_context.h" |
| 55 #include "chrome/browser/sync/syncable/autofill_migration.h" | 53 #include "chrome/browser/sync/syncable/autofill_migration.h" |
| 56 #include "chrome/browser/sync/syncable/directory_manager.h" | 54 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 57 #include "chrome/browser/sync/syncable/nigori_util.h" | |
| 58 #include "chrome/browser/sync/syncable/syncable.h" | 55 #include "chrome/browser/sync/syncable/syncable.h" |
| 59 #include "chrome/browser/sync/util/crypto_helpers.h" | 56 #include "chrome/browser/sync/util/crypto_helpers.h" |
| 60 #include "chrome/common/deprecated/event_sys.h" | 57 #include "chrome/common/deprecated/event_sys.h" |
| 61 #include "chrome/common/net/gaia/gaia_authenticator.h" | 58 #include "chrome/common/net/gaia/gaia_authenticator.h" |
| 62 #include "jingle/notifier/listener/mediator_thread_impl.h" | 59 #include "jingle/notifier/listener/mediator_thread_impl.h" |
| 63 #include "jingle/notifier/listener/notification_constants.h" | 60 #include "jingle/notifier/listener/notification_constants.h" |
| 64 #include "jingle/notifier/listener/talk_mediator.h" | 61 #include "jingle/notifier/listener/talk_mediator.h" |
| 65 #include "jingle/notifier/listener/talk_mediator_impl.h" | 62 #include "jingle/notifier/listener/talk_mediator_impl.h" |
| 66 #include "net/base/network_change_notifier.h" | 63 #include "net/base/network_change_notifier.h" |
| 67 | 64 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 | 185 |
| 189 std::string encode_output; | 186 std::string encode_output; |
| 190 CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); | 187 CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); |
| 191 return encode_output; | 188 return encode_output; |
| 192 } | 189 } |
| 193 | 190 |
| 194 sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( | 191 sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( |
| 195 const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) { | 192 const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) { |
| 196 if (!specifics.HasExtension(sync_pb::password)) | 193 if (!specifics.HasExtension(sync_pb::password)) |
| 197 return NULL; | 194 return NULL; |
| 198 const sync_pb::PasswordSpecifics& password_specifics = | 195 const sync_pb::EncryptedData& encrypted = |
| 199 specifics.GetExtension(sync_pb::password); | 196 specifics.GetExtension(sync_pb::password).encrypted(); |
| 200 if (!password_specifics.has_encrypted()) | |
| 201 return NULL; | |
| 202 const sync_pb::EncryptedData& encrypted = password_specifics.encrypted(); | |
| 203 scoped_ptr<sync_pb::PasswordSpecificsData> data( | 197 scoped_ptr<sync_pb::PasswordSpecificsData> data( |
| 204 new sync_pb::PasswordSpecificsData); | 198 new sync_pb::PasswordSpecificsData); |
| 205 if (!crypto->Decrypt(encrypted, data.get())) | 199 if (!crypto->Decrypt(encrypted, data.get())) |
| 206 return NULL; | 200 return NULL; |
| 207 return data.release(); | 201 return data.release(); |
| 208 } | 202 } |
| 209 | 203 |
| 210 bool BaseNode::DecryptIfNecessary(Entry* entry) { | 204 bool BaseNode::DecryptIfNecessary(Entry* entry) { |
| 211 if (GetIsFolder()) return true; // Ignore the top-level datatype folder. | 205 if (GetIsFolder()) return true; // Ignore the top-level password folder. |
| 212 const sync_pb::EntitySpecifics& specifics = | 206 const sync_pb::EntitySpecifics& specifics = |
| 213 entry->Get(syncable::SPECIFICS); | 207 entry->Get(syncable::SPECIFICS); |
| 214 if (specifics.HasExtension(sync_pb::password)) { | 208 if (specifics.HasExtension(sync_pb::password)) { |
| 215 // Passwords have their own legacy encryption structure. | |
| 216 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( | 209 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( |
| 217 specifics, GetTransaction()->GetCryptographer())); | 210 specifics, GetTransaction()->GetCryptographer())); |
| 218 if (!data.get()) | 211 if (!data.get()) |
| 219 return false; | 212 return false; |
| 220 password_data_.swap(data); | 213 password_data_.swap(data); |
| 221 return true; | |
| 222 } | |
| 223 | |
| 224 // We assume any node with the encrypted field set has encrypted data. | |
| 225 if (!specifics.has_encrypted()) | |
| 226 return true; | |
| 227 | |
| 228 const sync_pb::EncryptedData& encrypted = | |
| 229 specifics.encrypted(); | |
| 230 std::string plaintext_data = GetTransaction()->GetCryptographer()-> | |
| 231 DecryptToString(encrypted); | |
| 232 if (plaintext_data.length() == 0) | |
| 233 return false; | |
| 234 if (!unencrypted_data_.ParseFromString(plaintext_data)) { | |
| 235 LOG(ERROR) << "Failed to decrypt encrypted node of type " << | |
| 236 syncable::ModelTypeToString(entry->GetModelType()) << "."; | |
| 237 return false; | |
| 238 } | 214 } |
| 239 return true; | 215 return true; |
| 240 } | 216 } |
| 241 | 217 |
| 242 const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( | |
| 243 const syncable::Entry* entry) const { | |
| 244 const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); | |
| 245 if (specifics.has_encrypted()) { | |
| 246 DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) != | |
| 247 syncable::UNSPECIFIED); | |
| 248 return unencrypted_data_; | |
| 249 } else { | |
| 250 DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) == | |
| 251 syncable::UNSPECIFIED); | |
| 252 return specifics; | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 int64 BaseNode::GetParentId() const { | 218 int64 BaseNode::GetParentId() const { |
| 257 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), | 219 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), |
| 258 GetEntry()->Get(syncable::PARENT_ID)); | 220 GetEntry()->Get(syncable::PARENT_ID)); |
| 259 } | 221 } |
| 260 | 222 |
| 261 int64 BaseNode::GetId() const { | 223 int64 BaseNode::GetId() const { |
| 262 return GetEntry()->Get(syncable::META_HANDLE); | 224 return GetEntry()->Get(syncable::META_HANDLE); |
| 263 } | 225 } |
| 264 | 226 |
| 265 int64 BaseNode::GetModificationTime() const { | 227 int64 BaseNode::GetModificationTime() const { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), | 309 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), |
| 348 reinterpret_cast<const unsigned char*>(favicon.data() + | 310 reinterpret_cast<const unsigned char*>(favicon.data() + |
| 349 favicon.length())); | 311 favicon.length())); |
| 350 } | 312 } |
| 351 | 313 |
| 352 int64 BaseNode::GetExternalId() const { | 314 int64 BaseNode::GetExternalId() const { |
| 353 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); | 315 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); |
| 354 } | 316 } |
| 355 | 317 |
| 356 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { | 318 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { |
| 357 DCHECK_EQ(syncable::APPS, GetModelType()); | 319 DCHECK(GetModelType() == syncable::APPS); |
| 358 const sync_pb::EntitySpecifics& unencrypted = | 320 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::app); |
| 359 GetUnencryptedSpecifics(GetEntry()); | |
| 360 return unencrypted.GetExtension(sync_pb::app); | |
| 361 } | 321 } |
| 362 | 322 |
| 363 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { | 323 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { |
| 364 DCHECK_EQ(syncable::AUTOFILL, GetModelType()); | 324 DCHECK(GetModelType() == syncable::AUTOFILL); |
| 365 const sync_pb::EntitySpecifics& unencrypted = | 325 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill); |
| 366 GetUnencryptedSpecifics(GetEntry()); | |
| 367 return unencrypted.GetExtension(sync_pb::autofill); | |
| 368 } | 326 } |
| 369 | 327 |
| 370 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { | 328 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { |
| 371 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); | 329 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); |
| 372 const sync_pb::EntitySpecifics& unencrypted = | 330 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill_profile); |
| 373 GetUnencryptedSpecifics(GetEntry()); | |
| 374 return unencrypted.GetExtension(sync_pb::autofill_profile); | |
| 375 } | 331 } |
| 376 | 332 |
| 377 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { | 333 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { |
| 378 DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); | 334 DCHECK(GetModelType() == syncable::BOOKMARKS); |
| 379 const sync_pb::EntitySpecifics& unencrypted = | 335 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::bookmark); |
| 380 GetUnencryptedSpecifics(GetEntry()); | |
| 381 return unencrypted.GetExtension(sync_pb::bookmark); | |
| 382 } | 336 } |
| 383 | 337 |
| 384 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { | 338 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { |
| 385 DCHECK_EQ(syncable::NIGORI, GetModelType()); | 339 DCHECK(GetModelType() == syncable::NIGORI); |
| 386 const sync_pb::EntitySpecifics& unencrypted = | 340 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::nigori); |
| 387 GetUnencryptedSpecifics(GetEntry()); | |
| 388 return unencrypted.GetExtension(sync_pb::nigori); | |
| 389 } | 341 } |
| 390 | 342 |
| 391 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { | 343 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { |
| 392 DCHECK_EQ(syncable::PASSWORDS, GetModelType()); | 344 DCHECK(GetModelType() == syncable::PASSWORDS); |
| 393 DCHECK(password_data_.get()); | 345 DCHECK(password_data_.get()); |
| 394 return *password_data_; | 346 return *password_data_; |
| 395 } | 347 } |
| 396 | 348 |
| 397 const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { | 349 const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { |
| 398 DCHECK_EQ(syncable::PREFERENCES, GetModelType()); | 350 DCHECK(GetModelType() == syncable::PREFERENCES); |
| 399 const sync_pb::EntitySpecifics& unencrypted = | 351 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::preference); |
| 400 GetUnencryptedSpecifics(GetEntry()); | |
| 401 return unencrypted.GetExtension(sync_pb::preference); | |
| 402 } | 352 } |
| 403 | 353 |
| 404 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { | 354 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { |
| 405 DCHECK_EQ(syncable::THEMES, GetModelType()); | 355 DCHECK(GetModelType() == syncable::THEMES); |
| 406 const sync_pb::EntitySpecifics& unencrypted = | 356 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::theme); |
| 407 GetUnencryptedSpecifics(GetEntry()); | |
| 408 return unencrypted.GetExtension(sync_pb::theme); | |
| 409 } | 357 } |
| 410 | 358 |
| 411 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { | 359 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { |
| 412 DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); | 360 DCHECK(GetModelType() == syncable::TYPED_URLS); |
| 413 const sync_pb::EntitySpecifics& unencrypted = | 361 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::typed_url); |
| 414 GetUnencryptedSpecifics(GetEntry()); | |
| 415 return unencrypted.GetExtension(sync_pb::typed_url); | |
| 416 } | 362 } |
| 417 | 363 |
| 418 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { | 364 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { |
| 419 DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); | 365 DCHECK(GetModelType() == syncable::EXTENSIONS); |
| 420 const sync_pb::EntitySpecifics& unencrypted = | 366 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::extension); |
| 421 GetUnencryptedSpecifics(GetEntry()); | |
| 422 return unencrypted.GetExtension(sync_pb::extension); | |
| 423 } | 367 } |
| 424 | 368 |
| 425 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { | 369 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { |
| 426 DCHECK_EQ(syncable::SESSIONS, GetModelType()); | 370 DCHECK(GetModelType() == syncable::SESSIONS); |
| 427 const sync_pb::EntitySpecifics& unencrypted = | 371 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::session); |
| 428 GetUnencryptedSpecifics(GetEntry()); | |
| 429 return unencrypted.GetExtension(sync_pb::session); | |
| 430 } | 372 } |
| 431 | 373 |
| 432 syncable::ModelType BaseNode::GetModelType() const { | 374 syncable::ModelType BaseNode::GetModelType() const { |
| 433 return GetEntry()->GetModelType(); | 375 return GetEntry()->GetModelType(); |
| 434 } | 376 } |
| 435 | 377 |
| 436 //////////////////////////////////// | 378 //////////////////////////////////// |
| 437 // WriteNode member definitions | 379 // WriteNode member definitions |
| 438 void WriteNode::EncryptIfNecessary(sync_pb::EntitySpecifics* unencrypted) { | |
| 439 syncable::ModelType type = syncable::GetModelTypeFromSpecifics(*unencrypted); | |
| 440 DCHECK_NE(type, syncable::UNSPECIFIED); | |
| 441 DCHECK_NE(type, syncable::PASSWORDS); // Passwords use their own encryption. | |
| 442 DCHECK_NE(type, syncable::NIGORI); // Nigori is encrypted separately. | |
| 443 | |
| 444 syncable::ModelTypeSet encrypted_types = | |
| 445 GetEncryptedDataTypes(GetTransaction()->GetWrappedTrans()); | |
| 446 if (encrypted_types.count(type) == 0) { | |
| 447 // This datatype does not require encryption. | |
| 448 return; | |
| 449 } | |
| 450 | |
| 451 if (unencrypted->has_encrypted()) { | |
| 452 // This specifics is already encrypted, our work is done. | |
| 453 LOG(WARNING) << "Attempted to encrypt an already encrypted entity" | |
| 454 << " specifics of type " << syncable::ModelTypeToString(type) | |
| 455 << ". Dropping."; | |
| 456 return; | |
| 457 } | |
| 458 sync_pb::EntitySpecifics encrypted; | |
| 459 syncable::AddDefaultExtensionValue(type, &encrypted); | |
| 460 VLOG(2) << "Encrypted specifics of type " << syncable::ModelTypeToString(type) | |
| 461 << " with content: " << unencrypted->SerializeAsString() << "\n"; | |
| 462 if (!GetTransaction()->GetCryptographer()->Encrypt( | |
| 463 *unencrypted, | |
| 464 encrypted.mutable_encrypted())) { | |
| 465 LOG(ERROR) << "Could not encrypt data for node of type " << | |
| 466 syncable::ModelTypeToString(type); | |
| 467 NOTREACHED(); | |
| 468 } | |
| 469 unencrypted->CopyFrom(encrypted); | |
| 470 } | |
| 471 | |
| 472 void WriteNode::SetIsFolder(bool folder) { | 380 void WriteNode::SetIsFolder(bool folder) { |
| 473 if (entry_->Get(syncable::IS_DIR) == folder) | 381 if (entry_->Get(syncable::IS_DIR) == folder) |
| 474 return; // Skip redundant changes. | 382 return; // Skip redundant changes. |
| 475 | 383 |
| 476 entry_->Put(syncable::IS_DIR, folder); | 384 entry_->Put(syncable::IS_DIR, folder); |
| 477 MarkForSyncing(); | 385 MarkForSyncing(); |
| 478 } | 386 } |
| 479 | 387 |
| 480 void WriteNode::SetTitle(const std::wstring& title) { | 388 void WriteNode::SetTitle(const std::wstring& title) { |
| 481 std::string server_legal_name; | 389 std::string server_legal_name; |
| 482 SyncAPINameToServerName(title, &server_legal_name); | 390 SyncAPINameToServerName(title, &server_legal_name); |
| 483 | 391 |
| 484 string old_name = entry_->Get(syncable::NON_UNIQUE_NAME); | 392 string old_name = entry_->Get(syncable::NON_UNIQUE_NAME); |
| 485 | 393 |
| 486 if (server_legal_name == old_name) | 394 if (server_legal_name == old_name) |
| 487 return; // Skip redundant changes. | 395 return; // Skip redundant changes. |
| 488 | 396 |
| 489 entry_->Put(syncable::NON_UNIQUE_NAME, server_legal_name); | 397 entry_->Put(syncable::NON_UNIQUE_NAME, server_legal_name); |
| 490 MarkForSyncing(); | 398 MarkForSyncing(); |
| 491 } | 399 } |
| 492 | 400 |
| 493 void WriteNode::SetURL(const GURL& url) { | 401 void WriteNode::SetURL(const GURL& url) { |
| 494 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); | 402 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); |
| 495 new_value.set_url(url.spec()); | 403 new_value.set_url(url.spec()); |
| 496 SetBookmarkSpecifics(new_value); | 404 SetBookmarkSpecifics(new_value); |
| 497 } | 405 } |
| 498 | 406 |
| 499 void WriteNode::SetAppSpecifics( | 407 void WriteNode::SetAppSpecifics( |
| 500 const sync_pb::AppSpecifics& new_value) { | 408 const sync_pb::AppSpecifics& new_value) { |
| 501 DCHECK_EQ(syncable::APPS, GetModelType()); | 409 DCHECK(GetModelType() == syncable::APPS); |
| 502 PutAppSpecificsAndMarkForSyncing(new_value); | 410 PutAppSpecificsAndMarkForSyncing(new_value); |
| 503 } | 411 } |
| 504 | 412 |
| 505 void WriteNode::SetAutofillSpecifics( | 413 void WriteNode::SetAutofillSpecifics( |
| 506 const sync_pb::AutofillSpecifics& new_value) { | 414 const sync_pb::AutofillSpecifics& new_value) { |
| 507 DCHECK_EQ(syncable::AUTOFILL, GetModelType()); | 415 DCHECK(GetModelType() == syncable::AUTOFILL); |
| 508 PutAutofillSpecificsAndMarkForSyncing(new_value); | 416 PutAutofillSpecificsAndMarkForSyncing(new_value); |
| 509 } | 417 } |
| 510 | 418 |
| 511 void WriteNode::PutAutofillSpecificsAndMarkForSyncing( | 419 void WriteNode::PutAutofillSpecificsAndMarkForSyncing( |
| 512 const sync_pb::AutofillSpecifics& new_value) { | 420 const sync_pb::AutofillSpecifics& new_value) { |
| 513 sync_pb::EntitySpecifics entity_specifics; | 421 sync_pb::EntitySpecifics entity_specifics; |
| 514 entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); | 422 entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); |
| 515 EncryptIfNecessary(&entity_specifics); | |
| 516 PutSpecificsAndMarkForSyncing(entity_specifics); | 423 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 517 } | 424 } |
| 518 | 425 |
| 519 void WriteNode::SetAutofillProfileSpecifics( | 426 void WriteNode::SetAutofillProfileSpecifics( |
| 520 const sync_pb::AutofillProfileSpecifics& new_value) { | 427 const sync_pb::AutofillProfileSpecifics& new_value) { |
| 521 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); | 428 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); |
| 522 PutAutofillProfileSpecificsAndMarkForSyncing(new_value); | 429 PutAutofillProfileSpecificsAndMarkForSyncing(new_value); |
| 523 } | 430 } |
| 524 | 431 |
| 525 void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( | 432 void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( |
| 526 const sync_pb::AutofillProfileSpecifics& new_value) { | 433 const sync_pb::AutofillProfileSpecifics& new_value) { |
| 527 sync_pb::EntitySpecifics entity_specifics; | 434 sync_pb::EntitySpecifics entity_specifics; |
| 528 entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( | 435 entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( |
| 529 new_value); | 436 new_value); |
| 530 EncryptIfNecessary(&entity_specifics); | |
| 531 PutSpecificsAndMarkForSyncing(entity_specifics); | 437 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 532 } | 438 } |
| 533 | 439 |
| 534 void WriteNode::SetBookmarkSpecifics( | 440 void WriteNode::SetBookmarkSpecifics( |
| 535 const sync_pb::BookmarkSpecifics& new_value) { | 441 const sync_pb::BookmarkSpecifics& new_value) { |
| 536 DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); | 442 DCHECK(GetModelType() == syncable::BOOKMARKS); |
| 537 PutBookmarkSpecificsAndMarkForSyncing(new_value); | 443 PutBookmarkSpecificsAndMarkForSyncing(new_value); |
| 538 } | 444 } |
| 539 | 445 |
| 540 void WriteNode::PutBookmarkSpecificsAndMarkForSyncing( | 446 void WriteNode::PutBookmarkSpecificsAndMarkForSyncing( |
| 541 const sync_pb::BookmarkSpecifics& new_value) { | 447 const sync_pb::BookmarkSpecifics& new_value) { |
| 542 sync_pb::EntitySpecifics entity_specifics; | 448 sync_pb::EntitySpecifics entity_specifics; |
| 543 entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); | 449 entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); |
| 544 EncryptIfNecessary(&entity_specifics); | |
| 545 PutSpecificsAndMarkForSyncing(entity_specifics); | 450 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 546 } | 451 } |
| 547 | 452 |
| 548 void WriteNode::SetNigoriSpecifics( | 453 void WriteNode::SetNigoriSpecifics( |
| 549 const sync_pb::NigoriSpecifics& new_value) { | 454 const sync_pb::NigoriSpecifics& new_value) { |
| 550 DCHECK_EQ(syncable::NIGORI, GetModelType()); | 455 DCHECK(GetModelType() == syncable::NIGORI); |
| 551 PutNigoriSpecificsAndMarkForSyncing(new_value); | 456 PutNigoriSpecificsAndMarkForSyncing(new_value); |
| 552 } | 457 } |
| 553 | 458 |
| 554 void WriteNode::PutNigoriSpecificsAndMarkForSyncing( | 459 void WriteNode::PutNigoriSpecificsAndMarkForSyncing( |
| 555 const sync_pb::NigoriSpecifics& new_value) { | 460 const sync_pb::NigoriSpecifics& new_value) { |
| 556 sync_pb::EntitySpecifics entity_specifics; | 461 sync_pb::EntitySpecifics entity_specifics; |
| 557 entity_specifics.MutableExtension(sync_pb::nigori)->CopyFrom(new_value); | 462 entity_specifics.MutableExtension(sync_pb::nigori)->CopyFrom(new_value); |
| 558 PutSpecificsAndMarkForSyncing(entity_specifics); | 463 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 559 } | 464 } |
| 560 | 465 |
| 561 void WriteNode::SetPasswordSpecifics( | 466 void WriteNode::SetPasswordSpecifics( |
| 562 const sync_pb::PasswordSpecificsData& data) { | 467 const sync_pb::PasswordSpecificsData& data) { |
| 563 DCHECK_EQ(syncable::PASSWORDS, GetModelType()); | 468 DCHECK(GetModelType() == syncable::PASSWORDS); |
| 469 |
| 564 sync_pb::PasswordSpecifics new_value; | 470 sync_pb::PasswordSpecifics new_value; |
| 565 if (!GetTransaction()->GetCryptographer()->Encrypt( | 471 if (!GetTransaction()->GetCryptographer()->Encrypt( |
| 566 data, | 472 data, |
| 567 new_value.mutable_encrypted())) { | 473 new_value.mutable_encrypted())) { |
| 568 NOTREACHED(); | 474 NOTREACHED(); |
| 569 } | 475 } |
| 476 |
| 570 PutPasswordSpecificsAndMarkForSyncing(new_value); | 477 PutPasswordSpecificsAndMarkForSyncing(new_value); |
| 571 } | 478 } |
| 572 | 479 |
| 573 void WriteNode::SetPreferenceSpecifics( | 480 void WriteNode::SetPreferenceSpecifics( |
| 574 const sync_pb::PreferenceSpecifics& new_value) { | 481 const sync_pb::PreferenceSpecifics& new_value) { |
| 575 DCHECK_EQ(syncable::PREFERENCES, GetModelType()); | 482 DCHECK(GetModelType() == syncable::PREFERENCES); |
| 576 PutPreferenceSpecificsAndMarkForSyncing(new_value); | 483 PutPreferenceSpecificsAndMarkForSyncing(new_value); |
| 577 } | 484 } |
| 578 | 485 |
| 579 void WriteNode::SetThemeSpecifics( | 486 void WriteNode::SetThemeSpecifics( |
| 580 const sync_pb::ThemeSpecifics& new_value) { | 487 const sync_pb::ThemeSpecifics& new_value) { |
| 581 DCHECK_EQ(syncable::THEMES, GetModelType()); | 488 DCHECK(GetModelType() == syncable::THEMES); |
| 582 PutThemeSpecificsAndMarkForSyncing(new_value); | 489 PutThemeSpecificsAndMarkForSyncing(new_value); |
| 583 } | 490 } |
| 584 | 491 |
| 585 void WriteNode::SetSessionSpecifics( | 492 void WriteNode::SetSessionSpecifics( |
| 586 const sync_pb::SessionSpecifics& new_value) { | 493 const sync_pb::SessionSpecifics& new_value) { |
| 587 DCHECK_EQ(syncable::SESSIONS, GetModelType()); | 494 DCHECK(GetModelType() == syncable::SESSIONS); |
| 588 PutSessionSpecificsAndMarkForSyncing(new_value); | 495 PutSessionSpecificsAndMarkForSyncing(new_value); |
| 589 } | 496 } |
| 590 | 497 |
| 591 void WriteNode::ResetFromSpecifics() { | |
| 592 sync_pb::EntitySpecifics new_data; | |
| 593 new_data.CopyFrom(GetUnencryptedSpecifics(GetEntry())); | |
| 594 EncryptIfNecessary(&new_data); | |
| 595 PutSpecificsAndMarkForSyncing(new_data); | |
| 596 } | |
| 597 | 498 |
| 598 void WriteNode::PutPasswordSpecificsAndMarkForSyncing( | 499 void WriteNode::PutPasswordSpecificsAndMarkForSyncing( |
| 599 const sync_pb::PasswordSpecifics& new_value) { | 500 const sync_pb::PasswordSpecifics& new_value) { |
| 600 sync_pb::EntitySpecifics entity_specifics; | 501 sync_pb::EntitySpecifics entity_specifics; |
| 601 entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); | 502 entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); |
| 602 PutSpecificsAndMarkForSyncing(entity_specifics); | 503 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 603 } | 504 } |
| 604 | 505 |
| 605 void WriteNode::PutPreferenceSpecificsAndMarkForSyncing( | 506 void WriteNode::PutPreferenceSpecificsAndMarkForSyncing( |
| 606 const sync_pb::PreferenceSpecifics& new_value) { | 507 const sync_pb::PreferenceSpecifics& new_value) { |
| 607 sync_pb::EntitySpecifics entity_specifics; | 508 sync_pb::EntitySpecifics entity_specifics; |
| 608 entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); | 509 entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); |
| 609 EncryptIfNecessary(&entity_specifics); | |
| 610 PutSpecificsAndMarkForSyncing(entity_specifics); | 510 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 611 } | 511 } |
| 612 | 512 |
| 613 void WriteNode::SetTypedUrlSpecifics( | 513 void WriteNode::SetTypedUrlSpecifics( |
| 614 const sync_pb::TypedUrlSpecifics& new_value) { | 514 const sync_pb::TypedUrlSpecifics& new_value) { |
| 615 DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); | 515 DCHECK(GetModelType() == syncable::TYPED_URLS); |
| 616 PutTypedUrlSpecificsAndMarkForSyncing(new_value); | 516 PutTypedUrlSpecificsAndMarkForSyncing(new_value); |
| 617 } | 517 } |
| 618 | 518 |
| 619 void WriteNode::SetExtensionSpecifics( | 519 void WriteNode::SetExtensionSpecifics( |
| 620 const sync_pb::ExtensionSpecifics& new_value) { | 520 const sync_pb::ExtensionSpecifics& new_value) { |
| 621 DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); | 521 DCHECK(GetModelType() == syncable::EXTENSIONS); |
| 622 PutExtensionSpecificsAndMarkForSyncing(new_value); | 522 PutExtensionSpecificsAndMarkForSyncing(new_value); |
| 623 } | 523 } |
| 624 | 524 |
| 625 void WriteNode::PutAppSpecificsAndMarkForSyncing( | 525 void WriteNode::PutAppSpecificsAndMarkForSyncing( |
| 626 const sync_pb::AppSpecifics& new_value) { | 526 const sync_pb::AppSpecifics& new_value) { |
| 627 sync_pb::EntitySpecifics entity_specifics; | 527 sync_pb::EntitySpecifics entity_specifics; |
| 628 entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); | 528 entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); |
| 629 EncryptIfNecessary(&entity_specifics); | |
| 630 PutSpecificsAndMarkForSyncing(entity_specifics); | 529 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 631 } | 530 } |
| 632 | 531 |
| 633 void WriteNode::PutThemeSpecificsAndMarkForSyncing( | 532 void WriteNode::PutThemeSpecificsAndMarkForSyncing( |
| 634 const sync_pb::ThemeSpecifics& new_value) { | 533 const sync_pb::ThemeSpecifics& new_value) { |
| 635 sync_pb::EntitySpecifics entity_specifics; | 534 sync_pb::EntitySpecifics entity_specifics; |
| 636 entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); | 535 entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); |
| 637 EncryptIfNecessary(&entity_specifics); | |
| 638 PutSpecificsAndMarkForSyncing(entity_specifics); | 536 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 639 } | 537 } |
| 640 | 538 |
| 641 void WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( | 539 void WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( |
| 642 const sync_pb::TypedUrlSpecifics& new_value) { | 540 const sync_pb::TypedUrlSpecifics& new_value) { |
| 643 sync_pb::EntitySpecifics entity_specifics; | 541 sync_pb::EntitySpecifics entity_specifics; |
| 644 entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); | 542 entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); |
| 645 EncryptIfNecessary(&entity_specifics); | |
| 646 PutSpecificsAndMarkForSyncing(entity_specifics); | 543 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 647 } | 544 } |
| 648 | 545 |
| 649 void WriteNode::PutExtensionSpecificsAndMarkForSyncing( | 546 void WriteNode::PutExtensionSpecificsAndMarkForSyncing( |
| 650 const sync_pb::ExtensionSpecifics& new_value) { | 547 const sync_pb::ExtensionSpecifics& new_value) { |
| 651 sync_pb::EntitySpecifics entity_specifics; | 548 sync_pb::EntitySpecifics entity_specifics; |
| 652 entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); | 549 entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); |
| 653 EncryptIfNecessary(&entity_specifics); | |
| 654 PutSpecificsAndMarkForSyncing(entity_specifics); | 550 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 655 } | 551 } |
| 656 | 552 |
| 553 |
| 657 void WriteNode::PutSessionSpecificsAndMarkForSyncing( | 554 void WriteNode::PutSessionSpecificsAndMarkForSyncing( |
| 658 const sync_pb::SessionSpecifics& new_value) { | 555 const sync_pb::SessionSpecifics& new_value) { |
| 659 sync_pb::EntitySpecifics entity_specifics; | 556 sync_pb::EntitySpecifics entity_specifics; |
| 660 entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); | 557 entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); |
| 661 EncryptIfNecessary(&entity_specifics); | |
| 662 PutSpecificsAndMarkForSyncing(entity_specifics); | 558 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 663 } | 559 } |
| 664 | 560 |
| 561 |
| 665 void WriteNode::PutSpecificsAndMarkForSyncing( | 562 void WriteNode::PutSpecificsAndMarkForSyncing( |
| 666 const sync_pb::EntitySpecifics& specifics) { | 563 const sync_pb::EntitySpecifics& specifics) { |
| 667 // Skip redundant changes. | 564 // Skip redundant changes. |
| 668 if (specifics.SerializeAsString() == | 565 if (specifics.SerializeAsString() == |
| 669 entry_->Get(SPECIFICS).SerializeAsString()) { | 566 entry_->Get(SPECIFICS).SerializeAsString()) { |
| 670 return; | 567 return; |
| 671 } | 568 } |
| 672 entry_->Put(SPECIFICS, specifics); | 569 entry_->Put(SPECIFICS, specifics); |
| 673 MarkForSyncing(); | 570 MarkForSyncing(); |
| 674 } | 571 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 DCHECK(!entry_) << "Init called twice"; | 616 DCHECK(!entry_) << "Init called twice"; |
| 720 if (tag.empty()) | 617 if (tag.empty()) |
| 721 return false; | 618 return false; |
| 722 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 619 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
| 723 syncable::GET_BY_SERVER_TAG, tag); | 620 syncable::GET_BY_SERVER_TAG, tag); |
| 724 if (!entry_->good()) | 621 if (!entry_->good()) |
| 725 return false; | 622 return false; |
| 726 if (entry_->Get(syncable::IS_DEL)) | 623 if (entry_->Get(syncable::IS_DEL)) |
| 727 return false; | 624 return false; |
| 728 syncable::ModelType model_type = GetModelType(); | 625 syncable::ModelType model_type = GetModelType(); |
| 729 DCHECK_EQ(syncable::NIGORI, model_type); | 626 DCHECK(model_type == syncable::NIGORI); |
| 730 return true; | 627 return true; |
| 731 } | 628 } |
| 732 | 629 |
| 733 void WriteNode::PutModelType(syncable::ModelType model_type) { | 630 void WriteNode::PutModelType(syncable::ModelType model_type) { |
| 734 // Set an empty specifics of the appropriate datatype. The presence | 631 // Set an empty specifics of the appropriate datatype. The presence |
| 735 // of the specific extension will identify the model type. | 632 // of the specific extension will identify the model type. |
| 736 DCHECK(GetModelType() == model_type || | 633 DCHECK(GetModelType() == model_type || |
| 737 GetModelType() == syncable::UNSPECIFIED); // Immutable once set. | 634 GetModelType() == syncable::UNSPECIFIED); // Immutable once set. |
| 738 | 635 |
| 739 sync_pb::EntitySpecifics specifics; | 636 sync_pb::EntitySpecifics specifics; |
| 740 syncable::AddDefaultExtensionValue(model_type, &specifics); | 637 syncable::AddDefaultExtensionValue(model_type, &specifics); |
| 741 PutSpecificsAndMarkForSyncing(specifics); | 638 PutSpecificsAndMarkForSyncing(specifics); |
| 742 DCHECK_EQ(model_type, GetModelType()); | 639 DCHECK(GetModelType() == model_type); |
| 743 } | 640 } |
| 744 | 641 |
| 745 // Create a new node with default properties, and bind this WriteNode to it. | 642 // Create a new node with default properties, and bind this WriteNode to it. |
| 746 // Return true on success. | 643 // Return true on success. |
| 747 bool WriteNode::InitByCreation(syncable::ModelType model_type, | 644 bool WriteNode::InitByCreation(syncable::ModelType model_type, |
| 748 const BaseNode& parent, | 645 const BaseNode& parent, |
| 749 const BaseNode* predecessor) { | 646 const BaseNode* predecessor) { |
| 750 DCHECK(!entry_) << "Init called twice"; | 647 DCHECK(!entry_) << "Init called twice"; |
| 751 // |predecessor| must be a child of |parent| or NULL. | 648 // |predecessor| must be a child of |parent| or NULL. |
| 752 if (predecessor && predecessor->GetParentId() != parent.GetId()) { | 649 if (predecessor && predecessor->GetParentId() != parent.GetId()) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 } | 927 } |
| 1031 | 928 |
| 1032 WriteTransaction::~WriteTransaction() { | 929 WriteTransaction::~WriteTransaction() { |
| 1033 delete transaction_; | 930 delete transaction_; |
| 1034 } | 931 } |
| 1035 | 932 |
| 1036 syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { | 933 syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { |
| 1037 return transaction_; | 934 return transaction_; |
| 1038 } | 935 } |
| 1039 | 936 |
| 937 SyncManager::ExtraChangeRecordData::~ExtraChangeRecordData() {} |
| 938 |
| 1040 SyncManager::ChangeRecord::ChangeRecord() | 939 SyncManager::ChangeRecord::ChangeRecord() |
| 1041 : id(kInvalidId), action(ACTION_ADD) {} | 940 : id(kInvalidId), action(ACTION_ADD) {} |
| 1042 | 941 |
| 1043 SyncManager::ChangeRecord::~ChangeRecord() {} | 942 SyncManager::ChangeRecord::~ChangeRecord() {} |
| 1044 | 943 |
| 1045 DictionaryValue* SyncManager::ChangeRecord::ToValue( | 944 DictionaryValue* SyncManager::ChangeRecord::ToValue( |
| 1046 const BaseTransaction* trans) const { | 945 const BaseTransaction* trans) const { |
| 1047 DictionaryValue* value = new DictionaryValue(); | 946 DictionaryValue* value = new DictionaryValue(); |
| 1048 std::string action_str; | 947 std::string action_str; |
| 1049 switch (action) { | 948 switch (action) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1079 } | 978 } |
| 1080 } | 979 } |
| 1081 if (!node_value) { | 980 if (!node_value) { |
| 1082 NOTREACHED(); | 981 NOTREACHED(); |
| 1083 node_value = Value::CreateNullValue(); | 982 node_value = Value::CreateNullValue(); |
| 1084 } | 983 } |
| 1085 value->Set("node", node_value); | 984 value->Set("node", node_value); |
| 1086 return value; | 985 return value; |
| 1087 } | 986 } |
| 1088 | 987 |
| 1089 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} | |
| 1090 | |
| 1091 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( | 988 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( |
| 1092 const sync_pb::PasswordSpecificsData& data) | 989 const sync_pb::PasswordSpecificsData& data) |
| 1093 : unencrypted_(data) { | 990 : unencrypted_(data) {} |
| 1094 } | |
| 1095 | 991 |
| 1096 SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} | 992 SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} |
| 1097 | 993 |
| 1098 DictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const { | 994 DictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const { |
| 1099 return browser_sync::PasswordSpecificsDataToValue(unencrypted_); | 995 return browser_sync::PasswordSpecificsDataToValue(unencrypted_); |
| 1100 } | 996 } |
| 1101 | 997 |
| 1102 const sync_pb::PasswordSpecificsData& | 998 const sync_pb::PasswordSpecificsData& |
| 1103 SyncManager::ExtraPasswordChangeRecordData::unencrypted() const { | 999 SyncManager::ExtraPasswordChangeRecordData::unencrypted() const { |
| 1104 return unencrypted_; | 1000 return unencrypted_; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 // Update the set of enabled sync types. Usually called when the user disables | 1053 // Update the set of enabled sync types. Usually called when the user disables |
| 1158 // or enables a sync type. | 1054 // or enables a sync type. |
| 1159 void UpdateEnabledTypes(const syncable::ModelTypeSet& types); | 1055 void UpdateEnabledTypes(const syncable::ModelTypeSet& types); |
| 1160 | 1056 |
| 1161 // Tell the sync engine to start the syncing process. | 1057 // Tell the sync engine to start the syncing process. |
| 1162 void StartSyncing(); | 1058 void StartSyncing(); |
| 1163 | 1059 |
| 1164 // Whether or not the Nigori node is encrypted using an explicit passphrase. | 1060 // Whether or not the Nigori node is encrypted using an explicit passphrase. |
| 1165 bool IsUsingExplicitPassphrase(); | 1061 bool IsUsingExplicitPassphrase(); |
| 1166 | 1062 |
| 1167 // Set the datatypes we want to encrypt and encrypt any nodes as necessary. | |
| 1168 void EncryptDataTypes(const syncable::ModelTypeSet& encrypted_types); | |
| 1169 | |
| 1170 // Try to set the current passphrase to |passphrase|, and record whether | 1063 // Try to set the current passphrase to |passphrase|, and record whether |
| 1171 // it is an explicit passphrase or implicitly using gaia in the Nigori | 1064 // it is an explicit passphrase or implicitly using gaia in the Nigori |
| 1172 // node. | 1065 // node. |
| 1173 void SetPassphrase(const std::string& passphrase, bool is_explicit); | 1066 void SetPassphrase(const std::string& passphrase, bool is_explicit); |
| 1174 | 1067 |
| 1175 // Call periodically from a database-safe thread to persist recent changes | 1068 // Call periodically from a database-safe thread to persist recent changes |
| 1176 // to the syncapi model. | 1069 // to the syncapi model. |
| 1177 void SaveChanges(); | 1070 void SaveChanges(); |
| 1178 | 1071 |
| 1179 // This listener is called upon completion of a syncable transaction, and | 1072 // This listener is called upon completion of a syncable transaction, and |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 // See SyncManager::Shutdown for information. | 1128 // See SyncManager::Shutdown for information. |
| 1236 void Shutdown(); | 1129 void Shutdown(); |
| 1237 | 1130 |
| 1238 // Whether we're initialized to the point of being able to accept changes | 1131 // Whether we're initialized to the point of being able to accept changes |
| 1239 // (and hence allow transaction creation). See initialized_ for details. | 1132 // (and hence allow transaction creation). See initialized_ for details. |
| 1240 bool initialized() const { | 1133 bool initialized() const { |
| 1241 base::AutoLock lock(initialized_mutex_); | 1134 base::AutoLock lock(initialized_mutex_); |
| 1242 return initialized_; | 1135 return initialized_; |
| 1243 } | 1136 } |
| 1244 | 1137 |
| 1245 // If this is a deletion for a password, sets the legacy | |
| 1246 // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets | |
| 1247 // |buffer|'s specifics field to contain the unencrypted data. | |
| 1248 void SetExtraChangeRecordData(int64 id, | 1138 void SetExtraChangeRecordData(int64 id, |
| 1249 syncable::ModelType type, | 1139 syncable::ModelType type, |
| 1250 ChangeReorderBuffer* buffer, | 1140 ChangeReorderBuffer* buffer, |
| 1251 Cryptographer* cryptographer, | 1141 Cryptographer* cryptographer, |
| 1252 const syncable::EntryKernel& original, | 1142 const syncable::EntryKernel& original, |
| 1253 bool existed_before, | 1143 bool existed_before, |
| 1254 bool exists_now); | 1144 bool exists_now); |
| 1255 | 1145 |
| 1256 // Called only by our NetworkChangeNotifier. | 1146 // Called only by our NetworkChangeNotifier. |
| 1257 virtual void OnIPAddressChanged(); | 1147 virtual void OnIPAddressChanged(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 return true; | 1253 return true; |
| 1364 if (a.ref(syncable::PARENT_ID) != b.Get(syncable::PARENT_ID)) | 1254 if (a.ref(syncable::PARENT_ID) != b.Get(syncable::PARENT_ID)) |
| 1365 return true; | 1255 return true; |
| 1366 return false; | 1256 return false; |
| 1367 } | 1257 } |
| 1368 | 1258 |
| 1369 // Determine if any of the fields made visible to clients of the Sync API | 1259 // Determine if any of the fields made visible to clients of the Sync API |
| 1370 // differ between the versions of an entry stored in |a| and |b|. A return | 1260 // differ between the versions of an entry stored in |a| and |b|. A return |
| 1371 // value of false means that it should be OK to ignore this change. | 1261 // value of false means that it should be OK to ignore this change. |
| 1372 static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, | 1262 static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, |
| 1373 const syncable::Entry& b, | 1263 const syncable::Entry& b) { |
| 1374 Cryptographer* cryptographer) { | |
| 1375 syncable::ModelType model_type = b.GetModelType(); | 1264 syncable::ModelType model_type = b.GetModelType(); |
| 1376 // Suppress updates to items that aren't tracked by any browser model. | 1265 // Suppress updates to items that aren't tracked by any browser model. |
| 1377 if (model_type == syncable::UNSPECIFIED || | 1266 if (model_type == syncable::UNSPECIFIED || |
| 1378 model_type == syncable::TOP_LEVEL_FOLDER) { | 1267 model_type == syncable::TOP_LEVEL_FOLDER) { |
| 1379 return false; | 1268 return false; |
| 1380 } | 1269 } |
| 1381 if (a.ref(syncable::NON_UNIQUE_NAME) != b.Get(syncable::NON_UNIQUE_NAME)) | 1270 if (a.ref(syncable::NON_UNIQUE_NAME) != b.Get(syncable::NON_UNIQUE_NAME)) |
| 1382 return true; | 1271 return true; |
| 1383 if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) | 1272 if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) |
| 1384 return true; | 1273 return true; |
| 1385 // Check if data has changed (account for encryption). | 1274 if (a.ref(SPECIFICS).SerializeAsString() != |
| 1386 std::string a_str, b_str; | 1275 b.Get(SPECIFICS).SerializeAsString()) { |
| 1387 if (a.ref(SPECIFICS).has_encrypted()) { | |
| 1388 const sync_pb::EncryptedData& encrypted = a.ref(SPECIFICS).encrypted(); | |
| 1389 a_str = cryptographer->DecryptToString(encrypted); | |
| 1390 } else { | |
| 1391 a_str = a.ref(SPECIFICS).SerializeAsString(); | |
| 1392 } | |
| 1393 if (b.Get(SPECIFICS).has_encrypted()) { | |
| 1394 const sync_pb::EncryptedData& encrypted = b.Get(SPECIFICS).encrypted(); | |
| 1395 b_str = cryptographer->DecryptToString(encrypted); | |
| 1396 } else { | |
| 1397 b_str = b.Get(SPECIFICS).SerializeAsString(); | |
| 1398 } | |
| 1399 if (a_str != b_str) { | |
| 1400 return true; | 1276 return true; |
| 1401 } | 1277 } |
| 1402 if (VisiblePositionsDiffer(a, b)) | 1278 if (VisiblePositionsDiffer(a, b)) |
| 1403 return true; | 1279 return true; |
| 1404 return false; | 1280 return false; |
| 1405 } | 1281 } |
| 1406 | 1282 |
| 1407 bool ChangeBuffersAreEmpty() { | 1283 bool ChangeBuffersAreEmpty() { |
| 1408 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { | 1284 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { |
| 1409 if (!change_buffers_[i].IsEmpty()) | 1285 if (!change_buffers_[i].IsEmpty()) |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1594 syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, | 1470 syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, |
| 1595 const syncable::AutofillMigrationDebugInfo& info) { | 1471 const syncable::AutofillMigrationDebugInfo& info) { |
| 1596 return data_->SetAutofillMigrationDebugInfo(property_to_set, info); | 1472 return data_->SetAutofillMigrationDebugInfo(property_to_set, info); |
| 1597 } | 1473 } |
| 1598 | 1474 |
| 1599 void SyncManager::SetPassphrase(const std::string& passphrase, | 1475 void SyncManager::SetPassphrase(const std::string& passphrase, |
| 1600 bool is_explicit) { | 1476 bool is_explicit) { |
| 1601 data_->SetPassphrase(passphrase, is_explicit); | 1477 data_->SetPassphrase(passphrase, is_explicit); |
| 1602 } | 1478 } |
| 1603 | 1479 |
| 1604 void SyncManager::EncryptDataTypes( | |
| 1605 const syncable::ModelTypeSet& encrypted_types) { | |
| 1606 data_->EncryptDataTypes(encrypted_types); | |
| 1607 } | |
| 1608 | |
| 1609 bool SyncManager::IsUsingExplicitPassphrase() { | 1480 bool SyncManager::IsUsingExplicitPassphrase() { |
| 1610 return data_ && data_->IsUsingExplicitPassphrase(); | 1481 return data_ && data_->IsUsingExplicitPassphrase(); |
| 1611 } | 1482 } |
| 1612 | 1483 |
| 1613 bool SyncManager::RequestPause() { | 1484 bool SyncManager::RequestPause() { |
| 1614 if (data_->syncer_thread()) | 1485 if (data_->syncer_thread()) |
| 1615 return data_->syncer_thread()->RequestPause(); | 1486 return data_->syncer_thread()->RequestPause(); |
| 1616 return false; | 1487 return false; |
| 1617 } | 1488 } |
| 1618 | 1489 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 NOTREACHED(); | 1575 NOTREACHED(); |
| 1705 return; | 1576 return; |
| 1706 } | 1577 } |
| 1707 | 1578 |
| 1708 if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) | 1579 if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) |
| 1709 return; | 1580 return; |
| 1710 | 1581 |
| 1711 Cryptographer* cryptographer = share_.dir_manager->cryptographer(); | 1582 Cryptographer* cryptographer = share_.dir_manager->cryptographer(); |
| 1712 cryptographer->Bootstrap(restored_key_for_bootstrapping); | 1583 cryptographer->Bootstrap(restored_key_for_bootstrapping); |
| 1713 | 1584 |
| 1714 sync_pb::NigoriSpecifics nigori; | 1585 ReadTransaction trans(GetUserShare()); |
| 1715 { | 1586 ReadNode node(&trans); |
| 1716 ReadTransaction trans(GetUserShare()); | 1587 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1717 ReadNode node(&trans); | 1588 NOTREACHED(); |
| 1718 if (!node.InitByTagLookup(kNigoriTag)) { | 1589 return; |
| 1719 NOTREACHED(); | 1590 } |
| 1720 return; | |
| 1721 } | |
| 1722 | 1591 |
| 1723 nigori.CopyFrom(node.GetNigoriSpecifics()); | 1592 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); |
| 1724 if (!nigori.encrypted().blob().empty()) { | 1593 if (!nigori.encrypted().blob().empty()) { |
| 1725 if (cryptographer->CanDecrypt(nigori.encrypted())) { | 1594 if (cryptographer->CanDecrypt(nigori.encrypted())) { |
| 1726 cryptographer->SetKeys(nigori.encrypted()); | 1595 cryptographer->SetKeys(nigori.encrypted()); |
| 1727 } else { | 1596 } else { |
| 1728 cryptographer->SetPendingKeys(nigori.encrypted()); | 1597 cryptographer->SetPendingKeys(nigori.encrypted()); |
| 1729 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 1598 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 1730 OnPassphraseRequired(true)); | 1599 OnPassphraseRequired(true)); |
| 1731 } | |
| 1732 } | 1600 } |
| 1733 } | 1601 } |
| 1734 | |
| 1735 // Refresh list of encrypted datatypes. | |
| 1736 syncable::ModelTypeSet encrypted_types = | |
| 1737 syncable::GetEncryptedDataTypesFromNigori(nigori); | |
| 1738 | |
| 1739 // Ensure any datatypes that need encryption are encrypted. | |
| 1740 EncryptDataTypes(encrypted_types); | |
| 1741 } | 1602 } |
| 1742 | 1603 |
| 1743 void SyncManager::SyncInternal::StartSyncing() { | 1604 void SyncManager::SyncInternal::StartSyncing() { |
| 1744 if (syncer_thread()) // NULL during certain unittests. | 1605 if (syncer_thread()) // NULL during certain unittests. |
| 1745 syncer_thread()->Start(); // Start the syncer thread. This won't actually | 1606 syncer_thread()->Start(); // Start the syncer thread. This won't actually |
| 1746 // result in any syncing until at least the | 1607 // result in any syncing until at least the |
| 1747 // DirectoryManager broadcasts the OPENED event, | 1608 // DirectoryManager broadcasts the OPENED event, |
| 1748 // and a valid server connection is detected. | 1609 // and a valid server connection is detected. |
| 1749 } | 1610 } |
| 1750 | 1611 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 | 1702 |
| 1842 if (!setup_for_test_mode_) { | 1703 if (!setup_for_test_mode_) { |
| 1843 UpdateCredentials(credentials); | 1704 UpdateCredentials(credentials); |
| 1844 } | 1705 } |
| 1845 return true; | 1706 return true; |
| 1846 } | 1707 } |
| 1847 | 1708 |
| 1848 void SyncManager::SyncInternal::UpdateCredentials( | 1709 void SyncManager::SyncInternal::UpdateCredentials( |
| 1849 const SyncCredentials& credentials) { | 1710 const SyncCredentials& credentials) { |
| 1850 DCHECK_EQ(MessageLoop::current(), core_message_loop_); | 1711 DCHECK_EQ(MessageLoop::current(), core_message_loop_); |
| 1851 DCHECK_EQ(credentials.email, share_.name); | 1712 DCHECK(share_.name == credentials.email); |
| 1852 connection_manager()->set_auth_token(credentials.sync_token); | 1713 connection_manager()->set_auth_token(credentials.sync_token); |
| 1853 TalkMediatorLogin(credentials.email, credentials.sync_token); | 1714 TalkMediatorLogin(credentials.email, credentials.sync_token); |
| 1854 CheckServerReachable(); | 1715 CheckServerReachable(); |
| 1855 sync_manager_->RequestNudge(); | 1716 sync_manager_->RequestNudge(); |
| 1856 } | 1717 } |
| 1857 | 1718 |
| 1858 void SyncManager::SyncInternal::UpdateEnabledTypes( | 1719 void SyncManager::SyncInternal::UpdateEnabledTypes( |
| 1859 const syncable::ModelTypeSet& types) { | 1720 const syncable::ModelTypeSet& types) { |
| 1860 DCHECK_EQ(MessageLoop::current(), core_message_loop_); | 1721 DCHECK_EQ(MessageLoop::current(), core_message_loop_); |
| 1861 | 1722 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 OnPassphraseRequired(true)); | 1796 OnPassphraseRequired(true)); |
| 1936 return; | 1797 return; |
| 1937 } | 1798 } |
| 1938 | 1799 |
| 1939 // TODO(tim): If this is the first time the user has entered a passphrase | 1800 // TODO(tim): If this is the first time the user has entered a passphrase |
| 1940 // since the protocol changed to store passphrase preferences in the cloud, | 1801 // since the protocol changed to store passphrase preferences in the cloud, |
| 1941 // make sure we update this preference. See bug 62103. | 1802 // make sure we update this preference. See bug 62103. |
| 1942 if (is_explicit) | 1803 if (is_explicit) |
| 1943 SetUsingExplicitPassphrasePrefForMigration(); | 1804 SetUsingExplicitPassphrasePrefForMigration(); |
| 1944 | 1805 |
| 1945 // Nudge the syncer so that encrypted datatype updates that were waiting for | 1806 // Nudge the syncer so that passwords updates that were waiting for this |
| 1946 // this passphrase get applied as soon as possible. | 1807 // passphrase get applied as soon as possible. |
| 1947 sync_manager_->RequestNudge(); | 1808 sync_manager_->RequestNudge(); |
| 1948 } else { | 1809 } else { |
| 1949 WriteTransaction trans(GetUserShare()); | 1810 WriteTransaction trans(GetUserShare()); |
| 1950 WriteNode node(&trans); | 1811 WriteNode node(&trans); |
| 1951 if (!node.InitByTagLookup(kNigoriTag)) { | 1812 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1952 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | 1813 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. |
| 1953 NOTREACHED(); | 1814 NOTREACHED(); |
| 1954 return; | 1815 return; |
| 1955 } | 1816 } |
| 1956 | 1817 |
| 1957 // Prevent an implicit SetPassphrase request from changing an explicitly | 1818 // Prevent an implicit SetPassphrase request from changing an explicitly |
| 1958 // set passphrase. | 1819 // set passphrase. |
| 1959 if (!is_explicit && node.GetNigoriSpecifics().using_explicit_passphrase()) | 1820 if (!is_explicit && node.GetNigoriSpecifics().using_explicit_passphrase()) |
| 1960 return; | 1821 return; |
| 1961 | 1822 |
| 1962 cryptographer->AddKey(params); | 1823 cryptographer->AddKey(params); |
| 1963 | 1824 |
| 1964 // TODO(tim): Bug 58231. It would be nice if SetPassphrase didn't require | 1825 // TODO(tim): Bug 58231. It would be nice if SetPassphrase didn't require |
| 1965 // messing with the Nigori node, because we can't call SetPassphrase until | 1826 // messing with the Nigori node, because we can't call SetPassphrase until |
| 1966 // download conditions are met vs Cryptographer init. It seems like it's | 1827 // download conditions are met vs Cryptographer init. It seems like it's |
| 1967 // safe to defer this work. | 1828 // safe to defer this work. |
| 1968 sync_pb::NigoriSpecifics specifics(node.GetNigoriSpecifics()); | 1829 sync_pb::NigoriSpecifics specifics; |
| 1969 specifics.clear_encrypted(); | |
| 1970 cryptographer->GetKeys(specifics.mutable_encrypted()); | 1830 cryptographer->GetKeys(specifics.mutable_encrypted()); |
| 1971 specifics.set_using_explicit_passphrase(is_explicit); | 1831 specifics.set_using_explicit_passphrase(is_explicit); |
| 1972 node.SetNigoriSpecifics(specifics); | 1832 node.SetNigoriSpecifics(specifics); |
| 1973 ReEncryptEverything(&trans); | 1833 ReEncryptEverything(&trans); |
| 1974 } | 1834 } |
| 1975 | 1835 |
| 1976 std::string bootstrap_token; | 1836 std::string bootstrap_token; |
| 1977 cryptographer->GetBootstrapToken(&bootstrap_token); | 1837 cryptographer->GetBootstrapToken(&bootstrap_token); |
| 1978 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 1838 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 1979 OnPassphraseAccepted(bootstrap_token)); | 1839 OnPassphraseAccepted(bootstrap_token)); |
| 1980 } | 1840 } |
| 1981 | 1841 |
| 1982 bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { | 1842 bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { |
| 1983 ReadTransaction trans(&share_); | 1843 ReadTransaction trans(&share_); |
| 1984 ReadNode node(&trans); | 1844 ReadNode node(&trans); |
| 1985 if (!node.InitByTagLookup(kNigoriTag)) { | 1845 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1986 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | 1846 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. |
| 1987 NOTREACHED(); | 1847 NOTREACHED(); |
| 1988 return false; | 1848 return false; |
| 1989 } | 1849 } |
| 1990 | 1850 |
| 1991 return node.GetNigoriSpecifics().using_explicit_passphrase(); | 1851 return node.GetNigoriSpecifics().using_explicit_passphrase(); |
| 1992 } | 1852 } |
| 1993 | 1853 |
| 1994 void SyncManager::SyncInternal::EncryptDataTypes( | 1854 void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { |
| 1995 const syncable::ModelTypeSet& encrypted_types) { | 1855 // TODO(tim): bug 59242. We shouldn't lookup by data type and instead use |
| 1996 // Verify the encrypted types are all enabled. | 1856 // a protocol flag or existence of an EncryptedData message, but for now, |
| 1997 ModelSafeRoutingInfo routes; | 1857 // encryption is on if-and-only-if the type is passwords, and we haven't |
| 1998 registrar_->GetModelSafeRoutingInfo(&routes); | 1858 // ironed out the protocol for generic encryption. |
| 1999 for (syncable::ModelTypeSet::const_iterator iter = encrypted_types.begin(); | 1859 static const char* passwords_tag = "google_chrome_passwords"; |
| 2000 iter != encrypted_types.end(); ++iter) { | 1860 ReadNode passwords_root(trans); |
| 2001 if (routes.count(*iter) == 0) { | 1861 if (!passwords_root.InitByTagLookup(passwords_tag)) { |
| 2002 LOG(WARNING) << "Attempted to encrypt non-enabled datatype " | 1862 LOG(WARNING) << "No passwords to reencrypt."; |
| 2003 << syncable::ModelTypeToString(*iter) << ", dropping type."; | |
| 2004 routes.erase(*iter); | |
| 2005 } | |
| 2006 } | |
| 2007 | |
| 2008 WriteTransaction trans(GetUserShare()); | |
| 2009 WriteNode node(&trans); | |
| 2010 if (!node.InitByTagLookup(kNigoriTag)) { | |
| 2011 LOG(ERROR) << "Unable to set encrypted datatypes because Nigori node not " | |
| 2012 << "found."; | |
| 2013 NOTREACHED(); | |
| 2014 return; | 1863 return; |
| 2015 } | 1864 } |
| 2016 | 1865 |
| 2017 // Update the Nigori node set of encrypted datatypes so other machines notice. | 1866 int64 child_id = passwords_root.GetFirstChildId(); |
| 2018 sync_pb::NigoriSpecifics nigori; | 1867 while (child_id != kInvalidId) { |
| 2019 nigori.CopyFrom(node.GetNigoriSpecifics()); | 1868 WriteNode child(trans); |
| 2020 syncable::FillNigoriEncryptedTypes(encrypted_types, &nigori); | 1869 if (!child.InitByIdLookup(child_id)) { |
| 2021 node.SetNigoriSpecifics(nigori); | |
| 2022 | |
| 2023 // TODO(zea): only reencrypt this datatype? ReEncrypting everything is a | |
| 2024 // safer approach, and should not impact anything that is already encrypted | |
| 2025 // (redundant changes are ignored). | |
| 2026 ReEncryptEverything(&trans); | |
| 2027 return; | |
| 2028 } | |
| 2029 | |
| 2030 void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { | |
| 2031 syncable::ModelTypeSet encrypted_types = | |
| 2032 GetEncryptedDataTypes(trans->GetWrappedTrans()); | |
| 2033 ModelSafeRoutingInfo routes; | |
| 2034 registrar_->GetModelSafeRoutingInfo(&routes); | |
| 2035 std::string tag; | |
| 2036 for (syncable::ModelTypeSet::iterator iter = encrypted_types.begin(); | |
| 2037 iter != encrypted_types.end(); ++iter) { | |
| 2038 if (*iter == syncable::PASSWORDS || routes.count(*iter) == 0) | |
| 2039 continue; | |
| 2040 ReadNode type_root(trans); | |
| 2041 tag = syncable::ModelTypeToRootTag(*iter); | |
| 2042 if (!type_root.InitByTagLookup(tag)) { | |
| 2043 NOTREACHED(); | 1870 NOTREACHED(); |
| 2044 return; | 1871 return; |
| 2045 } | 1872 } |
| 2046 | 1873 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); |
| 2047 // Iterate through all children of this datatype. | 1874 child_id = child.GetSuccessorId(); |
| 2048 std::queue<int64> to_visit; | |
| 2049 int64 child_id = type_root.GetFirstChildId(); | |
| 2050 to_visit.push(child_id); | |
| 2051 while (!to_visit.empty()) { | |
| 2052 child_id = to_visit.front(); | |
| 2053 to_visit.pop(); | |
| 2054 if (child_id == kInvalidId) | |
| 2055 continue; | |
| 2056 | |
| 2057 WriteNode child(trans); | |
| 2058 if (!child.InitByIdLookup(child_id)) { | |
| 2059 NOTREACHED(); | |
| 2060 return; | |
| 2061 } | |
| 2062 if (child.GetIsFolder()) { | |
| 2063 to_visit.push(child.GetFirstChildId()); | |
| 2064 } else { | |
| 2065 // Rewrite the specifics of the node with encrypted data if necessary. | |
| 2066 child.ResetFromSpecifics(); | |
| 2067 } | |
| 2068 to_visit.push(child.GetSuccessorId()); | |
| 2069 } | |
| 2070 } | 1875 } |
| 2071 | |
| 2072 if (routes.count(syncable::PASSWORDS) > 0) { | |
| 2073 // Passwords are encrypted with their own legacy scheme. | |
| 2074 encrypted_types.insert(syncable::PASSWORDS); | |
| 2075 ReadNode passwords_root(trans); | |
| 2076 std::string passwords_tag = | |
| 2077 syncable::ModelTypeToRootTag(syncable::PASSWORDS); | |
| 2078 if (!passwords_root.InitByTagLookup(passwords_tag)) { | |
| 2079 LOG(WARNING) << "No passwords to reencrypt."; | |
| 2080 return; | |
| 2081 } | |
| 2082 | |
| 2083 int64 child_id = passwords_root.GetFirstChildId(); | |
| 2084 while (child_id != kInvalidId) { | |
| 2085 WriteNode child(trans); | |
| 2086 if (!child.InitByIdLookup(child_id)) { | |
| 2087 NOTREACHED(); | |
| 2088 return; | |
| 2089 } | |
| 2090 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); | |
| 2091 child_id = child.GetSuccessorId(); | |
| 2092 } | |
| 2093 } | |
| 2094 | |
| 2095 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 2096 OnEncryptionComplete(encrypted_types)); | |
| 2097 } | 1876 } |
| 2098 | 1877 |
| 2099 SyncManager::~SyncManager() { | 1878 SyncManager::~SyncManager() { |
| 2100 delete data_; | 1879 delete data_; |
| 2101 } | 1880 } |
| 2102 | 1881 |
| 2103 void SyncManager::AddObserver(Observer* observer) { | 1882 void SyncManager::AddObserver(Observer* observer) { |
| 2104 data_->AddObserver(observer); | 1883 data_->AddObserver(observer); |
| 2105 } | 1884 } |
| 2106 | 1885 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2334 nudge_delay, | 2113 nudge_delay, |
| 2335 SyncerThread::kLocal, | 2114 SyncerThread::kLocal, |
| 2336 model_types); | 2115 model_types); |
| 2337 } | 2116 } |
| 2338 } | 2117 } |
| 2339 | 2118 |
| 2340 void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, | 2119 void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, |
| 2341 syncable::ModelType type, ChangeReorderBuffer* buffer, | 2120 syncable::ModelType type, ChangeReorderBuffer* buffer, |
| 2342 Cryptographer* cryptographer, const syncable::EntryKernel& original, | 2121 Cryptographer* cryptographer, const syncable::EntryKernel& original, |
| 2343 bool existed_before, bool exists_now) { | 2122 bool existed_before, bool exists_now) { |
| 2344 // If this is a deletion and the datatype was encrypted, we need to decrypt it | 2123 // If this is a deletion, attach the entity specifics as extra data |
| 2345 // and attach it to the buffer. | 2124 // so that the delete can be processed. |
| 2346 if (!exists_now && existed_before) { | 2125 if (!exists_now && existed_before) { |
| 2347 sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS)); | 2126 buffer->SetSpecificsForId(id, original.ref(SPECIFICS)); |
| 2348 if (type == syncable::PASSWORDS) { | 2127 if (type == syncable::PASSWORDS) { |
| 2349 // Passwords must use their own legacy ExtraPasswordChangeRecordData. | 2128 // Need to dig a bit deeper as passwords are encrypted. |
| 2350 scoped_ptr<sync_pb::PasswordSpecificsData> data( | 2129 scoped_ptr<sync_pb::PasswordSpecificsData> data( |
| 2351 DecryptPasswordSpecifics(original_specifics, cryptographer)); | 2130 DecryptPasswordSpecifics(original.ref(SPECIFICS), cryptographer)); |
| 2352 if (!data.get()) { | 2131 if (!data.get()) { |
| 2353 NOTREACHED(); | 2132 NOTREACHED(); |
| 2354 return; | 2133 return; |
| 2355 } | 2134 } |
| 2356 buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); | 2135 buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); |
| 2357 } else if (original_specifics.has_encrypted()) { | |
| 2358 // All other datatypes can just create a new unencrypted specifics and | |
| 2359 // attach it. | |
| 2360 const sync_pb::EncryptedData& encrypted = original_specifics.encrypted(); | |
| 2361 if (!cryptographer->Decrypt(encrypted, &original_specifics)) { | |
| 2362 NOTREACHED(); | |
| 2363 return; | |
| 2364 } | |
| 2365 } | 2136 } |
| 2366 buffer->SetSpecificsForId(id, original_specifics); | |
| 2367 } | 2137 } |
| 2368 } | 2138 } |
| 2369 | 2139 |
| 2370 void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( | 2140 void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( |
| 2371 const syncable::DirectoryChangeEvent& event) { | 2141 const syncable::DirectoryChangeEvent& event) { |
| 2372 // We only expect one notification per sync step, so change_buffers_ should | 2142 // We only expect one notification per sync step, so change_buffers_ should |
| 2373 // contain no pending entries. | 2143 // contain no pending entries. |
| 2374 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::CALCULATE_CHANGES); | 2144 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::CALCULATE_CHANGES); |
| 2375 DCHECK(event.writer == syncable::SYNCER || | 2145 DCHECK(event.writer == syncable::SYNCER || |
| 2376 event.writer == syncable::UNITTEST); | 2146 event.writer == syncable::UNITTEST); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2387 | 2157 |
| 2388 // Omit items that aren't associated with a model. | 2158 // Omit items that aren't associated with a model. |
| 2389 syncable::ModelType type = e.GetModelType(); | 2159 syncable::ModelType type = e.GetModelType(); |
| 2390 if (type == syncable::TOP_LEVEL_FOLDER || type == syncable::UNSPECIFIED) | 2160 if (type == syncable::TOP_LEVEL_FOLDER || type == syncable::UNSPECIFIED) |
| 2391 continue; | 2161 continue; |
| 2392 | 2162 |
| 2393 if (exists_now && !existed_before) | 2163 if (exists_now && !existed_before) |
| 2394 change_buffers_[type].PushAddedItem(id); | 2164 change_buffers_[type].PushAddedItem(id); |
| 2395 else if (!exists_now && existed_before) | 2165 else if (!exists_now && existed_before) |
| 2396 change_buffers_[type].PushDeletedItem(id); | 2166 change_buffers_[type].PushDeletedItem(id); |
| 2397 else if (exists_now && existed_before && | 2167 else if (exists_now && existed_before && VisiblePropertiesDiffer(*i, e)) |
| 2398 VisiblePropertiesDiffer(*i, e, dir_manager()->cryptographer())) { | |
| 2399 change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); | 2168 change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); |
| 2400 } | |
| 2401 | 2169 |
| 2402 SetExtraChangeRecordData(id, type, &change_buffers_[type], | 2170 SetExtraChangeRecordData(id, type, &change_buffers_[type], |
| 2403 dir_manager()->cryptographer(), *i, | 2171 dir_manager()->cryptographer(), *i, |
| 2404 existed_before, exists_now); | 2172 existed_before, exists_now); |
| 2405 } | 2173 } |
| 2406 } | 2174 } |
| 2407 | 2175 |
| 2408 SyncManager::Status SyncManager::SyncInternal::GetStatus() { | 2176 SyncManager::Status SyncManager::SyncInternal::GetStatus() { |
| 2409 return allstatus_.status(); | 2177 return allstatus_.status(); |
| 2410 } | 2178 } |
| 2411 | 2179 |
| 2412 void SyncManager::SyncInternal::OnSyncEngineEvent( | 2180 void SyncManager::SyncInternal::OnSyncEngineEvent( |
| 2413 const SyncEngineEvent& event) { | 2181 const SyncEngineEvent& event) { |
| 2414 if (observers_.size() <= 0) | 2182 if (observers_.size() <= 0) |
| 2415 return; | 2183 return; |
| 2416 | 2184 |
| 2417 // Only send an event if this is due to a cycle ending and this cycle | 2185 // Only send an event if this is due to a cycle ending and this cycle |
| 2418 // concludes a canonical "sync" process; that is, based on what is known | 2186 // concludes a canonical "sync" process; that is, based on what is known |
| 2419 // locally we are "all happy" and up-to-date. There may be new changes on | 2187 // locally we are "all happy" and up-to-date. There may be new changes on |
| 2420 // the server, but we'll get them on a subsequent sync. | 2188 // the server, but we'll get them on a subsequent sync. |
| 2421 // | 2189 // |
| 2422 // Notifications are sent at the end of every sync cycle, regardless of | 2190 // Notifications are sent at the end of every sync cycle, regardless of |
| 2423 // whether we should sync again. | 2191 // whether we should sync again. |
| 2424 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { | 2192 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { |
| 2425 ModelSafeRoutingInfo enabled_types; | 2193 ModelSafeRoutingInfo enabled_types; |
| 2426 registrar_->GetModelSafeRoutingInfo(&enabled_types); | 2194 registrar_->GetModelSafeRoutingInfo(&enabled_types); |
| 2427 { | 2195 if (enabled_types.count(syncable::PASSWORDS) > 0) { |
| 2428 // Check to see if we need to notify the frontend that we have newly | 2196 Cryptographer* cryptographer = |
| 2429 // encrypted types or that we require a passphrase. | 2197 GetUserShare()->dir_manager->cryptographer(); |
| 2430 sync_api::ReadTransaction trans(GetUserShare()); | 2198 if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { |
| 2431 sync_api::ReadNode node(&trans); | 2199 sync_api::ReadTransaction trans(GetUserShare()); |
| 2432 if (!node.InitByTagLookup(kNigoriTag)) { | 2200 sync_api::ReadNode node(&trans); |
| 2433 DCHECK(!event.snapshot->is_share_usable); | 2201 if (!node.InitByTagLookup(kNigoriTag)) { |
| 2434 return; | 2202 DCHECK(!event.snapshot->is_share_usable); |
| 2203 return; |
| 2204 } |
| 2205 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); |
| 2206 if (!nigori.encrypted().blob().empty()) { |
| 2207 DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); |
| 2208 cryptographer->SetPendingKeys(nigori.encrypted()); |
| 2209 } |
| 2435 } | 2210 } |
| 2436 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); | |
| 2437 syncable::ModelTypeSet encrypted_types = | |
| 2438 syncable::GetEncryptedDataTypesFromNigori(nigori); | |
| 2439 // If passwords are enabled, they're automatically considered encrypted. | |
| 2440 if (enabled_types.count(syncable::PASSWORDS) > 0) | |
| 2441 encrypted_types.insert(syncable::PASSWORDS); | |
| 2442 if (encrypted_types.size() > 0) { | |
| 2443 Cryptographer* cryptographer = | |
| 2444 GetUserShare()->dir_manager->cryptographer(); | |
| 2445 if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { | |
| 2446 if (!nigori.encrypted().blob().empty()) { | |
| 2447 DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); | |
| 2448 cryptographer->SetPendingKeys(nigori.encrypted()); | |
| 2449 } | |
| 2450 } | |
| 2451 | 2211 |
| 2452 // If we've completed a sync cycle and the cryptographer isn't ready | 2212 // If we've completed a sync cycle and the cryptographer isn't ready yet, |
| 2453 // yet, prompt the user for a passphrase. | 2213 // prompt the user for a passphrase. |
| 2454 if (cryptographer->has_pending_keys()) { | 2214 if (cryptographer->has_pending_keys()) { |
| 2455 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 2215 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2456 OnPassphraseRequired(true)); | 2216 OnPassphraseRequired(true)); |
| 2457 } else if (!cryptographer->is_ready()) { | 2217 } else if (!cryptographer->is_ready()) { |
| 2458 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 2218 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2459 OnPassphraseRequired(false)); | 2219 OnPassphraseRequired(false)); |
| 2460 } else { | |
| 2461 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 2462 OnEncryptionComplete(encrypted_types)); | |
| 2463 } | |
| 2464 } | 2220 } |
| 2465 } | 2221 } |
| 2466 | 2222 |
| 2467 if (!initialized()) | 2223 if (!initialized()) |
| 2468 return; | 2224 return; |
| 2469 | 2225 |
| 2470 if (!event.snapshot->has_more_to_sync) { | 2226 if (!event.snapshot->has_more_to_sync) { |
| 2471 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 2227 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2472 OnSyncCycleCompleted(event.snapshot)); | 2228 OnSyncCycleCompleted(event.snapshot)); |
| 2473 } | 2229 } |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2822 | 2578 |
| 2823 void SyncManager::TriggerOnIncomingNotificationForTest( | 2579 void SyncManager::TriggerOnIncomingNotificationForTest( |
| 2824 const syncable::ModelTypeBitSet& model_types) { | 2580 const syncable::ModelTypeBitSet& model_types) { |
| 2825 IncomingNotificationData notification_data; | 2581 IncomingNotificationData notification_data; |
| 2826 notification_data.service_url = model_types.to_string(); | 2582 notification_data.service_url = model_types.to_string(); |
| 2827 // Here we rely on the default notification method being SERVER. | 2583 // Here we rely on the default notification method being SERVER. |
| 2828 data_->OnIncomingNotification(notification_data); | 2584 data_->OnIncomingNotification(notification_data); |
| 2829 } | 2585 } |
| 2830 | 2586 |
| 2831 } // namespace sync_api | 2587 } // namespace sync_api |
| OLD | NEW |