blob: bb87af3b347958f3f207624a6c14a6bf376d6820 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SYNC_BRIDGE_H_
#define CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SYNC_BRIDGE_H_
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include "base/containers/flat_set.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "components/sync/model/conflict_resolution.h"
#include "components/sync/model/data_type_store.h"
#include "components/sync/model/data_type_store_base.h"
#include "components/sync/model/data_type_store_with_in_memory_cache.h"
#include "components/sync/model/data_type_sync_bridge.h"
#include "components/sync/protocol/cookie_specifics.pb.h"
namespace syncer {
class DataTypeLocalChangeProcessor;
struct EntityData;
class MetadataBatch;
class MetadataChangeList;
class ModelError;
} // namespace syncer
namespace net {
class CanonicalCookie;
} // namespace net
namespace ash::floating_sso {
class FloatingSsoSyncBridge : public syncer::DataTypeSyncBridge {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnCookiesAddedOrUpdatedRemotely(
const std::vector<net::CanonicalCookie>& cookies) = 0;
virtual void OnCookiesRemovedRemotely(
const std::vector<net::CanonicalCookie>& cookies) = 0;
};
using CookieSpecificsEntries =
std::map<std::string, sync_pb::CookieSpecifics>;
explicit FloatingSsoSyncBridge(
std::unique_ptr<syncer::DataTypeLocalChangeProcessor> change_processor,
syncer::OnceDataTypeStoreFactory create_store_callback);
~FloatingSsoSyncBridge() override;
// syncer::DataTypeSyncBridge:
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
std::optional<syncer::ModelError> MergeFullSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList remote_entities) override;
std::optional<syncer::ModelError> ApplyIncrementalSyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
std::string GetStorageKey(
const syncer::EntityData& entity_data) const override;
std::string GetClientTag(
const syncer::EntityData& entity_data) const override;
std::unique_ptr<syncer::DataBatch> GetDataForCommit(
StorageKeyList storage_keys) override;
std::unique_ptr<syncer::DataBatch> GetAllDataForDebugging() override;
syncer::ConflictResolution ResolveConflict(
const std::string& storage_key,
const syncer::EntityData& remote_data) const override;
// Methods to notify Sync about local cookie changes on this client.
void AddOrUpdateCookie(const net::CanonicalCookie& cookie);
void DeleteCookie(const net::CanonicalCookie& cookie);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// `callback` will be run immediately if `MergeFullSyncData` was already
// called.
void SetOnMergeFullSyncDataCallback(base::OnceClosure callback);
// Cookie corresponding to `storage_key` will not be overridden by remote
// cookie on initial merge of Sync data.
void AddToLocallyPreferredCookies(const std::string& storage_key);
// Assumes that the `store_` is initialized.
const CookieSpecificsEntries& CookieSpecificsInStore() const;
bool IsInitialDataReadFinishedForTest() const;
void SetOnStoreCommitCallbackForTest(base::RepeatingClosure callback);
private:
using StoreWithCache =
syncer::DataTypeStoreWithInMemoryCache<sync_pb::CookieSpecifics>;
void OnStoreCreated(const std::optional<syncer::ModelError>& error,
std::unique_ptr<StoreWithCache> store,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
void ProcessQueuedCookies();
void OnStoreCommit(const std::optional<syncer::ModelError>& error);
void CommitToStore(std::unique_ptr<StoreWithCache::WriteBatch> batch);
bool IsCookieInStore(const std::string& storage_key) const;
void OnMergeFullSyncDataFinished();
void DeleteCookieWithKey(const std::string& storage_key);
// Whether we finished reading data and metadata from disk on initial bridge
// creation.
bool is_initial_data_read_finished_ = false;
base::RepeatingClosure on_store_commit_callback_for_test_;
// Whether `MergeFullSyncData()` was executed.
bool merge_full_sync_data_finished_ = false;
base::OnceClosure on_merge_full_sync_data_callback_;
// Reads and writes data from/to disk, maintains an in-memory copy of the
// data.
std::unique_ptr<StoreWithCache> store_;
// Used to store cookies to be added/deleted while the store or change
// processor are not ready.
std::map<std::string, net::CanonicalCookie> deferred_cookie_additions_;
std::set<std::string> deferred_cookie_deletions_;
// Storage keys of cookies for which we should always prefer local version
// during conflict resolution.
base::flat_set<std::string> keep_local_cookie_keys_;
// Observers which are notified about all incoming remote changes.
base::ObserverList<Observer> observers_;
base::WeakPtrFactory<FloatingSsoSyncBridge> weak_ptr_factory_{this};
};
} // namespace ash::floating_sso
#endif // CHROME_BROWSER_ASH_FLOATING_SSO_FLOATING_SSO_SYNC_BRIDGE_H_