// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/webrtc/webrtc_internals.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/browser/webrtc/webrtc_internals_connections_observer.h"
#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
#include "content/public/browser/audio_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/webrtc_event_logger.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "media/audio/audio_debug_recording_session.h"
#include "media/audio/audio_manager.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/audio/public/cpp/debug_recording_session_factory.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/shell_dialogs/selected_file_info.h"

using base::ProcessId;
using std::string;

namespace content {

namespace {

const base::FilePath::CharType kEventLogFilename[] =
    FILE_PATH_LITERAL("event_log");

constexpr char kGetUserMedia[] = "getUserMedia";
constexpr char kGetDisplayMedia[] = "getDisplayMedia";

// This is intended to limit DoS attacks against the browser process consisting
// of many getUserMedia()/getDisplayMedia() calls. See https://crbug.com/804440.
const size_t kMaxMediaEntries = 1000;

// Makes sure that |dict| has a List under path "log".
base::Value::List& EnsureLogList(base::Value::Dict& dict) {
  base::Value::List* log = dict.FindList("log");
  if (log)
    return *log;
  return dict.Set("log", base::Value::List())->GetList();
}

// Removes the log entry associated with a given record.
void FreeLogList(base::Value* value) {
  DCHECK(value->is_dict());
  value->GetDict().Remove("log");
}

}  // namespace

WebRTCInternals* WebRTCInternals::g_webrtc_internals = nullptr;

WebRTCInternals::PendingUpdate::PendingUpdate(const std::string& event_name,
                                              base::Value event_data)
    : event_name_(event_name), event_data_(std::move(event_data)) {}

WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other)
    : event_name_(other.event_name_),
      event_data_(std::move(other.event_data_)) {}

WebRTCInternals::PendingUpdate::~PendingUpdate() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

const std::string& WebRTCInternals::PendingUpdate::event_name() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return event_name_;
}

const base::Value* WebRTCInternals::PendingUpdate::event_data() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return event_data_.is_none() ? nullptr : &event_data_;
}

WebRTCInternals::WebRTCInternals() : WebRTCInternals(500, true) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
                                 bool should_block_power_saving)
    : peer_connection_data_(base::Value::List()),
      selection_type_(SelectionType::kAudioDebugRecordings),
      command_line_derived_logging_path_(
          base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
              switches::kWebRtcLocalEventLogging)),
      event_log_recordings_(false),
      num_connected_connections_(0),
      should_block_power_saving_(should_block_power_saving),
      aggregate_updates_ms_(aggregate_updates_ms) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!g_webrtc_internals);

  const base::FilePath default_path =
      GetContentClient()->browser()->GetDefaultDownloadDirectory();
  audio_debug_recordings_file_path_ = default_path;
  event_log_recordings_file_path_ = default_path;
  data_channel_recordings_file_path_ = default_path;

  if (!default_path.empty()) {
    audio_debug_recordings_file_path_ =
        audio_debug_recordings_file_path_.Append(
            FILE_PATH_LITERAL("audio_debug"));
    event_log_recordings_file_path_ =
        event_log_recordings_file_path_.Append(kEventLogFilename);
    data_channel_recordings_file_path_ =
        data_channel_recordings_file_path_.Append(
            FILE_PATH_LITERAL("data_channel"));
  }

  // Allow command-line based setting of (local) WebRTC event logging.
  if (!command_line_derived_logging_path_.empty()) {
    const base::FilePath local_logs_path =
        command_line_derived_logging_path_.Append(kEventLogFilename);
    WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
    if (logger) {
      logger->EnableLocalLogging(local_logs_path);
    }
    // For clarity's sake, though these aren't supposed to be regarded now:
    event_log_recordings_ = true;
    event_log_recordings_file_path_.clear();
  }

  g_webrtc_internals = this;
}

WebRTCInternals::~WebRTCInternals() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(g_webrtc_internals);
  g_webrtc_internals = nullptr;

  if (select_file_dialog_) {
    select_file_dialog_->ListenerDestroyed();
  }
}

