blob: 63da8da0e0f674ecf9e75dd44cadeaf5e0b0497d [file] [log] [blame]
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/rtc_certificate_generator.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/render_thread_impl.h"
#include "media/media_buildflags.h"
#include "third_party/webrtc/api/scoped_refptr.h"
#include "third_party/webrtc/rtc_base/rtc_certificate.h"
#include "third_party/webrtc/rtc_base/rtc_certificate_generator.h"
#include "url/gurl.h"
namespace content {
namespace {
rtc::KeyParams WebRTCKeyParamsToKeyParams(
const blink::WebRTCKeyParams& key_params) {
switch (key_params.KeyType()) {
case blink::kWebRTCKeyTypeRSA:
return rtc::KeyParams::RSA(key_params.RsaParams().mod_length,
key_params.RsaParams().pub_exp);
case blink::kWebRTCKeyTypeECDSA:
return rtc::KeyParams::ECDSA(
static_cast<rtc::ECCurve>(key_params.EcCurve()));
default:
NOTREACHED();
return rtc::KeyParams();
}
}
// A certificate generation request spawned by
// |GenerateCertificateWithOptionalExpiration|. This
// is handled by a separate class so that reference counting can keep the
// request alive independently of the |RTCCertificateGenerator| that spawned it.
class RTCCertificateGeneratorRequest
: public base::RefCountedThreadSafe<RTCCertificateGeneratorRequest> {
private:
using CertificateCallbackPtr = std::unique_ptr<
blink::WebRTCCertificateCallback,
base::OnTaskRunnerDeleter>;
public:
RTCCertificateGeneratorRequest(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
const scoped_refptr<base::SingleThreadTaskRunner>& worker_thread)
: main_thread_(main_thread),
worker_thread_(worker_thread) {
DCHECK(main_thread_);
DCHECK(worker_thread_);
}
void GenerateCertificateAsync(
const blink::WebRTCKeyParams& key_params,
const absl::optional<uint64_t>& expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(observer);
CertificateCallbackPtr transition(observer.release(),
base::OnTaskRunnerDeleter(main_thread_));
worker_thread_->PostTask(
FROM_HERE,
base::BindOnce(
&RTCCertificateGeneratorRequest::GenerateCertificateOnWorkerThread,
this, key_params, expires_ms, std::move(transition)));
}
private:
friend class base::RefCountedThreadSafe<RTCCertificateGeneratorRequest>;
~RTCCertificateGeneratorRequest() {}
void GenerateCertificateOnWorkerThread(
const blink::WebRTCKeyParams key_params,
const absl::optional<uint64_t> expires_ms,
CertificateCallbackPtr observer) {
DCHECK(worker_thread_->BelongsToCurrentThread());
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificateGenerator::GenerateCertificate(
WebRTCKeyParamsToKeyParams(key_params), expires_ms);
main_thread_->PostTask(
FROM_HERE,
base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
this, std::move(observer), certificate));
}
void DoCallbackOnMainThread(
CertificateCallbackPtr observer,
rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(observer);
if (certificate)
observer->OnSuccess(std::move(certificate));
else
observer->OnError();
}
// The main thread is the renderer thread.
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
// The WebRTC worker thread.
const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_;
};
void GenerateCertificateWithOptionalExpiration(
const blink::WebRTCKeyParams& key_params,
const absl::optional<uint64_t>& expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK(WebRTCKeyParamsToKeyParams(key_params).IsValid());
PeerConnectionDependencyFactory* pc_dependency_factory =
RenderThreadImpl::current()->GetPeerConnectionDependencyFactory();
pc_dependency_factory->EnsureInitialized();
scoped_refptr<RTCCertificateGeneratorRequest> request =
new RTCCertificateGeneratorRequest(
task_runner, pc_dependency_factory->GetWebRtcWorkerThread());
request->GenerateCertificateAsync(key_params, expires_ms,
std::move(observer));
}
} // namespace
void RTCCertificateGenerator::GenerateCertificate(
const blink::WebRTCKeyParams& key_params,
std::unique_ptr<blink::WebRTCCertificateCallback> observer,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
GenerateCertificateWithOptionalExpiration(key_params, absl::nullopt,
std::move(observer), task_runner);
}
void RTCCertificateGenerator::GenerateCertificateWithExpiration(
const blink::WebRTCKeyParams& key_params,
uint64_t expires_ms,
std::unique_ptr<blink::WebRTCCertificateCallback> observer,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
GenerateCertificateWithOptionalExpiration(key_params, expires_ms,
std::move(observer), task_runner);
}
bool RTCCertificateGenerator::IsSupportedKeyParams(
const blink::WebRTCKeyParams& key_params) {
return WebRTCKeyParamsToKeyParams(key_params).IsValid();
}
rtc::scoped_refptr<rtc::RTCCertificate> RTCCertificateGenerator::FromPEM(
blink::WebString pem_private_key,
blink::WebString pem_certificate) {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificate::FromPEM(rtc::RTCCertificatePEM(
pem_private_key.Utf8(), pem_certificate.Utf8()));
if (!certificate)
return nullptr;
return certificate;
}
} // namespace content