chromium/components/facilitated_payments/android/facilitated_payments_api_client_android.cc

// 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.

#include "components/facilitated_payments/android/facilitated_payments_api_client_android.h"

#include <memory>
#include <utility>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/facilitated_payments/android/java/jni_headers/FacilitatedPaymentsApiClientBridge_jni.h"

namespace payments::facilitated {

std::unique_ptr<FacilitatedPaymentsApiClient>
LazyInitFacilitatedPaymentsApiClient(
    content::GlobalRenderFrameHostId render_frame_host_id) {
  content::RenderFrameHost* render_frame_host =
      content::RenderFrameHost::FromID(render_frame_host_id);
  return render_frame_host
             ? std::make_unique<FacilitatedPaymentsApiClientAndroid>(
                   render_frame_host)
             : nullptr;
}

// Declared in the cross-platform header
// `facilitated_payments_api_client_factory.h`.
FacilitatedPaymentsApiClientCreator GetFacilitatedPaymentsApiClientCreator(
    content::GlobalRenderFrameHostId render_frame_host_id) {
  return base::BindOnce(&LazyInitFacilitatedPaymentsApiClient,
                        render_frame_host_id);
}

FacilitatedPaymentsApiClientAndroid::FacilitatedPaymentsApiClientAndroid(
    content::RenderFrameHost* render_frame_host)
    : java_bridge_(Java_FacilitatedPaymentsApiClientBridge_Constructor(
          base::android::AttachCurrentThread(),
          reinterpret_cast<intptr_t>(this),
          render_frame_host->GetJavaRenderFrameHost())) {}

FacilitatedPaymentsApiClientAndroid::~FacilitatedPaymentsApiClientAndroid() {
  Java_FacilitatedPaymentsApiClientBridge_resetNativePointer(
      base::android::AttachCurrentThread(), java_bridge_);
}

void FacilitatedPaymentsApiClientAndroid::IsAvailable(
    base::OnceCallback<void(bool)> callback) {
  DCHECK(!IsAnyCallbackPending());

  is_available_callback_ = std::move(callback);
  Java_FacilitatedPaymentsApiClientBridge_isAvailable(
      base::android::AttachCurrentThread(), java_bridge_);
}

void FacilitatedPaymentsApiClientAndroid::GetClientToken(
    base::OnceCallback<void(std::vector<uint8_t>)> callback) {
  DCHECK(!IsAnyCallbackPending());

  get_client_token_callback_ = std::move(callback);
  Java_FacilitatedPaymentsApiClientBridge_getClientToken(
      base::android::AttachCurrentThread(), java_bridge_);
}

void FacilitatedPaymentsApiClientAndroid::InvokePurchaseAction(
    CoreAccountInfo primary_account,
    base::span<const uint8_t> action_token,
    base::OnceCallback<void(PurchaseActionResult)> callback) {
  DCHECK(!IsAnyCallbackPending());

  purchase_action_callback_ = std::move(callback);
  JNIEnv* env = base::android::AttachCurrentThread();
  Java_FacilitatedPaymentsApiClientBridge_invokePurchaseAction(
      env, java_bridge_, ConvertToJavaCoreAccountInfo(env, primary_account),
      base::android::ToJavaByteArray(env, action_token));
}

void FacilitatedPaymentsApiClientAndroid::OnIsAvailable(
    JNIEnv* env,
    jboolean is_api_available) {
  if (is_available_callback_) {
    std::move(is_available_callback_).Run(is_api_available);
  }
}

void FacilitatedPaymentsApiClientAndroid::OnGetClientToken(
    JNIEnv* env,
    const base::android::JavaRef<jbyteArray>& jclient_token_byte_array) {
  if (get_client_token_callback_) {
    std::vector<uint8_t> client_token;
    if (jclient_token_byte_array) {
      base::android::JavaByteArrayToByteVector(env, jclient_token_byte_array,
                                               &client_token);
    }
    std::move(get_client_token_callback_).Run(std::move(client_token));
  }
}

void FacilitatedPaymentsApiClientAndroid::OnPurchaseActionResultEnum(
    JNIEnv* env,
    jint purchase_action_result) {
  if (!purchase_action_callback_ ||
      purchase_action_result <
          static_cast<int>(PurchaseActionResult::kCouldNotInvoke) ||
      purchase_action_result >
          static_cast<int>(PurchaseActionResult::kResultCanceled)) {
    return;
  }

  std::move(purchase_action_callback_)
      .Run(static_cast<PurchaseActionResult>(purchase_action_result));
}

bool FacilitatedPaymentsApiClientAndroid::IsAnyCallbackPending() const {
  return !is_available_callback_.is_null() ||
         !get_client_token_callback_.is_null() ||
         !purchase_action_callback_.is_null();
}

}  // namespace payments::facilitated