chromium/chrome/services/sharing/nearby/platform/credential_storage.cc

// 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 "chrome/services/sharing/nearby/platform/credential_storage.h"
#include "chromeos/ash/components/nearby/presence/conversions/proto_conversions.h"
#include "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom.h"

namespace nearby::chrome {

CredentialStorage::CredentialStorage(
    const mojo::SharedRemote<
        ash::nearby::presence::mojom::NearbyPresenceCredentialStorage>&
        nearby_presence_credential_storage)
    : nearby_presence_credential_storage_(nearby_presence_credential_storage) {}

CredentialStorage::~CredentialStorage() = default;

void CredentialStorage::SaveCredentials(
    std::string_view manager_app_id,
    std::string_view account_name,
    const std::vector<LocalCredential>& private_credentials,
    const std::vector<SharedCredential>& public_credentials,
    PublicCredentialType public_credential_type,
    SaveCredentialsResultCallback callback) {
  std::vector<ash::nearby::presence::mojom::LocalCredentialPtr>
      local_credentials_mojom;
  for (const auto& local_credential : private_credentials) {
    local_credentials_mojom.push_back(
        ash::nearby::presence::proto::LocalCredentialToMojom(local_credential));
  }

  std::vector<ash::nearby::presence::mojom::SharedCredentialPtr>
      shared_credentials_mojom;
  for (const auto& shared_credential : public_credentials) {
    shared_credentials_mojom.push_back(
        ash::nearby::presence::proto::SharedCredentialToMojom(
            shared_credential));
  }

  nearby_presence_credential_storage_->SaveCredentials(
      std::move(local_credentials_mojom), std::move(shared_credentials_mojom),
      ash::nearby::presence::proto::PublicCredentialTypeToMojom(
          public_credential_type),
      base::BindOnce(&CredentialStorage::OnCredentialsSaved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void CredentialStorage::UpdateLocalCredential(
    std::string_view manager_app_id,
    std::string_view account_name,
    nearby::internal::LocalCredential credential,
    SaveCredentialsResultCallback callback) {
  // Credentials are stored per-account with a constant manager_app_id, so
  // these parameters are disregarded.
  ash::nearby::presence::mojom::LocalCredentialPtr local_credential_mojom =
      ash::nearby::presence::proto::LocalCredentialToMojom(credential);

  nearby_presence_credential_storage_->UpdateLocalCredential(
      std::move(local_credential_mojom),
      base::BindOnce(&CredentialStorage::OnLocalCredentialUpdated,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void CredentialStorage::GetLocalCredentials(
    const CredentialSelector& credential_selector,
    GetLocalCredentialsResultCallback callback) {
  // Because 'manager_app_id' and 'account_name' are consistent per user, and
  // credentials are stored in the user's cryptohome, 'credential_selector' is
  // redundant.
  nearby_presence_credential_storage_->GetPrivateCredentials(
      base::BindOnce(&CredentialStorage::OnLocalCredentialsRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

// TODO(b/287334335): Implement.
void CredentialStorage::GetPublicCredentials(
    const CredentialSelector& credential_selector,
    PublicCredentialType public_credential_type,
    GetPublicCredentialsResultCallback callback) {
  // TODO(b/299300880): Extract identity_type from credential_selector
  // and pass to the browser process to filter SharedCredentials.
  nearby_presence_credential_storage_->GetPublicCredentials(
      ash::nearby::presence::proto::PublicCredentialTypeToMojom(
          public_credential_type),
      base::BindOnce(&CredentialStorage::OnPublicCredentialsRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void CredentialStorage::OnCredentialsSaved(
    nearby::presence::SaveCredentialsResultCallback
        on_credentials_saved_callback,
    mojo_base::mojom::AbslStatusCode credential_save_result) {
  if (credential_save_result == mojo_base::mojom::AbslStatusCode::kOk) {
    std::move(on_credentials_saved_callback)
        .credentials_saved_cb(absl::OkStatus());
  } else {
    std::move(on_credentials_saved_callback)
        .credentials_saved_cb(absl::Status(absl::StatusCode::kUnknown,
                                           "Failed to save to database."));
  }
}

void CredentialStorage::OnPublicCredentialsRetrieved(
    nearby::presence::GetPublicCredentialsResultCallback
        on_public_credentials_retrieved_callback,
    mojo_base::mojom::AbslStatusCode retrieved_status,
    std::optional<
        std::vector<ash::nearby::presence::mojom::SharedCredentialPtr>>
        shared_credentials_mojom) {
  if (retrieved_status != mojo_base::mojom::AbslStatusCode::kOk) {
    std::move(on_public_credentials_retrieved_callback)
        .credentials_fetched_cb(absl::Status(
            absl::StatusCode::kAborted,
            "Failed to retrieve public credentials from database."));
    return;
  }

  CHECK(shared_credentials_mojom.has_value());

  std::vector<SharedCredential> shared_credentials;
  for (const auto& shared_credential_mojom : *shared_credentials_mojom) {
    shared_credentials.push_back(
        ash::nearby::presence::proto::SharedCredentialFromMojom(
            shared_credential_mojom.get()));
  }

  std::move(on_public_credentials_retrieved_callback)
      .credentials_fetched_cb(shared_credentials);
}

void CredentialStorage::OnLocalCredentialsRetrieved(
    nearby::presence::GetLocalCredentialsResultCallback
        on_local_credentials_retrieved_callback,
    mojo_base::mojom::AbslStatusCode retrieved_status,
    std::optional<std::vector<ash::nearby::presence::mojom::LocalCredentialPtr>>
        local_credentials_mojom) {
  if (retrieved_status != mojo_base::mojom::AbslStatusCode::kOk) {
    std::move(on_local_credentials_retrieved_callback)
        .credentials_fetched_cb(absl::Status(
            absl::StatusCode::kAborted, "Failed to retrieve from database."));
    return;
  }

  CHECK(local_credentials_mojom.has_value());

  std::vector<LocalCredential> local_credentials;
  for (const auto& local_credential_mojom : *local_credentials_mojom) {
    local_credentials.push_back(
        ash::nearby::presence::proto::LocalCredentialFromMojom(
            local_credential_mojom.get()));
  }

  std::move(on_local_credentials_retrieved_callback)
      .credentials_fetched_cb(local_credentials);
}

void CredentialStorage::OnLocalCredentialUpdated(
    nearby::presence::SaveCredentialsResultCallback
        on_local_credential_updated_callback,
    mojo_base::mojom::AbslStatusCode update_status) {
  if (update_status != mojo_base::mojom::AbslStatusCode::kOk) {
    std::move(on_local_credential_updated_callback)
        .credentials_saved_cb(
            absl::Status(absl::StatusCode::kAborted,
                         "Failed to update the local credential."));
    return;
  }
  std::move(on_local_credential_updated_callback)
      .credentials_saved_cb(absl::OkStatus());
}

}  // namespace nearby::chrome