| 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> |
| 7 #include <bitset> | 8 #include <bitset> |
| 8 #include <iomanip> | 9 #include <iomanip> |
| 9 #include <list> | 10 #include <list> |
| 11 #include <queue> |
| 10 #include <string> | 12 #include <string> |
| 11 #include <vector> | 13 #include <vector> |
| 12 | 14 |
| 13 #include "base/base64.h" | 15 #include "base/base64.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 16 #include "base/observer_list.h" | 18 #include "base/observer_list.h" |
| 17 #include "base/scoped_ptr.h" | 19 #include "base/scoped_ptr.h" |
| 18 #include "base/sha1.h" | 20 #include "base/sha1.h" |
| 19 #include "base/string_number_conversions.h" | 21 #include "base/string_number_conversions.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 45 #include "chrome/browser/sync/protocol/proto_value_conversions.h" | 47 #include "chrome/browser/sync/protocol/proto_value_conversions.h" |
| 46 #include "chrome/browser/sync/protocol/service_constants.h" | 48 #include "chrome/browser/sync/protocol/service_constants.h" |
| 47 #include "chrome/browser/sync/protocol/session_specifics.pb.h" | 49 #include "chrome/browser/sync/protocol/session_specifics.pb.h" |
| 48 #include "chrome/browser/sync/protocol/sync.pb.h" | 50 #include "chrome/browser/sync/protocol/sync.pb.h" |
| 49 #include "chrome/browser/sync/protocol/theme_specifics.pb.h" | 51 #include "chrome/browser/sync/protocol/theme_specifics.pb.h" |
| 50 #include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" | 52 #include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" |
| 51 #include "chrome/browser/sync/sessions/sync_session.h" | 53 #include "chrome/browser/sync/sessions/sync_session.h" |
| 52 #include "chrome/browser/sync/sessions/sync_session_context.h" | 54 #include "chrome/browser/sync/sessions/sync_session_context.h" |
| 53 #include "chrome/browser/sync/syncable/autofill_migration.h" | 55 #include "chrome/browser/sync/syncable/autofill_migration.h" |
| 54 #include "chrome/browser/sync/syncable/directory_manager.h" | 56 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 57 #include "chrome/browser/sync/syncable/nigori_util.h" |
| 55 #include "chrome/browser/sync/syncable/syncable.h" | 58 #include "chrome/browser/sync/syncable/syncable.h" |
| 56 #include "chrome/browser/sync/util/crypto_helpers.h" | 59 #include "chrome/browser/sync/util/crypto_helpers.h" |
| 57 #include "chrome/common/deprecated/event_sys.h" | 60 #include "chrome/common/deprecated/event_sys.h" |
| 58 #include "chrome/common/net/gaia/gaia_authenticator.h" | 61 #include "chrome/common/net/gaia/gaia_authenticator.h" |
| 59 #include "jingle/notifier/listener/mediator_thread_impl.h" | 62 #include "jingle/notifier/listener/mediator_thread_impl.h" |
| 60 #include "jingle/notifier/listener/notification_constants.h" | 63 #include "jingle/notifier/listener/notification_constants.h" |
| 61 #include "jingle/notifier/listener/talk_mediator.h" | 64 #include "jingle/notifier/listener/talk_mediator.h" |
| 62 #include "jingle/notifier/listener/talk_mediator_impl.h" | 65 #include "jingle/notifier/listener/talk_mediator_impl.h" |
| 63 #include "net/base/network_change_notifier.h" | 66 #include "net/base/network_change_notifier.h" |
| 64 | 67 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 if (!crypto->Decrypt(encrypted, data.get())) | 202 if (!crypto->Decrypt(encrypted, data.get())) |
| 200 return NULL; | 203 return NULL; |
| 201 return data.release(); | 204 return data.release(); |
| 202 } | 205 } |
| 203 | 206 |
| 204 bool BaseNode::DecryptIfNecessary(Entry* entry) { | 207 bool BaseNode::DecryptIfNecessary(Entry* entry) { |
| 205 if (GetIsFolder()) return true; // Ignore the top-level password folder. | 208 if (GetIsFolder()) return true; // Ignore the top-level password folder. |
| 206 const sync_pb::EntitySpecifics& specifics = | 209 const sync_pb::EntitySpecifics& specifics = |
| 207 entry->Get(syncable::SPECIFICS); | 210 entry->Get(syncable::SPECIFICS); |
| 208 if (specifics.HasExtension(sync_pb::password)) { | 211 if (specifics.HasExtension(sync_pb::password)) { |
| 212 // Passwords have their own legacy encryption structure. |
| 209 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( | 213 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( |
| 210 specifics, GetTransaction()->GetCryptographer())); | 214 specifics, GetTransaction()->GetCryptographer())); |
| 211 if (!data.get()) | 215 if (!data.get()) |
| 212 return false; | 216 return false; |
| 213 password_data_.swap(data); | 217 password_data_.swap(data); |
| 218 return true; |
| 219 } |
| 220 |
| 221 // We assume any node with the encrypted field set has encrypted data. |
| 222 if (!specifics.has_encrypted()) |
| 223 return true; |
| 224 |
| 225 const sync_pb::EncryptedData& encrypted = |
| 226 specifics.encrypted(); |
| 227 std::string plaintext_data = GetTransaction()->GetCryptographer()-> |
| 228 DecryptToString(encrypted); |
| 229 if (plaintext_data.length() == 0) |
| 230 return false; |
| 231 if (!unencrypted_data_.ParseFromString(plaintext_data)) { |
| 232 LOG(ERROR) << "Failed to decrypt encrypted node of type " << |
| 233 syncable::ModelTypeToString(entry->GetModelType()) << "."; |
| 234 return false; |
| 214 } | 235 } |
| 215 return true; | 236 return true; |
| 216 } | 237 } |
| 217 | 238 |
| 239 const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( |
| 240 const syncable::Entry* entry) const { |
| 241 const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); |
| 242 if (specifics.has_encrypted()) { |
| 243 DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) != |
| 244 syncable::UNSPECIFIED); |
| 245 return unencrypted_data_; |
| 246 } else { |
| 247 DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) == |
| 248 syncable::UNSPECIFIED); |
| 249 return specifics; |
| 250 } |
| 251 } |
| 252 |
| 218 int64 BaseNode::GetParentId() const { | 253 int64 BaseNode::GetParentId() const { |
| 219 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), | 254 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), |
| 220 GetEntry()->Get(syncable::PARENT_ID)); | 255 GetEntry()->Get(syncable::PARENT_ID)); |
| 221 } | 256 } |
| 222 | 257 |
| 223 int64 BaseNode::GetId() const { | 258 int64 BaseNode::GetId() const { |
| 224 return GetEntry()->Get(syncable::META_HANDLE); | 259 return GetEntry()->Get(syncable::META_HANDLE); |
| 225 } | 260 } |
| 226 | 261 |
| 227 int64 BaseNode::GetModificationTime() const { | 262 int64 BaseNode::GetModificationTime() const { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), | 344 output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), |
| 310 reinterpret_cast<const unsigned char*>(favicon.data() + | 345 reinterpret_cast<const unsigned char*>(favicon.data() + |
| 311 favicon.length())); | 346 favicon.length())); |
| 312 } | 347 } |
| 313 | 348 |
| 314 int64 BaseNode::GetExternalId() const { | 349 int64 BaseNode::GetExternalId() const { |
| 315 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); | 350 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); |
| 316 } | 351 } |
| 317 | 352 |
| 318 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { | 353 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { |
| 319 DCHECK(GetModelType() == syncable::APPS); | 354 DCHECK_EQ(syncable::APPS, GetModelType()); |
| 320 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::app); | 355 const sync_pb::EntitySpecifics& unencrypted = |
| 356 GetUnencryptedSpecifics(GetEntry()); |
| 357 return unencrypted.GetExtension(sync_pb::app); |
| 321 } | 358 } |
| 322 | 359 |
| 323 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { | 360 const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { |
| 324 DCHECK(GetModelType() == syncable::AUTOFILL); | 361 DCHECK_EQ(syncable::AUTOFILL, GetModelType()); |
| 325 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill); | 362 const sync_pb::EntitySpecifics& unencrypted = |
| 363 GetUnencryptedSpecifics(GetEntry()); |
| 364 return unencrypted.GetExtension(sync_pb::autofill); |
| 326 } | 365 } |
| 327 | 366 |
| 328 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { | 367 const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { |
| 329 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); | 368 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); |
| 330 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::autofill_profile); | 369 const sync_pb::EntitySpecifics& unencrypted = |
| 370 GetUnencryptedSpecifics(GetEntry()); |
| 371 return unencrypted.GetExtension(sync_pb::autofill_profile); |
| 331 } | 372 } |
| 332 | 373 |
| 333 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { | 374 const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { |
| 334 DCHECK(GetModelType() == syncable::BOOKMARKS); | 375 DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); |
| 335 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::bookmark); | 376 const sync_pb::EntitySpecifics& unencrypted = |
| 377 GetUnencryptedSpecifics(GetEntry()); |
| 378 return unencrypted.GetExtension(sync_pb::bookmark); |
| 336 } | 379 } |
| 337 | 380 |
| 338 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { | 381 const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { |
| 339 DCHECK(GetModelType() == syncable::NIGORI); | 382 DCHECK_EQ(syncable::NIGORI, GetModelType()); |
| 340 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::nigori); | 383 const sync_pb::EntitySpecifics& unencrypted = |
| 384 GetUnencryptedSpecifics(GetEntry()); |
| 385 return unencrypted.GetExtension(sync_pb::nigori); |
| 341 } | 386 } |
| 342 | 387 |
| 343 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { | 388 const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { |
| 344 DCHECK(GetModelType() == syncable::PASSWORDS); | 389 DCHECK_EQ(syncable::PASSWORDS, GetModelType()); |
| 345 DCHECK(password_data_.get()); | 390 DCHECK(password_data_.get()); |
| 346 return *password_data_; | 391 return *password_data_; |
| 347 } | 392 } |
| 348 | 393 |
| 349 const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { | 394 const sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { |
| 350 DCHECK(GetModelType() == syncable::PREFERENCES); | 395 DCHECK_EQ(syncable::PREFERENCES, GetModelType()); |
| 351 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::preference); | 396 const sync_pb::EntitySpecifics& unencrypted = |
| 397 GetUnencryptedSpecifics(GetEntry()); |
| 398 return unencrypted.GetExtension(sync_pb::preference); |
| 352 } | 399 } |
| 353 | 400 |
| 354 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { | 401 const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { |
| 355 DCHECK(GetModelType() == syncable::THEMES); | 402 DCHECK_EQ(syncable::THEMES, GetModelType()); |
| 356 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::theme); | 403 const sync_pb::EntitySpecifics& unencrypted = |
| 404 GetUnencryptedSpecifics(GetEntry()); |
| 405 return unencrypted.GetExtension(sync_pb::theme); |
| 357 } | 406 } |
| 358 | 407 |
| 359 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { | 408 const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { |
| 360 DCHECK(GetModelType() == syncable::TYPED_URLS); | 409 DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); |
| 361 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::typed_url); | 410 const sync_pb::EntitySpecifics& unencrypted = |
| 411 GetUnencryptedSpecifics(GetEntry()); |
| 412 return unencrypted.GetExtension(sync_pb::typed_url); |
| 362 } | 413 } |
| 363 | 414 |
| 364 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { | 415 const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { |
| 365 DCHECK(GetModelType() == syncable::EXTENSIONS); | 416 DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); |
| 366 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::extension); | 417 const sync_pb::EntitySpecifics& unencrypted = |
| 418 GetUnencryptedSpecifics(GetEntry()); |
| 419 return unencrypted.GetExtension(sync_pb::extension); |
| 367 } | 420 } |
| 368 | 421 |
| 369 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { | 422 const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { |
| 370 DCHECK(GetModelType() == syncable::SESSIONS); | 423 DCHECK_EQ(syncable::SESSIONS, GetModelType()); |
| 371 return GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::session); | 424 const sync_pb::EntitySpecifics& unencrypted = |
| 425 GetUnencryptedSpecifics(GetEntry()); |
| 426 return unencrypted.GetExtension(sync_pb::session); |
| 372 } | 427 } |
| 373 | 428 |
| 374 syncable::ModelType BaseNode::GetModelType() const { | 429 syncable::ModelType BaseNode::GetModelType() const { |
| 375 return GetEntry()->GetModelType(); | 430 return GetEntry()->GetModelType(); |
| 376 } | 431 } |
| 377 | 432 |
| 378 //////////////////////////////////// | 433 //////////////////////////////////// |
| 379 // WriteNode member definitions | 434 // WriteNode member definitions |
| 435 void WriteNode::EncryptIfNecessary(sync_pb::EntitySpecifics* unencrypted) { |
| 436 syncable::ModelType type = syncable::GetModelTypeFromSpecifics(*unencrypted); |
| 437 DCHECK_NE(type, syncable::UNSPECIFIED); |
| 438 DCHECK_NE(type, syncable::PASSWORDS); // Passwords use their own encryption. |
| 439 DCHECK_NE(type, syncable::NIGORI); // Nigori is encrypted separately. |
| 440 |
| 441 syncable::ModelTypeSet encrypted_types = |
| 442 GetEncryptedDataTypes(GetTransaction()->GetWrappedTrans()); |
| 443 if (encrypted_types.count(type) == 0) { |
| 444 // This datatype does not require encryption. |
| 445 return; |
| 446 } |
| 447 |
| 448 if (unencrypted->has_encrypted()) { |
| 449 // This specifics is already encrypted, our work is done. |
| 450 LOG(WARNING) << "Attempted to encrypt an already encrypted entity" |
| 451 << " specifics of type " << syncable::ModelTypeToString(type) |
| 452 << ". Dropping."; |
| 453 return; |
| 454 } |
| 455 sync_pb::EntitySpecifics encrypted; |
| 456 syncable::AddDefaultExtensionValue(type, &encrypted); |
| 457 VLOG(2) << "Encrypted specifics of type " << syncable::ModelTypeToString(type) |
| 458 << " with content: " << unencrypted->SerializeAsString() << "\n"; |
| 459 if (!GetTransaction()->GetCryptographer()->Encrypt( |
| 460 *unencrypted, |
| 461 encrypted.mutable_encrypted())) { |
| 462 LOG(ERROR) << "Could not encrypt data for node of type " << |
| 463 syncable::ModelTypeToString(type); |
| 464 NOTREACHED(); |
| 465 } |
| 466 unencrypted->CopyFrom(encrypted); |
| 467 } |
| 468 |
| 380 void WriteNode::SetIsFolder(bool folder) { | 469 void WriteNode::SetIsFolder(bool folder) { |
| 381 if (entry_->Get(syncable::IS_DIR) == folder) | 470 if (entry_->Get(syncable::IS_DIR) == folder) |
| 382 return; // Skip redundant changes. | 471 return; // Skip redundant changes. |
| 383 | 472 |
| 384 entry_->Put(syncable::IS_DIR, folder); | 473 entry_->Put(syncable::IS_DIR, folder); |
| 385 MarkForSyncing(); | 474 MarkForSyncing(); |
| 386 } | 475 } |
| 387 | 476 |
| 388 void WriteNode::SetTitle(const std::wstring& title) { | 477 void WriteNode::SetTitle(const std::wstring& title) { |
| 389 std::string server_legal_name; | 478 std::string server_legal_name; |
| 390 SyncAPINameToServerName(title, &server_legal_name); | 479 SyncAPINameToServerName(title, &server_legal_name); |
| 391 | 480 |
| 392 string old_name = entry_->Get(syncable::NON_UNIQUE_NAME); | 481 string old_name = entry_->Get(syncable::NON_UNIQUE_NAME); |
| 393 | 482 |
| 394 if (server_legal_name == old_name) | 483 if (server_legal_name == old_name) |
| 395 return; // Skip redundant changes. | 484 return; // Skip redundant changes. |
| 396 | 485 |
| 397 entry_->Put(syncable::NON_UNIQUE_NAME, server_legal_name); | 486 entry_->Put(syncable::NON_UNIQUE_NAME, server_legal_name); |
| 398 MarkForSyncing(); | 487 MarkForSyncing(); |
| 399 } | 488 } |
| 400 | 489 |
| 401 void WriteNode::SetURL(const GURL& url) { | 490 void WriteNode::SetURL(const GURL& url) { |
| 402 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); | 491 sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); |
| 403 new_value.set_url(url.spec()); | 492 new_value.set_url(url.spec()); |
| 404 SetBookmarkSpecifics(new_value); | 493 SetBookmarkSpecifics(new_value); |
| 405 } | 494 } |
| 406 | 495 |
| 407 void WriteNode::SetAppSpecifics( | 496 void WriteNode::SetAppSpecifics( |
| 408 const sync_pb::AppSpecifics& new_value) { | 497 const sync_pb::AppSpecifics& new_value) { |
| 409 DCHECK(GetModelType() == syncable::APPS); | 498 DCHECK_EQ(syncable::APPS, GetModelType()); |
| 410 PutAppSpecificsAndMarkForSyncing(new_value); | 499 PutAppSpecificsAndMarkForSyncing(new_value); |
| 411 } | 500 } |
| 412 | 501 |
| 413 void WriteNode::SetAutofillSpecifics( | 502 void WriteNode::SetAutofillSpecifics( |
| 414 const sync_pb::AutofillSpecifics& new_value) { | 503 const sync_pb::AutofillSpecifics& new_value) { |
| 415 DCHECK(GetModelType() == syncable::AUTOFILL); | 504 DCHECK_EQ(syncable::AUTOFILL, GetModelType()); |
| 416 PutAutofillSpecificsAndMarkForSyncing(new_value); | 505 PutAutofillSpecificsAndMarkForSyncing(new_value); |
| 417 } | 506 } |
| 418 | 507 |
| 419 void WriteNode::PutAutofillSpecificsAndMarkForSyncing( | 508 void WriteNode::PutAutofillSpecificsAndMarkForSyncing( |
| 420 const sync_pb::AutofillSpecifics& new_value) { | 509 const sync_pb::AutofillSpecifics& new_value) { |
| 421 sync_pb::EntitySpecifics entity_specifics; | 510 sync_pb::EntitySpecifics entity_specifics; |
| 422 entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); | 511 entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); |
| 512 EncryptIfNecessary(&entity_specifics); |
| 423 PutSpecificsAndMarkForSyncing(entity_specifics); | 513 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 424 } | 514 } |
| 425 | 515 |
| 426 void WriteNode::SetAutofillProfileSpecifics( | 516 void WriteNode::SetAutofillProfileSpecifics( |
| 427 const sync_pb::AutofillProfileSpecifics& new_value) { | 517 const sync_pb::AutofillProfileSpecifics& new_value) { |
| 428 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); | 518 DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); |
| 429 PutAutofillProfileSpecificsAndMarkForSyncing(new_value); | 519 PutAutofillProfileSpecificsAndMarkForSyncing(new_value); |
| 430 } | 520 } |
| 431 | 521 |
| 432 void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( | 522 void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( |
| 433 const sync_pb::AutofillProfileSpecifics& new_value) { | 523 const sync_pb::AutofillProfileSpecifics& new_value) { |
| 434 sync_pb::EntitySpecifics entity_specifics; | 524 sync_pb::EntitySpecifics entity_specifics; |
| 435 entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( | 525 entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( |
| 436 new_value); | 526 new_value); |
| 527 EncryptIfNecessary(&entity_specifics); |
| 437 PutSpecificsAndMarkForSyncing(entity_specifics); | 528 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 438 } | 529 } |
| 439 | 530 |
| 440 void WriteNode::SetBookmarkSpecifics( | 531 void WriteNode::SetBookmarkSpecifics( |
| 441 const sync_pb::BookmarkSpecifics& new_value) { | 532 const sync_pb::BookmarkSpecifics& new_value) { |
| 442 DCHECK(GetModelType() == syncable::BOOKMARKS); | 533 DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); |
| 443 PutBookmarkSpecificsAndMarkForSyncing(new_value); | 534 PutBookmarkSpecificsAndMarkForSyncing(new_value); |
| 444 } | 535 } |
| 445 | 536 |
| 446 void WriteNode::PutBookmarkSpecificsAndMarkForSyncing( | 537 void WriteNode::PutBookmarkSpecificsAndMarkForSyncing( |
| 447 const sync_pb::BookmarkSpecifics& new_value) { | 538 const sync_pb::BookmarkSpecifics& new_value) { |
| 448 sync_pb::EntitySpecifics entity_specifics; | 539 sync_pb::EntitySpecifics entity_specifics; |
| 449 entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); | 540 entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); |
| 541 EncryptIfNecessary(&entity_specifics); |
| 450 PutSpecificsAndMarkForSyncing(entity_specifics); | 542 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 451 } | 543 } |
| 452 | 544 |
| 453 void WriteNode::SetNigoriSpecifics( | 545 void WriteNode::SetNigoriSpecifics( |
| 454 const sync_pb::NigoriSpecifics& new_value) { | 546 const sync_pb::NigoriSpecifics& new_value) { |
| 455 DCHECK(GetModelType() == syncable::NIGORI); | 547 DCHECK_EQ(syncable::NIGORI, GetModelType()); |
| 456 PutNigoriSpecificsAndMarkForSyncing(new_value); | 548 PutNigoriSpecificsAndMarkForSyncing(new_value); |
| 457 } | 549 } |
| 458 | 550 |
| 459 void WriteNode::PutNigoriSpecificsAndMarkForSyncing( | 551 void WriteNode::PutNigoriSpecificsAndMarkForSyncing( |
| 460 const sync_pb::NigoriSpecifics& new_value) { | 552 const sync_pb::NigoriSpecifics& new_value) { |
| 461 sync_pb::EntitySpecifics entity_specifics; | 553 sync_pb::EntitySpecifics entity_specifics; |
| 462 entity_specifics.MutableExtension(sync_pb::nigori)->CopyFrom(new_value); | 554 entity_specifics.MutableExtension(sync_pb::nigori)->CopyFrom(new_value); |
| 463 PutSpecificsAndMarkForSyncing(entity_specifics); | 555 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 464 } | 556 } |
| 465 | 557 |
| 466 void WriteNode::SetPasswordSpecifics( | 558 void WriteNode::SetPasswordSpecifics( |
| 467 const sync_pb::PasswordSpecificsData& data) { | 559 const sync_pb::PasswordSpecificsData& data) { |
| 468 DCHECK(GetModelType() == syncable::PASSWORDS); | 560 DCHECK_EQ(syncable::PASSWORDS, GetModelType()); |
| 469 | |
| 470 sync_pb::PasswordSpecifics new_value; | 561 sync_pb::PasswordSpecifics new_value; |
| 471 if (!GetTransaction()->GetCryptographer()->Encrypt( | 562 if (!GetTransaction()->GetCryptographer()->Encrypt( |
| 472 data, | 563 data, |
| 473 new_value.mutable_encrypted())) { | 564 new_value.mutable_encrypted())) { |
| 474 NOTREACHED(); | 565 NOTREACHED(); |
| 475 } | 566 } |
| 476 | |
| 477 PutPasswordSpecificsAndMarkForSyncing(new_value); | 567 PutPasswordSpecificsAndMarkForSyncing(new_value); |
| 478 } | 568 } |
| 479 | 569 |
| 480 void WriteNode::SetPreferenceSpecifics( | 570 void WriteNode::SetPreferenceSpecifics( |
| 481 const sync_pb::PreferenceSpecifics& new_value) { | 571 const sync_pb::PreferenceSpecifics& new_value) { |
| 482 DCHECK(GetModelType() == syncable::PREFERENCES); | 572 DCHECK_EQ(syncable::PREFERENCES, GetModelType()); |
| 483 PutPreferenceSpecificsAndMarkForSyncing(new_value); | 573 PutPreferenceSpecificsAndMarkForSyncing(new_value); |
| 484 } | 574 } |
| 485 | 575 |
| 486 void WriteNode::SetThemeSpecifics( | 576 void WriteNode::SetThemeSpecifics( |
| 487 const sync_pb::ThemeSpecifics& new_value) { | 577 const sync_pb::ThemeSpecifics& new_value) { |
| 488 DCHECK(GetModelType() == syncable::THEMES); | 578 DCHECK_EQ(syncable::THEMES, GetModelType()); |
| 489 PutThemeSpecificsAndMarkForSyncing(new_value); | 579 PutThemeSpecificsAndMarkForSyncing(new_value); |
| 490 } | 580 } |
| 491 | 581 |
| 492 void WriteNode::SetSessionSpecifics( | 582 void WriteNode::SetSessionSpecifics( |
| 493 const sync_pb::SessionSpecifics& new_value) { | 583 const sync_pb::SessionSpecifics& new_value) { |
| 494 DCHECK(GetModelType() == syncable::SESSIONS); | 584 DCHECK_EQ(syncable::SESSIONS, GetModelType()); |
| 495 PutSessionSpecificsAndMarkForSyncing(new_value); | 585 PutSessionSpecificsAndMarkForSyncing(new_value); |
| 496 } | 586 } |
| 497 | 587 |
| 588 void WriteNode::ResetFromSpecifics() { |
| 589 sync_pb::EntitySpecifics new_data; |
| 590 new_data.CopyFrom(GetUnencryptedSpecifics(GetEntry())); |
| 591 EncryptIfNecessary(&new_data); |
| 592 PutSpecificsAndMarkForSyncing(new_data); |
| 593 } |
| 498 | 594 |
| 499 void WriteNode::PutPasswordSpecificsAndMarkForSyncing( | 595 void WriteNode::PutPasswordSpecificsAndMarkForSyncing( |
| 500 const sync_pb::PasswordSpecifics& new_value) { | 596 const sync_pb::PasswordSpecifics& new_value) { |
| 501 sync_pb::EntitySpecifics entity_specifics; | 597 sync_pb::EntitySpecifics entity_specifics; |
| 502 entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); | 598 entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); |
| 503 PutSpecificsAndMarkForSyncing(entity_specifics); | 599 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 504 } | 600 } |
| 505 | 601 |
| 506 void WriteNode::PutPreferenceSpecificsAndMarkForSyncing( | 602 void WriteNode::PutPreferenceSpecificsAndMarkForSyncing( |
| 507 const sync_pb::PreferenceSpecifics& new_value) { | 603 const sync_pb::PreferenceSpecifics& new_value) { |
| 508 sync_pb::EntitySpecifics entity_specifics; | 604 sync_pb::EntitySpecifics entity_specifics; |
| 509 entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); | 605 entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); |
| 606 EncryptIfNecessary(&entity_specifics); |
| 510 PutSpecificsAndMarkForSyncing(entity_specifics); | 607 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 511 } | 608 } |
| 512 | 609 |
| 513 void WriteNode::SetTypedUrlSpecifics( | 610 void WriteNode::SetTypedUrlSpecifics( |
| 514 const sync_pb::TypedUrlSpecifics& new_value) { | 611 const sync_pb::TypedUrlSpecifics& new_value) { |
| 515 DCHECK(GetModelType() == syncable::TYPED_URLS); | 612 DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); |
| 516 PutTypedUrlSpecificsAndMarkForSyncing(new_value); | 613 PutTypedUrlSpecificsAndMarkForSyncing(new_value); |
| 517 } | 614 } |
| 518 | 615 |
| 519 void WriteNode::SetExtensionSpecifics( | 616 void WriteNode::SetExtensionSpecifics( |
| 520 const sync_pb::ExtensionSpecifics& new_value) { | 617 const sync_pb::ExtensionSpecifics& new_value) { |
| 521 DCHECK(GetModelType() == syncable::EXTENSIONS); | 618 DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); |
| 522 PutExtensionSpecificsAndMarkForSyncing(new_value); | 619 PutExtensionSpecificsAndMarkForSyncing(new_value); |
| 523 } | 620 } |
| 524 | 621 |
| 525 void WriteNode::PutAppSpecificsAndMarkForSyncing( | 622 void WriteNode::PutAppSpecificsAndMarkForSyncing( |
| 526 const sync_pb::AppSpecifics& new_value) { | 623 const sync_pb::AppSpecifics& new_value) { |
| 527 sync_pb::EntitySpecifics entity_specifics; | 624 sync_pb::EntitySpecifics entity_specifics; |
| 528 entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); | 625 entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); |
| 626 EncryptIfNecessary(&entity_specifics); |
| 529 PutSpecificsAndMarkForSyncing(entity_specifics); | 627 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 530 } | 628 } |
| 531 | 629 |
| 532 void WriteNode::PutThemeSpecificsAndMarkForSyncing( | 630 void WriteNode::PutThemeSpecificsAndMarkForSyncing( |
| 533 const sync_pb::ThemeSpecifics& new_value) { | 631 const sync_pb::ThemeSpecifics& new_value) { |
| 534 sync_pb::EntitySpecifics entity_specifics; | 632 sync_pb::EntitySpecifics entity_specifics; |
| 535 entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); | 633 entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); |
| 634 EncryptIfNecessary(&entity_specifics); |
| 536 PutSpecificsAndMarkForSyncing(entity_specifics); | 635 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 537 } | 636 } |
| 538 | 637 |
| 539 void WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( | 638 void WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( |
| 540 const sync_pb::TypedUrlSpecifics& new_value) { | 639 const sync_pb::TypedUrlSpecifics& new_value) { |
| 541 sync_pb::EntitySpecifics entity_specifics; | 640 sync_pb::EntitySpecifics entity_specifics; |
| 542 entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); | 641 entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); |
| 642 EncryptIfNecessary(&entity_specifics); |
| 543 PutSpecificsAndMarkForSyncing(entity_specifics); | 643 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 544 } | 644 } |
| 545 | 645 |
| 546 void WriteNode::PutExtensionSpecificsAndMarkForSyncing( | 646 void WriteNode::PutExtensionSpecificsAndMarkForSyncing( |
| 547 const sync_pb::ExtensionSpecifics& new_value) { | 647 const sync_pb::ExtensionSpecifics& new_value) { |
| 548 sync_pb::EntitySpecifics entity_specifics; | 648 sync_pb::EntitySpecifics entity_specifics; |
| 549 entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); | 649 entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); |
| 650 EncryptIfNecessary(&entity_specifics); |
| 550 PutSpecificsAndMarkForSyncing(entity_specifics); | 651 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 551 } | 652 } |
| 552 | 653 |
| 553 | |
| 554 void WriteNode::PutSessionSpecificsAndMarkForSyncing( | 654 void WriteNode::PutSessionSpecificsAndMarkForSyncing( |
| 555 const sync_pb::SessionSpecifics& new_value) { | 655 const sync_pb::SessionSpecifics& new_value) { |
| 556 sync_pb::EntitySpecifics entity_specifics; | 656 sync_pb::EntitySpecifics entity_specifics; |
| 557 entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); | 657 entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); |
| 658 EncryptIfNecessary(&entity_specifics); |
| 558 PutSpecificsAndMarkForSyncing(entity_specifics); | 659 PutSpecificsAndMarkForSyncing(entity_specifics); |
| 559 } | 660 } |
| 560 | 661 |
| 561 | |
| 562 void WriteNode::PutSpecificsAndMarkForSyncing( | 662 void WriteNode::PutSpecificsAndMarkForSyncing( |
| 563 const sync_pb::EntitySpecifics& specifics) { | 663 const sync_pb::EntitySpecifics& specifics) { |
| 564 // Skip redundant changes. | 664 // Skip redundant changes. |
| 565 if (specifics.SerializeAsString() == | 665 if (specifics.SerializeAsString() == |
| 566 entry_->Get(SPECIFICS).SerializeAsString()) { | 666 entry_->Get(SPECIFICS).SerializeAsString()) { |
| 567 return; | 667 return; |
| 568 } | 668 } |
| 569 entry_->Put(SPECIFICS, specifics); | 669 entry_->Put(SPECIFICS, specifics); |
| 570 MarkForSyncing(); | 670 MarkForSyncing(); |
| 571 } | 671 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 DCHECK(!entry_) << "Init called twice"; | 716 DCHECK(!entry_) << "Init called twice"; |
| 617 if (tag.empty()) | 717 if (tag.empty()) |
| 618 return false; | 718 return false; |
| 619 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 719 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
| 620 syncable::GET_BY_SERVER_TAG, tag); | 720 syncable::GET_BY_SERVER_TAG, tag); |
| 621 if (!entry_->good()) | 721 if (!entry_->good()) |
| 622 return false; | 722 return false; |
| 623 if (entry_->Get(syncable::IS_DEL)) | 723 if (entry_->Get(syncable::IS_DEL)) |
| 624 return false; | 724 return false; |
| 625 syncable::ModelType model_type = GetModelType(); | 725 syncable::ModelType model_type = GetModelType(); |
| 626 DCHECK(model_type == syncable::NIGORI); | 726 DCHECK_EQ(syncable::NIGORI, model_type); |
| 627 return true; | 727 return true; |
| 628 } | 728 } |
| 629 | 729 |
| 630 void WriteNode::PutModelType(syncable::ModelType model_type) { | 730 void WriteNode::PutModelType(syncable::ModelType model_type) { |
| 631 // Set an empty specifics of the appropriate datatype. The presence | 731 // Set an empty specifics of the appropriate datatype. The presence |
| 632 // of the specific extension will identify the model type. | 732 // of the specific extension will identify the model type. |
| 633 DCHECK(GetModelType() == model_type || | 733 DCHECK(GetModelType() == model_type || |
| 634 GetModelType() == syncable::UNSPECIFIED); // Immutable once set. | 734 GetModelType() == syncable::UNSPECIFIED); // Immutable once set. |
| 635 | 735 |
| 636 sync_pb::EntitySpecifics specifics; | 736 sync_pb::EntitySpecifics specifics; |
| 637 syncable::AddDefaultExtensionValue(model_type, &specifics); | 737 syncable::AddDefaultExtensionValue(model_type, &specifics); |
| 638 PutSpecificsAndMarkForSyncing(specifics); | 738 PutSpecificsAndMarkForSyncing(specifics); |
| 639 DCHECK(GetModelType() == model_type); | 739 DCHECK_EQ(model_type, GetModelType()); |
| 640 } | 740 } |
| 641 | 741 |
| 642 // Create a new node with default properties, and bind this WriteNode to it. | 742 // Create a new node with default properties, and bind this WriteNode to it. |
| 643 // Return true on success. | 743 // Return true on success. |
| 644 bool WriteNode::InitByCreation(syncable::ModelType model_type, | 744 bool WriteNode::InitByCreation(syncable::ModelType model_type, |
| 645 const BaseNode& parent, | 745 const BaseNode& parent, |
| 646 const BaseNode* predecessor) { | 746 const BaseNode* predecessor) { |
| 647 DCHECK(!entry_) << "Init called twice"; | 747 DCHECK(!entry_) << "Init called twice"; |
| 648 // |predecessor| must be a child of |parent| or NULL. | 748 // |predecessor| must be a child of |parent| or NULL. |
| 649 if (predecessor && predecessor->GetParentId() != parent.GetId()) { | 749 if (predecessor && predecessor->GetParentId() != parent.GetId()) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 } | 1027 } |
| 928 | 1028 |
| 929 WriteTransaction::~WriteTransaction() { | 1029 WriteTransaction::~WriteTransaction() { |
| 930 delete transaction_; | 1030 delete transaction_; |
| 931 } | 1031 } |
| 932 | 1032 |
| 933 syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { | 1033 syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { |
| 934 return transaction_; | 1034 return transaction_; |
| 935 } | 1035 } |
| 936 | 1036 |
| 937 SyncManager::ExtraChangeRecordData::~ExtraChangeRecordData() {} | |
| 938 | |
| 939 SyncManager::ChangeRecord::ChangeRecord() | 1037 SyncManager::ChangeRecord::ChangeRecord() |
| 940 : id(kInvalidId), action(ACTION_ADD) {} | 1038 : id(kInvalidId), action(ACTION_ADD) {} |
| 941 | 1039 |
| 942 DictionaryValue* SyncManager::ChangeRecord::ToValue( | 1040 DictionaryValue* SyncManager::ChangeRecord::ToValue( |
| 943 const BaseTransaction* trans) const { | 1041 const BaseTransaction* trans) const { |
| 944 DictionaryValue* value = new DictionaryValue(); | 1042 DictionaryValue* value = new DictionaryValue(); |
| 945 std::string action_str; | 1043 std::string action_str; |
| 946 switch (action) { | 1044 switch (action) { |
| 947 case ACTION_ADD: | 1045 case ACTION_ADD: |
| 948 action_str = "Add"; | 1046 action_str = "Add"; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 976 } | 1074 } |
| 977 } | 1075 } |
| 978 if (!node_value) { | 1076 if (!node_value) { |
| 979 NOTREACHED(); | 1077 NOTREACHED(); |
| 980 node_value = Value::CreateNullValue(); | 1078 node_value = Value::CreateNullValue(); |
| 981 } | 1079 } |
| 982 value->Set("node", node_value); | 1080 value->Set("node", node_value); |
| 983 return value; | 1081 return value; |
| 984 } | 1082 } |
| 985 | 1083 |
| 1084 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} |
| 1085 |
| 986 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( | 1086 SyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( |
| 987 const sync_pb::PasswordSpecificsData& data) | 1087 const sync_pb::PasswordSpecificsData& data) |
| 988 : unencrypted_(data) {} | 1088 : unencrypted_(data) { |
| 1089 } |
| 989 | 1090 |
| 990 SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} | 1091 SyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} |
| 991 | 1092 |
| 992 DictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const { | 1093 DictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const { |
| 993 return browser_sync::PasswordSpecificsDataToValue(unencrypted_); | 1094 return browser_sync::PasswordSpecificsDataToValue(unencrypted_); |
| 994 } | 1095 } |
| 995 | 1096 |
| 996 const sync_pb::PasswordSpecificsData& | 1097 const sync_pb::PasswordSpecificsData& |
| 997 SyncManager::ExtraPasswordChangeRecordData::unencrypted() const { | 1098 SyncManager::ExtraPasswordChangeRecordData::unencrypted() const { |
| 998 return unencrypted_; | 1099 return unencrypted_; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 | 1147 |
| 1047 // Update tokens that we're using in Sync. Email must stay the same. | 1148 // Update tokens that we're using in Sync. Email must stay the same. |
| 1048 void UpdateCredentials(const SyncCredentials& credentials); | 1149 void UpdateCredentials(const SyncCredentials& credentials); |
| 1049 | 1150 |
| 1050 // Tell the sync engine to start the syncing process. | 1151 // Tell the sync engine to start the syncing process. |
| 1051 void StartSyncing(); | 1152 void StartSyncing(); |
| 1052 | 1153 |
| 1053 // Whether or not the Nigori node is encrypted using an explicit passphrase. | 1154 // Whether or not the Nigori node is encrypted using an explicit passphrase. |
| 1054 bool IsUsingExplicitPassphrase(); | 1155 bool IsUsingExplicitPassphrase(); |
| 1055 | 1156 |
| 1157 // Set the datatypes we want to encrypt and encrypt any nodes as necessary. |
| 1158 void EncryptDataTypes(const syncable::ModelTypeSet& encrypted_types); |
| 1159 |
| 1056 // Try to set the current passphrase to |passphrase|, and record whether | 1160 // Try to set the current passphrase to |passphrase|, and record whether |
| 1057 // it is an explicit passphrase or implicitly using gaia in the Nigori | 1161 // it is an explicit passphrase or implicitly using gaia in the Nigori |
| 1058 // node. | 1162 // node. |
| 1059 void SetPassphrase(const std::string& passphrase, bool is_explicit); | 1163 void SetPassphrase(const std::string& passphrase, bool is_explicit); |
| 1060 | 1164 |
| 1061 // Call periodically from a database-safe thread to persist recent changes | 1165 // Call periodically from a database-safe thread to persist recent changes |
| 1062 // to the syncapi model. | 1166 // to the syncapi model. |
| 1063 void SaveChanges(); | 1167 void SaveChanges(); |
| 1064 | 1168 |
| 1065 // This listener is called upon completion of a syncable transaction, and | 1169 // This listener is called upon completion of a syncable transaction, and |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 // See SyncManager::Shutdown for information. | 1225 // See SyncManager::Shutdown for information. |
| 1122 void Shutdown(); | 1226 void Shutdown(); |
| 1123 | 1227 |
| 1124 // Whether we're initialized to the point of being able to accept changes | 1228 // Whether we're initialized to the point of being able to accept changes |
| 1125 // (and hence allow transaction creation). See initialized_ for details. | 1229 // (and hence allow transaction creation). See initialized_ for details. |
| 1126 bool initialized() const { | 1230 bool initialized() const { |
| 1127 base::AutoLock lock(initialized_mutex_); | 1231 base::AutoLock lock(initialized_mutex_); |
| 1128 return initialized_; | 1232 return initialized_; |
| 1129 } | 1233 } |
| 1130 | 1234 |
| 1235 // If this is a deletion for a password, sets the legacy |
| 1236 // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets |
| 1237 // |buffer|'s specifics field to contain the unencrypted data. |
| 1131 void SetExtraChangeRecordData(int64 id, | 1238 void SetExtraChangeRecordData(int64 id, |
| 1132 syncable::ModelType type, | 1239 syncable::ModelType type, |
| 1133 ChangeReorderBuffer* buffer, | 1240 ChangeReorderBuffer* buffer, |
| 1134 Cryptographer* cryptographer, | 1241 Cryptographer* cryptographer, |
| 1135 const syncable::EntryKernel& original, | 1242 const syncable::EntryKernel& original, |
| 1136 bool existed_before, | 1243 bool existed_before, |
| 1137 bool exists_now); | 1244 bool exists_now); |
| 1138 | 1245 |
| 1139 // Called only by our NetworkChangeNotifier. | 1246 // Called only by our NetworkChangeNotifier. |
| 1140 virtual void OnIPAddressChanged(); | 1247 virtual void OnIPAddressChanged(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 return true; | 1353 return true; |
| 1247 if (a.ref(syncable::PARENT_ID) != b.Get(syncable::PARENT_ID)) | 1354 if (a.ref(syncable::PARENT_ID) != b.Get(syncable::PARENT_ID)) |
| 1248 return true; | 1355 return true; |
| 1249 return false; | 1356 return false; |
| 1250 } | 1357 } |
| 1251 | 1358 |
| 1252 // Determine if any of the fields made visible to clients of the Sync API | 1359 // Determine if any of the fields made visible to clients of the Sync API |
| 1253 // differ between the versions of an entry stored in |a| and |b|. A return | 1360 // differ between the versions of an entry stored in |a| and |b|. A return |
| 1254 // value of false means that it should be OK to ignore this change. | 1361 // value of false means that it should be OK to ignore this change. |
| 1255 static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, | 1362 static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, |
| 1256 const syncable::Entry& b) { | 1363 const syncable::Entry& b, |
| 1364 Cryptographer* cryptographer) { |
| 1257 syncable::ModelType model_type = b.GetModelType(); | 1365 syncable::ModelType model_type = b.GetModelType(); |
| 1258 // Suppress updates to items that aren't tracked by any browser model. | 1366 // Suppress updates to items that aren't tracked by any browser model. |
| 1259 if (model_type == syncable::UNSPECIFIED || | 1367 if (model_type == syncable::UNSPECIFIED || |
| 1260 model_type == syncable::TOP_LEVEL_FOLDER) { | 1368 model_type == syncable::TOP_LEVEL_FOLDER) { |
| 1261 return false; | 1369 return false; |
| 1262 } | 1370 } |
| 1263 if (a.ref(syncable::NON_UNIQUE_NAME) != b.Get(syncable::NON_UNIQUE_NAME)) | 1371 if (a.ref(syncable::NON_UNIQUE_NAME) != b.Get(syncable::NON_UNIQUE_NAME)) |
| 1264 return true; | 1372 return true; |
| 1265 if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) | 1373 if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) |
| 1266 return true; | 1374 return true; |
| 1267 if (a.ref(SPECIFICS).SerializeAsString() != | 1375 // Check if data has changed (account for encryption). |
| 1268 b.Get(SPECIFICS).SerializeAsString()) { | 1376 std::string a_str, b_str; |
| 1377 if (a.ref(SPECIFICS).has_encrypted()) { |
| 1378 const sync_pb::EncryptedData& encrypted = a.ref(SPECIFICS).encrypted(); |
| 1379 a_str = cryptographer->DecryptToString(encrypted); |
| 1380 } else { |
| 1381 a_str = a.ref(SPECIFICS).SerializeAsString(); |
| 1382 } |
| 1383 if (b.Get(SPECIFICS).has_encrypted()) { |
| 1384 const sync_pb::EncryptedData& encrypted = b.Get(SPECIFICS).encrypted(); |
| 1385 b_str = cryptographer->DecryptToString(encrypted); |
| 1386 } else { |
| 1387 b_str = b.Get(SPECIFICS).SerializeAsString(); |
| 1388 } |
| 1389 if (a_str != b_str) { |
| 1269 return true; | 1390 return true; |
| 1270 } | 1391 } |
| 1271 if (VisiblePositionsDiffer(a, b)) | 1392 if (VisiblePositionsDiffer(a, b)) |
| 1272 return true; | 1393 return true; |
| 1273 return false; | 1394 return false; |
| 1274 } | 1395 } |
| 1275 | 1396 |
| 1276 bool ChangeBuffersAreEmpty() { | 1397 bool ChangeBuffersAreEmpty() { |
| 1277 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { | 1398 for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { |
| 1278 if (!change_buffers_[i].IsEmpty()) | 1399 if (!change_buffers_[i].IsEmpty()) |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1455 syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, | 1576 syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, |
| 1456 const syncable::AutofillMigrationDebugInfo& info) { | 1577 const syncable::AutofillMigrationDebugInfo& info) { |
| 1457 return data_->SetAutofillMigrationDebugInfo(property_to_set, info); | 1578 return data_->SetAutofillMigrationDebugInfo(property_to_set, info); |
| 1458 } | 1579 } |
| 1459 | 1580 |
| 1460 void SyncManager::SetPassphrase(const std::string& passphrase, | 1581 void SyncManager::SetPassphrase(const std::string& passphrase, |
| 1461 bool is_explicit) { | 1582 bool is_explicit) { |
| 1462 data_->SetPassphrase(passphrase, is_explicit); | 1583 data_->SetPassphrase(passphrase, is_explicit); |
| 1463 } | 1584 } |
| 1464 | 1585 |
| 1586 void SyncManager::EncryptDataTypes( |
| 1587 const syncable::ModelTypeSet& encrypted_types) { |
| 1588 data_->EncryptDataTypes(encrypted_types); |
| 1589 } |
| 1590 |
| 1465 bool SyncManager::IsUsingExplicitPassphrase() { | 1591 bool SyncManager::IsUsingExplicitPassphrase() { |
| 1466 return data_ && data_->IsUsingExplicitPassphrase(); | 1592 return data_ && data_->IsUsingExplicitPassphrase(); |
| 1467 } | 1593 } |
| 1468 | 1594 |
| 1469 bool SyncManager::RequestPause() { | 1595 bool SyncManager::RequestPause() { |
| 1470 if (data_->syncer_thread()) | 1596 if (data_->syncer_thread()) |
| 1471 return data_->syncer_thread()->RequestPause(); | 1597 return data_->syncer_thread()->RequestPause(); |
| 1472 return false; | 1598 return false; |
| 1473 } | 1599 } |
| 1474 | 1600 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 NOTREACHED(); | 1686 NOTREACHED(); |
| 1561 return; | 1687 return; |
| 1562 } | 1688 } |
| 1563 | 1689 |
| 1564 if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) | 1690 if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) |
| 1565 return; | 1691 return; |
| 1566 | 1692 |
| 1567 Cryptographer* cryptographer = share_.dir_manager->cryptographer(); | 1693 Cryptographer* cryptographer = share_.dir_manager->cryptographer(); |
| 1568 cryptographer->Bootstrap(restored_key_for_bootstrapping); | 1694 cryptographer->Bootstrap(restored_key_for_bootstrapping); |
| 1569 | 1695 |
| 1570 ReadTransaction trans(GetUserShare()); | 1696 sync_pb::NigoriSpecifics nigori; |
| 1571 ReadNode node(&trans); | 1697 { |
| 1572 if (!node.InitByTagLookup(kNigoriTag)) { | 1698 ReadTransaction trans(GetUserShare()); |
| 1573 NOTREACHED(); | 1699 ReadNode node(&trans); |
| 1574 return; | 1700 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1701 NOTREACHED(); |
| 1702 return; |
| 1703 } |
| 1704 |
| 1705 nigori.CopyFrom(node.GetNigoriSpecifics()); |
| 1706 if (!nigori.encrypted().blob().empty()) { |
| 1707 if (cryptographer->CanDecrypt(nigori.encrypted())) { |
| 1708 cryptographer->SetKeys(nigori.encrypted()); |
| 1709 } else { |
| 1710 cryptographer->SetPendingKeys(nigori.encrypted()); |
| 1711 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 1712 OnPassphraseRequired(true)); |
| 1713 } |
| 1714 } |
| 1575 } | 1715 } |
| 1576 | 1716 |
| 1577 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); | 1717 // Refresh list of encrypted datatypes. |
| 1578 if (!nigori.encrypted().blob().empty()) { | 1718 syncable::ModelTypeSet encrypted_types = |
| 1579 if (cryptographer->CanDecrypt(nigori.encrypted())) { | 1719 syncable::GetEncryptedDataTypesFromNigori(nigori); |
| 1580 cryptographer->SetKeys(nigori.encrypted()); | 1720 |
| 1581 } else { | 1721 // Ensure any datatypes that need encryption are encrypted. |
| 1582 cryptographer->SetPendingKeys(nigori.encrypted()); | 1722 EncryptDataTypes(encrypted_types); |
| 1583 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 1584 OnPassphraseRequired(true)); | |
| 1585 } | |
| 1586 } | |
| 1587 } | 1723 } |
| 1588 | 1724 |
| 1589 void SyncManager::SyncInternal::StartSyncing() { | 1725 void SyncManager::SyncInternal::StartSyncing() { |
| 1590 if (syncer_thread()) // NULL during certain unittests. | 1726 if (syncer_thread()) // NULL during certain unittests. |
| 1591 syncer_thread()->Start(); // Start the syncer thread. This won't actually | 1727 syncer_thread()->Start(); // Start the syncer thread. This won't actually |
| 1592 // result in any syncing until at least the | 1728 // result in any syncing until at least the |
| 1593 // DirectoryManager broadcasts the OPENED event, | 1729 // DirectoryManager broadcasts the OPENED event, |
| 1594 // and a valid server connection is detected. | 1730 // and a valid server connection is detected. |
| 1595 } | 1731 } |
| 1596 | 1732 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 | 1823 |
| 1688 if (!setup_for_test_mode_) { | 1824 if (!setup_for_test_mode_) { |
| 1689 UpdateCredentials(credentials); | 1825 UpdateCredentials(credentials); |
| 1690 } | 1826 } |
| 1691 return true; | 1827 return true; |
| 1692 } | 1828 } |
| 1693 | 1829 |
| 1694 void SyncManager::SyncInternal::UpdateCredentials( | 1830 void SyncManager::SyncInternal::UpdateCredentials( |
| 1695 const SyncCredentials& credentials) { | 1831 const SyncCredentials& credentials) { |
| 1696 DCHECK_EQ(MessageLoop::current(), core_message_loop_); | 1832 DCHECK_EQ(MessageLoop::current(), core_message_loop_); |
| 1697 DCHECK(share_.name == credentials.email); | 1833 DCHECK_EQ(credentials.email, share_.name); |
| 1698 connection_manager()->set_auth_token(credentials.sync_token); | 1834 connection_manager()->set_auth_token(credentials.sync_token); |
| 1699 TalkMediatorLogin(credentials.email, credentials.sync_token); | 1835 TalkMediatorLogin(credentials.email, credentials.sync_token); |
| 1700 CheckServerReachable(); | 1836 CheckServerReachable(); |
| 1701 sync_manager_->RequestNudge(); | 1837 sync_manager_->RequestNudge(); |
| 1702 } | 1838 } |
| 1703 | 1839 |
| 1704 void SyncManager::SyncInternal::InitializeTalkMediator() { | 1840 void SyncManager::SyncInternal::InitializeTalkMediator() { |
| 1705 if (notifier_options_.notification_method == | 1841 if (notifier_options_.notification_method == |
| 1706 notifier::NOTIFICATION_SERVER) { | 1842 notifier::NOTIFICATION_SERVER) { |
| 1707 syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); | 1843 syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 OnPassphraseRequired(true)); | 1899 OnPassphraseRequired(true)); |
| 1764 return; | 1900 return; |
| 1765 } | 1901 } |
| 1766 | 1902 |
| 1767 // TODO(tim): If this is the first time the user has entered a passphrase | 1903 // TODO(tim): If this is the first time the user has entered a passphrase |
| 1768 // since the protocol changed to store passphrase preferences in the cloud, | 1904 // since the protocol changed to store passphrase preferences in the cloud, |
| 1769 // make sure we update this preference. See bug 62103. | 1905 // make sure we update this preference. See bug 62103. |
| 1770 if (is_explicit) | 1906 if (is_explicit) |
| 1771 SetUsingExplicitPassphrasePrefForMigration(); | 1907 SetUsingExplicitPassphrasePrefForMigration(); |
| 1772 | 1908 |
| 1773 // Nudge the syncer so that passwords updates that were waiting for this | 1909 // Nudge the syncer so that encrypted datatype updates that were waiting for |
| 1774 // passphrase get applied as soon as possible. | 1910 // this passphrase get applied as soon as possible. |
| 1775 sync_manager_->RequestNudge(); | 1911 sync_manager_->RequestNudge(); |
| 1776 } else { | 1912 } else { |
| 1777 WriteTransaction trans(GetUserShare()); | 1913 WriteTransaction trans(GetUserShare()); |
| 1778 WriteNode node(&trans); | 1914 WriteNode node(&trans); |
| 1779 if (!node.InitByTagLookup(kNigoriTag)) { | 1915 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1780 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | 1916 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. |
| 1781 NOTREACHED(); | 1917 NOTREACHED(); |
| 1782 return; | 1918 return; |
| 1783 } | 1919 } |
| 1784 | 1920 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1811 ReadNode node(&trans); | 1947 ReadNode node(&trans); |
| 1812 if (!node.InitByTagLookup(kNigoriTag)) { | 1948 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1813 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. | 1949 // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. |
| 1814 NOTREACHED(); | 1950 NOTREACHED(); |
| 1815 return false; | 1951 return false; |
| 1816 } | 1952 } |
| 1817 | 1953 |
| 1818 return node.GetNigoriSpecifics().using_explicit_passphrase(); | 1954 return node.GetNigoriSpecifics().using_explicit_passphrase(); |
| 1819 } | 1955 } |
| 1820 | 1956 |
| 1821 void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { | 1957 void SyncManager::SyncInternal::EncryptDataTypes( |
| 1822 // TODO(tim): bug 59242. We shouldn't lookup by data type and instead use | 1958 const syncable::ModelTypeSet& encrypted_types) { |
| 1823 // a protocol flag or existence of an EncryptedData message, but for now, | 1959 // Verify the encrypted types are all enabled. |
| 1824 // encryption is on if-and-only-if the type is passwords, and we haven't | 1960 ModelSafeRoutingInfo routes; |
| 1825 // ironed out the protocol for generic encryption. | 1961 registrar_->GetModelSafeRoutingInfo(&routes); |
| 1826 static const char* passwords_tag = "google_chrome_passwords"; | 1962 for (syncable::ModelTypeSet::const_iterator iter = encrypted_types.begin(); |
| 1827 ReadNode passwords_root(trans); | 1963 iter != encrypted_types.end(); ++iter) { |
| 1828 if (!passwords_root.InitByTagLookup(passwords_tag)) { | 1964 if (routes.count(*iter) == 0) { |
| 1829 LOG(WARNING) << "No passwords to reencrypt."; | 1965 LOG(WARNING) << "Attempted to encrypt non-enabled datatype " |
| 1966 << syncable::ModelTypeToString(*iter) << ", dropping type."; |
| 1967 routes.erase(*iter); |
| 1968 } |
| 1969 } |
| 1970 if (routes.count(syncable::PASSWORDS) > 0 && |
| 1971 encrypted_types.count(syncable::PASSWORDS) == 0) { |
| 1972 LOG(ERROR) << "Attempted to set PASSWORDS datatype as unencrypted"; |
| 1973 NOTREACHED(); |
| 1974 return; |
| 1975 } |
| 1976 WriteTransaction trans(GetUserShare()); |
| 1977 WriteNode node(&trans); |
| 1978 if (!node.InitByTagLookup(kNigoriTag)) { |
| 1979 LOG(ERROR) << "Unable to set encrypted datatypes because Nigori node not " |
| 1980 << "found."; |
| 1981 NOTREACHED(); |
| 1830 return; | 1982 return; |
| 1831 } | 1983 } |
| 1832 | 1984 |
| 1833 int64 child_id = passwords_root.GetFirstChildId(); | 1985 // Update the Nigori node set of encrypted datatypes so other machines notice. |
| 1834 while (child_id != kInvalidId) { | 1986 sync_pb::NigoriSpecifics nigori; |
| 1835 WriteNode child(trans); | 1987 nigori.CopyFrom(node.GetNigoriSpecifics()); |
| 1836 if (!child.InitByIdLookup(child_id)) { | 1988 syncable::FillNigoriEncryptedTypes(encrypted_types, &nigori); |
| 1989 node.SetNigoriSpecifics(nigori); |
| 1990 |
| 1991 // TODO(zea): only reencrypt this datatype? ReEncrypting everything is a |
| 1992 // safer approach, and should not impact anything that is already encrypted |
| 1993 // (redundant changes are ignored). |
| 1994 ReEncryptEverything(&trans); |
| 1995 return; |
| 1996 } |
| 1997 |
| 1998 void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { |
| 1999 syncable::ModelTypeSet encrypted_types = |
| 2000 GetEncryptedDataTypes(trans->GetWrappedTrans()); |
| 2001 std::string tag; |
| 2002 for (syncable::ModelTypeSet::iterator iter = encrypted_types.begin(); |
| 2003 iter != encrypted_types.end(); ++iter) { |
| 2004 if (*iter == syncable::PASSWORDS) |
| 2005 continue; // Has special implementation below. |
| 2006 ReadNode type_root(trans); |
| 2007 tag = syncable::ModelTypeToRootTag(*iter); |
| 2008 if (!type_root.InitByTagLookup(tag)) { |
| 1837 NOTREACHED(); | 2009 NOTREACHED(); |
| 1838 return; | 2010 return; |
| 1839 } | 2011 } |
| 1840 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); | 2012 |
| 1841 child_id = child.GetSuccessorId(); | 2013 // Iterate through all children of this datatype. |
| 2014 std::queue<int64> to_visit; |
| 2015 int64 child_id = type_root.GetFirstChildId(); |
| 2016 to_visit.push(child_id); |
| 2017 while (!to_visit.empty()) { |
| 2018 child_id = to_visit.front(); |
| 2019 to_visit.pop(); |
| 2020 if (child_id == kInvalidId) |
| 2021 continue; |
| 2022 |
| 2023 WriteNode child(trans); |
| 2024 if (!child.InitByIdLookup(child_id)) { |
| 2025 NOTREACHED(); |
| 2026 return; |
| 2027 } |
| 2028 if (child.GetIsFolder()) { |
| 2029 to_visit.push(child.GetFirstChildId()); |
| 2030 } else { |
| 2031 // Rewrite the specifics of the node with encrypted data if necessary. |
| 2032 child.ResetFromSpecifics(); |
| 2033 } |
| 2034 to_visit.push(child.GetSuccessorId()); |
| 2035 } |
| 1842 } | 2036 } |
| 2037 |
| 2038 if (encrypted_types.count(syncable::PASSWORDS) > 0) { |
| 2039 // Passwords are encrypted with their own legacy scheme. |
| 2040 ReadNode passwords_root(trans); |
| 2041 std::string passwords_tag = |
| 2042 syncable::ModelTypeToRootTag(syncable::PASSWORDS); |
| 2043 if (!passwords_root.InitByTagLookup(passwords_tag)) { |
| 2044 LOG(WARNING) << "No passwords to reencrypt."; |
| 2045 return; |
| 2046 } |
| 2047 |
| 2048 int64 child_id = passwords_root.GetFirstChildId(); |
| 2049 while (child_id != kInvalidId) { |
| 2050 WriteNode child(trans); |
| 2051 if (!child.InitByIdLookup(child_id)) { |
| 2052 NOTREACHED(); |
| 2053 return; |
| 2054 } |
| 2055 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); |
| 2056 child_id = child.GetSuccessorId(); |
| 2057 } |
| 2058 } |
| 2059 |
| 2060 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2061 OnEncryptionComplete(encrypted_types)); |
| 1843 } | 2062 } |
| 1844 | 2063 |
| 1845 SyncManager::~SyncManager() { | 2064 SyncManager::~SyncManager() { |
| 1846 delete data_; | 2065 delete data_; |
| 1847 } | 2066 } |
| 1848 | 2067 |
| 1849 void SyncManager::AddObserver(Observer* observer) { | 2068 void SyncManager::AddObserver(Observer* observer) { |
| 1850 data_->AddObserver(observer); | 2069 data_->AddObserver(observer); |
| 1851 } | 2070 } |
| 1852 | 2071 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 nudge_delay, | 2293 nudge_delay, |
| 2075 SyncerThread::kLocal, | 2294 SyncerThread::kLocal, |
| 2076 model_types); | 2295 model_types); |
| 2077 } | 2296 } |
| 2078 } | 2297 } |
| 2079 | 2298 |
| 2080 void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, | 2299 void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, |
| 2081 syncable::ModelType type, ChangeReorderBuffer* buffer, | 2300 syncable::ModelType type, ChangeReorderBuffer* buffer, |
| 2082 Cryptographer* cryptographer, const syncable::EntryKernel& original, | 2301 Cryptographer* cryptographer, const syncable::EntryKernel& original, |
| 2083 bool existed_before, bool exists_now) { | 2302 bool existed_before, bool exists_now) { |
| 2084 // If this is a deletion, attach the entity specifics as extra data | 2303 // If this is a deletion and the datatype was encrypted, we need to decrypt it |
| 2085 // so that the delete can be processed. | 2304 // and attach it to the buffer. |
| 2086 if (!exists_now && existed_before) { | 2305 if (!exists_now && existed_before) { |
| 2087 buffer->SetSpecificsForId(id, original.ref(SPECIFICS)); | 2306 sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS)); |
| 2088 if (type == syncable::PASSWORDS) { | 2307 if (type == syncable::PASSWORDS) { |
| 2089 // Need to dig a bit deeper as passwords are encrypted. | 2308 // Passwords must use their own legacy ExtraPasswordChangeRecordData. |
| 2090 scoped_ptr<sync_pb::PasswordSpecificsData> data( | 2309 scoped_ptr<sync_pb::PasswordSpecificsData> data( |
| 2091 DecryptPasswordSpecifics(original.ref(SPECIFICS), cryptographer)); | 2310 DecryptPasswordSpecifics(original_specifics, cryptographer)); |
| 2092 if (!data.get()) { | 2311 if (!data.get()) { |
| 2093 NOTREACHED(); | 2312 NOTREACHED(); |
| 2094 return; | 2313 return; |
| 2095 } | 2314 } |
| 2096 buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); | 2315 buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); |
| 2316 } else if (original_specifics.has_encrypted()) { |
| 2317 // All other datatypes can just create a new unencrypted specifics and |
| 2318 // attach it. |
| 2319 const sync_pb::EncryptedData& encrypted = original_specifics.encrypted(); |
| 2320 if (!cryptographer->Decrypt(encrypted, &original_specifics)) { |
| 2321 NOTREACHED(); |
| 2322 return; |
| 2323 } |
| 2097 } | 2324 } |
| 2325 buffer->SetSpecificsForId(id, original_specifics); |
| 2098 } | 2326 } |
| 2099 } | 2327 } |
| 2100 | 2328 |
| 2101 void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( | 2329 void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( |
| 2102 const syncable::DirectoryChangeEvent& event) { | 2330 const syncable::DirectoryChangeEvent& event) { |
| 2103 // We only expect one notification per sync step, so change_buffers_ should | 2331 // We only expect one notification per sync step, so change_buffers_ should |
| 2104 // contain no pending entries. | 2332 // contain no pending entries. |
| 2105 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::CALCULATE_CHANGES); | 2333 DCHECK_EQ(event.todo, syncable::DirectoryChangeEvent::CALCULATE_CHANGES); |
| 2106 DCHECK(event.writer == syncable::SYNCER || | 2334 DCHECK(event.writer == syncable::SYNCER || |
| 2107 event.writer == syncable::UNITTEST); | 2335 event.writer == syncable::UNITTEST); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2118 | 2346 |
| 2119 // Omit items that aren't associated with a model. | 2347 // Omit items that aren't associated with a model. |
| 2120 syncable::ModelType type = e.GetModelType(); | 2348 syncable::ModelType type = e.GetModelType(); |
| 2121 if (type == syncable::TOP_LEVEL_FOLDER || type == syncable::UNSPECIFIED) | 2349 if (type == syncable::TOP_LEVEL_FOLDER || type == syncable::UNSPECIFIED) |
| 2122 continue; | 2350 continue; |
| 2123 | 2351 |
| 2124 if (exists_now && !existed_before) | 2352 if (exists_now && !existed_before) |
| 2125 change_buffers_[type].PushAddedItem(id); | 2353 change_buffers_[type].PushAddedItem(id); |
| 2126 else if (!exists_now && existed_before) | 2354 else if (!exists_now && existed_before) |
| 2127 change_buffers_[type].PushDeletedItem(id); | 2355 change_buffers_[type].PushDeletedItem(id); |
| 2128 else if (exists_now && existed_before && VisiblePropertiesDiffer(*i, e)) | 2356 else if (exists_now && existed_before && |
| 2357 VisiblePropertiesDiffer(*i, e, dir_manager()->cryptographer())) { |
| 2129 change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); | 2358 change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); |
| 2359 } |
| 2130 | 2360 |
| 2131 SetExtraChangeRecordData(id, type, &change_buffers_[type], | 2361 SetExtraChangeRecordData(id, type, &change_buffers_[type], |
| 2132 dir_manager()->cryptographer(), *i, | 2362 dir_manager()->cryptographer(), *i, |
| 2133 existed_before, exists_now); | 2363 existed_before, exists_now); |
| 2134 } | 2364 } |
| 2135 } | 2365 } |
| 2136 | 2366 |
| 2137 SyncManager::Status SyncManager::SyncInternal::GetStatus() { | 2367 SyncManager::Status SyncManager::SyncInternal::GetStatus() { |
| 2138 return allstatus_.status(); | 2368 return allstatus_.status(); |
| 2139 } | 2369 } |
| 2140 | 2370 |
| 2141 void SyncManager::SyncInternal::OnSyncEngineEvent( | 2371 void SyncManager::SyncInternal::OnSyncEngineEvent( |
| 2142 const SyncEngineEvent& event) { | 2372 const SyncEngineEvent& event) { |
| 2143 if (observers_.size() <= 0) | 2373 if (observers_.size() <= 0) |
| 2144 return; | 2374 return; |
| 2145 | 2375 |
| 2146 // Only send an event if this is due to a cycle ending and this cycle | 2376 // Only send an event if this is due to a cycle ending and this cycle |
| 2147 // concludes a canonical "sync" process; that is, based on what is known | 2377 // concludes a canonical "sync" process; that is, based on what is known |
| 2148 // locally we are "all happy" and up-to-date. There may be new changes on | 2378 // locally we are "all happy" and up-to-date. There may be new changes on |
| 2149 // the server, but we'll get them on a subsequent sync. | 2379 // the server, but we'll get them on a subsequent sync. |
| 2150 // | 2380 // |
| 2151 // Notifications are sent at the end of every sync cycle, regardless of | 2381 // Notifications are sent at the end of every sync cycle, regardless of |
| 2152 // whether we should sync again. | 2382 // whether we should sync again. |
| 2153 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { | 2383 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { |
| 2154 ModelSafeRoutingInfo enabled_types; | 2384 ModelSafeRoutingInfo enabled_types; |
| 2155 registrar_->GetModelSafeRoutingInfo(&enabled_types); | 2385 registrar_->GetModelSafeRoutingInfo(&enabled_types); |
| 2156 if (enabled_types.count(syncable::PASSWORDS) > 0) { | 2386 { |
| 2157 Cryptographer* cryptographer = | 2387 // Check to see if we need to notify the frontend that we have newly |
| 2158 GetUserShare()->dir_manager->cryptographer(); | 2388 // encrypted types or that we require a passphrase. |
| 2159 if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { | 2389 sync_api::ReadTransaction trans(GetUserShare()); |
| 2160 sync_api::ReadTransaction trans(GetUserShare()); | 2390 sync_api::ReadNode node(&trans); |
| 2161 sync_api::ReadNode node(&trans); | 2391 if (!node.InitByTagLookup(kNigoriTag)) { |
| 2162 if (!node.InitByTagLookup(kNigoriTag)) { | 2392 DCHECK(!event.snapshot->is_share_usable); |
| 2163 DCHECK(!event.snapshot->is_share_usable); | 2393 return; |
| 2164 return; | 2394 } |
| 2395 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); |
| 2396 syncable::ModelTypeSet encrypted_types = |
| 2397 syncable::GetEncryptedDataTypesFromNigori(nigori); |
| 2398 // If this is a first time sync with encryption, it's possible Passwords |
| 2399 // hasn't been added to the encryption types list. |
| 2400 if (enabled_types.count(syncable::PASSWORDS) > 0) |
| 2401 encrypted_types.insert(syncable::PASSWORDS); |
| 2402 if (encrypted_types.size() > 0) { |
| 2403 Cryptographer* cryptographer = |
| 2404 GetUserShare()->dir_manager->cryptographer(); |
| 2405 if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { |
| 2406 if (!nigori.encrypted().blob().empty()) { |
| 2407 DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); |
| 2408 cryptographer->SetPendingKeys(nigori.encrypted()); |
| 2409 } |
| 2165 } | 2410 } |
| 2166 const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); | 2411 |
| 2167 if (!nigori.encrypted().blob().empty()) { | 2412 // If we've completed a sync cycle and the cryptographer isn't ready |
| 2168 DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); | 2413 // yet, prompt the user for a passphrase. |
| 2169 cryptographer->SetPendingKeys(nigori.encrypted()); | 2414 if (cryptographer->has_pending_keys()) { |
| 2415 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2416 OnPassphraseRequired(true)); |
| 2417 } else if (!cryptographer->is_ready()) { |
| 2418 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2419 OnPassphraseRequired(false)); |
| 2420 } else { |
| 2421 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2422 OnEncryptionComplete(encrypted_types)); |
| 2170 } | 2423 } |
| 2171 } | 2424 } |
| 2172 | |
| 2173 // If we've completed a sync cycle and the cryptographer isn't ready yet, | |
| 2174 // prompt the user for a passphrase. | |
| 2175 if (cryptographer->has_pending_keys()) { | |
| 2176 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 2177 OnPassphraseRequired(true)); | |
| 2178 } else if (!cryptographer->is_ready()) { | |
| 2179 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
| 2180 OnPassphraseRequired(false)); | |
| 2181 } | |
| 2182 } | 2425 } |
| 2183 | 2426 |
| 2184 if (!initialized()) | 2427 if (!initialized()) |
| 2185 return; | 2428 return; |
| 2186 | 2429 |
| 2187 if (!event.snapshot->has_more_to_sync) { | 2430 if (!event.snapshot->has_more_to_sync) { |
| 2188 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 2431 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
| 2189 OnSyncCycleCompleted(event.snapshot)); | 2432 OnSyncCycleCompleted(event.snapshot)); |
| 2190 } | 2433 } |
| 2191 | 2434 |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2539 | 2782 |
| 2540 void SyncManager::TriggerOnIncomingNotificationForTest( | 2783 void SyncManager::TriggerOnIncomingNotificationForTest( |
| 2541 const syncable::ModelTypeBitSet& model_types) { | 2784 const syncable::ModelTypeBitSet& model_types) { |
| 2542 IncomingNotificationData notification_data; | 2785 IncomingNotificationData notification_data; |
| 2543 notification_data.service_url = model_types.to_string(); | 2786 notification_data.service_url = model_types.to_string(); |
| 2544 // Here we rely on the default notification method being SERVER. | 2787 // Here we rely on the default notification method being SERVER. |
| 2545 data_->OnIncomingNotification(notification_data); | 2788 data_->OnIncomingNotification(notification_data); |
| 2546 } | 2789 } |
| 2547 | 2790 |
| 2548 } // namespace sync_api | 2791 } // namespace sync_api |
| OLD | NEW |