JNI+mm: Generate certificate if non-default key type is specified.

By comparing key type with KT_DEFAULT we remove the implicit assumption that
the default is RSA.

Removing the assumptions about what the default is is necessary for a
follow-up CL that will change the default.

BUG=webrtc:5795, webrtc:5707
R=hta@webrtc.org, magjed@webrtc.org, tommi@webrtc.org
TBR=tkchin@webrtc.org

Review URL: https://codereview.webrtc.org/1965313002 .

Cr-Commit-Position: refs/heads/master@{#12722}
diff --git a/webrtc/api/java/jni/peerconnection_jni.cc b/webrtc/api/java/jni/peerconnection_jni.cc
index ac328ef..02b43f7 100644
--- a/webrtc/api/java/jni/peerconnection_jni.cc
+++ b/webrtc/api/java/jni/peerconnection_jni.cc
@@ -64,6 +64,7 @@
 #include "webrtc/base/logsinks.h"
 #include "webrtc/base/messagequeue.h"
 #include "webrtc/base/networkmonitor.h"
+#include "webrtc/base/rtccertificategenerator.h"
 #include "webrtc/base/ssladapter.h"
 #include "webrtc/base/stringutils.h"
 #include "webrtc/media/base/videocapturer.h"
@@ -1565,20 +1566,17 @@
                                       "Lorg/webrtc/PeerConnection$KeyType;");
   jobject j_key_type = GetObjectField(jni, j_rtc_config, j_key_type_id);
 
