Add certificate gen/set functionality to bring Android closer to JS API

The JS API supports two operations which have never been implemented in
the Android counterpart:
 - generate a new certificate
 - use this certificate when creating a new PeerConnection

Both functions are illustrated in the generateCertificate example code:
 - https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/generateCertificate

Currently, on Android, a new certificate is automatically generated for
every PeerConnection with no programmatic way to set a specific
certificate.

A twin of this feature is already underway for iOS here:
 - https://webrtc-review.googlesource.com/c/src/+/87303

Work sponsored by |pipe|

Bug: webrtc:9546
Change-Id: Iac221517df3ae380aef83c18c9e59b028d709a4f
Reviewed-on: https://webrtc-review.googlesource.com/c/89980
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25090}
This commit is contained in:
Michael Iedema
2018-10-09 15:30:01 +02:00
committed by Commit Bot
parent dcc023816e
commit 0213786b39
9 changed files with 309 additions and 11 deletions

View File

@ -47,6 +47,7 @@
#include "sdk/android/src/jni/pc/icecandidate.h"
#include "sdk/android/src/jni/pc/mediaconstraints.h"
#include "sdk/android/src/jni/pc/mediastreamtrack.h"
#include "sdk/android/src/jni/pc/rtccertificate.h"
#include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h"
#include "sdk/android/src/jni/pc/rtpsender.h"
#include "sdk/android/src/jni/pc/sdpobserver.h"
@ -129,6 +130,8 @@ void JavaToNativeRTCConfiguration(
Java_RTCConfiguration_getBundlePolicy(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_rtcp_mux_policy =
Java_RTCConfiguration_getRtcpMuxPolicy(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_rtc_certificate =
Java_RTCConfiguration_getCertificate(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_tcp_candidate_policy =
Java_RTCConfiguration_getTcpCandidatePolicy(jni, j_rtc_config);
ScopedJavaLocalRef<jobject> j_candidate_network_policy =
@ -148,6 +151,13 @@ void JavaToNativeRTCConfiguration(
rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy);
rtc_config->rtcp_mux_policy =
JavaToNativeRtcpMuxPolicy(jni, j_rtcp_mux_policy);
if (!j_rtc_certificate.is_null()) {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificate::FromPEM(
JavaToNativeRTCCertificatePEM(jni, j_rtc_certificate));
RTC_CHECK(certificate != nullptr) << "supplied certificate is malformed.";
rtc_config->certificates.push_back(certificate);
}
rtc_config->tcp_candidate_policy =
JavaToNativeTcpCandidatePolicy(jni, j_tcp_candidate_policy);
rtc_config->candidate_network_policy =
@ -429,6 +439,16 @@ static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetRemoteDescription(
return sdp ? NativeToJavaSessionDescription(jni, sdp) : nullptr;
}
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetCertificate(
JNIEnv* jni,
const JavaParamRef<jobject>& j_pc) {
const PeerConnectionInterface::RTCConfiguration rtc_config =
ExtractNativePC(jni, j_pc)->GetConfiguration();
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc_config.certificates[0];
return NativeToJavaRTCCertificatePEM(jni, certificate->ToPEM());
}
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateDataChannel(
JNIEnv* jni,
const JavaParamRef<jobject>& j_pc,

View File

@ -396,18 +396,20 @@ static jlong JNI_PeerConnectionFactory_CreatePeerConnection(
PeerConnectionInterface::RTCConfigurationType::kAggressive);
JavaToNativeRTCConfiguration(jni, j_rtc_config, &rtc_config);
// Generate non-default certificate.
rtc::KeyType key_type = GetRtcConfigKeyType(jni, j_rtc_config);
if (key_type != rtc::KT_DEFAULT) {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificateGenerator::GenerateCertificate(
rtc::KeyParams(key_type), absl::nullopt);
if (!certificate) {
RTC_LOG(LS_ERROR) << "Failed to generate certificate. KeyType: "
<< key_type;
return 0;
if (rtc_config.certificates.empty()) {
// Generate non-default certificate.
rtc::KeyType key_type = GetRtcConfigKeyType(jni, j_rtc_config);
if (key_type != rtc::KT_DEFAULT) {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificateGenerator::GenerateCertificate(
rtc::KeyParams(key_type), absl::nullopt);
if (!certificate) {
RTC_LOG(LS_ERROR) << "Failed to generate certificate. KeyType: "
<< key_type;
return 0;
}
rtc_config.certificates.push_back(certificate);
}
rtc_config.certificates.push_back(certificate);
}
std::unique_ptr<MediaConstraintsInterface> constraints;

View File

@ -0,0 +1,60 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "sdk/android/src/jni/pc/rtccertificate.h"
#include "sdk/android/src/jni/pc/icecandidate.h"
#include "rtc_base/refcount.h"
#include "rtc_base/rtccertificate.h"
#include "rtc_base/rtccertificategenerator.h"
#include "sdk/android/generated_peerconnection_jni/jni/RtcCertificatePem_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
rtc::RTCCertificatePEM JavaToNativeRTCCertificatePEM(
JNIEnv* jni,
const JavaRef<jobject>& j_rtc_certificate) {
ScopedJavaLocalRef<jstring> privatekey_field =
Java_RtcCertificatePem_getPrivateKey(jni, j_rtc_certificate);
ScopedJavaLocalRef<jstring> certificate_field =
Java_RtcCertificatePem_getCertificate(jni, j_rtc_certificate);
return rtc::RTCCertificatePEM(JavaToNativeString(jni, privatekey_field),
JavaToNativeString(jni, certificate_field));
}
ScopedJavaLocalRef<jobject> NativeToJavaRTCCertificatePEM(
JNIEnv* jni,
const rtc::RTCCertificatePEM& certificate) {
return Java_RtcCertificatePem_Constructor(
jni, NativeToJavaString(jni, certificate.private_key()),
NativeToJavaString(jni, certificate.certificate()));
}
static ScopedJavaLocalRef<jobject> JNI_RtcCertificatePem_GenerateCertificate(
JNIEnv* jni,
const JavaParamRef<jclass>&,
const JavaParamRef<jobject>& j_key_type,
jlong j_expires) {
rtc::KeyType key_type = JavaToNativeKeyType(jni, j_key_type);
uint64_t expires = (uint64_t)j_expires;
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificateGenerator::GenerateCertificate(
rtc::KeyParams(key_type), expires);
rtc::RTCCertificatePEM pem = certificate->ToPEM();
return Java_RtcCertificatePem_Constructor(
jni, NativeToJavaString(jni, pem.private_key()),
NativeToJavaString(jni, pem.certificate()));
}
} // namespace jni
} // namespace webrtc

View File

@ -0,0 +1,33 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SDK_ANDROID_SRC_JNI_PC_RTCCERTIFICATE_H_
#define SDK_ANDROID_SRC_JNI_PC_RTCCERTIFICATE_H_
#include "rtc_base/refcount.h"
#include "rtc_base/rtccertificate.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
namespace webrtc {
namespace jni {
rtc::RTCCertificatePEM JavaToNativeRTCCertificatePEM(
JNIEnv* jni,
const JavaRef<jobject>& j_rtc_certificate);
ScopedJavaLocalRef<jobject> NativeToJavaRTCCertificatePEM(
JNIEnv* env,
const rtc::RTCCertificatePEM& certificate);
} // namespace jni
} // namespace webrtc
#endif // SDK_ANDROID_SRC_JNI_PC_RTCCERTIFICATE_H_