blob: d2495adc2217ec6e090785327e879634f0a1e3c9 [file] [log] [blame]
// Copyright 2019 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 "chrome/renderer/media/webrtc_logging_agent_impl.h"
#include "base/no_destructor.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
namespace chrome {
namespace {
constexpr base::TimeDelta kMinTimeSinceLastLogBufferSend =
base::TimeDelta::FromMilliseconds(100);
constexpr base::TimeDelta kSendLogBufferDelay =
base::TimeDelta::FromMilliseconds(200);
// There can be only one registered WebRtcLogMessageDelegate, and so this class
// abstracts away that detail, so that we can set callbacks more than once. It
// also abstracts away the detail of what thread the LogMessage call runs on.
class WebRtcLogMessageDelegateImpl : public blink::WebRtcLogMessageDelegate {
public:
static WebRtcLogMessageDelegateImpl* GetInstance() {
static base::NoDestructor<WebRtcLogMessageDelegateImpl> instance;
return instance.get();
}
void Start(
base::RepeatingCallback<void(mojom::WebRtcLoggingMessagePtr)> callback) {
auto task_runner = base::SequencedTaskRunnerHandle::Get();
{
base::AutoLock locked(lock_);
task_runner_ = task_runner;
callback_ = std::move(callback);
}
blink::InitWebRtcLogging();
}
void Stop() {
{
base::AutoLock locked(lock_);
task_runner_ = nullptr;
callback_.Reset();
}
}
// blink::WebRtcLogMessageDelegate methods:
void LogMessage(const std::string& message) override {
// Called from a random thread.
auto data = mojom::WebRtcLoggingMessage::New(base::Time::Now(), message);
{
base::AutoLock locked(lock_);
if (callback_)
task_runner_->PostTask(FROM_HERE,
base::BindOnce(callback_, std::move(data)));
}
}
WebRtcLogMessageDelegateImpl() { blink::InitWebRtcLoggingDelegate(this); }
private:
~WebRtcLogMessageDelegateImpl() override = default;
base::Lock lock_;
base::RepeatingCallback<void(mojom::WebRtcLoggingMessagePtr)> callback_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
};
} // namespace
WebRtcLoggingAgentImpl::WebRtcLoggingAgentImpl() = default;
WebRtcLoggingAgentImpl::~WebRtcLoggingAgentImpl() = default;
void WebRtcLoggingAgentImpl::AddReceiver(
mojo::PendingReceiver<mojom::WebRtcLoggingAgent> receiver) {
self_receiver_set_.Add(this, std::move(receiver));
}
void WebRtcLoggingAgentImpl::Start(
mojo::PendingRemote<mojom::WebRtcLoggingClient> pending_client) {
// We only support one client at a time. OK to drop any existing client.
client_.reset();
client_.Bind(std::move(pending_client));
WebRtcLogMessageDelegateImpl::GetInstance()->Start(base::BindRepeating(
&WebRtcLoggingAgentImpl::OnNewMessage, weak_factory_.GetWeakPtr()));
}
void WebRtcLoggingAgentImpl::Stop() {
if (!log_buffer_.empty())
SendLogBuffer();
WebRtcLogMessageDelegateImpl::GetInstance()->Stop();
if (client_) {
client_->OnStopped();
client_.reset();
}
}
void WebRtcLoggingAgentImpl::OnNewMessage(
mojom::WebRtcLoggingMessagePtr message) {
// We may have already been asked to stop.
if (!client_)
return;
log_buffer_.emplace_back(std::move(message));
if (log_buffer_.size() > 1) {
// A delayed task has already been posted for sending the buffer contents.
return;
}
if ((base::TimeTicks::Now() - last_log_buffer_send_) >
kMinTimeSinceLastLogBufferSend) {
SendLogBuffer();
} else {
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&WebRtcLoggingAgentImpl::SendLogBuffer,
weak_factory_.GetWeakPtr()),
kSendLogBufferDelay);
}
}
void WebRtcLoggingAgentImpl::SendLogBuffer() {
last_log_buffer_send_ = base::TimeTicks::Now();
if (client_) {
client_->OnAddMessages(std::move(log_buffer_));
} else {
log_buffer_.clear();
}
}
} // namespace chrome