blob: 2f4b7b1b000798f35d4f0975e5c6564d75fc9045 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/power_bookmarks/storage/power_bookmark_sync_bridge.h"
#include "components/power_bookmarks/common/power.h"
#include "components/power_bookmarks/storage/power_bookmark_sync_metadata_database.h"
#include "components/sync/model/in_memory_metadata_change_list.h"
#include "components/sync/model/metadata_batch.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model/sync_metadata_store_change_list.h"
namespace power_bookmarks {
namespace {
void WritePowersToSyncData(const std::vector<std::unique_ptr<Power>>& powers,
PowerBookmarkSyncBridge::DataCallback callback) {
auto batch = std::make_unique<syncer::MutableDataBatch>();
for (const auto& power : powers) {
std::string guid = power->guid_string();
auto entity_data = std::make_unique<syncer::EntityData>();
entity_data->name = guid;
power->ToPowerBookmarkSpecifics(
entity_data->specifics.mutable_power_bookmark());
batch->Put(guid, std::move(entity_data));
}
std::move(callback).Run(std::move(batch));
}
} // namespace
PowerBookmarkSyncBridge::PowerBookmarkSyncBridge(
PowerBookmarkSyncMetadataDatabase* meta_db,
Delegate* delegate,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor)
: syncer::ModelTypeSyncBridge(std::move(change_processor)),
meta_db_(meta_db),
delegate_(delegate) {}
PowerBookmarkSyncBridge::~PowerBookmarkSyncBridge() = default;
void PowerBookmarkSyncBridge::Init() {
std::unique_ptr<syncer::MetadataBatch> batch = meta_db_->GetAllSyncMetadata();
if (batch) {
initialized_ = true;
change_processor()->ModelReadyToSync(std::move(batch));
} else {
change_processor()->ReportError({FROM_HERE, "Failed to load metadata"});
}
}
std::unique_ptr<syncer::MetadataChangeList>
PowerBookmarkSyncBridge::CreateMetadataChangeList() {
return std::make_unique<syncer::InMemoryMetadataChangeList>();
}
std::optional<syncer::ModelError> PowerBookmarkSyncBridge::MergeFullSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
return ApplyChanges(std::move(metadata_change_list), entity_changes,
/*is_initial_merge=*/true);
}
std::optional<syncer::ModelError>
PowerBookmarkSyncBridge::ApplyIncrementalSyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
return ApplyChanges(std::move(metadata_change_list), entity_changes,
/*is_initial_merge=*/false);
}
std::string PowerBookmarkSyncBridge::GetStorageKey(
const syncer::EntityData& entity_data) {
return entity_data.specifics.power_bookmark().guid();
}
std::string PowerBookmarkSyncBridge::GetClientTag(
const syncer::EntityData& entity_data) {
return GetStorageKey(entity_data);
}
void PowerBookmarkSyncBridge::GetData(StorageKeyList storage_keys,
DataCallback callback) {
WritePowersToSyncData(delegate_->GetPowersForGUIDs(storage_keys),
std::move(callback));
}
void PowerBookmarkSyncBridge::GetAllDataForDebugging(DataCallback callback) {
WritePowersToSyncData(delegate_->GetAllPowers(), std::move(callback));
}
void PowerBookmarkSyncBridge::SendPowerToSync(const Power& power) {
if (!change_processor()->IsTrackingMetadata()) {
return;
}
auto entity_data = std::make_unique<syncer::EntityData>();
power.ToPowerBookmarkSpecifics(
entity_data->specifics.mutable_power_bookmark());
entity_data->name = power.guid_string();
change_processor()->Put(power.guid_string(), std::move(entity_data),
CreateMetadataChangeListInTransaction().get());
}
void PowerBookmarkSyncBridge::NotifySyncForDeletion(const std::string& guid) {
if (!change_processor()->IsTrackingMetadata()) {
return;
}
change_processor()->Delete(guid,
CreateMetadataChangeListInTransaction().get());
}
std::unique_ptr<syncer::MetadataChangeList>
PowerBookmarkSyncBridge::CreateMetadataChangeListInTransaction() {
// TODO(crbug.com/40247772): Add a DCHECK to make sure this is called inside a
// transaction.
return std::make_unique<syncer::SyncMetadataStoreChangeList>(
meta_db_, syncer::POWER_BOOKMARK,
base::BindRepeating(&syncer::ModelTypeChangeProcessor::ReportError,
change_processor()->GetWeakPtr()));
}
std::optional<syncer::ModelError> PowerBookmarkSyncBridge::ApplyChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList& entity_changes,
bool is_initial_merge) {
std::set<std::string> synced_entries;
std::unique_ptr<Transaction> transaction = delegate_->BeginTransaction();
if (!transaction) {
return syncer::ModelError(
FROM_HERE, "Failed to begin transaction for PowerBookmarks.");
}
for (const std::unique_ptr<syncer::EntityChange>& change : entity_changes) {
switch (change->type()) {
case syncer::EntityChange::ACTION_ADD:
case syncer::EntityChange::ACTION_UPDATE:
if (!delegate_->CreateOrMergePowerFromSync(*std::make_unique<Power>(
change->data().specifics.power_bookmark()))) {
return syncer::ModelError(
FROM_HERE, "Failed to merge local powers for PowerBookmarks.");
}
if (is_initial_merge) {
synced_entries.insert(change->storage_key());
}
break;
case syncer::EntityChange::ACTION_DELETE:
if (!delegate_->DeletePowerFromSync(change->storage_key())) {
return syncer::ModelError(
FROM_HERE, "Failed to delete local powers for PowerBookmarks.");
}
break;
}
}
if (is_initial_merge) {
// Send local only powers to sync.
for (const std::unique_ptr<Power>& power : delegate_->GetAllPowers()) {
if (synced_entries.count(power->guid_string()) == 0) {
SendPowerToSync(*power);
}
}
}
std::unique_ptr<syncer::MetadataChangeList> power_bookmark_change_list =
CreateMetadataChangeListInTransaction();
static_cast<syncer::InMemoryMetadataChangeList*>(metadata_change_list.get())
->TransferChangesTo(power_bookmark_change_list.get());
if (!transaction->Commit()) {
return syncer::ModelError(
FROM_HERE, "Failed to commit transaction for PowerBookmarks.");
}
delegate_->NotifyPowersChanged();
return {};
}
void PowerBookmarkSyncBridge::ReportError(const syncer::ModelError& error) {
change_processor()->ReportError(error);
}
} // namespace power_bookmarks