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

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

Issue 264793007: Keep track of which attachments are referenced by which sync entries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix memory leak. Created 6 years, 7 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, 344 syncer::ModelType type,
324 syncer::ModelType type, 345 const std::string& type_str,
325 const std::string& type_str, 346 syncer::WriteNode* node,
326 syncer::WriteNode* node, 347 DataTypeErrorHandler* error_handler) {
327 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,
335 "Failed to delete " + type_str + " node. Local data, empty tag. " + 355 "Failed to delete " + type_str + " node. Local data, empty tag. " +
336 change.location().ToString(), 356 change.location().ToString(),
337 type); 357 type);
(...skipping 23 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): Here is where we're going to update the in-directory
394 // entry to indicate that the attachments have been successfully stored on
395 // disk. Why do we care? Because we might crash after persisting the
396 // directory to disk, but before we have persisted its attachments, leaving us
397 // with danging attachment ids. Having a flag that indicates we've stored the
398 // entry will allow us to detect and filter entries with dangling attachment
399 // ids (bug 368353).
400 }
401
402 void StoreAttachments(syncer::AttachmentService* attachment_service,
403 const syncer::AttachmentList& attachments) {
404 DCHECK(attachment_service);
405 syncer::AttachmentService::StoreCallback ignore_store_result =
406 base::Bind(&IgnoreStoreResult);
407 attachment_service->StoreAttachments(attachments, ignore_store_result);
408 }
409
371 } // namespace 410 } // namespace
372 411
373 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( 412 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges(
374 const tracked_objects::Location& from_here, 413 const tracked_objects::Location& from_here,
375 const syncer::SyncChangeList& list_of_changes) { 414 const syncer::SyncChangeList& list_of_changes) {
376 DCHECK(CalledOnValidThread()); 415 DCHECK(CalledOnValidThread());
416
417 // Keep track of brand new attachments so we can persist them on this device
418 // and upload them to the server.
419 syncer::AttachmentList new_attachments;
420
377 syncer::WriteTransaction trans(from_here, share_handle()); 421 syncer::WriteTransaction trans(from_here, share_handle());
378 422
379 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); 423 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin();
380 iter != list_of_changes.end(); 424 iter != list_of_changes.end();
381 ++iter) { 425 ++iter) {
382 const syncer::SyncChange& change = *iter; 426 const syncer::SyncChange& change = *iter;
383 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED); 427 DCHECK_NE(change.sync_data().GetDataType(), syncer::UNSPECIFIED);
384 syncer::ModelType type = change.sync_data().GetDataType(); 428 syncer::ModelType type = change.sync_data().GetDataType();
385 std::string type_str = syncer::ModelTypeToString(type); 429 std::string type_str = syncer::ModelTypeToString(type);
386 syncer::WriteNode sync_node(&trans); 430 syncer::WriteNode sync_node(&trans);
387 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) { 431 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) {
388 syncer::SyncError error = 432 syncer::SyncError error =
389 AttemptDelete(change, type, type_str, &sync_node, error_handler()); 433 AttemptDelete(change, type, type_str, &sync_node, error_handler());
390 if (error.IsSet()) { 434 if (error.IsSet()) {
391 NOTREACHED(); 435 NOTREACHED();
392 return error; 436 return error;
393 } 437 }
394 attachment_service_->OnSyncDataDelete(change.sync_data());
395 if (merge_result_.get()) { 438 if (merge_result_.get()) {
396 merge_result_->set_num_items_deleted( 439 merge_result_->set_num_items_deleted(
397 merge_result_->num_items_deleted() + 1); 440 merge_result_->num_items_deleted() + 1);
398 } 441 }
399 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { 442 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) {
400 syncer::SyncError error = 443 syncer::SyncError error = HandleActionAdd(
401 HandleActionAdd(change, type_str, type, trans, &sync_node); 444 change, type_str, type, trans, &sync_node, &new_attachments);
402 if (error.IsSet()) { 445 if (error.IsSet()) {
403 return error; 446 return error;
404 } 447 }
405 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { 448 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) {
406 syncer::SyncError error = 449 syncer::SyncError error = HandleActionUpdate(
407 HandleActionUpdate(change, type_str, type, trans, &sync_node); 450 change, type_str, type, trans, &sync_node, &new_attachments);
408 if (error.IsSet()) { 451 if (error.IsSet()) {
409 return error; 452 return error;
410 } 453 }
411 } else { 454 } else {
412 syncer::SyncError error( 455 syncer::SyncError error(
413 FROM_HERE, 456 FROM_HERE,
414 syncer::SyncError::DATATYPE_ERROR, 457 syncer::SyncError::DATATYPE_ERROR,
415 "Received unset SyncChange in the change processor, " + 458 "Received unset SyncChange in the change processor, " +
416 change.location().ToString(), 459 change.location().ToString(),
417 type); 460 type);
418 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 461 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
419 error.message()); 462 error.message());
420 NOTREACHED(); 463 NOTREACHED();
421 LOG(ERROR) << "Unset sync change."; 464 LOG(ERROR) << "Unset sync change.";
422 return error; 465 return error;
423 } 466 }
424 } 467 }
468
469 if (!new_attachments.empty()) {
470 StoreAttachments(attachment_service_.get(), new_attachments);
471 }
472
425 return syncer::SyncError(); 473 return syncer::SyncError();
426 } 474 }
427 475
428 // WARNING: this code is sensitive to compiler optimizations. Be careful 476 // WARNING: this code is sensitive to compiler optimizations. Be careful
429 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else 477 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else
430 // the compiler attempts to merge it with other calls, losing useful information 478 // the compiler attempts to merge it with other calls, losing useful information
431 // in breakpad uploads. 479 // in breakpad uploads.
432 syncer::SyncError GenericChangeProcessor::HandleActionAdd( 480 syncer::SyncError GenericChangeProcessor::HandleActionAdd(
433 const syncer::SyncChange& change, 481 const syncer::SyncChange& change,
434 const std::string& type_str, 482 const std::string& type_str,
435 const syncer::ModelType& type, 483 const syncer::ModelType& type,
436 const syncer::WriteTransaction& trans, 484 const syncer::WriteTransaction& trans,
437 syncer::WriteNode* sync_node) { 485 syncer::WriteNode* sync_node,
486 syncer::AttachmentList* new_attachments) {
438 // TODO(sync): Handle other types of creation (custom parents, folders, 487 // TODO(sync): Handle other types of creation (custom parents, folders,
439 // etc.). 488 // etc.).
440 syncer::ReadNode root_node(&trans); 489 syncer::ReadNode root_node(&trans);
490 const syncer::SyncDataLocal sync_data_local(change.sync_data());
441 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag( 491 if (root_node.InitByTagLookup(syncer::ModelTypeToRootTag(
442 change.sync_data().GetDataType())) != syncer::BaseNode::INIT_OK) { 492 sync_data_local.GetDataType())) != syncer::BaseNode::INIT_OK) {
443 syncer::SyncError error(FROM_HERE, 493 syncer::SyncError error(FROM_HERE,
444 syncer::SyncError::DATATYPE_ERROR, 494 syncer::SyncError::DATATYPE_ERROR,
445 "Failed to look up root node for type " + type_str, 495 "Failed to look up root node for type " + type_str,
446 type); 496 type);
447 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 497 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
448 error.message()); 498 error.message());
449 NOTREACHED(); 499 NOTREACHED();
450 LOG(ERROR) << "Create: no root node."; 500 LOG(ERROR) << "Create: no root node.";
451 return error; 501 return error;
452 } 502 }
453 syncer::WriteNode::InitUniqueByCreationResult result = 503 syncer::WriteNode::InitUniqueByCreationResult result =
454 sync_node->InitUniqueByCreation( 504 sync_node->InitUniqueByCreation(
455 change.sync_data().GetDataType(), 505 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) { 506 if (result != syncer::WriteNode::INIT_SUCCESS) {
459 std::string error_prefix = "Failed to create " + type_str + " node: " + 507 std::string error_prefix = "Failed to create " + type_str + " node: " +
460 change.location().ToString() + ", "; 508 change.location().ToString() + ", ";
461 switch (result) { 509 switch (result) {
462 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: { 510 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: {
463 syncer::SyncError error; 511 syncer::SyncError error;
464 error.Reset(FROM_HERE, error_prefix + "empty tag", type); 512 error.Reset(FROM_HERE, error_prefix + "empty tag", type);
465 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 513 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
466 error.message()); 514 error.message());
467 LOG(ERROR) << "Create: Empty tag."; 515 LOG(ERROR) << "Create: Empty tag.";
(...skipping 28 matching lines...) Expand all
496 syncer::SyncError error; 544 syncer::SyncError error;
497 error.Reset(FROM_HERE, error_prefix + "unknown error", type); 545 error.Reset(FROM_HERE, error_prefix + "unknown error", type);
498 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 546 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
499 error.message()); 547 error.message());
500 LOG(ERROR) << "Create: Unknown error."; 548 LOG(ERROR) << "Create: Unknown error.";
501 return error; 549 return error;
502 } 550 }
503 } 551 }
504 } 552 }
505 sync_node->SetTitle(change.sync_data().GetTitle()); 553 sync_node->SetTitle(change.sync_data().GetTitle());
506 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); 554 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node);
507 attachment_service_->OnSyncDataAdd(change.sync_data()); 555
556 syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds();
557 SetAttachmentMetadata(attachment_ids, sync_node);
558
559 // Return any newly added attachments.
560 const syncer::AttachmentList& local_attachments_for_upload =
561 sync_data_local.GetLocalAttachmentsForUpload();
562 new_attachments->insert(new_attachments->end(),
563 local_attachments_for_upload.begin(),
564 local_attachments_for_upload.end());
565
508 if (merge_result_.get()) { 566 if (merge_result_.get()) {
509 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); 567 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1);
510 } 568 }
511 return syncer::SyncError(); 569 return syncer::SyncError();
512 } 570 }
513 // WARNING: this code is sensitive to compiler optimizations. Be careful 571 // WARNING: this code is sensitive to compiler optimizations. Be careful
514 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else 572 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else
515 // the compiler attempts to merge it with other calls, losing useful information 573 // the compiler attempts to merge it with other calls, losing useful information
516 // in breakpad uploads. 574 // in breakpad uploads.
517 syncer::SyncError GenericChangeProcessor::HandleActionUpdate( 575 syncer::SyncError GenericChangeProcessor::HandleActionUpdate(
518 const syncer::SyncChange& change, 576 const syncer::SyncChange& change,
519 const std::string& type_str, 577 const std::string& type_str,
520 const syncer::ModelType& type, 578 const syncer::ModelType& type,
521 const syncer::WriteTransaction& trans, 579 const syncer::WriteTransaction& trans,
522 syncer::WriteNode* sync_node) { 580 syncer::WriteNode* sync_node,
581 syncer::AttachmentList* new_attachments) {
523 // TODO(zea): consider having this logic for all possible changes? 582 // TODO(zea): consider having this logic for all possible changes?
583
584 const syncer::SyncDataLocal sync_data_local(change.sync_data());
524 syncer::BaseNode::InitByLookupResult result = 585 syncer::BaseNode::InitByLookupResult result =
525 sync_node->InitByClientTagLookup( 586 sync_node->InitByClientTagLookup(sync_data_local.GetDataType(),
526 change.sync_data().GetDataType(), 587 sync_data_local.GetTag());
527 syncer::SyncDataLocal(change.sync_data()).GetTag());
528 if (result != syncer::BaseNode::INIT_OK) { 588 if (result != syncer::BaseNode::INIT_OK) {
529 std::string error_prefix = "Failed to load " + type_str + " node. " + 589 std::string error_prefix = "Failed to load " + type_str + " node. " +
530 change.location().ToString() + ", "; 590 change.location().ToString() + ", ";
531 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) { 591 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) {
532 syncer::SyncError error; 592 syncer::SyncError error;
533 error.Reset(FROM_HERE, error_prefix + "empty tag", type); 593 error.Reset(FROM_HERE, error_prefix + "empty tag", type);
534 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 594 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
535 error.message()); 595 error.message());
536 LOG(ERROR) << "Update: Empty tag."; 596 LOG(ERROR) << "Update: Empty tag.";
537 return error; 597 return error;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 type); 659 type);
600 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, 660 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE,
601 error.message()); 661 error.message());
602 LOG(ERROR) << "Update: encr case 4."; 662 LOG(ERROR) << "Update: encr case 4.";
603 return error; 663 return error;
604 } 664 }
605 } 665 }
606 } 666 }
607 667
608 sync_node->SetTitle(change.sync_data().GetTitle()); 668 sync_node->SetTitle(change.sync_data().GetTitle());
609 SetNodeSpecifics(change.sync_data().GetSpecifics(), sync_node); 669 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node);
610 attachment_service_->OnSyncDataUpdate(sync_node->GetAttachmentIds(), 670 SetAttachmentMetadata(sync_data_local.GetAttachmentIds(), sync_node);
611 change.sync_data()); 671
672 // Return any newly added attachments.
673 const syncer::AttachmentList& local_attachments_for_upload =
674 sync_data_local.GetLocalAttachmentsForUpload();
675 new_attachments->insert(new_attachments->end(),
676 local_attachments_for_upload.begin(),
677 local_attachments_for_upload.end());
678
612 if (merge_result_.get()) { 679 if (merge_result_.get()) {
613 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + 680 merge_result_->set_num_items_modified(merge_result_->num_items_modified() +
614 1); 681 1);
615 } 682 }
616 // TODO(sync): Support updating other parts of the sync node (title, 683 // TODO(sync): Support updating other parts of the sync node (title,
617 // successor, parent, etc.). 684 // successor, parent, etc.).
618 return syncer::SyncError(); 685 return syncer::SyncError();
619 } 686 }
620 687
621 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( 688 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 void GenericChangeProcessor::StartImpl() { 722 void GenericChangeProcessor::StartImpl() {
656 DCHECK(CalledOnValidThread()); 723 DCHECK(CalledOnValidThread());
657 } 724 }
658 725
659 syncer::UserShare* GenericChangeProcessor::share_handle() const { 726 syncer::UserShare* GenericChangeProcessor::share_handle() const {
660 DCHECK(CalledOnValidThread()); 727 DCHECK(CalledOnValidThread());
661 return share_handle_; 728 return share_handle_;
662 } 729 }
663 730
664 } // namespace browser_sync 731 } // namespace browser_sync
OLDNEW
« no previous file with comments | « components/sync_driver/generic_change_processor.h ('k') | components/sync_driver/generic_change_processor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698