blob: 95e362c0f6cfed69b324bd60a0d08b89df4f32e8 [file] [log] [blame]
// Copyright 2023 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_DATA_SHARING_PUBLIC_DATA_SHARING_SERVICE_H_
#define COMPONENTS_DATA_SHARING_PUBLIC_DATA_SHARING_SERVICE_H_
#include <set>
#include <string>
#include "base/functional/callback_forward.h"
#include "base/observer_list_types.h"
#include "base/supports_user_data.h"
#include "base/types/expected.h"
#include "build/build_config.h"
#include "components/data_sharing/migration/public/context_id.h"
#include "components/data_sharing/public/data_sharing_ui_delegate.h"
#include "components/data_sharing/public/group_data.h"
#include "components/data_sharing/public/share_url_interception_context.h"
#include "components/keyed_service/core/keyed_service.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
#endif // BUILDFLAG(IS_ANDROID)
namespace gfx {
class Image;
} // namespace gfx
namespace image_fetcher {
class ImageFetcher;
} // namespace image_fetcher
namespace syncer {
class DataTypeControllerDelegate;
} // namespace syncer
namespace data_sharing {
class DataSharingNetworkLoader;
class DataSharingSDKDelegate;
class Logger;
class PreviewServerProxy;
// The core class for managing data sharing.
class DataSharingService : public KeyedService, public base::SupportsUserData {
public:
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.components.data_sharing)
enum class DataPreviewActionFailure {
kUnknown = 0,
kPermissionDenied = 1,
kGroupFull = 2,
kGroupClosedByOrganizationPolicy = 3,
kOtherFailure = 4
};
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.components.data_sharing)
enum class PeopleGroupActionFailure {
kUnknown = 0,
kTransientFailure = 1,
kPersistentFailure = 2
};
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.components.data_sharing)
enum class PeopleGroupActionOutcome {
kUnknown = 0,
kSuccess = 1,
kTransientFailure = 2,
kPersistentFailure = 3
};
class Observer : public base::CheckedObserver {
public:
Observer() = default;
Observer(const Observer&) = delete;
Observer& operator=(const Observer&) = delete;
~Observer() override = default;
// Called when the group data model has been loaded. Use
// DataSharingService::IsGroupDataModelLoaded() to check if the model has
// been already loaded before starting to observe the service.
virtual void OnGroupDataModelLoaded() {}
// Called when the group data model has been changed.
virtual void OnGroupChanged(const GroupData& group_data,
const base::Time& event_time) {}
// User either created a new group or has been invited to the existing one.
virtual void OnGroupAdded(const GroupData& group_data,
const base::Time& event_time) {}
// Either group has been deleted or user has been removed from the group.
virtual void OnGroupRemoved(const GroupId& group_id,
const base::Time& event_time) {}
// Two methods below are called in addition to OnGroupChanged().
// Called when a new member has been added to the group.
virtual void OnGroupMemberAdded(const GroupId& group_id,
const GaiaId& member_gaia_id,
const base::Time& event_time) {}
// Called when a member has been removed from the group.
virtual void OnGroupMemberRemoved(const GroupId& group_id,
const GaiaId& member_gaia_id,
const base::Time& event_time) {}
// Called to notify of the sync bridge state changes, e.g. whether initial
// merge or disable sync are in progress. Interested consumers can choose
// to ignore incoming sync events during this duration.
virtual void OnSyncBridgeUpdateTypeChanged(
SyncBridgeUpdateType sync_bridge_update_type) {}
// Invoked when the DataSharingService is being destroyed. Give the subclass
// a chance to cleanup.
virtual void OnDataSharingServiceDestroyed() {}
};
using GroupDataOrFailureOutcome =
base::expected<GroupData, PeopleGroupActionFailure>;
using GroupsDataSetOrFailureOutcome =
base::expected<std::set<GroupData>, PeopleGroupActionFailure>;
using SharedDataPreviewOrFailureOutcome =
base::expected<SharedDataPreview, DataPreviewActionFailure>;
#if BUILDFLAG(IS_ANDROID)
// Returns a Java object of the type DataSharingService for the given
// DataSharingService.
static base::android::ScopedJavaLocalRef<jobject> GetJavaObject(
DataSharingService* data_sharing_service);
#endif // BUILDFLAG(IS_ANDROID)
DataSharingService() = default;
~DataSharingService() override = default;
// Disallow copy/assign.
DataSharingService(const DataSharingService&) = delete;
DataSharingService& operator=(const DataSharingService&) = delete;
// Whether the service is an empty implementation. This is here because the
// Chromium build disables RTTI, and we need to be able to verify that we are
// using an empty service from the Chrome embedder.
virtual bool IsEmptyService() = 0;
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
// Returns the network loader for fetching data.
virtual DataSharingNetworkLoader* GetDataSharingNetworkLoader() = 0;
// Returns DataTypeControllerDelegate for the collaboration group datatype.
virtual base::WeakPtr<syncer::DataTypeControllerDelegate>
GetCollaborationGroupControllerDelegate() = 0;
// People Group API.
// Returns true if the group data model has been loaded. Read APIs will return
// empty results if the model is not loaded.
virtual bool IsGroupDataModelLoaded() = 0;
// Synchronously reads a group from the local storage. Returns nullopt if the
// group doesn't exist, it has not been fetched from the server yet, or the
// model is not loaded yet.
virtual std::optional<GroupData> ReadGroup(const GroupId& group_id) = 0;
// Synchronously reads all groups from the local storage. Returns empty set
// if the groups haven't been fetched from the server yet, or the model is not
// loaded yet.
virtual std::set<GroupData> ReadAllGroups() = 0;
// Synchronously reads partial group member data either from the group store
// or from the special database that stores partial data of removed members.
// Returns nullopt if no data is found.
virtual std::optional<GroupMemberPartialData> GetPossiblyRemovedGroupMember(
const GroupId& group_id,
const GaiaId& member_gaia_id) = 0;
// Provides lookup functionality for groups that were known at some point
// during the current session, but have been deleted. This does not look at
// currently available groups, for that you should use `ReadGroup`.
virtual std::optional<GroupData> GetPossiblyRemovedGroup(
const GroupId& group_id) = 0;
// Refreshes data if necessary and passes the GroupData to `callback`.
// Deprecated: use synchronous ReadGroup() above instead.
virtual void ReadGroupDeprecated(
const GroupId& group_id,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) = 0;
// Attempt to read a group that the user is not member of. This does not
// refresh the cached data. Returns the group data on success.
virtual void ReadNewGroup(
const GroupToken& token,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) = 0;
// Attempts to create a new group. Returns a created group on success.
virtual void CreateGroup(
const std::string& group_name,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) = 0;
// Attempts to delete a group.
virtual void DeleteGroup(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) = 0;
// Attempts to invite a new user to the group.
virtual void InviteMember(
const GroupId& group_id,
const std::string& invitee_email,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) = 0;
// Attempts to add the primary account associated with the current profile to
// the group.
virtual void AddMember(
const GroupId& group_id,
const std::string& access_token,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) = 0;
// Attempts to remove a user from the group.
virtual void RemoveMember(
const GroupId& group_id,
const std::string& member_email,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) = 0;
// Attempts to leave a group the current user has joined before.
virtual void LeaveGroup(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) = 0;
// Returns whether the current user has attempted to leave or delete a group
// in the current session that they had joined or created before. This is
// different than if the member is removed from the group by someone else.
// Returns true for the entire current session even after leave / delete
// attempt has been committed.
virtual bool IsLeavingOrDeletingGroup(const GroupId& group_id) = 0;
// Returns group events since the DataSharingService was started. This is
// similar to events exposed to Observers, but allows to collect changes by
// observer that were created after DataSharingService was started.
virtual std::vector<GroupEvent> GetGroupEventsSinceStartup() = 0;
// DEPRECATED: Called when a data sharing type URL has been intercepted.
// Called when a data sharing type URL has been intercepted.
virtual void HandleShareURLNavigationIntercepted(
const GURL& url,
std::unique_ptr<ShareURLInterceptionContext> context) = 0;
// Create a data sharing URL used for sharing. This does not validate if the
// group is still active nor guarantee that the URL is not expired. The caller
// needs to get the valid group info from the other APIs above. Make sure
// EnsureGroupVisibility API is called before getting the URL for the group.
virtual std::unique_ptr<GURL> GetDataSharingUrl(
const GroupData& group_data) = 0;
// This ensures that the group is open for new members to join. Only owner can
// call this API. The owner must always call this API before
// GetDataSharingUrl().
virtual void EnsureGroupVisibility(
const GroupId& group_id,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) = 0;
// Gets a preview of the shared entities. The returned result may contain
// all types of shared entities for the group.
virtual void GetSharedEntitiesPreview(
const GroupToken& group_token,
base::OnceCallback<void(const SharedDataPreviewOrFailureOutcome&)>
callback) = 0;
// Gets avatar image for the given `avatar_url. It's by default cropped into a
// circle where the diameter will be set to the `size`.
// TODO(crbug.com/382127659): Shouldn't force UI to pass in an image_fetcher.
virtual void GetAvatarImageForURL(
const GURL& avatar_url,
int size,
base::OnceCallback<void(const gfx::Image&)> callback,
image_fetcher::ImageFetcher* image_fetcher) = 0;
// Sets the current DataSharingSDKDelegate instance.
virtual void SetSDKDelegate(
std::unique_ptr<DataSharingSDKDelegate> sdk_delegate) = 0;
// Get the current SDK Delegate instance.
virtual DataSharingSDKDelegate* GetSDKDelegate() = 0;
// Sets the current DataSharingUIDelegate instance.
virtual void SetUIDelegate(
std::unique_ptr<DataSharingUIDelegate> ui_delegate) = 0;
// Get the current DataSharingUIDelegate instance.
virtual DataSharingUIDelegate* GetUiDelegate() = 0;
virtual Logger* GetLogger() = 0;
// Sets a group for testing. When ReadGroup is called, the GroupData that
// matches GroupId will be returned. This function does not notify observers
// of the group being added. Settings 2 groups with the same GroupId will
// replace the existing GroupData.
virtual void AddGroupDataForTesting(GroupData group_data) = 0;
// Getter/setter for the preview proxy to allow override in tests.
virtual void SetPreviewServerProxyForTesting(
std::unique_ptr<PreviewServerProxy> preview_server_proxy) = 0;
virtual PreviewServerProxy* GetPreviewServerProxyForTesting() = 0;
// Called when a collaboration group is removed by the user locally. This
// happens when user leaves or deletes a group.
virtual void OnCollaborationGroupRemoved(const GroupId& group_id) = 0;
// Returns synchronous whether the `context_id` is shared based on local data.
// If a migration is ongoing, return the last stable state (e.g. If a
// migration is ongoing from private to shared, then it would return false).
virtual bool IsContextIdShared(const ContextId& context_id) = 0;
};
} // namespace data_sharing
#endif // COMPONENTS_DATA_SHARING_PUBLIC_DATA_SHARING_SERVICE_H_