1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "base/power_monitor/power_observer.h"
16 #include "base/stl_util.h"
17 #include "base/values.h"
18 #include "third_party/blink/public/common/peerconnection/peer_connection_tracker_mojom_traits.h"
19 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
20 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream.h"
21 #include "third_party/blink/public/platform/platform.h"
22 #include "third_party/blink/public/web/web_document.h"
23 #include "third_party/blink/public/web/web_local_frame.h"
24 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
25 #include "third_party/blink/renderer/modules/mediastream/user_media_request.h"
26 #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h"
27 #include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
28 #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
29 #include "third_party/blink/renderer/platform/peerconnection/rtc_answer_options_platform.h"
30 #include "third_party/blink/renderer/platform/peerconnection/rtc_ice_candidate_platform.h"
31 #include "third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h"
32 #include "third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h"
33 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
34 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
35 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
36 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
37
38 using webrtc::StatsReport;
39 using webrtc::StatsReports;
40
41 namespace blink {
42 class InternalStandardStatsObserver;
43 }
44
45 namespace WTF {
46
47 template <>
48 struct CrossThreadCopier<scoped_refptr<blink::InternalStandardStatsObserver>>
49 : public CrossThreadCopierPassThrough<
50 scoped_refptr<blink::InternalStandardStatsObserver>> {
51 STATIC_ONLY(CrossThreadCopier);
52 };
53
54 template <typename T>
55 struct CrossThreadCopier<rtc::scoped_refptr<T>> {
56 STATIC_ONLY(CrossThreadCopier);
57 using Type = rtc::scoped_refptr<T>;
CopyWTF::CrossThreadCopier58 static Type Copy(Type pointer) { return pointer; }
59 };
60
61 } // namespace WTF
62
63 namespace blink {
64
65 // TODO(hta): This module should be redesigned to reduce string copies.
66
67 namespace {
68
SerializeBoolean(bool value)69 String SerializeBoolean(bool value) {
70 return value ? "true" : "false";
71 }
72
SerializeServers(const std::vector<webrtc::PeerConnectionInterface::IceServer> & servers)73 String SerializeServers(
74 const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
75 StringBuilder result;
76 result.Append("[");
77
78 bool following = false;
79 for (const auto& server : servers) {
80 for (const auto& url : server.urls) {
81 if (following)
82 result.Append(", ");
83 else
84 following = true;
85
86 result.Append(String::FromUTF8(url));
87 }
88 }
89 result.Append("]");
90 return result.ToString();
91 }
92
SerializeMediaConstraints(const MediaConstraints & constraints)93 String SerializeMediaConstraints(const MediaConstraints& constraints) {
94 return String(constraints.ToString());
95 }
96
SerializeOfferOptions(blink::RTCOfferOptionsPlatform * options)97 String SerializeOfferOptions(blink::RTCOfferOptionsPlatform* options) {
98 if (!options)
99 return "null";
100
101 StringBuilder result;
102 result.Append("offerToReceiveVideo: ");
103 result.AppendNumber(options->OfferToReceiveVideo());
104 result.Append(", offerToReceiveAudio: ");
105 result.AppendNumber(options->OfferToReceiveAudio());
106 result.Append(", voiceActivityDetection: ");
107 result.Append(SerializeBoolean(options->VoiceActivityDetection()));
108 result.Append(", iceRestart: ");
109 result.Append(SerializeBoolean(options->IceRestart()));
110 return result.ToString();
111 }
112
SerializeAnswerOptions(blink::RTCAnswerOptionsPlatform * options)113 String SerializeAnswerOptions(blink::RTCAnswerOptionsPlatform* options) {
114 if (!options)
115 return "null";
116
117 StringBuilder result;
118 result.Append(", voiceActivityDetection: ");
119 result.Append(SerializeBoolean(options->VoiceActivityDetection()));
120 return result.ToString();
121 }
122
SerializeMediaStreamIds(const Vector<String> & stream_ids)123 String SerializeMediaStreamIds(const Vector<String>& stream_ids) {
124 if (!stream_ids.size())
125 return "[]";
126 StringBuilder result;
127 result.Append("[");
128 for (const auto& stream_id : stream_ids) {
129 if (result.length() > 2u)
130 result.Append(",");
131 result.Append("'");
132 result.Append(stream_id);
133 result.Append("'");
134 }
135 result.Append("]");
136 return result.ToString();
137 }
138
SerializeDirection(webrtc::RtpTransceiverDirection direction)139 String SerializeDirection(webrtc::RtpTransceiverDirection direction) {
140 switch (direction) {
141 case webrtc::RtpTransceiverDirection::kSendRecv:
142 return "'sendrecv'";
143 case webrtc::RtpTransceiverDirection::kSendOnly:
144 return "'sendonly'";
145 case webrtc::RtpTransceiverDirection::kRecvOnly:
146 return "'recvonly'";
147 case webrtc::RtpTransceiverDirection::kInactive:
148 return "'inactive'";
149 case webrtc::RtpTransceiverDirection::kStopped:
150 return "'stopped'";
151 default:
152 NOTREACHED();
153 return String();
154 }
155 }
156
SerializeOptionalDirection(const base::Optional<webrtc::RtpTransceiverDirection> & direction)157 String SerializeOptionalDirection(
158 const base::Optional<webrtc::RtpTransceiverDirection>& direction) {
159 return direction ? SerializeDirection(*direction) : "null";
160 }
161
SerializeSender(const String & indent,const blink::RTCRtpSenderPlatform & sender)162 String SerializeSender(const String& indent,
163 const blink::RTCRtpSenderPlatform& sender) {
164 StringBuilder result;
165 result.Append("{\n");
166 // track:'id',
167 result.Append(indent);
168 result.Append(" track:");
169 if (!sender.Track()) {
170 result.Append("null");
171 } else {
172 result.Append("'");
173 result.Append(sender.Track()->Id());
174 result.Append("'");
175 }
176 result.Append(",\n");
177 // streams:['id,'id'],
178 result.Append(indent);
179 result.Append(" streams:");
180 result.Append(SerializeMediaStreamIds(sender.StreamIds()));
181 result.Append(",\n");
182 result.Append(indent);
183 result.Append("}");
184 return result.ToString();
185 }
186
SerializeReceiver(const String & indent,const RTCRtpReceiverPlatform & receiver)187 String SerializeReceiver(const String& indent,
188 const RTCRtpReceiverPlatform& receiver) {
189 StringBuilder result;
190 result.Append("{\n");
191 // track:'id',
192 DCHECK(receiver.Track());
193 result.Append(indent);
194 result.Append(" track:'");
195 result.Append(receiver.Track()->Id());
196 result.Append("',\n");
197 // streams:['id,'id'],
198 result.Append(indent);
199 result.Append(" streams:");
200 result.Append(SerializeMediaStreamIds(receiver.StreamIds()));
201 result.Append(",\n");
202 result.Append(indent);
203 result.Append("}");
204 return result.ToString();
205 }
206
SerializeTransceiver(const RTCRtpTransceiverPlatform & transceiver)207 String SerializeTransceiver(const RTCRtpTransceiverPlatform& transceiver) {
208 if (transceiver.ImplementationType() ==
209 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver) {
210 StringBuilder result;
211 result.Append("{\n");
212 // mid:'foo',
213 if (transceiver.Mid().IsNull()) {
214 result.Append(" mid:null,\n");
215 } else {
216 result.Append(" mid:'");
217 result.Append(String(transceiver.Mid()));
218 result.Append("',\n");
219 }
220 // sender:{...},
221 result.Append(" sender:");
222 result.Append(SerializeSender(" ", *transceiver.Sender()));
223 result.Append(",\n");
224 // receiver:{...},
225 result.Append(" receiver:");
226 result.Append(SerializeReceiver(" ", *transceiver.Receiver()));
227 result.Append(",\n");
228 // stopped:false,
229 result.Append(" stopped:");
230 result.Append(SerializeBoolean(transceiver.Stopped()));
231 result.Append(",\n");
232 // direction:'sendrecv',
233 result.Append(" direction:");
234 result.Append(SerializeDirection(transceiver.Direction()));
235 result.Append(",\n");
236 // currentDirection:null,
237 result.Append(" currentDirection:");
238 result.Append(SerializeOptionalDirection(transceiver.CurrentDirection()));
239 result.Append(",\n");
240 result.Append("}");
241 return result.ToString();
242 }
243 if (transceiver.ImplementationType() ==
244 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly) {
245 return SerializeSender("", *transceiver.Sender());
246 }
247 DCHECK(transceiver.ImplementationType() ==
248 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
249 return SerializeReceiver("", *transceiver.Receiver());
250 }
251
SerializeIceTransportType(webrtc::PeerConnectionInterface::IceTransportsType type)252 String SerializeIceTransportType(
253 webrtc::PeerConnectionInterface::IceTransportsType type) {
254 String transport_type("");
255 switch (type) {
256 case webrtc::PeerConnectionInterface::kNone:
257 transport_type = "none";
258 break;
259 case webrtc::PeerConnectionInterface::kRelay:
260 transport_type = "relay";
261 break;
262 case webrtc::PeerConnectionInterface::kAll:
263 transport_type = "all";
264 break;
265 case webrtc::PeerConnectionInterface::kNoHost:
266 transport_type = "noHost";
267 break;
268 default:
269 NOTREACHED();
270 }
271 return transport_type;
272 }
273
SerializeBundlePolicy(webrtc::PeerConnectionInterface::BundlePolicy policy)274 String SerializeBundlePolicy(
275 webrtc::PeerConnectionInterface::BundlePolicy policy) {
276 String policy_str("");
277 switch (policy) {
278 case webrtc::PeerConnectionInterface::kBundlePolicyBalanced:
279 policy_str = "balanced";
280 break;
281 case webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle:
282 policy_str = "max-bundle";
283 break;
284 case webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat:
285 policy_str = "max-compat";
286 break;
287 default:
288 NOTREACHED();
289 }
290 return policy_str;
291 }
292
SerializeRtcpMuxPolicy(webrtc::PeerConnectionInterface::RtcpMuxPolicy policy)293 String SerializeRtcpMuxPolicy(
294 webrtc::PeerConnectionInterface::RtcpMuxPolicy policy) {
295 String policy_str("");
296 switch (policy) {
297 case webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate:
298 policy_str = "negotiate";
299 break;
300 case webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire:
301 policy_str = "require";
302 break;
303 default:
304 NOTREACHED();
305 }
306 return policy_str;
307 }
308
SerializeSdpSemantics(webrtc::SdpSemantics sdp_semantics)309 String SerializeSdpSemantics(webrtc::SdpSemantics sdp_semantics) {
310 String sdp_semantics_str("");
311 switch (sdp_semantics) {
312 case webrtc::SdpSemantics::kPlanB:
313 sdp_semantics_str = "plan-b";
314 break;
315 case webrtc::SdpSemantics::kUnifiedPlan:
316 sdp_semantics_str = "unified-plan";
317 break;
318 default:
319 NOTREACHED();
320 }
321 return sdp_semantics_str;
322 }
323
SerializeConfiguration(const webrtc::PeerConnectionInterface::RTCConfiguration & config)324 String SerializeConfiguration(
325 const webrtc::PeerConnectionInterface::RTCConfiguration& config) {
326 StringBuilder result;
327 // TODO(hbos): Add serialization of certificate.
328 result.Append("{ iceServers: ");
329 result.Append(SerializeServers(config.servers));
330 result.Append(", iceTransportPolicy: ");
331 result.Append(SerializeIceTransportType(config.type));
332 result.Append(", bundlePolicy: ");
333 result.Append(SerializeBundlePolicy(config.bundle_policy));
334 result.Append(", rtcpMuxPolicy: ");
335 result.Append(SerializeRtcpMuxPolicy(config.rtcp_mux_policy));
336 result.Append(", iceCandidatePoolSize: ");
337 result.AppendNumber(config.ice_candidate_pool_size);
338 result.Append(", sdpSemantics: \"");
339 result.Append(SerializeSdpSemantics(config.sdp_semantics));
340 result.Append("\" }");
341 return result.ToString();
342 }
343
344 // Note: All of these strings need to be kept in sync with
345 // peer_connection_update_table.js, in order to be displayed as friendly
346 // strings on chrome://webrtc-internals.
347
GetSignalingStateString(webrtc::PeerConnectionInterface::SignalingState state)348 const char* GetSignalingStateString(
349 webrtc::PeerConnectionInterface::SignalingState state) {
350 const char* result = "";
351 switch (state) {
352 case webrtc::PeerConnectionInterface::SignalingState::kStable:
353 return "SignalingStateStable";
354 case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalOffer:
355 return "SignalingStateHaveLocalOffer";
356 case webrtc::PeerConnectionInterface::SignalingState::kHaveRemoteOffer:
357 return "SignalingStateHaveRemoteOffer";
358 case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalPrAnswer:
359 return "SignalingStateHaveLocalPrAnswer";
360 case webrtc::PeerConnectionInterface::SignalingState::kHaveRemotePrAnswer:
361 return "SignalingStateHaveRemotePrAnswer";
362 case webrtc::PeerConnectionInterface::SignalingState::kClosed:
363 return "SignalingStateClosed";
364 default:
365 NOTREACHED();
366 break;
367 }
368 return result;
369 }
370
GetIceConnectionStateString(webrtc::PeerConnectionInterface::IceConnectionState state)371 const char* GetIceConnectionStateString(
372 webrtc::PeerConnectionInterface::IceConnectionState state) {
373 switch (state) {
374 case webrtc::PeerConnectionInterface::kIceConnectionNew:
375 return "new";
376 case webrtc::PeerConnectionInterface::kIceConnectionChecking:
377 return "checking";
378 case webrtc::PeerConnectionInterface::kIceConnectionConnected:
379 return "connected";
380 case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
381 return "completed";
382 case webrtc::PeerConnectionInterface::kIceConnectionFailed:
383 return "failed";
384 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
385 return "disconnected";
386 case webrtc::PeerConnectionInterface::kIceConnectionClosed:
387 return "closed";
388 default:
389 NOTREACHED();
390 return "";
391 }
392 }
393
GetConnectionStateString(webrtc::PeerConnectionInterface::PeerConnectionState state)394 const char* GetConnectionStateString(
395 webrtc::PeerConnectionInterface::PeerConnectionState state) {
396 switch (state) {
397 case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
398 return "new";
399 case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
400 return "connecting";
401 case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
402 return "connected";
403 case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
404 return "disconnected";
405 case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
406 return "failed";
407 case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
408 return "closed";
409 default:
410 NOTREACHED();
411 return "";
412 }
413 }
414
GetIceGatheringStateString(webrtc::PeerConnectionInterface::IceGatheringState state)415 const char* GetIceGatheringStateString(
416 webrtc::PeerConnectionInterface::IceGatheringState state) {
417 switch (state) {
418 case webrtc::PeerConnectionInterface::kIceGatheringNew:
419 return "new";
420 case webrtc::PeerConnectionInterface::kIceGatheringGathering:
421 return "gathering";
422 case webrtc::PeerConnectionInterface::kIceGatheringComplete:
423 return "complete";
424 default:
425 NOTREACHED();
426 return "";
427 }
428 }
429
GetTransceiverUpdatedReasonString(PeerConnectionTracker::TransceiverUpdatedReason reason)430 const char* GetTransceiverUpdatedReasonString(
431 PeerConnectionTracker::TransceiverUpdatedReason reason) {
432 switch (reason) {
433 case PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver:
434 return "addTransceiver";
435 case PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack:
436 return "addTrack";
437 case PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack:
438 return "removeTrack";
439 case PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription:
440 return "setLocalDescription";
441 case PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription:
442 return "setRemoteDescription";
443 }
444 NOTREACHED();
445 return nullptr;
446 }
447
448 // Builds a DictionaryValue from the StatsReport.
449 // Note:
450 // The format must be consistent with what webrtc_internals.js expects.
451 // If you change it here, you must change webrtc_internals.js as well.
GetDictValueStats(const StatsReport & report)452 std::unique_ptr<base::DictionaryValue> GetDictValueStats(
453 const StatsReport& report) {
454 if (report.values().empty())
455 return nullptr;
456
457 auto values = std::make_unique<base::ListValue>();
458
459 for (const auto& v : report.values()) {
460 const StatsReport::ValuePtr& value = v.second;
461 values->AppendString(value->display_name());
462 switch (value->type()) {
463 case StatsReport::Value::kInt:
464 values->AppendInteger(value->int_val());
465 break;
466 case StatsReport::Value::kFloat:
467 values->AppendDouble(value->float_val());
468 break;
469 case StatsReport::Value::kString:
470 values->AppendString(value->string_val());
471 break;
472 case StatsReport::Value::kStaticString:
473 values->AppendString(value->static_string_val());
474 break;
475 case StatsReport::Value::kBool:
476 values->AppendBoolean(value->bool_val());
477 break;
478 case StatsReport::Value::kInt64: // int64_t isn't supported, so use
479 // string.
480 case StatsReport::Value::kId:
481 default:
482 values->AppendString(value->ToString());
483 break;
484 }
485 }
486
487 auto dict = std::make_unique<base::DictionaryValue>();
488 dict->SetDouble("timestamp", report.timestamp());
489 dict->Set("values", std::move(values));
490
491 return dict;
492 }
493
494 // Builds a DictionaryValue from the StatsReport.
495 // The caller takes the ownership of the returned value.
GetDictValue(const StatsReport & report)496 std::unique_ptr<base::DictionaryValue> GetDictValue(const StatsReport& report) {
497 std::unique_ptr<base::DictionaryValue> stats = GetDictValueStats(report);
498 if (!stats)
499 return nullptr;
500
501 // Note:
502 // The format must be consistent with what webrtc_internals.js expects.
503 // If you change it here, you must change webrtc_internals.js as well.
504 auto result = std::make_unique<base::DictionaryValue>();
505 result->Set("stats", std::move(stats));
506 result->SetString("id", report.id()->ToString());
507 result->SetString("type", report.TypeToString());
508
509 return result;
510 }
511
512 } // namespace
513
514 // chrome://webrtc-internals displays stats and stats graphs. The call path
515 // involves thread and process hops (IPC). This is the webrtc::StatsObserver
516 // that is used when webrtc-internals wants legacy stats. It starts in
517 // webrtc_internals.js performing requestLegacyStats and the result gets
518 // asynchronously delivered to webrtc_internals.js at addLegacyStats.
519 class InternalLegacyStatsObserver : public webrtc::StatsObserver {
520 public:
InternalLegacyStatsObserver(int lid,scoped_refptr<base::SingleThreadTaskRunner> main_thread,CrossThreadOnceFunction<void (int,base::Value)> completion_callback)521 InternalLegacyStatsObserver(
522 int lid,
523 scoped_refptr<base::SingleThreadTaskRunner> main_thread,
524 CrossThreadOnceFunction<void(int, base::Value)> completion_callback)
525 : lid_(lid),
526 main_thread_(std::move(main_thread)),
527 completion_callback_(std::move(completion_callback)) {}
528
OnComplete(const StatsReports & reports)529 void OnComplete(const StatsReports& reports) override {
530 auto list = std::make_unique<base::ListValue>();
531 for (const auto* r : reports) {
532 std::unique_ptr<base::DictionaryValue> report = GetDictValue(*r);
533 if (report)
534 list->Append(std::move(report));
535 }
536
537 if (!list->empty()) {
538 PostCrossThreadTask(
539 *main_thread_.get(), FROM_HERE,
540 CrossThreadBindOnce(&InternalLegacyStatsObserver::OnCompleteImpl,
541 std::move(list), lid_,
542 std::move(completion_callback_)));
543 }
544 }
545
546 protected:
~InternalLegacyStatsObserver()547 ~InternalLegacyStatsObserver() override {
548 // Will be destructed on libjingle's signaling thread.
549 // The signaling thread is where libjingle's objects live and from where
550 // libjingle makes callbacks. This may or may not be the same thread as
551 // the main thread.
552 }
553
554 private:
555 // Static since |this| will most likely have been deleted by the time we
556 // get here.
OnCompleteImpl(std::unique_ptr<base::ListValue> list,int lid,CrossThreadOnceFunction<void (int,base::Value)> completion_callback)557 static void OnCompleteImpl(
558 std::unique_ptr<base::ListValue> list,
559 int lid,
560 CrossThreadOnceFunction<void(int, base::Value)> completion_callback) {
561 DCHECK(!list->empty());
562 std::move(completion_callback).Run(lid, std::move(*list.get()));
563 }
564
565 const int lid_;
566 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
567 CrossThreadOnceFunction<void(int, base::Value)> completion_callback_;
568 };
569
570 // chrome://webrtc-internals displays stats and stats graphs. The call path
571 // involves thread and process hops (IPC). This is the ----webrtc::StatsObserver
572 // that is used when webrtc-internals wants standard stats. It starts in
573 // webrtc_internals.js performing requestStandardStats and the result gets
574 // asynchronously delivered to webrtc_internals.js at addStandardStats.
575 class InternalStandardStatsObserver : public webrtc::RTCStatsCollectorCallback {
576 public:
InternalStandardStatsObserver(int lid,scoped_refptr<base::SingleThreadTaskRunner> main_thread,CrossThreadOnceFunction<void (int,base::Value)> completion_callback)577 InternalStandardStatsObserver(
578 int lid,
579 scoped_refptr<base::SingleThreadTaskRunner> main_thread,
580 CrossThreadOnceFunction<void(int, base::Value)> completion_callback)
581 : lid_(lid),
582 main_thread_(std::move(main_thread)),
583 completion_callback_(std::move(completion_callback)) {}
584
OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport> & report)585 void OnStatsDelivered(
586 const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override {
587 // We're on the signaling thread.
588 DCHECK(!main_thread_->BelongsToCurrentThread());
589 PostCrossThreadTask(
590 *main_thread_.get(), FROM_HERE,
591 CrossThreadBindOnce(
592 &InternalStandardStatsObserver::OnStatsDeliveredOnMainThread,
593 scoped_refptr<InternalStandardStatsObserver>(this), report));
594 }
595
596 protected:
~InternalStandardStatsObserver()597 ~InternalStandardStatsObserver() override {}
598
599 private:
OnStatsDeliveredOnMainThread(rtc::scoped_refptr<const webrtc::RTCStatsReport> report)600 void OnStatsDeliveredOnMainThread(
601 rtc::scoped_refptr<const webrtc::RTCStatsReport> report) {
602 auto list = ReportToList(report);
603 std::move(completion_callback_).Run(lid_, std::move(*list.get()));
604 }
605
ReportToList(const rtc::scoped_refptr<const webrtc::RTCStatsReport> & report)606 std::unique_ptr<base::ListValue> ReportToList(
607 const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) {
608 std::unique_ptr<base::ListValue> result_list(new base::ListValue());
609 for (const auto& stats : *report) {
610 // The format of "stats_subdictionary" is:
611 // {timestamp:<milliseconds>, values: [<key-value pairs>]}
612 auto stats_subdictionary = std::make_unique<base::DictionaryValue>();
613 // Timestamp is reported in milliseconds.
614 stats_subdictionary->SetDouble("timestamp",
615 stats.timestamp_us() / 1000.0);
616 // Values are reported as
617 // "values": ["member1", value, "member2", value...]
618 auto name_value_pairs = std::make_unique<base::ListValue>();
619 for (const auto* member : stats.Members()) {
620 if (!member->is_defined())
621 continue;
622 // Non-standardized / provisional stats which are not exposed
623 // to Javascript are postfixed with an asterisk.
624 std::string postfix = member->is_standardized() ? "" : "*";
625 name_value_pairs->AppendString(member->name() + postfix);
626 name_value_pairs->Append(MemberToValue(*member));
627 }
628 stats_subdictionary->Set("values", std::move(name_value_pairs));
629
630 // The format of "stats_dictionary" is:
631 // {id:<string>, stats:<stats_subdictionary>, type:<string>}
632 auto stats_dictionary = std::make_unique<base::DictionaryValue>();
633 stats_dictionary->Set("stats", std::move(stats_subdictionary));
634 stats_dictionary->SetString("id", stats.id());
635 stats_dictionary->SetString("type", stats.type());
636 result_list->Append(std::move(stats_dictionary));
637 }
638 return result_list;
639 }
640
MemberToValue(const webrtc::RTCStatsMemberInterface & member)641 std::unique_ptr<base::Value> MemberToValue(
642 const webrtc::RTCStatsMemberInterface& member) {
643 switch (member.type()) {
644 // Types supported by base::Value are passed as the appropriate type.
645 case webrtc::RTCStatsMemberInterface::Type::kBool:
646 return std::make_unique<base::Value>(
647 *member.cast_to<webrtc::RTCStatsMember<bool>>());
648 case webrtc::RTCStatsMemberInterface::Type::kInt32:
649 return std::make_unique<base::Value>(
650 *member.cast_to<webrtc::RTCStatsMember<int32_t>>());
651 case webrtc::RTCStatsMemberInterface::Type::kString:
652 return std::make_unique<base::Value>(
653 *member.cast_to<webrtc::RTCStatsMember<std::string>>());
654 // Types not supported by base::Value are converted to string.
655 case webrtc::RTCStatsMemberInterface::Type::kUint32:
656 case webrtc::RTCStatsMemberInterface::Type::kInt64:
657 case webrtc::RTCStatsMemberInterface::Type::kUint64:
658 case webrtc::RTCStatsMemberInterface::Type::kDouble:
659 case webrtc::RTCStatsMemberInterface::Type::kSequenceBool:
660 case webrtc::RTCStatsMemberInterface::Type::kSequenceInt32:
661 case webrtc::RTCStatsMemberInterface::Type::kSequenceUint32:
662 case webrtc::RTCStatsMemberInterface::Type::kSequenceInt64:
663 case webrtc::RTCStatsMemberInterface::Type::kSequenceUint64:
664 case webrtc::RTCStatsMemberInterface::Type::kSequenceDouble:
665 case webrtc::RTCStatsMemberInterface::Type::kSequenceString:
666 default:
667 return std::make_unique<base::Value>(member.ValueToString());
668 }
669 }
670
671 const int lid_;
672 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
673 CrossThreadOnceFunction<void(int, base::Value)> completion_callback_;
674 };
675
676 // static
GetInstance()677 PeerConnectionTracker* PeerConnectionTracker::GetInstance() {
678 DEFINE_STATIC_LOCAL(PeerConnectionTracker, instance,
679 (Thread::MainThread()->GetTaskRunner()));
680 return &instance;
681 }
682
PeerConnectionTracker(scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)683 PeerConnectionTracker::PeerConnectionTracker(
684 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
685 : next_local_id_(1),
686 main_thread_task_runner_(std::move(main_thread_task_runner)) {
687 blink::Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
688 peer_connection_tracker_host_.BindNewPipeAndPassReceiver());
689 }
690
PeerConnectionTracker(mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost> host,scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)691 PeerConnectionTracker::PeerConnectionTracker(
692 mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost> host,
693 scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
694 : next_local_id_(1),
695 peer_connection_tracker_host_(std::move(host)),
696 main_thread_task_runner_(std::move(main_thread_task_runner)) {}
697
~PeerConnectionTracker()698 PeerConnectionTracker::~PeerConnectionTracker() {}
699
Bind(mojo::PendingReceiver<blink::mojom::blink::PeerConnectionManager> receiver)700 void PeerConnectionTracker::Bind(
701 mojo::PendingReceiver<blink::mojom::blink::PeerConnectionManager>
702 receiver) {
703 DCHECK(!receiver_.is_bound());
704 receiver_.Bind(std::move(receiver));
705 }
706
OnSuspend()707 void PeerConnectionTracker::OnSuspend() {
708 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
709 // Closing peer connections fires events. If JavaScript triggers the creation
710 // or garbage collection of more peer connections, this would invalidate the
711 // |peer_connection_local_id_map_| iterator. Therefor we iterate on a copy.
712 PeerConnectionLocalIdMap peer_connection_map_copy =
713 peer_connection_local_id_map_;
714 for (const auto& pair : peer_connection_map_copy) {
715 RTCPeerConnectionHandler* peer_connection_handler = pair.key;
716 if (!base::Contains(peer_connection_local_id_map_,
717 peer_connection_handler)) {
718 // Skip peer connections that have been unregistered during this method
719 // call. Avoids use-after-free.
720 continue;
721 }
722 peer_connection_handler->CloseClientPeerConnection();
723 }
724 }
725
OnThermalStateChange(mojom::blink::DeviceThermalState thermal_state)726 void PeerConnectionTracker::OnThermalStateChange(
727 mojom::blink::DeviceThermalState thermal_state) {
728 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
729 mojo::EnumTraits<mojom::blink::DeviceThermalState,
730 base::PowerObserver::DeviceThermalState>::
731 FromMojom(thermal_state, ¤t_thermal_state_);
732 for (auto& entry : peer_connection_local_id_map_) {
733 entry.key->OnThermalStateChange(current_thermal_state_);
734 }
735 }
736
StartEventLog(int peer_connection_local_id,int output_period_ms)737 void PeerConnectionTracker::StartEventLog(int peer_connection_local_id,
738 int output_period_ms) {
739 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
740 for (auto& it : peer_connection_local_id_map_) {
741 if (it.value == peer_connection_local_id) {
742 it.key->StartEventLog(output_period_ms);
743 return;
744 }
745 }
746 }
747
StopEventLog(int peer_connection_local_id)748 void PeerConnectionTracker::StopEventLog(int peer_connection_local_id) {
749 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
750 for (auto& it : peer_connection_local_id_map_) {
751 if (it.value == peer_connection_local_id) {
752 it.key->StopEventLog();
753 return;
754 }
755 }
756 }
757
GetStandardStats()758 void PeerConnectionTracker::GetStandardStats() {
759 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
760
761 for (const auto& pair : peer_connection_local_id_map_) {
762 scoped_refptr<InternalStandardStatsObserver> observer(
763 new rtc::RefCountedObject<InternalStandardStatsObserver>(
764 pair.value, main_thread_task_runner_,
765 CrossThreadBindOnce(&PeerConnectionTracker::AddStandardStats,
766 AsWeakPtr())));
767 pair.key->GetStandardStatsForTracker(observer);
768 }
769 }
770
GetLegacyStats()771 void PeerConnectionTracker::GetLegacyStats() {
772 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
773
774 for (const auto& pair : peer_connection_local_id_map_) {
775 rtc::scoped_refptr<InternalLegacyStatsObserver> observer(
776 new rtc::RefCountedObject<InternalLegacyStatsObserver>(
777 pair.value, main_thread_task_runner_,
778 CrossThreadBindOnce(&PeerConnectionTracker::AddLegacyStats,
779 AsWeakPtr())));
780 pair.key->GetStats(observer,
781 webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
782 nullptr);
783 }
784 }
785
RegisterPeerConnection(RTCPeerConnectionHandler * pc_handler,const webrtc::PeerConnectionInterface::RTCConfiguration & config,const MediaConstraints & constraints,const blink::WebLocalFrame * frame)786 void PeerConnectionTracker::RegisterPeerConnection(
787 RTCPeerConnectionHandler* pc_handler,
788 const webrtc::PeerConnectionInterface::RTCConfiguration& config,
789 const MediaConstraints& constraints,
790 const blink::WebLocalFrame* frame) {
791 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
792 DCHECK(pc_handler);
793 DCHECK_EQ(GetLocalIDForHandler(pc_handler), -1);
794 DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
795 auto info = blink::mojom::blink::PeerConnectionInfo::New();
796
797 info->lid = GetNextLocalID();
798 info->rtc_configuration = SerializeConfiguration(config);
799
800 info->constraints = SerializeMediaConstraints(constraints);
801 if (frame)
802 info->url = frame->GetDocument().Url().GetString();
803 else
804 info->url = "test:testing";
805
806 int32_t lid = info->lid;
807 peer_connection_tracker_host_->AddPeerConnection(std::move(info));
808
809 peer_connection_local_id_map_.insert(pc_handler, lid);
810
811 if (current_thermal_state_ !=
812 base::PowerObserver::DeviceThermalState::kUnknown) {
813 pc_handler->OnThermalStateChange(current_thermal_state_);
814 }
815 }
816
UnregisterPeerConnection(RTCPeerConnectionHandler * pc_handler)817 void PeerConnectionTracker::UnregisterPeerConnection(
818 RTCPeerConnectionHandler* pc_handler) {
819 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
820 DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
821
822 auto it = peer_connection_local_id_map_.find(pc_handler);
823
824 if (it == peer_connection_local_id_map_.end()) {
825 // The PeerConnection might not have been registered if its initilization
826 // failed.
827 return;
828 }
829
830 peer_connection_tracker_host_->RemovePeerConnection(it->value);
831
832 peer_connection_local_id_map_.erase(it);
833 }
834
TrackCreateOffer(RTCPeerConnectionHandler * pc_handler,RTCOfferOptionsPlatform * options)835 void PeerConnectionTracker::TrackCreateOffer(
836 RTCPeerConnectionHandler* pc_handler,
837 RTCOfferOptionsPlatform* options) {
838 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
839 int id = GetLocalIDForHandler(pc_handler);
840 if (id == -1)
841 return;
842 SendPeerConnectionUpdate(id, "createOffer",
843 "options: {" + SerializeOfferOptions(options) + "}");
844 }
845
TrackCreateOffer(RTCPeerConnectionHandler * pc_handler,const MediaConstraints & constraints)846 void PeerConnectionTracker::TrackCreateOffer(
847 RTCPeerConnectionHandler* pc_handler,
848 const MediaConstraints& constraints) {
849 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
850 int id = GetLocalIDForHandler(pc_handler);
851 if (id == -1)
852 return;
853 SendPeerConnectionUpdate(
854 id, "createOffer",
855 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
856 }
857
TrackCreateAnswer(RTCPeerConnectionHandler * pc_handler,blink::RTCAnswerOptionsPlatform * options)858 void PeerConnectionTracker::TrackCreateAnswer(
859 RTCPeerConnectionHandler* pc_handler,
860 blink::RTCAnswerOptionsPlatform* options) {
861 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
862 int id = GetLocalIDForHandler(pc_handler);
863 if (id == -1)
864 return;
865 SendPeerConnectionUpdate(
866 id, "createAnswer", "options: {" + SerializeAnswerOptions(options) + "}");
867 }
868
TrackCreateAnswer(RTCPeerConnectionHandler * pc_handler,const MediaConstraints & constraints)869 void PeerConnectionTracker::TrackCreateAnswer(
870 RTCPeerConnectionHandler* pc_handler,
871 const MediaConstraints& constraints) {
872 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
873 int id = GetLocalIDForHandler(pc_handler);
874 if (id == -1)
875 return;
876 SendPeerConnectionUpdate(
877 id, "createAnswer",
878 "constraints: {" + SerializeMediaConstraints(constraints) + "}");
879 }
880
TrackSetSessionDescription(RTCPeerConnectionHandler * pc_handler,const String & sdp,const String & type,Source source)881 void PeerConnectionTracker::TrackSetSessionDescription(
882 RTCPeerConnectionHandler* pc_handler,
883 const String& sdp,
884 const String& type,
885 Source source) {
886 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
887 int id = GetLocalIDForHandler(pc_handler);
888 if (id == -1)
889 return;
890 String value = "type: " + type + ", sdp: " + sdp;
891 SendPeerConnectionUpdate(
892 id,
893 source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
894 value);
895 }
896
TrackSetSessionDescriptionImplicit(RTCPeerConnectionHandler * pc_handler)897 void PeerConnectionTracker::TrackSetSessionDescriptionImplicit(
898 RTCPeerConnectionHandler* pc_handler) {
899 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
900 int id = GetLocalIDForHandler(pc_handler);
901 if (id == -1)
902 return;
903 SendPeerConnectionUpdate(id, "setLocalDescriptionImplicitCreateOfferOrAnswer",
904 "");
905 }
906
TrackSetConfiguration(RTCPeerConnectionHandler * pc_handler,const webrtc::PeerConnectionInterface::RTCConfiguration & config)907 void PeerConnectionTracker::TrackSetConfiguration(
908 RTCPeerConnectionHandler* pc_handler,
909 const webrtc::PeerConnectionInterface::RTCConfiguration& config) {
910 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
911 int id = GetLocalIDForHandler(pc_handler);
912 if (id == -1)
913 return;
914
915 SendPeerConnectionUpdate(id, "setConfiguration",
916 SerializeConfiguration(config));
917 }
918
TrackAddIceCandidate(RTCPeerConnectionHandler * pc_handler,RTCIceCandidatePlatform * candidate,Source source,bool succeeded)919 void PeerConnectionTracker::TrackAddIceCandidate(
920 RTCPeerConnectionHandler* pc_handler,
921 RTCIceCandidatePlatform* candidate,
922 Source source,
923 bool succeeded) {
924 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
925 int id = GetLocalIDForHandler(pc_handler);
926 if (id == -1)
927 return;
928 String value =
929 "sdpMid: " + String(candidate->SdpMid()) + ", " + "sdpMLineIndex: " +
930 (candidate->SdpMLineIndex() ? String::Number(*candidate->SdpMLineIndex())
931 : "null") +
932 ", " + "candidate: " + String(candidate->Candidate());
933
934 // OnIceCandidate always succeeds as it's a callback from the browser.
935 DCHECK(source != SOURCE_LOCAL || succeeded);
936
937 const char* event =
938 (source == SOURCE_LOCAL)
939 ? "onIceCandidate"
940 : (succeeded ? "addIceCandidate" : "addIceCandidateFailed");
941
942 SendPeerConnectionUpdate(id, event, value);
943 }
944
TrackIceCandidateError(RTCPeerConnectionHandler * pc_handler,const String & address,base::Optional<uint16_t> port,const String & host_candidate,const String & url,int error_code,const String & error_text)945 void PeerConnectionTracker::TrackIceCandidateError(
946 RTCPeerConnectionHandler* pc_handler,
947 const String& address,
948 base::Optional<uint16_t> port,
949 const String& host_candidate,
950 const String& url,
951 int error_code,
952 const String& error_text) {
953 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
954 int id = GetLocalIDForHandler(pc_handler);
955 if (id == -1)
956 return;
957 String address_string = address ? "address: " + address + "\n" : String();
958 String port_string =
959 port.has_value() ? String::Format("port: %d\n", port.value()) : "";
960 String value = "url: " + url + "\n" + address_string + port_string +
961 "host_candidate: " + host_candidate + "\n" +
962 "error_text: " + error_text + "\n" +
963 "error_code: " + String::Number(error_code);
964 SendPeerConnectionUpdate(id, "icecandidateerror", value);
965 }
966
TrackAddTransceiver(RTCPeerConnectionHandler * pc_handler,PeerConnectionTracker::TransceiverUpdatedReason reason,const RTCRtpTransceiverPlatform & transceiver,size_t transceiver_index)967 void PeerConnectionTracker::TrackAddTransceiver(
968 RTCPeerConnectionHandler* pc_handler,
969 PeerConnectionTracker::TransceiverUpdatedReason reason,
970 const RTCRtpTransceiverPlatform& transceiver,
971 size_t transceiver_index) {
972 TrackTransceiver("Added", pc_handler, reason, transceiver, transceiver_index);
973 }
974
TrackModifyTransceiver(RTCPeerConnectionHandler * pc_handler,PeerConnectionTracker::TransceiverUpdatedReason reason,const RTCRtpTransceiverPlatform & transceiver,size_t transceiver_index)975 void PeerConnectionTracker::TrackModifyTransceiver(
976 RTCPeerConnectionHandler* pc_handler,
977 PeerConnectionTracker::TransceiverUpdatedReason reason,
978 const RTCRtpTransceiverPlatform& transceiver,
979 size_t transceiver_index) {
980 TrackTransceiver("Modified", pc_handler, reason, transceiver,
981 transceiver_index);
982 }
983
TrackRemoveTransceiver(RTCPeerConnectionHandler * pc_handler,PeerConnectionTracker::TransceiverUpdatedReason reason,const RTCRtpTransceiverPlatform & transceiver,size_t transceiver_index)984 void PeerConnectionTracker::TrackRemoveTransceiver(
985 RTCPeerConnectionHandler* pc_handler,
986 PeerConnectionTracker::TransceiverUpdatedReason reason,
987 const RTCRtpTransceiverPlatform& transceiver,
988 size_t transceiver_index) {
989 TrackTransceiver("Removed", pc_handler, reason, transceiver,
990 transceiver_index);
991 }
992
TrackTransceiver(const char * callback_type_ending,RTCPeerConnectionHandler * pc_handler,PeerConnectionTracker::TransceiverUpdatedReason reason,const RTCRtpTransceiverPlatform & transceiver,size_t transceiver_index)993 void PeerConnectionTracker::TrackTransceiver(
994 const char* callback_type_ending,
995 RTCPeerConnectionHandler* pc_handler,
996 PeerConnectionTracker::TransceiverUpdatedReason reason,
997 const RTCRtpTransceiverPlatform& transceiver,
998 size_t transceiver_index) {
999 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1000 int id = GetLocalIDForHandler(pc_handler);
1001 if (id == -1)
1002 return;
1003 String callback_type;
1004 if (transceiver.ImplementationType() ==
1005 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver) {
1006 callback_type = "transceiver";
1007 } else if (transceiver.ImplementationType() ==
1008 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly) {
1009 callback_type = "sender";
1010 } else {
1011 callback_type = "receiver";
1012 }
1013 callback_type = callback_type + callback_type_ending;
1014
1015 StringBuilder result;
1016 result.Append("Caused by: ");
1017 result.Append(GetTransceiverUpdatedReasonString(reason));
1018 result.Append("\n\n");
1019 if (transceiver.ImplementationType() ==
1020 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver) {
1021 result.Append("getTransceivers()");
1022 } else if (transceiver.ImplementationType() ==
1023 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly) {
1024 result.Append("getSenders()");
1025 } else {
1026 DCHECK_EQ(transceiver.ImplementationType(),
1027 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
1028 result.Append("getReceivers()");
1029 }
1030 result.Append(String("[" + String::Number(transceiver_index) + "]:"));
1031 result.Append(SerializeTransceiver(transceiver));
1032 SendPeerConnectionUpdate(id, callback_type, result.ToString());
1033 }
1034
TrackCreateDataChannel(RTCPeerConnectionHandler * pc_handler,const webrtc::DataChannelInterface * data_channel,Source source)1035 void PeerConnectionTracker::TrackCreateDataChannel(
1036 RTCPeerConnectionHandler* pc_handler,
1037 const webrtc::DataChannelInterface* data_channel,
1038 Source source) {
1039 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1040 int id = GetLocalIDForHandler(pc_handler);
1041 if (id == -1)
1042 return;
1043 String value = "label: " + String::FromUTF8(data_channel->label()) +
1044 ", reliable: " + SerializeBoolean(data_channel->reliable());
1045 SendPeerConnectionUpdate(
1046 id,
1047 source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
1048 value);
1049 }
1050
TrackStop(RTCPeerConnectionHandler * pc_handler)1051 void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
1052 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1053 int id = GetLocalIDForHandler(pc_handler);
1054 if (id == -1)
1055 return;
1056 SendPeerConnectionUpdate(id, "stop", String(""));
1057 }
1058
TrackSignalingStateChange(RTCPeerConnectionHandler * pc_handler,webrtc::PeerConnectionInterface::SignalingState state)1059 void PeerConnectionTracker::TrackSignalingStateChange(
1060 RTCPeerConnectionHandler* pc_handler,
1061 webrtc::PeerConnectionInterface::SignalingState state) {
1062 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1063 int id = GetLocalIDForHandler(pc_handler);
1064 if (id == -1)
1065 return;
1066 SendPeerConnectionUpdate(id, "signalingStateChange",
1067 GetSignalingStateString(state));
1068 }
1069
TrackLegacyIceConnectionStateChange(RTCPeerConnectionHandler * pc_handler,webrtc::PeerConnectionInterface::IceConnectionState state)1070 void PeerConnectionTracker::TrackLegacyIceConnectionStateChange(
1071 RTCPeerConnectionHandler* pc_handler,
1072 webrtc::PeerConnectionInterface::IceConnectionState state) {
1073 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1074 int id = GetLocalIDForHandler(pc_handler);
1075 if (id == -1)
1076 return;
1077 SendPeerConnectionUpdate(id, "legacyIceConnectionStateChange",
1078 GetIceConnectionStateString(state));
1079 }
1080
TrackIceConnectionStateChange(RTCPeerConnectionHandler * pc_handler,webrtc::PeerConnectionInterface::IceConnectionState state)1081 void PeerConnectionTracker::TrackIceConnectionStateChange(
1082 RTCPeerConnectionHandler* pc_handler,
1083 webrtc::PeerConnectionInterface::IceConnectionState state) {
1084 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1085 int id = GetLocalIDForHandler(pc_handler);
1086 if (id == -1)
1087 return;
1088 SendPeerConnectionUpdate(id, "iceConnectionStateChange",
1089 GetIceConnectionStateString(state));
1090 }
1091
TrackConnectionStateChange(RTCPeerConnectionHandler * pc_handler,webrtc::PeerConnectionInterface::PeerConnectionState state)1092 void PeerConnectionTracker::TrackConnectionStateChange(
1093 RTCPeerConnectionHandler* pc_handler,
1094 webrtc::PeerConnectionInterface::PeerConnectionState state) {
1095 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1096 int id = GetLocalIDForHandler(pc_handler);
1097 if (id == -1)
1098 return;
1099 SendPeerConnectionUpdate(id, "connectionStateChange",
1100 GetConnectionStateString(state));
1101 }
1102
TrackIceGatheringStateChange(RTCPeerConnectionHandler * pc_handler,webrtc::PeerConnectionInterface::IceGatheringState state)1103 void PeerConnectionTracker::TrackIceGatheringStateChange(
1104 RTCPeerConnectionHandler* pc_handler,
1105 webrtc::PeerConnectionInterface::IceGatheringState state) {
1106 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1107 int id = GetLocalIDForHandler(pc_handler);
1108 if (id == -1)
1109 return;
1110 SendPeerConnectionUpdate(id, "iceGatheringStateChange",
1111 GetIceGatheringStateString(state));
1112 }
1113
TrackSessionDescriptionCallback(RTCPeerConnectionHandler * pc_handler,Action action,const String & callback_type,const String & value)1114 void PeerConnectionTracker::TrackSessionDescriptionCallback(
1115 RTCPeerConnectionHandler* pc_handler,
1116 Action action,
1117 const String& callback_type,
1118 const String& value) {
1119 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1120 int id = GetLocalIDForHandler(pc_handler);
1121 if (id == -1)
1122 return;
1123 String update_type;
1124 switch (action) {
1125 case ACTION_SET_LOCAL_DESCRIPTION:
1126 update_type = "setLocalDescription";
1127 break;
1128 case ACTION_SET_LOCAL_DESCRIPTION_IMPLICIT:
1129 update_type = "setLocalDescriptionImplicitCreateOfferOrAnswer";
1130 break;
1131 case ACTION_SET_REMOTE_DESCRIPTION:
1132 update_type = "setRemoteDescription";
1133 break;
1134 case ACTION_CREATE_OFFER:
1135 update_type = "createOffer";
1136 break;
1137 case ACTION_CREATE_ANSWER:
1138 update_type = "createAnswer";
1139 break;
1140 default:
1141 NOTREACHED();
1142 break;
1143 }
1144 update_type = update_type + callback_type;
1145
1146 SendPeerConnectionUpdate(id, update_type, value);
1147 }
1148
TrackSessionId(RTCPeerConnectionHandler * pc_handler,const String & session_id)1149 void PeerConnectionTracker::TrackSessionId(RTCPeerConnectionHandler* pc_handler,
1150 const String& session_id) {
1151 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1152 DCHECK(pc_handler);
1153 DCHECK(!session_id.IsEmpty());
1154 const int local_id = GetLocalIDForHandler(pc_handler);
1155 if (local_id == -1) {
1156 return;
1157 }
1158
1159 String non_null_session_id =
1160 session_id.IsNull() ? WTF::g_empty_string : session_id;
1161 peer_connection_tracker_host_->OnPeerConnectionSessionIdSet(
1162 local_id, non_null_session_id);
1163 }
1164
TrackOnRenegotiationNeeded(RTCPeerConnectionHandler * pc_handler)1165 void PeerConnectionTracker::TrackOnRenegotiationNeeded(
1166 RTCPeerConnectionHandler* pc_handler) {
1167 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1168 int id = GetLocalIDForHandler(pc_handler);
1169 if (id == -1)
1170 return;
1171 SendPeerConnectionUpdate(id, "onRenegotiationNeeded", String(""));
1172 }
1173
TrackGetUserMedia(UserMediaRequest * user_media_request)1174 void PeerConnectionTracker::TrackGetUserMedia(
1175 UserMediaRequest* user_media_request) {
1176 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1177
1178 // When running tests, it is possible that UserMediaRequest's
1179 // ExecutionContext is null.
1180 //
1181 // TODO(crbug.com/704136): Is there a better way to do this?
1182 String security_origin;
1183 if (!user_media_request->GetExecutionContext()) {
1184 security_origin =
1185 SecurityOrigin::CreateFromString("test://test")->ToString();
1186 } else {
1187 security_origin = user_media_request->GetExecutionContext()
1188 ->GetSecurityOrigin()
1189 ->ToString();
1190 }
1191
1192 peer_connection_tracker_host_->GetUserMedia(
1193 security_origin, user_media_request->Audio(), user_media_request->Video(),
1194 SerializeMediaConstraints(user_media_request->AudioConstraints()),
1195 SerializeMediaConstraints(user_media_request->VideoConstraints()));
1196 }
1197
TrackRtcEventLogWrite(RTCPeerConnectionHandler * pc_handler,const WTF::Vector<uint8_t> & output)1198 void PeerConnectionTracker::TrackRtcEventLogWrite(
1199 RTCPeerConnectionHandler* pc_handler,
1200 const WTF::Vector<uint8_t>& output) {
1201 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1202 int id = GetLocalIDForHandler(pc_handler);
1203 if (id == -1)
1204 return;
1205
1206 peer_connection_tracker_host_->WebRtcEventLogWrite(id, output);
1207 }
1208
GetNextLocalID()1209 int PeerConnectionTracker::GetNextLocalID() {
1210 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1211 if (next_local_id_ < 0)
1212 next_local_id_ = 1;
1213 return next_local_id_++;
1214 }
1215
GetLocalIDForHandler(RTCPeerConnectionHandler * handler) const1216 int PeerConnectionTracker::GetLocalIDForHandler(
1217 RTCPeerConnectionHandler* handler) const {
1218 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1219 const auto found = peer_connection_local_id_map_.find(handler);
1220 if (found == peer_connection_local_id_map_.end())
1221 return -1;
1222 DCHECK_NE(found->value, -1);
1223 return found->value;
1224 }
1225
SendPeerConnectionUpdate(int local_id,const String & callback_type,const String & value)1226 void PeerConnectionTracker::SendPeerConnectionUpdate(
1227 int local_id,
1228 const String& callback_type,
1229 const String& value) {
1230 DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
1231 peer_connection_tracker_host_->UpdatePeerConnection(local_id, callback_type,
1232 value);
1233 }
1234
AddStandardStats(int lid,base::Value value)1235 void PeerConnectionTracker::AddStandardStats(int lid, base::Value value) {
1236 peer_connection_tracker_host_->AddStandardStats(lid, std::move(value));
1237 }
1238
AddLegacyStats(int lid,base::Value value)1239 void PeerConnectionTracker::AddLegacyStats(int lid, base::Value value) {
1240 peer_connection_tracker_host_->AddLegacyStats(lid, std::move(value));
1241 }
1242
1243 } // namespace blink
1244