WebRTCInternals* WebRTCInternals::CreateSingletonInstance() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!g_webrtc_internals);
  g_webrtc_internals = new WebRTCInternals;
  return g_webrtc_internals;
}

WebRTCInternals* WebRTCInternals::GetInstance() {
  // TODO(crbug.com/40837773): DCHECK calling from UI thread.
  // Currently, some unit tests call this from outside of the UI thread,
  // but that's not a real issue as these tests neglect setting
  // `g_webrtc_internals` to begin with, and therefore just ignore it.
  DCHECK(!g_webrtc_internals || BrowserThread::CurrentlyOn(BrowserThread::UI));
  return g_webrtc_internals;
}

void WebRTCInternals::OnPeerConnectionAdded(GlobalRenderFrameHostId frame_id,
                                            int lid,
                                            ProcessId pid,
                                            const string& url,
                                            const string& rtc_configuration) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(tommi): Consider changing this design so that webrtc-internals has
  // minimal impact if chrome://webrtc-internals isn't open.

  base::Value::Dict dict;
  dict.Set("rid", frame_id.child_id);
  dict.Set("lid", lid);
  dict.Set("pid", static_cast<int>(pid));
  dict.Set("rtcConfiguration", rtc_configuration);
  dict.Set("url", url);
  dict.Set("isOpen", true);
  dict.Set("connected", false);

  if (!observers_.empty())
    SendUpdate("add-peer-connection", dict.Clone());

  peer_connection_data().Append(std::move(dict));

  if (render_process_id_set_.insert(frame_id.child_id).second) {
    RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
    if (host)
      host->AddObserver(this);
  }
}

void WebRTCInternals::OnPeerConnectionRemoved(GlobalRenderFrameHostId frame_id,
                                              int lid) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto it = FindRecord(frame_id, lid);
  if (it != peer_connection_data().end()) {
    MaybeClosePeerConnection(*it);
    peer_connection_data().erase(it);
  }

  if (!observers_.empty()) {
    base::Value::Dict id;
    id.Set("rid", frame_id.child_id);
    id.Set("lid", lid);
    SendUpdate("remove-peer-connection", std::move(id));
  }
}

void WebRTCInternals::OnPeerConnectionUpdated(GlobalRenderFrameHostId frame_id,
                                              int lid,
                                              const string& type,
                                              const string& value) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  auto it = FindRecord(frame_id, lid);
  if (it == peer_connection_data().end())
    return;

  if (type == "iceconnectionstatechange") {
    if (value == "connected" || value == "checking" || value == "completed") {
      MaybeMarkPeerConnectionAsConnected(*it);
    } else if (value == "failed" || value == "disconnected" ||
               value == "closed" || value == "new") {
      MaybeMarkPeerConnectionAsNotConnected(*it);
    }
  } else if (type == "close") {
    MaybeClosePeerConnection(*it);
  } else if (type == "setConfiguration") {
    // Update the configuration we have for this connection.
    it->GetDict().Set("rtcConfiguration", value);
  }

  // Don't update entries if there aren't any observers.
  if (observers_.empty())
    return;

  base::Value::Dict log_entry;

  double epoch_time = base::Time::Now().InMillisecondsFSinceUnixEpoch();
  string time = base::NumberToString(epoch_time);
  log_entry.Set("time", time);
  log_entry.Set("type", type);
  log_entry.Set("value", value);

  base::Value::Dict update;
  update.Set("rid", frame_id.child_id);
  update.Set("lid", lid);
  update.Merge(log_entry.Clone());

  SendUpdate("update-peer-connection", std::move(update));

  // Append the update to the end of the log.
  EnsureLogList(it->GetDict()).Append(std::move(log_entry));
}

