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