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

Side by Side Diff: components/sync_driver/generic_change_processor.cc

Issue 247983002: Keep track of which attachments are referenced by which sync entries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix "copy yourself bug". Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "components/sync_driver/generic_change_processor.h" 5 #include "components/sync_driver/generic_change_processor.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "sync/api/sync_change.h" 10 #include "sync/api/sync_change.h"
(...skipping 18 matching lines...) Expand all
29 syncer::WriteNode* write_node) { 29 syncer::WriteNode* write_node) {
30 if (syncer::GetModelTypeFromSpecifics(entity_specifics) == 30 if (syncer::GetModelTypeFromSpecifics(entity_specifics) ==
31 syncer::PASSWORDS) { 31 syncer::PASSWORDS) {
32 write_node->SetPasswordSpecifics( 32 write_node->SetPasswordSpecifics(
33 entity_specifics.password().client_only_encrypted_data()); 33 entity_specifics.password().client_only_encrypted_data());
34 } else { 34 } else {
35 write_node->SetEntitySpecifics(entity_specifics); 35 write_node->SetEntitySpecifics(entity_specifics);
36 } 36 }
37 } 37 }
38 38
39 // Helper function to convert AttachmentId to AttachmentMetadataRecord.
40 sync_pb::AttachmentMetadataRecord AttachmentIdToRecord(
41 const syncer::AttachmentId& attachment_id) {
42 sync_pb::AttachmentMetadataRecord record;
43 *record.mutable_id() = attachment_id.GetProto();
44 return record;
45 }
46
47 // Replace |write_nodes|'s attachment ids with |attachment_ids|.
48 void SetAttachmentMetadata(const syncer::AttachmentIdList& attachment_ids,
49 syncer::WriteNode* write_node) {
50 DCHECK(write_node);
51 sync_pb::AttachmentMetadata attachment_metadata;
52 std::transform(
53 attachment_ids.begin(),
54 attachment_ids.end(),
55 RepeatedFieldBackInserter(attachment_metadata.mutable_record()),
56 AttachmentIdToRecord);
57 write_node->SetAttachmentMetadata(attachment_metadata);
58 }
59
39 syncer::SyncData BuildRemoteSyncData( 60 syncer::SyncData BuildRemoteSyncData(
40 int64 sync_id, 61 int64 sync_id,
41 const syncer::BaseNode& read_node, 62 const syncer::BaseNode& read_node,
42 const syncer::AttachmentServiceProxy& attachment_service_proxy) { 63 const syncer::AttachmentServiceProxy& attachment_service_proxy) {
43 const syncer::AttachmentIdList& attachment_ids = read_node.GetAttachmentIds(); 64 const syncer::AttachmentIdList& attachment_ids = read_node.GetAttachmentIds();
44 // Use the specifics of non-password datatypes directly (encryption has 65 // Use the specifics of non-password datatypes directly (encryption has
45 // already been handled). 66 // already been handled).
46 if (read_node.GetModelType() != syncer::PASSWORDS) { 67 if (read_node.GetModelType() != syncer::PASSWORDS) {
47 return syncer::SyncData::CreateRemoteData(sync_id, 68 return syncer::SyncData::CreateRemoteData(sync_id,
48 read_node.GetEntitySpecifics(), 69 read_node.GetEntitySpecifics(),
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 // Should have listed all the possible error cases above. 333 // Should have listed all the possible error cases above.
313 error.Reset(from_here, error_prefix + "unknown error", type); 334 error.Reset(from_here, error_prefix + "unknown error", type);
314 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, 335 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE,
315 error.message()); 336 error.message());
316 LOG(ERROR) << "Delete: Unknown error."; 337 LOG(ERROR) << "Delete: Unknown error.";
317 return error; 338 return error;
318 } 339 }
319 } 340 }
320 } 341 }
321 342
322 syncer::SyncError AttemptDelete( 343 syncer::SyncError AttemptDelete(const syncer::SyncChange& change,
323 const syncer::SyncChange& change,
324 syncer::ModelType type, 344 syncer::ModelType type,
pavely 2014/04/28 23:26:27 nit: Indentation is off.
maniscalco 2014/04/29 20:53:22 Fixed (and ran through "git cl format").
325 const std::string& type_str, 345 const std::string& type_str,
326 syncer::WriteNode* node, 346 syncer::WriteNode* node,
327 DataTypeErrorHandler* error_handler) { 347 DataTypeErrorHandler* error_handler) {
328 DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE); 348 DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE);
329 if (change.sync_data().IsLocal()) { 349 if (change.sync_data().IsLocal()) {
330 const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); 350 const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag();
331 if (tag.empty()) { 351 if (tag.empty()) {
332 syncer::SyncError error( 352 syncer::SyncError error(
333 FROM_HERE, 353 FROM_HERE,
334 syncer::SyncError::DATATYPE_ERROR, 354 syncer::SyncError::DATATYPE_ERROR,
(...skipping 26 matching lines...) Expand all
361 type, error_handler); 381 type, error_handler);
362 } 382 }
363 } 383 }
364 if (IsActOnceDataType(type)) 384 if (IsActOnceDataType(type))
365 node->Drop(); 385 node->Drop();
366 else 386 else
367 node->Tombstone(); 387 node->Tombstone();
368 return syncer::SyncError(); 388 return syncer::SyncError();
369 } 389 }
370 390
391 // A callback invoked on completion of AttachmentService::StoreAttachment.
392 void IgnoreStoreResult(const syncer::AttachmentService::StoreResult&) {
393 // TODO(maniscalco): Log errors?
394 }
395
396 void StoreAttachments(syncer::AttachmentService* attachment_service,
397 const syncer::AttachmentList& attachments) {
398 DCHECK(attachment_service);
399 syncer::AttachmentService::StoreCallback ignore_store_result =
400 base::Bind(&IgnoreStoreResult);
401 attachment_service->StoreAttachments(attachments, ignore_store_result);
402 }
403
371 } // namespace 404 } // namespace
372 405
373 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( 406 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges(
374 const tracked_objects::Location& from_here, 407 const tracked_objects::Location& from_here,
375 const syncer::SyncChangeList& list_of_changes) { 408 const syncer::SyncChangeList& list_of_changes) {
376 DCHECK(CalledOnValidThread()); 409 DCHECK(CalledOnValidThread());
410
411 // Keep track of brand new attachments so we can persist them on this device
412 // and upload them to the server.
413 syncer::AttachmentList new_attachments;
414
377 syncer::WriteTransaction trans(from_here, share_handle()); 415 syncer::WriteTransaction trans(from_here, share_handle());
378 416
379 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); 417 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin();
380 iter != list_of_changes.end(); 418 iter != list_of_changes.end();
381 ++iter) { 419 ++iter) {
382 const syncer::SyncChange& change = *iter; 420 const syncer::SyncChange& change = *iter;
383 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED); 421 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED);
384 syncer::ModelType type = change.sync_data().GetDataType(); 422 syncer::ModelType type = change.sync_data().GetDataType();
385 std::string type_str = syncer::ModelTypeToString(type); 423 std::string type_str = syncer::ModelTypeToString(type);
386 syncer::WriteNode sync_node(&trans); 424 syncer::WriteNode sync_node(&trans);
387 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) { 425 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) {
388 syncer::SyncError error = 426 syncer::SyncError error =
389 AttemptDelete(change, type, type_str, &sync_node, error_handler()); 427 AttemptDelete(change, type, type_str, &sync_node, error_handler());
390 if (error.IsSet()) { 428 if (error.IsSet()) {
391 NOTREACHED(); 429 NOTREACHED();
392 return error; 430 return error;
393 } 431 }
394 attachment_service_->OnSyncDataDelete(change.sync_data());
395 if (merge_result_.get()) { 432 if (merge_result_.get()) {
396 merge_result_->set_num_items_deleted( 433 merge_result_->set_num_items_deleted(
397 merge_result_->num_items_deleted() + 1); 434 merge_result_->num_items_deleted() + 1);
398 } 435 }
399 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { 436 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) {
400 syncer::SyncError error = 437 syncer::SyncError error = HandleActionAdd(
401 HandleActionAdd(change, type_str, type, trans, &sync_node); 438 change, type_str, type, trans, &sync_node, &new_attachments);
402 if (error.IsSet()) { 439 if (error.IsSet()) {
403 return error; 440 return error;
404 } 441 }
405 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { 442 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) {
406 syncer::SyncError error = 443 syncer::SyncError error = HandleActionUpdate(
407 HandleActionUpdate(change, type_str, type, trans, &sync_node); 444 change, type_str, type, trans, &sync_node, &new_attachments);
408 if (error.IsSet()) { 445 if (error.IsSet()) {
409 return error; 446 return error;
410 } 447 }
411 } else { 448 } else {
412 syncer::SyncError error( 449 syncer::SyncError error(
413 FROM_HERE, 450 FROM_HERE,
414 syncer::SyncError::DATATYPE_ERROR, 451 syncer::SyncError::DATATYPE_ERROR,
415 "Received unset SyncChange in the change processor, " + 452 "Received unset SyncChange in the change processor, " +
416 change.location().ToString(), 453 change.location().ToString(),
417 type); 454 type);
418 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 455 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
419 error.message()); 456 error.message());
420 NOTREACHED(); 457 NOTREACHED();
421 LOG(ERROR) << "Unset sync change."; 458 LOG(ERROR) << "Unset sync change.";
422 return error; 459 return error;
423 } 460 }
424 } 461 }
462
463 if (!new_attachments.empty()) {
464 StoreAttachments(attachment_service_.get(), new_attachments);
465 }
466
425 return syncer::SyncError(); 467 return syncer::SyncError();
426 } 468 }
427 469
428 // WARNING: this code is sensitive to compiler optimizations. Be careful 470 // WARNING: this code is sensitive to compiler optimizations. Be careful
429 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else 471 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else
430 // the compiler attempts to merge it with other calls, losing useful information 472 // the compiler attempts to merge it with other calls, losing useful information
431 // in breakpad uploads. 473 // in breakpad uploads.
432 syncer::SyncError GenericChangeProcessor::HandleActionAdd( 474 syncer::SyncError GenericChangeProcessor::HandleActionAdd(
433 const syncer::SyncChange& change, 475 const syncer::SyncChange& change,
434 const std::string& type_str, 476 const std::string& type_str,
435 const syncer::ModelType& type, 477 const syncer::ModelType& type,
436 const syncer::WriteTransaction& trans, 478 const syncer::WriteTransaction& trans,
437 syncer::WriteNode* sync_node) { 479 syncer::WriteNode* sync_node,
480 syncer::AttachmentList* new_attachments) {
438 // TODO(sync): Handle other types of creation (custom parents, folders, 481 // TODO(sync): Handle other types of creation (custom parents, folders,
439 // etc.). 482 // etc.).
440 syncer::ReadNode root_node(&trans); 483 syncer::ReadNode root_node(&trans);
484 const syncer::SyncDataLocal sync_data_local(change.sync_data());
441 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag( 485 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag(
442 change.sync_data().GetDataType())) != syncer::BaseNode::INIT_OK) { 486 sync_data_local.GetDataType())) != syncer::BaseNode::INIT_OK) {
443 syncer::SyncError error(FROM_HERE, 487 syncer::SyncError error(FROM_HERE,
444 syncer::SyncError::DATATYPE_ERROR, 488 syncer::SyncError::DATATYPE_ERROR,
445 "Failed to look up root node for type " + type_str, 489 "Failed to look up root node for type " + type_str,
446 type); 490 type);
447 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 491 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
448 error.message()); 492 error.message());
449 NOTREACHED(); 493 NOTREACHED();
450 LOG(ERROR) << "Create: no root node."; 494 LOG(ERROR) << "Create: no root node.";
451 return error; 495 return error;
452 } 496 }
453 syncer::WriteNode::InitUniqueByCreationResult result = 497 syncer::WriteNode::InitUniqueByCreationResult result =
454 sync_node->InitUniqueByCreation( 498 sync_node->InitUniqueByCreation(
455 change.sync_data().GetDataType(), 499 sync_data_local.GetDataType(), root_node, sync_data_local.GetTag());
456 root_node,
457 syncer::SyncDataLocal(change.sync_data()).GetTag());
458 if (result != syncer::WriteNode::INIT_SUCCESS) { 500 if (result != syncer::WriteNode::INIT_SUCCESS) {
459 std::string error_prefix = "Failed to create " + type_str + " node: " + 501 std::string error_prefix = "Failed to create " + type_str + " node: " +
460 change.location().ToString() + ", "; 502 change.location().ToString() + ", ";
461 switch (result) { 503 switch (result) {
462 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: { 504 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: {
463 syncer::SyncError error; 505 syncer::SyncError error;
464 error.Reset(FROM_HERE, error_prefix + "empty tag", type); 506 error.Reset(FROM_HERE, error_prefix + "empty tag", type);
465 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 507 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
466 error.message()); 508 error.message());
467 LOG(ERROR) << "Create: Empty tag."; 509 LOG(ERROR) << "Create: Empty tag.";
(...skipping 28 matching lines...) Expand all
496 syncer::SyncError error; 538 syncer::SyncError error;
497 error.Reset(FROM_HERE, error_prefix + "unknown error", type); 539 error.Reset(FROM_HERE, error_prefix + "unknown error", type);
498 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 540 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
499 error.message()); 541 error.message());
500 LOG(ERROR) << "Create: Unknown error."; 542 LOG(ERROR) << "Create: Unknown error.";
501 return error; 543 return error;
502 } 544 }
503 } 545 }
504 } 546 }
505 sync_node->SetTitle(change.sync_data().GetTitle()); 547 sync_node->SetTitle(change.sync_data().GetTitle());
506 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); 548 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node);
507 attachment_service_->OnSyncDataAdd(change.sync_data()); 549
550 syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds();
551 SetAttachmentMetadata(attachment_ids, sync_node);
552
553 // Return any newly added attachments.
554 const syncer::AttachmentList& local_attachments_for_upload =
555 sync_data_local.GetLocalAttachmentsForUpload();
556 new_attachments->insert(new_attachments->end(),
557 local_attachments_for_upload.begin(),
558 local_attachments_for_upload.end());
559
508 if (merge_result_.get()) { 560 if (merge_result_.get()) {
509 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); 561 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1);
510 } 562 }
511 return syncer::SyncError(); 563 return syncer::SyncError();
512 } 564 }
513 // WARNING: this code is sensitive to compiler optimizations. Be careful 565 // WARNING: this code is sensitive to compiler optimizations. Be careful
514 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else 566 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else
515 // the compiler attempts to merge it with other calls, losing useful information 567 // the compiler attempts to merge it with other calls, losing useful information
516 // in breakpad uploads. 568 // in breakpad uploads.
517 syncer::SyncError GenericChangeProcessor::HandleActionUpdate( 569 syncer::SyncError GenericChangeProcessor::HandleActionUpdate(
518 const syncer::SyncChange& change, 570 const syncer::SyncChange& change,
519 const std::string& type_str, 571 const std::string& type_str,
520 const syncer::ModelType& type, 572 const syncer::ModelType& type,
521 const syncer::WriteTransaction& trans, 573 const syncer::WriteTransaction& trans,
522 syncer::WriteNode* sync_node) { 574 syncer::WriteNode* sync_node,
575 syncer::AttachmentList* new_attachments) {
523 // TODO(zea): consider having this logic for all possible changes? 576 // TODO(zea): consider having this logic for all possible changes?
577
578 const syncer::SyncDataLocal sync_data_local(change.sync_data());
524 syncer::BaseNode::InitByLookupResult result = 579 syncer::BaseNode::InitByLookupResult result =
525 sync_node->InitByClientTagLookup( 580 sync_node->InitByClientTagLookup(sync_data_local.GetDataType(),
526 change.sync_data().GetDataType(), 581 sync_data_local.GetTag());
527 syncer::SyncDataLocal(change.sync_data()).GetTag());
528 if (result != syncer::BaseNode::INIT_OK) { 582 if (result != syncer::BaseNode::INIT_OK) {
529 std::string error_prefix = "Failed to load " + type_str + " node. " + 583 std::string error_prefix = "Failed to load " + type_str + " node. " +
530 change.location().ToString() + ", "; 584 change.location().ToString() + ", ";
531 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) { 585 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) {
532 syncer::SyncError error; 586 syncer::SyncError error;
533 error.Reset(FROM_HERE, error_prefix + "empty tag", type); 587 error.Reset(FROM_HERE, error_prefix + "empty tag", type);
534 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 588 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
535 error.message()); 589 error.message());
536 LOG(ERROR) << "Update: Empty tag."; 590 LOG(ERROR) << "Update: Empty tag.";
537 return error; 591 return error;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 type); 653 type);
600 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 654 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
601 error.message()); 655 error.message());
602 LOG(ERROR) << "Update: encr case 4."; 656 LOG(ERROR) << "Update: encr case 4.";
603 return error; 657 return error;
604 } 658 }
605 } 659 }
606 } 660 }
607 661
608 sync_node->SetTitle(change.sync_data().GetTitle()); 662 sync_node->SetTitle(change.sync_data().GetTitle());
609 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); 663 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node);
610 attachment_service_->OnSyncDataUpdate(sync_node->GetAttachmentIds(), 664 SetAttachmentMetadata(sync_data_local.GetAttachmentIds(), sync_node);
611 change.sync_data()); 665
666 // Return any newly added attachments.
667 const syncer::AttachmentList& local_attachments_for_upload =
668 sync_data_local.GetLocalAttachmentsForUpload();
669 new_attachments->insert(new_attachments->end(),
670 local_attachments_for_upload.begin(),
671 local_attachments_for_upload.end());
672
612 if (merge_result_.get()) { 673 if (merge_result_.get()) {
613 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + 674 merge_result_->set_num_items_modified(merge_result_->num_items_modified() +
614 1); 675 1);
615 } 676 }
616 // TODO(sync): Support updating other parts of the sync node (title, 677 // TODO(sync): Support updating other parts of the sync node (title,
617 // successor, parent, etc.). 678 // successor, parent, etc.).
618 return syncer::SyncError(); 679 return syncer::SyncError();
619 } 680 }
620 681
621 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( 682 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 void GenericChangeProcessor::StartImpl() { 716 void GenericChangeProcessor::StartImpl() {
656 DCHECK(CalledOnValidThread()); 717 DCHECK(CalledOnValidThread());
657 } 718 }
658 719
659 syncer::UserShare* GenericChangeProcessor::share_handle() const { 720 syncer::UserShare* GenericChangeProcessor::share_handle() const {
660 DCHECK(CalledOnValidThread()); 721 DCHECK(CalledOnValidThread());
661 return share_handle_; 722 return share_handle_;
662 } 723 }
663 724
664 } // namespace browser_sync 725 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698