chromium/components/data_sharing/internal/android/data_sharing_sdk_delegate_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/data_sharing/internal/android/data_sharing_sdk_delegate_android.h"

#include <vector>

#include "base/android/callback_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "components/data_sharing/internal/android/data_sharing_network_loader_android.h"
#include "components/data_sharing/internal/jni_headers/DataSharingSDKDelegateBridge_jni.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/android/gurl_android.h"

using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;

namespace data_sharing {

// static
std::unique_ptr<DataSharingSDKDelegate> DataSharingSDKDelegate::CreateDelegate(
    ScopedJavaLocalRef<jobject> sdk_delegate) {
  return std::make_unique<DataSharingSDKDelegateAndroid>(sdk_delegate);
}

DataSharingSDKDelegateAndroid::DataSharingSDKDelegateAndroid(
    const JavaRef<jobject>& sdk_delegate) {
  JNIEnv* env = AttachCurrentThread();
  java_obj_.Reset(env, Java_DataSharingSDKDelegateBridge_create(
                           env, reinterpret_cast<int64_t>(this), sdk_delegate)
                           .obj());
}

DataSharingSDKDelegateAndroid::~DataSharingSDKDelegateAndroid() {
  Java_DataSharingSDKDelegateBridge_clearNativePtr(AttachCurrentThread(),
                                                   java_obj_);
}

ScopedJavaLocalRef<jobject> DataSharingSDKDelegateAndroid::GetJavaObject() {
  return ScopedJavaLocalRef<jobject>(java_obj_);
}

void DataSharingSDKDelegateAndroid::Initialize(
    DataSharingNetworkLoader* data_sharing_network_loader) {
  JNIEnv* env = AttachCurrentThread();
  network_loader_ = std::make_unique<DataSharingNetworkLoaderAndroid>(
      data_sharing_network_loader);
  Java_DataSharingSDKDelegateBridge_initialize(
      env, java_obj_, network_loader_->GetJavaObject());
}
void DataSharingSDKDelegateAndroid::CreateGroup(
    const data_sharing_pb::CreateGroupParams& params,
    CreateGroupCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string create_group_params;
  params.SerializeToString(&create_group_params);
  std::unique_ptr<CreateGroupCallback> wrapped_callback =
      std::make_unique<CreateGroupCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_createGroup(
      env, java_obj_, ConvertUTF8ToJavaString(env, create_group_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunCreateGroupCallback.
  wrapped_callback.release();
}

void DataSharingSDKDelegateAndroid::ReadGroups(
    const data_sharing_pb::ReadGroupsParams& params,
    ReadGroupsCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string read_groups_params;
  params.SerializeToString(&read_groups_params);
  std::unique_ptr<ReadGroupsCallback> wrapped_callback =
      std::make_unique<ReadGroupsCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_readGroups(
      env, java_obj_, ConvertUTF8ToJavaString(env, read_groups_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunReadGroupsCallback.
  wrapped_callback.release();
}
void DataSharingSDKDelegateAndroid::AddMember(
    const data_sharing_pb::AddMemberParams& params,
    GetStatusCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string add_member_params;
  params.SerializeToString(&add_member_params);
  std::unique_ptr<GetStatusCallback> wrapped_callback =
      std::make_unique<GetStatusCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_addMember(
      env, java_obj_, ConvertUTF8ToJavaString(env, add_member_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunAddMemberCallback.
  wrapped_callback.release();
}

void DataSharingSDKDelegateAndroid::RemoveMember(
    const data_sharing_pb::RemoveMemberParams& params,
    GetStatusCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string remove_member_params;
  params.SerializeToString(&remove_member_params);
  std::unique_ptr<GetStatusCallback> wrapped_callback =
      std::make_unique<GetStatusCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_removeMember(
      env, java_obj_, ConvertUTF8ToJavaString(env, remove_member_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunRemoveMemberCallback.
  wrapped_callback.release();
}

void DataSharingSDKDelegateAndroid::DeleteGroup(
    const data_sharing_pb::DeleteGroupParams& params,
    GetStatusCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string delete_group_params;
  params.SerializeToString(&delete_group_params);
  std::unique_ptr<GetStatusCallback> wrapped_callback =
      std::make_unique<GetStatusCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_deleteGroup(
      env, java_obj_, ConvertUTF8ToJavaString(env, delete_group_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunDeleteGroupCallback.
  wrapped_callback.release();
}

void DataSharingSDKDelegateAndroid::LookupGaiaIdByEmail(
    const data_sharing_pb::LookupGaiaIdByEmailParams& params,
    LookupGaiaIdByEmailCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string lookup_gaid_id_params;
  params.SerializeToString(&lookup_gaid_id_params);
  std::unique_ptr<LookupGaiaIdByEmailCallback> wrapped_callback =
      std::make_unique<LookupGaiaIdByEmailCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_lookupGaiaIdByEmail(
      env, java_obj_, ConvertUTF8ToJavaString(env, lookup_gaid_id_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunLookupGaiaIdByEmailCallback.
  wrapped_callback.release();
}

void DataSharingSDKDelegateAndroid::AddAccessToken(
    const data_sharing_pb::AddAccessTokenParams& params,
    AddAccessTokenCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  std::string add_access_token_params;
  params.SerializeToString(&add_access_token_params);
  std::unique_ptr<AddAccessTokenCallback> wrapped_callback =
      std::make_unique<AddAccessTokenCallback>(std::move(callback));
  CHECK(wrapped_callback.get());
  jlong j_native_ptr = reinterpret_cast<jlong>(wrapped_callback.get());
  Java_DataSharingSDKDelegateBridge_addAccessToken(
      env, java_obj_, ConvertUTF8ToJavaString(env, add_access_token_params),
      j_native_ptr);
  // We expect Java to always call us back through
  // JNI_DataSharingSDKDelegateBridge_RunAddAccessTokenCallback.
  wrapped_callback.release();
}

static void JNI_DataSharingSDKDelegateBridge_RunCreateGroupCallback(
    JNIEnv* env,
    jlong callback,
    const jni_zero::JavaParamRef<jbyteArray>& j_serlialized_proto,
    jint j_status) {
  std::unique_ptr<DataSharingSDKDelegateAndroid::CreateGroupCallback>
      callback_ptr(
          reinterpret_cast<DataSharingSDKDelegateAndroid::CreateGroupCallback*>(
              callback));
  std::string str;
  base::android::JavaByteArrayToString(env, j_serlialized_proto, &str);
  data_sharing_pb::CreateGroupResult result;
  if (j_status != 0 || str.empty() || !result.ParseFromString(str)) {
    std::move(*callback_ptr).Run(base::unexpected(absl::CancelledError()));
  } else {
    std::move(*callback_ptr).Run(std::move(result));
  }
}

static void JNI_DataSharingSDKDelegateBridge_RunReadGroupsCallback(
    JNIEnv* env,
    jlong callback,
    const jni_zero::JavaParamRef<jbyteArray>& j_serlialized_proto,
    jint j_status) {
  std::unique_ptr<DataSharingSDKDelegateAndroid::ReadGroupsCallback>
      callback_ptr(
          reinterpret_cast<DataSharingSDKDelegateAndroid::ReadGroupsCallback*>(
              callback));
  std::string str;
  base::android::JavaByteArrayToString(env, j_serlialized_proto, &str);
  data_sharing_pb::ReadGroupsResult result;
  if (j_status != 0 || str.empty() || !result.ParseFromString(str)) {
    std::move(*callback_ptr).Run(base::unexpected(absl::CancelledError()));
  } else {
    std::move(*callback_ptr).Run(std::move(result));
  }
}

static void JNI_DataSharingSDKDelegateBridge_RunGetStatusCallback(
    JNIEnv* env,
    jlong callback,
    jint j_status) {
  std::unique_ptr<DataSharingSDKDelegateAndroid::GetStatusCallback>
      callback_ptr(
          reinterpret_cast<DataSharingSDKDelegateAndroid::GetStatusCallback*>(
              callback));
  absl::Status error_status =
      (j_status == 0) ? absl::OkStatus() : absl::CancelledError();
  std::move(*callback_ptr).Run(error_status);
}

static void JNI_DataSharingSDKDelegateBridge_RunLookupGaiaIdByEmailCallback(
    JNIEnv* env,
    jlong callback,
    const jni_zero::JavaParamRef<jbyteArray>& j_serlialized_proto,
    jint j_status) {
  std::unique_ptr<DataSharingSDKDelegateAndroid::LookupGaiaIdByEmailCallback>
      callback_ptr(reinterpret_cast<
                   DataSharingSDKDelegateAndroid::LookupGaiaIdByEmailCallback*>(
          callback));
  std::string str;
  base::android::JavaByteArrayToString(env, j_serlialized_proto, &str);
  data_sharing_pb::LookupGaiaIdByEmailResult result;
  if (j_status != 0 || str.empty() || !result.ParseFromString(str)) {
    std::move(*callback_ptr).Run(base::unexpected(absl::CancelledError()));
  } else {
    std::move(*callback_ptr).Run(std::move(result));
  }
}

static void JNI_DataSharingSDKDelegateBridge_RunAddAccessTokenCallback(
    JNIEnv* env,
    jlong callback,
    const jni_zero::JavaParamRef<jbyteArray>& j_serlialized_proto,
    jint j_status) {
  std::unique_ptr<DataSharingSDKDelegateAndroid::AddAccessTokenCallback>
      callback_ptr(reinterpret_cast<
                   DataSharingSDKDelegateAndroid::AddAccessTokenCallback*>(
          callback));
  std::string str;
  base::android::JavaByteArrayToString(env, j_serlialized_proto, &str);
  data_sharing_pb::AddAccessTokenResult result;
  if (j_status != 0 || str.empty() || !result.ParseFromString(str)) {
    std::move(*callback_ptr).Run(base::unexpected(absl::CancelledError()));
  } else {
    std::move(*callback_ptr).Run(std::move(result));
  }
}

}  // namespace data_sharing