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

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: Rebase + small fix 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
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/engine/syncapi_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncapi.h ('k') | chrome/browser/sync/engine/syncapi_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698