blob: 7f73c9b6d54b6d32c1f98e8d8e3d888b3b621941 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/peerconnection/rtc_stats_report.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
namespace {
v8::Local<v8::Value> WebRTCStatsToValue(ScriptState* script_state,
const WebRTCStats* stats) {
V8ObjectBuilder builder(script_state);
builder.AddString("id", stats->Id());
builder.AddNumber("timestamp", stats->Timestamp());
builder.AddString("type", stats->GetType());
auto add_vector = [&builder](const WebString& name, auto web_vector) {
Vector<typename decltype(web_vector)::value_type> vector(
SafeCast<wtf_size_t>(web_vector.size()));
std::move(web_vector.begin(), web_vector.end(), vector.begin());
builder.Add(name, vector);
};
for (size_t i = 0; i < stats->MembersCount(); ++i) {
std::unique_ptr<WebRTCStatsMember> member = stats->GetMember(i);
if (!member->IsDefined())
continue;
WebString name = member->GetName();
switch (member->GetType()) {
case kWebRTCStatsMemberTypeBool:
builder.AddBoolean(name, member->ValueBool());
break;
case kWebRTCStatsMemberTypeInt32:
builder.AddNumber(name, static_cast<double>(member->ValueInt32()));
break;
case kWebRTCStatsMemberTypeUint32:
builder.AddNumber(name, static_cast<double>(member->ValueUint32()));
break;
case kWebRTCStatsMemberTypeInt64:
builder.AddNumber(name, static_cast<double>(member->ValueInt64()));
break;
case kWebRTCStatsMemberTypeUint64:
builder.AddNumber(name, static_cast<double>(member->ValueUint64()));
break;
case kWebRTCStatsMemberTypeDouble:
builder.AddNumber(name, member->ValueDouble());
break;
case kWebRTCStatsMemberTypeString:
builder.AddString(name, member->ValueString());
break;
case kWebRTCStatsMemberTypeSequenceBool: {
WebVector<int> sequence = member->ValueSequenceBool();
Vector<bool> vector(SafeCast<wtf_size_t>(sequence.size()));
std::copy(sequence.begin(), sequence.end(), vector.begin());
builder.Add(name, vector);
break;
}
case kWebRTCStatsMemberTypeSequenceInt32:
add_vector(name, member->ValueSequenceInt32());
break;
case kWebRTCStatsMemberTypeSequenceUint32:
add_vector(name, member->ValueSequenceUint32());
break;
case kWebRTCStatsMemberTypeSequenceInt64:
add_vector(name, member->ValueSequenceInt64());
break;
case kWebRTCStatsMemberTypeSequenceUint64:
add_vector(name, member->ValueSequenceUint64());
break;
case kWebRTCStatsMemberTypeSequenceDouble:
add_vector(name, member->ValueSequenceDouble());
break;
case kWebRTCStatsMemberTypeSequenceString:
add_vector(name, member->ValueSequenceString());
break;
default:
NOTREACHED();
}
}
v8::Local<v8::Object> v8_object = builder.V8Value();
if (v8_object.IsEmpty()) {
NOTREACHED();
return v8::Undefined(script_state->GetIsolate());
}
return v8_object;
}
class RTCStatsReportIterationSource final
: public PairIterable<String, v8::Local<v8::Value>>::IterationSource {
public:
RTCStatsReportIterationSource(std::unique_ptr<WebRTCStatsReport> report)
: report_(std::move(report)) {}
bool Next(ScriptState* script_state,
String& key,
v8::Local<v8::Value>& value,
ExceptionState& exception_state) override {
std::unique_ptr<WebRTCStats> stats = report_->Next();
if (!stats)
return false;
key = stats->Id();
value = WebRTCStatsToValue(script_state, stats.get());
return true;
}
private:
std::unique_ptr<WebRTCStatsReport> report_;
};
} // namespace
RTCStatsFilter GetRTCStatsFilter(const ScriptState* script_state) {
const ExecutionContext* context = ExecutionContext::From(script_state);
DCHECK(context->IsContextThread());
// If this original trial is enabled then it exposes jitterBufferFlushes
// metric
return origin_trials::RtcAudioJitterBufferMaxPacketsEnabled(context)
? RTCStatsFilter::kIncludeNonStandardMembers
: RTCStatsFilter::kIncludeOnlyStandardMembers;
}
RTCStatsReport::RTCStatsReport(std::unique_ptr<WebRTCStatsReport> report)
: report_(std::move(report)) {}
uint32_t RTCStatsReport::size() const {
return base::saturated_cast<uint32_t>(report_->Size());
}
PairIterable<String, v8::Local<v8::Value>>::IterationSource*
RTCStatsReport::StartIteration(ScriptState*, ExceptionState&) {
return new RTCStatsReportIterationSource(report_->CopyHandle());
}
bool RTCStatsReport::GetMapEntry(ScriptState* script_state,
const String& key,
v8::Local<v8::Value>& value,
ExceptionState&) {
std::unique_ptr<WebRTCStats> stats = report_->GetStats(key);
if (!stats)
return false;
value = WebRTCStatsToValue(script_state, stats.get());
return true;
}
} // namespace blink