void WebRTCInternals::OnAddStandardStats(GlobalRenderFrameHostId frame_id,
                                         int lid,
                                         base::Value::List value) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (observers_.empty())
    return;

  base::Value::Dict dict;
  dict.Set("rid", frame_id.child_id);
  dict.Set("lid", lid);

  dict.Set("reports", std::move(value));

  SendUpdate("add-standard-stats", std::move(dict));
}

void WebRTCInternals::OnGetMedia(const std::string& request_type,
                                 GlobalRenderFrameHostId frame_id,
                                 base::ProcessId pid,
                                 int request_id,
                                 bool audio,
                                 bool video,
                                 const std::string& audio_constraints,
                                 const std::string& video_constraints) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (get_user_media_requests_.size() >= kMaxMediaEntries) {
    LOG(WARNING) << "Maximum number of tracked getUserMedia/getDisplayMedia "
                    "requests reached in webrtc-internals.";
    return;
  }

  RenderFrameHost* rfh = RenderFrameHost::FromID(frame_id);
  // Frame may be gone (and does not exist in tests).
  std::string origin = rfh ? rfh->GetLastCommittedOrigin().Serialize() : "";

  base::Value::Dict dict;
  dict.Set("rid", frame_id.child_id);
  dict.Set("pid", static_cast<int>(pid));
  dict.Set("request_id", request_id);
  dict.Set("request_type", request_type);
  dict.Set("origin", origin);
  dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
  if (audio)
    dict.Set("audio", audio_constraints);
  if (video)
    dict.Set("video", video_constraints);

  if (!observers_.empty())
    SendUpdate("add-media", dict.Clone());

  get_user_media_requests_.Append(std::move(dict));

  if (render_process_id_set_.insert(frame_id.child_id).second) {
    RenderProcessHost* rph = RenderProcessHost::FromID(frame_id.child_id);
    if (rph)
      rph->AddObserver(this);
  }
}

void WebRTCInternals::OnGetMediaSuccess(const std::string& request_type,
                                        GlobalRenderFrameHostId frame_id,
                                        base::ProcessId pid,
                                        int request_id,
                                        const std::string& stream_id,
                                        const std::string& audio_track_info,
                                        const std::string& video_track_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (get_user_media_requests_.size() >= kMaxMediaEntries) {
    LOG(WARNING) << "Maximum number of tracked getUserMedia/getDisplayMedia "
                    "requests reached in webrtc-internals.";
    return;
  }

  base::Value::Dict dict;
  dict.Set("rid", frame_id.child_id);
  dict.Set("pid", static_cast<int>(pid));
  dict.Set("request_id", request_id);
  dict.Set("request_type", request_type);
  dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
  dict.Set("stream_id", stream_id);
  if (!audio_track_info.empty())
    dict.Set("audio_track_info", audio_track_info);
  if (!video_track_info.empty())
    dict.Set("video_track_info", video_track_info);

  if (!observers_.empty())
    SendUpdate("update-media", dict.Clone());

  get_user_media_requests_.Append(std::move(dict));

  if (render_process_id_set_.insert(frame_id.child_id).second) {
    RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
    if (host)
      host->AddObserver(this);
  }
}

void WebRTCInternals::OnGetMediaFailure(const std::string& request_type,
                                        GlobalRenderFrameHostId frame_id,
                                        base::ProcessId pid,
                                        int request_id,
                                        const std::string& error,
                                        const std::string& error_message) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (get_user_media_requests_.size() >= kMaxMediaEntries) {
    LOG(WARNING) << "Maximum number of tracked /getDisplayMedia "
                    "requests reached in webrtc-internals.";
    return;
  }

  base::Value::Dict dict;
  dict.Set("rid", frame_id.child_id);
  dict.Set("pid", static_cast<int>(pid));
  dict.Set("request_id", request_id);
  dict.Set("request_type", request_type);
  dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
  dict.Set("error", error);
  dict.Set("error_message", error_message);

  if (!observers_.empty())
    SendUpdate("update-media", dict.Clone());

  get_user_media_requests_.Append(std::move(dict));

  if (render_process_id_set_.insert(frame_id.child_id).second) {
    RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
    if (host)
      host->AddObserver(this);
  }
}

