blob: 95bfc13407b288228cdcd3e7ef78dc7f13904861 [file] [log] [blame]
// Copyright 2019 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 "chromeos/components/sync_wifi/wifi_configuration_bridge.h"
#include <algorithm>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "chromeos/components/sync_wifi/synced_network_updater.h"
#include "components/sync/model/entity_change.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/protocol/model_type_state.pb.h"
namespace sync_wifi {
namespace {
std::unique_ptr<syncer::EntityData> GenerateWifiEntityData(
const sync_pb::WifiConfigurationSpecificsData& data) {
auto entity_data = std::make_unique<syncer::EntityData>();
entity_data->specifics.mutable_wifi_configuration()
->mutable_client_only_encrypted_data()
->CopyFrom(data);
entity_data->name = data.ssid();
return entity_data;
}
} // namespace
WifiConfigurationBridge::WifiConfigurationBridge(
SyncedNetworkUpdater* synced_network_updater,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
syncer::OnceModelTypeStoreFactory create_store_callback)
: ModelTypeSyncBridge(std::move(change_processor)),
synced_network_updater_(synced_network_updater) {
std::move(create_store_callback)
.Run(syncer::WIFI_CONFIGURATIONS,
base::BindOnce(&WifiConfigurationBridge::OnStoreCreated,
weak_ptr_factory_.GetWeakPtr()));
}
WifiConfigurationBridge::~WifiConfigurationBridge() {}
std::unique_ptr<syncer::MetadataChangeList>
WifiConfigurationBridge::CreateMetadataChangeList() {
return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
}
base::Optional<syncer::ModelError> WifiConfigurationBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK(entries_.empty());
return ApplySyncChanges(std::move(metadata_change_list),
std::move(entity_data));
}
base::Optional<syncer::ModelError> WifiConfigurationBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch =
store_->CreateWriteBatch();
for (std::unique_ptr<syncer::EntityChange>& change : entity_changes) {
if (change->type() == syncer::EntityChange::ACTION_DELETE) {
auto it = entries_.find(change->storage_key());
if (it != entries_.end()) {
entries_.erase(it);
batch->DeleteData(change->storage_key());
synced_network_updater_->RemoveNetwork(change->storage_key());
}
continue;
}
auto& specifics = change->data()
.specifics.wifi_configuration()
.client_only_encrypted_data();
synced_network_updater_->AddOrUpdateNetwork(specifics);
batch->WriteData(change->storage_key(), specifics.SerializeAsString());
entries_[change->storage_key()] = std::move(specifics);
}
batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
Commit(std::move(batch));
return base::nullopt;
}
void WifiConfigurationBridge::GetData(StorageKeyList storage_keys,
DataCallback callback) {
auto batch = std::make_unique<syncer::MutableDataBatch>();
for (const std::string& id : storage_keys) {
auto it = entries_.find(id);
if (it == entries_.end()) {
continue;
}
batch->Put(id, GenerateWifiEntityData(it->second));
}
std::move(callback).Run(std::move(batch));
}
void WifiConfigurationBridge::GetAllDataForDebugging(DataCallback callback) {
auto batch = std::make_unique<syncer::MutableDataBatch>();
for (const auto& entry : entries_) {
batch->Put(entry.first, GenerateWifiEntityData(entry.second));
}
std::move(callback).Run(std::move(batch));
}
std::string WifiConfigurationBridge::GetClientTag(
const syncer::EntityData& entity_data) {
return GetStorageKey(entity_data);
}
std::string WifiConfigurationBridge::GetStorageKey(
const syncer::EntityData& entity_data) {
return entity_data.specifics.wifi_configuration()
.client_only_encrypted_data()
.ssid();
}
void WifiConfigurationBridge::OnStoreCreated(
const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store) {
if (error) {
change_processor()->ReportError(*error);
return;
}
store_ = std::move(store);
store_->ReadAllData(base::BindOnce(&WifiConfigurationBridge::OnReadAllData,
weak_ptr_factory_.GetWeakPtr()));
}
void WifiConfigurationBridge::OnReadAllData(
const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> records) {
if (error) {
change_processor()->ReportError(*error);
return;
}
for (syncer::ModelTypeStore::Record& record : *records) {
sync_pb::WifiConfigurationSpecificsData data;
if (record.id.empty() || !data.ParseFromString(record.value)) {
DVLOG(1) << "Unable to parse proto for entry with key: " << record.id;
continue;
}
entries_[record.id] = std::move(data);
}
store_->ReadAllMetadata(
base::BindOnce(&WifiConfigurationBridge::OnReadAllMetadata,
weak_ptr_factory_.GetWeakPtr()));
}
void WifiConfigurationBridge::OnReadAllMetadata(
const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
if (error) {
change_processor()->ReportError(*error);
return;
}
change_processor()->ModelReadyToSync(std::move(metadata_batch));
}
void WifiConfigurationBridge::OnCommit(
const base::Optional<syncer::ModelError>& error) {
if (error)
change_processor()->ReportError(*error);
}
void WifiConfigurationBridge::Commit(
std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch) {
store_->CommitWriteBatch(std::move(batch),
base::BindOnce(&WifiConfigurationBridge::OnCommit,
weak_ptr_factory_.GetWeakPtr()));
}
std::vector<std::string> WifiConfigurationBridge::GetAllSsidsForTesting() {
std::vector<std::string> ssids;
for (const auto& entry : entries_)
ssids.push_back(entry.second.ssid());
return ssids;
}
} // namespace sync_wifi