1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87

content / browser / android / client_data_json_android.cc [blame]

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

#include "content/browser/webauth/client_data_json.h"

#include <jni.h>

#include <cstddef>
#include <cstring>
#include <utility>
#include <vector>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_bytebuffer.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/containers/span.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "content/public/android/content_jni_headers/ClientDataJsonImpl_jni.h"

namespace content {
namespace {

void DeserializePaymentOptionsFromJavaByteBuffer(
    JNIEnv* env,
    const base::android::JavaRef<jobject>& jbuffer,
    mojo::StructPtr<blink::mojom::PaymentOptions>* out) {
  DCHECK(out);
  if (jbuffer.is_null()) {
    *out = nullptr;
    return;
  }
  base::span<const uint8_t> span =
      base::android::JavaByteBufferToSpan(env, jbuffer.obj());
  if (span.empty()) {
    *out = nullptr;
    return;
  }
  bool success = blink::mojom::PaymentOptions::Deserialize(span, out);
  DCHECK(success);
}

}  // namespace

static base::android::ScopedJavaLocalRef<jstring>
JNI_ClientDataJsonImpl_BuildClientDataJson(
    JNIEnv* env,
    jint jclient_data_request_type,
    const base::android::JavaParamRef<jstring>& jcaller_origin,
    const base::android::JavaParamRef<jbyteArray>& jchallenge,
    jboolean jis_cross_origin,
    const base::android::JavaParamRef<jobject>& joptions_byte_buffer,
    const base::android::JavaParamRef<jstring>& jrelying_party_id,
    const base::android::JavaParamRef<jobject>& jtop_origin) {
  ClientDataRequestType type =
      static_cast<ClientDataRequestType>(jclient_data_request_type);
  std::string caller_origin =
      base::android::ConvertJavaStringToUTF8(env, jcaller_origin);
  std::vector<uint8_t> challenge;
  base::android::JavaByteArrayToByteVector(env, jchallenge, &challenge);
  bool is_cross_origin = static_cast<bool>(jis_cross_origin);

  blink::mojom::PaymentOptionsPtr options;
  DeserializePaymentOptionsFromJavaByteBuffer(env, joptions_byte_buffer,
                                              &options);

  std::string relying_party_id =
      jrelying_party_id
          ? base::android::ConvertJavaStringToUTF8(env, jrelying_party_id)
          : "";

  ClientDataJsonParams client_data_json_params(
      /*type=*/type, /*origin=*/url::Origin::Create(GURL(caller_origin)),
      /*top_origin=*/url::Origin::FromJavaObject(env, jtop_origin),
      /*challenge=*/challenge, /*is_cross_origin_iframe=*/is_cross_origin);
  client_data_json_params.payment_options = std::move(options);
  client_data_json_params.payment_rp = relying_party_id;
  std::string client_data_json =
      BuildClientDataJson(std::move(client_data_json_params));
  return base::android::ConvertUTF8ToJavaString(env, client_data_json);
}

}  // namespace content