#ifndef COMPONENTS_COMMERCE_CORE_SUBSCRIPTIONS_SUBSCRIPTIONS_MANAGER_H_
#define COMPONENTS_COMMERCE_CORE_SUBSCRIPTIONS_SUBSCRIPTIONS_MANAGER_H_
#include <queue>
#include <string>
#include <unordered_map>
#include "base/check.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "components/commerce/core/account_checker.h"
#include "components/commerce/core/proto/commerce_subscription_db_content.pb.h"
#include "components/session_proto_db/session_proto_storage.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_change_event.h"
namespace network {
class SharedURLLoaderFactory;
}
namespace commerce {
class SubscriptionsObserver;
class SubscriptionsServerProxy;
class SubscriptionsStorage;
enum class SubscriptionType;
struct CommerceSubscription;
extern const char kTrackResultHistogramName[];
extern const char kUntrackResultHistogramName[];
enum class SubscriptionsRequestStatus {
kSuccess = 0,
kServerParseError = 1,
kServerInternalError = 2,
kStorageError = 3,
kLastSyncFailed = 4,
kInvalidArgument = 5,
kLost = 6,
kNoOp = 7,
kMaxValue = kNoOp
};
using SubscriptionsRequestCallback =
base::OnceCallback<void(SubscriptionsRequestStatus)>;
class SubscriptionsManager : public signin::IdentityManager::Observer {
public:
SubscriptionsManager(
signin::IdentityManager* identity_manager,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
SessionProtoStorage<
commerce_subscription_db::CommerceSubscriptionContentProto>*
subscription_proto_db,
AccountChecker* account_checker,
signin::ConsentLevel consent_level);
SubscriptionsManager(signin::IdentityManager* identity_manager,
std::unique_ptr<SubscriptionsServerProxy> server_proxy,
std::unique_ptr<SubscriptionsStorage> storage,
AccountChecker* account_checker);
SubscriptionsManager(const SubscriptionsManager&) = delete;
SubscriptionsManager& operator=(const SubscriptionsManager&) = delete;
~SubscriptionsManager() override;
void Subscribe(
std::unique_ptr<std::vector<CommerceSubscription>> subscriptions,
base::OnceCallback<void(bool)> callback);
void Unsubscribe(
std::unique_ptr<std::vector<CommerceSubscription>> subscriptions,
base::OnceCallback<void(bool)> callback);
void IsSubscribed(CommerceSubscription subscription,
base::OnceCallback<void(bool)> callback);
bool IsSubscribedFromCache(const CommerceSubscription& subscription);
void GetAllSubscriptions(
SubscriptionType type,
base::OnceCallback<void(std::vector<CommerceSubscription>)> callback);
virtual void CheckTimestampOnBookmarkChange(
int64_t bookmark_subscription_change_time);
void AddObserver(SubscriptionsObserver* observer);
void RemoveObserver(SubscriptionsObserver* observer);
bool GetLastSyncSucceededForTesting();
int64_t GetLastSyncTimeForTesting();
void SetHasRequestRunningForTesting(bool has_request_running);
bool HasPendingRequestsForTesting();
void SetLastRequestStartedTimeForTesting(base::Time time);
protected:
SubscriptionsManager();
private:
enum class AsyncOperation {
kSync = 0,
kSubscribe = 1,
kUnsubscribe = 2,
kLookupOne = 3,
kGetAll = 4,
kCheckOnBookmarkChange = 5,
};
struct Request {
Request(AsyncOperation operation, base::OnceCallback<void()> callback);
Request(const Request&) = delete;
Request& operator=(const Request&) = delete;
Request(Request&&);
Request& operator=(Request&&) = default;
~Request();
AsyncOperation operation;
base::OnceCallback<void()> callback;
};
void SyncSubscriptions();
void CheckAndProcessRequest();
void SyncIfNeeded();
void OnRequestCompletion();
void UpdateSyncStates(bool sync_succeeded);
void HandleSync();
void OnSyncStatusFetched(SubscriptionsRequestStatus result);
void HandleSubscribe(
std::unique_ptr<std::vector<CommerceSubscription>> subscriptions,
base::OnceCallback<void(bool)> callback);
void OnSubscribeStatusFetched(
std::vector<CommerceSubscription> notified_subscriptions,
base::OnceCallback<void(bool)> callback,
SubscriptionsRequestStatus result);
void OnIncomingSubscriptionsFilteredForSubscribe(
SubscriptionType type,
SubscriptionsRequestCallback callback,
std::unique_ptr<std::vector<CommerceSubscription>> unique_subscriptions);
void HandleUnsubscribe(
std::unique_ptr<std::vector<CommerceSubscription>> subscriptions,
base::OnceCallback<void(bool)> callback);
void OnUnsubscribeStatusFetched(
std::vector<CommerceSubscription> notified_subscriptions,
base::OnceCallback<void(bool)> callback,
SubscriptionsRequestStatus result);
void OnIncomingSubscriptionsFilteredForUnsubscribe(
SubscriptionType type,
SubscriptionsRequestCallback callback,
std::unique_ptr<std::vector<CommerceSubscription>> unique_subscriptions);
void GetRemoteSubscriptionsAndUpdateStorage(
SubscriptionType type,
SubscriptionsRequestCallback callback);
void HandleGetSubscriptionsResponse(
SubscriptionType type,
SubscriptionsRequestCallback callback,
SubscriptionsRequestStatus status,
std::unique_ptr<std::vector<CommerceSubscription>> remote_subscriptions);
void HandleManageSubscriptionsResponse(
SubscriptionType type,
SubscriptionsRequestCallback callback,
SubscriptionsRequestStatus status,
std::unique_ptr<std::vector<CommerceSubscription>> remote_subscriptions);
void HandleLookup(CommerceSubscription subscription,
base::OnceCallback<void(bool)> callback);
void OnLookupResult(base::OnceCallback<void(bool)> callback,
bool is_subscribed);
void HandleGetAll(
SubscriptionType type,
base::OnceCallback<void(std::vector<CommerceSubscription>)> callback);
void OnGetAllResult(
base::OnceCallback<void(std::vector<CommerceSubscription>)> callback,
std::unique_ptr<std::vector<CommerceSubscription>> subscriptions);
void HandleCheckTimestampOnBookmarkChange(
int64_t bookmark_subscription_change_time);
void HandleGetSubscriptionsResponseOnBookmarkChange(
SubscriptionsRequestStatus status,
std::unique_ptr<std::vector<CommerceSubscription>> remote_subscriptions);
void OnStorageUpdatedOnBookmarkChange(
SubscriptionsRequestStatus status,
std::vector<CommerceSubscription> added_subs,
std::vector<CommerceSubscription> removed_subs);
void OnSubscribe(const std::vector<CommerceSubscription>& subscriptions,
bool succeeded);
void OnUnsubscribe(const std::vector<CommerceSubscription>& subscriptions,
bool succeeded);
void OnPrimaryAccountChanged(
const signin::PrimaryAccountChangeEvent& event_details) override;
bool HasRequestRunning();
std::queue<Request> pending_requests_;
bool last_sync_succeeded_ = false;
int64_t last_sync_time_{0L};
bool has_request_running_ = false;
base::Time last_request_started_time_ = base::Time();
AsyncOperation last_request_operation_;
base::ScopedObservation<signin::IdentityManager,
signin::IdentityManager::Observer>
scoped_identity_manager_observation_{this};
std::unique_ptr<SubscriptionsServerProxy> server_proxy_;
std::unique_ptr<SubscriptionsStorage> storage_;
raw_ptr<AccountChecker> account_checker_;
base::ObserverList<SubscriptionsObserver>::Unchecked observers_;
base::WeakPtrFactory<SubscriptionsManager> weak_ptr_factory_{this};
};
}
#endif