| // Copyright 2024 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_COLLABORATION_INTERNAL_MESSAGING_MESSAGING_BACKEND_SERVICE_IMPL_H_ |
| #define COMPONENTS_COLLABORATION_INTERNAL_MESSAGING_MESSAGING_BACKEND_SERVICE_IMPL_H_ |
| |
| #include <memory> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/scoped_observation.h" |
| #include "components/collaboration/internal/messaging/configuration.h" |
| #include "components/collaboration/internal/messaging/data_sharing_change_notifier.h" |
| #include "components/collaboration/internal/messaging/instant_message_processor.h" |
| #include "components/collaboration/internal/messaging/storage/messaging_backend_store.h" |
| #include "components/collaboration/internal/messaging/tab_group_change_notifier.h" |
| #include "components/collaboration/public/messaging/message.h" |
| #include "components/collaboration/public/messaging/messaging_backend_service.h" |
| #include "components/saved_tab_groups/public/tab_group_sync_service.h" |
| #include "components/signin/public/identity_manager/identity_manager.h" |
| |
| namespace collaboration_pb { |
| class Message; |
| } // namespace collaboration_pb |
| |
| namespace data_sharing { |
| class DataSharingService; |
| } // namespace data_sharing |
| |
| namespace tab_groups { |
| class TabGroupSyncService; |
| } // namespace tab_groups |
| |
| namespace collaboration::messaging { |
| class DataSharingChangeNotifier; |
| class MessagingBackendStore; |
| |
| // The implementation of the MessagingBackendService. |
| class MessagingBackendServiceImpl : public MessagingBackendService, |
| public TabGroupChangeNotifier::Observer, |
| public DataSharingChangeNotifier::Observer { |
| public: |
| MessagingBackendServiceImpl( |
| const MessagingBackendConfiguration& configuration, |
| std::unique_ptr<TabGroupChangeNotifier> tab_group_change_notifier, |
| std::unique_ptr<DataSharingChangeNotifier> data_sharing_change_notifier, |
| std::unique_ptr<MessagingBackendStore> messaging_backend_store, |
| std::unique_ptr<InstantMessageProcessor> instant_message_processor, |
| tab_groups::TabGroupSyncService* tab_group_sync_service, |
| data_sharing::DataSharingService* data_sharing_service, |
| signin::IdentityManager* identity_manager); |
| ~MessagingBackendServiceImpl() override; |
| |
| // MessagingBackendService implementation. |
| void SetInstantMessageDelegate( |
| InstantMessageDelegate* instant_message_delegate) override; |
| void AddPersistentMessageObserver( |
| PersistentMessageObserver* observer) override; |
| void RemovePersistentMessageObserver( |
| PersistentMessageObserver* observer) override; |
| bool IsInitialized() override; |
| std::vector<PersistentMessage> GetMessagesForTab( |
| tab_groups::EitherTabID tab_id, |
| std::optional<PersistentNotificationType> type) override; |
| std::vector<PersistentMessage> GetMessagesForGroup( |
| tab_groups::EitherGroupID group_id, |
| std::optional<PersistentNotificationType> type) override; |
| std::vector<PersistentMessage> GetMessages( |
| std::optional<PersistentNotificationType> type) override; |
| std::vector<ActivityLogItem> GetActivityLog( |
| const ActivityLogQueryParams& params) override; |
| void ClearDirtyTabMessagesForGroup( |
| const data_sharing::GroupId& collaboration_group_id) override; |
| void ClearPersistentMessage( |
| const base::Uuid& message_id, |
| std::optional<PersistentNotificationType> type) override; |
| void RemoveMessages(const std::vector<base::Uuid>& message_ids) override; |
| void AddActivityLogForTesting( |
| data_sharing::GroupId collaboration_id, |
| const std::vector<ActivityLogItem>& activity_log) override; |
| |
| // TabGroupChangeNotifier::Observer. |
| void OnTabGroupChangeNotifierInitialized() override; |
| void OnSyncDisabled() override; |
| void OnTabGroupAdded(const tab_groups::SavedTabGroup& added_group, |
| tab_groups::TriggerSource source) override; |
| void OnTabGroupRemoved(tab_groups::SavedTabGroup removed_group, |
| tab_groups::TriggerSource source) override; |
| void OnTabGroupNameUpdated(const tab_groups::SavedTabGroup& updated_group, |
| tab_groups::TriggerSource source) override; |
| void OnTabGroupColorUpdated(const tab_groups::SavedTabGroup& updated_group, |
| tab_groups::TriggerSource source) override; |
| void OnTabAdded(const tab_groups::SavedTabGroupTab& added_tab, |
| tab_groups::TriggerSource source) override; |
| void OnTabRemoved(tab_groups::SavedTabGroupTab removed_tab, |
| tab_groups::TriggerSource source, |
| bool is_selected) override; |
| void OnTabUpdated(const tab_groups::SavedTabGroupTab& before, |
| const tab_groups::SavedTabGroupTab& after, |
| tab_groups::TriggerSource source, |
| bool is_selected) override; |
| void OnTabSelectionChanged(const tab_groups::LocalTabID& tab_id, |
| bool is_selected) override; |
| void OnTabLastSeenTimeChanged(const base::Uuid& tab_id, |
| tab_groups::TriggerSource source) override; |
| void OnTabGroupOpened(const tab_groups::SavedTabGroup& tab_group) override; |
| void OnTabGroupClosed(const tab_groups::SavedTabGroup& tab_group) override; |
| |
| // DataSharingChangeNotifier::Observer. |
| void OnDataSharingChangeNotifierInitialized() override; |
| void OnGroupMemberAdded(const data_sharing::GroupData& group_data, |
| const GaiaId& member_gaia_id, |
| const base::Time& event_time) override; |
| void OnGroupMemberRemoved(const data_sharing::GroupData& group_data, |
| const GaiaId& member_gaia_id, |
| const base::Time& event_time) override; |
| |
| static std::u16string GetTruncatedTabTitleForTesting( |
| const std::u16string& original_title); |
| |
| private: |
| void OnStoreInitialized(bool success); |
| |
| void ClearDirtyTabMessagesForGroup( |
| const data_sharing::GroupId& collaboration_group_id, |
| const std::optional<tab_groups::SavedTabGroup>& tab_group); |
| |
| // Uses all available sources to try to retrieve a name that describes the |
| // given user. |
| std::optional<std::string> GetDisplayNameForUserInGroup( |
| const data_sharing::GroupId& group_id, |
| const GaiaId& gaia_id); |
| |
| // Converts a stored message to an ActivityLogItem for display. Some events |
| // should not be part of the activity log and for those std::nullopt is |
| // return. |
| std::optional<ActivityLogItem> ConvertMessageToActivityLogItem( |
| const collaboration_pb::Message& message, |
| bool is_tab_activity); |
| |
| // Looks for the related collaboration GroupId for the given tab, using the |
| // information available in the tab group sync service. |
| std::optional<data_sharing::GroupId> GetCollaborationGroupIdForTab( |
| const tab_groups::SavedTabGroupTab& tab); |
| |
| // Uses the provided data to create TabGroupMessageMetadata. |
| TabGroupMessageMetadata CreateTabGroupMessageMetadataFromCollaborationId( |
| const collaboration_pb::Message& message, |
| std::optional<tab_groups::SavedTabGroup> tab_group, |
| std::optional<data_sharing::GroupId> collaboration_group_id); |
| |
| // Creates a TabGroupMessageMetadata based on the sources given as input. |
| TabGroupMessageMetadata CreateTabGroupMessageMetadataFromMessageOrTabGroup( |
| const collaboration_pb::Message& message, |
| const std::optional<tab_groups::SavedTabGroup>& tab_group); |
| |
| // Tries to retrieve the tab group from CollaborationId. |
| std::optional<tab_groups::SavedTabGroup> GetTabGroupFromCollaborationId( |
| const std::string& collaboration_id); |
| |
| // Uses the available data to look up a GroupMember. |
| std::optional<data_sharing::GroupMember> GetGroupMemberFromGaiaId( |
| const data_sharing::GroupId& collaboration_group_id, |
| std::optional<GaiaId> gaia_id); |
| |
| // Retrieves the relevant tab group from the TabGroupSyncService and looks up |
| // its collaboration group id. |
| std::optional<data_sharing::GroupId> GetCollaborationGroupId( |
| tab_groups::EitherGroupID group_id); |
| |
| // Looks up the tab from tab group sync service. |
| std::optional<tab_groups::SavedTabGroupTab> GetTabFromTabId( |
| tab_groups::EitherTabID tab_id); |
| |
| // Convert all the provided stored Messages to PersistentMessages. |
| std::vector<PersistentMessage> ConvertMessagesToPersistentMessages( |
| const std::vector<collaboration_pb::Message>& messages, |
| DirtyType lookup_dirty_type, |
| const std::optional<PersistentNotificationType>& type); |
| |
| // Convert a single stored Message to PersistentMessages. Each stored message |
| // may result in multiple PersistentMessages, e.g. both CHIP and DIRTY_TAB. |
| std::vector<PersistentMessage> ConvertMessageToPersistentMessages( |
| const collaboration_pb::Message& message, |
| DirtyType lookup_dirty_type, |
| const std::optional<PersistentNotificationType>& type, |
| bool allow_dirty_tab_group_message); |
| |
| // Creates a PersistentMessage based on the provided information. |
| PersistentMessage CreatePersistentMessage( |
| const collaboration_pb::Message& message, |
| const std::optional<tab_groups::SavedTabGroup>& tab_group, |
| const std::optional<tab_groups::SavedTabGroupTab>& tab, |
| const std::optional<PersistentNotificationType>& type); |
| |
| InstantMessage CreateInstantMessage( |
| const collaboration_pb::Message& message, |
| const std::optional<tab_groups::SavedTabGroup>& tab_group, |
| const std::optional<tab_groups::SavedTabGroupTab>& tab); |
| |
| // Creates individual messages based on `base_message` per type, and notifies |
| // oservers to display the messages. |
| void NotifyDisplayPersistentMessagesForTypes( |
| const PersistentMessage& base_message, |
| const std::vector<PersistentNotificationType>& types); |
| |
| // Creates individual messages based on `base_message` per type, and notifies |
| // oservers to hide the messages. |
| void NotifyHidePersistentMessagesForTypes( |
| const PersistentMessage& base_message, |
| const std::vector<PersistentNotificationType>& types); |
| |
| // Notifies observers to display or hide the dirty dot for a tab group. |
| void DisplayOrHideTabGroupDirtyDotForTabGroup( |
| const data_sharing::GroupId& collaboration_group_id, |
| base::Uuid shared_tab_group_id); |
| |
| // Creates MessageAttribution based on all the provided information. |
| MessageAttribution CreateMessageAttributionForTabUpdates( |
| const collaboration_pb::Message& message, |
| const std::optional<tab_groups::SavedTabGroup>& tab_group, |
| const std::optional<tab_groups::SavedTabGroupTab>& tab); |
| |
| // Notifies the InstantMessageDelegate to display the message for all the |
| // provided levels. |
| void DisplayInstantMessage( |
| const base::Uuid& db_message_uuid, |
| const InstantMessage& base_message, |
| const std::vector<InstantNotificationLevel>& levels); |
| |
| // Clears the dirty bit for the given DB message ID if `success` is true. |
| void ClearMessageDirtyBit(base::Uuid db_message_id, bool success); |
| |
| // Creates a PersistentMessage based on tab group and tab for when we do not |
| // have a db Message available. |
| PersistentMessage CreatePersistentMessageFromTabGroupAndTab( |
| const data_sharing::GroupId& collaboration_group_id, |
| const tab_groups::SavedTabGroupTab tab, |
| CollaborationEvent collaboration_event); |
| |
| // A configuration for how the MessagingBackendService should behave. |
| MessagingBackendConfiguration configuration_; |
| |
| // Provides functionality to go from observing the TabGroupSyncService to |
| // a delta based observer API. |
| std::unique_ptr<TabGroupChangeNotifier> tab_group_change_notifier_; |
| |
| // Provides functionality to go from observing the DataSharingService to a |
| // smaller API surface and delta observation. |
| std::unique_ptr<DataSharingChangeNotifier> data_sharing_change_notifier_; |
| |
| // Store for reading and writing messages: |
| std::unique_ptr<MessagingBackendStore> store_; |
| |
| // Scoped observers for our delta change notifiers. |
| base::ScopedObservation<TabGroupChangeNotifier, |
| TabGroupChangeNotifier::Observer> |
| tab_group_change_notifier_observer_{this}; |
| base::ScopedObservation<DataSharingChangeNotifier, |
| DataSharingChangeNotifier::Observer> |
| data_sharing_change_notifier_observer_{this}; |
| |
| // Whether initialization has completed. |
| bool initialized_ = false; |
| |
| // A callback invoked when we are ready to flush all the events from the |
| // data sharing service. |
| DataSharingChangeNotifier::FlushCallback data_sharing_flush_callback_; |
| |
| // Queues and processes instant messages. Invokes the delegate to ask UI to |
| // show the instant message. |
| std::unique_ptr<InstantMessageProcessor> instant_message_processor_; |
| |
| // Service providing information about tabs and tab groups. |
| raw_ptr<tab_groups::TabGroupSyncService> tab_group_sync_service_; |
| |
| // Service providing information about people groups. |
| raw_ptr<data_sharing::DataSharingService> data_sharing_service_; |
| |
| // Service providing information about sign in. |
| raw_ptr<signin::IdentityManager> identity_manager_; |
| |
| // The list of observers for any changes to persistent messages. |
| base::ObserverList<PersistentMessageObserver> persistent_message_observers_; |
| |
| // Test-only mock activity log, keyed by collaboration id. |
| std::unordered_map<data_sharing::GroupId, const std::vector<ActivityLogItem>&> |
| activity_log_for_testing_; |
| |
| base::WeakPtrFactory<MessagingBackendServiceImpl> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace collaboration::messaging |
| |
| #endif // COMPONENTS_COLLABORATION_INTERNAL_MESSAGING_MESSAGING_BACKEND_SERVICE_IMPL_H_ |