1 // Copyright 2016 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/rtc_stats_report.h"
6 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
7 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
8
9 #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
10 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
11 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
12 #include "third_party/webrtc/api/stats/rtc_stats.h"
13
14 namespace blink {
15
16 namespace {
17
RTCStatsToValue(ScriptState * script_state,const RTCStats * stats)18 v8::Local<v8::Value> RTCStatsToValue(ScriptState* script_state,
19 const RTCStats* stats) {
20 V8ObjectBuilder builder(script_state);
21
22 builder.AddString("id", stats->Id());
23 builder.AddNumber("timestamp", stats->Timestamp());
24 builder.AddString("type", stats->GetType());
25
26 for (size_t i = 0; i < stats->MembersCount(); ++i) {
27 std::unique_ptr<RTCStatsMember> member = stats->GetMember(i);
28 if (!member->IsDefined())
29 continue;
30 String name = member->GetName();
31 switch (member->GetType()) {
32 case webrtc::RTCStatsMemberInterface::kBool:
33 builder.AddBoolean(name, member->ValueBool());
34 break;
35 case webrtc::RTCStatsMemberInterface::kInt32:
36 builder.AddNumber(name, static_cast<double>(member->ValueInt32()));
37 break;
38 case webrtc::RTCStatsMemberInterface::kUint32:
39 builder.AddNumber(name, static_cast<double>(member->ValueUint32()));
40 break;
41 case webrtc::RTCStatsMemberInterface::kInt64:
42 builder.AddNumber(name, static_cast<double>(member->ValueInt64()));
43 break;
44 case webrtc::RTCStatsMemberInterface::kUint64:
45 builder.AddNumber(name, static_cast<double>(member->ValueUint64()));
46 break;
47 case webrtc::RTCStatsMemberInterface::kDouble:
48 builder.AddNumber(name, member->ValueDouble());
49 break;
50 case webrtc::RTCStatsMemberInterface::kString:
51 builder.AddString(name, member->ValueString());
52 break;
53 case webrtc::RTCStatsMemberInterface::kSequenceBool: {
54 builder.Add(name, member->ValueSequenceBool());
55 break;
56 }
57 case webrtc::RTCStatsMemberInterface::kSequenceInt32:
58 builder.Add(name, member->ValueSequenceInt32());
59 break;
60 case webrtc::RTCStatsMemberInterface::kSequenceUint32:
61 builder.Add(name, member->ValueSequenceUint32());
62 break;
63 case webrtc::RTCStatsMemberInterface::kSequenceInt64:
64 builder.Add(name, member->ValueSequenceInt64());
65 break;
66 case webrtc::RTCStatsMemberInterface::kSequenceUint64:
67 builder.Add(name, member->ValueSequenceUint64());
68 break;
69 case webrtc::RTCStatsMemberInterface::kSequenceDouble:
70 builder.Add(name, member->ValueSequenceDouble());
71 break;
72 case webrtc::RTCStatsMemberInterface::kSequenceString:
73 builder.Add(name, member->ValueSequenceString());
74 break;
75 default:
76 NOTREACHED();
77 }
78 }
79
80 v8::Local<v8::Object> v8_object = builder.V8Value();
81 if (v8_object.IsEmpty()) {
82 NOTREACHED();
83 return v8::Undefined(script_state->GetIsolate());
84 }
85 return v8_object;
86 }
87
88 class RTCStatsReportIterationSource final
89 : public PairIterable<String, v8::Local<v8::Value>>::IterationSource {
90 public:
RTCStatsReportIterationSource(std::unique_ptr<RTCStatsReportPlatform> report)91 RTCStatsReportIterationSource(std::unique_ptr<RTCStatsReportPlatform> report)
92 : report_(std::move(report)) {}
93
Next(ScriptState * script_state,String & key,v8::Local<v8::Value> & value,ExceptionState & exception_state)94 bool Next(ScriptState* script_state,
95 String& key,
96 v8::Local<v8::Value>& value,
97 ExceptionState& exception_state) override {
98 std::unique_ptr<RTCStats> stats = report_->Next();
99 if (!stats)
100 return false;
101 key = stats->Id();
102 value = RTCStatsToValue(script_state, stats.get());
103 return true;
104 }
105
106 private:
107 std::unique_ptr<RTCStatsReportPlatform> report_;
108 };
109
110 } // namespace
111
GetExposedGroupIds(const ScriptState * script_state)112 Vector<webrtc::NonStandardGroupId> GetExposedGroupIds(
113 const ScriptState* script_state) {
114 const ExecutionContext* context = ExecutionContext::From(script_state);
115 DCHECK(context->IsContextThread());
116 Vector<webrtc::NonStandardGroupId> enabled_origin_trials;
117 if (RuntimeEnabledFeatures::RtcAudioJitterBufferMaxPacketsEnabled(context)) {
118 enabled_origin_trials.emplace_back(
119 webrtc::NonStandardGroupId::kRtcAudioJitterBufferMaxPackets);
120 }
121 if (RuntimeEnabledFeatures::RTCStatsRelativePacketArrivalDelayEnabled(
122 context)) {
123 enabled_origin_trials.emplace_back(
124 webrtc::NonStandardGroupId::kRtcStatsRelativePacketArrivalDelay);
125 }
126 return enabled_origin_trials;
127 }
128
RTCStatsReport(std::unique_ptr<RTCStatsReportPlatform> report)129 RTCStatsReport::RTCStatsReport(std::unique_ptr<RTCStatsReportPlatform> report)
130 : report_(std::move(report)) {}
131
size() const132 uint32_t RTCStatsReport::size() const {
133 return base::saturated_cast<uint32_t>(report_->Size());
134 }
135
136 PairIterable<String, v8::Local<v8::Value>>::IterationSource*
StartIteration(ScriptState *,ExceptionState &)137 RTCStatsReport::StartIteration(ScriptState*, ExceptionState&) {
138 return MakeGarbageCollected<RTCStatsReportIterationSource>(
139 report_->CopyHandle());
140 }
141
GetMapEntry(ScriptState * script_state,const String & key,v8::Local<v8::Value> & value,ExceptionState &)142 bool RTCStatsReport::GetMapEntry(ScriptState* script_state,
143 const String& key,
144 v8::Local<v8::Value>& value,
145 ExceptionState&) {
146 std::unique_ptr<RTCStats> stats = report_->GetStats(key);
147 if (!stats)
148 return false;
149 value = RTCStatsToValue(script_state, stats.get());
150 return true;
151 }
152
153 } // namespace blink
154