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