910e62b5创建于 1月15日历史提交
// 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;
  bool IsEntityDataValid(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_