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