void WebRTCInternals::OnGetUserMedia(GlobalRenderFrameHostId frame_id,
                                     base::ProcessId pid,
                                     int request_id,
                                     bool audio,
                                     bool video,
                                     const std::string& audio_constraints,
                                     const std::string& video_constraints) {
  OnGetMedia(kGetUserMedia, frame_id, pid, request_id, audio, video,
             audio_constraints, video_constraints);
}

void WebRTCInternals::OnGetUserMediaSuccess(
    GlobalRenderFrameHostId frame_id,
    base::ProcessId pid,
    int request_id,
    const std::string& stream_id,
    const std::string& audio_track_info,
    const std::string& video_track_info) {
  OnGetMediaSuccess(kGetUserMedia, frame_id, pid, request_id, stream_id,
                    audio_track_info, video_track_info);
}

void WebRTCInternals::OnGetUserMediaFailure(GlobalRenderFrameHostId frame_id,
                                            base::ProcessId pid,
                                            int request_id,
                                            const std::string& error,
                                            const std::string& error_message) {
  OnGetMediaFailure(kGetUserMedia, frame_id, pid, request_id, error,
                    error_message);
}

void WebRTCInternals::OnGetDisplayMedia(GlobalRenderFrameHostId frame_id,
                                        base::ProcessId pid,
                                        int request_id,
                                        bool audio,
                                        bool video,
                                        const std::string& audio_constraints,
                                        const std::string& video_constraints) {
  OnGetMedia(kGetDisplayMedia, frame_id, pid, request_id, audio, video,
             audio_constraints, video_constraints);
}

void WebRTCInternals::OnGetDisplayMediaSuccess(
    GlobalRenderFrameHostId frame_id,
    base::ProcessId pid,
    int request_id,
    const std::string& stream_id,
    const std::string& audio_track_info,
    const std::string& video_track_info) {
  OnGetMediaSuccess(kGetDisplayMedia, frame_id, pid, request_id, stream_id,
                    audio_track_info, video_track_info);
}

void WebRTCInternals::OnGetDisplayMediaFailure(
    GlobalRenderFrameHostId frame_id,
    base::ProcessId pid,
    int request_id,
    const std::string& error,
    const std::string& error_message) {
  OnGetMediaFailure(kGetDisplayMedia, frame_id, pid, request_id, error,
                    error_message);
}

void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.AddObserver(observer);
}

void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  observers_.RemoveObserver(observer);
  if (!observers_.empty())
    return;

  // Disables event log and audio debug recordings if enabled and the last
  // webrtc-internals page is going away.
  DisableAudioDebugRecordings();
  if (CanToggleEventLogRecordings()) {
    // Do not disable event log recording when the browser was started
    // with the flag to enable the recordings on the command line.
    DisableLocalEventLogRecordings();
  }

  // TODO(tommi): Consider removing all the peer_connection_data().
  for (auto& dictionary : peer_connection_data())
    FreeLogList(&dictionary);
}

void WebRTCInternals::AddConnectionsObserver(
    WebRtcInternalsConnectionsObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  connections_observers_.AddObserver(observer);
}

void WebRTCInternals::RemoveConnectionsObserver(
    WebRtcInternalsConnectionsObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  connections_observers_.RemoveObserver(observer);
}

void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (peer_connection_data().size() > 0)
    observer->OnUpdate("update-all-peer-connections", &peer_connection_data_);

  for (const auto& request : get_user_media_requests_) {
    // If there is a stream_id key or an error key this is an update.
    if (request.GetDict().FindString("stream_id") ||
        request.GetDict().FindString("error")) {
      observer->OnUpdate("update-media", &request);
    } else {
      observer->OnUpdate("add-media", &request);
    }
  }
}

