#ifndef CHROME_BROWSER_GLIC_HOST_CONTEXT_GLIC_PINNED_TAB_MANAGER_H_
#define CHROME_BROWSER_GLIC_HOST_CONTEXT_GLIC_PINNED_TAB_MANAGER_H_
#include <vector>
#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/glic/host/context/glic_tab_data.h"
#include "chrome/browser/glic/host/glic.mojom.h"
#include "chrome/browser/glic/widget/glic_window_controller.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/tabs/public/tab_interface.h"
#include "mojo/public/cpp/bindings/remote.h"
class Profile;
class BrowserTabStripTracker;
namespace glic {
class GlicMetrics;
enum class GlicPinnedTabContextEventType { kConversationTurnSubmitted };
struct GlicPinnedTabContextEvent {
explicit GlicPinnedTabContextEvent(GlicPinnedTabContextEventType type);
~GlicPinnedTabContextEvent();
GlicPinnedTabContextEventType type;
base::TimeTicks timestamp;
};
class GlicPinnedTabManager : public TabStripModelObserver {
public:
explicit GlicPinnedTabManager(Profile* profile,
GlicInstance::UIDelegate* ui_delegate,
GlicMetrics* metrics);
~GlicPinnedTabManager() override;
using PinnedTabsChangedCallback =
base::RepeatingCallback<void(const std::vector<content::WebContents*>&)>;
base::CallbackListSubscription AddPinnedTabsChangedCallback(
PinnedTabsChangedCallback callback);
using TabPinningStatusChangedCallback =
base::RepeatingCallback<void(tabs::TabInterface*, bool)>;
base::CallbackListSubscription AddTabPinningStatusChangedCallback(
TabPinningStatusChangedCallback callback);
using TabPinningStatusEventCallback =
base::RepeatingCallback<void(tabs::TabInterface*,
GlicPinningStatusEvent)>;
base::CallbackListSubscription AddTabPinningStatusEventCallback(
TabPinningStatusEventCallback callback);
using PinnedTabDataChangedCallback =
base::RepeatingCallback<void(const TabDataChange&)>;
base::CallbackListSubscription AddPinnedTabDataChangedCallback(
PinnedTabDataChangedCallback callback);
bool PinTabs(base::span<const tabs::TabHandle> tab_handles,
GlicPinTrigger trigger = GlicPinTrigger::kUnknown);
bool UnpinTabs(base::span<const tabs::TabHandle> tab_handles,
GlicUnpinTrigger trigger = GlicUnpinTrigger::kUnknown);
void UnpinAllTabs(GlicUnpinTrigger trigger = GlicUnpinTrigger::kUnknown);
uint32_t SetMaxPinnedTabs(uint32_t max_pinned_tabs);
uint32_t GetMaxPinnedTabs() const;
uint32_t GetNumPinnedTabs() const;
bool IsTabPinned(tabs::TabHandle tab_handle) const;
std::optional<GlicPinnedTabUsage> GetPinnedTabUsage(
tabs::TabHandle tab_handle) const;
std::vector<content::WebContents*> GetPinnedTabs() const;
void SubscribeToPinCandidates(
mojom::GetPinCandidatesOptionsPtr options,
mojo::PendingRemote<mojom::PinCandidatesObserver> observer);
void OnPinnedTabContextEvent(tabs::TabHandle tab_handle,
GlicPinnedTabContextEvent context_event);
void OnAllPinnedTabsContextEvent(GlicPinnedTabContextEvent context_event);
virtual bool IsBrowserValidForSharing(BrowserWindowInterface* browser_window);
virtual bool IsValidForSharing(content::WebContents* web_contents);
virtual bool IsGlicWindowShowing();
private:
class UpdateThrottler;
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
void TabChangedAt(content::WebContents* contents,
int index,
TabChangeType change_type) override;
void OnTabWillBeRemoved(content::WebContents* contents, int index) override;
void OnPinCandidatesObserverDisconnected();
void SendPinCandidatesUpdate();
std::vector<content::WebContents*> GetUnsortedPinCandidates();
class PinnedTabObserver;
friend PinnedTabObserver;
struct PinnedTabEntry {
PinnedTabEntry(tabs::TabHandle tab_handle,
std::unique_ptr<PinnedTabObserver> tab_observer,
GlicPinnedTabUsage usage);
~PinnedTabEntry();
PinnedTabEntry(PinnedTabEntry&& other);
PinnedTabEntry& operator=(PinnedTabEntry&& other);
PinnedTabEntry(const PinnedTabEntry&) = delete;
PinnedTabEntry& operator=(const PinnedTabEntry&) = delete;
tabs::TabHandle tab_handle;
std::unique_ptr<PinnedTabObserver> tab_observer;
GlicPinnedTabUsage usage;
};
void NotifyPinnedTabsChanged();
const PinnedTabEntry* GetPinnedTabEntry(tabs::TabHandle tab_handle) const;
GlicPinnedTabUsage* GetPinnedTabUsageInternal(tabs::TabHandle tab_handle);
bool IsTabPinned(int tab_id) const;
void OnTabWillClose(tabs::TabHandle tab_handles);
void OnTabDataChanged(tabs::TabHandle tab_handle, TabDataChange);
void OnTabChangedOrigin(tabs::TabHandle tab_handle);
void OnPinnedTabContextEvent(GlicPinnedTabUsage& pinned_usage,
GlicPinnedTabContextEvent context_event);
base::RepeatingCallbackList<void(const std::vector<content::WebContents*>&)>
pinned_tabs_changed_callback_list_;
base::RepeatingCallbackList<void(const TabDataChange&)>
pinned_tab_data_changed_callback_list_;
base::RepeatingCallbackList<void(tabs::TabInterface*, bool)>
pinning_status_changed_callback_list_;
base::RepeatingCallbackList<void(tabs::TabInterface*, GlicPinningStatusEvent)>
pinning_status_event_callback_list_;
raw_ptr<Profile> profile_;
raw_ptr<GlicInstance::UIDelegate> ui_delegate_;
raw_ptr<GlicMetrics> metrics_;
std::vector<PinnedTabEntry> pinned_tabs_;
uint32_t max_pinned_tabs_;
mojo::Remote<mojom::PinCandidatesObserver> pin_candidates_observer_;
mojom::GetPinCandidatesOptionsPtr pin_candidates_options_;
std::unique_ptr<UpdateThrottler> pin_candidate_updater_;
std::unique_ptr<BrowserTabStripTracker> tab_strip_tracker_;
base::WeakPtrFactory<GlicPinnedTabManager> weak_ptr_factory_{this};
};
}
#endif