#ifndef ASH_BIRCH_BIRCH_MODEL_H_
#define ASH_BIRCH_BIRCH_MODEL_H_
#include <map>
#include <optional>
#include <vector>
#include "ash/ash_export.h"
#include "ash/birch/birch_client.h"
#include "ash/birch/birch_coral_item.h"
#include "ash/birch/birch_coral_provider.h"
#include "ash/birch/birch_item.h"
#include "ash/public/cpp/session/session_observer.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/geolocation/system_location_provider.h"
#include "components/prefs/pref_change_registrar.h"
class PrefRegistrySimple;
namespace ash {
class BirchDataProvider;
class BirchIconCache;
class BirchItemRemover;
class CoralItemRemover;
class ASH_EXPORT BirchModel : public SessionObserver,
public SystemLocationProvider::Observer,
public BirchCoralProvider::Observer {
public:
using LostMediaDataChangedCallback =
base::RepeatingCallback<void(std::unique_ptr<BirchItem>)>;
class Observer : public base::CheckedObserver {
public:
~Observer() override = default;
virtual void OnBirchClientSet() = 0;
};
BirchModel();
BirchModel(const BirchModel&) = delete;
BirchModel& operator=(const BirchModel&) = delete;
~BirchModel() override;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
void RequestBirchDataFetch(bool is_post_login, base::OnceClosure callback);
void SetCalendarItems(const std::vector<BirchCalendarItem>& calendar_items);
void SetAttachmentItems(
const std::vector<BirchAttachmentItem>& attachment_items);
void SetFileSuggestItems(
const std::vector<BirchFileItem>& file_suggest_items);
void SetRecentTabItems(const std::vector<BirchTabItem>& recent_tab_items);
void SetLastActiveItems(const std::vector<BirchLastActiveItem>& items);
void SetMostVisitedItems(const std::vector<BirchMostVisitedItem>& items);
void SetSelfShareItems(
const std::vector<BirchSelfShareItem>& self_share_items);
void SetLostMediaItems(const std::vector<BirchLostMediaItem>& items);
void SetReleaseNotesItems(
const std::vector<BirchReleaseNotesItem>& release_notes_items);
void SetWeatherItems(const std::vector<BirchWeatherItem>& weather_items);
void SetCoralItems(const std::vector<BirchCoralItem>& coral_items);
void SetClientAndInit(BirchClient* client);
BirchClient* birch_client() { return birch_client_; }
BirchIconCache* icon_cache() { return icon_cache_.get(); }
const std::vector<BirchCalendarItem>& GetCalendarItemsForTest() const {
return calendar_data_.items;
}
const std::vector<BirchAttachmentItem>& GetAttachmentItemsForTest() const {
return attachment_data_.items;
}
const std::vector<BirchFileItem>& GetFileSuggestItemsForTest() const {
return file_suggest_data_.items;
}
const std::vector<BirchTabItem>& GetTabsForTest() const {
return recent_tab_data_.items;
}
const std::vector<BirchLastActiveItem>& GetLastActiveItemsForTest() const {
return last_active_data_.items;
}
const std::vector<BirchMostVisitedItem>& GetMostVisitedItemsForTest() const {
return most_visited_data_.items;
}
std::vector<BirchSelfShareItem>& GetSelfShareItemsForTest() {
return self_share_data_.items;
}
std::vector<BirchLostMediaItem>& GetLostMediaItemsForTest() {
return lost_media_data_.items;
}
const std::vector<BirchReleaseNotesItem>& GetReleaseNotesItemsForTest()
const {
return release_notes_data_.items;
}
const std::vector<BirchWeatherItem>& GetWeatherForTest() const {
return weather_data_.items;
}
std::vector<BirchCoralItem>& GetCoralItemsForTest() {
return coral_data_.items;
}
BirchItemRemover* GetItemRemoverForTest() { return item_remover_.get(); }
CoralItemRemover* GetCoralItemRemoverForTest();
std::vector<std::unique_ptr<BirchItem>> GetAllItems();
std::vector<std::unique_ptr<BirchItem>> GetItemsForDisplay();
bool IsDataFresh();
void RemoveItem(BirchItem* item);
void SetLostMediaDataChangedCallback(LostMediaDataChangedCallback callback);
void ResetLostMediaDataChangedCallback();
void OnActiveUserSessionChanged(const AccountId& account_id) override;
void OnGeolocationPermissionChanged(bool enabled) override;
void OnCoralGroupRemoved(const base::Token& group_id) override;
void OnCoralGroupTitleUpdated(const base::Token& group_id,
const std::string& title) override;
BirchDataProvider* GetWeatherProviderForTest();
void OverrideWeatherProviderForTest(
std::unique_ptr<BirchDataProvider> weather_provider);
BirchDataProvider* GetCoralProviderForTest();
void OverrideCoralProviderForTest(
std::unique_ptr<BirchDataProvider> coral_provider);
void OverrideClockForTest(base::Clock* clock);
void SetDataFetchCallbackForTest(base::OnceClosure callback);
private:
friend class BirchModelTest;
struct PendingRequest {
PendingRequest();
~PendingRequest();
base::OnceClosure callback;
std::unique_ptr<base::OneShotTimer> timer;
};
template <typename T>
struct DataTypeInfo {
DataTypeInfo(const std::string& pref_name,
const std::string& metric_suffix);
~DataTypeInfo();
bool fetch_in_progress = false;
base::Time fetch_start_time;
std::vector<T> items;
bool is_fresh = false;
std::string pref_name;
std::string metric_suffix;
std::optional<PendingRequest> update_request;
};
template <typename T>
void SetItems(DataTypeInfo<T>& data_info, const std::vector<T>& items);
void HandleRequestTimeout(size_t request_id);
void HandleLostMediaUpdateRequest();
void MaybeRespondToDataFetchRequest();
base::Time GetNow() const;
void ClearAllItems();
void MarkDataNotFresh();
void InitPrefChangeRegistrars();
void OnCalendarPrefChanged();
void OnFileSuggestPrefChanged();
void OnChromeTabsPrefChanged();
void OnLostMediaPrefChanged();
void OnWeatherPrefChanged();
void OnReleaseNotesPrefChanged();
void OnCoralPrefChanged();
bool IsItemRemoverInitialized();
template <typename T>
void StartDataFetchIfNeeded(DataTypeInfo<T>& data_info,
BirchDataProvider* data_provider);
bool ShouldShowLastActive();
bool ShouldShowMostVisited();
void OnLostMediaDataProviderChanged();
bool is_post_login_fetch_ = false;
size_t next_request_id_ = 0u;
std::map<size_t, PendingRequest> pending_requests_;
base::Time fetch_start_time_;
DataTypeInfo<BirchCalendarItem> calendar_data_;
DataTypeInfo<BirchAttachmentItem> attachment_data_;
DataTypeInfo<BirchFileItem> file_suggest_data_;
DataTypeInfo<BirchTabItem> recent_tab_data_;
DataTypeInfo<BirchLastActiveItem> last_active_data_;
DataTypeInfo<BirchMostVisitedItem> most_visited_data_;
DataTypeInfo<BirchSelfShareItem> self_share_data_;
DataTypeInfo<BirchLostMediaItem> lost_media_data_;
DataTypeInfo<BirchReleaseNotesItem> release_notes_data_;
DataTypeInfo<BirchWeatherItem> weather_data_;
DataTypeInfo<BirchCoralItem> coral_data_;
raw_ptr<BirchClient> birch_client_ = nullptr;
std::unique_ptr<BirchIconCache> icon_cache_;
std::unique_ptr<BirchDataProvider> weather_provider_;
std::unique_ptr<BirchDataProvider> coral_provider_;
raw_ptr<base::Clock> clock_override_ = nullptr;
bool has_active_user_session_changed_ = false;
PrefChangeRegistrar calendar_pref_registrar_;
PrefChangeRegistrar file_suggest_pref_registrar_;
PrefChangeRegistrar chrome_tabs_pref_registrar_;
PrefChangeRegistrar lost_media_pref_registrar_;
PrefChangeRegistrar weather_pref_registrar_;
PrefChangeRegistrar release_notes_pref_registrar_;
PrefChangeRegistrar coral_pref_registrar_;
std::unique_ptr<BirchItemRemover> item_remover_;
base::ObserverList<Observer> observers_;
base::OnceClosure data_fetch_callback_for_test_;
base::Time last_active_last_shown_;
base::Time most_visited_last_shown_;
LostMediaDataChangedCallback lost_media_data_changed_callback_;
base::WeakPtrFactory<BirchModel> weak_ptr_factory_{this};
};
}
#endif