void WebRTCInternals::EnableAudioDebugRecordings(
    content::WebContents* web_contents) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(IS_ANDROID)
  EnableAudioDebugRecordingsOnAllRenderProcessHosts();
#else
  MaybeShowSelectFileDialog(web_contents, SelectionType::kAudioDebugRecordings);
#endif
}

void WebRTCInternals::DisableAudioDebugRecordings() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!audio_debug_recording_session_)
    return;
  audio_debug_recording_session_.reset();

  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    i.GetCurrentValue()->DisableAudioDebugRecordings();
  }
}

bool WebRTCInternals::IsAudioDebugRecordingsEnabled() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return !!audio_debug_recording_session_;
}

const base::FilePath& WebRTCInternals::GetAudioDebugRecordingsFilePath() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return audio_debug_recordings_file_path_;
}

void WebRTCInternals::EnableLocalEventLogRecordings(
    content::WebContents* web_contents) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(web_contents);
  DCHECK(CanToggleEventLogRecordings());

#if BUILDFLAG(IS_ANDROID)
  WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
  if (logger) {
    logger->EnableLocalLogging(event_log_recordings_file_path_);
  }
#else
  MaybeShowSelectFileDialog(web_contents, SelectionType::kRtcEventLogs);
#endif
}

void WebRTCInternals::DisableLocalEventLogRecordings() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  event_log_recordings_ = false;
  DCHECK(CanToggleEventLogRecordings());
  WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
  if (logger) {
    logger->DisableLocalLogging();
  }
}

void WebRTCInternals::EnableDataChannelRecordings(
    content::WebContents* web_contents) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(IS_ANDROID)
  WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
  if (logger) {
    logger->EnableDataChannelLogging(data_channel_recordings_file_path_);
  }
#else
  MaybeShowSelectFileDialog(web_contents,
                            SelectionType::kDataChannelRecordings);
#endif
}

void WebRTCInternals::DisableDataChannelRecordings() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  data_channel_recording_active_ = false;
  WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
  if (logger) {
    logger->DisableDataChannelLogging();
  }
}

bool WebRTCInternals::IsEventLogRecordingsEnabled() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return event_log_recordings_;
}

bool WebRTCInternals::IsDataChannelRecordingsEnabled() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return data_channel_recording_active_;
}

bool WebRTCInternals::CanToggleEventLogRecordings() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return command_line_derived_logging_path_.empty();
}

void WebRTCInternals::SendUpdate(const std::string& event_name,
                                 base::Value event_data) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!observers_.empty());

  bool queue_was_empty = pending_updates_.empty();
  pending_updates_.push(PendingUpdate(event_name, std::move(event_data)));

  if (queue_was_empty) {
    GetUIThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&WebRTCInternals::ProcessPendingUpdates,
                       weak_factory_.GetWeakPtr()),
        base::Milliseconds(aggregate_updates_ms_));
  }
}

void WebRTCInternals::SendUpdate(const std::string& event_name,
                                 base::Value::Dict event_data) {
  SendUpdate(event_name, base::Value(std::move(event_data)));
}

void WebRTCInternals::RenderProcessExited(
    RenderProcessHost* host,
    const ChildProcessTerminationInfo& info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  OnRendererExit(host->GetDeprecatedID());
  render_process_id_set_.erase(host->GetDeprecatedID());
  host->RemoveObserver(this);
}

