blob: d305c88b1df777b9c28e2c2414966f21674055d9 [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 "modules/peerconnection/RTCStatsReport.h"
namespace blink {
namespace {
template <typename T>
bool addPropertyValue(v8::Local<v8::Object>& v8Object,
v8::Isolate* isolate,
T name,
v8::Local<v8::Value> value) {
return v8CallBoolean(v8Object->CreateDataProperty(
isolate->GetCurrentContext(), v8String(isolate, name), value));
}
bool addPropertySequenceOfBooleans(v8::Local<v8::Object>& v8Object,
v8::Isolate* isolate,
WebString name,
const WebVector<int>& webVector) {
v8::Local<v8::Array> v8Array = v8::Array::New(isolate, webVector.size());
for (size_t i = 0; i < webVector.size(); ++i) {
if (!v8CallBoolean(v8Array->CreateDataProperty(
isolate->GetCurrentContext(), static_cast<uint32_t>(i),
v8::Boolean::New(isolate, static_cast<bool>(webVector[i])))))
return false;
}
return addPropertyValue(v8Object, isolate, name, v8Array);
}
template <typename T>
bool addPropertySequenceOfNumbers(v8::Local<v8::Object>& v8Object,
v8::Isolate* isolate,
WebString name,
const WebVector<T>& webVector) {
v8::Local<v8::Array> v8Array = v8::Array::New(isolate, webVector.size());
for (size_t i = 0; i < webVector.size(); ++i) {
if (!v8CallBoolean(v8Array->CreateDataProperty(
isolate->GetCurrentContext(), static_cast<uint32_t>(i),
v8::Number::New(isolate, static_cast<double>(webVector[i])))))
return false;
}
return addPropertyValue(v8Object, isolate, name, v8Array);
}
bool addPropertySequenceOfStrings(v8::Local<v8::Object>& v8Object,
v8::Isolate* isolate,
WebString name,
const WebVector<WebString>& webVector) {
v8::Local<v8::Array> v8Array = v8::Array::New(isolate, webVector.size());
for (size_t i = 0; i < webVector.size(); ++i) {
if (!v8CallBoolean(v8Array->CreateDataProperty(
isolate->GetCurrentContext(), static_cast<uint32_t>(i),
v8String(isolate, webVector[i]))))
return false;
}
return addPropertyValue(v8Object, isolate, name, v8Array);
}
v8::Local<v8::Value> webRTCStatsToValue(ScriptState* scriptState,
const WebRTCStats* stats) {
v8::Isolate* isolate = scriptState->isolate();
v8::Local<v8::Object> v8Object = v8::Object::New(isolate);
bool success = true;
success &=
addPropertyValue(v8Object, isolate, "id", v8String(isolate, stats->id()));
success &= addPropertyValue(v8Object, isolate, "timestamp",
v8::Number::New(isolate, stats->timestamp()));
success &= addPropertyValue(v8Object, isolate, "type",
v8String(isolate, stats->type()));
for (size_t i = 0; i < stats->membersCount() && success; ++i) {
std::unique_ptr<WebRTCStatsMember> member = stats->getMember(i);
if (!member->isDefined())
continue;
WebString name = member->name();
switch (member->type()) {
case WebRTCStatsMemberTypeBool:
success &=
addPropertyValue(v8Object, isolate, name,
v8::Boolean::New(isolate, member->valueBool()));
break;
case WebRTCStatsMemberTypeInt32:
success &= addPropertyValue(
v8Object, isolate, name,
v8::Number::New(isolate,
static_cast<double>(member->valueInt32())));
break;
case WebRTCStatsMemberTypeUint32:
success &= addPropertyValue(
v8Object, isolate, name,
v8::Number::New(isolate,
static_cast<double>(member->valueUint32())));
break;
case WebRTCStatsMemberTypeInt64:
success &= addPropertyValue(
v8Object, isolate, name,
v8::Number::New(isolate,
static_cast<double>(member->valueInt64())));
break;
case WebRTCStatsMemberTypeUint64:
success &= addPropertyValue(
v8Object, isolate, name,
v8::Number::New(isolate,
static_cast<double>(member->valueUint64())));
break;
case WebRTCStatsMemberTypeDouble:
success &=
addPropertyValue(v8Object, isolate, name,
v8::Number::New(isolate, member->valueDouble()));
break;
case WebRTCStatsMemberTypeString:
success &= addPropertyValue(v8Object, isolate, name,
v8String(isolate, member->valueString()));
break;
case WebRTCStatsMemberTypeSequenceBool:
success &= addPropertySequenceOfBooleans(v8Object, isolate, name,
member->valueSequenceBool());
break;
case WebRTCStatsMemberTypeSequenceInt32:
success &= addPropertySequenceOfNumbers(v8Object, isolate, name,
member->valueSequenceInt32());
break;
case WebRTCStatsMemberTypeSequenceUint32:
success &= addPropertySequenceOfNumbers(v8Object, isolate, name,
member->valueSequenceUint32());
break;
case WebRTCStatsMemberTypeSequenceInt64:
success &= addPropertySequenceOfNumbers(v8Object, isolate, name,
member->valueSequenceInt64());
break;
case WebRTCStatsMemberTypeSequenceUint64:
success &= addPropertySequenceOfNumbers(v8Object, isolate, name,
member->valueSequenceUint64());
break;
case WebRTCStatsMemberTypeSequenceDouble:
success &= addPropertySequenceOfNumbers(v8Object, isolate, name,
member->valueSequenceDouble());
break;
case WebRTCStatsMemberTypeSequenceString:
success &= addPropertySequenceOfStrings(v8Object, isolate, name,
member->valueSequenceString());
break;
default:
NOTREACHED();
}
}
if (!success) {
NOTREACHED();
return v8::Undefined(isolate);
}
return v8Object;
}
class RTCStatsReportIterationSource final
: public PairIterable<String, v8::Local<v8::Value>>::IterationSource {
public:
RTCStatsReportIterationSource(std::unique_ptr<WebRTCStatsReport> report)
: m_report(std::move(report)) {}
bool next(ScriptState* scriptState,
String& key,
v8::Local<v8::Value>& value,
ExceptionState& exceptionState) override {
std::unique_ptr<WebRTCStats> stats = m_report->next();
if (!stats)
return false;
key = stats->id();
value = webRTCStatsToValue(scriptState, stats.get());
return true;
}
private:
std::unique_ptr<WebRTCStatsReport> m_report;
};
} // namespace
RTCStatsReport::RTCStatsReport(std::unique_ptr<WebRTCStatsReport> report)
: m_report(std::move(report)) {}
PairIterable<String, v8::Local<v8::Value>>::IterationSource*
RTCStatsReport::startIteration(ScriptState*, ExceptionState&) {
return new RTCStatsReportIterationSource(m_report->copyHandle());
}
bool RTCStatsReport::getMapEntry(ScriptState* scriptState,
const String& key,
v8::Local<v8::Value>& value,
ExceptionState&) {
std::unique_ptr<WebRTCStats> stats = m_report->getStats(key);
if (!stats)
return false;
value = webRTCStatsToValue(scriptState, stats.get());
return true;
}
} // namespace blink