| // 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 |