Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: chrome/browser/sync/engine/syncapi.cc

Issue 6465005: [Sync] Initial support for encrypting any datatype (no UI hookup yet). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Feedback and fix windows crash. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698