chromium/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h

// 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.

#ifndef CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_
#define CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_

#include <memory>
#include <optional>
#include <set>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/sync/model/data_type_store.h"
#include "components/sync/model/data_type_sync_bridge.h"
#include "components/sync/model/entity_change.h"
#include "components/sync/model/model_error.h"
#include "url/gurl.h"

namespace syncer {
class DataTypeLocalChangeProcessor;
struct EntityData;
class MetadataChangeList;
}  // namespace syncer

namespace ash::printing::oauth2 {

// This class is the bridge responsible for the synchronization of the list of
// trusted Authorization Servers between the user's profile and this client.
class ProfileAuthServersSyncBridge : public syncer::DataTypeSyncBridge {
 public:
  class Observer {
   public:
    // This method is called when the sync bridge is ready to process calls to
    // AddAuthorizationServer(). This method is called only once.
    virtual void OnProfileAuthorizationServersInitialized() = 0;

    // This method is called when new data from the user's profile is loaded
    // (either from the local store or from the sync server). This includes
    // loading of the initial list of servers as well as any changes that occur
    // on other clients. Each change reported by this method is represented by
    // two disjoint sets of URIs:
    //  * `added` - the set of URIs added to the list of trusted servers; and
    //  * `deleted` - the set of URIs removed from the list.
    virtual void OnProfileAuthorizationServersUpdate(
        std::set<GURL> added,
        std::set<GURL> deleted) = 0;

   protected:
    virtual ~Observer() = default;
  };

  // Factory function. |observer| must not be nullptr.
  static std::unique_ptr<ProfileAuthServersSyncBridge> Create(
      Observer* observer,
      syncer::OnceDataTypeStoreFactory store_factory);

  // Factory function for testing. |observer| and |change_processor| must not be
  // nullptr.
  static std::unique_ptr<ProfileAuthServersSyncBridge> CreateForTesting(
      Observer* observer,
      std::unique_ptr<syncer::DataTypeLocalChangeProcessor> change_processor,
      syncer::OnceDataTypeStoreFactory store_factory);

  ProfileAuthServersSyncBridge(const ProfileAuthServersSyncBridge&) = delete;
  ProfileAuthServersSyncBridge& operator=(const ProfileAuthServersSyncBridge&) =
      delete;

  ~ProfileAuthServersSyncBridge() override;

  // Returns true <=> the callback OnProfileAuthorizationServersInitialized()
  // was called. It means that the bridge can accept calls to
  // AddAuthorizationServer().
  bool IsInitialized() const { return initialization_completed_; }

  // This method must be called when a new Authorization Server is added to the
  // list of trusted Authorization Servers on this client. The new record will
  // be saved in the user's profile. This method DOES NOT trigger a call to the
  // Observer's method OnProfileAuthorizationServersUpdate() on this client and
  // the added record WILL NOT be included in the changes reported by any call
  // to OnProfileAuthorizationServersUpdate() on this client. This method MUST
  // NOT be called before the Observer receives the call to
  // OnProfileAuthorizationServersInitialized().
  void AddAuthorizationServer(const GURL& server);

  // Implementation of DataTypeSyncBridge interface. For internal use only.
  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
      override;
  std::optional<syncer::ModelError> MergeFullSyncData(
      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
      syncer::EntityChangeList entity_data) override;
  std::optional<syncer::ModelError> ApplyIncrementalSyncChanges(
      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
      syncer::EntityChangeList entity_changes) override;
  std::unique_ptr<syncer::DataBatch> GetDataForCommit(
      StorageKeyList storage_keys) override;
  std::unique_ptr<syncer::DataBatch> GetAllDataForDebugging() override;
  std::string GetClientTag(const syncer::EntityData& entity_data) override;
  std::string GetStorageKey(const syncer::EntityData& entity_data) override;

 private:
  ProfileAuthServersSyncBridge(
      std::unique_ptr<syncer::DataTypeLocalChangeProcessor> change_processor,
      syncer::OnceDataTypeStoreFactory store_factory,
      Observer* observer);

  // Callback for DataTypeStore initialization.
  void OnStoreCreated(const std::optional<syncer::ModelError>& error,
                      std::unique_ptr<syncer::DataTypeStore> store);

  // Callback from the store when all data are loaded.
  void OnReadAllData(
      const std::optional<syncer::ModelError>& error,
      std::unique_ptr<syncer::DataTypeStore::RecordList> record_list);

  // Callback from the store when all metadata are loaded.
  void OnReadAllMetadata(const std::optional<syncer::ModelError>& error,
                         std::unique_ptr<syncer::MetadataBatch> metadata_batch);

  // Callback to handle commit errors.
  void OnCommit(const std::optional<syncer::ModelError>& error);

  // Notifies the observer about changes.
  void NotifyObserver(const std::set<std::string>& added,
                      const std::set<std::string>& deleted);

  // This is set to true when the object is ready to use. Use the method
  // IsInitialized() or the callback from the Observer to check this.
  bool initialization_completed_ = false;

  // The current trusted list of Authorization Servers URIs.
  std::set<std::string> servers_uris_;

  // The local store.
  std::unique_ptr<syncer::DataTypeStore> store_;

  raw_ptr<Observer> const observer_;
  base::WeakPtrFactory<ProfileAuthServersSyncBridge> weak_ptr_factory_{this};
};

}  // namespace ash::printing::oauth2

#endif  // CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_