OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <windows.h> | 10 #include <windows.h> |
(...skipping 14 matching lines...) Expand all Loading... |
25 | 25 |
26 #include <iomanip> | 26 #include <iomanip> |
27 #include <list> | 27 #include <list> |
28 #include <string> | 28 #include <string> |
29 #include <vector> | 29 #include <vector> |
30 | 30 |
31 #include "base/basictypes.h" | 31 #include "base/basictypes.h" |
32 #include "base/lock.h" | 32 #include "base/lock.h" |
33 #include "base/platform_thread.h" | 33 #include "base/platform_thread.h" |
34 #include "base/scoped_ptr.h" | 34 #include "base/scoped_ptr.h" |
| 35 #include "base/sha1.h" |
35 #include "base/string_util.h" | 36 #include "base/string_util.h" |
36 #include "base/task.h" | 37 #include "base/task.h" |
37 #include "base/utf_string_conversions.h" | 38 #include "base/utf_string_conversions.h" |
38 #include "chrome/browser/sync/engine/all_status.h" | 39 #include "chrome/browser/sync/engine/all_status.h" |
39 #include "chrome/browser/sync/engine/auth_watcher.h" | 40 #include "chrome/browser/sync/engine/auth_watcher.h" |
40 #include "chrome/browser/sync/engine/change_reorder_buffer.h" | 41 #include "chrome/browser/sync/engine/change_reorder_buffer.h" |
41 #include "chrome/browser/sync/engine/model_safe_worker.h" | 42 #include "chrome/browser/sync/engine/model_safe_worker.h" |
42 #include "chrome/browser/sync/engine/net/gaia_authenticator.h" | 43 #include "chrome/browser/sync/engine/net/gaia_authenticator.h" |
43 #include "chrome/browser/sync/engine/net/server_connection_manager.h" | 44 #include "chrome/browser/sync/engine/net/server_connection_manager.h" |
44 #include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h" | 45 #include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h" |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 } | 383 } |
383 } | 384 } |
384 | 385 |
385 //////////////////////////////////// | 386 //////////////////////////////////// |
386 // BaseNode member definitions. | 387 // BaseNode member definitions. |
387 | 388 |
388 BaseNode::BaseNode() {} | 389 BaseNode::BaseNode() {} |
389 | 390 |
390 BaseNode::~BaseNode() {} | 391 BaseNode::~BaseNode() {} |
391 | 392 |
| 393 std::string BaseNode::GenerateSyncableHash( |
| 394 syncable::ModelType model_type, const std::string& client_tag) { |
| 395 // blank PB with just the extension in it has termination symbol, |
| 396 // handy for delimiter |
| 397 sync_pb::EntitySpecifics serialized_type; |
| 398 syncable::AddDefaultExtensionValue(model_type, &serialized_type); |
| 399 std::string hash_input; |
| 400 serialized_type.AppendToString(&hash_input); |
| 401 hash_input.append(client_tag); |
| 402 return base::SHA1HashString(hash_input); |
| 403 } |
| 404 |
392 int64 BaseNode::GetParentId() const { | 405 int64 BaseNode::GetParentId() const { |
393 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), | 406 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), |
394 GetEntry()->Get(syncable::PARENT_ID)); | 407 GetEntry()->Get(syncable::PARENT_ID)); |
395 } | 408 } |
396 | 409 |
397 int64 BaseNode::GetId() const { | 410 int64 BaseNode::GetId() const { |
398 return GetEntry()->Get(syncable::META_HANDLE); | 411 return GetEntry()->Get(syncable::META_HANDLE); |
399 } | 412 } |
400 | 413 |
401 bool BaseNode::GetIsFolder() const { | 414 bool BaseNode::GetIsFolder() const { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 DCHECK(!entry_) << "Init called twice"; | 562 DCHECK(!entry_) << "Init called twice"; |
550 DCHECK_NE(id, kInvalidId); | 563 DCHECK_NE(id, kInvalidId); |
551 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 564 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
552 syncable::GET_BY_HANDLE, id); | 565 syncable::GET_BY_HANDLE, id); |
553 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); | 566 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); |
554 } | 567 } |
555 | 568 |
556 // Find a node by client tag, and bind this WriteNode to it. | 569 // Find a node by client tag, and bind this WriteNode to it. |
557 // Return true if the write node was found, and was not deleted. | 570 // Return true if the write node was found, and was not deleted. |
558 // Undeleting a deleted node is possible by ClientTag. | 571 // Undeleting a deleted node is possible by ClientTag. |
559 bool WriteNode::InitByClientTagLookup(const std::string& tag) { | 572 bool WriteNode::InitByClientTagLookup(syncable::ModelType model_type, |
| 573 const std::string& tag) { |
560 DCHECK(!entry_) << "Init called twice"; | 574 DCHECK(!entry_) << "Init called twice"; |
561 if (tag.empty()) | 575 if (tag.empty()) |
562 return false; | 576 return false; |
| 577 |
| 578 const std::string hash = GenerateSyncableHash(model_type, tag); |
| 579 |
563 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 580 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
564 syncable::GET_BY_CLIENT_TAG, tag); | 581 syncable::GET_BY_CLIENT_TAG, hash); |
565 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); | 582 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); |
566 } | 583 } |
567 | 584 |
568 void WriteNode::PutModelType(syncable::ModelType model_type) { | 585 void WriteNode::PutModelType(syncable::ModelType model_type) { |
569 // Set an empty specifics of the appropriate datatype. The presence | 586 // Set an empty specifics of the appropriate datatype. The presence |
570 // of the specific extension will identify the model type. | 587 // of the specific extension will identify the model type. |
| 588 DCHECK(GetModelType() == model_type || |
| 589 GetModelType() == syncable::UNSPECIFIED); // Immutable once set. |
| 590 |
571 sync_pb::EntitySpecifics specifics; | 591 sync_pb::EntitySpecifics specifics; |
572 syncable::AddDefaultExtensionValue(model_type, &specifics); | 592 syncable::AddDefaultExtensionValue(model_type, &specifics); |
573 PutSpecificsAndMarkForSyncing(specifics); | 593 PutSpecificsAndMarkForSyncing(specifics); |
574 DCHECK(GetModelType() == model_type); | 594 DCHECK(GetModelType() == model_type); |
575 } | 595 } |
576 | 596 |
577 // Create a new node with default properties, and bind this WriteNode to it. | 597 // Create a new node with default properties, and bind this WriteNode to it. |
578 // Return true on success. | 598 // Return true on success. |
579 bool WriteNode::InitByCreation(syncable::ModelType model_type, | 599 bool WriteNode::InitByCreation(syncable::ModelType model_type, |
580 const BaseNode& parent, | 600 const BaseNode& parent, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 // and bind this WriteNode to it. | 633 // and bind this WriteNode to it. |
614 // Return true on success. If the tag exists in the database, then | 634 // Return true on success. If the tag exists in the database, then |
615 // we will attempt to undelete the node. | 635 // we will attempt to undelete the node. |
616 // TODO(chron): Code datatype into hash tag. | 636 // TODO(chron): Code datatype into hash tag. |
617 // TODO(chron): Is model type ever lost? | 637 // TODO(chron): Is model type ever lost? |
618 bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, | 638 bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, |
619 const BaseNode& parent, | 639 const BaseNode& parent, |
620 const std::string& tag) { | 640 const std::string& tag) { |
621 DCHECK(!entry_) << "Init called twice"; | 641 DCHECK(!entry_) << "Init called twice"; |
622 | 642 |
| 643 const std::string hash = GenerateSyncableHash(model_type, tag); |
| 644 |
623 syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); | 645 syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); |
624 | 646 |
625 // Start out with a dummy name. We expect | 647 // Start out with a dummy name. We expect |
626 // the caller to set a meaningful name after creation. | 648 // the caller to set a meaningful name after creation. |
627 string dummy(kDefaultNameForNewNodes); | 649 string dummy(kDefaultNameForNewNodes); |
628 | 650 |
629 // Check if we have this locally and need to undelete it. | 651 // Check if we have this locally and need to undelete it. |
630 scoped_ptr<syncable::MutableEntry> existing_entry( | 652 scoped_ptr<syncable::MutableEntry> existing_entry( |
631 new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 653 new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
632 syncable::GET_BY_CLIENT_TAG, tag)); | 654 syncable::GET_BY_CLIENT_TAG, hash)); |
633 | 655 |
634 if (existing_entry->good()) { | 656 if (existing_entry->good()) { |
635 if (existing_entry->Get(syncable::IS_DEL)) { | 657 if (existing_entry->Get(syncable::IS_DEL)) { |
636 // Rules for undelete: | 658 // Rules for undelete: |
637 // BASE_VERSION: Must keep the same. | 659 // BASE_VERSION: Must keep the same. |
638 // ID: Essential to keep the same. | 660 // ID: Essential to keep the same. |
639 // META_HANDLE: Must be the same, so we can't "split" the entry. | 661 // META_HANDLE: Must be the same, so we can't "split" the entry. |
640 // IS_DEL: Must be set to false, will cause reindexing. | 662 // IS_DEL: Must be set to false, will cause reindexing. |
641 // This one is weird because IS_DEL is true for "update only" | 663 // This one is weird because IS_DEL is true for "update only" |
642 // items. It should be OK to undelete an update only. | 664 // items. It should be OK to undelete an update only. |
(...skipping 20 matching lines...) Expand all Loading... |
663 return false; | 685 return false; |
664 } | 686 } |
665 } else { | 687 } else { |
666 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), | 688 entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), |
667 syncable::CREATE, parent_id, dummy); | 689 syncable::CREATE, parent_id, dummy); |
668 if (!entry_->good()) { | 690 if (!entry_->good()) { |
669 return false; | 691 return false; |
670 } | 692 } |
671 | 693 |
672 // Only set IS_DIR for new entries. Don't bitflip undeleted ones. | 694 // Only set IS_DIR for new entries. Don't bitflip undeleted ones. |
673 entry_->Put(syncable::UNIQUE_CLIENT_TAG, tag); | 695 entry_->Put(syncable::UNIQUE_CLIENT_TAG, hash); |
674 } | 696 } |
675 | 697 |
676 // We don't support directory and tag combinations. | 698 // We don't support directory and tag combinations. |
677 entry_->Put(syncable::IS_DIR, false); | 699 entry_->Put(syncable::IS_DIR, false); |
678 | 700 |
679 // Will clear specifics data. | 701 // Will clear specifics data. |
680 PutModelType(model_type); | 702 PutModelType(model_type); |
681 | 703 |
682 // Now set the predecessor, which sets IS_UNSYNCED as necessary. | 704 // Now set the predecessor, which sets IS_UNSYNCED as necessary. |
683 PutPredecessor(NULL); | 705 PutPredecessor(NULL); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 return false; | 796 return false; |
775 if (entry_->Get(syncable::IS_DEL)) | 797 if (entry_->Get(syncable::IS_DEL)) |
776 return false; | 798 return false; |
777 syncable::ModelType model_type = GetModelType(); | 799 syncable::ModelType model_type = GetModelType(); |
778 LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || | 800 LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || |
779 model_type == syncable::TOP_LEVEL_FOLDER) | 801 model_type == syncable::TOP_LEVEL_FOLDER) |
780 << "SyncAPI InitByIdLookup referencing unusual object."; | 802 << "SyncAPI InitByIdLookup referencing unusual object."; |
781 return true; | 803 return true; |
782 } | 804 } |
783 | 805 |
784 bool ReadNode::InitByClientTagLookup(const std::string& tag) { | 806 bool ReadNode::InitByClientTagLookup(syncable::ModelType model_type, |
| 807 const std::string& tag) { |
785 DCHECK(!entry_) << "Init called twice"; | 808 DCHECK(!entry_) << "Init called twice"; |
786 if (tag.empty()) | 809 if (tag.empty()) |
787 return false; | 810 return false; |
| 811 |
| 812 const std::string hash = GenerateSyncableHash(model_type, tag); |
| 813 |
788 entry_ = new syncable::Entry(transaction_->GetWrappedTrans(), | 814 entry_ = new syncable::Entry(transaction_->GetWrappedTrans(), |
789 syncable::GET_BY_CLIENT_TAG, tag); | 815 syncable::GET_BY_CLIENT_TAG, hash); |
790 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); | 816 return (entry_->good() && !entry_->Get(syncable::IS_DEL)); |
791 } | 817 } |
792 | 818 |
793 const syncable::Entry* ReadNode::GetEntry() const { | 819 const syncable::Entry* ReadNode::GetEntry() const { |
794 return entry_; | 820 return entry_; |
795 } | 821 } |
796 | 822 |
797 const BaseTransaction* ReadNode::GetTransaction() const { | 823 const BaseTransaction* ReadNode::GetTransaction() const { |
798 return transaction_; | 824 return transaction_; |
799 } | 825 } |
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 BaseTransaction::~BaseTransaction() { | 1864 BaseTransaction::~BaseTransaction() { |
1839 delete lookup_; | 1865 delete lookup_; |
1840 } | 1866 } |
1841 | 1867 |
1842 UserShare* SyncManager::GetUserShare() const { | 1868 UserShare* SyncManager::GetUserShare() const { |
1843 DCHECK(data_->initialized()) << "GetUserShare requires initialization!"; | 1869 DCHECK(data_->initialized()) << "GetUserShare requires initialization!"; |
1844 return data_->GetUserShare(); | 1870 return data_->GetUserShare(); |
1845 } | 1871 } |
1846 | 1872 |
1847 } // namespace sync_api | 1873 } // namespace sync_api |
OLD | NEW |