void WebRTCInternals::MaybeShowSelectFileDialog(
    content::WebContents* web_contents,
    SelectionType log_type) {
  if (select_file_dialog_) {
    return;
  }

  base::FilePath* file_path = nullptr;
  switch (log_type) {
    case (SelectionType::kRtcEventLogs): {
      file_path = &event_log_recordings_file_path_;
      break;
    }
    case (SelectionType::kAudioDebugRecordings): {
      file_path = &audio_debug_recordings_file_path_;
      break;
    }
    case (SelectionType::kDataChannelRecordings): {
      file_path = &data_channel_recordings_file_path_;
      break;
    }
  }
  CHECK(file_path);

  selection_type_ = log_type;
  select_file_dialog_ = ui::SelectFileDialog::Create(
      this,
      GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
  select_file_dialog_->SelectFile(
      ui::SelectFileDialog::SELECT_SAVEAS_FILE,
      /*title=*/std::u16string(), *file_path, /*file_types=*/nullptr,
      /*file_type_index=*/0,
      /*default_extension=*/base::FilePath::StringType(),
      web_contents->GetTopLevelNativeWindow());
}

void WebRTCInternals::FileSelected(const ui::SelectedFileInfo& file,
                                   int /* unused_index */) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  switch (selection_type_) {
    case SelectionType::kRtcEventLogs: {
      event_log_recordings_file_path_ = file.path();
      event_log_recordings_ = true;
      WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
      if (logger) {
        logger->EnableLocalLogging(file.path());
      }
      break;
    }
    case SelectionType::kAudioDebugRecordings: {
      audio_debug_recordings_file_path_ = file.path();
      EnableAudioDebugRecordingsOnAllRenderProcessHosts();
      break;
    }
    case SelectionType::kDataChannelRecordings: {
      data_channel_recordings_file_path_ = file.path();
      data_channel_recording_active_ = true;
      WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
      if (logger) {
        logger->EnableDataChannelLogging(file.path());
      }
      break;
    }
    default: {
      NOTREACHED();
    }
  }
  select_file_dialog_.reset();
}

void WebRTCInternals::FileSelectionCanceled() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  switch (selection_type_) {
    case SelectionType::kRtcEventLogs:
      SendUpdate("event-log-recordings-file-selection-cancelled",
                 base::Value());
      break;
    case SelectionType::kAudioDebugRecordings:
      SendUpdate("audio-debug-recordings-file-selection-cancelled",
                 base::Value());
      break;
    case SelectionType::kDataChannelRecordings:
      SendUpdate("data-channel-recordings-file-selection-cancelled",
                 base::Value());
      break;
    default:
      NOTREACHED();
  }
  select_file_dialog_.reset();
}

void WebRTCInternals::OnRendererExit(int render_process_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Iterates from the end of the list to remove the PeerConnections created
  // by the exiting renderer.
  for (int i = peer_connection_data().size() - 1; i >= 0; --i) {
    DCHECK(peer_connection_data()[i].is_dict());

    std::optional<int> this_rid, this_lid;
    this_rid = peer_connection_data()[i].GetDict().FindInt("rid");
    this_lid = peer_connection_data()[i].GetDict().FindInt("lid");

    if (this_rid.value_or(0) == render_process_id) {
      if (!observers_.empty()) {
        base::Value::Dict update;
        update.Set("rid", this_rid.value_or(0));
        update.Set("lid", this_lid.value_or(0));
        SendUpdate("remove-peer-connection", std::move(update));
      }
      MaybeClosePeerConnection(peer_connection_data()[i]);
      peer_connection_data().erase(peer_connection_data().begin() + i);
    }
  }
  UpdateWakeLock();

  bool found_any = false;
  // Iterates from the end of the list to remove the getUserMedia requests
  // created by the exiting renderer.
  for (int i = get_user_media_requests_.size() - 1; i >= 0; --i) {
    DCHECK(get_user_media_requests_[i].is_dict());

    std::optional<int> this_rid =
        get_user_media_requests_[i].GetDict().FindInt("rid");

    if (this_rid.value_or(0) == render_process_id) {
      get_user_media_requests_.erase(get_user_media_requests_.begin() + i);
      found_any = true;
    }
  }

  if (found_any && !observers_.empty()) {
    base::Value::Dict update;
    update.Set("rid", render_process_id);
    SendUpdate("remove-media-for-renderer", std::move(update));
  }
}

