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, &current_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