| // Copyright (c) 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 "content/renderer/media/webrtc/rtc_stats.h" |
| |
| #include <set> |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/time/time.h" |
| #include "third_party/webrtc/api/stats/rtcstats_objects.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| class RTCStatsWhitelist { |
| public: |
| RTCStatsWhitelist() { |
| whitelisted_stats_types_.insert(webrtc::RTCCertificateStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCCodecStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCDataChannelStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCIceCandidatePairStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCIceCandidateStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCLocalIceCandidateStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCRemoteIceCandidateStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCMediaStreamStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCMediaStreamTrackStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCPeerConnectionStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCRTPStreamStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCInboundRTPStreamStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCOutboundRTPStreamStats::kType); |
| whitelisted_stats_types_.insert(webrtc::RTCTransportStats::kType); |
| } |
| |
| bool IsWhitelisted(const webrtc::RTCStats& stats) { |
| return whitelisted_stats_types_.find(stats.type()) != |
| whitelisted_stats_types_.end(); |
| } |
| |
| void WhitelistStatsForTesting(const char* type) { |
| whitelisted_stats_types_.insert(type); |
| } |
| |
| private: |
| std::set<std::string> whitelisted_stats_types_; |
| }; |
| |
| RTCStatsWhitelist* GetStatsWhitelist() { |
| static RTCStatsWhitelist* whitelist = new RTCStatsWhitelist(); |
| return whitelist; |
| } |
| |
| bool IsWhitelistedStats(const webrtc::RTCStats& stats) { |
| return GetStatsWhitelist()->IsWhitelisted(stats); |
| } |
| |
| } // namespace |
| |
| RTCStatsReport::RTCStatsReport( |
| const scoped_refptr<const webrtc::RTCStatsReport>& stats_report) |
| : stats_report_(stats_report), |
| it_(stats_report_->begin()), |
| end_(stats_report_->end()) { |
| DCHECK(stats_report_); |
| } |
| |
| RTCStatsReport::~RTCStatsReport() { |
| } |
| |
| std::unique_ptr<blink::WebRTCStatsReport> RTCStatsReport::CopyHandle() const { |
| return std::unique_ptr<blink::WebRTCStatsReport>( |
| new RTCStatsReport(stats_report_)); |
| } |
| |
| std::unique_ptr<blink::WebRTCStats> RTCStatsReport::GetStats( |
| blink::WebString id) const { |
| const webrtc::RTCStats* stats = stats_report_->Get(id.Utf8()); |
| if (!stats || !IsWhitelistedStats(*stats)) |
| return std::unique_ptr<blink::WebRTCStats>(); |
| return std::unique_ptr<blink::WebRTCStats>( |
| new RTCStats(stats_report_, stats)); |
| } |
| |
| std::unique_ptr<blink::WebRTCStats> RTCStatsReport::Next() { |
| while (it_ != end_) { |
| const webrtc::RTCStats& next = *it_; |
| ++it_; |
| if (IsWhitelistedStats(next)) { |
| return std::unique_ptr<blink::WebRTCStats>( |
| new RTCStats(stats_report_, &next)); |
| } |
| } |
| return std::unique_ptr<blink::WebRTCStats>(); |
| } |
| |
| size_t RTCStatsReport::Size() const { |
| return stats_report_->size(); |
| } |
| |
| RTCStats::RTCStats( |
| const scoped_refptr<const webrtc::RTCStatsReport>& stats_owner, |
| const webrtc::RTCStats* stats) |
| : stats_owner_(stats_owner), |
| stats_(stats), |
| stats_members_(stats->Members()) { |
| DCHECK(stats_owner_); |
| DCHECK(stats_); |
| DCHECK(stats_owner_->Get(stats_->id())); |
| } |
| |
| RTCStats::~RTCStats() { |
| } |
| |
| blink::WebString RTCStats::Id() const { |
| return blink::WebString::FromUTF8(stats_->id()); |
| } |
| |
| blink::WebString RTCStats::GetType() const { |
| return blink::WebString::FromUTF8(stats_->type()); |
| } |
| |
| double RTCStats::Timestamp() const { |
| return stats_->timestamp_us() / static_cast<double>( |
| base::Time::kMicrosecondsPerMillisecond); |
| } |
| |
| size_t RTCStats::MembersCount() const { |
| return stats_members_.size(); |
| } |
| |
| std::unique_ptr<blink::WebRTCStatsMember> RTCStats::GetMember(size_t i) const { |
| DCHECK_LT(i, stats_members_.size()); |
| return std::unique_ptr<blink::WebRTCStatsMember>( |
| new RTCStatsMember(stats_owner_, stats_members_[i])); |
| } |
| |
| RTCStatsMember::RTCStatsMember( |
| const scoped_refptr<const webrtc::RTCStatsReport>& stats_owner, |
| const webrtc::RTCStatsMemberInterface* member) |
| : stats_owner_(stats_owner), |
| member_(member) { |
| DCHECK(stats_owner_); |
| DCHECK(member_); |
| } |
| |
| RTCStatsMember::~RTCStatsMember() { |
| } |
| |
| blink::WebString RTCStatsMember::GetName() const { |
| return blink::WebString::FromUTF8(member_->name()); |
| } |
| |
| blink::WebRTCStatsMemberType RTCStatsMember::GetType() const { |
| switch (member_->type()) { |
| case webrtc::RTCStatsMemberInterface::kBool: |
| return blink::kWebRTCStatsMemberTypeBool; |
| case webrtc::RTCStatsMemberInterface::kInt32: |
| return blink::kWebRTCStatsMemberTypeInt32; |
| case webrtc::RTCStatsMemberInterface::kUint32: |
| return blink::kWebRTCStatsMemberTypeUint32; |
| case webrtc::RTCStatsMemberInterface::kInt64: |
| return blink::kWebRTCStatsMemberTypeInt64; |
| case webrtc::RTCStatsMemberInterface::kUint64: |
| return blink::kWebRTCStatsMemberTypeUint64; |
| case webrtc::RTCStatsMemberInterface::kDouble: |
| return blink::kWebRTCStatsMemberTypeDouble; |
| case webrtc::RTCStatsMemberInterface::kString: |
| return blink::kWebRTCStatsMemberTypeString; |
| case webrtc::RTCStatsMemberInterface::kSequenceBool: |
| return blink::kWebRTCStatsMemberTypeSequenceBool; |
| case webrtc::RTCStatsMemberInterface::kSequenceInt32: |
| return blink::kWebRTCStatsMemberTypeSequenceInt32; |
| case webrtc::RTCStatsMemberInterface::kSequenceUint32: |
| return blink::kWebRTCStatsMemberTypeSequenceUint32; |
| case webrtc::RTCStatsMemberInterface::kSequenceInt64: |
| return blink::kWebRTCStatsMemberTypeSequenceInt64; |
| case webrtc::RTCStatsMemberInterface::kSequenceUint64: |
| return blink::kWebRTCStatsMemberTypeSequenceUint64; |
| case webrtc::RTCStatsMemberInterface::kSequenceDouble: |
| return blink::kWebRTCStatsMemberTypeSequenceDouble; |
| case webrtc::RTCStatsMemberInterface::kSequenceString: |
| return blink::kWebRTCStatsMemberTypeSequenceString; |
| default: |
| NOTREACHED(); |
| return blink::kWebRTCStatsMemberTypeSequenceInt32; |
| } |
| } |
| |
| bool RTCStatsMember::IsDefined() const { |
| return member_->is_defined(); |
| } |
| |
| bool RTCStatsMember::ValueBool() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<bool>>(); |
| } |
| |
| int32_t RTCStatsMember::ValueInt32() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<int32_t>>(); |
| } |
| |
| uint32_t RTCStatsMember::ValueUint32() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<uint32_t>>(); |
| } |
| |
| int64_t RTCStatsMember::ValueInt64() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<int64_t>>(); |
| } |
| |
| uint64_t RTCStatsMember::ValueUint64() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<uint64_t>>(); |
| } |
| |
| double RTCStatsMember::ValueDouble() const { |
| DCHECK(IsDefined()); |
| return *member_->cast_to<webrtc::RTCStatsMember<double>>(); |
| } |
| |
| blink::WebString RTCStatsMember::ValueString() const { |
| DCHECK(IsDefined()); |
| return blink::WebString::FromUTF8( |
| *member_->cast_to<webrtc::RTCStatsMember<std::string>>()); |
| } |
| |
| blink::WebVector<int> RTCStatsMember::ValueSequenceBool() const { |
| DCHECK(IsDefined()); |
| const std::vector<bool>& vector = |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<bool>>>(); |
| std::vector<int> uint32_vector; |
| uint32_vector.reserve(vector.size()); |
| for (size_t i = 0; i < vector.size(); ++i) { |
| uint32_vector.push_back(vector[i] ? 1 : 0); |
| } |
| return blink::WebVector<int>(uint32_vector); |
| } |
| |
| blink::WebVector<int32_t> RTCStatsMember::ValueSequenceInt32() const { |
| DCHECK(IsDefined()); |
| return blink::WebVector<int32_t>( |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<int32_t>>>()); |
| } |
| |
| blink::WebVector<uint32_t> RTCStatsMember::ValueSequenceUint32() const { |
| DCHECK(IsDefined()); |
| return blink::WebVector<uint32_t>( |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint32_t>>>()); |
| } |
| |
| blink::WebVector<int64_t> RTCStatsMember::ValueSequenceInt64() const { |
| DCHECK(IsDefined()); |
| return blink::WebVector<int64_t>( |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<int64_t>>>()); |
| } |
| |
| blink::WebVector<uint64_t> RTCStatsMember::ValueSequenceUint64() const { |
| DCHECK(IsDefined()); |
| return blink::WebVector<uint64_t>( |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<uint64_t>>>()); |
| } |
| |
| blink::WebVector<double> RTCStatsMember::ValueSequenceDouble() const { |
| DCHECK(IsDefined()); |
| return blink::WebVector<double>( |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<double>>>()); |
| } |
| |
| blink::WebVector<blink::WebString> RTCStatsMember::ValueSequenceString() const { |
| DCHECK(IsDefined()); |
| const std::vector<std::string>& sequence = |
| *member_->cast_to<webrtc::RTCStatsMember<std::vector<std::string>>>(); |
| blink::WebVector<blink::WebString> web_sequence(sequence.size()); |
| for (size_t i = 0; i < sequence.size(); ++i) |
| web_sequence[i] = blink::WebString::FromUTF8(sequence[i]); |
| return web_sequence; |
| } |
| |
| void WhitelistStatsForTesting(const char* type) { |
| GetStatsWhitelist()->WhitelistStatsForTesting(type); |
| } |
| |
| } // namespace content |