void WebRTCInternals::EnableAudioDebugRecordingsOnAllRenderProcessHosts() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!audio_debug_recording_session_);
  mojo::PendingRemote<audio::mojom::DebugRecording> debug_recording;
  content::GetAudioService().BindDebugRecording(
      debug_recording.InitWithNewPipeAndPassReceiver());
  audio_debug_recording_session_ = audio::CreateAudioDebugRecordingSession(
      audio_debug_recordings_file_path_, std::move(debug_recording));

  for (RenderProcessHost::iterator i(
           content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    i.GetCurrentValue()->EnableAudioDebugRecordings(
        audio_debug_recordings_file_path_);
  }
}

void WebRTCInternals::MaybeClosePeerConnection(base::Value& record) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  std::optional<bool> is_open = record.GetDict().FindBool("isOpen");
  DCHECK(is_open.has_value());
  if (!*is_open)
    return;

  record.GetDict().Set("isOpen", false);
  MaybeMarkPeerConnectionAsNotConnected(record);
}

void WebRTCInternals::MaybeMarkPeerConnectionAsConnected(base::Value& record) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  bool was_connected = record.GetDict().FindBool("connected").value_or(true);
  if (!was_connected) {
    ++num_connected_connections_;
    record.GetDict().Set("connected", true);
    UpdateWakeLock();
    for (auto& observer : connections_observers_)
      observer.OnConnectionsCountChange(num_connected_connections_);
  }
}

void WebRTCInternals::MaybeMarkPeerConnectionAsNotConnected(
    base::Value& record) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  bool was_connected = record.GetDict().FindBool("connected").value_or(false);
  if (was_connected) {
    record.GetDict().Set("connected", false);
    --num_connected_connections_;
    DCHECK_GE(num_connected_connections_, 0);
    UpdateWakeLock();
    for (auto& observer : connections_observers_)
      observer.OnConnectionsCountChange(num_connected_connections_);
  }
}

void WebRTCInternals::UpdateWakeLock() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!should_block_power_saving_)
    return;

  if (num_connected_connections_ == 0) {
    DVLOG(1)
        << ("Cancel the wake lock on application suspension since no "
            "PeerConnections are active anymore.");
    GetWakeLock()->CancelWakeLock();
  } else {
    DCHECK_GT(num_connected_connections_, 0);
    DVLOG(1) << ("Preventing the application from being suspended while one or "
                 "more PeerConnections are active.");
    GetWakeLock()->RequestWakeLock();
  }
}

device::mojom::WakeLock* WebRTCInternals::GetWakeLock() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // Here is a lazy binding, and will not reconnect after connection error.
  if (!wake_lock_) {
    mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
    GetDeviceService().BindWakeLockProvider(
        wake_lock_provider.BindNewPipeAndPassReceiver());
    wake_lock_provider->GetWakeLockWithoutContext(
        device::mojom::WakeLockType::kPreventAppSuspension,
        device::mojom::WakeLockReason::kOther,
        "WebRTC has active PeerConnections",
        wake_lock_.BindNewPipeAndPassReceiver());
  }
  return wake_lock_.get();
}

void WebRTCInternals::ProcessPendingUpdates() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  while (!pending_updates_.empty()) {
    const auto& update = pending_updates_.front();
    for (auto& observer : observers_)
      observer.OnUpdate(update.event_name(), update.event_data());
    pending_updates_.pop();
  }
}

base::Value::List::iterator WebRTCInternals::FindRecord(
    GlobalRenderFrameHostId frame_id,
    int lid) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  for (auto it = peer_connection_data().begin();
       it != peer_connection_data().end(); ++it) {
    DCHECK(it->is_dict());

    int this_rid = it->GetDict().FindInt("rid").value_or(0);
    int this_lid = it->GetDict().FindInt("lid").value_or(0);

    if (this_rid == frame_id.child_id && this_lid == lid)
      return it;
  }
  return peer_connection_data().end();
}
}  // namespace content
