blob: d8915f4017ea0da2d254bed2db91525270165015 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]94fb5102013-01-23 09:00:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
mcasas6b8c0c82016-07-29 23:04:355#include "content/browser/webrtc/webrtc_internals.h"
[email protected]94fb5102013-01-23 09:00:476
avi7f277562015-12-25 02:41:267#include <stddef.h>
8
dcheng031a8f82016-09-08 21:04:339#include <memory>
10#include <utility>
11
Elad Alonc0928bf12018-02-28 19:35:1712#include "base/command_line.h"
Avi Drissmanadac21992023-01-11 23:46:3913#include "base/functional/bind.h"
David Sandersd4bf5eb2022-03-17 07:12:0514#include "base/observer_list.h"
[email protected]84e83b32014-07-01 23:10:1515#include "base/strings/string_number_conversions.h"
avi7f277562015-12-25 02:41:2616#include "build/build_config.h"
[email protected]fc2b46b2014-05-03 16:33:4517#include "content/browser/web_contents/web_contents_view.h"
Tarun Bansalf153d6832019-06-17 18:18:0518#include "content/browser/webrtc/webrtc_internals_connections_observer.h"
mcasas6b8c0c82016-07-29 23:04:3519#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
Ken Rockot72964402019-12-06 10:40:5120#include "content/public/browser/audio_service.h"
Eric Seckler8652dcd52018-09-20 10:42:2821#include "content/public/browser/browser_task_traits.h"
[email protected]94fb5102013-01-23 09:00:4722#include "content/public/browser/browser_thread.h"
[email protected]820b9b262014-05-09 14:47:1623#include "content/public/browser/content_browser_client.h"
Ken Rockot44d73be2019-12-12 22:25:5924#include "content/public/browser/device_service.h"
David Sanders2ee1f3502022-03-16 07:21:1925#include "content/public/browser/render_process_host.h"
[email protected]bf3657b2013-12-17 12:36:1726#include "content/public/browser/web_contents.h"
Elad Alon12ecdf02018-03-14 12:07:3127#include "content/public/browser/webrtc_event_logger.h"
Hans Wennborg5ffd1392019-10-16 11:00:0228#include "content/public/common/content_client.h"
Elad Alonc0928bf12018-02-28 19:35:1729#include "content/public/common/content_switches.h"
Marina Ciocea741a4fb12018-01-27 09:55:1230#include "media/audio/audio_debug_recording_session.h"
grunell086a4112017-03-02 09:23:0431#include "media/audio/audio_manager.h"
Scott Violeta35f9a42018-03-22 22:00:4432#include "media/media_buildflags.h"
Miyoung Shinff876662019-09-05 17:52:0433#include "mojo/public/cpp/bindings/pending_receiver.h"
Marina Cioceac6d46d2f2018-02-26 15:21:2834#include "services/audio/public/cpp/debug_recording_session_factory.h"
Ke He31d0bb02018-02-24 07:16:2435#include "services/device/public/mojom/wake_lock_provider.mojom.h"
Brett Wilson804e83c2017-08-18 22:57:3336#include "ui/shell_dialogs/select_file_policy.h"
Avi Drissmand0b88a2b2023-12-28 22:49:3837#include "ui/shell_dialogs/selected_file_info.h"
ivoccf0887d2016-07-07 18:23:5338
[email protected]94fb5102013-01-23 09:00:4739using base::ProcessId;
[email protected]94fb5102013-01-23 09:00:4740using std::string;
41
[email protected]64ccac32013-01-29 21:40:0442namespace content {
43
44namespace {
marshall8ad27422014-09-19 18:53:0045
Elad Alonc0928bf12018-02-28 19:35:1746const base::FilePath::CharType kEventLogFilename[] =
47 FILE_PATH_LITERAL("event_log");
48
Philipp Hancke89add412022-11-18 14:07:0749constexpr char kGetUserMedia[] = "getUserMedia";
50constexpr char kGetDisplayMedia[] = "getDisplayMedia";
51
Guido Urdaneta645fc982018-02-20 19:46:0352// This is intended to limit DoS attacks against the browser process consisting
Philipp Hancke89add412022-11-18 14:07:0753// of many getUserMedia()/getDisplayMedia() calls. See https://crbug.com/804440.
54const size_t kMaxMediaEntries = 1000;
Guido Urdaneta645fc982018-02-20 19:46:0355
Matt Menke67484ed32022-07-22 18:54:3356// Makes sure that |dict| has a List under path "log".
57base::Value::List& EnsureLogList(base::Value::Dict& dict) {
58 base::Value::List* log = dict.FindList("log");
59 if (log)
60 return *log;
61 return dict.Set("log", base::Value::List())->GetList();
[email protected]c054f092013-01-27 08:12:4962}
63
tommi15e9cea2017-03-06 13:56:2864// Removes the log entry associated with a given record.
65void FreeLogList(base::Value* value) {
jdoerriee48b26a2017-12-09 14:19:0866 DCHECK(value->is_dict());
Matt Menke67484ed32022-07-22 18:54:3367 value->GetDict().Remove("log");
tommi15e9cea2017-03-06 13:56:2868}
69
[email protected]64ccac32013-01-29 21:40:0470} // namespace
71
Elad Alona619d5562018-01-13 01:30:1572WebRTCInternals* WebRTCInternals::g_webrtc_internals = nullptr;
73
Maks Orlovich442f3782021-06-04 18:05:0974WebRTCInternals::PendingUpdate::PendingUpdate(const std::string& event_name,
75 base::Value event_data)
rbpotter5796b002021-03-10 18:49:2176 : event_name_(event_name), event_data_(std::move(event_data)) {}
tommi75d54fe842016-02-09 14:56:3077
78WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other)
rbpotter5796b002021-03-10 18:49:2179 : event_name_(other.event_name_),
80 event_data_(std::move(other.event_data_)) {}
tommi75d54fe842016-02-09 14:56:3081
82WebRTCInternals::PendingUpdate::~PendingUpdate() {
83 DCHECK(thread_checker_.CalledOnValidThread());
84}
85
rbpotter5796b002021-03-10 18:49:2186const std::string& WebRTCInternals::PendingUpdate::event_name() const {
tommi75d54fe842016-02-09 14:56:3087 DCHECK(thread_checker_.CalledOnValidThread());
rbpotter5796b002021-03-10 18:49:2188 return event_name_;
tommi75d54fe842016-02-09 14:56:3089}
90
rbpotter5796b002021-03-10 18:49:2191const base::Value* WebRTCInternals::PendingUpdate::event_data() const {
tommi75d54fe842016-02-09 14:56:3092 DCHECK(thread_checker_.CalledOnValidThread());
Maks Orlovich442f3782021-06-04 18:05:0993 return event_data_.is_none() ? nullptr : &event_data_;
tommi75d54fe842016-02-09 14:56:3094}
95
Elad Alon67ac27bc42022-05-03 15:30:2696WebRTCInternals::WebRTCInternals() : WebRTCInternals(500, true) {
97 DCHECK_CURRENTLY_ON(BrowserThread::UI);
98}
tommi75d54fe842016-02-09 14:56:3099
maxmorinc369574d2016-07-25 15:28:17100WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
101 bool should_block_power_saving)
Matt Menke67484ed32022-07-22 18:54:33102 : peer_connection_data_(base::Value::List()),
103 selection_type_(SelectionType::kAudioDebugRecordings),
Elad Alonc0928bf12018-02-28 19:35:17104 command_line_derived_logging_path_(
105 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
106 switches::kWebRtcLocalEventLogging)),
ivocadd54f0d2015-12-18 23:17:05107 event_log_recordings_(false),
Guido Urdaneta0bc103a2018-11-16 19:54:33108 num_connected_connections_(0),
maxmorinc369574d2016-07-25 15:28:17109 should_block_power_saving_(should_block_power_saving),
Jeremy Roman3bca4bf2019-07-11 03:41:25110 aggregate_updates_ms_(aggregate_updates_ms) {
Elad Alonc0928bf12018-02-28 19:35:17111 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alona619d5562018-01-13 01:30:15112 DCHECK(!g_webrtc_internals);
113
Philip Eliasson9b5072d42025-05-13 13:13:49114 const base::FilePath default_path =
[email protected]820b9b262014-05-09 14:47:16115 GetContentClient()->browser()->GetDefaultDownloadDirectory();
Philip Eliasson9b5072d42025-05-13 13:13:49116 audio_debug_recordings_file_path_ = default_path;
117 event_log_recordings_file_path_ = default_path;
118 data_channel_recordings_file_path_ = default_path;
ivocadd54f0d2015-12-18 23:17:05119
Philip Eliasson9b5072d42025-05-13 13:13:49120 if (!default_path.empty()) {
grunell7566ffc2015-09-07 07:39:44121 audio_debug_recordings_file_path_ =
122 audio_debug_recordings_file_path_.Append(
123 FILE_PATH_LITERAL("audio_debug"));
ivocadd54f0d2015-12-18 23:17:05124 event_log_recordings_file_path_ =
Elad Alonc0928bf12018-02-28 19:35:17125 event_log_recordings_file_path_.Append(kEventLogFilename);
Philip Eliasson9b5072d42025-05-13 13:13:49126 data_channel_recordings_file_path_ =
127 data_channel_recordings_file_path_.Append(
128 FILE_PATH_LITERAL("data_channel"));
Elad Alonc0928bf12018-02-28 19:35:17129 }
130
131 // Allow command-line based setting of (local) WebRTC event logging.
132 if (!command_line_derived_logging_path_.empty()) {
133 const base::FilePath local_logs_path =
134 command_line_derived_logging_path_.Append(kEventLogFilename);
Elad Alon12ecdf02018-03-14 12:07:31135 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
136 if (logger) {
Patrick Monette2169e672021-03-30 15:54:22137 logger->EnableLocalLogging(local_logs_path);
Elad Alon12ecdf02018-03-14 12:07:31138 }
Elad Alonc0928bf12018-02-28 19:35:17139 // For clarity's sake, though these aren't supposed to be regarded now:
140 event_log_recordings_ = true;
141 event_log_recordings_file_path_.clear();
[email protected]820b9b262014-05-09 14:47:16142 }
Elad Alona619d5562018-01-13 01:30:15143
144 g_webrtc_internals = this;
[email protected]94fb5102013-01-23 09:00:47145}
146
[email protected]64ccac32013-01-29 21:40:04147WebRTCInternals::~WebRTCInternals() {
Elad Alon67ac27bc42022-05-03 15:30:26148 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alona619d5562018-01-13 01:30:15149 DCHECK(g_webrtc_internals);
150 g_webrtc_internals = nullptr;
Lei Zhangad220ec2023-09-28 18:28:55151
152 if (select_file_dialog_) {
153 select_file_dialog_->ListenerDestroyed();
154 }
Elad Alona619d5562018-01-13 01:30:15155}
156
157WebRTCInternals* WebRTCInternals::CreateSingletonInstance() {
Elad Alon67ac27bc42022-05-03 15:30:26158 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alona619d5562018-01-13 01:30:15159 DCHECK(!g_webrtc_internals);
160 g_webrtc_internals = new WebRTCInternals;
161 return g_webrtc_internals;
[email protected]94fb5102013-01-23 09:00:47162}
163
[email protected]64ccac32013-01-29 21:40:04164WebRTCInternals* WebRTCInternals::GetInstance() {
Alison Gale47d1537d2024-04-19 21:31:46165 // TODO(crbug.com/40837773): DCHECK calling from UI thread.
Elad Alon67ac27bc42022-05-03 15:30:26166 // Currently, some unit tests call this from outside of the UI thread,
167 // but that's not a real issue as these tests neglect setting
168 // `g_webrtc_internals` to begin with, and therefore just ignore it.
169 DCHECK(!g_webrtc_internals || BrowserThread::CurrentlyOn(BrowserThread::UI));
Elad Alona619d5562018-01-13 01:30:15170 return g_webrtc_internals;
[email protected]94fb5102013-01-23 09:00:47171}
172
Alexander Timin8690530c2021-06-19 00:34:32173void WebRTCInternals::OnPeerConnectionAdded(GlobalRenderFrameHostId frame_id,
Patrick Monette948b4732021-03-30 10:00:30174 int lid,
Patrick Monettece1ee722021-03-30 18:41:05175 ProcessId pid,
Patrick Monette948b4732021-03-30 10:00:30176 const string& url,
Harald Alvestrand39468ab42024-02-08 18:47:23177 const string& rtc_configuration) {
mostynb4c27d042015-03-18 21:47:47178 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]94fb5102013-01-23 09:00:47179
tommi15e9cea2017-03-06 13:56:28180 // TODO(tommi): Consider changing this design so that webrtc-internals has
181 // minimal impact if chrome://webrtc-internals isn't open.
182
Matt Menke67484ed32022-07-22 18:54:33183 base::Value::Dict dict;
184 dict.Set("rid", frame_id.child_id);
185 dict.Set("lid", lid);
186 dict.Set("pid", static_cast<int>(pid));
187 dict.Set("rtcConfiguration", rtc_configuration);
Matt Menke67484ed32022-07-22 18:54:33188 dict.Set("url", url);
189 dict.Set("isOpen", true);
190 dict.Set("connected", false);
[email protected]94fb5102013-01-23 09:00:47191
Mitsuru Oshima69031e62021-01-20 18:01:58192 if (!observers_.empty())
Maks Orlovich442f3782021-06-04 18:05:09193 SendUpdate("add-peer-connection", dict.Clone());
amistry163a4a32015-05-25 23:48:15194
Matt Menke67484ed32022-07-22 18:54:33195 peer_connection_data().Append(std::move(dict));
dcheng031a8f82016-09-08 21:04:33196
Patrick Monettece1ee722021-03-30 18:41:05197 if (render_process_id_set_.insert(frame_id.child_id).second) {
198 RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
amistry163a4a32015-05-25 23:48:15199 if (host)
200 host->AddObserver(this);
201 }
[email protected]94fb5102013-01-23 09:00:47202}
203
Alexander Timin8690530c2021-06-19 00:34:32204void WebRTCInternals::OnPeerConnectionRemoved(GlobalRenderFrameHostId frame_id,
Patrick Monettece1ee722021-03-30 18:41:05205 int lid) {
mostynb4c27d042015-03-18 21:47:47206 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]94fb5102013-01-23 09:00:47207
Maks Orlovich442f3782021-06-04 18:05:09208 auto it = FindRecord(frame_id, lid);
Matt Menke67484ed32022-07-22 18:54:33209 if (it != peer_connection_data().end()) {
Elaine Chien5df4237b2022-01-07 18:51:39210 MaybeClosePeerConnection(*it);
Matt Menke67484ed32022-07-22 18:54:33211 peer_connection_data().erase(it);
tommi15e9cea2017-03-06 13:56:28212 }
[email protected]94fb5102013-01-23 09:00:47213
Mitsuru Oshima69031e62021-01-20 18:01:58214 if (!observers_.empty()) {
Matt Menke67484ed32022-07-22 18:54:33215 base::Value::Dict id;
216 id.Set("rid", frame_id.child_id);
217 id.Set("lid", lid);
rbpotter5796b002021-03-10 18:49:21218 SendUpdate("remove-peer-connection", std::move(id));
[email protected]c054f092013-01-27 08:12:49219 }
220}
221
Alexander Timin8690530c2021-06-19 00:34:32222void WebRTCInternals::OnPeerConnectionUpdated(GlobalRenderFrameHostId frame_id,
Patrick Monette948b4732021-03-30 10:00:30223 int lid,
224 const string& type,
225 const string& value) {
mostynb4c27d042015-03-18 21:47:47226 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]c054f092013-01-27 08:12:49227
Maks Orlovich442f3782021-06-04 18:05:09228 auto it = FindRecord(frame_id, lid);
Matt Menke67484ed32022-07-22 18:54:33229 if (it == peer_connection_data().end())
[email protected]94fb5102013-01-23 09:00:47230 return;
tommi15e9cea2017-03-06 13:56:28231
Philipp Hancke151dc552021-11-04 15:18:04232 if (type == "iceconnectionstatechange") {
Guido Urdaneta0bc103a2018-11-16 19:54:33233 if (value == "connected" || value == "checking" || value == "completed") {
Elaine Chien5df4237b2022-01-07 18:51:39234 MaybeMarkPeerConnectionAsConnected(*it);
Guido Urdaneta0bc103a2018-11-16 19:54:33235 } else if (value == "failed" || value == "disconnected" ||
236 value == "closed" || value == "new") {
Elaine Chien5df4237b2022-01-07 18:51:39237 MaybeMarkPeerConnectionAsNotConnected(*it);
Guido Urdaneta0bc103a2018-11-16 19:54:33238 }
Philipp Hancke951e042e2021-11-01 13:44:18239 } else if (type == "close") {
Elaine Chien5df4237b2022-01-07 18:51:39240 MaybeClosePeerConnection(*it);
Philipp Hancke1a456272021-03-24 12:10:55241 } else if (type == "setConfiguration") {
242 // Update the configuration we have for this connection.
Matt Menke67484ed32022-07-22 18:54:33243 it->GetDict().Set("rtcConfiguration", value);
Guido Urdaneta0bc103a2018-11-16 19:54:33244 }
tommi15e9cea2017-03-06 13:56:28245
246 // Don't update entries if there aren't any observers.
Mitsuru Oshima69031e62021-01-20 18:01:58247 if (observers_.empty())
tommi15e9cea2017-03-06 13:56:28248 return;
249
Matt Menke67484ed32022-07-22 18:54:33250 base::Value::Dict log_entry;
tommi15e9cea2017-03-06 13:56:28251
Peter Kasting08b91b42023-10-21 03:46:09252 double epoch_time = base::Time::Now().InMillisecondsFSinceUnixEpoch();
Brett Wilson5ed06e72017-12-01 01:25:11253 string time = base::NumberToString(epoch_time);
Matt Menke67484ed32022-07-22 18:54:33254 log_entry.Set("time", time);
255 log_entry.Set("type", type);
256 log_entry.Set("value", value);
tommi15e9cea2017-03-06 13:56:28257
Matt Menke67484ed32022-07-22 18:54:33258 base::Value::Dict update;
259 update.Set("rid", frame_id.child_id);
260 update.Set("lid", lid);
261 update.Merge(log_entry.Clone());
tommi15e9cea2017-03-06 13:56:28262
rbpotter5796b002021-03-10 18:49:21263 SendUpdate("update-peer-connection", std::move(update));
tommi15e9cea2017-03-06 13:56:28264
265 // Append the update to the end of the log.
Matt Menke67484ed32022-07-22 18:54:33266 EnsureLogList(it->GetDict()).Append(std::move(log_entry));
[email protected]94fb5102013-01-23 09:00:47267}
268
Alexander Timin8690530c2021-06-19 00:34:32269void WebRTCInternals::OnAddStandardStats(GlobalRenderFrameHostId frame_id,
Henrik Boström33ece3e92019-04-23 10:08:53270 int lid,
Fabrice de Gans432f4de2022-04-04 17:47:41271 base::Value::List value) {
Elad Alon67ac27bc42022-05-03 15:30:26272 DCHECK_CURRENTLY_ON(BrowserThread::UI);
273
Mitsuru Oshima69031e62021-01-20 18:01:58274 if (observers_.empty())
[email protected]6efd5f22013-02-06 19:20:37275 return;
276
Fabrice de Gans432f4de2022-04-04 17:47:41277 base::Value::Dict dict;
278 dict.Set("rid", frame_id.child_id);
279 dict.Set("lid", lid);
[email protected]6efd5f22013-02-06 19:20:37280
Fabrice de Gans432f4de2022-04-04 17:47:41281 dict.Set("reports", std::move(value));
[email protected]6efd5f22013-02-06 19:20:37282
Matt Menke67484ed32022-07-22 18:54:33283 SendUpdate("add-standard-stats", std::move(dict));
Henrik Boström33ece3e92019-04-23 10:08:53284}
285
Philipp Hancke89add412022-11-18 14:07:07286void WebRTCInternals::OnGetMedia(const std::string& request_type,
287 GlobalRenderFrameHostId frame_id,
288 base::ProcessId pid,
289 int request_id,
290 bool audio,
291 bool video,
292 const std::string& audio_constraints,
293 const std::string& video_constraints) {
mostynb4c27d042015-03-18 21:47:47294 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]a0437b202014-01-02 22:45:51295
Philipp Hancke89add412022-11-18 14:07:07296 if (get_user_media_requests_.size() >= kMaxMediaEntries) {
297 LOG(WARNING) << "Maximum number of tracked getUserMedia/getDisplayMedia "
[email protected]deb232b2022-11-28 11:22:16298 "requests reached in webrtc-internals.";
Guido Urdaneta645fc982018-02-20 19:46:03299 return;
300 }
301
Peter Kastinga06ccf712022-08-24 07:43:12302 RenderFrameHost* rfh = RenderFrameHost::FromID(frame_id);
Philipp Hanckedb92acef2021-12-01 09:57:43303 // Frame may be gone (and does not exist in tests).
Peter Kastinga06ccf712022-08-24 07:43:12304 std::string origin = rfh ? rfh->GetLastCommittedOrigin().Serialize() : "";
Philipp Hanckedb92acef2021-12-01 09:57:43305
Matt Menke67484ed32022-07-22 18:54:33306 base::Value::Dict dict;
307 dict.Set("rid", frame_id.child_id);
308 dict.Set("pid", static_cast<int>(pid));
309 dict.Set("request_id", request_id);
Philipp Hancke89add412022-11-18 14:07:07310 dict.Set("request_type", request_type);
Matt Menke67484ed32022-07-22 18:54:33311 dict.Set("origin", origin);
Peter Kasting08b91b42023-10-21 03:46:09312 dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
[email protected]a0437b202014-01-02 22:45:51313 if (audio)
Matt Menke67484ed32022-07-22 18:54:33314 dict.Set("audio", audio_constraints);
[email protected]a0437b202014-01-02 22:45:51315 if (video)
Matt Menke67484ed32022-07-22 18:54:33316 dict.Set("video", video_constraints);
[email protected]a0437b202014-01-02 22:45:51317
Mitsuru Oshima69031e62021-01-20 18:01:58318 if (!observers_.empty())
[email protected]deb232b2022-11-28 11:22:16319 SendUpdate("add-media", dict.Clone());
amistry163a4a32015-05-25 23:48:15320
dcheng031a8f82016-09-08 21:04:33321 get_user_media_requests_.Append(std::move(dict));
322
Patrick Monettece1ee722021-03-30 18:41:05323 if (render_process_id_set_.insert(frame_id.child_id).second) {
Peter Kastinga06ccf712022-08-24 07:43:12324 RenderProcessHost* rph = RenderProcessHost::FromID(frame_id.child_id);
325 if (rph)
326 rph->AddObserver(this);
amistry163a4a32015-05-25 23:48:15327 }
[email protected]a0437b202014-01-02 22:45:51328}
Philipp Hancke17347d082021-11-24 06:51:26329
Philipp Hancke89add412022-11-18 14:07:07330void WebRTCInternals::OnGetMediaSuccess(const std::string& request_type,
331 GlobalRenderFrameHostId frame_id,
332 base::ProcessId pid,
333 int request_id,
334 const std::string& stream_id,
335 const std::string& audio_track_info,
336 const std::string& video_track_info) {
Philipp Hancked013ad92021-11-22 22:23:08337 DCHECK_CURRENTLY_ON(BrowserThread::UI);
338
Philipp Hancke89add412022-11-18 14:07:07339 if (get_user_media_requests_.size() >= kMaxMediaEntries) {
340 LOG(WARNING) << "Maximum number of tracked getUserMedia/getDisplayMedia "
[email protected]deb232b2022-11-28 11:22:16341 "requests reached in webrtc-internals.";
Philipp Hancked013ad92021-11-22 22:23:08342 return;
343 }
344
Matt Menke67484ed32022-07-22 18:54:33345 base::Value::Dict dict;
346 dict.Set("rid", frame_id.child_id);
347 dict.Set("pid", static_cast<int>(pid));
348 dict.Set("request_id", request_id);
Philipp Hancke89add412022-11-18 14:07:07349 dict.Set("request_type", request_type);
Peter Kasting08b91b42023-10-21 03:46:09350 dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
Matt Menke67484ed32022-07-22 18:54:33351 dict.Set("stream_id", stream_id);
Philipp Hancked013ad92021-11-22 22:23:08352 if (!audio_track_info.empty())
Matt Menke67484ed32022-07-22 18:54:33353 dict.Set("audio_track_info", audio_track_info);
Philipp Hancked013ad92021-11-22 22:23:08354 if (!video_track_info.empty())
Matt Menke67484ed32022-07-22 18:54:33355 dict.Set("video_track_info", video_track_info);
Philipp Hancked013ad92021-11-22 22:23:08356
357 if (!observers_.empty())
[email protected]deb232b2022-11-28 11:22:16358 SendUpdate("update-media", dict.Clone());
Philipp Hancked013ad92021-11-22 22:23:08359
360 get_user_media_requests_.Append(std::move(dict));
361
362 if (render_process_id_set_.insert(frame_id.child_id).second) {
363 RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
364 if (host)
365 host->AddObserver(this);
366 }
367}
[email protected]a0437b202014-01-02 22:45:51368
Philipp Hancke89add412022-11-18 14:07:07369void WebRTCInternals::OnGetMediaFailure(const std::string& request_type,
370 GlobalRenderFrameHostId frame_id,
371 base::ProcessId pid,
372 int request_id,
373 const std::string& error,
374 const std::string& error_message) {
Philipp Hancke17347d082021-11-24 06:51:26375 DCHECK_CURRENTLY_ON(BrowserThread::UI);
376
Philipp Hancke89add412022-11-18 14:07:07377 if (get_user_media_requests_.size() >= kMaxMediaEntries) {
[email protected]deb232b2022-11-28 11:22:16378 LOG(WARNING) << "Maximum number of tracked /getDisplayMedia "
379 "requests reached in webrtc-internals.";
Philipp Hancke17347d082021-11-24 06:51:26380 return;
381 }
382
Matt Menke67484ed32022-07-22 18:54:33383 base::Value::Dict dict;
384 dict.Set("rid", frame_id.child_id);
385 dict.Set("pid", static_cast<int>(pid));
386 dict.Set("request_id", request_id);
Philipp Hancke89add412022-11-18 14:07:07387 dict.Set("request_type", request_type);
Peter Kasting08b91b42023-10-21 03:46:09388 dict.Set("timestamp", base::Time::Now().InMillisecondsFSinceUnixEpoch());
Matt Menke67484ed32022-07-22 18:54:33389 dict.Set("error", error);
390 dict.Set("error_message", error_message);
Philipp Hancke17347d082021-11-24 06:51:26391
392 if (!observers_.empty())
[email protected]deb232b2022-11-28 11:22:16393 SendUpdate("update-media", dict.Clone());
Philipp Hancke17347d082021-11-24 06:51:26394
395 get_user_media_requests_.Append(std::move(dict));
396
397 if (render_process_id_set_.insert(frame_id.child_id).second) {
398 RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
399 if (host)
400 host->AddObserver(this);
401 }
402}
403
Philipp Hancke89add412022-11-18 14:07:07404void WebRTCInternals::OnGetUserMedia(GlobalRenderFrameHostId frame_id,
405 base::ProcessId pid,
406 int request_id,
407 bool audio,
408 bool video,
409 const std::string& audio_constraints,
410 const std::string& video_constraints) {
411 OnGetMedia(kGetUserMedia, frame_id, pid, request_id, audio, video,
412 audio_constraints, video_constraints);
413}
414
415void WebRTCInternals::OnGetUserMediaSuccess(
416 GlobalRenderFrameHostId frame_id,
417 base::ProcessId pid,
418 int request_id,
419 const std::string& stream_id,
420 const std::string& audio_track_info,
421 const std::string& video_track_info) {
422 OnGetMediaSuccess(kGetUserMedia, frame_id, pid, request_id, stream_id,
423 audio_track_info, video_track_info);
424}
425
426void WebRTCInternals::OnGetUserMediaFailure(GlobalRenderFrameHostId frame_id,
427 base::ProcessId pid,
428 int request_id,
429 const std::string& error,
430 const std::string& error_message) {
431 OnGetMediaFailure(kGetUserMedia, frame_id, pid, request_id, error,
432 error_message);
433}
434
435void WebRTCInternals::OnGetDisplayMedia(GlobalRenderFrameHostId frame_id,
436 base::ProcessId pid,
437 int request_id,
438 bool audio,
439 bool video,
440 const std::string& audio_constraints,
441 const std::string& video_constraints) {
442 OnGetMedia(kGetDisplayMedia, frame_id, pid, request_id, audio, video,
443 audio_constraints, video_constraints);
444}
445
446void WebRTCInternals::OnGetDisplayMediaSuccess(
447 GlobalRenderFrameHostId frame_id,
448 base::ProcessId pid,
449 int request_id,
450 const std::string& stream_id,
451 const std::string& audio_track_info,
452 const std::string& video_track_info) {
453 OnGetMediaSuccess(kGetDisplayMedia, frame_id, pid, request_id, stream_id,
454 audio_track_info, video_track_info);
455}
456
457void WebRTCInternals::OnGetDisplayMediaFailure(
458 GlobalRenderFrameHostId frame_id,
459 base::ProcessId pid,
460 int request_id,
461 const std::string& error,
462 const std::string& error_message) {
463 OnGetMediaFailure(kGetDisplayMedia, frame_id, pid, request_id, error,
464 error_message);
465}
466
tommi75d54fe842016-02-09 14:56:30467void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) {
mostynb4c27d042015-03-18 21:47:47468 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]94fb5102013-01-23 09:00:47469 observers_.AddObserver(observer);
470}
471
tommi75d54fe842016-02-09 14:56:30472void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) {
mostynb4c27d042015-03-18 21:47:47473 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]94fb5102013-01-23 09:00:47474 observers_.RemoveObserver(observer);
Mitsuru Oshima69031e62021-01-20 18:01:58475 if (!observers_.empty())
tommi15e9cea2017-03-06 13:56:28476 return;
[email protected]bf3657b2013-12-17 12:36:17477
ivoccf0887d2016-07-07 18:23:53478 // Disables event log and audio debug recordings if enabled and the last
grunell7566ffc2015-09-07 07:39:44479 // webrtc-internals page is going away.
tommi15e9cea2017-03-06 13:56:28480 DisableAudioDebugRecordings();
Philipp Hanckef922d4b12022-09-09 16:04:33481 if (CanToggleEventLogRecordings()) {
482 // Do not disable event log recording when the browser was started
483 // with the flag to enable the recordings on the command line.
484 DisableLocalEventLogRecordings();
485 }
tommi15e9cea2017-03-06 13:56:28486
Matt Menke67484ed32022-07-22 18:54:33487 // TODO(tommi): Consider removing all the peer_connection_data().
488 for (auto& dictionary : peer_connection_data())
jdoerriea5676c62017-04-11 18:09:14489 FreeLogList(&dictionary);
[email protected]94fb5102013-01-23 09:00:47490}
491
Tarun Bansalf153d6832019-06-17 18:18:05492void WebRTCInternals::AddConnectionsObserver(
493 WebRtcInternalsConnectionsObserver* observer) {
494 DCHECK_CURRENTLY_ON(BrowserThread::UI);
495 connections_observers_.AddObserver(observer);
496}
497
498void WebRTCInternals::RemoveConnectionsObserver(
499 WebRtcInternalsConnectionsObserver* observer) {
500 DCHECK_CURRENTLY_ON(BrowserThread::UI);
501 connections_observers_.RemoveObserver(observer);
502}
503
[email protected]a0437b202014-01-02 22:45:51504void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
mostynb4c27d042015-03-18 21:47:47505 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Matt Menke67484ed32022-07-22 18:54:33506 if (peer_connection_data().size() > 0)
rbpotter5796b002021-03-10 18:49:21507 observer->OnUpdate("update-all-peer-connections", &peer_connection_data_);
[email protected]a0437b202014-01-02 22:45:51508
Matt Menke67484ed32022-07-22 18:54:33509 for (const auto& request : get_user_media_requests_) {
Philipp Hancke17347d082021-11-24 06:51:26510 // If there is a stream_id key or an error key this is an update.
Matt Menke67484ed32022-07-22 18:54:33511 if (request.GetDict().FindString("stream_id") ||
512 request.GetDict().FindString("error")) {
[email protected]deb232b2022-11-28 11:22:16513 observer->OnUpdate("update-media", &request);
Philipp Hancked013ad92021-11-22 22:23:08514 } else {
[email protected]deb232b2022-11-28 11:22:16515 observer->OnUpdate("add-media", &request);
Philipp Hancked013ad92021-11-22 22:23:08516 }
[email protected]a0437b202014-01-02 22:45:51517 }
[email protected]c054f092013-01-27 08:12:49518}
519
grunell7566ffc2015-09-07 07:39:44520void WebRTCInternals::EnableAudioDebugRecordings(
521 content::WebContents* web_contents) {
grunell7566ffc2015-09-07 07:39:44522 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Xiaohan Wangf096c6322022-01-15 18:46:20523#if BUILDFLAG(IS_ANDROID)
grunell7566ffc2015-09-07 07:39:44524 EnableAudioDebugRecordingsOnAllRenderProcessHosts();
[email protected]f146d0d2014-02-15 14:30:24525#else
Philip Eliassond04b7872025-05-14 08:15:58526 MaybeShowSelectFileDialog(web_contents, SelectionType::kAudioDebugRecordings);
[email protected]bf3657b2013-12-17 12:36:17527#endif
528}
529
grunell7566ffc2015-09-07 07:39:44530void WebRTCInternals::DisableAudioDebugRecordings() {
grunell7566ffc2015-09-07 07:39:44531 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Marina Ciocea741a4fb12018-01-27 09:55:12532 if (!audio_debug_recording_session_)
tommi15e9cea2017-03-06 13:56:28533 return;
Marina Ciocea741a4fb12018-01-27 09:55:12534 audio_debug_recording_session_.reset();
[email protected]a43fc4a2014-06-03 14:47:05535
[email protected]bf3657b2013-12-17 12:36:17536 for (RenderProcessHost::iterator i(
537 content::RenderProcessHost::AllHostsIterator());
538 !i.IsAtEnd(); i.Advance()) {
grunell7566ffc2015-09-07 07:39:44539 i.GetCurrentValue()->DisableAudioDebugRecordings();
[email protected]bf3657b2013-12-17 12:36:17540 }
[email protected]bf3657b2013-12-17 12:36:17541}
542
grunell7566ffc2015-09-07 07:39:44543bool WebRTCInternals::IsAudioDebugRecordingsEnabled() const {
544 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Marina Ciocea741a4fb12018-01-27 09:55:12545 return !!audio_debug_recording_session_;
grunell7566ffc2015-09-07 07:39:44546}
547
548const base::FilePath& WebRTCInternals::GetAudioDebugRecordingsFilePath() const {
549 DCHECK_CURRENTLY_ON(BrowserThread::UI);
550 return audio_debug_recordings_file_path_;
551}
552
Elad Alon2afe2492017-12-01 15:11:46553void WebRTCInternals::EnableLocalEventLogRecordings(
ivocadd54f0d2015-12-18 23:17:05554 content::WebContents* web_contents) {
555 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alon67ac27bc42022-05-03 15:30:26556 DCHECK(web_contents);
Elad Alonc0928bf12018-02-28 19:35:17557 DCHECK(CanToggleEventLogRecordings());
Elad Alon67ac27bc42022-05-03 15:30:26558
Xiaohan Wangf096c6322022-01-15 18:46:20559#if BUILDFLAG(IS_ANDROID)
Elad Alon12ecdf02018-03-14 12:07:31560 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
561 if (logger) {
Patrick Monette2169e672021-03-30 15:54:22562 logger->EnableLocalLogging(event_log_recordings_file_path_);
Elad Alon12ecdf02018-03-14 12:07:31563 }
ivocadd54f0d2015-12-18 23:17:05564#else
Philip Eliassond04b7872025-05-14 08:15:58565 MaybeShowSelectFileDialog(web_contents, SelectionType::kRtcEventLogs);
ivocadd54f0d2015-12-18 23:17:05566#endif
ivoccf0887d2016-07-07 18:23:53567}
ivocadd54f0d2015-12-18 23:17:05568
Elad Alon2afe2492017-12-01 15:11:46569void WebRTCInternals::DisableLocalEventLogRecordings() {
Elad Alon67ac27bc42022-05-03 15:30:26570 DCHECK_CURRENTLY_ON(BrowserThread::UI);
571
ivoccf0887d2016-07-07 18:23:53572 event_log_recordings_ = false;
Elad Alonc0928bf12018-02-28 19:35:17573 DCHECK(CanToggleEventLogRecordings());
Elad Alon12ecdf02018-03-14 12:07:31574 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
575 if (logger) {
Patrick Monette2169e672021-03-30 15:54:22576 logger->DisableLocalLogging();
Elad Alon12ecdf02018-03-14 12:07:31577 }
ivocadd54f0d2015-12-18 23:17:05578}
579
Philip Eliasson9b5072d42025-05-13 13:13:49580void WebRTCInternals::EnableDataChannelRecordings(
581 content::WebContents* web_contents) {
582 DCHECK_CURRENTLY_ON(BrowserThread::UI);
583#if BUILDFLAG(IS_ANDROID)
584 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
585 if (logger) {
586 logger->EnableDataChannelLogging(data_channel_recordings_file_path_);
587 }
588#else
Philip Eliassond04b7872025-05-14 08:15:58589 MaybeShowSelectFileDialog(web_contents,
590 SelectionType::kDataChannelRecordings);
Philip Eliasson9b5072d42025-05-13 13:13:49591#endif
592}
593
594void WebRTCInternals::DisableDataChannelRecordings() {
595 DCHECK_CURRENTLY_ON(BrowserThread::UI);
596
597 data_channel_recording_active_ = false;
Philip Eliasson9b5072d42025-05-13 13:13:49598 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
599 if (logger) {
600 logger->DisableDataChannelLogging();
601 }
602}
603
ivocadd54f0d2015-12-18 23:17:05604bool WebRTCInternals::IsEventLogRecordingsEnabled() const {
605 DCHECK_CURRENTLY_ON(BrowserThread::UI);
606 return event_log_recordings_;
607}
608
Philip Eliasson9b5072d42025-05-13 13:13:49609bool WebRTCInternals::IsDataChannelRecordingsEnabled() const {
610 DCHECK_CURRENTLY_ON(BrowserThread::UI);
611 return data_channel_recording_active_;
612}
613
Elad Alonc0928bf12018-02-28 19:35:17614bool WebRTCInternals::CanToggleEventLogRecordings() const {
Elad Alon67ac27bc42022-05-03 15:30:26615 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alonc0928bf12018-02-28 19:35:17616 return command_line_derived_logging_path_.empty();
617}
618
rbpotter5796b002021-03-10 18:49:21619void WebRTCInternals::SendUpdate(const std::string& event_name,
Maks Orlovich442f3782021-06-04 18:05:09620 base::Value event_data) {
mostynb4c27d042015-03-18 21:47:47621 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Mitsuru Oshima69031e62021-01-20 18:01:58622 DCHECK(!observers_.empty());
[email protected]94fb5102013-01-23 09:00:47623
tommi75d54fe842016-02-09 14:56:30624 bool queue_was_empty = pending_updates_.empty();
rbpotter5796b002021-03-10 18:49:21625 pending_updates_.push(PendingUpdate(event_name, std::move(event_data)));
tommi75d54fe842016-02-09 14:56:30626
627 if (queue_was_empty) {
Gabriel Charettee7cdc5cd2020-05-27 23:35:05628 GetUIThreadTaskRunner({})->PostDelayedTask(
629 FROM_HERE,
tzike2aca992017-09-05 08:50:54630 base::BindOnce(&WebRTCInternals::ProcessPendingUpdates,
631 weak_factory_.GetWeakPtr()),
Peter Kastinge5a38ed2021-10-02 03:06:35632 base::Milliseconds(aggregate_updates_ms_));
tommi75d54fe842016-02-09 14:56:30633 }
[email protected]94fb5102013-01-23 09:00:47634}
[email protected]64ccac32013-01-29 21:40:04635
Matt Menke67484ed32022-07-22 18:54:33636void WebRTCInternals::SendUpdate(const std::string& event_name,
637 base::Value::Dict event_data) {
638 SendUpdate(event_name, base::Value(std::move(event_data)));
639}
640
Bo Liu2a489402018-04-24 23:41:27641void WebRTCInternals::RenderProcessExited(
642 RenderProcessHost* host,
643 const ChildProcessTerminationInfo& info) {
mostynb4c27d042015-03-18 21:47:47644 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Emily Andrewsd15fd762024-12-10 20:41:54645 OnRendererExit(host->GetDeprecatedID());
646 render_process_id_set_.erase(host->GetDeprecatedID());
amistry163a4a32015-05-25 23:48:15647 host->RemoveObserver(this);
[email protected]f4eaf7b92013-02-28 22:00:40648}
[email protected]020633b2013-01-30 23:35:35649
Philip Eliassond04b7872025-05-14 08:15:58650void WebRTCInternals::MaybeShowSelectFileDialog(
651 content::WebContents* web_contents,
652 SelectionType log_type) {
653 if (select_file_dialog_) {
654 return;
655 }
656
657 base::FilePath* file_path = nullptr;
658 switch (log_type) {
659 case (SelectionType::kRtcEventLogs): {
660 file_path = &event_log_recordings_file_path_;
661 break;
662 }
663 case (SelectionType::kAudioDebugRecordings): {
664 file_path = &audio_debug_recordings_file_path_;
665 break;
666 }
667 case (SelectionType::kDataChannelRecordings): {
668 file_path = &data_channel_recordings_file_path_;
669 break;
670 }
671 }
672 CHECK(file_path);
673
674 selection_type_ = log_type;
675 select_file_dialog_ = ui::SelectFileDialog::Create(
676 this,
677 GetContentClient()->browser()->CreateSelectFilePolicy(web_contents));
678 select_file_dialog_->SelectFile(
679 ui::SelectFileDialog::SELECT_SAVEAS_FILE,
680 /*title=*/std::u16string(), *file_path, /*file_types=*/nullptr,
681 /*file_type_index=*/0,
682 /*default_extension=*/base::FilePath::StringType(),
683 web_contents->GetTopLevelNativeWindow());
684}
685
Avi Drissmand0b88a2b2023-12-28 22:49:38686void WebRTCInternals::FileSelected(const ui::SelectedFileInfo& file,
Ellyb4b57fa2024-07-02 16:17:40687 int /* unused_index */) {
grunell7566ffc2015-09-07 07:39:44688 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alonb0a304d2017-11-02 19:08:43689 switch (selection_type_) {
Elad Alon71ec4bb2018-01-15 11:38:03690 case SelectionType::kRtcEventLogs: {
Avi Drissmand0b88a2b2023-12-28 22:49:38691 event_log_recordings_file_path_ = file.path();
Elad Alon61506012017-12-12 08:45:54692 event_log_recordings_ = true;
Elad Alon12ecdf02018-03-14 12:07:31693 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
694 if (logger) {
Avi Drissmand0b88a2b2023-12-28 22:49:38695 logger->EnableLocalLogging(file.path());
Elad Alon12ecdf02018-03-14 12:07:31696 }
Elad Alonb0a304d2017-11-02 19:08:43697 break;
Elad Alon71ec4bb2018-01-15 11:38:03698 }
699 case SelectionType::kAudioDebugRecordings: {
Avi Drissmand0b88a2b2023-12-28 22:49:38700 audio_debug_recordings_file_path_ = file.path();
Elad Alonb0a304d2017-11-02 19:08:43701 EnableAudioDebugRecordingsOnAllRenderProcessHosts();
702 break;
Elad Alon71ec4bb2018-01-15 11:38:03703 }
Philip Eliasson9b5072d42025-05-13 13:13:49704 case SelectionType::kDataChannelRecordings: {
705 data_channel_recordings_file_path_ = file.path();
706 data_channel_recording_active_ = true;
707 WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
708 if (logger) {
709 logger->EnableDataChannelLogging(file.path());
710 }
711 break;
712 }
Peter Boström188188d2024-05-17 21:35:58713 default: {
Peter Boströmfc7ddc182024-10-31 19:37:21714 NOTREACHED();
Peter Boström188188d2024-05-17 21:35:58715 }
ivocadd54f0d2015-12-18 23:17:05716 }
Philip Eliassonbe1d34f2025-05-14 08:58:15717 select_file_dialog_.reset();
[email protected]bf3657b2013-12-17 12:36:17718}
719
Ellyb4b57fa2024-07-02 16:17:40720void WebRTCInternals::FileSelectionCanceled() {
grunell7566ffc2015-09-07 07:39:44721 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Elad Alonb0a304d2017-11-02 19:08:43722 switch (selection_type_) {
Elad Alon5e351e02017-11-06 17:53:35723 case SelectionType::kRtcEventLogs:
Maks Orlovich442f3782021-06-04 18:05:09724 SendUpdate("event-log-recordings-file-selection-cancelled",
725 base::Value());
Elad Alonb0a304d2017-11-02 19:08:43726 break;
Elad Alon5e351e02017-11-06 17:53:35727 case SelectionType::kAudioDebugRecordings:
Maks Orlovich442f3782021-06-04 18:05:09728 SendUpdate("audio-debug-recordings-file-selection-cancelled",
729 base::Value());
Elad Alonb0a304d2017-11-02 19:08:43730 break;
Philip Eliasson9b5072d42025-05-13 13:13:49731 case SelectionType::kDataChannelRecordings:
732 SendUpdate("data-channel-recordings-file-selection-cancelled",
733 base::Value());
734 break;
Elad Alonb0a304d2017-11-02 19:08:43735 default:
Peter Boströmfc7ddc182024-10-31 19:37:21736 NOTREACHED();
ivocadd54f0d2015-12-18 23:17:05737 }
Philip Eliassonbe1d34f2025-05-14 08:58:15738 select_file_dialog_.reset();
[email protected]09f12a02014-03-28 16:54:08739}
740
[email protected]f4eaf7b92013-02-28 22:00:40741void WebRTCInternals::OnRendererExit(int render_process_id) {
mostynb4c27d042015-03-18 21:47:47742 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]32eadb442014-08-08 16:55:39743
[email protected]020633b2013-01-30 23:35:35744 // Iterates from the end of the list to remove the PeerConnections created
Maks Orlovich442f3782021-06-04 18:05:09745 // by the exiting renderer.
Matt Menke67484ed32022-07-22 18:54:33746 for (int i = peer_connection_data().size() - 1; i >= 0; --i) {
747 DCHECK(peer_connection_data()[i].is_dict());
[email protected]020633b2013-01-30 23:35:35748
Arthur Sonzognic686e8f2024-01-11 08:36:37749 std::optional<int> this_rid, this_lid;
Matt Menke67484ed32022-07-22 18:54:33750 this_rid = peer_connection_data()[i].GetDict().FindInt("rid");
751 this_lid = peer_connection_data()[i].GetDict().FindInt("lid");
[email protected]020633b2013-01-30 23:35:35752
Maks Orlovich442f3782021-06-04 18:05:09753 if (this_rid.value_or(0) == render_process_id) {
Mitsuru Oshima69031e62021-01-20 18:01:58754 if (!observers_.empty()) {
Matt Menke67484ed32022-07-22 18:54:33755 base::Value::Dict update;
756 update.Set("rid", this_rid.value_or(0));
757 update.Set("lid", this_lid.value_or(0));
rbpotter5796b002021-03-10 18:49:21758 SendUpdate("remove-peer-connection", std::move(update));
[email protected]020633b2013-01-30 23:35:35759 }
Matt Menke67484ed32022-07-22 18:54:33760 MaybeClosePeerConnection(peer_connection_data()[i]);
761 peer_connection_data().erase(peer_connection_data().begin() + i);
[email protected]020633b2013-01-30 23:35:35762 }
763 }
ke.he1671f062017-05-20 00:34:52764 UpdateWakeLock();
[email protected]a0437b202014-01-02 22:45:51765
766 bool found_any = false;
767 // Iterates from the end of the list to remove the getUserMedia requests
768 // created by the exiting renderer.
Matt Menke67484ed32022-07-22 18:54:33769 for (int i = get_user_media_requests_.size() - 1; i >= 0; --i) {
770 DCHECK(get_user_media_requests_[i].is_dict());
[email protected]a0437b202014-01-02 22:45:51771
Arthur Sonzognic686e8f2024-01-11 08:36:37772 std::optional<int> this_rid =
Matt Menke67484ed32022-07-22 18:54:33773 get_user_media_requests_[i].GetDict().FindInt("rid");
[email protected]a0437b202014-01-02 22:45:51774
Maks Orlovich442f3782021-06-04 18:05:09775 if (this_rid.value_or(0) == render_process_id) {
Matt Menke67484ed32022-07-22 18:54:33776 get_user_media_requests_.erase(get_user_media_requests_.begin() + i);
[email protected]a0437b202014-01-02 22:45:51777 found_any = true;
778 }
779 }
780
Mitsuru Oshima69031e62021-01-20 18:01:58781 if (found_any && !observers_.empty()) {
Matt Menke67484ed32022-07-22 18:54:33782 base::Value::Dict update;
783 update.Set("rid", render_process_id);
[email protected]deb232b2022-11-28 11:22:16784 SendUpdate("remove-media-for-renderer", std::move(update));
[email protected]a0437b202014-01-02 22:45:51785 }
[email protected]020633b2013-01-30 23:35:35786}
787
grunell7566ffc2015-09-07 07:39:44788void WebRTCInternals::EnableAudioDebugRecordingsOnAllRenderProcessHosts() {
789 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Marina Ciocea741a4fb12018-01-27 09:55:12790 DCHECK(!audio_debug_recording_session_);
Ken Rockot72964402019-12-06 10:40:51791 mojo::PendingRemote<audio::mojom::DebugRecording> debug_recording;
792 content::GetAudioService().BindDebugRecording(
793 debug_recording.InitWithNewPipeAndPassReceiver());
Marina Cioceac6d46d2f2018-02-26 15:21:28794 audio_debug_recording_session_ = audio::CreateAudioDebugRecordingSession(
Ken Rockot72964402019-12-06 10:40:51795 audio_debug_recordings_file_path_, std::move(debug_recording));
grunell086a4112017-03-02 09:23:04796
[email protected]f146d0d2014-02-15 14:30:24797 for (RenderProcessHost::iterator i(
798 content::RenderProcessHost::AllHostsIterator());
799 !i.IsAtEnd(); i.Advance()) {
grunell7566ffc2015-09-07 07:39:44800 i.GetCurrentValue()->EnableAudioDebugRecordings(
801 audio_debug_recordings_file_path_);
[email protected]f146d0d2014-02-15 14:30:24802 }
[email protected]a0437b202014-01-02 22:45:51803}
804
Elaine Chien5df4237b2022-01-07 18:51:39805void WebRTCInternals::MaybeClosePeerConnection(base::Value& record) {
Elad Alon67ac27bc42022-05-03 15:30:26806 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Arthur Sonzognic686e8f2024-01-11 08:36:37807 std::optional<bool> is_open = record.GetDict().FindBool("isOpen");
Maks Orlovich442f3782021-06-04 18:05:09808 DCHECK(is_open.has_value());
809 if (!*is_open)
guidou542c74f2016-11-17 18:34:28810 return;
811
Matt Menke67484ed32022-07-22 18:54:33812 record.GetDict().Set("isOpen", false);
Guido Urdaneta0bc103a2018-11-16 19:54:33813 MaybeMarkPeerConnectionAsNotConnected(record);
814}
815
Elaine Chien5df4237b2022-01-07 18:51:39816void WebRTCInternals::MaybeMarkPeerConnectionAsConnected(base::Value& record) {
Elad Alon67ac27bc42022-05-03 15:30:26817 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Matt Menke67484ed32022-07-22 18:54:33818 bool was_connected = record.GetDict().FindBool("connected").value_or(true);
Guido Urdaneta0bc103a2018-11-16 19:54:33819 if (!was_connected) {
820 ++num_connected_connections_;
Matt Menke67484ed32022-07-22 18:54:33821 record.GetDict().Set("connected", true);
Guido Urdaneta0bc103a2018-11-16 19:54:33822 UpdateWakeLock();
Tarun Bansalf153d6832019-06-17 18:18:05823 for (auto& observer : connections_observers_)
824 observer.OnConnectionsCountChange(num_connected_connections_);
Guido Urdaneta0bc103a2018-11-16 19:54:33825 }
826}
827
828void WebRTCInternals::MaybeMarkPeerConnectionAsNotConnected(
Elaine Chien5df4237b2022-01-07 18:51:39829 base::Value& record) {
Elad Alon67ac27bc42022-05-03 15:30:26830 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Matt Menke67484ed32022-07-22 18:54:33831 bool was_connected = record.GetDict().FindBool("connected").value_or(false);
Guido Urdaneta0bc103a2018-11-16 19:54:33832 if (was_connected) {
Matt Menke67484ed32022-07-22 18:54:33833 record.GetDict().Set("connected", false);
Guido Urdaneta0bc103a2018-11-16 19:54:33834 --num_connected_connections_;
835 DCHECK_GE(num_connected_connections_, 0);
836 UpdateWakeLock();
Tarun Bansalf153d6832019-06-17 18:18:05837 for (auto& observer : connections_observers_)
838 observer.OnConnectionsCountChange(num_connected_connections_);
Guido Urdaneta0bc103a2018-11-16 19:54:33839 }
guidou542c74f2016-11-17 18:34:28840}
841
ke.he1671f062017-05-20 00:34:52842void WebRTCInternals::UpdateWakeLock() {
mostynb4c27d042015-03-18 21:47:47843 DCHECK_CURRENTLY_ON(BrowserThread::UI);
maxmorinc369574d2016-07-25 15:28:17844 if (!should_block_power_saving_)
845 return;
[email protected]32eadb442014-08-08 16:55:39846
Guido Urdaneta0bc103a2018-11-16 19:54:33847 if (num_connected_connections_ == 0) {
ke.he1671f062017-05-20 00:34:52848 DVLOG(1)
849 << ("Cancel the wake lock on application suspension since no "
850 "PeerConnections are active anymore.");
juncai8e8d6ec2017-06-06 20:48:18851 GetWakeLock()->CancelWakeLock();
Guido Urdaneta0bc103a2018-11-16 19:54:33852 } else {
853 DCHECK_GT(num_connected_connections_, 0);
[email protected]32eadb442014-08-08 16:55:39854 DVLOG(1) << ("Preventing the application from being suspended while one or "
855 "more PeerConnections are active.");
juncai8e8d6ec2017-06-06 20:48:18856 GetWakeLock()->RequestWakeLock();
[email protected]32eadb442014-08-08 16:55:39857 }
858}
859
juncai8e8d6ec2017-06-06 20:48:18860device::mojom::WakeLock* WebRTCInternals::GetWakeLock() {
Elad Alon67ac27bc42022-05-03 15:30:26861 DCHECK_CURRENTLY_ON(BrowserThread::UI);
ke.he1671f062017-05-20 00:34:52862 // Here is a lazy binding, and will not reconnect after connection error.
juncai8e8d6ec2017-06-06 20:48:18863 if (!wake_lock_) {
Ken Rockot44d73be2019-12-12 22:25:59864 mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
865 GetDeviceService().BindWakeLockProvider(
866 wake_lock_provider.BindNewPipeAndPassReceiver());
867 wake_lock_provider->GetWakeLockWithoutContext(
868 device::mojom::WakeLockType::kPreventAppSuspension,
869 device::mojom::WakeLockReason::kOther,
870 "WebRTC has active PeerConnections",
871 wake_lock_.BindNewPipeAndPassReceiver());
ke.he1671f062017-05-20 00:34:52872 }
juncai8e8d6ec2017-06-06 20:48:18873 return wake_lock_.get();
ke.he1671f062017-05-20 00:34:52874}
875
tommi75d54fe842016-02-09 14:56:30876void WebRTCInternals::ProcessPendingUpdates() {
877 DCHECK_CURRENTLY_ON(BrowserThread::UI);
878 while (!pending_updates_.empty()) {
879 const auto& update = pending_updates_.front();
ericwilligers254597b2016-10-17 10:32:31880 for (auto& observer : observers_)
rbpotter5796b002021-03-10 18:49:21881 observer.OnUpdate(update.event_name(), update.event_data());
tommi75d54fe842016-02-09 14:56:30882 pending_updates_.pop();
883 }
884}
885
Matt Menke67484ed32022-07-22 18:54:33886base::Value::List::iterator WebRTCInternals::FindRecord(
Alexander Timin8690530c2021-06-19 00:34:32887 GlobalRenderFrameHostId frame_id,
Maks Orlovich442f3782021-06-04 18:05:09888 int lid) {
tommi15e9cea2017-03-06 13:56:28889 DCHECK_CURRENTLY_ON(BrowserThread::UI);
890
Matt Menke67484ed32022-07-22 18:54:33891 for (auto it = peer_connection_data().begin();
892 it != peer_connection_data().end(); ++it) {
Maks Orlovich442f3782021-06-04 18:05:09893 DCHECK(it->is_dict());
tommi15e9cea2017-03-06 13:56:28894
Matt Menke67484ed32022-07-22 18:54:33895 int this_rid = it->GetDict().FindInt("rid").value_or(0);
896 int this_lid = it->GetDict().FindInt("lid").value_or(0);
tommi15e9cea2017-03-06 13:56:28897
Maks Orlovich442f3782021-06-04 18:05:09898 if (this_rid == frame_id.child_id && this_lid == lid)
899 return it;
tommi15e9cea2017-03-06 13:56:28900 }
Matt Menke67484ed32022-07-22 18:54:33901 return peer_connection_data().end();
tommi15e9cea2017-03-06 13:56:28902}
[email protected]64ccac32013-01-29 21:40:04903} // namespace content