-  // Create ECDSA certificate.
-  if (JavaKeyTypeToNativeType(jni, j_key_type) == rtc::KT_ECDSA) {
-    std::unique_ptr<rtc::SSLIdentity> ssl_identity(
-        rtc::SSLIdentity::Generate(webrtc::kIdentityName, rtc::KT_ECDSA));
-    if (ssl_identity.get()) {
-      rtc_config.certificates.push_back(
-          rtc::RTCCertificate::Create(std::move(ssl_identity)));
-      LOG(LS_INFO) << "ECDSA certificate created.";
-    } else {
-      // Failing to create certificate should not abort peer connection
-      // creation. Instead default encryption (currently RSA) will be used.
-      LOG(LS_WARNING) <<
-          "Failed to generate SSLIdentity. Default encryption will be used.";
+  // Generate non-default certificate.
+  rtc::KeyType key_type = JavaKeyTypeToNativeType(jni, j_key_type);
+  if (key_type != rtc::KT_DEFAULT) {
+    rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+        rtc::RTCCertificateGenerator::GenerateCertificate(
+            rtc::KeyParams(key_type), rtc::Optional<uint64_t>());
+    if (!certificate) {
+      LOG(LS_ERROR) << "Failed to generate certificate. KeyType: " << key_type;
+      return 0;
     }
+    rtc_config.certificates.push_back(certificate);
   }
 
   PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
diff --git a/webrtc/base/sslidentity.h b/webrtc/base/sslidentity.h
index da94e76..7457ff5 100644
--- a/webrtc/base/sslidentity.h
+++ b/webrtc/base/sslidentity.h
@@ -117,9 +117,6 @@
 // KT_DEFAULT is currently an alias for KT_RSA.  This is likely to change.
 // KT_LAST is intended for vector declarations and loops over all key types;
 // it does not represent any key type in itself.
-// TODO(hbos,torbjorng): Don't change KT_DEFAULT without first updating
-// PeerConnectionFactory_nativeCreatePeerConnection's certificate generation
-// code.
 enum KeyType { KT_RSA, KT_ECDSA, KT_LAST, KT_DEFAULT = KT_RSA };
 
 static const int kRsaDefaultModSize = 1024;
diff --git a/webrtc/sdk/objc/Framework/Classes/RTCConfiguration+Private.h b/webrtc/sdk/objc/Framework/Classes/RTCConfiguration+Private.h
index 5a1663b..4c020f9 100644
--- a/webrtc/sdk/objc/Framework/Classes/RTCConfiguration+Private.h
+++ b/webrtc/sdk/objc/Framework/Classes/RTCConfiguration+Private.h
@@ -21,7 +21,7 @@
  * needed to pass to the underlying C++ APIs.
  */
 @property(nonatomic, readonly)
-    webrtc::PeerConnectionInterface::RTCConfiguration nativeConfiguration;
+    webrtc::PeerConnectionInterface::RTCConfiguration* nativeConfiguration;
 
 + (webrtc::PeerConnectionInterface::IceTransportsType)
     nativeTransportsTypeForTransportPolicy:(RTCIceTransportPolicy)policy;
diff --git a/webrtc/sdk/objc/Framework/Classes/RTCConfiguration.mm b/webrtc/sdk/objc/Framework/Classes/RTCConfiguration.mm
index 0bb85a2..5beae99 100644
--- a/webrtc/sdk/objc/Framework/Classes/RTCConfiguration.mm
+++ b/webrtc/sdk/objc/Framework/Classes/RTCConfiguration.mm
@@ -15,6 +15,7 @@
 #import "RTCIceServer+Private.h"
 #import "WebRTC/RTCLogging.h"
 
+#include "webrtc/base/rtccertificategenerator.h"
 #include "webrtc/base/sslidentity.h"
 
 @implementation RTCConfiguration
@@ -74,39 +75,43 @@
 
 #pragma mark - Private
 
-- (webrtc::PeerConnectionInterface::RTCConfiguration)nativeConfiguration {
-  webrtc::PeerConnectionInterface::RTCConfiguration nativeConfig;
+- (webrtc::PeerConnectionInterface::RTCConfiguration*)nativeConfiguration {
+  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration>
+      nativeConfig(new webrtc::PeerConnectionInterface::RTCConfiguration());
 
   for (RTCIceServer *iceServer in _iceServers) {
-    nativeConfig.servers.push_back(iceServer.nativeServer);
+    nativeConfig->servers.push_back(iceServer.nativeServer);
   }
-  nativeConfig.type =
+  nativeConfig->type =
       [[self class] nativeTransportsTypeForTransportPolicy:_iceTransportPolicy];
-  nativeConfig.bundle_policy =
+  nativeConfig->bundle_policy =
       [[self class] nativeBundlePolicyForPolicy:_bundlePolicy];
-  nativeConfig.rtcp_mux_policy =
+  nativeConfig->rtcp_mux_policy =
       [[self class] nativeRtcpMuxPolicyForPolicy:_rtcpMuxPolicy];
-  nativeConfig.tcp_candidate_policy =
+  nativeConfig->tcp_candidate_policy =
       [[self class] nativeTcpCandidatePolicyForPolicy:_tcpCandidatePolicy];
-  nativeConfig.continual_gathering_policy = [[self class]
+  nativeConfig->continual_gathering_policy = [[self class]
       nativeContinualGatheringPolicyForPolicy:_continualGatheringPolicy];
-  nativeConfig.audio_jitter_buffer_max_packets = _audioJitterBufferMaxPackets;
-  nativeConfig.ice_connection_receiving_timeout =
+  nativeConfig->audio_jitter_buffer_max_packets = _audioJitterBufferMaxPackets;
+  nativeConfig->ice_connection_receiving_timeout =
       _iceConnectionReceivingTimeout;
-  nativeConfig.ice_backup_candidate_pair_ping_interval =
+  nativeConfig->ice_backup_candidate_pair_ping_interval =
       _iceBackupCandidatePairPingInterval;
-  if (_keyType == RTCEncryptionKeyTypeECDSA) {
-    std::unique_ptr<rtc::SSLIdentity> identity(
-        rtc::SSLIdentity::Generate(webrtc::kIdentityName, rtc::KT_ECDSA));
-    if (identity) {
-      nativeConfig.certificates.push_back(
-          rtc::RTCCertificate::Create(std::move(identity)));
-    } else {
-      RTCLogWarning(@"Failed to generate ECDSA identity. RSA will be used.");
+  rtc::KeyType keyType =
+      [[self class] nativeEncryptionKeyTypeForKeyType:_keyType];
+  // Generate non-default certificate.
+  if (keyType != rtc::KT_DEFAULT) {
+    rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+        rtc::RTCCertificateGenerator::GenerateCertificate(
+            rtc::KeyParams(keyType), rtc::Optional<uint64_t>());
+    if (!certificate) {
+      RTCLogWarning(@"Failed to generate certificate.");
+      return nullptr;
     }
+    nativeConfig->certificates.push_back(certificate);
   }
 
-  return nativeConfig;
+  return nativeConfig.release();
 }
 
 + (webrtc::PeerConnectionInterface::IceTransportsType)
@@ -224,6 +229,16 @@
   }
 }
 
++ (rtc::KeyType)nativeEncryptionKeyTypeForKeyType:
+    (RTCEncryptionKeyType)keyType {
+  switch (keyType) {
+    case RTCEncryptionKeyTypeRSA:
+      return rtc::KT_RSA;
+    case RTCEncryptionKeyTypeECDSA:
+      return rtc::KT_ECDSA;
+  }
+}
+
 + (RTCTcpCandidatePolicy)tcpCandidatePolicyForNativePolicy:
     (webrtc::PeerConnectionInterface::TcpCandidatePolicy)nativePolicy {
   switch (nativePolicy) {
diff --git a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
index 3b7632c..57c6780 100644
--- a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
+++ b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
@@ -197,14 +197,16 @@
                     constraints:(RTCMediaConstraints *)constraints
                        delegate:(id<RTCPeerConnectionDelegate>)delegate {
   NSParameterAssert(factory);
+  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
+      configuration.nativeConfiguration);
+  if (!config)
+    return nullptr;
   if (self = [super init]) {
     _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
-    webrtc::PeerConnectionInterface::RTCConfiguration config =
-        configuration.nativeConfiguration;
     std::unique_ptr<webrtc::MediaConstraints> nativeConstraints =
         constraints.nativeConstraints;
     _peerConnection =
-        factory.nativeFactory->CreatePeerConnection(config,
+        factory.nativeFactory->CreatePeerConnection(*config,
                                                     nativeConstraints.get(),
                                                     nullptr,
                                                     nullptr,
@@ -251,7 +253,11 @@
 }
 
 - (BOOL)setConfiguration:(RTCConfiguration *)configuration {
-  return _peerConnection->SetConfiguration(configuration.nativeConfiguration);
+  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
+      configuration.nativeConfiguration);
+  if (!config)
+    return false;
+  return _peerConnection->SetConfiguration(*config);
 }
 
 - (void)close {
diff --git a/webrtc/sdk/objc/Framework/UnitTests/RTCConfigurationTest.mm b/webrtc/sdk/objc/Framework/UnitTests/RTCConfigurationTest.mm
index eba9ded..9dec115 100644
--- a/webrtc/sdk/objc/Framework/UnitTests/RTCConfigurationTest.mm
+++ b/webrtc/sdk/objc/Framework/UnitTests/RTCConfigurationTest.mm
@@ -44,26 +44,26 @@
   config.continualGatheringPolicy =
       RTCContinualGatheringPolicyGatherContinually;
 
-  webrtc::PeerConnectionInterface::RTCConfiguration nativeConfig =
-      config.nativeConfiguration;
-  EXPECT_EQ(1u, nativeConfig.servers.size());
+  std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration>
+      nativeConfig(config.nativeConfiguration);
+  EXPECT_EQ(1u, nativeConfig->servers.size());
   webrtc::PeerConnectionInterface::IceServer nativeServer =
-      nativeConfig.servers.front();
+      nativeConfig->servers.front();
   EXPECT_EQ(1u, nativeServer.urls.size());
   EXPECT_EQ("stun:stun1.example.net", nativeServer.urls.front());
 
-  EXPECT_EQ(webrtc::PeerConnectionInterface::kRelay, nativeConfig.type);
+  EXPECT_EQ(webrtc::PeerConnectionInterface::kRelay, nativeConfig->type);
   EXPECT_EQ(webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle,
-            nativeConfig.bundle_policy);
+            nativeConfig->bundle_policy);
   EXPECT_EQ(webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
-            nativeConfig.rtcp_mux_policy);
+            nativeConfig->rtcp_mux_policy);
   EXPECT_EQ(webrtc::PeerConnectionInterface::kTcpCandidatePolicyDisabled,
-            nativeConfig.tcp_candidate_policy);
-  EXPECT_EQ(maxPackets, nativeConfig.audio_jitter_buffer_max_packets);
-  EXPECT_EQ(timeout, nativeConfig.ice_connection_receiving_timeout);
-  EXPECT_EQ(interval, nativeConfig.ice_backup_candidate_pair_ping_interval);
+            nativeConfig->tcp_candidate_policy);
+  EXPECT_EQ(maxPackets, nativeConfig->audio_jitter_buffer_max_packets);
+  EXPECT_EQ(timeout, nativeConfig->ice_connection_receiving_timeout);
+  EXPECT_EQ(interval, nativeConfig->ice_backup_candidate_pair_ping_interval);
   EXPECT_EQ(webrtc::PeerConnectionInterface::GATHER_CONTINUALLY,
-            nativeConfig.continual_gathering_policy);
+            nativeConfig->continual_gathering_policy);
 }
 
 @end