chromium/chrome/browser/nearby_sharing/nearby_receive_manager.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nearby_sharing/nearby_receive_manager.h"

#include "base/functional/callback_helpers.h"
#include "components/cross_device/logging/logging.h"

NearbyReceiveManager::NearbyReceiveManager(
    NearbySharingService* nearby_sharing_service)
    : nearby_sharing_service_(nearby_sharing_service) {
  DCHECK(nearby_sharing_service_);
  nearby_sharing_service_->AddObserver(this);
}

NearbyReceiveManager::~NearbyReceiveManager() {
  UnregisterForegroundReceiveSurface(base::DoNothing());
  observers_set_.Clear();
  nearby_sharing_service_->RemoveObserver(this);
}

void NearbyReceiveManager::OnTransferUpdate(
    const ShareTarget& share_target,
    const TransferMetadata& transfer_metadata) {
  TransferMetadata::Status status = transfer_metadata.status();
  CD_LOG(VERBOSE, Feature::NS)
      << __func__ << ": Nearby receive manager: "
      << "Transfer update for share target with ID " << share_target.id << ": "
      << TransferMetadata::StatusToString(transfer_metadata.status());

  NotifyOnTransferUpdate(share_target, transfer_metadata);
  if (TransferMetadata::Status::kAwaitingLocalConfirmation == status) {
    share_targets_map_.insert_or_assign(share_target.id, share_target);
  } else if (transfer_metadata.is_final_status()) {
    share_targets_map_.erase(share_target.id);
  }
}

void NearbyReceiveManager::AddReceiveObserver(
    ::mojo::PendingRemote<nearby_share::mojom::ReceiveObserver> observer) {
  observers_set_.Add(std::move(observer));
}

void NearbyReceiveManager::IsInHighVisibility(
    IsInHighVisibilityCallback callback) {
  std::move(callback).Run(nearby_sharing_service_->IsInHighVisibility());
}

void NearbyReceiveManager::RegisterForegroundReceiveSurface(
    RegisterForegroundReceiveSurfaceCallback callback) {
  const NearbySharingService::StatusCodes result =
      nearby_sharing_service_->RegisterReceiveSurface(
          this, NearbySharingService::ReceiveSurfaceState::kForeground);
  switch (result) {
    case NearbySharingService::StatusCodes::kOk:
      std::move(callback).Run(
          nearby_share::mojom::RegisterReceiveSurfaceResult::kSuccess);
      return;
    case NearbySharingService::StatusCodes::kError:
    case NearbySharingService::StatusCodes::kOutOfOrderApiCall:
    case NearbySharingService::StatusCodes::kStatusAlreadyStopped:
      std::move(callback).Run(
          nearby_share::mojom::RegisterReceiveSurfaceResult::kFailure);
      return;
    case NearbySharingService::StatusCodes::kTransferAlreadyInProgress:
      std::move(callback).Run(
          nearby_share::mojom::RegisterReceiveSurfaceResult::
              kTransferInProgress);
      return;
    case NearbySharingService::StatusCodes::kNoAvailableConnectionMedium:
      std::move(callback).Run(
          nearby_share::mojom::RegisterReceiveSurfaceResult::
              kNoConnectionMedium);
      return;
  }
}

void NearbyReceiveManager::UnregisterForegroundReceiveSurface(
    UnregisterForegroundReceiveSurfaceCallback callback) {
  bool success = NearbySharingService::StatusCodes::kOk ==
                 nearby_sharing_service_->UnregisterReceiveSurface(this);
  std::move(callback).Run(success);
}

void NearbyReceiveManager::Accept(const base::UnguessableToken& share_target_id,
                                  AcceptCallback callback) {
  auto iter = share_targets_map_.find(share_target_id);
  if (iter == share_targets_map_.end()) {
    CD_LOG(ERROR, Feature::NS)
        << "Unknown share target accepted: id=" << share_target_id;
    std::move(callback).Run(false);
    return;
  }
  nearby_sharing_service_->Accept(
      iter->second, base::BindOnce(
                        [](AcceptCallback accept_callback,
                           NearbySharingService::StatusCodes status_code) {
                          bool success =
                              NearbySharingService::StatusCodes::kOk ==
                              status_code;
                          std::move(accept_callback).Run(success);
                        },
                        std::move(callback)));
}

void NearbyReceiveManager::Reject(const base::UnguessableToken& share_target_id,
                                  RejectCallback callback) {
  auto iter = share_targets_map_.find(share_target_id);
  if (iter == share_targets_map_.end()) {
    CD_LOG(ERROR, Feature::NS)
        << "Unknown share target rejected: id=" << share_target_id;
    std::move(callback).Run(false);
    return;
  }
  nearby_sharing_service_->Reject(
      iter->second, base::BindOnce(
                        [](RejectCallback reject_callback,
                           NearbySharingService::StatusCodes status_code) {
                          bool success =
                              NearbySharingService::StatusCodes::kOk ==
                              status_code;
                          std::move(reject_callback).Run(success);
                        },
                        std::move(callback)));
}

void NearbyReceiveManager::RecordFastInitiationNotificationUsage(bool success) {
  nearby_sharing_service_->RecordFastInitiationNotificationUsage(success);
}

void NearbyReceiveManager::OnHighVisibilityChanged(bool in_high_visibility) {
  for (auto& remote : observers_set_) {
    remote->OnHighVisibilityChanged(in_high_visibility);
  }
}

void NearbyReceiveManager::OnNearbyProcessStopped() {
  for (auto& remote : observers_set_) {
    remote->OnNearbyProcessStopped();
  }
}

void NearbyReceiveManager::OnStartAdvertisingFailure() {
  for (auto& remote : observers_set_) {
    remote->OnStartAdvertisingFailure();
  }
}

void NearbyReceiveManager::NotifyOnTransferUpdate(
    const ShareTarget& share_target,
    const TransferMetadata& metadata) {
  for (auto& remote : observers_set_) {
    remote->OnTransferUpdate(share_target, metadata.ToMojo());
  }
}