blob: 61ee173375f9faaf2f2a421f0e1ca641b0a89582 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CONTEXTUAL_TASKS_INTERNAL_CONTEXTUAL_TASKS_SERVICE_IMPL_H_
#define COMPONENTS_CONTEXTUAL_TASKS_INTERNAL_CONTEXTUAL_TASKS_SERVICE_IMPL_H_
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "base/barrier_closure.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/uuid.h"
#include "base/version_info/channel.h"
#include "components/contextual_tasks/internal/ai_thread_sync_bridge.h"
#include "components/contextual_tasks/internal/contextual_task_sync_bridge.h"
#include "components/contextual_tasks/internal/proto/ai_thread_entity.pb.h"
#include "components/contextual_tasks/internal/proto/contextual_task_entity.pb.h"
#include "components/contextual_tasks/public/context_decorator.h"
#include "components/contextual_tasks/public/contextual_task.h"
#include "components/contextual_tasks/public/contextual_tasks_service.h"
#include "components/sessions/core/session_id.h"
#include "components/sync/model/data_type_store.h"
#include "url/gurl.h"
class AimEligibilityService;
namespace signin {
class IdentityManager;
}
namespace contextual_tasks {
class CompositeContextDecorator;
struct ContextualTaskContext;
class ContextualTasksServiceImpl : public ContextualTasksService,
public AiThreadSyncBridge::Observer,
public ContextualTaskSyncBridge::Observer {
public:
ContextualTasksServiceImpl(
version_info::Channel channel,
syncer::RepeatingDataTypeStoreFactory data_type_store_factory,
std::unique_ptr<CompositeContextDecorator> composite_context_decorator,
AimEligibilityService* aim_eligibility_service,
signin::IdentityManager* identity_manager,
bool supports_ephemeral_only);
~ContextualTasksServiceImpl() override;
ContextualTasksServiceImpl(const ContextualTasksServiceImpl&) = delete;
ContextualTasksServiceImpl& operator=(const ContextualTasksServiceImpl&) =
delete;
// ContextualTasksService implementation.
FeatureEligibility GetFeatureEligibility() override;
bool IsInitialized() override;
ContextualTask CreateTask() override;
ContextualTask CreateTaskFromUrl(const GURL& url) override;
void GetTaskById(const base::Uuid& task_id,
base::OnceCallback<void(std::optional<ContextualTask>)>
callback) const override;
void GetTasks(base::OnceCallback<void(std::vector<ContextualTask>)> callback)
const override;
void DeleteTask(const base::Uuid& task_id) override;
void UpdateThreadForTask(const base::Uuid& task_id,
ThreadType thread_type,
const std::string& server_id,
std::optional<std::string> conversation_turn_id,
std::optional<std::string> title) override;
void RemoveThreadFromTask(const base::Uuid& task_id,
ThreadType type,
const std::string& server_id) override;
std::optional<ContextualTask> GetTaskFromServerId(
ThreadType thread_type,
const std::string& server_id) override;
void AttachUrlToTask(const base::Uuid& task_id, const GURL& url) override;
void DetachUrlFromTask(const base::Uuid& task_id, const GURL& url) override;
void AssociateTabWithTask(const base::Uuid& task_id,
SessionID tab_id) override;
void DisassociateTabFromTask(const base::Uuid& task_id,
SessionID tab_id) override;
std::optional<ContextualTask> GetContextualTaskForTab(
SessionID tab_id) const override;
void ClearAllTabAssociationsForTask(const base::Uuid& task_id) override;
void GetContextForTask(
const base::Uuid& task_id,
const std::set<ContextualTaskContextSource>& sources,
base::OnceCallback<void(std::unique_ptr<ContextualTaskContext>)>
context_callback) override;
void AddObserver(ContextualTasksService::Observer* observer) override;
void RemoveObserver(ContextualTasksService::Observer* observer) override;
base::WeakPtr<syncer::DataTypeControllerDelegate>
GetAiThreadControllerDelegate() override;
size_t GetTabIdMapSizeForTesting() const;
private:
friend class ContextualTasksServiceImplTest;
// Finds a task by its ID, or creates a new one if it doesn't exist.
// Returns an iterator to the task in the map and a boolean indicating whether
// the task was newly created.
std::pair<std::map<base::Uuid, ContextualTask>::iterator, bool>
FindOrCreateTask(const base::Uuid& task_id,
ThreadType thread_type,
const std::string& server_id);
void RemoveTaskInternal(const base::Uuid& task_id, TriggerSource source);
void SetAiThreadSyncBridgeForTesting(
std::unique_ptr<AiThreadSyncBridge> bridge);
void SetContextualTaskSyncBridgeForTesting(
std::unique_ptr<ContextualTaskSyncBridge> bridge);
// AiThreadSyncBridge::Observer implementation.
void OnThreadDataStoreLoaded() override;
void OnThreadAddedOrUpdatedRemotely(
const std::vector<proto::AiThreadEntity>& threads) override;
void OnThreadRemovedRemotely(
const std::vector<base::Uuid>& thread_ids) override;
// ContextualTaskSyncBridge::Observer implementation.
void OnContextualTaskDataStoreLoaded() override;
void OnTaskAddedOrUpdatedRemotely(
const std::vector<ContextualTask>& task_entities) override;
void OnTaskRemovedRemotely(
const std::vector<base::Uuid>& task_entities) override;
void NotifyTaskAdded(const ContextualTask& task, TriggerSource source);
void NotifyTaskUpdated(const ContextualTask& task, TriggerSource source);
void NotifyTaskRemoved(const base::Uuid& task_id, TriggerSource source);
ContextualTask AddTaskAndNotify(ContextualTask task);
void OnDataStoresLoaded();
std::vector<ContextualTask> BuildTasks() const;
// The set of all tasks currently managed by the service, indexed by their
// unique task ID for efficient lookup.
std::map<base::Uuid, ContextualTask> tasks_;
// A map from tab IDs to task IDs, used to find the task associated with a
// given tab.
std::map<SessionID, base::Uuid> tab_to_task_;
// The entry point for the decorator chain that enriches the context.
std::unique_ptr<CompositeContextDecorator> composite_context_decorator_;
// Obsevers of the model.
base::ObserverList<ContextualTasksService::Observer> observers_;
std::unique_ptr<AiThreadSyncBridge> ai_thread_sync_bridge_;
std::unique_ptr<ContextualTaskSyncBridge> contextual_task_sync_bridge_;
// Barrier to run OnDataStoresLoaded() after both sync bridges have loaded
// their data.
base::RepeatingClosure on_data_loaded_barrier_;
// Whether the service is initialized.
bool is_initialized_ = false;
raw_ptr<AimEligibilityService> aim_eligibility_service_;
raw_ptr<signin::IdentityManager> identity_manager_;
// Whether the service only supports ephemeral tasks.
const bool supports_ephemeral_only_;
base::WeakPtrFactory<ContextualTasksServiceImpl> weak_ptr_factory_{this};
};
} // namespace contextual_tasks
#endif // COMPONENTS_CONTEXTUAL_TASKS_INTERNAL_CONTEXTUAL_TASKS_SERVICE_IMPL_H_