| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/sync_bookmarks/synced_bookmark_tracker.h" |
| |
| #include <utility> |
| |
| #include "base/base64.h" |
| #include "base/sha1.h" |
| #include "components/bookmarks/browser/bookmark_node.h" |
| #include "components/sync/base/time.h" |
| #include "components/sync/model/entity_data.h" |
| |
| namespace sync_bookmarks { |
| |
| namespace { |
| |
| void HashSpecifics(const sync_pb::EntitySpecifics& specifics, |
| std::string* hash) { |
| DCHECK_GT(specifics.ByteSize(), 0); |
| base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()), hash); |
| } |
| |
| } // namespace |
| |
| SyncedBookmarkTracker::Entity::Entity( |
| const bookmarks::BookmarkNode* bookmark_node, |
| std::unique_ptr<sync_pb::EntityMetadata> metadata) |
| : bookmark_node_(bookmark_node), metadata_(std::move(metadata)) { |
| if (bookmark_node) { |
| DCHECK(!metadata_->is_deleted()); |
| } else { |
| DCHECK(metadata_->is_deleted()); |
| } |
| } |
| |
| SyncedBookmarkTracker::Entity::~Entity() = default; |
| |
| bool SyncedBookmarkTracker::Entity::MatchesData( |
| const syncer::EntityData& data) const { |
| if (metadata_->is_deleted() || data.is_deleted()) { |
| // In case of deletion, no need to check the specifics. |
| return metadata_->is_deleted() == data.is_deleted(); |
| } |
| return MatchesSpecificsHash(data.specifics); |
| } |
| |
| bool SyncedBookmarkTracker::Entity::MatchesSpecificsHash( |
| const sync_pb::EntitySpecifics& specifics) const { |
| DCHECK(!metadata_->is_deleted()); |
| DCHECK_GT(specifics.ByteSize(), 0); |
| std::string hash; |
| HashSpecifics(specifics, &hash); |
| return hash == metadata_->specifics_hash(); |
| } |
| |
| bool SyncedBookmarkTracker::Entity::IsUnsynced() const { |
| return metadata_->sequence_number() > metadata_->acked_sequence_number(); |
| } |
| |
| SyncedBookmarkTracker::SyncedBookmarkTracker( |
| std::vector<NodeMetadataPair> nodes_metadata, |
| std::unique_ptr<sync_pb::ModelTypeState> model_type_state) |
| : model_type_state_(std::move(model_type_state)) { |
| for (NodeMetadataPair& node_metadata : nodes_metadata) { |
| const std::string& sync_id = node_metadata.second->server_id(); |
| sync_id_to_entities_map_[sync_id] = std::make_unique<Entity>( |
| node_metadata.first, std::move(node_metadata.second)); |
| } |
| } |
| |
| SyncedBookmarkTracker::~SyncedBookmarkTracker() = default; |
| |
| const SyncedBookmarkTracker::Entity* SyncedBookmarkTracker::GetEntityForSyncId( |
| const std::string& sync_id) const { |
| auto it = sync_id_to_entities_map_.find(sync_id); |
| return it != sync_id_to_entities_map_.end() ? it->second.get() : nullptr; |
| } |
| |
| void SyncedBookmarkTracker::Add(const std::string& sync_id, |
| const bookmarks::BookmarkNode* bookmark_node, |
| int64_t server_version, |
| base::Time creation_time, |
| const sync_pb::EntitySpecifics& specifics) { |
| DCHECK_GT(specifics.ByteSize(), 0); |
| auto metadata = std::make_unique<sync_pb::EntityMetadata>(); |
| metadata->set_is_deleted(false); |
| metadata->set_server_id(sync_id); |
| metadata->set_server_version(server_version); |
| metadata->set_creation_time(syncer::TimeToProtoTime(creation_time)); |
| HashSpecifics(specifics, metadata->mutable_specifics_hash()); |
| sync_id_to_entities_map_[sync_id] = |
| std::make_unique<Entity>(bookmark_node, std::move(metadata)); |
| } |
| |
| void SyncedBookmarkTracker::Update(const std::string& sync_id, |
| int64_t server_version, |
| base::Time modification_time, |
| const sync_pb::EntitySpecifics& specifics) { |
| DCHECK_GT(specifics.ByteSize(), 0); |
| auto it = sync_id_to_entities_map_.find(sync_id); |
| Entity* entity = it->second.get(); |
| DCHECK(entity); |
| entity->metadata()->set_server_id(sync_id); |
| entity->metadata()->set_server_version(server_version); |
| entity->metadata()->set_modification_time( |
| syncer::TimeToProtoTime(modification_time)); |
| HashSpecifics(specifics, entity->metadata()->mutable_specifics_hash()); |
| } |
| |
| void SyncedBookmarkTracker::Remove(const std::string& sync_id) { |
| sync_id_to_entities_map_.erase(sync_id); |
| } |
| |
| sync_pb::BookmarkModelMetadata |
| SyncedBookmarkTracker::BuildBookmarkModelMetadata() const { |
| sync_pb::BookmarkModelMetadata model_metadata; |
| for (const std::pair<const std::string, std::unique_ptr<Entity>>& pair : |
| sync_id_to_entities_map_) { |
| sync_pb::BookmarkMetadata* bookmark_metadata = |
| model_metadata.add_bookmarks_metadata(); |
| if (pair.second->bookmark_node() != nullptr) { |
| bookmark_metadata->set_id(pair.second->bookmark_node()->id()); |
| } |
| *bookmark_metadata->mutable_metadata() = *pair.second->metadata(); |
| } |
| *model_metadata.mutable_model_type_state() = *model_type_state_; |
| return model_metadata; |
| } |
| |
| std::size_t SyncedBookmarkTracker::TrackedEntitiesCountForTest() const { |
| return sync_id_to_entities_map_.size(); |
| } |
| |
| } // namespace sync_bookmarks |