blob: 980f5ef15043ba8b6130f3097525266f006fbaad [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.
#include "components/data_sharing/internal/data_sharing_service_impl.h"
#include <optional>
#include "base/check_is_test.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/metrics/histogram_functions_internal_overloads.h"
#include "base/notimplemented.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/task/single_thread_task_runner.h"
#include "base/version_info/channel.h"
#include "components/data_sharing/internal/avatar_fetcher.h"
#include "components/data_sharing/internal/collaboration_group_sync_bridge.h"
#include "components/data_sharing/internal/data_sharing_network_loader_impl.h"
#include "components/data_sharing/internal/group_data_proto_utils.h"
#include "components/data_sharing/internal/logger_impl.h"
#include "components/data_sharing/public/data_sharing_sdk_delegate.h"
#include "components/data_sharing/public/data_sharing_service.h"
#include "components/data_sharing/public/features.h"
#include "components/data_sharing/public/group_data.h"
#include "components/data_sharing/public/protocol/data_sharing_sdk.pb.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/report_unrecoverable_error.h"
#include "components/sync/model/client_tag_based_data_type_processor.h"
#include "components/sync/model/data_type_store.h"
#include "components/sync/model/data_type_sync_bridge.h"
#include "net/base/url_util.h"
#include "third_party/abseil-cpp/absl/status/status.h"
namespace data_sharing {
namespace {
constexpr char kGroupIdKey[] = "g";
constexpr char kTokenBlobKey[] = "t";
constexpr base::FilePath::CharType kDataSharingDir[] =
FILE_PATH_LITERAL("DataSharing");
// Should not be called with kOk StatusCode, unless SDK delegate misbehaves by
// passing it as an error value.
DataSharingService::PeopleGroupActionFailure StatusToPeopleGroupActionFailure(
const absl::Status& status) {
switch (status.code()) {
case absl::StatusCode::kOk:
// Not expected here, treat as a persistent failure.
return DataSharingService::PeopleGroupActionFailure::kPersistentFailure;
case absl::StatusCode::kCancelled:
case absl::StatusCode::kUnknown:
case absl::StatusCode::kDeadlineExceeded:
case absl::StatusCode::kResourceExhausted:
case absl::StatusCode::kAborted:
case absl::StatusCode::kInternal:
case absl::StatusCode::kUnavailable:
return DataSharingService::PeopleGroupActionFailure::kTransientFailure;
case absl::StatusCode::kNotFound:
case absl::StatusCode::kAlreadyExists:
case absl::StatusCode::kPermissionDenied:
case absl::StatusCode::kFailedPrecondition:
case absl::StatusCode::kOutOfRange:
case absl::StatusCode::kUnimplemented:
case absl::StatusCode::kDataLoss:
case absl::StatusCode::kUnauthenticated:
return DataSharingService::PeopleGroupActionFailure::kPersistentFailure;
default:
// absl::StatusCode should always have "default:" in `switch()`.
return DataSharingService::PeopleGroupActionFailure::kPersistentFailure;
}
}
DataSharingService::PeopleGroupActionOutcome StatusToPeopleGroupActionOutcome(
const absl::Status& status) {
if (status.ok()) {
return DataSharingService::PeopleGroupActionOutcome::kSuccess;
}
switch (StatusToPeopleGroupActionFailure(status)) {
case DataSharingService::PeopleGroupActionFailure::kUnknown:
return DataSharingService::PeopleGroupActionOutcome::kUnknown;
case DataSharingService::PeopleGroupActionFailure::kPersistentFailure:
return DataSharingService::PeopleGroupActionOutcome::kPersistentFailure;
case DataSharingService::PeopleGroupActionFailure::kTransientFailure:
return DataSharingService::PeopleGroupActionOutcome::kTransientFailure;
}
}
} // namespace
DataSharingServiceImpl::DataSharingServiceImpl(
const base::FilePath& profile_dir,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
signin::IdentityManager* identity_manager,
syncer::OnceDataTypeStoreFactory data_type_store_factory,
version_info::Channel channel,
std::unique_ptr<DataSharingSDKDelegate> sdk_delegate,
std::unique_ptr<DataSharingUIDelegate> ui_delegate)
: data_sharing_network_loader_(
std::make_unique<DataSharingNetworkLoaderImpl>(url_loader_factory,
identity_manager)),
sdk_delegate_(std::move(sdk_delegate)),
ui_delegate_(std::move(ui_delegate)),
profile_dir_(profile_dir),
preview_server_proxy_(
std::make_unique<PreviewServerProxy>(identity_manager,
url_loader_factory,
channel)),
avatar_fetcher_(std::make_unique<AvatarFetcher>()),
logger_(std::make_unique<LoggerImpl>()) {
auto change_processor =
std::make_unique<syncer::ClientTagBasedDataTypeProcessor>(
syncer::COLLABORATION_GROUP,
base::BindRepeating(&syncer::ReportUnrecoverableError, channel));
collaboration_group_sync_bridge_ =
std::make_unique<CollaborationGroupSyncBridge>(
std::move(change_processor), std::move(data_type_store_factory));
OnSDKDelegateUpdated();
}
DataSharingServiceImpl::~DataSharingServiceImpl() {
ClearAllUserData();
if (group_data_model_) {
group_data_model_->RemoveObserver(this);
}
for (auto& observer : observers_) {
observer.OnDataSharingServiceDestroyed();
}
}
bool DataSharingServiceImpl::IsEmptyService() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return false;
}
void DataSharingServiceImpl::AddObserver(
DataSharingService::Observer* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
observers_.AddObserver(observer);
}
void DataSharingServiceImpl::RemoveObserver(
DataSharingService::Observer* observer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
observers_.RemoveObserver(observer);
}
DataSharingNetworkLoader*
DataSharingServiceImpl::GetDataSharingNetworkLoader() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return data_sharing_network_loader_.get();
}
base::WeakPtr<syncer::DataTypeControllerDelegate>
DataSharingServiceImpl::GetCollaborationGroupControllerDelegate() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return collaboration_group_sync_bridge_->change_processor()
->GetControllerDelegate();
}
bool DataSharingServiceImpl::IsGroupDataModelLoaded() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return group_data_model_ && group_data_model_->IsModelLoaded();
}
std::optional<GroupData> DataSharingServiceImpl::ReadGroup(
const GroupId& group_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (group_data_for_testing_.contains(group_id)) {
CHECK_IS_TEST();
return group_data_for_testing_[group_id];
}
if (!group_data_model_) {
return std::nullopt;
}
return group_data_model_->GetGroup(group_id);
}
std::set<GroupData> DataSharingServiceImpl::ReadAllGroups() {
if (!group_data_model_) {
return std::set<GroupData>();
}
return group_data_model_->GetAllGroups();
}
std::optional<GroupMemberPartialData>
DataSharingServiceImpl::GetPossiblyRemovedGroupMember(
const GroupId& group_id,
const GaiaId& member_gaia_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (group_data_for_testing_.contains(group_id)) {
CHECK_IS_TEST();
const auto& group = group_data_for_testing_[group_id];
for (const auto& member : group.members) {
if (member.gaia_id == member_gaia_id) {
return GroupMemberPartialData::FromGroupMember(member);
}
}
}
if (!group_data_model_) {
return std::nullopt;
}
return group_data_model_->GetPossiblyRemovedGroupMember(group_id,
member_gaia_id);
}
std::optional<GroupData> DataSharingServiceImpl::GetPossiblyRemovedGroup(
const GroupId& group_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (deleted_groups_this_session_.find(group_id) ==
deleted_groups_this_session_.end()) {
return std::nullopt;
}
return deleted_groups_this_session_.at(group_id);
}
void DataSharingServiceImpl::ReadGroupDeprecated(
const GroupId& group_id,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// TODO(crbug.com/382036119): this method should be deleted.
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
base::unexpected(PeopleGroupActionFailure::kPersistentFailure)));
return;
}
data_sharing_pb::ReadGroupsParams params;
data_sharing_pb::ReadGroupsParams::GroupParams* group_params =
params.add_group_params();
group_params->set_group_id(group_id.value());
group_params->set_consistency_token("");
sdk_delegate_->ReadGroups(
params,
base::BindOnce(&DataSharingServiceImpl::OnReadSingleGroupCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::ReadNewGroup(
const GroupToken& token,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
base::unexpected(PeopleGroupActionFailure::kPersistentFailure)));
return;
}
data_sharing_pb::ReadGroupWithTokenParams params;
const std::string& group_id = token.group_id.value();
params.set_group_id(group_id);
params.set_access_token(token.access_token);
sdk_delegate_->ReadGroupWithToken(
params,
base::BindOnce(&DataSharingServiceImpl::OnReadSingleGroupCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::CreateGroup(
const std::string& group_name,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
base::unexpected(PeopleGroupActionFailure::kPersistentFailure)));
return;
}
data_sharing_pb::CreateGroupParams params;
params.set_display_name(group_name);
sdk_delegate_->CreateGroup(
params,
base::BindOnce(&DataSharingServiceImpl::OnCreateGroupCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::DeleteGroup(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
PeopleGroupActionOutcome::kPersistentFailure));
return;
}
groups_attempted_to_leave_or_delete_by_current_user_in_current_session_
.insert(group_id);
data_sharing_pb::DeleteGroupParams params;
params.set_group_id(group_id.value());
sdk_delegate_->DeleteGroup(
params,
base::BindOnce(&DataSharingServiceImpl::OnSimpleGroupActionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::InviteMember(
const GroupId& group_id,
const std::string& invitee_email,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
PeopleGroupActionOutcome::kPersistentFailure));
return;
}
data_sharing_pb::LookupGaiaIdByEmailParams lookup_params;
lookup_params.set_email(invitee_email);
sdk_delegate_->LookupGaiaIdByEmail(
lookup_params,
base::BindOnce(
&DataSharingServiceImpl::OnGaiaIdLookupForAddMemberCompleted,
weak_ptr_factory_.GetWeakPtr(), group_id, std::move(callback)));
}
void DataSharingServiceImpl::AddMember(
const GroupId& group_id,
const std::string& access_token,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
PeopleGroupActionOutcome::kPersistentFailure));
return;
}
data_sharing_pb::AddMemberParams params;
params.set_group_id(group_id.value());
params.set_access_token(access_token);
sdk_delegate_->AddMember(
params,
base::BindOnce(&DataSharingServiceImpl::OnSimpleGroupActionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::RemoveMember(
const GroupId& group_id,
const std::string& member_email,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
PeopleGroupActionOutcome::kPersistentFailure));
return;
}
data_sharing_pb::LookupGaiaIdByEmailParams lookup_params;
lookup_params.set_email(member_email);
sdk_delegate_->LookupGaiaIdByEmail(
lookup_params,
base::BindOnce(
&DataSharingServiceImpl::OnGaiaIdLookupForRemoveMemberCompleted,
weak_ptr_factory_.GetWeakPtr(), group_id, std::move(callback)));
}
void DataSharingServiceImpl::LeaveGroup(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
PeopleGroupActionOutcome::kPersistentFailure));
return;
}
groups_attempted_to_leave_or_delete_by_current_user_in_current_session_
.insert(group_id);
data_sharing_pb::LeaveGroupParams params;
params.set_group_id(group_id.value());
sdk_delegate_->LeaveGroup(
params,
base::BindOnce(&DataSharingServiceImpl::OnSimpleGroupActionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
bool DataSharingServiceImpl::IsLeavingOrDeletingGroup(const GroupId& group_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return groups_attempted_to_leave_or_delete_by_current_user_in_current_session_
.contains(group_id);
}
std::vector<GroupEvent> DataSharingServiceImpl::GetGroupEventsSinceStartup() {
if (!group_data_model_) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return std::vector<GroupEvent>();
}
return group_data_model_->GetGroupEventsSinceStartup();
}
void DataSharingServiceImpl::OnModelLoaded() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::set<GroupData> groups = ReadAllGroups();
for (const GroupData& group : groups) {
base::UmaHistogramCounts100("DataSharing.TotalMembersInGroup.AtStartup",
group.members.size());
}
for (auto& observer : observers_) {
observer.OnGroupDataModelLoaded();
}
}
void DataSharingServiceImpl::OnGroupAdded(const GroupId& group_id,
const base::Time& event_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
CHECK(group_data_model_);
std::optional<GroupData> group_data = group_data_model_->GetGroup(group_id);
CHECK(group_data);
for (auto& observer : observers_) {
observer.OnGroupAdded(*group_data, event_time);
}
}
void DataSharingServiceImpl::OnGroupUpdated(const GroupId& group_id,
const base::Time& event_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
CHECK(group_data_model_);
std::optional<GroupData> group_data = group_data_model_->GetGroup(group_id);
CHECK(group_data);
for (auto& observer : observers_) {
observer.OnGroupChanged(*group_data, event_time);
}
}
void DataSharingServiceImpl::OnGroupDeleted(
const GroupId& group_id,
const std::optional<GroupData>& group_data,
const base::Time& event_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (group_data) {
CHECK(group_id == group_data->group_token.group_id);
deleted_groups_this_session_.emplace(group_id, *group_data);
}
for (auto& observer : observers_) {
observer.OnGroupRemoved(group_id, event_time);
}
}
void DataSharingServiceImpl::OnMemberAdded(const GroupId& group_id,
const GaiaId& member_gaia_id,
const base::Time& event_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : observers_) {
observer.OnGroupMemberAdded(group_id, member_gaia_id, event_time);
}
}
void DataSharingServiceImpl::OnMemberRemoved(const GroupId& group_id,
const GaiaId& member_gaia_id,
const base::Time& event_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : observers_) {
observer.OnGroupMemberRemoved(group_id, member_gaia_id, event_time);
}
}
void DataSharingServiceImpl::OnSyncBridgeUpdateTypeChanged(
SyncBridgeUpdateType sync_bridge_update_type) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto& observer : observers_) {
observer.OnSyncBridgeUpdateTypeChanged(sync_bridge_update_type);
}
}
void DataSharingServiceImpl::Shutdown() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (sdk_delegate_) {
sdk_delegate_->Shutdown();
}
}
// static
std::unique_ptr<GURL> DataSharingServiceImpl::GetDataSharingUrl(
const GroupToken& group_token) {
GURL url = GURL(data_sharing::features::kDataSharingURL.Get());
url =
net::AppendQueryParameter(url, kGroupIdKey, group_token.group_id.value());
url = net::AppendQueryParameter(url, kTokenBlobKey, group_token.access_token);
return std::make_unique<GURL>(url);
}
void DataSharingServiceImpl::OnReadSingleGroupCompleted(
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback,
const base::expected<data_sharing_pb::ReadGroupsResult, absl::Status>&
result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (result.has_value()) {
if (result.value().group_data_size() == 1) {
std::move(callback).Run(GroupDataFromProto(result.value().group_data(0)));
return;
} else {
// SDK indicated success, but didn't return exactly single group,
// indicating serious bug in SDK.
std::move(callback).Run(
base::unexpected(PeopleGroupActionFailure::kPersistentFailure));
return;
}
}
std::move(callback).Run(
base::unexpected(StatusToPeopleGroupActionFailure(result.error())));
}
void DataSharingServiceImpl::OnCreateGroupCompleted(
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback,
const base::expected<data_sharing_pb::CreateGroupResult, absl::Status>&
result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (result.has_value()) {
std::move(callback).Run(GroupDataFromProto(result.value().group_data()));
return;
}
std::move(callback).Run(
base::unexpected(StatusToPeopleGroupActionFailure(result.error())));
}
void DataSharingServiceImpl::OnGaiaIdLookupForAddMemberCompleted(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback,
const base::expected<data_sharing_pb::LookupGaiaIdByEmailResult,
absl::Status>& result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!result.has_value()) {
std::move(callback).Run(StatusToPeopleGroupActionOutcome(result.error()));
return;
}
data_sharing_pb::AddMemberParams params;
params.set_group_id(group_id.value());
params.set_member_gaia_id(result.value().gaia_id());
sdk_delegate_->AddMember(
params,
base::BindOnce(&DataSharingServiceImpl::OnSimpleGroupActionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::OnGaiaIdLookupForRemoveMemberCompleted(
const GroupId& group_id,
base::OnceCallback<void(PeopleGroupActionOutcome)> callback,
const base::expected<data_sharing_pb::LookupGaiaIdByEmailResult,
absl::Status>& result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!result.has_value()) {
std::move(callback).Run(StatusToPeopleGroupActionOutcome(result.error()));
return;
}
data_sharing_pb::RemoveMemberParams params;
params.set_group_id(group_id.value());
params.set_member_gaia_id(result.value().gaia_id());
sdk_delegate_->RemoveMember(
params,
base::BindOnce(&DataSharingServiceImpl::OnSimpleGroupActionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::OnSimpleGroupActionCompleted(
base::OnceCallback<void(PeopleGroupActionOutcome)> callback,
const absl::Status& status) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::move(callback).Run(StatusToPeopleGroupActionOutcome(status));
}
CollaborationGroupSyncBridge*
DataSharingServiceImpl::GetCollaborationGroupSyncBridgeForTesting() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return collaboration_group_sync_bridge_.get();
}
void DataSharingServiceImpl::HandleShareURLNavigationIntercepted(
const GURL& url,
std::unique_ptr<ShareURLInterceptionContext> context) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!ui_delegate_) {
return;
}
ui_delegate_->HandleShareURLIntercepted(url, std::move(context));
}
std::unique_ptr<GURL> DataSharingServiceImpl::GetDataSharingUrl(
const GroupData& group_data) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!group_data.group_token.IsValid()) {
return nullptr;
}
return GetDataSharingUrl(group_data.group_token);
}
void DataSharingServiceImpl::EnsureGroupVisibility(
const GroupId& group_id,
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!sdk_delegate_) {
// Reply in a posted task to avoid reentrance on the calling side.
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
base::unexpected(PeopleGroupActionFailure::kPersistentFailure)));
return;
}
// TODO(ritikagup@): If a token was added recently then skip adding and return
// read group.
data_sharing_pb::AddAccessTokenParams params;
params.set_group_id(group_id.value());
sdk_delegate_->AddAccessToken(
params,
base::BindOnce(&DataSharingServiceImpl::OnAccessTokenAdded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void DataSharingServiceImpl::GetSharedEntitiesPreview(
const GroupToken& group_token,
base::OnceCallback<void(const SharedDataPreviewOrFailureOutcome&)>
callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
preview_server_proxy_->GetSharedDataPreview(
group_token, syncer::DataType::SHARED_TAB_GROUP_DATA,
std::move(callback));
}
void DataSharingServiceImpl::GetAvatarImageForURL(
const GURL& avatar_url,
int size,
base::OnceCallback<void(const gfx::Image&)> callback,
image_fetcher::ImageFetcher* image_fetcher) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
avatar_fetcher_->Fetch(avatar_url, size, std::move(callback), image_fetcher);
}
void DataSharingServiceImpl::SetSDKDelegate(
std::unique_ptr<DataSharingSDKDelegate> sdk_delegate) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
CHECK(!sdk_delegate || (sdk_delegate && !sdk_delegate_));
sdk_delegate_ = std::move(sdk_delegate);
OnSDKDelegateUpdated();
}
DataSharingSDKDelegate* DataSharingServiceImpl::GetSDKDelegate() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return sdk_delegate_.get();
}
void DataSharingServiceImpl::SetUIDelegate(
std::unique_ptr<DataSharingUIDelegate> ui_delegate) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ui_delegate_ = std::move(ui_delegate);
}
DataSharingUIDelegate* DataSharingServiceImpl::GetUiDelegate() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (sdk_delegate_) {
sdk_delegate_->ForceInitialize(data_sharing_network_loader_.get());
}
return ui_delegate_.get();
}
Logger* DataSharingServiceImpl::GetLogger() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return logger_.get();
}
void DataSharingServiceImpl::AddGroupDataForTesting(GroupData group_data) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
group_data_for_testing_.emplace(group_data.group_token.group_id, group_data);
}
void DataSharingServiceImpl::SetPreviewServerProxyForTesting(
std::unique_ptr<PreviewServerProxy> preview_server_proxy) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
preview_server_proxy_ = std::move(preview_server_proxy);
}
PreviewServerProxy* DataSharingServiceImpl::GetPreviewServerProxyForTesting() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return preview_server_proxy_.get();
}
void DataSharingServiceImpl::OnCollaborationGroupRemoved(
const data_sharing::GroupId& group_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (collaboration_group_sync_bridge_) {
collaboration_group_sync_bridge_->RemoveGroupLocally(group_id);
}
}
void DataSharingServiceImpl::OnAccessTokenAdded(
base::OnceCallback<void(const GroupDataOrFailureOutcome&)> callback,
const base::expected<data_sharing_pb::AddAccessTokenResult, absl::Status>&
result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (result.has_value()) {
std::move(callback).Run(GroupDataFromProto(result.value().group_data()));
return;
}
std::move(callback).Run(
base::unexpected(StatusToPeopleGroupActionFailure(result.error())));
}
void DataSharingServiceImpl::OnSDKDelegateUpdated() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (group_data_model_) {
group_data_model_->RemoveObserver(this);
group_data_model_.reset();
}
if (sdk_delegate_) {
sdk_delegate_->Initialize(data_sharing_network_loader_.get());
const base::FilePath data_sharing_dir =
profile_dir_.Append(kDataSharingDir);
group_data_model_ = std::make_unique<GroupDataModel>(
data_sharing_dir, collaboration_group_sync_bridge_.get(),
sdk_delegate_.get());
group_data_model_->AddObserver(this);
}
}
} // namespace data_sharing